Crypto++
socketft.h
00001 #ifndef CRYPTOPP_SOCKETFT_H
00002 #define CRYPTOPP_SOCKETFT_H
00003 
00004 #include "config.h"
00005 
00006 #ifdef SOCKETS_AVAILABLE
00007 
00008 #include "network.h"
00009 #include "queue.h"
00010 
00011 #ifdef USE_WINDOWS_STYLE_SOCKETS
00012 #   if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
00013 #       error Winsock 1 is not supported by this library. Please include this file or winsock2.h before windows.h.
00014 #   endif
00015 #include <winsock2.h>
00016 #include "winpipes.h"
00017 #else
00018 #include <sys/time.h>
00019 #include <sys/types.h>
00020 #include <sys/socket.h>
00021 #include <unistd.h>
00022 #endif
00023 
00024 NAMESPACE_BEGIN(CryptoPP)
00025 
00026 #ifdef USE_WINDOWS_STYLE_SOCKETS
00027 typedef ::SOCKET socket_t;
00028 #else
00029 typedef int socket_t;
00030 const socket_t INVALID_SOCKET = -1;
00031 // cygwin 1.1.4 doesn't have SHUT_RD
00032 const int SD_RECEIVE = 0;
00033 const int SD_SEND = 1;
00034 const int SD_BOTH = 2;
00035 const int SOCKET_ERROR = -1;
00036 #endif
00037 
00038 #ifndef socklen_t
00039 typedef TYPE_OF_SOCKLEN_T socklen_t;    // see config.h
00040 #endif
00041 
00042 //! wrapper for Windows or Berkeley Sockets
00043 class Socket
00044 {
00045 public:
00046     //! exception thrown by Socket class
00047     class Err : public OS_Error
00048     {
00049     public:
00050         Err(socket_t s, const std::string& operation, int error);
00051         socket_t GetSocket() const {return m_s;}
00052 
00053     private:
00054         socket_t m_s;
00055     };
00056 
00057     Socket(socket_t s = INVALID_SOCKET, bool own=false) : m_s(s), m_own(own) {}
00058     Socket(const Socket &s) : m_s(s.m_s), m_own(false) {}
00059     virtual ~Socket();
00060 
00061     bool GetOwnership() const {return m_own;}
00062     void SetOwnership(bool own) {m_own = own;}
00063 
00064     operator socket_t() {return m_s;}
00065     socket_t GetSocket() const {return m_s;}
00066     void AttachSocket(socket_t s, bool own=false);
00067     socket_t DetachSocket();
00068     void CloseSocket();
00069 
00070     void Create(int nType = SOCK_STREAM);
00071     void Bind(unsigned int port, const char *addr=NULL);
00072     void Bind(const sockaddr* psa, socklen_t saLen);
00073     void Listen(int backlog=5);
00074     // the next three functions return false if the socket is in nonblocking mode
00075     // and the operation cannot be completed immediately
00076     bool Connect(const char *addr, unsigned int port);
00077     bool Connect(const sockaddr* psa, socklen_t saLen);
00078     bool Accept(Socket& s, sockaddr *psa=NULL, socklen_t *psaLen=NULL);
00079     void GetSockName(sockaddr *psa, socklen_t *psaLen);
00080     void GetPeerName(sockaddr *psa, socklen_t *psaLen);
00081     unsigned int Send(const byte* buf, size_t bufLen, int flags=0);
00082     unsigned int Receive(byte* buf, size_t bufLen, int flags=0);
00083     void ShutDown(int how = SD_SEND);
00084 
00085     void IOCtl(long cmd, unsigned long *argp);
00086     bool SendReady(const timeval *timeout);
00087     bool ReceiveReady(const timeval *timeout);
00088 
00089     virtual void HandleError(const char *operation) const;
00090     void CheckAndHandleError_int(const char *operation, int result) const
00091         {if (result == SOCKET_ERROR) HandleError(operation);}
00092     void CheckAndHandleError(const char *operation, socket_t result) const
00093         {if (result == SOCKET_ERROR) HandleError(operation);}
00094 #ifdef USE_WINDOWS_STYLE_SOCKETS
00095     void CheckAndHandleError(const char *operation, BOOL result) const
00096         {assert(result==TRUE || result==FALSE); if (!result) HandleError(operation);}
00097     void CheckAndHandleError(const char *operation, bool result) const
00098         {if (!result) HandleError(operation);}
00099 #endif
00100 
00101     //! look up the port number given its name, returns 0 if not found
00102     static unsigned int PortNameToNumber(const char *name, const char *protocol="tcp");
00103     //! start Windows Sockets 2
00104     static void StartSockets();
00105     //! calls WSACleanup for Windows Sockets
00106     static void ShutdownSockets();
00107     //! returns errno or WSAGetLastError
00108     static int GetLastError();
00109     //! sets errno or calls WSASetLastError
00110     static void SetLastError(int errorCode);
00111 
00112 protected:
00113     virtual void SocketChanged() {}
00114 
00115     socket_t m_s;
00116     bool m_own;
00117 };
00118 
00119 class SocketsInitializer
00120 {
00121 public:
00122     SocketsInitializer() {Socket::StartSockets();}
00123     ~SocketsInitializer() {try {Socket::ShutdownSockets();} catch (...) {}}
00124 };
00125 
00126 class SocketReceiver : public NetworkReceiver
00127 {
00128 public:
00129     SocketReceiver(Socket &s);
00130 
00131 #ifdef USE_BERKELEY_STYLE_SOCKETS
00132     bool MustWaitToReceive() {return true;}
00133 #else
00134     ~SocketReceiver();
00135     bool MustWaitForResult() {return true;}
00136 #endif
00137     bool Receive(byte* buf, size_t bufLen);
00138     unsigned int GetReceiveResult();
00139     bool EofReceived() const {return m_eofReceived;}
00140 
00141     unsigned int GetMaxWaitObjectCount() const {return 1;}
00142     void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
00143 
00144 private:
00145     Socket &m_s;
00146     bool m_eofReceived;
00147 
00148 #ifdef USE_WINDOWS_STYLE_SOCKETS
00149     WindowsHandle m_event;
00150     OVERLAPPED m_overlapped;
00151     bool m_resultPending;
00152     DWORD m_lastResult;
00153 #else
00154     unsigned int m_lastResult;
00155 #endif
00156 };
00157 
00158 class SocketSender : public NetworkSender
00159 {
00160 public:
00161     SocketSender(Socket &s);
00162 
00163 #ifdef USE_BERKELEY_STYLE_SOCKETS
00164     bool MustWaitToSend() {return true;}
00165 #else
00166     ~SocketSender();
00167     bool MustWaitForResult() {return true;}
00168     bool MustWaitForEof() { return true; }
00169     bool EofSent();
00170 #endif
00171     void Send(const byte* buf, size_t bufLen);
00172     unsigned int GetSendResult();
00173     void SendEof();
00174 
00175     unsigned int GetMaxWaitObjectCount() const {return 1;}
00176     void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
00177 
00178 private:
00179     Socket &m_s;
00180 #ifdef USE_WINDOWS_STYLE_SOCKETS
00181     WindowsHandle m_event;
00182     OVERLAPPED m_overlapped;
00183     bool m_resultPending;
00184     DWORD m_lastResult;
00185 #else
00186     unsigned int m_lastResult;
00187 #endif
00188 };
00189 
00190 //! socket-based implementation of NetworkSource
00191 class SocketSource : public NetworkSource, public Socket
00192 {
00193 public:
00194     SocketSource(socket_t s = INVALID_SOCKET, bool pumpAll = false, BufferedTransformation *attachment = NULL)
00195         : NetworkSource(attachment), Socket(s), m_receiver(*this)
00196     {
00197         if (pumpAll)
00198             PumpAll();
00199     }
00200 
00201 private:
00202     NetworkReceiver & AccessReceiver() {return m_receiver;}
00203     SocketReceiver m_receiver;
00204 };
00205 
00206 //! socket-based implementation of NetworkSink
00207 class SocketSink : public NetworkSink, public Socket
00208 {
00209 public:
00210     SocketSink(socket_t s=INVALID_SOCKET, unsigned int maxBufferSize=0, unsigned int autoFlushBound=16*1024)
00211         : NetworkSink(maxBufferSize, autoFlushBound), Socket(s), m_sender(*this) {}
00212 
00213     void SendEof() {ShutDown(SD_SEND);}
00214 
00215 private:
00216     NetworkSender & AccessSender() {return m_sender;}
00217     SocketSender m_sender;
00218 };
00219 
00220 NAMESPACE_END
00221 
00222 #endif  // #ifdef SOCKETS_AVAILABLE
00223 
00224 #endif