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)
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);
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
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