Gerrit Renker [Sun, 23 May 2010 05:43:04 +0000 (07:43 +0200)]
sender: clean up old FEC API
After the preceding two patches integrated the new function pointers, this
patch removes the now obsolete open() and send_fec() pointers which are no
longer referenced anywhere. It also reorders send.h to get rid of forward
declarations.
Gerrit Renker [Sun, 23 May 2010 05:43:04 +0000 (07:43 +0200)]
udp: integrate new fec interaction
This patch implements the new UDP-FEC interface in two steps:
(1) updating the UDP sender analogously to the previous (DCCP sender) patch;
(2) unifying the struct udp_target by factoring out the fields it has in
common with 'struct sender_client'.
The open() function is deferred to a subsequent patch. The user can override
the MPS value by supplying a max_slice_bytes value not larger than the MPS.
Gerrit Renker [Sun, 23 May 2010 05:43:04 +0000 (07:43 +0200)]
dccp: integrate new fec interaction
This updates the DCCP sender code to access and initialize the new fec_client
structs.
Particulars:
* the open() method has been removed, to be supplied in a later patch;
* the sender_client field became redundant, it is now available as fc->sc.
Gerrit Renker [Sun, 23 May 2010 05:43:04 +0000 (07:43 +0200)]
vss: add state variable for fec client
This merges the two boolean/integer members 'error' and 'ready' into a
single state variable with the same effect:
* the specific value of 'error' was not evaluated within vss.c,
where error < 0 used to disable the fec_client;
* the ready/and error states are mutually exclusive;
* the assertion that compute_next_fec_slice() is not called when
the fec_client is disabled has been removed, since this function is only
called from vss_send(), which ensures that this condition holds;
* likewise, vss_playing() holds in compute_slice_timeout() since
this condition is tested earlier in the caller vss_compute_timeout().
Gerrit Renker [Sun, 23 May 2010 05:43:03 +0000 (07:43 +0200)]
vss: unify calls to the FEC layer
This reorganizes the internal vss data structures a bit to unify calls to the
FEC layer across different senders:
* each sender supplies its sender_client data via the 'sc' pointer;
* the init_fec()/send_fec() function pointers are now parameters
(so that a global variable is not needed);
* both these functions then operate on the supplied sender_client data;
* the transport layer can then interpret the sender_client data in
specific ways, e.g. by accessing sc->private_data;
* a new 'ready' flag has been added to track transport-layer state;
* max_slice_size as paramter has been restored (for overriding MPS value).
Note: this is one patch out of several. It comments out now-incompatible
changes in the API for the sake of being able to compile. However,
the new global API requires the whole set of patches to be applied.
Andre Noll [Tue, 27 Apr 2010 19:43:19 +0000 (21:43 +0200)]
Basic infrastructure changes for FEC/DCCP support.
This patch allows to add a FEC client without specifying the FEC
parameters. Instead, these parameters are set at stream start time
via the new ->open() method of the senders.
It is desirable to defer ssetting the FEC parameters to allow dynamic
determination of the slice size. We need an established connection
to find out the best value for the slice size, but the UDP sender
currently has to fix the slice size at target add time, which is
too early.
The slice size for the UDP and the DCCP sender are currently hardcoded
values; this will be fixed by subsequent patches.
Andre Noll [Fri, 21 May 2010 17:16:22 +0000 (19:16 +0200)]
Fix paraslash.ico.
Somehow this broke quite some time ago. The command
convert -colors 16 paraslash.png paraslash.ico
converts the png to an .ico File that is displayed nicely at least
with firefox. Of course, this should be generated on the fly, but
for now it's simpler to just check it in.
Andre Noll [Sun, 23 May 2010 17:21:02 +0000 (19:21 +0200)]
fecdec_filter: Detect and ingore duplicate slices.
This introduces a bit array to keep track of the slices of a FEC group
that have been received so far. This allows to quickly look up whether
the current slice is already present in the FEC group, in which case we
simply ignore it.
This avoids errors of the kind
unregister_task: unregistering fecdec (slot 0) (invalid index vector)
which have been observed with the UDP transport.
The patch also cleans up add_slice() a bit: It replaces the calls to para_malloc()
and memset() by a simple call to para_calloc() and initializes slice_num earlier
so that it can be used throughout the function.
Andre Noll [Sun, 23 May 2010 17:02:06 +0000 (19:02 +0200)]
fecdec_filter: Simplify clear_group().
There is no point in invalidating the index and data pointers if we are about
to free them anyway. So just set the whole thing to zero. This is easier and
does not require modifications if struct fecdec_group changes.
Gerrit Renker [Sun, 23 May 2010 05:43:04 +0000 (07:43 +0200)]
string: constant value
This replaces the LLONG_MAX constant with the value stolen
from limits.h (that value is only accessible when using
-std=c99). The value of 2^63-1 assumes 64-bit and can also
be computed as (1ULL << (sizeof(long long) * 8 - 1)) - 1).
Andre Noll [Thu, 8 Apr 2010 01:07:50 +0000 (03:07 +0200)]
para_client: Fix unreliable uses of FD_ISSET().
The client_recv_buffer() function of client_common.c did not
check for EAGAIN. Use the new nonblock API if possible that
gets things just right and add a check for EAGAIN for RC4
encrypted connections.
Andre Noll [Sun, 25 Apr 2010 18:01:06 +0000 (20:01 +0200)]
Rework para_accept().
Make it take an fd_set pointer and check the fd for readability
within para_accept() rather than in each caller. Also, don't return
an error on EAGAIN.
Fix all callers accordingly. Most of them become a bit simpler due
to this change.
Andre Noll [Sun, 25 Apr 2010 17:34:35 +0000 (19:34 +0200)]
dccp_recv/udp_recv: Use the new nonblock API.
This simplifies the code quite a bit. In particular it allows to
kill the extra check for EAGAIN that was necessary to deal with
unreliable return value of FD_ISSET().
Andre Noll [Sun, 25 Apr 2010 17:27:45 +0000 (19:27 +0200)]
Introduce the new nonblock API.
This patch is an attempt to create a better API for reads from
non-blocking file descriptors. It adds readv_nonblock() and implements
read_nonblock() as a simple wrapper for readv_nonblock(). Both new
functions check the given file descriptor for readability and read
as much as possible until an error occurs or the buffer is full.
Two additional parameters are introduced: An fd_set and a result
pointer for the number of bytes that have been read successfully. The
optional fd_set pointer is used to have the fixup code for unreliable
returns of FD_ISSET() at one place only.
Having an extra parameter for storing the number of bytes read allows
to treat EOF as an error condition but EAGAIN as a normal condition.
This will simplify callers (dccp_recv and upd_recv) a bit.
Andre Noll [Sun, 25 Apr 2010 12:36:15 +0000 (14:36 +0200)]
oggdec: Fix end-of-file detection.
This bug causes the end of the decoded output not being written to the child nodes
of the buffer tree under certain circumstances. Even if the buffer tree detects EOF
we must not just bail out because there might still be data available for ov_read().
So remember the node status and return negative only if the node status is negative
_and_ ov_read() returns zero.
Andre Noll [Thu, 22 Apr 2010 21:05:26 +0000 (23:05 +0200)]
audiod: Avoid busy loop in standby/off mode.
Without this patch, must_start_decoder() incorrectly returned true if para_server
is announcing a stream but the audiod status is not on. This results in
status_pre_select() requesting a minimal delay.
Andre Noll [Thu, 22 Apr 2010 16:01:34 +0000 (18:01 +0200)]
osx_write fixes.
Boy, that was broken since the switch to the buffer tree API
and hasn't obviously seen any testing since then.
That code is rather strange and full of braindead crap. It
should be rewritten eventually. For now, this patch beats it
a little bit into the direction of sanitity.
Andre Noll [Thu, 22 Apr 2010 07:27:24 +0000 (09:27 +0200)]
gui: Avoid bogus "key is not bound" message.
Commit 0e4306dd5162a2850e623bf3082b3f7291aaad45 introduced a
bug causing para_gui to print a "key not found" message after
each command. Fix it by inserting a missing return statement.
Andre Noll [Tue, 20 Apr 2010 09:51:31 +0000 (11:51 +0200)]
FEC: Change the default slice size from 1490 to 1472.
1472 is the maximal possible size that does not result in fragmentation
on networks with 1500 MTU size (1500 = 1472 payload + 8 UDP header +
20 IP header).
This can be verified using
tcpdump -nv -i eth0 udp
The output must contain a zero offset value, and the "Don't Fragment"
IP flag (DF) should be set.
Andre Noll [Mon, 19 Apr 2010 21:50:51 +0000 (23:50 +0200)]
audiod: Fix status item parsing for long status items.
This was broken since audiod started to use the buffer tree API. Actually there are
two bugs which are both fixed by this patch:
- for_each_stat_item() copies the remaining part of the buffer containing
the incomplete part of the last status item to the beginning of the buffer.
This is necessary if the buffer tree API is not used but messes up the buffer
contents if it _is_ used. Move this memmove() call from for_each_status_item(),
which is called from audiod.c and gui.c, to gui.c, as only gui.c needs it.
- Secondly, audiod.c called btr_node_status() with an minimum input queue
size of zero, which is does not work if a status item crosses a buffer
boundary. In this case for_each_status_item() will only ever see the first buffer
containing the incomplete status item, hence it can never make progress.
Fix this by introducing the min_iqs field of struct status_task. Set this field
to non-zero if the full buffer size was returned by for_each_status_item(),
indicating that the next status item is spread out over two or more buffers.
Andre Noll [Tue, 6 Apr 2010 17:51:17 +0000 (19:51 +0200)]
udp_send: Force chunk queuing.
This adds the public cq_force_enqueue() function to chunk_queue.c.
Unlike cq_enqueue() the new function does not return an error if the
queue is full, but drops old chunks from the queue in order to make
space for the new chunk.
The upd sender uses the new function to avoid kicking targets.
This was not really a good idea as it only papers over the real bug.
A better fix is to check whether the currently active buffer tree
matches the status information obtained from para_server. This will
be implemented in a subsequent patch.
Gerrit Renker [Thu, 25 Mar 2010 16:43:22 +0000 (17:43 +0100)]
para_recv: handle EAGAIN on non-blocking socket
Checking whether the non-blocking socket is readable is not sufficient
to guarantee that EAGAIN is not encountered on the non-blocking socket,
the following was observed in the middle of a UDP/FEC stream:
Mar 24 17:12:44:0533 audi (0) decode_group: writing group 2784 (4232/4374 decoded data bytes)
Mar 24 17:12:44:0710 audi (0) get_time_string: slot 0: 32:42 [94:49] (26%/127:31)
Mar 24 17:12:44:0710 audi (2) btr_remove_node: removing btr node udp from buffer tree
Mar 24 17:12:44:0710 audi (1) unregister_task: unregistering udp receiver node (Resource temporarily unavailable)
The patch fixes the problem by not interpreting the case "data not
yet ready" as an error, but as a temporary condition.
Andre Noll [Sun, 21 Mar 2010 18:16:20 +0000 (19:16 +0100)]
audiod: Revamp the decoder starting logic.
Use an approach that is based on the server start time of the stream. This value
changes whenever para_server announces a new stream.
This makes para_audiod restart the receiver much earlier and should get of timing
problems that cause the UDP sender to remove the UDP target because there
is no listener on the receiving side.
Andre Noll [Sun, 21 Mar 2010 13:13:18 +0000 (14:13 +0100)]
udp_recv: Close receiver after 5 seconds of inactivitly.
There is no way for the UDP receiver to tell that para_server won't send any more
data, e.g. because the UDP target has been deleted. Currently, in this case the UDP
receiver listens on its socket indefinitely and the buffer tree stays active as well. This
can be fatal if para_server starts sending data for another audio format much later.
So close the UDP socket if no data has been received for 5 seconds.
Andre Noll [Tue, 16 Mar 2010 21:14:31 +0000 (22:14 +0100)]
udp_recv: Replace recv_bin_buffer() by Use para_readv().
As pointed out by Gerrit Renker, the UDP receiver suffers from the
same problem that was fixed in commit 9e44ee8 for the DCCP receiver:
recv() might lose data if less than a full datagram is available in
the receiving buffer.
This patch solves the problem for udp_recv in the same way as 9e44ee8
does for dccp_recv.
Gerrit Renker [Sat, 13 Mar 2010 12:08:32 +0000 (13:08 +0100)]
net: fix broken dccp_available_ccids()
This fixes a dumb programming error in dccp_available_ccids(), where a
pointer to 1-byte address was type cast to a socklent_t (typically 4 byte)
pointer. Changed the interface to not expose internals of call.
In addition, this patch adds a missing close() in the error path of makesock().
Andre Noll [Wed, 10 Mar 2010 07:56:55 +0000 (08:56 +0100)]
audiod: Don't init slot info unless opening the receiver succeeds.
Currently we set the slot's audio format number even if the receiver could not
be opened. This confuses the slot clearing code as no writer is active in
this case which triggers the assertion
Andre Noll [Sun, 7 Mar 2010 15:34:25 +0000 (16:34 +0100)]
setup_next_fec_group(): Return early on eof.
The old code updated the group start via set_group_timing() even if the
end of the file was reached. This could confuse the logic in vss_send()
as it uses the goup start timestamp to find out whether all FEC clients
have sent all remaining slices.
Fix this by moving the check for the eof condition before the call to
set_group_timing() that updates the group start.
Andre Noll [Fri, 5 Mar 2010 08:18:49 +0000 (09:18 +0100)]
Minor doxygen fixes.
Fixes
net.c:279: Warning: Found unknown command `\opt'
net.h:104: Warning: argument 'l3type' of command @param is not found in the argument list of makesock...
Andre Noll [Fri, 5 Mar 2010 07:42:13 +0000 (08:42 +0100)]
audiod: Make default filters work also for udp streams.
Currently one has to use --no_default_filters and must specify fecdec as the
first filter for UDP streams, a fact that is not documented anywhere. Make decoding
of udp streams work if no filters were given by changing init_default_filters() to
add fecdec automatically if the udp receiver is used.
Gerrit Renker [Wed, 3 Mar 2010 16:57:14 +0000 (17:57 +0100)]
net: revert restricting SO_REUSEADDR
This reverts part of commit a5927501e41fa3fca2975452617474e78ffecc48
(08_refactor-makesock.diff, 25 Feb 2010), which restricted by default
SO_REUSEADDR to connection-oriented protocols only - it used to be
set on all passive sockets.
However, the same problem exists also for UDP, whenever connecting
more than one listener on the same host, hence revert it.
Andre Noll [Tue, 2 Mar 2010 06:10:00 +0000 (07:10 +0100)]
btr: Fix a nasty thinko in merge_input_pool().
We must take into account the number of bytes already consumed from the wrap buffer.
Otherwise, we might end up not merging as much as we must, which may cause errors
in the child nodes.
This bug was quite hard to hit, but it did bite the aac decoder reliably when used in audiod
with UDP + FEC.
Andre Noll [Thu, 25 Feb 2010 16:33:54 +0000 (17:33 +0100)]
net.h: Fic compilation on systems with partial DCCP support.
There exists at least one system that defines IPPROTO_DCCP but not
DCCP_SOCKOPT_CCID and friends. On such systems compilation fails due
to to undefined symbols.
Fix this problem by checking each value separately.
Gerrit Renker [Thu, 25 Feb 2010 16:05:46 +0000 (17:05 +0100)]
10_set-client-ccid.diff
This adds a commandline option to either
* select the CCID in use for the sender-receiver half-connection or
* advertise the (para_)client's priorities for the CCID;
* the feature is optional and can be used to fine-tune a connection.
The arguments are both range-checked by gengetopt, and against the CCIDs
available on the host. Currently known CCIDs are 2-4, 248-254. Trying a
CCID which is not supported by the host exits via the following route:
dccp_recv_ccid_support_check: 'CCID-253' not supported on this host.
main: parse failed
main: recv syntax error
The CCID negotiation can be watched in wireshark, between the 'Request'
packet sent by the para_client and the corresponding 'Response' packet of
the para_server. Here are some example negotiations:
The server list of (2, 3, 4) is the unaltered default, it can be changed on
the server using the same mechanism.
As shown, the easiest way is to use just a single '--ccid <n>' argument;
when passing multiple values, the outcome is determined by the algorithm
described in RFC 4340, 6.3.1:
* 'server-priority' means that the server overrids the result;
* the server traverses its list of preferences in order of priority and
* uses the first entry which also appears in the client-list;
* resets connection with negotiation failure when there is no common value.
Applying this algorithm on the above lists can be used to verify the
table. This also illustrates that repetition of CCID values has no effect
on the outcome: if the repeated value is first in the server list, it will
be chosen; otherwise all instances of that value are ignored.
Gerrit Renker [Thu, 25 Feb 2010 16:05:45 +0000 (17:05 +0100)]
09_fix-errno-usage.diff
This fixes a bug in the use of errno which corresponds to the 'common mistake'
in the use of errno(3): to not save it before making new system calls. Thanks.
Gerrit Renker [Thu, 25 Feb 2010 16:05:45 +0000 (17:05 +0100)]
08_refactor-makesock.diff
This is a refactoring of makesock():
* the ubiquitous AF_UNSPEC is promoted as the default;
* a wrapper for active sockets, para_connect_simple();
* para_listen() now supports flowopts;
* a wrapper for passive sockets, para_listen_simple();
* for consistency, port numbers (which are 2 byte in
UDP, TCP, and DCCP) have all been set to 'uint16_t'.