libnice/agent/component.h
Olivier Crête b9da818037 agent: Resolve TURN server IP addresses
This should enable having servers that do both IPv4 and IPv6. And
ideally should make life easier for app developers.
2023-01-04 14:40:31 -05:00

364 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* This file is part of the Nice GLib ICE library.
*
* (C) 2006-2010 Collabora Ltd.
* Contact: Youness Alaoui
* (C) 2006-2010 Nokia Corporation. All rights reserved.
* Contact: Kai Vehmanen
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Nice GLib ICE library.
*
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
* Corporation. All Rights Reserved.
*
* Contributors:
* Dafydd Harries, Collabora Ltd.
* Youness Alaoui, Collabora Ltd.
* Kai Vehmanen, Nokia
*
* Alternatively, the contents of this file may be used under the terms of the
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
* case the provisions of LGPL are applicable instead of those above. If you
* wish to allow use of your version of this file only under the terms of the
* LGPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replace
* them with the notice and other provisions required by the LGPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the LGPL.
*/
#ifndef _NICE_COMPONENT_H
#define _NICE_COMPONENT_H
#include <glib.h>
typedef struct _NiceComponent NiceComponent;
#include "agent.h"
#include "agent-priv.h"
#include "candidate-priv.h"
#include "stun/stunagent.h"
#include "stun/usages/timer.h"
#include "pseudotcp.h"
#include "stream.h"
#include "socket.h"
G_BEGIN_DECLS
/* (ICE §4.1.1.1, ID-19)
* ""For RTP-based media streams, the RTP itself has a component
* ID of 1, and RTCP a component ID of 2. If an agent is using RTCP it MUST
* obtain a candidate for it. If an agent is using both RTP and RTCP, it
* would end up with 2*K host candidates if an agent has K interfaces.""
*/
typedef struct _CandidatePair CandidatePair;
typedef struct _CandidatePairKeepalive CandidatePairKeepalive;
typedef struct _CandidatePairConsentCheck CandidatePairConsentCheck;
typedef struct _IncomingCheck IncomingCheck;
struct _CandidatePairKeepalive
{
guint64 next_tick; /* next tick timestamp */
guint stream_id;
guint component_id;
StunTimer timer;
};
struct _CandidatePairConsentCheck
{
GSource *tick_source;
gboolean have;
guint64 last_received; /* g_get_monotonic_time() of last remote
consent received */
};
struct _CandidatePair
{
NiceCandidateImpl *local;
NiceCandidateImpl *remote;
guint64 priority; /* candidate pair priority */
guint32 stun_priority;
CandidatePairKeepalive keepalive;
CandidatePairConsentCheck remote_consent;
};
struct _IncomingCheck
{
NiceAddress from;
NiceSocket *local_socket;
guint32 priority;
gboolean use_candidate;
uint8_t *username;
uint16_t username_len;
};
void
incoming_check_free (IncomingCheck *icheck);
/* A pair of a socket and the GSource which polls it from the main loop. All
* GSources in a Component must be attached to the same main context:
* component->ctx.
*
* Socket must be non-NULL, but source may be NULL if it has been detached.
*
* The Component is stored so this may be used as the user data for a GSource
* callback. */
typedef struct {
NiceSocket *socket;
GSource *source;
NiceComponent *component;
} SocketSource;
/* A message which has been received and processed (so is guaranteed not
* to be a STUN packet, or to contain pseudo-TCP header bytes, for example), but
* which hasnt yet been sent to the client in an I/O callback. This could be
* due to the main context not being run, or due to the I/O callback being
* detached.
*
* The @offset member gives the byte offset into @buf which has already been
* sent to the client. #IOCallbackData buffers remain in the
* #Component::pending_io_messages queue until all of their bytes have been sent
* to the client.
*
* @offset is guaranteed to be smaller than @buf_len. */
typedef struct {
guint8 *buf; /* owned */
gsize buf_len;
gsize offset;
} IOCallbackData;
IOCallbackData *
io_callback_data_new (const guint8 *buf, gsize buf_len);
void
io_callback_data_free (IOCallbackData *data);
#define NICE_TYPE_COMPONENT nice_component_get_type()
#define NICE_COMPONENT(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), NICE_TYPE_COMPONENT, NiceComponent))
#define NICE_COMPONENT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), NICE_TYPE_COMPONENT, NiceComponentClass))
#define NICE_IS_COMPONENT(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NICE_TYPE_COMPONENT))
#define NICE_IS_COMPONENT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), NICE_TYPE_COMPONENT))
#define NICE_COMPONENT_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), NICE_TYPE_COMPONENT, NiceComponentClass))
struct _NiceComponent {
/*< private >*/
GObject parent;
NiceComponentType type;
guint id; /* component id */
NiceComponentState state;
GSList *local_candidates; /* list of NiceCandidate objs */
GSList *remote_candidates; /* list of NiceCandidate objs */
GList *valid_candidates; /* list of owned remote NiceCandidates that are part of valid pairs */
GSList *socket_sources; /* list of SocketSource objs; must only grow monotonically */
guint socket_sources_age; /* incremented when socket_sources changes */
GQueue incoming_checks; /* list of IncomingCheck objs */
GList *turn_servers; /* List of TurnServer objs */
CandidatePair selected_pair; /* independent from checklists,
see ICE 11.1. "Sending Media" (ID-19) */
gboolean fallback_mode; /* in this case, accepts packets from all, ignore candidate validation */
NiceCandidate *restart_candidate; /* for storing active remote candidate during a restart */
NiceCandidateImpl *turn_candidate; /* for storing active turn candidate if turn servers have been cleared */
/* I/O handling. The main context must always be non-NULL, and is used for all
* socket recv() operations. All io_callback emissions are invoked in this
* context too.
*
* recv_messages and io_callback are mutually exclusive, but it is allowed for
* both to be NULL if the Component is not currently ready to receive data. */
GMutex io_mutex; /* protects io_callback, io_user_data,
pending_io_messages and io_callback_id.
immutable: can be accessed without
holding the agent lock; if the agent
lock is to be taken, it must always be
taken before this one */
NiceAgentRecvFunc io_callback; /* function called on io cb */
gpointer io_user_data; /* data passed to the io function */
GQueue pending_io_messages; /* queue of messages which have been
received but not passed to the client
in an I/O callback or recv() call yet.
each element is an owned
IOCallbackData */
guint io_callback_id; /* GSource ID of the I/O callback */
GMainContext *own_ctx; /* own context for GSources for this
component */
GMainContext *ctx; /* context for GSources for this
component (possibly set from the app) */
NiceInputMessage *recv_messages; /* unowned messages for receiving into */
guint n_recv_messages; /* length of recv_messages */
NiceInputMessageIter recv_messages_iter; /* current write position in
recv_messages */
GError **recv_buf_error; /* error information about failed reads */
GWeakRef agent_ref;
guint stream_id;
StunAgent stun_agent; /* This stun agent is used to validate all stun requests */
GCancellable *stop_cancellable;
GSource *stop_cancellable_source; /* owned */
PseudoTcpSocket *tcp;
GSource* tcp_clock;
guint64 last_clock_timeout;
gboolean tcp_readable;
GCancellable *tcp_writable_cancellable;
GIOStream *iostream;
guint min_port;
guint max_port;
/* Queue of messages received before a selected socket was available to send
* ACKs on. The messages are dequeued to the pseudo-TCP socket once a selected
* UDP socket is available. This is only used for reliable Components. */
GQueue queued_tcp_packets;
gboolean have_local_consent;
/* scratch buffer for use in the component_io_cb() function to
* hold the incoming packet, allocated at component creation, since
* the callback is a critical path, where memory allocation should
* be avoided.
*/
guint8 *recv_buffer;
guint recv_buffer_size;
/* ICE-TCP frame state */
guint8 *rfc4571_buffer;
guint rfc4571_buffer_offset;
guint rfc4571_buffer_size;
guint rfc4571_frame_offset;
guint rfc4571_frame_size;
guint rfc4571_consumed_size;
NiceAddress rfc4571_remote_addr;
gboolean rfc4571_wakeup_needed;
/* TURN resolution */
GCancellable *turn_resolving_cancellable;
};
typedef struct {
GObjectClass parent_class;
} NiceComponentClass;
GType nice_component_get_type (void);
NiceComponent *
nice_component_new (guint component_id, NiceAgent *agent, NiceStream *stream);
void
nice_component_close (NiceAgent *agent, NiceStream *stream,
NiceComponent *component);
void
nice_component_shutdown (NiceComponent *component, gboolean shutdown_read,
gboolean shutdown_write);
gboolean
nice_component_find_pair (NiceComponent *component, NiceAgent *agent,
const gchar *lfoundation, const gchar *rfoundation, CandidatePair *pair);
void
nice_component_restart (NiceComponent *component, NiceAgent *agent);
void
nice_component_update_selected_pair (NiceAgent *agent, NiceComponent *component,
const CandidatePair *pair);
NiceCandidate *
nice_component_find_remote_candidate (NiceComponent *component,
const NiceAddress *addr, NiceCandidateTransport transport);
NiceCandidateImpl *
nice_component_set_selected_remote_candidate (NiceComponent *component,
NiceAgent *agent, NiceCandidate *candidate);
void
nice_component_attach_socket (NiceComponent *component, NiceSocket *nsocket);
void
nice_component_remove_socket (NiceAgent *agent, NiceComponent *component,
NiceSocket *nsocket);
void
nice_component_detach_all_sockets (NiceComponent *component);
void
nice_component_free_socket_sources (NiceComponent *component);
GSource *
nice_component_input_source_new (NiceAgent *agent, guint stream_id,
guint component_id, GPollableInputStream *pollable_istream,
GCancellable *cancellable);
GMainContext *
nice_component_dup_io_context (NiceComponent *component);
void
nice_component_set_io_context (NiceComponent *component, GMainContext *context);
void
nice_component_set_io_callback (NiceComponent *component,
NiceAgentRecvFunc func, gpointer user_data,
NiceInputMessage *recv_messages, guint n_recv_messages,
GError **error);
void
nice_component_emit_io_callback (NiceAgent *agent, NiceComponent *component,
gsize buf_len);
gboolean
nice_component_has_io_callback (NiceComponent *component);
void
nice_component_clean_turn_servers (NiceAgent *agent, NiceComponent *component);
TurnServer *
turn_server_new (const gchar *server_ip, guint server_port,
const gchar *username, const gchar *password, NiceRelayType type);
TurnServer *
turn_server_copy (TurnServer *turn);
TurnServer *
turn_server_ref (TurnServer *turn);
void
turn_server_unref (TurnServer *turn);
void
nice_component_add_valid_candidate (NiceAgent *agent, NiceComponent *component,
const NiceCandidate *candidate);
gboolean
nice_component_verify_remote_candidate (NiceComponent *component,
const NiceAddress *address, NiceSocket *nicesock);
GPtrArray *
nice_component_get_sockets (NiceComponent *component);
guint
nice_component_compute_rfc4571_headroom (NiceComponent *component);
gboolean
nice_component_resolving_turn (NiceComponent *component);
G_END_DECLS
#endif /* _NICE_COMPONENT_H */