TurnMsgLib.h 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
  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(u08bits *buf, size_t sz) throw (WrongStunBufferFormatException) :
  70. _buf(buf), _sz(sz) {
  71. if(!stun_is_command_message_str(_buf, _sz)) {
  72. throw WrongStunBufferFormatException();
  73. }
  74. _sar = stun_attr_get_first_str(_buf, _sz);
  75. }
  76. /**
  77. * Iterator constructor: create iterator over message.
  78. */
  79. template<class T>
  80. StunAttrIterator(T &msg) throw (WrongStunBufferFormatException) :
  81. _buf(msg.getRawBuffer()), _sz(msg.getSize()) {
  82. if(!stun_is_command_message_str(_buf, _sz)) {
  83. throw WrongStunBufferFormatException();
  84. }
  85. _sar = stun_attr_get_first_str(_buf, _sz);
  86. }
  87. /**
  88. * Iterator constructor: creates iterator over raw buffer, starting from first
  89. * location of an attribute of particular type.
  90. */
  91. StunAttrIterator(u08bits *buf, size_t sz, u16bits attr_type) throw (WrongStunBufferFormatException) :
  92. _buf(buf), _sz(sz) {
  93. if(!stun_is_command_message_str(_buf, _sz)) {
  94. throw WrongStunBufferFormatException();
  95. }
  96. _sar = stun_attr_get_first_by_type_str(_buf, _sz, attr_type);
  97. }
  98. /**
  99. * Iterator constructor: creates iterator over message, starting from first
  100. * location of an attribute of particular type.
  101. */
  102. template<class T>
  103. StunAttrIterator(T &msg, u16bits attr_type) throw (WrongStunBufferFormatException) :
  104. _buf(msg.getRawBuffer()), _sz(msg.getSize()) {
  105. if(!stun_is_command_message_str(_buf, _sz)) {
  106. throw WrongStunBufferFormatException();
  107. }
  108. _sar = stun_attr_get_first_by_type_str(_buf, _sz, attr_type);
  109. }
  110. /**
  111. * Moves iterator to next attribute location
  112. */
  113. void next() throw(EndOfStunMsgException) {
  114. if(!_sar) {
  115. throw EndOfStunMsgException();
  116. }
  117. _sar = stun_attr_get_next_str(_buf,_sz,_sar);
  118. }
  119. /**
  120. * Is the iterator finished
  121. */
  122. bool eof() const {
  123. return (!_sar);
  124. }
  125. /**
  126. * Is the iterator at an address attribute
  127. */
  128. bool isAddr() const {
  129. return stun_attr_is_addr(_sar);
  130. }
  131. /**
  132. * Return address family attribute value (if the iterator at the "address family" attribute.
  133. */
  134. int getAddressFamily() const {
  135. return stun_get_requested_address_family(_sar);
  136. }
  137. /**
  138. * Get attribute type
  139. */
  140. int getType() const {
  141. return stun_attr_get_type(_sar);
  142. }
  143. /**
  144. * Destructor
  145. */
  146. virtual ~StunAttrIterator() {}
  147. /**
  148. * Return raw memroy field of the attribute value.
  149. * If the attribute value length is zero (0), then return NULL.
  150. */
  151. const u08bits *getRawBuffer(size_t &sz) const throw(WrongStunAttrFormatException) {
  152. int len = stun_attr_get_len(_sar);
  153. if(len<0)
  154. throw WrongStunAttrFormatException();
  155. sz = (size_t)len;
  156. const u08bits *value = stun_attr_get_value(_sar);
  157. return value;
  158. }
  159. friend class StunAttr;
  160. private:
  161. u08bits *_buf;
  162. size_t _sz;
  163. stun_attr_ref _sar;
  164. };
  165. /**
  166. * Root class of all STUN attributes.
  167. * Can be also used for a generic attribute object.
  168. */
  169. class StunAttr {
  170. public:
  171. /**
  172. * Empty constructor
  173. */
  174. StunAttr() : _attr_type(0), _value(0), _sz(0) {}
  175. /**
  176. * Constructs attribute from iterator
  177. */
  178. StunAttr(const StunAttrIterator &iter) throw(WrongStunAttrFormatException, EndOfStunMsgException) {
  179. if(iter.eof()) {
  180. throw EndOfStunMsgException();
  181. }
  182. size_t sz = 0;
  183. const u08bits *ptr = iter.getRawBuffer(sz);
  184. if(sz>=0xFFFF)
  185. throw WrongStunAttrFormatException();
  186. int at = iter.getType();
  187. if(at<0)
  188. throw WrongStunAttrFormatException();
  189. _attr_type = (u16bits)at;
  190. _sz = sz;
  191. _value=(u08bits*)turn_malloc(_sz);
  192. if(ptr)
  193. ns_bcopy(ptr,_value,_sz);
  194. }
  195. /**
  196. * Destructor
  197. */
  198. virtual ~StunAttr() {
  199. if(_value)
  200. turn_free(_value,_sz);
  201. }
  202. /**
  203. * Return raw data representation of the attribute
  204. */
  205. const u08bits *getRawValue(size_t &sz) const {
  206. sz=_sz;
  207. return _value;
  208. }
  209. /**
  210. * Set raw data value
  211. */
  212. void setRawValue(u08bits *value, size_t sz) throw(WrongStunAttrFormatException) {
  213. if(sz>0xFFFF)
  214. throw WrongStunAttrFormatException();
  215. if(_value)
  216. turn_free(_value,_sz);
  217. _sz = sz;
  218. _value=(u08bits*)turn_malloc(_sz);
  219. if(value)
  220. ns_bcopy(value,_value,_sz);
  221. }
  222. /**
  223. * Get attribute type
  224. */
  225. u16bits getType() const {
  226. return _attr_type;
  227. }
  228. /**
  229. * Set attribute type
  230. */
  231. void setType(u16bits at) {
  232. _attr_type = at;
  233. }
  234. /**
  235. * Add attribute to a message
  236. */
  237. template<class T>
  238. int addToMsg(T &msg) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  239. if(!_attr_type)
  240. throw WrongStunAttrFormatException();
  241. u08bits *buffer = msg.getRawBuffer();
  242. if(buffer) {
  243. size_t sz = msg.getSize();
  244. if(addToBuffer(buffer, sz)<0) {
  245. throw WrongStunBufferFormatException();
  246. }
  247. msg.setSize(sz);
  248. return 0;
  249. }
  250. throw WrongStunBufferFormatException();
  251. }
  252. protected:
  253. /**
  254. * Virtual function member to add attribute to a raw buffer
  255. */
  256. virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  257. if(buffer) {
  258. if(!_value)
  259. throw WrongStunAttrFormatException();
  260. if(stun_attr_add_str(buffer, &sz, _attr_type, _value, _sz)<0) {
  261. throw WrongStunBufferFormatException();
  262. }
  263. return 0;
  264. }
  265. throw WrongStunBufferFormatException();
  266. }
  267. /**
  268. * Get low-level iterator object
  269. */
  270. static stun_attr_ref getSar(const StunAttrIterator &iter) {
  271. return iter._sar;
  272. }
  273. private:
  274. u16bits _attr_type;
  275. u08bits *_value;
  276. size_t _sz;
  277. };
  278. /**
  279. * Channel number attribute class
  280. */
  281. class StunAttrChannelNumber : public StunAttr {
  282. public:
  283. StunAttrChannelNumber() : _cn(0) {
  284. setType(STUN_ATTRIBUTE_CHANNEL_NUMBER);
  285. }
  286. StunAttrChannelNumber(const StunAttrIterator &iter)
  287. throw(WrongStunAttrFormatException, EndOfStunMsgException) :
  288. StunAttr(iter) {
  289. if(iter.eof())
  290. throw EndOfStunMsgException();
  291. _cn = stun_attr_get_channel_number(getSar(iter));
  292. if(!_cn)
  293. throw WrongStunAttrFormatException();
  294. }
  295. virtual ~StunAttrChannelNumber() {}
  296. u16bits getChannelNumber() const {
  297. return _cn;
  298. }
  299. void setChannelNumber(u16bits cn) {
  300. _cn = cn;
  301. }
  302. protected:
  303. virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  304. return stun_attr_add_channel_number_str(buffer,&sz,_cn);
  305. }
  306. private:
  307. u16bits _cn;
  308. };
  309. /**
  310. * Even port attribute class
  311. */
  312. class StunAttrEvenPort : public StunAttr {
  313. public:
  314. StunAttrEvenPort() : _ep(0) {
  315. setType(STUN_ATTRIBUTE_EVEN_PORT);
  316. }
  317. StunAttrEvenPort(const StunAttrIterator &iter)
  318. throw(WrongStunAttrFormatException, EndOfStunMsgException) :
  319. StunAttr(iter) {
  320. if(iter.eof())
  321. throw EndOfStunMsgException();
  322. _ep = stun_attr_get_even_port(getSar(iter));
  323. }
  324. virtual ~StunAttrEvenPort() {}
  325. u08bits getEvenPort() const {
  326. return _ep;
  327. }
  328. void setEvenPort(u08bits ep) {
  329. _ep = ep;
  330. }
  331. protected:
  332. virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  333. return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_EVEN_PORT, &_ep, 1);
  334. }
  335. private:
  336. u08bits _ep;
  337. };
  338. /**
  339. * Reservation token attribute class
  340. */
  341. class StunAttrReservationToken : public StunAttr {
  342. public:
  343. StunAttrReservationToken() : _rt(0) {
  344. setType(STUN_ATTRIBUTE_RESERVATION_TOKEN);
  345. }
  346. StunAttrReservationToken(const StunAttrIterator &iter)
  347. throw(WrongStunAttrFormatException, EndOfStunMsgException) :
  348. StunAttr(iter) {
  349. if(iter.eof())
  350. throw EndOfStunMsgException();
  351. _rt = stun_attr_get_reservation_token_value(getSar(iter));
  352. }
  353. virtual ~StunAttrReservationToken() {}
  354. u64bits getReservationToken() const {
  355. return _rt;
  356. }
  357. void setReservationToken(u64bits rt) {
  358. _rt = rt;
  359. }
  360. protected:
  361. virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  362. uint64_t reservation_token = ioa_ntoh64(_rt);
  363. return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_RESERVATION_TOKEN, (u08bits*) (&reservation_token), 8);
  364. }
  365. private:
  366. u64bits _rt;
  367. };
  368. /**
  369. * This attribute class is used for all address attributes
  370. */
  371. class StunAttrAddr : public StunAttr {
  372. public:
  373. StunAttrAddr(u16bits attr_type = 0) {
  374. addr_set_any(&_addr);
  375. setType(attr_type);
  376. }
  377. StunAttrAddr(const StunAttrIterator &iter)
  378. throw(WrongStunAttrFormatException, EndOfStunMsgException) :
  379. StunAttr(iter) {
  380. if(iter.eof())
  381. throw EndOfStunMsgException();
  382. size_t sz = 0;
  383. const u08bits *buf = iter.getRawBuffer(sz);
  384. if(stun_attr_get_addr_str(buf,sz,getSar(iter),&_addr,NULL)<0) {
  385. throw WrongStunAttrFormatException();
  386. }
  387. }
  388. virtual ~StunAttrAddr() {}
  389. void getAddr(ioa_addr &addr) const {
  390. addr_cpy(&addr,&_addr);
  391. }
  392. void setAddr(ioa_addr &addr) {
  393. addr_cpy(&_addr,&addr);
  394. }
  395. protected:
  396. virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  397. return stun_attr_add_addr_str(buffer, &sz, getType(), &_addr);
  398. }
  399. private:
  400. ioa_addr _addr;
  401. };
  402. /**
  403. * Change Request attribute class
  404. */
  405. class StunAttrChangeRequest : public StunAttr {
  406. public:
  407. StunAttrChangeRequest() : _changeIp(0), _changePort(0) {
  408. setType(STUN_ATTRIBUTE_CHANGE_REQUEST);
  409. }
  410. StunAttrChangeRequest(const StunAttrIterator &iter)
  411. throw(WrongStunAttrFormatException, EndOfStunMsgException) :
  412. StunAttr(iter) {
  413. if(iter.eof())
  414. throw EndOfStunMsgException();
  415. if(stun_attr_get_change_request_str(getSar(iter), &_changeIp, &_changePort)<0) {
  416. throw WrongStunAttrFormatException();
  417. }
  418. }
  419. virtual ~StunAttrChangeRequest() {}
  420. bool getChangeIp() const {
  421. return _changeIp;
  422. }
  423. void setChangeIp(bool ci) {
  424. if(ci)
  425. _changeIp = 1;
  426. else
  427. _changeIp = 0;
  428. }
  429. bool getChangePort() const {
  430. return _changePort;
  431. }
  432. void setChangePort(bool cp) {
  433. if(cp)
  434. _changePort = 1;
  435. else
  436. _changePort = 0;
  437. }
  438. protected:
  439. virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  440. return stun_attr_add_change_request_str(buffer, &sz, _changeIp, _changePort);
  441. }
  442. private:
  443. int _changeIp;
  444. int _changePort;
  445. };
  446. /**
  447. * Change Request attribute class
  448. */
  449. class StunAttrResponsePort : public StunAttr {
  450. public:
  451. StunAttrResponsePort() : _rp(0) {
  452. setType(STUN_ATTRIBUTE_RESPONSE_PORT);
  453. }
  454. StunAttrResponsePort(const StunAttrIterator &iter)
  455. throw(WrongStunAttrFormatException, EndOfStunMsgException) :
  456. StunAttr(iter) {
  457. if(iter.eof())
  458. throw EndOfStunMsgException();
  459. int rp = stun_attr_get_response_port_str(getSar(iter));
  460. if(rp<0) {
  461. throw WrongStunAttrFormatException();
  462. }
  463. _rp = (u16bits)rp;
  464. }
  465. virtual ~StunAttrResponsePort() {}
  466. u16bits getResponsePort() const {
  467. return _rp;
  468. }
  469. void setResponsePort(u16bits p) {
  470. _rp = p;
  471. }
  472. protected:
  473. virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  474. return stun_attr_add_response_port_str(buffer, &sz, _rp);
  475. }
  476. private:
  477. u16bits _rp;
  478. };
  479. /**
  480. * Padding attribute class
  481. */
  482. class StunAttrPadding : public StunAttr {
  483. public:
  484. StunAttrPadding() : _p(0) {
  485. setType(STUN_ATTRIBUTE_PADDING);
  486. }
  487. StunAttrPadding(const StunAttrIterator &iter)
  488. throw(WrongStunAttrFormatException, EndOfStunMsgException) :
  489. StunAttr(iter) {
  490. if(iter.eof())
  491. throw EndOfStunMsgException();
  492. int p = stun_attr_get_padding_len_str(getSar(iter));
  493. if(p<0) {
  494. throw WrongStunAttrFormatException();
  495. }
  496. _p = (u16bits)p;
  497. }
  498. virtual ~StunAttrPadding() {}
  499. u16bits getPadding() const {
  500. return _p;
  501. }
  502. /**
  503. * Set length of padding
  504. */
  505. void setPadding(u16bits p) {
  506. _p = p;
  507. }
  508. protected:
  509. virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  510. return stun_attr_add_padding_str(buffer, &sz, _p);
  511. }
  512. private:
  513. u16bits _p;
  514. };
  515. /**
  516. * Generic "STUN Message" class, base class for all messages
  517. */
  518. class StunMsg {
  519. public:
  520. /**
  521. * Empty constructor
  522. */
  523. StunMsg() {
  524. _allocated_sz = 0xFFFF;
  525. _buffer = (u08bits*)turn_malloc(_allocated_sz);
  526. _deallocate = true;
  527. _sz = 0;
  528. _constructed = 0;
  529. }
  530. /**
  531. * Construct message over raw buffer.
  532. * Parameter "construct" is true if the buffer is initialized.
  533. */
  534. StunMsg(u08bits *buffer, size_t total_sz, size_t sz, bool constructed) :
  535. _buffer(buffer), _deallocate(false), _allocated_sz(total_sz),
  536. _sz(sz), _constructed(constructed) {}
  537. /**
  538. * Destructor
  539. */
  540. virtual ~StunMsg() {
  541. if(_deallocate && _buffer) {
  542. turn_free(_buffer, _allocated_sz);
  543. }
  544. }
  545. /**
  546. * Initialize buffer
  547. */
  548. void construct() {
  549. constructBuffer();
  550. }
  551. /**
  552. * Checks if the message is properly constructed
  553. */
  554. bool isValid() {
  555. return check();
  556. }
  557. /**
  558. * get raw buffer
  559. */
  560. u08bits *getRawBuffer() {
  561. return _buffer;
  562. }
  563. /**
  564. * Get message size in the buffer (message can be mnuch smaller than the whole buffer)
  565. */
  566. size_t getSize() const {
  567. return _sz;
  568. }
  569. /**
  570. * Set message size
  571. */
  572. void setSize(size_t sz) throw(WrongStunBufferFormatException) {
  573. if(sz>_allocated_sz)
  574. throw WrongStunBufferFormatException();
  575. _sz = sz;
  576. }
  577. /**
  578. * Check if the raw buffer is a TURN "command" (request, response or indication).
  579. */
  580. static bool isCommand(u08bits *buffer, size_t sz) {
  581. return stun_is_command_message_str(buffer, sz);
  582. }
  583. /**
  584. * Check if the current message object is a "command" (request, response, or indication).
  585. */
  586. bool isCommand() const {
  587. return stun_is_command_message_str(_buffer, _sz);
  588. }
  589. static bool isIndication(u08bits *buffer, size_t sz) {
  590. return stun_is_indication_str(buffer, sz);
  591. }
  592. static bool isRequest(u08bits *buffer, size_t sz) {
  593. return stun_is_request_str(buffer, sz);
  594. }
  595. static bool isSuccessResponse(u08bits *buffer, size_t sz) {
  596. return stun_is_success_response_str(buffer, sz);
  597. }
  598. static bool isErrorResponse(u08bits *buffer, size_t sz,
  599. int &err_code, u08bits *err_msg, size_t err_msg_size) {
  600. return stun_is_error_response_str(buffer, sz, &err_code, err_msg, err_msg_size);
  601. }
  602. /**
  603. * Check if the raw buffer is a challenge response (the one with 401 error and realm and nonce values).
  604. */
  605. static bool isChallengeResponse(const u08bits* buf, size_t sz,
  606. int &err_code, u08bits *err_msg, size_t err_msg_size,
  607. u08bits *realm, u08bits *nonce) {
  608. return stun_is_challenge_response_str(buf, sz, &err_code, err_msg, err_msg_size, realm, nonce);
  609. }
  610. /**
  611. * Check if the message is a channel message
  612. */
  613. static bool isChannel(u08bits *buffer, size_t sz) {
  614. return is_channel_msg_str(buffer, sz);
  615. }
  616. /**
  617. * Check if the fingerprint is present.
  618. */
  619. static bool isFingerprintPresent(u08bits *buffer, size_t sz) {
  620. if(!stun_is_command_message_str(buffer,sz))
  621. return false;
  622. stun_attr_ref sar = stun_attr_get_first_by_type_str(buffer, sz, STUN_ATTRIBUTE_FINGERPRINT);
  623. if(!sar)
  624. return false;
  625. return true;
  626. }
  627. /**
  628. * Check the fingerprint
  629. */
  630. static bool checkFingerprint(u08bits *buffer, size_t sz) {
  631. return stun_is_command_message_full_check_str(buffer, sz, 1, NULL);
  632. }
  633. /**
  634. * Add attribute to the message
  635. */
  636. int addAttr(StunAttr &attr) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
  637. return attr.addToMsg(*this);
  638. }
  639. /**
  640. * Get transaction ID
  641. */
  642. virtual stun_tid getTid() const throw(WrongStunBufferFormatException) {
  643. if(!_constructed || !isCommand())
  644. throw WrongStunBufferFormatException();
  645. stun_tid tid;
  646. stun_tid_from_message_str(_buffer,_sz,&tid);
  647. return tid;
  648. }
  649. /**
  650. * Set transaction ID
  651. */
  652. virtual void setTid(stun_tid &tid) throw(WrongStunBufferFormatException) {
  653. if(!_constructed || !isCommand())
  654. throw WrongStunBufferFormatException();
  655. stun_tid_message_cpy(_buffer, &tid);
  656. }
  657. /**
  658. * Add fingerprint to the message
  659. */
  660. void addFingerprint() throw(WrongStunBufferFormatException) {
  661. if(!_constructed || !isCommand())
  662. throw WrongStunBufferFormatException();
  663. stun_attr_add_fingerprint_str(_buffer,&_sz);
  664. }
  665. /**
  666. * Check message integrity, in secure communications.
  667. */
  668. bool checkMessageIntegrity(turn_credential_type ct, std::string &uname, std::string &realm, std::string &upwd) const
  669. throw(WrongStunBufferFormatException) {
  670. if(!_constructed || !isCommand())
  671. throw WrongStunBufferFormatException();
  672. u08bits *suname=(u08bits*)strdup(uname.c_str());
  673. u08bits *srealm=(u08bits*)strdup(realm.c_str());
  674. u08bits *supwd=(u08bits*)strdup(upwd.c_str());
  675. SHATYPE sht = SHATYPE_SHA1;
  676. bool ret = (0< stun_check_message_integrity_str(ct,_buffer, _sz, suname, srealm, supwd, sht));
  677. free(suname);
  678. free(srealm);
  679. free(supwd);
  680. return ret;
  681. }
  682. /**
  683. * Adds long-term message integrity data to the message.
  684. */
  685. void addLTMessageIntegrity(std::string &uname, std::string &realm, std::string &upwd, std::string &nonce)
  686. throw(WrongStunBufferFormatException) {
  687. if(!_constructed || !isCommand())
  688. throw WrongStunBufferFormatException();
  689. u08bits *suname=(u08bits*)strdup(uname.c_str());
  690. u08bits *srealm=(u08bits*)strdup(realm.c_str());
  691. u08bits *supwd=(u08bits*)strdup(upwd.c_str());
  692. u08bits *snonce=(u08bits*)strdup(nonce.c_str());
  693. stun_attr_add_integrity_by_user_str(_buffer, &_sz, suname, srealm, supwd, snonce, SHATYPE_SHA1);
  694. free(suname);
  695. free(srealm);
  696. free(supwd);
  697. free(snonce);
  698. }
  699. /**
  700. * Adds short-term message integrity data to the message.
  701. */
  702. void addSTMessageIntegrity(std::string &uname, std::string &upwd)
  703. throw(WrongStunBufferFormatException) {
  704. if(!_constructed || !isCommand())
  705. throw WrongStunBufferFormatException();
  706. u08bits *suname=(u08bits*)strdup(uname.c_str());
  707. u08bits *supwd=(u08bits*)strdup(upwd.c_str());
  708. stun_attr_add_integrity_by_user_short_term_str(_buffer, &_sz, suname, supwd, SHATYPE_SHA1);
  709. free(suname);
  710. free(supwd);
  711. }
  712. protected:
  713. virtual void constructBuffer() = 0;
  714. virtual bool check() = 0;
  715. protected:
  716. u08bits *_buffer;
  717. bool _deallocate;
  718. size_t _allocated_sz;
  719. size_t _sz;
  720. bool _constructed;
  721. };
  722. /**
  723. * Class that represents the "request" flavor of STUN/TURN messages.
  724. */
  725. class StunMsgRequest : public StunMsg {
  726. public:
  727. StunMsgRequest(u16bits method) : _method(method) {};
  728. StunMsgRequest(u08bits *buffer, size_t total_sz, size_t sz, bool constructed)
  729. throw(WrongStunBufferFormatException) :
  730. StunMsg(buffer,total_sz,sz,constructed),_method(0) {
  731. if(constructed) {
  732. if(!stun_is_request_str(buffer,sz)) {
  733. throw WrongStunBufferFormatException();
  734. }
  735. _method = stun_get_method_str(buffer,sz);
  736. }
  737. }
  738. virtual ~StunMsgRequest() {}
  739. /**
  740. * Get request method
  741. */
  742. u16bits getMethod() const {
  743. return _method;
  744. }
  745. /**
  746. * Set method
  747. */
  748. void setMethod(u16bits method) {
  749. _method = method;
  750. }
  751. /**
  752. * Construct binding request
  753. */
  754. void constructBindingRequest() {
  755. stun_set_binding_request_str(_buffer, &_sz);
  756. }
  757. bool isBindingRequest() const {
  758. return stun_is_binding_request_str(_buffer,_sz,0);
  759. }
  760. /**
  761. * Construct allocate request
  762. */
  763. void constructAllocateRequest(u32bits lifetime, int af4, int af6, u08bits transport, int mobile) {
  764. stun_set_allocate_request_str(_buffer, &_sz, lifetime, af4, af6, transport, mobile);
  765. }
  766. /**
  767. * Construct channel bind request
  768. */
  769. void constructChannelBindRequest(const ioa_addr &peer_addr, u16bits channel_number) {
  770. stun_set_channel_bind_request_str(_buffer, &_sz,
  771. &peer_addr, channel_number);
  772. }
  773. protected:
  774. virtual void constructBuffer() {
  775. stun_init_request_str(_method,_buffer,&_sz);
  776. _constructed = true;
  777. }
  778. virtual bool check() {
  779. if(!_constructed)
  780. return false;
  781. if(!stun_is_request_str(_buffer,_sz)) {
  782. return false;
  783. }
  784. if(_method != stun_get_method_str(_buffer,_sz)) {
  785. return false;
  786. }
  787. return true;
  788. }
  789. private:
  790. u16bits _method;
  791. };
  792. /**
  793. * Class for STUN/TURN responses
  794. */
  795. class StunMsgResponse : public StunMsg {
  796. public:
  797. StunMsgResponse(u16bits method, stun_tid &tid) : _method(method), _err(0), _reason(""), _tid(tid) {};
  798. StunMsgResponse(u16bits method, int error_code, std::string reason, stun_tid &tid) :
  799. _method(method), _err(error_code), _reason(reason), _tid(tid) {
  800. };
  801. StunMsgResponse(u08bits *buffer, size_t total_sz, size_t sz, bool constructed)
  802. throw(WrongStunBufferFormatException) :
  803. StunMsg(buffer,total_sz,sz,constructed),_method(0),_err(0),_reason("") {
  804. if(constructed) {
  805. if(!stun_is_success_response_str(buffer,sz)) {
  806. u08bits errtxt[0xFFFF];
  807. if(!stun_is_error_response_str(buffer,sz,&_err,errtxt,sizeof(errtxt))) {
  808. throw WrongStunBufferFormatException();
  809. }
  810. _reason = (char*)errtxt;
  811. }
  812. _method = stun_get_method_str(buffer,sz);
  813. stun_tid_from_message_str(_buffer,_sz,&_tid);
  814. }
  815. }
  816. u16bits getMethod() const {
  817. return _method;
  818. }
  819. void setMethod(u16bits method) {
  820. _method = method;
  821. }
  822. /**
  823. * Get error code
  824. */
  825. int getError() const {
  826. return _err;
  827. }
  828. /**
  829. * Set error code
  830. */
  831. void setError(int err) {
  832. _err = err;
  833. }
  834. /**
  835. * Get error message
  836. */
  837. std::string getReason() const {
  838. return _reason;
  839. }
  840. /**
  841. * Set error message
  842. */
  843. void setReason(std::string reason) {
  844. _reason = reason;
  845. }
  846. /**
  847. * Set transaction ID
  848. */
  849. void setTid(stun_tid &tid) throw(WrongStunBufferFormatException) {
  850. _tid = tid;
  851. }
  852. /**
  853. * Get transaction ID
  854. */
  855. virtual stun_tid getTid() const throw(WrongStunBufferFormatException) {
  856. return _tid;
  857. }
  858. /**
  859. * Check if this is a challenge response, and return realm and nonce
  860. */
  861. bool isChallenge(std::string &realm, std::string &nonce) const {
  862. bool ret = false;
  863. if(_constructed) {
  864. int err_code;
  865. u08bits err_msg[1025];
  866. size_t err_msg_size=sizeof(err_msg);
  867. u08bits srealm[0xFFFF];
  868. u08bits snonce[0xFFFF];
  869. ret = stun_is_challenge_response_str(_buffer, _sz, &err_code, err_msg, err_msg_size, srealm, snonce);
  870. if(ret) {
  871. realm = (char*)srealm;
  872. nonce = (char*)snonce;
  873. }
  874. }
  875. return ret;
  876. }
  877. bool isChallenge() const {
  878. std::string realm, nonce;
  879. return isChallenge(realm, nonce);
  880. }
  881. /**
  882. * Check if this is a success response
  883. */
  884. bool isSuccess() const {
  885. return (_err == 0);
  886. }
  887. /**
  888. * Construct binding response
  889. */
  890. void constructBindingResponse(stun_tid &tid,
  891. const ioa_addr &reflexive_addr, int error_code,
  892. const u08bits *reason) {
  893. stun_set_binding_response_str(_buffer, &_sz, &tid,
  894. &reflexive_addr, error_code,
  895. reason, 0 , 0);
  896. }
  897. bool isBindingResponse() const {
  898. return stun_is_binding_response_str(_buffer,_sz);
  899. }
  900. /**
  901. * Construct allocate response
  902. */
  903. void constructAllocateResponse(stun_tid &tid,
  904. const ioa_addr &relayed_addr1,
  905. const ioa_addr &relayed_addr2,
  906. const ioa_addr &reflexive_addr,
  907. u32bits lifetime, int error_code, const u08bits *reason,
  908. u64bits reservation_token, char *mobile_id) {
  909. stun_set_allocate_response_str(_buffer, &_sz, &tid,
  910. &relayed_addr1, &relayed_addr2,
  911. &reflexive_addr,
  912. lifetime, error_code, reason,
  913. reservation_token, mobile_id);
  914. }
  915. /**
  916. * Construct channel bind response
  917. */
  918. void constructChannelBindResponse(stun_tid &tid, int error_code, const u08bits *reason) {
  919. stun_set_channel_bind_response_str(_buffer, &_sz, &tid, error_code, reason);
  920. }
  921. protected:
  922. virtual void constructBuffer() {
  923. if(_err) {
  924. stun_init_error_response_str(_method, _buffer, &_sz, _err, (const u08bits*)_reason.c_str(), &_tid);
  925. } else {
  926. stun_init_success_response_str(_method, _buffer, &_sz, &_tid);
  927. }
  928. _constructed = true;
  929. }
  930. virtual bool check() {
  931. if(!_constructed)
  932. return false;
  933. if(!stun_is_success_response_str(_buffer,_sz)) {
  934. u08bits errtxt[0xFFFF];
  935. int cerr=0;
  936. if(!stun_is_error_response_str(_buffer,_sz,&cerr,errtxt,sizeof(errtxt))) {
  937. throw WrongStunBufferFormatException();
  938. }
  939. if(cerr != _err) {
  940. throw WrongStunBufferFormatException();
  941. }
  942. }
  943. if(_method != stun_get_method_str(_buffer,_sz)) {
  944. return false;
  945. }
  946. return true;
  947. }
  948. private:
  949. u16bits _method;
  950. int _err;
  951. std::string _reason;
  952. stun_tid _tid;
  953. };
  954. /**
  955. * Class for STUN/TURN indications
  956. */
  957. class StunMsgIndication : public StunMsg {
  958. public:
  959. StunMsgIndication(u16bits method) : _method(method) {};
  960. StunMsgIndication(u08bits *buffer, size_t total_sz, size_t sz, bool constructed)
  961. throw(WrongStunBufferFormatException) :
  962. StunMsg(buffer,total_sz,sz,constructed),_method(0) {
  963. if(constructed) {
  964. if(!stun_is_indication_str(buffer,sz)) {
  965. throw WrongStunBufferFormatException();
  966. }
  967. _method = stun_get_method_str(buffer,sz);
  968. }
  969. }
  970. virtual ~StunMsgIndication() {}
  971. u16bits getMethod() const {
  972. return _method;
  973. }
  974. void setMethod(u16bits method) {
  975. _method = method;
  976. }
  977. protected:
  978. virtual void constructBuffer() {
  979. stun_init_indication_str(_method,_buffer,&_sz);
  980. _constructed = true;
  981. }
  982. virtual bool check() {
  983. if(!_constructed)
  984. return false;
  985. if(!stun_is_indication_str(_buffer,_sz)) {
  986. return false;
  987. }
  988. if(_method != stun_get_method_str(_buffer,_sz)) {
  989. return false;
  990. }
  991. return true;
  992. }
  993. private:
  994. u16bits _method;
  995. };
  996. /**
  997. * Channel message
  998. */
  999. class StunMsgChannel : public StunMsg {
  1000. public:
  1001. StunMsgChannel(u16bits cn, int length) : _cn(cn), _len(length) {};
  1002. StunMsgChannel(u08bits *buffer, size_t total_sz, size_t sz, bool constructed)
  1003. throw(WrongStunBufferFormatException) :
  1004. StunMsg(buffer,total_sz,sz,constructed),_cn(0) {
  1005. if(constructed) {
  1006. if(!stun_is_channel_message_str(buffer,&_sz,&_cn,0)) {
  1007. throw WrongStunBufferFormatException();
  1008. }
  1009. if(_sz>0xFFFF || _sz<4)
  1010. throw WrongStunBufferFormatException();
  1011. _len = _sz-4;
  1012. } else {
  1013. if(total_sz>0xFFFF || total_sz<4)
  1014. throw WrongStunBufferFormatException();
  1015. _len = 0;
  1016. }
  1017. }
  1018. virtual ~StunMsgChannel() {}
  1019. u16bits getChannelNumber() const {
  1020. return _cn;
  1021. }
  1022. void setChannelNumber(u16bits cn) {
  1023. _cn = cn;
  1024. }
  1025. /**
  1026. * Get length of message itself (excluding the 4 channel number bytes)
  1027. */
  1028. size_t getLength() const {
  1029. return _len;
  1030. }
  1031. /**
  1032. * Set length of message itself (excluding the 4 channel number bytes)
  1033. */
  1034. void setLength(size_t len) {
  1035. _len = len;
  1036. }
  1037. protected:
  1038. virtual void constructBuffer() {
  1039. stun_init_channel_message_str(_cn,_buffer,&_sz,(int)_len,0);
  1040. _constructed = true;
  1041. }
  1042. virtual bool check() {
  1043. if(!_constructed)
  1044. return false;
  1045. u16bits cn = 0;
  1046. if(!stun_is_channel_message_str(_buffer,&_sz,&cn,0)) {
  1047. return false;
  1048. }
  1049. if(_cn != cn) {
  1050. return false;
  1051. }
  1052. return true;
  1053. }
  1054. private:
  1055. u16bits _cn;
  1056. size_t _len;
  1057. };
  1058. };
  1059. /* namespace */
  1060. #endif
  1061. /* __LIB_TURN_MSG_CPP__ */