6 #if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE) 12 #if defined(CRYPTOPP_WIN32_AVAILABLE) 13 # if ((WINVER >= 0x0602 ) || (_WIN32_WINNT >= 0x0602 )) 14 # include <synchapi.h> 15 # include <ioapiset.h> 16 # define USE_WINDOWS8_API 20 #ifdef USE_BERKELEY_STYLE_SOCKETS 24 #include <arpa/inet.h> 25 #include <netinet/in.h> 26 #include <sys/ioctl.h> 29 #if defined(CRYPTOPP_MSAN) 30 # include <sanitizer/msan_interface.h> 36 #if defined(__MINGW32__) && (_WIN32_WINNT < 0x501) 38 # define _WIN32_WINNT 0x501 41 #ifdef USE_WINDOWS_STYLE_SOCKETS 42 # pragma comment(lib, "ws2_32.lib") 43 # if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x501) 50 #ifdef USE_WINDOWS_STYLE_SOCKETS 51 const int SOCKET_EINVAL = WSAEINVAL;
52 const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
53 typedef int socklen_t;
55 const int SOCKET_EINVAL = EINVAL;
56 const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
61 # define INADDR_NONE 0xffffffff 65 #ifndef INET_ADDRSTRLEN 66 # define INET_ADDRSTRLEN (22) 68 #ifndef INET6_ADDRSTRLEN 69 # define INET6_ADDRSTRLEN (65) 72 #define MAX_ADDRSTRLEN (INET6_ADDRSTRLEN > INET_ADDRSTRLEN ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN) 75 #if defined(USE_WINDOWS_STYLE_SOCKETS) 76 int inet_pton(
int af,
const char *src,
void *dst)
78 #if CRYPTOPP_MSC_VERSION 79 # pragma warning(push) 80 # pragma warning(disable: 4996) 84 if(!src || !dst)
return 0;
86 struct sockaddr_storage ss;
87 ZeroMemory(&ss,
sizeof(ss));
89 #if CRYPTOPP_MSC_VERSION >= 1400 90 char temp[MAX_ADDRSTRLEN];
91 strcpy_s(temp,
sizeof(temp), src);
93 char temp[MAX_ADDRSTRLEN];
94 strncpy(temp, src,
sizeof(temp));
95 temp[MAX_ADDRSTRLEN-1] =
'\0';
99 int size =
sizeof(ss);
100 if (WSAStringToAddressA(temp, af, NULLPTR, (
struct sockaddr *)&ss, &size) == 0) {
103 *(
struct in_addr *)dst = ((
struct sockaddr_in *)&ss)->sin_addr;
106 *(
struct in6_addr *)dst = ((
struct sockaddr_in6 *)&ss)->sin6_addr;
111 ((sockaddr_in *)dst)->sin_addr.s_addr = INADDR_NONE;
114 #if CRYPTOPP_MSC_VERSION 115 # pragma warning(pop) 120 Socket::Err::Err(socket_t s,
const std::string& operation,
int error)
121 :
OS_Error(IO_ERROR,
"Socket: " + operation +
" operation failed with error " +
IntToString(error), operation, error)
141 void Socket::AttachSocket(socket_t s,
bool own)
151 socket_t Socket::DetachSocket()
154 m_s = INVALID_SOCKET;
159 void Socket::Create(
int nType)
162 m_s = socket(AF_INET, nType, 0);
163 CheckAndHandleError(
"socket", m_s);
168 void Socket::CloseSocket()
170 if (m_s != INVALID_SOCKET)
172 #ifdef USE_WINDOWS_STYLE_SOCKETS 173 # if defined(USE_WINDOWS8_API) 174 BOOL result = CancelIoEx((HANDLE) m_s, NULLPTR);
176 CheckAndHandleError_int(
"closesocket", closesocket(m_s));
177 CRYPTOPP_UNUSED(result);
179 BOOL result = CancelIo((HANDLE) m_s);
181 CheckAndHandleError_int(
"closesocket", closesocket(m_s));
182 CRYPTOPP_UNUSED(result);
185 CheckAndHandleError_int(
"close", close(m_s));
187 m_s = INVALID_SOCKET;
192 void Socket::Bind(
unsigned int port,
const char *addr)
195 memset(&sa, 0,
sizeof(sa));
196 sa.sin_family = AF_INET;
199 sa.sin_addr.s_addr = htonl(INADDR_ANY);
203 unsigned long result;
204 if (inet_pton(AF_INET, addr, &result) < 1 || result == INADDR_NONE)
207 CheckAndHandleError_int(
"inet_addr", SOCKET_ERROR);
209 sa.sin_addr.s_addr = result;
212 sa.sin_port = htons((
unsigned short)port);
214 Bind((sockaddr *)&sa,
sizeof(sa));
217 void Socket::Bind(
const sockaddr *psa, socklen_t saLen)
221 CheckAndHandleError_int(
"bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
224 void Socket::Listen(
int backlog)
227 CheckAndHandleError_int(
"listen", listen(m_s, backlog));
230 bool Socket::Connect(
const char *addr,
unsigned int port)
235 memset(&sa, 0,
sizeof(sa));
236 sa.sin_family = AF_INET;
239 if (!addr || inet_pton(AF_INET, addr, &sa.sin_addr.s_addr) < 1)
240 sa.sin_addr.s_addr = INADDR_NONE;
242 if (sa.sin_addr.s_addr == INADDR_NONE)
244 addrinfo hints, *result = NULLPTR;
245 memset(&hints, 0,
sizeof(hints));
247 hints.ai_socktype = SOCK_STREAM;
248 hints.ai_family = AF_INET;
250 if (getaddrinfo(addr, NULLPTR, &hints, &result) != 0 || result == NULLPTR)
252 freeaddrinfo(result);
254 CheckAndHandleError_int(
"getaddrinfo", SOCKET_ERROR);
260 struct sockaddr_in* sap = (
struct sockaddr_in *)result->ai_addr;
261 memcpy(&sa.sin_addr.s_addr, &sap->sin_addr.s_addr,
sizeof(sa.sin_addr.s_addr));
262 freeaddrinfo(result);
266 sa.sin_port = htons((
unsigned short)port);
268 return Connect((
const sockaddr *)&sa,
sizeof(sa));
271 bool Socket::Connect(
const sockaddr* psa, socklen_t saLen)
274 int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
275 if (result == SOCKET_ERROR &&
GetLastError() == SOCKET_EWOULDBLOCK)
277 CheckAndHandleError_int(
"connect", result);
281 bool Socket::Accept(
Socket& target, sockaddr *psa, socklen_t *psaLen)
284 socket_t s = accept(m_s, psa, psaLen);
285 if (s == INVALID_SOCKET &&
GetLastError() == SOCKET_EWOULDBLOCK)
287 CheckAndHandleError(
"accept", s);
288 target.AttachSocket(s,
true);
292 void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
295 CheckAndHandleError_int(
"getsockname", getsockname(m_s, psa, psaLen));
298 void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
301 CheckAndHandleError_int(
"getpeername", getpeername(m_s, psa, psaLen));
304 unsigned int Socket::Send(
const byte* buf,
size_t bufLen,
int flags)
307 int result = send(m_s, (
const char *)buf,
UnsignedMin(INT_MAX, bufLen), flags);
308 CheckAndHandleError_int(
"send", result);
312 unsigned int Socket::Receive(byte* buf,
size_t bufLen,
int flags)
315 int result = recv(m_s, (
char *)buf,
UnsignedMin(INT_MAX, bufLen), flags);
316 CheckAndHandleError_int(
"recv", result);
320 void Socket::ShutDown(
int how)
323 int result = shutdown(m_s, how);
324 CheckAndHandleError_int(
"shutdown", result);
327 void Socket::IOCtl(
long cmd,
unsigned long *argp)
330 #ifdef USE_WINDOWS_STYLE_SOCKETS 331 CheckAndHandleError_int(
"ioctlsocket", ioctlsocket(m_s, cmd, argp));
333 CheckAndHandleError_int(
"ioctl", ioctl(m_s, cmd, argp));
337 bool Socket::SendReady(
const timeval *timeout)
343 __msan_unpoison(&fds,
sizeof(fds));
347 if (timeout == NULLPTR)
348 ready = select((
int)m_s+1, NULLPTR, &fds, NULLPTR, NULLPTR);
351 timeval timeoutCopy = *timeout;
352 ready = select((
int)m_s+1, NULLPTR, &fds, NULLPTR, &timeoutCopy);
354 CheckAndHandleError_int(
"select", ready);
358 bool Socket::ReceiveReady(
const timeval *timeout)
364 __msan_unpoison(&fds,
sizeof(fds));
368 if (timeout == NULLPTR)
369 ready = select((
int)m_s+1, &fds, NULLPTR, NULLPTR, NULLPTR);
372 timeval timeoutCopy = *timeout;
373 ready = select((
int)m_s+1, &fds, NULLPTR, NULLPTR, &timeoutCopy);
375 CheckAndHandleError_int(
"select", ready);
381 int port = atoi(name);
385 servent *se = getservbyname(name, protocol);
387 throw Err(INVALID_SOCKET,
"getservbyname", SOCKET_EINVAL);
388 return ntohs(se->s_port);
393 #ifdef USE_WINDOWS_STYLE_SOCKETS 395 int result = WSAStartup(0x0202, &wsd);
397 throw Err(INVALID_SOCKET,
"WSAStartup", result);
403 #ifdef USE_WINDOWS_STYLE_SOCKETS 404 int result = WSACleanup();
406 throw Err(INVALID_SOCKET,
"WSACleanup", result);
412 #ifdef USE_WINDOWS_STYLE_SOCKETS 413 return WSAGetLastError();
421 #ifdef USE_WINDOWS_STYLE_SOCKETS 422 WSASetLastError(errorCode);
428 void Socket::HandleError(
const char *operation)
const 431 throw Err(m_s, operation, err);
434 #ifdef USE_WINDOWS_STYLE_SOCKETS 436 SocketReceiver::SocketReceiver(
Socket &s)
437 : m_s(s), m_lastResult(0), m_resultPending(false), m_eofReceived(false)
439 m_event.AttachHandle(CreateEvent(NULLPTR,
true,
false, NULLPTR),
true);
440 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
441 memset(&m_overlapped, 0,
sizeof(m_overlapped));
442 m_overlapped.hEvent = m_event;
445 SocketReceiver::~SocketReceiver()
447 #ifdef USE_WINDOWS_STYLE_SOCKETS 448 # if defined(USE_WINDOWS8_API) 449 BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULLPTR);
450 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
451 CRYPTOPP_UNUSED(result);
453 BOOL result = CancelIo((HANDLE) m_s.GetSocket());
454 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
455 CRYPTOPP_UNUSED(result);
466 WSABUF wsabuf = {
UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
467 if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULLPTR) == 0)
469 if (m_lastResult == 0)
470 m_eofReceived =
true;
474 switch (WSAGetLastError())
477 m_s.CheckAndHandleError_int(
"WSARecv", SOCKET_ERROR);
481 m_eofReceived =
true;
484 m_resultPending =
true;
487 return !m_resultPending;
493 container.AddHandle(m_event,
CallStack(
"SocketReceiver::GetWaitObjects() - result pending", &callStack));
494 else if (!m_eofReceived)
495 container.SetNoWait(
CallStack(
"SocketReceiver::GetWaitObjects() - result ready", &callStack));
498 unsigned int SocketReceiver::GetReceiveResult()
503 if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags))
505 if (m_lastResult == 0)
506 m_eofReceived =
true;
510 switch (WSAGetLastError())
513 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", FALSE);
517 m_eofReceived =
true;
520 m_resultPending =
false;
527 SocketSender::SocketSender(
Socket &s)
528 : m_s(s), m_lastResult(0), m_resultPending(false)
530 m_event.AttachHandle(CreateEvent(NULLPTR,
true,
false, NULLPTR),
true);
531 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
532 memset(&m_overlapped, 0,
sizeof(m_overlapped));
533 m_overlapped.hEvent = m_event;
537 SocketSender::~SocketSender()
539 #ifdef USE_WINDOWS_STYLE_SOCKETS 540 # if defined(USE_WINDOWS8_API) 541 BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULLPTR);
542 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
543 CRYPTOPP_UNUSED(result);
545 BOOL result = CancelIo((HANDLE) m_s.GetSocket());
546 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
547 CRYPTOPP_UNUSED(result);
552 void SocketSender::Send(
const byte* buf,
size_t bufLen)
557 WSABUF wsabuf = {
UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
558 if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULLPTR) == 0)
560 m_resultPending =
false;
561 m_lastResult = written;
565 if (WSAGetLastError() != WSA_IO_PENDING)
566 m_s.CheckAndHandleError_int(
"WSASend", SOCKET_ERROR);
568 m_resultPending =
true;
572 void SocketSender::SendEof()
575 m_s.ShutDown(SD_SEND);
576 m_s.CheckAndHandleError(
"ResetEvent", ResetEvent(m_event));
577 m_s.CheckAndHandleError_int(
"WSAEventSelect", WSAEventSelect(m_s, m_event, FD_CLOSE));
578 m_resultPending =
true;
581 bool SocketSender::EofSent()
585 WSANETWORKEVENTS events;
586 m_s.CheckAndHandleError_int(
"WSAEnumNetworkEvents", WSAEnumNetworkEvents(m_s, m_event, &events));
587 if ((events.lNetworkEvents & FD_CLOSE) != FD_CLOSE)
588 throw Socket::Err(m_s,
"WSAEnumNetworkEvents (FD_CLOSE not present)", E_FAIL);
589 if (events.iErrorCode[FD_CLOSE_BIT] != 0)
590 throw Socket::Err(m_s,
"FD_CLOSE (via WSAEnumNetworkEvents)", events.iErrorCode[FD_CLOSE_BIT]);
591 m_resultPending =
false;
593 return m_lastResult != 0;
599 container.AddHandle(m_event,
CallStack(
"SocketSender::GetWaitObjects() - result pending", &callStack));
601 container.SetNoWait(
CallStack(
"SocketSender::GetWaitObjects() - result ready", &callStack));
604 unsigned int SocketSender::GetSendResult()
609 BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags);
610 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", result);
611 m_resultPending =
false;
618 #ifdef USE_BERKELEY_STYLE_SOCKETS 620 SocketReceiver::SocketReceiver(
Socket &s)
621 : m_s(s), m_lastResult(0), m_eofReceived(false)
628 container.AddReadFd(m_s,
CallStack(
"SocketReceiver::GetWaitObjects()", &callStack));
633 m_lastResult = m_s.Receive(buf, bufLen);
634 if (bufLen > 0 && m_lastResult == 0)
635 m_eofReceived =
true;
639 unsigned int SocketReceiver::GetReceiveResult()
644 SocketSender::SocketSender(
Socket &s)
645 : m_s(s), m_lastResult(0)
649 void SocketSender::Send(
const byte* buf,
size_t bufLen)
651 m_lastResult = m_s.Send(buf, bufLen);
654 void SocketSender::SendEof()
656 m_s.ShutDown(SD_SEND);
659 unsigned int SocketSender::GetSendResult()
666 container.AddWriteFd(m_s,
CallStack(
"SocketSender::GetWaitObjects()", &callStack));
669 #endif // USE_BERKELEY_STYLE_SOCKETS 673 #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
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
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
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.