TurnMsgLib.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. /*
  2. * Copyright (C) 2011, 2012, 2013 Citrix Systems
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the project nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. #ifndef __LIB_TURN_MSG_CPP__
  31. #define __LIB_TURN_MSG_CPP__
  32. #include "ns_turn_ioaddr.h"
  33. #include "ns_turn_msg.h"
  34. #include <string>
  35. namespace turn {
  36. class StunAttr;
  37. /**
  38. * Exception "end of buffer"
  39. */
  40. class EndOfStunMsgException {
  41. public:
  42. EndOfStunMsgException() {}
  43. virtual ~EndOfStunMsgException() {}
  44. };
  45. /**
  46. * Exception "wrong format of StunAttr"
  47. */
  48. class WrongStunAttrFormatException {
  49. public:
  50. WrongStunAttrFormatException() {}
  51. virtual ~WrongStunAttrFormatException() {}
  52. };
  53. /**
  54. * Exception "wrong format of StunBuffer"
  55. */
  56. class WrongStunBufferFormatException {
  57. public:
  58. WrongStunBufferFormatException() {}
  59. virtual ~WrongStunBufferFormatException() {}
  60. };
  61. /**
  62. * Iterator class for attributes
  63. */
  64. class StunAttrIterator {
  65. public:
  66. /**
  67. * Iterator constructor: creates iterator on raw messagebuffer.
  68. */
  69. StunAttrIterator(uint8_t *buf, size_t sz) : _buf(buf), _sz(sz) {
  70. if (!stun_is_command_message_str(_buf, _sz)) {
  71. throw WrongStunBufferFormatException();
  72. }
  73. _sar = stun_attr_get_first_str(_buf, _sz);
  74. }
  75. /**
  76. * Iterator constructor: create iterator over message.
  77. */
  78. template <class T> StunAttrIterator(T &msg) : _buf(msg.getRawBuffer()), _sz(msg.getSize()) {
  79. if (!stun_is_command_message_str(_buf, _sz)) {
  80. throw WrongStunBufferFormatException();
  81. }
  82. _sar = stun_attr_get_first_str(_buf, _sz);
  83. }
  84. /**
  85. * Iterator constructor: creates iterator over raw buffer, starting from first
  86. * location of an attribute of particular type.
  87. */
  88. StunAttrIterator(uint8_t *buf, size_t sz, uint16_t attr_type) : _buf(buf), _sz(sz) {
  89. if (!stun_is_command_message_str(_buf, _sz)) {
  90. throw WrongStunBufferFormatException();
  91. }
  92. _sar = stun_attr_get_first_by_type_str(_buf, _sz, attr_type);
  93. }
  94. /**
  95. * Iterator constructor: creates iterator over message, starting from first
  96. * location of an attribute of particular type.
  97. */
  98. template <class T> StunAttrIterator(T &msg, uint16_t attr_type) : _buf(msg.getRawBuffer()), _sz(msg.getSize()) {
  99. if (!stun_is_command_message_str(_buf, _sz)) {
  100. throw WrongStunBufferFormatException();
  101. }
  102. _sar = stun_attr_get_first_by_type_str(_buf, _sz, attr_type);
  103. }
  104. /**
  105. * Moves iterator to next attribute location
  106. */
  107. void next() {
  108. if (!_sar) {
  109. throw EndOfStunMsgException();
  110. }
  111. _sar = stun_attr_get_next_str(_buf, _sz, _sar);
  112. }
  113. /**
  114. * Is the iterator finished
  115. */
  116. bool eof() const { return (!_sar); }
  117. /**
  118. * Is the iterator at an address attribute
  119. */
  120. bool isAddr() const { return stun_attr_is_addr(_sar); }
  121. /**
  122. * Return address family attribute value (if the iterator at the "address family" attribute.
  123. */
  124. int getAddressFamily() const { return stun_get_requested_address_family(_sar); }
  125. /**
  126. * Get attribute type
  127. */
  128. int getType() const { return stun_attr_get_type(_sar); }
  129. /**
  130. * Destructor
  131. */
  132. virtual ~StunAttrIterator() {}
  133. /**
  134. * Return raw memroy field of the attribute value.
  135. * If the attribute value length is zero (0), then return NULL.
  136. */
  137. const uint8_t *getRawBuffer(size_t &sz) const {
  138. int len = stun_attr_get_len(_sar);
  139. if (len < 0) {
  140. throw WrongStunAttrFormatException();
  141. }
  142. sz = (size_t)len;
  143. const uint8_t *value = stun_attr_get_value(_sar);
  144. return value;
  145. }
  146. friend class StunAttr;
  147. private:
  148. uint8_t *_buf;
  149. size_t _sz;
  150. stun_attr_ref _sar;
  151. };
  152. /**
  153. * Root class of all STUN attributes.
  154. * Can be also used for a generic attribute object.
  155. */
  156. class StunAttr {
  157. public:
  158. /**
  159. * Empty constructor
  160. */
  161. StunAttr() : _attr_type(0), _value(0), _sz(0) {}
  162. /**
  163. * Constructs attribute from iterator
  164. */
  165. StunAttr(const StunAttrIterator &iter) {
  166. if (iter.eof()) {
  167. throw EndOfStunMsgException();
  168. }
  169. size_t sz = 0;
  170. const uint8_t *ptr = iter.getRawBuffer(sz);
  171. if (sz >= 0xFFFF) {
  172. throw WrongStunAttrFormatException();
  173. }
  174. int at = iter.getType();
  175. if (at < 0) {
  176. throw WrongStunAttrFormatException();
  177. }
  178. _attr_type = (uint16_t)at;
  179. _sz = sz;
  180. _value = (uint8_t *)malloc(_sz);
  181. if (ptr) {
  182. memcpy(_value, ptr, _sz);
  183. }
  184. }
  185. /**
  186. * Destructor
  187. */
  188. virtual ~StunAttr() {
  189. if (_value) {
  190. free(_value);
  191. }
  192. }
  193. /**
  194. * Return raw data representation of the attribute
  195. */
  196. const uint8_t *getRawValue(size_t &sz) const {
  197. sz = _sz;
  198. return _value;
  199. }
  200. /**
  201. * Set raw data value
  202. */
  203. void setRawValue(uint8_t *value, size_t sz) {
  204. if (sz > 0xFFFF) {
  205. throw WrongStunAttrFormatException();
  206. }
  207. if (_value) {
  208. free(_value);
  209. }
  210. _sz = sz;
  211. _value = (uint8_t *)malloc(_sz);
  212. if (value) {
  213. memcpy(_value, value, _sz);
  214. }
  215. }
  216. /**
  217. * Get attribute type
  218. */
  219. uint16_t getType() const { return _attr_type; }
  220. /**
  221. * Set attribute type
  222. */
  223. void setType(uint16_t at) { _attr_type = at; }
  224. /**
  225. * Add attribute to a message
  226. */
  227. template <class T> int addToMsg(T &msg) {
  228. if (!_attr_type) {
  229. throw WrongStunAttrFormatException();
  230. }
  231. uint8_t *buffer = msg.getRawBuffer();
  232. if (buffer) {
  233. size_t sz = msg.getSize();
  234. if (addToBuffer(buffer, sz) < 0) {
  235. throw WrongStunBufferFormatException();
  236. }
  237. msg.setSize(sz);
  238. return 0;
  239. }
  240. throw WrongStunBufferFormatException();
  241. }
  242. protected:
  243. /**
  244. * Virtual function member to add attribute to a raw buffer
  245. */
  246. virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
  247. if (buffer) {
  248. if (!_value) {
  249. throw WrongStunAttrFormatException();
  250. }
  251. if (stun_attr_add_str(buffer, &sz, _attr_type, _value, _sz) < 0) {
  252. throw WrongStunBufferFormatException();
  253. }
  254. return 0;
  255. }
  256. throw WrongStunBufferFormatException();
  257. }
  258. /**
  259. * Get low-level iterator object
  260. */
  261. static stun_attr_ref getSar(const StunAttrIterator &iter) { return iter._sar; }
  262. private:
  263. uint16_t _attr_type;
  264. uint8_t *_value;
  265. size_t _sz;
  266. };
  267. /**
  268. * Channel number attribute class
  269. */
  270. class StunAttrChannelNumber : public StunAttr {
  271. public:
  272. StunAttrChannelNumber() : _cn(0) { setType(STUN_ATTRIBUTE_CHANNEL_NUMBER); }
  273. StunAttrChannelNumber(const StunAttrIterator &iter) : StunAttr(iter) {
  274. if (iter.eof()) {
  275. throw EndOfStunMsgException();
  276. }
  277. _cn = stun_attr_get_channel_number(getSar(iter));
  278. if (!_cn) {
  279. throw WrongStunAttrFormatException();
  280. }
  281. }
  282. virtual ~StunAttrChannelNumber() {}
  283. uint16_t getChannelNumber() const { return _cn; }
  284. void setChannelNumber(uint16_t cn) { _cn = cn; }
  285. protected:
  286. virtual int addToBuffer(uint8_t *buffer, size_t &sz) { return stun_attr_add_channel_number_str(buffer, &sz, _cn); }
  287. private:
  288. uint16_t _cn;
  289. };
  290. /**
  291. * Even port attribute class
  292. */
  293. class StunAttrEvenPort : public StunAttr {
  294. public:
  295. StunAttrEvenPort() : _ep(0) { setType(STUN_ATTRIBUTE_EVEN_PORT); }
  296. StunAttrEvenPort(const StunAttrIterator &iter) : StunAttr(iter) {
  297. if (iter.eof()) {
  298. throw EndOfStunMsgException();
  299. }
  300. _ep = stun_attr_get_even_port(getSar(iter));
  301. }
  302. virtual ~StunAttrEvenPort() {}
  303. uint8_t getEvenPort() const { return _ep; }
  304. void setEvenPort(uint8_t ep) { _ep = ep; }
  305. protected:
  306. virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
  307. return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_EVEN_PORT, &_ep, 1);
  308. }
  309. private:
  310. uint8_t _ep;
  311. };
  312. /**
  313. * Reservation token attribute class
  314. */
  315. class StunAttrReservationToken : public StunAttr {
  316. public:
  317. StunAttrReservationToken() : _rt(0) { setType(STUN_ATTRIBUTE_RESERVATION_TOKEN); }
  318. StunAttrReservationToken(const StunAttrIterator &iter) : StunAttr(iter) {
  319. if (iter.eof()) {
  320. throw EndOfStunMsgException();
  321. }
  322. _rt = stun_attr_get_reservation_token_value(getSar(iter));
  323. }
  324. virtual ~StunAttrReservationToken() {}
  325. uint64_t getReservationToken() const { return _rt; }
  326. void setReservationToken(uint64_t rt) { _rt = rt; }
  327. protected:
  328. virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
  329. uint64_t reservation_token = ioa_ntoh64(_rt);
  330. return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_RESERVATION_TOKEN, (uint8_t *)(&reservation_token), 8);
  331. }
  332. private:
  333. uint64_t _rt;
  334. };
  335. /**
  336. * This attribute class is used for all address attributes
  337. */
  338. class StunAttrAddr : public StunAttr {
  339. public:
  340. StunAttrAddr(uint16_t attr_type = 0) {
  341. addr_set_any(&_addr);
  342. setType(attr_type);
  343. }
  344. StunAttrAddr(const StunAttrIterator &iter) : StunAttr(iter) {
  345. if (iter.eof()) {
  346. throw EndOfStunMsgException();
  347. }
  348. size_t sz = 0;
  349. const uint8_t *buf = iter.getRawBuffer(sz);
  350. if (stun_attr_get_addr_str(buf, sz, getSar(iter), &_addr, NULL) < 0) {
  351. throw WrongStunAttrFormatException();
  352. }
  353. }
  354. virtual ~StunAttrAddr() {}
  355. void getAddr(ioa_addr &addr) const { addr_cpy(&addr, &_addr); }
  356. void setAddr(ioa_addr &addr) { addr_cpy(&_addr, &addr); }
  357. protected:
  358. virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
  359. return stun_attr_add_addr_str(buffer, &sz, getType(), &_addr);
  360. }
  361. private:
  362. ioa_addr _addr;
  363. };
  364. /**
  365. * Change Request attribute class
  366. */
  367. class StunAttrChangeRequest : public StunAttr {
  368. public:
  369. StunAttrChangeRequest() : _changeIp(0), _changePort(0) { setType(STUN_ATTRIBUTE_CHANGE_REQUEST); }
  370. StunAttrChangeRequest(const StunAttrIterator &iter) : StunAttr(iter) {
  371. if (iter.eof()) {
  372. throw EndOfStunMsgException();
  373. }
  374. if (stun_attr_get_change_request_str(getSar(iter), &_changeIp, &_changePort) < 0) {
  375. throw WrongStunAttrFormatException();
  376. }
  377. }
  378. virtual ~StunAttrChangeRequest() {}
  379. bool getChangeIp() const { return _changeIp; }
  380. void setChangeIp(bool ci) {
  381. if (ci) {
  382. _changeIp = 1;
  383. } else {
  384. _changeIp = 0;
  385. }
  386. }
  387. bool getChangePort() const { return _changePort; }
  388. void setChangePort(bool cp) {
  389. if (cp) {
  390. _changePort = 1;
  391. } else {
  392. _changePort = 0;
  393. }
  394. }
  395. protected:
  396. virtual int addToBuffer(uint8_t *buffer, size_t &sz) {
  397. return stun_attr_add_change_request_str(buffer, &sz, _changeIp, _changePort);
  398. }
  399. private:
  400. int _changeIp;
  401. int _changePort;
  402. };
  403. /**
  404. * Change Request attribute class
  405. */
  406. class StunAttrResponsePort : public StunAttr {
  407. public:
  408. StunAttrResponsePort() : _rp(0) { setType(STUN_ATTRIBUTE_RESPONSE_PORT); }
  409. StunAttrResponsePort(const StunAttrIterator &iter) : StunAttr(iter) {
  410. if (iter.eof()) {
  411. throw EndOfStunMsgException();
  412. }
  413. int rp = stun_attr_get_response_port_str(getSar(iter));
  414. if (rp < 0) {
  415. throw WrongStunAttrFormatException();
  416. }
  417. _rp = (uint16_t)rp;
  418. }
  419. virtual ~StunAttrResponsePort() {}
  420. uint16_t getResponsePort() const { return _rp; }
  421. void setResponsePort(uint16_t p) { _rp = p; }
  422. protected:
  423. virtual int addToBuffer(uint8_t *buffer, size_t &sz) { return stun_attr_add_response_port_str(buffer, &sz, _rp); }
  424. private:
  425. uint16_t _rp;
  426. };
  427. /**
  428. * Padding attribute class
  429. */
  430. class StunAttrPadding : public StunAttr {
  431. public:
  432. StunAttrPadding() : _p(0) { setType(STUN_ATTRIBUTE_PADDING); }
  433. StunAttrPadding(const StunAttrIterator &iter) : StunAttr(iter) {
  434. if (iter.eof()) {
  435. throw EndOfStunMsgException();
  436. }
  437. int p = stun_attr_get_padding_len_str(getSar(iter));
  438. if (p < 0) {
  439. throw WrongStunAttrFormatException();
  440. }
  441. _p = (uint16_t)p;
  442. }
  443. virtual ~StunAttrPadding() {}
  444. uint16_t getPadding() const { return _p; }
  445. /**
  446. * Set length of padding
  447. */
  448. void setPadding(uint16_t p) { _p = p; }
  449. protected:
  450. virtual int addToBuffer(uint8_t *buffer, size_t &sz) { return stun_attr_add_padding_str(buffer, &sz, _p); }
  451. private:
  452. uint16_t _p;
  453. };
  454. /**
  455. * Generic "STUN Message" class, base class for all messages
  456. */
  457. class StunMsg {
  458. public:
  459. /**
  460. * Empty constructor
  461. */
  462. StunMsg() {
  463. _allocated_sz = 0xFFFF;
  464. _buffer = (uint8_t *)malloc(_allocated_sz);
  465. _deallocate = true;
  466. _sz = 0;
  467. _constructed = 0;
  468. }
  469. /**
  470. * Construct message over raw buffer.
  471. * Parameter "construct" is true if the buffer is initialized.
  472. */
  473. StunMsg(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed)
  474. : _buffer(buffer), _deallocate(false), _allocated_sz(total_sz), _sz(sz), _constructed(constructed) {}
  475. /**
  476. * Destructor
  477. */
  478. virtual ~StunMsg() {
  479. if (_deallocate && _buffer) {
  480. free(_buffer);
  481. }
  482. }
  483. /**
  484. * Initialize buffer
  485. */
  486. void construct() { constructBuffer(); }
  487. /**
  488. * Checks if the message is properly constructed
  489. */
  490. bool isValid() { return check(); }
  491. /**
  492. * get raw buffer
  493. */
  494. uint8_t *getRawBuffer() { return _buffer; }
  495. /**
  496. * Get message size in the buffer (message can be mnuch smaller than the whole buffer)
  497. */
  498. size_t getSize() const { return _sz; }
  499. /**
  500. * Set message size
  501. */
  502. void setSize(size_t sz) {
  503. if (sz > _allocated_sz) {
  504. throw WrongStunBufferFormatException();
  505. }
  506. _sz = sz;
  507. }
  508. /**
  509. * Check if the raw buffer is a TURN "command" (request, response or indication).
  510. */
  511. static bool isCommand(uint8_t *buffer, size_t sz) { return stun_is_command_message_str(buffer, sz); }
  512. /**
  513. * Check if the current message object is a "command" (request, response, or indication).
  514. */
  515. bool isCommand() const { return stun_is_command_message_str(_buffer, _sz); }
  516. static bool isIndication(uint8_t *buffer, size_t sz) { return stun_is_indication_str(buffer, sz); }
  517. static bool isRequest(uint8_t *buffer, size_t sz) { return stun_is_request_str(buffer, sz); }
  518. static bool isSuccessResponse(uint8_t *buffer, size_t sz) { return stun_is_success_response_str(buffer, sz); }
  519. static bool isErrorResponse(uint8_t *buffer, size_t sz, int &err_code, uint8_t *err_msg, size_t err_msg_size) {
  520. return stun_is_error_response_str(buffer, sz, &err_code, err_msg, err_msg_size);
  521. }
  522. /**
  523. * Check if the raw buffer is a challenge response (the one with 401 error and realm and nonce values).
  524. */
  525. static bool isChallengeResponse(const uint8_t *buf, size_t sz, int &err_code, uint8_t *err_msg, size_t err_msg_size,
  526. uint8_t *realm, uint8_t *nonce, uint8_t *server_name, int *oauth) {
  527. return stun_is_challenge_response_str(buf, sz, &err_code, err_msg, err_msg_size, realm, nonce, server_name, oauth);
  528. }
  529. /**
  530. * Check if the message is a channel message
  531. */
  532. static bool isChannel(uint8_t *buffer, size_t sz) { return is_channel_msg_str(buffer, sz); }
  533. /**
  534. * Check if the fingerprint is present.
  535. */
  536. static bool isFingerprintPresent(uint8_t *buffer, size_t sz) {
  537. if (!stun_is_command_message_str(buffer, sz)) {
  538. return false;
  539. }
  540. stun_attr_ref sar = stun_attr_get_first_by_type_str(buffer, sz, STUN_ATTRIBUTE_FINGERPRINT);
  541. if (!sar) {
  542. return false;
  543. }
  544. return true;
  545. }
  546. /**
  547. * Check the fingerprint
  548. */
  549. static bool checkFingerprint(uint8_t *buffer, size_t sz) {
  550. return stun_is_command_message_full_check_str(buffer, sz, 1, NULL);
  551. }
  552. /**
  553. * Add attribute to the message
  554. */
  555. int addAttr(StunAttr &attr) { return attr.addToMsg(*this); }
  556. /**
  557. * Get transaction ID
  558. */
  559. virtual stun_tid getTid() const {
  560. if (!_constructed || !isCommand()) {
  561. throw WrongStunBufferFormatException();
  562. }
  563. stun_tid tid;
  564. stun_tid_from_message_str(_buffer, _sz, &tid);
  565. return tid;
  566. }
  567. /**
  568. * Set transaction ID
  569. */
  570. virtual void setTid(stun_tid &tid) {
  571. if (!_constructed || !isCommand()) {
  572. throw WrongStunBufferFormatException();
  573. }
  574. stun_tid_message_cpy(_buffer, &tid);
  575. }
  576. /**
  577. * Add fingerprint to the message
  578. */
  579. void addFingerprint() {
  580. if (!_constructed || !isCommand()) {
  581. throw WrongStunBufferFormatException();
  582. }
  583. stun_attr_add_fingerprint_str(_buffer, &_sz);
  584. }
  585. /**
  586. * Check message integrity, in secure communications.
  587. */
  588. bool checkMessageIntegrity(turn_credential_type ct, std::string &uname, std::string &realm, std::string &upwd) const {
  589. if (!_constructed || !isCommand()) {
  590. throw WrongStunBufferFormatException();
  591. }
  592. uint8_t *suname = (uint8_t *)strdup(uname.c_str());
  593. uint8_t *srealm = (uint8_t *)strdup(realm.c_str());
  594. uint8_t *supwd = (uint8_t *)strdup(upwd.c_str());
  595. SHATYPE sht = SHATYPE_SHA1;
  596. bool ret = (0 < stun_check_message_integrity_str(ct, _buffer, _sz, suname, srealm, supwd, sht));
  597. free(suname);
  598. free(srealm);
  599. free(supwd);
  600. return ret;
  601. }
  602. /**
  603. * Adds long-term message integrity data to the message.
  604. */
  605. void addLTMessageIntegrity(std::string &uname, std::string &realm, std::string &upwd, std::string &nonce) {
  606. if (!_constructed || !isCommand()) {
  607. throw WrongStunBufferFormatException();
  608. }
  609. uint8_t *suname = (uint8_t *)strdup(uname.c_str());
  610. uint8_t *srealm = (uint8_t *)strdup(realm.c_str());
  611. uint8_t *supwd = (uint8_t *)strdup(upwd.c_str());
  612. uint8_t *snonce = (uint8_t *)strdup(nonce.c_str());
  613. stun_attr_add_integrity_by_user_str(_buffer, &_sz, suname, srealm, supwd, snonce, SHATYPE_SHA1);
  614. free(suname);
  615. free(srealm);
  616. free(supwd);
  617. free(snonce);
  618. }
  619. /**
  620. * Adds short-term message integrity data to the message.
  621. */
  622. void addSTMessageIntegrity(std::string &uname, std::string &upwd) {
  623. if (!_constructed || !isCommand()) {
  624. throw WrongStunBufferFormatException();
  625. }
  626. uint8_t *suname = (uint8_t *)strdup(uname.c_str());
  627. uint8_t *supwd = (uint8_t *)strdup(upwd.c_str());
  628. stun_attr_add_integrity_by_user_short_term_str(_buffer, &_sz, suname, supwd, SHATYPE_SHA1);
  629. free(suname);
  630. free(supwd);
  631. }
  632. protected:
  633. virtual void constructBuffer() = 0;
  634. virtual bool check() = 0;
  635. protected:
  636. uint8_t *_buffer;
  637. bool _deallocate;
  638. size_t _allocated_sz;
  639. size_t _sz;
  640. bool _constructed;
  641. };
  642. /**
  643. * Class that represents the "request" flavor of STUN/TURN messages.
  644. */
  645. class StunMsgRequest : public StunMsg {
  646. public:
  647. StunMsgRequest(uint16_t method) : _method(method){};
  648. StunMsgRequest(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed)
  649. : StunMsg(buffer, total_sz, sz, constructed), _method(0) {
  650. if (constructed) {
  651. if (!stun_is_request_str(buffer, sz)) {
  652. throw WrongStunBufferFormatException();
  653. }
  654. _method = stun_get_method_str(buffer, sz);
  655. }
  656. }
  657. virtual ~StunMsgRequest() {}
  658. /**
  659. * Get request method
  660. */
  661. uint16_t getMethod() const { return _method; }
  662. /**
  663. * Set method
  664. */
  665. void setMethod(uint16_t method) { _method = method; }
  666. /**
  667. * Construct binding request
  668. */
  669. void constructBindingRequest() { stun_set_binding_request_str(_buffer, &_sz); }
  670. bool isBindingRequest() const { return stun_is_binding_request_str(_buffer, _sz, 0); }
  671. /**
  672. * Construct allocate request
  673. */
  674. void constructAllocateRequest(uint32_t lifetime, int af4, int af6, uint8_t transport, int mobile, const char *rt,
  675. int ep) {
  676. stun_set_allocate_request_str(_buffer, &_sz, lifetime, af4, af6, transport, mobile, rt, ep);
  677. }
  678. /**
  679. * Construct channel bind request
  680. */
  681. void constructChannelBindRequest(const ioa_addr &peer_addr, uint16_t channel_number) {
  682. stun_set_channel_bind_request_str(_buffer, &_sz, &peer_addr, channel_number);
  683. }
  684. protected:
  685. virtual void constructBuffer() {
  686. stun_init_request_str(_method, _buffer, &_sz);
  687. _constructed = true;
  688. }
  689. virtual bool check() {
  690. if (!_constructed) {
  691. return false;
  692. }
  693. if (!stun_is_request_str(_buffer, _sz)) {
  694. return false;
  695. }
  696. if (_method != stun_get_method_str(_buffer, _sz)) {
  697. return false;
  698. }
  699. return true;
  700. }
  701. private:
  702. uint16_t _method;
  703. };
  704. /**
  705. * Class for STUN/TURN responses
  706. */
  707. class StunMsgResponse : public StunMsg {
  708. public:
  709. StunMsgResponse(uint16_t method, stun_tid &tid) : _method(method), _err(0), _reason(""), _tid(tid){};
  710. StunMsgResponse(uint16_t method, int error_code, std::string reason, stun_tid &tid)
  711. : _method(method), _err(error_code), _reason(reason), _tid(tid){
  712. };
  713. StunMsgResponse(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed)
  714. : StunMsg(buffer, total_sz, sz, constructed), _method(0), _err(0), _reason("") {
  715. if (constructed) {
  716. if (!stun_is_success_response_str(buffer, sz)) {
  717. uint8_t errtxt[0xFFFF];
  718. if (!stun_is_error_response_str(buffer, sz, &_err, errtxt, sizeof(errtxt))) {
  719. throw WrongStunBufferFormatException();
  720. }
  721. _reason = (char *)errtxt;
  722. }
  723. _method = stun_get_method_str(buffer, sz);
  724. stun_tid_from_message_str(_buffer, _sz, &_tid);
  725. }
  726. }
  727. uint16_t getMethod() const { return _method; }
  728. void setMethod(uint16_t method) { _method = method; }
  729. /**
  730. * Get error code
  731. */
  732. int getError() const { return _err; }
  733. /**
  734. * Set error code
  735. */
  736. void setError(int err) { _err = err; }
  737. /**
  738. * Get error message
  739. */
  740. std::string getReason() const { return _reason; }
  741. /**
  742. * Set error message
  743. */
  744. void setReason(std::string reason) { _reason = reason; }
  745. /**
  746. * Set transaction ID
  747. */
  748. void setTid(stun_tid &tid) { _tid = tid; }
  749. /**
  750. * Get transaction ID
  751. */
  752. virtual stun_tid getTid() const { return _tid; }
  753. /**
  754. * Check if this is a challenge response, and return realm and nonce
  755. */
  756. bool isChallenge(std::string &realm, std::string &nonce) const {
  757. bool ret = false;
  758. if (_constructed) {
  759. int err_code;
  760. uint8_t err_msg[1025];
  761. size_t err_msg_size = sizeof(err_msg);
  762. uint8_t srealm[0xFFFF];
  763. uint8_t snonce[0xFFFF];
  764. ret = stun_is_challenge_response_str(_buffer, _sz, &err_code, err_msg, err_msg_size, srealm, snonce, NULL, NULL);
  765. if (ret) {
  766. realm = (char *)srealm;
  767. nonce = (char *)snonce;
  768. }
  769. }
  770. return ret;
  771. }
  772. bool isChallenge() const {
  773. std::string realm, nonce;
  774. return isChallenge(realm, nonce);
  775. }
  776. /**
  777. * Check if this is a success response
  778. */
  779. bool isSuccess() const { return (_err == 0); }
  780. /**
  781. * Construct binding response
  782. */
  783. void constructBindingResponse(stun_tid &tid, const ioa_addr &reflexive_addr, int error_code, const uint8_t *reason) {
  784. stun_set_binding_response_str(_buffer, &_sz, &tid, &reflexive_addr, error_code, reason, 0, 0, 1);
  785. }
  786. bool isBindingResponse() const { return stun_is_binding_response_str(_buffer, _sz); }
  787. /**
  788. * Construct allocate response
  789. */
  790. void constructAllocateResponse(stun_tid &tid, const ioa_addr &relayed_addr1, const ioa_addr &relayed_addr2,
  791. const ioa_addr &reflexive_addr, uint32_t lifetime, int error_code,
  792. const uint8_t *reason, uint64_t reservation_token, char *mobile_id) {
  793. stun_set_allocate_response_str(_buffer, &_sz, &tid, &relayed_addr1, &relayed_addr2, &reflexive_addr, lifetime,
  794. STUN_DEFAULT_MAX_ALLOCATE_LIFETIME, error_code, reason, reservation_token,
  795. mobile_id);
  796. }
  797. /**
  798. * Construct channel bind response
  799. */
  800. void constructChannelBindResponse(stun_tid &tid, int error_code, const uint8_t *reason) {
  801. stun_set_channel_bind_response_str(_buffer, &_sz, &tid, error_code, reason);
  802. }
  803. protected:
  804. virtual void constructBuffer() {
  805. if (_err) {
  806. stun_init_error_response_str(_method, _buffer, &_sz, _err, (const uint8_t *)_reason.c_str(), &_tid);
  807. } else {
  808. stun_init_success_response_str(_method, _buffer, &_sz, &_tid);
  809. }
  810. _constructed = true;
  811. }
  812. virtual bool check() {
  813. if (!_constructed) {
  814. return false;
  815. }
  816. if (!stun_is_success_response_str(_buffer, _sz)) {
  817. uint8_t errtxt[0xFFFF];
  818. int cerr = 0;
  819. if (!stun_is_error_response_str(_buffer, _sz, &cerr, errtxt, sizeof(errtxt))) {
  820. throw WrongStunBufferFormatException();
  821. }
  822. if (cerr != _err) {
  823. throw WrongStunBufferFormatException();
  824. }
  825. }
  826. if (_method != stun_get_method_str(_buffer, _sz)) {
  827. return false;
  828. }
  829. return true;
  830. }
  831. private:
  832. uint16_t _method;
  833. int _err;
  834. std::string _reason;
  835. stun_tid _tid;
  836. };
  837. /**
  838. * Class for STUN/TURN indications
  839. */
  840. class StunMsgIndication : public StunMsg {
  841. public:
  842. StunMsgIndication(uint16_t method) : _method(method){};
  843. StunMsgIndication(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed)
  844. : StunMsg(buffer, total_sz, sz, constructed), _method(0) {
  845. if (constructed) {
  846. if (!stun_is_indication_str(buffer, sz)) {
  847. throw WrongStunBufferFormatException();
  848. }
  849. _method = stun_get_method_str(buffer, sz);
  850. }
  851. }
  852. virtual ~StunMsgIndication() {}
  853. uint16_t getMethod() const { return _method; }
  854. void setMethod(uint16_t method) { _method = method; }
  855. protected:
  856. virtual void constructBuffer() {
  857. stun_init_indication_str(_method, _buffer, &_sz);
  858. _constructed = true;
  859. }
  860. virtual bool check() {
  861. if (!_constructed) {
  862. return false;
  863. }
  864. if (!stun_is_indication_str(_buffer, _sz)) {
  865. return false;
  866. }
  867. if (_method != stun_get_method_str(_buffer, _sz)) {
  868. return false;
  869. }
  870. return true;
  871. }
  872. private:
  873. uint16_t _method;
  874. };
  875. /**
  876. * Channel message
  877. */
  878. class StunMsgChannel : public StunMsg {
  879. public:
  880. StunMsgChannel(uint16_t cn, int length) : _cn(cn), _len(length){};
  881. StunMsgChannel(uint8_t *buffer, size_t total_sz, size_t sz, bool constructed)
  882. : StunMsg(buffer, total_sz, sz, constructed), _cn(0) {
  883. if (constructed) {
  884. if (!stun_is_channel_message_str(buffer, &_sz, &_cn, 0)) {
  885. throw WrongStunBufferFormatException();
  886. }
  887. if (_sz > 0xFFFF || _sz < 4) {
  888. throw WrongStunBufferFormatException();
  889. }
  890. _len = _sz - 4;
  891. } else {
  892. if (total_sz > 0xFFFF || total_sz < 4) {
  893. throw WrongStunBufferFormatException();
  894. }
  895. _len = 0;
  896. }
  897. }
  898. virtual ~StunMsgChannel() {}
  899. uint16_t getChannelNumber() const { return _cn; }
  900. void setChannelNumber(uint16_t cn) { _cn = cn; }
  901. /**
  902. * Get length of message itself (excluding the 4 channel number bytes)
  903. */
  904. size_t getLength() const { return _len; }
  905. /**
  906. * Set length of message itself (excluding the 4 channel number bytes)
  907. */
  908. void setLength(size_t len) { _len = len; }
  909. protected:
  910. virtual void constructBuffer() {
  911. stun_init_channel_message_str(_cn, _buffer, &_sz, (int)_len, 0);
  912. _constructed = true;
  913. }
  914. virtual bool check() {
  915. if (!_constructed) {
  916. return false;
  917. }
  918. uint16_t cn = 0;
  919. if (!stun_is_channel_message_str(_buffer, &_sz, &cn, 0)) {
  920. return false;
  921. }
  922. if (_cn != cn) {
  923. return false;
  924. }
  925. return true;
  926. }
  927. private:
  928. uint16_t _cn;
  929. size_t _len;
  930. };
  931. } // namespace turn
  932. /* namespace */
  933. #endif
  934. /* __LIB_TURN_MSG_CPP__ */