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 (int)
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 #ifndef MSG_NOSIGNAL
00074 #define MSG_NOSIGNAL 0
00075 #endif
00076
00077 #ifdef CCXX_NAMESPACES
00078 namespace ost {
00079 #endif
00080
00084 typedef unsigned short tpport_t;
00085
00103 class __EXPORT Socket
00104 {
00105 public:
00106 enum Family
00107 {
00108 #ifdef CCXX_IPV6
00109 IPV6 = AF_INET6,
00110 #endif
00111 IPV4 = AF_INET
00112 };
00113
00114 typedef enum Family Family;
00115
00116 enum Error
00117 {
00118 errSuccess = 0,
00119 errCreateFailed,
00120 errCopyFailed,
00121 errInput,
00122 errInputInterrupt,
00123 errResourceFailure,
00124 errOutput,
00125 errOutputInterrupt,
00126 errNotConnected,
00127 errConnectRefused,
00128 errConnectRejected,
00129 errConnectTimeout,
00130 errConnectFailed,
00131 errConnectInvalid,
00132 errConnectBusy,
00133 errConnectNoRoute,
00134 errBindingFailed,
00135 errBroadcastDenied,
00136 errRoutingDenied,
00137 errKeepaliveDenied,
00138 errServiceDenied,
00139 errServiceUnavailable,
00140 errMulticastDisabled,
00141 errTimeout,
00142 errNoDelay,
00143 errExtended,
00144 errLookupFail,
00145 errSearchErr,
00146 errInvalidValue
00147 };
00148
00149 typedef enum Error Error;
00150
00151 enum Tos
00152 {
00153 tosLowDelay = 0,
00154 tosThroughput,
00155 tosReliability,
00156 tosMinCost,
00157 tosInvalid
00158 };
00159 typedef enum Tos Tos;
00160
00161 enum Pending
00162 {
00163 pendingInput,
00164 pendingOutput,
00165 pendingError
00166 };
00167 typedef enum Pending Pending;
00168
00169 protected:
00170 enum State
00171 {
00172 INITIAL,
00173 AVAILABLE,
00174 BOUND,
00175 CONNECTED,
00176 CONNECTING,
00177 STREAM
00178 };
00179 typedef enum State State;
00180
00181 private:
00182
00183 mutable Error errid;
00184 mutable const char *errstr;
00185 mutable long syserr;
00186
00187 void setSocket(void);
00188 friend SOCKET dupSocket(SOCKET s,Socket::State state);
00189
00190 protected:
00191 static Mutex mutex;
00192
00193 mutable struct
00194 {
00195 bool thrown: 1;
00196 bool broadcast: 1;
00197 bool route: 1;
00198 bool keepalive: 1;
00199 bool loopback: 1;
00200 bool multicast: 1;
00201 bool completion: 1;
00202 bool linger: 1;
00203 unsigned ttl: 8;
00204 } flags;
00205
00211 SOCKET volatile so;
00212 State volatile state;
00213
00222 Error error(Error error, char *err = NULL, long systemError = 0) const;
00223
00230 inline void error(char *err) const
00231 {error(errExtended, err);};
00232
00239 inline void setError(bool enable)
00240 {flags.thrown = !enable;};
00241
00247 void endSocket(void);
00248
00254 Error connectError(void);
00255
00259 Error sendLimit(int limit = 2048);
00260
00264 Error receiveLimit(int limit = 1);
00265
00272 Error sendTimeout(timeout_t timer);
00273
00280 Error receiveTimeout(timeout_t timer);
00281
00289 Error sendBuffer(unsigned size);
00290
00298 Error receiveBuffer(unsigned size);
00299
00307 Error bufferSize(unsigned size);
00308
00317 Error setBroadcast(bool enable);
00318
00330 Error setMulticastByFamily(bool enable, Family family = IPV4);
00331
00340 Error setLoopbackByFamily(bool enable, Family family = IPV4);
00341
00349 Error setTimeToLiveByFamily(unsigned char ttl, Family fam = IPV4);
00350
00357 Error join(const IPV4Multicast &ia);
00358 #ifdef CCXX_IPV6
00359 Error join(const IPV6Multicast &ia);
00360 #endif
00361
00368 Error drop(const IPV4Multicast &ia);
00369 #ifdef CCXX_IPV6
00370 Error drop(const IPV6Multicast &ia);
00371 #endif
00372
00380 Error setRouting(bool enable);
00381
00382
00389 Error setNoDelay(bool enable);
00390
00402 Socket(int domain, int type, int protocol = 0);
00403
00411 Socket(SOCKET fd);
00412
00416 Socket();
00417
00425 Socket(const Socket &source);
00426
00436 ssize_t readLine(char *buf, size_t len, timeout_t timeout = 0);
00437
00449 virtual ssize_t readData(void * buf,size_t len,char separator=0,timeout_t t=0);
00450
00459 virtual ssize_t writeData(const void* buf,size_t len,timeout_t t=0);
00460
00461 public:
00469 virtual ~Socket();
00470
00477 static bool check(Family fam);
00478
00482 Socket &operator=(const Socket &from);
00483
00493 IPV4Host getIPV4Sender(tpport_t *port = NULL) const;
00494
00495 inline IPV4Host getSender(tpport_t *port = NULL) const
00496 {return getIPV4Sender(port);}
00497
00498 #ifdef CCXX_IPV6
00499 IPV6Host getIPV6Sender(tpport_t *port = NULL) const;
00500 #endif
00501
00511 IPV4Host getIPV4Peer(tpport_t *port = NULL) const;
00512
00513 inline IPV4Host getPeer(tpport_t *port = NULL) const
00514 {return getIPV4Peer(port);}
00515
00516 #ifdef CCXX_IPV6
00517 IPV6Host getIPV6Peer(tpport_t *port = NULL) const;
00518 #endif
00519
00527 IPV4Host getIPV4Local(tpport_t *port = NULL) const;
00528
00529 inline IPV4Host getLocal(tpport_t *port = NULL) const
00530 {return getIPV4Local(port);}
00531
00532 #ifdef CCXX_IPV6
00533 IPV6Host getIPV6Local(tpport_t *port = NULL) const;
00534 #endif
00535
00563 IPV4Host getIPV4NAT(tpport_t *port = NULL) const;
00564
00565 inline IPV4Host getNAT(tpport_t *port) const
00566 {return getIPV4NAT(port);}
00567
00568 #ifdef CCXX_IPV6
00569 IPV6Host getIPV6NAT(tpport_t *port = NULL) const;
00570 #endif
00571
00582 void setCompletion(bool immediate);
00583
00589 Error setLinger(bool linger);
00590
00598 Error setKeepAlive(bool enable);
00599
00608 Error setTypeOfService(Tos service);
00609
00618 bool isConnected(void) const;
00619
00627 bool isActive(void) const;
00628
00633 bool operator!() const;
00634
00641 inline bool isBroadcast(void) const
00642 {return flags.broadcast;};
00643
00649 inline bool isRouted(void) const
00650 {return flags.route;};
00651
00658 inline Error getErrorNumber(void) const {return errid;}
00659
00666 inline const char *getErrorString(void) const {return errstr;}
00667
00668 inline long getSystemError(void) const {return syserr;}
00669
00670 const char *getSystemErrorString(void) const;
00671
00681 virtual bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
00682 };
00683
00716 class __EXPORT UDPSocket : public Socket
00717 {
00718 private:
00719 inline Error setKeepAlive(bool enable)
00720 {return Socket::setKeepAlive(enable);};
00721
00722 protected:
00723 #ifdef CCXX_IPV6
00724 union
00725 {
00726 struct sockaddr_in6 ipv6;
00727 struct sockaddr_in ipv4;
00728 } peer;
00729 #else
00730 union
00731 {
00732 struct sockaddr_in ipv4;
00733 } peer;
00734 #endif
00735
00736 Family family;
00737
00738 public:
00742 UDPSocket(Family family = IPV4);
00743
00747 UDPSocket(const char *name, Family family = IPV4);
00748
00758 UDPSocket(const IPV4Address &bind, tpport_t port);
00759 #ifdef CCXX_IPV6
00760 UDPSocket(const IPV6Address &bind, tpport_t port);
00761 #endif
00762
00766 virtual ~UDPSocket();
00767
00771 inline Error setLoopback(bool enable)
00772 {return Socket::setLoopbackByFamily(enable, family);}
00773
00777 inline Error setMulticast(bool enable)
00778 {return Socket::setMulticastByFamily(enable, family);}
00779
00783 inline Error setTimeToLive(char ttl)
00784 {return Socket::setTimeToLiveByFamily(ttl, family);}
00785
00793 void setPeer(const IPV4Host &host, tpport_t port);
00794 void connect(const IPV4Host &host, tpport_t port);
00795 #ifdef CCXX_IPV6
00796 void setPeer(const IPV6Host &host, tpport_t port);
00797 void connect(const IPV6Host &host, tpport_t port);
00798 #endif
00799
00807 Socket::Error getInterfaceIndex(const char *ethX,int& InterfaceIndex);
00808
00817 Socket::Error join(const IPV4Multicast &ia,int InterfaceIndex);
00818
00819
00827 ssize_t send(const void *buf, size_t len);
00828
00837 ssize_t receive(void *buf, size_t len, bool reply = false);
00838
00847 IPV4Host getIPV4Peer(tpport_t *port = NULL) const;
00848 inline IPV4Host getPeer(tpport_t *port = NULL) const
00849 {return getIPV4Peer(port);}
00850
00851 #ifdef CCXX_IPV6
00852 IPV6Host getIPV6Peer(tpport_t *port = NULL) const;
00853 #endif
00854
00862 inline ssize_t peek(void *buf, size_t len)
00863 {return _IORET64 ::recv(so, (char *)buf, _IOLEN64 len, MSG_PEEK);};
00864
00868 void setPeer(const char *service);
00869 void connect(const char *service);
00870
00875 Error disconnect(void);
00876 };
00877
00878
00887 class __EXPORT UDPBroadcast : public UDPSocket
00888 {
00889 private:
00890 void setPeer(const IPV4Host &ia, tpport_t port);
00891
00892 Error setBroadcast(bool enable)
00893 {return Socket::setBroadcast(enable);};
00894
00895 public:
00902 UDPBroadcast(const IPV4Address &ia, tpport_t port);
00903
00910 void setPeer(const IPV4Broadcast &subnet, tpport_t port);
00911 };
00912
00921 class __EXPORT UDPTransmit : protected UDPSocket
00922 {
00923 private:
00931 Error cConnect(const IPV4Address &ia, tpport_t port);
00932
00933 protected:
00937 UDPTransmit(Family family = IPV4);
00938
00950 UDPTransmit(const IPV4Address &bind, tpport_t port = 5005);
00951 #ifdef CCXX_IPV6
00952 UDPTransmit(const IPV6Address &bind, tpport_t port = 5005);
00953 #endif
00954
00964 Error connect(const IPV4Host &host, tpport_t port);
00965 #ifdef CCXX_IPV6
00966 Error connect(const IPV6Address &host, tpport_t port);
00967 #endif
00968
00978 Error connect(const IPV4Broadcast &subnet, tpport_t port);
00979
00987 Error connect(const IPV4Multicast &mgroup, tpport_t port);
00988 #ifdef CCXX_IPV6
00989 Error connect(const IPV6Multicast &mgroup, tpport_t port);
00990 #endif
00991
00999 inline ssize_t send(const void *buf, size_t len)
01000 {return _IORET64 ::send(so, (const char *)buf, _IOLEN64 len, MSG_NOSIGNAL);}
01001
01005 inline void endTransmitter(void)
01006 {Socket::endSocket();}
01007
01008
01009
01010
01011
01012
01013 inline SOCKET getTransmitter(void)
01014 {return so;};
01015
01016 inline Error setMulticast(bool enable)
01017 {return Socket::setMulticastByFamily(enable, family);}
01018
01019 inline Error setTimeToLive(unsigned char ttl)
01020 {return Socket::setTimeToLiveByFamily(ttl, family);};
01021
01022 public:
01032 inline ssize_t transmit(const char *buffer, size_t len)
01033 {return _IORET64 ::send(so, buffer, _IOLEN64 len, MSG_DONTWAIT|MSG_NOSIGNAL);}
01034
01041 inline bool isOutputReady(unsigned long timeout = 0l)
01042 {return Socket::isPending(Socket::pendingOutput, timeout);};
01043
01044
01045 inline Error setRouting(bool enable)
01046 {return Socket::setRouting(enable);};
01047
01048 inline Error setTypeOfService(Tos tos)
01049 {return Socket::setTypeOfService(tos);};
01050
01051 inline Error setBroadcast(bool enable)
01052 {return Socket::setBroadcast(enable);};
01053 };
01054
01063 class __EXPORT UDPReceive : protected UDPSocket
01064 {
01065 protected:
01076 UDPReceive(const IPV4Address &bind, tpport_t port);
01077 #ifdef CCXX_IPV6
01078 UDPReceive(const IPV6Address &bind, tpport_t port);
01079 #endif
01080
01090 Error connect(const IPV4Host &host, tpport_t port);
01091 #ifdef CCXX_IPV6
01092 Error connect(const IPV6Host &host, tpport_t port);
01093 #endif
01094
01101 bool isPendingReceive(timeout_t timeout)
01102 {return Socket::isPending(Socket::pendingInput, timeout);};
01103
01107 inline void endReceiver(void)
01108 {Socket::endSocket();}
01109
01110 inline SOCKET getReceiver(void) const
01111 {return so;};
01112
01113 inline Error setRouting(bool enable)
01114 {return Socket::setRouting(enable);}
01115
01116 inline Error setMulticast(bool enable)
01117 {return Socket::setMulticastByFamily(enable, family);}
01118
01119 inline Error join(const IPV4Multicast &ia)
01120 {return Socket::join(ia);}
01121
01122 #ifdef CCXX_IPV6
01123 inline Error join(const IPV6Multicast &ia)
01124 {return Socket::join(ia);}
01125 #endif
01126
01127 inline Error drop(const IPV4Multicast &ia)
01128 {return Socket::drop(ia);}
01129
01130 #ifdef CCXX_IPV6
01131 inline Error drop(const IPV6Multicast &ia)
01132 {return Socket::drop(ia);}
01133 #endif
01134
01135 public:
01143 inline ssize_t receive(void *buf, size_t len)
01144 {return _IORET64 ::recv(so, (char *)buf, _IOLEN64 len, 0);};
01145
01152 inline bool isInputReady(timeout_t timeout = TIMEOUT_INF)
01153 {return Socket::isPending(Socket::pendingInput, timeout);};
01154 };
01155
01166 class __EXPORT UDPDuplex : public UDPTransmit, public UDPReceive
01167 {
01168 public:
01176 UDPDuplex(const IPV4Address &bind, tpport_t port);
01177 #ifdef CCXX_IPV6
01178 UDPDuplex(const IPV6Address &bind, tpport_t port);
01179 #endif
01180
01190 Error connect(const IPV4Host &host, tpport_t port);
01191 #ifdef CCXX_IPV6
01192 Error connect(const IPV6Host &host, tpport_t port);
01193 #endif
01194
01201 Error disconnect(void);
01202 };
01203
01204
01229 class __EXPORT TCPSocket : protected Socket
01230 {
01231 protected:
01232 int segsize;
01233 void setSegmentSize(unsigned mss);
01234
01235 public:
01247 virtual bool onAccept(const IPV4Host &ia, tpport_t port);
01248
01252 inline SOCKET getSocket(void)
01253 {return so;};
01254
01258 inline int getSegmentSize(void)
01259 {return segsize;};
01260
01273 TCPSocket(const IPV4Address &bind, tpport_t port, unsigned backlog = 5, unsigned mss = 536);
01274
01285 TCPSocket(const char *name, unsigned backlog = 5, unsigned mss = 536);
01286
01295 inline IPV4Host getRequest(tpport_t *port = NULL) const
01296 {return Socket::getIPV4Sender(port);}
01297
01301 void reject(void);
01302
01306 inline IPV4Host getLocal(tpport_t *port = NULL) const
01307 {return Socket::getIPV4Local(port);}
01308
01314 inline bool isPendingConnection(timeout_t timeout = TIMEOUT_INF)
01315 {return Socket::isPending(Socket::pendingInput, timeout);}
01316
01320 virtual ~TCPSocket();
01321 };
01322
01323 #ifdef CCXX_IPV6
01324
01348 class __EXPORT TCPV6Socket : protected Socket
01349 {
01350 private:
01351 int segsize;
01352 void setSegmentSize(unsigned mss);
01353
01354 public:
01366 virtual bool onAccept(const IPV6Host &ia, tpport_t port);
01367
01371 inline SOCKET getSocket(void)
01372 {return so;};
01373
01374 inline int getSegmentSize(void)
01375 {return segsize;};
01376
01389 TCPV6Socket(const IPV6Address &bind, tpport_t port, unsigned backlog = 5, unsigned mss = 536);
01390
01401 TCPV6Socket(const char *name, unsigned backlog = 5, unsigned mss = 536);
01402
01411 inline IPV6Host getRequest(tpport_t *port = NULL) const
01412 {return Socket::getIPV6Sender(port);}
01413
01417 void reject(void);
01418
01422 inline IPV6Host getLocal(tpport_t *port = NULL) const
01423 {return Socket::getIPV6Local(port);}
01424
01430 inline bool isPendingConnection(timeout_t timeout = TIMEOUT_INF)
01431 {return Socket::isPending(Socket::pendingInput, timeout);}
01432
01436 virtual ~TCPV6Socket();
01437 };
01438
01439 #endif
01440
01441
01442
01443
01444
01445
01446
01447
01448 #ifdef _MSC_VER
01449 #pragma warning(disable:4275) // disable C4275 warning
01450 #endif
01451
01465 class __EXPORT TCPStream : protected std::streambuf, public Socket, public std::iostream
01466 {
01467 private:
01468 int doallocate();
01469
01470 void segmentBuffering(unsigned mss);
01471
01472 friend TCPStream& crlf(TCPStream&);
01473 friend TCPStream& lfcr(TCPStream&);
01474
01475 protected:
01476 timeout_t timeout;
01477 size_t bufsize;
01478 Family family;
01479 char *gbuf, *pbuf;
01480
01481 public:
01486 TCPStream(Family family = IPV4, bool throwflag = true, timeout_t to = 0);
01487
01491 void disconnect(void);
01492
01496 int getSegmentSize(void);
01497
01498 protected:
01505 void allocate(size_t size);
01506
01511 void endStream(void);
01512
01519 int underflow();
01520
01529 int uflow();
01530
01538 int overflow(int ch);
01539
01548 void connect(const IPV4Host &host, tpport_t port, unsigned mss = 536);
01549 #ifdef CCXX_IPV6
01550 void connect(const IPV6Host &host, tpport_t port, unsigned mss = 536);
01551 #endif
01552
01560 void connect(const char *name, unsigned mss = 536);
01561
01569 std::iostream *tcp(void)
01570 {return ((std::iostream *)this);};
01571
01572 public:
01582 TCPStream(TCPSocket &server, bool throwflag = true, timeout_t timeout = 0);
01583 #ifdef CCXX_IPV6
01584 TCPStream(TCPV6Socket &server, bool throwflag = true, timeout_t timeout = 0);
01585 #endif
01586
01592 void connect(TCPSocket &server);
01593 #ifdef CCXX_IPV6
01594 void connect(TCPV6Socket &server);
01595 #endif
01596
01607 TCPStream(const IPV4Host &host, tpport_t port, unsigned mss = 536, bool throwflag = true, timeout_t timeout = 0);
01608 #ifdef CCXX_IPV6
01609 TCPStream(const IPV6Host &host, tpport_t port, unsigned mss = 536, bool throwflag = true, timeout_t timeout = 0);
01610 #endif
01611
01621 TCPStream(const char *name, Family family = IPV4, unsigned mss = 536, bool throwflag = false, timeout_t timer = 0);
01622
01628 inline void setTimeout(timeout_t timer)
01629 {timeout = timer;};
01630
01637 TCPStream(const TCPStream &source);
01638
01643 virtual ~TCPStream();
01644
01651 int sync(void);
01652
01653 #ifdef HAVE_SNPRINTF
01654
01660 size_t printf(const char *format, ...);
01661 #endif
01662
01670 bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
01671
01679 inline ssize_t peek(void *buf, size_t len)
01680 {return _IORET64 ::recv(so, (char *)buf, _IOLEN64 len, MSG_PEEK);};
01681
01687 inline size_t getBufferSize(void) const
01688 {return bufsize;};
01689 };
01690
01701 class __EXPORT TCPSession : public Thread, public TCPStream
01702 {
01703 private:
01704 TCPSession(const TCPSession &rhs);
01705 protected:
01718 int waitConnection(timeout_t timeout = TIMEOUT_INF);
01719
01726 void initial(void);
01727
01728 public:
01739 TCPSession(const IPV4Host &host,
01740 tpport_t port, size_t size = 536, int pri = 0, size_t stack = 0);
01741 #ifdef CCXX_IPV6
01742 TCPSession(const IPV6Host &host,
01743 tpport_t port, size_t size = 536, int pri = 0, size_t stack = 0);
01744 #endif
01745
01755 TCPSession(TCPSocket &server, int pri = 0, size_t stack = 0);
01756 #ifdef CCXX_IPV6
01757 TCPSession(TCPV6Socket &server, int pri = 0, size_t stack = 0);
01758 #endif
01759
01763 virtual ~TCPSession();
01764 };
01765
01766 #if defined(WIN32)
01767
01777 class init_WSA
01778 {
01779 public:
01780 init_WSA();
01781 ~init_WSA();
01782 };
01783
01784 #endif // WIN32
01785
01786 class __EXPORT SimpleTCPStream;
01787
01799 class __EXPORT SimpleTCPStream : public Socket
01800 {
01801 private:
01802
01803 IPV4Host getSender(tpport_t *port) const;
01804
01805 protected:
01810 SimpleTCPStream();
01811
01816 void endStream(void);
01817
01826 void Connect(const IPV4Host &host, tpport_t port, size_t size);
01827
01828
01829 public:
01838 SimpleTCPStream(TCPSocket &server, size_t size = 512);
01839
01848 SimpleTCPStream(const IPV4Host &host, tpport_t port, size_t size = 512);
01849
01855 SimpleTCPStream(const SimpleTCPStream &source);
01856
01861 virtual ~SimpleTCPStream();
01862
01874 bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
01875
01876 void flush() {}
01877
01889 ssize_t read(char *bytes, size_t length, timeout_t timeout = 0);
01890
01902 ssize_t write(const char *bytes, size_t length, timeout_t timeout = 0);
01903
01917 ssize_t peek(char *bytes, size_t length, timeout_t timeout = 0);
01918
01919 };
01920
01921 #ifdef COMMON_STD_EXCEPTION
01922 class __EXPORT SockException : public IOException
01923 {
01924 private:
01925 Socket::Error _socketError;
01926
01927 public:
01928 SockException(const String &str, Socket::Error socketError, long systemError = 0) :
01929 IOException(str, systemError), _socketError(socketError) {};
01930
01931 inline Socket::Error getSocketError() const
01932 { return _socketError; }
01933 };
01934 #endif
01935
01936 #ifdef CCXX_NAMESPACES
01937 }
01938 #endif
01939
01940 #endif
01941