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 CancelIo((HANDLE) m_s);
00083 CheckAndHandleError_int("closesocket", closesocket(m_s));
00084 #else
00085 CheckAndHandleError_int("close", close(m_s));
00086 #endif
00087 m_s = INVALID_SOCKET;
00088 SocketChanged();
00089 }
00090 }
00091
00092 void Socket::Bind(unsigned int port, const char *addr)
00093 {
00094 sockaddr_in sa;
00095 memset(&sa, 0, sizeof(sa));
00096 sa.sin_family = AF_INET;
00097
00098 if (addr == NULL)
00099 sa.sin_addr.s_addr = htonl(INADDR_ANY);
00100 else
00101 {
00102 unsigned long result = inet_addr(addr);
00103 if (result == -1)
00104 {
00105 SetLastError(SOCKET_EINVAL);
00106 CheckAndHandleError_int("inet_addr", SOCKET_ERROR);
00107 }
00108 sa.sin_addr.s_addr = result;
00109 }
00110
00111 sa.sin_port = htons((u_short)port);
00112
00113 Bind((sockaddr *)&sa, sizeof(sa));
00114 }
00115
00116 void Socket::Bind(const sockaddr *psa, socklen_t saLen)
00117 {
00118 assert(m_s != INVALID_SOCKET);
00119
00120 CheckAndHandleError_int("bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
00121 }
00122
00123 void Socket::Listen(int backlog)
00124 {
00125 assert(m_s != INVALID_SOCKET);
00126 CheckAndHandleError_int("listen", listen(m_s, backlog));
00127 }
00128
00129 bool Socket::Connect(const char *addr, unsigned int port)
00130 {
00131 assert(addr != NULL);
00132
00133 sockaddr_in sa;
00134 memset(&sa, 0, sizeof(sa));
00135 sa.sin_family = AF_INET;
00136 sa.sin_addr.s_addr = inet_addr(addr);
00137
00138 if (sa.sin_addr.s_addr == -1)
00139 {
00140 hostent *lphost = gethostbyname(addr);
00141 if (lphost == NULL)
00142 {
00143 SetLastError(SOCKET_EINVAL);
00144 CheckAndHandleError_int("gethostbyname", SOCKET_ERROR);
00145 }
00146
00147 sa.sin_addr.s_addr = ((in_addr *)lphost->h_addr)->s_addr;
00148 }
00149
00150 sa.sin_port = htons((u_short)port);
00151
00152 return Connect((const sockaddr *)&sa, sizeof(sa));
00153 }
00154
00155 bool Socket::Connect(const sockaddr* psa, socklen_t saLen)
00156 {
00157 assert(m_s != INVALID_SOCKET);
00158 int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
00159 if (result == SOCKET_ERROR && GetLastError() == SOCKET_EWOULDBLOCK)
00160 return false;
00161 CheckAndHandleError_int("connect", result);
00162 return true;
00163 }
00164
00165 bool Socket::Accept(Socket& target, sockaddr *psa, socklen_t *psaLen)
00166 {
00167 assert(m_s != INVALID_SOCKET);
00168 socket_t s = accept(m_s, psa, psaLen);
00169 if (s == INVALID_SOCKET && GetLastError() == SOCKET_EWOULDBLOCK)
00170 return false;
00171 CheckAndHandleError("accept", s);
00172 target.AttachSocket(s, true);
00173 return true;
00174 }
00175
00176 void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
00177 {
00178 assert(m_s != INVALID_SOCKET);
00179 CheckAndHandleError_int("getsockname", getsockname(m_s, psa, psaLen));
00180 }
00181
00182 void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
00183 {
00184 assert(m_s != INVALID_SOCKET);
00185 CheckAndHandleError_int("getpeername", getpeername(m_s, psa, psaLen));
00186 }
00187
00188 unsigned int Socket::Send(const byte* buf, size_t bufLen, int flags)
00189 {
00190 assert(m_s != INVALID_SOCKET);
00191 int result = send(m_s, (const char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
00192 CheckAndHandleError_int("send", result);
00193 return result;
00194 }
00195
00196 unsigned int Socket::Receive(byte* buf, size_t bufLen, int flags)
00197 {
00198 assert(m_s != INVALID_SOCKET);
00199 int result = recv(m_s, (char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
00200 CheckAndHandleError_int("recv", result);
00201 return result;
00202 }
00203
00204 void Socket::ShutDown(int how)
00205 {
00206 assert(m_s != INVALID_SOCKET);
00207 int result = shutdown(m_s, how);
00208 CheckAndHandleError_int("shutdown", result);
00209 }
00210
00211 void Socket::IOCtl(long cmd, unsigned long *argp)
00212 {
00213 assert(m_s != INVALID_SOCKET);
00214 #ifdef USE_WINDOWS_STYLE_SOCKETS
00215 CheckAndHandleError_int("ioctlsocket", ioctlsocket(m_s, cmd, argp));
00216 #else
00217 CheckAndHandleError_int("ioctl", ioctl(m_s, cmd, argp));
00218 #endif
00219 }
00220
00221 bool Socket::SendReady(const timeval *timeout)
00222 {
00223 fd_set fds;
00224 FD_ZERO(&fds);
00225 FD_SET(m_s, &fds);
00226 int ready;
00227 if (timeout == NULL)
00228 ready = select((int)m_s+1, NULL, &fds, NULL, NULL);
00229 else
00230 {
00231 timeval timeoutCopy = *timeout;
00232 ready = select((int)m_s+1, NULL, &fds, NULL, &timeoutCopy);
00233 }
00234 CheckAndHandleError_int("select", ready);
00235 return ready > 0;
00236 }
00237
00238 bool Socket::ReceiveReady(const timeval *timeout)
00239 {
00240 fd_set fds;
00241 FD_ZERO(&fds);
00242 FD_SET(m_s, &fds);
00243 int ready;
00244 if (timeout == NULL)
00245 ready = select((int)m_s+1, &fds, NULL, NULL, NULL);
00246 else
00247 {
00248 timeval timeoutCopy = *timeout;
00249 ready = select((int)m_s+1, &fds, NULL, NULL, &timeoutCopy);
00250 }
00251 CheckAndHandleError_int("select", ready);
00252 return ready > 0;
00253 }
00254
00255 unsigned int Socket::PortNameToNumber(const char *name, const char *protocol)
00256 {
00257 int port = atoi(name);
00258 if (IntToString(port) == name)
00259 return port;
00260
00261 servent *se = getservbyname(name, protocol);
00262 if (!se)
00263 throw Err(INVALID_SOCKET, "getservbyname", SOCKET_EINVAL);
00264 return ntohs(se->s_port);
00265 }
00266
00267 void Socket::StartSockets()
00268 {
00269 #ifdef USE_WINDOWS_STYLE_SOCKETS
00270 WSADATA wsd;
00271 int result = WSAStartup(0x0202, &wsd);
00272 if (result != 0)
00273 throw Err(INVALID_SOCKET, "WSAStartup", result);
00274 #endif
00275 }
00276
00277 void Socket::ShutdownSockets()
00278 {
00279 #ifdef USE_WINDOWS_STYLE_SOCKETS
00280 int result = WSACleanup();
00281 if (result != 0)
00282 throw Err(INVALID_SOCKET, "WSACleanup", result);
00283 #endif
00284 }
00285
00286 int Socket::GetLastError()
00287 {
00288 #ifdef USE_WINDOWS_STYLE_SOCKETS
00289 return WSAGetLastError();
00290 #else
00291 return errno;
00292 #endif
00293 }
00294
00295 void Socket::SetLastError(int errorCode)
00296 {
00297 #ifdef USE_WINDOWS_STYLE_SOCKETS
00298 WSASetLastError(errorCode);
00299 #else
00300 errno = errorCode;
00301 #endif
00302 }
00303
00304 void Socket::HandleError(const char *operation) const
00305 {
00306 int err = GetLastError();
00307 throw Err(m_s, operation, err);
00308 }
00309
00310 #ifdef USE_WINDOWS_STYLE_SOCKETS
00311
00312 SocketReceiver::SocketReceiver(Socket &s)
00313 : m_s(s), m_resultPending(false), m_eofReceived(false)
00314 {
00315 m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
00316 m_s.CheckAndHandleError("CreateEvent", m_event.HandleValid());
00317 memset(&m_overlapped, 0, sizeof(m_overlapped));
00318 m_overlapped.hEvent = m_event;
00319 }
00320
00321 SocketReceiver::~SocketReceiver()
00322 {
00323 #ifdef USE_WINDOWS_STYLE_SOCKETS
00324 CancelIo((HANDLE) m_s.GetSocket());
00325 #endif
00326 }
00327
00328 bool SocketReceiver::Receive(byte* buf, size_t bufLen)
00329 {
00330 assert(!m_resultPending && !m_eofReceived);
00331
00332 DWORD flags = 0;
00333
00334 WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
00335 if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
00336 {
00337 if (m_lastResult == 0)
00338 m_eofReceived = true;
00339 }
00340 else
00341 {
00342 switch (WSAGetLastError())
00343 {
00344 default:
00345 m_s.CheckAndHandleError_int("WSARecv", SOCKET_ERROR);
00346 case WSAEDISCON:
00347 m_lastResult = 0;
00348 m_eofReceived = true;
00349 break;
00350 case WSA_IO_PENDING:
00351 m_resultPending = true;
00352 }
00353 }
00354 return !m_resultPending;
00355 }
00356
00357 void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
00358 {
00359 if (m_resultPending)
00360 container.AddHandle(m_event, CallStack("SocketReceiver::GetWaitObjects() - result pending", &callStack));
00361 else if (!m_eofReceived)
00362 container.SetNoWait(CallStack("SocketReceiver::GetWaitObjects() - result ready", &callStack));
00363 }
00364
00365 unsigned int SocketReceiver::GetReceiveResult()
00366 {
00367 if (m_resultPending)
00368 {
00369 DWORD flags = 0;
00370 if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags))
00371 {
00372 if (m_lastResult == 0)
00373 m_eofReceived = true;
00374 }
00375 else
00376 {
00377 switch (WSAGetLastError())
00378 {
00379 default:
00380 m_s.CheckAndHandleError("WSAGetOverlappedResult", FALSE);
00381 case WSAEDISCON:
00382 m_lastResult = 0;
00383 m_eofReceived = true;
00384 }
00385 }
00386 m_resultPending = false;
00387 }
00388 return m_lastResult;
00389 }
00390
00391
00392
00393 SocketSender::SocketSender(Socket &s)
00394 : m_s(s), m_resultPending(false), m_lastResult(0)
00395 {
00396 m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
00397 m_s.CheckAndHandleError("CreateEvent", m_event.HandleValid());
00398 memset(&m_overlapped, 0, sizeof(m_overlapped));
00399 m_overlapped.hEvent = m_event;
00400 }
00401
00402
00403 SocketSender::~SocketSender()
00404 {
00405 #ifdef USE_WINDOWS_STYLE_SOCKETS
00406 CancelIo((HANDLE) m_s.GetSocket());
00407 #endif
00408 }
00409
00410 void SocketSender::Send(const byte* buf, size_t bufLen)
00411 {
00412 assert(!m_resultPending);
00413 DWORD written = 0;
00414
00415 WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
00416 if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
00417 {
00418 m_resultPending = false;
00419 m_lastResult = written;
00420 }
00421 else
00422 {
00423 if (WSAGetLastError() != WSA_IO_PENDING)
00424 m_s.CheckAndHandleError_int("WSASend", SOCKET_ERROR);
00425
00426 m_resultPending = true;
00427 }
00428 }
00429
00430 void SocketSender::SendEof()
00431 {
00432 assert(!m_resultPending);
00433 m_s.ShutDown(SD_SEND);
00434 m_s.CheckAndHandleError("ResetEvent", ResetEvent(m_event));
00435 m_s.CheckAndHandleError_int("WSAEventSelect", WSAEventSelect(m_s, m_event, FD_CLOSE));
00436 m_resultPending = true;
00437 }
00438
00439 bool SocketSender::EofSent()
00440 {
00441 if (m_resultPending)
00442 {
00443 WSANETWORKEVENTS events;
00444 m_s.CheckAndHandleError_int("WSAEnumNetworkEvents", WSAEnumNetworkEvents(m_s, m_event, &events));
00445 if ((events.lNetworkEvents & FD_CLOSE) != FD_CLOSE)
00446 throw Socket::Err(m_s, "WSAEnumNetworkEvents (FD_CLOSE not present)", E_FAIL);
00447 if (events.iErrorCode[FD_CLOSE_BIT] != 0)
00448 throw Socket::Err(m_s, "FD_CLOSE (via WSAEnumNetworkEvents)", events.iErrorCode[FD_CLOSE_BIT]);
00449 m_resultPending = false;
00450 }
00451 return m_lastResult != 0;
00452 }
00453
00454 void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
00455 {
00456 if (m_resultPending)
00457 container.AddHandle(m_event, CallStack("SocketSender::GetWaitObjects() - result pending", &callStack));
00458 else
00459 container.SetNoWait(CallStack("SocketSender::GetWaitObjects() - result ready", &callStack));
00460 }
00461
00462 unsigned int SocketSender::GetSendResult()
00463 {
00464 if (m_resultPending)
00465 {
00466 DWORD flags = 0;
00467 BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags);
00468 m_s.CheckAndHandleError("WSAGetOverlappedResult", result);
00469 m_resultPending = false;
00470 }
00471 return m_lastResult;
00472 }
00473
00474 #endif
00475
00476 #ifdef USE_BERKELEY_STYLE_SOCKETS
00477
00478 SocketReceiver::SocketReceiver(Socket &s)
00479 : m_s(s), m_lastResult(0), m_eofReceived(false)
00480 {
00481 }
00482
00483 void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
00484 {
00485 if (!m_eofReceived)
00486 container.AddReadFd(m_s, CallStack("SocketReceiver::GetWaitObjects()", &callStack));
00487 }
00488
00489 bool SocketReceiver::Receive(byte* buf, size_t bufLen)
00490 {
00491 m_lastResult = m_s.Receive(buf, bufLen);
00492 if (bufLen > 0 && m_lastResult == 0)
00493 m_eofReceived = true;
00494 return true;
00495 }
00496
00497 unsigned int SocketReceiver::GetReceiveResult()
00498 {
00499 return m_lastResult;
00500 }
00501
00502 SocketSender::SocketSender(Socket &s)
00503 : m_s(s), m_lastResult(0)
00504 {
00505 }
00506
00507 void SocketSender::Send(const byte* buf, size_t bufLen)
00508 {
00509 m_lastResult = m_s.Send(buf, bufLen);
00510 }
00511
00512 void SocketSender::SendEof()
00513 {
00514 m_s.ShutDown(SD_SEND);
00515 }
00516
00517 unsigned int SocketSender::GetSendResult()
00518 {
00519 return m_lastResult;
00520 }
00521
00522 void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
00523 {
00524 container.AddWriteFd(m_s, CallStack("SocketSender::GetWaitObjects()", &callStack));
00525 }
00526
00527 #endif
00528
00529 NAMESPACE_END
00530
00531 #endif // #ifdef SOCKETS_AVAILABLE