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("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, size_t bufLen, int flags)
00182 {
00183 assert(m_s != INVALID_SOCKET);
00184 int result = send(m_s, (const char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
00185 CheckAndHandleError_int("send", result);
00186 return result;
00187 }
00188
00189 unsigned int Socket::Receive(byte* buf, size_t bufLen, int flags)
00190 {
00191 assert(m_s != INVALID_SOCKET);
00192 int result = recv(m_s, (char *)buf, UnsignedMin(INT_MAX, 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((int)m_s+1, NULL, &fds, NULL, NULL);
00222 else
00223 {
00224 timeval timeoutCopy = *timeout;
00225 ready = select((int)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((int)m_s+1, &fds, NULL, NULL, NULL);
00239 else
00240 {
00241 timeval timeoutCopy = *timeout;
00242 ready = select((int)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 bool SocketReceiver::Receive(byte* buf, size_t bufLen)
00315 {
00316 assert(!m_resultPending && !m_eofReceived);
00317
00318 DWORD flags = 0;
00319
00320 WSABUF wsabuf = {UnsignedMin(128U*1024U, bufLen), (char *)buf};
00321 if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
00322 {
00323 if (m_lastResult == 0)
00324 m_eofReceived = true;
00325 }
00326 else
00327 {
00328 switch (WSAGetLastError())
00329 {
00330 default:
00331 m_s.CheckAndHandleError_int("WSARecv", SOCKET_ERROR);
00332 case WSAEDISCON:
00333 m_lastResult = 0;
00334 m_eofReceived = true;
00335 break;
00336 case WSA_IO_PENDING:
00337 m_resultPending = true;
00338 }
00339 }
00340 return !m_resultPending;
00341 }
00342
00343 void SocketReceiver::GetWaitObjects(WaitObjectContainer &container)
00344 {
00345 if (m_resultPending)
00346 container.AddHandle(m_event);
00347 else if (!m_eofReceived)
00348 container.SetNoWait();
00349 }
00350
00351 unsigned int SocketReceiver::GetReceiveResult()
00352 {
00353 if (m_resultPending)
00354 {
00355 DWORD flags = 0;
00356 if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags))
00357 {
00358 if (m_lastResult == 0)
00359 m_eofReceived = true;
00360 }
00361 else
00362 {
00363 switch (WSAGetLastError())
00364 {
00365 default:
00366 m_s.CheckAndHandleError("WSAGetOverlappedResult", FALSE);
00367 case WSAEDISCON:
00368 m_lastResult = 0;
00369 m_eofReceived = true;
00370 }
00371 }
00372 m_resultPending = false;
00373 }
00374 return m_lastResult;
00375 }
00376
00377
00378
00379 SocketSender::SocketSender(Socket &s)
00380 : m_s(s), m_resultPending(false), m_lastResult(0)
00381 {
00382 m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
00383 m_s.CheckAndHandleError("CreateEvent", m_event.HandleValid());
00384 memset(&m_overlapped, 0, sizeof(m_overlapped));
00385 m_overlapped.hEvent = m_event;
00386 }
00387
00388 void SocketSender::Send(const byte* buf, size_t bufLen)
00389 {
00390 DWORD written = 0;
00391
00392 WSABUF wsabuf = {UnsignedMin(128U*1024U, bufLen), (char *)buf};
00393 if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
00394 {
00395 m_resultPending = false;
00396 m_lastResult = written;
00397 }
00398 else
00399 {
00400 if (WSAGetLastError() != WSA_IO_PENDING)
00401 m_s.CheckAndHandleError_int("WSASend", SOCKET_ERROR);
00402
00403 m_resultPending = true;
00404 }
00405 }
00406
00407 void SocketSender::GetWaitObjects(WaitObjectContainer &container)
00408 {
00409 if (m_resultPending)
00410 container.AddHandle(m_event);
00411 else
00412 container.SetNoWait();
00413 }
00414
00415 unsigned int SocketSender::GetSendResult()
00416 {
00417 if (m_resultPending)
00418 {
00419 DWORD flags = 0;
00420 BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags);
00421 m_s.CheckAndHandleError("WSAGetOverlappedResult", result);
00422 m_resultPending = false;
00423 }
00424 return m_lastResult;
00425 }
00426
00427 #endif
00428
00429 #ifdef USE_BERKELEY_STYLE_SOCKETS
00430
00431 SocketReceiver::SocketReceiver(Socket &s)
00432 : m_s(s), m_lastResult(0), m_eofReceived(false)
00433 {
00434 }
00435
00436 void SocketReceiver::GetWaitObjects(WaitObjectContainer &container)
00437 {
00438 if (!m_eofReceived)
00439 container.AddReadFd(m_s);
00440 }
00441
00442 bool SocketReceiver::Receive(byte* buf, size_t bufLen)
00443 {
00444 m_lastResult = m_s.Receive(buf, bufLen);
00445 if (bufLen > 0 && m_lastResult == 0)
00446 m_eofReceived = true;
00447 return true;
00448 }
00449
00450 unsigned int SocketReceiver::GetReceiveResult()
00451 {
00452 return m_lastResult;
00453 }
00454
00455 SocketSender::SocketSender(Socket &s)
00456 : m_s(s), m_lastResult(0)
00457 {
00458 }
00459
00460 void SocketSender::Send(const byte* buf, size_t bufLen)
00461 {
00462 m_lastResult = m_s.Send(buf, bufLen);
00463 }
00464
00465 unsigned int SocketSender::GetSendResult()
00466 {
00467 return m_lastResult;
00468 }
00469
00470 void SocketSender::GetWaitObjects(WaitObjectContainer &container)
00471 {
00472 container.AddWriteFd(m_s);
00473 }
00474
00475 #endif
00476
00477 NAMESPACE_END
00478
00479 #endif // #ifdef SOCKETS_AVAILABLE