00001 /* 00002 * wavesock.h 00003 * 00004 * Copyright (C) 2009 Thomas A. Vaughan 00005 * All rights reserved. 00006 * 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions are met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * * Neither the name of the <organization> nor the 00016 * names of its contributors may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY 00020 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00022 * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY 00023 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00026 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 * 00030 * 00031 * Quick and dirty abstraction layer (very low-level). 00032 */ 00033 00034 #ifndef WAVEPACKET_WAVESOCK_H__ 00035 #define WAVEPACKET_WAVESOCK_H__ 00036 00037 00038 // includes -------------------------------------------------------------------- 00039 #include "common/common.h" 00040 00041 00042 namespace netlib { 00043 00044 00045 // networking typedefs --------------------------------------------------------- 00046 00047 //////////////////////////////////////////////////////////////////////////////// 00048 /// 00049 /// \ingroup networking 00050 /// \defgroup wavesock Wavepacket Sockets API 00051 /// 00052 /// This is a quick and dirty sockets-like API to abstract the netlib 00053 /// implementation from operating-system-specific issues. 00054 /// 00055 /// Basically this abstracts the BSD Sockets and Winsock APIs. 00056 /// 00057 /// This is not completely general, it is tailored for netlib. For instance, 00058 /// it assumes (and enforces) nonblocking sockets. It quiets all signals. 00059 /// 00060 /// This follows BSD socket-style error handling. If something goes wrong, 00061 /// call wsGetError() for the error code. 00062 /// 00063 /// \b WARNING: the select() behavior is a bit funky. In particular, I took a 00064 /// shortcut and relied on global state for some of the fd sets. This means 00065 /// this library is NOT threadsafe. That's fine for now, but may be cleaned 00066 /// up someday. 00067 /// 00068 //////////////////////////////////////////////////////////////////////////////// 00069 /*@{*/ 00070 00071 00072 /// these are error codes. They also are abstracted! as a result, they don't 00073 /// cover the full spectrum of possible errors. They only cover what I've 00074 /// needed so far. Most errors will therefore be mapped to eWS_Unknown. 00075 enum eWSError { 00076 eWS_Okay = 0, ///< no error 00077 eWS_Again = 1, ///< read/write failed, just try again 00078 eWS_Denied = 2, ///< permission denied (bad port#?) 00079 eWS_InUse = 3, ///< address is already in use 00080 eWS_ConnectionRefused = 4, ///< no one listening at other end 00081 00082 eWS_Unknown = 0x100,///< unmapped error 00083 00084 // must be last! 00085 eWS_Invalid = 0x7ff 00086 }; 00087 00088 00089 00090 /// representation of IP address (abstracts IPv4 and IPv6) 00091 struct ip_addr_t { 00092 enum eType { 00093 eType_IPv4 = 1, ///< IPv4 address 00094 eType_IPv6 = 2, ///< IPv6 address 00095 00096 eType_Invalid = 0 // keep this last! 00097 }; 00098 00099 // constructor, manipulators 00100 ip_addr_t(void) throw() { this->clear(); } 00101 void clear(void) throw() { 00102 memset(addr, 0, 6 * sizeof(byte_t)); 00103 flags = 0; 00104 unused = 0; 00105 } 00106 00107 eType getType(void) const throw() { return (eType) flags; } 00108 00109 bool isValid(void) const throw() { 00110 // only support IPv4 for now 00111 return (eType_IPv4 == flags); 00112 } 00113 00114 bool operator != (IN const ip_addr_t& rhs) const throw() { 00115 return !(*this == rhs); 00116 } 00117 00118 bool operator == (IN const ip_addr_t& rhs) const throw() { 00119 return !memcmp(this, &rhs, 7); 00120 } 00121 00122 void dump(IN const char * title) const throw() { 00123 if (!flags) { 00124 DPRINTF("%s: (invalid IP address)", title); 00125 } else if (eType_IPv4 == flags) { 00126 DPRINTF("%s: IPv4 %d.%d.%d.%d", title, 00127 addr[0], addr[1], addr[2], addr[3]); 00128 } else if (eType_IPv6 == flags) { 00129 DPRINTF("%s: IPv6 address (?)", title); 00130 } else { 00131 DPRINTF("%s: corrupt!", title); 00132 } 00133 } 00134 00135 /// attempts to look up the IP of the remote host. Returns false on 00136 /// failure (and the value of the ip address object is unchanged). 00137 bool lookupHostname(IN const char * hostname); 00138 00139 /// is this just a loopback IP address? (127.0.0.1 for IPv4) 00140 bool isLoopback(void) const throw(); 00141 00142 /// sets to loopback (127.0.0.1 for IPv4) 00143 void setLoopback(void) throw(); 00144 00145 /// sets to broadcast. \b WARNING: this isn't a very clever method. 00146 /// It just sets the last byte to 255. If you want more control 00147 /// over the broadcast mask, set it explicitly. 00148 /// Only works when applied to an already-valid IP address. Returns 00149 /// false on failure. 00150 bool setBroadcast(void) throw(); 00151 00152 void setIPv4(IN const byte_t * ip) throw() { 00153 ASSERT(ip, "null"); 00154 this->clear(); 00155 flags = eType_IPv4; 00156 addr[0] = ip[0]; 00157 addr[1] = ip[1]; 00158 addr[2] = ip[2]; 00159 addr[3] = ip[3]; 00160 } 00161 00162 void setIPv6(IN const byte_t * ip) throw() { 00163 ASSERT(ip, "null"); 00164 this->clear(); 00165 ASSERT(false, "setIPv6() is not yet supported"); 00166 } 00167 00168 // data fields 00169 byte_t addr[6]; 00170 byte_t flags; // actually the type 00171 byte_t unused; // keep dword-aligned 00172 }; 00173 00174 00175 00176 /// holds the IP address and port of a remote host 00177 struct address_t { 00178 // constructor, manipulators 00179 address_t(IN const char * server, IN int remotePort) throw() { 00180 this->clear(); 00181 this->set(server, remotePort); 00182 } 00183 address_t(void) throw() { this->clear(); } 00184 void clear(void) throw() { 00185 ip.clear(); 00186 port = -1; 00187 } 00188 00189 bool isValid(void) const throw() { 00190 return (port > 0 && ip.isValid()); 00191 } 00192 00193 bool operator == (IN const address_t& rhs) const throw() { 00194 return (port == rhs.port && 00195 ip == rhs.ip); 00196 } 00197 00198 bool operator != (IN const address_t& rhs) const throw() { 00199 return !(*this == rhs); 00200 } 00201 00202 /// set the IP and port. Returns false if server name doesn't resolve 00203 bool set(IN const char * server, IN int remotePort); 00204 00205 /// set to local host (picks first non-loopback address) 00206 bool setlocal(IN int remotePort); 00207 00208 void dump(IN const char * msg) const throw() { 00209 DPRINTF("%s: internet address ================", msg); 00210 ip.dump(" ip"); 00211 DPRINTF(" port= %d", port); 00212 DPRINTF("%s: end of address ==================", msg); 00213 } 00214 00215 // data fields 00216 ip_addr_t ip; 00217 int port; 00218 }; 00219 00220 00221 00222 /// a map of IP addresses (typically interface name --> IP address) 00223 typedef std::map<std::string, ip_addr_t> map_ip_addr_t; 00224 00225 00226 /// get set of local interfaces 00227 bool getLocalInterfaces(OUT map_ip_addr_t& interfaces); 00228 00229 00230 /// is the given socket identifier valid? 00231 bool wsIsValidSocket(IN int s) throw(); 00232 00233 00234 /// gets the current error (0 means no error). This is mapped to the 00235 /// known (small) set of wavesocket errors, and therefore is only 00236 /// useful in a few cases. See the eWSError enum. 00237 /// If you need richer information, call wsGetErrorMessage(). 00238 eWSError wsGetError(void) throw(); 00239 00240 00241 /// returns the most recent error message 00242 void wsGetErrorMessage(IN char * buffer, 00243 IN int bufferSize) throw(); 00244 00245 00246 /// creates a socket that can be used for TCP 00247 int wsCreateTcpSocket(void) throw(); 00248 00249 00250 /// creates a socket that can be used for UDP 00251 int wsCreateUdpSocket(IN bool broadcast) throw(); 00252 00253 00254 /// binds the given socket to a specific local port for UDP or TCP 00255 /// returns 0 on success, -1 for error. See BSD bind() for details. 00256 int wsBindToPort(IN int s, 00257 IN int port) throw(); 00258 00259 00260 /// usually used for TCP listening sockets. See BSD listen() for details. 00261 /// Returns 0 on success, -1 for error. 00262 int wsListen(IN int s, 00263 IN int maxBacklog) throw(); 00264 00265 00266 00267 /// makes a connection to the specified server 00268 int wsConnect(IN int s, 00269 IN const address_t& server) throw(); 00270 00271 00272 /// receives data (typically from TCP). Look at BSD recv() for details. 00273 /// Returns the number of bytes read, -1 for error, 0 for disconnect 00274 int wsReceive(IN int s, 00275 IN char * buffer, 00276 IN int bufferSize) throw(); 00277 00278 00279 /// receives data (typically from UPD). This also tells you where the 00280 /// data came from (where the sender is). Look at BSD recvfrom() for 00281 /// details. 00282 /// Returns the number of bytes read, -1 for error, 0 for disconnect 00283 int wsReceiveFrom(IN int s, 00284 IN char * buffer, 00285 IN int bufferSize, 00286 OUT address_t& from) throw(); 00287 00288 00289 /// sends data (typically for TCP). Look at BSD send() for details. 00290 /// Returns the number of bytes sent, -1 for error 00291 int wsSend(IN int s, 00292 IN const char * buffer, 00293 IN int bufferSize) throw(); 00294 00295 00296 /// sends data (typically for UDP). Look at BSD sendto() for details. 00297 /// Returns the number of bytes sent, -1 for error 00298 int wsSendTo(IN int s, 00299 IN const char * buffer, 00300 IN int bufferSize, 00301 IN const address_t& to) throw(); 00302 00303 00304 /// accepts an incoming request. See BSD accept() for details. 00305 /// Returns the socket for the accepted connection. 00306 int wsAccept(IN int s, 00307 OUT address_t& address) throw(); 00308 00309 00310 typedef void * ws_set_t; 00311 00312 00313 /// creates an object that you can clear, and then populate with sockets. 00314 /// This involves memory allocation, so you should cache any sets you create. 00315 ws_set_t wsCreateSet(void); 00316 00317 00318 /// clears the given set 00319 void wsClearSet(IN ws_set_t set) throw(); 00320 00321 00322 /// adds the given socket to the given set 00323 void wsAddSocketToSet(IN ws_set_t set, 00324 IN int s) throw(); 00325 00326 00327 /// is the given socket in the set? 00328 bool wsIsSocketInSet(IN ws_set_t set, 00329 IN int s) throw(); 00330 00331 00332 /// destroys the given set 00333 void wsDestroySet(IN ws_set_t set) throw(); 00334 00335 00336 /// waits until a socket is ready for read/write. See BSD select() for details. 00337 /// To call this, you must first clear and then populate the reader and writer 00338 /// sets. 00339 /// Returns -1 on error 00340 int wsSelect(IN int maxSocket, ///< needs to be max+1 of any socket in any set 00341 IN ws_set_t readers, 00342 IN ws_set_t writers, 00343 IN long wait_microseconds) throw(); 00344 00345 00346 /// closes a socket 00347 void wsCloseSocket(IN int s) throw(); 00348 00349 00350 00351 }; // netlib namespace 00352 00353 00354 00355 #endif // WAVEPACKET_WAVESOCK_H__