| // 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::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::MessageLoop* main_thread_loop, int server_fd); | |
| private: | |
| debug_agent::DebugAgent* debug_agent_ = nullptr; | |
| std::unique_ptr<debug_agent::RemoteAPIAdapter> adapter_; | |
| std::unique_ptr<debug::BufferedFD> buffer_; | |
| bool connected_ = false; | |
| FXL_DISALLOW_COPY_AND_ASSIGN(SocketConnection); | |
| }; | |
| } // namespace debug_agent | |
| #endif // SRC_DEVELOPER_DEBUG_DEBUG_AGENT_SOCKET_CONNECTION_H_ |