Crypto++
|
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 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) // Solaris doesn't have INADDR_NONE 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 // cygwin workaround: needs const_cast 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) // Solaris doesn't have INADDR_NONE 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; // select() modified timeout on Linux 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; // select() modified timeout on Linux 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 // don't queue too much at once, or we might use up non-paged memory 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 // don't queue too much at once, or we might use up non-paged memory 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