Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

# socketft.cpp

    00001 // socketft.cpp - written and placed in the public domain by Wei Dai
    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)       // Solaris doesn't have INADDR_NONE
    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         // cygwin workaround: needs const_cast
    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)   // Solaris doesn't have INADDR_NONE
    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; // select() modified timeout on Linux
    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; // select() modified timeout on Linux
    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 bool SocketReceiver::Receive(byte* buf, unsigned int bufLen)
    00315 {
    00316         assert(!m_resultPending && !m_eofReceived);
    00317
    00318         DWORD flags = 0;
    00319         // don't queue too much at once, or we might use up non-paged memory
    00320         WSABUF wsabuf = {STDMIN(bufLen, 128U*1024U), (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, unsigned int bufLen)
    00389 {
    00390         DWORD written = 0;
    00391         // don't queue too much at once, or we might use up non-paged memory
    00392         WSABUF wsabuf = {STDMIN(bufLen, 128U*1024U), (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, unsigned int 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, unsigned int 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