For the latest stable version, please use Emilua API 0.10!

unix.seqpacket_socket

local sock = unix.seqpacket_socket.new()
sock.open()
sock.bind(filesystem.path.new('/tmp/9Lq7BNBnBycd6nxy.socket'))

local buf = byte_span.new(1024)
local nread = sock:receive(buf)
print(buf:slice(1, nread))

A note on 0-sized packets

AF_UNIX+SOCK_SEQPACKET sockets behave just the same on Linux and BSD systems. It’s safe to use them as IPC primitives in your system. However there are a few caveats related to the idea of what SOCK_SEQPACKET were supposed to mean originally.

seems SEQPACKET is too exotic thing that everyone implements it in own manner, because i’ve tested SCTP seqpacket implementation, and found […​]

The API for general SOCK_SEQPACKET sockets exposes a few incompatible mechanisms to tell EOF apart from 0-sized messages. These mechanisms are not found in AF_UNIX sockets.

According to POSIX the behaviour for Linux and BSD is wrong, but pointing to POSIX or changing the behaviour of current systems is useless (even harmful) at this point.

Emilua will just report EOF whenever a 0-sized read occurs.

If you control both sides of the communication channel, just avoid sending any 0-sized datagram and you’re safe.

If you don’t control the sending side, you might receive 0-sized datagrams that are in reality an attack to the system. If your program is the only receiver there’s hardly any harm. However if you need to make sure the connection is closed when your program deems it as so, just call shutdown("receive") or shutdown("both") to make sure the connection is closed to every associated handle.

However don’t let this small note scare you. AF_UNIX+SOCK_SEQPACKET sockets are a powerful IPC primitive that will save you from way worse concerns if your application needs a socket that is connection-oriented, preserves message boundaries, and delivers messages in the order that they were sent. SOCK_STREAM and SOCK_DGRAM will have their own caveats.

Functions

new() → unix.seqpacket_socket

new()                    (1)
new(fd: file_descriptor) (2)
1 Default constructor.
2 Converts a file descriptor into an unix.seqpacket_socket object.

pair() → unix.seqpacket_socket, unix.seqpacket_socket

Create a pair of connected sockets.

open(self)

Open the socket.

bind(self, pathname: filesystem.path)

Bind the socket to the given local endpoint.

close(self)

Close the socket.

Any asynchronous send, receive or connect operations will be cancelled immediately, and will complete with the boost::asio::error::operation_aborted error.

cancel(self)

Cancel all asynchronous operations associated with the socket.

This function causes all outstanding asynchronous connect, send and receive operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation_aborted error.

assign(self, fd: file_descriptor)

Assign an existing native socket to self.

release(self) → file_descriptor

Release ownership of the native descriptor implementation.

This function causes all outstanding asynchronous connect, send and receive operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation_aborted error. Ownership of the native socket is then transferred to the caller.

shutdown(self, what: string)

Disable sends or receives on the socket.

what can be one of the following:

"receive"

Shutdown the receive side of the socket.

"send"

Shutdown the send side of the socket.

"both"

Shutdown both send and receive on the socket.

connect(self, pathname: filesystem.path)

Initiate a connect operation and blocks current fiber until it completes or errs.

disconnect(self)

Dissolve the socket’s association by resetting the socket’s peer address (i.e. connect(3) will be called with an AF_UNSPEC address).

receive(self, buffer: byte_span[, flags: integer]) → integer

Receive a datagram and blocks current fiber until it completes or errs.

Returns the number of bytes read.

flags is 0 or an or-combination of values from unix.message_flag(3em).

send(self, buffer: byte_span[, flags: integer]) → integer

Send data on the seqpacket socket and blocks current fiber until it completes or errs.

Returns the number of bytes written.

flags is 0 or an or-combination of values from unix.message_flag(3em).

receive_with_fds(self, buffer: byte_span, maxfds: integer) → integer, file_descriptor[]

Receive a datagram and blocks current fiber until it completes or errs.

Returns the number of bytes read plus the table containing the fds read.

send_with_fds(self, buffer: byte_span, fds: file_descriptor[]) → integer

Send data on the seqpacket socket and blocks current fiber until it completes or errs.

Returns the number of bytes written.

set_option(self, opt: string, val)

Set an option on the socket.

Currently available options are:

get_option(self, opt: string) → value

Get an option from the socket.

Currently available options are:

"debug"

Check Boost.Asio documentation.

"send_buffer_size"

Check Boost.Asio documentation.

"receive_buffer_size"

Check Boost.Asio documentation.

"remote_credentials": { uid: integer, groups: integer[], pid: integer }

Returns the credentials from the remote process.

On Linux, groups don’t include the supplementary group list.
pid is racy and you shouldn’t use it for anything but debugging purposes.
"remote_security_labels": { [string]: string }|string|nil

(FreeBSD only) Returns the security labels associated with each policy for the remote process.

Optionally one may pass an extra argument to get_option() with either a list of strings for the policies of interest, or just a single string in case there’s only one policy of interest.

"remote_security_label": string

(Linux only) Returns the SELinux security label associated with the remote process.

io_control(self, command: string[, …​])

Perform an IO control command on the socket.

Currently available commands are:

"bytes_readable"

Expects no arguments. Get the amount of data that can be read without blocking. Implements the FIONREAD IO control command.

Properties

is_open: boolean

Whether the socket is open.

local_path: filesystem.path

The local address endpoint of the socket.

remote_path: filesystem.path

The remote address endpoint of the socket.