UCommon
|
00001 // Copyright (C) 1999-2005 Open Source Telecom Corporation. 00002 // Copyright (C) 2006-2013 David Sugar, Tycho Softworks. 00003 // Copyright (C) 2014 David Sugar, Tycho Softworks, Savoir-Faire Linux Inc. 00004 // Copyright (C) 2015 Cherokees of Idaho, Savoir-Faire Linux Inc. 00005 // 00006 // This program is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License as published by 00008 // the Free Software Foundation; either version 2 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // This program is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public License 00017 // along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 // 00019 // As a special exception, you may use this file as part of a free software 00020 // library without restriction. Specifically, if other files instantiate 00021 // templates or use macros or inline functions from this file, or you compile 00022 // this file and link it with other files to produce an executable, this 00023 // file does not by itself cause the resulting executable to be covered by 00024 // the GNU General Public License. This exception does not however 00025 // invalidate any other reasons why the executable file might be covered by 00026 // the GNU General Public License. 00027 // 00028 // This exception applies only to the code released under the name GNU 00029 // Common C++. If you copy code from other releases into a copy of GNU 00030 // Common C++, as the General Public License permits, the exception does 00031 // not apply to the code that you add in this way. To avoid misleading 00032 // anyone as to the status of such modified files, you must delete 00033 // this exception notice from them. 00034 // 00035 // If you write modifications of your own for GNU Common C++, it is your choice 00036 // whether to permit this exception to apply to your modifications. 00037 // If you do not wish that, delete this exception notice. 00038 // 00039 00045 #ifndef COMMONCPP_SOCKET_H_ 00046 #define COMMONCPP_SOCKET_H_ 00047 00048 #include <cstdio> 00049 00050 #ifndef COMMONCPP_CONFIG_H_ 00051 #include <commoncpp/config.h> 00052 #endif 00053 00054 #ifndef COMMONCPP_STRING_H_ 00055 #include <commoncpp/string.h> 00056 #endif 00057 00058 #ifndef COMMONCPP_ADDRESS_H_ 00059 #include <commoncpp/address.h> 00060 #endif 00061 00062 #ifndef COMMONCPP_EXCEPTION_H_ 00063 #include <commoncpp/exception.h> 00064 #endif 00065 00066 #ifndef MSG_DONTWAIT 00067 #define MSG_DONTWAIT 0 00068 #endif 00069 00070 #ifndef MSG_NOSIGNAL 00071 #define MSG_NOSIGNAL 0 00072 #endif 00073 00074 #ifndef SOCK_DCCP 00075 #define SOCK_DCCP 6 00076 #endif 00077 #ifndef IPPROTO_DCCP 00078 #define IPPROTO_DCCP 33 00079 #endif 00080 #ifndef SOL_DCCP 00081 #define SOL_DCCP 269 00082 #endif 00083 #define DCCP_SOCKOPT_AVAILABLE_CCIDS 12 00084 #define DCCP_SOCKOPT_CCID 13 00085 #define DCCP_SOCKOPT_TX_CCID 14 00086 #define DCCP_SOCKOPT_RX_CCID 15 00087 00088 namespace ost { 00089 00090 typedef socket_t SOCKET; 00091 00092 class __EXPORT Socket : protected ucommon::Socket 00093 { 00094 public: 00095 enum State { 00096 INITIAL, 00097 AVAILABLE, 00098 BOUND, 00099 CONNECTED, 00100 CONNECTING, 00101 STREAM 00102 }; 00103 typedef enum State State; 00104 00105 enum Family { 00106 #ifdef CCXX_IPV6 00107 IPV6 = AF_INET6, 00108 #endif 00109 IPV4 = AF_INET 00110 }; 00111 00112 typedef enum Family Family; 00113 00114 enum Error { 00115 errSuccess = 0, 00116 errCreateFailed, 00117 errCopyFailed, 00118 errInput, 00119 errInputInterrupt, 00120 errResourceFailure, 00121 errOutput, 00122 errOutputInterrupt, 00123 errNotConnected, 00124 errConnectRefused, 00125 errConnectRejected, 00126 errConnectTimeout, 00127 errConnectFailed, 00128 errConnectInvalid, 00129 errConnectBusy, 00130 errConnectNoRoute, 00131 errBindingFailed, 00132 errBroadcastDenied, 00133 errRoutingDenied, 00134 errKeepaliveDenied, 00135 errServiceDenied, 00136 errServiceUnavailable, 00137 errMulticastDisabled, 00138 errTimeout, 00139 errNoDelay, 00140 errExtended, 00141 errLookupFail, 00142 errSearchErr, 00143 errInvalidValue 00144 }; 00145 00146 typedef enum Error Error; 00147 00148 enum Tos { 00149 tosLowDelay = 0, 00150 tosThroughput, 00151 tosReliability, 00152 tosMinCost, 00153 tosInvalid 00154 }; 00155 typedef enum Tos Tos; 00156 00157 enum Pending { 00158 pendingInput, 00159 pendingOutput, 00160 pendingError 00161 }; 00162 typedef enum Pending Pending; 00163 00164 private: 00165 // used by exception handlers.... 00166 mutable Error errid; 00167 mutable const char *errstr; 00168 mutable long syserr; 00169 00170 void setSocket(void); 00171 00172 protected: 00173 static socket_t dupSocket(socket_t s,Socket::State state); 00174 00175 mutable struct { 00176 bool thrown: 1; 00177 bool broadcast: 1; 00178 bool route: 1; 00179 bool keepalive: 1; 00180 bool loopback: 1; 00181 bool multicast: 1; 00182 bool completion: 1; 00183 bool linger: 1; 00184 unsigned ttl: 8; 00185 } flags; 00186 00187 State volatile state; 00188 00197 Error error(Error error, const char *err = NULL, long systemError = 0) const; 00198 00205 inline void error(const char *err) const 00206 {error(errExtended, err);} 00207 00214 inline void setError(bool enable) 00215 {flags.thrown = !enable;} 00216 00222 void endSocket(void); 00223 00229 Error connectError(void); 00230 00234 Error sendLimit(int limit = 2048); 00235 00239 Error receiveLimit(int limit = 1); 00240 00247 Error sendTimeout(timeout_t timer); 00248 00255 Error receiveTimeout(timeout_t timer); 00256 00264 Error sendBuffer(unsigned size); 00265 00273 Error receiveBuffer(unsigned size); 00274 00282 Error bufferSize(unsigned size); 00283 00292 Error setBroadcast(bool enable); 00293 00305 Error setMulticastByFamily(bool enable, Family family = IPV4); 00306 00315 Error setLoopbackByFamily(bool enable, Family family = IPV4); 00316 00324 Error setTimeToLiveByFamily(unsigned char ttl, Family fam = IPV4); 00325 00332 Error join(const ucommon::Socket::address &ia, int iface = 0); 00333 inline Error join(const IPV4Multicast &ia) { return join(ucommon::Socket::address(getaddress(ia))); } 00334 #ifdef CCXX_IPV6 00335 inline Error join(const IPV6Multicast &ia, int iface = 0) { return join(ucommon::Socket::address(getaddress(ia)), iface); } 00336 #endif 00337 00344 Error drop(const ucommon::Socket::address &ia, int iface = 0); 00345 Error drop(const IPV4Multicast &ia) { return drop(ucommon::Socket::address(getaddress(ia))); } 00346 #ifdef CCXX_IPV6 00347 Error drop(const IPV6Multicast &ia, int iface = 0) { return drop(ucommon::Socket::address(getaddress(ia)), iface); } 00348 #endif 00349 00357 Error setRouting(bool enable); 00358 00365 Error setNoDelay(bool enable); 00366 00378 Socket(int domain, int type, int protocol = 0); 00379 00387 Socket(socket_t fd); 00388 00392 Socket(); 00393 00401 Socket(const Socket &source); 00402 00412 ssize_t readLine(char *buf, size_t len, timeout_t timeout = 0); 00413 00425 virtual ssize_t readData(void * buf,size_t len,char separator=0,timeout_t t=0); 00426 00435 virtual ssize_t writeData(const void* buf,size_t len,timeout_t t=0); 00436 00437 public: 00438 ~Socket(); 00439 00446 inline Error getErrorNumber(void) const {return errid;} 00447 00454 inline const char *getErrorString(void) const {return errstr;} 00455 00456 inline long getSystemError(void) const {return syserr;} 00457 00458 const char *getSystemErrorString(void) const; 00459 00469 virtual bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF); 00470 00477 static bool check(Family fam); 00478 00483 bool operator!() const; 00484 00485 operator bool() const; 00486 00490 Socket &operator=(const Socket &from); 00491 00501 ucommon::Socket::address getSender() const; 00502 00503 virtual IPV4Host getIPV4Sender(tpport_t *port = NULL) const; 00504 00505 inline IPV4Host getSender(tpport_t *port) const 00506 {return getIPV4Sender(port);} 00507 00508 #ifdef CCXX_IPV6 00509 virtual IPV6Host getIPV6Sender(tpport_t *port = NULL) const; 00510 #endif 00511 00521 ucommon::Socket::address getPeer() const; 00522 00523 IPV4Host getIPV4Peer(tpport_t *port = NULL) const; 00524 00525 inline IPV4Host getPeer(tpport_t *port) const 00526 {return getIPV4Peer(port);} 00527 00528 #ifdef CCXX_IPV6 00529 IPV6Host getIPV6Peer(tpport_t *port = NULL) const; 00530 #endif 00531 00539 IPV4Host getIPV4Local(tpport_t *port = NULL) const; 00540 00541 inline IPV4Host getLocal(tpport_t *port) const 00542 {return getIPV4Local(port);} 00543 00544 #ifdef CCXX_IPV6 00545 IPV6Host getIPV6Local(tpport_t *port = NULL) const; 00546 #endif 00547 00548 ucommon::Socket::address getLocal() const; 00549 00560 void setCompletion(bool immediate); 00561 00567 Error setLinger(bool linger); 00568 00576 Error setKeepAlive(bool enable); 00577 00586 Error setTypeOfService(Tos service); 00587 00596 bool isConnected(void) const; 00597 00605 bool isActive(void) const; 00606 00613 inline bool isBroadcast(void) const 00614 {return flags.broadcast;} 00615 00621 inline bool isRouted(void) const 00622 {return flags.route;} 00623 00624 00625 inline struct in_addr getaddress(const IPV4Address &ia) 00626 {return ia.getAddress();} 00627 00628 #ifdef CCXX_IPV6 00629 inline struct in6_addr getaddress(const IPV6Address &ia) 00630 {return ia.getAddress();} 00631 #endif 00632 00633 }; 00634 00635 #if defined(CCXX_EXCEPTIONS) 00636 00637 class __EXPORT SockException : public IOException 00638 { 00639 private: 00640 Socket::Error _socketError; 00641 00642 public: 00643 inline SockException(const String &str, Socket::Error socketError, long systemError = 0) : 00644 IOException(str, systemError), _socketError(socketError) {} 00645 00646 inline Socket::Error getSocketError() const 00647 {return _socketError;} 00648 }; 00649 00650 #endif 00651 00652 } // namespace ost 00653 00654 #endif