Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound 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 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