1#ifndef CRYPTOPP_SOCKETFT_H 2#define CRYPTOPP_SOCKETFT_H 3 4#include "config.h" 5 6#ifdef SOCKETS_AVAILABLE 7 8#include "network.h" 9#include "queue.h" 10 11#ifdef USE_WINDOWS_STYLE_SOCKETS 12# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) 13# error Winsock 1 is not supported by this library. Please include this file or winsock2.h before windows.h. 14# endif 15#include <winsock2.h> 16#include "winpipes.h" 17#else 18#include <sys/time.h> 19#include <sys/types.h> 20#include <sys/socket.h> 21#include <unistd.h> 22#endif 23 24NAMESPACE_BEGIN(CryptoPP) 25 26#ifdef USE_WINDOWS_STYLE_SOCKETS 27typedef ::SOCKET socket_t; 28#else 29typedef int socket_t; 30const socket_t INVALID_SOCKET = -1; 31// cygwin 1.1.4 doesn't have SHUT_RD 32const int SD_RECEIVE = 0; 33const int SD_SEND = 1; 34const int SD_BOTH = 2; 35const int SOCKET_ERROR = -1; 36#endif 37 38#ifndef socklen_t 39typedef TYPE_OF_SOCKLEN_T socklen_t; // see config.h 40#endif 41 42//! wrapper for Windows or Berkeley Sockets 43class Socket 44{ 45public: 46 //! exception thrown by Socket class 47 class Err : public OS_Error 48 { 49 public: 50 Err(socket_t s, const std::string& operation, int error); 51 socket_t GetSocket() const {return m_s;} 52 53 private: 54 socket_t m_s; 55 }; 56 57 Socket(socket_t s = INVALID_SOCKET, bool own=false) : m_s(s), m_own(own) {} 58 Socket(const Socket &s) : m_s(s.m_s), m_own(false) {} 59 virtual ~Socket(); 60 61 bool GetOwnership() const {return m_own;} 62 void SetOwnership(bool own) {m_own = own;} 63 64 operator socket_t() {return m_s;} 65 socket_t GetSocket() const {return m_s;} 66 void AttachSocket(socket_t s, bool own=false); 67 socket_t DetachSocket(); 68 void CloseSocket(); 69 70 void Create(int nType = SOCK_STREAM); 71 void Bind(unsigned int port, const char *addr=NULL); 72 void Bind(const sockaddr* psa, socklen_t saLen); 73 void Listen(int backlog=5); 74 // the next three functions return false if the socket is in nonblocking mode 75 // and the operation cannot be completed immediately 76 bool Connect(const char *addr, unsigned int port); 77 bool Connect(const sockaddr* psa, socklen_t saLen); 78 bool Accept(Socket& s, sockaddr *psa=NULL, socklen_t *psaLen=NULL); 79 void GetSockName(sockaddr *psa, socklen_t *psaLen); 80 void GetPeerName(sockaddr *psa, socklen_t *psaLen); 81 unsigned int Send(const byte* buf, size_t bufLen, int flags=0); 82 unsigned int Receive(byte* buf, size_t bufLen, int flags=0); 83 void ShutDown(int how = SD_SEND); 84 85 void IOCtl(long cmd, unsigned long *argp); 86 bool SendReady(const timeval *timeout); 87 bool ReceiveReady(const timeval *timeout); 88 89 virtual void HandleError(const char *operation) const; 90 void CheckAndHandleError_int(const char *operation, int result) const 91 {if (result == SOCKET_ERROR) HandleError(operation);} 92 void CheckAndHandleError(const char *operation, socket_t result) const 93 {if (result == SOCKET_ERROR) HandleError(operation);} 94#ifdef USE_WINDOWS_STYLE_SOCKETS 95 void CheckAndHandleError(const char *operation, BOOL result) const 96 {assert(result==TRUE || result==FALSE); if (!result) HandleError(operation);} 97 void CheckAndHandleError(const char *operation, bool result) const 98 {if (!result) HandleError(operation);} 99#endif 100 101 //! look up the port number given its name, returns 0 if not found 102 static unsigned int PortNameToNumber(const char *name, const char *protocol="tcp"); 103 //! start Windows Sockets 2 104 static void StartSockets(); 105 //! calls WSACleanup for Windows Sockets 106 static void ShutdownSockets(); 107 //! returns errno or WSAGetLastError 108 static int GetLastError(); 109 //! sets errno or calls WSASetLastError 110 static void SetLastError(int errorCode); 111 112protected: 113 virtual void SocketChanged() {} 114 115 socket_t m_s; 116 bool m_own; 117}; 118 119class SocketsInitializer 120{ 121public: 122 SocketsInitializer() {Socket::StartSockets();} 123 ~SocketsInitializer() {try {Socket::ShutdownSockets();} catch (...) {}} 124}; 125 126class SocketReceiver : public NetworkReceiver 127{ 128public: 129 SocketReceiver(Socket &s); 130 131#ifdef USE_BERKELEY_STYLE_SOCKETS 132 bool MustWaitToReceive() {return true;} 133#else 134 ~SocketReceiver(); 135 bool MustWaitForResult() {return true;} 136#endif 137 bool Receive(byte* buf, size_t bufLen); 138 unsigned int GetReceiveResult(); 139 bool EofReceived() const {return m_eofReceived;} 140 141 unsigned int GetMaxWaitObjectCount() const {return 1;} 142 void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack); 143 144private: 145 Socket &m_s; 146 bool m_eofReceived; 147 148#ifdef USE_WINDOWS_STYLE_SOCKETS 149 WindowsHandle m_event; 150 OVERLAPPED m_overlapped; 151 bool m_resultPending; 152 DWORD m_lastResult; 153#else 154 unsigned int m_lastResult; 155#endif 156}; 157 158class SocketSender : public NetworkSender 159{ 160public: 161 SocketSender(Socket &s); 162 163#ifdef USE_BERKELEY_STYLE_SOCKETS 164 bool MustWaitToSend() {return true;} 165#else 166 ~SocketSender(); 167 bool MustWaitForResult() {return true;} 168 bool MustWaitForEof() { return true; } 169 bool EofSent(); 170#endif 171 void Send(const byte* buf, size_t bufLen); 172 unsigned int GetSendResult(); 173 void SendEof(); 174 175 unsigned int GetMaxWaitObjectCount() const {return 1;} 176 void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack); 177 178private: 179 Socket &m_s; 180#ifdef USE_WINDOWS_STYLE_SOCKETS 181 WindowsHandle m_event; 182 OVERLAPPED m_overlapped; 183 bool m_resultPending; 184 DWORD m_lastResult; 185#else 186 unsigned int m_lastResult; 187#endif 188}; 189 190//! socket-based implementation of NetworkSource 191class SocketSource : public NetworkSource, public Socket 192{ 193public: 194 SocketSource(socket_t s = INVALID_SOCKET, bool pumpAll = false, BufferedTransformation *attachment = NULL) 195 : NetworkSource(attachment), Socket(s), m_receiver(*this) 196 { 197 if (pumpAll) 198 PumpAll(); 199 } 200 201private: 202 NetworkReceiver & AccessReceiver() {return m_receiver;} 203 SocketReceiver m_receiver; 204}; 205 206//! socket-based implementation of NetworkSink 207class SocketSink : public NetworkSink, public Socket 208{ 209public: 210 SocketSink(socket_t s=INVALID_SOCKET, unsigned int maxBufferSize=0, unsigned int autoFlushBound=16*1024) 211 : NetworkSink(maxBufferSize, autoFlushBound), Socket(s), m_sender(*this) {} 212 213 void SendEof() {ShutDown(SD_SEND);} 214 215private: 216 NetworkSender & AccessSender() {return m_sender;} 217 SocketSender m_sender; 218}; 219 220NAMESPACE_END 221 222#endif // #ifdef SOCKETS_AVAILABLE 223 224#endif 225