6 #define _WINSOCK_DEPRECATED_NO_WARNINGS 9 #ifdef SOCKETS_AVAILABLE 13 #ifdef USE_BERKELEY_STYLE_SOCKETS 17 #include <arpa/inet.h> 18 #include <netinet/in.h> 19 #include <sys/ioctl.h> 22 #ifdef PREFER_WINDOWS_STYLE_SOCKETS 23 # pragma comment(lib, "ws2_32.lib") 28 #ifdef USE_WINDOWS_STYLE_SOCKETS 29 const int SOCKET_EINVAL = WSAEINVAL;
30 const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
31 typedef int socklen_t;
33 const int SOCKET_EINVAL = EINVAL;
34 const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
39 # define INADDR_NONE 0xffffffff 42 Socket::Err::Err(socket_t s,
const std::string& operation,
int error)
43 :
OS_Error(IO_ERROR,
"Socket: " + operation +
" operation failed with error " +
IntToString(error), operation, error)
63 void Socket::AttachSocket(socket_t s,
bool own)
73 socket_t Socket::DetachSocket()
81 void Socket::Create(
int nType)
83 assert(m_s == INVALID_SOCKET);
84 m_s = socket(AF_INET, nType, 0);
85 CheckAndHandleError(
"socket", m_s);
90 void Socket::CloseSocket()
92 if (m_s != INVALID_SOCKET)
94 #ifdef USE_WINDOWS_STYLE_SOCKETS 95 CancelIo((HANDLE) m_s);
96 CheckAndHandleError_int(
"closesocket", closesocket(m_s));
98 CheckAndHandleError_int(
"close", close(m_s));
100 m_s = INVALID_SOCKET;
105 void Socket::Bind(
unsigned int port,
const char *addr)
108 memset(&sa, 0,
sizeof(sa));
109 sa.sin_family = AF_INET;
112 sa.sin_addr.s_addr = htonl(INADDR_ANY);
115 unsigned long result = inet_addr(addr);
116 if (result == INADDR_NONE)
118 SetLastError(SOCKET_EINVAL);
119 CheckAndHandleError_int(
"inet_addr", SOCKET_ERROR);
121 sa.sin_addr.s_addr = result;
124 sa.sin_port = htons((u_short)port);
126 Bind((sockaddr *)&sa,
sizeof(sa));
129 void Socket::Bind(
const sockaddr *psa, socklen_t saLen)
131 assert(m_s != INVALID_SOCKET);
133 CheckAndHandleError_int(
"bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
136 void Socket::Listen(
int backlog)
138 assert(m_s != INVALID_SOCKET);
139 CheckAndHandleError_int(
"listen", listen(m_s, backlog));
142 bool Socket::Connect(
const char *addr,
unsigned int port)
144 assert(addr != NULL);
147 memset(&sa, 0,
sizeof(sa));
148 sa.sin_family = AF_INET;
149 sa.sin_addr.s_addr = inet_addr(addr);
151 if (sa.sin_addr.s_addr == INADDR_NONE)
153 hostent *lphost = gethostbyname(addr);
156 SetLastError(SOCKET_EINVAL);
157 CheckAndHandleError_int(
"gethostbyname", SOCKET_ERROR);
161 sa.sin_addr.s_addr = ((in_addr *)lphost->h_addr)->s_addr;
165 sa.sin_port = htons((u_short)port);
167 return Connect((
const sockaddr *)&sa,
sizeof(sa));
170 bool Socket::Connect(
const sockaddr* psa, socklen_t saLen)
172 assert(m_s != INVALID_SOCKET);
173 int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
174 if (result == SOCKET_ERROR && GetLastError() == SOCKET_EWOULDBLOCK)
176 CheckAndHandleError_int(
"connect", result);
180 bool Socket::Accept(Socket& target, sockaddr *psa, socklen_t *psaLen)
182 assert(m_s != INVALID_SOCKET);
183 socket_t s = accept(m_s, psa, psaLen);
184 if (s == INVALID_SOCKET && GetLastError() == SOCKET_EWOULDBLOCK)
186 CheckAndHandleError(
"accept", s);
187 target.AttachSocket(s,
true);
191 void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
193 assert(m_s != INVALID_SOCKET);
194 CheckAndHandleError_int(
"getsockname", getsockname(m_s, psa, psaLen));
197 void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
199 assert(m_s != INVALID_SOCKET);
200 CheckAndHandleError_int(
"getpeername", getpeername(m_s, psa, psaLen));
203 unsigned int Socket::Send(
const byte* buf,
size_t bufLen,
int flags)
205 assert(m_s != INVALID_SOCKET);
206 int result = send(m_s, (
const char *)buf,
UnsignedMin(INT_MAX, bufLen), flags);
207 CheckAndHandleError_int(
"send", result);
211 unsigned int Socket::Receive(byte* buf,
size_t bufLen,
int flags)
213 assert(m_s != INVALID_SOCKET);
214 int result = recv(m_s, (
char *)buf,
UnsignedMin(INT_MAX, bufLen), flags);
215 CheckAndHandleError_int(
"recv", result);
219 void Socket::ShutDown(
int how)
221 assert(m_s != INVALID_SOCKET);
222 int result = shutdown(m_s, how);
223 CheckAndHandleError_int(
"shutdown", result);
226 void Socket::IOCtl(
long cmd,
unsigned long *argp)
228 assert(m_s != INVALID_SOCKET);
229 #ifdef USE_WINDOWS_STYLE_SOCKETS 230 CheckAndHandleError_int(
"ioctlsocket", ioctlsocket(m_s, cmd, argp));
232 CheckAndHandleError_int(
"ioctl", ioctl(m_s, cmd, argp));
236 bool Socket::SendReady(
const timeval *timeout)
243 ready = select((
int)m_s+1, NULL, &fds, NULL, NULL);
246 timeval timeoutCopy = *timeout;
247 ready = select((
int)m_s+1, NULL, &fds, NULL, &timeoutCopy);
249 CheckAndHandleError_int(
"select", ready);
253 bool Socket::ReceiveReady(
const timeval *timeout)
260 ready = select((
int)m_s+1, &fds, NULL, NULL, NULL);
263 timeval timeoutCopy = *timeout;
264 ready = select((
int)m_s+1, &fds, NULL, NULL, &timeoutCopy);
266 CheckAndHandleError_int(
"select", ready);
270 unsigned int Socket::PortNameToNumber(
const char *name,
const char *protocol)
272 int port = atoi(name);
276 servent *se = getservbyname(name, protocol);
278 throw Err(INVALID_SOCKET,
"getservbyname", SOCKET_EINVAL);
279 return ntohs(se->s_port);
282 void Socket::StartSockets()
284 #ifdef USE_WINDOWS_STYLE_SOCKETS 286 int result = WSAStartup(0x0202, &wsd);
288 throw Err(INVALID_SOCKET,
"WSAStartup", result);
292 void Socket::ShutdownSockets()
294 #ifdef USE_WINDOWS_STYLE_SOCKETS 295 int result = WSACleanup();
297 throw Err(INVALID_SOCKET,
"WSACleanup", result);
301 int Socket::GetLastError()
303 #ifdef USE_WINDOWS_STYLE_SOCKETS 304 return WSAGetLastError();
310 void Socket::SetLastError(
int errorCode)
312 #ifdef USE_WINDOWS_STYLE_SOCKETS 313 WSASetLastError(errorCode);
319 void Socket::HandleError(
const char *operation)
const 321 int err = GetLastError();
322 throw Err(m_s, operation, err);
325 #ifdef USE_WINDOWS_STYLE_SOCKETS 327 SocketReceiver::SocketReceiver(Socket &s)
328 : m_s(s), m_eofReceived(false), m_resultPending(false)
330 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
331 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
332 memset(&m_overlapped, 0,
sizeof(m_overlapped));
333 m_overlapped.hEvent = m_event;
336 SocketReceiver::~SocketReceiver()
338 #ifdef USE_WINDOWS_STYLE_SOCKETS 339 CancelIo((HANDLE) m_s.GetSocket());
343 bool SocketReceiver::Receive(byte* buf,
size_t bufLen)
345 assert(!m_resultPending && !m_eofReceived);
349 WSABUF wsabuf = {
UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
350 if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
352 if (m_lastResult == 0)
353 m_eofReceived =
true;
357 switch (WSAGetLastError())
360 m_s.CheckAndHandleError_int(
"WSARecv", SOCKET_ERROR);
363 m_eofReceived =
true;
366 m_resultPending =
true;
369 return !m_resultPending;
375 container.AddHandle(m_event,
CallStack(
"SocketReceiver::GetWaitObjects() - result pending", &callStack));
376 else if (!m_eofReceived)
377 container.SetNoWait(
CallStack(
"SocketReceiver::GetWaitObjects() - result ready", &callStack));
380 unsigned int SocketReceiver::GetReceiveResult()
385 if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags))
387 if (m_lastResult == 0)
388 m_eofReceived =
true;
392 switch (WSAGetLastError())
395 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", FALSE);
398 m_eofReceived =
true;
401 m_resultPending =
false;
408 SocketSender::SocketSender(Socket &s)
409 : m_s(s), m_resultPending(false), m_lastResult(0)
411 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
412 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
413 memset(&m_overlapped, 0,
sizeof(m_overlapped));
414 m_overlapped.hEvent = m_event;
418 SocketSender::~SocketSender()
420 #ifdef USE_WINDOWS_STYLE_SOCKETS 421 CancelIo((HANDLE) m_s.GetSocket());
425 void SocketSender::Send(
const byte* buf,
size_t bufLen)
427 assert(!m_resultPending);
430 WSABUF wsabuf = {
UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
431 if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
433 m_resultPending =
false;
434 m_lastResult = written;
438 if (WSAGetLastError() != WSA_IO_PENDING)
439 m_s.CheckAndHandleError_int(
"WSASend", SOCKET_ERROR);
441 m_resultPending =
true;
445 void SocketSender::SendEof()
447 assert(!m_resultPending);
448 m_s.ShutDown(SD_SEND);
449 m_s.CheckAndHandleError(
"ResetEvent", ResetEvent(m_event));
450 m_s.CheckAndHandleError_int(
"WSAEventSelect", WSAEventSelect(m_s, m_event, FD_CLOSE));
451 m_resultPending =
true;
454 bool SocketSender::EofSent()
458 WSANETWORKEVENTS events;
459 m_s.CheckAndHandleError_int(
"WSAEnumNetworkEvents", WSAEnumNetworkEvents(m_s, m_event, &events));
460 if ((events.lNetworkEvents & FD_CLOSE) != FD_CLOSE)
461 throw Socket::Err(m_s,
"WSAEnumNetworkEvents (FD_CLOSE not present)", E_FAIL);
462 if (events.iErrorCode[FD_CLOSE_BIT] != 0)
463 throw Socket::Err(m_s,
"FD_CLOSE (via WSAEnumNetworkEvents)", events.iErrorCode[FD_CLOSE_BIT]);
464 m_resultPending =
false;
466 return m_lastResult != 0;
472 container.AddHandle(m_event,
CallStack(
"SocketSender::GetWaitObjects() - result pending", &callStack));
474 container.SetNoWait(
CallStack(
"SocketSender::GetWaitObjects() - result ready", &callStack));
477 unsigned int SocketSender::GetSendResult()
482 BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags);
483 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", result);
484 m_resultPending =
false;
491 #ifdef USE_BERKELEY_STYLE_SOCKETS 493 SocketReceiver::SocketReceiver(Socket &s)
494 : m_s(s), m_eofReceived(false), m_lastResult(0)
501 container.AddReadFd(m_s,
CallStack(
"SocketReceiver::GetWaitObjects()", &callStack));
504 bool SocketReceiver::Receive(byte* buf,
size_t bufLen)
506 m_lastResult = m_s.Receive(buf, bufLen);
507 if (bufLen > 0 && m_lastResult == 0)
508 m_eofReceived =
true;
512 unsigned int SocketReceiver::GetReceiveResult()
517 SocketSender::SocketSender(Socket &s)
518 : m_s(s), m_lastResult(0)
522 void SocketSender::Send(
const byte* buf,
size_t bufLen)
524 m_lastResult = m_s.Send(buf, bufLen);
527 void SocketSender::SendEof()
529 m_s.ShutDown(SD_SEND);
532 unsigned int SocketSender::GetSendResult()
539 container.AddWriteFd(m_s,
CallStack(
"SocketSender::GetWaitObjects()", &callStack));
546 #endif // #ifdef SOCKETS_AVAILABLE Base class for all exceptions thrown by Crypto++.
container of wait objects
The operating system reported an error.
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Crypto++ library namespace.