ip.tcp.socket

-- `socket_pair()` implementation is
-- left as an exercise for the reader
local a, b = socket_pair()

spawn(function()
    local buf = byte_span.new(1024)
    local nread = b:read_some(buf)
    print(buf:slice(1, nread))
end):detach()

local nwritten = stream.write_all(a, 'Hello World')
print(nwritten)

Functions

new() → ip.tcp.socket

Constructor.

open(self, address_family: "v4"|"v6"|ip.address)

Open the socket.

address_family can be either "v4" or "v6". If you provide an ip.address object, the appropriate value will be inferred.

bind(self, addr: ip.address|string, port: integer)

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 acceptor.

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, address_family: "v4"|"v6"|ip.address, fd: file_descriptor)

Assign an existing native socket to self.

address_family can be either "v4" or "v6". If you provide an ip.address object, the appropriate value will be inferred.

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.

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.

shutdown(self, what: "receive"|"send"|"both")

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, addr: ip.address, port: integer)

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).

read_some(self, buffer: byte_span) → integer

Read data from the stream socket and blocks current fiber until it completes or errs.

Returns the number of bytes read.

write_some(self, buffer: byte_span) → integer

Write data to the stream socket and blocks current fiber until it completes or errs.

Returns the number of bytes written.

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

Read data from the stream socket and blocks current fiber until it completes or errs.

Returns the number of bytes read.

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

Write data to the stream socket and blocks current fiber until it completes or errs.

Returns the number of bytes written.

send_file(self, file: file.random_access, offset: integer, size_in_bytes: integer[, head: byte_span[, tail: byte_span[, n_number_of_bytes_per_send: integer]]]) → integer

A wrapper for the TransmitFile() function.

Only available on Windows.
Lua conventions on index starting at 1 are ignored. Indexes here are OS-mandated and start at 0.

wait(self, wait_type: "read"|"write"|"error")

Wait for the socket to become ready to read, ready to write, or to have pending error conditions.

In short, the reactor model is exposed on top of the proactor model.

You shouldn’t be using reactor-style operations on Emilua. However there’s this one obsolete and buggy TCP feature that presumes reactor-style operations: SO_OOBINLINE (out_of_band_inline) + sockatmark() (at_mark). If you’re implementing an ancient obscure protocol that for some reason can avoid the TCP OOB bugs then you’ll need to use this function.

wait_type can be one of the following:

"read"

Wait for a socket to become ready to read.

"write"

Wait for a socket to become ready to write.

"error"

Wait for a socket to have error conditions pending.

set_option(self, opt: string, val)

Set an option on the socket.

Currently available options are:

"tcp_no_delay"

Check Boost.Asio documentation.

"send_low_watermark"

Check Boost.Asio documentation.

"send_buffer_size"

Check Boost.Asio documentation.

"receive_low_watermark"

Check Boost.Asio documentation.

"receive_buffer_size"

Check Boost.Asio documentation.

"out_of_band_inline"

Socket option for putting received out-of-band data inline.

"linger"

Check Boost.Asio documentation.

"keep_alive"

Check Boost.Asio documentation.

"do_not_route"

Check Boost.Asio documentation.

"debug"

Check Boost.Asio documentation.

"v6_only"

Check Boost.Asio documentation.

get_option(self, opt: string) → value

Get an option from the socket.

Currently available options are:

Function flags

do_not_route

Specify that the data should not be subject to routing.

end_of_record

Specifies that the data marks the end of a record.

out_of_band

Process out-of-band data.

peek

Peek at incoming data without removing it from the input queue.

Properties

is_open: boolean

Whether the socket is open.

local_address: ip.address

The local address endpoint of the socket.

local_port: integer

The local port endpoint of the socket.

remote_address: ip.address

The remote address endpoint of the socket.

remote_port: integer

The remote port endpoint of the socket.

at_mark: boolean

Whether the socket is at the out-of-band data mark.

You must set the out_of_band_inline socket option and use reactor-style operations (wait()) to use this feature.