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