00001 /* -*- Mode: C++ -*- 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvStream-based TCP connection and server classes. 00006 */ 00007 #ifndef __WVTCP_H 00008 #define __WVTCP_H 00009 00010 #include "wvfdstream.h" 00011 #include "wvaddr.h" 00012 #include "wvresolver.h" 00013 00014 00015 #if 0 00016 // FIXME: this is needed on BSD 00017 #include <netinet/in_systm.h> 00018 #define SOL_TCP 6 00019 #define SOL_IP 4 00020 #endif 00021 00022 #ifdef ISBSD 00023 #define socklen_t unsigned int 00024 #endif 00025 00026 #ifdef ISDARWIN 00027 #define socklen_t int 00028 #endif 00029 00030 00031 class WvStreamList; 00032 class WvTCPListener; 00033 00034 /** 00035 * WvTCPConn tries to make all outgoing connections asynchronously (in 00036 * the background). You can tell the connection has been established 00037 * when a select() call returns 'true' with writable==true. 00038 */ 00039 class WvTCPConn : public WvFDStream 00040 { 00041 friend class WvTCPListener; 00042 protected: 00043 bool resolved, connected; 00044 WvString hostname; 00045 WvIPPortAddr remaddr; 00046 WvResolver dns; 00047 00048 /** Start a WvTCPConn on an already-open socket (used by WvTCPListener) */ 00049 WvTCPConn(int _fd, const WvIPPortAddr &_remaddr); 00050 00051 /** Connect to the remote end - note the "Protected" above ;) */ 00052 void do_connect(); 00053 00054 /** Resolve the remote address, if it was fed in non-IP form */ 00055 void check_resolver(); 00056 00057 public: 00058 /** 00059 * WvTCPConn tries to make all outgoing connections asynchronously (in 00060 * the background). You can tell the connection has been established 00061 * when a select() call returns 'true' with writable==true. 00062 */ 00063 WvTCPConn(const WvIPPortAddr &_remaddr); 00064 00065 /** Resolve the hostname, then connect a new socket */ 00066 WvTCPConn(WvStringParm _hostname, __u16 _port = 0); 00067 00068 /** 00069 * Destructor - rarely do you need to call this - close() 00070 * is a much better way to tear down a TCP Stream ;) 00071 */ 00072 virtual ~WvTCPConn(); 00073 00074 /** 00075 * function to set up a TCP socket the way we like 00076 * (Read/Write, Non-Blocking, KeepAlive) 00077 */ 00078 void nice_tcpopts(); 00079 00080 /** 00081 * function to set up a TCP socket the way we like 00082 * In addition to the nice_tcpopts(), set TCP_NODELAY 00083 */ 00084 void low_delay(); 00085 00086 /** 00087 * function to set up a TCP socket the way we *don't* like: turn the 00088 * timeouts way down so that network errors show up easily for debugging 00089 */ 00090 void debug_mode(); 00091 00092 /** 00093 * the local address of this socket (ie. from getsockname()) 00094 * really useful only for transparent proxies, but always available. 00095 * may be 0.0.0.0 if we did not bind explicitly! 00096 */ 00097 WvIPPortAddr localaddr(); 00098 00099 /** 00100 * return the remote address (source of all incoming packets), 00101 * which is a constant for any given TCP connection. 00102 */ 00103 virtual const WvIPPortAddr *src() const; 00104 00105 /** has the connection been completed yet? */ 00106 bool isconnected() const 00107 { return connected; } 00108 00109 /** override pre_select() to cause select() results when resolving names. */ 00110 virtual bool pre_select(SelectInfo &si); 00111 00112 /** 00113 * override post_select() to set the 'connected' variable as soon as we 00114 * are connected. 00115 */ 00116 virtual bool post_select(SelectInfo &si); 00117 00118 /** 00119 * Is this connection OK? 00120 * Note: isok() will always be true if !resolved, even though fd==-1. 00121 */ 00122 virtual bool isok() const; 00123 00124 protected: 00125 virtual size_t uwrite(const void *buf, size_t count); 00126 }; 00127 00128 /** Class to easily create the Server side of a TCPConn... */ 00129 class WvTCPListener : public WvFDStream 00130 { 00131 public: 00132 /** 00133 * Create a WvStream that listens on _listenport of the current machine 00134 * This is how you set up a TCP Server. 00135 */ 00136 WvTCPListener(const WvIPPortAddr &_listenport); 00137 00138 /** Destructor - remember - close() is your friend ;) */ 00139 virtual ~WvTCPListener(); 00140 00141 /** Shut down the server, and disconnect from the port */ 00142 virtual void close(); 00143 00144 /** 00145 * return a new WvTCPConn socket corresponding to a newly-accepted 00146 * connection. If no connection is ready immediately, we wait for 00147 * one indefinitely. You can use select(read=true) to check for a 00148 * waiting connection. 00149 */ 00150 WvTCPConn *accept(); 00151 00152 /** 00153 * set a callback() function that automatically accepts new WvTCPConn 00154 * connections, assigning them their own callback function 'callfunc' 00155 * with parameter 'userdata.' Pass list==NULL or define your own 00156 * own callback function to disable auto-accepting. 00157 * 00158 * Be careful not to accept() connections yourself if you do this, 00159 * or we may end up accept()ing twice, causing a hang the second time. 00160 */ 00161 void auto_accept(WvStreamList *list, 00162 WvStreamCallback callfunc = NULL, void *userdata = NULL); 00163 00164 /** 00165 * these don't do anything, but they confuse the socket, so we'll 00166 * ignore them on purpose. 00167 */ 00168 virtual size_t uread(void *buf, size_t len); 00169 virtual size_t uwrite(const void *buf, size_t len); 00170 00171 /** src() is a bit of a misnomer, but it returns the listener port. */ 00172 virtual const WvIPPortAddr *src() const; 00173 00174 protected: 00175 WvIPPortAddr listenport; 00176 WvStreamList *auto_list; 00177 WvStreamCallback auto_callback; 00178 void *auto_userdata; 00179 00180 static void accept_callback(WvStream &s, void *userdata); 00181 }; 00182 00183 00184 #endif // __WVTCP_H