00001
00002
00003
#include "pch.h"
00004
#include "socketft.h"
00005
00006
#ifdef SOCKETS_AVAILABLE
00007
00008
#include "wait.h"
00009
00010
#ifdef USE_BERKELEY_STYLE_SOCKETS
00011
#include <errno.h>
00012
#include <netdb.h>
00013
#include <unistd.h>
00014
#include <arpa/inet.h>
00015
#include <netinet/in.h>
00016
#include <sys/ioctl.h>
00017
#endif
00018
00019 NAMESPACE_BEGIN(CryptoPP)
00020
00021 #ifdef USE_WINDOWS_STYLE_SOCKETS
00022
const int SOCKET_EINVAL = WSAEINVAL;
00023
const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
00024
typedef int socklen_t;
00025
#else
00026
const int SOCKET_EINVAL = EINVAL;
00027
const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
00028
#endif
00029
00030 Socket::Err::Err(socket_t s,
const std::string& operation,
int error)
00031 :
OS_Error(IO_ERROR, "
Socket: " + operation + " operation failed with error " + IntToString(error), operation, error)
00032 , m_s(s)
00033 {
00034 }
00035
00036 Socket::~Socket()
00037 {
00038
if (m_own)
00039 {
00040
try
00041 {
00042 CloseSocket();
00043 }
00044
catch (...)
00045 {
00046 }
00047 }
00048 }
00049
00050
void Socket::AttachSocket(socket_t s,
bool own)
00051 {
00052
if (m_own)
00053 CloseSocket();
00054
00055 m_s = s;
00056 m_own = own;
00057 SocketChanged();
00058 }
00059
00060 socket_t Socket::DetachSocket()
00061 {
00062 socket_t s = m_s;
00063 m_s = INVALID_SOCKET;
00064 SocketChanged();
00065
return s;
00066 }
00067
00068
void Socket::Create(
int nType)
00069 {
00070 assert(m_s == INVALID_SOCKET);
00071 m_s = socket(AF_INET, nType, 0);
00072 CheckAndHandleError(
"socket", m_s);
00073 m_own =
true;
00074 SocketChanged();
00075 }
00076
00077
void Socket::CloseSocket()
00078 {
00079
if (m_s != INVALID_SOCKET)
00080 {
00081
#ifdef USE_WINDOWS_STYLE_SOCKETS
00082
CheckAndHandleError_int(
"closesocket", closesocket(m_s));
00083
#else
00084
CheckAndHandleError_int(
"close", close(m_s));
00085
#endif
00086
m_s = INVALID_SOCKET;
00087 SocketChanged();
00088 }
00089 }
00090
00091
void Socket::Bind(
unsigned int port,
const char *addr)
00092 {
00093 sockaddr_in sa;
00094 memset(&sa, 0,
sizeof(sa));
00095 sa.sin_family = AF_INET;
00096
00097
if (addr == NULL)
00098 sa.sin_addr.s_addr = htonl(INADDR_ANY);
00099
else
00100 {
00101
unsigned long result = inet_addr(addr);
00102
if (result == -1)
00103 {
00104
SetLastError(SOCKET_EINVAL);
00105 CheckAndHandleError_int(
"inet_addr", SOCKET_ERROR);
00106 }
00107 sa.sin_addr.s_addr = result;
00108 }
00109
00110 sa.sin_port = htons((u_short)port);
00111
00112 Bind((sockaddr *)&sa,
sizeof(sa));
00113 }
00114
00115
void Socket::Bind(
const sockaddr *psa, socklen_t saLen)
00116 {
00117 assert(m_s != INVALID_SOCKET);
00118
00119 CheckAndHandleError_int(
"bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
00120 }
00121
00122
void Socket::Listen(
int backlog)
00123 {
00124 assert(m_s != INVALID_SOCKET);
00125 CheckAndHandleError_int(
"listen", listen(m_s, backlog));
00126 }
00127
00128
bool Socket::Connect(
const char *addr,
unsigned int port)
00129 {
00130 assert(addr != NULL);
00131
00132 sockaddr_in sa;
00133 memset(&sa, 0,
sizeof(sa));
00134 sa.sin_family = AF_INET;
00135 sa.sin_addr.s_addr = inet_addr(addr);
00136
00137
if (sa.sin_addr.s_addr == -1)
00138 {
00139 hostent *lphost = gethostbyname(addr);
00140
if (lphost == NULL)
00141 {
00142
SetLastError(SOCKET_EINVAL);
00143 CheckAndHandleError_int(
"gethostbyname", SOCKET_ERROR);
00144 }
00145
00146 sa.sin_addr.s_addr = ((in_addr *)lphost->h_addr)->s_addr;
00147 }
00148
00149 sa.sin_port = htons((u_short)port);
00150
00151
return Connect((
const sockaddr *)&sa,
sizeof(sa));
00152 }
00153
00154
bool Socket::Connect(
const sockaddr* psa, socklen_t saLen)
00155 {
00156 assert(m_s != INVALID_SOCKET);
00157
int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
00158
if (result == SOCKET_ERROR &&
GetLastError() == SOCKET_EWOULDBLOCK)
00159
return false;
00160 CheckAndHandleError_int(
"connect", result);
00161
return true;
00162 }
00163
00164
bool Socket::Accept(
Socket& target, sockaddr *psa, socklen_t *psaLen)
00165 {
00166 assert(m_s != INVALID_SOCKET);
00167 socket_t s = accept(m_s, psa, psaLen);
00168
if (s == INVALID_SOCKET &&
GetLastError() == SOCKET_EWOULDBLOCK)
00169
return false;
00170 CheckAndHandleError_int(
"accept", s);
00171 target.
AttachSocket(s,
true);
00172
return true;
00173 }
00174
00175
void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
00176 {
00177 assert(m_s != INVALID_SOCKET);
00178 CheckAndHandleError_int(
"getsockname", getsockname(m_s, psa, psaLen));
00179 }
00180
00181
unsigned int Socket::Send(
const byte* buf,
unsigned int bufLen,
int flags)
00182 {
00183 assert(m_s != INVALID_SOCKET);
00184
int result = send(m_s, (
const char *)buf, bufLen, flags);
00185 CheckAndHandleError_int(
"send", result);
00186
return result;
00187 }
00188
00189
unsigned int Socket::Receive(byte* buf,
unsigned int bufLen,
int flags)
00190 {
00191 assert(m_s != INVALID_SOCKET);
00192
int result = recv(m_s, (
char *)buf, bufLen, flags);
00193 CheckAndHandleError_int(
"recv", result);
00194
return result;
00195 }
00196
00197
void Socket::ShutDown(
int how)
00198 {
00199 assert(m_s != INVALID_SOCKET);
00200
int result = shutdown(m_s, how);
00201 CheckAndHandleError_int(
"shutdown", result);
00202 }
00203
00204
void Socket::IOCtl(
long cmd,
unsigned long *argp)
00205 {
00206 assert(m_s != INVALID_SOCKET);
00207
#ifdef USE_WINDOWS_STYLE_SOCKETS
00208
CheckAndHandleError_int(
"ioctlsocket", ioctlsocket(m_s, cmd, argp));
00209
#else
00210
CheckAndHandleError_int(
"ioctl", ioctl(m_s, cmd, argp));
00211
#endif
00212
}
00213
00214
bool Socket::SendReady(
const timeval *timeout)
00215 {
00216 fd_set fds;
00217 FD_ZERO(&fds);
00218 FD_SET(m_s, &fds);
00219
int ready;
00220
if (timeout == NULL)
00221 ready = select(m_s+1, NULL, &fds, NULL, NULL);
00222
else
00223 {
00224 timeval timeoutCopy = *timeout;
00225 ready = select(m_s+1, NULL, &fds, NULL, &timeoutCopy);
00226 }
00227 CheckAndHandleError_int(
"select", ready);
00228
return ready > 0;
00229 }
00230
00231
bool Socket::ReceiveReady(
const timeval *timeout)
00232 {
00233 fd_set fds;
00234 FD_ZERO(&fds);
00235 FD_SET(m_s, &fds);
00236
int ready;
00237
if (timeout == NULL)
00238 ready = select(m_s+1, &fds, NULL, NULL, NULL);
00239
else
00240 {
00241 timeval timeoutCopy = *timeout;
00242 ready = select(m_s+1, &fds, NULL, NULL, &timeoutCopy);
00243 }
00244 CheckAndHandleError_int(
"select", ready);
00245
return ready > 0;
00246 }
00247
00248 unsigned int Socket::PortNameToNumber(
const char *name,
const char *protocol)
00249 {
00250
int port = atoi(name);
00251
if (IntToString(port) == name)
00252
return port;
00253
00254 servent *se = getservbyname(name, protocol);
00255
if (!se)
00256
throw Err(INVALID_SOCKET,
"getservbyname", SOCKET_EINVAL);
00257
return ntohs(se->s_port);
00258 }
00259
00260 void Socket::StartSockets()
00261 {
00262
#ifdef USE_WINDOWS_STYLE_SOCKETS
00263
WSADATA wsd;
00264
int result = WSAStartup(0x0002, &wsd);
00265
if (result != 0)
00266
throw Err(INVALID_SOCKET,
"WSAStartup", result);
00267
#endif
00268
}
00269
00270 void Socket::ShutdownSockets()
00271 {
00272
#ifdef USE_WINDOWS_STYLE_SOCKETS
00273
int result = WSACleanup();
00274
if (result != 0)
00275
throw Err(INVALID_SOCKET,
"WSACleanup", result);
00276
#endif
00277
}
00278
00279 int Socket::GetLastError()
00280 {
00281
#ifdef USE_WINDOWS_STYLE_SOCKETS
00282
return WSAGetLastError();
00283
#else
00284
return errno;
00285
#endif
00286
}
00287
00288 void Socket::SetLastError(
int errorCode)
00289 {
00290
#ifdef USE_WINDOWS_STYLE_SOCKETS
00291
WSASetLastError(errorCode);
00292
#else
00293
errno = errorCode;
00294
#endif
00295
}
00296
00297
void Socket::HandleError(
const char *operation)
const
00298
{
00299
int err =
GetLastError();
00300
throw Err(m_s, operation, err);
00301 }
00302
00303
#ifdef USE_WINDOWS_STYLE_SOCKETS
00304
00305 SocketReceiver::SocketReceiver(
Socket &s)
00306 : m_s(s), m_resultPending(false), m_eofReceived(false)
00307 {
00308 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
00309 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
00310 memset(&m_overlapped, 0,
sizeof(m_overlapped));
00311 m_overlapped.hEvent = m_event;
00312 }
00313
00314
void SocketReceiver::Receive(byte* buf,
unsigned int bufLen)
00315 {
00316 assert(!m_resultPending && !m_eofReceived);
00317
00318 DWORD flags = 0;
00319 WSABUF wsabuf = {bufLen, (
char *)buf};
00320
if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
00321 {
00322
if (m_lastResult == 0)
00323 m_eofReceived =
true;
00324 }
00325
else
00326 {
00327
switch (WSAGetLastError())
00328 {
00329
default:
00330 m_s.CheckAndHandleError_int(
"WSARecv", SOCKET_ERROR);
00331
case WSAEDISCON:
00332 m_lastResult = 0;
00333 m_eofReceived =
true;
00334
break;
00335
case WSA_IO_PENDING:
00336 m_resultPending =
true;
00337 }
00338 }
00339 }
00340
00341
void SocketReceiver::GetWaitObjects(
WaitObjectContainer &container)
00342 {
00343
if (m_resultPending)
00344 container.
AddHandle(m_event);
00345
else if (!m_eofReceived)
00346 container.
SetNoWait();
00347 }
00348
00349
unsigned int SocketReceiver::GetReceiveResult()
00350 {
00351
if (m_resultPending)
00352 {
00353 DWORD flags = 0;
00354
if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags))
00355 {
00356
if (m_lastResult == 0)
00357 m_eofReceived =
true;
00358 }
00359
else
00360 {
00361
switch (WSAGetLastError())
00362 {
00363
default:
00364 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", FALSE);
00365
case WSAEDISCON:
00366 m_lastResult = 0;
00367 m_eofReceived =
true;
00368 }
00369 }
00370 m_resultPending =
false;
00371 }
00372
return m_lastResult;
00373 }
00374
00375
00376
00377 SocketSender::SocketSender(
Socket &s)
00378 : m_s(s), m_resultPending(false), m_lastResult(0)
00379 {
00380 m_event.AttachHandle(CreateEvent(NULL,
true,
false, NULL),
true);
00381 m_s.CheckAndHandleError(
"CreateEvent", m_event.HandleValid());
00382 memset(&m_overlapped, 0,
sizeof(m_overlapped));
00383 m_overlapped.hEvent = m_event;
00384 }
00385
00386
void SocketSender::Send(
const byte* buf,
unsigned int bufLen)
00387 {
00388 DWORD written = 0;
00389 WSABUF wsabuf = {bufLen, (
char *)buf};
00390
if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
00391 {
00392 m_resultPending =
false;
00393 m_lastResult = written;
00394 }
00395
else
00396 {
00397
if (WSAGetLastError() != WSA_IO_PENDING)
00398 m_s.CheckAndHandleError_int(
"WSASend", SOCKET_ERROR);
00399
00400 m_resultPending =
true;
00401 }
00402 }
00403
00404
void SocketSender::GetWaitObjects(
WaitObjectContainer &container)
00405 {
00406
if (m_resultPending)
00407 container.
AddHandle(m_event);
00408
else
00409 container.
SetNoWait();
00410 }
00411
00412
unsigned int SocketSender::GetSendResult()
00413 {
00414
if (m_resultPending)
00415 {
00416 DWORD flags = 0;
00417 BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult,
false, &flags);
00418 m_s.CheckAndHandleError(
"WSAGetOverlappedResult", result);
00419 m_resultPending =
false;
00420 }
00421
return m_lastResult;
00422 }
00423
00424
#endif
00425
00426
#ifdef USE_BERKELEY_STYLE_SOCKETS
00427
00428 SocketReceiver::SocketReceiver(
Socket &s)
00429 : m_s(s), m_lastResult(0), m_eofReceived(false)
00430 {
00431 }
00432
00433
void SocketReceiver::GetWaitObjects(
WaitObjectContainer &container)
00434 {
00435
if (!m_eofReceived)
00436 container.AddReadFd(m_s);
00437 }
00438
00439
void SocketReceiver::Receive(byte* buf,
unsigned int bufLen)
00440 {
00441 m_lastResult = m_s.Receive(buf, bufLen);
00442
if (bufLen > 0 && m_lastResult == 0)
00443 m_eofReceived =
true;
00444 }
00445
00446
unsigned int SocketReceiver::GetReceiveResult()
00447 {
00448
return m_lastResult;
00449 }
00450
00451 SocketSender::SocketSender(
Socket &s)
00452 : m_s(s), m_lastResult(0)
00453 {
00454 }
00455
00456
void SocketSender::Send(
const byte* buf,
unsigned int bufLen)
00457 {
00458 m_lastResult = m_s.Send(buf, bufLen);
00459 }
00460
00461
unsigned int SocketSender::GetSendResult()
00462 {
00463
return m_lastResult;
00464 }
00465
00466
void SocketSender::GetWaitObjects(
WaitObjectContainer &container)
00467 {
00468 container.AddWriteFd(m_s);
00469 }
00470
00471
#endif
00472
00473 NAMESPACE_END
00474
00475
#endif // #ifdef SOCKETS_AVAILABLE