Fabcoin Core  0.16.2
P2P Digital Currency
socketft.cpp
Go to the documentation of this file.
1 // socketft.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "config.h"
5 
6 #if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE)
7 
8 #include "socketft.h"
9 #include "wait.h"
10 
11 // Windows 8, Windows Server 2012, and Windows Phone 8.1 need <synchapi.h> and <ioapiset.h>
12 #if defined(CRYPTOPP_WIN32_AVAILABLE)
13 # if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
14 # include <synchapi.h>
15 # include <ioapiset.h>
16 # define USE_WINDOWS8_API
17 # endif
18 #endif
19 
20 #ifdef USE_BERKELEY_STYLE_SOCKETS
21 #include <errno.h>
22 #include <netdb.h>
23 #include <unistd.h>
24 #include <arpa/inet.h>
25 #include <netinet/in.h>
26 #include <sys/ioctl.h>
27 #endif
28 
29 #if defined(CRYPTOPP_MSAN)
30 # include <sanitizer/msan_interface.h>
31 #endif
32 
33 #ifdef PREFER_WINDOWS_STYLE_SOCKETS
34 # pragma comment(lib, "ws2_32.lib")
35 #endif
36 
38 
39 #ifdef USE_WINDOWS_STYLE_SOCKETS
40 const int SOCKET_EINVAL = WSAEINVAL;
41 const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
42 typedef int socklen_t;
43 #else
44 const int SOCKET_EINVAL = EINVAL;
45 const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
46 #endif
47 
48 // Solaris doesn't have INADDR_NONE
49 #ifndef INADDR_NONE
50 # define INADDR_NONE 0xffffffff
51 #endif /* INADDR_NONE */
52 
53 // Some Windows SDKs do not have INET6_ADDRSTRLEN
54 #ifndef INET_ADDRSTRLEN
55 # define INET_ADDRSTRLEN (22)
56 #endif
57 #ifndef INET6_ADDRSTRLEN
58 # define INET6_ADDRSTRLEN (65)
59 #endif
60 
61 #define MAX_ADDRSTRLEN (INET6_ADDRSTRLEN > INET_ADDRSTRLEN ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN)
62 
63 // Also see http://stackoverflow.com/a/20816961 and http://github.com/weidai11/cryptopp/issues/322
64 #if defined(USE_WINDOWS_STYLE_SOCKETS)
65 int inet_pton(int af, const char *src, void *dst)
66 {
67 #if CRYPTOPP_MSC_VERSION
68 # pragma warning(push)
69 # pragma warning(disable: 4996)
70 #endif
71 
72  // Posix states only src is validated. Avoid a bad dst dereference.
73  if(!src || !dst) return 0;
74 
75  struct sockaddr_storage ss;
76  ZeroMemory(&ss, sizeof(ss));
77 
78 #if CRYPTOPP_MSC_VERSION >= 1400
79  char temp[MAX_ADDRSTRLEN];
80  strcpy_s(temp, sizeof(temp), src);
81 #else
82  char temp[MAX_ADDRSTRLEN];
83  strncpy(temp, src, sizeof(temp));
84  temp[MAX_ADDRSTRLEN-1] = '\0';
85 #endif
86 
87 
88  int size = sizeof(ss);
89  if (WSAStringToAddress(temp, af, NULL, (struct sockaddr *)&ss, &size) == 0) {
90  switch (af) {
91  case AF_INET:
92  *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
93  return 1;
94  case AF_INET6:
95  *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
96  return 1;
97  }
98  }
99 
100  ((sockaddr_in *)dst)->sin_addr.s_addr = INADDR_NONE;
101  return 0;
102 
103 #if CRYPTOPP_MSC_VERSION
104 # pragma warning(pop)
105 #endif
106 }
107 #endif
108 
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)
111  , m_s(s)
112 {
113 }
114 
115 Socket::~Socket()
116 {
117  if (m_own)
118  {
119  try
120  {
121  CloseSocket();
122  }
123  catch (const Exception&)
124  {
125  CRYPTOPP_ASSERT(0);
126  }
127  }
128 }
129 
130 void Socket::AttachSocket(socket_t s, bool own)
131 {
132  if (m_own)
133  CloseSocket();
134 
135  m_s = s;
136  m_own = own;
137  SocketChanged();
138 }
139 
140 socket_t Socket::DetachSocket()
141 {
142  socket_t s = m_s;
143  m_s = INVALID_SOCKET;
144  SocketChanged();
145  return s;
146 }
147 
148 void Socket::Create(int nType)
149 {
151  m_s = socket(AF_INET, nType, 0);
152  CheckAndHandleError("socket", m_s);
153  m_own = true;
154  SocketChanged();
155 }
156 
157 void Socket::CloseSocket()
158 {
159  if (m_s != INVALID_SOCKET)
160  {
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); // Used by CRYPTOPP_ASSERT in debug builds
167 # else
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);
172 # endif
173 #else
174  CheckAndHandleError_int("close", close(m_s));
175 #endif
176  m_s = INVALID_SOCKET;
177  SocketChanged();
178  }
179 }
180 
181 void Socket::Bind(unsigned int port, const char *addr)
182 {
183  sockaddr_in sa;
184  memset(&sa, 0, sizeof(sa));
185  sa.sin_family = AF_INET;
186 
187  if (addr == NULL)
188  sa.sin_addr.s_addr = htonl(INADDR_ANY);
189  else
190  {
191  // unsigned long result = inet_addr(addr);
192  unsigned long result;
193  if (inet_pton(AF_INET, addr, &result) < 1 || result == INADDR_NONE)
194  {
195  SetLastError(SOCKET_EINVAL);
196  CheckAndHandleError_int("inet_addr", SOCKET_ERROR);
197  }
198  sa.sin_addr.s_addr = result;
199  }
200 
201  sa.sin_port = htons((unsigned short)port);
202 
203  Bind((sockaddr *)&sa, sizeof(sa));
204 }
205 
206 void Socket::Bind(const sockaddr *psa, socklen_t saLen)
207 {
209  // cygwin workaround: needs const_cast
210  CheckAndHandleError_int("bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
211 }
212 
213 void Socket::Listen(int backlog)
214 {
216  CheckAndHandleError_int("listen", listen(m_s, backlog));
217 }
218 
219 bool Socket::Connect(const char *addr, unsigned int port)
220 {
221  CRYPTOPP_ASSERT(addr != NULL);
222 
223  sockaddr_in sa;
224  memset(&sa, 0, sizeof(sa));
225  sa.sin_family = AF_INET;
226 
227  // Make inet_pton failures non-fatal.
228  if (!addr || inet_pton(AF_INET, addr, &sa.sin_addr.s_addr) < 1)
229  sa.sin_addr.s_addr = INADDR_NONE;
230 
231  if (sa.sin_addr.s_addr == INADDR_NONE)
232  {
233  addrinfo hints, *result = NULL;
234  memset(&hints, 0, sizeof(hints));
235 
236  hints.ai_socktype = SOCK_STREAM;
237  hints.ai_family = AF_INET;
238 
239  if (getaddrinfo(addr, NULL, &hints, &result) != 0 || result == NULL)
240  {
241  freeaddrinfo(result);
242  SetLastError(SOCKET_EINVAL);
243  CheckAndHandleError_int("getaddrinfo", SOCKET_ERROR);
244  }
245  else
246  {
247  // sa.sin_addr.s_addr = ((in_addr *)(void *)lphost->h_addr)->s_addr;
248  sa.sin_addr.s_addr = ((struct sockaddr_in *)(result->ai_addr))->sin_addr.s_addr;
249  freeaddrinfo(result);
250  }
251  }
252 
253  sa.sin_port = htons((unsigned short)port);
254 
255  return Connect((const sockaddr *)&sa, sizeof(sa));
256 }
257 
258 bool Socket::Connect(const sockaddr* psa, socklen_t saLen)
259 {
261  int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
262  if (result == SOCKET_ERROR && GetLastError() == SOCKET_EWOULDBLOCK)
263  return false;
264  CheckAndHandleError_int("connect", result);
265  return true;
266 }
267 
268 bool Socket::Accept(Socket& target, sockaddr *psa, socklen_t *psaLen)
269 {
271  socket_t s = accept(m_s, psa, psaLen);
272  if (s == INVALID_SOCKET && GetLastError() == SOCKET_EWOULDBLOCK)
273  return false;
274  CheckAndHandleError("accept", s);
275  target.AttachSocket(s, true);
276  return true;
277 }
278 
279 void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
280 {
282  CheckAndHandleError_int("getsockname", getsockname(m_s, psa, psaLen));
283 }
284 
285 void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
286 {
288  CheckAndHandleError_int("getpeername", getpeername(m_s, psa, psaLen));
289 }
290 
291 unsigned int Socket::Send(const byte* buf, size_t bufLen, int flags)
292 {
294  int result = send(m_s, (const char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
295  CheckAndHandleError_int("send", result);
296  return result;
297 }
298 
299 unsigned int Socket::Receive(byte* buf, size_t bufLen, int flags)
300 {
302  int result = recv(m_s, (char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
303  CheckAndHandleError_int("recv", result);
304  return result;
305 }
306 
307 void Socket::ShutDown(int how)
308 {
310  int result = shutdown(m_s, how);
311  CheckAndHandleError_int("shutdown", result);
312 }
313 
314 void Socket::IOCtl(long cmd, unsigned long *argp)
315 {
317 #ifdef USE_WINDOWS_STYLE_SOCKETS
318  CheckAndHandleError_int("ioctlsocket", ioctlsocket(m_s, cmd, argp));
319 #else
320  CheckAndHandleError_int("ioctl", ioctl(m_s, cmd, argp));
321 #endif
322 }
323 
324 bool Socket::SendReady(const timeval *timeout)
325 {
326  fd_set fds;
327  FD_ZERO(&fds);
328  FD_SET(m_s, &fds);
329 #ifdef CRYPTOPP_MSAN
330  __msan_unpoison(&fds, sizeof(fds));
331 #endif
332 
333  int ready;
334  if (timeout == NULL)
335  ready = select((int)m_s+1, NULL, &fds, NULL, NULL);
336  else
337  {
338  timeval timeoutCopy = *timeout; // select() modified timeout on Linux
339  ready = select((int)m_s+1, NULL, &fds, NULL, &timeoutCopy);
340  }
341  CheckAndHandleError_int("select", ready);
342  return ready > 0;
343 }
344 
345 bool Socket::ReceiveReady(const timeval *timeout)
346 {
347  fd_set fds;
348  FD_ZERO(&fds);
349  FD_SET(m_s, &fds);
350 #ifdef CRYPTOPP_MSAN
351  __msan_unpoison(&fds, sizeof(fds));
352 #endif
353 
354  int ready;
355  if (timeout == NULL)
356  ready = select((int)m_s+1, &fds, NULL, NULL, NULL);
357  else
358  {
359  timeval timeoutCopy = *timeout; // select() modified timeout on Linux
360  ready = select((int)m_s+1, &fds, NULL, NULL, &timeoutCopy);
361  }
362  CheckAndHandleError_int("select", ready);
363  return ready > 0;
364 }
365 
366 unsigned int Socket::PortNameToNumber(const char *name, const char *protocol)
367 {
368  int port = atoi(name);
369  if (IntToString(port) == name)
370  return port;
371 
372  servent *se = getservbyname(name, protocol);
373  if (!se)
374  throw Err(INVALID_SOCKET, "getservbyname", SOCKET_EINVAL);
375  return ntohs(se->s_port);
376 }
377 
378 void Socket::StartSockets()
379 {
380 #ifdef USE_WINDOWS_STYLE_SOCKETS
381  WSADATA wsd;
382  int result = WSAStartup(0x0202, &wsd);
383  if (result != 0)
384  throw Err(INVALID_SOCKET, "WSAStartup", result);
385 #endif
386 }
387 
388 void Socket::ShutdownSockets()
389 {
390 #ifdef USE_WINDOWS_STYLE_SOCKETS
391  int result = WSACleanup();
392  if (result != 0)
393  throw Err(INVALID_SOCKET, "WSACleanup", result);
394 #endif
395 }
396 
397 int Socket::GetLastError()
398 {
399 #ifdef USE_WINDOWS_STYLE_SOCKETS
400  return WSAGetLastError();
401 #else
402  return errno;
403 #endif
404 }
405 
406 void Socket::SetLastError(int errorCode)
407 {
408 #ifdef USE_WINDOWS_STYLE_SOCKETS
409  WSASetLastError(errorCode);
410 #else
411  errno = errorCode;
412 #endif
413 }
414 
415 void Socket::HandleError(const char *operation) const
416 {
417  int err = GetLastError();
418  throw Err(m_s, operation, err);
419 }
420 
421 #ifdef USE_WINDOWS_STYLE_SOCKETS
422 
423 SocketReceiver::SocketReceiver(Socket &s)
424  : m_s(s), m_lastResult(0), m_resultPending(false), m_eofReceived(false)
425 {
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;
430 }
431 
432 SocketReceiver::~SocketReceiver()
433 {
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); // Used by CRYPTOPP_ASSERT in debug builds
439 # else
440  BOOL result = CancelIo((HANDLE) m_s.GetSocket());
441  CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
442  CRYPTOPP_UNUSED(result);
443 # endif
444 #endif
445 }
446 
447 bool SocketReceiver::Receive(byte* buf, size_t bufLen)
448 {
449  CRYPTOPP_ASSERT(!m_resultPending && !m_eofReceived);
450 
451  DWORD flags = 0;
452  // don't queue too much at once, or we might use up non-paged memory
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)
455  {
456  if (m_lastResult == 0)
457  m_eofReceived = true;
458  }
459  else
460  {
461  switch (WSAGetLastError())
462  {
463  default:
464  m_s.CheckAndHandleError_int("WSARecv", SOCKET_ERROR);
465  // Fall through for non-fatal
466  case WSAEDISCON:
467  m_lastResult = 0;
468  m_eofReceived = true;
469  break;
470  case WSA_IO_PENDING:
471  m_resultPending = true;
472  }
473  }
474  return !m_resultPending;
475 }
476 
477 void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
478 {
479  if (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));
483 }
484 
485 unsigned int SocketReceiver::GetReceiveResult()
486 {
487  if (m_resultPending)
488  {
489  DWORD flags = 0;
490  if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags))
491  {
492  if (m_lastResult == 0)
493  m_eofReceived = true;
494  }
495  else
496  {
497  switch (WSAGetLastError())
498  {
499  default:
500  m_s.CheckAndHandleError("WSAGetOverlappedResult", FALSE);
501  // Fall through for non-fatal
502  case WSAEDISCON:
503  m_lastResult = 0;
504  m_eofReceived = true;
505  }
506  }
507  m_resultPending = false;
508  }
509  return m_lastResult;
510 }
511 
512 // *************************************************************
513 
514 SocketSender::SocketSender(Socket &s)
515  : m_s(s), m_lastResult(0), m_resultPending(false)
516 {
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;
521 }
522 
523 
524 SocketSender::~SocketSender()
525 {
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); // Used by CRYPTOPP_ASSERT in debug builds
531 # else
532  BOOL result = CancelIo((HANDLE) m_s.GetSocket());
533  CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
534  CRYPTOPP_UNUSED(result);
535 # endif
536 #endif
537 }
538 
539 void SocketSender::Send(const byte* buf, size_t bufLen)
540 {
541  CRYPTOPP_ASSERT(!m_resultPending);
542  DWORD written = 0;
543  // don't queue too much at once, or we might use up non-paged memory
544  WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
545  if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
546  {
547  m_resultPending = false;
548  m_lastResult = written;
549  }
550  else
551  {
552  if (WSAGetLastError() != WSA_IO_PENDING)
553  m_s.CheckAndHandleError_int("WSASend", SOCKET_ERROR);
554 
555  m_resultPending = true;
556  }
557 }
558 
559 void SocketSender::SendEof()
560 {
561  CRYPTOPP_ASSERT(!m_resultPending);
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;
566 }
567 
568 bool SocketSender::EofSent()
569 {
570  if (m_resultPending)
571  {
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;
579  }
580  return m_lastResult != 0;
581 }
582 
583 void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
584 {
585  if (m_resultPending)
586  container.AddHandle(m_event, CallStack("SocketSender::GetWaitObjects() - result pending", &callStack));
587  else
588  container.SetNoWait(CallStack("SocketSender::GetWaitObjects() - result ready", &callStack));
589 }
590 
591 unsigned int SocketSender::GetSendResult()
592 {
593  if (m_resultPending)
594  {
595  DWORD flags = 0;
596  BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags);
597  m_s.CheckAndHandleError("WSAGetOverlappedResult", result);
598  m_resultPending = false;
599  }
600  return m_lastResult;
601 }
602 
603 #endif
604 
605 #ifdef USE_BERKELEY_STYLE_SOCKETS
606 
607 SocketReceiver::SocketReceiver(Socket &s)
608  : m_s(s), m_lastResult(0), m_eofReceived(false)
609 {
610 }
611 
612 void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
613 {
614  if (!m_eofReceived)
615  container.AddReadFd(m_s, CallStack("SocketReceiver::GetWaitObjects()", &callStack));
616 }
617 
618 bool SocketReceiver::Receive(byte* buf, size_t bufLen)
619 {
620  m_lastResult = m_s.Receive(buf, bufLen);
621  if (bufLen > 0 && m_lastResult == 0)
622  m_eofReceived = true;
623  return true;
624 }
625 
626 unsigned int SocketReceiver::GetReceiveResult()
627 {
628  return m_lastResult;
629 }
630 
631 SocketSender::SocketSender(Socket &s)
632  : m_s(s), m_lastResult(0)
633 {
634 }
635 
636 void SocketSender::Send(const byte* buf, size_t bufLen)
637 {
638  m_lastResult = m_s.Send(buf, bufLen);
639 }
640 
641 void SocketSender::SendEof()
642 {
643  m_s.ShutDown(SD_SEND);
644 }
645 
646 unsigned int SocketSender::GetSendResult()
647 {
648  return m_lastResult;
649 }
650 
651 void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
652 {
653  container.AddWriteFd(m_s, CallStack("SocketSender::GetWaitObjects()", &callStack));
654 }
655 
656 #endif // USE_BERKELEY_STYLE_SOCKETS
657 
659 
660 #endif // SOCKETS_AVAILABLE
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:140
bool error(const char *fmt, const Args &...args)
Definition: util.h:178
uint8_t byte
Definition: Common.h:57
The operating system reported an error.
Definition: cryptlib.h:219
#define NAMESPACE_BEGIN(x)
Definition: config.h:200
Library configuration file.
void HandleError(const leveldb::Status &status)
Handle database error by throwing dbwrapper_error exception.
Definition: dbwrapper.cpp:199
#define INVALID_SOCKET
Definition: compat.h:62
#define WSAGetLastError()
Definition: compat.h:53
#define SOCKET_ERROR
Definition: compat.h:63
const char * name
Definition: rest.cpp:36
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
Definition: misc.h:512
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Definition: netbase.cpp:732
#define WSAEWOULDBLOCK
Definition: compat.h:56
#define CRYPTOPP_ASSERT(exp)
Definition: trap.h:92
#define WSAEINVAL
Definition: compat.h:54
uint8_t const size_t const size
Definition: sha3.h:20
#define CRYPTOPP_UNUSED(x)
Definition: config.h:741
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:539
#define NAMESPACE_END
Definition: config.h:201
int atoi(const std::string &str)