First part of an RPC mechanism for container <-> host communication

Mostly based on the protobuf based implementation from Mir.
This commit is contained in:
Simon Fels 2016-06-28 00:21:30 +02:00
commit da971a88c3
38 changed files with 1750 additions and 52 deletions

50
Android.mk Normal file
View file

@ -0,0 +1,50 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libprocess-cpp-minimal
LOCAL_SRC_FILES := \
external/process-cpp-minimal/src/core/posix/process.cpp \
external/process-cpp-minimal/src/core/posix/process_group.cpp \
external/process-cpp-minimal/src/core/posix/signal.cpp \
external/process-cpp-minimal/src/core/posix/signalable.cpp \
external/process-cpp-minimal/src/core/posix/standard_stream.cpp \
external/process-cpp-minimal/src/core/posix/wait.cpp
LOCAL_CFLAGS := \
-fexceptions
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/external/process-cpp-minimal/include
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE := anboxd
LOCAL_SRC_FILES := \
android/service/main.cpp \
android/service/daemon.cpp \
android/service/host_connector.cpp \
android/service/local_socket_connection.cpp \
android/service/message_processor.cpp \
src/anbox/common/fd.cpp \
src/anbox/bridge/message_processor.cpp \
src/anbox/bridge/pending_call_cache.cpp \
src/anbox/bridge/rpc_channel.cpp \
src/anbox/protobuf/bridge.proto
proto_header_dir := $(call local-generated-sources-dir)/proto/$(LOCAL_PATH)/src/anbox/protobuf
LOCAL_C_INCLUDES += \
$(proto_header_dir) \
$(LOCAL_PATH)/external/process-cpp-minimal/include \
$(LOCAL_PATH)/src \
$(LOCAL_PATH)/android/service
LOCAL_EXPORT_C_INCLUDE_DIRS += $(proto_header_dir)
LOCAL_STATIC_LIBRARIES := \
libprocess-cpp-minimal
LOCAL_SHARED_LIBRARIES := \
liblog \
libprotobuf-cpp-lite \
libsysutils
LOCAL_CFLAGS := \
-fexceptions \
-std=c++1y
include $(BUILD_EXECUTABLE)

View file

@ -60,6 +60,7 @@ find_package(PkgConfig)
find_package(Threads)
find_package(EGL REQUIRED)
find_package(GLESv2 REQUIRED)
find_package(Protobuf REQUIRED)
# TODO(morphis): make mir an optional requirement so we can also add support
# for X11, wayland, ... at a later point if needed.

View file

@ -1,43 +0,0 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES = \
jni/anbox_support.cpp \
jni/application_manager.cpp \
jni/jni_helper.cpp
LOCAL_C_INCLUDES := \
$(JNI_H_INCLUDE) \
libcore/include
LOCAL_SHARED_LIBRARIES := \
liblog \
libnativehelper
LOCAL_MODULE := libanbox_support
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/java
LOCAL_SRC_FILES := $(call all-java-files-under, java)
LOCAL_JAVA_LIBRARIES := telephony-common
LOCAL_JNI_SHARED_LIBRARIES := \
libanbox_support
# Block certain packages from being installed
# LOCAL_OVERRIDES_PACKAGES := \
# SystemUI \
# Home \
# Launcher2 \
# Calculator \
# BasicDreams \
# Calendar \
# PrintSpooler \
# WallpaperCropper
LOCAL_PACKAGE_NAME := anboxd
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))

View file

@ -1,4 +1,21 @@
include_directories(
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src
${CMAKE_BINARY_DIR}/src)
set(ANBOXD_SOURCES
${CMAKE_SOURCE_DIR}/src/anbox/bridge/message_processor.cpp
${CMAKE_SOURCE_DIR}/src/anbox/bridge/pending_call_cache.cpp
${CMAKE_SOURCE_DIR}/src/anbox/common/fd.cpp
service/server.cpp
service/message_processor.cpp
service/local_socket_connection.cpp
service/host_connector.cpp
service/daemon.cpp
service/main.cpp)
add_executable(anboxd ${ANBOXD_SOURCES})
target_link_libraries(anboxd
pthread
process-cpp
anbox-protobuf)

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "android/service/daemon.h"
#include "android/service/host_connector.h"
#include "core/posix/signal.h"
#include <memory>
#include <cstdlib>
namespace anbox {
namespace android {
Daemon::Daemon() {
}
Daemon::~Daemon() {
}
int Daemon::run() {
auto trap = core::posix::trap_signals_for_process({core::posix::Signal::sig_term,
core::posix::Signal::sig_int});
trap->signal_raised().connect([trap](const core::posix::Signal&) {
trap->stop();
});
auto host_connector = std::make_shared<HostConnector>();
trap->run();
return EXIT_SUCCESS;
}
} // namespace android
} // namespace anbox

33
android/service/daemon.h Normal file
View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_ANDROID_DAEMON_H_
#define ANBOX_ANDROID_DAEMON_H_
namespace anbox {
namespace android {
class Daemon {
public:
Daemon();
~Daemon();
int run();
};
} // namespace android
} // namespace anbox
#endif

