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

📄 stun.cxx

📁 现在应用最广泛的一种私网穿透方式
💻 CXX
📖 第 1 页 / 共 5 页
字号:
static voidstunCreateErrorResponse(StunMessage& response, int cl, int number, const char* msg){   response.msgHdr.msgType = BindErrorResponseMsg;   response.hasErrorCode = true;   response.errorCode.errorClass = cl;   response.errorCode.number = number;   strcpy(response.errorCode.reason, msg);}#if 0static voidstunCreateSharedSecretErrorResponse(StunMessage& response, int cl, int number, const char* msg){   response.msgHdr.msgType = SharedSecretErrorResponseMsg;   response.hasErrorCode = true;   response.errorCode.errorClass = cl;   response.errorCode.number = number;   strcpy(response.errorCode.reason, msg);}#endifstatic voidstunCreateSharedSecretResponse(const StunMessage& request, const StunAddress4& source, StunMessage& response){   response.msgHdr.msgType = SharedSecretResponseMsg;   response.msgHdr.id = request.msgHdr.id;	   response.hasUsername = true;   stunCreateUserName( source, &response.username);	   response.hasPassword = true;   stunCreatePassword( response.username, &response.password);}// This funtion takes a single message sent to a stun server, parses// and constructs an apropriate repsonse - returns true if message is// validboolstunServerProcessMsg( char* buf,                      unsigned int bufLen,                      StunAddress4& from,                       StunAddress4& secondary,                      StunAddress4& myAddr,                      StunAddress4& altAddr,                       StunMessage* resp,                      StunAddress4* destination,                      StunAtrString* hmacPassword,                      bool* changePort,                      bool* changeIp,                      bool verbose){       // set up information for default response 	   memset( resp, 0 , sizeof(*resp) );	   *changeIp = false;   *changePort = false;	   StunMessage req;   bool ok = stunParseMessage( buf,bufLen, req, verbose);	   if (!ok)      // Complete garbage, drop it on the floor   {      if (verbose) clog << "Request did not parse" << endl;      return false;   }   if (verbose) clog << "Request parsed ok" << endl;	   StunAddress4 mapped = req.mappedAddress.ipv4;   StunAddress4 respondTo = req.responseAddress.ipv4;   UInt32 flags = req.changeRequest.value;	   switch (req.msgHdr.msgType)   {      case SharedSecretRequestMsg:         if(verbose) clog << "Received SharedSecretRequestMsg on udp. send error 433." << endl;         // !cj! - should fix so you know if this came over TLS or UDP         stunCreateSharedSecretResponse(req, from, *resp);         //stunCreateSharedSecretErrorResponse(*resp, 4, 33, "this request must be over TLS");         return true;			      case BindRequestMsg:         if (!req.hasMessageIntegrity)         {            if (verbose) clog << "BindRequest does not contain MessageIntegrity" << endl;				            if (0) // !jf! mustAuthenticate            {               if(verbose) clog << "Received BindRequest with no MessageIntegrity. Sending 401." << endl;               stunCreateErrorResponse(*resp, 4, 1, "Missing MessageIntegrity");               return true;            }         }         else         {            if (!req.hasUsername)            {               if (verbose) clog << "No UserName. Send 432." << endl;               stunCreateErrorResponse(*resp, 4, 32, "No UserName and contains MessageIntegrity");               return true;            }            else            {               if (verbose) clog << "Validating username: " << req.username.value << endl;               // !jf! could retrieve associated password from provisioning here               if (strcmp(req.username.value, "test") == 0)               {                  if (0)                  {                     // !jf! if the credentials are stale                      stunCreateErrorResponse(*resp, 4, 30, "Stale credentials on BindRequest");                     return true;                  }                  else                  {                     if (verbose) clog << "Validating MessageIntegrity" << endl;                     // need access to shared secret							                     unsigned char hmac[20];#ifndef NOSSL                     unsigned int hmacSize=20;                     HMAC(EVP_sha1(),                           "1234", 4,                           reinterpret_cast<const unsigned char*>(buf), bufLen-20-4,                           hmac, &hmacSize);                     assert(hmacSize == 20);#endif							                     if (memcmp(buf, hmac, 20) != 0)                     {                        if (verbose) clog << "MessageIntegrity is bad. Sending " << endl;                        stunCreateErrorResponse(*resp, 4, 3, "Unknown username. Try test with password 1234");                        return true;                     }							                     // need to compute this later after message is filled in                     resp->hasMessageIntegrity = true;                     assert(req.hasUsername);                     resp->hasUsername = true;                     resp->username = req.username; // copy username in                  }               }               else               {                  if (verbose) clog << "Invalid username: " << req.username.value << "Send 430." << endl;                }            }         }			         // TODO !jf! should check for unknown attributes here and send 420 listing the         // unknown attributes. 			         if ( respondTo.port == 0 ) respondTo = from;         if ( mapped.port == 0 ) mapped = from;				         *changeIp   = ( flags & ChangeIpFlag )?true:false;         *changePort = ( flags & ChangePortFlag )?true:false;			         if (verbose)         {            clog << "Request is valid:" << endl;            clog << "\t flags=" << flags << endl;            clog << "\t changeIp=" << *changeIp << endl;            clog << "\t changePort=" << *changePort << endl;            clog << "\t from = " << from << endl;            clog << "\t respond to = " << respondTo << endl;            clog << "\t mapped = " << mapped << endl;         }				         // form the outgoing message         resp->msgHdr.msgType = BindResponseMsg;         for ( int i=0; i<16; i++ )         {            resp->msgHdr.id.octet[i] = req.msgHdr.id.octet[i];         }		         if ( req.xorOnly == false )         {            resp->hasMappedAddress = true;            resp->mappedAddress.ipv4.port = mapped.port;            resp->mappedAddress.ipv4.addr = mapped.addr;         }         if (1) // do xorMapped address or not          {            resp->hasXorMappedAddress = true;            UInt16 id16 = req.msgHdr.id.octet[7]<<8                | req.msgHdr.id.octet[6];            UInt32 id32 = req.msgHdr.id.octet[7]<<24                |  req.msgHdr.id.octet[6]<<16                |  req.msgHdr.id.octet[5]<<8                | req.msgHdr.id.octet[4];;            resp->xorMappedAddress.ipv4.port = mapped.port^id16;            resp->xorMappedAddress.ipv4.addr = mapped.addr^id32;         }                  resp->hasSourceAddress = true;         resp->sourceAddress.ipv4.port = (*changePort) ? altAddr.port : myAddr.port;         resp->sourceAddress.ipv4.addr = (*changeIp)   ? altAddr.addr : myAddr.addr;			         resp->hasChangedAddress = true;         resp->changedAddress.ipv4.port = altAddr.port;         resp->changedAddress.ipv4.addr = altAddr.addr;	         if ( secondary.port != 0 )         {            resp->hasSecondaryAddress = true;            resp->secondaryAddress.ipv4.port = secondary.port;            resp->secondaryAddress.ipv4.addr = secondary.addr;         }                  if ( req.hasUsername && req.username.sizeValue > 0 )          {            // copy username in            resp->hasUsername = true;            assert( req.username.sizeValue % 4 == 0 );            assert( req.username.sizeValue < STUN_MAX_STRING );            memcpy( resp->username.value, req.username.value, req.username.sizeValue );            resp->username.sizeValue = req.username.sizeValue;         }		         if (1) // add ServerName          {            resp->hasServerName = true;            const char serverName[] = "Vovida.org " STUN_VERSION; // must pad to mult of 4                        assert( sizeof(serverName) < STUN_MAX_STRING );            //cerr << "sizeof serverName is "  << sizeof(serverName) << endl;            assert( sizeof(serverName)%4 == 0 );            memcpy( resp->serverName.value, serverName, sizeof(serverName));            resp->serverName.sizeValue = sizeof(serverName);         }                  if ( req.hasMessageIntegrity & req.hasUsername )           {            // this creates the password that will be used in the HMAC when then            // messages is sent            stunCreatePassword( req.username, hmacPassword );         }				         if (req.hasUsername && (req.username.sizeValue > 64 ) )         {            UInt32 source;            assert( sizeof(int) == sizeof(UInt32) );					            sscanf(req.username.value, "%x", &source);            resp->hasReflectedFrom = true;            resp->reflectedFrom.ipv4.port = 0;            resp->reflectedFrom.ipv4.addr = source;         }				         destination->port = respondTo.port;         destination->addr = respondTo.addr;			         return true;			      default:         if (verbose) clog << "Unknown or unsupported request " << endl;         return false;   }	   assert(0);   return false;}boolstunInitServer(StunServerInfo& info, const StunAddress4& myAddr, const StunAddress4& altAddr, int startMediaPort, bool verbose ){   assert( myAddr.port != 0 );   assert( altAddr.port!= 0 );   assert( myAddr.addr  != 0 );   //assert( altAddr.addr != 0 );	   info.myAddr = myAddr;   info.altAddr = altAddr;	   info.myFd = INVALID_SOCKET;   info.altPortFd = INVALID_SOCKET;   info.altIpFd = INVALID_SOCKET;   info.altIpPortFd = INVALID_SOCKET;   memset(info.relays, 0, sizeof(info.relays));   if (startMediaPort > 0)   {      info.relay = true;      for (int i=0; i<MAX_MEDIA_RELAYS; ++i)      {         StunMediaRelay* relay = &info.relays[i];         relay->relayPort = startMediaPort+i;         relay->fd = 0;         relay->expireTime = 0;      }   }   else   {      info.relay = false;   }      if ((info.myFd = openPort(myAddr.port, myAddr.addr,verbose)) == INVALID_SOCKET)   {      clog << "Can't open " << myAddr << endl;      stunStopServer(info);      return false;   }   //if (verbose) clog << "Opened " << myAddr.addr << ":" << myAddr.port << " --> " << info.myFd << endl;   if ((info.altPortFd = openPort(altAddr.port,myAddr.addr,verbose)) == INVALID_SOCKET)   {      clog << "Can't open " << myAddr << endl;      stunStopServer(info);      return false;   }   //if (verbose) clog << "Opened " << myAddr.addr << ":" << altAddr.port << " --> " << info.altPortFd << endl;         info.altIpFd = INVALID_SOCKET;   if (  altAddr.addr != 0 )   {      if ((info.altIpFd = openPort( myAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET)      {         clog << "Can't open " << altAddr << endl;         stunStopServer(info);         return false;      }      //if (verbose) clog << "Opened " << altAddr.addr << ":" << myAddr.port << " --> " << info.altIpFd << endl;;   }      info.altIpPortFd = INVALID_SOCKET;   if (  altAddr.addr != 0 )   {  if ((info.altIpPortFd = openPort(altAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET)      {         clog << "Can't open " << altAddr << endl;         stunStopServer(info);         return false;      }      //if (verbose) clog << "Opened " << altAddr.addr << ":" << altAddr.port << " --> " << info.altIpPortFd << endl;;   }      return true;}voidstunStopServer(StunServerInfo& info){   if (info.myFd > 0) closesocket(info.myFd);   if (info.altPortFd > 0) closesocket(info.altPortFd);   if (info.altIpFd > 0) closesocket(info.altIpFd);   if (info.altIpPortFd > 0) closesocket(info.altIpPortFd);      if (info.relay)   {      for (int i=0; i<MAX_MEDIA_RELAYS; ++i)      {         StunMediaRelay* relay = &info.relays[i];         if (relay->fd)         {            closesocket(relay->fd);            relay->fd = 0;         }      }   }}boolstunServerProcess(StunServerInfo& info, bool verbose){   char msg[STUN_MAX_MESSAGE_SIZE];   int msgLen = sizeof(msg);   	   bool ok = false;   bool recvAltIp =false;   bool recvAltPort = false;	   fd_set fdSet; #ifdef WIN32   unsigned int maxFd=0;#else   int maxFd=0;#endif   FD_ZERO(&fdSet);    FD_SET(info.myFd,&fdSet);    if ( info.myFd >= maxFd ) maxFd=info.myFd+1;   FD_SET(info.altPortFd,&fdSet);    if ( info.altPortFd >= maxFd ) maxFd=info.altPortFd+1;   if ( info.altIpFd != INVALID_SOCKET )   {      FD_SET(info.altIpFd,&fdSet);      if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1;   }   if ( info.altIpPortFd != INVALID_SOCKET )   {      FD_SET(info.altIpPortFd,&fdSet);      if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1;   }   if (info.relay)   {      for (int i=0; i<MAX_MEDIA_RELAYS; ++i)      {         StunMediaRelay* relay = &info.relays[i];         if (relay->fd)         {            FD_SET(relay->fd, &fdSet);            if (relay->fd >= maxFd) maxFd=relay->fd+1;         }      }   }      if ( info.altIpFd != INVALID_SOCKET )   {      FD_SET(info.altIpFd,&fdSet);      if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1;   }   if ( info.altIpPortFd != INVALID_SOCKET )   {      FD_SET(info.altIpPortFd,&fdSet);      if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1;   }      struct timeval tv;   tv.tv_sec = 0;   tv.tv_usec = 1000;	   int e = select( maxFd, &fdSet, NULL,NULL, &tv );   if (e < 0)   {      int err = getErrno();      clog << "Error on select: " << strerror(err) << endl;   }   else if (e >= 0)   {      StunAddress4 from;      // do the media relaying      if (info.relay)      {         time_t now = time(0);         for (int i=0; i<MAX_MEDIA_RELAYS; ++i)         {            StunMediaRelay* relay = &info.relays[i];            if (relay->fd)            {               if (FD_ISSET(relay->fd, &fdSet))               {                  char msg[MAX_RTP_MSG_SIZE];                  int msgLen = sizeof(msg);                                    StunAddress4 rtpFrom;                  ok = getMessage( relay->fd, msg, &msgLen, &rtpFrom.addr, &rtpFrom.port ,verbose);                  if (ok)                  {                     sendMessage(info.myFd, msg, msgLen, relay->destination.addr, relay->destination.port, verbose);                     relay->expireTime = now + MEDIA_RELAY_TIMEOUT;                     if ( verbose ) clog << "Relay packet on "                                          << relay->fd                                          << " from " << rtpFrom                                          << " -> " << relay->destination                                          << endl;                  }               }               else if (now > relay->expireTime)               {                  closesocket(relay->fd);                  relay->fd = 0;               }            }         }      }                 if (FD_ISSET(info.myFd,&fdSet))      {         if (verbose) clog << "received on A1:P1" << endl;         recvAltIp = false;         recvAltPort = false;         ok = getMessage( info.myFd, msg, &msgLen, &from.addr, &from.port,verbose );      }      else if (FD_ISSET(info.altPortFd, &fdSet))

⌨️ 快捷键说明

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