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 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) 64 #if defined(USE_WINDOWS_STYLE_SOCKETS) 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()
148 void Socket::Create(
int nType)
151 m_s = socket(AF_INET, nType, 0);
152 CheckAndHandleError(
"socket", m_s);
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));
168 BOOL result = CancelIo((HANDLE) m_s);
169 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
170 CheckAndHandleError_int(
"closesocket", closesocket(m_s));
174 CheckAndHandleError_int(
"close", close(m_s));
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);
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);
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);
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);
366 unsigned int Socket::PortNameToNumber(
const char *
name,
const char *protocol)
368 int port =
atoi(name);
372 servent *se = getservbyname(name, protocol);
375 return ntohs(se->s_port);
378 void Socket::StartSockets()
380 #ifdef USE_WINDOWS_STYLE_SOCKETS 382 int result = WSAStartup(0x0202, &wsd);
388 void Socket::ShutdownSockets()
390 #ifdef USE_WINDOWS_STYLE_SOCKETS 391 int result = WSACleanup();
397 int Socket::GetLastError()
399 #ifdef USE_WINDOWS_STYLE_SOCKETS 406 void Socket::SetLastError(
int errorCode)
408 #ifdef USE_WINDOWS_STYLE_SOCKETS 409 WSASetLastError(errorCode);
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));
440 BOOL result = CancelIo((HANDLE) m_s.GetSocket());
441 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
447 bool SocketReceiver::Receive(
byte* buf,
size_t bufLen)
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;
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;
500 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", FALSE);
504 m_eofReceived =
true;
507 m_resultPending =
false;
514 SocketSender::SocketSender(Socket &s)
515 : m_s(s), m_lastResult(0), m_resultPending(false)
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));
532 BOOL result = CancelIo((HANDLE) m_s.GetSocket());
533 CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
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;
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));
618 bool SocketReceiver::Receive(
byte* buf,
size_t bufLen)
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.
bool error(const char *fmt, const Args &...args)
The operating system reported an error.
#define NAMESPACE_BEGIN(x)
Library configuration file.
void HandleError(const leveldb::Status &status)
Handle database error by throwing dbwrapper_error exception.
#define WSAGetLastError()
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
#define CRYPTOPP_ASSERT(exp)
uint8_t const size_t const size
#define CRYPTOPP_UNUSED(x)
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
int atoi(const std::string &str)