|
socket.hGo to the documentation of this file.00001 // Copyright (C) 1999-2000 Open Source Telecom Corporation. 00002 // 00003 // This program is free software; you can redistribute it and/or modify 00004 // it under the terms of the GNU General Public License as published by 00005 // the Free Software Foundation; either version 2 of the License, or 00006 // (at your option) any later version. 00007 // 00008 // This program is distributed in the hope that it will be useful, 00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 // GNU General Public License for more details. 00012 // 00013 // You should have received a copy of the GNU General Public License 00014 // along with this program; if not, write to the Free Software 00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00016 // 00017 // As a special exception to the GNU General Public License, permission is 00018 // granted for additional uses of the text contained in its release 00019 // of Common C++. 00020 // 00021 // The exception is that, if you link the Common C++ library with other files 00022 // to produce an executable, this does not by itself cause the 00023 // resulting executable to be covered by the GNU General Public License. 00024 // Your use of that executable is in no way restricted on account of 00025 // linking the Common C++ library code into it. 00026 // 00027 // This exception does not however invalidate any other reasons why 00028 // the executable file might be covered by the GNU General Public License. 00029 // 00030 // This exception applies only to the code released under the 00031 // name Common C++. If you copy code from other releases into a copy of 00032 // Common C++, as the General Public License permits, the exception does 00033 // not apply to the code that you add in this way. To avoid misleading 00034 // anyone as to the status of such modified files, you must delete 00035 // this exception notice from them. 00036 // 00037 // If you write modifications of your own for Common C++, it is your choice 00038 // whether to permit this exception to apply to your modifications. 00039 // If you do not wish that, delete this exception notice. 00040 00041 #ifndef __CCXX_SOCKET_H__ 00042 #define __CCXX_SOCKET_H__ 00043 00044 #include "config.h" 00045 00046 #if defined(WIN32) 00047 # ifndef __CCXX_THREAD_H__ 00048 # include <thread.h> 00049 # endif 00050 # include <winsock.h> 00051 # define TIMEOUT_INF ~((timeout_t) 0) 00052 typedef int socklen_t; 00053 #else 00054 # ifndef __CCXX_THREAD_H__ 00055 # include <cc++/thread.h> 00056 # elif defined(__CCXX_NAMESPACE_H__) 00057 # include <cc++/macros.h> 00058 # endif 00059 # define INVALID_SOCKET -1 00060 # ifdef __EXPORT 00061 # undef __EXPORT 00062 # endif 00063 # define __EXPORT 00064 typedef int SOCKET; 00065 #endif 00066 00067 #include <iostream.h> 00068 00069 #ifndef MSG_DONTWAIT 00070 #define MSG_DONTWAIT 0 00071 #endif 00072 00077 typedef enum 00078 { 00079 SOCKET_COMPLETION_IMMEDIATE, 00080 SOCKET_COMPLETION_DELAYED 00081 } sockcomplete_t; 00082 00083 typedef enum 00084 { 00085 SOCKET_INITIAL, 00086 SOCKET_AVAILABLE, 00087 SOCKET_BOUND, 00088 SOCKET_CONNECTED, 00089 SOCKET_CONNECTING, 00090 SOCKET_STREAM 00091 } sockstate_t; 00092 00093 typedef enum 00094 { 00095 SOCKET_SUCCESS = 0, 00096 SOCKET_CREATE_FAILED, 00097 SOCKET_COPY_FAILED, 00098 SOCKET_INPUT_ERROR, 00099 SOCKET_INPUT_INTERRUPT, 00100 SOCKET_RESOURCE_FAILURE, 00101 SOCKET_OUTPUT_ERROR, 00102 SOCKET_OUTPUT_INTERRUPT, 00103 SOCKET_NOT_CONNECTED, 00104 SOCKET_CONNECT_REFUSED, 00105 SOCKET_CONNECT_REJECTED, 00106 SOCKET_CONNECT_TIMEOUT, 00107 SOCKET_CONNECT_FAILED, 00108 SOCKET_CONNECT_INVALID, 00109 SOCKET_CONNECT_BUSY, 00110 SOCKET_CONNECT_NOROUTE, 00111 SOCKET_BINDING_FAILED, 00112 SOCKET_BROADCAST_DENIED, 00113 SOCKET_ROUTING_DENIED, 00114 SOCKET_KEEPALIVE_DENIED, 00115 SOCKET_SERVICE_DENIED, 00116 SOCKET_SERVICE_UNAVAILABLE, 00117 SOCKET_MULTICAST_DISABLED, 00118 SOCKET_EXTENDED_ERROR 00119 } sockerror_t; 00120 00121 typedef enum 00122 { 00123 SOCKET_IPTOS_LOWDELAY, 00124 SOCKET_IPTOS_THROUGHPUT, 00125 SOCKET_IPTOS_RELIABILITY, 00126 SOCKET_IPTOS_MINCOST, 00127 SOCKET_IPTOS_INVALID 00128 } socktos_t; 00129 00130 typedef enum 00131 { 00132 SOCKET_PENDING_INPUT, 00133 SOCKET_PENDING_OUTPUT, 00134 SOCKET_PENDING_ERROR 00135 } sockpend_t; 00136 00140 typedef unsigned short tpport_t; 00141 00142 class __EXPORT InetAddress; 00143 class __EXPORT InetHostAddress; 00144 class __EXPORT InetMaskAddress; 00145 class __EXPORT BroadcastAddress; 00146 class __EXPORT Socket; 00147 class __EXPORT UDPSocket; 00148 class __EXPORT UDPBroadcast; 00149 class __EXPORT UDPTransmit; 00150 class __EXPORT UDPReceive; 00151 class __EXPORT UDPDuplex; 00152 class __EXPORT TCPSocket; 00153 class __EXPORT TCPStream; 00154 class __EXPORT tcpstream; 00155 class __EXPORT TCPSession; 00156 00171 class InetAddress 00172 { 00173 protected: 00174 struct in_addr * ipaddr; 00175 size_t addr_count; 00176 #if defined(WIN32) 00177 static MutexCounter counter; 00178 #else 00179 static Mutex mutex; 00180 #endif 00181 00188 bool setIPAddress(const char *host); 00189 00196 void setAddress(const char *host); 00197 00198 public: 00203 InetAddress(); 00204 00212 InetAddress(struct in_addr addr); 00213 00220 InetAddress(const char *address); 00221 00225 InetAddress(const InetAddress &rhs); 00226 00230 virtual ~InetAddress(); 00231 00238 const char *getHostname(void) const; 00239 00247 bool isInetAddress(void) const; 00248 00256 struct in_addr getAddress(void) const; 00257 00269 struct in_addr getAddress(size_t i) const; 00270 00276 size_t getAddressCount() const { return addr_count; } 00277 00278 InetAddress &operator=(const char *str); 00279 InetAddress &operator=(struct in_addr addr); 00280 InetAddress &operator=(const InetAddress &rhs); 00281 00285 InetAddress &operator=(unsigned long addr); 00286 00287 inline bool operator!() const 00288 {return !isInetAddress();}; 00289 00298 bool operator==(const InetAddress &a) const; 00299 00307 bool operator!=(const InetAddress &a) const; 00308 }; 00309 00322 class InetMaskAddress : public InetAddress 00323 { 00324 public: 00331 InetMaskAddress(const char *mask); 00332 00343 friend InetHostAddress operator&(const InetHostAddress &addr, 00344 const InetMaskAddress &mask); 00345 00349 InetAddress &operator=(unsigned long addr) 00350 { return InetAddress::operator =(addr); } 00351 }; 00352 00360 class InetHostAddress : public InetAddress 00361 { 00362 public: 00375 InetHostAddress(const char *host = NULL); 00376 00384 InetHostAddress(struct in_addr addr); 00385 00389 InetAddress &operator=(unsigned long addr) 00390 { return InetAddress::operator =(addr); } 00391 00396 InetHostAddress &operator&=(const InetMaskAddress &mask); 00397 00398 friend class InetMaskAddress; 00399 friend InetHostAddress operator&(const InetHostAddress &addr, 00400 const InetMaskAddress &mask); 00401 }; 00402 00407 class BroadcastAddress : public InetAddress 00408 { 00409 public: 00417 BroadcastAddress(const char *net = "255.255.255.255"); 00418 }; 00419 00437 class Socket 00438 { 00439 private: 00440 // used by exception handlers.... 00441 mutable sockerror_t errid; 00442 mutable const char *errstr; 00443 00444 mutable struct 00445 { 00446 bool thrown: 1; 00447 bool broadcast: 1; 00448 bool route: 1; 00449 bool keepalive: 1; 00450 bool loopback: 1; 00451 bool multicast: 1; 00452 unsigned ttl: 8; 00453 } flags; 00454 00455 void setSocket(void); 00456 00457 protected: 00463 SOCKET so; 00464 sockstate_t state; 00465 00473 sockerror_t Error(sockerror_t error, char *errstr = NULL) const; 00474 00481 inline void Error(char *estr) 00482 {Error(SOCKET_EXTENDED_ERROR, estr);}; 00483 00490 inline void setError(bool enable) 00491 {flags.thrown = !enable;}; 00492 00498 void endSocket(void); 00499 00505 sockerror_t connectError(void); 00506 00515 sockerror_t setBroadcast(bool enable); 00516 00527 sockerror_t setMulticast(bool enable); 00528 00536 sockerror_t setLoopback(bool enable); 00537 00544 sockerror_t setTimeToLive(unsigned char ttl); 00545 00552 sockerror_t Join(InetAddress &ia); 00553 00560 sockerror_t Drop(InetAddress &ia); 00561 00569 sockerror_t setRouting(bool enable); 00570 00582 Socket(int domain, int type, int protocol = 0); 00583 00591 Socket(SOCKET fd); 00592 00600 Socket(const Socket &source); 00601 00610 ssize_t Readline(char *buf, size_t len); 00611 00612 public: 00620 virtual ~Socket() 00621 {endSocket();}; 00622 00626 Socket &operator=(const Socket &from); 00627 00637 InetHostAddress getSender(tpport_t *port = NULL) const; 00638 00648 InetHostAddress getPeer(tpport_t *port = NULL) const; 00649 00657 InetHostAddress getLocal(tpport_t *port = NULL) const; 00658 00669 void setCompletion(sockcomplete_t completion); 00670 00678 sockerror_t setKeepAlive(bool enable); 00679 00688 sockerror_t setTypeOfService(socktos_t service); 00689 00698 bool isConnected(void) const; 00699 00707 bool isActive(void) const; 00708 00713 bool operator!() const; 00714 00721 inline bool isBroadcast(void) const 00722 {return flags.broadcast;}; 00723 00729 inline bool isRouted(void) const 00730 {return flags.route;}; 00731 00738 inline sockerror_t getErrorNumber(void) const {return errid;} 00739 00746 inline const char *getErrorString(void) const {return errstr;} 00747 00757 virtual bool isPending(sockpend_t pend, timeout_t timeout = TIMEOUT_INF); 00758 }; 00759 00792 class UDPSocket : public Socket 00793 { 00794 private: 00795 inline sockerror_t setKeepAlive(bool enable) 00796 {return Socket::setKeepAlive(enable);}; 00797 00798 protected: 00799 struct sockaddr_in peer; 00800 00801 public: 00805 UDPSocket(void); 00806 00816 UDPSocket(const InetAddress &bind, tpport_t port); 00817 00821 ~UDPSocket() 00822 {endSocket();}; 00823 00831 void setPeer(const InetHostAddress &host, tpport_t port); 00832 00840 inline int Send(void *buf, size_t len) 00841 {return ::sendto(so, (const char *)buf, len, 0, (struct sockaddr *)&peer, (socklen_t)sizeof(peer));}; 00842 00850 inline int Recv(void *buf, size_t len) 00851 {return ::recv(so, (char *)buf, len, 0);}; 00852 00861 InetHostAddress getPeer(tpport_t *port = NULL) const; 00862 00870 inline int Peek(void *buf, size_t len) 00871 {return ::recv(so, (char *)buf, len, MSG_PEEK);}; 00872 }; 00873 00874 00883 class UDPBroadcast : public UDPSocket 00884 { 00885 private: 00886 void setPeer(const InetHostAddress &ia, tpport_t port) {}; 00887 00888 sockerror_t setBroadcast(bool enable) 00889 {return Socket::setBroadcast(enable);}; 00890 00891 public: 00898 UDPBroadcast(const InetAddress &ia, tpport_t port); 00899 00906 void setPeer(const BroadcastAddress &subnet, tpport_t port); 00907 }; 00908 00917 class UDPTransmit : private UDPSocket 00918 { 00919 protected: 00923 UDPTransmit(); 00924 00937 UDPTransmit(const InetAddress &bind, tpport_t port = 5005); 00938 00947 sockerror_t Connect(const InetHostAddress &host, tpport_t port); 00948 00957 sockerror_t Connect(const BroadcastAddress &subnet, tpport_t port); 00958 00963 sockerror_t Disconnect(void); 00964 00972 inline int Send(void *buf, int len) 00973 {return ::send(so, (char *)buf, len, 0);} 00974 00978 inline void endTransmitter(void) 00979 {Socket::endSocket();} 00980 00981 /* 00982 * Get transmitter socket. 00983 * 00984 * @return transmitter. 00985 */ 00986 inline SOCKET getTransmitter(void) 00987 {return so;}; 00988 00989 public: 00999 inline int Transmit(const char *buffer, size_t len) 01000 {return ::send(so, buffer, len, MSG_DONTWAIT);} 01001 01008 inline bool isOutputReady(unsigned long timeout = 0l) 01009 {return Socket::isPending(SOCKET_PENDING_OUTPUT, timeout);}; 01010 01011 01012 inline sockerror_t setRouting(bool enable) 01013 {return Socket::setRouting(enable);}; 01014 01015 inline sockerror_t setTypeOfService(socktos_t tos) 01016 {return Socket::setTypeOfService(tos);}; 01017 01018 inline sockerror_t setBroadcast(bool enable) 01019 {return Socket::setBroadcast(enable);}; 01020 }; 01021 01030 class UDPReceive : private UDPSocket 01031 { 01032 protected: 01044 UDPReceive(const InetAddress &bind, tpport_t port); 01045 01054 sockerror_t Connect(const InetHostAddress &host, tpport_t port); 01055 01060 sockerror_t Disconnect(void); 01061 01068 bool isPendingReceive(timeout_t timeout) 01069 {return Socket::isPending(SOCKET_PENDING_INPUT, timeout);}; 01070 01074 inline void endReceiver(void) 01075 {Socket::endSocket();} 01076 01077 inline SOCKET getReceiver(void) 01078 {return so;}; 01079 01080 inline sockerror_t setRouting(bool enable) 01081 {return Socket::setRouting(enable);}; 01082 01083 public: 01091 inline int Receive(void *buf, size_t len) 01092 {return ::recv(so, (char *)buf, len, 0);}; 01093 01100 inline bool isInputReady(timeout_t timeout = TIMEOUT_INF) 01101 {return Socket::isPending(SOCKET_PENDING_INPUT, timeout);}; 01102 }; 01103 01114 class UDPDuplex : public UDPTransmit, public UDPReceive 01115 { 01116 public: 01125 UDPDuplex(const InetAddress &bind, tpport_t port); 01126 01136 sockerror_t Connect(const InetHostAddress &host, tpport_t port); 01137 01144 sockerror_t Disconnect(void); 01145 }; 01146 01147 01172 class TCPSocket : private Socket 01173 { 01174 protected: 01182 virtual bool OnAccept(const InetHostAddress &ia, short port) { 01183 return false; 01184 } 01185 01197 virtual bool OnAccept(const InetHostAddress &ia, tpport_t port) 01198 {return true;}; 01199 01200 friend class TCPStream; 01201 friend class SocketPort; 01202 friend class tcpstream; 01203 01204 public: 01216 TCPSocket(const InetAddress &bind, tpport_t port, int backlog = 5); 01217 01226 inline InetHostAddress getRequest(tpport_t *port = NULL) const 01227 {return Socket::getSender(port);}; 01228 01232 void Reject(void); 01233 01237 inline InetHostAddress getLocal(tpport_t *port = NULL) const 01238 {return Socket::getLocal(port);}; 01239 01243 inline bool isPendingConnection(timeout_t timeout = TIMEOUT_INF) 01244 {return Socket::isPending(SOCKET_PENDING_INPUT, timeout);} 01245 01249 ~TCPSocket() 01250 {endSocket();}; 01251 }; 01252 01253 /* 01254 :\projects\libraries\cplusplus\commonc++\win32\socket.h(357) : warning C4275: non dll-interface class 'streambuf' used as base for dll-interface class 'TCPStream' 01255 c:\program files\microsoft visual studio\vc98\include\streamb.h(69) : see declaration of 'streambuf' 01256 c:\projects\libraries\cplusplus\commonc++\win32\socket.h(358) : warning C4275: non dll-interface class 'iostream' used as base for dll-interface class 'TCPStream' 01257 c:\program files\microsoft visual studio\vc98\include\iostream.h(66) : see declaration of 'iostream' 01258 */ 01259 01260 #ifndef __KCC 01261 #pragma warning(disable:4275) // disable C4275 warning 01262 #endif 01263 01277 #if defined(STLPORT) || defined(__KCC) 01278 #define iostream iostream_withassign 01279 #endif 01280 #ifdef __KCC 01281 using std::iostream; 01282 #endif 01283 class TCPStream : public Socket, public streambuf, public iostream 01284 { 01285 private: 01286 inline sockerror_t setBroadcast(bool enable) 01287 {return Socket::setBroadcast(enable);}; 01288 01289 inline InetHostAddress getSender(tpport_t *port) const 01290 {return InetHostAddress();}; 01291 01292 int doallocate(); 01293 01294 friend TCPStream& crlf(TCPStream&); 01295 friend TCPStream& lfcr(TCPStream&); 01296 01297 protected: 01298 int bufsize; 01299 char *gbuf, *pbuf; 01300 01305 TCPStream(); 01306 01313 void Allocate(int size); 01314 01319 void endStream(void); 01320 01327 virtual int underflow(void); 01328 01337 int uflow(void); 01338 01346 int overflow(int ch); 01347 01356 void Connect(const InetHostAddress &host, tpport_t port, int size); 01357 01365 iostream *tcp(void) 01366 {return ((iostream *)this);}; 01367 01368 public: 01376 TCPStream(TCPSocket &server, int size = 512); 01377 01386 TCPStream(const InetHostAddress &host, tpport_t port, int size = 512); 01387 01394 TCPStream(const TCPStream &source); 01395 01400 ~TCPStream() 01401 {endStream();}; 01402 01409 int sync(void); 01410 01418 bool isPending(sockpend_t pend, timeout_t timeout = TIMEOUT_INF); 01419 01425 int getBufferSize(void) const 01426 {return bufsize;}; 01427 }; 01428 01437 class tcpstream : public TCPStream 01438 { 01439 public: 01443 tcpstream(); 01444 01452 tcpstream(const char *addr, int buffer = 512); 01453 01461 tcpstream(TCPSocket &tcp, int buffer = 512); 01462 01470 void open(const char *addr, int buffer = 512); 01471 01478 void open(TCPSocket &tcp, int buffer = 512); 01479 01483 void close(void); 01484 01488 bool operator!() const; 01489 }; 01490 01501 class TCPSession : public TCPStream, public Thread 01502 { 01503 protected: 01516 int WaitConnection(timeout_t timeout = TIMEOUT_INF); 01517 01524 void Initial(void); 01525 01531 void Final(void) 01532 {delete this;}; 01533 public: 01545 TCPSession(Semaphore *start, const InetHostAddress &host, 01546 tpport_t port, int size = 512, int pri = 0, int stack = 0); 01547 01559 TCPSession(Semaphore *start, TCPSocket &server, int size = 512, 01560 int pri = 0, int stack = 0); 01561 }; 01562 01563 extern __EXPORT ::ostream &operator<<(::ostream &os, const InetAddress &ia); 01564 01565 inline struct in_addr getaddress(const InetAddress &ia) 01566 {return ia.getAddress();} 01567 01568 #if defined(WIN32) 01569 01583 class init_WSA 01584 { 01585 public: 01586 init_WSA(); 01587 private: 01588 WSADATA wsaData; 01589 }; 01590 01591 #else // !WIN32 01592 01593 class SocketService; 01594 01614 class SocketPort : public Socket, public TimerPort 01615 { 01616 private: 01617 SocketPort *next, *prev; 01618 SocketService *service; 01619 struct timeval porttimer; 01620 #ifdef __CCXX_USE_POLL 01621 struct pollfd * ufd; 01622 #endif 01623 bool detect_pending; 01624 bool detect_output; 01625 bool detect_disconnect; 01626 01627 friend class SocketService; 01628 01629 protected: 01638 SocketPort(SocketService *svc, TCPSocket &tcp); 01639 01648 SocketPort(SocketService *svc, const InetAddress &ia, tpport_t port); 01649 01655 void Attach( SocketService* svc ); 01656 01657 01662 virtual ~SocketPort(); 01663 01668 void setDetectPending( bool ); 01669 01673 bool getDetectPending( void ) const 01674 { return detect_pending; } 01675 01680 void setDetectOutput( bool ); 01681 01685 bool getDetectOutput( void ) const 01686 { return detect_output; } 01687 01692 virtual void Expired(void) 01693 {return;}; 01694 01699 virtual void Pending(void) 01700 {return;}; 01701 01706 virtual void Output(void) 01707 {return;}; 01708 01713 virtual void Disconnect(void) 01714 {return;}; 01715 01726 sockerror_t Connect(const InetAddress &ia, tpport_t port); 01727 01737 inline int Send(void *buf, int len) 01738 {return ::send(so, (char *)buf, len, 0);}; 01739 01748 inline int Recv(void *buf, size_t len) 01749 {return ::recv(so, (char *)buf, len, 0);}; 01750 01759 inline int Peek(void *buf, size_t len) 01760 {return ::recv(so, (char *)buf, len, MSG_PEEK);}; 01761 01762 public: 01770 void setTimer(timeout_t timeout = 0); 01771 01779 void incTimer(timeout_t timeout); 01780 }; 01781 01794 class SocketService : public Thread, private Mutex 01795 { 01796 private: 01797 fd_set connect; 01798 int iosync[2]; 01799 int hiwater; 01800 int count; 01801 SocketPort *first, *last; 01802 01808 void Attach(SocketPort *port); 01814 void Detach(SocketPort *port); 01815 01819 void Run(void); 01820 01821 friend class SocketPort; 01822 01823 protected: 01829 virtual void OnUpdate(unsigned char buf) 01830 {return;}; 01831 01837 virtual void OnEvent(void) 01838 {return;}; 01839 01847 virtual void OnCallback(SocketPort *port) 01848 {return;}; 01849 01850 public: 01861 void Update(unsigned char flag = 0xff); 01862 01869 SocketService(int pri = 0); 01870 01875 ~SocketService(); 01876 01883 inline int getCount(void) const 01884 {return count;}; 01885 }; 01886 01887 #ifdef __CCXX_NAMESPACE_H__ 01888 #undef __CCXX_NAMESPACE_H__ 01889 #include <cc++/namespace.h> 01890 #endif 01891 01892 #endif // !WIN32 01893 01894 #endif 01895 Generated at Fri Mar 23 10:47:54 2001 for CommonC++ by 1.2.1 written by Dimitri van Heesch, © 1997-2000 |