/*
* Farstream - Farstream Candidate
*
* Copyright 2007 Collabora Ltd.
* @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk>
* Copyright 2007 Nokia Corp.
*
* fs-candidate.c - A Farstream candidate
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "fs-candidate.h"
/**
* SECTION:fs-candidate
* @short_description: Structure describing a transport candidate.
*
* An FsCandidate is a way to exchange candidate information between the client
* and Farstream. This description is compatible with ICE-13. It can also be a
* multicast address. Candidates are linked to streams. The information
* specified in this structure is usually representative of the codec
* information exchanged in the signaling.
*/
GType
fs_candidate_get_type (void)
{
static GType candidate_type = 0;
if (candidate_type == 0)
{
candidate_type = g_boxed_type_register_static (
"FsCandidate",
(GBoxedCopyFunc)fs_candidate_copy,
(GBoxedFreeFunc)fs_candidate_destroy);
}
return candidate_type;
}
GType
fs_candidate_list_get_type (void)
{
static GType candidate_list_type = 0;
if (candidate_list_type == 0)
{
candidate_list_type = g_boxed_type_register_static (
"FsCandidateList",
(GBoxedCopyFunc)fs_candidate_list_copy,
(GBoxedFreeFunc)fs_candidate_list_destroy);
}
return candidate_list_type;
}
/**
* fs_candidate_destroy: (skip)
* @cand: a #FsCandidate to delete
*
* Frees a #FsCandidate and all its contents
*/
void
fs_candidate_destroy (FsCandidate * cand)
{
if (cand == NULL)
return;
g_free ((gchar *) cand->foundation);
g_free ((gchar *) cand->ip);
g_free ((gchar *) cand->base_ip);
g_free ((gchar *) cand->username);
g_free ((gchar *) cand->password);
g_slice_free (FsCandidate, cand);
}
/**
* fs_candidate_copy:
* @cand: a #FsCandidate to copy
*
* Copies a #FsCandidate and its contents.
*
* Returns: a new #FsCandidate
*/
FsCandidate *
fs_candidate_copy (const FsCandidate * cand)
{
FsCandidate *copy = g_slice_new0 (FsCandidate);
if (cand == NULL)
return NULL;
copy->component_id = cand->component_id;
copy->port = cand->port;
copy->base_port = cand->base_port;
copy->proto = cand->proto;
copy->priority = cand->priority;
copy->type = cand->type;
copy->ttl = cand->ttl;
copy->foundation = g_strdup (cand->foundation);
copy->ip = g_strdup (cand->ip);
copy->base_ip = g_strdup (cand->base_ip);
copy->username = g_strdup (cand->username);
copy->password = g_strdup (cand->password);
return copy;
}
/**
* fs_candidate_list_destroy: (skip)
* @candidate_list: A GList of #FsCandidate
*
* Deletes a GList of #FsCandidate and its contents
*/
void
fs_candidate_list_destroy (GList *candidate_list)
{
GList *lp;
FsCandidate *cand;
for (lp = candidate_list; lp; lp = g_list_next (lp)) {
cand = (FsCandidate *) lp->data;
fs_candidate_destroy (cand);
lp->data = NULL;
}
g_list_free (candidate_list);
}
/**
* fs_candidate_list_copy:
* @candidate_list: (element-type FsCodec): A GList of #FsCandidate
*
* Copies a GList of #FsCandidate and its contents
*
* Returns: (element-type FsCodec) (transfer full): a new GList of #FsCandidate
*/
GList *
fs_candidate_list_copy (const GList *candidate_list)
{
GQueue copy = G_QUEUE_INIT;
const GList *lp;
for (lp = candidate_list; lp; lp = g_list_next (lp)) {
FsCandidate *cand = lp->data;
g_queue_push_tail (©, fs_candidate_copy (cand));
}
return copy.head;
}
/**
* fs_candidate_new:
* @foundation: The foundation of the candidate
* @component_id: The component this candidate is for
* @type: The type of candidate
* @proto: The protocol this component is for
* @ip: (allow-none): The IP address of this component (can be NULL for local candidate to
* mean any address)
* @port: the UDP/TCP port
*
* Allocates a new #FsCandidate, the rest of the fields can be optionally
* filled manually. See also fs_candidate_new_full()
*
* Returns: a newly-allocated #FsCandidate
*/
FsCandidate *
fs_candidate_new (
const gchar *foundation,
guint component_id,
FsCandidateType type,
FsNetworkProtocol proto,
const gchar *ip,
guint port)
{
FsCandidate *candidate = g_slice_new0 (FsCandidate);
candidate->foundation = g_strdup (foundation);
candidate->component_id = component_id;
candidate->type = type;
candidate->proto = proto;
candidate->ip = g_strdup (ip);
candidate->port = port;
return candidate;
}
/**
* fs_candidate_new_full:
* @foundation: The foundation of the candidate
* @component_id: The component this candidate is for
* @ip: (allow-none): The IP address of this component (can be NULL for local candidate to
* mean any address)
* @port: the UDP/TCP port
* @base_ip: (allow-none): IP of base in dotted format as defined in ICE-19.
* @base_port: Port of base as defined in ICE-19.
* @proto: The protocol this component is for
* @priority: Value between 0 and (2^31 - 1) representing the priority
* @type: The type of candidate
* @username: (allow-none): Username to use to connect to client if necessary,
* NULL otherwise
* @password: (allow-none): Username to use to connect to client if necessary,
* NULL otherwise
* @ttl: The TTL used when sending Multicast packet (0 = auto)
*
* Allocates a new #FsCandidate, filling all the fields. See also
* fs_candidate_new()
*
* Returns: a newly-allocated #FsCandidate
*/
FsCandidate *
fs_candidate_new_full (
const gchar *foundation,
guint component_id,
const gchar *ip,
guint16 port,
const gchar *base_ip,
guint16 base_port,
FsNetworkProtocol proto,
guint32 priority,
FsCandidateType type,
const gchar *username,
const gchar *password,
guint ttl)
{
FsCandidate *candidate = g_slice_new (FsCandidate);
candidate->foundation = g_strdup (foundation);
candidate->component_id = component_id;
candidate->ip = g_strdup (ip);
candidate->port = port;
candidate->base_ip = g_strdup (base_ip);
candidate->base_port = base_port;
candidate->proto = proto;
candidate->priority = priority;
candidate->type = type;
candidate->username = g_strdup (username);
candidate->password = g_strdup (password);
candidate->ttl = ttl;
return candidate;
}
/**
* fs_value_set_candidate_list:
* @value: a #GValue of type #FS_TYPE_CANDIDATE_LIST
* @candidates: (element-type FsCandidate) (allow-none): A #GList of #FsCandidate
*
* This is for the bindings benefit. Works around the limitations of GObject
* introspection.
*
*/
void
fs_value_set_candidate_list (GValue *value, GList *candidates)
{
g_value_init (value, FS_TYPE_CANDIDATE_LIST);
g_value_set_boxed (value, candidates);
}