[Patch] svdrp.c SO_REUSE_PORT

  • Hi,


    ich habe das Problem, daß der VDR kein Bind auf UDP Port 6419 machen kann, wenn bereits andere Programme diesen Port gebunden haben.

    Die Fehlermeldung ist folgende:

    Code
    1. Oct 6 09:22:10 dev vdr: [24382] SVDRP client handler thread started (pid=24342, tid=24382, prio=low)
    2. Oct 6 09:22:10 dev vdr: [24382] SVDRP dev opening port 6419/udp
    3. Oct 6 09:22:10 dev vdr: [24382] ERROR (svdrp.c,161): Die Adresse wird bereits verwendet
    4. Oct 6 09:22:10 dev vdr: [24382] SVDRP client handler thread ended (pid=24342, tid=24382)

    Der angehängte patch setzt einfach nur noch die zusätzliche Socket Option SO_REUSE_PORT (falls vorhanden). Damit funktioniert der Bind des VDR problemlos.

    Wobei ich nicht verstehe, warum das Script peerdemo auf Anhieb ohne Probleme funktioniert hat und nur der VDR nicht wollte.


    Zabrimus

  • Warum lauschen bei dir mehrere Programme auf dem gleichen Port? Wer bekommt denn die Verbindung, wenn man eine zu dem Port aufbaut?


    Lars

  • Es geht nur um den UDP Port 6419, den der VDR zum Discovery (Broadcast) verwendet. Der "normale" SVDRP Port kann und soll natürlich nicht problemlos geshared werden.

    Bei mir sind es in Produktion und Entwicklung: Mehrere VDR Instanzen und auch jonglisto-ng, der die Möglichkeit bekommen soll auf das Discovery zu reagieren.


    Edit:

    Der Einwand war berechtigt. Ich habe den Patch so verändert, daß wirklich nur der UDP port das SO_REUSE_PORT erhält.


    Zabrimus

  • Seltsam. Ich hatte das explizit ausprobiert und dachte, dass das


    // allow it to always reuse the same port:

    int ReUseAddr = 1;

    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &ReUseAddr, sizeof(ReUseAddr));

    gereicht hätte. Wieso hat das dann bei mir funktioniert und bei dir nicht?


    Klaus

  • Mittlerweile vermute ich, daß die Java Implementierung, die ich verwende (Netty, https://netty.io/) irgendwas mit den Sockets doch anders macht, als die C-Variante.


    Und bezüglich SO_REUSEADDR und SO_REUSEPORT gibt es eine Menge Unklarheiten. Ein User hat auf Stackoverflow (https://stackoverflow.com/ques…hey-differ-do-they-mean-t) versucht, das umfassend zu erklären, aber so richtig viel schlauer bin ich immer noch nicht. SO_REUSEPORT gibt es seit Linux Kernel 3.9 und andere Socketimplementierungen/Systeme haben das oder auch nicht.

    Ich habe gerade nochmal versucht, es kreuzweise in der Java-Implementierung und im VDR zu ändern. SO_REUSEPORT mal an und aus, in Java und in C, aber die einzige Variante, die tatsächlich auf meinem System funktioniert ist, wenn beide Sockets das SO_REUSEPORT erhalten. Warum auch immer das SO_REUSEADDR nicht ausreicht. Vielleicht müsste ich den Bind auf IPv4 begrenzen oder .... keine Ahnung.


    In der Zielkonfiguration erhalten alle VDR und die Java-Applikation eigene IPs, sofern sollte es später kein Problem geben. Es ist nur während der Entwicklung nicht hilfreich, wenn der Bind der Sockets fehlschlägt.


    Edit: Ein Bind auf die IPv4-only funktioniert auch nicht :(


    Zabrimus

  • Ich muss auf das Problem noch einmal zurückkommen, weil ich es mittlerweile wieder habe (ohne den Patch).


    Sobald ich peerdemo und VDR auf derselben Maschine starten will, bekomme ich - abhängig von der Startreihenfolge - entweder einen Fehler im VDR, daß der UDP bind nicht funktioniert hat oder peerdemo meldet, daß der Port schon belegt sei, wobei der SVDRP TCP Port mit dem Parameter -p schon woanders hingelegt wurde. Andere Programme lauschen auf keinen der beiden Ports (UDP und dem SVDRP TCP Port von peerdemo).


    Mit dem Patch kann ich sowohl peerdemo, als auch VDR auf derselben Maschine laufen lassen (Debian Stable, Kernel 4.9).

    Im peerdemo ist der reuse-Port auch aktiviert:
    $UdpSocket = new IO::Socket::INET( LocalPort => $UdpPort, Proto => "udp", ReusePort => 1) || die "$!";


    Ein weiterer Test hat aber dann ergeben, daß ein ReuseAddr (statt ReusePort) im peerdemo zumindest mein Problem auch löst.


    Zabrimus