|
Packit |
133782 |
/*
|
|
Packit |
133782 |
* Farstream - Farstream libnice Stream Transmitter
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* Copyright 2007 Collabora Ltd.
|
|
Packit |
133782 |
* @author: Olivier Crete <olivier.crete@collabora.co.uk>
|
|
Packit |
133782 |
* Copyright 2007 Nokia Corp.
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* fs-nice-stream-transmitter.c - A Farstream libnice stream transmitter
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
133782 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
133782 |
* License as published by the Free Software Foundation; either
|
|
Packit |
133782 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
133782 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
133782 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
133782 |
* Lesser General Public License for more details.
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
133782 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
133782 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
133782 |
*/
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/**
|
|
Packit |
133782 |
* SECTION:fs-nice-stream-transmitter
|
|
Packit |
133782 |
* @short_description: A stream transmitter object for ICE using libnice
|
|
Packit |
133782 |
* @see_also: #FsRawUdpStreamTransmitter
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
*/
|
|
Packit |
133782 |
|
|
Packit |
133782 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
133782 |
#include "config.h"
|
|
Packit |
133782 |
#endif
|
|
Packit |
133782 |
|
|
Packit |
133782 |
#include "fs-nice-stream-transmitter.h"
|
|
Packit |
133782 |
#include "fs-nice-transmitter.h"
|
|
Packit |
133782 |
#include "fs-nice-agent.h"
|
|
Packit |
133782 |
|
|
Packit |
133782 |
#include <farstream/fs-conference.h>
|
|
Packit |
133782 |
|
|
Packit |
133782 |
#include <gst/gst.h>
|
|
Packit |
133782 |
|
|
Packit |
133782 |
#include <string.h>
|
|
Packit |
133782 |
#include <sys/types.h>
|
|
Packit |
133782 |
|
|
Packit |
133782 |
#define GST_CAT_DEFAULT fs_nice_transmitter_debug
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* Signals */
|
|
Packit |
133782 |
enum
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
LAST_SIGNAL
|
|
Packit |
133782 |
};
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* props */
|
|
Packit |
133782 |
enum
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
PROP_0,
|
|
Packit |
133782 |
PROP_SENDING,
|
|
Packit |
133782 |
PROP_PREFERRED_LOCAL_CANDIDATES,
|
|
Packit |
133782 |
PROP_STUN_IP,
|
|
Packit |
133782 |
PROP_STUN_PORT,
|
|
Packit |
133782 |
PROP_CONTROLLING_MODE,
|
|
Packit |
133782 |
PROP_STREAM_ID,
|
|
Packit |
133782 |
PROP_COMPATIBILITY_MODE,
|
|
Packit |
133782 |
PROP_ASSOCIATE_ON_SOURCE,
|
|
Packit |
133782 |
PROP_RELAY_INFO,
|
|
Packit |
133782 |
PROP_MIN_PORT,
|
|
Packit |
133782 |
PROP_MAX_PORT,
|
|
Packit |
133782 |
PROP_ICE_TCP,
|
|
Packit |
133782 |
PROP_ICE_UDP,
|
|
Packit |
133782 |
PROP_RELIABLE,
|
|
Packit |
133782 |
PROP_DEBUG,
|
|
Packit |
133782 |
PROP_SEND_COMPONENT_MUX
|
|
Packit |
133782 |
};
|
|
Packit |
133782 |
|
|
Packit |
133782 |
struct _FsNiceStreamTransmitterPrivate
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceTransmitter *transmitter;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FsNiceAgent *agent;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
guint stream_id;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
guint min_port;
|
|
Packit |
133782 |
guint max_port;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
gchar *stun_ip;
|
|
Packit |
133782 |
guint stun_port;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
gboolean controlling_mode;
|
|
Packit |
133782 |
gboolean ice_udp;
|
|
Packit |
133782 |
gboolean ice_tcp;
|
|
Packit |
133782 |
gboolean reliable;
|
|
Packit |
133782 |
gboolean send_component_mux;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
guint compatibility_mode;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GMutex mutex;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GList *preferred_local_candidates;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
gulong state_changed_handler_id;
|
|
Packit |
133782 |
gulong gathering_done_handler_id;
|
|
Packit |
133782 |
gulong new_selected_pair_handler_id;
|
|
Packit |
133782 |
gulong new_candidate_handler_id;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
gulong tos_changed_handler_id;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GPtrArray *relay_info;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
volatile gint associate_on_source;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
gboolean *component_has_been_ready; /* only from NiceAgent main thread */
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* Everything below is protected by the mutex */
|
|
Packit |
133782 |
|
|
Packit |
133782 |
gboolean sending;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
gboolean forced_candidates;
|
|
Packit |
133782 |
GList *remote_candidates;
|
|
Packit |
133782 |
GList *local_candidates;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* These are fixed and must be identical in the latest draft */
|
|
Packit |
133782 |
gchar *username;
|
|
Packit |
133782 |
gchar *password;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
gboolean gathered;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
NiceGstStream *gststream;
|
|
Packit |
133782 |
};
|
|
Packit |
133782 |
|
|
Packit |
133782 |
#define FS_NICE_STREAM_TRANSMITTER_GET_PRIVATE(o) \
|
|
Packit |
133782 |
(G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_NICE_STREAM_TRANSMITTER, \
|
|
Packit |
133782 |
FsNiceStreamTransmitterPrivate))
|
|
Packit |
133782 |
|
|
Packit |
133782 |
#define FS_NICE_STREAM_TRANSMITTER_LOCK(o) g_mutex_lock (&(o)->priv->mutex)
|
|
Packit |
133782 |
#define FS_NICE_STREAM_TRANSMITTER_UNLOCK(o) g_mutex_unlock (&(o)->priv->mutex)
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void fs_nice_stream_transmitter_class_init (FsNiceStreamTransmitterClass *klass);
|
|
Packit |
133782 |
static void fs_nice_stream_transmitter_init (FsNiceStreamTransmitter *self);
|
|
Packit |
133782 |
static void fs_nice_stream_transmitter_dispose (GObject *object);
|
|
Packit |
133782 |
static void fs_nice_stream_transmitter_finalize (GObject *object);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void fs_nice_stream_transmitter_get_property (GObject *object,
|
|
Packit |
133782 |
guint prop_id,
|
|
Packit |
133782 |
GValue *value,
|
|
Packit |
133782 |
GParamSpec *pspec);
|
|
Packit |
133782 |
static void fs_nice_stream_transmitter_set_property (GObject *object,
|
|
Packit |
133782 |
guint prop_id,
|
|
Packit |
133782 |
const GValue *value,
|
|
Packit |
133782 |
GParamSpec *pspec);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean fs_nice_stream_transmitter_add_remote_candidates (
|
|
Packit |
133782 |
FsStreamTransmitter *streamtransmitter, GList *candidates,
|
|
Packit |
133782 |
GError **error);
|
|
Packit |
133782 |
static gboolean fs_nice_stream_transmitter_force_remote_candidates (
|
|
Packit |
133782 |
FsStreamTransmitter *streamtransmitter,
|
|
Packit |
133782 |
GList *remote_candidates,
|
|
Packit |
133782 |
GError **error);
|
|
Packit |
133782 |
static gboolean fs_nice_stream_transmitter_gather_local_candidates (
|
|
Packit |
133782 |
FsStreamTransmitter *streamtransmitter,
|
|
Packit |
133782 |
GError **error);
|
|
Packit |
133782 |
static void fs_nice_stream_transmitter_stop (
|
|
Packit |
133782 |
FsStreamTransmitter *streamtransmitter);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void agent_state_changed (NiceAgent *agent,
|
|
Packit |
133782 |
guint stream_id,
|
|
Packit |
133782 |
guint component_id,
|
|
Packit |
133782 |
guint state,
|
|
Packit |
133782 |
gpointer user_data);
|
|
Packit |
133782 |
static void agent_gathering_done (NiceAgent *agent, guint stream_id,
|
|
Packit |
133782 |
gpointer user_data);
|
|
Packit |
133782 |
static void agent_new_selected_pair (NiceAgent *agent,
|
|
Packit |
133782 |
guint stream_id,
|
|
Packit |
133782 |
guint component_id,
|
|
Packit |
133782 |
const gchar *lfoundation,
|
|
Packit |
133782 |
const gchar *rfoundation,
|
|
Packit |
133782 |
gpointer user_data);
|
|
Packit |
133782 |
static void agent_new_candidate (NiceAgent *agent,
|
|
Packit |
133782 |
guint stream_id,
|
|
Packit |
133782 |
guint component_id,
|
|
Packit |
133782 |
const gchar *foundation,
|
|
Packit |
133782 |
gpointer user_data);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static GstPadProbeReturn known_buffer_have_buffer_handler (GstPad *pad,
|
|
Packit |
133782 |
GstPadProbeInfo *info,
|
|
Packit |
133782 |
gpointer user_data);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static GObjectClass *parent_class = NULL;
|
|
Packit |
133782 |
// static guint signals[LAST_SIGNAL] = { 0 };
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static GType type = 0;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GType
|
|
Packit |
133782 |
fs_nice_stream_transmitter_get_type (void)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
return type;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GType
|
|
Packit |
133782 |
fs_nice_stream_transmitter_register_type (FsPlugin *module G_GNUC_UNUSED)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
static const GTypeInfo info = {
|
|
Packit |
133782 |
sizeof (FsNiceStreamTransmitterClass),
|
|
Packit |
133782 |
NULL,
|
|
Packit |
133782 |
NULL,
|
|
Packit |
133782 |
(GClassInitFunc) fs_nice_stream_transmitter_class_init,
|
|
Packit |
133782 |
NULL,
|
|
Packit |
133782 |
NULL,
|
|
Packit |
133782 |
sizeof (FsNiceStreamTransmitter),
|
|
Packit |
133782 |
0,
|
|
Packit |
133782 |
(GInstanceInitFunc) fs_nice_stream_transmitter_init
|
|
Packit |
133782 |
};
|
|
Packit |
133782 |
|
|
Packit |
133782 |
type = g_type_register_static (FS_TYPE_STREAM_TRANSMITTER,
|
|
Packit |
133782 |
"FsNiceStreamTransmitter", &info, 0);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return type;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
fs_nice_stream_transmitter_class_init (FsNiceStreamTransmitterClass *klass)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
GObjectClass *gobject_class = (GObjectClass *) klass;
|
|
Packit |
133782 |
FsStreamTransmitterClass *streamtransmitterclass =
|
|
Packit |
133782 |
FS_STREAM_TRANSMITTER_CLASS (klass);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
parent_class = g_type_class_peek_parent (klass);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
gobject_class->set_property = fs_nice_stream_transmitter_set_property;
|
|
Packit |
133782 |
gobject_class->get_property = fs_nice_stream_transmitter_get_property;
|
|
Packit |
133782 |
gobject_class->dispose = fs_nice_stream_transmitter_dispose;
|
|
Packit |
133782 |
gobject_class->finalize = fs_nice_stream_transmitter_finalize;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
streamtransmitterclass->add_remote_candidates =
|
|
Packit |
133782 |
fs_nice_stream_transmitter_add_remote_candidates;
|
|
Packit |
133782 |
streamtransmitterclass->force_remote_candidates =
|
|
Packit |
133782 |
fs_nice_stream_transmitter_force_remote_candidates;
|
|
Packit |
133782 |
streamtransmitterclass->gather_local_candidates =
|
|
Packit |
133782 |
fs_nice_stream_transmitter_gather_local_candidates;
|
|
Packit |
133782 |
streamtransmitterclass->stop =
|
|
Packit |
133782 |
fs_nice_stream_transmitter_stop;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_type_class_add_private (klass, sizeof (FsNiceStreamTransmitterPrivate));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_override_property (gobject_class, PROP_SENDING, "sending");
|
|
Packit |
133782 |
g_object_class_override_property (gobject_class,
|
|
Packit |
133782 |
PROP_PREFERRED_LOCAL_CANDIDATES, "preferred-local-candidates");
|
|
Packit |
133782 |
g_object_class_override_property (gobject_class, PROP_ASSOCIATE_ON_SOURCE,
|
|
Packit |
133782 |
"associate-on-source");
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_STUN_IP,
|
|
Packit |
133782 |
g_param_spec_string (
|
|
Packit |
133782 |
"stun-ip",
|
|
Packit |
133782 |
"STUN server",
|
|
Packit |
133782 |
"The STUN server used to obtain server-reflexive candidates",
|
|
Packit |
133782 |
NULL,
|
|
Packit |
133782 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_STUN_PORT,
|
|
Packit |
133782 |
g_param_spec_uint (
|
|
Packit |
133782 |
"stun-port",
|
|
Packit |
133782 |
"STUN server port",
|
|
Packit |
133782 |
"The STUN server used to obtain server-reflexive candidates",
|
|
Packit |
133782 |
0, 65536,
|
|
Packit |
133782 |
3478,
|
|
Packit |
133782 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_CONTROLLING_MODE,
|
|
Packit |
133782 |
g_param_spec_boolean (
|
|
Packit |
133782 |
"controlling-mode",
|
|
Packit |
133782 |
"ICE controlling mode",
|
|
Packit |
133782 |
"Whether the agent is in controlling mode",
|
|
Packit |
133782 |
TRUE,
|
|
Packit |
133782 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_ICE_UDP,
|
|
Packit |
133782 |
g_param_spec_boolean (
|
|
Packit |
133782 |
"ice-udp",
|
|
Packit |
133782 |
"ICE UDP",
|
|
Packit |
133782 |
"Whether the agent gathers UDP candidates",
|
|
Packit |
133782 |
TRUE,
|
|
Packit |
133782 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_ICE_TCP,
|
|
Packit |
133782 |
g_param_spec_boolean (
|
|
Packit |
133782 |
"ice-tcp",
|
|
Packit |
133782 |
"ICE TCP",
|
|
Packit |
133782 |
"Whether the agent gathers TCP candidates",
|
|
Packit |
133782 |
TRUE,
|
|
Packit |
133782 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_RELIABLE,
|
|
Packit |
133782 |
g_param_spec_boolean (
|
|
Packit |
133782 |
"reliable",
|
|
Packit |
133782 |
"reliable mode",
|
|
Packit |
133782 |
"Whether the agent is reliable",
|
|
Packit |
133782 |
FALSE,
|
|
Packit |
133782 |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_STREAM_ID,
|
|
Packit |
133782 |
g_param_spec_uint (
|
|
Packit |
133782 |
"stream-id",
|
|
Packit |
133782 |
"The id of the stream",
|
|
Packit |
133782 |
"The id of the stream according to libnice",
|
|
Packit |
133782 |
0, G_MAXINT,
|
|
Packit |
133782 |
0,
|
|
Packit |
133782 |
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_COMPATIBILITY_MODE,
|
|
Packit |
133782 |
g_param_spec_uint (
|
|
Packit |
133782 |
"compatibility-mode",
|
|
Packit |
133782 |
"The compability-mode",
|
|
Packit |
133782 |
"The id of the stream according to libnice",
|
|
Packit |
133782 |
NICE_COMPATIBILITY_DRAFT19, NICE_COMPATIBILITY_LAST,
|
|
Packit |
133782 |
NICE_COMPATIBILITY_DRAFT19,
|
|
Packit |
133782 |
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/**
|
|
Packit |
133782 |
* FsNiceStreamTransmitter:relay-info:
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* This is a #GPtrArray containing one or more #GstStructure.
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* The fields in the structure are:
|
|
Packit |
133782 |
* <informaltable>
|
|
Packit |
133782 |
* Required
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* (gchar*)
|
|
Packit |
133782 |
* ip
|
|
Packit |
133782 |
* The IP address of the TURN server
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* (guint)
|
|
Packit |
133782 |
* port
|
|
Packit |
133782 |
* The port of the TURN server
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* (gchar*)
|
|
Packit |
133782 |
* username
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* (gchar*)
|
|
Packit |
133782 |
* password
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* Optional
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* (gchar *)
|
|
Packit |
133782 |
* relay-type
|
|
Packit |
133782 |
* The type of TURN server, can use "udp", "tcp" or "tls".
|
|
Packit |
133782 |
* Defaults to "udp" if not specified.
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* (guint)
|
|
Packit |
133782 |
* component
|
|
Packit |
133782 |
* The component this TURN server and creditials will be used for.
|
|
Packit |
133782 |
* If no component is specified, it will be used for all components where
|
|
Packit |
133782 |
* no per-component details were specified.
|
|
Packit |
133782 |
* This is useful if you want to specify different short term creditial
|
|
Packit |
133782 |
* username/password combinations for Google and MSN compatibility modes.
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* </informaltable>
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
* Example:
|
|
Packit |
133782 |
* |[
|
|
Packit |
133782 |
GPtrArray *relay_info = g_ptr_array_new_full (1, (GDestroyNotify) gst_structure_free);
|
|
Packit |
133782 |
g_ptr_array_add (relay_info,
|
|
Packit |
133782 |
gst_structure_new ("aa",
|
|
Packit |
133782 |
"ip", G_TYPE_STRING, "127.0.0.1",
|
|
Packit |
133782 |
"port", G_TYPE_UINT, 7654,
|
|
Packit |
133782 |
"username", G_TYPE_STRING, "blah",
|
|
Packit |
133782 |
"password", G_TYPE_STRING, "blah2",
|
|
Packit |
133782 |
"relay-type", G_TYPE_STRING, "udp",
|
|
Packit |
133782 |
NULL));
|
|
Packit |
133782 |
|]
|
|
Packit |
133782 |
*
|
|
Packit |
133782 |
*/
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_RELAY_INFO,
|
|
Packit |
133782 |
g_param_spec_boxed (
|
|
Packit |
133782 |
"relay-info",
|
|
Packit |
133782 |
"Information for the TURN server",
|
|
Packit |
133782 |
"ip/port/username/password/relay-type/component of the TURN servers"
|
|
Packit |
133782 |
" in a GPtrArray of GstStructures",
|
|
Packit |
133782 |
G_TYPE_PTR_ARRAY,
|
|
Packit |
133782 |
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_DEBUG,
|
|
Packit |
133782 |
g_param_spec_boolean (
|
|
Packit |
133782 |
"debug",
|
|
Packit |
133782 |
"Enable debug messages",
|
|
Packit |
133782 |
"Whether the agent should enable libnice and stun debug messages",
|
|
Packit |
133782 |
FALSE,
|
|
Packit |
133782 |
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_MIN_PORT,
|
|
Packit |
133782 |
g_param_spec_uint (
|
|
Packit |
133782 |
"min-port",
|
|
Packit |
133782 |
"Minimal listen port",
|
|
Packit |
133782 |
"Minimal port number for allocating host candidates."
|
|
Packit |
133782 |
" 0 means use any port",
|
|
Packit |
133782 |
0, 65535,
|
|
Packit |
133782 |
0,
|
|
Packit |
133782 |
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_MAX_PORT,
|
|
Packit |
133782 |
g_param_spec_uint (
|
|
Packit |
133782 |
"max-port",
|
|
Packit |
133782 |
"Maximal listen port",
|
|
Packit |
133782 |
"Maximal port number for allocating host candidates."
|
|
Packit |
133782 |
" It should apply that min-port < max-port; otherwise, any port is"
|
|
Packit |
133782 |
" used, just as when the value is 0",
|
|
Packit |
133782 |
0, 65535,
|
|
Packit |
133782 |
0,
|
|
Packit |
133782 |
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_class_install_property (gobject_class, PROP_SEND_COMPONENT_MUX,
|
|
Packit |
133782 |
g_param_spec_boolean (
|
|
Packit |
133782 |
"send-component-mux",
|
|
Packit |
133782 |
"Send component mux",
|
|
Packit |
133782 |
"Whether to mux all components on the same component as component 1",
|
|
Packit |
133782 |
FALSE,
|
|
Packit |
133782 |
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
fs_nice_stream_transmitter_init (FsNiceStreamTransmitter *self)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
/* member init */
|
|
Packit |
133782 |
self->priv = FS_NICE_STREAM_TRANSMITTER_GET_PRIVATE (self);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
self->priv->sending = TRUE;
|
|
Packit |
133782 |
g_mutex_init (&self->priv->mutex);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
self->priv->controlling_mode = TRUE;
|
|
Packit |
133782 |
self->priv->ice_udp = TRUE;
|
|
Packit |
133782 |
self->priv->ice_tcp = TRUE;
|
|
Packit |
133782 |
self->priv->reliable = TRUE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
fs_nice_stream_transmitter_dispose (GObject *object)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = FS_NICE_STREAM_TRANSMITTER (object);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
fs_nice_stream_transmitter_stop (FS_STREAM_TRANSMITTER_CAST (object));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
if (self->priv->state_changed_handler_id)
|
|
Packit |
133782 |
g_signal_handler_disconnect (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->state_changed_handler_id);
|
|
Packit |
133782 |
self->priv->state_changed_handler_id = 0;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->gathering_done_handler_id)
|
|
Packit |
133782 |
g_signal_handler_disconnect (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->gathering_done_handler_id);
|
|
Packit |
133782 |
self->priv->gathering_done_handler_id = 0;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->new_selected_pair_handler_id)
|
|
Packit |
133782 |
g_signal_handler_disconnect (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->new_selected_pair_handler_id);
|
|
Packit |
133782 |
self->priv->new_selected_pair_handler_id = 0;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->new_candidate_handler_id)
|
|
Packit |
133782 |
g_signal_handler_disconnect (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->new_candidate_handler_id);
|
|
Packit |
133782 |
self->priv->new_candidate_handler_id = 0;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->tos_changed_handler_id)
|
|
Packit |
133782 |
g_signal_handler_disconnect (self->priv->transmitter,
|
|
Packit |
133782 |
self->priv->tos_changed_handler_id);
|
|
Packit |
133782 |
self->priv->tos_changed_handler_id = 0;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->agent)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_object_unref (self->priv->agent);
|
|
Packit |
133782 |
self->priv->agent = NULL;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->transmitter)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_object_unref (self->priv->transmitter);
|
|
Packit |
133782 |
self->priv->transmitter = NULL;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
parent_class->dispose (object);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
fs_nice_stream_transmitter_stop (FsStreamTransmitter *streamtransmitter)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self =
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER (streamtransmitter);
|
|
Packit |
133782 |
NiceGstStream *gststream;
|
|
Packit |
133782 |
guint stream_id;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
gststream = self->priv->gststream;
|
|
Packit |
133782 |
self->priv->gststream = NULL;
|
|
Packit |
133782 |
stream_id = self->priv->stream_id;
|
|
Packit |
133782 |
/* We can't unset the stream id because it gets messy fast, just leave it as
|
|
Packit |
133782 |
* is, all calls should fail anyway
|
|
Packit |
133782 |
*/
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (gststream)
|
|
Packit |
133782 |
fs_nice_transmitter_free_gst_stream (self->priv->transmitter, gststream);
|
|
Packit |
133782 |
if (stream_id)
|
|
Packit |
133782 |
nice_agent_remove_stream (self->priv->agent->agent, stream_id);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
fs_nice_stream_transmitter_finalize (GObject *object)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = FS_NICE_STREAM_TRANSMITTER (object);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
fs_candidate_list_destroy (self->priv->preferred_local_candidates);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
fs_candidate_list_destroy (self->priv->remote_candidates);
|
|
Packit |
133782 |
fs_candidate_list_destroy (self->priv->local_candidates);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->relay_info)
|
|
Packit |
133782 |
g_ptr_array_unref (self->priv->relay_info);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_free (self->priv->stun_ip);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_mutex_clear (&self->priv->mutex);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_free (self->priv->username);
|
|
Packit |
133782 |
g_free (self->priv->password);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_free (self->priv->component_has_been_ready);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
parent_class->finalize (object);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
fs_nice_stream_transmitter_get_property (GObject *object,
|
|
Packit |
133782 |
guint prop_id,
|
|
Packit |
133782 |
GValue *value,
|
|
Packit |
133782 |
GParamSpec *pspec)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = FS_NICE_STREAM_TRANSMITTER (object);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
switch (prop_id)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
case PROP_SENDING:
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
g_value_set_boolean (value, self->priv->sending);
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_PREFERRED_LOCAL_CANDIDATES:
|
|
Packit |
133782 |
g_value_set_boxed (value, self->priv->preferred_local_candidates);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_STUN_IP:
|
|
Packit |
133782 |
if (self->priv->agent)
|
|
Packit |
133782 |
g_object_get_property (G_OBJECT (self->priv->agent->agent),
|
|
Packit |
133782 |
g_param_spec_get_name (pspec), value);
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
g_value_set_string (value, self->priv->stun_ip);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_STUN_PORT:
|
|
Packit |
133782 |
if (self->priv->agent)
|
|
Packit |
133782 |
g_object_get_property (G_OBJECT (self->priv->agent->agent),
|
|
Packit |
133782 |
g_param_spec_get_name (pspec), value);
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
g_value_set_uint (value, self->priv->stun_port);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_CONTROLLING_MODE:
|
|
Packit |
133782 |
if (self->priv->agent)
|
|
Packit |
133782 |
g_object_get_property (G_OBJECT (self->priv->agent->agent),
|
|
Packit |
133782 |
g_param_spec_get_name (pspec), value);
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
g_value_set_boolean (value, self->priv->controlling_mode);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_ICE_UDP:
|
|
Packit |
133782 |
if (self->priv->agent)
|
|
Packit |
133782 |
g_object_get_property (G_OBJECT (self->priv->agent->agent),
|
|
Packit |
133782 |
g_param_spec_get_name (pspec), value);
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
g_value_set_boolean (value, self->priv->ice_udp);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_ICE_TCP:
|
|
Packit |
133782 |
if (self->priv->agent)
|
|
Packit |
133782 |
g_object_get_property (G_OBJECT (self->priv->agent->agent),
|
|
Packit |
133782 |
g_param_spec_get_name (pspec), value);
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
g_value_set_boolean (value, self->priv->ice_tcp);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_RELIABLE:
|
|
Packit |
133782 |
if (self->priv->agent)
|
|
Packit |
133782 |
g_object_get_property (G_OBJECT (self->priv->agent->agent),
|
|
Packit |
133782 |
g_param_spec_get_name (pspec), value);
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
g_value_set_boolean (value, self->priv->reliable);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_STREAM_ID:
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
g_value_set_uint (value, self->priv->stream_id);
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_COMPATIBILITY_MODE:
|
|
Packit |
133782 |
g_value_set_uint (value, self->priv->compatibility_mode);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_ASSOCIATE_ON_SOURCE:
|
|
Packit |
133782 |
g_value_set_boolean (value,
|
|
Packit |
133782 |
g_atomic_int_get (&self->priv->associate_on_source));
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_SEND_COMPONENT_MUX:
|
|
Packit |
133782 |
g_value_set_boolean (value, self->priv->send_component_mux);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
default:
|
|
Packit |
133782 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
fs_nice_stream_transmitter_set_property (GObject *object,
|
|
Packit |
133782 |
guint prop_id,
|
|
Packit |
133782 |
const GValue *value,
|
|
Packit |
133782 |
GParamSpec *pspec)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = FS_NICE_STREAM_TRANSMITTER (object);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
switch (prop_id)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
case PROP_SENDING:
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
self->priv->sending = g_value_get_boolean (value);
|
|
Packit |
133782 |
if (self->priv->gststream)
|
|
Packit |
133782 |
fs_nice_transmitter_set_sending (self->priv->transmitter,
|
|
Packit |
133782 |
self->priv->gststream, g_value_get_boolean (value));
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_PREFERRED_LOCAL_CANDIDATES:
|
|
Packit |
133782 |
self->priv->preferred_local_candidates = g_value_dup_boxed (value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_STUN_IP:
|
|
Packit |
133782 |
self->priv->stun_ip = g_value_dup_string (value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_STUN_PORT:
|
|
Packit |
133782 |
self->priv->stun_port = g_value_get_uint (value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_CONTROLLING_MODE:
|
|
Packit |
133782 |
self->priv->controlling_mode = g_value_get_boolean (value);
|
|
Packit |
133782 |
if (self->priv->transmitter && self->priv->agent)
|
|
Packit |
133782 |
g_object_set_property (G_OBJECT (self->priv->agent->agent),
|
|
Packit |
133782 |
g_param_spec_get_name (pspec), value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_ICE_UDP:
|
|
Packit |
133782 |
self->priv->ice_udp = g_value_get_boolean (value);
|
|
Packit |
133782 |
if (self->priv->transmitter && self->priv->agent)
|
|
Packit |
133782 |
g_object_set_property (G_OBJECT (self->priv->agent->agent),
|
|
Packit |
133782 |
g_param_spec_get_name (pspec), value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_ICE_TCP:
|
|
Packit |
133782 |
self->priv->ice_tcp = g_value_get_boolean (value);
|
|
Packit |
133782 |
if (self->priv->transmitter && self->priv->agent)
|
|
Packit |
133782 |
g_object_set_property (G_OBJECT (self->priv->agent->agent),
|
|
Packit |
133782 |
g_param_spec_get_name (pspec), value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_RELIABLE:
|
|
Packit |
133782 |
self->priv->reliable = g_value_get_boolean (value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_COMPATIBILITY_MODE:
|
|
Packit |
133782 |
self->priv->compatibility_mode = g_value_get_uint (value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_ASSOCIATE_ON_SOURCE:
|
|
Packit |
133782 |
g_atomic_int_set (&self->priv->associate_on_source,
|
|
Packit |
133782 |
g_value_get_boolean (value));
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_RELAY_INFO:
|
|
Packit |
133782 |
self->priv->relay_info = g_value_dup_boxed (value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_MIN_PORT:
|
|
Packit |
133782 |
self->priv->min_port = g_value_get_uint (value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_MAX_PORT:
|
|
Packit |
133782 |
self->priv->max_port = g_value_get_uint (value);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_DEBUG:
|
|
Packit |
133782 |
if (g_value_get_boolean (value)) {
|
|
Packit |
133782 |
nice_debug_enable (TRUE);
|
|
Packit |
133782 |
} else {
|
|
Packit |
133782 |
nice_debug_disable (TRUE);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
case PROP_SEND_COMPONENT_MUX:
|
|
Packit |
133782 |
self->priv->send_component_mux = g_value_get_boolean (value);
|
|
Packit |
133782 |
if (self->priv->gststream != NULL)
|
|
Packit |
133782 |
fs_nice_transmitter_set_send_component_mux (self->priv->transmitter,
|
|
Packit |
133782 |
self->priv->gststream, self->priv->send_component_mux);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
default:
|
|
Packit |
133782 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static NiceCandidateType
|
|
Packit |
133782 |
fs_candidate_type_to_nice_candidate_type (FsCandidateType type)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
switch (type)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
case FS_CANDIDATE_TYPE_HOST:
|
|
Packit |
133782 |
return NICE_CANDIDATE_TYPE_HOST;
|
|
Packit |
133782 |
case FS_CANDIDATE_TYPE_SRFLX:
|
|
Packit |
133782 |
return NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE;
|
|
Packit |
133782 |
case FS_CANDIDATE_TYPE_PRFLX:
|
|
Packit |
133782 |
return NICE_CANDIDATE_TYPE_PEER_REFLEXIVE;
|
|
Packit |
133782 |
case FS_CANDIDATE_TYPE_RELAY:
|
|
Packit |
133782 |
return NICE_CANDIDATE_TYPE_RELAYED;
|
|
Packit |
133782 |
default:
|
|
Packit |
133782 |
GST_WARNING ("Invalid candidate type %d, defaulting to type host", type);
|
|
Packit |
133782 |
return NICE_CANDIDATE_TYPE_HOST;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static NiceCandidateTransport
|
|
Packit |
133782 |
fs_network_protocol_to_nice_candidate_protocol (FsNetworkProtocol proto)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
switch (proto)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
case FS_NETWORK_PROTOCOL_UDP:
|
|
Packit |
133782 |
return NICE_CANDIDATE_TRANSPORT_UDP;
|
|
Packit |
133782 |
case FS_NETWORK_PROTOCOL_TCP_ACTIVE:
|
|
Packit |
133782 |
return NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
|
|
Packit |
133782 |
case FS_NETWORK_PROTOCOL_TCP_PASSIVE:
|
|
Packit |
133782 |
return NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
|
|
Packit |
133782 |
case FS_NETWORK_PROTOCOL_TCP_SO:
|
|
Packit |
133782 |
return NICE_CANDIDATE_TRANSPORT_TCP_SO;
|
|
Packit |
133782 |
default:
|
|
Packit |
133782 |
GST_WARNING ("Invalid Fs network protocol type %u", proto);
|
|
Packit |
133782 |
return NICE_CANDIDATE_TRANSPORT_UDP;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static NiceCandidate *
|
|
Packit |
133782 |
fs_candidate_to_nice_candidate (FsNiceStreamTransmitter *self,
|
|
Packit |
133782 |
FsCandidate *candidate)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
NiceCandidate *nc = nice_candidate_new (
|
|
Packit |
133782 |
fs_candidate_type_to_nice_candidate_type (candidate->type));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
nc->transport =
|
|
Packit |
133782 |
fs_network_protocol_to_nice_candidate_protocol (candidate->proto);
|
|
Packit |
133782 |
nc->priority = candidate->priority;
|
|
Packit |
133782 |
nc->stream_id = self->priv->stream_id;
|
|
Packit |
133782 |
nc->component_id = candidate->component_id;
|
|
Packit |
133782 |
if (candidate->foundation != NULL)
|
|
Packit |
133782 |
strncpy (nc->foundation, candidate->foundation,
|
|
Packit |
133782 |
NICE_CANDIDATE_MAX_FOUNDATION - 1);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
nc->username = g_strdup(candidate->username);
|
|
Packit |
133782 |
nc->password = g_strdup(candidate->password);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (candidate->ip == NULL)
|
|
Packit |
133782 |
goto error;
|
|
Packit |
133782 |
if (!nice_address_set_from_string (&nc->addr, candidate->ip))
|
|
Packit |
133782 |
goto error;
|
|
Packit |
133782 |
nice_address_set_port (&nc->addr, candidate->port);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (candidate->base_ip && candidate->base_port)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
if (!nice_address_set_from_string (&nc->base_addr, candidate->base_ip))
|
|
Packit |
133782 |
goto error;
|
|
Packit |
133782 |
nice_address_set_port (&nc->base_addr, candidate->base_port);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return nc;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
error:
|
|
Packit |
133782 |
nice_candidate_free (nc);
|
|
Packit |
133782 |
return NULL;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
fs_nice_stream_transmitter_add_remote_candidates (
|
|
Packit |
133782 |
FsStreamTransmitter *streamtransmitter,
|
|
Packit |
133782 |
GList *candidates,
|
|
Packit |
133782 |
GError **error)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self =
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER (streamtransmitter);
|
|
Packit |
133782 |
GList *item;
|
|
Packit |
133782 |
GSList *nice_candidates = NULL;
|
|
Packit |
133782 |
gint c;
|
|
Packit |
133782 |
const gchar *username;
|
|
Packit |
133782 |
const gchar *password;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!candidates)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
GST_DEBUG ("NULL candidates passed, lets do an ICE restart");
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
if (self->priv->remote_candidates)
|
|
Packit |
133782 |
fs_candidate_list_destroy (self->priv->remote_candidates);
|
|
Packit |
133782 |
self->priv->remote_candidates = NULL;
|
|
Packit |
133782 |
self->priv->forced_candidates = FALSE;
|
|
Packit |
133782 |
g_free (self->priv->username);
|
|
Packit |
133782 |
g_free (self->priv->password);
|
|
Packit |
133782 |
self->priv->username = NULL;
|
|
Packit |
133782 |
self->priv->password = NULL;
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
nice_agent_restart (self->priv->agent->agent);
|
|
Packit |
133782 |
return TRUE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
username = self->priv->username;
|
|
Packit |
133782 |
password = self->priv->password;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* Validate candidates */
|
|
Packit |
133782 |
for (item = candidates;
|
|
Packit |
133782 |
item;
|
|
Packit |
133782 |
item = g_list_next (item))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsCandidate *candidate = item->data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!candidate->ip)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Candidate MUST have an IP address");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (candidate->component_id == 0 ||
|
|
Packit |
133782 |
candidate->component_id > self->priv->transmitter->components)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Candidate MUST have a component id between 1 and %d, %d is invalid",
|
|
Packit |
133782 |
self->priv->transmitter->components, candidate->component_id);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (candidate->type == FS_CANDIDATE_TYPE_MULTICAST)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"libnice transmitter does not accept multicast candidates");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!candidate->username)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Invalid remote candidates passed, does not have a username");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->compatibility_mode != NICE_COMPATIBILITY_GOOGLE &&
|
|
Packit |
133782 |
!candidate->password)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Invalid remote candidates passed, does not have a password");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->compatibility_mode != NICE_COMPATIBILITY_GOOGLE &&
|
|
Packit |
133782 |
self->priv->compatibility_mode != NICE_COMPATIBILITY_MSN &&
|
|
Packit |
133782 |
self->priv->compatibility_mode != NICE_COMPATIBILITY_OC2007)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
if (!username)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
username = candidate->username;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
else if (strcmp (username, candidate->username))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Invalid remote candidates passed, does not have the right"
|
|
Packit |
133782 |
" username");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!password)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
password = candidate->password;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
else if (strcmp (password, candidate->password))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Invalid remote candidates passed, does not have the right"
|
|
Packit |
133782 |
" password");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!self->priv->username)
|
|
Packit |
133782 |
self->priv->username = g_strdup (username);
|
|
Packit |
133782 |
if (!self->priv->password)
|
|
Packit |
133782 |
self->priv->password = g_strdup (password);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->forced_candidates)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Candidates have been forced, can't set remote candidates");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!self->priv->gathered)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
self->priv->remote_candidates = g_list_concat (
|
|
Packit |
133782 |
self->priv->remote_candidates,
|
|
Packit |
133782 |
fs_candidate_list_copy (candidates));
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
return TRUE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->compatibility_mode != NICE_COMPATIBILITY_GOOGLE &&
|
|
Packit |
133782 |
self->priv->compatibility_mode != NICE_COMPATIBILITY_MSN &&
|
|
Packit |
133782 |
self->priv->compatibility_mode != NICE_COMPATIBILITY_OC2007)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
username = g_strdup (username);
|
|
Packit |
133782 |
password = g_strdup (password);
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!nice_agent_set_remote_credentials (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->stream_id, username, password))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_free ((gchar*) username);
|
|
Packit |
133782 |
g_free ((gchar*) password);
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL,
|
|
Packit |
133782 |
"Could not set the security credentials");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
g_free ((gchar*) username);
|
|
Packit |
133782 |
g_free ((gchar*) password);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (c = 1; c <= self->priv->transmitter->components; c++)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
for (item = candidates;
|
|
Packit |
133782 |
item;
|
|
Packit |
133782 |
item = g_list_next (item))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsCandidate *candidate = item->data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (candidate->component_id == c)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
NiceCandidate *nc = fs_candidate_to_nice_candidate (self, candidate);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!nc)
|
|
Packit |
133782 |
goto error;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
nice_candidates = g_slist_append (nice_candidates, nc);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
nice_agent_set_remote_candidates (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->stream_id, c, nice_candidates);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_slist_foreach (nice_candidates, (GFunc)nice_candidate_free, NULL);
|
|
Packit |
133782 |
g_slist_free (nice_candidates);
|
|
Packit |
133782 |
nice_candidates = NULL;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return TRUE;
|
|
Packit |
133782 |
error:
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Invalid remote candidates passed");
|
|
Packit |
133782 |
g_slist_foreach (nice_candidates, (GFunc) nice_candidate_free, NULL);
|
|
Packit |
133782 |
g_slist_free (nice_candidates);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
fs_nice_stream_transmitter_force_remote_candidates_act (
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self,
|
|
Packit |
133782 |
GList *remote_candidates)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
gboolean res = TRUE;
|
|
Packit |
133782 |
GList *item = NULL;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (item = remote_candidates;
|
|
Packit |
133782 |
item && res;
|
|
Packit |
133782 |
item = g_list_next (item))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsCandidate *candidate = item->data;
|
|
Packit |
133782 |
NiceCandidate *nc = fs_candidate_to_nice_candidate (self, candidate);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
res &= nice_agent_set_selected_remote_candidate (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->stream_id, candidate->component_id, nc);
|
|
Packit |
133782 |
nice_candidate_free (nc);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return res;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
fs_nice_stream_transmitter_force_remote_candidates (
|
|
Packit |
133782 |
FsStreamTransmitter *streamtransmitter,
|
|
Packit |
133782 |
GList *remote_candidates,
|
|
Packit |
133782 |
GError **error)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self =
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER (streamtransmitter);
|
|
Packit |
133782 |
GList *item = NULL;
|
|
Packit |
133782 |
gboolean res = TRUE;
|
|
Packit |
133782 |
gboolean *done;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
done = g_new0(gboolean, self->priv->transmitter->components);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
memset (done, 0, self->priv->transmitter->components * sizeof (gboolean));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->stream_id == 0)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Can not call this function before gathering local candidates");
|
|
Packit |
133782 |
res = FALSE;
|
|
Packit |
133782 |
goto out;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* First lets check that we have valid candidates */
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (item = remote_candidates; item; item = g_list_next (item))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsCandidate *candidate = item->data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (candidate->component_id < 1 ||
|
|
Packit |
133782 |
candidate->component_id > self->priv->transmitter->components)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"The component on this candidate is wrong");
|
|
Packit |
133782 |
res = FALSE;
|
|
Packit |
133782 |
goto out;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (done[candidate->component_id-1])
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"You can set only one candidate per component");
|
|
Packit |
133782 |
res = FALSE;
|
|
Packit |
133782 |
goto out;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
done[candidate->component_id-1] = TRUE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
self->priv->forced_candidates = TRUE;
|
|
Packit |
133782 |
if (self->priv->gathered)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
res = fs_nice_stream_transmitter_force_remote_candidates_act (self,
|
|
Packit |
133782 |
remote_candidates);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
if (self->priv->remote_candidates)
|
|
Packit |
133782 |
fs_candidate_list_destroy (self->priv->remote_candidates);
|
|
Packit |
133782 |
self->priv->remote_candidates = fs_candidate_list_copy (remote_candidates);
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!res)
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL,
|
|
Packit |
133782 |
"Unknown error while selecting remote candidates");
|
|
Packit |
133782 |
|
|
Packit |
133782 |
out:
|
|
Packit |
133782 |
g_free(done);
|
|
Packit |
133782 |
return res;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static FsCandidateType
|
|
Packit |
133782 |
nice_candidate_type_to_fs_candidate_type (NiceCandidateType type)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
switch (type)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
case NICE_CANDIDATE_TYPE_HOST:
|
|
Packit |
133782 |
return FS_CANDIDATE_TYPE_HOST;
|
|
Packit |
133782 |
case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
|
|
Packit |
133782 |
return FS_CANDIDATE_TYPE_SRFLX;
|
|
Packit |
133782 |
case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
|
|
Packit |
133782 |
return FS_CANDIDATE_TYPE_PRFLX;
|
|
Packit |
133782 |
case NICE_CANDIDATE_TYPE_RELAYED:
|
|
Packit |
133782 |
return FS_CANDIDATE_TYPE_RELAY;
|
|
Packit |
133782 |
default:
|
|
Packit |
133782 |
GST_WARNING ("Invalid candidate type %d, defaulting to type host", type);
|
|
Packit |
133782 |
return FS_CANDIDATE_TYPE_HOST;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static FsNetworkProtocol
|
|
Packit |
133782 |
nice_candidate_transport_to_fs_network_protocol (NiceCandidateTransport trans)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
switch (trans)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
case NICE_CANDIDATE_TRANSPORT_UDP:
|
|
Packit |
133782 |
return FS_NETWORK_PROTOCOL_UDP;
|
|
Packit |
133782 |
case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
|
|
Packit |
133782 |
return FS_NETWORK_PROTOCOL_TCP_PASSIVE;
|
|
Packit |
133782 |
case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
|
|
Packit |
133782 |
return FS_NETWORK_PROTOCOL_TCP_ACTIVE;
|
|
Packit |
133782 |
case NICE_CANDIDATE_TRANSPORT_TCP_SO:
|
|
Packit |
133782 |
return FS_NETWORK_PROTOCOL_TCP_SO;
|
|
Packit |
133782 |
default:
|
|
Packit |
133782 |
GST_WARNING ("Invalid Nice network transport type %u", trans);
|
|
Packit |
133782 |
return FS_NETWORK_PROTOCOL_UDP;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static FsCandidate *
|
|
Packit |
133782 |
nice_candidate_to_fs_candidate (NiceAgent *agent, NiceCandidate *nicecandidate,
|
|
Packit |
133782 |
gboolean local)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsCandidate *fscandidate;
|
|
Packit |
133782 |
gchar *ipaddr = g_malloc (INET6_ADDRSTRLEN);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
nice_address_to_string (&nicecandidate->addr, ipaddr);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
fscandidate = fs_candidate_new (
|
|
Packit |
133782 |
nicecandidate->foundation,
|
|
Packit |
133782 |
nicecandidate->component_id,
|
|
Packit |
133782 |
nice_candidate_type_to_fs_candidate_type (nicecandidate->type),
|
|
Packit |
133782 |
nice_candidate_transport_to_fs_network_protocol (
|
|
Packit |
133782 |
nicecandidate->transport),
|
|
Packit |
133782 |
ipaddr,
|
|
Packit |
133782 |
nice_address_get_port (&nicecandidate->addr));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (nice_address_is_valid (&nicecandidate->base_addr) &&
|
|
Packit |
133782 |
nicecandidate->type != NICE_CANDIDATE_TYPE_HOST)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
nice_address_to_string (&nicecandidate->base_addr, ipaddr);
|
|
Packit |
133782 |
fscandidate->base_ip = ipaddr;
|
|
Packit |
133782 |
fscandidate->base_port = nice_address_get_port (&nicecandidate->base_addr);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_free (ipaddr);
|
|
Packit |
133782 |
ipaddr = NULL;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
fscandidate->username = g_strdup (nicecandidate->username);
|
|
Packit |
133782 |
fscandidate->password = g_strdup (nicecandidate->password);
|
|
Packit |
133782 |
fscandidate->priority = nicecandidate->priority;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (local && fscandidate->username == NULL && fscandidate->password == NULL)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
gchar *username = NULL, *password = NULL;
|
|
Packit |
133782 |
nice_agent_get_local_credentials (agent, nicecandidate->stream_id,
|
|
Packit |
133782 |
&username, &password);
|
|
Packit |
133782 |
fscandidate->username = username;
|
|
Packit |
133782 |
fscandidate->password = password;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (username == NULL || password == NULL)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
GST_WARNING ("The stream has no credentials??");
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return fscandidate;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
candidate_list_are_equal (GList *list1, GList *list2)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
for (;
|
|
Packit |
133782 |
list1 && list2;
|
|
Packit |
133782 |
list1 = list1->next, list2 = list2->next)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsCandidate *cand1 = list1->data;
|
|
Packit |
133782 |
FsCandidate *cand2 = list2->data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (strcmp (cand1->ip, cand2->ip))
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return TRUE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
weak_agent_removed (gpointer user_data, GObject *where_the_object_was)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
GList *agents = NULL;
|
|
Packit |
133782 |
FsParticipant *participant = user_data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_PARTICIPANT_DATA_LOCK (participant);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
agents = g_object_get_data (G_OBJECT (participant), "nice-agents");
|
|
Packit |
133782 |
agents = g_list_remove (agents, where_the_object_was);
|
|
Packit |
133782 |
g_object_set_data (G_OBJECT (participant), "nice-agents", agents);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_PARTICIPANT_DATA_UNLOCK (participant);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_unref (participant);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
fs_nice_stream_transmitter_set_relay_info (FsNiceStreamTransmitter *self,
|
|
Packit |
133782 |
const GstStructure *s, guint component_id, GError **error)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
const gchar *username, *password, *ip;
|
|
Packit |
133782 |
const gchar *relay_type_string;
|
|
Packit |
133782 |
NiceRelayType relay_type = NICE_RELAY_TYPE_TURN_UDP;
|
|
Packit |
133782 |
guint port;
|
|
Packit |
133782 |
gboolean has_port;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
ip = gst_structure_get_string (s, "ip");
|
|
Packit |
133782 |
has_port = gst_structure_get_uint (s, "port", &port);
|
|
Packit |
133782 |
username = gst_structure_get_string (s, "username");
|
|
Packit |
133782 |
password = gst_structure_get_string (s, "password");
|
|
Packit |
133782 |
relay_type_string = gst_structure_get_string (s, "relay-type");
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!ip || !has_port || !username || !password || port > 65535)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Need to pass an ip, port, username and password for a relay");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (relay_type_string)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
if (!g_ascii_strcasecmp(relay_type_string, "tcp"))
|
|
Packit |
133782 |
relay_type = NICE_RELAY_TYPE_TURN_TCP;
|
|
Packit |
133782 |
else if (!g_ascii_strcasecmp(relay_type_string, "tls"))
|
|
Packit |
133782 |
relay_type = NICE_RELAY_TYPE_TURN_TLS;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
nice_agent_set_relay_info(self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->stream_id, component_id, ip, port, username, password,
|
|
Packit |
133782 |
relay_type);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return TRUE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
tos_changed (GObject *transmitter, GParamSpec *param,
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
guint tos;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_get (transmitter, "tos", &tos, NULL);
|
|
Packit |
133782 |
nice_agent_set_stream_tos (self->priv->agent->agent, self->priv->stream_id,
|
|
Packit |
133782 |
tos);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
fs_nice_stream_transmitter_build (FsNiceStreamTransmitter *self,
|
|
Packit |
133782 |
FsParticipant *participant,
|
|
Packit |
133782 |
GError **error)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
GList *item;
|
|
Packit |
133782 |
GList *agents = NULL;
|
|
Packit |
133782 |
FsNiceAgent *agent = NULL;
|
|
Packit |
133782 |
gint i;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* Before going any further, check that the list of candidates are ok */
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (item = g_list_first (self->priv->preferred_local_candidates);
|
|
Packit |
133782 |
item;
|
|
Packit |
133782 |
item = g_list_next (item))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsCandidate *cand = item->data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (cand->ip == NULL)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"You have to set an ip on your preferred candidate");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (cand->port || cand->component_id)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"You can not set a port or component id"
|
|
Packit |
133782 |
" for the preferred nice candidate");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (cand->type != FS_CANDIDATE_TYPE_HOST)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"You can only set preferred candidates of type host");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* Now if we have a relayinfo, lets verify that its ok */
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->relay_info)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
for (i = 0; i < self->priv->relay_info->len; i++)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
const GstStructure *s = g_ptr_array_index (self->priv->relay_info, i);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!s)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Element %d of the relay-info GPtrArray is NULL",
|
|
Packit |
133782 |
i);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!gst_structure_has_field_typed (s, "ip", G_TYPE_STRING))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Element %d of the relay-info does not have an ip as a string", i);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!gst_structure_has_field_typed (s, "port", G_TYPE_UINT))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Element %d of the relay-info does not have a port as a guint", i);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (gst_structure_has_field (s, "username") &&
|
|
Packit |
133782 |
!gst_structure_has_field_typed (s, "username", G_TYPE_STRING))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Element %d of the relay-info has a username that is not a string",
|
|
Packit |
133782 |
i);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (gst_structure_has_field (s, "password") &&
|
|
Packit |
133782 |
!gst_structure_has_field_typed (s, "password", G_TYPE_STRING))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Element %d of the relay-info has a password that is not a string",
|
|
Packit |
133782 |
i);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (gst_structure_has_field (s, "relay-type") &&
|
|
Packit |
133782 |
!gst_structure_has_field_typed (s, "relay-type",
|
|
Packit |
133782 |
G_TYPE_STRING))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Element %d of the relay-info a relay-type"
|
|
Packit |
133782 |
" that is not a string", i);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (gst_structure_has_field (s, "component") &&
|
|
Packit |
133782 |
!gst_structure_has_field_typed (s, "component",
|
|
Packit |
133782 |
G_TYPE_UINT))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"Element %d of the relay-info has a component that is not a uint",
|
|
Packit |
133782 |
i);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* First find if there is already a matching agent */
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_PARTICIPANT_DATA_LOCK (participant);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
agents = g_object_get_data (G_OBJECT (participant), "nice-agents");
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (item = g_list_first (agents);
|
|
Packit |
133782 |
item;
|
|
Packit |
133782 |
item = g_list_next (item))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
guint stun_port;
|
|
Packit |
133782 |
gchar *stun_server;
|
|
Packit |
133782 |
guint compatibility;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
agent = item->data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_get (agent->agent,
|
|
Packit |
133782 |
"stun-server", &stun_server,
|
|
Packit |
133782 |
"stun-server-port", &stun_port,
|
|
Packit |
133782 |
"compatibility", &compatibility,
|
|
Packit |
133782 |
NULL);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/*
|
|
Packit |
133782 |
* Check if the agent matches our requested criteria
|
|
Packit |
133782 |
*/
|
|
Packit |
133782 |
if (compatibility == self->priv->compatibility_mode &&
|
|
Packit |
133782 |
stun_port == self->priv->stun_port &&
|
|
Packit |
133782 |
(stun_server == self->priv->stun_ip ||
|
|
Packit |
133782 |
(stun_server && self->priv->stun_ip &&
|
|
Packit |
133782 |
!strcmp (stun_server, self->priv->stun_ip))))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
GList *prefs = NULL;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_get (G_OBJECT (agent),
|
|
Packit |
133782 |
"preferred-local-candidates", &prefs,
|
|
Packit |
133782 |
NULL);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (candidate_list_are_equal (prefs,
|
|
Packit |
133782 |
self->priv->preferred_local_candidates))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
fs_candidate_list_destroy (prefs);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
fs_candidate_list_destroy (prefs);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* In this case we need to build a new agent */
|
|
Packit |
133782 |
if (item == NULL)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
agent = fs_nice_agent_new (self->priv->compatibility_mode,
|
|
Packit |
133782 |
self->priv->preferred_local_candidates, self->priv->reliable,
|
|
Packit |
133782 |
error);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!agent)
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->stun_ip && self->priv->stun_port)
|
|
Packit |
133782 |
g_object_set (agent->agent,
|
|
Packit |
133782 |
"stun-server", self->priv->stun_ip,
|
|
Packit |
133782 |
"stun-server-port", self->priv->stun_port,
|
|
Packit |
133782 |
NULL);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_object_set (agent->agent,
|
|
Packit |
133782 |
"controlling-mode", self->priv->controlling_mode,
|
|
Packit |
133782 |
"ice-udp", self->priv->ice_udp,
|
|
Packit |
133782 |
"ice-tcp", self->priv->ice_tcp,
|
|
Packit |
133782 |
NULL);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
agents = g_list_prepend (agents, agent);
|
|
Packit |
133782 |
g_object_set_data (G_OBJECT (participant), "nice-agents", agents);
|
|
Packit |
133782 |
g_object_weak_ref (G_OBJECT (agent), weak_agent_removed, participant);
|
|
Packit |
133782 |
g_object_ref (participant);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
self->priv->agent = agent;
|
|
Packit |
133782 |
} else {
|
|
Packit |
133782 |
self->priv->agent = g_object_ref (agent);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_PARTICIPANT_DATA_UNLOCK (participant);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
self->priv->component_has_been_ready = g_new0 (gboolean,
|
|
Packit |
133782 |
self->priv->transmitter->components);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
self->priv->stream_id = nice_agent_add_stream (
|
|
Packit |
133782 |
self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->transmitter->components);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->stream_id == 0)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
|
|
Packit |
133782 |
"Could not create libnice stream");
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* if we have a relay- info, lets set it */
|
|
Packit |
133782 |
if (self->priv->relay_info)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
gint c;
|
|
Packit |
133782 |
for (c = 1; c <= self->priv->transmitter->components; c++)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
gboolean relay_info_set = FALSE;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (i = 0; i < self->priv->relay_info->len; i++)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
const GstStructure *s = g_ptr_array_index (self->priv->relay_info, i);
|
|
Packit |
133782 |
guint component_id;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (gst_structure_get_uint (s, "component", &component_id) &&
|
|
Packit |
133782 |
component_id == c)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
if (!fs_nice_stream_transmitter_set_relay_info (self, s, c, error))
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
relay_info_set = TRUE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!relay_info_set)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
for (i = 0; i < self->priv->relay_info->len; i++)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
const GstStructure *s = g_ptr_array_index (self->priv->relay_info, i);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!gst_structure_has_field (s, "component"))
|
|
Packit |
133782 |
if (!fs_nice_stream_transmitter_set_relay_info (self, s, c, error))
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* Set a port range if it has been specified. */
|
|
Packit |
133782 |
if (self->priv->min_port && (self->priv->min_port < self->priv->max_port))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
gint c;
|
|
Packit |
133782 |
for (c = 1; c <= self->priv->transmitter->components; c++)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
nice_agent_set_port_range (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->stream_id, c, self->priv->min_port, self->priv->max_port);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
self->priv->state_changed_handler_id = g_signal_connect_object (agent->agent,
|
|
Packit |
133782 |
"component-state-changed", G_CALLBACK (agent_state_changed), self, 0);
|
|
Packit |
133782 |
self->priv->gathering_done_handler_id = g_signal_connect_object (agent->agent,
|
|
Packit |
133782 |
"candidate-gathering-done", G_CALLBACK (agent_gathering_done), self, 0);
|
|
Packit |
133782 |
self->priv->new_selected_pair_handler_id = g_signal_connect_object (
|
|
Packit |
133782 |
agent->agent, "new-selected-pair", G_CALLBACK (agent_new_selected_pair),
|
|
Packit |
133782 |
self, 0);
|
|
Packit |
133782 |
self->priv->new_candidate_handler_id = g_signal_connect_object (agent->agent,
|
|
Packit |
133782 |
"new-candidate", G_CALLBACK (agent_new_candidate), self, 0);
|
|
Packit |
133782 |
self->priv->tos_changed_handler_id = g_signal_connect_object (
|
|
Packit |
133782 |
self->priv->transmitter, "notify::tos", G_CALLBACK (tos_changed), self,
|
|
Packit |
133782 |
0);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
tos_changed (G_OBJECT (self->priv->transmitter), NULL, self);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
self->priv->gststream = fs_nice_transmitter_add_gst_stream (
|
|
Packit |
133782 |
self->priv->transmitter,
|
|
Packit |
133782 |
self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->stream_id,
|
|
Packit |
133782 |
known_buffer_have_buffer_handler, self,
|
|
Packit |
133782 |
error);
|
|
Packit |
133782 |
if (self->priv->gststream == NULL)
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
fs_nice_transmitter_set_send_component_mux (self->priv->transmitter,
|
|
Packit |
133782 |
self->priv->gststream, self->priv->send_component_mux);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GST_DEBUG ("Created a stream with %u components",
|
|
Packit |
133782 |
self->priv->transmitter->components);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return TRUE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
fs_nice_stream_transmitter_gather_local_candidates (
|
|
Packit |
133782 |
FsStreamTransmitter *streamtransmitter,
|
|
Packit |
133782 |
GError **error)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self =
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER (streamtransmitter);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GST_DEBUG ("Stream %u started", self->priv->stream_id);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
nice_agent_gather_candidates (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->stream_id);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return TRUE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static FsStreamState
|
|
Packit |
133782 |
nice_component_state_to_fs_stream_state (NiceComponentState state)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
switch (state)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
case NICE_COMPONENT_STATE_DISCONNECTED:
|
|
Packit |
133782 |
return FS_STREAM_STATE_DISCONNECTED;
|
|
Packit |
133782 |
case NICE_COMPONENT_STATE_GATHERING:
|
|
Packit |
133782 |
return FS_STREAM_STATE_GATHERING;
|
|
Packit |
133782 |
case NICE_COMPONENT_STATE_CONNECTING:
|
|
Packit |
133782 |
return FS_STREAM_STATE_CONNECTING;
|
|
Packit |
133782 |
case NICE_COMPONENT_STATE_CONNECTED:
|
|
Packit |
133782 |
return FS_STREAM_STATE_CONNECTED;
|
|
Packit |
133782 |
case NICE_COMPONENT_STATE_READY:
|
|
Packit |
133782 |
return FS_STREAM_STATE_READY;
|
|
Packit |
133782 |
case NICE_COMPONENT_STATE_FAILED:
|
|
Packit |
133782 |
return FS_STREAM_STATE_FAILED;
|
|
Packit |
133782 |
default:
|
|
Packit |
133782 |
GST_ERROR ("Invalid state %u", state);
|
|
Packit |
133782 |
return FS_STREAM_STATE_FAILED;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
struct state_changed_signal_data
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self;
|
|
Packit |
133782 |
guint component_id;
|
|
Packit |
133782 |
FsStreamState fs_state;
|
|
Packit |
133782 |
};
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
free_state_changed_signal_data (gpointer user_data)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
struct state_changed_signal_data *data = user_data;
|
|
Packit |
133782 |
g_object_unref (data->self);
|
|
Packit |
133782 |
g_slice_free (struct state_changed_signal_data, data);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
state_changed_signal_idle (gpointer userdata)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
struct state_changed_signal_data *data = userdata;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_signal_emit_by_name (data->self, "state-changed", data->component_id,
|
|
Packit |
133782 |
data->fs_state);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
agent_state_changed (NiceAgent *agent,
|
|
Packit |
133782 |
guint stream_id,
|
|
Packit |
133782 |
guint component_id,
|
|
Packit |
133782 |
guint state,
|
|
Packit |
133782 |
gpointer user_data)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = FS_NICE_STREAM_TRANSMITTER (user_data);
|
|
Packit |
133782 |
FsStreamState fs_state;
|
|
Packit |
133782 |
struct state_changed_signal_data *data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (stream_id != self->priv->stream_id)
|
|
Packit |
133782 |
return;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_return_if_fail (component_id > 0 &&
|
|
Packit |
133782 |
component_id <= self->priv->transmitter->components);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
/* Ignore failed until we've connected, never time out because
|
|
Packit |
133782 |
* of the dribbling case, more candidates could come later
|
|
Packit |
133782 |
*/
|
|
Packit |
133782 |
if (state == NICE_COMPONENT_STATE_FAILED &&
|
|
Packit |
133782 |
!self->priv->component_has_been_ready[component_id - 1])
|
|
Packit |
133782 |
return;
|
|
Packit |
133782 |
else if (state == NICE_COMPONENT_STATE_READY)
|
|
Packit |
133782 |
self->priv->component_has_been_ready[component_id - 1] = TRUE;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
fs_state = nice_component_state_to_fs_stream_state (state);
|
|
Packit |
133782 |
data = g_slice_new (struct state_changed_signal_data);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GST_DEBUG ("Stream: %u Component %u has state %u",
|
|
Packit |
133782 |
self->priv->stream_id, component_id, state);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
data->self = g_object_ref (self);
|
|
Packit |
133782 |
data->component_id = component_id;
|
|
Packit |
133782 |
data->fs_state = fs_state;
|
|
Packit |
133782 |
fs_nice_agent_add_idle (self->priv->agent, state_changed_signal_idle,
|
|
Packit |
133782 |
data, free_state_changed_signal_data);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (fs_state >= FS_STREAM_STATE_CONNECTED)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
if (self->priv->gststream)
|
|
Packit |
133782 |
fs_nice_transmitter_request_keyunit (self->priv->transmitter,
|
|
Packit |
133782 |
self->priv->gststream, component_id);
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
struct candidate_signal_data
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self;
|
|
Packit |
133782 |
const gchar *signal_name;
|
|
Packit |
133782 |
FsCandidate *candidate1;
|
|
Packit |
133782 |
FsCandidate *candidate2;
|
|
Packit |
133782 |
};
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
free_candidate_signal_data (gpointer user_data)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
struct candidate_signal_data *data = user_data;
|
|
Packit |
133782 |
fs_candidate_destroy (data->candidate1);
|
|
Packit |
133782 |
if (data->candidate2)
|
|
Packit |
133782 |
fs_candidate_destroy (data->candidate2);
|
|
Packit |
133782 |
g_object_unref (data->self);
|
|
Packit |
133782 |
g_slice_free (struct candidate_signal_data, data);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
agent_candidate_signal_idle (gpointer userdata)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
struct candidate_signal_data *data = userdata;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_signal_emit_by_name (data->self, data->signal_name, data->candidate1,
|
|
Packit |
133782 |
data->candidate2);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
agent_new_selected_pair (NiceAgent *agent,
|
|
Packit |
133782 |
guint stream_id,
|
|
Packit |
133782 |
guint component_id,
|
|
Packit |
133782 |
const gchar *lfoundation,
|
|
Packit |
133782 |
const gchar *rfoundation,
|
|
Packit |
133782 |
gpointer user_data)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = FS_NICE_STREAM_TRANSMITTER (user_data);
|
|
Packit |
133782 |
GSList *candidates, *item;
|
|
Packit |
133782 |
FsCandidate *local = NULL;
|
|
Packit |
133782 |
FsCandidate *remote = NULL;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (stream_id != self->priv->stream_id)
|
|
Packit |
133782 |
return;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
candidates = nice_agent_get_local_candidates (agent,
|
|
Packit |
133782 |
self->priv->stream_id, component_id);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (item = candidates; item; item = g_slist_next (item))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
NiceCandidate *candidate = item->data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!strcmp (candidate->foundation, lfoundation))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
local = nice_candidate_to_fs_candidate (agent, candidate, TRUE);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
g_slist_foreach (candidates, (GFunc)nice_candidate_free, NULL);
|
|
Packit |
133782 |
g_slist_free (candidates);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
candidates = nice_agent_get_remote_candidates (agent,
|
|
Packit |
133782 |
self->priv->stream_id, component_id);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (item = candidates; item; item = g_slist_next (item))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
NiceCandidate *candidate = item->data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!strcmp (candidate->foundation, rfoundation))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
remote = nice_candidate_to_fs_candidate (agent, candidate, FALSE);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
g_slist_foreach (candidates, (GFunc)nice_candidate_free, NULL);
|
|
Packit |
133782 |
g_slist_free (candidates);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (local && remote)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
struct candidate_signal_data *data =
|
|
Packit |
133782 |
g_slice_new (struct candidate_signal_data);
|
|
Packit |
133782 |
data->self = g_object_ref (self);
|
|
Packit |
133782 |
data->signal_name = "new-active-candidate-pair";
|
|
Packit |
133782 |
data->candidate1 = local;
|
|
Packit |
133782 |
data->candidate2 = remote;
|
|
Packit |
133782 |
fs_nice_agent_add_idle (self->priv->agent, agent_candidate_signal_idle,
|
|
Packit |
133782 |
data, free_candidate_signal_data);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
if (local)
|
|
Packit |
133782 |
fs_candidate_destroy (local);
|
|
Packit |
133782 |
if (remote)
|
|
Packit |
133782 |
fs_candidate_destroy (remote);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
agent_new_candidate (NiceAgent *agent,
|
|
Packit |
133782 |
guint stream_id,
|
|
Packit |
133782 |
guint component_id,
|
|
Packit |
133782 |
const gchar *foundation,
|
|
Packit |
133782 |
gpointer user_data)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = FS_NICE_STREAM_TRANSMITTER (user_data);
|
|
Packit |
133782 |
FsCandidate *fscandidate = NULL;
|
|
Packit |
133782 |
GSList *candidates, *item;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (stream_id != self->priv->stream_id)
|
|
Packit |
133782 |
return;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GST_DEBUG ("New candidate found for stream %u component %u",
|
|
Packit |
133782 |
stream_id, component_id);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
candidates = nice_agent_get_local_candidates (agent, stream_id, component_id);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (item = candidates; item; item = g_slist_next (item))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
NiceCandidate *candidate = item->data;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!strcmp (candidate->foundation, foundation))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
fscandidate = nice_candidate_to_fs_candidate (agent, candidate, TRUE);
|
|
Packit |
133782 |
break;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
g_slist_foreach (candidates, (GFunc) nice_candidate_free, NULL);
|
|
Packit |
133782 |
g_slist_free (candidates);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (fscandidate)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
if (!self->priv->gathered)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
/* Nice doesn't do connchecks while gathering, so don't tell the upper
|
|
Packit |
133782 |
* layers about the candidates untill gathering is finished.
|
|
Packit |
133782 |
* Also older versions of farstream would fail the connection right away
|
|
Packit |
133782 |
* when the first candidate given failed immediately (e.g. ipv6 on a
|
|
Packit |
133782 |
* non-ipv6 capable host, so we order ipv6 candidates after ipv4 ones */
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (strchr (fscandidate->ip, ':'))
|
|
Packit |
133782 |
self->priv->local_candidates = g_list_append
|
|
Packit |
133782 |
(self->priv->local_candidates, fscandidate);
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
self->priv->local_candidates = g_list_prepend
|
|
Packit |
133782 |
(self->priv->local_candidates, fscandidate);
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
struct candidate_signal_data *data =
|
|
Packit |
133782 |
g_slice_new (struct candidate_signal_data);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
data->self = g_object_ref (self);
|
|
Packit |
133782 |
data->signal_name = "new-local-candidate";
|
|
Packit |
133782 |
data->candidate1 = fscandidate;
|
|
Packit |
133782 |
data->candidate2 = NULL;
|
|
Packit |
133782 |
fs_nice_agent_add_idle (self->priv->agent, agent_candidate_signal_idle,
|
|
Packit |
133782 |
data, free_candidate_signal_data);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
GST_WARNING ("Could not find local candidate with foundation %s"
|
|
Packit |
133782 |
" for component %d in stream %d", foundation, component_id,
|
|
Packit |
133782 |
stream_id);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static gboolean
|
|
Packit |
133782 |
agent_gathering_done_idle (gpointer data)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = data;
|
|
Packit |
133782 |
GList *remote_candidates = NULL;
|
|
Packit |
133782 |
GList *local_candidates = NULL;
|
|
Packit |
133782 |
gboolean forced_candidates;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_LOCK (self);
|
|
Packit |
133782 |
if (self->priv->gathered)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
self->priv->gathered = TRUE;
|
|
Packit |
133782 |
remote_candidates = self->priv->remote_candidates;
|
|
Packit |
133782 |
self->priv->remote_candidates = NULL;
|
|
Packit |
133782 |
local_candidates = self->priv->local_candidates;
|
|
Packit |
133782 |
self->priv->local_candidates = NULL;
|
|
Packit |
133782 |
forced_candidates = self->priv->forced_candidates;
|
|
Packit |
133782 |
FS_NICE_STREAM_TRANSMITTER_UNLOCK (self);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
GST_DEBUG ("Candidates gathered for stream %u", self->priv->stream_id);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (local_candidates)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
GList *l;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
for (l = local_candidates ; l != NULL; l = g_list_next (l))
|
|
Packit |
133782 |
g_signal_emit_by_name (self, "new-local-candidate", l->data);
|
|
Packit |
133782 |
fs_candidate_list_destroy (local_candidates);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_signal_emit_by_name (self, "local-candidates-prepared");
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (remote_candidates)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
if (forced_candidates)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
if (!fs_nice_stream_transmitter_force_remote_candidates_act (self,
|
|
Packit |
133782 |
remote_candidates))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
fs_stream_transmitter_emit_error (FS_STREAM_TRANSMITTER (self),
|
|
Packit |
133782 |
FS_ERROR_INTERNAL,
|
|
Packit |
133782 |
"Error setting delayed forced remote candidates");
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
else
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
GError *error = NULL;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (self->priv->compatibility_mode != NICE_COMPATIBILITY_GOOGLE &&
|
|
Packit |
133782 |
self->priv->compatibility_mode != NICE_COMPATIBILITY_MSN &&
|
|
Packit |
133782 |
self->priv->compatibility_mode != NICE_COMPATIBILITY_OC2007)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
if (!nice_agent_set_remote_credentials (self->priv->agent->agent,
|
|
Packit |
133782 |
self->priv->stream_id, self->priv->username,
|
|
Packit |
133782 |
self->priv->password))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
fs_stream_transmitter_emit_error (FS_STREAM_TRANSMITTER (self),
|
|
Packit |
133782 |
FS_ERROR_INTERNAL,
|
|
Packit |
133782 |
"Could not set the security credentials");
|
|
Packit |
133782 |
fs_candidate_list_destroy (remote_candidates);
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!fs_nice_stream_transmitter_add_remote_candidates (
|
|
Packit |
133782 |
FS_STREAM_TRANSMITTER_CAST (self),
|
|
Packit |
133782 |
remote_candidates, &error))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
fs_stream_transmitter_emit_error (FS_STREAM_TRANSMITTER (self),
|
|
Packit |
133782 |
error->code, error->message);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
g_clear_error (&error);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
fs_candidate_list_destroy (remote_candidates);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return FALSE;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static void
|
|
Packit |
133782 |
agent_gathering_done (NiceAgent *agent, guint stream_id, gpointer user_data)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = FS_NICE_STREAM_TRANSMITTER (user_data);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (stream_id != self->priv->stream_id)
|
|
Packit |
133782 |
return;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
fs_nice_agent_add_idle (self->priv->agent, agent_gathering_done_idle,
|
|
Packit |
133782 |
g_object_ref (self), g_object_unref);
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
FsNiceStreamTransmitter *
|
|
Packit |
133782 |
fs_nice_stream_transmitter_newv (FsNiceTransmitter *transmitter,
|
|
Packit |
133782 |
FsParticipant *participant,
|
|
Packit |
133782 |
guint n_parameters,
|
|
Packit |
133782 |
GParameter *parameters,
|
|
Packit |
133782 |
GError **error)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *streamtransmitter = NULL;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!participant || !FS_IS_PARTICIPANT (participant))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
|
|
Packit |
133782 |
"You need a valid participant");
|
|
Packit |
133782 |
return NULL;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
streamtransmitter = g_object_newv (FS_TYPE_NICE_STREAM_TRANSMITTER,
|
|
Packit |
133782 |
n_parameters, parameters);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!streamtransmitter)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
|
|
Packit |
133782 |
"Could not build the stream transmitter");
|
|
Packit |
133782 |
return NULL;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
streamtransmitter->priv->transmitter = g_object_ref (transmitter);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!fs_nice_stream_transmitter_build (streamtransmitter, participant, error))
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
g_object_unref (streamtransmitter);
|
|
Packit |
133782 |
return NULL;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return streamtransmitter;
|
|
Packit |
133782 |
}
|
|
Packit |
133782 |
|
|
Packit |
133782 |
|
|
Packit |
133782 |
static GstPadProbeReturn
|
|
Packit |
133782 |
known_buffer_have_buffer_handler (GstPad *pad, GstPadProbeInfo *info,
|
|
Packit |
133782 |
gpointer user_data)
|
|
Packit |
133782 |
{
|
|
Packit |
133782 |
FsNiceStreamTransmitter *self = FS_NICE_STREAM_TRANSMITTER (user_data);
|
|
Packit |
133782 |
guint component_id;
|
|
Packit |
133782 |
GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
if (!g_atomic_int_get (&self->priv->associate_on_source))
|
|
Packit |
133782 |
return GST_PAD_PROBE_OK;
|
|
Packit |
133782 |
|
|
Packit |
133782 |
component_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (pad),
|
|
Packit |
133782 |
"component-id"));
|
|
Packit |
133782 |
|
|
Packit |
133782 |
g_signal_emit_by_name (self, "known-source-packet-received", component_id,
|
|
Packit |
133782 |
buffer);
|
|
Packit |
133782 |
|
|
Packit |
133782 |
return GST_PAD_PROBE_OK;
|
|
Packit |
133782 |
}
|