EMILUA(3em)
πΈ NAME
Emilua β the Lua execution engine π (this is a page from the Emilua reference manual, and bestie, we're deep in the ip.tcp.socket section, so buckle up π)
β¨ SYNOPSIS
Okay so here's the vibe β two sockets, one fiber reading, main thread writing, and zero drama:
-- `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:first(nread))
end):detach()
local nwritten = stream.write_all(a, 'Hello World')
print(nwritten)
Like, spawn kicks off a fiber, it reads into a byte_span, and meanwhile we write 'Hello World' through stream.write_all β and both of them print their byte counts. Iconic. π₯
π FUNCTIONS
new() β ip.tcp.socket
Constructor. That's it, that's the whole thing π it makes you a socket.
open(self, address_family: v4"|"v6"|ip.address)"
Opens the socket up, slay.
address_family can be either "v4" or "v6". And if you hand it an ip.address object instead, it'll infer the right value for you like the main character it is β¨
bind(self, addr: ip.address|string, port: integer)
Binds the socket to the given local endpoint. Like claiming your seat, no cap πͺ
close(self)
Closes the socket. Bye bestie π
It just forwards the call to the close function with the same name in Boost.Asio:
Any asynchronous send, receive or connect operations will be cancelled immediately, and will complete with the boost::asio::error::operation_aborted error.
cancel(self)
Cancels all asynchronous operations associated with the acceptor.
Also a forward to the cancel function with the same name in Boost.Asio:
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)"
Assigns an existing native socket to self. Reusing, we love to see it β»οΈ
address_family can be either "v4" or "v6". And if you pass an ip.address object, the appropriate value gets inferred π
release(self) β file_descriptor
Releases ownership of the native descriptor implementation β like handing over the aux cord, the descriptor is yours now π§
Forwards to the release function with the same name in Boost.Asio:
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[, ...])
Performs an IO control command on the socket. Fancy I/O business π§
Currently available commands are:
"bytes_readable"β expects no arguments. Gets the amount of data that can be read without blocking. It implements theFIONREADIO control command. So basically "how much can I slurp without waiting" π
shutdown(self, what: receive"|"send"|"both")"
Disables sends or receives on the socket. Half-closing, we're being efficient π
what can be one of these:
"receive"β shuts down the receive side of the socket."send"β shuts down the send side of the socket."both"β shuts down both send and receive on the socket. All of it. Periodt.
connect(self, addr: ip.address, port: integer)
Starts a connect operation and blocks the current fiber until it finishes or errs. It's giving "wait for me" energy π
disconnect(self)
Dissolves the socket's association by resetting the socket's peer address (i.e. connect(3) will be called with an AF_UNSPEC address). Basically "we're strangers now" π
read_some(self, buffer: byte_span) β integer
Reads data from the stream socket and blocks the current fiber until it completes or errs.
Returns the number of bytes read. β
write_some(self, buffer: byte_span) β integer
Writes data to the stream socket and blocks the current fiber until it completes or errs.
Returns the number of bytes written. β
receive(self, buffer: byte_span, flags: string[]) β integer
Reads data from the stream socket and blocks the current fiber until it completes or errs.
Returns the number of bytes read. (Yeah, same description as read_some, I'm not gonna pretend otherwise π)
send(self, buffer: byte_span, flags: string[]) β integer
Writes data to the stream socket and blocks the 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.
Note Only available on Windows. πͺ
Important Lua conventions on index starting at 1 are ignored. Indexes here are OS-mandated and start at 0. Yes, genuinely. Do not come for me, I'm just the messenger π
Reference: https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile
wait(self, wait_type: read"|"write"|"error")"
Waits 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. Wild, I know.
Important You shouldn't be using reactor-style operations on Emilua. BUT β there's this one obsolete and buggy TCP feature that presumes reactor-style operations:SO_OOBINLINE(out_of_band_inline) +sockatmark()(at_mark). So 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. Only then. I said what I said π
wait_type can be one of the following:
"read"β waits for a socket to become ready to read."write"β waits for a socket to become ready to write."error"β waits for a socket to have error conditions pending.
set_option(self, opt: string, val)
Sets an option on the socket. Little knobs, big power π₯
Currently available options are:
"tcp_no_delay"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/ip__tcp/no_delay.html"send_low_watermark"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/send_low_watermark.html"send_buffer_size"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/send_buffer_size.html"receive_low_watermark"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/receive_low_watermark.html"receive_buffer_size"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/receive_buffer_size.html"out_of_band_inline"β socket option for putting received out-of-band data inline.
Important Do bear in mind that the BSD socket API forSO_OOBINLINEis incompatible with proactor-style operations. Like, actually incompatible. Not a vibe. π Reference:http://www.serverframework.com/asynchronousevents/2011/10/out-of-band-data-and-overlapped-io.html
"linger"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/linger.html"keep_alive"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/keep_alive.html"do_not_route"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/do_not_route.html"debug"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/debug.html"v6_only"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/reference/ip%5F_v6_only.html
get_option(self, opt: string) β value
Gets an option from the socket. Same knobs, now you're reading them π
Currently available options are:
"tcp_no_delay"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/ip__tcp/no_delay.html"send_low_watermark"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/send_low_watermark.html"send_buffer_size"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/send_buffer_size.html"receive_low_watermark"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/receive_low_watermark.html"receive_buffer_size"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/receive_buffer_size.html"out_of_band_inline"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/out_of_band_inline.html(note this is a different URL than theset_optionone, iykyk π)"linger"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/linger.html"keep_alive"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/keep_alive.html"do_not_route"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/do_not_route.html"debug"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_72_0/doc/html/boost_asio/reference/socket_base/debug.html"v6_only"β check the Boost.Asio documentation:https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/reference/ip%5F_v6_only.html
π FUNCTION FLAGS
These are the flags you can hand to receive / send (the flags: string[] ones, remember?), and each one is literally the Boost.Asio flag with the same name π
do_not_route
The do_not_route flag with the same name in Boost.Asio:
Specify that the data should not be subject to routing.
end_of_record
The end_of_record flag with the same name in Boost.Asio:
Specifies that the data marks the end of a record.
out_of_band
The out_of_band flag with the same name in Boost.Asio:
Process out-of-band data.
peek
The peek flag with the same name in Boost.Asio:
Peek at incoming data without removing it from the input queue.
(https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/reference/socket_base/message_peek.html)
Peeking is so main character energy β look but don't touch π¦
β¨ PROPERTIES β¨
okay bestie, this is the good part β all the little attributes you can peek at on your socket π each one's got a type and a whole personality, let's get into it.
π is_open: boolean
literally just tells you whether the socket is open or not. that's it. that's the whole vibe check. open = true, closed = false, no cap π¦
πΈ local_address: ip.address
the local address endpoint of the socket β like, where you are on the network, bestie. it's giving "this is my house" π
π local_port: integer
the local port endpoint of the socket. the number your side is chillin' on π
π¦ remote_address: ip.address
the remote address endpoint of the socket β where the other side lives. the pen pal address, if you will β¨
π remote_port: integer
the remote port endpoint of the socket. the port number on the other end, slay π
π₯ at_mark: boolean
whether the socket is at the out-of-band data mark. ooooh fancy π
β οΈ Important β οΈ bestie listen to me fr fr β you must set theout_of_band_inlinesocket option and use reactor-style operations (wait()) to use this feature. no shortcuts, no vibes-only approach, it literally will not work otherwise ππ
and that's the whole page, bestie!! you made it to the end, proud of you π«Ά this icon of a manpage is from Emilua 0.12.1-nixpkgs1, dated 1980-01-01, and it lives in section EMILUA(3em) β go forth and socket responsibly, mwah πβ¨
π¦ where this page comes from
- nixos 26.05: emilua 0.12.1
- nixpkgs unstable: emilua 0.12.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms