| // Copyright 2018 The Fuchsia Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | #ifndef SRC_DEVELOPER_DEBUG_DEBUG_AGENT_SOCKET_CONNECTION_H_ | 
 | #define SRC_DEVELOPER_DEBUG_DEBUG_AGENT_SOCKET_CONNECTION_H_ | 
 |  | 
 | #include "lib/sys/cpp/service_directory.h" | 
 | #include "src/developer/debug/debug_agent/remote_api_adapter.h" | 
 | #include "src/developer/debug/shared/buffered_fd.h" | 
 | #include "src/developer/debug/shared/platform_message_loop.h" | 
 |  | 
 | namespace debug_agent { | 
 |  | 
 | class DebugAgent; | 
 | class SocketConnection; | 
 |  | 
 | // SocketServer ------------------------------------------------------------------------------------ | 
 | // | 
 | // Listens for connections on a socket. Only one connection is supported at a | 
 | // time. It waits for connections in a blocking fashion, and then runs the | 
 | // message loop on that connection. | 
 | // | 
 | // IMPORTANT: This class is being used to accept connections on a background thread in order to let | 
 | //            the message loop run. But a lot of code (from the DebugAgent down) assumes that it's | 
 | //            running on the main thread, so it's important to know on which thread each call is | 
 | //            made. | 
 | // | 
 | //            The criteria is as follows: | 
 | // | 
 | //            Only call Run on background thread. | 
 | //            All other must be called on the main thread. | 
 | // | 
 | // NOTE: No synchronization is needed because all the connection/agent management occurs on the | 
 | //       main thread. The only thing that's done on the background thread is accepting the | 
 | //       connection. After that, the actual agent creation is posted to the message loop. | 
 | class SocketServer { | 
 |  public: | 
 |   SocketServer() = default; | 
 |  | 
 |   // All fields of |config| must be correctly set. | 
 |   // | 
 |   // IMPORTANT: Only this can be called on another thread. | 
 |   //            We use |main_thread_loop| to post a task that actually creates the debug agent on | 
 |   //            the main thread after the connection has been made. This is because the agent has a | 
 |   //            lot of assumptions of being run on the thread of the message loop. | 
 |   struct ConnectionConfig { | 
 |     debug_ipc::PlatformMessageLoop* message_loop = nullptr; | 
 |     debug_agent::DebugAgent* debug_agent = nullptr; | 
 |     int port = 0; | 
 |   }; | 
 |   void Run(ConnectionConfig config); | 
 |  | 
 |   // IMPORTANT: All others can only be called on the main thread. | 
 |  | 
 |   bool Init(uint16_t port); | 
 |   // Call before consecutive calls to |Run|. | 
 |   void Reset(); | 
 |  | 
 |   bool connected() const { return !!connection_; } | 
 |  | 
 |  private: | 
 |   fbl::unique_fd server_socket_; | 
 |   std::unique_ptr<SocketConnection> connection_; | 
 |  | 
 |   FXL_DISALLOW_COPY_AND_ASSIGN(SocketServer); | 
 | }; | 
 |  | 
 | // Socket Connection ------------------------------------------------------------------------------- | 
 | // | 
 | // Represents a instance of a connection "attempt" to a client. | 
 | // It owns a DebugAgent, which is currently always associated to one connection. | 
 | class SocketConnection { | 
 |  public: | 
 |   SocketConnection(debug_agent::DebugAgent*); | 
 |   ~SocketConnection(); | 
 |  | 
 |   // |main_thread_loop| is used for posting a task that creates the debug agent after accepting a | 
 |   // a connection. This is because the debug agent assumes it's running on the message loop's | 
 |   // thread. | 
 |   bool Accept(debug_ipc::MessageLoop* main_thread_loop, int server_fd); | 
 |  | 
 |  private: | 
 |   debug_agent::DebugAgent* debug_agent_ = nullptr; | 
 |  | 
 |   std::unique_ptr<debug_agent::RemoteAPIAdapter> adapter_; | 
 |   debug_ipc::BufferedFD buffer_; | 
 |   bool connected_ = false; | 
 |  | 
 |   FXL_DISALLOW_COPY_AND_ASSIGN(SocketConnection); | 
 | }; | 
 |  | 
 | }  // namespace debug_agent | 
 |  | 
 | #endif  // SRC_DEVELOPER_DEBUG_DEBUG_AGENT_SOCKET_CONNECTION_H_ |