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/commands/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/commands/ivserver/hald_client.h"
25 #include "host/commands/ivserver/qemu_client.h"
26
27 namespace ivserver {
28
IVServer(const IVServerOptions & options,int qemu_channel_fd,int client_channel_fd)29 IVServer::IVServer(const IVServerOptions &options, int qemu_channel_fd,
30 int client_channel_fd)
31 : vsoc_shmem_(VSoCSharedMemory::New(options.shm_file_path)) {
32 if (qemu_channel_fd > 0) {
33 qemu_channel_ = cvd::SharedFD::Dup(qemu_channel_fd);
34 } else {
35 LOG_IF(WARNING, unlink(options.qemu_socket_path.c_str()) == 0)
36 << "Removed existing unix socket: " << options.qemu_socket_path
37 << ". We can't confirm yet whether another instance is running.";
38 qemu_channel_ = cvd::SharedFD::SocketLocalServer(
39 options.qemu_socket_path.c_str(), false, SOCK_STREAM, 0666);
40 }
41 LOG_IF(FATAL, !qemu_channel_->IsOpen())
42 << "Could not create QEmu channel: " << qemu_channel_->StrError();
43
44 if (client_channel_fd > 0) {
45 client_channel_ = cvd::SharedFD::Dup(client_channel_fd);
46 } else {
47 LOG_IF(WARNING, unlink(options.client_socket_path.c_str()) == 0)
48 << "Removed existing unix socket: " << options.client_socket_path
49 << ". We can't confirm yet whether another instance is running.";
50 client_channel_ = cvd::SharedFD::SocketLocalServer(
51 options.client_socket_path.c_str(), false, SOCK_STREAM, 0666);
52 }
53 LOG_IF(FATAL, !client_channel_->IsOpen())
54 << "Could not create Client channel: " << client_channel_->StrError();
55 }
56
Serve()57 void IVServer::Serve() {
58 while (true) {
59 cvd::SharedFDSet rset;
60 rset.Set(qemu_channel_);
61 rset.Set(client_channel_);
62 cvd::Select(&rset, nullptr, nullptr, nullptr);
63
64 if (rset.IsSet(qemu_channel_)) {
65 HandleNewQemuConnection();
66 }
67
68 if (rset.IsSet(client_channel_)) {
69 HandleNewClientConnection();
70 }
71 }
72
73 LOG(FATAL) << "Control reached out of event loop";
74 }
75
HandleNewClientConnection()76 void IVServer::HandleNewClientConnection() {
77 std::unique_ptr<HaldClient> res = HaldClient::New(
78 *vsoc_shmem_, cvd::SharedFD::Accept(*client_channel_, nullptr, nullptr));
79 if (!res) {
80 LOG(WARNING) << "Rejecting unsuccessful HALD connection.";
81 }
82 }
83
HandleNewQemuConnection()84 void IVServer::HandleNewQemuConnection() {
85 std::unique_ptr<QemuClient> res = QemuClient::New(
86 *vsoc_shmem_, cvd::SharedFD::Accept(*qemu_channel_, nullptr, nullptr));
87
88 if (!res) {
89 LOG(WARNING) << "Could not accept new QEmu client.";
90 }
91 }
92
93 } // namespace ivserver
94