📄 stun.cxx
字号:
{ if (verbose) clog << "received on A1:P2" << endl; recvAltIp = false; recvAltPort = true; ok = getMessage( info.altPortFd, msg, &msgLen, &from.addr, &from.port,verbose ); } else if ( (info.altIpFd!=INVALID_SOCKET) && FD_ISSET(info.altIpFd,&fdSet)) { if (verbose) clog << "received on A2:P1" << endl; recvAltIp = true; recvAltPort = false; ok = getMessage( info.altIpFd, msg, &msgLen, &from.addr, &from.port ,verbose); } else if ( (info.altIpPortFd!=INVALID_SOCKET) && FD_ISSET(info.altIpPortFd, &fdSet)) { if (verbose) clog << "received on A2:P2" << endl; recvAltIp = true; recvAltPort = true; ok = getMessage( info.altIpPortFd, msg, &msgLen, &from.addr, &from.port,verbose ); } else { return true; } int relayPort = 0; if (info.relay) { for (int i=0; i<MAX_MEDIA_RELAYS; ++i) { StunMediaRelay* relay = &info.relays[i]; if (relay->destination.addr == from.addr && relay->destination.port == from.port) { relayPort = relay->relayPort; relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT; break; } } if (relayPort == 0) { for (int i=0; i<MAX_MEDIA_RELAYS; ++i) { StunMediaRelay* relay = &info.relays[i]; if (relay->fd == 0) { if ( verbose ) clog << "Open relay port " << relay->relayPort << endl; relay->fd = openPort(relay->relayPort, info.myAddr.addr, verbose); relay->destination.addr = from.addr; relay->destination.port = from.port; relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT; relayPort = relay->relayPort; break; } } } } if ( !ok ) { if ( verbose ) clog << "Get message did not return a valid message" <<endl; return true; } if ( verbose ) clog << "Got a request (len=" << msgLen << ") from " << from << endl; if ( msgLen <= 0 ) { return true; } bool changePort = false; bool changeIp = false; StunMessage resp; StunAddress4 dest; StunAtrString hmacPassword; hmacPassword.sizeValue = 0; StunAddress4 secondary; secondary.port = 0; secondary.addr = 0; if (info.relay && relayPort) { secondary = from; from.addr = info.myAddr.addr; from.port = relayPort; } ok = stunServerProcessMsg( msg, msgLen, from, secondary, recvAltIp ? info.altAddr : info.myAddr, recvAltIp ? info.myAddr : info.altAddr, &resp, &dest, &hmacPassword, &changePort, &changeIp, verbose ); if ( !ok ) { if ( verbose ) clog << "Failed to parse message" << endl; return true; } char buf[STUN_MAX_MESSAGE_SIZE]; int len = sizeof(buf); len = stunEncodeMessage( resp, buf, len, hmacPassword,verbose ); if ( dest.addr == 0 ) ok=false; if ( dest.port == 0 ) ok=false; if ( ok ) { assert( dest.addr != 0 ); assert( dest.port != 0 ); Socket sendFd; bool sendAltIp = recvAltIp; // send on the received IP address bool sendAltPort = recvAltPort; // send on the received port if ( changeIp ) sendAltIp = !sendAltIp; // if need to change IP, then flip logic if ( changePort ) sendAltPort = !sendAltPort; // if need to change port, then flip logic if ( !sendAltPort ) { if ( !sendAltIp ) { sendFd = info.myFd; } else { sendFd = info.altIpFd; } } else { if ( !sendAltIp ) { sendFd = info.altPortFd; } else { sendFd = info.altIpPortFd; } } if ( sendFd != INVALID_SOCKET ) { sendMessage( sendFd, buf, len, dest.addr, dest.port, verbose ); } } } return true;}int stunFindLocalInterfaces(UInt32* addresses,int maxRet){#if defined(WIN32) || defined(__sparc__) return 0;#else struct ifconf ifc; int s = socket( AF_INET, SOCK_DGRAM, 0 ); int len = 100 * sizeof(struct ifreq); char buf[ len ]; ifc.ifc_len = len; ifc.ifc_buf = buf; int e = ioctl(s,SIOCGIFCONF,&ifc); char *ptr = buf; int tl = ifc.ifc_len; int count=0; while ( (tl > 0) && ( count < maxRet) ) { struct ifreq* ifr = (struct ifreq *)ptr; int si = sizeof(ifr->ifr_name) + sizeof(struct sockaddr); tl -= si; ptr += si; //char* name = ifr->ifr_ifrn.ifrn_name; //cerr << "name = " << name << endl; struct ifreq ifr2; ifr2 = *ifr; e = ioctl(s,SIOCGIFADDR,&ifr2); if ( e == -1 ) { break; } //cerr << "ioctl addr e = " << e << endl; struct sockaddr a = ifr2.ifr_addr; struct sockaddr_in* addr = (struct sockaddr_in*) &a; UInt32 ai = ntohl( addr->sin_addr.s_addr ); if (int((ai>>24)&0xFF) != 127) { addresses[count++] = ai; } #if 0 cerr << "Detected interface " << int((ai>>24)&0xFF) << "." << int((ai>>16)&0xFF) << "." << int((ai>> 8)&0xFF) << "." << int((ai )&0xFF) << endl;#endif } closesocket(s); return count;#endif}voidstunBuildReqSimple( StunMessage* msg, const StunAtrString& username, bool changePort, bool changeIp, unsigned int id ){ assert( msg ); memset( msg , 0 , sizeof(*msg) ); msg->msgHdr.msgType = BindRequestMsg; for ( int i=0; i<16; i=i+4 ) { assert(i+3<16); int r = stunRand(); msg->msgHdr.id.octet[i+0]= r>>0; msg->msgHdr.id.octet[i+1]= r>>8; 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( 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 ); // add some delay so the packets don't get sent too quickly #ifdef WIN32 // !cj! TODO - should fix this up in windows clock_t now = clock(); assert( CLOCKS_PER_SEC == 1000 ); while ( clock() <= now+10 ) { };#else usleep(10*1000);#endif}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);}void stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* sAddr ){ assert( dest.addr != 0 ); assert( dest.port != 0 ); int port = randomPort(); UInt32 interfaceIp=0; if (sAddr) { interfaceIp = sAddr->addr; if ( sAddr->port != 0 ) { port = sAddr->port; } } Socket myFd = openPort(port,interfaceIp,verbose); 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; StunAddress4 from; getMessage( myFd, msg, &msgLen, &from.addr, &from.port,verbose ); 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; }}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 = randomPort(); } UInt32 interfaceIp=0; if (sAddr) { interfaceIp = sAddr->addr; } Socket myFd1 = openPort(port,interfaceIp,verbose); 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; memset(&testImappedAddr,0,sizeof(testImappedAddr)); StunAtrString username; StunAtrString password; username.sizeValue = 0; password.sizeValue = 0; #ifdef USE_TLS stunGetUserNameAndPassword( dest, username, password );#endif //stunSendTest( myFd1, dest, username, password, 1, verbose ); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -