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

📄 stun.cxx

📁 这是国外的resip协议栈
💻 CXX
📖 第 1 页 / 共 5 页
字号:
      msg->msgHdr.id.octet[i+2]= r>>16;      msg->msgHdr.id.octet[i+3]= r>>24;   }	   if ( id != 0 )   {      msg->msgHdr.id.octet[0] = id;    }	   msg->hasChangeRequest = true;   msg->changeRequest.value =(changeIp?ChangeIpFlag:0) |       (changePort?ChangePortFlag:0);	   if ( username.sizeValue > 0 )   {      msg->hasUsername = true;      msg->username = username;   }}static void stunSendTest( resip::Socket myFd, StunAddress4& dest,               const StunAtrString& username, const StunAtrString& password,               int testNum, bool verbose ){    assert( dest.addr != 0 );   assert( dest.port != 0 );	   bool changePort=false;   bool changeIP=false;   bool discard=false;	   switch (testNum)   {      case 1:      case 10:      case 11:         break;      case 2:         //changePort=true;         changeIP=true;         break;      case 3:         changePort=true;         break;      case 4:         changeIP=true;         break;      case 5:         discard=true;         break;      default:         cerr << "Test " << testNum <<" is unkown\n";         assert(0);   }	   StunMessage req;   memset(&req, 0, sizeof(StunMessage));	   stunBuildReqSimple( &req, username,                        changePort , changeIP ,                        testNum );	   char buf[STUN_MAX_MESSAGE_SIZE];   int len = STUN_MAX_MESSAGE_SIZE;	   len = stunEncodeMessage( req, buf, len, password,verbose );	   if ( verbose )   {      clog << "About to send msg of len " << len << " to " << dest << endl;   }	   sendMessage( myFd, buf, len, dest.addr, dest.port, verbose );}void stunGetUserNameAndPassword(  const StunAddress4& dest,                              StunAtrString* username,                             StunAtrString* password){    // !cj! This is totally bogus - need to make TLS connection to dest and get a   // username and password to use    stunCreateUserName(dest, username);   stunCreatePassword(*username, password);}bool stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* sAddr, unsigned long timeoutMs ){    assert( dest.addr != 0 );   assert( dest.port != 0 );	   int port = stunRandomPort();   UInt32 interfaceIp=0;   if (sAddr)   {      interfaceIp = sAddr->addr;      if ( sAddr->port != 0 )      {        port = sAddr->port;      }   }   resip::Socket myFd = openPort(port,interfaceIp,verbose);   if (myFd == INVALID_SOCKET)   {	   return false;   }   // make socket non-blocking   if (!makeSocketNonBlocking(myFd))   {      return false;   }	   StunAtrString username;   StunAtrString password;	   username.sizeValue = 0;   password.sizeValue = 0;	#ifdef USE_TLS   stunGetUserNameAndPassword( dest, username, password );#endif	   stunSendTest( myFd, dest, username, password, testNum, verbose );       char msg[STUN_MAX_MESSAGE_SIZE];   int msgLen = STUN_MAX_MESSAGE_SIZE;	   // Wait to receive a packet   resip::FdSet myFdSet;   myFdSet.setRead(myFd);   if (myFdSet.selectMilliSeconds(timeoutMs) < 1)   {      // no packet received or an error occured      return false;   }   StunAddress4 from;   if (!getMessage(myFd, msg, &msgLen, &from.addr, &from.port, verbose))   {	   closeSocket(myFd);	   return false;   }	   StunMessage resp;   memset(&resp, 0, sizeof(StunMessage));	   if ( verbose ) clog << "Got a response" << endl;   bool ok = stunParseMessage( msg,msgLen, resp,verbose );	   if ( verbose )   {      clog << "\t ok=" << ok << endl;      clog << "\t id=" << resp.msgHdr.id << endl;      clog << "\t mappedAddr=" << resp.mappedAddress.ipv4 << endl;      clog << "\t changedAddr=" << resp.changedAddress.ipv4 << endl;      clog << endl;   }	   if (sAddr)   {      sAddr->port = resp.mappedAddress.ipv4.port;      sAddr->addr = resp.mappedAddress.ipv4.addr;   }   closeSocket(myFd);   return ok;}NatTypestunNatType( StunAddress4& dest,              bool verbose,             bool* preservePort, // if set, is return for if NAT preservers ports or not             bool* hairpin,  // if set, is the return for if NAT will hairpin packets             int port, // port to use for the test, 0 to choose random port             StunAddress4* sAddr // NIC to use    ){    assert( dest.addr != 0 );   assert( dest.port != 0 );	   if ( hairpin )    {      *hairpin = false;   }	   if ( port == 0 )   {      port = stunRandomPort();   }   UInt32 interfaceIp=0;   if (sAddr)   {      interfaceIp = sAddr->addr;   }   resip::Socket myFd1 = openPort(port,interfaceIp,verbose);   resip::Socket myFd2 = openPort(port+1,interfaceIp,verbose);   if ( ( myFd1 == INVALID_SOCKET) || ( myFd2 == INVALID_SOCKET) )   {        cerr << "Some problem opening port/interface to send on" << endl;       return StunTypeFailure;    }   assert( myFd1 != INVALID_SOCKET );   assert( myFd2 != INVALID_SOCKET );       bool respTestI=false;   bool isNat=true;   StunAddress4 testIchangedAddr;   StunAddress4 testImappedAddr;   bool respTestI2=false;    bool mappedIpSame = true;   StunAddress4 testI2mappedAddr;   StunAddress4 testI2dest=dest;   bool respTestII=false;   bool respTestIII=false;   bool respTestHairpin=false;   bool respTestPreservePort=false;	   memset(&testImappedAddr,0,sizeof(testImappedAddr));	   StunAtrString username;   StunAtrString password;	   username.sizeValue = 0;   password.sizeValue = 0;	#ifdef USE_TLS    stunGetUserNameAndPassword( dest, username, password );#endif	   int count=0;   while ( count < 7 )   {      struct timeval tv;      fd_set fdSet; #ifdef WIN32      unsigned int fdSetSize;#else      int fdSetSize;#endif      FD_ZERO(&fdSet); fdSetSize=0;      FD_SET(myFd1,&fdSet); fdSetSize = (myFd1+1>fdSetSize) ? myFd1+1 : fdSetSize;      FD_SET(myFd2,&fdSet); fdSetSize = (myFd2+1>fdSetSize) ? myFd2+1 : fdSetSize;      tv.tv_sec=0;      tv.tv_usec=150*1000; // 150 ms       if ( count == 0 ) tv.tv_usec=0;		      int  err = select(fdSetSize, &fdSet, NULL, NULL, &tv);      int e = getErrno();      if ( err == SOCKET_ERROR )      {         // error occured         cerr << "Error " << e << " " << strerror(e) << " in select" << endl;        return StunTypeFailure;      }      else if ( err == 0 )      {         // timeout occured          count++;			         if ( !respTestI )          {            stunSendTest( myFd1, dest, username, password, 1 ,verbose );         }         			         if ( (!respTestI2) && respTestI )          {            // check the address to send to if valid             if (  ( testI2dest.addr != 0 ) &&                  ( testI2dest.port != 0 ) )            {               stunSendTest( myFd1, testI2dest, username, password, 10  ,verbose);            }         }			         if ( !respTestII )         {            stunSendTest( myFd2, dest, username, password, 2 ,verbose );         }			         if ( !respTestIII )         {            stunSendTest( myFd2, dest, username, password, 3 ,verbose );         }			         if ( respTestI && (!respTestHairpin) )         {            if (  ( testImappedAddr.addr != 0 ) &&                  ( testImappedAddr.port != 0 ) )            {               stunSendTest( myFd1, testImappedAddr, username, password, 11 ,verbose );            }         }      }      else      {         //if (verbose) clog << "-----------------------------------------" << endl;         assert( err>0 );         // data is avialbe on some fd 			         for ( int i=0; i<2; i++)         {            resip::Socket myFd;            if ( i==0 )             {               myFd=myFd1;            }            else            {               myFd=myFd2;            }				            if ( myFd!=INVALID_SOCKET )             {					               if ( FD_ISSET(myFd,&fdSet) )               {                  char msg[STUN_MAX_MESSAGE_SIZE];                  int msgLen = sizeof(msg);                  						                  StunAddress4 from;						                  getMessage( myFd,                              msg,                              &msgLen,                              &from.addr,                              &from.port,verbose );						                  StunMessage resp;                  memset(&resp, 0, sizeof(StunMessage));						                  stunParseMessage( msg,msgLen, resp,verbose );						                  if ( verbose )                  {                     clog << "Received message of type " << resp.msgHdr.msgType                           << "  id=" << (int)(resp.msgHdr.id.octet[0]) << endl;                  }						                  switch( resp.msgHdr.id.octet[0] )                  {                     case 1:                     {                        if ( !respTestI )                        {									                           testIchangedAddr.addr = resp.changedAddress.ipv4.addr;                           testIchangedAddr.port = resp.changedAddress.ipv4.port;                           testImappedAddr.addr = resp.mappedAddress.ipv4.addr;                           testImappedAddr.port = resp.mappedAddress.ipv4.port;			                           respTestPreservePort = ( testImappedAddr.port == port );                            if ( preservePort )                           {                              *preservePort = respTestPreservePort;                           }																	                           testI2dest.addr = resp.changedAddress.ipv4.addr;									                           if (sAddr)                           {                              sAddr->port = testImappedAddr.port;                              sAddr->addr = testImappedAddr.addr;                           }									                           count = 0;                        }		                        respTestI=true;                     }                     break;                     case 2:                     {                          respTestII=true;                     }                     break;                     case 3:                     {                        respTestIII=true;                     }                     break;                     case 10:                     {                        if ( !respTestI2 )                        {                           testI2mappedAddr.addr = resp.mappedAddress.ipv4.addr;                           testI2mappedAddr.port = resp.mappedAddress.ipv4.port;								                           mappedIpSame = false;                           if ( (testI2mappedAddr.addr  == testImappedAddr.addr ) &&                                (testI2mappedAddr.port == testImappedAddr.port ))                           {                               mappedIpSame = true;                           }															                        }                        respTestI2=true;                     }                     break;                     case 11:                     {							                        if ( hairpin )                         {                           *hairpin = true;                        }                        respTestHairpin = true;                     }                     break;                  }               }            }         }      }   }   closeSocket(myFd1);   closeSocket(myFd2);   // see if we can bind to this address    //cerr << "try binding to " << testImappedAddr << endl;   resip::Socket s = openPort( 0/*use ephemeral*/, testImappedAddr.addr, false );   if ( s != INVALID_SOCKET )   {      closeSocket(s);      isNat = false;      //cerr << "binding worked" << endl;   }   else   {      isNat = true;      //cerr << "binding failed" << endl;   }	   if (verbose)   {      clog << "test I = " << respTestI << endl;      clog << "test II = " << respTestII << endl;      clog << "test III = " << respTestIII << endl;      clog << "test I(2) = " << respTestI2 << endl;      clog << "is nat  = " << isNat <<endl;      clog << "mapped IP same = " << mappedIpSame << endl;      clog << "hairpin = " << respTestHairpin << endl;      clog << "preserver port = " << respTestPreservePort << endl;   }	#if 0   // implement logic flow chart from draft RFC   if ( respTestI )   {      if ( isNat )      {         if (respTestII)         {            return StunTypeConeNat;         }         else         {            if ( mappedIpSame )            {               if ( respTestIII )               {                  return StunTypeRestrictedNat;               }               else               {                  return StunTypePortRestrict

⌨️ 快捷键说明

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