Andre Noll [Thu, 3 Mar 2011 16:39:11 +0000 (17:39 +0100)]
handle_connect(): Don't send anything to non-authorized clients.
Currently, if we don't receive a valid authentication request, we send
back an RC4-encrypted error message to the client, which is kind of
pointless since the RC4 keys are not set up at this point.
Of course we could send an unencryted error message in this case,
but in since the peer could be anything, it seems safer to just close
the connection.
Andre Noll [Thu, 3 Mar 2011 14:51:41 +0000 (15:51 +0100)]
score: Fix use of uninitialized memory on 64 bit machines.
The score of an audio file in the score table is defined as a quantity
which is sizeof(long) bytes large, i.e. 4 bytes on 32bit systems and
8 bytes on 64 bit systems. This is not a problem per se because the
score column lives only in memory, so we do not have to worry about
incompatibilities of the on-disk layout.
However, at several places in score.c we cast the pointer to the osl
object to (int *) rather than (long *). When writing to the object on
a 64 bit machine, this will only set 4 out of the 8 allocated bytes,
the other four bytes stay uninitialized. The "ls" command uses the
correct cast to (long *) and reads the full 8 bytes. This causes
valgrind to complain:
==5433== Conditional jump or move depends on uninitialised value(s)
==5433== at 0x4164F4: prepare_ls_row (aft.c:1334)
==5433== by 0x4E2F421: osl_rbtree_loop (osl.c:1457)
==5433== by 0x418935: admissible_file_loop (score.c:255)
==5433== by 0x41601A: com_ls_callback (aft.c:1363)
==5433== by 0x411FDE: command_post_select (afs.c:842)
==5433== by 0x41B67A: schedule (sched.c:76)
==5433== by 0x411ACF: afs_init (afs.c:986)
==5433== by 0x408863: main (server.c:451)
==5433==
==5433== Conditional jump or move depends on uninitialised value(s)
==5433== at 0x41650A: prepare_ls_row (aft.c:1334)
==5433== by 0x4E2F421: osl_rbtree_loop (osl.c:1457)
==5433== by 0x418935: admissible_file_loop (score.c:255)
==5433== by 0x41601A: com_ls_callback (aft.c:1363)
==5433== by 0x411FDE: command_post_select (afs.c:842)
==5433== by 0x41B67A: schedule (sched.c:76)
==5433== by 0x411ACF: afs_init (afs.c:986)
==5433== by 0x408863: main (server.c:451)
Andre Noll [Thu, 3 Mar 2011 14:09:53 +0000 (15:09 +0100)]
RC4: Fix invalid read.
Commit 7cb8fa26 (May 2010) created a target buffer for the RC4-encoded
data which is slightly larger than the input buffer because openssl
apparently wrote beyond the size it was told to write.
As it turns out, this was not enough as RC4() may also read-overflow
the input buffer. Valgrind says on Linux/x86_64:
==2423== Invalid read of size 8
==2423== at 0x5312020: RC4 (in /lib/libcrypto.so.0.9.8)
==2423== by 0x40F01D: rc4_send_bin_buffer (crypt.c:224)
==2423== by 0x40C724: com_stat (command.c:391)
==2423== by 0x40BABF: handle_connect (command.c:838)
==2423== by 0x408330: command_post_select (server.c:404)
==2423== by 0x41B5DA: schedule (sched.c:76)
==2423== by 0x4089C3: main (server.c:581)
==2423== Address 0x6cefeb8 is 232 bytes inside a block of size 235 alloc'd
==2423== at 0x4C275A2: realloc (vg_replace_malloc.c:525)
==2423== by 0x40DE74: para_realloc (string.c:40)
==2423== by 0x40E324: make_message (string.c:134)
==2423== by 0x40C5D0: com_stat (command.c:328)
==2423== by 0x40BABF: handle_connect (command.c:838)
==2423== by 0x408330: command_post_select (server.c:404)
==2423== by 0x41B5DA: schedule (sched.c:76)
==2423== by 0x4089C3: main (server.c:581)
Fix this by treating the last len % 8 bytes of the input
separately. It's ugly but it does silence valgrind and should not be
noticeably slower since we are only doing one extra copy of at most
7 bytes.
We need to round the input size up and down to a multiple of 8,
so this patch introduces generic macros in para.h for this purpose.
Andre Noll [Mon, 28 Feb 2011 13:05:31 +0000 (14:05 +0100)]
audiod: Update --no_default_filters help text.
This was quite outdated: We got the defaults right for udp and dccp
streams at least since commit 28f8405e (April 2010). Moreover, two new
audio formats (wma and spx) are supported now but are not mentioned
in the help text. Describe that the corresponding decoder is used as
the default filter rather than listing all supported audio formats.
Andre Noll [Mon, 28 Feb 2011 10:32:16 +0000 (11:32 +0100)]
Makefile: Stop building on ggo errors.
The dependency files *.d are implicitly made by -include command
during make's first pass. The "-" prefix instructs make to ignore any
non-existing files *and* all errors resulting from executing the rules
for the *.d targets . This prefix is necessary to avoid the warning
messages about non-existing dependency files, for example after a
"make clean2".
This implies that make proceeds even if a dependency file could not
be created due to a syntax error in a .ggo file. We'd like to stop
if this happens, but unfortunately gnu make does not have an option
for specifying this behaviour in an include command.
This patch works around this shortcoming by letting the "all"
target depend on the new phony target "dep" which depends on all .d
files. This way all *.d targets are considered twice: Once during the
first pass (where errors are ignored) and again due to the all->dep
dependency.
If no errors occur, "make dep" is a no-op, so this change should not
slow down the build noticeably. A slight drawback of this solution
is that, in case of an error in a ggo file, the error will be printed
twice. But this it is still better than silently ignoring the error.
Andre Noll [Fri, 25 Feb 2011 14:33:58 +0000 (15:33 +0100)]
Fix depend.sh on NetBSD.
NetBSD's sed apparently does not understand the \+ syntax to match the preceeding
pattern one or more times. OTOH, {1,} seems to work, so use this syntax instead.
This caused the build to abort silently because make gives up on the targets that
depend on files in the "cmdline" directory.
Andre Noll [Sun, 20 Feb 2011 18:56:59 +0000 (19:56 +0100)]
Fix oss_init() error path.
A bug similar to the one fixed in the previous patch for the alsa
writer is also present in the oss writer: If oss_init() fails the
->private_data pointer is non-NULL, but its contents have already
been freed. glibc detects this, aborts the process and spits out
Andre Noll [Sun, 20 Feb 2011 16:01:15 +0000 (17:01 +0100)]
Fix alsa_init() error path.
If alsa_init() fails, alsa_write_post_select() removes the buffer tree
node and sets t->error to a negative value. para_audiod (or para_write)
then calls alsa->close() to deallocate any resources. At this point
wn->private_data is non-NULL while pad->handle _is_ NULL. The
subsequent call to snd_pcm_nonblock() therefore triggers the assertion
which aborts para_audiod. Fix this bug by freeing the ->private_data
pointer already in alsa_write_post_select() if alsa_init() fails. This
way, ->private_data and pad->handle are either both NULL or both
non-NULL, which meets the expectations of alsa_close().
Andre Noll [Mon, 5 Jul 2010 21:42:31 +0000 (23:42 +0200)]
Make autoconf-2.66 happy.
This removes more lines than it adds and avoids the following warning;
configure.ac:689: warning: AC_DEFINE_UNQUOTED: `
configure.ac:689: result=
configure.ac:689: for i in $status_items; do
configure.ac:689: result="$result SI_$(echo $i | tr 'a-z' 'A-Z')' is not a valid preprocessor define value
(cherry picked from commit 5842e3e7f2aa17fe16cb806b4ba955ce1f25ce53)
Andre Noll [Wed, 9 Feb 2011 17:18:17 +0000 (18:18 +0100)]
Speed up the oggdec filter and avoid wasting tons of memory.
Calls to ov_read appear to return at most 4K, no matter how much data
was requested. We allocated 64K per output chunk, so 60K of that space
is wasted. On the other hand we need large output buffers in order to
not sacrifice performance when para_filter decodes to stdout.
Fix this flaw by increasing the oggdec output buffer size from 64K to
640K, calling ov_read() until the output buffer is full or there is
nothing left to read, and then reallocating the buffer to the amount
of bytes actually read.
Assuming CD audio, the 640K output buffer size roughly matches
the decoded size of the 32K input buffer used by the stdin task,
so each input buffer corresponds roughly to one output buffer. The
patched version performs almost identically to the oggdec reference
implementation while previous versions were up to a factor of 2 slower.
Andre Noll [Mon, 17 Jan 2011 07:32:52 +0000 (08:32 +0100)]
oggdec: Replace stream start delay by minimum input queue size.
Waiting 300ms at stream start is both ugly and unnecessary if playback
does not start in the middle of the stream. This patch removes the
->stream_start member of struct private_oggdec_data and delays plaback
only if ov_read returns OV_HOLE, i.e. if streaming does not start at
the beginning of the file.
This delay is enforced by setting the minimal input queue size.
Andre Noll [Mon, 17 Jan 2011 07:24:37 +0000 (08:24 +0100)]
ogg_afh: Compute chunk time more accurately.
The chunk table is constructed so that each chunk corresponds to
frames_per_chunk samples as determined by the granule position of
the ogg page. Use this exact value for computing the duration of a
chunk rather than the avaerage num_frames / num_chunks.
Andre Noll [Tue, 18 Jan 2011 21:36:32 +0000 (22:36 +0100)]
gui: Don't exit without shutting down curses on config reload.
Currently, if a config file containing errors is being reloaded,
gui_cmdline_parser_ext() calls exit() which leaves the terminal
in an unusable state because para_gui had no chance to call
endwin() in order to reset the terminal.
Fix this flaw by instructing gengetopt to generate code that does
not exit on errors. We can still tell that the command line or the
config file contained errors by looking at the return value of the
various parsers.
Andre Noll [Mon, 6 Dec 2010 22:05:28 +0000 (23:05 +0100)]
client: Kill superfluous label "err".
The position of this label is identical to the "out" label, and "out"
is more to the point as we jump there not only in case of an error. So
jump always to "out" and remove the "err" label.
Andre Noll [Sun, 21 Nov 2010 20:48:42 +0000 (21:48 +0100)]
color: Simplify color error handling.
We exit on errors anyway, so get rid of the return value of
color_parse() and daemon_set_log_color() and abort immediately rather
than returning -1. Add the familiar "_or_die" suffix to these functions
to make it clear that no error handling is necessary in the caller.
Andre Noll [Sun, 28 Nov 2010 21:43:45 +0000 (22:43 +0100)]
fecdec: Use a fixed buffer pool size of 64K.
With the new variable sized FEC slices, it may happen that the
number of bytes per slice of the first FEC group is very small. It is
therefore no longer appropriate to base the size of the buffer pool
on this quantity. It happened to be much too small (< 1000 bytes)
for one aac file which caused the fecdec filter to abort early due
to a full buffer pool.
This patch uses a fixed buffer pool size of 64K for the fecdec filter,
which ought to be enough for everybody.
Andre Noll [Sun, 28 Nov 2010 21:32:13 +0000 (22:32 +0100)]
write_common: Don't abort if btr_exec_up() failed.
btr_exec_up() failure is unusual but possible if the upper btr node dies just in
the right moment. It happened for an aac file due to another bug in the fecdec
filter (fixed in a subsequent patch) which caused the fecdec and hence the aacdec
btr nodes to unregister themselves due to a full buffer tree pool.
So replace the assertion by a fat error message. This sets the sample rate,
channel count and the sample format to zero which makes the writer unregister
itsself. This is better than aborting.
Andre Noll [Mon, 1 Nov 2010 15:30:22 +0000 (16:30 +0100)]
vss: Avoid large FEC parameters for the DCCP transport.
Now that for DCCP streams the audio file header is sent only once at client
connect time, we can go one step further and send the header as its own FEC
group. Then all subsequent FEC groups contain data slices only, hence the
maximal required size for a FEC group reduces from
header_size + largest_chunk_size
to
max(header_size, largest_chunk_size)
This patch introduces a new helper function need_data_slices() which returns
false only at the beginning of a DCCP stream. In this case FEC group 0 consists
of the header only and an arbitrary time interval of 200ms is used for this
group.
Andre Noll [Sat, 6 Nov 2010 10:43:59 +0000 (11:43 +0100)]
osx_write: Make osx_write_open() a no-op.
Move the allocation of the private_osx_write_data struct to core_audio_init()
and adjust the the check whether core audio has been initialized accordingly.
Andre Noll [Fri, 5 Nov 2010 18:28:24 +0000 (19:28 +0100)]
file_writer: Make file_write_open() a no-op.
Move the allocation of the private_file_write_data struct to ->post_select()
and adjust the the check whether the output file has already been opened
accordingly.
If the output file has just been opened, pfwd->fd will never be set in
the write fd set of the scheduler, so we can skip this test.
Andre Noll [Fri, 5 Nov 2010 18:07:39 +0000 (19:07 +0100)]
alsa: Make alsa_open() a no-op.
Move the allocation of the private_alsa_write_data struct to
->post_select() and adjust the the check whether alsa has
been initialialized accordingly.
Andre Noll [Fri, 5 Nov 2010 07:45:20 +0000 (08:45 +0100)]
writers: Unify ->pre_select().
Always treat the easy cases "nothing to do", "error", and "not yet initialized"
first. For the alsa writer, this change fixes two minor bugs:
First, if data is available but alsa has not yet been initialized, we return
from ->pre_select() without setting a delay. This is wrong, we should init
the alsa handle ASAP in this case.
Second, on errors we wait 20ms which is both ugly and unnecessary.
Requesting a minimal delay is the right thing to do here as well.
Andre Noll [Thu, 4 Nov 2010 22:34:33 +0000 (23:34 +0100)]
file_write: Fix NULL pointer dereference.
register_writer_node() is the only caller of the ->open method for paraslash
writers. It does not check its return value, which is OK for alsa, oss and osx
as these writer's ->open method always succeeds. However, the ->open() method
of the file writer may fail, for example because the output file could not be
opened. This error will be ignored and the writer node task is registered as
usual with ->fd being initialized to zero.
Fix this bug by splitting the ->open method of the file writer into the part which
merely allocates the private_file_write_data structure, hence always succeeds,
and the part which actually opens the output file. This second part is called later
from ->post_select as soon as there is data available to be written.
After this patch the ->open methods of all writers always succeed and we
may change its return value to void which is done in the next patch.
Andre Noll [Thu, 4 Nov 2010 08:12:57 +0000 (09:12 +0100)]
write_common: Remove check which is never true.
All writers have a config parser. This check was bogus anyway: If there was a writer
without config parser and we call it without arguments (i.e. "c" is NULL), this would lead
to a NULL pointer dereference.
Andre Noll [Thu, 4 Nov 2010 07:59:57 +0000 (08:59 +0100)]
write: Simplify config parsers.
These functions all call the gengetopt parser which aborts on errors. It is therefore
pointless to check the return value. Document this fact and make it explicit by renaming
->parse_config of struct writer to ->parse_config_or_die().
Andre Noll [Sun, 10 Oct 2010 16:51:17 +0000 (18:51 +0200)]
Minor makesock() fixes.
On getaddrinfo() or setsockopt() errors, we leak the flowopts and/or
the local/remote address info structure. Fix this by jumping to the
cleanup section at the bottom of makesock() rather than returning
early without cleaning up.
Moreover, we can not rely on errno containing a valid error code in the
cleanup part of the function because flowopt_cleanup() calls free()
which usually resets errno. So use the error code provided via "rc"
if possible and fall back to the new -E_MAKESOCK if rc is non-negative
to make sure we return a negative value on errors.
Andre Noll [Sun, 12 Sep 2010 21:30:59 +0000 (23:30 +0200)]
Make build of para_server optional.
para_server is the only executables which requires libosl, so do not consider
it a fatal error if libosl could not be located. This allows to build the
paraslash package for example on client-only machines which do not need
para_server anyway.
Andre Noll [Wed, 6 Oct 2010 22:08:31 +0000 (00:08 +0200)]
udp: Remove chunk queueing.
This was broken beyond repair for several reasons:
First of all, not each write to a UDP socket with no listener on
the remote leads to a write error. For a local connection on Linux,
only each second write yields ECONNREFUSED while all others seem to
succeed. So we would only queue each second FEC slice which is next
to useless.
Secondly, only buffer references are stored in the chunk queue, the
buffer contents are not copied for performance reasons. This works fine
if the buffers point to the read-only memory map of the audio file,
which is the case for the HTTP sender, but not for the UDP sender.
In fact, for UDP the buffer is always the same, namely ->enc_buf of
the FEC client struct for the UDP target.
Finally, it is not clear that the buffer references stored in the chunk
queue are still valid when the chunk queue is emptied by sending the
buffers since vss.c might have realloced the enc_buf.
Andre Noll [Wed, 6 Oct 2010 21:38:17 +0000 (23:38 +0200)]
udp: Also send the EOF packet when a target is removed.
This notifies the client of the EOF condition and causes it to remove
its buffer tree. Without this patch, the client keeps listening
which can lead to problems when the target is added later while a
different audio file is being streamed.
Also there is no point to check twice whether the chunk queue exists.
Andre Noll [Wed, 6 Oct 2010 21:23:19 +0000 (23:23 +0200)]
Remove unused field "sc" of struct udp_target.
All functions get/pass a struct sender_client which contains a struct
udp_target as its private data, but we never need to get the struct
sender_client from a struct udp_target. So the sc pointer is unnecessary.
Andre Noll [Wed, 6 Oct 2010 20:56:23 +0000 (22:56 +0200)]
udp_send: Add/remove the udp socket fd only once.
Currently, we remove this fd from the close-on-fork list in
udp_close_target() and re-add it in udp_init_session(). This is wrong
because we want the fd being closed in the command handlers also if
the child process for the command is spawned while the udp sender
is inactive.
So add/delete the fd when the udp target is added/removed rather than
on a per session basis.
Andre Noll [Mon, 16 Aug 2010 07:29:59 +0000 (09:29 +0200)]
vss: Avoid potential double free of FEC parameters.
If an error occurs in initialize_fec_client() we free the FEC parameter
structure but do not invalidate it. It's both easier and safer to
free this struct just before allocating it.