BAS LuaSocket Compatibility Library

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.

Scope and Design Notes

Modules in /socket/

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.

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.

BAS-Specific Additions and Differences (socket/core.lua)

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 reads

Reads 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 reads

Reads 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 reads

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

SMTP/TLS Extensions (socket/smtp.lua and socket/tp.lua)

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)

Behavior:

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

File Sources (ltn12.lua)

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.

High-Level Mail Helper (socket/mail.lua)

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.