In inetd und systemd -Typsystemen ist es möglich, dass das System einen Socket bindet und die Anwendung mit dem bereits vorhandenen Socket startet, um beispielsweise socket-basiert zu sein Dienst beginnt. Ich möchte diese Funktionalität in einem meiner Haskell-Daemons ausnutzen.
Der Daemon ruft derzeit socket
, bindSocket
, listen
auf, um ein Objekt Socket
zu erstellen, das ich später accept
aufrufen kann. Um dies in ein inetd
Typ System zu ändern, müsste ich die Standardeingabe als Socket
verwenden, aber alles, was ich bisher finden kann, ist stdin :: Handle
, oder fdToHandle :: CInt -> Handle
- beides ist nicht das, was ich brauche.
Ich kann anscheinend nichts finden, das Handle -> Socket
oder irgendetwas wie stdin :: Socket
hat. Der nächste, den ich finden kann, ist mkSocket
, was sehr niedrig ist, und die meisten anderen Sprachen (z. B. Ruby) bieten einen Aufruf, um einen Dateideskriptor in einen Socket zu verwandeln, ohne verschiedene andere Parameter angeben zu müssen.
C-Anwendungen haben den Luxus, sd-daemon.h
zu haben, was Socket-Passing automatisch behandelt. In Haskell muss diese Datei manuell emuliert werden.
Sie können % co_de verwenden % , um den Dateideskriptor stdInput
zu erhalten. Die stdin
Funktion kann natürlich auch verwendet werden. Da Sie POSIX-spezifisches Verhalten wünschen, können Sie nicht erwarten, dass es unter Windows funktioniert.
Sobald Sie die FD haben, haben Sie keine andere Wahl, als die Funktion handleToFd
zu verwenden. Haskell kann nicht erraten, welche Art von Socket Sie möchten, also müssen Sie es angeben. Sie möchten wahrscheinlich:
Bitte beachten Sie, dass dies nicht unbedingt ist, wie mkSocket
Dateideskriptoren an Ihre Anwendung übergibt. Sie müssen die Umgebungsvariablen systemd
und LISTEN_FDS
überprüfen, um zu sehen, welche Dateideskriptoren verwendet werden sollen und ob es Ihr Job ist, die Sockets zu binden. Der Standard-Dateideskriptor, der den Standard-Socket darstellt, ist FD 3, nicht FD 0, wie Sie annehmen. LISTEN_PID
könnte Ihnen auch mehrere Sockets geben, wenn die Servicedatei dies erfordert.
Der Haupttrick für MkSocket besteht darin, zu wissen, dass Sie die richtigen Parameter haben. Der sd-daemon.h hilft dabei. Ich sehe von systemd Manpage auf sd_is_fifo , dass es fstat und getsockname verwendet, das code für sd_is_socket ist hier in git .
Sie können fstat
im Unix-Paket verwenden, um zu helfen
Das Netzwerkpaket (teilweise unter Verwendung des Network.Socket.Internals) verwendet auch die C getsockname
-Funktion (der Helfer withNewSockAddr
weist den richtigen Puffer für die Antwort zu). Dies erfordert entweder das Erraten der "Familie" oder vielleicht nur das Zuweisen eines großen Puffers für die Antwort ( sockaddr_storage
von RFC 2553). Aber Network nimmt den Socket-Dateideskriptor von den Socket
-Daten. Sie könnten den Code aus Network herausziehen und die Prüfungen, die die sd-daemons.h durchführt, erneut implementieren.
Der getsockopt
Code wurde wahrscheinlich auch in das Paket für Netzwerk-Socket-Optionen eingeschlossen .
Aber es scheint nicht, dass irgendjemand es so zusammengestellt hat, wie Sie es brauchen. Seltsam.
Tags und Links haskell posix networking systemd inetd