View file

@ -0,0 +1,74 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "android/service/host_connector.h"
#include "android/service/local_socket_connection.h"
#include "android/service/message_processor.h"
#include "android/service/server.h"
#include <functional>
#include <array>
namespace anbox {
namespace android {
HostConnector::HostConnector() :
socket_(std::make_shared<LocalSocketConnection>("/dev/anbox_bridge")),
pending_calls_(std::make_shared<bridge::PendingCallCache>()),
server_(std::make_shared<Server>()),
message_processor_(std::make_shared<MessageProcessor>(socket_, pending_calls_, server_)),
running_(false) {
}
HostConnector::~HostConnector() {
}
void HostConnector::start() {
if (running_)
return;
running_.exchange(true);
thread_ = std::thread(std::bind(&HostConnector::main_loop, this));
}
void HostConnector::stop() {
if (!running_.exchange(false))
return;
thread_.join();
}
void HostConnector::main_loop() {
while (running_) {
std::array<std::uint8_t, 8192> buffer;
const auto bytes_read = socket_->read_all(buffer.data(), buffer.size());
if (bytes_read == 0)
break;
// MessageProcessor wants an vector so give it what it wants until
// we refactor this.
std::vector<std::uint8_t> data;
for (auto n = 0; n < bytes_read; n++)
data.push_back(buffer[n]);
if (!message_processor_->process_data(data))
break;
}
// FIXME notify our core that we've stopped
}
} // namespace android
} // namespace anbox

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_ANDROID_HOST_CONNECTOR_H_
#define ANBOX_ANDROID_HOST_CONNECTOR_H_
#include <memory>
#include <thread>
#include <atomic>
namespace anbox {
namespace bridge {
class PendingCallCache;
} // namespace bridge
namespace android {
class LocalSocketConnection;
class MessageProcessor;
class Server;
class HostConnector {
public:
HostConnector();
~HostConnector();
void start();
void stop();
private:
void main_loop();
std::shared_ptr<LocalSocketConnection> socket_;
std::shared_ptr<bridge::PendingCallCache> pending_calls_;
std::shared_ptr<Server> server_;
std::shared_ptr<MessageProcessor> message_processor_;
std::thread thread_;
std::atomic<bool> running_;
};
} // namespace android
} // namespace anbox
#endif

View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "android/service/local_socket_connection.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
namespace {
bool socket_error_is_transient(int error_code) {
return (error_code == EINTR);
}
}
namespace anbox {
namespace android {
LocalSocketConnection::LocalSocketConnection(const std::string &path) :
fd_(Fd::invalid) {
struct sockaddr_un socket_address;
memset(&socket_address, 0, sizeof(socket_address));
socket_address.sun_family = AF_UNIX;
memcpy(socket_address.sun_path, path.data(), path.size());
fd_ = Fd{socket(AF_UNIX, SOCK_STREAM, 0)};
if (connect(fd_, reinterpret_cast<sockaddr*>(&socket_address), sizeof(socket_address)) < 0)
throw std::runtime_error("Failed to connect to server socket");
}
LocalSocketConnection::~LocalSocketConnection() {
if (fd_ > 0)
::close(fd_);
}
ssize_t LocalSocketConnection::read_all(std::uint8_t *buffer, const size_t &size) {
ssize_t bytes_read = ::recv(fd_, reinterpret_cast<void*>(buffer), size, 0);
return bytes_read;
}
void LocalSocketConnection::send(char const* data, size_t length) {
size_t bytes_written{0};
while(bytes_written < length) {
ssize_t const result = ::send(fd_,
data + bytes_written,
length - bytes_written,
MSG_NOSIGNAL);
if (result < 0) {
if (socket_error_is_transient(errno))
continue;
else
throw std::runtime_error("Failed to send message to server");
}
bytes_written += result;
}
}
} // namespace android
} // namespace anbox

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_ANDROID_LOCAL_SOCKET_CONNECTION_H_
#define ANBOX_ANDROID_LOCAL_SOCKET_CONNECTION_H_
#include <string>
#include <vector>
#include "anbox/common/fd.h"
#include "anbox/network/message_sender.h"
namespace anbox {
namespace android {
class LocalSocketConnection : public network::MessageSender {
public:
LocalSocketConnection(const std::string &path);
~LocalSocketConnection();
ssize_t read_all(std::uint8_t *buffer, const size_t &size);
void send(char const* data, size_t length) override;
private:
Fd fd_;
};
} // namespace android
} // namespace anbox
#endif

View file

