⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pstun.cxx

📁 pwlib源码库
💻 CXX
📖 第 1 页 / 共 2 页
字号:
  }};bool PSTUNClient::OpenSocket(PUDPSocket & socket, PortInfo & portInfo) const{  PWaitAndSignal mutex(portInfo.mutex);  WORD startPort = portInfo.currentPort;  do {    portInfo.currentPort++;    if (portInfo.currentPort > portInfo.maxPort)      portInfo.currentPort = portInfo.basePort;    if (socket.Listen(1, portInfo.currentPort)) {      socket.SetSendAddress(serverAddress, serverPort);      socket.SetReadTimeout(replyTimeout);      return true;    }  } while (portInfo.currentPort != startPort);  PTRACE(1, "STUN\tFailed to bind to local UDP port in range "         << portInfo.currentPort << '-' << portInfo.maxPort);  return false;}PSTUNClient::NatTypes PSTUNClient::GetNatType(BOOL force){  if (!force && natType != UnknownNat)    return natType;  PUDPSocket socket;  if (!OpenSocket(socket, singlePortInfo))    return natType = UnknownNat;  // RFC3489 discovery  /* test I - the client sends a STUN Binding Request to a server, without     any flags set in the CHANGE-REQUEST attribute, and without the     RESPONSE-ADDRESS attribute. This causes the server to send the response     back to the address and port that the request came from. */  PSTUNMessage requestI(PSTUNMessage::BindingRequest);  requestI.AddAttribute(PSTUNChangeRequest(false, false));  PSTUNMessage responseI;  if (!responseI.Poll(socket, requestI, pollRetries)) {    if (socket.GetErrorCode(PChannel::LastWriteError) != PChannel::NoError) {      PTRACE(1, "STUN\tError writing to server " << serverAddress << ':' << serverPort << " - " << socket.GetErrorText(PChannel::LastWriteError));      return natType = UnknownNat; // No response usually means blocked    }    PTRACE(3, "STUN\tNo response to server " << serverAddress << ':' << serverPort << " - " << socket.GetErrorText(PChannel::LastReadError));    return natType = BlockedNat; // No response usually means blocked  }  PSTUNMappedAddress * mappedAddress = (PSTUNMappedAddress *)responseI.FindAttribute(PSTUNAttribute::MAPPED_ADDRESS);  if (mappedAddress == NULL) {    PTRACE(2, "STUN\tExpected mapped address attribute from server " << serverAddress << ':' << serverPort);    return natType = UnknownNat; // Protocol error  }  PIPSocket::Address mappedAddressI = mappedAddress->GetIP();  WORD mappedPortI = mappedAddress->port;  bool notNAT = socket.GetPort() == mappedPortI && PIPSocket::IsLocalHost(mappedAddressI);  /* Test II - the client sends a Binding Request with both the "change IP"     and "change port" flags from the CHANGE-REQUEST attribute set. */  PSTUNMessage requestII(PSTUNMessage::BindingRequest);  requestII.AddAttribute(PSTUNChangeRequest(true, true));  PSTUNMessage responseII;  bool testII = responseII.Poll(socket, requestII, pollRetries);  if (notNAT) {    // Is not NAT or symmetric firewall    return natType = (testII ? OpenNat : SymmetricFirewall);  }  if (testII)    return natType = ConeNat;  PSTUNChangedAddress * changedAddress = (PSTUNChangedAddress *)responseI.FindAttribute(PSTUNAttribute::CHANGED_ADDRESS);  if (changedAddress == NULL)    return natType = UnknownNat; // Protocol error  // Send test I to another server, to see if restricted or symmetric  PIPSocket::Address secondaryServer = changedAddress->GetIP();  WORD secondaryPort = changedAddress->port;  socket.SetSendAddress(secondaryServer, secondaryPort);  PSTUNMessage requestI2(PSTUNMessage::BindingRequest);  requestI2.AddAttribute(PSTUNChangeRequest(false, false));  PSTUNMessage responseI2;  if (!responseI2.Poll(socket, requestI2, pollRetries)) {    PTRACE(2, "STUN\tPoll of secondary server " << secondaryServer << ':' << secondaryPort           << " failed, NAT partially blocked by firwall rules.");    return natType = PartialBlockedNat;  }  mappedAddress = (PSTUNMappedAddress *)responseI2.FindAttribute(PSTUNAttribute::MAPPED_ADDRESS);  if (mappedAddress == NULL) {    PTRACE(2, "STUN\tExpected mapped address attribute from server " << serverAddress << ':' << serverPort);    return UnknownNat; // Protocol error  }  if (mappedAddress->port != mappedPortI || mappedAddress->GetIP() != mappedAddressI)    return natType = SymmetricNat;  socket.SetSendAddress(serverAddress, serverPort);  PSTUNMessage requestIII(PSTUNMessage::BindingRequest);  requestIII.SetAttribute(PSTUNChangeRequest(false, true));  PSTUNMessage responseIII;  return natType = (responseIII.Poll(socket, requestIII, pollRetries) ? RestrictedNat : PortRestrictedNat);}PString PSTUNClient::GetNatTypeString(NatTypes type){  static const char * const Names[NumNatTypes] = {    "Unknown NAT",    "Open NAT",    "Cone NAT",    "Restricted NAT",    "Port Restricted NAT",    "Symmetric NAT",    "Symmetric Firewall",    "Blocked",    "Partially Blocked"  };  if (type < NumNatTypes)    return Names[type];    return psprintf("<NATType %u>", type);}PSTUNClient::RTPSupportTypes PSTUNClient::IsSupportingRTP(BOOL force){  switch (GetNatType(force)) {    // types that do support RTP     case OpenNat:    case ConeNat:      return RTPOK;    // types that support RTP if media sent first    case SymmetricFirewall:    case RestrictedNat:    case PortRestrictedNat:      return RTPIfSendMedia;    // types that do not support RTP    case BlockedNat:    case SymmetricNat:      return RTPUnsupported;    // types that have unknown RTP support    case UnknownNat:    case PartialBlockedNat:    default:      break;  }  return RTPUnknown;}BOOL PSTUNClient::GetExternalAddress(PIPSocket::Address & externalAddress,                                     const PTimeInterval & maxAge){  if (cachedExternalAddress.IsValid() && (PTime() - timeAddressObtained > maxAge)) {    externalAddress = cachedExternalAddress;    return TRUE;  }  externalAddress = 0; // Set to invalid address  PUDPSocket socket;  if (!OpenSocket(socket, singlePortInfo))    return false;  PSTUNMessage request(PSTUNMessage::BindingRequest);  request.AddAttribute(PSTUNChangeRequest(false, false));  PSTUNMessage response;  if (!response.Poll(socket, request, pollRetries))  {    PTRACE(1, "STUN\tServer " << serverAddress << ':' << serverPort << " unexpectedly went offline.");    return false;  }  PSTUNMappedAddress * mappedAddress = (PSTUNMappedAddress *)response.FindAttribute(PSTUNAttribute::MAPPED_ADDRESS);  if (mappedAddress == NULL)  {    PTRACE(2, "STUN\tExpected mapped address attribute from server " << serverAddress << ':' << serverPort);    return false;  }    externalAddress = cachedExternalAddress = mappedAddress->GetIP();  timeAddressObtained = PTime();  return true;}BOOL PSTUNClient::CreateSocket(PUDPSocket * & socket){  socket = NULL;  switch (GetNatType(FALSE)) {    case ConeNat :    case RestrictedNat :    case PortRestrictedNat :      break;    case SymmetricNat :      if (singlePortInfo.basePort == 0 || singlePortInfo.basePort > singlePortInfo.maxPort)      {        PTRACE(1, "STUN\tInvalid local UDP port range "               << singlePortInfo.currentPort << '-' << singlePortInfo.maxPort);        return FALSE;      }      break;    default : // UnknownNet, SymmetricFirewall, BlockedNat      PTRACE(1, "STUN\tCannot create socket using NAT type " << GetNatTypeName());      return FALSE;  }  PSTUNUDPSocket * stunSocket = new PSTUNUDPSocket;  if (OpenSocket(*stunSocket, singlePortInfo))  {    PSTUNMessage request(PSTUNMessage::BindingRequest);    request.AddAttribute(PSTUNChangeRequest(false, false));    PSTUNMessage response;    if (response.Poll(*stunSocket, request, pollRetries))    {      PSTUNMappedAddress * mappedAddress = (PSTUNMappedAddress *)response.FindAttribute(PSTUNAttribute::MAPPED_ADDRESS);      if (mappedAddress != NULL)      {        stunSocket->externalIP = mappedAddress->GetIP();        if (GetNatType(FALSE) != SymmetricNat)          stunSocket->port = mappedAddress->port;        stunSocket->SetSendAddress(0, 0);        stunSocket->SetReadTimeout(PMaxTimeInterval);        socket = stunSocket;        return true;      }      PTRACE(2, "STUN\tExpected mapped address attribute from server " << serverAddress << ':' << serverPort);    }    else      PTRACE(1, "STUN\tServer " << serverAddress << ':' << serverPort << " unexpectedly went offline.");  }  delete stunSocket;  return false;}BOOL PSTUNClient::CreateSocketPair(PUDPSocket * & socket1,                                   PUDPSocket * & socket2){  socket1 = NULL;  socket2 = NULL;  switch (GetNatType(FALSE)) {    case ConeNat :    case RestrictedNat :    case PortRestrictedNat :      break;    case SymmetricNat :      if (pairedPortInfo.basePort == 0 || pairedPortInfo.basePort > pairedPortInfo.maxPort)      {        PTRACE(1, "STUN\tInvalid local UDP port range "               << pairedPortInfo.currentPort << '-' << pairedPortInfo.maxPort);        return FALSE;      }      break;    default : // UnknownNet, SymmetricFirewall, BlockedNat      PTRACE(1, "STUN\tCannot create socket pair using NAT type " << GetNatTypeName());      return FALSE;  }  PINDEX i;  PList<PSTUNUDPSocket> stunSocket;  PList<PSTUNMessage> request;  PList<PSTUNMessage> response;  for (i = 0; i < numSocketsForPairing; i++)  {    PINDEX idx = stunSocket.Append(new PSTUNUDPSocket);    if (!OpenSocket(stunSocket[idx], pairedPortInfo))      return false;    idx = request.Append(new PSTUNMessage(PSTUNMessage::BindingRequest));    request[idx].AddAttribute(PSTUNChangeRequest(false, false));    response.Append(new PSTUNMessage);  }  for (i = 0; i < numSocketsForPairing; i++)  {    if (!response[i].Poll(stunSocket[i], request[i], pollRetries))    {      PTRACE(1, "STUN\tServer " << serverAddress << ':' << serverPort << " unexpectedly went offline.");      return false;    }  }  for (i = 0; i < numSocketsForPairing; i++)  {    PSTUNMappedAddress * mappedAddress = (PSTUNMappedAddress *)response[i].FindAttribute(PSTUNAttribute::MAPPED_ADDRESS);    if (mappedAddress == NULL)    {      PTRACE(2, "STUN\tExpected mapped address attribute from server " << serverAddress << ':' << serverPort);      return false;    }    if (GetNatType(FALSE) != SymmetricNat)      stunSocket[i].port = mappedAddress->port;    stunSocket[i].externalIP = mappedAddress->GetIP();  }  for (i = 0; i < numSocketsForPairing; i++)  {    for (PINDEX j = 0; j < numSocketsForPairing; j++)    {      if ((stunSocket[i].port&1) == 0 && (stunSocket[i].port+1) == stunSocket[j].port)      {	stunSocket[i].SetSendAddress(0, 0);	stunSocket[i].SetReadTimeout(PMaxTimeInterval);	stunSocket[j].SetSendAddress(0, 0);	stunSocket[j].SetReadTimeout(PMaxTimeInterval);	socket1 = &stunSocket[i];	socket2 = &stunSocket[j];	stunSocket.DisallowDeleteObjects();	stunSocket.Remove(socket1);	stunSocket.Remove(socket2);	stunSocket.AllowDeleteObjects();	return true;      }    }  }  PTRACE(2, "STUN\tCould not get a pair of adjacent port numbers from NAT");  return false;}BOOL PSTUNClient::IsAvailable() {   switch (GetNatType(FALSE)) {    case ConeNat :    case RestrictedNat :    case PortRestrictedNat :      break;    case SymmetricNat :      if (pairedPortInfo.basePort == 0 || pairedPortInfo.basePort > pairedPortInfo.maxPort)         return FALSE;            break;    default : // UnknownNet, SymmetricFirewall, BlockedNat      return FALSE;  }	  return TRUE; }////////////////////////////////////////////////////////////////PSTUNUDPSocket::PSTUNUDPSocket()  : externalIP(0){}BOOL PSTUNUDPSocket::GetLocalAddress(Address & addr){  if (!externalIP.IsValid())    return PUDPSocket::GetLocalAddress(addr);  addr = externalIP;  return true;}BOOL PSTUNUDPSocket::GetLocalAddress(Address & addr, WORD & port){  if (!externalIP.IsValid())    return PUDPSocket::GetLocalAddress(addr, port);  addr = externalIP;  port = GetPort();  return true;}// End of File ////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -