6 #ifdef SOCKETS_AVAILABLE
10 #ifdef USE_BERKELEY_STYLE_SOCKETS
14 #include <arpa/inet.h>
15 #include <netinet/in.h>
16 #include <sys/ioctl.h>
19 NAMESPACE_BEGIN(CryptoPP)
21 #ifdef USE_WINDOWS_STYLE_SOCKETS
22 const int SOCKET_EINVAL = WSAEINVAL;
23 const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
24 typedef int socklen_t;
26 const int SOCKET_EINVAL = EINVAL;
27 const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
30 Socket::Err::Err(socket_t s,
const std::string& operation,
int error)
31 :
OS_Error(IO_ERROR,
"Socket: " + operation +
" operation failed with error " + IntToString(error), operation, error)
50 void Socket::AttachSocket(socket_t s,
bool own)
60 socket_t Socket::DetachSocket()
68 void Socket::Create(
int nType)
70 assert(m_s == INVALID_SOCKET);
71 m_s = socket(AF_INET, nType, 0);
72 CheckAndHandleError(
"socket", m_s);
77 void Socket::CloseSocket()
79 if (m_s != INVALID_SOCKET)
81 #ifdef USE_WINDOWS_STYLE_SOCKETS
82 CancelIo((HANDLE) m_s);
83 CheckAndHandleError_int(
"closesocket", closesocket(m_s));
85 CheckAndHandleError_int(
"close", close(m_s));
92 void Socket::Bind(
unsigned int port,
const char *addr)
95 memset(&sa, 0,
sizeof(sa));
96 sa.sin_family = AF_INET;
99 sa.sin_addr.s_addr = htonl(INADDR_ANY);
102 unsigned long result = inet_addr(addr);
106 CheckAndHandleError_int(
"inet_addr", SOCKET_ERROR);
108 sa.sin_addr.s_addr = result;
111 sa.sin_port = htons((u_short)port);
113 Bind((sockaddr *)&sa,
sizeof(sa));
116 void Socket::Bind(
const sockaddr *psa, socklen_t saLen)
118 assert(m_s != INVALID_SOCKET);
120 CheckAndHandleError_int(
"bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
123 void Socket::Listen(
int backlog)
125 assert(m_s != INVALID_SOCKET);
126 CheckAndHandleError_int(
"listen", listen(m_s, backlog));
129 bool Socket::Connect(
const char *addr,
unsigned int port)
131 assert(addr != NULL);
134 memset(&sa, 0,
sizeof(sa));
135 sa.sin_family = AF_INET;
136 sa.sin_addr.s_addr = inet_addr(addr);
138 if (sa.sin_addr.s_addr == -1)
140 hostent *lphost = gethostbyname(addr);
144 CheckAndHandleError_int(
"gethostbyname", SOCKET_ERROR);
147 sa.sin_addr.s_addr = ((in_addr *)lphost->h_addr)->s_addr;
150 sa.sin_port = htons((u_short)port);
152 return Connect((
const sockaddr *)&sa,
sizeof(sa));
155 bool Socket::Connect(
const sockaddr* psa, socklen_t saLen)
157 assert(m_s != INVALID_SOCKET);
158 int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
159 if (result == SOCKET_ERROR &&
GetLastError() == SOCKET_EWOULDBLOCK)
161 CheckAndHandleError_int(
"connect", result);
165 bool Socket::Accept(
Socket& target, sockaddr *psa, socklen_t *psaLen)
167 assert(m_s != INVALID_SOCKET);
168 socket_t s = accept(m_s, psa, psaLen);
169 if (s == INVALID_SOCKET &&
GetLastError() == SOCKET_EWOULDBLOCK)
171 CheckAndHandleError(
"accept", s);
172 target.AttachSocket(s,
true);
176 void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
178 assert(m_s != INVALID_SOCKET);
179 CheckAndHandleError_int(
"getsockname", getsockname(m_s, psa, psaLen));
182 void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
184 assert(m_s != INVALID_SOCKET);
185 CheckAndHandleError_int(
"getpeername", getpeername(m_s, psa, psaLen));
188 unsigned int Socket::Send(
const byte* buf,
size_t bufLen,
int flags)
190 assert(m_s != INVALID_SOCKET);
191 int result = send(m_s, (
const char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
192 CheckAndHandleError_int(
"send", result);
196 unsigned int Socket::Receive(byte* buf,
size_t bufLen,
int flags)
198 assert(m_s != INVALID_SOCKET);
199 int result = recv(m_s, (
char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
200 CheckAndHandleError_int(
"recv", result);
204 void Socket::ShutDown(
int how)
206 assert(m_s != INVALID_SOCKET);
207 int result = shutdown(m_s, how);
208 CheckAndHandleError_int(
"shutdown", result);
211 void Socket::IOCtl(
long cmd,
unsigned long *argp)
213 assert(m_s != INVALID_SOCKET);
214 #ifdef USE_WINDOWS_STYLE_SOCKETS
215 CheckAndHandleError_int(
"ioctlsocket", ioctlsocket(m_s, cmd, argp));
217 CheckAndHandleError_int(
"ioctl", ioctl(m_s, cmd, argp));
221 bool Socket::SendReady(
const timeval *timeout)
228 ready = select((
int)m_s+1, NULL, &fds, NULL, NULL);
231 timeval timeoutCopy = *timeout;
232 ready = select((
int)m_s+1, NULL, &fds, NULL, &timeoutCopy);
234 CheckAndHandleError_int(
"select", ready);
238 bool Socket::ReceiveReady(
const timeval *timeout)
245 ready = select((
int)m_s+1, &fds, NULL, NULL, NULL);
248 timeval timeoutCopy = *timeout;
249 ready = select((
int)m_s+1, &fds, NULL, NULL, &timeoutCopy);
251 CheckAndHandleError_int(
"select", ready);
257 int port = atoi(name);
258 if (IntToString(port) == name)
261 servent *se = getservbyname(name, protocol);
263 throw Err(INVALID_SOCKET,
"getservbyname", SOCKET_EINVAL);
264 return ntohs(se->s_port);
269 #ifdef USE_WINDOWS_STYLE_SOCKETS
271 int result = WSAStartup(0x0202, &wsd);
273 throw Err(INVALID_SOCKET,
"WSAStartup", result);
279 #ifdef USE_WINDOWS_STYLE_SOCKETS
280 int result = WSACleanup();
282 throw Err(INVALID_SOCKET,
"WSACleanup", result);
288 #ifdef USE_WINDOWS_STYLE_SOCKETS
289 return WSAGetLastError();
297 #ifdef USE_WINDOWS_STYLE_SOCKETS
298 WSASetLastError(errorCode);
304 void Socket::HandleError(
const char *operation)
const
307 throw Err(m_s, operation, err);
310 #ifdef USE_WINDOWS_STYLE_SOCKETS
312 SocketReceiver::SocketReceiver(
Socket &s)
313 : m_s(s), m_resultPending(false), m_eofReceived(false)
315 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
316 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
317 memset(&m_overlapped, 0,
sizeof(m_overlapped));
318 m_overlapped.hEvent = m_event;
321 SocketReceiver::~SocketReceiver()
323 #ifdef USE_WINDOWS_STYLE_SOCKETS
324 CancelIo((HANDLE) m_s.GetSocket());
330 assert(!m_resultPending && !m_eofReceived);
334 WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
335 if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
337 if (m_lastResult == 0)
338 m_eofReceived =
true;
342 switch (WSAGetLastError())
345 m_s.CheckAndHandleError_int(
"WSARecv", SOCKET_ERROR);
348 m_eofReceived =
true;
351 m_resultPending =
true;
354 return !m_resultPending;
360 container.AddHandle(m_event,
CallStack(
"SocketReceiver::GetWaitObjects() - result pending", &callStack));
361 else if (!m_eofReceived)
362 container.SetNoWait(
CallStack(
"SocketReceiver::GetWaitObjects() - result ready", &callStack));
365 unsigned int SocketReceiver::GetReceiveResult()
370 if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags))
372 if (m_lastResult == 0)
373 m_eofReceived =
true;
377 switch (WSAGetLastError())
380 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", FALSE);
383 m_eofReceived =
true;
386 m_resultPending =
false;
393 SocketSender::SocketSender(
Socket &s)
394 : m_s(s), m_resultPending(false), m_lastResult(0)
396 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
397 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
398 memset(&m_overlapped, 0,
sizeof(m_overlapped));
399 m_overlapped.hEvent = m_event;
403 SocketSender::~SocketSender()
405 #ifdef USE_WINDOWS_STYLE_SOCKETS
406 CancelIo((HANDLE) m_s.GetSocket());
410 void SocketSender::Send(
const byte* buf,
size_t bufLen)
412 assert(!m_resultPending);
415 WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (
char *)buf};
416 if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
418 m_resultPending =
false;
419 m_lastResult = written;
423 if (WSAGetLastError() != WSA_IO_PENDING)
424 m_s.CheckAndHandleError_int(
"WSASend", SOCKET_ERROR);
426 m_resultPending =
true;
430 void SocketSender::SendEof()
432 assert(!m_resultPending);
433 m_s.ShutDown(SD_SEND);
434 m_s.CheckAndHandleError(
"ResetEvent", ResetEvent(m_event));
435 m_s.CheckAndHandleError_int(
"WSAEventSelect", WSAEventSelect(m_s, m_event, FD_CLOSE));
436 m_resultPending =
true;
439 bool SocketSender::EofSent()
443 WSANETWORKEVENTS events;
444 m_s.CheckAndHandleError_int(
"WSAEnumNetworkEvents", WSAEnumNetworkEvents(m_s, m_event, &events));
445 if ((events.lNetworkEvents & FD_CLOSE) != FD_CLOSE)
446 throw Socket::Err(m_s,
"WSAEnumNetworkEvents (FD_CLOSE not present)", E_FAIL);
447 if (events.iErrorCode[FD_CLOSE_BIT] != 0)
448 throw Socket::Err(m_s,
"FD_CLOSE (via WSAEnumNetworkEvents)", events.iErrorCode[FD_CLOSE_BIT]);
449 m_resultPending =
false;
451 return m_lastResult != 0;
457 container.AddHandle(m_event,
CallStack(
"SocketSender::GetWaitObjects() - result pending", &callStack));
459 container.SetNoWait(
CallStack(
"SocketSender::GetWaitObjects() - result ready", &callStack));
462 unsigned int SocketSender::GetSendResult()
467 BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags);
468 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", result);
469 m_resultPending =
false;
476 #ifdef USE_BERKELEY_STYLE_SOCKETS
478 SocketReceiver::SocketReceiver(
Socket &s)
479 : m_s(s), m_lastResult(0), m_eofReceived(false)
486 container.AddReadFd(m_s,
CallStack(
"SocketReceiver::GetWaitObjects()", &callStack));
491 m_lastResult = m_s.Receive(buf, bufLen);
492 if (bufLen > 0 && m_lastResult == 0)
493 m_eofReceived =
true;
497 unsigned int SocketReceiver::GetReceiveResult()
502 SocketSender::SocketSender(
Socket &s)
503 : m_s(s), m_lastResult(0)
507 void SocketSender::Send(
const byte* buf,
size_t bufLen)
509 m_lastResult = m_s.Send(buf, bufLen);
512 void SocketSender::SendEof()
514 m_s.ShutDown(SD_SEND);
517 unsigned int SocketSender::GetSendResult()
524 container.AddWriteFd(m_s,
CallStack(
"SocketSender::GetWaitObjects()", &callStack));
531 #endif // #ifdef SOCKETS_AVAILABLE