@ -15,6 +15,9 @@
*
*/
#include "android/service/daemon.h"
int main(int, char**) {
return 0;
anbox::android::Daemon daemon;
return daemon.run();
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "android/service/message_processor.h"
#include "android/service/server.h"
#include "anbox/bridge/template_message_processor.h"
namespace anbox {
namespace android {
MessageProcessor::MessageProcessor(const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<bridge::PendingCallCache> &pending_calls,
const std::shared_ptr<Server> &server) :
bridge::MessageProcessor(sender, pending_calls),
server_(server) {
}
MessageProcessor::~MessageProcessor() {
}
void MessageProcessor::dispatch(bridge::Invocation const& invocation) {
if (invocation.method_name() == "install_application")
invoke(this, server_.get(), &Server::install_application, invocation);
else if (invocation.method_name() == "launch_application")
invoke(this, server_.get(), &Server::launch_application, invocation);
}
void MessageProcessor::process_event_sequence(const std::string&) {
}
} // namespace anbox
} // namespace network

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_ANDROID_MESSAGE_PROCESSOR_H_
#define ANBOX_ANDROID_MESSAGE_PROCESSOR_H_
#include "anbox/bridge/message_processor.h"
namespace anbox {
namespace android {
class Server;
class MessageProcessor : public bridge::MessageProcessor {
public:
MessageProcessor(const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<bridge::PendingCallCache> &pending_calls,
const std::shared_ptr<Server> &server);
~MessageProcessor();
void dispatch(bridge::Invocation const& invocation) override;
void process_event_sequence(const std::string &event) override;
private:
std::shared_ptr<Server> server_;
};
} // namespace anbox
} // namespace network
#endif

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "android/service/server.h"
#include "anbox_bridge.pb.h"
namespace anbox {
namespace android {
Server::Server() {
}
Server::~Server() {
}
void Server::install_application(anbox::protobuf::bridge::InstallApplication const *request,
anbox::protobuf::bridge::Void *response,
google::protobuf::Closure *done) {
(void) request;
(void) response;
done->Run();
}
void Server::launch_application(anbox::protobuf::bridge::LaunchApplication const *request,
anbox::protobuf::bridge::Void *response,
google::protobuf::Closure *done) {
(void) request;
(void) response;
done->Run();
}
} // namespace anbox
} // namespace network

52
android/service/server.h Normal file
View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_ANDROID_SERVER_H_
#define ANBOX_ANDROID_SERVER_H_
namespace google {
namespace protobuf {
class Closure;
} // namespace protobuf
} // namespace google
namespace anbox {
namespace protobuf {
namespace bridge {
class InstallApplication;
class LaunchApplication;
class Void;
} // namespace bridge
} // namespace protobuf
namespace android {
class Server {
public:
Server();
~Server();
void install_application(anbox::protobuf::bridge::InstallApplication const *request,
anbox::protobuf::bridge::Void *response,
google::protobuf::Closure *done);
void launch_application(anbox::protobuf::bridge::LaunchApplication const *request,
anbox::protobuf::bridge::Void *response,
google::protobuf::Closure *done);
};
} // namespace android
} // namespace anbox
#endif

View file

@ -10,6 +10,20 @@ include_directories(
${CMAKE_SOURCE_DIR}/external/android-emugl/host/include
)
set(PROTOBUF_SOURCES
anbox/protobuf/anbox_bridge.proto)
protobuf_generate_cpp(
GENERATED_PROTOBUF_SRCS GENERATED_PROTOBUF_HDRS
${PROTOBUF_SOURCES})
add_library(anbox-protobuf
${GENERATED_PROTOBUF_SRCS}
${GENERATED_PROTOBUF_HDRS}
anbox/protobuf/google_protobuf_guard.cpp)
target_link_libraries(anbox-protobuf
${PROTOBUF_LITE_LIBRARIES})
set(SOURCES
anbox/logger.cpp
anbox/utils.cpp
@ -56,6 +70,18 @@ set(SOURCES
anbox/support/sensors_message_processor.cpp
anbox/support/camera_message_processor.cpp
anbox/support/fingerprint_message_processor.cpp
anbox/support/gsm_message_processor.cpp
anbox/support/at_parser.cpp
anbox/bridge/constants.h
anbox/bridge/connection_creator.cpp
anbox/bridge/message_processor.cpp
anbox/bridge/template_message_processor.h
anbox/bridge/pending_call_cache.cpp
anbox/bridge/make_protobuf_object.h
anbox/bridge/platform_message_processor.cpp
anbox/bridge/platform_server.cpp
anbox/bridge/rpc_channel.cpp
anbox/ubuntu/platform_server.cpp
anbox/ubuntu/mir_display_connection.cpp
@ -82,7 +108,8 @@ target_link_libraries(anbox-core
add_executable(anbox main.cpp)
target_link_libraries(anbox
anbox-core)
anbox-core
anbox-protobuf)
add_executable(anbox-container container_main.cpp)
target_link_libraries(anbox-container

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "anbox/bridge/connection_creator.h"
#include "anbox/bridge/message_processor.h"
#include "anbox/network/socket_messenger.h"
#include "anbox/logger.h"
#include <string>
namespace ba = boost::asio;
namespace anbox {
namespace bridge {
ConnectionCreator::ConnectionCreator(const std::shared_ptr<Runtime> &rt, const MessageProcessorFactory &factory) :
runtime_(rt),
next_connection_id_(0),
connections_(std::make_shared<network::Connections<network::SocketConnection>>()),
message_processor_factory_(factory) {
}
ConnectionCreator::~ConnectionCreator() {
}
void ConnectionCreator::create_connection_for(
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) {
if (connections_->size() >= 1) {
socket->close();
WARNING("A second client tried to connect. Denied request as we already have one"
"and only allow a single client");
return;
}
DEBUG("");
auto const messenger = std::make_shared<network::SocketMessenger>(socket);
auto const processor = message_processor_factory_(messenger);
auto const& connection = std::make_shared<network::SocketConnection>(
messenger, messenger, next_id(), connections_, processor);
connections_->add(connection);
connection->read_next_message();
}
int ConnectionCreator::next_id()
{
return next_connection_id_.fetch_add(1);
}
} // namespace anbox
} // namespace network

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_BRIDGE_CONNECTION_CREATOR_H_
#define ANBOX_BRIDGE_CONNECTION_CREATOR_H_
#include <boost/asio.hpp>
#include <memory>
#include "anbox/do_not_copy_or_move.h"
#include "anbox/runtime.h"
#include "anbox/network/connections.h"
#include "anbox/network/socket_connection.h"
#include "anbox/network/connection_creator.h"
#include "anbox/network/socket_messenger.h"
namespace anbox {
namespace bridge {
class ConnectionCreator : public network::ConnectionCreator {
public:
typedef std::function<std::shared_ptr<network::MessageProcessor>(const std::shared_ptr<network::MessageSender>&)> MessageProcessorFactory;
ConnectionCreator(
const std::shared_ptr<Runtime> &rt, const MessageProcessorFactory &factory);
~ConnectionCreator() noexcept;
void create_connection_for(
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) override;
private:
int next_id();
std::shared_ptr<Runtime> runtime_;
std::atomic<int> next_connection_id_;
std::shared_ptr<network::Connections<network::SocketConnection>> const connections_;
MessageProcessorFactory message_processor_factory_;
};
} // namespace anbox
} // namespace network
#endif

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_BRIDGE_CONSTANTS_H_
#define ANBOX_BRIDGE_CONSTANTS_H_
namespace anbox {
namespace bridge {
static constexpr const long header_size{3};
static constexpr unsigned int const serialization_buffer_size{2048};
enum MessageType {
invocation = 0,
response = 1,
};
} // namespace anbox
} // namespace network
#endif

View file

@ -0,0 +1,40 @@
/*
* Copyright © 2015 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Alberto Aguirre <alberto.aguirre@canonical.com>
*/
#ifndef ANBOX_BRIDGE_MAKE_PROTOBUF_OBJECT_H_
#define ANBOX_BRIDGE_MAKE_PROTOBUF_OBJECT_H_
#include <memory>
namespace anbox {
namespace bridge {
template <typename ProtobufType>
auto make_protobuf_object() {
return std::unique_ptr<ProtobufType>{ProtobufType::default_instance().New()};
}
template <typename ProtobufType>
auto make_protobuf_object(ProtobufType const& from) {
auto object = make_protobuf_object<ProtobufType>();
object->CopyFrom(from);
return object;
}
} // namespace bridge
} // namespace anbox
#endif

View file

@ -0,0 +1,119 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "anbox/bridge/message_processor.h"
#include "anbox/bridge/template_message_processor.h"
#include "anbox/bridge/make_protobuf_object.h"
#include "anbox/bridge/constants.h"
#include "anbox/common/variable_length_array.h"
#include "anbox_bridge.pb.h"
namespace anbox {
namespace bridge {
const ::std::string& Invocation::method_name() const {
return invocation_.method_name();
}
const ::std::string& Invocation::parameters() const {
return invocation_.parameters();
}
google::protobuf::uint32 Invocation::id() const {
return invocation_.id();
}
MessageProcessor::MessageProcessor(const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<PendingCallCache> &pending_calls) :
sender_(sender),
pending_calls_(pending_calls) {
}
MessageProcessor::~MessageProcessor() {
}
bool MessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
for (const auto &byte : data)
buffer_.push_back(byte);
unsigned char const high = buffer_[0];
unsigned char const low = buffer_[1];
size_t const message_size = (high << 8) + low;
unsigned char const message_type = buffer_[2];
// If we don't have yet all bytes for a new message return and wait
// until we have all.
if (buffer_.size() - header_size < message_size)
return true;
buffer_.erase(buffer_.begin(), buffer_.begin() + header_size);
if (message_type == MessageType::invocation) {
anbox::protobuf::bridge::Invocation raw_invocation;
raw_invocation.ParseFromArray(buffer_.data(), message_size);
buffer_.erase(buffer_.begin(), buffer_.begin() + message_size);
dispatch(Invocation(raw_invocation));
}
else if (message_type == MessageType::response) {
auto result = make_protobuf_object<protobuf::bridge::Result>();
result->ParseFromArray(buffer_.data(), message_size);
buffer_.erase(buffer_.begin(), buffer_.end() + message_size);
for (int i = 0; i != result->events_size(); ++i)
process_event_sequence(result->events(i));
pending_calls_->complete_response(*result);
}
return true;
}
void MessageProcessor::send_response(::google::protobuf::uint32 id, google::protobuf::MessageLite *response) {
VariableLengthArray<serialization_buffer_size> send_response_buffer(
static_cast<size_t>(response->ByteSize()));
response->SerializeWithCachedSizesToArray(send_response_buffer.data());
anbox::protobuf::bridge::Result send_response_result;
send_response_result.set_id(id);
send_response_result.set_response(send_response_buffer.data(), send_response_buffer.size());
send_response_buffer.resize(send_response_result.ByteSize());
send_response_result.SerializeWithCachedSizesToArray(send_response_buffer.data());
const size_t size = send_response_buffer.size();
const unsigned char header_bytes[header_size] = {
static_cast<unsigned char>((size >> 8) & 0xff),
static_cast<unsigned char>((size >> 0) & 0xff),
MessageType::response,
};
std::vector<std::uint8_t> send_buffer(sizeof(header_bytes) + size);
std::copy(header_bytes,
header_bytes + sizeof(header_bytes),
send_buffer.begin());
std::copy(send_response_buffer.data(),
send_response_buffer.data() + send_response_buffer.size(),
send_buffer.begin() + sizeof(header_bytes));
sender_->send(reinterpret_cast<const char*>(send_buffer.data()), send_buffer.size());
}
} // namespace anbox
} // namespace network

View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_BRIDGE_MESSAGE_PROCESSOR_H_
#define ANBOX_BRIDGE_MESSAGE_PROCESSOR_H_
#include "anbox/network/message_processor.h"
#include "anbox/network/message_sender.h"
#include "anbox/bridge/pending_call_cache.h"
#include <memory>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message_lite.h>
namespace anbox {
namespace protobuf {
namespace bridge {
class Invocation;
} // namespace bridge
} // namespace protobuf
namespace bridge {
class Invocation
{
public:
Invocation(anbox::protobuf::bridge::Invocation const& invocation) :
invocation_(invocation) {}
const ::std::string& method_name() const;
const ::std::string& parameters() const;
google::protobuf::uint32 id() const;
private:
anbox::protobuf::bridge::Invocation const& invocation_;
};
class MessageProcessor : public network::MessageProcessor {
public:
MessageProcessor(const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<PendingCallCache> &pending_calls);
~MessageProcessor();
bool process_data(const std::vector<std::uint8_t> &data) override;
void send_response(::google::protobuf::uint32 id, google::protobuf::MessageLite *response);
virtual void dispatch(Invocation const& invocation) = 0;
virtual void process_event_sequence(const std::string &event) = 0;
private:
std::shared_ptr<network::MessageSender> sender_;
std::vector<std::uint8_t> buffer_;
std::shared_ptr<PendingCallCache> pending_calls_;
};
} // namespace bridge
} // namespace anbox
#endif

View file

@ -0,0 +1,72 @@
/*
* Copyright © 2012 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Alan Griffiths <alan@octopull.co.uk>
*/
#include "anbox/bridge/pending_call_cache.h"
#include "anbox_bridge.pb.h"
namespace anbox {
namespace bridge {
PendingCallCache::PendingCallCache() {
}
void PendingCallCache::save_completion_details(anbox::protobuf::bridge::Invocation const &invocation,
google::protobuf::MessageLite *response,
google::protobuf::Closure *complete) {
std::unique_lock<std::mutex> lock(mutex_);
pending_calls_[invocation.id()] = PendingCall(response, complete);
}
void PendingCallCache::populate_message_for_result(anbox::protobuf::bridge::Result &result,
std::function<void(google::protobuf::MessageLite*)> const& populator) {
std::unique_lock<std::mutex> lock(mutex_);
populator(pending_calls_.at(result.id()).response);
}
void PendingCallCache::complete_response(anbox::protobuf::bridge::Result& result) {
PendingCall completion;
{
std::unique_lock<std::mutex> lock(mutex_);
auto call = pending_calls_.find(result.id());
if (call != pending_calls_.end()) {
completion = call->second;
pending_calls_.erase(call);
}
}
if (completion.complete)
completion.complete->Run();
}
void PendingCallCache::force_completion() {
std::unique_lock<std::mutex> lock(mutex_);
for (auto& call : pending_calls_) {
auto& completion = call.second;
completion.complete->Run();
}
pending_calls_.erase(pending_calls_.begin(), pending_calls_.end());
}
bool PendingCallCache::empty() const {
std::unique_lock<std::mutex> lock(mutex_);
return pending_calls_.empty();
}
} // namespace bridge
} // namespace anbox

View file

@ -0,0 +1,77 @@
/*
* Copyright © 2012 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Alan Griffiths <alan@octopull.co.uk>
*/
#ifndef ANBOX_BRIDGE_PENDING_CALL_CACHE_
#define ANBOX_BRIDGE_PENDING_CALL_CACHE_
#include <functional>
#include <mutex>
#include <map>
namespace google {
namespace protobuf {
class Closure;
class MessageLite;
} // namespace protobuf
} // namespace google
namespace anbox {
namespace protobuf {
namespace bridge {
class Invocation;
class Result;
} // namespace bridge
} // namespace protobuf
namespace bridge {
class PendingCallCache {
public:
PendingCallCache();
void save_completion_details(anbox::protobuf::bridge::Invocation const &invocation,
google::protobuf::MessageLite *response,
google::protobuf::Closure *complete);
void populate_message_for_result(anbox::protobuf::bridge::Result &result,
std::function<void(google::protobuf::MessageLite*)> const& populator);
void complete_response(anbox::protobuf::bridge::Result& result);
void force_completion();
bool empty() const;
private:
struct PendingCall {
PendingCall(google::protobuf::MessageLite *response,
google::protobuf::Closure *target) :
response(response),
complete(target) {
}
PendingCall() :
response(0),
complete() {
}
google::protobuf::MessageLite *response;
google::protobuf::Closure *complete;
};
std::mutex mutable mutex_;
std::map<int, PendingCall> pending_calls_;
};
} // namespace bridge
} // namespace anbox
#endif

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "anbox/bridge/platform_message_processor.h"
#include "anbox/bridge/platform_server.h"
#include "anbox/bridge/template_message_processor.h"
#include "anbox_bridge.pb.h"
namespace anbox {
namespace bridge {
PlatformMessageProcessor::PlatformMessageProcessor(const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<PlatformServer> &server,
const std::shared_ptr<PendingCallCache> &pending_calls) :
MessageProcessor(sender, pending_calls),
server_(server) {
}
PlatformMessageProcessor::~PlatformMessageProcessor() {
}
void PlatformMessageProcessor::dispatch(Invocation const& invocation) {
if (invocation.method_name() == "handle_notification") {
invoke(this, server_.get(), &PlatformServer::handle_notification, invocation);
}
}
void PlatformMessageProcessor::process_event_sequence(const std::string&) {
}
} // namespace anbox
} // namespace network

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_BRIDGE_PLATFORM_MESSAGE_PROCESSOR_H_
#define ANBOX_BRIDGE_PLATFORM_MESSAGE_PROCESSOR_H_
#include "anbox/bridge/message_processor.h"
namespace anbox {
namespace bridge {
class PlatformServer;
class PlatformMessageProcessor : public MessageProcessor {
public:
PlatformMessageProcessor(const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<PlatformServer> &server,
const std::shared_ptr<PendingCallCache> &pending_calls);
~PlatformMessageProcessor();
void dispatch(Invocation const& invocation) override;
void process_event_sequence(const std::string &event) override;
private:
std::shared_ptr<PlatformServer> server_;
};
} // namespace anbox
} // namespace network
#endif

View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "anbox/bridge/platform_server.h"
#include "anbox/logger.h"
#include "anbox_bridge.pb.h"
namespace anbox {
namespace bridge {
PlatformServer::PlatformServer(const std::shared_ptr<PendingCallCache> &pending_calls) :
pending_calls_(pending_calls) {
}
PlatformServer::~PlatformServer() {
}
} // namespace bridge
} // namespace anbox

View file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_BRIDGE_PLATFORM_SERVER_H_
#define ANBOX_BRIDGE_PLATFORM_SERVER_H_
#include <memory>
namespace google {
namespace protobuf {
class Closure;
} // namespace protobuf
} // namespace google
namespace anbox {
namespace protobuf {
namespace bridge {
class Notification;
class Void;
} // namespace bridge
} // namespace protobuf
namespace bridge {
class PendingCallCache;
class PlatformServer {
public:
PlatformServer(const std::shared_ptr<PendingCallCache> &pending_calls);
virtual ~PlatformServer();
virtual void handle_notification(anbox::protobuf::bridge::Notification const *request,
anbox::protobuf::bridge::Void *response,
google::protobuf::Closure *done) = 0;
private:
std::shared_ptr<PendingCallCache> pending_calls_;
};
} // namespace bridge
} // namespace anbox
#endif

View file

@ -0,0 +1,94 @@
/*
* Copyright © 2012 Canonical Ltd.
* © 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Alan Griffiths <alan@octopull.co.uk>
*/
#include "anbox/bridge/rpc_channel.h"
#include "anbox/bridge/pending_call_cache.h"
#include "anbox/bridge/constants.h"
#include "anbox/common/variable_length_array.h"
#include "anbox/network/message_sender.h"
#include "anbox_bridge.pb.h"
namespace anbox {
namespace bridge {
RpcChannel::RpcChannel(const std::shared_ptr<PendingCallCache> &pending_calls,
const std::shared_ptr<network::MessageSender> &sender) :
pending_calls_(pending_calls),
sender_(sender) {
}
RpcChannel::~RpcChannel() {
}
void RpcChannel::call_method(std::string const& method_name,
google::protobuf::MessageLite const *parameters,
google::protobuf::MessageLite *response,
google::protobuf::Closure *complete) {
auto const &invocation = invocation_for(method_name, parameters);
pending_calls_->save_completion_details(invocation, response, complete);
send_message(invocation);
}
protobuf::bridge::Invocation RpcChannel::invocation_for(std::string const& method_name,
google::protobuf::MessageLite const* request) {
anbox::VariableLengthArray<2048> buffer{static_cast<size_t>(request->ByteSize())};
request->SerializeWithCachedSizesToArray(buffer.data());
anbox::protobuf::bridge::Invocation invoke;
invoke.set_id(next_id());
invoke.set_method_name(method_name);
invoke.set_parameters(buffer.data(), buffer.size());
return invoke;
}
void RpcChannel::send_message(anbox::protobuf::bridge::Invocation const& invocation) {
const size_t size = invocation.ByteSize();
const unsigned char header_bytes[header_size] = {
static_cast<unsigned char>((size >> 8) & 0xff),
static_cast<unsigned char>((size >> 0) & 0xff),
MessageType::invocation,
};
std::vector<std::uint8_t> send_buffer(sizeof(header_bytes) + size);
std::copy(header_bytes, header_bytes + sizeof(header_bytes), send_buffer.begin());
invocation.SerializeToArray(send_buffer.data() + sizeof(header_bytes), size);
try {
std::lock_guard<std::mutex> lock(write_mutex_);
sender_->send(reinterpret_cast<const char*>(send_buffer.data()), send_buffer.size());
}
catch (std::runtime_error const&) {
notify_disconnected();
throw;
}
}
void RpcChannel::notify_disconnected() {
pending_calls_->force_completion();
}
int RpcChannel::next_id() {
return next_message_id_.fetch_add(1);
}
} // namespace bridge
} // namespace anbox

View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_BRIDGE_RPC_CHANNEL_H_
#define ANBOX_BRIDGE_RPC_CHANNEL_H_
#include <memory>
#include <atomic>
#include <mutex>
namespace google {
namespace protobuf {
class Closure;
class MessageLite;
} // namespace protobuf
} // namespace google
namespace anbox {
namespace protobuf {
namespace bridge {
class Invocation;
} // namespace bridge
} // namespace protobuf
namespace network {
class MessageSender;
} // namespace network
namespace bridge {
class PendingCallCache;
class RpcChannel {
public:
RpcChannel(const std::shared_ptr<PendingCallCache> &pending_calls,
const std::shared_ptr<network::MessageSender> &sender);
~RpcChannel();
void call_method(std::string const& method_name,
google::protobuf::MessageLite const *parameters,
google::protobuf::MessageLite *response,
google::protobuf::Closure *complete);
private:
protobuf::bridge::Invocation invocation_for(
std::string const& method_name,
google::protobuf::MessageLite const* request);
void send_message(anbox::protobuf::bridge::Invocation const& invocation);
int next_id();
void notify_disconnected();
std::atomic<int> next_message_id_;
std::shared_ptr<PendingCallCache> pending_calls_;
std::shared_ptr<network::MessageSender> sender_;
std::mutex write_mutex_;
};
} // namespace bridge
} // namespace anbox
#endif

View file

@ -0,0 +1,80 @@
/*
* Copyright © 2014 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Alan Griffiths <alan@octopull.co.uk>
*/
#ifndef ANBOX_BRIDGE_TEMPLATE_MESSAGE_PROCESSOR_H_
#define ANBOX_BRIDGE_TEMPLATE_MESSAGE_PROCESSOR_H_
#include <google/protobuf/stubs/common.h>
#include "anbox/bridge/message_processor.h"
#include "anbox_bridge.pb.h"
namespace anbox {
namespace bridge {
// Utility metafunction result_ptr_t<> allows invoke() to pick the right
// send_response() overload. The base template resolves to the prototype
// "send_response(::google::protobuf::uint32 id, ::google::protobuf::Message* response)"
// Client code may specialize result_ptr_t to resolve to another overload.
template<typename ResultType> struct result_ptr_t
{ typedef ::google::protobuf::MessageLite* type; };
// Boiler plate for unpacking a parameter message, invoking a server function, and
// sending the result message. Assumes the existence of Self::send_response().
template<class Self, class Bridge, class BridgeX, class ParameterMessage, class ResultMessage>
void invoke(
Self* self,
Bridge* bridge,
void (BridgeX::*function)(
ParameterMessage const* request,
ResultMessage* response,
::google::protobuf::Closure* done),
Invocation const& invocation)
{
ParameterMessage parameter_message;
if (!parameter_message.ParseFromString(invocation.parameters()))
throw std::runtime_error("Failed to parse message parameters!");
ResultMessage result_message;
try
{
std::unique_ptr<google::protobuf::Closure> callback(
google::protobuf::NewPermanentCallback<
Self,
::google::protobuf::uint32,
typename result_ptr_t<ResultMessage>::type>(
self,
&Self::send_response,
invocation.id(),
&result_message));
(bridge->*function)(
&parameter_message,
&result_message,
callback.get());
}
catch (std::exception const& x)
{
result_message.set_error(std::string("Error processing request: ") + x.what());
self->send_response(invocation.id(), &result_message);
}
}
} // namespace bridge
} // namespace anbox
#endif

View file

@ -29,6 +29,9 @@
#include "anbox/network/qemu_pipe_connection_creator.h"
#include "anbox/graphics/gl_renderer_server.h"
#include "anbox/input/manager.h"
#include "anbox/bridge/connection_creator.h"
#include "anbox/bridge/platform_message_processor.h"
#include "anbox/bridge/rpc_channel.h"
#include "anbox/ubuntu/platform_server.h"
#include "anbox/ubuntu/window_creator.h"
@ -89,10 +92,22 @@ anbox::cmds::Run::Run()
rt,
std::make_shared<network::QemuPipeConnectionCreator>(rt, renderer->socket_path()));
auto bridge_connector = std::make_shared<network::PublishedSocketConnector>(
utils::string_format("%s/anbox_bridge", config::data_path()),
rt,
std::make_shared<bridge::ConnectionCreator>(rt,
[](const std::shared_ptr<network::MessageSender> &sender) {
auto pending_calls = std::make_shared<bridge::PendingCallCache>();
auto rpc_channel = std::make_shared<bridge::RpcChannel>(pending_calls, sender);
auto server = std::make_shared<ubuntu::PlatformServer>(pending_calls);
return std::make_shared<bridge::PlatformMessageProcessor>(sender, server, pending_calls);
}));
auto spec = Container::Spec::Default();
spec.rootfs_path = rootfs_;
spec.bind_paths.insert({qemud_connector->socket_file(), "/dev/qemud"});
spec.bind_paths.insert({qemu_pipe_connector->socket_file(), "/dev/qemu_pipe"});
spec.bind_paths.insert({bridge_connector->socket_file(), "/dev/anbox_bridge"});
input_manager->generate_mappings(spec.bind_paths);

View file

@ -15,8 +15,8 @@
*
*/
#ifndef ANBOX_CMDS_RUN_QEMU_H_
#define ANBOX_CMDS_RUN_QEMU_H_
#ifndef ANBOX_CMDS_SHELL_H_
#define ANBOX_CMDS_SHELL_H_
#include <functional>
#include <iostream>

View file

@ -51,7 +51,7 @@ void SocketMessenger::send(char const* data, size_t length)
VariableLengthArray<serialization_buffer_size> whole_message{length};
std::copy(data, data + length, whole_message.data());
while (true) {
for (;;) {
try {
std::unique_lock<std::mutex> lg(message_lock);
ba::write(*socket,
@ -62,10 +62,6 @@ void SocketMessenger::send(char const* data, size_t length)
if (err.code() == boost::asio::error::try_again)
continue;
}
catch (const std::exception &err) {
ERROR("Could not write message: %s", err.what());
}
break;
}
}

View file

@ -0,0 +1,43 @@
option optimize_for = LITE_RUNTIME;
package anbox.protobuf.bridge;
message Invocation {
required uint32 id = 1;
required string method_name = 2;
required bytes parameters = 3;
required uint32 protocol_version = 4;
}
message Result {
optional uint32 id = 1;
optional bytes response = 2;
repeated bytes events = 3;
}
message StructuredError {
optional uint32 domain = 1;
optional uint32 code = 2;
}
message Void {
optional string error = 127;
optional StructuredError structured_error = 128;
}
message Notification {
required string package_name = 1;
required string category = 2;
required string title = 3;
optional string ticker_text = 4;
optional string text = 5;
}
message InstallApplication {
required string path = 1;
}
message LaunchApplication {
required string package_name = 1;
optional string activity = 2;
}

View file

@ -0,0 +1,40 @@
/*
* Copyright © 2012 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Alan Griffiths <alan@octopull.co.uk>
*/
#include <google/protobuf/stubs/common.h>
extern "C" int __attribute__((constructor))
init_google_protobuf()
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
return 0;
}
extern "C" int __attribute__((destructor))
shutdown_google_protobuf()
{
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
// Preserve ABI
namespace anbox { namespace protobuf { void google_protobuf_guard(); }}
void anbox::protobuf::google_protobuf_guard()
{
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "anbox/ubuntu/platform_server.h"
#include "anbox/logger.h"
#include "bridge.pb.h"
namespace anbox {
namespace ubuntu {
PlatformServer::PlatformServer(const std::shared_ptr<bridge::PendingCallCache> &pending_calls) :
bridge::PlatformServer(pending_calls) {
}
PlatformServer::~PlatformServer() {
}
void PlatformServer::handle_notification(anbox::protobuf::bridge::Notification const *request,
anbox::protobuf::bridge::Void *response,
google::protobuf::Closure *done) {
(void) request;
(void) response;
DEBUG("");
done->Run();
}
} // namespace ubuntu
} // namespace anbox

View file

@ -0,0 +1,37 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_UBUNTU_PLATFORM_SERVER_H_
#define ANBOX_UBUNTU_PLATFORM_SERVER_H_
#include "anbox/bridge/platform_server.h"
namespace anbox {
namespace ubuntu {
class PlatformServer : public bridge::PlatformServer {
public:
PlatformServer(const std::shared_ptr<bridge::PendingCallCache> &pending_calls);
virtual ~PlatformServer();
void handle_notification(anbox::protobuf::bridge::Notification const *request,
anbox::protobuf::bridge::Void *response,
google::protobuf::Closure *done) override;
};
} // namespace bridge
} // namespace anbox
#endif