Coder Social home page Coder Social logo

nqptp's Introduction

NQPTP – Not Quite PTP

nqptp is a daemon that monitors timing data from PTP clocks it sees on ports 319 and 320. It maintains records for one clock, identified by its Clock ID.

It is a companion application to Shairport Sync and provides timing information for AirPlay 2 operation.

Installation

This guide is for recent Linux and FreeBSD systems.

As usual, you should first ensure everything is up to date.

Please use git!

As you probably know, you can download the repository in two ways: (1) using git to clone it -- recommended -- or (2) downloading the repository as a ZIP archive. Please use the git method. The reason it that when you use git, the build process can incorporate the git build information in the version string you get when you execute the command $ nqptp -V. This will be very useful for identifying the exact build if you are making comments or bug reports. Here is an example:

Version with git build information:
Version: 1.1-dev-24-g0c00a79. Shared Memory Interface Version: 5.

Version without git build information:
Version: 1.1-dev. Shared Memory Interface Version: 5.

Remove Old Service Files

Linux

If you are updating from version 1.2.4 or earlier in Linux, remove the service file nqptp.service from the directories /lib/systemd/system and /usr/local/lib/systemd/system (you'll need superuser privileges):

# rm /lib/systemd/system/nqptp.service
# rm /usr/local/lib/systemd/system/nqptp.service
# systemctl daemon-reload

Don't worry if you get a message stating that the files doesn't exist -- no harm done.

FreeBSD

At present, there is no need to remove the old startup script as (in FreeBSD only) it is always replaced during the # make install step.

The startup script is at /usr/local/etc/rc.d/nqptp.

Build and Install

Note that you will need superuser privileges to install, enable and start the daemon.

Linux

$ git clone https://github.com/mikebrady/nqptp.git
$ cd nqptp
$ autoreconf -fi
$ ./configure --with-systemd-startup
$ make
# make install

FreeBSD

$ git clone https://github.com/mikebrady/nqptp.git
$ cd nqptp
$ autoreconf -fi
$ ./configure --with-freebsd-startup
$ make
# make install

The make install installs a startup script as requested. You should enable it and start it in the normal way:

First Install or Update?

Linux

First Install

If you are installing nqptp for the first time, enable it and start it:

# systemctl enable nqptp
# systemctl start nqptp

If Shairport Sync is already running, you should restart it after starting nqptp:

# systemctl restart shairport-sync
Update

If you are updating an existing installation of nqptp, after installing it you should restart it. You should then also restart Shairport Sync:

# systemctl restart nqptp
# systemctl restart shairport-sync

FreeBSD

First Install

If you are installing nqptp for the first time, add an automatic startup entry for it in /etc/rc.local and start it:

  1. Edit /etc/rc.conf and add the following line:
    nqptp_enable="YES"
    
  2. When you have finished editing /etc/rc.conf, you can start nqptp from the command line:
    # service nqptp start
    

If Shairport Sync is already running, you should you restart it after starting nqptp:

# service shairport_sync restart
Update

If you are updating an existing installation of nqptp, after installing it you should restart it. You should then also restart Shairport Sync:

# service nqptp restart
# service shairport_sync restart

Firewall

If your system runs a firewall, ensure that ports 319 and 320 are open for UDP traffic in both directions. These ports are associated with PTP service and may be referred to as "PTP" in firewall rules. For example, the following would open ports 319 and 320 for Fedora, which uses firewalld:

# firewall-cmd --add-service=ptp
# firewall-cmd --permanent --add-service=ptp # make it permanent across reboots

Notes

The nqptp application requires exclusive access to ports 319 and 320. This means that it can not coexist with any other user of those ports, such as full PTP service daemons. In Linux, nqptp runs as a low-priviliged user but is given special access to ports 319 and 320 using systemd AmbientCapabilities. In FreeBSD, nqptp runs as root user.

Programming Notes

Commands and status information are sent to nqptp over port 9000.

Information about the PTP clock is provided via a POSIX shared memory interface.

Here are details of the interface:

typedef struct {
  uint64_t master_clock_id;             // the current master clock
  uint64_t local_time;                  // the time when the offset was calculated
  uint64_t local_to_master_time_offset; // add this to the local time to get master clock time
  uint64_t master_clock_start_time;     // this is when the master clock became master
} shm_structure_set;

// The actual interface comprises a shared memory region of type struct shm_structure.
// This comprises two records of type shm_structure_set. 
// The secondary record is written strictly after all writes to the main record are
// complete. This is ensured using the __sync_synchronize() construct.
// The reader should ensure that both copies match for a read to be valid.
// For safety, the secondary record should be read strictly after the first.

struct shm_structure {
  uint16_t version; // check this is equal to NQPTP_SHM_STRUCTURES_VERSION
  shm_structure_set main;
  shm_structure_set secondary;
};

Clock records that are not updated for a period are deleted.

Known Issues

  • nqptp has not been thoroughly checked or audited for security issues. Note that it runs in root mode on FreeBSD.
  • It's probably buggy!
  • nqptp does not take advantage of hardware timestamping.

Things Can Change

The nqptp daemon is under active development and, consequently, everything here can change, possibly very radically.

NQPTP is not PTP!

nqptp uses just a part of the IEEE 1588-2008 protocol. It is not a PTP clock.

nqptp's People

Contributors

fwcd avatar heitbaum avatar hifiberry avatar hs-yeah avatar klemensn avatar mikebrady avatar qerub avatar tsbernar avatar weidav avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nqptp's Issues

Tags for versionning

Tags with fixed software number would be good, as well as what you do on shairport-sync. I created a Yocto layer for shairport and using a fixed version number of nqptp would be cleaner, instead of just a commit hash.
In addition, you could link shairport and nqptp versions together.

Btw, thanks for the projects !!

systemd

is there any way to tell make not to copy the systemd service to the system?

is creating an ebuild for gentoo, but make is trying to copy the service file and that's causing me problems.

>>> Install net-misc/nqptp-1.1.0 into /var/tmp/portage/net-misc/nqptp-1.1.0/image
make -j4 DESTDIR=/var/tmp/portage/net-misc/nqptp-1.1.0/image install 
make[1]: Entering directory '/var/tmp/portage/net-misc/nqptp-1.1.0/work/nqptp-1.1.0'
make[1]: Nothing to be done for 'install-data-am'.
 /bin/mkdir -p '/var/tmp/portage/net-misc/nqptp-1.1.0/image/usr/local/bin'
  /usr/lib/portage/python3.8/ebuild-helpers/xattr/install -c nqptp '/var/tmp/portage/net-misc/nqptp-1.1.0/image/usr/local/bin'
make  install-exec-hook
make[2]: Entering directory '/var/tmp/portage/net-misc/nqptp-1.1.0/work/nqptp-1.1.0'
[ -e /lib/systemd/system ] || mkdir -p /lib/systemd/system
cp nqptp.service /lib/systemd/system
 * ACCESS DENIED:  open_wr:      /lib/systemd/system/nqptp.service
cp: cannot create regular file '/lib/systemd/system/nqptp.service': Permission denied
make[2]: *** [Makefile:818: install-exec-hook] Error 1
make[2]: Leaving directory '/var/tmp/portage/net-misc/nqptp-1.1.0/work/nqptp-1.1.0'
make[1]: *** [Makefile:738: install-exec-am] Error 2
make[1]: Leaving directory '/var/tmp/portage/net-misc/nqptp-1.1.0/work/nqptp-1.1.0'

Suggestion: use DynamicUser=yes in nqptp.service

Hi @mikebrady,

I'm using nqptp/shairport-sync as part of a media distribution for the raspberry pi, and it's quite inconvenient for me to have to add and maintain a new nqptp user and group for the purpose of privilege separation. The lazy bastard that I am uses DynamicUser=yes in the service file instead of setting user and group to nqptp.
And I found out that you actually get additional security benefits from that, as the service is essentially sandboxed from the system, check out Lennart's little howto.
Now I don't know if this has actual benefits in the case of nqptp, but I'm definitely going to play with this some more for other exposed services, and maybe it provides inspiration for you as well.

All best, Jörn

Limitation of MAX_CLOCKS 32 required?

When adding more than 16 Airplay 2 speakers to a group (around 14 of which were shairport-sync), the nqptp services started dying with the log message fatal error: Clock tables full!.

Just grepping a little through the code, it looks like it's caused by #define MAX_CLOCKS 32, which at face value would look like it should set a maximum number of devices to 32?

I'm not sure of the real-world consequences (and I haven't adjusted all output to match their audio backend latencies etc), but to get past this, I just did a quick sed -i -e 's/define MAX_CLOCKS 32/define MAX_CLOCKS 256/g' nqptp-shm-structures.h and rebuilt nqptp, and I had no more complaints from nqptp going to 21 devices. After removing a non-wired Airplay 2 speaker from the group, shairport-sync also stopped logging most complaints of large positive/negative syncs, lead times and too small packets.

