Crypto++
|
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