test_stun.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /* Copyright (C) 2014 Mamadou DIOP.
  2. *
  3. * This file is part of Open Source Doubango Framework.
  4. *
  5. * DOUBANGO is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * DOUBANGO is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with DOUBANGO.
  17. *
  18. */
  19. #ifndef TNET_TEST_STUN_H
  20. #define TNET_TEST_STUN_H
  21. #include "stun/tnet_stun_pkt.h"
  22. #include "stun/tnet_stun_utils.h"
  23. #include "turn/tnet_turn_session.h"
  24. #define kStunUsrName "bossiel@yahoo.fr"
  25. #define kStunPwd "tinynet"
  26. #define kStunServerIP "ns313841.ovh.net" /*"numb.viagenie.ca"*/
  27. #define kStunServerPort kStunPortDefaultTcpUdp
  28. #define kStunServerProto tnet_socket_type_udp_ipv4
  29. #define kTurnPeerIP "192.168.0.37"
  30. #define kTurnPeerPort 2020
  31. #define TNET_TEST_STUN_SEND_BUFF_TO(buff_ptr, buff_size, IP, PORT) \
  32. { \
  33. struct sockaddr_storage addr_to; \
  34. tnet_socket_t* socket = tnet_socket_create(0, 0, kStunServerProto); \
  35. tnet_sockaddr_init((IP), (PORT), kStunServerProto, &addr_to); \
  36. tnet_sockfd_sendto(socket->fd, (const struct sockaddr *)&addr_to, (buff_ptr), (buff_size)); \
  37. TSK_OBJECT_SAFE_FREE(socket); \
  38. }
  39. #define TNET_TEST_STUN_SEND_BUFF(buff_ptr, buff_size) TNET_TEST_STUN_SEND_BUFF_TO((buff_ptr), (buff_size), kStunServerIP, kStunServerPort)
  40. uint8_t __parse_buff_write_ptr[1200];
  41. static const tsk_size_t __parse_buff_write_size = sizeof(__parse_buff_write_ptr)/sizeof(__parse_buff_write_ptr[0]);
  42. uint8_t __parse_buff_read_ptr[1200];
  43. static const tsk_size_t __parse_buff_read_size = sizeof(__parse_buff_read_ptr)/sizeof(__parse_buff_read_ptr[0]);
  44. // http://tools.ietf.org/html/draft-ietf-behave-stun-test-vectors-04
  45. static int test_stun_buff_cmp(const uint8_t* pc_buf1_ptr, tsk_size_t n_buff1_size, const uint8_t* pc_buf2_ptr, tsk_size_t n_buff2_size)
  46. {
  47. int ret;
  48. tsk_size_t u;
  49. if (!pc_buf1_ptr || !pc_buf2_ptr || (n_buff1_size != n_buff2_size)) {
  50. return -1;
  51. }
  52. for (u = 0; u < n_buff1_size; ++u) {
  53. if ((ret = (pc_buf1_ptr[u] - pc_buf2_ptr[u]))) {
  54. return ret;
  55. }
  56. }
  57. return 0;
  58. }
  59. static void test_stun_parser()
  60. {
  61. tnet_stun_pkt_t* p_pkt = tsk_null;
  62. tsk_size_t n_written_bytes, n_read_bytes;
  63. static const char* __pc_mapped_addr_ipv4 = "192.168.0.37";
  64. static const char* __pc_mapped_addr_ipv6 = "fdf8:f53b:82e4::53";
  65. static const uint16_t __u_mapped_addr_port = 5060;
  66. static const char __pc_username[] = "Mamadou DIOP";
  67. static const uint16_t __u_username = sizeof(__pc_username);
  68. static const char __pc_integrity[TSK_SHA1_DIGEST_SIZE] = { 0 };
  69. static const uint16_t __u_integrity = sizeof(__pc_integrity);
  70. static const uint32_t __u_fingerprint = 19831983;
  71. static const uint8_t __u_error_class = 4; // (4 * 100) = 404
  72. static const uint8_t __u_error_number = 4; // + 4 = 404
  73. static const char* __pc_error_reason = "Not Found";
  74. tnet_stun_addr_t addr_ipv4, addr_ipv6;
  75. static const char __pc_realm[] = "doubango.org";
  76. static const uint16_t __u_realm = sizeof(__pc_realm);
  77. static const char __pc_nonce[128] = { 0 };
  78. static const uint16_t __u_nonce = sizeof(__pc_nonce);
  79. static const char __pc_software[] = "tinyNET 2.0";
  80. static const uint16_t __u_software = sizeof(__pc_software);
  81. static const uint32_t __u_life_time = 600;
  82. static const uint32_t __u_req_transport = 17; // UDP
  83. (n_read_bytes);
  84. BAIL_IF_ERR(tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, &p_pkt));
  85. BAIL_IF_ERR(tnet_stun_utils_inet_pton_v4(__pc_mapped_addr_ipv4, &addr_ipv4));
  86. BAIL_IF_ERR(tnet_stun_utils_inet_pton_v6(__pc_mapped_addr_ipv6, &addr_ipv6));
  87. BAIL_IF_ERR(tnet_stun_pkt_attrs_add(p_pkt,
  88. TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS_V4(__u_mapped_addr_port, &addr_ipv4),
  89. TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS_V6(__u_mapped_addr_port, &addr_ipv6),
  90. TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS_V4(__u_mapped_addr_port, &addr_ipv4),
  91. TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS_V6(__u_mapped_addr_port, &addr_ipv6),
  92. TNET_STUN_PKT_ATTR_ADD_USERNAME_ZT(__pc_username),
  93. TNET_STUN_PKT_ATTR_ADD_MESSAGE_INTEGRITY(__pc_integrity, __u_integrity),
  94. TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(__u_error_class, __u_error_number, __pc_error_reason),
  95. TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_TRY_ALTERNATE(),
  96. TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_BAD_REQUEST(),
  97. TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_UNAUTHORIZED(),
  98. TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_UNKNOWN_ATTRIBUTE(),
  99. TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_STALE_NONCE(),
  100. TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_SERVER_ERROR(),
  101. TNET_STUN_PKT_ATTR_ADD_REALM_ZT(__pc_realm),
  102. TNET_STUN_PKT_ATTR_ADD_NONCE(__pc_nonce, __u_nonce),
  103. TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS(
  104. TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(0x0001), // MAPPED-ADDRESS
  105. TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(0x0006), // USERNAME
  106. TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(0x0007), // PASSWORD
  107. TNET_STUN_PKT_ATTR_ADD_NULL()),
  108. TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(__pc_software),
  109. TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER_V4(__u_mapped_addr_port, &addr_ipv4),
  110. TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER_V6(__u_mapped_addr_port, &addr_ipv6),
  111. TNET_STUN_PKT_ATTR_ADD_LIFETIME(__u_life_time),
  112. TNET_STUN_PKT_ATTR_ADD_REQUESTED_TRANSPORT(__u_req_transport),
  113. TNET_STUN_PKT_ATTR_ADD_DONT_FRAGMENT(),
  114. TNET_STUN_PKT_ATTR_ADD_FINGERPRINT(__u_fingerprint),
  115. TNET_STUN_PKT_ATTR_ADD_NULL()));
  116. BAIL_IF_ERR(tnet_stun_pkt_write_with_padding(p_pkt, __parse_buff_write_ptr, __parse_buff_write_size, &n_written_bytes));
  117. TNET_TEST_STUN_SEND_BUFF(__parse_buff_write_ptr, n_written_bytes);
  118. TSK_OBJECT_SAFE_FREE(p_pkt);
  119. BAIL_IF_ERR(tnet_stun_pkt_read(__parse_buff_write_ptr, n_written_bytes, &p_pkt));
  120. BAIL_IF_ERR(tnet_stun_pkt_write_with_padding(p_pkt, __parse_buff_read_ptr, __parse_buff_read_size, &n_read_bytes));
  121. //TNET_TEST_STUN_SEND_BUFF(__parse_buff_read_ptr, n_read_bytes);
  122. BAIL_IF_ERR(test_stun_buff_cmp(__parse_buff_write_ptr, n_written_bytes, __parse_buff_read_ptr, n_read_bytes));
  123. TSK_DEBUG_INFO("test_stun_parser...OK");
  124. bail:
  125. TSK_OBJECT_SAFE_FREE(p_pkt);
  126. }
  127. static struct tnet_turn_session_s* __pc_ss1 = tsk_null;
  128. static struct tnet_turn_session_s* __pc_ss2 = tsk_null;
  129. static char* __p_rel_ip_ss1 = tsk_null;
  130. static uint16_t __u_rel_port_ss1 = 0;
  131. static tsk_bool_t __b_rel_ipv6_ss1 = 0;
  132. static tnet_turn_peer_id_t __u_peer_id1 = kTurnPeerIdInvalid;
  133. static char* __p_rel_ip_ss2 = tsk_null;
  134. static uint16_t __u_rel_port_ss2 = 0;
  135. static tsk_bool_t __b_rel_ipv6_ss2 = 0;
  136. static tnet_turn_peer_id_t __u_peer_id2 = kTurnPeerIdInvalid;
  137. static int _test_turn_session_callback(const struct tnet_turn_session_event_xs *e)
  138. {
  139. const struct tnet_turn_session_s* pc_ss = (const struct tnet_turn_session_s*)e->pc_usr_data;
  140. int ret = 0;
  141. switch (e->e_type) {
  142. case tnet_turn_session_event_type_alloc_ok: {
  143. uint16_t *pu_port = (pc_ss == __pc_ss2) ? &__u_rel_port_ss1 : &__u_rel_port_ss2;
  144. char** pp_ip = (pc_ss == __pc_ss2) ? &__p_rel_ip_ss1 : &__p_rel_ip_ss2;
  145. tsk_bool_t *pb_ipv6 = (pc_ss == __pc_ss2) ? &__b_rel_ipv6_ss1 : &__b_rel_ipv6_ss2;
  146. tnet_turn_peer_id_t *pu_peer_id = (pc_ss == __pc_ss2) ? &__u_peer_id2 : &__u_peer_id1;
  147. BAIL_IF_ERR(tnet_turn_session_get_relayed_addr(pc_ss, pp_ip, pu_port, pb_ipv6));
  148. // BAIL_IF_ERR(tnet_turn_session_get_srflx_addr(pc_ss, pu_port, &u_port, &b_ipv6)); // get my own server reflexive address (in order to send data to myself)
  149. BAIL_IF_ERR(tnet_turn_session_createpermission((struct tnet_turn_session_s*)pc_ss, *pp_ip, *pu_port, pu_peer_id)); // Input = ADDR(remote.candidate.relay)
  150. break;
  151. }
  152. case tnet_turn_session_event_type_alloc_nok: {
  153. TSK_DEBUG_INFO("*** TURN ALLOC NOK ***");
  154. break;
  155. }
  156. case tnet_turn_session_event_type_perm_ok: {
  157. static const char __pc_data[] = { "TURN Sample Data (Send Indication)" };
  158. int i;
  159. tnet_turn_peer_id_t u_peer_id = (pc_ss == __pc_ss2) ? __u_peer_id2 : __u_peer_id1;
  160. // Bind a channel (not required). If succeed, will be used to save data.
  161. tnet_turn_session_chanbind((struct tnet_turn_session_s*)pc_ss, u_peer_id);
  162. // Send data (will use channel if one is active. Otherwise (no channel), SendIndications will be used)
  163. for (i = 0; i < 10; ++i) {
  164. BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, u_peer_id, __pc_data, sizeof(__pc_data)));
  165. }
  166. break;
  167. }
  168. case tnet_turn_session_event_type_perm_nok: {
  169. TSK_DEBUG_INFO("*** TURN PERM NOK ***");
  170. break;
  171. }
  172. case tnet_turn_session_event_type_chanbind_ok: {
  173. static const char __pc_data[] = { "TURN Sample Data (ChannelData)" };
  174. int i;
  175. tnet_turn_peer_id_t u_peer_id = (pc_ss == __pc_ss2) ? __u_peer_id2 : __u_peer_id1;
  176. for (i = 0; i < 10; ++i) {
  177. BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, u_peer_id, __pc_data, sizeof(__pc_data)));
  178. }
  179. break;
  180. }
  181. case tnet_turn_session_event_type_chanbind_nok: {
  182. TSK_DEBUG_INFO("*** TURN CHANBIND NOK ***");
  183. break;
  184. }
  185. case tnet_turn_session_event_type_recv_data: {
  186. TSK_DEBUG_INFO("RECV DATA:%.*s", e->data.u_data_size, (const char*)e->data.pc_data_ptr);
  187. break;
  188. }
  189. default: {
  190. break;
  191. }
  192. }
  193. bail:
  194. return ret;
  195. }
  196. static void test_turn_session()
  197. {
  198. BAIL_IF_ERR(tnet_turn_session_create_udp_ipv4(tnet_turn_transport_udp, kStunServerIP, kStunServerPort, &__pc_ss1));
  199. BAIL_IF_ERR(tnet_turn_session_set_callback(__pc_ss1, _test_turn_session_callback, __pc_ss1));
  200. BAIL_IF_ERR(tnet_turn_session_set_cred(__pc_ss1, kStunUsrName, kStunPwd));
  201. BAIL_IF_ERR(tnet_turn_session_prepare(__pc_ss1));
  202. BAIL_IF_ERR(tnet_turn_session_start(__pc_ss1));
  203. BAIL_IF_ERR(tnet_turn_session_create_udp_ipv4(tnet_turn_transport_udp, kStunServerIP, kStunServerPort, &__pc_ss2));
  204. BAIL_IF_ERR(tnet_turn_session_set_callback(__pc_ss2, _test_turn_session_callback, __pc_ss2));
  205. BAIL_IF_ERR(tnet_turn_session_set_cred(__pc_ss2, kStunUsrName, kStunPwd));
  206. BAIL_IF_ERR(tnet_turn_session_prepare(__pc_ss2));
  207. BAIL_IF_ERR(tnet_turn_session_start(__pc_ss2));
  208. BAIL_IF_ERR(tnet_turn_session_allocate(__pc_ss1));
  209. BAIL_IF_ERR(tnet_turn_session_allocate(__pc_ss2));
  210. TSK_DEBUG_INFO("*** Press ENTER to continue ***");
  211. getchar();
  212. bail:
  213. TSK_OBJECT_SAFE_FREE(__pc_ss1);
  214. TSK_OBJECT_SAFE_FREE(__pc_ss2);
  215. }
  216. static void test_stun()
  217. {
  218. //test_stun_parser();
  219. test_turn_session();
  220. }
  221. #endif /* TNET_TEST_STUN_H */