This leaves me wondering whether it needs to be 32, could be user-configurable or just set as higher by default? It's not clear to me what the drawbacks are by doing what I did but it made me wonder :)

Tags corresponding to release notes

As the packager of nqptp for nixpkgs, it would be really helpful if you could add a git tag corresponding to the development release notes. It is our convention to use the date of the commit when a tag does not exist. Thus the nixpkgs version displayed does not match well with your (fantastic!) release notes.

Possible missing $(DESTDIR) in Makefile.am

Sorry if this is a stupid question, I'm not really comfortable with Make/Automake (and, honestly, the entire stack) yet.

I'm currently trying to update some dependencies in duhow/xiaoai-patch and, because of that, came across the following line in Makefile.am:

install-exec-hook:
if BUILD_FOR_LINUX
# NQPTP runs as user/group nqptp/nqptp on Linux and uses setcap to access ports 319 and 320
	setcap 'cap_net_bind_service=+ep' $(bindir)/nqptp

In #7, the DESTDIR variable was added, and I believe that variable is also necessary for the call to setcap. If left unedited, running Make will try to modify /usr/bin/nqptp instead of the one in the folder set by DESTDIR.

This is how I was able to fix my build:

install-exec-hook:
if BUILD_FOR_LINUX
# NQPTP runs as user/group nqptp/nqptp on Linux and uses setcap to access ports 319 and 320
	setcap 'cap_net_bind_service=+ep' $(DESTDIR)$(bindir)/nqptp

Is this correct? I can also submit a PR, but I thought I'd ask first.

run nqptp as non root

Hi,
thank you for your excellent work.

Today I installed shairport-sync with AirPlay2 support.
According the documentation, nqptp (must) run as root.
Why is this?
I assume this is due to listening to ports < 1024.

After creation of a user / group nqptp and patching nqptp.service (replace root by nqptp) and running this command:

setcap 'cap_net_bind_service=+ep' /usr/local/bin/nqptp

nqptp runs as user nqptp and I was able to stream from my MBP2020 macOS12 to shairport-sync.

udp        0      0 0.0.0.0:9000            0.0.0.0:*                           2702/nqptp           off (0.00/0/0)
udp        0      0 0.0.0.0:319             0.0.0.0:*                           2702/nqptp           off (0.00/0/0)
udp        0      0 0.0.0.0:320             0.0.0.0:*                           2702/nqptp           off (0.00/0/0)
udp6       0      0 :::9000                 :::*                                2702/nqptp           off (0.00/0/0)
udp6       0      0 :::319                  :::*                                2702/nqptp           off (0.00/0/0)
udp6       0      0 :::320                  :::*                                2702/nqptp           off (0.00/0/0)

nqptp     2702  1.8  0.0   2212   460 ?        SLs  19:20   0:13 /usr/local/bin/nqptp`

I am not sure how I can verify that nqptp is definitely working, but I observed that when nqptp is stopped that I can not stream from iPhone nor from macOS. If I then start nqptp then it's possible to stream from macOS12. So I assume nqptp is working while not running as root.

Any other hints to verify functionality running nqptp as non root?

TIA, T

edit: streaming from iOS is also not possible when nqptp was stopped. This seems to be expected.

Suggestion: Bind NQPTP_CONTROL_PORT to localhost instead of NULL

Hello,
from what I understand from the code of nqptp and shairport-sync, nqptp listens as Server to Port 9000 and shairport-sync talks to port 9000.

Lets assume that nqptp and shaiport-sync run always on the same host/system/container - but I am not sure if this assumption is always valid - then it would be ideal, if nqptp would listen only on localhost instead on any interface.

I tested this successfully with very few quick hack changes to nqptp.c and nqptp-utilities(.c | .h).

unable to listen on IPv4 port 319

nqptp -v returns following error:

0.000030945 "nqptp.c:158" startup
0.001729555 "nqptp-utilities.c:92" *fatal error: unable to listen on IPv4 port 319. The error is: "Address already in use". Daemon must run as root. Or is a separate PTP daemon running?
0.000077685 "nqptp.c:107" goodbye

It runs as root and is the only process listening to 319. I'm not aware of any other PTP daemon on my system. Any idea how can I fix it?

Unable to listen on port 319

Sorry, I'v been running in another problem.

Everything was running before the update.
I checked that there is no nqptp service running under /lib/systemd/system

Now I get:

root@shairport-sync:~# nqptp -v
0.000739953 "nqptp.c:168" Version: 1.2.4, smi10. Clock ID: "d83addfffe4340e6".
0.001290425 "nqptp-utilities.c:109" *fatal error: unable to listen on port 319. The error is: "Address already in use". NQPTP must run as root to access this port. Or is another PTP daemon -- possibly another instance on NQPTP -- running already?
0.000236928 "nqptp.c:114" goodbye

Question about Versioning

It's getting a bit confusing (to me at least!) as to which versions are being checked and in use.

So, I was going to try to use a git version of the semantic versioning system, initially on nqptp.

It follows that the program's version, as reported by the application itself, will be relatively fixed, e.g. 4.0-dev, but the build version will be available using the $ git describe --dirty command. The slight problem here is that if you are not using git to manage the sources (e.g. if you are downloading a .zip or .tar.gz` archive), then this won't be available.

So, my question is, are you all using git for this? Is it okay to proceed along these lines?

-bash: ./configure: No such file or directory

Hi,

I'm on a Raspberry and I try to update. When I type "./configure --with-systemd-startup" I get the message "-bash: ./configure: No such file or directory"

Did I do something wrong?

Thanks!

Container packaging

It is very convenient to use the shairport-sync daemon in a container.

Using nqptp alongside can be preferable for such setups.

This would require container packaging for the nqptp daemon.

ALSA Mixer Scaling of volume

Hello,

I am using an Orange PI with an Extension Board.

With the docker container in the latest version I got everything working. Current the hardware mixer does not properly work.

During startup I get this message:

0.000064708 "audio_alsa.c:940" *warning: The hardware mixer specified -- "LINEOUT volume" -- does not have a dB volume scale.
0.000624500 "audio_alsa.c:955" alsa: hardware mixer "LINEOUT volume" selected, with dB volume from -99999.990000 to 1.500000.

It seems like the calculations for the actual volume for the alsamixer seem to be not reliable with these upper and lower values:

0.000041500 "player.c:3528" player_volume_without_notification: volume mode is 1, airplay volume is -24.00, software_attenuation dB: 0.00, hardware_attenuation dB: -56999.35, muting is disabled.
0.000003709 "player.c:3528" player_volume_without_notification: volume mode is 1, airplay volume is -24.00, software_attenuation dB: 0.00, hardware_attenuation dB: -56999.35, muting is disabled.
0.000002000 "player.c:3528" player_volume_without_notification: volume mode is 1, airplay volume is -22.12, software_attenuation dB: 0.00, hardware_attenuation dB: -51374.26, muting is disabled.
0.000212458 "player.c:3528" player_volume_without_notification: volume mode is 1, airplay volume is -20.25, software_attenuation dB: 0.00, hardware_attenuation dB: -45749.18, muting is disabled.
0.000001166 "player.c:3528" player_volume_without_notification: volume mode is 1, airplay volume is -16.50, software_attenuation dB: 0.00, hardware_attenuation dB: -34499.01, muting is disabled.
0.000052708 "player.c:3528" player_volume_without_notification: volume mode is 1, airplay volume is -12.75, software_attenuation dB: 0.00, hardware_attenuation dB: -23248.85, muting is disabled.
0.000069333 "player.c:3528" player_volume_without_notification: volume mode is 1, airplay volume is -7.12, software_attenuation dB: 0.00, hardware_attenuation dB: -11873.68, muting is disabled.
0.000646125 "player.c:3528" player_volume_without_notification: volume mode is 1, airplay volume is -3.38, software_attenuation dB: 0.00, hardware_attenuation dB: -5623.58, muting is disabled.
0.000048666 "player.c:3528" player_volume_without_notification: volume mode is 1, airplay volume is 0.00, software_attenuation dB: 0.00, hardware_attenuation dB: 1.50, muting is disabled.

