A convenience wrapper around de.lucaswerkmeister.ceylond.core for record-based daemons. A record is considered to be a string, encoded in some fashion (usually UTF-8), terminated by a record separator (also a string). For instance, the record separator might be "\n", in which case a record is a line; it might also be "::", in which case the socket message a::b::c:: is interpreted as the three records a, b, and c.

For example, a simplistic HTTP server could be implemented like this:

shared void run()
     => startRecordBased {
         recordSeparator = "\r\n";
         function instance(void write(String|ByteBuffer content, WriteCallback callback), void close()) {
             variable String? path = null;
             void read(String record) {
                 if (exists requestedPath = path) {
                     if (record.empty) {
                         String? content;
                         // TODO fill in content based on path (e.���g. read file from disc)
                         if (exists content) {
                             write("HTTP/1.0 200 OK", noop);
                             write("Content-type: text/plain; charset=utf-8", noop);
                             write("", noop);
                             write(utf8.encodeBuffer(content), close);
                         } else {
                             write("HTTP/1.0 404 File not found", noop);
                             write("", close);
                         }
                     } else {
                         assert (record.split().first.endsWith(":"));
                         // ignore header
                     }
                 } else {
                     value parts = record.split().sequence();
                     assert (exists method = parts[0]);
                     switch (method)
                     case ("GET") {
                         assert (exists p = parts[1],
                             exists version = parts[2],
                             !parts[3] exists);
                         assert (version in { "HTTP/1.0", "HTTP/1.1" });
                         path = p;
                     }
                     // TODO implement other methods if desired
                     else {
                         write("HTTP/1.0 501 Unsupported method ('``method``')", noop);
                         write("", close);
                     }
                 }
             }
             return [read, logAndAbort(`module`)];
         }
         fd = ...;
     };
Platform: JavaScript, Java
Packages
de.lucaswerkmeister.ceylond.recordBased

The main package.

Dependencies
de.lucaswerkmeister.ceylond.core1.0.0

The main package.

Aliases
ReadRecordCallbackshared ReadRecordCallback=> Anything(String)

A read callback, to be called with a record string when one full record has been read from the socket.

Functions
makeLineBasedInstanceSee makeRecordBasedInstance()
makeRecordBasedInstanceshared [ReadCallback, SocketExceptionHandler]? makeRecordBasedInstance([ReadRecordCallback, SocketExceptionHandler]? instance(void write(String|ByteBuffer content, WriteCallback callback), void close()), String recordSeparator = ..., Charset charset = ..., ErrorStrategy errorStrategy = ...)(void write(ByteBuffer content, WriteCallback callback), void close())

Create an instance for start that reads and writes String records, separated by a record separator, transferred over the socket using a charset with an error strategy.

Parameters:
  • instance

    This function is called whenever a new connection to the socket is opened. It works just like instance, except that write() also accepts a record (in which case it appends the record separator and encodes with the charset), and the read callback is only called with complete individual records.

  • recordSeparator = "\n"

    The record separator, which may be any nonempty String. The default is the newline (\n), so that a record is a line. Many internet protocols (e.��g. HTTP, SMTP, Telnet) use CRLF (\r\n).

    • Record separator must not be empty

  • charset = utf8

    The charset that is used to encode and decode records for transfer on the socket.

  • errorStrategy = strict

    The error strategy for the charset.

Aliases: makeLineBasedInstance
startLineBasedSee startRecordBased()
startRecordBasedshared void startRecordBased([ReadRecordCallback, SocketExceptionHandler]? instance(void write(String|ByteBuffer content, WriteCallback callback), void close()), Integer fd, ServerExceptionHandler handler = ..., Boolean concurrent = true, String recordSeparator = ..., Charset charset = ..., ErrorStrategy errorStrategy = ...)

Start listening on the socket, reading and writing records.

Usage example:

startRecordBased {
    function instance(void write(String record, WriteCallback callback), void close()) {
        write("Hello, World! Please supply your name.", noop);
        void read(String name) {
            write("Greetings, ``name``!", noop);
            write("Goodbye.", close);
        }
        return [read, logAndAbort(`module`)];
    }
    fd = switch (runtime.name) case ("jvm") 0 case ("node.js") 3 else -1;
};
Parameters:
Aliases: startLineBased