PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/libs/protobuf_comm/server.h

https://gitlab.com/F34140r/rockin-refbox
C Header | 200 lines | 109 code | 35 blank | 56 comment | 0 complexity | 1b4c50efd0dae2abecc8c78ff4e6c786 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /***************************************************************************
  2. * server.h - Protobuf stream protocol - server
  3. *
  4. * Created: Wed Jan 30 16:41:22 2013
  5. * Copyright 2013 Tim Niemueller [www.niemueller.de]
  6. ****************************************************************************/
  7. /* Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * - Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * - Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * - Neither the name of the authors nor the names of its contributors
  18. * may be used to endorse or promote products derived from this
  19. * software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  26. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  28. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  30. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  32. * OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #ifndef __PROTOBUF_COMM_SERVER_H_
  35. #define __PROTOBUF_COMM_SERVER_H_
  36. #include <protobuf_comm/frame_header.h>
  37. #include <protobuf_comm/message_register.h>
  38. #include <protobuf_comm/queue_entry.h>
  39. #include <boost/asio.hpp>
  40. #include <boost/signals2.hpp>
  41. #include <boost/enable_shared_from_this.hpp>
  42. #include <google/protobuf/message.h>
  43. #ifndef _GLIBCXX_USE_SCHED_YIELD
  44. # define _GLIBCXX_USE_SCHED_YIELD
  45. #endif
  46. #include <thread>
  47. #include <mutex>
  48. #include <queue>
  49. #include <atomic>
  50. namespace protobuf_comm {
  51. #if 0 /* just to make Emacs auto-indent happy */
  52. }
  53. #endif
  54. class ProtobufStreamServer
  55. {
  56. public:
  57. /** ID to identify connected clients. */
  58. typedef unsigned int ClientID;
  59. ProtobufStreamServer(unsigned short port);
  60. ProtobufStreamServer(unsigned short port, std::vector<std::string> &proto_path);
  61. ProtobufStreamServer(unsigned short port, MessageRegister *mr);
  62. ~ProtobufStreamServer();
  63. void send(ClientID client, uint16_t component_id, uint16_t msg_type,
  64. google::protobuf::Message &m);
  65. void send(ClientID client, uint16_t component_id, uint16_t msg_type,
  66. std::shared_ptr<google::protobuf::Message> m);
  67. void send(ClientID client, std::shared_ptr<google::protobuf::Message> m);
  68. void send(ClientID client, google::protobuf::Message &m);
  69. void send_to_all(uint16_t component_id, uint16_t msg_type,
  70. google::protobuf::Message &m);
  71. void send_to_all(uint16_t component_id, uint16_t msg_type,
  72. std::shared_ptr<google::protobuf::Message> m);
  73. void send_to_all(std::shared_ptr<google::protobuf::Message> m);
  74. void send_to_all(google::protobuf::Message &m);
  75. void disconnect(ClientID client);
  76. /** Get the server's message register.
  77. * @return message register
  78. */
  79. MessageRegister & message_register()
  80. { return *message_register_; }
  81. /** Signal that is invoked when a message has been received.
  82. * @return signal
  83. */
  84. boost::signals2::signal<void (ClientID, uint16_t, uint16_t,
  85. std::shared_ptr<google::protobuf::Message>)> &
  86. signal_received() { return sig_rcvd_; }
  87. /** Signal that is invoked when receiving a message failed.
  88. * @return signal
  89. */
  90. boost::signals2::signal<void (ClientID, uint16_t, uint16_t, std::string)> &
  91. signal_receive_failed() { return sig_recv_failed_; }
  92. /** Signal that is invoked when a new client has connected.
  93. * @return signal
  94. */
  95. boost::signals2::signal<void (ClientID, boost::asio::ip::tcp::endpoint &)> &
  96. signal_connected() { return sig_connected_; }
  97. /** Signal that is invoked when a new client has disconnected.
  98. * @return signal
  99. */
  100. boost::signals2::signal<void (ClientID, const boost::system::error_code &)> &
  101. signal_disconnected() { return sig_disconnected_; }
  102. private:
  103. class Session : public boost::enable_shared_from_this<Session>
  104. {
  105. public:
  106. /** Shortcut for shared pointer of session. */
  107. typedef boost::shared_ptr<Session> Ptr;
  108. Session(ClientID id, ProtobufStreamServer *parent,
  109. boost::asio::io_service &io_service);
  110. ~Session();
  111. /** Get underlying socket.
  112. * @return socket */
  113. boost::asio::ip::tcp::socket & socket() { return socket_; }
  114. /** Get client ID.
  115. * @return client ID */
  116. ClientID id() const { return id_; }
  117. /** Get client's endpoint.
  118. * @return remote client's endpoint */
  119. boost::asio::ip::tcp::endpoint & remote_endpoint()
  120. { return remote_endpoint_; }
  121. void start_session();
  122. void start_read();
  123. void send(uint16_t component_id, uint16_t msg_type,
  124. google::protobuf::Message &m);
  125. void disconnect();
  126. private:
  127. void handle_read_message(const boost::system::error_code& error);
  128. void handle_read_header(const boost::system::error_code& error);
  129. void handle_write(const boost::system::error_code& error,
  130. size_t /*bytes_transferred*/, QueueEntry *entry);
  131. private:
  132. ClientID id_;
  133. ProtobufStreamServer *parent_;
  134. boost::asio::ip::tcp::socket socket_;
  135. boost::asio::ip::tcp::endpoint remote_endpoint_;
  136. frame_header_t in_frame_header_;
  137. size_t in_data_size_;
  138. void * in_data_;
  139. std::queue<QueueEntry *> outbound_queue_;
  140. std::mutex outbound_mutex_;
  141. bool outbound_active_;
  142. };
  143. private: // methods
  144. void run_asio();
  145. void start_accept();
  146. void handle_accept(Session::Ptr new_session, const boost::system::error_code& error);
  147. void disconnected(boost::shared_ptr<Session> session,
  148. const boost::system::error_code &error);
  149. private: // members
  150. boost::asio::io_service io_service_;
  151. boost::asio::ip::tcp::acceptor acceptor_;
  152. boost::signals2::signal<void (ClientID, uint16_t, uint16_t,
  153. std::shared_ptr<google::protobuf::Message>)> sig_rcvd_;
  154. boost::signals2::signal<void (ClientID, uint16_t, uint16_t, std::string)> sig_recv_failed_;
  155. boost::signals2::signal<void (ClientID, boost::asio::ip::tcp::endpoint &)> sig_connected_;
  156. boost::signals2::signal<void (ClientID, const boost::system::error_code &)>
  157. sig_disconnected_;
  158. std::thread asio_thread_;
  159. std::map<ClientID, boost::shared_ptr<Session>> sessions_;
  160. std::atomic<ClientID> next_cid_;
  161. MessageRegister *message_register_;
  162. bool own_message_register_;
  163. };
  164. } // end namespace protobuf_comm
  165. #endif