📄 socket.cxx
字号:
SelectList & write, SelectList & except, const PTimeInterval & timeout){ PINDEX i, j; PINDEX nextfd = 0; int maxfds = 0; Errors lastError = NoError; PThread * unblockThread = PThread::Current(); P_fd_set fds[3]; SelectList * list[3] = { &read, &write, &except }; for (i = 0; i < 3; i++) { for (j = 0; j < list[i]->GetSize(); j++) { PSocket & socket = (*list[i])[j]; if (!socket.IsOpen()) lastError = NotOpen; else { int h = socket.GetHandle(); fds[i] += h; if (h > maxfds) maxfds = h; } socket.px_selectMutex.Wait(); socket.px_selectThread = unblockThread; } } if (lastError == NoError) { P_timeval tval = timeout; int result = ::select(maxfds+1, (fd_set *)fds[0], (fd_set *)fds[1], (fd_set *)fds[2], tval); int osError; (void)ConvertOSError(result, lastError, osError); } for (i = 0; i < 3; i++) { for (j = 0; j < list[i]->GetSize(); j++) { PSocket & socket = (*list[i])[j]; socket.px_selectThread = NULL; socket.px_selectMutex.Signal(); if (lastError == NoError) { int h = socket.GetHandle(); if (h < 0) lastError = Interrupted; else if (!fds[i].IsPresent(h)) list[i]->RemoveAt(j--); } } } return lastError;} #elsePChannel::Errors PSocket::Select(SelectList & read, SelectList & write, SelectList & except, const PTimeInterval & timeout){ PINDEX i, j; int maxfds = 0; Errors lastError = NoError; PThread * unblockThread = PThread::Current(); int unblockPipe = unblockThread->unblockPipe[0]; P_fd_set fds[3]; SelectList * list[3] = { &read, &write, &except }; for (i = 0; i < 3; i++) { for (j = 0; j < list[i]->GetSize(); j++) { PSocket & socket = (*list[i])[j]; if (!socket.IsOpen()) lastError = NotOpen; else { int h = socket.GetHandle(); fds[i] += h; if (h > maxfds) maxfds = h; } socket.px_selectMutex.Wait(); socket.px_selectThread = unblockThread; } } int result = -1; if (lastError == NoError) { fds[0] += unblockPipe; if (unblockPipe > maxfds) maxfds = unblockPipe; P_timeval tval = timeout; do { result = ::select(maxfds+1, (fd_set *)fds[0], (fd_set *)fds[1], (fd_set *)fds[2], tval); } while (result < 0 && errno == EINTR); int osError; if (ConvertOSError(result, lastError, osError)) { if (fds[0].IsPresent(unblockPipe)) { PTRACE(6, "PWLib\tSelect unblocked fd=" << unblockPipe); BYTE ch; ::read(unblockPipe, &ch, 1); lastError = Interrupted; } } } for (i = 0; i < 3; i++) { for (j = 0; j < list[i]->GetSize(); j++) { PSocket & socket = (*list[i])[j]; socket.px_selectThread = NULL; socket.px_selectMutex.Signal(); if (lastError == NoError) { int h = socket.GetHandle(); if (h < 0) lastError = Interrupted; else if (!fds[i].IsPresent(h)) list[i]->RemoveAt(j--); } } } return lastError;}#endifPIPSocket::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_addr = dw; } return *this;}PIPSocket::Address::operator DWORD() const{ return version != 4 ? 0 : (DWORD)v.four.s_addr;}BYTE PIPSocket::Address::Byte1() const{ return *(((BYTE *)&v.four.s_addr)+0);}BYTE PIPSocket::Address::Byte2() const{ return *(((BYTE *)&v.four.s_addr)+1);}BYTE PIPSocket::Address::Byte3() const{ return *(((BYTE *)&v.four.s_addr)+2);}BYTE PIPSocket::Address::Byte4() const{ return *(((BYTE *)&v.four.s_addr)+3);}PIPSocket::Address::Address(BYTE b1, BYTE b2, BYTE b3, BYTE b4){ version = 4; BYTE * p = (BYTE *)&v.four.s_addr; p[0] = b1; p[1] = b2; p[2] = b3; p[3] = b4;}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 Address addr = hostname; if (addr.IsLoopback()) // Is 127.0.0.1 return TRUE; if (!addr.IsValid()) return FALSE; if (!GetHostAddress(hostname, addr)) return FALSE;#ifdef P_HAS_IPV6 { FILE * file; int dummy; int addr6[16]; char ifaceName[9]; BOOL found = FALSE; if ((file = fopen("/proc/net/if_inet6", "r")) != NULL) { while (!found && (fscanf(file, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %02x %02x %02x %02x %8s\n", &addr6[0], &addr6[1], &addr6[2], &addr6[3], &addr6[4], &addr6[5], &addr6[6], &addr6[7], &addr6[8], &addr6[9], &addr6[10], &addr6[11], &addr6[12], &addr6[13], &addr6[14], &addr6[15], &dummy, &dummy, &dummy, &dummy, ifaceName) != EOF)) { Address ip6addr( psprintf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", addr6[0], addr6[1], addr6[2], addr6[3], addr6[4], addr6[5], addr6[6], addr6[7], addr6[8], addr6[9], addr6[10], addr6[11], addr6[12], addr6[13], addr6[14], addr6[15] ) ); found = (ip6addr *= addr); } fclose(file); } if (found) return TRUE; }#endif PUDPSocket sock; // check IPV4 addresses int ifNum;#ifdef SIOCGIFNUM PAssert(::ioctl(sock.GetHandle(), SIOCGIFNUM, &ifNum) >= 0, "could not do ioctl for ifNum");#else ifNum = 100;#endif PBYTEArray buffer; struct ifconf ifConf; ifConf.ifc_len = ifNum * sizeof(ifreq); ifConf.ifc_req = (struct ifreq *)buffer.GetPointer(ifConf.ifc_len); if (ioctl(sock.GetHandle(), SIOCGIFCONF, &ifConf) >= 0) {#ifndef SIOCGIFNUM ifNum = ifConf.ifc_len / sizeof(ifreq);#endif int num = 0; for (num = 0; num < ifNum; num++) { ifreq * ifName = ifConf.ifc_req + num; struct ifreq ifReq; strcpy(ifReq.ifr_name, ifName->ifr_name); if (ioctl(sock.GetHandle(), SIOCGIFFLAGS, &ifReq) >= 0) { int flags = ifReq.ifr_flags; if (ioctl(sock.GetHandle(), SIOCGIFADDR, &ifReq) >= 0) { if ((flags & IFF_UP) && (addr *= Address(((sockaddr_in *)&ifReq.ifr_addr)->sin_addr))) return TRUE; } } } } return FALSE;}//////////////////////////////////////////////////////////////////// PTCPSocket//BOOL PTCPSocket::Read(void * buf, PINDEX maxLen){ lastReadCount = 0; // wait until select indicates there is data to read, or until // a timeout occurs if (!PXSetIOBlock(PXReadBlock, readTimeout)) return FALSE; // attempt to read out of band data char buffer[32]; int ooblen; while ((ooblen = ::recv(os_handle, buffer, sizeof(buffer), MSG_OOB)) > 0) OnOutOfBand(buffer, ooblen); // attempt to read non-out of band data int r = ::recv(os_handle, (char *)buf, maxLen, 0); if (!ConvertOSError(r, LastReadError)) return FALSE; lastReadCount = r; return lastReadCount > 0;}#if P_HAS_RECVMSGint PSocket::os_recvfrom( void * buf, // Data to be written as URGENT TCP data. PINDEX len, // Number of bytes pointed to by <CODE>buf</CODE>. int flags, sockaddr * addr, // Address from which the datagram was received. PINDEX * addrlen){ lastReadCount = 0; if (!PXSetIOBlock(PXReadBlock, readTimeout)) return FALSE; // if we don't care what interface the packet arrives on, then don't bother getting the information if (!catchReceiveToAddr) { int r = ::recvfrom(os_handle, (char *)buf, len, flags, (sockaddr *)addr, (socklen_t *)addrlen); if (!ConvertOSError(r, LastReadError)) return FALSE; lastReadCount = r; return lastReadCount > 0; } msghdr readData; memset(&readData, 0, sizeof(readData)); readData.msg_name = addr; readData.msg_namelen = *addrlen; iovec readVector; readVector.iov_base = buf; readVector.iov_len = len; readData.msg_iov = &readVector; readData.msg_iovlen = 1; char auxdata[50]; readData.msg_control = auxdata; readData.msg_controllen = sizeof(auxdata); // read a packet int r = ::recvmsg(os_handle, &readData, 0); if (!ConvertOSError(r, LastReadError)) return FALSE; lastReadCount = r; if (r >= 0) { struct cmsghdr * cmsg; for (cmsg = CMSG_FIRSTHDR(&readData); cmsg != NULL; cmsg = CMSG_NXTHDR(&readData,cmsg)) { if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) { in_pktinfo * info = (in_pktinfo *)CMSG_DATA(cmsg); SetLastReceiveAddr(&info->ipi_spec_dst, sizeof(in_addr)); break; } } } return lastReadCount > 0;}#elseBOOL PSocket::os_recvfrom( void * buf, // Data to be written as URGENT TCP data. PINDEX len, // Number of bytes pointed to by <CODE>buf</CODE>. int flags, sockaddr * addr, // Address from which the datagram was received. PINDEX * addrlen){ lastReadCount = 0; if (!PXSetIOBlock(PXReadBlock, readTimeout)) return FALSE; // attempt to read non-out of band data int r = ::recvfrom(os_handle, (char *)buf, len, flags, (sockaddr *)addr, (socklen_t *)addrlen); if (!ConvertOSError(r, LastReadError)) return FALSE; lastReadCount = r; return lastReadCount > 0;}#endifBOOL PSocket::os_sendto( const void * buf, // Data to be written as URGENT TCP data. PINDEX len, // Number of bytes pointed to by <CODE>buf</CODE>. int flags, sockaddr * addr, // Address to which the datagram is sent. PINDEX addrlen) { lastWriteCount = 0; if (!IsOpen()) return SetErrorValues(NotOpen, EBADF, LastWriteError); // attempt to read data int result; for (;;) { if (addr != NULL) result = ::sendto(os_handle, (char *)buf, len, flags, (sockaddr *)addr, addrlen); else result = ::send(os_handle, (char *)buf, len, flags); if (result > 0) break; if (errno != EWOULDBLOCK) return ConvertOSError(-1, LastWriteError); if (!PXSetIOBlock(PXWriteBlock, writeTimeout)) return FALSE; }#if !defined(P_PTHREADS) && !defined(P_MAC_MPTHREADS) PThread::Yield(); // Starvation prevention#endif lastWriteCount = result; return ConvertOSError(0, LastWriteError);}BOOL PSocket::Read(void * buf, PINDEX len){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF, LastReadError); if (!PXSetIOBlock(PXReadBlock, readTimeout)) return FALSE; if (ConvertOSError(lastReadCount = ::recv(os_handle, (char *)buf, len, 0))) return lastReadCount > 0; lastReadCount = 0; return FALSE;}////////////////////////////////////////////////////////////////////// PEthSocket//PEthSocket::PEthSocket(PINDEX, PINDEX, PINDEX){ medium = MediumUnknown; filterMask = FilterDirected|FilterBroadcast; filterType = TypeAll; fakeMacHeader = FALSE; ipppInterface = FALSE;}PEthSocket::~PEthSocket(){ Close();}BOOL PEthSocket::Connect(const PString & interfaceName){ Close(); fakeMacHeader = FALSE; ipppInterface = FALSE; if (strncmp("eth", interfaceName, 3) == 0) medium = Medium802_3; else if (strncmp("lo", interfaceName, 2) == 0) medium = MediumLoop; else if (strncmp("sl", interfaceName, 2) == 0) { medium = MediumWan; fakeMacHeader = TRUE; } else if (strncmp("ppp", interfaceName, 3) == 0) { medium = MediumWan; fakeMacHeader = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -