From 3b843ed159d34e081eb2b6f2bcf7895de6a17127 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 17 Apr 2015 17:04:47 +0100 Subject: [PATCH] agent: Move NiceAgent:reliable down to Component:reliable By my reading of the ICE-TCP standard (RFC 6544), different stream components should be able to differ in whether they are TCP or UDP, and hence one component could run over TCP-over-UDP, while another runs over raw UDP, for example. Otherwise, both components would have to be TCP, and the UDP component would essentially run as framed UDP within TCP-over-UDP. Push the NiceAgent:reliable property down to a field in Component, and update all the checks for it to use the component rather than the agent. https://bugs.freedesktop.org/show_bug.cgi?id=90154 --- agent/agent-priv.h | 3 + agent/agent.c | 119 ++++++++++++++++------------ agent/agent.h | 66 +++++++++++---- agent/component.c | 8 +- agent/component.h | 5 +- agent/conncheck.c | 19 +++-- agent/discovery.c | 20 ++--- agent/inputstream.c | 18 ++--- agent/outputstream.c | 19 +++-- agent/stream.c | 10 ++- agent/stream.h | 3 +- docs/reference/libnice/libnice-sections.txt | 2 + nice/libnice.sym | 1 + win32/vs9/libnice.def | 1 + 14 files changed, 187 insertions(+), 107 deletions(-) diff --git a/agent/agent-priv.h b/agent/agent-priv.h index c413bc1..5996d56 100644 --- a/agent/agent-priv.h +++ b/agent/agent-priv.h @@ -241,6 +241,9 @@ output_message_get_size (const NiceOutputMessage *message); gssize agent_socket_send (NiceSocket *sock, const NiceAddress *addr, gsize len, const gchar *buf); +void +agent_pseudo_tcp_socket_create (NiceAgent *agent, Stream *stream, + Component *component); guint32 nice_candidate_jingle_priority (NiceCandidate *candidate); diff --git a/agent/agent.c b/agent/agent.c index 259fdc9..0e45723 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -1379,8 +1379,9 @@ static void component->stream->id, component->id); } -static void -pseudo_tcp_socket_create (NiceAgent *agent, Stream *stream, Component *component) +void +agent_pseudo_tcp_socket_create (NiceAgent *agent, Stream *stream, + Component *component) { PseudoTcpCallbacks tcp_callbacks = {component, pseudo_tcp_socket_opened, @@ -1964,7 +1965,7 @@ process_queued_tcp_packets (NiceAgent *agent, Stream *stream, guint stream_id = stream->id; guint component_id = component->id; - g_assert (agent->reliable); + g_assert (component->reliable); if (component->selected_pair.local == NULL || pseudo_tcp_socket_is_closed (component->tcp) || @@ -2022,9 +2023,9 @@ void agent_signal_new_selected_pair (NiceAgent *agent, guint stream_id, nice_udp_turn_socket_set_peer (lcandidate->sockptr, &rcandidate->addr); } - if(agent->reliable && !nice_socket_is_reliable (lcandidate->sockptr)) { + if (component->reliable && !nice_socket_is_reliable (lcandidate->sockptr)) { if (!component->tcp) - pseudo_tcp_socket_create (agent, stream, component); + agent_pseudo_tcp_socket_create (agent, stream, component); process_queued_tcp_packets (agent, stream, component); pseudo_tcp_socket_connect (component->tcp); @@ -2078,7 +2079,7 @@ void agent_signal_new_selected_pair (NiceAgent *agent, guint stream_id, agent_queue_signal (agent, signals[SIGNAL_NEW_SELECTED_PAIR], stream_id, component_id, lcandidate->foundation, rcandidate->foundation); - if(agent->reliable && nice_socket_is_reliable (lcandidate->sockptr)) { + if (component->reliable && nice_socket_is_reliable (lcandidate->sockptr)) { agent_signal_socket_writable (agent, component); } } @@ -2138,7 +2139,7 @@ void agent_signal_component_state_change (NiceAgent *agent, guint stream_id, gui component->state = state; - if (agent->reliable) + if (component->reliable) process_queued_tcp_packets (agent, stream, component); agent_queue_signal (agent, signals[SIGNAL_COMPONENT_STATE_CHANGED], @@ -2292,7 +2293,7 @@ priv_add_new_candidate_discovery_turn (NiceAgent *agent, if (nicesock == NULL) return; - if (agent->reliable) + if (component->reliable) nice_socket_set_writable_callback (nicesock, _tcp_sock_is_writable, component); if (turn->type == NICE_RELAY_TYPE_TURN_TLS && @@ -2348,35 +2349,27 @@ priv_add_new_candidate_discovery_turn (NiceAgent *agent, ++agent->discovery_unsched_items; } -NICEAPI_EXPORT guint -nice_agent_add_stream ( - NiceAgent *agent, - guint n_components) +static guint +add_streamv (NiceAgent *agent, guint n_components, va_list component_flags) { Stream *stream; guint ret = 0; - guint i; + NiceComponentFlags default_flags; g_return_val_if_fail (NICE_IS_AGENT (agent), 0); g_return_val_if_fail (n_components >= 1, 0); agent_lock(); - stream = stream_new (n_components, agent); + + default_flags = agent->deprecated_reliable ? + NICE_COMPONENT_RELIABLE : NICE_COMPONENT_NONE; + + stream = stream_newv (agent, n_components, component_flags, + default_flags); agent->streams = g_slist_append (agent->streams, stream); stream->id = agent->next_stream_id++; nice_debug ("Agent %p : allocating stream id %u (%p)", agent, stream->id, stream); - if (agent->reliable) { - nice_debug ("Agent %p : reliable stream", agent); - for (i = 0; i < n_components; i++) { - Component *component = stream_find_component_by_id (stream, i + 1); - if (component) { - pseudo_tcp_socket_create (agent, stream, component); - } else { - nice_debug ("Agent %p: couldn't find component %d", agent, i+1); - } - } - } stream_initialize_credentials (stream, agent->rng); @@ -2386,6 +2379,29 @@ nice_agent_add_stream ( return ret; } +NICEAPI_EXPORT guint +nice_agent_add_stream ( + NiceAgent *agent, + guint n_components) +{ + return add_streamv (agent, n_components, NULL); +} + +NICEAPI_EXPORT guint +nice_agent_add_stream_full ( + NiceAgent *agent, + guint n_components, + ...) +{ + guint retval; + va_list flags; + + va_start (flags, n_components); + retval = add_streamv (agent, n_components, flags); + va_end (flags); + + return retval; +} NICEAPI_EXPORT gboolean nice_agent_set_relay_info(NiceAgent *agent, @@ -2776,7 +2792,7 @@ nice_agent_gather_candidates ( nice_address_set_port (addr, 0); - if (agent->reliable) + if (component->reliable) nice_socket_set_writable_callback (host_candidate->sockptr, _tcp_sock_is_writable, component); @@ -3614,7 +3630,7 @@ agent_recv_message_unlocked ( } /* Unhandled STUN; try handling TCP data, then pass to the client. */ - if (message->length > 0 && agent->reliable) { + if (message->length > 0 && component->reliable) { if (!nice_socket_is_reliable (nicesock) && !pseudo_tcp_socket_is_closed (component->tcp)) { /* If we don’t yet have an underlying selected socket, queue up the @@ -4014,8 +4030,17 @@ nice_agent_recv_messages_blocking_or_nonblocking (NiceAgent *agent, return -1; } + agent_lock (); + + if (!agent_find_component (agent, stream_id, component_id, + &stream, &component)) { + g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE, + "Invalid stream/component."); + goto done; + } + /* Receive buffer size must be at least 1280 for STUN */ - if (!agent->reliable) { + if (!component->reliable) { for (i = 0; i < n_messages; i++) { if (input_message_get_size (&messages[i]) < 1280) { GInputVector *vec; @@ -4032,15 +4057,6 @@ nice_agent_recv_messages_blocking_or_nonblocking (NiceAgent *agent, } } - agent_lock (); - - if (!agent_find_component (agent, stream_id, component_id, - &stream, &component)) { - g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE, - "Invalid stream/component."); - goto done; - } - nice_debug ("%s: %p: (%s):", G_STRFUNC, agent, blocking ? "blocking" : "non-blocking"); nice_debug_input_message_composition (messages, n_messages); @@ -4070,7 +4086,7 @@ nice_agent_recv_messages_blocking_or_nonblocking (NiceAgent *agent, while (!received_enough && !g_queue_is_empty (&component->pending_io_messages)) { - pending_io_messages_recv_messages (component, agent->reliable, + pending_io_messages_recv_messages (component, component->reliable, component->recv_messages, component->n_recv_messages, &component->recv_messages_iter); @@ -4088,7 +4104,7 @@ nice_agent_recv_messages_blocking_or_nonblocking (NiceAgent *agent, /* For a reliable stream, grab any data from the pseudo-TCP input buffer * before trying the sockets. */ - if (agent->reliable && + if (component->reliable && pseudo_tcp_socket_get_available_bytes (component->tcp) > 0) { pseudo_tcp_socket_recv_messages (component->tcp, component->recv_messages, component->n_recv_messages, @@ -4146,7 +4162,7 @@ nice_agent_recv_messages_blocking_or_nonblocking (NiceAgent *agent, component->recv_messages, component->n_recv_messages); error_reported = (child_error != NULL && !g_error_matches (child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)); - reached_eos = (agent->reliable && + reached_eos = (component->reliable && pseudo_tcp_socket_is_closed_remotely (component->tcp) && nice_input_message_iter_compare (&prev_recv_messages_iter, &component->recv_messages_iter)); @@ -4340,7 +4356,7 @@ nice_agent_send_messages_nonblocking_internal ( nice_address_get_port (&component->selected_pair.remote->addr)); } - if(agent->reliable && + if (component->reliable && !nice_socket_is_reliable (component->selected_pair.local->sockptr)) { if (!pseudo_tcp_socket_is_closed (component->tcp)) { /* Send on the pseudo-TCP socket. */ @@ -4790,7 +4806,7 @@ component_io_cb (GSocket *gsocket, GIOCondition condition, gpointer user_data) * need to take the agent lock to change the Component’s io_callback. */ g_assert (!has_io_callback || component->recv_messages == NULL); - if (agent->reliable && !nice_socket_is_reliable (socket_source->socket)) { + if (component->reliable && !nice_socket_is_reliable (socket_source->socket)) { #define TCP_HEADER_SIZE 24 /* bytes */ guint8 local_header_buf[TCP_HEADER_SIZE]; /* FIXME: Currently, the critical path for reliable packet delivery has two @@ -4993,7 +5009,7 @@ nice_agent_attach_recv ( * next incoming data. * but only do this if we know we're already readable, otherwise we might * trigger an error in the initial, pre-connection attach. */ - if (agent->reliable && !pseudo_tcp_socket_is_closed (component->tcp) && + if (component->reliable && !pseudo_tcp_socket_is_closed (component->tcp) && component->tcp_readable) pseudo_tcp_socket_readable (component->tcp, component); } @@ -5036,7 +5052,7 @@ nice_agent_set_selected_pair ( /* step: stop connectivity checks (note: for the whole stream) */ conn_check_prune_stream (agent, stream); - if (agent->reliable && !nice_socket_is_reliable (pair.local->sockptr) && + if (component->reliable && !nice_socket_is_reliable (pair.local->sockptr) && pseudo_tcp_socket_is_closed (component->tcp)) { nice_debug ("Agent %p: not setting selected pair for s%d:%d because " "pseudo tcp socket does not exist in reliable mode", agent, @@ -5107,15 +5123,15 @@ nice_agent_get_selected_socket (NiceAgent *agent, guint stream_id, agent_lock(); - /* Reliable streams are pseudotcp or MUST use RFC 4571 framing */ - if (agent->reliable) - goto done; - /* step: check that params specify an existing pair */ if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) goto done; + /* Reliable streams are pseudotcp or MUST use RFC 4571 framing */ + if (component->reliable) + goto done; + if (!component->selected_pair.local || !component->selected_pair.remote) goto done; @@ -5209,7 +5225,7 @@ nice_agent_set_selected_remote_candidate ( if (!lcandidate) goto done; - if (agent->reliable && !nice_socket_is_reliable (lcandidate->sockptr) && + if (component->reliable && !nice_socket_is_reliable (lcandidate->sockptr) && pseudo_tcp_socket_is_closed (component->tcp)) { nice_debug ("Agent %p: not setting selected remote candidate s%d:%d because" " pseudo tcp socket does not exist in reliable mode", agent, @@ -5930,13 +5946,14 @@ nice_agent_get_io_stream (NiceAgent *agent, guint stream_id, g_return_val_if_fail (stream_id >= 1, NULL); g_return_val_if_fail (component_id >= 1, NULL); - g_return_val_if_fail (agent->reliable, NULL); - agent_lock (); if (!agent_find_component (agent, stream_id, component_id, NULL, &component)) goto done; + if (!component->reliable) + goto done; + if (component->iostream == NULL) component->iostream = nice_io_stream_new (agent, stream_id, component_id); diff --git a/agent/agent.h b/agent/agent.h index 47c4d5a..6b256a1 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -173,8 +173,8 @@ G_BEGIN_DECLS * @length: total number of valid bytes contiguously stored in @buffers * * Represents a single message received off the network. For reliable - * connections, this is essentially just an array of buffers (specifically, - * @from can be ignored). for non-reliable connections, it represents a single + * components, this is essentially just an array of buffers (specifically, + * @from can be ignored). for non-reliable components, it represents a single * packet as received from the OS. * * @n_buffers may be -1 to indicate that @buffers is terminated by a @@ -203,8 +203,8 @@ typedef struct { * is %NULL-terminated * * Represents a single message to transmit on the network. For - * reliable connections, this is essentially just an array of - * buffer. for non-reliable connections, it represents a single packet + * reliable components, this is essentially just an array of + * buffer. for non-reliable components, it represents a single packet * to send to the OS. * * @n_buffers may be -1 to indicate that @buffers is terminated by a @@ -313,6 +313,21 @@ typedef enum NICE_COMPONENT_TYPE_RTCP = 2 } NiceComponentType; +/** + * NiceComponentFlags: + * @NICE_COMPONENT_NONE: No flags enabled. + * @NICE_COMPONENT_UNRELIABLE: Use unreliable UDP transport, rather than TCP. + * @NICE_COMPONENT_RELIABLE: Use reliable TCP transport rather than UDP. + * + * Flags for creating a new component. + * + * Since: 0.1.12.1 + */ +typedef enum { + NICE_COMPONENT_NONE = 0, + NICE_COMPONENT_UNRELIABLE = 0, + NICE_COMPONENT_RELIABLE = 1 << 0, +} NiceComponentFlags; /** * NiceCompatibility: @@ -336,10 +351,10 @@ typedef enum If @NICE_COMPATIBILITY_RFC5245 compatibility mode is used for a non-reliable - agent, then ICE-UDP will be used with higher priority and ICE-TCP will also - be used when the UDP connectivity fails. If it is used with a reliable agent, - then ICE-UDP will be used with the TCP-Over-UDP (#PseudoTcpSocket) if ICE-TCP - fails and ICE-UDP succeeds. + component, then ICE-UDP will be used with higher priority and ICE-TCP will + also be used when the UDP connectivity fails. If it is used with a reliable + component, then ICE-UDP will be used with the TCP-Over-UDP (#PseudoTcpSocket) + if ICE-TCP fails and ICE-UDP succeeds. * @@ -447,14 +462,16 @@ nice_agent_new_reliable (GMainContext *ctx, NiceCompatibility compat); gboolean nice_agent_add_local_address (NiceAgent *agent, NiceAddress *addr); - /** * nice_agent_add_stream: * @agent: The #NiceAgent Object * @n_components: The number of components to add to the stream * - * Adds a data stream to @agent containing @n_components components. The - * returned stream ID is guaranteed to be positive on success. + * Adds a data stream to @agent containing @n_components components. All + * components will be unreliable by default, unless the #NiceAgent was created + * using nice_agent_new_reliable(). Use nice_agent_add_stream_full() to specify + * flags for each component. The returned stream ID is guaranteed to be + * positive on success. * * Returns: The ID of the new stream, 0 on failure **/ @@ -464,6 +481,27 @@ nice_agent_add_stream ( guint n_components); /** + * nice_agent_add_stream_full: + * @agent: The #NiceAgent object + * @n_components: The number of components to add to the stream + * @...: Exactly @n_components parameters of type #NiceComponentFlags, + * specifying the flags for each component + * + * Adds a data stream to @agent, as nice_agent_add_stream() does, but + * additionally allows the flags for each of its components to be specified. + * @... must have exactly @n_components entries of type #NiceComponentFlags, + * which specify the flags for each component in order. + * + * Returns: The ID of the new stream, 0 on failure + * Since: 0.1.12.1 + */ +guint +nice_agent_add_stream_full ( + NiceAgent *agent, + guint n_components, + ...); + +/** * nice_agent_remove_stream: * @agent: The #NiceAgent Object * @stream_id: The ID of the stream to remove @@ -768,7 +806,7 @@ nice_agent_send ( * application would have to use nice_agent_sent() to fill the buffer or have * to retry sending at a later point. * - * On failure, -1 will be returned and @error will be set. If the #NiceAgent is + * On failure, -1 will be returned and @error will be set. If the component is * reliable and the socket is not yet connected, %G_IO_ERROR_BROKEN_PIPE will be * returned; if the write buffer is full, %G_IO_ERROR_WOULD_BLOCK will be * returned. In both cases, wait for the #NiceAgent::reliable-transport-writable @@ -1517,9 +1555,9 @@ nice_agent_parse_remote_candidate_sdp ( * The #GInputStream and #GOutputStream implement #GPollableInputStream and * #GPollableOutputStream. * - * This function may only be called on reliable #NiceAgents. It is a + * This function may only be called on reliable components. It is a * programming error to try and create an I/O stream wrapper for an - * unreliable stream. + * unreliable component. * * Returns: (transfer full): A #GIOStream. * diff --git a/agent/component.c b/agent/component.c index 1a1f84a..a88f00e 100644 --- a/agent/component.c +++ b/agent/component.c @@ -122,7 +122,8 @@ socket_source_free (SocketSource *source) } Component * -component_new (guint id, NiceAgent *agent, Stream *stream) +component_new (guint id, NiceAgent *agent, Stream *stream, + NiceComponentFlags flags) { Component *component; @@ -137,6 +138,7 @@ component_new (guint id, NiceAgent *agent, Stream *stream) component->tcp = NULL; component->agent = agent; component->stream = stream; + component->reliable = ((flags & NICE_COMPONENT_RELIABLE) != 0); nice_agent_init_stun_agent (agent, &component->stun_agent); @@ -160,6 +162,10 @@ component_new (guint id, NiceAgent *agent, Stream *stream) g_queue_init (&component->queued_tcp_packets); + if (component->reliable) { + agent_pseudo_tcp_socket_create (agent, stream, component); + } + return component; } diff --git a/agent/component.h b/agent/component.h index 7ded710..cc1a263 100644 --- a/agent/component.h +++ b/agent/component.h @@ -195,6 +195,8 @@ struct _Component GCancellable *stop_cancellable; GSource *stop_cancellable_source; /* owned */ + gboolean reliable; /* construct-only */ + PseudoTcpSocket *tcp; GSource* tcp_clock; guint64 last_clock_timeout; @@ -213,7 +215,8 @@ struct _Component }; Component * -component_new (guint component_id, NiceAgent *agent, Stream *stream); +component_new (guint component_id, NiceAgent *agent, Stream *stream, + NiceComponentFlags flags); void component_close (Component *cmp); diff --git a/agent/conncheck.c b/agent/conncheck.c index 057fc81..5017696 100644 --- a/agent/conncheck.c +++ b/agent/conncheck.c @@ -571,6 +571,7 @@ static gboolean priv_conn_keepalive_retransmissions_tick (gpointer pointer) } static guint32 peer_reflexive_candidate_priority (NiceAgent *agent, + Component *component, NiceCandidate *local_candidate) { NiceCandidate *candidate_priority = @@ -586,10 +587,10 @@ static guint32 peer_reflexive_candidate_priority (NiceAgent *agent, priority = nice_candidate_msn_priority (candidate_priority); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { priority = nice_candidate_ms_ice_priority (candidate_priority, - agent->reliable, FALSE); + component->reliable, FALSE); } else { priority = nice_candidate_ice_priority (candidate_priority, - agent->reliable, FALSE); + component->reliable, FALSE); } nice_candidate_free (candidate_priority); @@ -639,7 +640,8 @@ static gboolean priv_conn_keepalive_tick_unlocked (NiceAgent *agent) size_t password_len = priv_get_password (agent, agent_find_stream (agent, stream->id), p->remote, &password); - priority = peer_reflexive_candidate_priority (agent, p->local); + priority = peer_reflexive_candidate_priority (agent, component, + p->local); if (nice_debug_is_enabled ()) { gchar tmpbuf[INET6_ADDRSTRLEN]; @@ -1782,7 +1784,8 @@ size_t priv_get_password (NiceAgent *agent, Stream *stream, /* Implement the computation specific in RFC 5245 section 16 */ static unsigned int priv_compute_conncheck_timer (NiceAgent *agent, - Stream *stream) + Stream *stream, + Component *component) { GSList *item; guint waiting_and_in_progress = 0; @@ -1801,7 +1804,7 @@ static unsigned int priv_compute_conncheck_timer (NiceAgent *agent, rto = agent->timer_ta * waiting_and_in_progress; /* We assume non-reliable streams are RTP, so we use 100 as the max */ - if (agent->reliable) + if (component->reliable) return MAX (rto, 500); else return MAX (rto, 100); @@ -1844,7 +1847,7 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair) pair->remote, pair->local, uname, sizeof (uname), FALSE); password_len = priv_get_password (agent, stream, pair->remote, &password); - priority = peer_reflexive_candidate_priority (agent, pair->local); + priority = peer_reflexive_candidate_priority (agent, component, pair->local); if (password != NULL && (agent->compatibility == NICE_COMPATIBILITY_MSN || @@ -1894,7 +1897,7 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair) stun_timer_start_reliable(&pair->timer, STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT); } else { stun_timer_start (&pair->timer, - priv_compute_conncheck_timer (agent, stream), + priv_compute_conncheck_timer (agent, stream, component), STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS); } @@ -2049,7 +2052,7 @@ static gboolean priv_schedule_triggered_check (NiceAgent *agent, Stream *stream, p->timer_restarted ? "no" : "yes"); if (!nice_socket_is_reliable (p->sockptr) && !p->timer_restarted) { stun_timer_start (&p->timer, - priv_compute_conncheck_timer (agent, stream), + priv_compute_conncheck_timer (agent, stream, component), STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS); p->timer_restarted = TRUE; } diff --git a/agent/discovery.c b/agent/discovery.c index f3a702d..3394809 100644 --- a/agent/discovery.c +++ b/agent/discovery.c @@ -544,10 +544,10 @@ HostCandidateResult discovery_add_local_host_candidate ( candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, - agent->reliable, FALSE); + component->reliable, FALSE); } else { candidate->priority = nice_candidate_ice_priority (candidate, - agent->reliable, FALSE); + component->reliable, FALSE); } priv_generate_candidate_credentials (agent, candidate); @@ -630,10 +630,10 @@ discovery_add_server_reflexive_candidate ( candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, - agent->reliable, nat_assisted); + component->reliable, nat_assisted); } else { candidate->priority = nice_candidate_ice_priority (candidate, - agent->reliable, nat_assisted); + component->reliable, nat_assisted); } /* step: link to the base candidate+socket */ @@ -739,10 +739,10 @@ discovery_add_relay_candidate ( candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, - agent->reliable, FALSE); + component->reliable, FALSE); } else { candidate->priority = nice_candidate_ice_priority (candidate, - agent->reliable, FALSE); + component->reliable, FALSE); } /* step: link to the base candidate+socket */ @@ -830,10 +830,10 @@ discovery_add_peer_reflexive_candidate ( candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, - agent->reliable, FALSE); + component->reliable, FALSE); } else { candidate->priority = nice_candidate_ice_priority (candidate, - agent->reliable, FALSE); + component->reliable, FALSE); } priv_assign_foundation (agent, candidate); @@ -931,10 +931,10 @@ NiceCandidate *discovery_learn_remote_peer_reflexive_candidate ( candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, - agent->reliable, FALSE); + component->reliable, FALSE); } else { candidate->priority = nice_candidate_ice_priority (candidate, - agent->reliable, FALSE); + component->reliable, FALSE); } priv_assign_remote_foundation (agent, candidate); diff --git a/agent/inputstream.c b/agent/inputstream.c index b9c5369..6ebdeea 100644 --- a/agent/inputstream.c +++ b/agent/inputstream.c @@ -122,8 +122,7 @@ nice_input_stream_class_init (NiceInputStreamClass *klass) /*** * NiceInputStream:agent: * - * The #NiceAgent to wrap with an input stream. This must be an existing - * reliable agent. + * The #NiceAgent to wrap with an input stream. * * A reference is not held on the #NiceAgent. If the agent is destroyed before * the #NiceInputStream, %G_IO_ERROR_CLOSED will be returned for all @@ -157,7 +156,8 @@ nice_input_stream_class_init (NiceInputStreamClass *klass) /*** * NiceInputStream:component-id: * - * ID of the component to use in the #NiceInputStream:agent. + * ID of the component to use in the #NiceInputStream:agent. This must be an + * existing reliable component. * * Since: 0.1.5 */ @@ -273,8 +273,8 @@ nice_input_stream_init_pollable (GPollableInputStreamInterface *iface) * @stream_id: The ID of the agent’s stream to wrap * @component_id: The ID of the agent’s component to wrap * - * Create a new #NiceInputStream wrapping the given stream/component from - * @agent, which must be a reliable #NiceAgent. + * Create a new #NiceInputStream wrapping the given reliable stream/component + * from @agent. * * The constructed #NiceInputStream will not hold a reference to @agent. If * @agent is destroyed before the input stream, %G_IO_ERROR_CLOSED will be @@ -345,7 +345,7 @@ nice_input_stream_close (GInputStream *stream, GCancellable *cancellable, /* Shut down the read side of the pseudo-TCP stream, if it still exists. */ if (agent_find_component (agent, priv->stream_id, priv->component_id, - &_stream, &component) && agent->reliable && + &_stream, &component) && component->reliable && !pseudo_tcp_socket_is_closed (component->tcp)) { pseudo_tcp_socket_shutdown (component->tcp, PSEUDO_TCP_SHUTDOWN_RD); } @@ -385,9 +385,9 @@ nice_input_stream_is_readable (GPollableInputStream *stream) goto done; } - /* If it’s a reliable agent, see if there’s any pending data in the pseudo-TCP - * buffer. */ - if (agent->reliable && + /* If it’s a reliable component, see if there’s any pending data in the + * pseudo-TCP buffer. */ + if (component->reliable && pseudo_tcp_socket_get_available_bytes (component->tcp) > 0) { retval = TRUE; goto done; diff --git a/agent/outputstream.c b/agent/outputstream.c index d479aa5..229cf15 100644 --- a/agent/outputstream.c +++ b/agent/outputstream.c @@ -42,9 +42,8 @@ * @stability: Stable * * #NiceOutputStream is a #GOutputStream wrapper for a single reliable stream - * and component of a #NiceAgent. Given an existing reliable #NiceAgent, plus - * the IDs of an existing stream and component in the agent, it will provide a - * streaming output interface for writing to the given component. + * and component of a #NiceAgent. Given an existing reliable component, it will + * provide a streaming output interface for writing to that component. * * A single #NiceOutputStream can only be used with a single agent, stream and * component triple, and will be closed as soon as that stream is removed from @@ -133,8 +132,7 @@ nice_output_stream_class_init (NiceOutputStreamClass *klass) /*** * NiceOutputStream:agent: * - * The #NiceAgent to wrap with an output stream. This must be an existing - * reliable agent. + * The #NiceAgent to wrap with an output stream. * * A reference is not held on the #NiceAgent. If the agent is destroyed before * the #NiceOutputStream, %G_IO_ERROR_CLOSED will be returned for all @@ -168,7 +166,8 @@ nice_output_stream_class_init (NiceOutputStreamClass *klass) /*** * NiceOutputStream:component-id: * - * ID of the component to use in the #NiceOutputStream:agent. + * ID of the component to use in the #NiceOutputStream:agent.This must be an + * existing reliable component. * * Since: 0.1.5 */ @@ -287,8 +286,8 @@ nice_output_stream_init_pollable (GPollableOutputStreamInterface *iface) * @stream_id: The ID of the agent’s stream to wrap * @component_id: The ID of the agent’s component to wrap * - * Create a new #NiceOutputStream wrapping the given stream/component from - * @agent, which must be a reliable #NiceAgent. + * Create a new #NiceOutputStream wrapping the given reliable stream/component + * from @agent. * * The constructed #NiceOutputStream will not hold a reference to @agent. If * @agent is destroyed before the output stream, %G_IO_ERROR_CLOSED will be @@ -489,7 +488,7 @@ nice_output_stream_close (GOutputStream *stream, GCancellable *cancellable, /* Shut down the write side of the pseudo-TCP stream. */ if (agent_find_component (agent, priv->stream_id, priv->component_id, - &_stream, &component) && agent->reliable && + &_stream, &component) && component->reliable && !pseudo_tcp_socket_is_closed (component->tcp)) { pseudo_tcp_socket_shutdown (component->tcp, PSEUDO_TCP_SHUTDOWN_WR); } @@ -530,7 +529,7 @@ nice_output_stream_is_writable (GPollableOutputStream *stream) if (component->selected_pair.local != NULL) { NiceSocket *sockptr = component->selected_pair.local->sockptr; - /* If it’s a reliable agent, see if there’s any space in the pseudo-TCP + /* If it’s a reliable component, see if there’s any space in the pseudo-TCP * output buffer. */ if (!nice_socket_is_reliable (sockptr)) { retval = pseudo_tcp_socket_can_send (component->tcp); diff --git a/agent/stream.c b/agent/stream.c index 09f79b5..b67f442 100644 --- a/agent/stream.c +++ b/agent/stream.c @@ -53,7 +53,8 @@ static volatile unsigned int n_streams_destroyed = 0; * @brief ICE stream functionality */ Stream * -stream_new (guint n_components, NiceAgent *agent) +stream_newv (NiceAgent *agent, guint n_components, va_list component_flags, + NiceComponentFlags default_flags) { Stream *stream; guint n; @@ -65,7 +66,12 @@ stream_new (guint n_components, NiceAgent *agent) stream = g_slice_new0 (Stream); for (n = 0; n < n_components; n++) { - component = component_new (n + 1, agent, stream); + NiceComponentFlags flags; + + flags = (component_flags != NULL) ? + va_arg (component_flags, NiceComponentFlags) : default_flags; + + component = component_new (n + 1, agent, stream, flags); stream->components = g_slist_append (stream->components, component); } diff --git a/agent/stream.h b/agent/stream.h index e220f43..4df4e79 100644 --- a/agent/stream.h +++ b/agent/stream.h @@ -78,7 +78,8 @@ struct _Stream Stream * -stream_new (guint n_components, NiceAgent *agent); +stream_newv (NiceAgent *agent, guint n_components, va_list component_flags, + NiceComponentFlags default_flags); void stream_close (Stream *stream); diff --git a/docs/reference/libnice/libnice-sections.txt b/docs/reference/libnice/libnice-sections.txt index 82f0197..e43615c 100644 --- a/docs/reference/libnice/libnice-sections.txt +++ b/docs/reference/libnice/libnice-sections.txt @@ -9,12 +9,14 @@ NiceCompatibility NiceAgentRecvFunc NiceInputMessage NiceOutputMessage +NiceComponentFlags NICE_AGENT_MAX_REMOTE_CANDIDATES nice_agent_new nice_agent_new_reliable nice_agent_add_local_address nice_agent_set_port_range nice_agent_add_stream +nice_agent_add_stream_full nice_agent_remove_stream nice_agent_set_relay_info nice_agent_forget_relays diff --git a/nice/libnice.sym b/nice/libnice.sym index efcfdc3..ff502fd 100644 --- a/nice/libnice.sym +++ b/nice/libnice.sym @@ -17,6 +17,7 @@ nice_address_set_port nice_address_to_string nice_agent_add_local_address nice_agent_add_stream +nice_agent_add_stream_full nice_agent_recv nice_agent_recv_messages nice_agent_recv_nonblocking diff --git a/win32/vs9/libnice.def b/win32/vs9/libnice.def index 7065330..6569ce7 100644 --- a/win32/vs9/libnice.def +++ b/win32/vs9/libnice.def @@ -21,6 +21,7 @@ nice_address_set_port nice_address_to_string nice_agent_add_local_address nice_agent_add_stream +nice_agent_add_stream_full nice_agent_attach_recv nice_agent_forget_relays nice_agent_gather_candidates -- 2.1.0