Guest User

Untitled

a guest
Sep 12th, 2018
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.18 KB | None | 0 0
  1. #ifdef HAVE_CONFIG_H
  2. # include <config.h>
  3. #endif
  4.  
  5. #ifdef __sun
  6. #define _XPG4_2 1
  7. #endif
  8.  
  9. #ifndef _WIN32
  10.  
  11. #include <stdio.h>
  12. #include <stdint.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <signal.h>
  16.  
  17. #include <sys/types.h>
  18. #include <arpa/inet.h>
  19.  
  20. #include <sys/socket.h>
  21. #include <netdb.h>
  22. #include <netinet/in.h>
  23.  
  24. #include <unistd.h>
  25. #include <errno.h>
  26. #include <limits.h>
  27.  
  28. #include <glib.h>
  29.  
  30. #include "stunagent.h"
  31. #include "agent-priv.h"
  32. #include "agent.h"
  33.  
  34. #ifndef SOL_IP
  35. # define SOL_IP IPPROTO_IP
  36. #endif
  37.  
  38. #ifndef SOL_IPV6
  39. # define SOL_IPV6 IPPROTO_IPV6
  40. #endif
  41.  
  42. #ifndef IPV6_RECVPKTINFO
  43. # define IPV6_RECVPKTINFO IPV6_PKTINFO
  44. #endif
  45.  
  46. #ifndef MAX_CANDS
  47. # define MAX_CANDS 3
  48. #endif
  49.  
  50. /** Default port for STUN binding discovery */
  51. #define IPPORT_STUN 3456
  52.  
  53. static const uint16_t known_attributes[] = {
  54. 0
  55. };
  56.  
  57. static GMainLoop *loop = NULL;
  58. static NiceCandidate *remote_candidate[MAX_CANDS];
  59. static GMutex setting_remote_candidates_mutex;
  60. static GMutex adding_remote_cand;
  61. static GCond candidate_gathering_done;
  62. static gboolean all_remote_addr_added = FALSE;
  63. static NiceAddress addr_remote[MAX_CANDS];
  64. static GSList* remote_list = NULL;
  65.  
  66. /*
  67. * Creates a listening socket
  68. */
  69. static int listen_socket (unsigned int port)
  70. {
  71. int yes = 1;
  72. int fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  73.  
  74. if (fd == -1)
  75. {
  76. perror ("Error opening IP port");
  77. return -1;
  78. }
  79. if (fd < 3)
  80. goto error;
  81.  
  82. struct sockaddr_in addr;
  83. memset (&addr, 0, sizeof (addr));
  84. addr.sin_family = AF_INET;
  85. inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
  86. addr.sin_port = htons(port);
  87. setsockopt (fd, SOL_IP, IP_RECVERR, &yes, sizeof (yes));
  88.  
  89. if (bind (fd, (struct sockaddr_in *)&addr, sizeof (struct sockaddr_in)))
  90. {
  91. perror ("Error opening IP port");
  92. goto error;
  93. }
  94.  
  95. return fd;
  96.  
  97. error:
  98. close (fd);
  99. return -1;
  100. }
  101.  
  102. static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
  103. {
  104. struct sockaddr_storage addr;
  105. socklen_t addr_len;
  106. uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  107. size_t buf_len = 0;
  108. size_t len = 0;
  109. StunMessage request;
  110. StunMessage response;
  111. StunValidationStatus validation;
  112. StunAgent *agent = NULL;
  113.  
  114. addr_len = sizeof (struct sockaddr_in);
  115. g_debug("listening for STUN requests");
  116. len = recvfrom (sock, buf, sizeof(buf), 0,
  117. (struct sockaddr *)&addr, &addr_len);
  118. if (buf_len == (size_t)-1)
  119. return -1;
  120.  
  121. validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0);
  122.  
  123. if (validation == STUN_VALIDATION_SUCCESS) {
  124. agent = newagent;
  125. }
  126. else {
  127. validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0);
  128. agent = oldagent;
  129. }
  130.  
  131. /* Unknown attributes */
  132. if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE)
  133. {
  134. buf_len = stun_agent_build_unknown_attributes_error (agent, &response, buf,
  135. sizeof (buf), &request);
  136. goto send_buf;
  137. }
  138.  
  139. /* Mal-formatted packets */
  140. if (validation != STUN_VALIDATION_SUCCESS ||
  141. stun_message_get_class (&request) != STUN_REQUEST) {
  142. return -1;
  143. }
  144.  
  145. switch (stun_message_get_method (&request))
  146. {
  147. case STUN_BINDING:
  148. stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
  149. if (stun_message_has_cookie (&request))
  150. stun_message_append_xor_addr (&response,
  151. STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
  152. (struct sockaddr *)&addr, addr_len);
  153. else
  154. stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
  155. (struct sockaddr *)&addr, addr_len);
  156. break;
  157.  
  158. default:
  159. if (!stun_agent_init_error (agent, &response, buf, sizeof (buf),
  160. &request, STUN_ERROR_BAD_REQUEST))
  161. return -1;
  162. }
  163.  
  164. buf_len = stun_agent_finish_message (agent, &response, NULL, 0);
  165.  
  166. send_buf:
  167. while(!all_remote_addr_added) {
  168. g_mutex_lock(&setting_remote_candidates_mutex);
  169. g_cond_wait(&candidate_gathering_done, &setting_remote_candidates_mutex);
  170. len = sendto (sock, buf, buf_len, 0,
  171. (struct sockaddr *)&addr, addr_len);
  172. g_debug("STUN response sent");
  173. g_main_loop_quit(loop);
  174. return (len < buf_len) ? -1 : 0;
  175. }
  176. return -1;
  177. }
  178.  
  179.  
  180. static gpointer stun_thread_func (const gpointer user_data)
  181. {
  182. StunAgent oldagent;
  183. StunAgent newagent;
  184. int sock = listen_socket (IPPORT_STUN);
  185.  
  186. if (sock == -1)
  187. return GINT_TO_POINTER(-1);
  188.  
  189. stun_agent_init (&oldagent, known_attributes,
  190. STUN_COMPATIBILITY_RFC3489, 0);
  191. stun_agent_init (&newagent, known_attributes,
  192. STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
  193.  
  194. for (;;)
  195. dgram_process (sock, &oldagent, &newagent);
  196.  
  197. return NULL;
  198. }
  199.  
  200. static NiceCandidate* nice_candidate_from_nice_address(NiceAgent* agent, guint stream_id, NiceAddress* addr)
  201. {
  202. NiceCandidate *cand = nice_candidate_new(NICE_CANDIDATE_TYPE_HOST);
  203. cand->addr = *addr;
  204. cand->stream_id = stream_id;
  205.  
  206. gchar *ufrag = NULL, *password = NULL;
  207. nice_agent_get_local_credentials(agent, stream_id, &ufrag, &password);
  208.  
  209. cand->username = ufrag;
  210. cand->password = password;
  211.  
  212. g_free(ufrag);
  213. g_free(password);
  214.  
  215. return cand;
  216. }
  217.  
  218. static void cb_set_new_remote_address(NiceAgent *agent, guint stream_id,guint component_id, guint state, gpointer user_data)
  219. {
  220. g_debug("test-new-dribble-mode: %s", G_STRFUNC);
  221. static int index = 1;
  222. if( state >= NICE_COMPONENT_STATE_GATHERING && state <= NICE_COMPONENT_STATE_FAILED && index < MAX_CANDS) {
  223. g_debug("Index is : %d", index);
  224. remote_list = g_slist_append(remote_list, remote_candidate[index]);
  225. index++;
  226. g_assert(nice_agent_set_remote_candidates(agent, stream_id, NICE_COMPONENT_TYPE_RTP, remote_list));
  227. }
  228.  
  229. if(index >= MAX_CANDS && !all_remote_addr_added) {
  230. g_debug("Signalling STUN thread");
  231. g_mutex_lock(&setting_remote_candidates_mutex);
  232. all_remote_addr_added = TRUE;
  233. g_cond_signal(&candidate_gathering_done);
  234. g_mutex_unlock(&setting_remote_candidates_mutex);
  235. }
  236. }
  237.  
  238. gint
  239. main (void)
  240. {
  241. #if !GLIB_CHECK_VERSION(2,31,0)
  242. g_thread_init(NULL);
  243. #endif
  244.  
  245. g_type_init ();
  246.  
  247. NiceAgent *agent;
  248. NiceAddress addr_local;
  249. guint stream_id;
  250. GThread *stun_thread;
  251.  
  252. int i = 0;
  253.  
  254. g_debug("dribble mode test initiated");
  255.  
  256. #if !GLIB_CHECK_VERSION(2,31,8)
  257. g_thread_init(NULL);
  258. #endif
  259.  
  260. nice_address_init (&addr_local);
  261.  
  262. for(i = 0; i < MAX_CANDS; i++) {
  263. nice_address_init (&addr_remote[i]);
  264. }
  265.  
  266. loop = g_main_loop_new(NULL, FALSE);
  267.  
  268. g_mutex_init(&setting_remote_candidates_mutex);
  269. g_mutex_init(&adding_remote_cand);
  270. g_cond_init(&candidate_gathering_done);
  271. agent = nice_agent_new (g_main_loop_get_context (loop), NICE_COMPATIBILITY_RFC5245);
  272.  
  273. // Start STUN Daemon in another thread
  274. stun_thread = g_thread_new("listen for STUN requests", stun_thread_func, NULL);
  275.  
  276. g_assert (nice_address_set_from_string (&addr_local, "127.0.0.1"));
  277. g_assert (agent->local_addresses == NULL);
  278.  
  279. /* add one local address */
  280. nice_agent_add_local_address (agent, &addr_local);
  281. g_assert (agent->local_addresses != NULL);
  282. g_assert (g_slist_length (agent->local_addresses) == 1);
  283. g_assert (nice_address_equal (agent->local_addresses->data, &addr_local));
  284.  
  285. /* add a stream */
  286. stream_id = nice_agent_add_stream (agent, 1);
  287.  
  288. // Set stun server and port
  289. g_object_set (G_OBJECT (agent), "stun-server", "127.0.0.1", NULL);
  290. g_object_set (G_OBJECT (agent), "stun-server-port", IPPORT_STUN, NULL);
  291.  
  292. g_assert (nice_address_set_from_string (&addr_remote[0], "127.0.0.1"));
  293. g_assert (nice_address_set_from_string (&addr_remote[1], "172.1.0.1"));
  294. g_assert (nice_address_set_from_string (&addr_remote[2], "129.0.0.1"));
  295.  
  296.  
  297. for( i = 0; i < MAX_CANDS; i++) {
  298. nice_address_set_port (&addr_remote[i], 2345);
  299. g_assert (nice_address_is_valid(&addr_remote[i]));
  300. remote_candidate[i] = nice_candidate_from_nice_address(agent, stream_id, &addr_remote[i]);
  301. }
  302.  
  303. nice_agent_gather_candidates (agent, stream_id);
  304.  
  305. remote_list = g_slist_append(remote_list, remote_candidate[0]);
  306. nice_agent_set_remote_candidates(agent, stream_id, NICE_COMPONENT_TYPE_RTP, remote_list);
  307.  
  308. g_signal_connect (G_OBJECT (agent), "component-state-changed",
  309. G_CALLBACK (cb_set_new_remote_address), NULL);
  310.  
  311.  
  312. g_main_loop_run(loop);
  313.  
  314. // Clean up
  315. g_slist_free(remote_list);
  316. g_thread_unref(stun_thread);
  317. g_object_unref(agent);
  318. g_main_loop_unref(loop);
  319. return 0;
  320. }
  321.  
  322. #else
  323. int main (int argc, char **argv) {
  324. return 0;
  325. }
  326.  
  327. #endif
Add Comment
Please, Sign In to add comment