static gboolean set_the_candidates (gpointer user_data) { FsStreamTransmitter *st = FS_STREAM_TRANSMITTER (user_data); GList *candidates = g_object_get_data (G_OBJECT (st), "candidates-set"); gboolean ret; GError *error = NULL; if (!candidates) { g_debug ("Skipping libnice check because it found NO local candidates"); g_atomic_int_set(&running, FALSE); g_main_loop_quit (loop); return FALSE; } if (force_candidates) { GList *item = NULL; GList *next = NULL; GList *new_list = NULL; for (item = candidates; item; item = next) { FsCandidate *cand = item->data; GList *item2 = NULL; next = g_list_next (item); for (item2 = new_list; item2; item2 = g_list_next (item2)) { FsCandidate *cand2 = item2->data; if (cand2->component_id == cand->component_id) break; } if (!item2) { candidates = g_list_remove (candidates, cand); new_list = g_list_append (new_list, cand); } } ret = fs_stream_transmitter_force_remote_candidates (st, new_list, &error); fs_candidate_list_destroy (new_list); } else { ret = fs_stream_transmitter_add_remote_candidates (st, candidates, &error); } if (error) ts_fail ("Error while adding candidate: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_unless (ret == TRUE, "No detailed error setting remote_candidate"); fs_candidate_list_destroy (candidates); return FALSE; }
static gboolean fs_rtp_stream_force_remote_candidates (FsStream *stream, GList *remote_candidates, GError **error) { FsRtpStream *self = FS_RTP_STREAM (stream); FsStreamTransmitter *st = fs_rtp_stream_get_stream_transmitter (self, error); gboolean ret = FALSE; if (!st) return FALSE; ret = fs_stream_transmitter_force_remote_candidates ( self->priv->stream_transmitter, remote_candidates, error); g_object_unref (st); return ret; }
static void _new_local_candidate (FsStreamTransmitter *st, FsCandidate *candidate, gpointer user_data) { gboolean is_local = GPOINTER_TO_INT (user_data) & FLAG_IS_LOCAL; GError *error = NULL; GList *item = NULL; gboolean ret; GST_DEBUG ("Has local candidate %s:%u of type %d", candidate->ip, candidate->port, candidate->type); ts_fail_if (candidate == NULL, "Passed NULL candidate"); ts_fail_unless (candidate->ip != NULL, "Null IP in candidate"); ts_fail_if (candidate->port == 0, "Candidate has port 0"); ts_fail_unless (candidate->proto == FS_NETWORK_PROTOCOL_UDP, "Protocol is not UDP"); if (has_stun) ts_fail_unless (candidate->type == FS_CANDIDATE_TYPE_SRFLX, "Has stun, but candidate is not server reflexive," " it is: %s:%u of type %d on component %u", candidate->ip, candidate->port, candidate->type, candidate->component_id); else { ts_fail_unless (candidate->type == FS_CANDIDATE_TYPE_HOST, "Does not have stun, but candidate is not host"); if (candidate->component_id == FS_COMPONENT_RTP) { ts_fail_unless (candidate->port % 2 == 0, "RTP port should be odd"); } else if (candidate->component_id == FS_COMPONENT_RTCP) { ts_fail_unless (candidate->port % 2 == 1, "RTCP port should be event"); } } if (is_local) { ts_fail_unless (!strcmp (candidate->ip, "127.0.0.1"), "IP is wrong, it is %s but should be 127.0.0.1 when local candidate set", candidate->ip); if (candidate->component_id == FS_COMPONENT_RTP) { ts_fail_unless (candidate->port >= RTP_PORT , "RTP port invalid"); } else if (candidate->component_id == FS_COMPONENT_RTCP) { ts_fail_unless (candidate->port >= RTCP_PORT, "RTCP port invalid"); } } candidates[candidate->component_id-1] = 1; GST_DEBUG ("New local candidate %s:%d of type %d for component %d", candidate->ip, candidate->port, candidate->type, candidate->component_id); item = g_list_prepend (NULL, candidate); ret = fs_stream_transmitter_force_remote_candidates (st, item, &error); g_list_free (item); if (error) ts_fail ("Error while adding candidate: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_unless (ret == TRUE, "No detailed error from add_remote_candidate"); }
static gboolean set_the_candidates (gpointer user_data) { FsStreamTransmitter *st = FS_STREAM_TRANSMITTER (user_data); GList *candidates = g_object_get_data (G_OBJECT (st), "candidates-set"); gboolean ret; GError *error = NULL; if (!candidates) { g_debug ("Skipping libnice check because it found NO local candidates"); g_atomic_int_set(&running, FALSE); g_main_loop_quit (loop); return FALSE; } if (force_candidates) { GList *item = NULL; GList *next = NULL; GList *new_list = NULL; for (item = candidates; item; item = next) { FsCandidate *cand = item->data; GList *item2 = NULL; next = g_list_next (item); if (cand->type != FS_CANDIDATE_TYPE_HOST) continue; if (cand->component_id != 1) continue; for (item2 = candidates; item2; item2 = g_list_next (item2)) { FsCandidate *cand2 = item2->data; if (cand2->component_id == 2 && !strcmp (cand->foundation, cand2->foundation)) { new_list = g_list_append (new_list, cand); new_list = g_list_append (new_list, cand2); goto got_candidates; } } } ts_fail ("Could not find two matching host candidates???"); got_candidates: ts_fail_unless (g_list_length (new_list) == 2); ret = fs_stream_transmitter_force_remote_candidates (st, new_list, &error); } else { ret = fs_stream_transmitter_add_remote_candidates (st, candidates, &error); } if (error) ts_fail ("Error while adding candidate: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_unless (ret == TRUE, "No detailed error setting remote_candidate"); fs_candidate_list_destroy (candidates); return FALSE; }
static void run_shm_transmitter_test (gint flags) { GError *error = NULL; FsTransmitter *trans; FsStreamTransmitter *st; GstBus *bus = NULL; GParameter params[1]; GList *local_cands = NULL; GstStateChangeReturn ret; FsCandidate *cand; GList *remote_cands = NULL; int param_count = 0; gint bus_source; done = FALSE; connected_count = 0; g_cond_init (&cond); g_mutex_init (&test_mutex); buffer_count[0] = 0; buffer_count[1] = 0; received_known[0] = 0; received_known[1] = 0; got_candidates[0] = FALSE; got_candidates[1] = FALSE; got_prepared[0] = FALSE; got_prepared[1] = FALSE; if (unlink ("/tmp/src1") < 0 && errno != ENOENT) fail ("Could not unlink /tmp/src1: %s", strerror (errno)); if (unlink ("/tmp/src2") < 0 && errno != ENOENT) fail ("Could not unlink /tmp/src2: %s", strerror (errno)); local_cands = g_list_append (local_cands, fs_candidate_new (NULL, 1, FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, "/tmp/src1", 0)); local_cands = g_list_append (local_cands, fs_candidate_new (NULL, 2, FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, "/tmp/src2", 0)); if (flags & FLAG_LOCAL_CANDIDATES) { memset (params, 0, sizeof (GParameter)); params[0].name = "preferred-local-candidates"; g_value_init (¶ms[0].value, FS_TYPE_CANDIDATE_LIST); g_value_take_boxed (¶ms[0].value, local_cands); param_count = 1; } associate_on_source = !(flags & FLAG_NO_SOURCE); if ((flags & FLAG_NOT_SENDING) && (flags & FLAG_RECVONLY_FILTER)) { buffer_count[0] = 20; received_known[0] = 20; } trans = fs_transmitter_new ("shm", 2, 0, &error); if (error) ts_fail ("Error creating transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_if (trans == NULL, "No transmitter create, yet error is still NULL"); g_clear_error (&error); if (flags & FLAG_RECVONLY_FILTER) ts_fail_unless (g_signal_connect (trans, "get-recvonly-filter", G_CALLBACK (get_recvonly_filter), NULL)); pipeline = setup_pipeline (trans, G_CALLBACK (_handoff_handler)); bus = gst_element_get_bus (pipeline); bus_source = gst_bus_add_watch (bus, bus_error_callback, NULL); gst_bus_enable_sync_message_emission (bus); g_signal_connect (bus, "sync-message::error", G_CALLBACK (sync_error_handler), NULL); gst_object_unref (bus); st = fs_transmitter_new_stream_transmitter (trans, NULL, param_count, params, &error); if (param_count) g_value_unset (¶ms[0].value); if (error) ts_fail ("Error creating stream transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_if (st == NULL, "No stream transmitter created, yet error is NULL"); g_clear_error (&error); g_object_set (st, "sending", !(flags & FLAG_NOT_SENDING), NULL); ts_fail_unless (g_signal_connect (st, "new-local-candidate", G_CALLBACK (_new_local_candidate), trans), "Could not connect new-local-candidate signal"); ts_fail_unless (g_signal_connect (st, "local-candidates-prepared", G_CALLBACK (_candidate_prepared), NULL), "Could not connect local-candidates-prepared signal"); ts_fail_unless (g_signal_connect (st, "error", G_CALLBACK (stream_transmitter_error), NULL), "Could not connect error signal"); ts_fail_unless (g_signal_connect (st, "known-source-packet-received", G_CALLBACK (_known_source_packet_received), NULL), "Could not connect known-source-packet-received signal"); ts_fail_unless (g_signal_connect (st, "state-changed", G_CALLBACK (_state_changed), NULL), "Could not connect state-changed signal"); if (!fs_stream_transmitter_gather_local_candidates (st, &error)) { if (error) ts_fail ("Could not start gathering local candidates (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); else ts_fail ("Could not start gathering candidates" " (without a specified error)"); } else { ts_fail_unless (error == NULL); } g_clear_error (&error); ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); ts_fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not set the pipeline to playing"); if (!(flags & FLAG_LOCAL_CANDIDATES)) { ret = fs_stream_transmitter_force_remote_candidates (st, local_cands, &error); fs_candidate_list_destroy (local_cands); if (error) ts_fail ("Error while adding candidate: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_unless (ret == TRUE, "No detailed error from add_remote_candidate"); } else { ts_fail_unless (error == NULL); } g_clear_error (&error); cand = fs_candidate_new (NULL, 1, FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, NULL, 0); cand->username = g_strdup ("/tmp/src1"); remote_cands = g_list_prepend (remote_cands, cand); cand = fs_candidate_new (NULL, 2, FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, NULL, 0); cand->username = g_strdup ("/tmp/src2"); remote_cands = g_list_prepend (remote_cands, cand); ret = fs_stream_transmitter_force_remote_candidates (st, remote_cands, &error); fs_candidate_list_destroy (remote_cands); if (error) ts_fail ("Error while adding candidate: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_unless (ret == TRUE, "No detailed error from add_remote_candidate"); g_clear_error (&error); g_mutex_lock (&test_mutex); while (connected_count < 2) g_cond_wait (&cond, &test_mutex); g_mutex_unlock (&test_mutex); setup_fakesrc (trans, pipeline, 1); setup_fakesrc (trans, pipeline, 2); g_mutex_lock (&test_mutex); while (!done) g_cond_wait (&cond, &test_mutex); g_mutex_unlock (&test_mutex); fail_unless (got_prepared[0] == TRUE); fail_unless (got_prepared[1] == TRUE); fail_unless (got_candidates[0] == TRUE); fail_unless (got_candidates[1] == TRUE); gst_element_set_state (pipeline, GST_STATE_NULL); if (st) { fs_stream_transmitter_stop (st); g_object_unref (st); } g_object_unref (trans); g_source_remove (bus_source); gst_object_unref (pipeline); g_cond_clear (&cond); g_mutex_clear (&test_mutex); }