OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-cogserver / opencog / network / ServerSocket.h

156 lines · c ref:
/*
 * opencog/network/ServerSocket.h
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Written by Welter Luigi <welter@vettalabs.com>
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

#ifndef _OPENCOG_SERVER_SOCKET_H
#define _OPENCOG_SERVER_SOCKET_H

#include <atomic>
#include <pthread.h>
#include <asio.hpp>

namespace opencog
{

class SocketManager;

/** \addtogroup grp_server
 *  @{
 */

/**
 * An instance of this class is created when a network client connects
 * to the server. It handles all socket read/write for that client.
 *
 * When a client connects to the server, the ServerSocket::handle_connection()
 * method is called in a new thread (and thus all socket reads for that
 * client occur in this thread.)
 *
 * This class has two pure-virtual methods: OnConnection() and OnLine().
 * The OnConnection() method is called once, when the reader thread is
 * first entered.  The OnLine() method is called whenever a new-line
 * delimited bit of utf-8 text data arrives on the socket.
 *
 * Users of this class need only implement these two methods.
 *
 * This class exists only to hide the ugliness of asio. Some day
 * in the future, this should be re-written to avoid using asio!
 * But for now, it's stable debugged and it works.
 */
class ServerSocket
{
private:
    // The actual socket on which data comes & goes.
    asio::ip::tcp::socket* _socket;

    // Socket manager handles registration and coordination
    SocketManager* _socket_manager;

    // Read a newline-delimited line of text from socket.
    std::string get_telnet_line(asio::streambuf&);

    // Read _content_length bytes
    std::string get_http_body(asio::streambuf&);

    // Send an asio buffer that has data in it.
    void Send(const asio::const_buffer&);

    // WebSocket state machine; unused in the telnet interface.
    bool _got_first_line;
    bool _got_http_header;
    bool _do_frame_io;
    std::string _webkey;
    void HandshakeLine(const std::string&);
    std::string get_websocket_data(void);
    std::string get_websocket_line(void);
    void send_websocket_pong(void);
    void send_websocket(const std::string&);

protected:
    // WebSocket stuff that users will be interested in.
    bool _is_http_socket;
    bool _got_websock_header;
    bool _is_mcp_socket;

    // KeepAlive connections will repeatedly send HTTP headers.
    bool _keep_alive;

    bool _in_barrier;

    size_t _content_length;

    std::string _url;
    std::string _host_header;  // Host header from HTTP request

    /**
     * Connection callback: called whenever a new connection arrives
     */
    virtual void OnConnection(void) = 0;

    /**
     * Callback: called when a client has sent us a line of text.
     */
    virtual void OnLine (const std::string&) = 0;

    /**
     * Report human-readable stats for this socket.
     */
    time_t _start_time;
    pid_t _tid;    // OS-dependent thread ID.
    pthread_t _pth;
    const char* _status; // "start" or "run" or "close"
    time_t _last_activity;
    size_t _line_count;

    virtual std::string connection_header(void);
    virtual std::string connection_stats(void);
public:
    ServerSocket(SocketManager*);
    virtual ~ServerSocket();
    void act_as_http_socket(void) { _is_http_socket = true; }
    void act_as_mcp(void) { _is_mcp_socket = true; }

    // Access to socket manager for derived classes
    SocketManager* get_socket_manager() { return _socket_manager; }

    void set_connection(asio::ip::tcp::socket*);
    void handle_connection(void);

    /**
     * Send data to the client.
     */
    void Send(const std::string&);

    /**
     * Close this socket. Called from a thread other than
     * the one that is actually polling the socket.
     */
    void Exit(void);

    /** Total line count, handled by all sockets, ever. */
    static std::atomic_size_t total_line_count;

    /** Status string constants */
    static char START[6];
    static char BLOCK[6];
    static char IWAIT[6];
    static char QUING[6];
    static char BAR[6];
    static char DTOR[6];
    static char CLOSE[6];
    static char DOWN[6];

    // Expose frequently-needed socket manager operations
    // These delegate to the socket manager for this socket
    friend class SocketManager;
}; // class

/** @}*/
}  // namespace

#endif // _OPENCOG_SERVER_SOCKET_H