StunPacket.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /**
  2. ISC License
  3. Copyright © 2015, Iñaki Baz Castillo <ibc@aliax.net>
  4. Permission to use, copy, modify, and/or distribute this software for any
  5. purpose with or without fee is hereby granted, provided that the above
  6. copyright notice and this permission notice appear in all copies.
  7. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. */
  15. #ifndef MS_RTC_STUN_PACKET_HPP
  16. #define MS_RTC_STUN_PACKET_HPP
  17. #include "logger.h"
  18. #include "Utils.hpp"
  19. #include <string>
  20. namespace RTC
  21. {
  22. class StunPacket
  23. {
  24. public:
  25. // STUN message class.
  26. enum class Class : uint16_t
  27. {
  28. REQUEST = 0,
  29. INDICATION = 1,
  30. SUCCESS_RESPONSE = 2,
  31. ERROR_RESPONSE = 3
  32. };
  33. // STUN message method.
  34. enum class Method : uint16_t
  35. {
  36. BINDING = 1
  37. };
  38. // Attribute type.
  39. enum class Attribute : uint16_t
  40. {
  41. MAPPED_ADDRESS = 0x0001,
  42. USERNAME = 0x0006,
  43. MESSAGE_INTEGRITY = 0x0008,
  44. ERROR_CODE = 0x0009,
  45. UNKNOWN_ATTRIBUTES = 0x000A,
  46. REALM = 0x0014,
  47. NONCE = 0x0015,
  48. XOR_MAPPED_ADDRESS = 0x0020,
  49. PRIORITY = 0x0024,
  50. USE_CANDIDATE = 0x0025,
  51. SOFTWARE = 0x8022,
  52. ALTERNATE_SERVER = 0x8023,
  53. FINGERPRINT = 0x8028,
  54. ICE_CONTROLLED = 0x8029,
  55. ICE_CONTROLLING = 0x802A
  56. };
  57. // Authentication result.
  58. enum class Authentication
  59. {
  60. OK = 0,
  61. UNAUTHORIZED = 1,
  62. BAD_REQUEST = 2
  63. };
  64. public:
  65. static bool IsStun(const uint8_t* data, size_t len)
  66. {
  67. // clang-format off
  68. return (
  69. // STUN headers are 20 bytes.
  70. (len >= 20) &&
  71. // DOC: https://tools.ietf.org/html/draft-ietf-avtcore-rfc5764-mux-fixes
  72. (data[0] < 3) &&
  73. // Magic cookie must match.
  74. (data[4] == StunPacket::magicCookie[0]) && (data[5] == StunPacket::magicCookie[1]) &&
  75. (data[6] == StunPacket::magicCookie[2]) && (data[7] == StunPacket::magicCookie[3])
  76. );
  77. // clang-format on
  78. }
  79. static StunPacket* Parse(const uint8_t* data, size_t len);
  80. private:
  81. static const uint8_t magicCookie[];
  82. public:
  83. StunPacket(
  84. Class klass, Method method, const uint8_t* transactionId, const uint8_t* data, size_t size);
  85. ~StunPacket();
  86. void Dump() const;
  87. Class GetClass() const
  88. {
  89. return this->klass;
  90. }
  91. Method GetMethod() const
  92. {
  93. return this->method;
  94. }
  95. const uint8_t* GetData() const
  96. {
  97. return this->data;
  98. }
  99. size_t GetSize() const
  100. {
  101. return this->size;
  102. }
  103. void SetUsername(const char* username, size_t len)
  104. {
  105. this->username.assign(username, len);
  106. }
  107. void SetPriority(uint32_t priority)
  108. {
  109. this->priority = priority;
  110. }
  111. void SetIceControlling(uint64_t iceControlling)
  112. {
  113. this->iceControlling = iceControlling;
  114. }
  115. void SetIceControlled(uint64_t iceControlled)
  116. {
  117. this->iceControlled = iceControlled;
  118. }
  119. void SetUseCandidate()
  120. {
  121. this->hasUseCandidate = true;
  122. }
  123. void SetXorMappedAddress(const struct sockaddr* xorMappedAddress)
  124. {
  125. this->xorMappedAddress = xorMappedAddress;
  126. }
  127. void SetErrorCode(uint16_t errorCode)
  128. {
  129. this->errorCode = errorCode;
  130. }
  131. void SetMessageIntegrity(const uint8_t* messageIntegrity)
  132. {
  133. this->messageIntegrity = messageIntegrity;
  134. }
  135. void SetFingerprint()
  136. {
  137. this->hasFingerprint = true;
  138. }
  139. const std::string& GetUsername() const
  140. {
  141. return this->username;
  142. }
  143. uint32_t GetPriority() const
  144. {
  145. return this->priority;
  146. }
  147. uint64_t GetIceControlling() const
  148. {
  149. return this->iceControlling;
  150. }
  151. uint64_t GetIceControlled() const
  152. {
  153. return this->iceControlled;
  154. }
  155. bool HasUseCandidate() const
  156. {
  157. return this->hasUseCandidate;
  158. }
  159. uint16_t GetErrorCode() const
  160. {
  161. return this->errorCode;
  162. }
  163. bool HasMessageIntegrity() const
  164. {
  165. return (this->messageIntegrity ? true : false);
  166. }
  167. bool HasFingerprint() const
  168. {
  169. return this->hasFingerprint;
  170. }
  171. Authentication CheckAuthentication(
  172. const std::string& localUsername, const std::string& localPassword);
  173. StunPacket* CreateSuccessResponse();
  174. StunPacket* CreateErrorResponse(uint16_t errorCode);
  175. void Authenticate(const std::string& password);
  176. void Serialize(uint8_t* buffer);
  177. private:
  178. // Passed by argument.
  179. Class klass; // 2 bytes.
  180. Method method; // 2 bytes.
  181. const uint8_t* transactionId{ nullptr }; // 12 bytes.
  182. uint8_t* data{ nullptr }; // Pointer to binary data.
  183. size_t size{ 0u }; // The full message size (including header).
  184. // STUN attributes.
  185. std::string username; // Less than 513 bytes.
  186. uint32_t priority{ 0u }; // 4 bytes unsigned integer.
  187. uint64_t iceControlling{ 0u }; // 8 bytes unsigned integer.
  188. uint64_t iceControlled{ 0u }; // 8 bytes unsigned integer.
  189. bool hasUseCandidate{ false }; // 0 bytes.
  190. const uint8_t* messageIntegrity{ nullptr }; // 20 bytes.
  191. bool hasFingerprint{ false }; // 4 bytes.
  192. const struct sockaddr* xorMappedAddress{ nullptr }; // 8 or 20 bytes.
  193. uint16_t errorCode{ 0u }; // 4 bytes (no reason phrase).
  194. std::string password;
  195. };
  196. } // namespace RTC
  197. #endif