📄 winsock.cxx
字号:
for (PINDEX failsafe = 0; failsafe < 1000; failsafe++) { int sz = sizeof(err); if (::getsockopt(os_handle, SOL_SOCKET, SO_ERROR, (char *)&err, &sz) == 0) { if (err != 0) break; } ::Sleep(0); } if (err == 0) err = WSAEFAULT; // Need to have something! } break; case 0 : err = WSAETIMEDOUT; break; default : err = GetLastError(); } if (::ioctlsocket(os_handle, FIONBIO, &fionbio) == SOCKET_ERROR) { if (err == 0) err = GetLastError(); } SetLastError(err); return ConvertOSError(err == 0 ? 0 : SOCKET_ERROR);}BOOL PSocket::os_accept(PSocket & listener, struct sockaddr * addr, int * size){ if (listener.GetReadTimeout() != PMaxTimeInterval) { P_fd_set readfds = listener.GetHandle(); P_timeval tv = listener.GetReadTimeout(); switch (select(0, readfds, NULL, NULL, tv)) { case 1 : break; case 0 : SetLastError(WSAETIMEDOUT); // Then return -1 default : return ConvertOSError(-1); } } return ConvertOSError(os_handle = ::accept(listener.GetHandle(), addr, size));}BOOL PSocket::os_recvfrom(void * buf, PINDEX len, int flags, struct sockaddr * from, PINDEX * fromlen){ lastReadCount = 0; if (readTimeout != PMaxTimeInterval) { DWORD available; if (!ConvertOSError(ioctlsocket(os_handle, FIONREAD, &available), LastReadError)) return FALSE; if (available == 0) { P_fd_set readfds = os_handle; P_timeval tv = readTimeout; int selval = ::select(0, readfds, NULL, NULL, tv); if (!ConvertOSError(selval, LastReadError)) return FALSE; if (selval == 0) return SetErrorValues(Timeout, EAGAIN, LastReadError); if (!ConvertOSError(ioctlsocket(os_handle, FIONREAD, &available), LastReadError)) return FALSE; } if (available > 0 && len > (PINDEX)available) len = available; } int recvResult = ::recvfrom(os_handle, (char *)buf, len, flags, from, fromlen); if (!ConvertOSError(recvResult, LastReadError)) return FALSE; lastReadCount = recvResult; return TRUE;}BOOL PSocket::os_sendto(const void * buf, PINDEX len, int flags, struct sockaddr * to, PINDEX tolen){ lastWriteCount = 0; if (writeTimeout != PMaxTimeInterval) { P_fd_set writefds = os_handle; P_timeval tv = writeTimeout; int selval = ::select(0, NULL, writefds, NULL, tv); if (selval < 0) return FALSE; if (selval == 0) {#ifndef _WIN32_WCE errno = EAGAIN;#else SetLastError(EAGAIN);#endif return FALSE; } } int sendResult = ::sendto(os_handle, (const char *)buf, len, flags, to, tolen); if (!ConvertOSError(sendResult, LastWriteError)) return FALSE; if (sendResult == 0) return FALSE; lastWriteCount = sendResult; return TRUE;}PChannel::Errors PSocket::Select(SelectList & read, SelectList & write, SelectList & except, const PTimeInterval & timeout){ PINDEX i; P_fd_set readfds; for (i = 0; i < read.GetSize(); i++) { if (!read[i].IsOpen()) return NotOpen; readfds += read[i].GetHandle(); } P_fd_set writefds; for (i = 0; i < write.GetSize(); i++) { if (!write[i].IsOpen()) return NotOpen; writefds += write[i].GetHandle(); } P_fd_set exceptfds; for (i = 0; i < except.GetSize(); i++) { if (!except[i].IsOpen()) return NotOpen; exceptfds += except[i].GetHandle(); } P_timeval tval = timeout; int retval = select(INT_MAX, readfds, writefds, exceptfds, tval); Errors lastError; int osError; if (!ConvertOSError(retval, lastError, osError)) return lastError; if (retval > 0) { for (i = 0; i < read.GetSize(); i++) { int h = read[i].GetHandle(); if (h < 0) return Interrupted; if (!readfds.IsPresent(h)) read.RemoveAt(i--); } for (i = 0; i < write.GetSize(); i++) { int h = write[i].GetHandle(); if (h < 0) return Interrupted; if (!writefds.IsPresent(h)) write.RemoveAt(i--); } for (i = 0; i < except.GetSize(); i++) { int h = except[i].GetHandle(); if (h < 0) return Interrupted; if (!exceptfds.IsPresent(h)) except.RemoveAt(i--); } } else { read.RemoveAll(); write.RemoveAll(); except.RemoveAll(); } return NoError;}BOOL PSocket::ConvertOSError(int status, ErrorGroup group){ Errors lastError; int osError; BOOL ok = ConvertOSError(status, lastError, osError); SetErrorValues(lastError, osError, group); return ok;}BOOL PSocket::ConvertOSError(int status, Errors & lastError, int & osError){ if (status >= 0) { lastError = NoError; osError = 0; return TRUE; }#ifdef _WIN32 SetLastError(WSAGetLastError()); return PChannel::ConvertOSError(-2, lastError, osError);#else osError = WSAGetLastError(); switch (osError) { case 0 : lastError = NoError; return TRUE; case WSAEWOULDBLOCK : lastError = Timeout; break; default : osError |= PWIN32ErrorFlag; lastError = Miscellaneous; } return FALSE;#endif}//////////////////////////////////////////////////////////////////////////////// PIPSocket::AddressPIPSocket::Address::Address(BYTE b1, BYTE b2, BYTE b3, BYTE b4){ version = 4; v.four.S_un.S_un_b.s_b1 = b1; v.four.S_un.S_un_b.s_b2 = b2; v.four.S_un.S_un_b.s_b3 = b3; v.four.S_un.S_un_b.s_b4 = b4;}PIPSocket::Address::Address(DWORD dw){ operator=(dw);}PIPSocket::Address & PIPSocket::Address::operator=(DWORD dw){ if (dw == 0) { version = 0; memset(&v, 0, sizeof(v)); } else { version = 4; v.four.S_un.S_addr = dw; } return *this;}PIPSocket::Address::operator DWORD() const{ return version != 4 ? 0 : v.four.S_un.S_addr;}BYTE PIPSocket::Address::Byte1() const{ return v.four.S_un.S_un_b.s_b1;}BYTE PIPSocket::Address::Byte2() const{ return v.four.S_un.S_un_b.s_b2;}BYTE PIPSocket::Address::Byte3() const{ return v.four.S_un.S_un_b.s_b3;}BYTE PIPSocket::Address::Byte4() const{ return v.four.S_un.S_un_b.s_b4;}//////////////////////////////////////////////////////////////////////////////// PIPSocketBOOL P_IsOldWin95(){ static int state = -1; if (state < 0) { state = 1; OSVERSIONINFO info; info.dwOSVersionInfoSize = sizeof(info); if (GetVersionEx(&info)) { state = 0; if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && info.dwBuildNumber < 1000) state = 1; } } return state != 0;}BOOL PIPSocket::IsLocalHost(const PString & hostname){ if (hostname.IsEmpty()) return TRUE; if (hostname *= "localhost") return TRUE; // lookup the host address using inet_addr, assuming it is a "." address PIPSocket::Address addr = hostname; if (addr.IsLoopback()) // Is 127.0.0.1 or ::1 return TRUE; if (addr == 0) { if (!GetHostAddress(hostname, addr)) return FALSE; } // Seb: Should check that it's really IPv4 aware. struct hostent * host_info = ::gethostbyname(GetHostName()); if (P_IsOldWin95()) return addr == *(struct in_addr *)host_info->h_addr_list[0]; for (PINDEX i = 0; host_info->h_addr_list[i] != NULL; i++) {#if P_HAS_IPV6 if (host_info->h_length == 16) { if (addr == *(struct in6_addr *)host_info->h_addr_list[i]) return TRUE; } else#endif if (addr == *(struct in_addr *)host_info->h_addr_list[i]) return TRUE; } return FALSE;}//////////////////////////////////////////////////////////////////////////////// PUDPSocketBOOL PUDPSocket::disableQoS = TRUE;void PUDPSocket::EnableQoS(){ disableQoS = FALSE;}BOOL PUDPSocket::SupportQoS(const PIPSocket::Address &#if P_HAS_QOS address#endif // P_HAS_QOS ){#if P_HAS_QOS if (disableQoS) return FALSE; if (!address.IsValid()) return FALSE; // Check to See if OS supportive OSVERSIONINFO versInfo; ZeroMemory(&versInfo,sizeof(OSVERSIONINFO)); versInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!(GetVersionEx(&versInfo))) return FALSE; else { if (versInfo.dwMajorVersion < 5) return FALSE; // Not Supported in Windows if (versInfo.dwMajorVersion == 5 && versInfo.dwMinorVersion == 0) return FALSE; //Windows 2000 does not always support QOS_DESTADDR } // Need to put in a check to see if the NIC has 802.1p packet priority support // This Requires access to the NIC driver and requires Windows DDK. To Be Done Sometime... // Get the name of the required NIC to check whether it supports 802.1p PString NICname = PIPSocket::GetInterface(address); // For Now Assume it can. return TRUE;#else return FALSE;#endif // P_HAS_QOS}#if P_HAS_QOS#ifndef _WIN32_WCEPWinQoS::~PWinQoS(){ delete sa;}PWinQoS::PWinQoS(PQoS & pqos, struct sockaddr * to, char * inBuf, DWORD & bufLen){ QOS * qos = (QOS *)inBuf; if (pqos.GetTokenRate() == QOS_NOT_SPECIFIED) qos->SendingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT; else qos->SendingFlowspec.ServiceType = pqos.GetServiceType(); qos->SendingFlowspec.TokenRate = pqos.GetTokenRate(); qos->SendingFlowspec.TokenBucketSize = pqos.GetTokenBucketSize(); qos->SendingFlowspec.PeakBandwidth = pqos.GetPeakBandwidth();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -