|
reSIProcate/rutil
9694
|
#include <cassert>#include <cstring>#include <iostream>#include <cstdlib>#include <errno.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/types.h>#include <arpa/inet.h>#include <fcntl.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/nameser.h>#include <resolv.h>#include <net/if.h>#include "Udp.hxx"#include "Stun.hxx"#include "rutil/Socket.hxx"#include "rutil/WinLeakCheck.hxx"
Go to the source code of this file.
Functions | |
| static bool | stunParseAtrAddress (char *body, unsigned int hdrLen, StunAtrAddress4 &result) |
| static bool | stunParseUInt32 (char *body, unsigned int hdrLen, UInt32 &result) |
| static bool | stunParseAtrChangeRequest (char *body, unsigned int hdrLen, StunAtrChangeRequest &result) |
| static bool | stunParseAtrError (char *body, unsigned int hdrLen, StunAtrError &result) |
| static bool | stunParseAtrUnknown (char *body, unsigned int hdrLen, StunAtrUnknown &result) |
| static bool | stunParseAtrString (char *body, unsigned int hdrLen, StunAtrString &result) |
| static bool | stunParseAtrIntegrity (char *body, unsigned int hdrLen, StunAtrIntegrity &result) |
| bool | stunParseMessage (char *buf, unsigned int bufLen, StunMessage &msg, bool verbose) |
| static char * | encode16 (char *buf, UInt16 data) |
| static char * | encode32 (char *buf, UInt32 data) |
| static char * | encode (char *buf, const char *data, unsigned int length) |
| static char * | encodeTurnData (char *ptr, const resip::Data *td) |
| static char * | encodeAtrUInt32 (char *ptr, UInt16 type, UInt32 value) |
| static char * | encodeAtrAddress4 (char *ptr, UInt16 type, const StunAtrAddress4 &atr) |
| static char * | encodeAtrChangeRequest (char *ptr, const StunAtrChangeRequest &atr) |
| static char * | encodeMagicCookie (char *ptr, const UInt32 &cookie) |
| static char * | encodeAtrError (char *ptr, const StunAtrError &atr) |
| static char * | encodeAtrUnknown (char *ptr, const StunAtrUnknown &atr) |
| static char * | encodeXorOnly (char *ptr) |
| static char * | encodeAtrString (char *ptr, UInt16 type, const StunAtrString &atr) |
| static char * | encodeAtrIntegrity (char *ptr, const StunAtrIntegrity &atr) |
| unsigned int | stunEncodeMessage (const StunMessage &msg, char *buf, unsigned int bufLen, const StunAtrString &password, bool verbose) |
| int | stunRand () |
| int | stunRandomPort () |
| return a random number to use as a port | |
| void | computeHmac (char *hmac, const char *input, int length, const char *key, int sizeKey) |
| static void | toHex (const char *buffer, int bufferSize, char *output) |
| void | stunCreateUserName (const StunAddress4 &source, StunAtrString *username) |
| void | stunCreatePassword (const StunAtrString &username, StunAtrString *password) |
| UInt64 | stunGetSystemTimeSecs () |
| ostream & | operator<< (ostream &strm, const UInt128 &r) |
| ostream & | operator<< (ostream &strm, const StunAddress4 &addr) |
| ostream & | operator<< (ostream &os, const StunMsgHdr &h) |
| bool | stunParseHostName (char *peerName, UInt32 &ip, UInt16 &portVal, UInt16 defaultPort) |
| bool | stunParseServerName (char *name, StunAddress4 &addr) |
| find the IP address of a the specified stun server - return false is fails parse | |
| static void | stunCreateErrorResponse (StunMessage &response, int cl, int number, const char *msg) |
| static void | stunCreateSharedSecretResponse (const StunMessage &request, const StunAddress4 &source, StunMessage &response) |
| bool | stunServerProcessMsg (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) |
| bool | stunInitServer (StunServerInfo &info, const StunAddress4 &myAddr, const StunAddress4 &altAddr, int startMediaPort, bool verbose) |
| return true if all is OK Create a media relay and do the STERN thing if startMediaPort is non-zero | |
| void | stunStopServer (StunServerInfo &info) |
| bool | stunServerProcess (StunServerInfo &info, bool verbose) |
| return true if all is OK | |
| int | stunFindLocalInterfaces (UInt32 *addresses, int maxRet) |
| returns number of address found - take array or addres | |
| void | stunBuildReqSimple (StunMessage *msg, const StunAtrString &username, bool changePort, bool changeIp, unsigned int id) |
| static void | stunSendTest (resip::Socket myFd, StunAddress4 &dest, const StunAtrString &username, const StunAtrString &password, int testNum, bool verbose) |
| void | stunGetUserNameAndPassword (const StunAddress4 &dest, StunAtrString *username, StunAtrString *password) |
| bool | stunTest (StunAddress4 &dest, int testNum, bool verbose, StunAddress4 *sAddr, unsigned long timeoutMs) |
| NatType | stunNatType (StunAddress4 &dest, bool verbose, bool *preservePort, bool *hairpin, int port, StunAddress4 *sAddr) |
| int | stunOpenSocket (StunAddress4 &dest, StunAddress4 *mapAddr, int port, StunAddress4 *srcAddr, bool verbose) |
| bool | stunOpenSocketPair (StunAddress4 &dest, StunAddress4 *mapAddr, int *fd1, int *fd2, int port, StunAddress4 *srcAddr, bool verbose) |
| bool | operator< (const UInt128 &lhs, const UInt128 &rhs) |
| bool | operator== (const UInt128 &lhs, const UInt128 &rhs) |
| bool | operator< (const StunMsgHdr &lhs, const StunMsgHdr &rhs) |
| void computeHmac | ( | char * | hmac, |
| const char * | input, | ||
| int | length, | ||
| const char * | key, | ||
| int | sizeKey | ||
| ) |
Definition at line 881 of file Stun.cxx.
Referenced by stunCreatePassword(), stunCreateUserName(), and stunEncodeMessage().
{
strncpy(hmac,"hmac-not-implemented",20);
}
| static char* encode | ( | char * | buf, |
| const char * | data, | ||
| unsigned int | length | ||
| ) | [static] |
Definition at line 536 of file Stun.cxx.
Referenced by encodeAtrError(), encodeAtrIntegrity(), encodeAtrString(), main(), and stunEncodeMessage().
{
memcpy(buf, data, length);
return buf + length;
}
| static char* encode16 | ( | char * | buf, |
| UInt16 | data | ||
| ) | [static] |
Definition at line 519 of file Stun.cxx.
Referenced by encodeAtrAddress4(), encodeAtrChangeRequest(), encodeAtrError(), encodeAtrIntegrity(), encodeAtrString(), encodeAtrUInt32(), encodeAtrUnknown(), encodeMagicCookie(), encodeTurnData(), encodeXorOnly(), and stunEncodeMessage().
| static char* encode32 | ( | char * | buf, |
| UInt32 | data | ||
| ) | [static] |
Definition at line 527 of file Stun.cxx.
Referenced by encodeAtrAddress4(), encodeAtrChangeRequest(), encodeAtrUInt32(), and encodeMagicCookie().
| static char* encodeAtrAddress4 | ( | char * | ptr, |
| UInt16 | type, | ||
| const StunAtrAddress4 & | atr | ||
| ) | [static] |
Definition at line 563 of file Stun.cxx.
References StunAddress4::addr, encode16(), encode32(), StunAtrAddress4::ipv4, IPv4Family, StunAtrAddress4::pad, and StunAddress4::port.
Referenced by stunEncodeMessage().
{
ptr = encode16(ptr, type);
ptr = encode16(ptr, 8);
*ptr++ = atr.pad;
*ptr++ = IPv4Family;
ptr = encode16(ptr, atr.ipv4.port);
ptr = encode32(ptr, atr.ipv4.addr);
return ptr;
}

| static char* encodeAtrChangeRequest | ( | char * | ptr, |
| const StunAtrChangeRequest & | atr | ||
| ) | [static] |
Definition at line 576 of file Stun.cxx.
References ChangeRequest, encode16(), encode32(), and StunAtrChangeRequest::value.
Referenced by stunEncodeMessage().
{
ptr = encode16(ptr, ChangeRequest);
ptr = encode16(ptr, 4);
ptr = encode32(ptr, atr.value);
return ptr;
}

| static char* encodeAtrError | ( | char * | ptr, |
| const StunAtrError & | atr | ||
| ) | [static] |
Definition at line 595 of file Stun.cxx.
References encode(), encode16(), StunAtrError::errorClass, ErrorCode, StunAtrError::number, StunAtrError::pad, StunAtrError::reason, and StunAtrError::sizeReason.
Referenced by stunEncodeMessage().
{
ptr = encode16(ptr, ErrorCode);
ptr = encode16(ptr, 4 + atr.sizeReason);
ptr = encode16(ptr, atr.pad);
*ptr++ = atr.errorClass;
*ptr++ = atr.number;
ptr = encode(ptr, atr.reason, atr.sizeReason);
return ptr;
}

| static char* encodeAtrIntegrity | ( | char * | ptr, |
| const StunAtrIntegrity & | atr | ||
| ) | [static] |
Definition at line 641 of file Stun.cxx.
References encode(), encode16(), StunAtrIntegrity::hash, and MessageIntegrity.
Referenced by stunEncodeMessage().
{
ptr = encode16(ptr, MessageIntegrity);
ptr = encode16(ptr, 20);
ptr = encode(ptr, atr.hash, sizeof(atr.hash));
return ptr;
}

| static char* encodeAtrString | ( | char * | ptr, |
| UInt16 | type, | ||
| const StunAtrString & | atr | ||
| ) | [static] |
Definition at line 629 of file Stun.cxx.
References encode(), encode16(), StunAtrString::sizeValue, and StunAtrString::value.
Referenced by stunEncodeMessage().
{
assert(atr.sizeValue % 4 == 0);
ptr = encode16(ptr, type);
ptr = encode16(ptr, atr.sizeValue);
ptr = encode(ptr, atr.value, atr.sizeValue);
return ptr;
}

Definition at line 554 of file Stun.cxx.
References encode16(), and encode32().
Referenced by stunEncodeMessage().

| static char* encodeAtrUnknown | ( | char * | ptr, |
| const StunAtrUnknown & | atr | ||
| ) | [static] |
Definition at line 608 of file Stun.cxx.
References StunAtrUnknown::attrType, encode16(), StunAtrUnknown::numAttributes, and UnknownAttribute.
Referenced by stunEncodeMessage().
{
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* encodeMagicCookie | ( | char * | ptr, |
| const UInt32 & | cookie | ||
| ) | [static] |
Definition at line 585 of file Stun.cxx.
References encode16(), encode32(), and TurnMagicCookie.
Referenced by stunEncodeMessage().
{
ptr = encode16(ptr, TurnMagicCookie);
ptr = encode16(ptr, 4);
ptr = encode32(ptr, cookie);
return ptr;
}

| static char* encodeTurnData | ( | char * | ptr, |
| const resip::Data * | td | ||
| ) | [static] |
Definition at line 543 of file Stun.cxx.
References resip::Data::data(), encode16(), resip::Data::size(), and TurnData.
Referenced by stunEncodeMessage().
{
ptr = encode16(ptr, TurnData);
ptr = encode16(ptr, (UInt16)td->size());
memcpy(ptr, td->data(), td->size());
ptr += td->size();
return ptr;
}

| static char* encodeXorOnly | ( | char * | ptr | ) | [static] |
Definition at line 621 of file Stun.cxx.
References encode16(), and XorOnly.
Referenced by stunEncodeMessage().

| bool operator< | ( | const StunMsgHdr & | lhs, |
| const StunMsgHdr & | rhs | ||
| ) |
| ostream& operator<< | ( | ostream & | strm, |
| const UInt128 & | r | ||
| ) |
Definition at line 999 of file Stun.cxx.
References UInt128::octet.
| ostream& operator<< | ( | ostream & | strm, |
| const StunAddress4 & | addr | ||
| ) |
Definition at line 1011 of file Stun.cxx.
References StunAddress4::addr, and StunAddress4::port.
| ostream& operator<< | ( | ostream & | os, |
| const StunMsgHdr & | h | ||
| ) |
Definition at line 1025 of file Stun.cxx.
References BindErrorResponseMsg, BindRequestMsg, BindResponseMsg, StunMsgHdr::id, StunMsgHdr::msgType, UInt128::octet, TurnAllocateErrorResponse, TurnAllocateRequest, TurnAllocateResponse, TurnDataIndication, TurnSendErrorResponse, TurnSendRequest, TurnSendResponse, TurnSetActiveDestinationErrorResponse, TurnSetActiveDestinationRequest, and TurnSetActiveDestinationResponse.
{
os << "STUN: ";
switch (h.msgType) {
case BindRequestMsg:
os << "BindingRequest";
break;
case BindResponseMsg:
os << "BindingResponse";
break;
case BindErrorResponseMsg:
os << "BindingErrorResponse";
break;
case TurnAllocateRequest:
os << "TurnAllocateRequest";
break;
case TurnAllocateResponse:
os << "TurnAllocateResponse";
break;
case TurnAllocateErrorResponse:
os << "TurnAllocateErrorResponse";
break;
case TurnSendRequest:
os << "TurnSendRequest";
break;
case TurnSendResponse:
os << "TurnSendResponse";
break;
case TurnSendErrorResponse:
os << "TurnSendErrorResponse";
break;
case TurnDataIndication:
os << "TurnDataIndication";
break;
case TurnSetActiveDestinationRequest:
os << "TurnSetActiveDestinationRequest";
break;
case TurnSetActiveDestinationResponse:
os << "TurnSetActiveDestinationResponse";
break;
case TurnSetActiveDestinationErrorResponse:
os << "TurnSetActiveDestinationErrorResponse";
break;
}
os << ", id ";
os << std::hex;
for (unsigned int i = 0; i < sizeof(UInt128); i++) {
os << static_cast<int>(h.id.octet[i]);
}
os << std::dec;
return os;
}
| void stunBuildReqSimple | ( | StunMessage * | msg, |
| const StunAtrString & | username, | ||
| bool | changePort, | ||
| bool | changeIp, | ||
| unsigned int | id | ||
| ) |
Definition at line 1916 of file Stun.cxx.
References BindRequestMsg, ChangeIpFlag, ChangePortFlag, StunMessage::changeRequest, StunMessage::hasChangeRequest, StunMessage::hasUsername, StunMsgHdr::id, StunMessage::msgHdr, StunMsgHdr::msgType, UInt128::octet, StunAtrString::sizeValue, stunRand(), StunMessage::username, and StunAtrChangeRequest::value.
Referenced by stunSendTest().
{
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 stunCreateErrorResponse | ( | StunMessage & | response, |
| int | cl, | ||
| int | number, | ||
| const char * | msg | ||
| ) | [static] |
Definition at line 1200 of file Stun.cxx.
References BindErrorResponseMsg, StunAtrError::errorClass, StunMessage::errorCode, StunMessage::hasErrorCode, StunMessage::msgHdr, StunMsgHdr::msgType, StunAtrError::number, StunAtrError::reason, and StunAtrError::sizeReason.
Referenced by stunServerProcessMsg().
{
response.msgHdr.msgType = BindErrorResponseMsg;
response.hasErrorCode = true;
response.errorCode.errorClass = cl;
response.errorCode.number = number;
strcpy(response.errorCode.reason, msg);
response.errorCode.sizeReason = (UInt16)strlen(msg);
}
| void stunCreatePassword | ( | const StunAtrString & | username, |
| StunAtrString * | password | ||
| ) |
Definition at line 966 of file Stun.cxx.
References computeHmac(), StunAtrString::sizeValue, toHex(), and StunAtrString::value.
Referenced by stunCreateSharedSecretResponse(), stunGetUserNameAndPassword(), and stunServerProcessMsg().
{
char hmac[20];
char key[] = "Fluffy";
//char buffer[STUN_MAX_STRING];
computeHmac(hmac, username.value, (int)strlen(username.value), key, (int)strlen(key));
toHex(hmac, 20, password->value);
password->sizeValue = 40;
password->value[40]=0;
//clog << "password=" << password->value << endl;
}

| static void stunCreateSharedSecretResponse | ( | const StunMessage & | request, |
| const StunAddress4 & | source, | ||
| StunMessage & | response | ||
| ) | [static] |
Definition at line 1223 of file Stun.cxx.
References StunMessage::hasPassword, StunMessage::hasUsername, StunMsgHdr::id, StunMessage::msgHdr, StunMsgHdr::msgType, StunMessage::password, SharedSecretResponseMsg, stunCreatePassword(), stunCreateUserName(), and StunMessage::username.
Referenced by stunServerProcessMsg().
{
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);
}

| void stunCreateUserName | ( | const StunAddress4 & | source, |
| StunAtrString * | username | ||
| ) |
Definition at line 928 of file Stun.cxx.
References StunAddress4::addr, computeHmac(), StunAtrString::sizeValue, STUN_MAX_STRING, stunGetSystemTimeSecs(), stunRand(), toHex(), and StunAtrString::value.
Referenced by stunCreateSharedSecretResponse(), and stunGetUserNameAndPassword().
{
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, (int)strlen(buffer), key, (int)strlen(key) );
char hmacHex[41];
toHex(hmac, 20, hmacHex );
hmacHex[40] =0;
strcat(buffer,hmacHex);
int l = (int)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;
}

| unsigned int stunEncodeMessage | ( | const StunMessage & | msg, |
| char * | buf, | ||
| unsigned int | bufLen, | ||
| const StunAtrString & | password, | ||
| bool | verbose | ||
| ) |
Definition at line 651 of file Stun.cxx.
References ChangedAddress, StunMessage::changedAddress, StunMessage::changeRequest, computeHmac(), encode(), encode16(), encodeAtrAddress4(), encodeAtrChangeRequest(), encodeAtrError(), encodeAtrIntegrity(), encodeAtrString(), encodeAtrUInt32(), encodeAtrUnknown(), encodeMagicCookie(), encodeTurnData(), encodeXorOnly(), StunAtrError::errorClass, StunMessage::errorCode, StunMessage::hasChangedAddress, StunMessage::hasChangeRequest, StunMessage::hasErrorCode, StunAtrIntegrity::hash, StunMessage::hasMappedAddress, StunMessage::hasPassword, StunMessage::hasReflectedFrom, StunMessage::hasResponseAddress, StunMessage::hasSecondaryAddress, StunMessage::hasServerName, StunMessage::hasSourceAddress, StunMessage::hasTurnAlternateServer, StunMessage::hasTurnBandwidth, StunMessage::hasTurnData, StunMessage::hasTurnDestinationAddress, StunMessage::hasTurnLifetime, StunMessage::hasTurnMagicCookie, StunMessage::hasUnknownAttributes, StunMessage::hasUsername, StunMessage::hasXorMappedAddress, StunMsgHdr::id, StunAtrAddress4::ipv4, MappedAddress, StunMessage::mappedAddress, MessageIntegrity, StunMessage::msgHdr, StunMsgHdr::msgType, StunAtrError::number, UInt128::octet, Password, StunMessage::password, StunAtrError::reason, ReflectedFrom, StunMessage::reflectedFrom, ResponseAddress, StunMessage::responseAddress, SecondaryAddress, StunMessage::secondaryAddress, ServerName, StunMessage::serverName, StunAtrString::sizeValue, SourceAddress, StunMessage::sourceAddress, TurnAlternateServer, StunMessage::turnAlternateServer, TurnBandwidth, StunMessage::turnBandwidth, StunMessage::turnData, TurnDestinationAddress, StunMessage::turnDestinationAddress, TurnLifetime, StunMessage::turnLifetime, StunMessage::turnMagicCookie, StunMessage::unknownAttributes, Username, StunMessage::username, StunAtrChangeRequest::value, StunAtrString::value, XorMappedAddress, StunMessage::xorMappedAddress, and StunMessage::xorOnly.
Referenced by stunSendTest(), and stunServerProcess().
{
assert(bufLen >= sizeof(StunMsgHdr));
char* ptr = buf;
if (verbose) clog << "Encoding stun message: " << endl;
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 (msg.hasTurnMagicCookie)
{
if (verbose) clog << "Encoding TurnMagicCookie: " << msg.turnMagicCookie << endl;
ptr = encodeMagicCookie(ptr, msg.turnMagicCookie);
}
if (msg.hasTurnDestinationAddress)
{
if (verbose) clog << "Encoding TurnDestinationAddress: " << msg.turnDestinationAddress.ipv4 << endl;
ptr = encodeAtrAddress4 (ptr, TurnDestinationAddress, msg.turnDestinationAddress);
}
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.hasTurnAlternateServer )
{
if (verbose) clog << "Encoding AlternateServer: " << msg.turnAlternateServer.ipv4 << endl;
ptr = encodeAtrAddress4 (ptr, TurnAlternateServer, msg.turnAlternateServer);
}
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 (msg.hasTurnLifetime)
{
if (verbose) clog << "Encoding Turn Lifetime: " << msg.turnLifetime << endl;
ptr = encodeAtrUInt32(ptr, TurnLifetime, msg.turnLifetime);
}
if (msg.hasTurnBandwidth)
{
if (verbose) clog << "Encoding Turn Bandwidth: " << msg.turnBandwidth << endl;
ptr = encodeAtrUInt32(ptr, TurnBandwidth, msg.turnBandwidth);
}
if (msg.hasTurnData)
{
if (verbose) clog << "Encoding TurnData (not shown)" << endl;
ptr = encodeTurnData (ptr, msg.turnData);
}
if (password.sizeValue > 0)
{
if (verbose) clog << "HMAC with password: " << password.value << endl;
// allocate space for message integrity attribute (hash + attribute type + size)
char* ptrMessageIntegrity = ptr;
ptr += 20 + sizeof(MessageIntegrity) + sizeof(UInt16);
encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr)));
StunAtrIntegrity integrity;
// pad with zeros prior to calculating message integrity attribute
int padding = 0;
int len = int(ptrMessageIntegrity - buf);
if (len % 64)
{
padding = 64 - (len % 64);
memset(ptrMessageIntegrity, 0, padding);
}
computeHmac(integrity.hash, buf, len + padding, password.value, password.sizeValue);
encodeAtrIntegrity(ptrMessageIntegrity, integrity);
}
if (verbose) clog << endl;
encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr)));
return int(ptr - buf);
}

| int stunFindLocalInterfaces | ( | UInt32 * | addresses, |
| int | maxRet | ||
| ) |
returns number of address found - take array or addres
Definition at line 1850 of file Stun.cxx.
References resip::closeSocket().
{
#if defined(WIN32) || defined(__sparc__)
return 0;
#else
struct ifconf ifc;
int s = socket( AF_INET, SOCK_DGRAM, 0 );
const 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
}

| UInt64 stunGetSystemTimeSecs | ( | ) |
Definition at line 981 of file Stun.cxx.
Referenced by stunCreateUserName().
{
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;
}
| void stunGetUserNameAndPassword | ( | const StunAddress4 & | dest, |
| StunAtrString * | username, | ||
| StunAtrString * | password | ||
| ) |
Definition at line 2011 of file Stun.cxx.
References stunCreatePassword(), and stunCreateUserName().
Referenced by stunNatType(), stunOpenSocket(), stunOpenSocketPair(), and stunTest().
{
// !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 stunInitServer | ( | StunServerInfo & | info, |
| const StunAddress4 & | myAddr, | ||
| const StunAddress4 & | altAddr, | ||
| int | startMediaPort, | ||
| bool | verbose | ||
| ) |
return true if all is OK Create a media relay and do the STERN thing if startMediaPort is non-zero
Definition at line 1470 of file Stun.cxx.
References StunAddress4::addr, StunServerInfo::altAddr, StunServerInfo::altIpFd, StunServerInfo::altIpPortFd, StunServerInfo::altPortFd, StunMediaRelay::expireTime, StunMediaRelay::fd, INVALID_SOCKET, MAX_MEDIA_RELAYS, StunServerInfo::myAddr, StunServerInfo::myFd, openPort(), StunAddress4::port, StunServerInfo::relay, StunMediaRelay::relayPort, StunServerInfo::relays, and stunStopServer().
{
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)
{
if (verbose) 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)
{
if (verbose) 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)
{
if (verbose) 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)
{
if (verbose) clog << "Can't open " << altAddr << endl;
stunStopServer(info);
return false;
}
//if (verbose) clog << "Opened " << altAddr.addr << ":" << altAddr.port << " --> " << info.altIpPortFd << endl;;
}
return true;
}

| NatType stunNatType | ( | StunAddress4 & | dest, |
| bool | verbose, | ||
| bool * | preservePort, | ||
| bool * | hairpin, | ||
| int | port, | ||
| StunAddress4 * | sAddr | ||
| ) |
Definition at line 2110 of file Stun.cxx.
References StunAddress4::addr, StunMessage::changedAddress, resip::closeSocket(), resip::getErrno(), getMessage(), StunMsgHdr::id, INVALID_SOCKET, StunAtrAddress4::ipv4, StunMessage::mappedAddress, StunMessage::msgHdr, StunMsgHdr::msgType, UInt128::octet, openPort(), StunAddress4::port, StunAtrString::sizeValue, SOCKET_ERROR, strerror(), STUN_MAX_MESSAGE_SIZE, stunGetUserNameAndPassword(), stunParseMessage(), stunRandomPort(), stunSendTest(), StunTypeBlocked, StunTypeDependentFilter, StunTypeDependentMapping, StunTypeFailure, StunTypeFirewall, StunTypeIndependentFilter, StunTypeOpen, StunTypePortDependedFilter, and StunTypeUnknown.
{
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
typedef unsigned int FdSetSize;
#else
typedef int FdSetSize;
#endif
FdSetSize fdSetSize;
FD_ZERO(&fdSet); fdSetSize=0;
FD_SET(myFd1,&fdSet); fdSetSize = ((FdSetSize)myFd1+1>fdSetSize) ? (FdSetSize)myFd1+1 : fdSetSize;
FD_SET(myFd2,&fdSet); fdSetSize = ((FdSetSize)myFd2+1>fdSetSize) ? (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 StunTypePortRestrictedNat;
}
}
else
{
return StunTypeSymNat;
}
}
}
else
{
if (respTestII)
{
return StunTypeOpen;
}
else
{
return StunTypeSymFirewall;
}
}
}
else
{
return StunTypeBlocked;
}
#else
if ( respTestI ) // not blocked
{
if ( isNat )
{
if ( mappedIpSame )
{
if (respTestII)
{
return StunTypeIndependentFilter;
}
else
{
if ( respTestIII )
{
return StunTypeDependentFilter;
}
else
{
return StunTypePortDependedFilter;
}
}
}
else // mappedIp is not same
{
return StunTypeDependentMapping;
}
}
else // isNat is false
{
if (respTestII)
{
return StunTypeOpen;
}
else
{
return StunTypeFirewall;
}
}
}
else
{
return StunTypeBlocked;
}
#endif
return StunTypeUnknown;
}

| int stunOpenSocket | ( | StunAddress4 & | dest, |
| StunAddress4 * | mapAddr, | ||
| int | port, | ||
| StunAddress4 * | srcAddr, | ||
| bool | verbose | ||
| ) |
Definition at line 2485 of file Stun.cxx.
References StunAddress4::addr, StunMessage::changedAddress, getMessage(), INVALID_SOCKET, StunAtrAddress4::ipv4, StunMessage::mappedAddress, openPort(), StunAddress4::port, StunAtrString::sizeValue, STUN_MAX_MESSAGE_SIZE, stunGetUserNameAndPassword(), stunParseMessage(), stunRandomPort(), and stunSendTest().
{
assert( dest.addr != 0 );
assert( dest.port != 0 );
assert( mapAddr );
if ( port == 0 )
{
port = stunRandomPort();
}
unsigned int interfaceIp = 0;
if ( srcAddr )
{
interfaceIp = srcAddr->addr;
}
resip::Socket myFd = openPort(port,interfaceIp,verbose);
if (myFd == INVALID_SOCKET)
{
return (int)myFd;
}
char msg[STUN_MAX_MESSAGE_SIZE];
int msgLen = sizeof(msg);
StunAtrString username;
StunAtrString password;
username.sizeValue = 0;
password.sizeValue = 0;
#ifdef USE_TLS
stunGetUserNameAndPassword( dest, username, password );
#endif
stunSendTest(myFd, dest, username, password, 1, 0/*false*/ );
StunAddress4 from;
getMessage( myFd, msg, &msgLen, &from.addr, &from.port,verbose );
StunMessage resp;
memset(&resp, 0, sizeof(StunMessage));
bool ok = stunParseMessage( msg, msgLen, resp,verbose );
if (!ok)
{
return -1;
}
StunAddress4 mappedAddr = resp.mappedAddress.ipv4;
StunAddress4 changedAddr = resp.changedAddress.ipv4;
//clog << "--- stunOpenSocket --- " << endl;
//clog << "\treq id=" << req.id << endl;
//clog << "\tresp id=" << id << endl;
//clog << "\tmappedAddr=" << mappedAddr << endl;
*mapAddr = mappedAddr;
return (int)myFd;
}

| bool stunOpenSocketPair | ( | StunAddress4 & | dest, |
| StunAddress4 * | mapAddr, | ||
| int * | fd1, | ||
| int * | fd2, | ||
| int | port, | ||
| StunAddress4 * | srcAddr, | ||
| bool | verbose | ||
| ) |
Definition at line 2552 of file Stun.cxx.
References StunAddress4::addr, StunMessage::changedAddress, resip::closeSocket(), getMessage(), StunAtrAddress4::ipv4, StunMessage::mappedAddress, openPort(), StunAddress4::port, StunAtrString::sizeValue, STUN_MAX_MESSAGE_SIZE, stunGetUserNameAndPassword(), stunParseMessage(), stunRandomPort(), and stunSendTest().
{
assert( dest.addr!= 0 );
assert( dest.port != 0 );
assert( mapAddr );
const int NUM=3;
if ( port == 0 )
{
port = stunRandomPort();
}
*fd1=-1;
*fd2=-1;
char msg[STUN_MAX_MESSAGE_SIZE];
int msgLen =sizeof(msg);
StunAddress4 from;
int fd[NUM];
int i;
unsigned int interfaceIp = 0;
if ( srcAddr )
{
interfaceIp = srcAddr->addr;
}
for( i=0; i<NUM; i++)
{
fd[i] = (int)openPort( (port == 0) ? 0 : (port + i),
interfaceIp, verbose);
if (fd[i] < 0)
{
while (i > 0)
{
closeSocket(fd[--i]);
}
return false;
}
}
StunAtrString username;
StunAtrString password;
username.sizeValue = 0;
password.sizeValue = 0;
#ifdef USE_TLS
stunGetUserNameAndPassword( dest, username, password );
#endif
for( i=0; i<NUM; i++)
{
stunSendTest(fd[i], dest, username, password, 1/*testNum*/, verbose );
}
StunAddress4 mappedAddr[NUM];
for( i=0; i<NUM; i++)
{
msgLen = sizeof(msg)/sizeof(*msg);
getMessage( fd[i],
msg,
&msgLen,
&from.addr,
&from.port ,verbose);
StunMessage resp;
memset(&resp, 0, sizeof(StunMessage));
bool ok = stunParseMessage( msg, msgLen, resp, verbose );
if (!ok)
{
return false;
}
mappedAddr[i] = resp.mappedAddress.ipv4;
StunAddress4 changedAddr = resp.changedAddress.ipv4;
}
if (verbose)
{
clog << "--- stunOpenSocketPair --- " << endl;
for( i=0; i<NUM; i++)
{
clog << "\t mappedAddr=" << mappedAddr[i] << endl;
}
}
if ( mappedAddr[0].port %2 == 0 )
{
if ( mappedAddr[0].port+1 == mappedAddr[1].port )
{
*mapAddr = mappedAddr[0];
*fd1 = fd[0];
*fd2 = fd[1];
closeSocket( fd[2] );
return true;
}
}
else
{
if (( mappedAddr[1].port %2 == 0 )
&& ( mappedAddr[1].port+1 == mappedAddr[2].port ))
{
*mapAddr = mappedAddr[1];
*fd1 = fd[1];
*fd2 = fd[2];
closeSocket( fd[0] );
return true;
}
}
// something failed, close all and return error
for( i=0; i<NUM; i++)
{
closeSocket( fd[i] );
}
return false;
}

| static bool stunParseAtrAddress | ( | char * | body, |
| unsigned int | hdrLen, | ||
| StunAtrAddress4 & | result | ||
| ) | [static] |
Definition at line 52 of file Stun.cxx.
References StunAddress4::addr, StunAtrAddress4::family, StunAtrAddress4::ipv4, IPv4Family, IPv6Family, StunAtrAddress4::pad, and StunAddress4::port.
Referenced by stunParseMessage().
{
if ( hdrLen != 8 )
{
// clog << "hdrLen wrong for Address" <<endl;
return false;
}
result.pad = *body++;
result.family = *body++;
if (result.family == IPv4Family)
{
UInt16 nport;
memcpy(&nport, body, 2); body+=2;
result.ipv4.port = ntohs(nport);
UInt32 naddr;
memcpy(&naddr, body, 4); body+=4;
result.ipv4.addr = ntohl(naddr);
return true;
}
else if (result.family == IPv6Family)
{
//clog << "ipv6 not supported" << endl;
}
else
{
//clog << "bad address family: " << result.family << endl;
}
return false;
}
| static bool stunParseAtrChangeRequest | ( | char * | body, |
| unsigned int | hdrLen, | ||
| StunAtrChangeRequest & | result | ||
| ) | [static] |
Definition at line 101 of file Stun.cxx.
References StunAtrChangeRequest::value.
Referenced by stunParseMessage().
| static bool stunParseAtrError | ( | char * | body, |
| unsigned int | hdrLen, | ||
| StunAtrError & | result | ||
| ) | [static] |
Definition at line 119 of file Stun.cxx.
References StunAtrError::errorClass, StunAtrError::number, StunAtrError::pad, StunAtrError::reason, and StunAtrError::sizeReason.
Referenced by stunParseMessage().
{
if ( hdrLen >= (sizeof(result)-sizeof(result.sizeReason)) ) // Note: result.sizeReason is extra info in StunAtrError that is not on the wire
{
//clog << "head on Error too large" << endl;
return false;
}
else
{
memcpy(&result.pad, body, 2); body+=2;
result.pad = ntohs(result.pad);
result.errorClass = *body++;
result.number = *body++;
result.sizeReason = hdrLen - 4;
memcpy(&result.reason, body, result.sizeReason);
result.reason[result.sizeReason] = 0;
return true;
}
}
| static bool stunParseAtrIntegrity | ( | char * | body, |
| unsigned int | hdrLen, | ||
| StunAtrIntegrity & | result | ||
| ) | [static] |
Definition at line 186 of file Stun.cxx.
References StunAtrIntegrity::hash.
Referenced by stunParseMessage().
{
if ( hdrLen != 20)
{
//clog << "MessageIntegrity must be 20 bytes" << endl;
return false;
}
else
{
memcpy(&result.hash, body, hdrLen);
return true;
}
}
| static bool stunParseAtrString | ( | char * | body, |
| unsigned int | hdrLen, | ||
| StunAtrString & | result | ||
| ) | [static] |
Definition at line 162 of file Stun.cxx.
References StunAtrString::sizeValue, STUN_MAX_STRING, and StunAtrString::value.
Referenced by stunParseMessage().
{
if ( hdrLen >= STUN_MAX_STRING )
{
//clog << "String is too large" << endl;
return false;
}
else
{
if (hdrLen % 4 != 0)
{
//clog << "Bad length string " << hdrLen << endl;
return false;
}
result.sizeValue = hdrLen;
memcpy(&result.value, body, hdrLen);
result.value[hdrLen] = 0;
return true;
}
}
| static bool stunParseAtrUnknown | ( | char * | body, |
| unsigned int | hdrLen, | ||
| StunAtrUnknown & | result | ||
| ) | [static] |
Definition at line 141 of file Stun.cxx.
References StunAtrUnknown::attrType, and StunAtrUnknown::numAttributes.
Referenced by stunParseMessage().
{
if ( hdrLen >= sizeof(result) )
{
return false;
}
else
{
if (hdrLen % 4 != 0) return false;
result.numAttributes = hdrLen / 4;
for (int i=0; i<result.numAttributes; i++)
{
memcpy(&result.attrType[i], body, 2); body+=2;
result.attrType[i] = ntohs(result.attrType[i]);
}
return true;
}
}
Definition at line 1084 of file Stun.cxx.
References resip::getErrno(), and WSANOTINITIALISED.
Referenced by stunParseServerName().
{
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;
}

| bool stunParseMessage | ( | char * | buf, |
| unsigned int | bufLen, | ||
| StunMessage & | msg, | ||
| bool | verbose | ||
| ) |
Definition at line 203 of file Stun.cxx.
References ChangedAddress, StunMessage::changedAddress, ChangeRequest, StunMessage::changeRequest, StunAtrError::errorClass, ErrorCode, StunMessage::errorCode, StunMessage::hasChangedAddress, StunMessage::hasChangeRequest, StunMessage::hasErrorCode, StunAtrIntegrity::hash, StunMessage::hasMappedAddress, StunMessage::hasMessageIntegrity, StunMessage::hasPassword, StunMessage::hasReflectedFrom, StunMessage::hasResponseAddress, StunMessage::hasSecondaryAddress, StunMessage::hasServerName, StunMessage::hasSourceAddress, StunMessage::hasTurnAlternateServer, StunMessage::hasTurnBandwidth, StunMessage::hasTurnData, StunMessage::hasTurnDestinationAddress, StunMessage::hasTurnLifetime, StunMessage::hasTurnMagicCookie, StunMessage::hasTurnRemoteAddress, StunMessage::hasUnknownAttributes, StunMessage::hasUsername, StunMessage::hasXorMappedAddress, StunAtrAddress4::ipv4, StunAtrHdr::length, MappedAddress, StunMessage::mappedAddress, MessageIntegrity, StunMessage::messageIntegrity, StunMessage::msgHdr, StunMsgHdr::msgLength, StunMsgHdr::msgType, StunAtrError::number, Password, StunMessage::password, StunAtrError::reason, ReflectedFrom, StunMessage::reflectedFrom, ResponseAddress, StunMessage::responseAddress, SecondaryAddress, StunMessage::secondaryAddress, ServerName, StunMessage::serverName, resip::Data::Share, SourceAddress, StunMessage::sourceAddress, stunParseAtrAddress(), stunParseAtrChangeRequest(), stunParseAtrError(), stunParseAtrIntegrity(), stunParseAtrString(), stunParseAtrUnknown(), stunParseUInt32(), TurnAlternateServer, StunMessage::turnAlternateServer, TurnBandwidth, StunMessage::turnBandwidth, TurnData, StunMessage::turnData, TurnDestinationAddress, StunMessage::turnDestinationAddress, TurnLifetime, StunMessage::turnLifetime, TurnMagicCookie, StunMessage::turnMagicCookie, TurnRemoteAddress, StunMessage::turnRemoteAddress, StunAtrHdr::type, UnknownAttribute, StunMessage::unknownAttributes, Username, StunMessage::username, StunAtrChangeRequest::value, StunAtrString::value, XorMappedAddress, StunMessage::xorMappedAddress, XorOnly, and StunMessage::xorOnly.
Referenced by stunNatType(), stunOpenSocket(), stunOpenSocketPair(), stunServerProcessMsg(), and stunTest().
{
if (verbose) clog << "Received stun message: " << bufLen << " bytes" << endl;
memset(&msg, 0, sizeof(msg));
if (sizeof(StunMsgHdr) > bufLen)
{
clog << "Bad message" << endl;
return false;
}
memcpy(&msg.msgHdr, buf, sizeof(StunMsgHdr));
msg.msgHdr.msgType = ntohs(msg.msgHdr.msgType);
msg.msgHdr.msgLength = ntohs(msg.msgHdr.msgLength);
if (msg.msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen)
{
clog << "Message header length doesn't match message size: " << msg.msgHdr.msgLength << " - " << bufLen << endl;
return false;
}
char* body = buf + sizeof(StunMsgHdr);
unsigned int size = msg.msgHdr.msgLength;
if (verbose) clog << "bytes after header = " << size << endl;
while ( size > 0 )
{
// !jf! should check that there are enough bytes left in the buffer
StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body);
unsigned int attrLen = ntohs(attr->length);
int atrType = ntohs(attr->type);
if (verbose) clog << "Found attribute type=" << atrType << " length=" << attrLen << endl;
if ( attrLen+4 > size )
{
clog << "claims attribute is larger than size of message " <<"(attribute type="<<atrType<<")"<< endl;
return false;
}
body += 4; // skip the length and type in attribute header
size -= 4;
switch ( atrType )
{
case MappedAddress:
msg.hasMappedAddress = true;
if ( stunParseAtrAddress( body, attrLen, msg.mappedAddress )== false )
{
clog << "problem parsing MappedAddress" << endl;
return false;
}
else
{
if (verbose) clog << "MappedAddress = " << msg.mappedAddress.ipv4 << endl;
}
break;
case ResponseAddress:
msg.hasResponseAddress = true;
if ( stunParseAtrAddress( body, attrLen, msg.responseAddress )== false )
{
if (verbose) clog << "problem parsing ResponseAddress" << endl;
return false;
}
else
{
if (verbose) clog << "ResponseAddress = " << msg.responseAddress.ipv4 << endl;
}
break;
case ChangeRequest:
msg.hasChangeRequest = true;
if (stunParseAtrChangeRequest( body, attrLen, msg.changeRequest) == false)
{
if (verbose) clog << "problem parsing ChangeRequest" << endl;
return false;
}
else
{
if (verbose) clog << "ChangeRequest = " << msg.changeRequest.value << endl;
}
break;
case SourceAddress:
msg.hasSourceAddress = true;
if ( stunParseAtrAddress( body, attrLen, msg.sourceAddress )== false )
{
if (verbose) clog << "problem parsing SourceAddress" << endl;
return false;
}
else
{
if (verbose) clog << "SourceAddress = " << msg.sourceAddress.ipv4 << endl;
}
break;
case ChangedAddress:
msg.hasChangedAddress = true;
if ( stunParseAtrAddress( body, attrLen, msg.changedAddress )== false )
{
if (verbose) clog << "problem parsing ChangedAddress" << endl;
return false;
}
else
{
if (verbose) clog << "ChangedAddress = " << msg.changedAddress.ipv4 << endl;
}
break;
case Username:
msg.hasUsername = true;
if (stunParseAtrString( body, attrLen, msg.username) == false)
{
if (verbose) clog << "problem parsing Username" << endl;
return false;
}
else
{
if (verbose) clog << "Username = " << msg.username.value << endl;
}
break;
case Password:
msg.hasPassword = true;
if (stunParseAtrString( body, attrLen, msg.password) == false)
{
if (verbose) clog << "problem parsing Password" << endl;
return false;
}
else
{
if (verbose) clog << "Password = " << msg.password.value << endl;
}
break;
case MessageIntegrity:
msg.hasMessageIntegrity = true;
if (stunParseAtrIntegrity( body, attrLen, msg.messageIntegrity) == false)
{
if (verbose) clog << "problem parsing MessageIntegrity" << endl;
return false;
}
else
{
if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl;
}
// read the current HMAC
// look up the password given the user of given the transaction id
// compute the HMAC on the buffer
// decide if they match or not
break;
case ErrorCode:
msg.hasErrorCode = true;
if (stunParseAtrError(body, attrLen, msg.errorCode) == false)
{
if (verbose) clog << "problem parsing ErrorCode" << endl;
return false;
}
else
{
if (verbose) clog << "ErrorCode = " << int(msg.errorCode.errorClass)
<< " " << int(msg.errorCode.number)
<< " " << msg.errorCode.reason << endl;
}
break;
case UnknownAttribute:
msg.hasUnknownAttributes = true;
if (stunParseAtrUnknown(body, attrLen, msg.unknownAttributes) == false)
{
if (verbose) clog << "problem parsing UnknownAttribute" << endl;
return false;
}
break;
case ReflectedFrom:
msg.hasReflectedFrom = true;
if ( stunParseAtrAddress( body, attrLen, msg.reflectedFrom ) == false )
{
if (verbose) clog << "problem parsing ReflectedFrom" << endl;
return false;
}
break;
case XorMappedAddress:
msg.hasXorMappedAddress = true;
if ( stunParseAtrAddress( body, attrLen, msg.xorMappedAddress ) == false )
{
if (verbose) clog << "problem parsing XorMappedAddress" << endl;
return false;
}
else
{
if (verbose) clog << "XorMappedAddress = " << msg.mappedAddress.ipv4 << endl;
}
break;
case XorOnly:
msg.xorOnly = true;
if (verbose)
{
if (verbose) clog << "xorOnly = true" << endl;
}
break;
case ServerName:
msg.hasServerName = true;
if (stunParseAtrString( body, attrLen, msg.serverName) == false)
{
if (verbose) clog << "problem parsing ServerName" << endl;
return false;
}
else
{
if (verbose) clog << "ServerName = " << msg.serverName.value << endl;
}
break;
case SecondaryAddress:
msg.hasSecondaryAddress = true;
if ( stunParseAtrAddress( body, attrLen, msg.secondaryAddress ) == false )
{
if (verbose) clog << "problem parsing secondaryAddress" << endl;
return false;
}
else
{
if (verbose) clog << "SecondaryAddress = " << msg.secondaryAddress.ipv4 << endl;
}
break;
// TURN attributes
case TurnLifetime:
msg.hasTurnLifetime = true;
if (stunParseUInt32( body, attrLen, msg.turnLifetime) == false)
{
return false;
}
break;
case TurnAlternateServer:
msg.hasTurnAlternateServer = true;
if ( stunParseAtrAddress( body, attrLen, msg.turnAlternateServer ) == false )
{
return false;
}
break;
case TurnMagicCookie:
msg.hasTurnMagicCookie = true;
if (stunParseUInt32( body, attrLen, msg.turnMagicCookie) == false)
{
return false;
}
break;
case TurnBandwidth:
msg.hasTurnBandwidth = true;
if (stunParseUInt32( body, attrLen, msg.turnBandwidth) == false)
{
return false;
}
break;
case TurnDestinationAddress:
msg.hasTurnDestinationAddress = true;
if ( stunParseAtrAddress( body, attrLen, msg.turnDestinationAddress ) == false )
{
return false;
}
break;
case TurnRemoteAddress:
msg.hasTurnRemoteAddress = true;
if ( stunParseAtrAddress( body, attrLen, msg.turnRemoteAddress ) == false )
{
return false;
}
break;
//overlay on parse, ownership is buffer parsed from
case TurnData:
msg.hasTurnData = true;
msg.turnData = new resip::Data(resip::Data::Share, body, attrLen);
break;
//case TurnNonce:
//break;
//case TurnRealm:
//break;
default:
if (verbose) clog << "Unknown attribute: " << atrType << endl;
if ( atrType <= 0x7FFF )
{
return false;
}
}
body += attrLen;
size -= attrLen;
}
return true;
}

| bool stunParseServerName | ( | char * | name, |
| StunAddress4 & | addr | ||
| ) |
find the IP address of a the specified stun server - return false is fails parse
Definition at line 1185 of file Stun.cxx.
References StunAddress4::addr, StunAddress4::port, and stunParseHostName().
{
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;
}

| static bool stunParseUInt32 | ( | char * | body, |
| unsigned int | hdrLen, | ||
| UInt32 & | result | ||
| ) | [static] |
Definition at line 85 of file Stun.cxx.
Referenced by stunParseMessage().
{
if ( hdrLen != 4 )
{
return false;
}
else
{
UInt32 tmp;
memcpy(&tmp, body, 4);
result = ntohl(tmp);
return true;
}
}
| int stunRand | ( | ) |
Definition at line 801 of file Stun.cxx.
References resip::closeSocket().
Referenced by stunBuildReqSimple(), stunCreateUserName(), and stunRandomPort().
{
// return 32 bits of random stuff
assert( sizeof(int) == 4 );
static bool init=false;
if ( !init )
{
init = true;
UInt64 tick;
#if defined(WIN32)
#if !defined(UNDER_CE) && !defined(__GNUC__) && !defined(_WIN64)
volatile unsigned int lowtick=0,hightick=0;
__asm
{
rdtsc
mov lowtick, eax
mov hightick, edx
}
tick = hightick;
tick <<= 32;
tick |= lowtick;
#else
tick = GetTickCount();
#endif
#elif defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) || defined(__x86_64__) )
asm("rdtsc" : "=A" (tick));
#elif defined (__SUNPRO_CC) || defined( __sparc__ )
tick = gethrtime();
#elif defined(__APPLE__) || defined(__MACH__)
int fd=open("/dev/random",O_RDONLY);
read(fd,&tick,sizeof(tick));
closeSocket(fd);
#elif defined(__linux__)
int fd=open("/dev/urandom",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
}

| int stunRandomPort | ( | ) |
return a random number to use as a port
Definition at line 866 of file Stun.cxx.
References stunRand().
Referenced by stunNatType(), stunOpenSocket(), stunOpenSocketPair(), and stunTest().
{
int min=0x4000;
int max=0x7FFF;
int ret = stunRand();
ret = ret|min;
ret = ret&max;
return ret;
}

| static void stunSendTest | ( | resip::Socket | myFd, |
| StunAddress4 & | dest, | ||
| const StunAtrString & | username, | ||
| const StunAtrString & | password, | ||
| int | testNum, | ||
| bool | verbose | ||
| ) | [static] |
Definition at line 1953 of file Stun.cxx.
References StunAddress4::addr, StunAddress4::port, sendMessage(), STUN_MAX_MESSAGE_SIZE, stunBuildReqSimple(), and stunEncodeMessage().
Referenced by stunNatType(), stunOpenSocket(), stunOpenSocketPair(), and stunTest().
{
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 unknown\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 );
}

| bool stunServerProcess | ( | StunServerInfo & | info, |
| bool | verbose | ||
| ) |
return true if all is OK
Definition at line 1571 of file Stun.cxx.
References StunAddress4::addr, StunServerInfo::altAddr, StunServerInfo::altIpFd, StunServerInfo::altIpPortFd, StunServerInfo::altPortFd, resip::closeSocket(), StunMediaRelay::destination, StunMediaRelay::expireTime, StunMediaRelay::fd, resip::getErrno(), getMessage(), INVALID_SOCKET, MAX_MEDIA_RELAYS, MAX_RTP_MSG_SIZE, MEDIA_RELAY_TIMEOUT, StunServerInfo::myAddr, StunServerInfo::myFd, openPort(), StunAddress4::port, StunServerInfo::relay, StunMediaRelay::relayPort, StunServerInfo::relays, sendMessage(), StunAtrString::sizeValue, strerror(), STUN_MAX_MESSAGE_SIZE, stunEncodeMessage(), and stunServerProcessMsg().
{
char msg[STUN_MAX_MESSAGE_SIZE];
int msgLen = sizeof(msg);
bool ok = false;
bool recvAltIp =false;
bool recvAltPort = false;
fd_set fdSet;
resip::Socket maxFd=0;
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 ((resip::Socket)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 = (int)select( (int)maxFd, &fdSet, NULL,NULL, &tv );
if (e < 0)
{
int err = getErrno();
if (verbose) 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))
{
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 = (int)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 );
resip::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;
}

| bool stunServerProcessMsg | ( | 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 | ||
| ) |
Definition at line 1240 of file Stun.cxx.
References StunAddress4::addr, BindRequestMsg, BindResponseMsg, StunMessage::changedAddress, ChangeIpFlag, ChangePortFlag, StunMessage::changeRequest, StunMessage::hasChangedAddress, StunMessage::hasMappedAddress, StunMessage::hasMessageIntegrity, StunMessage::hasReflectedFrom, StunMessage::hasSecondaryAddress, StunMessage::hasServerName, StunMessage::hasSourceAddress, StunMessage::hasUsername, StunMessage::hasXorMappedAddress, StunMsgHdr::id, StunAtrAddress4::ipv4, StunMessage::mappedAddress, StunMessage::msgHdr, StunMsgHdr::msgType, UInt128::octet, StunAddress4::port, StunMessage::reflectedFrom, StunMessage::responseAddress, StunMessage::secondaryAddress, StunMessage::serverName, SharedSecretRequestMsg, StunAtrString::sizeValue, StunMessage::sourceAddress, STUN_MAX_STRING, STUN_VERSION, stunCreateErrorResponse(), stunCreatePassword(), stunCreateSharedSecretResponse(), stunParseMessage(), StunMessage::username, StunAtrChangeRequest::value, StunAtrString::value, StunMessage::xorMappedAddress, and StunMessage::xorOnly.
Referenced by stunServerProcess().
{
// 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];
#ifdef USE_SSL
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[0]<<8
| req.msgHdr.id.octet[1];
UInt32 id32 = req.msgHdr.id.octet[0]<<24
| req.msgHdr.id.octet[1]<<16
| req.msgHdr.id.octet[2]<<8
| req.msgHdr.id.octet[3];
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;
}

| void stunStopServer | ( | StunServerInfo & | info | ) |
Definition at line 1549 of file Stun.cxx.
References StunServerInfo::altIpFd, StunServerInfo::altIpPortFd, StunServerInfo::altPortFd, resip::closeSocket(), StunMediaRelay::fd, MAX_MEDIA_RELAYS, StunServerInfo::myFd, StunServerInfo::relay, and StunServerInfo::relays.
Referenced by stunInitServer().
{
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;
}
}
}
}

| bool stunTest | ( | StunAddress4 & | dest, |
| int | testNum, | ||
| bool | verbose, | ||
| StunAddress4 * | sAddr, | ||
| unsigned long | timeoutMs | ||
| ) |
Definition at line 2023 of file Stun.cxx.
References StunAddress4::addr, StunMessage::changedAddress, resip::closeSocket(), getMessage(), StunMsgHdr::id, INVALID_SOCKET, StunAtrAddress4::ipv4, resip::makeSocketNonBlocking(), StunMessage::mappedAddress, StunMessage::msgHdr, openPort(), StunAddress4::port, resip::FdSet::selectMilliSeconds(), resip::FdSet::setRead(), StunAtrString::sizeValue, STUN_MAX_MESSAGE_SIZE, stunGetUserNameAndPassword(), stunParseMessage(), stunRandomPort(), and stunSendTest().
{
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;
}

| static void toHex | ( | const char * | buffer, |
| int | bufferSize, | ||
| char * | output | ||
| ) | [static] |
Definition at line 908 of file Stun.cxx.
References hexmap.
Referenced by stunCreatePassword(), and stunCreateUserName().
{
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;
}
1.7.5.1