//------------------------------------------------------------------------------ // // SetBlocking() // //------------------------------------------------------------------------------ bool TDSocket::SetBlocking(void) { i32 nCurFlags; #if WIN32 nCurFlags = 0; if (ioctlsocket(m_socket, FIONBIO, (ULONG *)&nCurFlags) != 0) { return false; } #else if ((nCurFlags = fcntl(m_socket, F_GETFL)) < 0) { TranslateSocketError(); return false; } nCurFlags &= (~O_NONBLOCK); if (fcntl(m_socket, F_SETFL, nCurFlags) != 0) { TranslateSocketError(); return false; } #endif m_bIsBlocking = true; return true; }
//------------------------------------------------------------------------------ // // SetNonblocking() // //------------------------------------------------------------------------------ bool CSimpleSocket::SetNonblocking(void) { int32 nCurFlags; #if WIN32 nCurFlags = 1; if (ioctlsocket(m_socket, FIONBIO, (ULONG *)&nCurFlags) != 0) { TranslateSocketError(); return false; } #else if ((nCurFlags = fcntl(m_socket, F_GETFL)) < 0) { TranslateSocketError(); return false; } nCurFlags |= O_NONBLOCK; if (fcntl(m_socket, F_SETFL, nCurFlags) != 0) { TranslateSocketError(); return false; } #endif m_bIsBlocking = false; return true; }
//------------------------------------------------------------------------------ // // ConnectUDP() - // //------------------------------------------------------------------------------ bool CActiveSocket::ConnectUDP(const char *pAddr, uint16 nPort) { bool bRetVal = false; struct in_addr stIpAddress; //------------------------------------------------------------------ // Pre-connection setup that must be preformed //------------------------------------------------------------------ memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr)); m_stServerSockaddr.sin_family = AF_INET; if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL) { #ifdef WIN32 TranslateSocketError(); #else if (h_errno == HOST_NOT_FOUND) { SetSocketError(SocketInvalidAddress); } #endif return bRetVal; } memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length); m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr; if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError) { TranslateSocketError(); return bRetVal; } m_stServerSockaddr.sin_port = htons(nPort); //------------------------------------------------------------------ // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only. // //------------------------------------------------------------------ m_timer.Initialize(); m_timer.SetStartTime(); if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError) { bRetVal = true; } TranslateSocketError(); m_timer.SetEndTime(); return bRetVal; }
//------------------------------------------------------------------------------ // // ConnectRAW() - // //------------------------------------------------------------------------------ bool TDSocket::ConnectRAW(const char *pAddr, i16 nPort) { bool bRetVal = false; struct in_addr stIpAddress; //------------------------------------------------------------------ // Pre-connection setup that must be preformed //------------------------------------------------------------------ memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr)); m_stServerSockaddr.sin_family = AF_INET; hostent * pHE = NULL; if ((pHE = GETHOSTBYNAME(pAddr)) == NULL) { #ifdef WIN32 TranslateSocketError(); #else if (h_errno == HOST_NOT_FOUND) { SetSocketError(SocketInvalidAddress); } #endif return bRetVal; } memcpy(&stIpAddress, pHE->h_addr_list[0], pHE->h_length); m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr; if ((i32)m_stServerSockaddr.sin_addr.s_addr == TDSocket::SocketError) { TranslateSocketError(); return bRetVal; } m_stServerSockaddr.sin_port = htons(nPort); //------------------------------------------------------------------ // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only. // //------------------------------------------------------------------ if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != TDSocket::SocketError) { bRetVal = true; } TranslateSocketError(); return bRetVal; }
//------------------------------------------------------------------------------ // // SetReceiveTimeout() // //------------------------------------------------------------------------------ bool TDSocket::SetReceiveTimeout(i32 nRecvTimeoutSec, i32 nRecvTimeoutUsec) { bool bRetVal = true; void* ptimeout = NULL; #if WIN32 int timeout = nRecvTimeoutSec * 1000 + nRecvTimeoutUsec / 1000; ptimeout = &timeout; #else m_stRecvTimeout.tv_sec = nRecvTimeoutSec; m_stRecvTimeout.tv_usec = nRecvTimeoutUsec; ptimeout = &m_stRecvTimeout; #endif //-------------------------------------------------------------------------- // Sanity check to make sure the options are supported! //-------------------------------------------------------------------------- if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_RCVTIMEO, ptimeout, sizeof(struct timeval)) == TDSocket::SocketError) { bRetVal = false; TranslateSocketError(); } return bRetVal; }
//------------------------------------------------------------------------------ // // SendFile() - stands-in for system provided sendfile // //------------------------------------------------------------------------------ i32 TDSocket::SendFile(i32 nOutFd, i32 nInFd, off_t *pOffset, i32 nCount) { i32 nOutCount = TDSocket::SocketError; static char szData[SOCKET_SENDFILE_BLOCKSIZE]; i32 nInCount = 0; if (LSEEK(nInFd, *pOffset, SEEK_SET) == -1) { return -1; } while (nOutCount < nCount) { nInCount = (nCount - nOutCount) < SOCKET_SENDFILE_BLOCKSIZE ? (nCount - nOutCount) : SOCKET_SENDFILE_BLOCKSIZE; if ((READ(nInFd, szData, nInCount)) != (i32)nInCount) { return -1; } if ((SEND(nOutFd, szData, nInCount, 0)) != (i32)nInCount) { return -1; } nOutCount += nInCount; } *pOffset += nOutCount; TranslateSocketError(); return nOutCount; }
//------------------------------------------------------------------------------ // // Close() - Close socket and free up any memory allocated for the socket // //------------------------------------------------------------------------------ bool CSimpleSocket::Close(void) { bool bRetVal = false; //-------------------------------------------------------------------------- // delete internal buffer //-------------------------------------------------------------------------- if (m_pBuffer != NULL) { delete [] m_pBuffer; m_pBuffer = NULL; } //-------------------------------------------------------------------------- // if socket handle is currently valid, close and then invalidate //-------------------------------------------------------------------------- if (IsSocketValid()) { if (CLOSE(m_socket) != CSimpleSocket::SocketError) { m_socket = INVALID_SOCKET; bRetVal = true; } } TranslateSocketError(); return bRetVal; }
//------------------------------------------------------------------------------ // // Send() - Send data on a valid socket // //------------------------------------------------------------------------------ int32 CPassiveSocket::Send(const uint8 *pBuf, size_t bytesToSend) { SetSocketError(SocketSuccess); m_nBytesSent = 0; switch(m_nSocketType) { case CSimpleSocket::SocketTypeUdp: { if (IsSocketValid()) { if ((bytesToSend > 0) && (pBuf != NULL)) { m_timer.Initialize(); m_timer.SetStartTime(); m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stClientSockaddr, sizeof(m_stClientSockaddr)); m_timer.SetEndTime(); if (m_nBytesSent == CSimpleSocket::SocketError) { TranslateSocketError(); } } } break; } default: CSimpleSocket::Send(pBuf, bytesToSend); break; } return m_nBytesSent; }
//------------------------------------------------------------------------------ // // Select() // //------------------------------------------------------------------------------ bool TDSocket::Select(i32 nTimeoutSec, i32 nTimeoutUSec) { bool bRetVal = false; struct timeval *pTimeout = NULL; struct timeval timeout; i32 nNumDescriptors = -1; i32 nError = 0; FD_ZERO(&m_errorFds); FD_ZERO(&m_readFds); FD_ZERO(&m_writeFds); FD_SET(m_socket, &m_errorFds); FD_SET(m_socket, &m_readFds); FD_SET(m_socket, &m_writeFds); //--------------------------------------------------------------------- // If timeout has been specified then set value, otherwise set timeout // to NULL which will block until a descriptor is ready for read/write // or an error has occurred. //--------------------------------------------------------------------- if ((nTimeoutSec >= 0) || (nTimeoutUSec >= 0)) { timeout.tv_sec = nTimeoutSec; timeout.tv_usec = nTimeoutUSec; pTimeout = &timeout; } nNumDescriptors = SELECT(m_socket + 1, &m_readFds, &m_writeFds, &m_errorFds, pTimeout); // nNumDescriptors = SELECT(m_socket+1, &m_readFds, NULL, NULL, pTimeout); //---------------------------------------------------------------------- // Handle timeout //---------------------------------------------------------------------- if (nNumDescriptors == 0) { SetSocketError(TDSocket::SocketTimedout); } //---------------------------------------------------------------------- // If a file descriptor (read/write) is set then check the // socket error (SO_ERROR) to see if there is a pending error. //---------------------------------------------------------------------- else if ((FD_ISSET(m_socket, &m_readFds)) || (FD_ISSET(m_socket, &m_writeFds))) { i32 nLen = sizeof(nError); if (GETSOCKOPT(m_socket, SOL_SOCKET, SO_ERROR, &nError, &nLen) == 0) { errno = nError; if (nError == 0) { bRetVal = true; } } TranslateSocketError(); } return bRetVal; }
//------------------------------------------------------------------------------ // // Shtudown() // //------------------------------------------------------------------------------ bool TDSocket::Shutdown(CShutdownMode nShutdown) { CSocketError nRetVal = SocketEunknown; nRetVal = (CSocketError)shutdown(m_socket, TDSocket::Sends); TranslateSocketError(); return (nRetVal == TDSocket::SocketSuccess) ? true : false; }
//------------------------------------------------------------------------------ // // Send() - Send data on a valid socket via a vector of buffers. // //------------------------------------------------------------------------------ i32 TDSocket::Send(const struct iovec *sendVector, i32 nNumItems) { SetSocketError(SocketSuccess); m_nBytesSent = 0; if ((m_nBytesSent = WRITEV(m_socket, sendVector, nNumItems)) == TDSocket::SocketError) { TranslateSocketError(); } return m_nBytesSent; }
int pgwin32_recv(SOCKET s, char *buf, int len, int f) { WSABUF wbuf; int r; DWORD b; DWORD flags = f; if (pgwin32_poll_signals()) return -1; wbuf.len = len; wbuf.buf = buf; r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL); if (r != SOCKET_ERROR && b > 0) /* Read succeeded right away */ return b; if (r == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) { TranslateSocketError(); return -1; } /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */ if (pgwin32_waitforsinglesocket(s, FD_READ | FD_CLOSE | FD_ACCEPT, INFINITE) == 0) return -1; r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL); if (r == SOCKET_ERROR) { TranslateSocketError(); return -1; } return b; }
/* * Create a socket, setting it to overlapped and non-blocking */ SOCKET pgwin32_socket(int af, int type, int protocol) { SOCKET s; unsigned long on = 1; s = WSASocket(af, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED); if (s == INVALID_SOCKET) { TranslateSocketError(); return INVALID_SOCKET; } if (ioctlsocket(s, FIONBIO, &on)) { TranslateSocketError(); return INVALID_SOCKET; } errno = 0; return s; }
//------------------------------------------------------------------------------ // // Accept() - // //------------------------------------------------------------------------------ CActiveSocket *CPassiveSocket::Accept(uint32_t timeout_sec) { uint32_t nSockLen; std::auto_ptr<CActiveSocket> ClientSocket; SOCKET socket = CSimpleSocket::SocketError; if (m_nSocketType != CSimpleSocket::SocketTypeTcp) { SetSocketError(CSimpleSocket::SocketProtocolError); return 0; } ClientSocket.reset (new CActiveSocket(m_compress_, m_nSocketType)); //-------------------------------------------------------------------------- // Wait for incoming connection. //-------------------------------------------------------------------------- CSocketError socketErrno = SocketSuccess; nSockLen = sizeof(m_stClientSockaddr); do { errno = 0; if (!Select (timeout_sec, 0)) return 0; socket = accept(m_socket, (struct sockaddr *)&m_stClientSockaddr, (socklen_t *)&nSockLen); if (socket != -1) { ClientSocket->SetSocketHandle(socket); ClientSocket->TranslateSocketError(); socketErrno = ClientSocket->GetSocketError(); socklen_t nSockLen = sizeof(struct sockaddr); //------------------------------------------------------------- // Store client and server IP and port information for this // connection. //------------------------------------------------------------- getpeername(m_socket, (struct sockaddr *)&ClientSocket->m_stClientSockaddr, &nSockLen); memcpy((void *)&ClientSocket->m_stClientSockaddr, (void *)&m_stClientSockaddr, nSockLen); memset(&ClientSocket->m_stServerSockaddr, 0, nSockLen); getsockname(m_socket, (struct sockaddr *)&ClientSocket->m_stServerSockaddr, &nSockLen); } else { TranslateSocketError(); socketErrno = GetSocketError(); } } while (socketErrno == CSimpleSocket::SocketInterrupted); if (socketErrno != CSimpleSocket::SocketSuccess) return 0; return ClientSocket.release (); }
int pgwin32_send(SOCKET s, char *buf, int len, int flags) { WSABUF wbuf; int r; DWORD b; if (pgwin32_poll_signals()) return -1; wbuf.len = len; wbuf.buf = buf; r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL); if (r != SOCKET_ERROR && b > 0) /* Write succeeded right away */ return b; if (r == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) { TranslateSocketError(); return -1; } /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */ if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE) == 0) return -1; r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL); if (r == SOCKET_ERROR) { TranslateSocketError(); return -1; } return b; }
//------------------------------------------------------------------------------ // // SetOptionReuseAddr() // //------------------------------------------------------------------------------ bool TDSocket::SetOptionReuseAddr() { bool bRetVal = false; i32 nReuse = IPTOS_LOWDELAY; if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(i32)) == 0) { bRetVal = true; } TranslateSocketError(); return bRetVal; }
int pgwin32_send(SOCKET s, const void *buf, int len, int flags) { WSABUF wbuf; int r; DWORD b; if (pgwin32_poll_signals()) return -1; wbuf.len = len; wbuf.buf = (char *) buf; /* * Readiness of socket to send data to UDP socket may be not true: socket * can become busy again! So loop until send or error occurs. */ for (;;) { r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL); if (r != SOCKET_ERROR && b > 0) /* Write succeeded right away */ return b; if (r == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) { TranslateSocketError(); return -1; } if (pgwin32_noblock) { /* * No data sent, and we are in "emulated non-blocking mode", so * return indicating that we'd block if we were to continue. */ errno = EWOULDBLOCK; return -1; } /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */ if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE, INFINITE) == 0) return -1; } return -1; }
//------------------------------------------------------------------------------ // // SetOptionLinger() // //------------------------------------------------------------------------------ bool TDSocket::SetOptionLinger(bool bEnable, u16 nTime) { bool bRetVal = false; m_stLinger.l_onoff = (bEnable == true) ? 1 : 0; m_stLinger.l_linger = nTime; if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_LINGER, &m_stLinger, sizeof(m_stLinger)) == 0) { bRetVal = true; } TranslateSocketError(); return bRetVal; }
//------------------------------------------------------------------------------ // // EnableNagleAlgorithm() // //------------------------------------------------------------------------------ bool TDSocket::EnableNagleAlgoritm() { bool bRetVal = false; i32 nTcpNoDelay = 0; //---------------------------------------------------------------------- // Set TCP NoDelay flag to false //---------------------------------------------------------------------- if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(i32)) == 0) { bRetVal = true; } TranslateSocketError(); return bRetVal; }
//------------------------------------------------------------------------------ // // GetSocketDscp() // //------------------------------------------------------------------------------ i32 TDSocket::GetSocketDscp(void) { i32 nTempVal = 0; socklen_t nLen = 0; if (IsSocketValid()) { if (GETSOCKOPT(m_socket, IPPROTO_IP, IP_TOS, &nTempVal, &nLen) == SocketError) { TranslateSocketError(); } nTempVal *= 4; nTempVal >>= 4; } return nTempVal; }
SOCKET pgwin32_accept(SOCKET s, struct sockaddr * addr, int *addrlen) { SOCKET rs; /* * Poll for signals, but don't return with EINTR, since we don't handle * that in pqcomm.c */ pgwin32_poll_signals(); rs = WSAAccept(s, addr, addrlen, NULL, 0); if (rs == INVALID_SOCKET) { TranslateSocketError(); return INVALID_SOCKET; } return rs; }
//------------------------------------------------------------------------------ // // Close() - Close socket and free up any memory allocated for the socket // //------------------------------------------------------------------------------ bool CPassiveSocket::Close(void) { if (IsSocketValid()) { if (shutdown(m_socket, CSimpleSocket::Both) != CSimpleSocket::SocketError) { if (CLOSE(m_socket) != CSimpleSocket::SocketError) { m_socket = CSimpleSocket::SocketError; SetSocketError(CSimpleSocket::SocketInvalidSocket); return true; } } } TranslateSocketError(); return false; }
//------------------------------------------------------------------------------ // // SetSocketDscp() // //------------------------------------------------------------------------------ bool TDSocket::SetSocketDscp(i32 nDscp) { bool bRetVal = true; i32 nTempVal = nDscp; nTempVal <<= 4; nTempVal /= 4; if (IsSocketValid()) { if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_TOS, &nTempVal, sizeof(nTempVal)) == SocketError) { TranslateSocketError(); bRetVal = false; } } return bRetVal; }
//------------------------------------------------------------------------------ // // SetWindowSize() // //------------------------------------------------------------------------------ u16 TDSocket::SetWindowSize(u32 nOptionName, u32 nWindowSize) { u32 nRetVal = 0; //------------------------------------------------------------------------- // no socket given, return system default allocate our own new socket //------------------------------------------------------------------------- if (m_socket != TDSocket::SocketError) { nRetVal = SETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nWindowSize, sizeof(nWindowSize)); TranslateSocketError(); } else { SetSocketError(TDSocket::SocketInvalidSocket); } return (u16)nWindowSize; }
int pgwin32_waitforsinglesocket(SOCKET s, int what) { static HANDLE waitevent = INVALID_HANDLE_VALUE; HANDLE events[2]; int r; if (waitevent == INVALID_HANDLE_VALUE) { waitevent = CreateEvent(NULL, TRUE, FALSE, NULL); if (waitevent == INVALID_HANDLE_VALUE) ereport(ERROR, (errmsg_internal("Failed to create socket waiting event: %i", (int) GetLastError()))); } else if (!ResetEvent(waitevent)) ereport(ERROR, (errmsg_internal("Failed to reset socket waiting event: %i", (int) GetLastError()))); if (WSAEventSelect(s, waitevent, what) == SOCKET_ERROR) { TranslateSocketError(); return 0; } events[0] = pgwin32_signal_event; events[1] = waitevent; r = WaitForMultipleObjectsEx(2, events, FALSE, INFINITE, TRUE); if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION) { pgwin32_dispatch_queued_signals(); errno = EINTR; return 0; } if (r == WAIT_OBJECT_0 + 1) return 1; ereport(ERROR, (errmsg_internal("Bad return from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError()))); return 0; }
//------------------------------------------------------------------------------ // // SetSendTimeout() // //------------------------------------------------------------------------------ bool TDSocket::SetSendTimeout(i32 nSendTimeoutSec, i32 nSendTimeoutUsec) { bool bRetVal = true; memset(&m_stSendTimeout, 0, sizeof(struct timeval)); m_stSendTimeout.tv_sec = nSendTimeoutSec; m_stSendTimeout.tv_usec = nSendTimeoutUsec; //-------------------------------------------------------------------------- // Sanity check to make sure the options are supported! //-------------------------------------------------------------------------- if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_SNDTIMEO, &m_stSendTimeout, sizeof(struct timeval)) == TDSocket::SocketError) { bRetVal = false; TranslateSocketError(); } return bRetVal; }
//------------------------------------------------------------------------------ // // Close() - Close socket and free up any memory allocated for the socket // //------------------------------------------------------------------------------ bool TDSocket::Close(void) { bool bRetVal = false; //-------------------------------------------------------------------------- // if socket handle is currently valid, close and then invalidate //-------------------------------------------------------------------------- if (IsSocketValid()) { if (CLOSE(m_socket) != TDSocket::SocketError) { m_socket = INVALID_SOCKET; bRetVal = true; } } m_bIsConnect = false; TranslateSocketError(); return bRetVal; }
//------------------------------------------------------------------------------ // // SetReceiveTimeout() // //------------------------------------------------------------------------------ bool CSimpleSocket::SetReceiveTimeout(int32 nRecvTimeoutSec, int32 nRecvTimeoutUsec) { bool bRetVal = true; memset(&m_stRecvTimeout, 0, sizeof(struct timeval)); m_stRecvTimeout.tv_sec = nRecvTimeoutSec; m_stRecvTimeout.tv_usec = nRecvTimeoutUsec; //-------------------------------------------------------------------------- // Sanity check to make sure the options are supported! //-------------------------------------------------------------------------- if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_RCVTIMEO, &m_stRecvTimeout, sizeof(struct timeval)) == CSimpleSocket::SocketError) { bRetVal = false; TranslateSocketError(); } return bRetVal; }
/* No signal delivery during connect. */ int pgwin32_connect(SOCKET s, const struct sockaddr * addr, int addrlen) { int r; r = WSAConnect(s, addr, addrlen, NULL, NULL, NULL, NULL); if (r == 0) return 0; if (WSAGetLastError() != WSAEWOULDBLOCK) { TranslateSocketError(); return -1; } while (pgwin32_waitforsinglesocket(s, FD_CONNECT, INFINITE) == 0) { /* Loop endlessly as long as we are just delivering signals */ } return 0; }
//------------------------------------------------------------------------------ // // Initialize() - Initialize socket class // //------------------------------------------------------------------------------ bool TDSocket::Initialize() { errno = TDSocket::SocketSuccess; #ifdef WIN32 //------------------------------------------------------------------------- // Data structure containing general Windows Sockets Info //------------------------------------------------------------------------- //memset(&m_hWSAData, 0, sizeof(m_hWSAData)); WSAStartup(MAKEWORD(2, 0), &m_hWSAData); #endif //------------------------------------------------------------------------- // Create the basic Socket Handle //------------------------------------------------------------------------- m_socket = socket(m_nSocketDomain, m_nSocketType, 0); TranslateSocketError(); return (IsSocketValid()); }