Cody Schuffelen | 134ff03 | 2019-11-22 00:25:32 -0800 | [diff] [blame^] | 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 |