From 9424729586fdb0aabb671d2f1266bdb07e0bed38 Mon Sep 17 00:00:00 2001 From: Gerd v. Egidy Date: Wed, 11 Oct 2006 17:29:49 +0000 Subject: [PATCH] libt2n: (gerd) doxygenize --- src/client.hxx | 2 + src/connection.cpp | 6 +++++ src/connection.hxx | 13 ++++++++++ src/server.cpp | 7 +++-- src/server.hxx | 59 +++++++++++++++++++++++++++++++++++++++-------- src/socket_client.hxx | 10 ++++++++ src/socket_handler.cpp | 21 +++++++++++++++++ src/socket_handler.hxx | 16 ++++++++----- src/socket_server.cpp | 25 ++++++++++++++++---- src/socket_server.hxx | 25 +++++++++++++------ src/types.hxx | 3 ++ 11 files changed, 155 insertions(+), 32 deletions(-) diff --git a/src/client.hxx b/src/client.hxx index 28cded2..293f548 100644 --- a/src/client.hxx +++ b/src/client.hxx @@ -27,6 +27,8 @@ namespace libt2n { +/** @brief a (generic) connection from client to server. Abstract. + */ class client_connection : public connection { public: diff --git a/src/connection.cpp b/src/connection.cpp index 459194d..a1b22a7 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -43,6 +43,11 @@ connection::packet_size_indicator connection::bytes_available() return psize; } +/** @brief read a complete data packet from the buffer. The packet is removed from the + connection buffer. + @param[out] data the data package + @retval true if packet found +*/ bool connection::get_packet(std::string& data) { packet_size_indicator psize; @@ -57,6 +62,7 @@ bool connection::get_packet(std::string& data) return false; } +/// send a blob to the peer void connection::write(const std::string& data) { // prepend packet size to data diff --git a/src/connection.hxx b/src/connection.hxx index 94506e2..633798b 100644 --- a/src/connection.hxx +++ b/src/connection.hxx @@ -24,6 +24,8 @@ namespace libt2n { +/** @brief a connection between client and server. abstact. +*/ class connection { private: @@ -45,14 +47,25 @@ class connection virtual ~connection() { close(); } + /// is this connection closed or not bool is_closed() { return closed; } + /// close this connection virtual void close() { closed=true; } + /** @brief look for new data and store it in the local buffer + @param usec_timeout wait until new data is found, max timeout usecs. + -1: wait endless + NULL: no timeout + @retval true if new data was found (does not mean that the received data + is a complete packet though) + */ virtual bool fill_buffer(long long usec_timeout=-1)=0; bool get_packet(std::string& data); + + /// returns true if a complete data packet is in the buffer. retrieve it with get_packet(). bool packet_available() { return bytes_available(); } diff --git a/src/server.cpp b/src/server.cpp index 3972ef4..20cce1e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -52,11 +52,11 @@ int server::add_connection(server_connection* newconn) } /** - Gets a connection by id + @brief Gets a connection by id - \param conn_id Connection ID + @param conn_id Connection ID - \retval Pointer to connection object + @retval Pointer to connection object */ server_connection* server::get_connection(unsigned int conn_id) { @@ -67,6 +67,7 @@ server_connection* server::get_connection(unsigned int conn_id) return p->second; } +/// check for timeouts, remove closed connections. don't forget to call this from time to time. void server::cleanup() { std::map::iterator ie=connections.end(); diff --git a/src/server.hxx b/src/server.hxx index 7e496d9..786770f 100644 --- a/src/server.hxx +++ b/src/server.hxx @@ -32,15 +32,26 @@ namespace libt2n class server; /** - Basic connection class + @brief connection on a server + + on a server every connection to a client is represented as server_connection. + a server_connection is abstract, derived classes like socket_server_connection are used. */ class server_connection : public connection { + friend class server; + private: int timeout; int last_action_time; unsigned int connection_id; + void set_server(server* _my_server) + { my_server=_my_server; } + + void set_id(unsigned int _connection_id) + { connection_id=_connection_id; } + protected: server_connection(int _timeout) : connection() @@ -54,22 +65,24 @@ class server_connection : public connection server *my_server; public: + /// check if timeout is expired, close connection if so void check_timeout(); + + /// reset the timeout, e.g. if something is received void reset_timeout(); + void set_timeout(int _timeout) { timeout=_timeout; } - void set_server(server* _my_server) - { my_server=_my_server; } - - void set_id(unsigned int _connection_id) - { connection_id=_connection_id; } + /// get the id of this connection within the server object unsigned int get_id() { return connection_id; } }; /** - Basic server class + @brief server base class + + constitutes a server. is abstract, use derived classes like socket_server. */ class server { @@ -90,16 +103,22 @@ class server next_id=1; } + virtual bool fill_connection_buffers(void)=0; + int add_connection(server_connection* newconn); public: virtual ~server(); + /// set the default timeout for new client connections void set_default_timeout(int _default_timeout) { default_timeout=_default_timeout; } + + /// get the current default timeout for client connections int get_default_timeout(void) { return default_timeout; } + /// activate logging to the given stream. everything above the given level is logged. void set_logging(std::ostream *_logstream, log_level_values _log_level) { log_level=_log_level; @@ -108,17 +127,37 @@ class server server_connection* get_connection(unsigned int conn_id); - virtual void fill_buffer(long long usec_timeout=-1)=0; + /** @brief look for new data on all open connections, accept new connections + @param usec_timeout wait until new data is found, max timeout usecs. + -1: wait endless + NULL: no timeout + @retval true if new data was found (does not mean that the received data + is a complete packet though) + */ + virtual bool fill_buffer(long long usec_timeout=-1)=0; + void cleanup(); + /** @brief get a complete data packet from any client. The packet is removed from the + connection buffer. + @param[out] data the data package + @retval true if packet found + */ bool get_packet(std::string& data) { unsigned int x; return get_packet(data,x); } - bool get_packet(std::string& data, unsigned int& conn_id); - virtual void fill_connection_buffers(void)=0; + /** @brief get a complete data packet from any client. The packet is removed from the + connection buffer. + @param[out] data the data package + @param[out] conn_id the connection id we got this packet from + @retval true if packet found + */ + bool get_packet(std::string& data, unsigned int& conn_id); + /// write a message to the log if logging is enabled void log(log_level_values level, const std::string& message) { log(level,message.c_str()); } + /// write a message to the log if logging is enabled void log(log_level_values level, const char* message); }; diff --git a/src/socket_client.hxx b/src/socket_client.hxx index a17ec88..8a379f8 100644 --- a/src/socket_client.hxx +++ b/src/socket_client.hxx @@ -24,7 +24,10 @@ namespace libt2n { +/** @brief a connection from client to server using sockets. + Use this class to connect from a client to a server. + */ class socket_client_connection : public client_connection, public socket_handler { static const int max_retries_default=3; @@ -45,6 +48,13 @@ class socket_client_connection : public client_connection, public socket_handler socket_client_connection(const std::string& _server, int _port, int _max_retries=max_retries_default); socket_client_connection(const std::string& _path, int _max_retries=max_retries_default); + /** @brief read data from the socket and copy it into buffer + @param usec_timeout wait until new data is found, max timeout usecs. + -1: wait endless + NULL: no timeout + @retval true if new data was found (does not mean that the received data + is a complete packet though) + */ bool fill_buffer(long long usec_timeout=-1) { return socket_handler::fill_buffer(buffer,usec_timeout); } diff --git a/src/socket_handler.cpp b/src/socket_handler.cpp index f2ddcb6..2856adf 100644 --- a/src/socket_handler.cpp +++ b/src/socket_handler.cpp @@ -44,6 +44,7 @@ using namespace std; namespace libt2n { +/// set options like fast reuse and keepalive every socket should have void socket_handler::set_socket_options(int sock) { int i=1; @@ -105,6 +106,8 @@ void socket_handler::set_socket_options(int sock) } } +/// close the underlying socket connection. Don't call directly, use the version provided +/// by the connection class you are using. void socket_handler::close() { // graceful shutdown @@ -112,6 +115,7 @@ void socket_handler::close() ::close(sock); } +/// is the underlying socket connection still open? bool socket_handler::is_closed() { int r=fcntl(sock,F_GETFL); @@ -119,6 +123,11 @@ bool socket_handler::is_closed() return !(r & O_ACCMODE); } +/** @brief check if new data is waiting on the raw socket + @param usec_timeout wait until new data is found, max timeout usecs. + -1: wait endless + NULL: no timeout +*/ bool socket_handler::data_waiting(long long usec_timeout) { // just our socket @@ -147,6 +156,12 @@ bool socket_handler::data_waiting(long long usec_timeout) return false; } +/** @brief read data from the raw socket and copy it into the provided buffer + @param buffer the buffer where to append the new data + @param usec_timeout wait until new data is found, max timeout usecs. + -1: wait endless + NULL: no timeout +*/ bool socket_handler::fill_buffer(std::string& buffer, long long usec_timeout) { // fast path for timeout==0 @@ -156,6 +171,10 @@ bool socket_handler::fill_buffer(std::string& buffer, long long usec_timeout) return false; } +/** @brief read data from the raw socket and copy it into the provided buffer. Returns + instantly if no data is waiting. + @param buffer the buffer where to append the new data +*/ bool socket_handler::fill_buffer(std::string& buffer) { bool try_again=false; @@ -201,6 +220,8 @@ bool socket_handler::fill_buffer(std::string& buffer) return false; } +/// writes raw data to the socket. Don't use directly, use the write() function provided by the +/// connection because it encapsulates the data. void socket_handler::socket_write(const std::string& data) { int offset = 0; diff --git a/src/socket_handler.hxx b/src/socket_handler.hxx index 832fa3a..8ea65a1 100644 --- a/src/socket_handler.hxx +++ b/src/socket_handler.hxx @@ -24,6 +24,9 @@ namespace libt2n { +/** @brief handles socket based communication. + Don't use directly, use socket_server or socket_client_connection instead. +*/ class socket_handler { private: @@ -47,18 +50,19 @@ class socket_handler virtual void log(log_level_values level, const char* message) { return; } - public: - socket_type_value get_type() - { return socket_type; } + void socket_write(const std::string& data); + + virtual void close(); bool fill_buffer(std::string& buffer, long long usec_timeout); bool fill_buffer(std::string& buffer); - virtual void close(); + public: + /// is this a tcp or udp socket connection + socket_type_value get_type() + { return socket_type; } bool is_closed(); - - void socket_write(const std::string& data); }; } diff --git a/src/socket_server.cpp b/src/socket_server.cpp index cbaaff6..87025d8 100644 --- a/src/socket_server.cpp +++ b/src/socket_server.cpp @@ -43,12 +43,22 @@ using namespace std; namespace libt2n { +/** @brief create a new tcp-based server + @param port tcp port you want to listen on + @param ip the local ip you want to listen on. "0.0.0.0" means all local ips (default). +*/ socket_server::socket_server(int port, const std::string& ip) : server(), socket_handler(0,tcp_s) { // TODO } +/** @brief create a new unix-socked-based server + @param path path of the socket + @param filemode permissions you want to open the socket with + @param user local username for the socket + @param group local groupname for the socket +*/ socket_server::socket_server(const std::string& path, mode_t filemode, const std::string& user, const std::string& group) : server(), socket_handler(0,unix_s) { @@ -174,7 +184,7 @@ void socket_server::new_connection() return; } -void socket_server::fill_buffer(long long usec_timeout) +bool socket_server::fill_buffer(long long usec_timeout) { fd_set used_fdset=connection_set; @@ -222,18 +232,23 @@ void socket_server::fill_buffer(long long usec_timeout) } // check all connections for pending data - fill_connection_buffers(); + return fill_connection_buffers(); } - return; + return false; } -void socket_server::fill_connection_buffers() +bool socket_server::fill_connection_buffers() { + bool data_found; + std::map::iterator ie=connections.end(); for(std::map::iterator i=connections.begin(); i != ie; i++) if (!i->second->server_connection::is_closed()) - i->second->fill_buffer(0); + if (i->second->fill_buffer(0)) + data_found=true; + + return data_found; } void socket_server::remove_connection_socket(int sock) diff --git a/src/socket_server.hxx b/src/socket_server.hxx index 5dcf4f3..a72ae48 100644 --- a/src/socket_server.hxx +++ b/src/socket_server.hxx @@ -29,17 +29,28 @@ namespace libt2n { -/** - Socket based server class +class socket_server_connection; + +/** @brief Socket based server class + + Use this class to instantiate a server listening for client connections. + Call fill_buffer() to read data from the network and get_packet() to retrieve + this data. Don't forget to call cleanup() from time to time to remove closed + connections and close idle ones. */ class socket_server : public socket_handler, public server { + friend class socket_server_connection; + private: fd_set connection_set; std::string unix_path; void new_connection(); + bool fill_connection_buffers(); + void remove_connection_socket(int sock); + protected: void log(log_level_values level, const std::string& message) { log(level,message.c_str()); } @@ -52,14 +63,12 @@ class socket_server : public socket_handler, public server ~socket_server(); - void fill_buffer(long long usec_timeout=-1); - void fill_connection_buffers(); - - void remove_connection_socket(int sock); + bool fill_buffer(long long usec_timeout=-1); }; -/** - Socket based connection class +/** @brief Socket based connection + + This class is used within a socket_server to represent the connection to each client. */ class socket_server_connection : public socket_handler, public server_connection { diff --git a/src/types.hxx b/src/types.hxx index 6ccad82..3053dc5 100644 --- a/src/types.hxx +++ b/src/types.hxx @@ -22,7 +22,10 @@ namespace libt2n { +/// possible levels for logging enum log_level_values { none=0, error=1, debug=2 }; + +/// possible types of a socket (tcp and unix) enum socket_type_value { tcp_s, unix_s }; } -- 1.7.1