TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / rpc / channel.cpp
1 /*
2  * Copyright © 2012 Canonical Ltd.
3  *           © 2016 Simon Fels <morphis@gravedo.de>
4  *
5  * This program is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License version 3,
7  * as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Authored by: Alan Griffiths <alan@octopull.co.uk>
18  */
19
20 #include "anbox/rpc/channel.h"
21 #include "anbox/common/variable_length_array.h"
22 #include "anbox/network/message_sender.h"
23 #include "anbox/rpc/constants.h"
24 #include "anbox/rpc/pending_call_cache.h"
25
26 #include "anbox_rpc.pb.h"
27
28 namespace anbox {
29 namespace rpc {
30 Channel::Channel(const std::shared_ptr<PendingCallCache> &pending_calls,
31                  const std::shared_ptr<network::MessageSender> &sender)
32     : pending_calls_(pending_calls), sender_(sender) {}
33
34 Channel::~Channel() {}
35
36 void Channel::call_method(std::string const &method_name,
37                           google::protobuf::MessageLite const *parameters,
38                           google::protobuf::MessageLite *response,
39                           google::protobuf::Closure *complete) {
40   auto const &invocation = invocation_for(method_name, parameters);
41   pending_calls_->save_completion_details(invocation, response, complete);
42   send_message(MessageType::invocation, invocation);
43 }
44
45 void Channel::send_event(google::protobuf::MessageLite const &event) {
46   VariableLengthArray<2048> buffer{static_cast<size_t>(event.ByteSize())};
47   event.SerializeWithCachedSizesToArray(buffer.data());
48
49   anbox::protobuf::rpc::Result response;
50   response.add_events(buffer.data(), buffer.size());
51
52   send_message(MessageType::response, response);
53 }
54
55 protobuf::rpc::Invocation Channel::invocation_for(
56     std::string const &method_name,
57     google::protobuf::MessageLite const *request) {
58   anbox::VariableLengthArray<2048> buffer{
59       static_cast<size_t>(request->ByteSize())};
60
61   request->SerializeWithCachedSizesToArray(buffer.data());
62
63   anbox::protobuf::rpc::Invocation invoke;
64
65   invoke.set_id(next_id());
66   invoke.set_method_name(method_name);
67   invoke.set_parameters(buffer.data(), buffer.size());
68   invoke.set_protocol_version(1);
69
70   return invoke;
71 }
72
73 void Channel::send_message(const std::uint8_t &type,
74                            google::protobuf::MessageLite const &message) {
75   const size_t size = message.ByteSize();
76   const unsigned char header_bytes[header_size] = {
77       static_cast<unsigned char>((size >>16) & 0xff),
78       static_cast<unsigned char>((size >> 8) & 0xff),
79       static_cast<unsigned char>((size >> 0) & 0xff), type,
80   };
81
82   std::vector<std::uint8_t> send_buffer(sizeof(header_bytes) + size);
83   std::copy(header_bytes, header_bytes + sizeof(header_bytes),
84             send_buffer.begin());
85   message.SerializeToArray(send_buffer.data() + sizeof(header_bytes), size);
86
87   try {
88     std::lock_guard<std::mutex> lock(write_mutex_);
89     sender_->send(reinterpret_cast<const char *>(send_buffer.data()),
90                   send_buffer.size());
91   } catch (std::runtime_error const &) {
92     notify_disconnected();
93     throw;
94   }
95 }
96
97 void Channel::notify_disconnected() { pending_calls_->force_completion(); }
98
99 std::uint32_t Channel::next_id() {
100   static std::uint32_t next_message_id = 0;
101   return next_message_id++;
102 }
103 }  // namespace rpc
104 }  // namespace anbox