The BAS LuaSocket Compatibility Library provides a LuaSocket-style API on top of the Barracuda App Server (BAS) socket layer. It was primarily created so the LuaSocket SMTP module can run on BAS, including secure SMTP via TLS/STARTTLS, but it is also useful for porting other Lua code written for the standard LuaSocket API.
This compatibility layer is not a byte-for-byte reimplementation of all LuaSocket behavior. It maps LuaSocket-style calls to BAS sockets (ba.socket) and adds BAS-specific TLS hooks (SharkSSL integration). The sections below document only APIs that are new or behave differently than standard LuaSocket.
The compatibility library in /socket/ is split into a small set of modules with different roles. They do not all follow the same module-return pattern.
socket/core.lua: BAS-to-LuaSocket compatibility layer. This module initializes the global compatible table socket (via BAS compatibility support) and adds/overrides methods on that table.socket/tp.lua: Shared text protocol transport helpers used by SMTP (command/reply handling, source pumping, TLS transport upgrade hook).socket/smtp.lua: SMTP client implementation based on LuaSocket SMTP, with BAS TLS/STARTTLS integration.socket/mail.lua: Convenience wrapper for composing/sending text, HTML, and attachment emails via socket.mail.
Module loading note: not all files in /socket/ return a module table. For example, socket/mail.lua defines socket.mail on the global compatible socket table and does not return a table value.
socket.tcp()Creates an unconnected compatibility wrapper. Call connect to attach a connection, or bind followed by listen to create a native listener.
Parameters
None.
Return values
Throws
Lua allocation errors can propagate.
socket.secure([shark]) (BAS extension)Sets the SharkSSL configuration used by subsequent connect calls that have no stored options. bind captures this value in its stored options when called. Direct upgrade calls use their explicit configuration or ba.sharkclient().
local socket = require("socket")
-- Default configuration for subsequent connections
socket.secure(ba.sharkclient())
Parameters
Return values
None.
Throws
Errors from ba.sharkclient() propagate when creating a default configuration. A supplied value is stored without validation; native operations validate it when used.
socket.gettime()Returns os.time(), with whole-second resolution.
Parameters
None.
Return values
Throws
Errors from the underlying os.time() call propagate.
socket.sleep(seconds) (behavior difference)
Uses BAS scheduling primitives. When running in a BAS socket context (cosocket), it temporarily disables the current cosocket and re-enables it via a timer; otherwise it falls back to ba.sleep(). This makes sleep behavior BAS event-loop aware.
Parameters
Return values
None. Results from the underlying scheduling calls are not returned.
Throws
Invalid duration types and errors from native timer, socket or sleep calls can throw. Calling from an unsupported execution context can throw.
tcp:bind(address, port) + tcp:listen([backlog]) (behavior difference)
bind() stores bind/connect options (including TLS state) and does not
immediately create/bind the underlying BAS socket. The actual server bind occurs
in listen(). The backlog argument is accepted for compatibility but is not used. The wrapper has no LuaSocket-style accept() method. For server applications, use ba.socket.bind() and its native accept() method. If you already have a listening wrapper, sock() returns its native listener; native accept returns a BAS socket, not a LuaSocket wrapper.
Parameters
Return values
Throws
Invalid objects can throw. bind stores its arguments without validating them; listen requires options set by bind or sock and propagates native argument-validation errors. Native bind failures reported as return values are returned as nil, error.
tcp:connect(address, port) (behavior difference)
In addition to normal host/port usage, address may be an existing BAS
socket userdata (detected by an upgrade method). In that case, the
compatibility object wraps the existing socket instead of creating a new connection. Starting connect closes any previously wrapped socket and discards unread buffered data, including if the new connection attempt fails.
Parameters
Return values
Throws
Invalid objects, addresses, ports or stored options can throw. Native connection argument and Lua allocation errors propagate. Reported connection failures return nil, error. Argument validation occurs after the previous socket has been closed.
tcp:certificate()Returns the certificate information retained by the native TLS socket. See socket:certificate() for the named certificate fields and linked parent tables.
Parameters
None.
Return values
Throws
Invalid objects can throw. Lua allocation errors from the native certificate query can propagate. Missing TLS or an unattached socket is reported through return values.
tcp:upgrade([shark])Upgrades an attached plain socket to TLS. For protocols such as SMTP, complete the protocol's STARTTLS exchange before calling this method.
Parameters
Return values
Throws
Invalid objects or native upgrade arguments can throw. Errors from default configuration creation and native calls propagate. Reported upgrade failures return nil, error.
tcp:dohandshake([op]) and tcp:sslhandshake()Returns success for a valid socket that already uses TLS, whether its session was resumed or established with a full handshake. Otherwise, upgrades the plain socket. sslhandshake() calls dohandshake() without options.
Parameters
Return values
Throws
Invalid objects or upgrade arguments can throw. Errors from option access, default configuration creation and native socket calls propagate. Reported upgrade failures use return values.
Recognizing an existing TLS connection does not repeat its handshake or certificate checks. Use the native socket's trust-checking API when required by the application.
tcp:sockname() / tcp:getsockname()Queries the local endpoint through the native BAS socket.
Parameters
None.
Return values
Throws
Invalid objects and native argument errors can throw. Lua allocation errors can propagate. Reported native failures return nil, error.
tcp:peername() / tcp:getpeername()Queries the remote endpoint through the native BAS socket.
Parameters
None.
Return values
Throws
Invalid objects and native argument errors can throw. Lua allocation errors can propagate. Reported native failures return nil, error.
tcp:sock([op])Returns the native socket and optionally replaces options used by later operations.
Parameters
Return values
Throws
Invalid objects can throw. Options are stored without validation; native operations validate them when used.
tcp:connected()Checks the native socket validity flag. This is a local state check, not a test of peer reachability. A listening socket can also be valid.
Parameters
None.
Return values
Throws
Invalid objects can throw. Errors from the underlying socket:state() call propagate. A closed or unattached socket returns nil, "closed".
tcp:close()Closes the underlying BAS socket. The wrapper retains the native socket object; connected() checks its current validity.
Parameters
None.
Return values
Throws
Invalid objects can throw. Errors from the native close call propagate.
tcp:getstats() (stored values only)Automatic traffic statistics are not supported. Sending and receiving data do not update the stored values, and age is not an elapsed duration.
Parameters
None.
Return values
A newly created wrapper returns nil for all three values until connect, listen or setstats initializes them. Values supplied to setstats are returned unchanged.
Throws
No errors are raised for a valid wrapper. Calling the method with an invalid object can throw.
tcp:setstats([received[,sent[,age]]]) (stored values only)Replaces the three values returned by getstats. This does not enable automatic accounting.
Parameters
Return values
Throws
Calling the method with an invalid object can throw. The implementation stores values without validating their types or ranges.
tcp:settimeout(value[,mode]) and tcp:gettimeout()Stores a timeout for subsequent receive calls. This value does not configure connect or send. mode is accepted but ignored; there is no separate total-operation timeout.
Parameters
gettimeout takes no arguments.
Return values
Throws
Invalid objects and values that cannot be compared or multiplied can throw. settimeout does not validate the native timeout range; errors from unsupported timeout values can occur on receive. gettimeout does not raise errors for a valid wrapper.
tcp:receive([pattern[,prefix]]): line readsReads a line when pattern is omitted, "l" or "*l". Removes the final newline and an immediately preceding carriage return. This section describes line reads; numeric and all-data patterns are separate forms.
Parameters
Return values
Throws
Invalid objects or argument types can throw. Native socket API-usage errors and Lua allocation errors can propagate. Reported read failures return nil, error, partial.
tcp:receive(pattern[,prefix]): all-data readsReads until the connection closes. A timeout returns an error and the data collected so far; it does not indicate a complete read.
Parameters
Return values
Throws
Invalid objects or argument types can throw. Native socket API-usage errors and Lua allocation errors can propagate. A reported timeout returns nil, "timeout", partial.
tcp:receive(count[,prefix]): fixed-length readsReads enough bytes to reach count, including the supplied prefix. For example, receive(5, "ab") reads three more bytes. Bytes received beyond the requested count remain buffered for the next call.
Parameters
Return values
Throws
For an attached socket, a negative, fractional or non-finite count throws before reading or changing buffered data. Invalid objects, unsupported patterns or invalid prefix types can also throw. An unattached wrapper returns nil, "closed", prefix before inspecting the pattern. Native socket API-usage errors and Lua allocation errors can propagate. Reported read failures return nil, error, partial.
tcp:send(data[,i[,j]]) (behavior differences)Sends the selected data through the underlying BAS socket. Returns a boolean success value, not LuaSocket's last-byte index. An empty selection succeeds without sending bytes.
Parameters
Return values
Throws
Invalid objects, invalid table contents and native write argument errors can throw. Data conversion errors and Lua allocation errors can propagate. Reported native write failures use return values. See ba.socket for native send and queue behavior.
tcp:shutdown() (behavior difference)
BAS compatibility maps shutdown() to close(). Half-close
semantics are not provided by this layer. An unattached wrapper returns nil, "closed".
Parameters
None. Additional arguments are ignored.
Return values
Throws
Invalid objects can throw. Errors from native close propagate.
The SMTP code is based on LuaSocket SMTP, but BAS adds TLS integration so it can operate with modern SMTP servers that require encryption.
smtp:upgrade([shark])Upgrades the SMTP transport to TLS before reading the server greeting, for implicit TLS.
Parameters
Return values
None on success.
Throws
This low-level method closes the transport and raises a reported upgrade failure through its cleanup handler. Other native or argument errors can propagate. The high-level socket.smtp.send catches errors inside its protected sending operation and returns nil, error.
smtp:starttls([domain[,shark]])Sends STARTTLS, checks the reply, upgrades the transport and sends EHLO again.
Parameters
Return values
Throws
This low-level method closes the transport and raises reported command, reply or upgrade failures through its cleanup handler. Other native or argument errors can propagate. The high-level socket.smtp.send returns protected failures as nil, error.
tp:upgrade([shark])Forwards a TLS upgrade to the protocol transport's socket.
Parameters
Return values
Throws
Invalid objects, configuration errors and exceptions from the socket upgrade can propagate. Reported upgrade failures use return values; this forwarding method does not itself close the transport.
socket.smtp.send(mailt) extra fields (BAS extensions)mailt.shark: SharkSSL client configuration to use for TLS.mailt.starttls (true/false): If true, require STARTTLS during the SMTP handshake.Behavior:
mailt.shark is set and mailt.starttls is not set, SMTP uses implicit TLS (typically SMTPS/465) before EHLO.mailt.starttls = true, SMTP upgrades after the initial EHLO when the server supports STARTTLS.mailt.starttls = true but the server does not advertise STARTTLS, send closes the connection and returns nil, "STARTTLS not supported". A rejected STARTTLS command or failed TLS upgrade also closes the connection and returns nil, error before authentication or message submission. Implicit TLS upgrade failures use the same cleanup and error handling.ba.sharkclient()) during TLS upgrade.Parameters
Return values
Throws
Throws before opening a connection if mailt.from or mailt.rcpt is missing, nil or false. Invalid access to mailt can also throw before connecting. After these checks, the high-level send function uses socket.protect: errors raised inside its protected body are returned as nil, error. Other argument and callback errors inside that body can therefore be returned, and their error value need not be a string. The low-level SMTP methods use socket.newtry and can raise errors; call them inside socket.protect when using them directly.
socket.smtp.message(mesgt) (behavior difference in this BAS copy)This BAS-modified version normalizes user-supplied header keys to lowercase when building the message source. Code that depends on LuaSocket's original header key casing behavior should be verified on BAS. The generated MIME-Version header is always 1.0, as specified by RFC 2045.
Parameters
Return values
Throws
Invalid message or header data, date formatting errors and Lua allocation errors can throw while creating the source. Once created, the source returns coroutine execution errors as nil, error.
local smtp = require("socket.smtp")
smtp.send{
server = "smtp.example.com",
port = 587,
user = "user",
password = "secret",
from = "<me@example.com>",
rcpt = "<you@example.com>",
source = smtp.message{
headers = { subject = "Test" },
body = "Hello from BAS"
},
starttls = true, -- BAS extension
shark = ba.sharkclient(), -- BAS extension (optional)
}
ltn12.source.file(handle[,io_error])Creates a chunk source used by data pumps, including file-backed SMTP message bodies and attachments. The source closes the file when a read returns no chunk, whether due to EOF or a reported read error.
Parameters
Return values
Throws
Invalid file objects or method calls can throw when the source runs. Errors thrown by read or close propagate. Error values returned by those methods are discarded. Lua allocation errors can also propagate.
If a consumer stops before the source closes the file, it remains responsible for closing it. Because this helper discards returned read errors, an incomplete file can appear to end normally, including when used for an SMTP attachment. Applications needing error reporting must supply a source that preserves those errors.
socket.mail(config) (BAS extension)
Creates a simplified mail sender wrapper on top of socket.smtp. This helper is BAS-specific and not part of standard LuaSocket. It is intended to make common email sending (text/HTML/attachments) easier. See the BAS SMTP documentation for details.
Parameters
Return values
Throws
Invalid configuration objects or a missing server field throw. Lua allocation errors can propagate.