reSIProcate/rutil  9694
Stun.hxx
Go to the documentation of this file.
00001 #ifndef STUN_HXX
00002 #define STUN_HXX
00003 
00004 #include <iostream>
00005 #include <time.h>
00006 #include "rutil/Data.hxx"
00007 #include "rutil/Socket.hxx"
00008 
00009 // if you change this version, change in makefile too 
00010 #define STUN_VERSION "0.96"
00011 
00012 #define STUN_MAX_STRING 256
00013 #define STUN_MAX_UNKNOWN_ATTRIBUTES 8
00014 #define STUN_MAX_MESSAGE_SIZE 2048
00015 
00016 #define STUN_PORT 3478
00017 
00018 #ifndef RESIP_COMPAT_HXX
00019 // define some basic types
00020 typedef unsigned char  UInt8;
00021 typedef unsigned short UInt16;
00022 #ifdef __APPLE__
00023 typedef unsigned long   UInt32;
00024 #else
00025 typedef unsigned int   UInt32;
00026 #endif
00027 #if defined( WIN32 )
00028 typedef unsigned __int64 UInt64;
00029 #else
00030 typedef unsigned long long UInt64;
00031 #endif
00032 #endif
00033 
00034 typedef struct { unsigned char octet[16]; }  UInt128;
00035 
00036 #ifdef __cplusplus
00037 bool operator<(const UInt128&, const UInt128&);
00038 bool operator==(const UInt128&, const UInt128&);
00039 #endif
00040 
00042 const UInt8  IPv4Family = 0x01;
00043 const UInt8  IPv6Family = 0x02;
00044 
00045 // define  flags  
00046 const UInt32 ChangeIpFlag   = 0x04;
00047 const UInt32 ChangePortFlag = 0x02;
00048 
00049 // define  stun attribute
00050 const UInt16 MappedAddress    = 0x0001;
00051 const UInt16 ResponseAddress  = 0x0002;
00052 const UInt16 ChangeRequest    = 0x0003;
00053 const UInt16 SourceAddress    = 0x0004;
00054 const UInt16 ChangedAddress   = 0x0005;
00055 const UInt16 Username         = 0x0006;
00056 const UInt16 Password         = 0x0007;
00057 const UInt16 MessageIntegrity = 0x0008;
00058 const UInt16 ErrorCode        = 0x0009;
00059 const UInt16 UnknownAttribute = 0x000A;
00060 const UInt16 ReflectedFrom    = 0x000B;
00061 const UInt16 XorMappedAddress = 0x8020;
00062 const UInt16 XorOnly          = 0x0021;
00063 const UInt16 ServerName       = 0x8022;
00064 const UInt16 SecondaryAddress = 0x8050; // Non standard extention
00065 
00066 // !jf! TURN specific message attributes - from turn-08
00067 const UInt16 TurnLifetime     = 0x000d;
00068 const UInt16 TurnAlternateServer = 0x000e;
00069 const UInt16 TurnMagicCookie = 0x000f;
00070 const UInt16 TurnBandwidth = 0x0010;
00071 const UInt16 TurnDestinationAddress = 0x0011;
00072 const UInt16 TurnRemoteAddress = 0x0012;
00073 const UInt16 TurnData = 0x0013;
00074 const UInt16 TurnNonce = 0x0014;
00075 const UInt16 TurnRealm = 0x0015;
00076 
00077 
00078 // define types for a stun message 
00079 const UInt16 BindRequestMsg               = 0x0001;
00080 const UInt16 BindResponseMsg              = 0x0101;
00081 const UInt16 BindErrorResponseMsg         = 0x0111;
00082 const UInt16 SharedSecretRequestMsg       = 0x0002;
00083 const UInt16 SharedSecretResponseMsg      = 0x0102;
00084 const UInt16 SharedSecretErrorResponseMsg = 0x0112;
00085 
00086 // define types for a turn message - per turn-08
00087 const UInt16 TurnAllocateRequest = 0x0003;
00088 const UInt16 TurnAllocateResponse = 0x0103;
00089 const UInt16 TurnAllocateErrorResponse = 0x0113;
00090 const UInt16 TurnSendRequest = 0x0004;
00091 const UInt16 TurnSendResponse = 0x0104;
00092 const UInt16 TurnSendErrorResponse = 0x0114;
00093 const UInt16 TurnDataIndication = 0x0115;
00094 const UInt16 TurnSetActiveDestinationRequest = 0x0006;
00095 const UInt16 TurnSetActiveDestinationResponse = 0x0106;
00096 const UInt16 TurnSetActiveDestinationErrorResponse = 0x0116;
00097 
00098 typedef struct 
00099 {
00100       UInt16 msgType;
00101       UInt16 msgLength;
00102       UInt128 id;
00103 } StunMsgHdr;
00104 
00105 #ifdef __cplusplus
00106 bool operator<(const StunMsgHdr&, const StunMsgHdr&);
00107 #endif
00108 
00109 typedef struct
00110 {
00111       UInt16 type;
00112       UInt16 length;
00113 } StunAtrHdr;
00114 
00115 typedef struct
00116 {
00117       UInt16 port;
00118       UInt32 addr;
00119 } StunAddress4;
00120 
00121 typedef struct
00122 {
00123       UInt8 pad;
00124       UInt8 family;
00125       StunAddress4 ipv4;
00126 } StunAtrAddress4;
00127 
00128 typedef struct
00129 {
00130       UInt32 value;
00131 } StunAtrChangeRequest;
00132 
00133 typedef struct
00134 {
00135       UInt16 pad; // all 0
00136       UInt8 errorClass;
00137       UInt8 number;
00138       char reason[STUN_MAX_STRING];
00139       UInt16 sizeReason;
00140 } StunAtrError;
00141 
00142 typedef struct
00143 {
00144       UInt16 attrType[STUN_MAX_UNKNOWN_ATTRIBUTES];
00145       UInt16 numAttributes;
00146 } StunAtrUnknown;
00147 
00148 typedef struct
00149 {
00150       char value[STUN_MAX_STRING];      
00151       UInt16 sizeValue;
00152 } StunAtrString;
00153 
00154 typedef struct
00155 {
00156       char hash[20];
00157 } StunAtrIntegrity;
00158 
00159 
00160 enum StunHmacStatus
00161 {
00162    HmacUnknown=0,
00163    HmacOK,
00164    HmacBadUserName,
00165    HmacUnknownUserName,
00166    HmacFailed
00167 };
00168 
00169 
00170 typedef struct
00171 {
00172       StunMsgHdr msgHdr;
00173         
00174       bool hasMappedAddress;
00175       StunAtrAddress4  mappedAddress;
00176         
00177       bool hasResponseAddress;
00178       StunAtrAddress4  responseAddress;
00179         
00180       bool hasChangeRequest;
00181       StunAtrChangeRequest changeRequest;
00182         
00183       bool hasSourceAddress;
00184       StunAtrAddress4 sourceAddress;
00185         
00186       bool hasChangedAddress;
00187       StunAtrAddress4 changedAddress;
00188         
00189       bool hasUsername;
00190       StunAtrString username;
00191         
00192       bool hasPassword;
00193       StunAtrString password;
00194         
00195       bool hasMessageIntegrity;
00196       StunAtrIntegrity messageIntegrity;
00197         
00198       bool hasErrorCode;
00199       StunAtrError errorCode;
00200         
00201       bool hasUnknownAttributes;
00202       StunAtrUnknown unknownAttributes;
00203         
00204       bool hasReflectedFrom;
00205       StunAtrAddress4 reflectedFrom;
00206 
00207       bool hasXorMappedAddress;
00208       StunAtrAddress4  xorMappedAddress;
00209         
00210       bool xorOnly;
00211 
00212       bool hasServerName;
00213       StunAtrString serverName;
00214       
00215       bool hasSecondaryAddress;
00216       StunAtrAddress4 secondaryAddress;
00217 
00218       bool hasTurnLifetime;
00219       UInt32 turnLifetime;
00220       
00221       bool hasTurnAlternateServer;
00222       StunAtrAddress4 turnAlternateServer;
00223       
00224       bool hasTurnMagicCookie;
00225       UInt32 turnMagicCookie;
00226       
00227       bool hasTurnBandwidth;
00228       UInt32 turnBandwidth;
00229       
00230       bool hasTurnDestinationAddress;
00231       StunAtrAddress4 turnDestinationAddress;
00232       
00233       bool hasTurnRemoteAddress;
00234       StunAtrAddress4 turnRemoteAddress;
00235       
00236       bool hasTurnData;
00237       resip::Data* turnData;
00238       
00239       //bool hasTurnNonce;
00240       // turnNonce;
00241       
00242       //bool hasTurnRealm;
00243       // turnRealm;
00244 } StunMessage; 
00245 
00246 
00247 // Define enum with different types of NAT 
00248 enum NatType
00249 {
00250    StunTypeUnknown=0,
00251    StunTypeFailure,
00252    StunTypeOpen,
00253    StunTypeBlocked,
00254 
00255    StunTypeIndependentFilter,
00256    StunTypeDependentFilter,
00257    StunTypePortDependedFilter,
00258    StunTypeDependentMapping,
00259 
00260    //StunTypeConeNat,
00261    //StunTypeRestrictedNat,
00262    //StunTypePortRestrictedNat,
00263    //StunTypeSymNat,
00264    
00265    StunTypeFirewall
00266 };
00267 
00268 
00269 #define MAX_MEDIA_RELAYS 500
00270 #define MAX_RTP_MSG_SIZE 1500
00271 #define MEDIA_RELAY_TIMEOUT 3*60
00272 
00273 typedef struct 
00274 {
00275       int relayPort;       // media relay port
00276       int fd;              // media relay file descriptor
00277       StunAddress4 destination; // NAT IP:port
00278       time_t expireTime;      // if no activity after time, close the socket 
00279 } StunMediaRelay;
00280 
00281 typedef struct
00282 {
00283       StunAddress4 myAddr;
00284       StunAddress4 altAddr;
00285       resip::Socket myFd;
00286       resip::Socket altPortFd;
00287       resip::Socket altIpFd;
00288       resip::Socket altIpPortFd;
00289       bool relay; // true if media relaying is to be done
00290       StunMediaRelay relays[MAX_MEDIA_RELAYS];
00291 } StunServerInfo;
00292 
00293 bool
00294 stunParseMessage( char* buf, 
00295                   unsigned int bufLen, 
00296                   StunMessage& message, 
00297                   bool verbose );
00298 
00299 void
00300 stunBuildReqSimple( StunMessage* msg,
00301                     const StunAtrString& username,
00302                     bool changePort, bool changeIp, unsigned int id=0 );
00303 
00304 unsigned int
00305 stunEncodeMessage( const StunMessage& message, 
00306                    char* buf, 
00307                    unsigned int bufLen, 
00308                    const StunAtrString& password,
00309                    bool verbose);
00310 
00311 void
00312 stunCreateUserName(const StunAddress4& addr, StunAtrString* username);
00313 
00314 void 
00315 stunGetUserNameAndPassword(  const StunAddress4& dest, 
00316                              StunAtrString* username,
00317                              StunAtrString* password);
00318 
00319 void
00320 stunCreatePassword(const StunAtrString& username, StunAtrString* password);
00321 
00322 int 
00323 stunRand();
00324 
00325 UInt64
00326 stunGetSystemTimeSecs();
00327 
00329 bool  
00330 stunParseServerName( char* serverName, StunAddress4& stunServerAddr);
00331 
00332 bool 
00333 stunParseHostName( char* peerName,
00334                    UInt32& ip,
00335                    UInt16& portVal,
00336                    UInt16 defaultPort );
00337 
00340 bool
00341 stunInitServer(StunServerInfo& info, 
00342                const StunAddress4& myAddr, 
00343                const StunAddress4& altAddr,
00344                int startMediaPort,
00345                bool verbose);
00346 
00347 void
00348 stunStopServer(StunServerInfo& info);
00349 
00351 bool
00352 stunServerProcess(StunServerInfo& info, bool verbose);
00353 
00355 int 
00356 stunFindLocalInterfaces(UInt32* addresses, int maxSize );
00357 
00358 bool 
00359 stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* srcAddr=0, unsigned long timeoutMs=5000 );
00360 
00361 NatType
00362 stunNatType( StunAddress4& dest, bool verbose, 
00363              bool* preservePort=0, // if set, is return for if NAT preservers ports or not
00364              bool* hairpin=0 ,  // if set, is the return for if NAT will hairpin packets
00365              int port=0, // port to use for the test, 0 to choose random port
00366              StunAddress4* sAddr=0 // NIC to use 
00367    );
00368 
00370 std::ostream& 
00371 operator<<( std::ostream& strm, const StunAddress4& addr);
00372 
00373 std::ostream& 
00374 operator<< ( std::ostream& strm, const UInt128& );
00375 
00376 std::ostream& 
00377 operator<< ( std::ostream& strm, const StunMsgHdr& );
00378 
00379 bool
00380 stunServerProcessMsg( char* buf,
00381                       unsigned int bufLen,
00382                       StunAddress4& from, 
00383                       StunAddress4& secondary,
00384                       StunAddress4& myAddr,
00385                       StunAddress4& altAddr, 
00386                       StunMessage* resp,
00387                       StunAddress4* destination,
00388                       StunAtrString* hmacPassword,
00389                       bool* changePort,
00390                       bool* changeIp,
00391                       bool verbose);
00392 
00393 int
00394 stunOpenSocket( StunAddress4& dest, 
00395                 StunAddress4* mappedAddr, 
00396                 int port=0, 
00397                 StunAddress4* srcAddr=0, 
00398                 bool verbose=false );
00399 
00400 bool
00401 stunOpenSocketPair( StunAddress4& dest, StunAddress4* mappedAddr, 
00402                     int* fd1, int* fd2, 
00403                     int srcPort=0,  StunAddress4* srcAddr=0,
00404                     bool verbose=false);
00405 
00406 int
00407 stunRandomPort();
00408 
00409 void computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey);
00410 
00411 #endif
00412 
00413 
00414 /* ====================================================================
00415  * The Vovida Software License, Version 1.0 
00416  * 
00417  * Redistribution and use in source and binary forms, with or without
00418  * modification, are permitted provided that the following conditions
00419  * are met:
00420  * 
00421  * 1. Redistributions of source code must retain the above copyright
00422  *    notice, this list of conditions and the following disclaimer.
00423  * 
00424  * 2. Redistributions in binary form must reproduce the above copyright
00425  *    notice, this list of conditions and the following disclaimer in
00426  *    the documentation and/or other materials provided with the
00427  *    distribution.
00428  * 
00429  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00430  *    and "Vovida Open Communication Application Library (VOCAL)" must
00431  *    not be used to endorse or promote products derived from this
00432  *    software without prior written permission. For written
00433  *    permission, please contact vocal@vovida.org.
00434  *
00435  * 4. Products derived from this software may not be called "VOCAL", nor
00436  *    may "VOCAL" appear in their name, without prior written
00437  *    permission of Vovida Networks, Inc.
00438  * 
00439  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00440  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00441  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00442  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00443  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00444  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00445  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00446  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00447  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00448  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00449  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00450  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00451  * DAMAGE.
00452  *
00453  */
00454 
00455 // Local Variables:
00456 // mode:c++
00457 // c-file-style:"ellemtel"
00458 // c-file-offsets:((case-label . +))
00459 // indent-tabs-mode:nil
00460 // End:
00461