static void cb_candidate_gathering_done(NiceAgent *agent, guint _stream_id, gpointer data) { g_debug("SIGNAL candidate gathering done\n"); // Candidate gathering is done. Send our local candidates on stdout printf("Copy this line to remote client:\n"); printf("\n "); print_local_data(agent, _stream_id, 1); printf("\n"); // Listen on stdin for the remote candidate list printf("Enter remote data (single line, no wrapping):\n"); g_io_add_watch(io_stdin, G_IO_IN, stdin_remote_info_cb, agent); printf("> "); fflush (stdout); }
static void * example_thread(void *data) { NiceAgent *agent; NiceCandidate *local, *remote; GIOChannel* io_stdin; guint stream_id; gchar *line = NULL; int rval; #ifdef G_OS_WIN32 io_stdin = g_io_channel_win32_new_fd(_fileno(stdin)); #else io_stdin = g_io_channel_unix_new(fileno(stdin)); #endif g_io_channel_set_flags (io_stdin, G_IO_FLAG_NONBLOCK, NULL); // Create the nice agent agent = nice_agent_new(g_main_loop_get_context (gloop), NICE_COMPATIBILITY_RFC5245); if (agent == NULL) g_error("Failed to create agent"); // Set the STUN settings and controlling mode if (stun_addr) { g_object_set(agent, "stun-server", stun_addr, NULL); g_object_set(agent, "stun-server-port", stun_port, NULL); } g_object_set(agent, "controlling-mode", controlling, NULL); // Connect to the signals g_signal_connect(agent, "candidate-gathering-done", G_CALLBACK(cb_candidate_gathering_done), NULL); g_signal_connect(agent, "new-selected-pair", G_CALLBACK(cb_new_selected_pair), NULL); g_signal_connect(agent, "component-state-changed", G_CALLBACK(cb_component_state_changed), NULL); // Create a new stream with one component stream_id = nice_agent_add_stream(agent, 1); if (stream_id == 0) g_error("Failed to add stream"); // Attach to the component to receive the data // Without this call, candidates cannot be gathered nice_agent_attach_recv(agent, stream_id, 1, g_main_loop_get_context (gloop), cb_nice_recv, NULL); // Start gathering local candidates if (!nice_agent_gather_candidates(agent, stream_id)) g_error("Failed to start candidate gathering"); g_debug("waiting for candidate-gathering-done signal..."); g_mutex_lock(&gather_mutex); while (!exit_thread && !candidate_gathering_done) g_cond_wait(&gather_cond, &gather_mutex); g_mutex_unlock(&gather_mutex); if (exit_thread) goto end; // Candidate gathering is done. Send our local candidates on stdout printf("Copy this line to remote client:\n"); printf("\n "); print_local_data(agent, stream_id, 1); printf("\n"); // Listen on stdin for the remote candidate list printf("Enter remote data (single line, no wrapping):\n"); printf("> "); fflush (stdout); while (!exit_thread) { GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL); if (s == G_IO_STATUS_NORMAL) { // Parse remote candidate list and set it on the agent rval = parse_remote_data(agent, stream_id, 1, line); if (rval == EXIT_SUCCESS) { g_free (line); break; } else { fprintf(stderr, "ERROR: failed to parse remote data\n"); printf("Enter remote data (single line, no wrapping):\n"); printf("> "); fflush (stdout); } g_free (line); } else if (s == G_IO_STATUS_AGAIN) { g_usleep (100000); } } g_debug("waiting for state READY or FAILED signal..."); g_mutex_lock(&negotiate_mutex); while (!exit_thread && !negotiation_done) g_cond_wait(&negotiate_cond, &negotiate_mutex); g_mutex_unlock(&negotiate_mutex); if (exit_thread) goto end; // Get current selected candidate pair and print IP address used if (nice_agent_get_selected_pair (agent, stream_id, 1, &local, &remote)) { gchar ipaddr[INET6_ADDRSTRLEN]; nice_address_to_string(&local->addr, ipaddr); printf("\nNegotiation complete: ([%s]:%d,", ipaddr, nice_address_get_port(&local->addr)); nice_address_to_string(&remote->addr, ipaddr); printf(" [%s]:%d)\n", ipaddr, nice_address_get_port(&remote->addr)); } // Listen to stdin and send data written to it printf("\nSend lines to remote (Ctrl-D to quit):\n"); printf("> "); fflush (stdout); while (!exit_thread) { GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL); if (s == G_IO_STATUS_NORMAL) { nice_agent_send(agent, stream_id, 1, strlen(line), line); g_free (line); printf("> "); fflush (stdout); } else if (s == G_IO_STATUS_AGAIN) { g_usleep (100000); } else { // Ctrl-D was pressed. nice_agent_send(agent, stream_id, 1, 1, "\0"); break; } } end: g_io_channel_unref (io_stdin); g_object_unref(agent); g_main_loop_quit (gloop); return NULL; }