00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00043 #ifndef CCXX_SOCKET_H_
00044 #define CCXX_SOCKET_H_
00045
00046 #ifndef CCXX_ADDRESS_H_
00047 #include <cc++/address.h>
00048 #endif
00049
00050 #if defined(WIN32) && !defined(__CYGWIN32__)
00051 #include <io.h>
00052 #define _IOLEN64 (unsigned)
00053 #define _IORET64 (ssize_t)
00054 #define TIMEOUT_INF ~((timeout_t) 0)
00055 typedef int socklen_t;
00056 #else
00057 #define INVALID_SOCKET -1
00058 typedef int SOCKET;
00059 #endif
00060
00061 #ifndef _IOLEN64
00062 #define _IOLEN64
00063 #endif
00064
00065 #ifndef _IORET64
00066 #define _IORET64
00067 #endif
00068
00069 #ifndef MSG_DONTWAIT
00070 #define MSG_DONTWAIT 0
00071 #endif
00072
00073 #ifdef CCXX_NAMESPACES
00074 namespace ost {
00075 #endif
00076
00080 typedef unsigned short tpport_t;
00081
00099 class __EXPORT Socket
00100 {
00101 public:
00102 enum Family
00103 {
00104 #ifdef CCXX_IPV6
00105 IPV6 = AF_INET6,
00106 #endif
00107 IPV4 = AF_INET
00108 };
00109
00110 typedef enum Family Family;
00111
00112 enum Error
00113 {
00114 errSuccess = 0,
00115 errCreateFailed,
00116 errCopyFailed,
00117 errInput,
00118 errInputInterrupt,
00119 errResourceFailure,
00120 errOutput,
00121 errOutputInterrupt,
00122 errNotConnected,
00123 errConnectRefused,
00124 errConnectRejected,
00125 errConnectTimeout,
00126 errConnectFailed,
00127 errConnectInvalid,
00128 errConnectBusy,
00129 errConnectNoRoute,
00130 errBindingFailed,
00131 errBroadcastDenied,
00132 errRoutingDenied,
00133 errKeepaliveDenied,
00134 errServiceDenied,
00135 errServiceUnavailable,
00136 errMulticastDisabled,
00137 errTimeout,
00138 errNoDelay,
00139 errExtended,
00140 errLookupFail,
00141 errSearchErr,
00142 errInvalidValue
00143 };
00144
00145 typedef enum Error Error;
00146
00147 enum Tos
00148 {
00149 tosLowDelay = 0,
00150 tosThroughput,
00151 tosReliability,
00152 tosMinCost,
00153 tosInvalid
00154 };
00155 typedef enum Tos Tos;
00156
00157 enum Pending
00158 {
00159 pendingInput,
00160 pendingOutput,
00161 pendingError
00162 };
00163 typedef enum Pending Pending;
00164
00165 protected:
00166 enum State
00167 {
00168 INITIAL,
00169 AVAILABLE,
00170 BOUND,
00171 CONNECTED,
00172 CONNECTING,
00173 STREAM
00174 };
00175 typedef enum State State;
00176
00177 private:
00178
00179 mutable Error errid;
00180 mutable const char *errstr;
00181 mutable long syserr;
00182
00183 void setSocket(void);
00184 friend SOCKET dupSocket(SOCKET s,Socket::State state);
00185
00186 protected:
00187 static Mutex mutex;
00188
00189 mutable struct
00190 {
00191 bool thrown: 1;
00192 bool broadcast: 1;
00193 bool route: 1;
00194 bool keepalive: 1;
00195 bool loopback: 1;
00196 bool multicast: 1;
00197 bool completion: 1;
00198 bool linger: 1;
00199 unsigned ttl: 8;
00200 } flags;
00201
00207 SOCKET volatile so;
00208 State volatile state;
00209
00218 Error error(Error error, char *err = NULL, long systemError = 0) const;
00219
00226 inline void error(char *err) const
00227 {error(errExtended, err);};
00228
00235 inline void setError(bool enable)
00236 {flags.thrown = !enable;};
00237
00243 void endSocket(void);
00244
00250 Error connectError(void);
00251
00255 Error sendLimit(int limit = 2048);
00256
00260 Error receiveLimit(int limit = 1);
00261
00268 Error sendTimeout(timeout_t to);
00269
00273 Error receiveTimeout(timeout_t to);
00274
00281 Error sendBuffer(unsigned bufsize);
00282
00289 Error receiveBuffer(unsigned bufsize);
00290
00297 Error bufferSize(unsigned bufsize);
00298
00307 Error setBroadcast(bool enable);
00308
00319 Error setMulticastByFamily(bool enable, Family family = IPV4);
00320
00328 Error setLoopbackByFamily(bool enable, Family family = IPV4);
00329
00336 Error setTimeToLiveByFamily(unsigned char ttl, Family fam = IPV4);
00337
00344 Error join(const IPV4Multicast &ia);
00345 #ifdef CCXX_IPV6
00346 Error join(const IPV6Multicast &ia);
00347 #endif
00348
00355 Error drop(const IPV4Multicast &ia);
00356 #ifdef CCXX_IPV6
00357 Error drop(const IPV6Multicast &ia);
00358 #endif
00359
00367 Error setRouting(bool enable);
00368
00369
00376 Error setNoDelay(bool enable);
00377
00389 Socket(int domain, int type, int protocol = 0);
00390
00398 Socket(SOCKET fd);
00399
00403 Socket();
00404
00412 Socket(const Socket &source);
00413
00423 ssize_t readLine(char *buf, size_t len, timeout_t timeout = 0);
00424
00436 virtual ssize_t readData(void * buf,size_t len,char separator=0,timeout_t t=0);
00437
00446 virtual ssize_t writeData(const void* buf,size_t len,timeout_t t=0);
00447
00448
00449 public:
00457 virtual ~Socket();
00458
00465 static bool check(Family fam);
00466
00470 Socket &operator=(const Socket &from);
00471
00481 IPV4Host getIPV4Sender(tpport_t *port = NULL) const;
00482
00483 inline IPV4Host getSender(tpport_t *port = NULL) const
00484 {return getIPV4Sender(port);}
00485
00486 #ifdef CCXX_IPV6
00487 IPV6Host getIPV6Sender(tpport_t *port = NULL) const;
00488 #endif
00489
00499 IPV4Host getIPV4Peer(tpport_t *port = NULL) const;
00500
00501 inline IPV4Host getPeer(tpport_t *port = NULL) const
00502 {return getIPV4Peer(port);}
00503
00504 #ifdef CCXX_IPV6
00505 IPV6Host getIPV6Peer(tpport_t *port = NULL) const;
00506 #endif
00507
00515 IPV4Host getIPV4Local(tpport_t *port = NULL) const;
00516
00517 inline IPV4Host getLocal(tpport_t *port = NULL) const
00518 {return getIPV4Local(port);}
00519
00520 #ifdef CCXX_IPV6
00521 IPV6Host getIPV6Local(tpport_t *port = NULL) const;
00522 #endif
00523
00551 IPV4Host getIPV4NAT(tpport_t *port = NULL) const;
00552
00553 inline IPV4Host getNAT(tpport_t *port) const
00554 {return getIPV4NAT(port);}
00555
00556 #ifdef CCXX_IPV6
00557 IPV6Host getIPV6NAT(tpport_t *port = NULL) const;
00558 #endif
00559
00570 void setCompletion(bool immediate);
00571
00577 Error setLinger(bool linger);
00578
00586 Error setKeepAlive(bool enable);
00587
00596 Error setTypeOfService(Tos service);
00597
00606 bool isConnected(void) const;
00607
00615 bool isActive(void) const;
00616
00621 bool operator!() const;
00622
00629 inline bool isBroadcast(void) const
00630 {return flags.broadcast;};
00631
00637 inline bool isRouted(void) const
00638 {return flags.route;};
00639
00646 inline Error getErrorNumber(void) const {return errid;}
00647
00654 inline const char *getErrorString(void) const {return errstr;}
00655
00656 inline long getSystemError(void) const {return syserr;}
00657
00658 const char *getSystemErrorString(void) const;
00659
00669 virtual bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
00670 };
00671
00704 class __EXPORT UDPSocket : public Socket
00705 {
00706 private:
00707 inline Error setKeepAlive(bool enable)
00708 {return Socket::setKeepAlive(enable);};
00709
00710 protected:
00711 #ifdef CCXX_IPV6
00712 union
00713 {
00714 struct sockaddr_in6 ipv6;
00715 struct sockaddr_in ipv4;
00716 } peer;
00717 #else
00718 union
00719 {
00720 struct sockaddr_in ipv4;
00721 } peer;
00722 #endif
00723
00724 Family family;
00725
00726 public:
00730 UDPSocket(Family family = IPV4);
00731
00735 UDPSocket(const char *name, Family family = IPV4);
00736
00746 UDPSocket(const IPV4Address &bind, tpport_t port);
00747 #ifdef CCXX_IPV6
00748 UDPSocket(const IPV6Address &bind, tpport_t port);
00749 #endif
00750
00754 virtual ~UDPSocket();
00755
00759 inline Error setLoopback(bool enable)
00760 {return Socket::setLoopbackByFamily(enable, family);}
00761
00765 inline Error setMulticast(bool enable)
00766 {return Socket::setMulticastByFamily(enable, family);}
00767
00771 inline Error setTimeToLive(char ttl)
00772 {return Socket::setTimeToLiveByFamily(ttl, family);}
00773
00781 void setPeer(const IPV4Host &host, tpport_t port);
00782 void connect(const IPV4Host &host, tpport_t port);
00783 #ifdef CCXX_IPV6
00784 void setPeer(const IPV6Host &host, tpport_t port);
00785 void connect(const IPV6Host &host, tpport_t port);
00786 #endif
00787
00795 Socket::Error getInterfaceIndex(const char *ethX,int& InterfaceIndex);
00796
00805 Socket::Error join(const IPV4Multicast &ia,int InterfaceIndex);
00806
00807
00815 ssize_t send(const void *buf, size_t len);
00816
00825 ssize_t receive(void *buf, size_t len, bool reply = false);
00826
00835 IPV4Host getIPV4Peer(tpport_t *port = NULL) const;
00836 inline IPV4Host getPeer(tpport_t *port = NULL) const
00837 {return getIPV4Peer(port);}
00838
00839 #ifdef CCXX_IPV6
00840 IPV6Host getIPV6Peer(tpport_t *port = NULL) const;
00841 #endif
00842
00850 inline ssize_t peek(void *buf, size_t len)
00851 {return _IORET64 ::recv(so, (char *)buf, _IOLEN64 len, MSG_PEEK);};
00852
00856 void setPeer(const char *service);
00857 void connect(const char *service);
00858
00863 Error disconnect(void);
00864 };
00865
00866
00875 class __EXPORT UDPBroadcast : public UDPSocket
00876 {
00877 private:
00878 void setPeer(const IPV4Host &ia, tpport_t port);
00879
00880 Error setBroadcast(bool enable)
00881 {return Socket::setBroadcast(enable);};
00882
00883 public:
00890 UDPBroadcast(const IPV4Address &ia, tpport_t port);
00891
00898 void setPeer(const IPV4Broadcast &subnet, tpport_t port);
00899 };
00900
00909 class __EXPORT UDPTransmit : protected UDPSocket
00910 {
00911 private:
00919 Error cConnect(const IPV4Address &ia, tpport_t port);
00920
00921 protected:
00925 UDPTransmit(Family family = IPV4);
00926
00938 UDPTransmit(const IPV4Address &bind, tpport_t port = 5005);
00939 #ifdef CCXX_IPV6
00940 UDPTransmit(const IPV6Address &bind, tpport_t port = 5005);
00941 #endif
00942
00952 Error connect(const IPV4Host &host, tpport_t port);
00953 #ifdef CCXX_IPV6
00954 Error connect(const IPV6Address &host, tpport_t port);
00955 #endif
00956
00966 Error connect(const IPV4Broadcast &subnet, tpport_t port);
00967
00975 Error connect(const IPV4Multicast &mgroup, tpport_t port);
00976 #ifdef CCXX_IPV6
00977 Error connect(const IPV6Multicast &mgroup, tpport_t port);
00978 #endif
00979
00987 inline ssize_t send(const void *buf, size_t len)
00988 {return _IORET64 ::send(so, (const char *)buf, _IOLEN64 len, 0);}
00989
00993 inline void endTransmitter(void)
00994 {Socket::endSocket();}
00995
00996
00997
00998
00999
01000
01001 inline SOCKET getTransmitter(void)
01002 {return so;};
01003
01004 inline Error setMulticast(bool enable)
01005 {return Socket::setMulticastByFamily(enable, family);}
01006
01007 inline Error setTimeToLive(unsigned char ttl)
01008 {return Socket::setTimeToLiveByFamily(ttl, family);};
01009
01010 public:
01020 inline ssize_t transmit(const char *buffer, size_t len)
01021 {return _IORET64 ::send(so, buffer, _IOLEN64 len, MSG_DONTWAIT);}
01022
01029 inline bool isOutputReady(unsigned long timeout = 0l)
01030 {return Socket::isPending(Socket::pendingOutput, timeout);};
01031
01032
01033 inline Error setRouting(bool enable)
01034 {return Socket::setRouting(enable);};
01035
01036 inline Error setTypeOfService(Tos tos)
01037 {return Socket::setTypeOfService(tos);};
01038
01039 inline Error setBroadcast(bool enable)
01040 {return Socket::setBroadcast(enable);};
01041 };
01042
01051 class __EXPORT UDPReceive : protected UDPSocket
01052 {
01053 protected:
01064 UDPReceive(const IPV4Address &bind, tpport_t port);
01065 #ifdef CCXX_IPV6
01066 UDPReceive(const IPV6Address &bind, tpport_t port);
01067 #endif
01068
01078 Error connect(const IPV4Host &host, tpport_t port);
01079 #ifdef CCXX_IPV6
01080 Error connect(const IPV6Host &host, tpport_t port);
01081 #endif
01082
01089 bool isPendingReceive(timeout_t timeout)
01090 {return Socket::isPending(Socket::pendingInput, timeout);};
01091
01095 inline void endReceiver(void)
01096 {Socket::endSocket();}
01097
01098 inline SOCKET getReceiver(void) const
01099 {return so;};
01100
01101 inline Error setRouting(bool enable)
01102 {return Socket::setRouting(enable);}
01103
01104 inline Error setMulticast(bool enable)
01105 {return Socket::setMulticastByFamily(enable, family);}
01106
01107 inline Error join(const IPV4Multicast &ia)
01108 {return Socket::join(ia);}
01109
01110 #ifdef CCXX_IPV6
01111 inline Error join(const IPV6Multicast &ia)
01112 {return Socket::join(ia);}
01113 #endif
01114
01115 inline Error drop(const IPV4Multicast &ia)
01116 {return Socket::drop(ia);}
01117
01118 #ifdef CCXX_IPV6
01119 inline Error drop(const IPV6Multicast &ia)
01120 {return Socket::drop(ia);}
01121 #endif
01122
01123 public:
01131 inline ssize_t receive(void *buf, size_t len)
01132 {return _IORET64 ::recv(so, (char *)buf, _IOLEN64 len, 0);};
01133
01140 inline bool isInputReady(timeout_t timeout = TIMEOUT_INF)
01141 {return Socket::isPending(Socket::pendingInput, timeout);};
01142 };
01143
01154 class __EXPORT UDPDuplex : public UDPTransmit, public UDPReceive
01155 {
01156 public:
01164 UDPDuplex(const IPV4Address &bind, tpport_t port);
01165 #ifdef CCXX_IPV6
01166 UDPDuplex(const IPV6Address &bind, tpport_t port);
01167 #endif
01168
01178 Error connect(const IPV4Host &host, tpport_t port);
01179 #ifdef CCXX_IPV6
01180 Error connect(const IPV6Host &host, tpport_t port);
01181 #endif
01182
01189 Error disconnect(void);
01190 };
01191
01192
01217 class __EXPORT TCPSocket : protected Socket
01218 {
01219 protected:
01220 int segsize;
01221 void setSegmentSize(unsigned mss);
01222
01223 public:
01235 virtual bool onAccept(const IPV4Host &ia, tpport_t port);
01236
01240 inline SOCKET getSocket(void)
01241 {return so;};
01242
01246 inline int getSegmentSize(void)
01247 {return segsize;};
01248
01261 TCPSocket(const IPV4Address &bind, tpport_t port, unsigned backlog = 5, unsigned mss = 536);
01262
01272 TCPSocket(const char *service, unsigned backlog = 5, unsigned mss = 536);
01273
01282 inline IPV4Host getRequest(tpport_t *port = NULL) const
01283 {return Socket::getIPV4Sender(port);}
01284
01288 void reject(void);
01289
01293 inline IPV4Host getLocal(tpport_t *port = NULL) const
01294 {return Socket::getIPV4Local(port);}
01295
01301 inline bool isPendingConnection(timeout_t timeout = TIMEOUT_INF)
01302 {return Socket::isPending(Socket::pendingInput, timeout);}
01303
01307 virtual ~TCPSocket();
01308 };
01309
01310 #ifdef CCXX_IPV6
01311
01335 class __EXPORT TCPV6Socket : protected Socket
01336 {
01337 private:
01338 int segsize;
01339 void setSegmentSize(unsigned mss);
01340
01341 public:
01353 virtual bool onAccept(const IPV6Host &ia, tpport_t port);
01354
01358 inline SOCKET getSocket(void)
01359 {return so;};
01360
01361 inline int getSegmentSize(void)
01362 {return segsize;};
01363
01375 TCPV6Socket(const IPV6Address &bind, tpport_t port, unsigned backlog = 5, unsigned mss = 536);
01376
01386 TCPV6Socket(const char *service, unsigned backlog = 5, unsigned mss = 536);
01387
01396 inline IPV6Host getRequest(tpport_t *port = NULL) const
01397 {return Socket::getIPV6Sender(port);}
01398
01402 void reject(void);
01403
01407 inline IPV6Host getLocal(tpport_t *port = NULL) const
01408 {return Socket::getIPV6Local(port);}
01409
01415 inline bool isPendingConnection(timeout_t timeout = TIMEOUT_INF)
01416 {return Socket::isPending(Socket::pendingInput, timeout);}
01417
01421 virtual ~TCPV6Socket();
01422 };
01423
01424 #endif
01425
01426
01427
01428
01429
01430
01431
01432
01433 #ifdef _MSC_VER
01434 #pragma warning(disable:4275) // disable C4275 warning
01435 #endif
01436
01450 class __EXPORT TCPStream : protected std::streambuf, public Socket, public std::iostream
01451 {
01452 private:
01453 int doallocate();
01454
01455 void segmentBuffering(unsigned mss);
01456
01457 friend TCPStream& crlf(TCPStream&);
01458 friend TCPStream& lfcr(TCPStream&);
01459
01460 protected:
01461 timeout_t timeout;
01462 size_t bufsize;
01463 Family family;
01464 char *gbuf, *pbuf;
01465
01466 public:
01471 TCPStream(Family family = IPV4, bool throwflag = true, timeout_t to = 0);
01472
01476 void disconnect(void);
01477
01481 int getSegmentSize(void);
01482
01483 protected:
01490 void allocate(size_t size);
01491
01496 void endStream(void);
01497
01504 int underflow();
01505
01514 int uflow();
01515
01523 int overflow(int ch);
01524
01533 void connect(const IPV4Host &host, tpport_t port, unsigned mss = 536);
01534 #ifdef CCXX_IPV6
01535 void connect(const IPV6Host &host, tpport_t port, unsigned mss = 536);
01536 #endif
01537
01545 void connect(const char *service, unsigned mss = 536);
01546
01554 std::iostream *tcp(void)
01555 {return ((std::iostream *)this);};
01556
01557 public:
01568 TCPStream(TCPSocket &server, bool throwflag = true, timeout_t timeout = 0);
01569 #ifdef CCXX_IPV6
01570 TCPStream(TCPV6Socket &server, bool throwflag = true, timeout_t timeout = 0);
01571 #endif
01572
01578 void connect(TCPSocket &server);
01579 #ifdef CCXX_IPV6
01580 void connect(TCPV6Socket &server);
01581 #endif
01582
01593 TCPStream(const IPV4Host &host, tpport_t port, unsigned mss = 536, bool throwflag = true, timeout_t timeout = 0);
01594 #ifdef CCXX_IPV6
01595 TCPStream(const IPV6Host &host, tpport_t port, unsigned mss = 536, bool throwflag = true, timeout_t timeout = 0);
01596 #endif
01597
01607 TCPStream(const char *service, Family fam = IPV4, unsigned mss = 536, bool throwflag = false, timeout_t to = 0);
01608
01614 inline void setTimeout(timeout_t to)
01615 {timeout = to;};
01616
01623 TCPStream(const TCPStream &source);
01624
01629 virtual ~TCPStream();
01630
01637 int sync(void);
01638
01639 #ifdef HAVE_SNPRINTF
01640
01646 size_t printf(const char *format, ...);
01647 #endif
01648
01656 bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
01657
01665 inline ssize_t peek(void *buf, size_t len)
01666 {return _IORET64 ::recv(so, (char *)buf, _IOLEN64 len, MSG_PEEK);};
01667
01673 inline size_t getBufferSize(void) const
01674 {return bufsize;};
01675 };
01676
01687 class __EXPORT TCPSession : public Thread, public TCPStream
01688 {
01689 private:
01690 TCPSession(const TCPSession &rhs);
01691 protected:
01704 int waitConnection(timeout_t timeout = TIMEOUT_INF);
01705
01712 void initial(void);
01713
01714 public:
01725 TCPSession(const IPV4Host &host,
01726 tpport_t port, size_t size = 536, int pri = 0, size_t stack = 0);
01727 #ifdef CCXX_IPV6
01728 TCPSession(const IPV6Host &host,
01729 tpport_t port, size_t size = 536, int pri = 0, size_t stack = 0);
01730 #endif
01731
01742 TCPSession(TCPSocket &server, int pri = 0, size_t stack = 0);
01743 #ifdef CCXX_IPV6
01744 TCPSession(TCPV6Socket &server, int pri = 0, size_t stack = 0);
01745 #endif
01746
01750 virtual ~TCPSession();
01751 };
01752
01753 #if defined(WIN32)
01754
01764 class init_WSA
01765 {
01766 public:
01767 init_WSA();
01768 ~init_WSA();
01769 };
01770
01771 #endif // WIN32
01772
01773 class __EXPORT SimpleTCPStream;
01774
01786 class __EXPORT SimpleTCPStream : public Socket
01787 {
01788 private:
01789
01790 IPV4Host getSender(tpport_t *port) const;
01791
01792 protected:
01797 SimpleTCPStream();
01798
01803 void endStream(void);
01804
01813 void Connect(const IPV4Host &host, tpport_t port, size_t size);
01814
01815
01816 public:
01825 SimpleTCPStream(TCPSocket &server, size_t size = 512);
01826
01835 SimpleTCPStream(const IPV4Host &host, tpport_t port, size_t size = 512);
01836
01842 SimpleTCPStream(const SimpleTCPStream &source);
01843
01848 virtual ~SimpleTCPStream();
01849
01861 bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
01862
01863 void flush() {}
01864
01876 ssize_t read(char *bytes, size_t length, timeout_t timeout = 0);
01877
01889 ssize_t write(const char *bytes, size_t length, timeout_t timeout = 0);
01890
01904 ssize_t peek(char *bytes, size_t length, timeout_t timeout = 0);
01905
01906 };
01907
01908 #ifdef COMMON_STD_EXCEPTION
01909 class __EXPORT SockException : public IOException
01910 {
01911 private:
01912 Socket::Error _socketError;
01913
01914 public:
01915 SockException(const String &str, Socket::Error socketError, long systemError = 0) :
01916 IOException(str, systemError), _socketError(socketError) {};
01917
01918 inline Socket::Error getSocketError() const
01919 { return _socketError; }
01920 };
01921 #endif
01922
01923 #ifdef CCXX_NAMESPACES
01924 }
01925 #endif
01926
01927 #endif
01928