Home | History | Annotate | Download | only in base
      1 /*
      2  * libjingle
      3  * Copyright 2004--2005, Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #ifndef TALK_P2P_BASE_STUN_H_
     29 #define TALK_P2P_BASE_STUN_H_
     30 
     31 // This file contains classes for dealing with the STUN protocol, as specified
     32 // in RFC 5389, and its descendants.
     33 
     34 #include <string>
     35 #include <vector>
     36 
     37 #include "talk/base/basictypes.h"
     38 #include "talk/base/bytebuffer.h"
     39 #include "talk/base/socketaddress.h"
     40 
     41 namespace cricket {
     42 
     43 // These are the types of STUN messages defined in RFC 5389.
     44 enum StunMessageType {
     45   STUN_BINDING_REQUEST                  = 0x0001,
     46   STUN_BINDING_INDICATION               = 0x0011,
     47   STUN_BINDING_RESPONSE                 = 0x0101,
     48   STUN_BINDING_ERROR_RESPONSE           = 0x0111,
     49 };
     50 
     51 // These are all known STUN attributes, defined in RFC 5389 and elsewhere.
     52 // Next to each is the name of the class (T is StunTAttribute) that implements
     53 // that type.
     54 // RETRANSMIT_COUNT is the number of outstanding pings without a response at
     55 // the time the packet is generated.
     56 enum StunAttributeType {
     57   STUN_ATTR_MAPPED_ADDRESS              = 0x0001,  // Address
     58   STUN_ATTR_USERNAME                    = 0x0006,  // ByteString
     59   STUN_ATTR_MESSAGE_INTEGRITY           = 0x0008,  // ByteString, 20 bytes
     60   STUN_ATTR_ERROR_CODE                  = 0x0009,  // ErrorCode
     61   STUN_ATTR_UNKNOWN_ATTRIBUTES          = 0x000a,  // UInt16List
     62   STUN_ATTR_REALM                       = 0x0014,  // ByteString
     63   STUN_ATTR_NONCE                       = 0x0015,  // ByteString
     64   STUN_ATTR_XOR_MAPPED_ADDRESS          = 0x0020,  // XorAddress
     65   STUN_ATTR_SOFTWARE                    = 0x8022,  // ByteString
     66   STUN_ATTR_ALTERNATE_SERVER            = 0x8023,  // ByteString
     67   STUN_ATTR_FINGERPRINT                 = 0x8028,  // UInt32
     68   STUN_ATTR_RETRANSMIT_COUNT            = 0xFF00   // UInt32
     69 };
     70 
     71 // These are the types of the values associated with the attributes above.
     72 // This allows us to perform some basic validation when reading or adding
     73 // attributes. Note that these values are for our own use, and not defined in
     74 // RFC 5389.
     75 enum StunAttributeValueType {
     76   STUN_VALUE_UNKNOWN                    = 0,
     77   STUN_VALUE_ADDRESS                    = 1,
     78   STUN_VALUE_XOR_ADDRESS                = 2,
     79   STUN_VALUE_UINT32                     = 3,
     80   STUN_VALUE_UINT64                     = 4,
     81   STUN_VALUE_BYTE_STRING                = 5,
     82   STUN_VALUE_ERROR_CODE                 = 6,
     83   STUN_VALUE_UINT16_LIST                = 7
     84 };
     85 
     86 // These are the types of STUN addresses defined in RFC 5389.
     87 enum StunAddressFamily {
     88   // NB: UNDEF is not part of the STUN spec.
     89   STUN_ADDRESS_UNDEF                    = 0,
     90   STUN_ADDRESS_IPV4                     = 1,
     91   STUN_ADDRESS_IPV6                     = 2
     92 };
     93 
     94 // These are the types of STUN error codes defined in RFC 5389.
     95 enum StunErrorCode {
     96   STUN_ERROR_TRY_ALTERNATE              = 300,
     97   STUN_ERROR_BAD_REQUEST                = 400,
     98   STUN_ERROR_UNAUTHORIZED               = 401,
     99   STUN_ERROR_UNKNOWN_ATTRIBUTE          = 420,
    100   STUN_ERROR_STALE_CREDENTIALS          = 430,  // GICE only
    101   STUN_ERROR_STALE_NONCE                = 438,
    102   STUN_ERROR_SERVER_ERROR               = 500,
    103   STUN_ERROR_GLOBAL_FAILURE             = 600
    104 };
    105 
    106 // Strings for the error codes above.
    107 extern const char STUN_ERROR_REASON_BAD_REQUEST[];
    108 extern const char STUN_ERROR_REASON_UNAUTHORIZED[];
    109 extern const char STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE[];
    110 extern const char STUN_ERROR_REASON_STALE_CREDENTIALS[];
    111 extern const char STUN_ERROR_REASON_STALE_NONCE[];
    112 extern const char STUN_ERROR_REASON_SERVER_ERROR[];
    113 
    114 // The mask used to determine whether a STUN message is a request/response etc.
    115 const uint32 kStunTypeMask = 0x0110;
    116 
    117 // STUN Attribute header length.
    118 const size_t kStunAttributeHeaderSize = 4;
    119 
    120 // Following values correspond to RFC5389.
    121 const size_t kStunHeaderSize = 20;
    122 const size_t kStunTransactionIdOffset = 8;
    123 const size_t kStunTransactionIdLength = 12;
    124 const uint32 kStunMagicCookie = 0x2112A442;
    125 const size_t kStunMagicCookieLength = sizeof(kStunMagicCookie);
    126 
    127 // Following value corresponds to an earlier version of STUN from
    128 // RFC3489.
    129 const size_t kStunLegacyTransactionIdLength = 16;
    130 
    131 // STUN Message Integrity HMAC length.
    132 const size_t kStunMessageIntegritySize = 20;
    133 
    134 class StunAttribute;
    135 class StunAddressAttribute;
    136 class StunXorAddressAttribute;
    137 class StunUInt32Attribute;
    138 class StunUInt64Attribute;
    139 class StunByteStringAttribute;
    140 class StunErrorCodeAttribute;
    141 class StunUInt16ListAttribute;
    142 
    143 // Records a complete STUN/TURN message.  Each message consists of a type and
    144 // any number of attributes.  Each attribute is parsed into an instance of an
    145 // appropriate class (see above).  The Get* methods will return instances of
    146 // that attribute class.
    147 class StunMessage {
    148  public:
    149   StunMessage();
    150   virtual ~StunMessage();
    151 
    152   int type() const { return type_; }
    153   size_t length() const { return length_; }
    154   const std::string& transaction_id() const { return transaction_id_; }
    155 
    156   // Returns true if the message confirms to RFC3489 rather than
    157   // RFC5389. The main difference between two version of the STUN
    158   // protocol is the presence of the magic cookie and different length
    159   // of transaction ID. For outgoing packets version of the protocol
    160   // is determined by the lengths of the transaction ID.
    161   bool IsLegacy() const;
    162 
    163   void SetType(int type) { type_ = static_cast<uint16>(type); }
    164   bool SetTransactionID(const std::string& str);
    165 
    166   // Gets the desired attribute value, or NULL if no such attribute type exists.
    167   const StunAddressAttribute* GetAddress(int type) const;
    168   const StunUInt32Attribute* GetUInt32(int type) const;
    169   const StunUInt64Attribute* GetUInt64(int type) const;
    170   const StunByteStringAttribute* GetByteString(int type) const;
    171 
    172   // Gets these specific attribute values.
    173   const StunErrorCodeAttribute* GetErrorCode() const;
    174   const StunUInt16ListAttribute* GetUnknownAttributes() const;
    175 
    176   // Takes ownership of the specified attribute, verifies it is of the correct
    177   // type, and adds it to the message. The return value indicates whether this
    178   // was successful.
    179   bool AddAttribute(StunAttribute* attr);
    180 
    181   // Validates that a raw STUN message has a correct MESSAGE-INTEGRITY value.
    182   // This can't currently be done on a StunMessage, since it is affected by
    183   // padding data (which we discard when reading a StunMessage).
    184   static bool ValidateMessageIntegrity(const char* data, size_t size,
    185                                        const std::string& password);
    186   // Adds a MESSAGE-INTEGRITY attribute that is valid for the current message.
    187   bool AddMessageIntegrity(const std::string& password);
    188   bool AddMessageIntegrity(const char* key, size_t keylen);
    189 
    190   // Verifies that a given buffer is STUN by checking for a correct FINGERPRINT.
    191   static bool ValidateFingerprint(const char* data, size_t size);
    192 
    193   // Adds a FINGERPRINT attribute that is valid for the current message.
    194   bool AddFingerprint();
    195 
    196   // Parses the STUN packet in the given buffer and records it here. The
    197   // return value indicates whether this was successful.
    198   bool Read(talk_base::ByteBuffer* buf);
    199 
    200   // Writes this object into a STUN packet. The return value indicates whether
    201   // this was successful.
    202   bool Write(talk_base::ByteBuffer* buf) const;
    203 
    204   // Creates an empty message. Overridable by derived classes.
    205   virtual StunMessage* CreateNew() const { return new StunMessage(); }
    206 
    207  protected:
    208   // Verifies that the given attribute is allowed for this message.
    209   virtual StunAttributeValueType GetAttributeValueType(int type) const;
    210 
    211  private:
    212   StunAttribute* CreateAttribute(int type, size_t length) /* const*/;
    213   const StunAttribute* GetAttribute(int type) const;
    214   static bool IsValidTransactionId(const std::string& transaction_id);
    215 
    216   uint16 type_;
    217   uint16 length_;
    218   std::string transaction_id_;
    219   std::vector<StunAttribute*>* attrs_;
    220 };
    221 
    222 // Base class for all STUN/TURN attributes.
    223 class StunAttribute {
    224  public:
    225   virtual ~StunAttribute() {
    226   }
    227 
    228   int type() const { return type_; }
    229   size_t length() const { return length_; }
    230 
    231   // Return the type of this attribute.
    232   virtual StunAttributeValueType value_type() const = 0;
    233 
    234   // Only XorAddressAttribute needs this so far.
    235   virtual void SetOwner(StunMessage* owner) {}
    236 
    237   // Reads the body (not the type or length) for this type of attribute from
    238   // the given buffer.  Return value is true if successful.
    239   virtual bool Read(talk_base::ByteBuffer* buf) = 0;
    240 
    241   // Writes the body (not the type or length) to the given buffer.  Return
    242   // value is true if successful.
    243   virtual bool Write(talk_base::ByteBuffer* buf) const = 0;
    244 
    245   // Creates an attribute object with the given type and smallest length.
    246   static StunAttribute* Create(StunAttributeValueType value_type, uint16 type,
    247                                uint16 length, StunMessage* owner);
    248   // TODO: Allow these create functions to take parameters, to reduce
    249   // the amount of work callers need to do to initialize attributes.
    250   static StunAddressAttribute* CreateAddress(uint16 type);
    251   static StunXorAddressAttribute* CreateXorAddress(uint16 type);
    252   static StunUInt32Attribute* CreateUInt32(uint16 type);
    253   static StunUInt64Attribute* CreateUInt64(uint16 type);
    254   static StunByteStringAttribute* CreateByteString(uint16 type);
    255   static StunErrorCodeAttribute* CreateErrorCode();
    256   static StunUInt16ListAttribute* CreateUnknownAttributes();
    257 
    258  protected:
    259   StunAttribute(uint16 type, uint16 length);
    260   void SetLength(uint16 length) { length_ = length; }
    261   void WritePadding(talk_base::ByteBuffer* buf) const;
    262   void ConsumePadding(talk_base::ByteBuffer* buf) const;
    263 
    264  private:
    265   uint16 type_;
    266   uint16 length_;
    267 };
    268 
    269 // Implements STUN attributes that record an Internet address.
    270 class StunAddressAttribute : public StunAttribute {
    271  public:
    272   static const uint16 SIZE_UNDEF = 0;
    273   static const uint16 SIZE_IP4 = 8;
    274   static const uint16 SIZE_IP6 = 20;
    275   StunAddressAttribute(uint16 type, const talk_base::SocketAddress& addr);
    276   StunAddressAttribute(uint16 type, uint16 length);
    277 
    278   virtual StunAttributeValueType value_type() const {
    279     return STUN_VALUE_ADDRESS;
    280   }
    281 
    282   StunAddressFamily family() const {
    283     switch (address_.ipaddr().family()) {
    284       case AF_INET:
    285         return STUN_ADDRESS_IPV4;
    286       case AF_INET6:
    287         return STUN_ADDRESS_IPV6;
    288     }
    289     return STUN_ADDRESS_UNDEF;
    290   }
    291 
    292   const talk_base::SocketAddress& GetAddress() const { return address_; }
    293   const talk_base::IPAddress& ipaddr() const { return address_.ipaddr(); }
    294   uint16 port() const { return address_.port(); }
    295 
    296   void SetAddress(const talk_base::SocketAddress& addr) {
    297     address_ = addr;
    298     EnsureAddressLength();
    299   }
    300   void SetIP(const talk_base::IPAddress& ip) {
    301     address_.SetIP(ip);
    302     EnsureAddressLength();
    303   }
    304   void SetPort(uint16 port) { address_.SetPort(port); }
    305 
    306   virtual bool Read(talk_base::ByteBuffer* buf);
    307   virtual bool Write(talk_base::ByteBuffer* buf) const;
    308 
    309  private:
    310   void EnsureAddressLength() {
    311     switch (family()) {
    312       case STUN_ADDRESS_IPV4: {
    313         SetLength(SIZE_IP4);
    314         break;
    315       }
    316       case STUN_ADDRESS_IPV6: {
    317         SetLength(SIZE_IP6);
    318         break;
    319       }
    320       default: {
    321         SetLength(SIZE_UNDEF);
    322         break;
    323       }
    324     }
    325   }
    326   talk_base::SocketAddress address_;
    327 };
    328 
    329 // Implements STUN attributes that record an Internet address. When encoded
    330 // in a STUN message, the address contained in this attribute is XORed with the
    331 // transaction ID of the message.
    332 class StunXorAddressAttribute : public StunAddressAttribute {
    333  public:
    334   StunXorAddressAttribute(uint16 type, const talk_base::SocketAddress& addr);
    335   StunXorAddressAttribute(uint16 type, uint16 length,
    336                           StunMessage* owner);
    337 
    338   virtual StunAttributeValueType value_type() const {
    339     return STUN_VALUE_XOR_ADDRESS;
    340   }
    341   virtual void SetOwner(StunMessage* owner) {
    342     owner_ = owner;
    343   }
    344   virtual bool Read(talk_base::ByteBuffer* buf);
    345   virtual bool Write(talk_base::ByteBuffer* buf) const;
    346 
    347  private:
    348   talk_base::IPAddress GetXoredIP() const;
    349   StunMessage* owner_;
    350 };
    351 
    352 // Implements STUN attributes that record a 32-bit integer.
    353 class StunUInt32Attribute : public StunAttribute {
    354  public:
    355   static const uint16 SIZE = 4;
    356   StunUInt32Attribute(uint16 type, uint32 value);
    357   explicit StunUInt32Attribute(uint16 type);
    358 
    359   virtual StunAttributeValueType value_type() const {
    360     return STUN_VALUE_UINT32;
    361   }
    362 
    363   uint32 value() const { return bits_; }
    364   void SetValue(uint32 bits) { bits_ = bits; }
    365 
    366   bool GetBit(size_t index) const;
    367   void SetBit(size_t index, bool value);
    368 
    369   virtual bool Read(talk_base::ByteBuffer* buf);
    370   virtual bool Write(talk_base::ByteBuffer* buf) const;
    371 
    372  private:
    373   uint32 bits_;
    374 };
    375 
    376 class StunUInt64Attribute : public StunAttribute {
    377  public:
    378   static const uint16 SIZE = 8;
    379   StunUInt64Attribute(uint16 type, uint64 value);
    380   explicit StunUInt64Attribute(uint16 type);
    381 
    382   virtual StunAttributeValueType value_type() const {
    383     return STUN_VALUE_UINT64;
    384   }
    385 
    386   uint64 value() const { return bits_; }
    387   void SetValue(uint64 bits) { bits_ = bits; }
    388 
    389   virtual bool Read(talk_base::ByteBuffer* buf);
    390   virtual bool Write(talk_base::ByteBuffer* buf) const;
    391 
    392  private:
    393   uint64 bits_;
    394 };
    395 
    396 // Implements STUN attributes that record an arbitrary byte string.
    397 class StunByteStringAttribute : public StunAttribute {
    398  public:
    399   explicit StunByteStringAttribute(uint16 type);
    400   StunByteStringAttribute(uint16 type, const std::string& str);
    401   StunByteStringAttribute(uint16 type, const void* bytes, size_t length);
    402   StunByteStringAttribute(uint16 type, uint16 length);
    403   ~StunByteStringAttribute();
    404 
    405   virtual StunAttributeValueType value_type() const {
    406     return STUN_VALUE_BYTE_STRING;
    407   }
    408 
    409   const char* bytes() const { return bytes_; }
    410   std::string GetString() const { return std::string(bytes_, length()); }
    411 
    412   void CopyBytes(const char* bytes);  // uses strlen
    413   void CopyBytes(const void* bytes, size_t length);
    414 
    415   uint8 GetByte(size_t index) const;
    416   void SetByte(size_t index, uint8 value);
    417 
    418   virtual bool Read(talk_base::ByteBuffer* buf);
    419   virtual bool Write(talk_base::ByteBuffer* buf) const;
    420 
    421  private:
    422   void SetBytes(char* bytes, size_t length);
    423 
    424   char* bytes_;
    425 };
    426 
    427 // Implements STUN attributes that record an error code.
    428 class StunErrorCodeAttribute : public StunAttribute {
    429  public:
    430   static const uint16 MIN_SIZE = 4;
    431   StunErrorCodeAttribute(uint16 type, int code, const std::string& reason);
    432   StunErrorCodeAttribute(uint16 type, uint16 length);
    433   ~StunErrorCodeAttribute();
    434 
    435   virtual StunAttributeValueType value_type() const {
    436     return STUN_VALUE_ERROR_CODE;
    437   }
    438 
    439   // The combined error and class, e.g. 0x400.
    440   int code() const;
    441   void SetCode(int code);
    442 
    443   // The individual error components.
    444   int eclass() const { return class_; }
    445   int number() const { return number_; }
    446   const std::string& reason() const { return reason_; }
    447   void SetClass(uint8 eclass) { class_ = eclass; }
    448   void SetNumber(uint8 number) { number_ = number; }
    449   void SetReason(const std::string& reason);
    450 
    451   bool Read(talk_base::ByteBuffer* buf);
    452   bool Write(talk_base::ByteBuffer* buf) const;
    453 
    454  private:
    455   uint8 class_;
    456   uint8 number_;
    457   std::string reason_;
    458 };
    459 
    460 // Implements STUN attributes that record a list of attribute names.
    461 class StunUInt16ListAttribute : public StunAttribute {
    462  public:
    463   StunUInt16ListAttribute(uint16 type, uint16 length);
    464   ~StunUInt16ListAttribute();
    465 
    466   virtual StunAttributeValueType value_type() const {
    467     return STUN_VALUE_UINT16_LIST;
    468   }
    469 
    470   size_t Size() const;
    471   uint16 GetType(int index) const;
    472   void SetType(int index, uint16 value);
    473   void AddType(uint16 value);
    474 
    475   bool Read(talk_base::ByteBuffer* buf);
    476   bool Write(talk_base::ByteBuffer* buf) const;
    477 
    478  private:
    479   std::vector<uint16>* attr_types_;
    480 };
    481 
    482 // Returns the (successful) response type for the given request type.
    483 // Returns -1 if |request_type| is not a valid request type.
    484 int GetStunSuccessResponseType(int request_type);
    485 
    486 // Returns the error response type for the given request type.
    487 // Returns -1 if |request_type| is not a valid request type.
    488 int GetStunErrorResponseType(int request_type);
    489 
    490 // Returns whether a given message is a request type.
    491 bool IsStunRequestType(int msg_type);
    492 
    493 // Returns whether a given message is an indication type.
    494 bool IsStunIndicationType(int msg_type);
    495 
    496 // Returns whether a given response is a success type.
    497 bool IsStunSuccessResponseType(int msg_type);
    498 
    499 // Returns whether a given response is an error type.
    500 bool IsStunErrorResponseType(int msg_type);
    501 
    502 // Computes the STUN long-term credential hash.
    503 bool ComputeStunCredentialHash(const std::string& username,
    504     const std::string& realm, const std::string& password, std::string* hash);
    505 
    506 // TODO: Move the TURN/ICE stuff below out to separate files.
    507 extern const char TURN_MAGIC_COOKIE_VALUE[4];
    508 
    509 // "GTURN" STUN methods.
    510 // TODO: Rename these methods to GTURN_ to make it clear they aren't
    511 // part of standard STUN/TURN.
    512 enum RelayMessageType {
    513   // For now, using the same defs from TurnMessageType below.
    514   // STUN_ALLOCATE_REQUEST              = 0x0003,
    515   // STUN_ALLOCATE_RESPONSE             = 0x0103,
    516   // STUN_ALLOCATE_ERROR_RESPONSE       = 0x0113,
    517   STUN_SEND_REQUEST                     = 0x0004,
    518   STUN_SEND_RESPONSE                    = 0x0104,
    519   STUN_SEND_ERROR_RESPONSE              = 0x0114,
    520   STUN_DATA_INDICATION                  = 0x0115,
    521 };
    522 
    523 // "GTURN"-specific STUN attributes.
    524 // TODO: Rename these attributes to GTURN_ to avoid conflicts.
    525 enum RelayAttributeType {
    526   STUN_ATTR_LIFETIME                    = 0x000d,  // UInt32
    527   STUN_ATTR_MAGIC_COOKIE                = 0x000f,  // ByteString, 4 bytes
    528   STUN_ATTR_BANDWIDTH                   = 0x0010,  // UInt32
    529   STUN_ATTR_DESTINATION_ADDRESS         = 0x0011,  // Address
    530   STUN_ATTR_SOURCE_ADDRESS2             = 0x0012,  // Address
    531   STUN_ATTR_DATA                        = 0x0013,  // ByteString
    532   STUN_ATTR_OPTIONS                     = 0x8001,  // UInt32
    533 };
    534 
    535 // A "GTURN" STUN message.
    536 class RelayMessage : public StunMessage {
    537  protected:
    538   virtual StunAttributeValueType GetAttributeValueType(int type) const {
    539     switch (type) {
    540       case STUN_ATTR_LIFETIME:            return STUN_VALUE_UINT32;
    541       case STUN_ATTR_MAGIC_COOKIE:        return STUN_VALUE_BYTE_STRING;
    542       case STUN_ATTR_BANDWIDTH:           return STUN_VALUE_UINT32;
    543       case STUN_ATTR_DESTINATION_ADDRESS: return STUN_VALUE_ADDRESS;
    544       case STUN_ATTR_SOURCE_ADDRESS2:     return STUN_VALUE_ADDRESS;
    545       case STUN_ATTR_DATA:                return STUN_VALUE_BYTE_STRING;
    546       case STUN_ATTR_OPTIONS:             return STUN_VALUE_UINT32;
    547       default: return StunMessage::GetAttributeValueType(type);
    548     }
    549   }
    550   virtual StunMessage* CreateNew() const { return new RelayMessage(); }
    551 };
    552 
    553 // Defined in TURN RFC 5766.
    554 enum TurnMessageType {
    555   STUN_ALLOCATE_REQUEST                 = 0x0003,
    556   STUN_ALLOCATE_RESPONSE                = 0x0103,
    557   STUN_ALLOCATE_ERROR_RESPONSE          = 0x0113,
    558   TURN_REFRESH_REQUEST                  = 0x0004,
    559   TURN_REFRESH_RESPONSE                 = 0x0104,
    560   TURN_REFRESH_ERROR_RESPONSE           = 0x0114,
    561   TURN_SEND_INDICATION                  = 0x0016,
    562   TURN_DATA_INDICATION                  = 0x0017,
    563   TURN_CREATE_PERMISSION_REQUEST        = 0x0008,
    564   TURN_CREATE_PERMISSION_RESPONSE       = 0x0108,
    565   TURN_CREATE_PERMISSION_ERROR_RESPONSE = 0x0118,
    566   TURN_CHANNEL_BIND_REQUEST             = 0x0009,
    567   TURN_CHANNEL_BIND_RESPONSE            = 0x0109,
    568   TURN_CHANNEL_BIND_ERROR_RESPONSE      = 0x0119,
    569 };
    570 
    571 enum TurnAttributeType {
    572   STUN_ATTR_CHANNEL_NUMBER              = 0x000C,  // UInt32
    573   STUN_ATTR_TURN_LIFETIME               = 0x000d,  // UInt32
    574   STUN_ATTR_XOR_PEER_ADDRESS            = 0x0012,  // XorAddress
    575   // TODO(mallinath) - Uncomment after RelayAttributes are renamed.
    576   // STUN_ATTR_DATA                     = 0x0013,  // ByteString
    577   STUN_ATTR_XOR_RELAYED_ADDRESS         = 0x0016,  // XorAddress
    578   STUN_ATTR_EVEN_PORT                   = 0x0018,  // ByteString, 1 byte.
    579   STUN_ATTR_REQUESTED_TRANSPORT         = 0x0019,  // UInt32
    580   STUN_ATTR_DONT_FRAGMENT               = 0x001A,  // No content, Length = 0
    581   STUN_ATTR_RESERVATION_TOKEN           = 0x0022,  // ByteString, 8 bytes.
    582   // TODO(mallinath) - Rename STUN_ATTR_TURN_LIFETIME to STUN_ATTR_LIFETIME and
    583   // STUN_ATTR_TURN_DATA to STUN_ATTR_DATA. Also rename RelayMessage attributes
    584   // by appending G to attribute name.
    585 };
    586 
    587 // RFC 5766-defined errors.
    588 enum TurnErrorType {
    589   STUN_ERROR_FORBIDDEN                  = 403,
    590   STUN_ERROR_ALLOCATION_MISMATCH        = 437,
    591   STUN_ERROR_WRONG_CREDENTIALS          = 441,
    592   STUN_ERROR_UNSUPPORTED_PROTOCOL       = 442
    593 };
    594 extern const char STUN_ERROR_REASON_FORBIDDEN[];
    595 extern const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[];
    596 extern const char STUN_ERROR_REASON_WRONG_CREDENTIALS[];
    597 extern const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[];
    598 class TurnMessage : public StunMessage {
    599  protected:
    600   virtual StunAttributeValueType GetAttributeValueType(int type) const {
    601     switch (type) {
    602       case STUN_ATTR_CHANNEL_NUMBER:      return STUN_VALUE_UINT32;
    603       case STUN_ATTR_TURN_LIFETIME:       return STUN_VALUE_UINT32;
    604       case STUN_ATTR_XOR_PEER_ADDRESS:    return STUN_VALUE_XOR_ADDRESS;
    605       case STUN_ATTR_DATA:                return STUN_VALUE_BYTE_STRING;
    606       case STUN_ATTR_XOR_RELAYED_ADDRESS: return STUN_VALUE_XOR_ADDRESS;
    607       case STUN_ATTR_EVEN_PORT:           return STUN_VALUE_BYTE_STRING;
    608       case STUN_ATTR_REQUESTED_TRANSPORT: return STUN_VALUE_UINT32;
    609       case STUN_ATTR_DONT_FRAGMENT:       return STUN_VALUE_BYTE_STRING;
    610       case STUN_ATTR_RESERVATION_TOKEN:   return STUN_VALUE_BYTE_STRING;
    611       default: return StunMessage::GetAttributeValueType(type);
    612     }
    613   }
    614   virtual StunMessage* CreateNew() const { return new TurnMessage(); }
    615 };
    616 
    617 // RFC 5245 ICE STUN attributes.
    618 enum IceAttributeType {
    619   STUN_ATTR_PRIORITY                    = 0x0024,  // UInt32
    620   STUN_ATTR_USE_CANDIDATE               = 0x0025,  // No content, Length = 0
    621   STUN_ATTR_ICE_CONTROLLED              = 0x8029,  // UInt64
    622   STUN_ATTR_ICE_CONTROLLING             = 0x802A   // UInt64
    623 };
    624 
    625 // RFC 5245-defined errors.
    626 enum IceErrorCode {
    627   STUN_ERROR_ROLE_CONFLICT              = 487,
    628 };
    629 extern const char STUN_ERROR_REASON_ROLE_CONFLICT[];
    630 
    631 // A RFC 5245 ICE STUN message.
    632 class IceMessage : public StunMessage {
    633  protected:
    634   virtual StunAttributeValueType GetAttributeValueType(int type) const {
    635     switch (type) {
    636       case STUN_ATTR_PRIORITY:        return STUN_VALUE_UINT32;
    637       case STUN_ATTR_USE_CANDIDATE:   return STUN_VALUE_BYTE_STRING;
    638       case STUN_ATTR_ICE_CONTROLLED:  return STUN_VALUE_UINT64;
    639       case STUN_ATTR_ICE_CONTROLLING: return STUN_VALUE_UINT64;
    640       default: return StunMessage::GetAttributeValueType(type);
    641     }
    642   }
    643   virtual StunMessage* CreateNew() const { return new IceMessage(); }
    644 };
    645 
    646 }  // namespace cricket
    647 
    648 #endif  // TALK_P2P_BASE_STUN_H_
    649