blob: 38587a1eb720078b927579b3a55b67cc0759c55d [file] [log] [blame]
// 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_