/** * $Id: small_socket.h,v 1.18 2002/10/21 08:37:22 plasmahh Exp $ * $Revision: 1.18 $ * $Author: plasmahh $ * $Date: 2002/10/21 08:37:22 $ */ #ifndef __SMALL_SOCKET_H #define __SMALL_SOCKET_H extern "C" { #include #include #include // For NetBSD compatibility #include #include #include #include #include } #ifndef __EXCEPTION_H #include #endif #define _DEFAULT_TIMEOUT 3000 /** * @brief basic socket class * This class implements a basic tcp/ip socket commuication interface. This * will be a good choice if you don't need special socket functions, but only * want to commuicate to i.e. a HTTP or SMTP server * @note On some Operating Systems, this has to be linked to some additional * libraries to function properly ! */ class small_socket/*{{{*/ { private: /// the *nix socket we use for commuication sint32 sock; /// *nix socket that will be used to listen for connections sint32 list_sock; /// true if we are a listen socket (this cannot connect/reconnect) BOOL listening; /// The IP of the other side mstring peer_ip; /// The port the connection should go to sint32 peer_port; /// Additional flag if we are connected to the peer or not BOOL connected; /// Last Error reported by getsockopt uint32 last_error; /** * Internal function to get the error of the last operation * @param none * @return int errno of last error * @note this function will additionally store the error in last_error * therefore this will always be called in an error condition. The user can get * the error message to be displayed with GetLastErrorMsg() call */ uint32 get_sock_error( void ); /** * Internal function to do the real work for the different Listen versions * since most of them do the same. */ BOOL do_listen( struct sockaddr* horchen, uint32 linger ); /** * internal function to check for the read socket. * @param bool must A Flag that mus be set at least to return true. This * can be used, to check if a connection is pending only if the flag for * the listener ist set. */ BOOL check_read ( BOOL must, sint32 csock, uint32 timeout_msec); public: /** * Creates the object with the necessary default information for a connection * @param none */ small_socket( void ) : sock(-1), list_sock(-1),listening(false),peer_ip("127.0.0.1"), peer_port(80),connected(false),last_error(0) { } /** * Copy constructor. Should do the same as the implicit one, since we have nothing * created with new */ small_socket( const small_socket& v) :sock(v.sock),list_sock(v.list_sock),listening(v.listening), peer_ip(v.peer_ip), peer_port(v.peer_port),connected(v.connected),last_error(0) { } /** * @param none * @return int the error value of the last socket error. */ inline uint32 GetLastError( void ) { return last_error; } /** * Returns the corresponding Error Message String to the error value. If * called with no or negative parameter, it will return the Error Message of * the last error occured * @param int err Error value * @return mstring The Systems Error message to the error. */ inline mstring GetLastErrorMsg( sint32 err = -1 ) { if ( err < 0) { return strerror(last_error); } return strerror(err); } /** * connects the socket to the specified IP & Port * @param int port TCP/IP port to connect to * @param mstring ipaddr Adress or hostname we should connect to * @return bool if the connection was succesfully * @note If ipaddr is no valid host, IP, or if it cannot be resolved the * connect will just fail and return false. */ BOOL Connect ( const mstring& ipaddr, uint16 port, uint32 timeout_msec=_DEFAULT_TIMEOUT ); /** * @short Prepares the socket to listen for incoming connections on port * port. * * The linger option specifies how many connections may wait at kernel * level. All additional connections will then be refused. Since the usual * default is 5, higher values should not be used. 0 or 1 should be used, if * only one connection may be allowed. This version of the call will bind * to the specified ipadress, so it will accept only connections coming to * this adress. * @param mstring ipaddr Adress to bind the listener to * @param int port Port this will listen to * @param int linger Maximum connections that may pend * @return true if listening is possible. Reason for false result may be * another process listening on the same port & interface. * @note If the socket is connected with e.g. a Connect(), this call will * fail. * @note A second call of this function causes the actual listener to die */ BOOL Listen ( const mstring& ipaddr, uint16 port , uint32 linger=5); /** * Listen to port on all interfaces, see version above for details. * @param int port Port to listen on * @param int linger Maximum connections that may pend * @return true if listening is possible. */ BOOL Listen ( uint16 port , uint32 linger=5); /** * Listen to port, and bind to interface iface only. See above for * additional details * @param int port Port to listen on * @param mstring iface Interface to listen on, like eth0 * @param int linger Maximum connections that may pend * @return true if listening is possible. */ BOOL Listen ( uint16 port, const mstring& iface, uint32 linger=5); /** * Checks if a connection is pending on current socket. Works only if a * Listen has been issued before. * @return true if a connection is pending. This can then be accepted with Accept */ BOOL ConnectionPending( uint32 timeout_msec=_DEFAULT_TIMEOUT ) { return check_read(listening, list_sock, timeout_msec); } /** * Accepts the current pending connection, if any. Timeout can be set to * avoid "hanging" of process. If timeout is set to 0, this will wait until a * connection is made. This is not very usefull for asynchronous and multiple * connection handling. The current connection can then be used to * communicate. It will not be possible to Connect to the server until a new * Listen will be issued. * @return true if the connection was established. * @param long timeout_msec timeout in milliseconds * */ BOOL Accept ( uint32 timeout_msec=_DEFAULT_TIMEOUT ); /** * Accepts the pending connection. This will copy the current connections * socket and pass a pointer to this copy to us. This means, that the * caller has to take care, that the object is destroyed !!! * @note although it is possible to use both, the current and the copied * object to communicate, it is recommended to use only the copied, since * the original might destroy some data. * @param bool closeit If the current listener should be closed. If you * plan to use more than one connection, set this to false. Then also * others may connect. * @return NULL * @note if the connection could not be established, the returned socket is * in unconnected state. */ small_socket* Accept ( BOOL closeit, uint32 timeout_msec=_DEFAULT_TIMEOUT); /** * Disconnect & close the current connetion. Buffers should(tm) be flushed * by the operating system * @return bool if disconnect was succesfully ( mh, why should it fail??) */ BOOL Disconnect ( void ); /** * reads incoming data to the buffer, behaves like the usual *nix read * function, except for the timeout * @param int timeout_msec Timeout for the read in Milliseconds, defaults to 3 seconds * @param int bytes A maximum of this much bytes will be read from the stream * @param char* buffer Read the Data into this buffer * @return int number of bytes that have been read from the stream. 0 * usually means that there is no data at the moment, while -1 means that * the connection is borken or another error occured * @note since the timeout is realized via a select() call, it might be * possible that the function returns earlzier when interrupted by a system * call ! */ sint32 Receive ( uchar8 * buffer, uint32 bytes, uint32 timeout_msec=_DEFAULT_TIMEOUT); /** * Receive up to bytes bytes with a timeout and give it back as a string. * @param int bytes maximum of bytes to be read * @param int timeout_msec timeout while receiving, defaults to 3 seconds * @return mstring The string the Data has been put into * @note If a `\0` occurs in the stream, or if the stream was not already * in the incoming buffer, the returning string might be smaller than * expected and the additional data in the stream after the `\0` will be lost. */ mstring Receive ( uint32 bytes , uint32 timeout_msec=_DEFAULT_TIMEOUT); /** * Sends some Data to the other side. similar to the *nix system call write() * @param const char* buffer the buffer that will be read from * @param int bytes this many bytes will be read from the buffer and sent to peer * @param int timeout_msec timeout after which the message will be * discarded if impossible to send * @return number of bytes written to the peer. -1 indicates an error */ sint32 Send ( const uchar8 * buffer, uint32 bytes, uint32 timeout_msec=_DEFAULT_TIMEOUT); /** * Just send this string out to the peer * @param mstring& s reference to the string we send out to the world * @param int timeout_msec again the timeout that defaults to 3 seconds */ sint32 Send ( const mstring& s, uint32 timeout_msec=_DEFAULT_TIMEOUT); /** * The data of a previously connect will be saved internally, and with this * function one can do a reconnect with the same paramters again. * @return if the reconnect was succesfully */ BOOL Reconnect ( uint32 timeout_msec=_DEFAULT_TIMEOUT*10 ); /** * Checks if socket is valid and connection flag is set * @return true if so, means we are still connected */ inline BOOL Connected ( void ) { return (( sock > 0 ) && connected); } /** * Checks if there is data ready for read at the socket. * @return true if there is data * @param int timeout_msec Timeout in millisecnds that we will wait at most * for incoming data. If until then no data has arrived, we consider this * as a false ! */ inline BOOL DataWaiting ( uint32 timeout_msec=_DEFAULT_TIMEOUT ) { return check_read(connected,sock,timeout_msec); } inline sint32 get_fd( void ) { return sock; } inline sint32 get_listen_fd( void ) { return list_sock; } inline mstring get_peer( void ) { return peer_ip; } inline uint16 get_port ( void ) { return peer_port; } /** * Resolves the IP/host given to an IP. If the input is an IP, the output * will also be an IP. If it cannot be resolved, an empty string is returned * @param mstring& host that should be resolved * @return mstring of the IP it has resolved to * @note If this returns an emtpy string, the system will most likely not * be able to resolv/connect */ static mstring get_resolved_ip ( const mstring & host ); /** * Resolves a hostname/ip to a hostname. If the input could not be * resolved, an empty string is returned. This will not mean, that the host * cannot be resolved, or reached, only reverse identification does not work. * @param mstring& host to be resolved to a fqdn * @return mstring with the hostname */ static mstring get_resolved_host ( const mstring & host ); inline mstring get_resolved_host ( void ){ return get_resolved_host(peer_ip); } inline mstring get_resolved_ip ( void ) { return get_resolved_ip(peer_ip); } };/*}}}*/ #else #warning Multiple inclusion of small_socket.h please check #endif // Ja, da hat der iceblox doch nen Comment geadded /** *$Log: small_socket.h,v $ *Revision 1.18 2002/10/21 08:37:22 plasmahh *beginning cleanup for smtpmap release 0.8-stable * *Revision 1.17 2002/08/12 13:15:26 plasmahh *removed some memory leaks * *Revision 1.16 2002/06/20 16:58:48 plasmahh *fixed & improved timeout behaviour in connect() call * *Revision 1.15 2002/06/17 14:05:07 plasmahh *resolv for IPs added * *Revision 1.14 2002/06/17 12:21:03 plasmahh *new exceptions for the future... * *Revision 1.13 2002/06/17 06:54:22 plasmahh *improved socket with connection timeout * *Revision 1.12 2002/06/09 21:23:22 plasmahh *changed a few things that might be bugs * *Revision 1.11 2002/05/28 20:49:41 plasmahh *included additional file in order to make compatible to NetBSD * *Revision 1.10 2002/05/27 06:24:09 plasmahh *New function in socket class to try detecting disconnects * *Revision 1.9 2002/05/23 19:48:08 plasmahh *removed some compiler warnings. *fixed one or two bugs. *refined include structure, for faster compiling *hm, what else ? don't know, I hope this works all ;) * *Revision 1.8 2002/05/15 08:48:15 plasmahh *Added documentation * *Revision 1.7 2002/05/01 23:08:28 plasmahh *ficed * *Revision 1.6 2002/05/01 20:13:23 plasmahh *made interface to socket a bit easier for simple use *added connection exception * *Revision 1.5 2002/04/30 22:29:01 plasmahh *changed socket interface to our string class * *Revision 1.4 2002/04/16 20:32:31 iceblox *Ja geil, Enter Log. Was will der hier von mir? * *Revision 1.3 2002/04/16 20:05:50 plasmahh *Added new header style * *Revision 1.2 2002/04/16 20:03:05 plasmahh *Added change log support to some files * */