Age | Commit message (Collapse) | Author | Files | Lines |
|
Expand documentation for nice_agent_gather_candidates() and
nice_agent_set_remote_credentials().
|
|
|
|
Ensure the agent’s context doesn’t get iterated while in the middle of
reading a message, as that will corrupt the component->recv_messages
state.
|
|
|
|
Use it instead of memcmp() to avoid comparing padding bytes.
|
|
|
|
|
|
enough for one STUN packet
|
|
|
|
|
|
|
|
And we get close to 10% perf boost
|
|
Looping through the list of send segment was the only thing from libnice
showing up in my profiler. Keeping a list of segment that were never sent
has made it disappear.
|
|
|
|
|
|
|
|
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.
|
|
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
|
|
It was used correctly only half the time anyway
|
|
We never send multiple messages to separate targets in practice, so
this will simplify the code
|
|
Otherwise it would have attached to a newly created context
|
|
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
added.
This includes modifications to the test-send-recv unit test to cover the
new API.
|
|
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.
|
|
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.
|
|
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
untouched.
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
buffer.
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.
|
|
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
thoroughly.
|
|
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.
|
|
This introduces no functional changes.
|
|
|
|
|
|
Make sure that if the timeout is now, no negative number is passed as
an unsigned
|
|
Integer comparisons need to take care of rollovers
|
|
|
|
This also means that it can't have the component ref. Also make the
cancellable a child source of this GPollableInputStream one
|
|
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.
|
|
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()
|
|
|
|
Otherwise it produces a deadlock
|
|
There was a possible race between disconnection and freeing of the WriteDatas
structure, now it's ref-counted so it can never happen. Also set the len to -1
if the cancellable was cancelled.
|
|
|
|
|
|
|
|
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
cheating.
Fix the problem by queuing incoming pseudo-TCP messages until an
outbound UDP socket is available to send the ACKs or SYNACKs on.
|
|
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.
|
|
|
|
|
|
Sharing is caring.
|
|
|
|
This prevents the pseudotcp socket from being destroyed from within a
callback.
|
|
Previously, the pseudo-TCP implementation’s readable() callback would
only be invoked when new data was received if it was enabled. The
callback is enabled by reading all data from the TCP input buffer until
EWOULDBLOCK is returned.
Reading all that data is not possible if the client buffer is of a
limited size, and can lead to livelocks if the client reads exactly the
number of bytes in the TCP input buffer (i.e. its buffer size matches
the TCP buffer fill level).
Instead, always invoke the readable() callback. This might be slightly
less performant, but the whole pseudo-TCP implementation is a shambles
anyway, and the callbacks need removing, so why not?
|