TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / rpc / channel.cpp
diff --git a/src/type3_AndroidCloud/anbox-master/src/anbox/rpc/channel.cpp b/src/type3_AndroidCloud/anbox-master/src/anbox/rpc/channel.cpp
new file mode 100644 (file)
index 0000000..b0c2ead
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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/rpc/channel.h"
+#include "anbox/common/variable_length_array.h"
+#include "anbox/network/message_sender.h"
+#include "anbox/rpc/constants.h"
+#include "anbox/rpc/pending_call_cache.h"
+
+#include "anbox_rpc.pb.h"
+
+namespace anbox {
+namespace rpc {
+Channel::Channel(const std::shared_ptr<PendingCallCache> &pending_calls,
+                 const std::shared_ptr<network::MessageSender> &sender)
+    : pending_calls_(pending_calls), sender_(sender) {}
+
+Channel::~Channel() {}
+
+void Channel::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(MessageType::invocation, invocation);
+}
+
+void Channel::send_event(google::protobuf::MessageLite const &event) {
+  VariableLengthArray<2048> buffer{static_cast<size_t>(event.ByteSize())};
+  event.SerializeWithCachedSizesToArray(buffer.data());
+
+  anbox::protobuf::rpc::Result response;
+  response.add_events(buffer.data(), buffer.size());
+
+  send_message(MessageType::response, response);
+}
+
+protobuf::rpc::Invocation Channel::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::rpc::Invocation invoke;
+
+  invoke.set_id(next_id());
+  invoke.set_method_name(method_name);
+  invoke.set_parameters(buffer.data(), buffer.size());
+  invoke.set_protocol_version(1);
+
+  return invoke;
+}
+
+void Channel::send_message(const std::uint8_t &type,
+                           google::protobuf::MessageLite const &message) {
+  const size_t size = message.ByteSize();
+  const unsigned char header_bytes[header_size] = {
+      static_cast<unsigned char>((size >>16) & 0xff),
+      static_cast<unsigned char>((size >> 8) & 0xff),
+      static_cast<unsigned char>((size >> 0) & 0xff), type,
+  };
+
+  std::vector<std::uint8_t> send_buffer(sizeof(header_bytes) + size);
+  std::copy(header_bytes, header_bytes + sizeof(header_bytes),
+            send_buffer.begin());
+  message.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 Channel::notify_disconnected() { pending_calls_->force_completion(); }
+
+std::uint32_t Channel::next_id() {
+  static std::uint32_t next_message_id = 0;
+  return next_message_id++;
+}
+}  // namespace rpc
+}  // namespace anbox