blob: ca274cc2ad6dfd0f3974aaa332171fe47201a0fb [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "host/commands/ivserver/ivserver.h"
#include <sys/select.h>
#include <algorithm>
#include <glog/logging.h>
#include "common/libs/fs/shared_select.h"
#include "host/commands/ivserver/hald_client.h"
#include "host/commands/ivserver/qemu_client.h"
namespace ivserver {
IVServer::IVServer(const IVServerOptions &options, int qemu_channel_fd,
int client_channel_fd)
: vsoc_shmem_(VSoCSharedMemory::New(options.shm_file_path)) {
if (qemu_channel_fd > 0) {
qemu_channel_ = cvd::SharedFD::Dup(qemu_channel_fd);
} else {
LOG_IF(WARNING, unlink(options.qemu_socket_path.c_str()) == 0)
<< "Removed existing unix socket: " << options.qemu_socket_path
<< ". We can't confirm yet whether another instance is running.";
qemu_channel_ = cvd::SharedFD::SocketLocalServer(
options.qemu_socket_path.c_str(), false, SOCK_STREAM, 0666);
}
LOG_IF(FATAL, !qemu_channel_->IsOpen())
<< "Could not create QEmu channel: " << qemu_channel_->StrError();
if (client_channel_fd > 0) {
client_channel_ = cvd::SharedFD::Dup(client_channel_fd);
} else {
LOG_IF(WARNING, unlink(options.client_socket_path.c_str()) == 0)
<< "Removed existing unix socket: " << options.client_socket_path
<< ". We can't confirm yet whether another instance is running.";
client_channel_ = cvd::SharedFD::SocketLocalServer(
options.client_socket_path.c_str(), false, SOCK_STREAM, 0666);
}
LOG_IF(FATAL, !client_channel_->IsOpen())
<< "Could not create Client channel: " << client_channel_->StrError();
}
void IVServer::Serve() {
while (true) {
cvd::SharedFDSet rset;
rset.Set(qemu_channel_);
rset.Set(client_channel_);
cvd::Select(&rset, nullptr, nullptr, nullptr);
if (rset.IsSet(qemu_channel_)) {
HandleNewQemuConnection();
}
if (rset.IsSet(client_channel_)) {
HandleNewClientConnection();
}
}
LOG(FATAL) << "Control reached out of event loop";
}
void IVServer::HandleNewClientConnection() {
std::unique_ptr<HaldClient> res = HaldClient::New(
*vsoc_shmem_, cvd::SharedFD::Accept(*client_channel_, nullptr, nullptr));
if (!res) {
LOG(WARNING) << "Rejecting unsuccessful HALD connection.";
}
}
void IVServer::HandleNewQemuConnection() {
std::unique_ptr<QemuClient> res = QemuClient::New(
*vsoc_shmem_, cvd::SharedFD::Accept(*qemu_channel_, nullptr, nullptr));
if (!res) {
LOG(WARNING) << "Could not accept new QEmu client.";
}
}
} // namespace ivserver