As these values are read from ALSA directly as I see, the following options right now

  1. use the vol_sw_only mode
  2. Adjust the volume code to use linear scale in the mixer from 0 to 100 for this strange min/max_db settings

alsa-info.txt
shairport-sync_hardware_mixer.log

Versioning

It's getting a bit confusing (to me at least!) as to which versions are being checked and in use.

So, I was going to try to use a git version of the semantic versioning system, initially on nqptp.

It follows that the program's version, as reported by the application itself, will be relatively fixed, e.g. 1.1-dev, but the build version will be available using the $ git describe --dirty command. The slight problem here is that if you are not using git to manage the sources (e.g. if you are downloading a .zip or .tar.gz archive), then this won't be available.

So, my question is, are you all using git for this? Is it okay to proceed along these lines?

Does not build from makedeb and makepkg

Similar to an issue I set with shairport-sync, this will not build as a package with either makedeb (for debian/RPi) nor makepkg (Arch) due to a permissions problem when it tries to create a group for nqptp.

Using either of these methods allows for nice build of installable/up[grade-able packages, FWIW. Under Arch, this patch allows shairport-sync to build.

I will have to craft a similar one for nqptp.

Thought you'd like to know.

This is the error I get:

[#] Starting package()...
make[1]: Entering directory '/Rune_dev/RuneOS/rpios_packages/nqptp/src/nqptp'
make[1]: Nothing to be done for 'install-data-am'.
 /usr/bin/mkdir -p '/Rune_dev/RuneOS/rpios_packages/nqptp/pkg/nqptp-git//usr/bin'
  /usr/bin/install -c nqptp '/Rune_dev/RuneOS/rpios_packages/nqptp/pkg/nqptp-git//usr/bin'
make  install-exec-hook
make[2]: Entering directory '/Rune_dev/RuneOS/rpios_packages/nqptp/src/nqptp'
getent group nqptp &>/dev/null || groupadd -r nqptp &>/dev/null
make[2]: *** [Makefile:817: install-exec-hook] Error 10
make[2]: Leaving directory '/Rune_dev/RuneOS/rpios_packages/nqptp/src/nqptp'
make[1]: *** [Makefile:734: install-exec-am] Error 2
make[1]: Leaving directory '/Rune_dev/RuneOS/rpios_packages/nqptp/src/nqptp'
make: *** [Makefile:673: install-am] Error 2
[! package()] A failure occurred in package().
    Aborting...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.