ucommon
commoncpp/socket.h
Go to the documentation of this file.
00001 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
00002 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
00003 // Copyright (C) 2014 Savoir-Faire Linux Inc.
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free software
00019 // library without restriction.  Specifically, if other files instantiate
00020 // templates or use macros or inline functions from this file, or you compile
00021 // this file and link it with other files to produce an executable, this
00022 // file does not by itself cause the resulting executable to be covered by
00023 // the GNU General Public License.  This exception does not however
00024 // invalidate any other reasons why the executable file might be covered by
00025 // the GNU General Public License.
00026 //
00027 // This exception applies only to the code released under the name GNU
00028 // Common C++.  If you copy code from other releases into a copy of GNU
00029 // Common C++, as the General Public License permits, the exception does
00030 // not apply to the code that you add in this way.  To avoid misleading
00031 // anyone as to the status of such modified files, you must delete
00032 // this exception notice from them.
00033 //
00034 // If you write modifications of your own for GNU Common C++, it is your choice
00035 // whether to permit this exception to apply to your modifications.
00036 // If you do not wish that, delete this exception notice.
00037 //
00038 
00044 #ifndef COMMONCPP_SOCKET_H_
00045 #define COMMONCPP_SOCKET_H_
00046 
00047 #include <cstdio>
00048 
00049 #ifndef COMMONCPP_CONFIG_H_
00050 #include <commoncpp/config.h>
00051 #endif
00052 
00053 #ifndef COMMONCPP_STRING_H_
00054 #include <commoncpp/string.h>
00055 #endif
00056 
00057 #ifndef COMMONCPP_ADDRESS_H_
00058 #include <commoncpp/address.h>
00059 #endif
00060 
00061 #ifndef COMMONCPP_EXCEPTION_H_
00062 #include <commoncpp/exception.h>
00063 #endif
00064 
00065 #ifndef MSG_DONTWAIT
00066 #define MSG_DONTWAIT    0
00067 #endif
00068 
00069 #ifndef MSG_NOSIGNAL
00070 #define MSG_NOSIGNAL    0
00071 #endif
00072 
00073 #ifndef SOCK_DCCP
00074 #define SOCK_DCCP       6
00075 #endif
00076 #ifndef IPPROTO_DCCP
00077 #define IPPROTO_DCCP    33
00078 #endif
00079 #ifndef SOL_DCCP
00080 #define SOL_DCCP       269
00081 #endif
00082 #define DCCP_SOCKOPT_AVAILABLE_CCIDS    12
00083 #define DCCP_SOCKOPT_CCID               13
00084 #define DCCP_SOCKOPT_TX_CCID            14
00085 #define DCCP_SOCKOPT_RX_CCID            15
00086 
00087 namespace ost {
00088 
00089 typedef socket_t    SOCKET;
00090 
00091 class __EXPORT Socket : protected ucommon::Socket
00092 {
00093 public:
00094     enum State {
00095         INITIAL,
00096         AVAILABLE,
00097         BOUND,
00098         CONNECTED,
00099         CONNECTING,
00100         STREAM
00101     };
00102     typedef enum State State;
00103 
00104     enum Family {
00105 #ifdef  CCXX_IPV6
00106         IPV6 = AF_INET6,
00107 #endif
00108         IPV4 = AF_INET
00109     };
00110 
00111     typedef enum Family Family;
00112 
00113     enum Error {
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         tosLowDelay = 0,
00149         tosThroughput,
00150         tosReliability,
00151         tosMinCost,
00152         tosInvalid
00153     };
00154     typedef enum Tos Tos;
00155 
00156     enum Pending {
00157         pendingInput,
00158         pendingOutput,
00159         pendingError
00160     };
00161     typedef enum Pending Pending;
00162 
00163 private:
00164     // used by exception handlers....
00165     mutable Error errid;
00166     mutable const char *errstr;
00167     mutable long syserr;
00168 
00169     void setSocket(void);
00170 
00171 protected:
00172     static socket_t dupSocket(socket_t s,Socket::State state);
00173 
00174     static Mutex mutex;
00175 
00176     mutable struct {
00177         bool thrown: 1;
00178         bool broadcast: 1;
00179         bool route: 1;
00180         bool keepalive: 1;
00181         bool loopback: 1;
00182         bool multicast: 1;
00183         bool completion: 1;
00184         bool linger: 1;
00185         unsigned ttl: 8;
00186     } flags;
00187 
00188     State volatile state;
00189 
00198     Error error(Error error, const char *err = NULL, long systemError = 0) const;
00199 
00206     inline void error(const char *err) const
00207         {error(errExtended, err);}
00208 
00215     inline void setError(bool enable)
00216         {flags.thrown = !enable;}
00217 
00223     void endSocket(void);
00224 
00230     Error connectError(void);
00231 
00235     Error sendLimit(int limit = 2048);
00236 
00240     Error receiveLimit(int limit = 1);
00241 
00248     Error sendTimeout(timeout_t timer);
00249 
00256     Error receiveTimeout(timeout_t timer);
00257 
00265     Error sendBuffer(unsigned size);
00266 
00274     Error receiveBuffer(unsigned size);
00275 
00283     Error bufferSize(unsigned size);
00284 
00293     Error setBroadcast(bool enable);
00294 
00306     Error setMulticastByFamily(bool enable, Family family = IPV4);
00307 
00316     Error setLoopbackByFamily(bool enable, Family family = IPV4);
00317 
00325     Error setTimeToLiveByFamily(unsigned char ttl, Family fam = IPV4);
00326 
00333     Error join(const ucommon::Socket::address &ia, int iface = 0);
00334     inline Error join(const IPV4Multicast &ia) { return join(ucommon::Socket::address(getaddress(ia))); }
00335 #ifdef  CCXX_IPV6
00336     inline Error join(const IPV6Multicast &ia, int iface = 0) { return join(ucommon::Socket::address(getaddress(ia)), iface); }
00337 #endif
00338 
00345     Error drop(const ucommon::Socket::address &ia, int iface = 0);
00346     Error drop(const IPV4Multicast &ia) { return drop(ucommon::Socket::address(getaddress(ia))); }
00347 #ifdef  CCXX_IPV6
00348     Error drop(const IPV6Multicast &ia, int iface = 0) { return drop(ucommon::Socket::address(getaddress(ia)), iface); }
00349 #endif
00350 
00358     Error setRouting(bool enable);
00359 
00366     Error setNoDelay(bool enable);
00367 
00379     Socket(int domain, int type, int protocol = 0);
00380 
00388     Socket(socket_t fd);
00389 
00393     Socket();
00394 
00402     Socket(const Socket &source);
00403 
00413     ssize_t readLine(char *buf, size_t len, timeout_t timeout = 0);
00414 
00426     virtual ssize_t readData(void * buf,size_t len,char separator=0,timeout_t t=0);
00427 
00436     virtual ssize_t writeData(const void* buf,size_t len,timeout_t t=0);
00437 
00438 public:
00439     ~Socket();
00440 
00447     inline Error getErrorNumber(void) const {return errid;}
00448 
00455     inline const char *getErrorString(void) const {return errstr;}
00456 
00457     inline long getSystemError(void) const {return syserr;}
00458 
00459     const char *getSystemErrorString(void) const;
00460 
00470     virtual bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
00471 
00478     static bool check(Family fam);
00479 
00484     bool operator!() const;
00485 
00486     operator bool() const;
00487 
00491     Socket &operator=(const Socket &from);
00492 
00502     ucommon::Socket::address getSender() const;
00503 
00504     virtual IPV4Host getIPV4Sender(tpport_t *port = NULL) const;
00505 
00506     inline IPV4Host getSender(tpport_t *port) const
00507         {return getIPV4Sender(port);}
00508 
00509 #ifdef  CCXX_IPV6
00510     virtual IPV6Host getIPV6Sender(tpport_t *port = NULL) const;
00511 #endif
00512 
00522     ucommon::Socket::address getPeer() const;
00523 
00524     IPV4Host getIPV4Peer(tpport_t *port = NULL) const;
00525 
00526     inline IPV4Host getPeer(tpport_t *port) const
00527         {return getIPV4Peer(port);}
00528 
00529 #ifdef  CCXX_IPV6
00530     IPV6Host getIPV6Peer(tpport_t *port = NULL) const;
00531 #endif
00532 
00540     IPV4Host getIPV4Local(tpport_t *port = NULL) const;
00541 
00542     inline IPV4Host getLocal(tpport_t *port) const
00543         {return getIPV4Local(port);}
00544 
00545 #ifdef  CCXX_IPV6
00546     IPV6Host getIPV6Local(tpport_t *port = NULL) const;
00547 #endif
00548 
00549     ucommon::Socket::address getLocal() const;
00550 
00561     void setCompletion(bool immediate);
00562 
00568     Error setLinger(bool linger);
00569 
00577     Error setKeepAlive(bool enable);
00578 
00587     Error setTypeOfService(Tos service);
00588 
00597     bool isConnected(void) const;
00598 
00606     bool isActive(void) const;
00607 
00614     inline bool isBroadcast(void) const
00615         {return flags.broadcast;}
00616 
00622     inline bool isRouted(void) const
00623         {return flags.route;}
00624 
00625 
00626     inline struct in_addr getaddress(const IPV4Address &ia)
00627         {return ia.getAddress();}
00628 
00629 #ifdef  CCXX_IPV6
00630     inline struct in6_addr getaddress(const IPV6Address &ia)
00631         {return ia.getAddress();}
00632 #endif
00633 
00634 };
00635 
00636 #if defined(CCXX_EXCEPTIONS)
00637 
00638 class __EXPORT SockException : public IOException
00639 {
00640 private:
00641     Socket::Error _socketError;
00642 
00643 public:
00644     inline SockException(const String &str, Socket::Error socketError, long systemError = 0) :
00645         IOException(str, systemError), _socketError(socketError) {}
00646 
00647     inline Socket::Error getSocketError() const
00648         {return _socketError;}
00649 };
00650 
00651 #endif
00652 
00653 } // namespace ost
00654 
00655 #endif