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

📄 pstun.cxx

📁 pwlib源码库
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * pstun.cxx * * STUN Client * * Portable Windows Library * * Copyright (c) 2003 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Contributor(s): ______________________________________. * * $Log: pstun.cxx,v $ * Revision 1.18  2005/07/13 11:15:26  csoutheren * Backported NAT abstraction files from isvo branch * * Revision 1.17  2005/06/20 10:55:17  rjongbloed * Changed the timeout and retries so if there is a blocking firewall it does not take 15 seconds to find out! * Added access functions so timeout and retries are application configurable. * Added function (and << operator) to get NAT type enum as string. * * Revision 1.16.4.1  2005/04/25 13:19:27  shorne * Add Support for other NAT methods * * Revision 1.16  2004/11/25 07:23:46  csoutheren * Added IsSupportingRTP function to simplify detecting when STUN supports RTP * * Revision 1.15  2004/10/26 05:58:23  csoutheren * Increased timeout on STUN responses to avoid spurious STUN failures due * to network trsffic/congestion etc * * Revision 1.14  2004/08/18 13:16:07  rjongbloed * Fixed STUN CreateSocketPair so first socket is always even. * * Revision 1.13  2004/03/14 05:47:52  rjongbloed * Fixed incorrect detection of symmetric NAT (eg Linux masquerading) and also *   some NAT systems which are partially blocked due to firewall rules. * * Revision 1.12  2004/02/24 11:15:48  rjongbloed * Added function to get external router address, also did a bunch of documentation. * * Revision 1.11  2004/02/17 11:11:05  rjongbloed * Added missing #pragma pack() to turn off byte alignment for the last class, thanks Ted Szoczei * * Revision 1.10  2004/01/17 17:54:02  rjongbloed * Added function to get server name from STUN client. * * Revision 1.9  2003/10/08 22:00:18  dereksmithies * Fix unsigned/signed warning message. Thanks to Craig Southeren. * * Revision 1.8  2003/10/05 00:56:25  rjongbloed * Rewrite of STUN to not to use imported code with undesirable license. * * Revision 1.5  2003/02/05 06:26:49  robertj * More work in making the STUN usable for Symmetric NAT systems. * * Revision 1.4  2003/02/04 07:02:17  robertj * Added ip/port version of constructor. * Removed creating sockets for Open type. * * Revision 1.3  2003/02/04 05:55:04  craigs * Added socket pair function * * Revision 1.2  2003/02/04 05:06:24  craigs * Added new functions * * Revision 1.1  2003/02/04 03:31:04  robertj * Added STUN * */#ifdef __GNUC__#pragma implementation "pstun.h"#endif#include <ptlib.h>#include <ptclib/pstun.h>#include <ptclib/random.h>// Sample server is at larry.gloo.net#define DEFAULT_REPLY_TIMEOUT 1000#define DEFAULT_POLL_RETRIES  5#define DEFAULT_NUM_SOCKETS_FOR_PAIRING 4///////////////////////////////////////////////////////////////////////PSTUNClient::PSTUNClient(const PString & server,                         WORD portBase, WORD portMax,                         WORD portPairBase, WORD portPairMax)  : serverAddress(0),    serverPort(DefaultPort),    replyTimeout(DEFAULT_REPLY_TIMEOUT),    pollRetries(DEFAULT_POLL_RETRIES),    numSocketsForPairing(DEFAULT_NUM_SOCKETS_FOR_PAIRING),    natType(UnknownNat),    cachedExternalAddress(0),    timeAddressObtained(0){  SetServer(server);  SetPortRanges(portBase, portMax, portPairBase, portPairMax);}PSTUNClient::PSTUNClient(const PIPSocket::Address & address, WORD port,                         WORD portBase, WORD portMax,                         WORD portPairBase, WORD portPairMax)  : serverAddress(address),    serverPort(port),    replyTimeout(DEFAULT_REPLY_TIMEOUT),    pollRetries(DEFAULT_POLL_RETRIES),    numSocketsForPairing(DEFAULT_NUM_SOCKETS_FOR_PAIRING),    natType(UnknownNat),    cachedExternalAddress(0),    timeAddressObtained(0){  SetPortRanges(portBase, portMax, portPairBase, portPairMax);}PString PSTUNClient::GetServer() const{  PStringStream str;  str << serverAddress << ':' << serverPort;  return str;}BOOL PSTUNClient::SetServer(const PString & server){  PINDEX colon = server.Find(':');  if (colon == P_MAX_INDEX) {    if (!PIPSocket::GetHostAddress(server, serverAddress))      return FALSE;  }  else {    if (!PIPSocket::GetHostAddress(server.Left(colon), serverAddress))      return FALSE;    serverPort = PIPSocket::GetPortByService("udp", server.Mid(colon+1));  }  return serverAddress.IsValid() && serverPort != 0;}BOOL PSTUNClient::SetServer(const PIPSocket::Address & address, WORD port){  serverAddress = address;  serverPort = port;  return serverAddress.IsValid() && serverPort != 0;}#pragma pack(1)struct PSTUNAttribute{  enum Types {    MAPPED_ADDRESS = 0x0001,    RESPONSE_ADDRESS = 0x0002,    CHANGE_REQUEST = 0x0003,    SOURCE_ADDRESS = 0x0004,    CHANGED_ADDRESS = 0x0005,    USERNAME = 0x0006,    PASSWORD = 0x0007,    MESSAGE_INTEGRITY = 0x0008,    ERROR_CODE = 0x0009,    UNKNOWN_ATTRIBUTES = 0x000a,    REFLECTED_FROM = 0x000b,  };    PUInt16b type;  PUInt16b length;    PSTUNAttribute * GetNext() const { return (PSTUNAttribute *)(((const BYTE *)this)+length+4); }};class PSTUNAddressAttribute : public PSTUNAttribute{public:  BYTE     pad;  BYTE     family;  PUInt16b port;  BYTE     ip[4];  PIPSocket::Address GetIP() const { return PIPSocket::Address(4, ip); }protected:  enum { SizeofAddressAttribute = sizeof(BYTE)+sizeof(BYTE)+sizeof(WORD)+sizeof(PIPSocket::Address) };  void InitAddrAttr(Types newType)  {    type = (WORD)newType;    length = SizeofAddressAttribute;	pad = 0;	family = 1;  }  bool IsValidAddrAttr(Types checkType) const  {    return type == checkType && length == SizeofAddressAttribute;  }};class PSTUNMappedAddress : public PSTUNAddressAttribute{public:  void Initialise() { InitAddrAttr(MAPPED_ADDRESS); }  bool IsValid() const { return IsValidAddrAttr(MAPPED_ADDRESS); }};class PSTUNChangedAddress : public PSTUNAddressAttribute{public:  void Initialise() { InitAddrAttr(CHANGED_ADDRESS); }  bool IsValid() const { return IsValidAddrAttr(CHANGED_ADDRESS); }};class PSTUNChangeRequest : public PSTUNAttribute{public:  BYTE flags[4];    PSTUNChangeRequest() { }  PSTUNChangeRequest(bool changeIP, bool changePort)  {    Initialise();    SetChangeIP(changeIP);    SetChangePort(changePort);  }  void Initialise()  {	type = CHANGE_REQUEST;	length = sizeof(flags);	memset(flags, 0, sizeof(flags));  }  bool IsValid() const { return type == CHANGE_REQUEST && length == sizeof(flags); }    bool GetChangeIP() const { return (flags[3]&4) != 0; }  void SetChangeIP(bool on) { if (on) flags[3] |= 4; else flags[3] &= ~4; }    bool GetChangePort() const { return (flags[3]&2) != 0; }  void SetChangePort(bool on) { if (on) flags[3] |= 2; else flags[3] &= ~2; }};class PSTUNMessageIntegrity : public PSTUNAttribute{public:  BYTE hmac[20];    void Initialise()  {    type = MESSAGE_INTEGRITY;    length = sizeof(hmac);    memset(hmac, 0, sizeof(hmac));  }  bool IsValid() const { return type == MESSAGE_INTEGRITY && length == sizeof(hmac); }};struct PSTUNMessageHeader{  PUInt16b       msgType;  PUInt16b       msgLength;  BYTE           transactionId[16];};#pragma pack()class PSTUNMessage : public PBYTEArray{public:  enum MsgType {    BindingRequest  = 0x0001,    BindingResponse = 0x0101,    BindingError    = 0x0111,          SharedSecretRequest  = 0x0002,    SharedSecretResponse = 0x0102,    SharedSecretError    = 0x0112,  };    PSTUNMessage()  { }    PSTUNMessage(MsgType newType, const BYTE * id = NULL)    : PBYTEArray(sizeof(PSTUNMessageHeader))  {    SetType(newType, id);  }  void SetType(MsgType newType, const BYTE * id = NULL)  {    SetMinSize(sizeof(PSTUNMessageHeader));    PSTUNMessageHeader * hdr = (PSTUNMessageHeader *)theArray;    hdr->msgType = (WORD)newType;    for (PINDEX i = 0; i < ((PINDEX)sizeof(hdr->transactionId)); i++)      hdr->transactionId[i] = id != NULL ? id[i] : (BYTE)PRandom::Number();  }  const PSTUNMessageHeader * operator->() const { return (PSTUNMessageHeader *)theArray; }    PSTUNAttribute * GetFirstAttribute() { return (PSTUNAttribute *)(theArray+sizeof(PSTUNMessageHeader)); }  bool Validate()  {    int length = ((PSTUNMessageHeader *)theArray)->msgLength;    PSTUNAttribute * attrib = GetFirstAttribute();    while (length > 0) {      length -= attrib->length + 4;      attrib = attrib->GetNext();    }    return length == 0;  // Exactly correct length  }  void AddAttribute(const PSTUNAttribute & attribute)  {    PSTUNMessageHeader * hdr = (PSTUNMessageHeader *)theArray;    int oldLength = hdr->msgLength;    int attrSize = attribute.length + 4;    int newLength = oldLength + attrSize;    hdr->msgLength = (WORD)newLength;    // hdr pointer may be invalidated by next statement    SetMinSize(newLength+sizeof(PSTUNMessageHeader));    memcpy(theArray+sizeof(PSTUNMessageHeader)+oldLength, &attribute, attrSize);  }  void SetAttribute(const PSTUNAttribute & attribute)  {    int length = ((PSTUNMessageHeader *)theArray)->msgLength;    PSTUNAttribute * attrib = GetFirstAttribute();    while (length > 0) {      if (attrib->type == attribute.type) {        if (attrib->length == attribute.length)          *attrib = attribute;        else {          // More here        }        return;      }      length -= attrib->length + 4;      attrib = attrib->GetNext();    }    AddAttribute(attribute);  }  PSTUNAttribute * FindAttribute(PSTUNAttribute::Types type)  {    int length = ((PSTUNMessageHeader *)theArray)->msgLength;    PSTUNAttribute * attrib = GetFirstAttribute();    while (length > 0) {      if (attrib->type == type)        return attrib;      length -= attrib->length + 4;      attrib = attrib->GetNext();    }    return NULL;  }  bool Read(PUDPSocket & socket)  {    if (!socket.Read(GetPointer(1000), 1000))      return false;    SetSize(socket.GetLastReadCount());    return true;  }    bool Write(PUDPSocket & socket) const  {    return socket.Write(theArray, ((PSTUNMessageHeader *)theArray)->msgLength+sizeof(PSTUNMessageHeader)) != FALSE;  }  bool Poll(PUDPSocket & socket, const PSTUNMessage & request, PINDEX pollRetries)  {    for (PINDEX retry = 0; retry < pollRetries; retry++) {      if (!request.Write(socket))        break;      if (Read(socket) && Validate() &&            memcmp(request->transactionId, (*this)->transactionId, sizeof(request->transactionId)) == 0)        return true;    }    return false;

⌨️ 快捷键说明

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