📄 stun.cxx
字号:
ptr = encode16(ptr, 6 + atr.sizeReason); ptr = encode16(ptr, atr.pad); *ptr++ = atr.errorClass; *ptr++ = atr.number; ptr = encode(ptr, atr.reason, atr.sizeReason); return ptr;}static char* encodeAtrUnknown(char* ptr, const StunAtrUnknown& atr){ ptr = encode16(ptr, UnknownAttribute); ptr = encode16(ptr, 2+2*atr.numAttributes); for (int i=0; i<atr.numAttributes; i++) { ptr = encode16(ptr, atr.attrType[i]); } return ptr;}static char* encodeXorOnly(char* ptr){ ptr = encode16(ptr, XorOnly ); return ptr;}static char* encodeAtrString(char* ptr, UInt16 type, const StunAtrString& atr){ assert(atr.sizeValue % 4 == 0); ptr = encode16(ptr, type); ptr = encode16(ptr, atr.sizeValue); ptr = encode(ptr, atr.value, atr.sizeValue); return ptr;}static char* encodeAtrIntegrity(char* ptr, const StunAtrIntegrity& atr){ ptr = encode16(ptr, MessageIntegrity); ptr = encode16(ptr, 20); ptr = encode(ptr, atr.hash, sizeof(atr.hash)); return ptr;}unsigned intstunEncodeMessage( const StunMessage& msg, char* buf, unsigned int bufLen, const StunAtrString& password, bool verbose){ assert(bufLen >= sizeof(StunMsgHdr)); char* ptr = buf; ptr = encode16(ptr, msg.msgHdr.msgType); char* lengthp = ptr; ptr = encode16(ptr, 0); ptr = encode(ptr, reinterpret_cast<const char*>(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id)); if (verbose) clog << "Encoding stun message: " << endl; if (msg.hasMappedAddress) { if (verbose) clog << "Encoding MappedAddress: " << msg.mappedAddress.ipv4 << endl; ptr = encodeAtrAddress4 (ptr, MappedAddress, msg.mappedAddress); } if (msg.hasResponseAddress) { if (verbose) clog << "Encoding ResponseAddress: " << msg.responseAddress.ipv4 << endl; ptr = encodeAtrAddress4(ptr, ResponseAddress, msg.responseAddress); } if (msg.hasChangeRequest) { if (verbose) clog << "Encoding ChangeRequest: " << msg.changeRequest.value << endl; ptr = encodeAtrChangeRequest(ptr, msg.changeRequest); } if (msg.hasSourceAddress) { if (verbose) clog << "Encoding SourceAddress: " << msg.sourceAddress.ipv4 << endl; ptr = encodeAtrAddress4(ptr, SourceAddress, msg.sourceAddress); } if (msg.hasChangedAddress) { if (verbose) clog << "Encoding ChangedAddress: " << msg.changedAddress.ipv4 << endl; ptr = encodeAtrAddress4(ptr, ChangedAddress, msg.changedAddress); } if (msg.hasUsername) { if (verbose) clog << "Encoding Username: " << msg.username.value << endl; ptr = encodeAtrString(ptr, Username, msg.username); } if (msg.hasPassword) { if (verbose) clog << "Encoding Password: " << msg.password.value << endl; ptr = encodeAtrString(ptr, Password, msg.password); } if (msg.hasErrorCode) { if (verbose) clog << "Encoding ErrorCode: class=" << int(msg.errorCode.errorClass) << " number=" << int(msg.errorCode.number) << " reason=" << msg.errorCode.reason << endl; ptr = encodeAtrError(ptr, msg.errorCode); } if (msg.hasUnknownAttributes) { if (verbose) clog << "Encoding UnknownAttribute: ???" << endl; ptr = encodeAtrUnknown(ptr, msg.unknownAttributes); } if (msg.hasReflectedFrom) { if (verbose) clog << "Encoding ReflectedFrom: " << msg.reflectedFrom.ipv4 << endl; ptr = encodeAtrAddress4(ptr, ReflectedFrom, msg.reflectedFrom); } if (msg.hasXorMappedAddress) { if (verbose) clog << "Encoding XorMappedAddress: " << msg.xorMappedAddress.ipv4 << endl; ptr = encodeAtrAddress4 (ptr, XorMappedAddress, msg.xorMappedAddress); } if (msg.xorOnly) { if (verbose) clog << "Encoding xorOnly: " << endl; ptr = encodeXorOnly( ptr ); } if (msg.hasServerName) { if (verbose) clog << "Encoding ServerName: " << msg.serverName.value << endl; ptr = encodeAtrString(ptr, ServerName, msg.serverName); } if (msg.hasSecondaryAddress) { if (verbose) clog << "Encoding SecondaryAddress: " << msg.secondaryAddress.ipv4 << endl; ptr = encodeAtrAddress4 (ptr, SecondaryAddress, msg.secondaryAddress); } if (password.sizeValue > 0) { if (verbose) clog << "HMAC with password: " << password.value << endl; StunAtrIntegrity integrity; computeHmac(integrity.hash, buf, int(ptr-buf) , password.value, password.sizeValue); ptr = encodeAtrIntegrity(ptr, integrity); } if (verbose) clog << endl; encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr))); return int(ptr - buf);}int stunRand(){ // return 32 bits of random stuff assert( sizeof(int) == 4 ); static bool init=false; if ( !init ) { init = true; UInt64 tick; #if defined(WIN32) volatile unsigned int lowtick=0,hightick=0; __asm { rdtsc mov lowtick, eax mov hightick, edx } tick = hightick; tick <<= 32; tick |= lowtick;#elif defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) ) asm("rdtsc" : "=A" (tick));#elif defined (__SUNPRO_CC) || defined( __sparc__ ) tick = gethrtime();#elif defined(__MACH__) int fd=open("/dev/random",O_RDONLY); read(fd,&tick,sizeof(tick)); closesocket(fd);#else# error Need some way to seed the random number generator #endif int seed = int(tick);#ifdef WIN32 srand(seed);#else srandom(seed);#endif } #ifdef WIN32 assert( RAND_MAX == 0x7fff ); int r1 = rand(); int r2 = rand(); int ret = (r1<<16) + r2; return ret;#else return random(); #endif}/// return a random number to use as a port static intrandomPort(){ int min=0x4000; int max=0x7FFF; int ret = stunRand(); ret = ret|min; ret = ret&max; return ret;}#ifdef NOSSLstatic voidcomputeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey){ strncpy(hmac,"hmac-not-implemented",20);}#else#include <openssl/hmac.h>static voidcomputeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey){ unsigned int resultSize=0; HMAC(EVP_sha1(), key, sizeKey, reinterpret_cast<const unsigned char*>(input), length, reinterpret_cast<unsigned char*>(hmac), &resultSize); assert(resultSize == 20);}#endifstatic voidtoHex(const char* buffer, int bufferSize, char* output) { static char hexmap[] = "0123456789abcdef"; const char* p = buffer; char* r = output; for (int i=0; i < bufferSize; i++) { unsigned char temp = *p++; int hi = (temp & 0xf0)>>4; int low = (temp & 0xf); *r++ = hexmap[hi]; *r++ = hexmap[low]; } *r = 0;}voidstunCreateUserName(const StunAddress4& source, StunAtrString* username){ UInt64 time = stunGetSystemTimeSecs(); time -= (time % 20*60); //UInt64 hitime = time >> 32; UInt64 lotime = time & 0xFFFFFFFF; char buffer[1024]; sprintf(buffer, "%08x:%08x:%08x:", UInt32(source.addr), UInt32(stunRand()), UInt32(lotime)); assert( strlen(buffer) < 1024 ); assert(strlen(buffer) + 41 < STUN_MAX_STRING); char hmac[20]; char key[] = "Jason"; computeHmac(hmac, buffer, strlen(buffer), key, strlen(key) ); char hmacHex[41]; toHex(hmac, 20, hmacHex ); hmacHex[40] =0; strcat(buffer,hmacHex); int l = strlen(buffer); assert( l+1 < STUN_MAX_STRING ); assert( l%4 == 0 ); username->sizeValue = l; memcpy(username->value,buffer,l); username->value[l]=0; //if (verbose) clog << "computed username=" << username.value << endl;}voidstunCreatePassword(const StunAtrString& username, StunAtrString* password){ char hmac[20]; char key[] = "Fluffy"; //char buffer[STUN_MAX_STRING]; computeHmac(hmac, username.value, strlen(username.value), key, strlen(key)); toHex(hmac, 20, password->value); password->sizeValue = 40; password->value[40]=0; //clog << "password=" << password->value << endl;}UInt64stunGetSystemTimeSecs(){ UInt64 time=0;#if defined(WIN32) SYSTEMTIME t; // CJ TODO - this probably has bug on wrap around every 24 hours GetSystemTime( &t ); time = (t.wHour*60+t.wMinute)*60+t.wSecond; #else struct timeval now; gettimeofday( &now , NULL ); //assert( now ); time = now.tv_sec;#endif return time;}ostream& operator<< ( ostream& strm, const UInt128& r ){ strm << int(r.octet[0]); for ( int i=1; i<16; i++ ) { strm << ':' << int(r.octet[i]); } return strm;}ostream& operator<<( ostream& strm, const StunAddress4& addr){ UInt32 ip = addr.addr; strm << ((int)(ip>>24)&0xFF) << "."; strm << ((int)(ip>>16)&0xFF) << "."; strm << ((int)(ip>> 8)&0xFF) << "."; strm << ((int)(ip>> 0)&0xFF) ; strm << ":" << addr.port; return strm;}// returns true if it scucceededbool stunParseHostName( char* peerName, UInt32& ip, UInt16& portVal, UInt16 defaultPort ){ in_addr sin_addr; char host[512]; strncpy(host,peerName,512); host[512-1]='\0'; char* port = NULL; int portNum = defaultPort; // pull out the port part if present. char* sep = strchr(host,':'); if ( sep == NULL ) { portNum = defaultPort; } else { *sep = '\0'; port = sep + 1; // set port part char* endPtr=NULL; portNum = strtol(port,&endPtr,10); if ( endPtr != NULL ) { if ( *endPtr != '\0' ) { portNum = defaultPort; } } } if ( portNum < 1024 ) return false; if ( portNum >= 0xFFFF ) return false; // figure out the host part struct hostent* h; #ifdef WIN32 assert( strlen(host) >= 1 ); if ( isdigit( host[0] ) ) { // assume it is a ip address unsigned long a = inet_addr(host); //cerr << "a=0x" << hex << a << dec << endl; ip = ntohl( a ); } else { // assume it is a host name h = gethostbyname( host ); if ( h == NULL ) { int err = getErrno(); std::cerr << "error was " << err << std::endl; assert( err != WSANOTINITIALISED ); ip = ntohl( 0x7F000001L ); return false; } else { sin_addr = *(struct in_addr*)h->h_addr; ip = ntohl( sin_addr.s_addr ); } } #else h = gethostbyname( host ); if ( h == NULL ) { int err = getErrno(); std::cerr << "error was " << err << std::endl; ip = ntohl( 0x7F000001L ); return false; } else { sin_addr = *(struct in_addr*)h->h_addr; ip = ntohl( sin_addr.s_addr ); }#endif portVal = portNum; return true;}boolstunParseServerName( char* name, StunAddress4& addr){ assert(name); // TODO - put in DNS SRV stuff. bool ret = stunParseHostName( name, addr.addr, addr.port, 3478); if ( ret != true ) { addr.port=0xFFFF; } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -