
Using a value of 10 seconds instead of 30 as specified, along with the request interval of 4 to 6 seconds, meant the connection state could go to failed when a single response was missing or delayed.
346 lines
13 KiB
C
346 lines
13 KiB
C
/*
|
|
* This file is part of the Nice GLib ICE library.
|
|
*
|
|
* (C) 2006-2009 Collabora Ltd.
|
|
* Contact: Youness Alaoui
|
|
* (C) 2006-2009 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_AGENT_PRIV_H
|
|
#define _NICE_AGENT_PRIV_H
|
|
|
|
/* note: this is a private header part of agent.h */
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#else
|
|
#define NICEAPI_EXPORT
|
|
#endif
|
|
|
|
#include <glib.h>
|
|
|
|
#include "agent.h"
|
|
|
|
/**
|
|
* NiceInputMessageIter:
|
|
* @message: index of the message currently being written into
|
|
* @buffer: index of the buffer currently being written into
|
|
* @offset: byte offset into the buffer
|
|
*
|
|
* Iterator for sequentially writing into an array of #NiceInputMessages,
|
|
* tracking the current write position (i.e. the index of the next byte to be
|
|
* written).
|
|
*
|
|
* If @message is equal to the number of messages in the associated
|
|
* #NiceInputMessage array, and @buffer and @offset are zero, the iterator is at
|
|
* the end of the messages array, and the array is (presumably) full.
|
|
*
|
|
* Since: 0.1.5
|
|
*/
|
|
typedef struct {
|
|
guint message;
|
|
guint buffer;
|
|
gsize offset;
|
|
} NiceInputMessageIter;
|
|
|
|
void
|
|
nice_input_message_iter_reset (NiceInputMessageIter *iter);
|
|
gboolean
|
|
nice_input_message_iter_is_at_end (NiceInputMessageIter *iter,
|
|
NiceInputMessage *messages, guint n_messages);
|
|
guint
|
|
nice_input_message_iter_get_n_valid_messages (NiceInputMessageIter *iter);
|
|
gboolean
|
|
nice_input_message_iter_compare (const NiceInputMessageIter *a,
|
|
const NiceInputMessageIter *b);
|
|
|
|
|
|
#include "socket.h"
|
|
#include "candidate.h"
|
|
#include "stream.h"
|
|
#include "conncheck.h"
|
|
#include "component.h"
|
|
#include "random.h"
|
|
#include "stun/stunagent.h"
|
|
#include "stun/usages/turn.h"
|
|
#include "stun/usages/ice.h"
|
|
|
|
#ifdef HAVE_GUPNP
|
|
#include <libgupnp-igd/gupnp-simple-igd-thread.h>
|
|
#endif
|
|
|
|
/* XXX: starting from ICE ID-18, Ta SHOULD now be set according
|
|
* to session bandwidth -> this is not yet implemented in NICE */
|
|
|
|
#define NICE_AGENT_TIMER_TA_DEFAULT 20 /* timer Ta, msecs (impl. defined) */
|
|
#define NICE_AGENT_TIMER_TR_DEFAULT 25000 /* timer Tr, msecs (impl. defined) */
|
|
#define NICE_AGENT_TIMER_CONSENT_DEFAULT 5000 /* msec timer consent freshness connchecks (RFC 7675) */
|
|
#define NICE_AGENT_TIMER_CONSENT_TIMEOUT 30000 /* msec timer for consent checks to timeout and assume consent lost (RFC 7675) */
|
|
#define NICE_AGENT_TIMER_MIN_CONSENT_INTERVAL 4000 /* msec timer minimum for consent lost requests (RFC 7675) */
|
|
#define NICE_AGENT_TIMER_KEEPALIVE_TIMEOUT 50000 /* msec timer for keepalive (without consent checks) to timeout and assume conection lost */
|
|
#define NICE_AGENT_MAX_CONNECTIVITY_CHECKS_DEFAULT 100 /* see RFC 8445 6.1.2.5 */
|
|
|
|
|
|
/* An upper limit to size of STUN packets handled (based on Ethernet
|
|
* MTU and estimated typical sizes of ICE STUN packet */
|
|
#define MAX_STUN_DATAGRAM_PAYLOAD 1300
|
|
|
|
#define NICE_COMPONENT_MAX_VALID_CANDIDATES 50 /* maximum number of validates remote candidates to keep, the number is arbitrary but hopefully large enough */
|
|
|
|
/* A convenient macro to test if the agent is compatible with RFC5245
|
|
* or OC2007R2. Specifically these two modes share the support
|
|
* of the regular or aggressive nomination mode */
|
|
#define NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2(obj) \
|
|
((obj)->compatibility == NICE_COMPATIBILITY_RFC5245 || \
|
|
(obj)->compatibility == NICE_COMPATIBILITY_OC2007R2)
|
|
|
|
struct _NiceAgent
|
|
{
|
|
GObject parent; /* gobject pointer */
|
|
|
|
GMutex agent_mutex; /* Mutex used for thread-safe lib */
|
|
|
|
gboolean full_mode; /* property: full-mode */
|
|
gchar *stun_server_ip; /* property: STUN server IP */
|
|
guint stun_server_port; /* property: STUN server port */
|
|
gchar *proxy_ip; /* property: Proxy server IP */
|
|
guint proxy_port; /* property: Proxy server port */
|
|
NiceProxyType proxy_type; /* property: Proxy type */
|
|
gchar *proxy_username; /* property: Proxy username */
|
|
gchar *proxy_password; /* property: Proxy password */
|
|
GHashTable *proxy_extra_headers;/* property: Proxy extra headers */
|
|
gboolean saved_controlling_mode;/* property: controlling-mode */
|
|
guint timer_ta; /* property: timer Ta */
|
|
guint max_conn_checks; /* property: max connectivity checks */
|
|
gboolean force_relay; /* property: force relay */
|
|
guint stun_max_retransmissions; /* property: stun max retransmissions, Rc */
|
|
guint stun_initial_timeout; /* property: stun initial timeout, RTO */
|
|
guint stun_reliable_timeout; /* property: stun reliable timeout */
|
|
NiceNominationMode nomination_mode; /* property: Nomination mode */
|
|
gboolean support_renomination; /* property: support RENOMINATION STUN attribute */
|
|
guint idle_timeout; /* property: conncheck timeout before stop */
|
|
|
|
GSList *local_addresses; /* list of NiceAddresses for local
|
|
interfaces */
|
|
GSList *streams; /* list of Stream objects */
|
|
GSList *pruning_streams; /* list of Streams current being shut down */
|
|
GMainContext *main_context; /* main context pointer */
|
|
guint next_candidate_id; /* id of next created candidate */
|
|
guint next_stream_id; /* id of next created candidate */
|
|
NiceRNG *rng; /* random number generator */
|
|
GSList *discovery_list; /* list of CandidateDiscovery items */
|
|
GSList *triggered_check_queue; /* pairs in the triggered check list */
|
|
guint discovery_unsched_items; /* number of discovery items unscheduled */
|
|
GSource *discovery_timer_source; /* source of discovery timer */
|
|
GSource *conncheck_timer_source; /* source of conncheck timer */
|
|
GSource *keepalive_timer_source; /* source of keepalive timer */
|
|
GSList *refresh_list; /* list of CandidateRefresh items */
|
|
GSList *pruning_refreshes; /* list of Refreshes current being shut down*/
|
|
guint64 tie_breaker; /* tie breaker (ICE sect 5.2
|
|
"Determining Role" ID-19) */
|
|
NiceCompatibility compatibility; /* property: Compatibility mode */
|
|
gboolean media_after_tick; /* Received media after keepalive tick */
|
|
gboolean upnp_enabled; /* whether UPnP discovery is enabled */
|
|
#ifdef HAVE_GUPNP
|
|
GUPnPSimpleIgdThread* upnp; /* GUPnP Single IGD agent */
|
|
guint upnp_timeout; /* UPnP discovery timeout */
|
|
#endif
|
|
gchar *software_attribute; /* SOFTWARE attribute */
|
|
gboolean reliable; /* property: reliable */
|
|
gboolean bytestream_tcp; /* property: bytestream-tcp */
|
|
gboolean keepalive_conncheck; /* property: keepalive_conncheck */
|
|
|
|
GCancellable *stun_resolving_cancellable; /* Cancel STUN name resolution */
|
|
GSList *stun_resolving_list; /* List of ongoing resolutions */
|
|
|
|
GQueue pending_signals;
|
|
gboolean use_ice_udp;
|
|
gboolean use_ice_tcp;
|
|
gboolean use_ice_trickle;
|
|
|
|
guint conncheck_ongoing_idle_delay; /* ongoing delay before timer stop */
|
|
gboolean controlling_mode; /* controlling mode used by the
|
|
conncheck */
|
|
gboolean consent_freshness; /* rfc 7675 consent freshness with
|
|
connchecks */
|
|
/* XXX: add pointer to internal data struct for ABI-safe extensions */
|
|
};
|
|
|
|
gboolean
|
|
agent_find_component (
|
|
NiceAgent *agent,
|
|
guint stream_id,
|
|
guint component_id,
|
|
NiceStream **stream,
|
|
NiceComponent **component) G_GNUC_WARN_UNUSED_RESULT;
|
|
|
|
NiceStream *agent_find_stream (NiceAgent *agent, guint stream_id);
|
|
|
|
void agent_gathering_done (NiceAgent *agent);
|
|
void agent_signal_gathering_done (NiceAgent *agent);
|
|
|
|
void agent_lock (NiceAgent *agent);
|
|
void agent_unlock (NiceAgent *agent);
|
|
void agent_unlock_and_emit (NiceAgent *agent);
|
|
|
|
void agent_signal_new_selected_pair (
|
|
NiceAgent *agent,
|
|
guint stream_id,
|
|
guint component_id,
|
|
NiceCandidate *lcandidate,
|
|
NiceCandidate *rcandidate);
|
|
|
|
void agent_signal_component_state_change (
|
|
NiceAgent *agent,
|
|
guint stream_id,
|
|
guint component_id,
|
|
NiceComponentState state);
|
|
|
|
void agent_signal_new_candidate (
|
|
NiceAgent *agent,
|
|
NiceCandidate *candidate);
|
|
|
|
void agent_signal_new_remote_candidate (NiceAgent *agent, NiceCandidate *candidate);
|
|
|
|
void agent_signal_initial_binding_request_received (NiceAgent *agent, NiceStream *stream);
|
|
|
|
guint64 agent_candidate_pair_priority (NiceAgent *agent, NiceCandidate *local, NiceCandidate *remote);
|
|
|
|
NiceSocket * agent_create_tcp_turn_socket (NiceAgent *agent,
|
|
NiceStream *stream, NiceComponent *component, NiceSocket *nicesock,
|
|
NiceAddress *server, NiceRelayType type, gboolean reliable_tcp);
|
|
|
|
typedef gboolean (*NiceTimeoutLockedCallback)(NiceAgent *agent,
|
|
gpointer user_data);
|
|
void agent_timeout_add_with_context (NiceAgent *agent, GSource **out,
|
|
const gchar *name, guint interval, NiceTimeoutLockedCallback function,
|
|
gpointer data);
|
|
void agent_timeout_add_seconds_with_context (NiceAgent *agent, GSource **out,
|
|
const gchar *name, guint interval, NiceTimeoutLockedCallback function,
|
|
gpointer data);
|
|
|
|
StunUsageIceCompatibility agent_to_ice_compatibility (NiceAgent *agent);
|
|
StunUsageTurnCompatibility agent_to_turn_compatibility (NiceAgent *agent);
|
|
NiceTurnSocketCompatibility agent_to_turn_socket_compatibility (NiceAgent *agent);
|
|
|
|
void agent_remove_local_candidate (NiceAgent *agent, NiceStream *stream,
|
|
NiceCandidate *candidate);
|
|
|
|
void nice_agent_init_stun_agent (NiceAgent *agent, StunAgent *stun_agent);
|
|
|
|
void _priv_set_socket_tos (NiceAgent *agent, NiceSocket *sock, gint tos);
|
|
|
|
void _tcp_sock_is_writable (NiceSocket *sock, gpointer user_data);
|
|
|
|
gboolean
|
|
component_io_cb (
|
|
GSocket *gsocket,
|
|
GIOCondition condition,
|
|
gpointer data);
|
|
|
|
gsize
|
|
memcpy_buffer_to_input_message (NiceInputMessage *message,
|
|
const guint8 *buffer, gsize buffer_length);
|
|
guint8 *
|
|
compact_input_message (const NiceInputMessage *message, gsize *buffer_length);
|
|
|
|
guint8 *
|
|
compact_output_message (const NiceOutputMessage *message, gsize *buffer_length);
|
|
|
|
gsize
|
|
output_message_get_size (const NiceOutputMessage *message);
|
|
|
|
gsize
|
|
input_message_get_size (const NiceInputMessage *message);
|
|
|
|
gssize agent_socket_send (NiceSocket *sock, const NiceAddress *addr, gsize len,
|
|
const gchar *buf);
|
|
|
|
guint32
|
|
nice_candidate_jingle_priority (NiceCandidate *candidate);
|
|
|
|
guint32
|
|
nice_candidate_msn_priority (NiceCandidate *candidate);
|
|
|
|
guint32
|
|
nice_candidate_ice_priority_full (guint type_pref, guint local_pref,
|
|
guint component_id);
|
|
|
|
guint32
|
|
nice_candidate_ice_priority (const NiceCandidate *candidate,
|
|
gboolean reliable, gboolean nat_assisted);
|
|
|
|
guint32
|
|
nice_candidate_ms_ice_priority (const NiceCandidate *candidate,
|
|
gboolean reliable, gboolean nat_assisted);
|
|
|
|
guint64
|
|
nice_candidate_pair_priority (guint32 o_prio, guint32 a_prio);
|
|
|
|
#define NICE_CANDIDATE_PAIR_PRIORITY_MAX_SIZE 32
|
|
|
|
void
|
|
nice_candidate_pair_priority_to_string (guint64 prio, gchar *string);
|
|
|
|
/*
|
|
* nice_debug_init:
|
|
*
|
|
* Initialize the debugging system. Uses the NICE_DEBUG environment variable
|
|
* to set the appropriate debugging flags
|
|
*/
|
|
void nice_debug_init (void);
|
|
|
|
|
|
#ifdef NDEBUG
|
|
static inline gboolean nice_debug_is_enabled (void) { return FALSE; }
|
|
static inline gboolean nice_debug_is_verbose (void) { return FALSE; }
|
|
static inline void nice_debug (const char *fmt, ...) { }
|
|
static inline void nice_debug_verbose (const char *fmt, ...) { }
|
|
#else
|
|
gboolean nice_debug_is_enabled (void);
|
|
gboolean nice_debug_is_verbose (void);
|
|
void nice_debug (const char *fmt, ...) G_GNUC_PRINTF (1, 2);
|
|
void nice_debug_verbose (const char *fmt, ...) G_GNUC_PRINTF (1, 2);
|
|
#endif
|
|
|
|
#if !GLIB_CHECK_VERSION(2, 59, 0)
|
|
#if __GNUC__ > 6
|
|
#define G_GNUC_FALLTHROUGH __attribute__((fallthrough))
|
|
#else
|
|
#define G_GNUC_FALLTHROUGH
|
|
#endif /* __GNUC__ */
|
|
#endif
|
|
|
|
#endif /*_NICE_AGENT_PRIV_H */
|