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> 33 #ifdef PREFER_WINDOWS_STYLE_SOCKETS 34 # pragma comment(lib, "ws2_32.lib") 39 #ifdef USE_WINDOWS_STYLE_SOCKETS 40 const int SOCKET_EINVAL = WSAEINVAL;
41 const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
42 typedef int socklen_t;
44 const int SOCKET_EINVAL = EINVAL;
45 const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
50 # define INADDR_NONE 0xffffffff 54 #ifndef INET_ADDRSTRLEN 55 # define INET_ADDRSTRLEN (22) 57 #ifndef INET6_ADDRSTRLEN 58 # define INET6_ADDRSTRLEN (65) 61 #define MAX_ADDRSTRLEN (INET6_ADDRSTRLEN > INET_ADDRSTRLEN ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN) 63 #if defined(CRYPTOPP_WIN32_AVAILABLE) 65 int inet_pton(
int af,
const char *src,
void *dst)
67 #if CRYPTOPP_MSC_VERSION 68 # pragma warning(push) 69 # pragma warning(disable: 4996) 73 if(!src || !dst)
return 0;
75 struct sockaddr_storage ss;
76 ZeroMemory(&ss,
sizeof(ss));
78 #if CRYPTOPP_MSC_VERSION >= 1400 79 char temp[MAX_ADDRSTRLEN];
80 strcpy_s(temp,
sizeof(temp), src);
82 char temp[MAX_ADDRSTRLEN];
83 strncpy(temp, src,
sizeof(temp));
84 temp[MAX_ADDRSTRLEN-1] =
'\0';
88 int size =
sizeof(ss);
89 if (WSAStringToAddress(temp, af, NULL, (
struct sockaddr *)&ss, &size) == 0) {
92 *(
struct in_addr *)dst = ((
struct sockaddr_in *)&ss)->sin_addr;
95 *(
struct in6_addr *)dst = ((
struct sockaddr_in6 *)&ss)->sin6_addr;
100 ((sockaddr_in *)dst)->sin_addr.s_addr = INADDR_NONE;
103 #if CRYPTOPP_MSC_VERSION 104 # pragma warning(pop) 109 Socket::Err::Err(socket_t s,
const std::string& operation,
int error)
110 :
OS_Error(IO_ERROR,
"Socket: " + operation +
" operation failed with error " +
IntToString(error), operation, error)
130 void Socket::AttachSocket(socket_t s,
bool own)
140 socket_t Socket::DetachSocket()
143 m_s = INVALID_SOCKET;
148 void Socket::Create(
int nType)
151 m_s = socket(AF_INET, nType, 0);
152 CheckAndHandleError(
"socket", m_s);
157 void Socket::CloseSocket()
159 if (m_s != INVALID_SOCKET)
161 #ifdef USE_WINDOWS_STYLE_SOCKETS 162 # if defined(USE_WINDOWS8_API) 163 BOOL result = CancelIoEx((HANDLE) m_s, NULL);
164 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
165 CheckAndHandleError_int(
"closesocket", closesocket(m_s));
166 CRYPTOPP_UNUSED(result);
168 BOOL result = CancelIo((HANDLE) m_s);
169 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
170 CheckAndHandleError_int(
"closesocket", closesocket(m_s));
171 CRYPTOPP_UNUSED(result);
174 CheckAndHandleError_int(
"close", close(m_s));
176 m_s = INVALID_SOCKET;
181 void Socket::Bind(
unsigned int port,
const char *addr)
184 memset(&sa, 0,
sizeof(sa));
185 sa.sin_family = AF_INET;
188 sa.sin_addr.s_addr = htonl(INADDR_ANY);
192 unsigned long result;
193 if (inet_pton(AF_INET, addr, &result) < 1 || result == INADDR_NONE)
195 SetLastError(SOCKET_EINVAL);
196 CheckAndHandleError_int(
"inet_addr", SOCKET_ERROR);
198 sa.sin_addr.s_addr = result;
201 sa.sin_port = htons((
unsigned short)port);
203 Bind((sockaddr *)&sa,
sizeof(sa));
206 void Socket::Bind(
const sockaddr *psa, socklen_t saLen)
210 CheckAndHandleError_int(
"bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
213 void Socket::Listen(
int backlog)
216 CheckAndHandleError_int(
"listen", listen(m_s, backlog));
219 bool Socket::Connect(
const char *addr,
unsigned int port)
224 memset(&sa, 0,
sizeof(sa));
225 sa.sin_family = AF_INET;
228 if (!addr || inet_pton(AF_INET, addr, &sa.sin_addr.s_addr) < 1)
229 sa.sin_addr.s_addr = INADDR_NONE;
231 if (sa.sin_addr.s_addr == INADDR_NONE)
233 addrinfo hints, *result = NULL;
234 memset(&hints, 0,
sizeof(hints));
236 hints.ai_socktype = SOCK_STREAM;
237 hints.ai_family = AF_INET;
239 if (getaddrinfo(addr, NULL, &hints, &result) != 0 || result == NULL)
241 freeaddrinfo(result);
242 SetLastError(SOCKET_EINVAL);
243 CheckAndHandleError_int(
"getaddrinfo", SOCKET_ERROR);
248 sa.sin_addr.s_addr = ((
struct sockaddr_in *)(result->ai_addr))->sin_addr.s_addr;
249 freeaddrinfo(result);
253 sa.sin_port = htons((
unsigned short)port);
255 return Connect((
const sockaddr *)&sa,
sizeof(sa));
258 bool Socket::Connect(
const sockaddr* psa, socklen_t saLen)
261 int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
262 if (result == SOCKET_ERROR && GetLastError() == SOCKET_EWOULDBLOCK)
264 CheckAndHandleError_int(
"connect", result);
268 bool Socket::Accept(
Socket& target, sockaddr *psa, socklen_t *psaLen)
271 socket_t s = accept(m_s, psa, psaLen);
272 if (s == INVALID_SOCKET && GetLastError() == SOCKET_EWOULDBLOCK)
274 CheckAndHandleError(
"accept", s);
275 target.AttachSocket(s,
true);
279 void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
282 CheckAndHandleError_int(
"getsockname", getsockname(m_s, psa, psaLen));
285 void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
288 CheckAndHandleError_int(
"getpeername", getpeername(m_s, psa, psaLen));
291 unsigned int Socket::Send(
const byte* buf,
size_t bufLen,
int flags)
294 int result = send(m_s, (
const char *)buf,
UnsignedMin(INT_MAX, bufLen), flags);
295 CheckAndHandleError_int(
"send", result);
299 unsigned int Socket::Receive(byte* buf,
size_t bufLen,
int flags)
302 int result = recv(m_s, (
char *)buf,
UnsignedMin(INT_MAX, bufLen), flags);
303 CheckAndHandleError_int(
"recv", result);
307 void Socket::ShutDown(
int how)
310 int result = shutdown(m_s, how);
311 CheckAndHandleError_int(
"shutdown", result);
314 void Socket::IOCtl(
long cmd,
unsigned long *argp)
317 #ifdef USE_WINDOWS_STYLE_SOCKETS 318 CheckAndHandleError_int(
"ioctlsocket", ioctlsocket(m_s, cmd, argp));
320 CheckAndHandleError_int(
"ioctl", ioctl(m_s, cmd, argp));
324 bool Socket::SendReady(
const timeval *timeout)
330 __msan_unpoison(&fds,
sizeof(fds));
335 ready = select((
int)m_s+1, NULL, &fds, NULL, NULL);
338 timeval timeoutCopy = *timeout;
339 ready = select((
int)m_s+1, NULL, &fds, NULL, &timeoutCopy);
341 CheckAndHandleError_int(
"select", ready);
345 bool Socket::ReceiveReady(
const timeval *timeout)
351 __msan_unpoison(&fds,
sizeof(fds));
356 ready = select((
int)m_s+1, &fds, NULL, NULL, NULL);
359 timeval timeoutCopy = *timeout;
360 ready = select((
int)m_s+1, &fds, NULL, NULL, &timeoutCopy);
362 CheckAndHandleError_int(
"select", ready);
368 int port = atoi(name);
372 servent *se = getservbyname(name, protocol);
374 throw Err(INVALID_SOCKET,
"getservbyname", SOCKET_EINVAL);
375 return ntohs(se->s_port);
380 #ifdef USE_WINDOWS_STYLE_SOCKETS 382 int result = WSAStartup(0x0202, &wsd);
384 throw Err(INVALID_SOCKET,
"WSAStartup", result);
390 #ifdef USE_WINDOWS_STYLE_SOCKETS 391 int result = WSACleanup();
393 throw Err(INVALID_SOCKET,
"WSACleanup", result);
399 #ifdef USE_WINDOWS_STYLE_SOCKETS 400 return WSAGetLastError();
408 #ifdef USE_WINDOWS_STYLE_SOCKETS 409 WSASetLastError(errorCode);
415 void Socket::HandleError(
const char *operation)
const 417 int err = GetLastError();
418 throw Err(m_s, operation, err);
421 #ifdef USE_WINDOWS_STYLE_SOCKETS 423 SocketReceiver::SocketReceiver(
Socket &s)
424 : m_s(s), m_lastResult(0), m_resultPending(
false), m_eofReceived(
false)
426 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
427 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
428 memset(&m_overlapped, 0,
sizeof(m_overlapped));
429 m_overlapped.hEvent = m_event;
432 SocketReceiver::~SocketReceiver()
434 #ifdef USE_WINDOWS_STYLE_SOCKETS 435 # if defined(USE_WINDOWS8_API) 436 BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULL);
437 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
438 CRYPTOPP_UNUSED(result);
440 BOOL result = CancelIo((HANDLE) m_s.GetSocket());
441 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
442 CRYPTOPP_UNUSED(result);
453 WSABUF wsabuf = {
UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
454 if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
456 if (m_lastResult == 0)
457 m_eofReceived =
true;
461 switch (WSAGetLastError())
464 m_s.CheckAndHandleError_int(
"WSARecv", SOCKET_ERROR);
468 m_eofReceived =
true;
471 m_resultPending =
true;
474 return !m_resultPending;
480 container.AddHandle(m_event,
CallStack(
"SocketReceiver::GetWaitObjects() - result pending", &callStack));
481 else if (!m_eofReceived)
482 container.SetNoWait(
CallStack(
"SocketReceiver::GetWaitObjects() - result ready", &callStack));
485 unsigned int SocketReceiver::GetReceiveResult()
490 if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags))
492 if (m_lastResult == 0)
493 m_eofReceived =
true;
497 switch (WSAGetLastError())
500 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", FALSE);
504 m_eofReceived =
true;
507 m_resultPending =
false;
514 SocketSender::SocketSender(
Socket &s)
515 : m_s(s), m_resultPending(
false), m_lastResult(0)
517 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
518 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
519 memset(&m_overlapped, 0,
sizeof(m_overlapped));
520 m_overlapped.hEvent = m_event;
524 SocketSender::~SocketSender()
526 #ifdef USE_WINDOWS_STYLE_SOCKETS 527 # if defined(USE_WINDOWS8_API) 528 BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULL);
529 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
530 CRYPTOPP_UNUSED(result);
532 BOOL result = CancelIo((HANDLE) m_s.GetSocket());
533 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
534 CRYPTOPP_UNUSED(result);
539 void SocketSender::Send(
const byte* buf,
size_t bufLen)
544 WSABUF wsabuf = {
UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
545 if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
547 m_resultPending =
false;
548 m_lastResult = written;
552 if (WSAGetLastError() != WSA_IO_PENDING)
553 m_s.CheckAndHandleError_int(
"WSASend", SOCKET_ERROR);
555 m_resultPending =
true;
559 void SocketSender::SendEof()
562 m_s.ShutDown(SD_SEND);
563 m_s.CheckAndHandleError(
"ResetEvent", ResetEvent(m_event));
564 m_s.CheckAndHandleError_int(
"WSAEventSelect", WSAEventSelect(m_s, m_event, FD_CLOSE));
565 m_resultPending =
true;
568 bool SocketSender::EofSent()
572 WSANETWORKEVENTS events;
573 m_s.CheckAndHandleError_int(
"WSAEnumNetworkEvents", WSAEnumNetworkEvents(m_s, m_event, &events));
574 if ((events.lNetworkEvents & FD_CLOSE) != FD_CLOSE)
575 throw Socket::Err(m_s,
"WSAEnumNetworkEvents (FD_CLOSE not present)", E_FAIL);
576 if (events.iErrorCode[FD_CLOSE_BIT] != 0)
577 throw Socket::Err(m_s,
"FD_CLOSE (via WSAEnumNetworkEvents)", events.iErrorCode[FD_CLOSE_BIT]);
578 m_resultPending =
false;
580 return m_lastResult != 0;
586 container.AddHandle(m_event,
CallStack(
"SocketSender::GetWaitObjects() - result pending", &callStack));
588 container.SetNoWait(
CallStack(
"SocketSender::GetWaitObjects() - result ready", &callStack));
591 unsigned int SocketSender::GetSendResult()
596 BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags);
597 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", result);
598 m_resultPending =
false;
605 #ifdef USE_BERKELEY_STYLE_SOCKETS 607 SocketReceiver::SocketReceiver(
Socket &s)
608 : m_s(s), m_lastResult(0), m_eofReceived(
false)
615 container.AddReadFd(m_s,
CallStack(
"SocketReceiver::GetWaitObjects()", &callStack));
620 m_lastResult = m_s.Receive(buf, bufLen);
621 if (bufLen > 0 && m_lastResult == 0)
622 m_eofReceived =
true;
626 unsigned int SocketReceiver::GetReceiveResult()
631 SocketSender::SocketSender(
Socket &s)
632 : m_s(s), m_lastResult(0)
636 void SocketSender::Send(
const byte* buf,
size_t bufLen)
638 m_lastResult = m_s.Send(buf, bufLen);
641 void SocketSender::SendEof()
643 m_s.ShutDown(SD_SEND);
646 unsigned int SocketSender::GetSendResult()
653 container.AddWriteFd(m_s,
CallStack(
"SocketSender::GetWaitObjects()", &callStack));
656 #endif // USE_BERKELEY_STYLE_SOCKETS 660 #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.