Devious Fish
Building & Installing pianod

Building & Installing pianod

You will need a C++11 or better compiler. C++ dependencies may need to be compiled with the same compiler; see note under troubleshooting.

Dependencies

  • libffmpeg, gstreamer or AVFoundation (OS X 10.7+)
  • libao or libsdl for use with ffmpeg
  • gcrypt (Optional, for Pandora)
  • cURL (Optional, for Pandora)
  • gnutls, mbed TLS, OpenSSL or OS X/SecureTransport (to support TLS in cURL, and for secure pianod connections)
  • mbed TLS (Optional, alternative to gcrypt/gnutls for Pandora).
  • json-c (Optional, for Pandora)
  • taglib (Recommended for filesystem/local file source with ffmpeg; C++)
  • zlib, gzstream (Optional, for compressing data files)
  • libpiano, rapidxml, etc. (Included; see COPYING for license information.)
  • UTF–8 console/locale for best results

libav support has been deprecated. Older versions will work, and new versions may even compile. However, similar-but-different APIs makes libav hazardous and it may not work correctly. The divergence of APIs coupled with poor documentation and support has lead to discontinuing support.

All dependencies can be downloaded and set up manually, but most systems have package managers that streamline this process. On OS X, see MacPorts; on Ubuntu or Debian, see apt-get; Gentoo, emerge; Fedora and RedHat, RPM; FreeBSD, try pkg or pkg_add. For other Linux distributions, check Wikipedia’s list to determine the packaging system used.

Features supported by output devices
Feature libao libsdl avdevices AVFoundation gstreamer
Crossfading Yes No Yes Yes Yes
Pandora Yes Yes Yes Yes Yes
Filesystem Yes Yes Yes Yes Yes
Tone generator Yes Yes Yes No Yes
Source dependencies
Package Pandora Filesystem Tonegen
gcrypt Required No No
cURL w/ TLS support Required No No
json-c Required No No
taglib No Optional† No
gzstream No Recommended Optional

† Provides better results than ffmpeg and gstreamer metadata readers; does not improve on AVFoundation. AVFoundation is found on OS X 10.7+.

Compilers supported
Compiler†† Incapable Capable
Clang (Apple LLVM) ≤ 3.8 ≥ 6.0
gcc (GNU compiler collection) < 4.8 ≥ 4.8.4

†† Viability of other compilers is unknown.

Building

If you have all of the dependencies listed above, use:

./configure && make

If you’d like to use the unit test to verify it works:

make check

You can run the software directly from the source directory now:

./src/pianod -c "$PWD/html"

To install it issue:

sudo make install

On startup, pianod reads your ~/.config/pianod2/startscript. A sample is found in the contrib directory.

Automatic Build Configuration

If you let configure make the choices, you will get the best supported set of features with the least redundancy:

  • Communication: Line and HTTP ports, and HTTPS support is available.
  • Media engine: gstreamer, ifnotfound ffmpeg, ifnotfound AVFoundation.
  • Audio output: One audio output scheme.
    • For ffmpeg: libavdevices and libao, ifnotfound libsdl.
    • For AVFoundation, whatever it provides.
  • All sources, subject to dependencies. For AVFoundation, only filesystem is supported.
  • File compression will be used, if available.

Manual Build Configuration

Configuring the build has some options:

--disable-sanity (default is --enable-sanity)
When enabled, configure expects a media engine and at least one output or it fails with an error. Disabling sanity reduces this to a warning.
--enable-debug (default is --disable-debug)
When enabled, turns on assertions (self-checks in the software), some additional logging and debug compile (-g). These enlarge and slow the code down slightly, but make debugging much, much easier.
--enable-compression or --disable-compression
When enabled, pianod stores persisted data in compressed form. If omitted, compression is used if required libraries are available at configuration time.
--enable-shadow[=option] or --disable-shadow
When enabled (and it also needs to be enabled with a command-line switch), pianod will allow login with system usernames and passwords, creating pianod accounts on-demand when necessary. option may be pam or passwd to force a validation method.
--with-engine=package
Chooses a media engine package. Packages may be: gstreamer, avfoundation (OS X), or ffmpeg.
--with-tls[=package] or --without-tls
Forces inclusion or exclusion of TLS support, or chooses a specific TLS package to use. Packages may be: gnutls, mbedtls, openssl, or securetransport.
--with-taglib or --without-taglib
Forces inclusion or exclusion taglib for reading ID3 data for the filesystem source. If omitted, taglib is included if the ffmpeg media engine is in use and the library is available at configuration time.
--with-pandora or --without-pandora
Forces inclusion or exclusion of Pandora. If omitted, Pandora is included if its dependencies are available.
--with-tonegenerator or --without-tonegenerator
Forces inclusion or exclusion of the tone generator. The tone generator has a 1KHz and 440Hz tones which could be used for setting levels, and is helpful for troubleshooting and testing, but generally it’s not needed. If omitted, the tone generator is included if either libao or libsdl outputs are available. It is not compatible with AVFoundation for output.
--with-filesystem or --without-filesystem
Forces inclusion or exclusion of the filesystem source, which uses media on a local disk or mounted network filesystem.
--with-libao or --without-libao; --with-libsdl or --without-libsdl
Forces inclusion or exclusion of libao or libsdl, two different output libraries. Both work with all sources for ffmpeg, or for the tone generator when using AVFoundation. However, **libsdl does not support crossfading**. Automatic configuration chooses one; you may choose more, or 0 if you disable sanity.
--with-libavdevices or --without-libavdevices
The third output library. On Linux, there is a good chance you will need to room reconfigure driver alsa id experimental. Test this with the console; after confirming it’s what you need, you can add it to your startscript.

Mac OS X

You’ll need to install Xcode developer tools found your installation DVD or downloaded from the App store or developer.apple.com. Tools are free. Alternately, on newer OS X versions, open terminal and enter “cc”. A window will pop up allowing you to install the command-line tools, which are much smaller than all of Xcode.

Once the developer tools are installed, you can easily install dependencies using MacPorts. The filesystem source is viable on OS X 10.7+ without any dependencies.

With clang (Apple’s compiler) you will need to set the compiler standard for Objective C:

OBJCXXFLAGS=-std=c++11
./configure

If ./configure fails because the compiler doesn’t support C++11, you will need to install a C++ compiler. gcc5 has been tested:

sudo port install gcc5
export CC=gcc-mp-5
export CXX=g++-mp-5
./configure

To install the dependencies:

sudo port -v install libgcrypt gnutls json-c

To use ffmpeg for audio (required on 10.6 or earlier; optional later):

sudo port -v install libao ffmpeg taglib

To create pianod from a tarball, using MacPorts for dependencies, you will also need these environment variables before invoking configure:

export CPPFLAGS=-I/opt/local/include
export LDFLAGS=-L/opt/local/lib

The tarball build will install to /usr/local/bin.

Linux

If launching as root, use ‘pianod -n pi’ to run pianod as the pi’s starter user.

To open audio devices, a process usually needs to belong to the audio group:

usermod --append --groups audio _username_

When launching as root (such as from init.d, systemd or /etc/rc.d files), specify the user to run as:

pianod -r _username_

Build Troubleshooting

Messages may vary slightly by system and compiler.

General Troubles

Mixing C++ Compilers

Linking between C++ code built with different compilers can cause woes. I encountered taglib corrupting the stack; build issues were confirmed via a simple test program (just read and get artist). If you run into troubles, rebuild the C++ dependencies yourself using the same C++11 compiler you are building pianod with.

Furthermore, mixing C++ standards creates linking issues. For example, with libraries compiled for Gnu++11 and pianod2 for C++11, they won’t link. I suppose this is preferable to generating a non-working executable, but it can be a nuisance to deal with. The solution is the same: rebuild the dependencies and pianod2 using the identical compiler and standards mode.

Expected Warnings

/usr/local/include/gcrypt.h:1401: warning: ‘gcry_ac_data_read_cb_t’ is deprecated
Ignore. There are typically several of these, all from gcrypt.h with the prefix gcry_.

Rare Mac Troubles

pianod and all libraries must be built with the same architecture. If the dependency libraries are installed but mismatched, you may override the default with export CFLAGS="-arch x86_64" or export CFLAGS="-arch i386".

TLS Configuration

To use transport layer encryption, you must provide certificate and key files. The script create-pianod-tls-cert in the contrib directory will create the necessary files, the certificate issued by a bogus CA. The certificate is for the current hostname, or another host specified as the first parameter.

Reporting Bugs

Report bugs to perette@deviousfish.com

Reporting a crash or hang

Providing useful and accurate information will help track down issues and get them fixed. If nobody reports things, they will stay broken; some bugs only show up on some operating systems or with certain hardware/software configurations. (Although these are written for pianod2, providing the details outlined here will be helpful to most open-source developers.)

First off, don’t rush to report problems; instead, study it and collect details. Vague and unclear reports may not get fixed. So, can you reproduce it? If so, what makes it happen? Does doing it always make it happen, or is it intermittent? Collect a stack dump if you can (see below).

When you’re ready, submit an e-mail to perette@deviousfish.com with:

  • Your notes on what causes it
  • A copy of config.log from the pianod build directory (created when you run “./configure” before building pianod).
  • Alternately, pianod version (pianod -v) and build details, operating system, output of uname -a, and kind of hardware you’re working on
  • A diagnostic report or stack dump of the crash or hang

If you’re experiencing crashes, it would be helpful to capture a snapshot of what’s going on. Thankfully, there are tools to do this.

Capturing a Diagnostics on a Mac

On application crash, a Mac automatically captures and logs the details. Look in ~/Library/Logs/DiagnosticReports; the files will be named pianod_year_mo_da_number_hostname.crash. Attach them to your report.

You can generate a diagnostic report for a stuck process with kill -ABRT <pid>

If you can’t see the Library folder in your home folder, open Finder and Go→Go to Folder and type in/cut-and-paste the above folder name. Find the report in there and mail it in.

Building for debugging

If you don’t know how to do this, you may skip this step—but if you compiled and installed your own software, then building a debug-friendly variant is straightforward and makes troubleshooting much easier. Please do it if you can. pianod’s configure script has an –enable-debug option; simply ./configure --enable-debug then make again, and make install if you want to install it.

Capturing a Stack Dump

To capture a stack dump, use gdb, the GNU debugger.

For a hang, attach to an existing process:

ps x | grep pianod
50942   ??  S      8:50.40 /usr/local/bin/pianod
gdb -p 50942

For crashes, start pianod from gdb:

gdb /usr/local/bin/pianod _add your normal pianod options here_
run

When pianod crashes, gdb will report this and give you a command prompt. (If you want to capture a hang this way, press control-C when pianod has hung.)

Now, in the gdb console, do the following: (For more on gdb, see the GDB Cheat sheet.)

info args
info locals
info variables
info threads
info signals
thread apply all where full

Cut-and-paste from the gdb window to your bug report and mail it in.

Security Implications

As with all network server applications, pianod should be considered a security risk out of paranoia: there may be undiscovered bugs or exploits in pianod or any of the libraries on which it is built. To minimize risk should it be compromised, pianod should be run as a unique, low- or non-privileged user account.

Passwords

User passwords are stored using OS-provided, one-way encryption with salt. They cannot be decrypted, although dictionary/brute-force attacks apply as they do to the underlying operating system.

Music service passwords for “remembered” sources, however, are stored in the user data file using a custom symetric encryption algorithm using a per-user key, and are easily decrypted. Users should use a unique password for any music password they register.

For these reasons, limiting access to the user data file (by chmoding the directory, or running pianod with a 077 umask) is recommended.

HTTP Server

The HTTP server does not create files. If a directory is requested, its index.html is provided (or a 404 occurs); directory contents are not listed. Requests to higher-level directories (http://myserver/../../../Documents/myprivatething.txt) are rejected, preventing download of arbitrary data for simple cases.

However, the server follows but does not analyze symbolic links, so a well-placed symbolic link within the client directory (such as myexploit -> /) could open a security hole subsequently used to retrieve arbitrary data. Following a break in, the client directory should be reviewed (or deleted and reinstalled) to ensure no such holes have been created by the intruder.

Starting pianod2

Configuration files location

pianod stores several files in a configuration directory, the configuration of which is set by:

  • -d directory command-line option, with /pianod2 appended.
  • $XDG_CONFIG_HOME/pianod2 (if XDG_CONFIG_HOME is set)
  • $HOME/.config/pianod2 (if HOME is set and running as root)
  • $(sysconfdir)/pianod2 (if running as root). sysconfdir is set at compile time by the configure script; a tarball install will use /opt/local/etc, MacPorts uses /opt/local/etc, and /etc is common when installing from a package manager.
  • ./pianod2 (if not running as root).

Configuration files

On startup, pianod2 reads its startscript, executing the command therein as a pianod administrator. The file uses the same syntax and commands as the socket interface. A sample startscript is provided in the contrib directory.

pianod also has a user data file, passwd. If the file does not exist, a single user admin (password admin) is created. This user is persisted, so once you create your own administrator account be sure to delete admin.

Launching at boot or login

Unlike older UNIX daemons, pianod does not use fork(2)/exec(2) or daemon(3) on startup. Supplied sample configuration files expect pianod to be installed in /usr/local/bin; if this is not right you will need to revise the files when installing.

If pianod is started as root, after establishing the listener socket, pianod drops root privileges and takes on a user persona, by default the user ‘nobody’. It also adopts the user’s groups. To allow data to be persisted, the configuration directory is (re)assigned to this user. The user can be selected via -n; -n root will allow pianod to retain root privileges. Using -n root may be a useful troubleshooting tool, but running any network-based service as root is risky.

The -g option can be used to specify a comma-separated list of groups instead of nobody’s groups. Some platforms have a group music or audio to which users must belong to be able to open audio ports.

pianod must not be installed setuid. Using a combination of -d and -n options, a malicious user could arbitrarily reassign file ownership.

On OS X:

  • Included in contrib is an example com.deviousfish.pianod.plist.
  • When installing the file, be sure to review the file as there are some file paths and user names in it.
  • To launch pianod upon login of a particular user, install the file in that user’s Library/LaunchAgents directory.
  • To launch pianod at boot, place it in the system’s /Library/LaunchDaemons directory. Edit the file to enable the UserName key, setting it to run as your desired user.

On Linux with systemd(8):

  • Included in contrib is pianod.service for systems using systemd(1).
  • To launch pianod at boot, place it in /usr/local/lib/systemd/system and put the startscript in /etc/pianod/startscript.
  • To launch pianod at login, install the file in the user’s .config/systemd directory [Need verification]. You will want to remove User=nobody and -i /etc/pianod/startscript from the [Service] section of the file.
  • After installing the file run “systemctl start pianod” to start the daemon and “systemctl enable pianod” to enable it to start on boot.
  • The sample expects pianod to be installed in /usr/sbin; set your configure options or modify the start file as needed.

On systems using /etc/init.d scripts:

  • Included in contrib is pianod.raspian.init.
  • The script is for the Raspbian distribution but can be modified as needed.
  • The sample expects pianod to be installed in /usr/sbin; set your configure options or modify the start file as needed.

For systems that use init without /etc/init.d, you’ll need to edit the inittab file. Add this to /etc/inittab:

pd:23:respawn:su - username -c /usr/local/bin/pianod

On Windows, you are on your own.

Start Options

See the pianod(1) manual page for the full list of command line options.