X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fsrc%2Fanbox%2Fnetwork%2Fbase_socket_messenger.cpp;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fsrc%2Fanbox%2Fnetwork%2Fbase_socket_messenger.cpp;h=23efc7871755e2d1371ad885fd01333c88d0243b;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/src/anbox/network/base_socket_messenger.cpp b/src/type3_AndroidCloud/anbox-master/src/anbox/network/base_socket_messenger.cpp new file mode 100644 index 0000000..23efc78 --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/src/anbox/network/base_socket_messenger.cpp @@ -0,0 +1,157 @@ +/* + * Copyright © 2013-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 . + * + * Authored by: Kevin DuBois + */ + +#include "anbox/network/base_socket_messenger.h" +#include "anbox/common/variable_length_array.h" +#include "anbox/logger.h" + +#include + +#include +#include + +#include + +namespace bs = boost::system; +namespace ba = boost::asio; + +namespace { +/// Buffers need to be big enough to support messages +unsigned int const serialization_buffer_size = 2048; +} + +namespace anbox { +namespace network { +template +BaseSocketMessenger::BaseSocketMessenger() {} + +template +BaseSocketMessenger::BaseSocketMessenger( + std::shared_ptr> const& socket) { + setup(socket); +} + +template +BaseSocketMessenger::~BaseSocketMessenger() {} + +template +void BaseSocketMessenger::setup( + std::shared_ptr> const& s) { + socket = s; + socket_fd = anbox::Fd{IntOwnedFd{socket->native_handle()}}; + socket->non_blocking(true); + boost::asio::socket_base::send_buffer_size option(64 * 1024); + socket->set_option(option); +} + +template +Credentials BaseSocketMessenger::creds() const { + struct ucred cr; + socklen_t cl = sizeof(cr); + + auto status = getsockopt(socket_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl); + + if (status) + BOOST_THROW_EXCEPTION( + std::runtime_error("Failed to query client socket credentials")); + + return {cr.pid, cr.uid, cr.gid}; +} + +template +ssize_t BaseSocketMessenger::send_raw(char const* data, + size_t length) { + VariableLengthArray whole_message{length}; + std::copy(data, data + length, whole_message.data()); + + std::unique_lock lg(message_lock); + return ::send(socket_fd, data, length, MSG_NOSIGNAL); +} + +template +void BaseSocketMessenger::send(char const* data, + size_t length) { + VariableLengthArray whole_message{length}; + std::copy(data, data + length, whole_message.data()); + + for (;;) { + try { + std::unique_lock lg(message_lock); + ba::write(*socket, ba::buffer(whole_message.data(), whole_message.size()), + boost::asio::transfer_all()); + } catch (const boost::system::system_error& err) { + if (err.code() == boost::asio::error::try_again) continue; + throw; + } + break; + } +} + +template +void BaseSocketMessenger::async_receive_msg( + AnboxReadHandler const& handler, ba::mutable_buffers_1 const& buffer) { + socket->async_read_some(buffer, handler); +} + +template +bs::error_code BaseSocketMessenger::receive_msg( + ba::mutable_buffers_1 const& buffer) { + bs::error_code e; + size_t nread = 0; + + while (nread < ba::buffer_size(buffer)) { + nread += + boost::asio::read(*socket, ba::mutable_buffers_1{buffer + nread}, e); + + if (e && e != ba::error::would_block) break; + } + + return e; +} + +template +size_t BaseSocketMessenger::available_bytes() { + boost::asio::socket_base::bytes_readable command{true}; + socket->io_control(command); + return command.get(); +} + +template +unsigned short BaseSocketMessenger::local_port() const { + return 0; +} + +template +void BaseSocketMessenger::set_no_delay() { + const auto fd = socket->native_handle(); + int flag = 1; + const auto ret = + ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(&flag), sizeof(flag)); + if (ret < 0) WARNING("Failed to disable TCP delay for socket"); +} + +template +void BaseSocketMessenger::close() { + socket->close(); +} + +template class BaseSocketMessenger; +template class BaseSocketMessenger; +} // namespace network +} // namespace anbox