1. 31 Jan, 2014 40 commits
    • Olivier Crête's avatar
    • Olivier Crête's avatar
      agent: Restore the ability nice_agent_send() to send partial buffers · 919b2c46
      Olivier Crête authored
      This is very important for reliable mode.
      Also use it in the GOutputStream so as to not get into the case where
      there is still some space in the TCP buffer, but not enough for one message.
      Also warn against this problem.
    • Olivier Crête's avatar
      agent: Replace nice_agent_build_io_stream() with nice_agent_get_io_stream() · 430e8db5
      Olivier Crête authored
      Also made the GIOStream into a singleton, it always returns the same one.
      Also make it impossible to create a GIOStream for a non-existing stream/component
    • Olivier Crête's avatar
      Remove the "length" parameter from NiceOutputMessage · 4f456a46
      Olivier Crête authored
      It was used correctly only half the time anyway
    • Olivier Crête's avatar
      Remove the "to" parameter from NiceOutputMessage · 5c235a86
      Olivier Crête authored
      We never send multiple messages to separate targets in practice, so
      this will simplify the code
    • Olivier Crête's avatar
      agent: Attaching to a NULL context should attach to the default one · a5c8a141
      Olivier Crête authored
      Otherwise it would have attached to a newly created context
    • Philip Withnall's avatar
      agent: Add support for vectored I/O for sends · f7b15f14
      Philip Withnall authored
      Add one new public function, nice_agent_send_messages_nonblocking(),
      which replaces nice_agent_send_full(). This isn’t an API break, because
      nice_agent_send_full() hasn’t been in a release yet. The new API allows
      sending multiple messages in a single call, and supports vectors of
      buffers to transmit the messages from.
      The existing nice_agent_send() API has been left untouched, although
      it’s a bit of a bugbear because it’s non-blocking and doesn’t fit with
      the new *_nonblocking() naming scheme. Oh well.
      This doesn’t bring any notable changes to the number of memcpy()s on the
      critical path: it remains at zero for the common cases and common socket
      types. It introduces the possibility for future work to eliminate some
      memcpy()s in more complex socket types, like tcp-turn and tcp-bsd, but
      these optimisations have not been made yet. FIXME comments have been
      This includes modifications to the test-send-recv unit test to cover the
      new API.
    • Philip Withnall's avatar
      socket: Add vectored I/O support for sending on sockets · 515481e6
      Philip Withnall authored
      Replace the send() API with a send_messages() API, which supports
      sending multiple messages, each with multiple buffers rather than a
      single monolithic buffer.
      This doesn’t break API, as the socket API is not exposed outside
      libnice. It does introduce a new struct: NiceOutputMessage, which is
      analogous to struct mmsghdr and NiceInputMessage.
      This includes updates to the test-bsd test to cover the changed API.
      The existing nice_socket_send() API has been retained as a thin wrapper
      around nice_socket_send_messages(), for convenience only. It’s hoped
      that internal usage of this API will decline to the point where it can
      be removed.
    • Philip Withnall's avatar
      agent: Move gtk-doc comments from agent.c to agent.h for new API · 55e53a9c
      Philip Withnall authored
      I completely disagree with this, and believe the C file is a much better
      place for them, as then they’re:
       • easier to read while hacking on the functions, and
       • easier to modify once finished hacking on the functions.
      I think the argument for putting them in the header files (so that the
      documentation is available by the function declarations) is weak, as the
      generated gtk-doc manual should be installed on the system alongside the
      header files in any case.
    • Philip Withnall's avatar
      agent: Add support for vectored I/O for receives · 253be348
      Philip Withnall authored
      Add two new public functions:
       • nice_agent_recv_messages()
       • nice_agent_recv_messages_nonblocking()
      which allow receiving multiple messages in a single call, and support
      vectors of buffers to receive the messages into.
      The existing nice_agent_recv[_nonblocking]() APIs have been left
      This tidies up a lot of the message handling code internally, and
      eliminates a couple of memcpy()s. There are still a few more memcpy()s
      on the critical path, which could be eliminated with further work.
      In the reliable agent case, every message is memcpy()ed twice: once into
      the pseudo-TCP receive buffer, and once out of it. The copy on input
      could be eliminated (in the case of in-order delivery of packets) by
      receiving directly into the receive buffer. The copy on output can’t be
      eliminated except in the I/O callback case (when
      nice_agent_attach_recv() has been used), in which case the callback
      could be invoked with a pointer directly into the pseudo-TCP receive
      In the non-reliable agent case, zero memcpy()s are used.
      A couple of the more complex socket implementations (TURN and HTTP) have
      slow paths during setup, and partially also during normal use. These
      could be optimised further, and FIXME comments have been added.
    • Philip Withnall's avatar
      stun: Add a fast version of stun_message_validate_buffer_length() · e9ebf991
      Philip Withnall authored
      stun_message_validate_buffer_length() is already fast, but requires the
      entire message to be in a single monolithic buffer. For introducing
      vectored I/O, this becomes impossible to guarantee.
      Rather than rewriting the STUN code to natively support vectors of
      buffers (which would be a huge undertaking, and would probably slow
      the code down considerably), implement a fast check of whether a message
      is likely to be a STUN packet which *does* support vectored I/O. This
      can then be used to determine whether to compact the vector of buffers
      to a single monolithic one in order to validate the message more
    • Philip Withnall's avatar
      socket: Add vectored I/O support for receiving on sockets · dfab04cd
      Philip Withnall authored
      Replace the recv() API with a recv_messages() API, which supports
      receiving multiple messages, each with multiple buffers rather than a
      single monolithic buffer.
      This doesn’t break API, as the socket API is not exposed outside
      libnice. It does introduce a new struct: NiceInputMessage, which is
      analogous to struct mmsghdr.
      This includes updates to the test-bsd test to cover the changed API.
    • Philip Withnall's avatar
      agent: Simplify control flow in agent_recv_locked() · bc527dcf
      Philip Withnall authored
      This introduces no functional changes.
    • Olivier Crête's avatar
      agent: Make sure there is no integer overflow if the timeout is now · 69b876b3
      Olivier Crête authored
      Make sure that if the timeout is now, no negative number is passed as
      an unsigned
    • Olivier Crête's avatar
      outputstream: Don't wake up on every input buffer · b5f79391
      Olivier Crête authored
      So instead of actually blocking on the FD, block on a GCancellable
      which is triggered when the writable callback is called. Also set the
      application's GCancellable as a child of this source.
    • Olivier Crête's avatar
      agent: Only change pseudotcp clock if the new timeout is sooner · 83bcf954
      Olivier Crête authored
      Destroying and creating GSources is expensive, so also don't destroy and
      re-create if possible, instead lets use the new g_source_set_ready_time()
    • Olivier Crête's avatar
    • Olivier Crête's avatar
    • Olivier Crête's avatar
    • Philip Withnall's avatar
      agent: Queue incoming pseudo-TCP messages until ACKs can be sent · 18e2e3a2
      Philip Withnall authored
      If pseudo-TCP messages are received before a socket has been selected
      from all the STUN candidates, they would previously be immediately
      passed to the pseudo-TCP state machine, which would attempt to send ACKs
      for them. This would fail (due to a lack of an outbound UDP socket), and
      would incur a retransmit timeout in the TCP state machine. This slowed
      down the tests enormously if one agent in a test completed candidate
      selection before the other (which is an entirely reasonable scenario).
      This never occurred before because the existing tests artificially run
      both agents in lock-step, and never send data packets from one to the
      other until both have completed candidate selection. This is basically
      Fix the problem by queuing incoming pseudo-TCP messages until an
      outbound UDP socket is available to send the ACKs or SYNACKs on.
    • Philip Withnall's avatar
      agent: Correct maximum UDP data length · d638586c
      Philip Withnall authored
      The maximum number of bytes in a UDP packet (ignoring problems like
      fragmentation and MTUs) is 65535 = 2^16-1 bytes, as the length field
      in the packet header is 16b wide.
    • Philip Withnall's avatar
      agent: Slightly improve debugging output · 7a05b330
      Philip Withnall authored
    • Philip Withnall's avatar
    • Philip Withnall's avatar
      agent: Combine nice_agent_recv() and nice_agent_recv_nonblocking() · b560a86f
      Philip Withnall authored
      Sharing is caring.
    • Philip Withnall's avatar
      agent: Add a nice_agent_recv_nonblocking() function · 6d3a32a0
      Philip Withnall authored
      This is a non-blocking variant of nice_agent_recv(), and will be used
      internally by the GPollableInputStream implementation. External
      implementations may use it as well.
      It reserves the right to iterate the main context, but doesn’t currently
      do so.
    • Philip Withnall's avatar
      agent: Add nice_agent_build_io_stream() API · 11f04d6c
      Philip Withnall authored
      This allows creation of a NiceIOStream from an existing NiceAgent
    • Philip Withnall's avatar
      agent: Add a nice_agent_send_full() API exposing error information · 5d63de5a
      Philip Withnall authored
      This adds GError and GCancellable parameters to the existing
      nice_agent_send() API, and is identical in all other respects (notably,
      it is non-blocking).
      The GCancellable is currently unused, but could be used in future if the
      API grows to support blocking writes.
      The GError is used to return more interesting error codes than just
    • Philip Withnall's avatar
      agent: Add nice_agent_recv() allowing blocking receives on sockets · 243c47ec
      Philip Withnall authored
      This is a blocking receive function, designed to be called from a worker
      thread. It cannot be used in conjunction with the existing
      nice_agent_attach_recv() API, as the blocking receive and the GSource
      would compete over access to the single copy of the data in the kernel’s
      receive buffer.
    • Philip Withnall's avatar
      agent: Move GSource handling into Component · c5672702
      Philip Withnall authored
      Rather than handle GSource creation, attachment and removal in
      NiceAgent, handle it inside Component. This brings it closer to the
      networking code, and improves encapsulation of the state of each
    • Philip Withnall's avatar
      agent: Fix format specifiers in debug messages · 12ee430e
      Philip Withnall authored
      Mostly problems with the specifier for gsize.
    • Philip Withnall's avatar
      agent: Support invoking I/O callbacks in non-default contexts · 2b6370a8
      Philip Withnall authored
      If the Component’s I/O receiver machinery is invoked from a thread which
      can’t acquire the main context specified for the I/O callbacks, the
      callbacks need to be queued as idle handlers in that main context.
      This is needed for the case where blocking reads are being performed in
      one thread, with their callbacks needing to be delivered in another
      This introduces a new fine-grained lock to Component: io_mutex. This
      protects accesses to Component->io_callback, Component->io_user_data and
      Component->pending_io_callbacks. If being locked at the same time as the
      main agent lock, it must always be locked afterwards, but the agent lock
      does not *have* to be held in order to lock io_mutex.
    • Philip Withnall's avatar
    • Philip Withnall's avatar
      agent: Integrate TcpUserData into Component · 68a9632e
      Philip Withnall authored
      It was allocated separately and always set, which is a wasted
      allocation. Instead, pull the NiceAgent and Stream pointers into the
      Component directly, and eliminate the redundant allocation.
      This also means the NiceAgent and Stream are available for use elsewhere
      in the Component code (not just with TCP stuff).
    • Philip Withnall's avatar
      agent: Clarify naming of internal recv function · 80716d38
      Philip Withnall authored
      Add ‘_locked’ to the name to clarify that it must be called with the
      agent’s lock already held.
    • Philip Withnall's avatar
      agent: Use guint8* as the type for internal buffers · 23c34a87
      Philip Withnall authored
      …rather than gchar*. This differentiates binary buffers from strings a
      little better, although the two types are functionally equivalent.
      Also use gsize for buffer sizes, rather than guint.
    • Philip Withnall's avatar
      agent: Move I/O callback handling from NiceAgent into Component · 6fe29601
      Philip Withnall authored
      Compartmentalise the handling of setting and clearing the user-provided
      per-Component I/O callbacks.
      Data flows from the socket, through nice_agent_g_source_cb(), to
      component_emit_io_callback() which calls the callback provided by the
      user when originally attaching to the stream/component.
    • Philip Withnall's avatar
      agent: Move socket/source handling from NiceAgent into Component · 790974e0
      Philip Withnall authored
      This compartmentalises it a little more, reducing the spread of
      state-changing code from three files down to one.
      The key change is the switch from using two GSLists of NiceSockets and
      GSources in Component, to using a single GSList of a struct {
      NiceSocket, GSource }. This is possible because there is at most one
      GSource per NiceSocket. This change reduces memory overhead (from the
      GSList structures) slightly, and makes the relationship between sockets
      and sources much clearer.
    • Philip Withnall's avatar
      agent: Refactor nice_agent_g_source_cb() · 7cca1250
      Philip Withnall authored
      Move all functionality which is unrelated to the GSource into
    • Philip Withnall's avatar
      agent: Add a NiceAgent::streams-removed signal · 053b2887
      Philip Withnall authored
      This is emitted when one or more streams are removed from the agent
      due to a call to nice_agent_remove_stream().
    • Olivier Crête's avatar
      agent: Don't make relayed sockets available in nice_agent_get_selected_socket() · 42358dde
      Olivier Crête authored
      Also document that fact.