How can I turn either a Unix POSIX file descriptor or standard input Handle into a Socket?
haskell, inetd, networking, posix, systemd
Solution
C applications have the luxury of having `sd-daemon.h` which handles socket passing automatically. In Haskell, this file has to be emulated manually.
You can use `stdInput` to get the `stdin` file descriptor. The `handleToFd` function can of course also be used. Since you want POSIX-specific behavior, you can't expect it to work on Windows, though.
Once you have the FD, you have no choice but to use the `mkSocket` function. Haskell can't guess what kind of socket that you want, so you have to specify it. You most probably want:
mkSocket fd AF_UNIX Stream defaultProtocol Listening
Please remember that this isn't necessarily how `systemd` passes file descriptors to your application. You must check the `LISTEN_FDS` and `LISTEN_PID` environment variables to see which file descriptors to use and whether its your job to even bind the sockets. The default file descriptor representing the default socket is FD 3, not FD 0 as you are assuming. `systemd` might also give you multiple sockets to use if the service file demands it.
Problem
In inetd and systemd type systems, it is possible for the system to bind a socket and launch the application with the socket already existing, for example to provide socket based service starting. I would like to take advantage of this functionality in one of my Haskell daemons. The daemon currently calls, `socket`, `bindSocket`, `listen` to create a `Socket` object that I can later call `accept` on. To change this to an `inetd` type system I would need to use standard input as a `Socket`, but all I can find so far is `stdin :: Handle`, or `fdToHandle :: CInt -> Handle` - neither are quite what I need. I can't seem to find anything that has type `Handle -> Socket`, nor anything that is like `stdin :: Socket`. The nearest I can find is `mkSocket` which is very low-level, and most other languages (ie, Ruby) provide a call to turn a file descriptor into a socket without having to specify various other parameters.