1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "host/libs/ivserver/ivserver.h"
17
18#include <sys/select.h>
19#include <algorithm>
20
21#include <glog/logging.h>
22
23#include "common/libs/fs/shared_select.h"
24#include "host/libs/ivserver/hald_client.h"
25#include "host/libs/ivserver/qemu_client.h"
26
27namespace ivserver {
28
29IVServer::IVServer(const IVServerOptions &options)
30    : vsoc_shmem_(VSoCSharedMemory::New(options.shm_file_path)) {
31  LOG_IF(WARNING, unlink(options.qemu_socket_path.c_str()) == 0)
32      << "Removed existing unix socket: " << options.qemu_socket_path
33      << ". We can't confirm yet whether another instance is running.";
34  qemu_channel_ = cvd::SharedFD::SocketLocalServer(
35      options.qemu_socket_path.c_str(), false, SOCK_STREAM, 0666);
36  LOG_IF(FATAL, !qemu_channel_->IsOpen())
37      << "Could not create QEmu channel: " << qemu_channel_->StrError();
38
39  LOG_IF(WARNING, unlink(options.client_socket_path.c_str()) == 0)
40      << "Removed existing unix socket: " << options.client_socket_path
41      << ". We can't confirm yet whether another instance is running.";
42  client_channel_ = cvd::SharedFD::SocketLocalServer(
43      options.client_socket_path.c_str(), false, SOCK_STREAM, 0666);
44  LOG_IF(FATAL, !client_channel_->IsOpen())
45      << "Could not create Client channel: " << client_channel_->StrError();
46}
47
48void IVServer::Serve() {
49  while (true) {
50    cvd::SharedFDSet rset;
51    rset.Set(qemu_channel_);
52    rset.Set(client_channel_);
53    cvd::Select(&rset, nullptr, nullptr, nullptr);
54
55    if (rset.IsSet(qemu_channel_)) {
56      HandleNewQemuConnection();
57    }
58
59    if (rset.IsSet(client_channel_)) {
60      HandleNewClientConnection();
61    }
62  }
63
64  LOG(FATAL) << "Control reached out of event loop";
65}
66
67void IVServer::HandleNewClientConnection() {
68  std::unique_ptr<HaldClient> res = HaldClient::New(
69      *vsoc_shmem_, cvd::SharedFD::Accept(*client_channel_, nullptr, nullptr));
70  if (!res) {
71    LOG(WARNING) << "Rejecting unsuccessful HALD connection.";
72  }
73}
74
75void IVServer::HandleNewQemuConnection() {
76  std::unique_ptr<QemuClient> res = QemuClient::New(
77      *vsoc_shmem_, cvd::SharedFD::Accept(*qemu_channel_, nullptr, nullptr));
78
79  if (!res) {
80    LOG(WARNING) << "Could not accept new QEmu client.";
81  }
82}
83
84}  // namespace ivserver
85