ucommon
commoncpp/socket.h
Go to the documentation of this file.
00001 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
00002 // Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
00003 //
00004 // This program is free software; you can redistribute it and/or modify
00005 // it under the terms of the GNU General Public License as published by
00006 // the Free Software Foundation; either version 2 of the License, or
00007 // (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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_COMMONCPP
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 IPV4Multicast &ia);
00334 #ifdef  CCXX_IPV6
00335     Error join(const IPV6Multicast &ia);
00336 #endif
00337 
00344     Error drop(const IPV4Multicast &ia);
00345 #ifdef  CCXX_IPV6
00346     Error drop(const IPV6Multicast &ia);
00347 #endif
00348 
00356     Error setRouting(bool enable);
00357 
00364     Error setNoDelay(bool enable);
00365 
00377     Socket(int domain, int type, int protocol = 0);
00378 
00386     Socket(socket_t fd);
00387 
00391     Socket();
00392 
00400     Socket(const Socket &source);
00401 
00411     ssize_t readLine(char *buf, size_t len, timeout_t timeout = 0);
00412 
00424     virtual ssize_t readData(void * buf,size_t len,char separator=0,timeout_t t=0);
00425 
00434     virtual ssize_t writeData(const void* buf,size_t len,timeout_t t=0);
00435 
00436 public:
00437     ~Socket();
00438 
00445     inline Error getErrorNumber(void) const {return errid;}
00446 
00453     inline const char *getErrorString(void) const {return errstr;}
00454 
00455     inline long getSystemError(void) const {return syserr;}
00456 
00457     const char *getSystemErrorString(void) const;
00458 
00468     virtual bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
00469 
00476     static bool check(Family fam);
00477 
00482     bool operator!() const;
00483 
00484     operator bool() const;
00485 
00489     Socket &operator=(const Socket &from);
00490 
00500     virtual IPV4Host getIPV4Sender(tpport_t *port = NULL) const;
00501 
00502     inline IPV4Host getSender(tpport_t *port = NULL) const
00503         {return getIPV4Sender(port);}
00504 
00505 #ifdef  CCXX_IPV6
00506     virtual IPV6Host getIPV6Sender(tpport_t *port = NULL) const;
00507 #endif
00508 
00518     IPV4Host getIPV4Peer(tpport_t *port = NULL) const;
00519 
00520     inline IPV4Host getPeer(tpport_t *port = NULL) const
00521         {return getIPV4Peer(port);}
00522 
00523 #ifdef  CCXX_IPV6
00524     IPV6Host getIPV6Peer(tpport_t *port = NULL) const;
00525 #endif
00526 
00534     IPV4Host getIPV4Local(tpport_t *port = NULL) const;
00535 
00536     inline IPV4Host getLocal(tpport_t *port = NULL) const
00537         {return getIPV4Local(port);}
00538 
00539 #ifdef  CCXX_IPV6
00540     IPV6Host getIPV6Local(tpport_t *port = NULL) const;
00541 #endif
00542 
00553     void setCompletion(bool immediate);
00554 
00560     Error setLinger(bool linger);
00561 
00569     Error setKeepAlive(bool enable);
00570 
00579     Error setTypeOfService(Tos service);
00580 
00589     bool isConnected(void) const;
00590 
00598     bool isActive(void) const;
00599 
00606     inline bool isBroadcast(void) const
00607         {return flags.broadcast;};
00608 
00614     inline bool isRouted(void) const
00615         {return flags.route;};
00616 
00617 
00618     inline struct in_addr getaddress(const IPV4Address &ia)
00619         {return ia.getAddress();}
00620 
00621 #ifdef  CCXX_IPV6
00622     inline struct in6_addr getaddress(const IPV6Address &ia)
00623         {return ia.getAddress();}
00624 #endif
00625 
00626 };
00627 
00628 #if defined(CCXX_EXCEPTIONS)
00629 
00630 class __EXPORT SockException : public IOException
00631 {
00632 private:
00633     Socket::Error _socketError;
00634 
00635 public:
00636     inline SockException(const String &str, Socket::Error socketError, long systemError = 0) :
00637         IOException(str, systemError), _socketError(socketError) {};
00638 
00639     inline Socket::Error getSocketError() const
00640     { return _socketError; }
00641 };
00642 
00643 #endif
00644 
00645 END_NAMESPACE
00646 
00647 #endif