6 #if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE) 9 #define _WINSOCK_DEPRECATED_NO_WARNINGS 14 #if defined(CRYPTOPP_WIN32_AVAILABLE) 15 # if ((WINVER >= 0x0602 ) || (_WIN32_WINNT >= 0x0602 )) 16 # include <synchapi.h> 17 # include <ioapiset.h> 18 # define USE_WINDOWS8_API 22 #ifdef USE_BERKELEY_STYLE_SOCKETS 26 #include <arpa/inet.h> 27 #include <netinet/in.h> 28 #include <sys/ioctl.h> 31 #if defined(CRYPTOPP_MSAN) 32 # include <sanitizer/msan_interface.h> 35 #ifdef PREFER_WINDOWS_STYLE_SOCKETS 36 # pragma comment(lib, "ws2_32.lib") 41 #ifdef USE_WINDOWS_STYLE_SOCKETS 42 const int SOCKET_EINVAL = WSAEINVAL;
43 const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
44 typedef int socklen_t;
46 const int SOCKET_EINVAL = EINVAL;
47 const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
52 # define INADDR_NONE 0xffffffff 55 Socket::Err::Err(socket_t s,
const std::string& operation,
int error)
56 :
OS_Error(IO_ERROR,
"Socket: " + operation +
" operation failed with error " +
IntToString(error), operation, error)
76 void Socket::AttachSocket(socket_t s,
bool own)
86 socket_t Socket::DetachSocket()
94 void Socket::Create(
int nType)
96 assert(m_s == INVALID_SOCKET);
97 m_s = socket(AF_INET, nType, 0);
98 CheckAndHandleError(
"socket", m_s);
103 void Socket::CloseSocket()
105 if (m_s != INVALID_SOCKET)
107 #ifdef USE_WINDOWS_STYLE_SOCKETS 108 # if defined(USE_WINDOWS8_API) 109 BOOL result = CancelIoEx((HANDLE) m_s, NULL);
110 assert(result || (!result && GetLastError() == ERROR_NOT_FOUND));
111 CheckAndHandleError_int(
"closesocket", closesocket(m_s));
112 CRYPTOPP_UNUSED(result);
114 BOOL result = CancelIo((HANDLE) m_s);
115 assert(result || (!result && GetLastError() == ERROR_NOT_FOUND));
116 CheckAndHandleError_int(
"closesocket", closesocket(m_s));
117 CRYPTOPP_UNUSED(result);
120 CheckAndHandleError_int(
"close", close(m_s));
122 m_s = INVALID_SOCKET;
127 void Socket::Bind(
unsigned int port,
const char *addr)
130 memset(&sa, 0,
sizeof(sa));
131 sa.sin_family = AF_INET;
134 sa.sin_addr.s_addr = htonl(INADDR_ANY);
137 unsigned long result = inet_addr(addr);
138 if (result == INADDR_NONE)
140 SetLastError(SOCKET_EINVAL);
141 CheckAndHandleError_int(
"inet_addr", SOCKET_ERROR);
143 sa.sin_addr.s_addr = result;
146 sa.sin_port = htons((
unsigned short)port);
148 Bind((sockaddr *)&sa,
sizeof(sa));
151 void Socket::Bind(
const sockaddr *psa, socklen_t saLen)
153 assert(m_s != INVALID_SOCKET);
155 CheckAndHandleError_int(
"bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
158 void Socket::Listen(
int backlog)
160 assert(m_s != INVALID_SOCKET);
161 CheckAndHandleError_int(
"listen", listen(m_s, backlog));
164 bool Socket::Connect(
const char *addr,
unsigned int port)
166 assert(addr != NULL);
169 memset(&sa, 0,
sizeof(sa));
170 sa.sin_family = AF_INET;
171 sa.sin_addr.s_addr = inet_addr(addr);
173 if (sa.sin_addr.s_addr == INADDR_NONE)
175 hostent *lphost = gethostbyname(addr);
178 SetLastError(SOCKET_EINVAL);
179 CheckAndHandleError_int(
"gethostbyname", SOCKET_ERROR);
183 assert(
IsAlignedOn(lphost->h_addr,GetAlignmentOf<in_addr>()));
184 sa.sin_addr.s_addr = ((in_addr *)(
void *)lphost->h_addr)->s_addr;
188 sa.sin_port = htons((
unsigned short)port);
190 return Connect((
const sockaddr *)&sa,
sizeof(sa));
193 bool Socket::Connect(
const sockaddr* psa, socklen_t saLen)
195 assert(m_s != INVALID_SOCKET);
196 int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
197 if (result == SOCKET_ERROR && GetLastError() == SOCKET_EWOULDBLOCK)
199 CheckAndHandleError_int(
"connect", result);
203 bool Socket::Accept(
Socket& target, sockaddr *psa, socklen_t *psaLen)
205 assert(m_s != INVALID_SOCKET);
206 socket_t s = accept(m_s, psa, psaLen);
207 if (s == INVALID_SOCKET && GetLastError() == SOCKET_EWOULDBLOCK)
209 CheckAndHandleError(
"accept", s);
210 target.AttachSocket(s,
true);
214 void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
216 assert(m_s != INVALID_SOCKET);
217 CheckAndHandleError_int(
"getsockname", getsockname(m_s, psa, psaLen));
220 void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
222 assert(m_s != INVALID_SOCKET);
223 CheckAndHandleError_int(
"getpeername", getpeername(m_s, psa, psaLen));
226 unsigned int Socket::Send(
const byte* buf,
size_t bufLen,
int flags)
228 assert(m_s != INVALID_SOCKET);
229 int result = send(m_s, (
const char *)buf,
UnsignedMin(INT_MAX, bufLen), flags);
230 CheckAndHandleError_int(
"send", result);
234 unsigned int Socket::Receive(byte* buf,
size_t bufLen,
int flags)
236 assert(m_s != INVALID_SOCKET);
237 int result = recv(m_s, (
char *)buf,
UnsignedMin(INT_MAX, bufLen), flags);
238 CheckAndHandleError_int(
"recv", result);
242 void Socket::ShutDown(
int how)
244 assert(m_s != INVALID_SOCKET);
245 int result = shutdown(m_s, how);
246 CheckAndHandleError_int(
"shutdown", result);
249 void Socket::IOCtl(
long cmd,
unsigned long *argp)
251 assert(m_s != INVALID_SOCKET);
252 #ifdef USE_WINDOWS_STYLE_SOCKETS 253 CheckAndHandleError_int(
"ioctlsocket", ioctlsocket(m_s, cmd, argp));
255 CheckAndHandleError_int(
"ioctl", ioctl(m_s, cmd, argp));
259 bool Socket::SendReady(
const timeval *timeout)
265 __msan_unpoison(&fds,
sizeof(fds));
270 ready = select((
int)m_s+1, NULL, &fds, NULL, NULL);
273 timeval timeoutCopy = *timeout;
274 ready = select((
int)m_s+1, NULL, &fds, NULL, &timeoutCopy);
276 CheckAndHandleError_int(
"select", ready);
280 bool Socket::ReceiveReady(
const timeval *timeout)
286 __msan_unpoison(&fds,
sizeof(fds));
291 ready = select((
int)m_s+1, &fds, NULL, NULL, NULL);
294 timeval timeoutCopy = *timeout;
295 ready = select((
int)m_s+1, &fds, NULL, NULL, &timeoutCopy);
297 CheckAndHandleError_int(
"select", ready);
303 int port = atoi(name);
307 servent *se = getservbyname(name, protocol);
309 throw Err(INVALID_SOCKET,
"getservbyname", SOCKET_EINVAL);
310 return ntohs(se->s_port);
315 #ifdef USE_WINDOWS_STYLE_SOCKETS 317 int result = WSAStartup(0x0202, &wsd);
319 throw Err(INVALID_SOCKET,
"WSAStartup", result);
325 #ifdef USE_WINDOWS_STYLE_SOCKETS 326 int result = WSACleanup();
328 throw Err(INVALID_SOCKET,
"WSACleanup", result);
334 #ifdef USE_WINDOWS_STYLE_SOCKETS 335 return WSAGetLastError();
343 #ifdef USE_WINDOWS_STYLE_SOCKETS 344 WSASetLastError(errorCode);
350 void Socket::HandleError(
const char *operation)
const 352 int err = GetLastError();
353 throw Err(m_s, operation, err);
356 #ifdef USE_WINDOWS_STYLE_SOCKETS 358 SocketReceiver::SocketReceiver(
Socket &s)
359 : m_s(s), m_eofReceived(
false), m_resultPending(
false)
361 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
362 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
363 memset(&m_overlapped, 0,
sizeof(m_overlapped));
364 m_overlapped.hEvent = m_event;
367 SocketReceiver::~SocketReceiver()
369 #ifdef USE_WINDOWS_STYLE_SOCKETS 370 # if defined(USE_WINDOWS8_API) 371 BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULL);
372 assert(result || (!result && GetLastError() == ERROR_NOT_FOUND));
373 CRYPTOPP_UNUSED(result);
375 BOOL result = CancelIo((HANDLE) m_s.GetSocket());
376 assert(result || (!result && GetLastError() == ERROR_NOT_FOUND));
377 CRYPTOPP_UNUSED(result);
384 assert(!m_resultPending && !m_eofReceived);
388 WSABUF wsabuf = {
UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
389 if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
391 if (m_lastResult == 0)
392 m_eofReceived =
true;
396 switch (WSAGetLastError())
399 m_s.CheckAndHandleError_int(
"WSARecv", SOCKET_ERROR);
402 m_eofReceived =
true;
405 m_resultPending =
true;
408 return !m_resultPending;
414 container.AddHandle(m_event,
CallStack(
"SocketReceiver::GetWaitObjects() - result pending", &callStack));
415 else if (!m_eofReceived)
416 container.SetNoWait(
CallStack(
"SocketReceiver::GetWaitObjects() - result ready", &callStack));
419 unsigned int SocketReceiver::GetReceiveResult()
424 if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags))
426 if (m_lastResult == 0)
427 m_eofReceived =
true;
431 switch (WSAGetLastError())
434 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", FALSE);
437 m_eofReceived =
true;
440 m_resultPending =
false;
447 SocketSender::SocketSender(
Socket &s)
448 : m_s(s), m_resultPending(
false), m_lastResult(0)
450 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
451 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
452 memset(&m_overlapped, 0,
sizeof(m_overlapped));
453 m_overlapped.hEvent = m_event;
457 SocketSender::~SocketSender()
459 #ifdef USE_WINDOWS_STYLE_SOCKETS 460 # if defined(USE_WINDOWS8_API) 461 BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULL);
462 assert(result || (!result && GetLastError() == ERROR_NOT_FOUND));
463 CRYPTOPP_UNUSED(result);
465 BOOL result = CancelIo((HANDLE) m_s.GetSocket());
466 assert(result || (!result && GetLastError() == ERROR_NOT_FOUND));
467 CRYPTOPP_UNUSED(result);
472 void SocketSender::Send(
const byte* buf,
size_t bufLen)
474 assert(!m_resultPending);
477 WSABUF wsabuf = {
UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
478 if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
480 m_resultPending =
false;
481 m_lastResult = written;
485 if (WSAGetLastError() != WSA_IO_PENDING)
486 m_s.CheckAndHandleError_int(
"WSASend", SOCKET_ERROR);
488 m_resultPending =
true;
492 void SocketSender::SendEof()
494 assert(!m_resultPending);
495 m_s.ShutDown(SD_SEND);
496 m_s.CheckAndHandleError(
"ResetEvent", ResetEvent(m_event));
497 m_s.CheckAndHandleError_int(
"WSAEventSelect", WSAEventSelect(m_s, m_event, FD_CLOSE));
498 m_resultPending =
true;
501 bool SocketSender::EofSent()
505 WSANETWORKEVENTS events;
506 m_s.CheckAndHandleError_int(
"WSAEnumNetworkEvents", WSAEnumNetworkEvents(m_s, m_event, &events));
507 if ((events.lNetworkEvents & FD_CLOSE) != FD_CLOSE)
508 throw Socket::Err(m_s,
"WSAEnumNetworkEvents (FD_CLOSE not present)", E_FAIL);
509 if (events.iErrorCode[FD_CLOSE_BIT] != 0)
510 throw Socket::Err(m_s,
"FD_CLOSE (via WSAEnumNetworkEvents)", events.iErrorCode[FD_CLOSE_BIT]);
511 m_resultPending =
false;
513 return m_lastResult != 0;
519 container.AddHandle(m_event,
CallStack(
"SocketSender::GetWaitObjects() - result pending", &callStack));
521 container.SetNoWait(
CallStack(
"SocketSender::GetWaitObjects() - result ready", &callStack));
524 unsigned int SocketSender::GetSendResult()
529 BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags);
530 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", result);
531 m_resultPending =
false;
538 #ifdef USE_BERKELEY_STYLE_SOCKETS 540 SocketReceiver::SocketReceiver(
Socket &s)
541 : m_s(s), m_eofReceived(
false), m_lastResult(0)
548 container.AddReadFd(m_s,
CallStack(
"SocketReceiver::GetWaitObjects()", &callStack));
553 m_lastResult = m_s.Receive(buf, bufLen);
554 if (bufLen > 0 && m_lastResult == 0)
555 m_eofReceived =
true;
559 unsigned int SocketReceiver::GetReceiveResult()
564 SocketSender::SocketSender(
Socket &s)
565 : m_s(s), m_lastResult(0)
569 void SocketSender::Send(
const byte* buf,
size_t bufLen)
571 m_lastResult = m_s.Send(buf, bufLen);
574 void SocketSender::SendEof()
576 m_s.ShutDown(SD_SEND);
579 unsigned int SocketSender::GetSendResult()
586 container.AddWriteFd(m_s,
CallStack(
"SocketSender::GetWaitObjects()", &callStack));
589 #endif // USE_BERKELEY_STYLE_SOCKETS 593 #endif // SOCKETS_AVAILABLE Base class for all exceptions thrown by the library.
static unsigned int PortNameToNumber(const char *name, const char *protocol="tcp")
look up the port number given its name, returns 0 if not found
container of wait objects
The operating system reported an error.
static void ShutdownSockets()
calls WSACleanup for Windows Sockets
Library configuration file.
exception thrown by Socket class
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
static void StartSockets()
start Windows Sockets 2
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
static void SetLastError(int errorCode)
sets errno or calls WSASetLastError
wrapper for Windows or Berkeley Sockets
bool Receive(byte *buf, size_t bufLen)
receive data from network source, returns whether result is immediately available ...
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Crypto++ library namespace.
void GetWaitObjects(WaitObjectContainer &container, CallStack const &callStack)
Retrieves waitable objects.
static int GetLastError()
returns errno or WSAGetLastError
void GetWaitObjects(WaitObjectContainer &container, CallStack const &callStack)
Retrieves waitable objects.