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
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
error reported by the operating system
static void ShutdownSockets()
calls WSACleanup for Windows Sockets
exception thrown by Socket class
static void StartSockets()
start Windows Sockets 2
static void SetLastError(int errorCode)
sets errno or calls WSASetLastError
wrapper for Windows or Berkeley Sockets
bool Receive(byte *buf, size_t bufLen)
receive data from network source, returns whether result is immediately available ...
void GetWaitObjects(WaitObjectContainer &container, CallStack const &callStack)
put wait objects into container
static int GetLastError()
returns errno or WSAGetLastError
void GetWaitObjects(WaitObjectContainer &container, CallStack const &callStack)
put wait objects into container