Socket.Unix
Programs on the same machine can connect to each other through a name in the file system instead of a network address, and this module makes such connections and listeners.
A Unix domain socket is a stream socket whose address is a path. A listener creates a socket
file at the path, and a client connects by naming that path. The
Connection and Listener made here are the same types
as for TCP, and are used through Socket; what is particular to this module is
making them and reading a connection's peer credentials.
A path is handed to the operating system as Path.toPosixString prints
it. That text must be at most 107 bytes of UTF-8 on Linux and 103 on macOS. On the native backend
under Windows, connecting and listening fail with Socket.NotSupported.
Since the address is a path, connecting and listening fail the way a file operation on that path
would: with Socket.AddressPathFailed and the
FileSystem.ErrorKind the path would have there, such as
NoSuchFileOrDirectory, NotADirectory, LinkLoop, ReadOnlyFileSystem, PathTooLong (a
path over the length limit) or PermissionDenied. The failures that describe the socket rather
than the path keep their own kinds: Socket.AddressInUse when something
already exists at the path, and Socket.ConnectionRefused when nobody
listens on it.
The socket file's path is the only name a connection has. On the side that connected it is the
remote endpoint, and on the side that accepted it is the local endpoint, in both cases as the path
Path.toPosixString prints, parsed again; the other endpoint is the empty
path, Path.empty.
A Unix domain connection can also tell who is at the other end: its peer credentials are the
process id, user id and group id of the program on the other side, which
peerCredentials reads.
Connecting
connect : Path -> Task Error ConnectionListening
type alias ListenOptions =
{ path : Path, removeExisting : Bool, permissions : Maybe Int }The options for listen: where to create the socket file, whether a socket file
already there may be replaced, and the mode to give it.
removeExisting removes a socket file already at path before listening, whether or not a
program still listens on it. Any other kind of file there, a symbolic link included, still makes
listen fail with Socket.AddressInUse.
permissions is the socket file's mode as a number (0o600 is 384), of which only the
low twelve bits, 0o7777, are used. On the native backend it is set before the socket starts
listening, so no client connects before it applies; on the JavaScript backend it is set once
listening has started, before the task succeeds. Nothing, or a negative number, leaves the mode
the process's umask gives. If the mode cannot be set, listen fails.
defaultListenOptions : Path -> ListenOptionsReturns the options for listening at path with which listen fails when anything already
exists there, and which leave the socket file's mode to the umask.
listen : ListenOptions -> Task Error ListenerStarts listening at options.path, creating the socket file there.
Fails with:
Socket.AddressInUsewhen something already exists at the path andremoveExistingdoes not allow it to be removed;Socket.AddressPathFailedwhen the path cannot be used, with theFileSystem.ErrorKindit would have there: for exampleNoSuchFileOrDirectorywhen a parent directory does not exist,NotADirectorywhen a part of the path is not a directory,PermissionDeniedwithout write permission on the directory,ReadOnlyFileSystem, orPathTooLong.
A listen that fails after creating the socket file removes it again, and so does
Socket.closeListener.
Each connection the listener hands out has as its local endpoint the path printed and parsed again, and the empty path as its remote endpoint.
Peer credentials
peerCredentials :
Connection
-> Task Error { pid : Int, uid : Int, gid : Int }Asks for the peer credentials of a Unix domain connection: the process id, user id and group id of the program at the other end, as the operating system reported them when the connection was made.
Fails with Socket.InvalidInput for a connection that is not a Unix domain
connection, and on the JavaScript backend for one that has closed. Otherwise it fails with
Socket.NotSupported where the credentials cannot be read: on the JavaScript backend for every Unix domain connection, and on the native backend on
systems other than Linux and macOS.
Connects to the listener whose socket file is at
path.Fails with:
Socket.AddressPathFailedFileSystem.NoSuchFileOrDirectorywhen nothing exists at the path, andAddressPathFailedwith anotherFileSystem.ErrorKindwhen the path cannot be used, for examplePermissionDeniedwithout write permission on the socket file,NotADirectorywhen a part of the path is not a directory, orPathTooLong;Socket.ConnectionRefusedwhen nobody listens on it;Socket.ListenQueueFullwhen the operating system's queue of connections waiting on that listener is full.The connection's remote endpoint is
path, printed and parsed again, and its local endpoint is the empty path.