Andre Noll [Mon, 4 May 2009 11:34:16 +0000 (13:34 +0200)]
Fix compilation on FreeBSD.
Without these two includes, compilation fails on FreeBSD with
/usr/include/net/if.h:265: error: field `ifru_addr' has incomplete type
/usr/include/net/if.h:266: error: field `ifru_dstaddr' has incomplete type
/usr/include/net/if.h:267: error: field `ifru_broadaddr' has incomplete type
/usr/include/net/if.h:299: error: field `ifra_addr' has incomplete type
/usr/include/net/if.h:300: error: field `ifra_broadaddr' has incomplete type
/usr/include/net/if.h:301: error: field `ifra_mask' has incomplete type
/usr/include/net/if.h:368: error: field `addr' has incomplete type
/usr/include/net/if.h:369: error: field `dstaddr' has incomplete type
Andre Noll [Mon, 4 May 2009 11:12:17 +0000 (13:12 +0200)]
Fix two gcc warnings.
mp3_afh.c:420: warning: comparison of distinct pointer types lacks a cast
alsa_write.c:119: warning: format '%zu' expects type 'size_t', but argument 4 has type 'int'
Andre Noll [Sun, 3 May 2009 16:11:22 +0000 (18:11 +0200)]
Alsa fixes and cleanups.
This patch
- replaces the unused E_SND_PCM_INFO error by E_PHYSICAL_WIDTH,
- checks the return value of snd_pcm_format_physical_width() and returns
-E_PHYSICAL_WIDTH if this causes bytes_per_frame being non-positive,
- introduces an upper bound for the start threshold. Without that
change, playback could be delayed by several seconds on some alsa
configurations (problem pointed out by Johannes Wörner, thanks).
- does not return early on input errors which could cause the last
part of the audio stream being skipped.
- avoids calling snd_pcm_writei() with a frame count of zero which
could happen with the old code in case there's more than zero but
less than a full frame of audio data available.
- cleans up the documentation of struct private_alsa_write_data
Currently, filters must not change their output buffer on the fly
because the writer might already have a reference to the old buffer
and keeps using this buffer.
As dealing with changing output buffers requires much more work,
including changes to the generic filter and writer code, let's defer
this change to post 0.3.4.
Andre Noll [Sun, 26 Apr 2009 17:45:59 +0000 (19:45 +0200)]
Avoid dirty afs tables on shutdown.
The server process must wait for afs because afs catches SIGINT/SIGTERM
and may thus not respond immediately to these SIGNALS.
Before reacting to the signal, afs might want to use the shared memory
area and the mmd mutex. If the server process destroys this mutex
too early and afs tries to lock the shared memory area, the call to
mutex_lock() will fail and terminate the afs process. This leads to
dirty osl tables.
There's no such problem with the other children of the server process
(the command handlers) as these reset their SIGINT/SIGTERM handlers
to the default action, i.e. these processes get killed immediately
by the above kill().
Andre Noll [Sun, 26 Apr 2009 16:08:13 +0000 (18:08 +0200)]
Fix an invalid free() in command handlers.
The chunk table and the info_string are pointers located in the mmd
struct that point to dynamically allocated memory that must be freed
by the parent and the child. However, as the mmd struct is in a shared
memory area, there's no guarantee that after the fork these pointers
are still valid in child context. As these two pointers are not used
in the child anyway, we save them to local variables and free the
memory via that copy in the child.
Andre Noll [Sat, 25 Apr 2009 13:17:58 +0000 (15:17 +0200)]
[net]: Fix buffer overflow in send_cred_buffer().
As pointed out by Johannes Wörner, para_audioc crashes on recent
Ubuntu systems due to stack smashing. This is caused by writing past
the end of the control buffer which stores the message header and
the socket credentials.
This patch fixes the bug by allocating a properly sized buffer.
Andre Noll [Thu, 23 Apr 2009 15:18:03 +0000 (17:18 +0200)]
[udp_send] Refuse to stream files with invalid chunk tables.
If an audio file contains a chunk so large that even the maximal
possible number of slices is not sufficient to put this chunk into
a single FEC group, we must refuse to send this file. It's likely a
corrupt file anyway.
The old code in num_slices() was buggy as it returned the number of
slices needed to send the file as an uint8_t, so the return value
was actually the number of needed slices mod 256. This could trigger
the assert() in setup_next_fec_group() which checks that the group
contains at least one chunk.
This patch changes num_slices() to detect this situation more
reliably. As it is likely caused by a bad audio file rather than by a
networking problem, we do _not_ kick the fec client, but deactivate
it for the current file only. This requires the new "error" member
of struct fec_client which indicates a temporarily disabled fec client.
Andre Noll [Thu, 23 Apr 2009 11:39:04 +0000 (13:39 +0200)]
[mp3_afh]: Ignore junk at the end of an mp3 file.
There are mp3 files containing large areas of zeros at the end of the
file. The old code in mp3_afh.c would include these zeros in the last
chunk of the file.
This leads to unnecessary network traffic as including this area in
a chunk means that useless data is going to be sent to the client.
More importantly, it causes the udp sender to bail out because such
large chunks can not be fec-encoded, even with the maximal number
of slices.
This patch uses frame_start+frame_length instead of the file size as
the end of the last chunk which avoids this particular problem.
Andre Noll [Mon, 6 Apr 2009 16:41:37 +0000 (18:41 +0200)]
Use para_sigaction() in command handlers.
This allows to get rid of an ugly hack for solaris. The patch also adds checks
for whether the signals were reset sucessfully in the command handler and
aborts early on errors.
Andre Noll [Mon, 6 Apr 2009 15:53:46 +0000 (17:53 +0200)]
Introduce para_sigaction().
This wrapper for sigaction() is public and may be used to setup
a handler different from the generic handler that gets installed
for the signal by para_install_sighandler().
Andre Noll [Mon, 6 Apr 2009 15:45:44 +0000 (17:45 +0200)]
signal: Switch from signal() to sigaction.
Use of signal() should be avoided because the behavior of signal() varies
across Unix versions, and has also varied historically across different
versions of Linux.
This patch rewrites para_install_sighandler so that it calls sigaction()
instead of signal(). The implementation is taken from good old APUE.
There are a couple of other users of signal() in the paraslash code. Most
of which are OK because they use signal() only to ignore/reset a signal which
happens to be the only portable use of signal(). All other users of signal()
have to be converted in subsequent patches.
Andre Noll [Sat, 21 Mar 2009 16:46:43 +0000 (17:46 +0100)]
server: Use a temporary SIGCHLD handler to catch afs init failures.
If afs dies immediately on startup (because of dirty tables) para_server
would not notice as the SIGCHLD handler is being intalled after the
call to afs_init().
Andre Noll [Thu, 19 Mar 2009 21:51:17 +0000 (22:51 +0100)]
audiod: Improve display of play time.
Keeping track of the offset, server stream start and the duration
of the audio file length at the time the receiver/writer was started
allows to compute the play time more accurately.
Andre Noll [Sun, 15 Mar 2009 16:35:37 +0000 (17:35 +0100)]
alsa: Split alsa_open().
Only perform what is absolutely necessary in alsa_open(). Call the
real alsa initialization from alsa_post_select(), when we actually
have audio data available to start streaming.
This should get rid of the sound artefacts that happen sometimes
at the beginning of the stream.
Andre Noll [Sun, 15 Mar 2009 14:29:12 +0000 (15:29 +0100)]
audiod: Improve receiver restart logic.
Use the vss status flags and the stream_start time announced by
para_server to decide when to start a new receiver.
This is better than basing this decision only on whether the vss status
equals "playing" as we did before. This allows to reliably detect when it
is safe to start a new receiver while the filter/writer of the current
stream are still active.
The old code would simply wait until filter/writer complete which, due to
buffering, might be much too late.
This was really a brain fart. Instead, introduce a small delay
in alsa_open() that defers audio data writing by 100ms. This seems
to be enough to get rid of the buffer underruns with the udp sender.
Andre Noll [Sun, 8 Mar 2009 20:41:27 +0000 (21:41 +0100)]
Make FEC work with oggvorbis streams.
Unfortunately, this required to rewrite large parts of the fec code
in vss.c. The new code behaves better if the FEC parameters are not
suitable for the current audio file, for example if the audio file header
does not fit into the desired number of slices. It detects this situation
and adjusts the given FEC parameters accordingly.
Andre Noll [Sun, 1 Mar 2009 22:09:51 +0000 (23:09 +0100)]
vss.c: Improve the fec timing code.
This patch
- Fixes a the bug where assert(start_buf) caused para_server
to abort.
- Gets rid of buffer underruns by introducing a quick hack that
sends all but the first slice a bit early.
- Moves some code from compute_next_fec_slice() to
setup_next_fec_group() where it belongs.
Andre Noll [Sat, 28 Feb 2009 13:55:46 +0000 (14:55 +0100)]
Add forward error correction code to the udp sender/receiver.
This patch adds the first draft of a FEC implementation based
on code by Luigi Rizzo.
On the server side, the FEC encoding is done within the virtual
streaming system which also contains the timing routines for sending
a FEC-encoded audio stream. Senders my request such an encoded stream
by calling vss_add_fec_client() with a fec_client_parms structure
that contains the FEC parameters and a callback function which is used
to actually send the data.
On the receiver side, the new fecdec filter is introduced which must
be used to decode a FEC-encoded stream. As the fec parameters are
contained in the header of each data slice of the encoded stream, no
options to this filter are necessary.
ATM, FEC is only used by the udp sender/receiver, but other protocols
can be easily changed to use FEC as well.
This new code is still experimental, lacks documentation and the fec
parameters can currently only be changed by editing the source code.
Gerrit Renker [Sat, 28 Feb 2009 12:40:01 +0000 (13:40 +0100)]
URL/UDPv6 support for the UDP sender.
This adds support for URL strings to support IPv4/IPv6 addresses, hostnames,
and optional port numbers to the UDP sender. The syntax is based on RFC 3986,
example URL strings to be used with the 'add'/'delete' commands are:
10.10.1.2:8000 # host:port
10.10.1.2 # host with default port 8000
localhost # hostname (for IPv4 or IPv6 host)
localhost:8001 # hostname with port
[::1]:8000 # same, but different syntax
[badc0de::1] # IPv6 host with default port 8000
The 'delete' command now also supports port-wildcarding, i.e. not specifying
the port in the 'delete' command removes all targets whose host names match.
The UDP sender has been tested to function with IPv6, including multicasting:
* server: para_server --udp_target=[ff05::beef]:8000 --udp_mcast_iface=eth1
* client: para_audiod -F -D -r 'ogg:udp -i ff05::beef -I eth0'