TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / qemu / pipe_connection_creator.cpp
1 /*
2  * Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 3, as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranties of
10  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #include <string>
19
20 #include "anbox/graphics/opengles_message_processor.h"
21 #include "anbox/logger.h"
22 #include "anbox/network/local_socket_messenger.h"
23 #include "anbox/qemu/adb_message_processor.h"
24 #include "anbox/qemu/boot_properties_message_processor.h"
25 #include "anbox/qemu/bootanimation_message_processor.h"
26 #include "anbox/qemu/camera_message_processor.h"
27 #include "anbox/qemu/fingerprint_message_processor.h"
28 #include "anbox/qemu/gsm_message_processor.h"
29 #include "anbox/qemu/hwcontrol_message_processor.h"
30 #include "anbox/qemu/null_message_processor.h"
31 #include "anbox/qemu/pipe_connection_creator.h"
32 #include "anbox/qemu/sensors_message_processor.h"
33
34 namespace ba = boost::asio;
35
36 namespace {
37 std::string client_type_to_string(
38     const anbox::qemu::PipeConnectionCreator::client_type &type) {
39   switch (type) {
40     case anbox::qemu::PipeConnectionCreator::client_type::opengles:
41       return "opengles";
42     case anbox::qemu::PipeConnectionCreator::client_type::qemud_boot_properties:
43       return "boot-properties";
44     case anbox::qemu::PipeConnectionCreator::client_type::qemud_hw_control:
45       return "hw-control";
46     case anbox::qemu::PipeConnectionCreator::client_type::qemud_sensors:
47       return "sensors";
48     case anbox::qemu::PipeConnectionCreator::client_type::qemud_camera:
49       return "camera";
50     case anbox::qemu::PipeConnectionCreator::client_type::qemud_fingerprint:
51       return "fingerprint";
52     case anbox::qemu::PipeConnectionCreator::client_type::qemud_gsm:
53       return "gsm";
54     case anbox::qemu::PipeConnectionCreator::client_type::qemud_adb:
55       return "adb";
56     case anbox::qemu::PipeConnectionCreator::client_type::bootanimation:
57       return "boot-animation";
58     case anbox::qemu::PipeConnectionCreator::client_type::invalid:
59       break;
60     default:
61       break;
62   }
63   return "unknown";
64 }
65 }
66 namespace anbox {
67 namespace qemu {
68 PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr<Renderer> &renderer, const std::shared_ptr<Runtime> &rt)
69     : renderer_(renderer),
70       runtime_(rt),
71       next_connection_id_(0),
72       connections_(
73           std::make_shared<network::Connections<network::SocketConnection>>()) {
74 }
75
76 PipeConnectionCreator::~PipeConnectionCreator() noexcept {
77   connections_->clear();
78 }
79
80 void PipeConnectionCreator::create_connection_for(
81     std::shared_ptr<boost::asio::local::stream_protocol::socket> const
82         &socket) {
83   auto const messenger = std::make_shared<network::LocalSocketMessenger>(socket);
84   const auto type = identify_client(messenger);
85   auto const processor = create_processor(type, messenger);
86   if (!processor)
87     BOOST_THROW_EXCEPTION(std::runtime_error("Unhandled client type"));
88
89   auto const &connection = std::make_shared<network::SocketConnection>(
90       messenger, messenger, next_id(), connections_, processor);
91   connection->set_name(client_type_to_string(type));
92   connections_->add(connection);
93   connection->read_next_message();
94 }
95
96 PipeConnectionCreator::client_type PipeConnectionCreator::identify_client(
97     std::shared_ptr<network::SocketMessenger> const &messenger) {
98   // The client will identify itself as first thing by writing a string
99   // in the format 'pipe:<name>[:<arguments>]\0' to the channel.
100   std::vector<char> buffer;
101   for (;;) {
102     unsigned char byte[1] = {0};
103     const auto err = messenger->receive_msg(ba::buffer(byte, 1));
104     if (err) break;
105     buffer.push_back(byte[0]);
106     if (byte[0] == 0x0) break;
107   }
108
109   std::string identifier_and_args = buffer.data();
110
111   if (utils::string_starts_with(identifier_and_args, "pipe:opengles"))
112     return client_type::opengles;
113   // Even if 'boot-properties' is an argument to the service 'qemud' here we
114   // take this as a own service instance as that is what it is.
115   else if (utils::string_starts_with(identifier_and_args,
116                                      "pipe:qemud:boot-properties"))
117     return client_type::qemud_boot_properties;
118   else if (utils::string_starts_with(identifier_and_args,
119                                      "pipe:qemud:hw-control"))
120     return client_type::qemud_hw_control;
121   else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:sensors"))
122     return client_type::qemud_sensors;
123   else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:camera"))
124     return client_type::qemud_camera;
125   else if (utils::string_starts_with(identifier_and_args,
126                                      "pipe:qemud:fingerprintlisten"))
127     return client_type::qemud_fingerprint;
128   else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:gsm"))
129     return client_type::qemud_gsm;
130   else if (utils::string_starts_with(identifier_and_args,
131                                      "pipe:anbox:bootanimation"))
132     return client_type::bootanimation;
133   else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:adb"))
134     return client_type::qemud_adb;
135
136   return client_type::invalid;
137 }
138
139 std::shared_ptr<network::MessageProcessor>
140 PipeConnectionCreator::create_processor(
141     const client_type &type,
142     const std::shared_ptr<network::SocketMessenger> &messenger) {
143   if (type == client_type::opengles)
144     return std::make_shared<graphics::OpenGlesMessageProcessor>(renderer_, messenger);
145   else if (type == client_type::qemud_boot_properties)
146     return std::make_shared<qemu::BootPropertiesMessageProcessor>(messenger);
147   else if (type == client_type::qemud_hw_control)
148     return std::make_shared<qemu::HwControlMessageProcessor>(messenger);
149   else if (type == client_type::qemud_sensors)
150     return std::make_shared<qemu::SensorsMessageProcessor>(messenger);
151   else if (type == client_type::qemud_camera)
152     return std::make_shared<qemu::CameraMessageProcessor>(messenger);
153   else if (type == client_type::qemud_fingerprint)
154     return std::make_shared<qemu::FingerprintMessageProcessor>(messenger);
155   else if (type == client_type::qemud_gsm)
156     return std::make_shared<qemu::GsmMessageProcessor>(messenger);
157   else if (type == client_type::qemud_adb)
158     return std::make_shared<qemu::AdbMessageProcessor>(runtime_, messenger);
159
160   return std::make_shared<qemu::NullMessageProcessor>();
161 }
162
163 int PipeConnectionCreator::next_id() {
164   return next_connection_id_.fetch_add(1);
165 }
166 }  // namespace qemu
167 }  // namespace anbox