Network services

There are many times where you may want to open a port in Prosody from a module, and accept connections. This is done via 'net' providers.

The provider

The provider is just a simple table that contains info about the service.

Ports are a shared resource, so to avoid port conflicts with other modules in the same Prosody instance you should only add net providers from global or shared modules.

To add a provider, simply call:

    local my_listener = {}; -- Listener object, explained below
 
    module:provides("net", {
       default_port = 5432; -- Default port, can be overridden by config
       listener = my_listener;
    });

As always with module:provides(), you may set a 'name' field (not shown in the example). It is recommended not to - the current module's name will be used by default (with mod_ or mod_net_ stripped from the front).

After loading the example module above, you should be able to telnet into Prosody: telnet localhost 5432 . It will all be silent so far, so let's add some connection handling using that listener object we created.

The listener

The most important thing you'll need is a 'listener'. This is an object that implements a few standard functions that get called in response to events on the port. The most common functions you'll need are:

  • onconnect: A new incoming connection
  • onincoming: A connection sent some data
  • ondisconnect: A connection closed

An example of a basic listener:

    function my_listener.onconnect(conn)
        conn:write("Hello!\n");
    end
 
    function my_listener.onincoming(conn, data)
        conn:write("You said "..data.."\n");
    end
 
    function my_listener.ondisconnect(conn, err)
       module:log("info", "Connection closed: %s", err or "no error");
    end

After adding this to the module above, you should be able to telnet in, and type and receive responses.

Usually in anything more than a basic protocol you will want to keep track of what connections are open, and store some information about them. You can create a sessions table, and use the connection object as the index:

    local my_listener = {};
    local sessions = {};
 
    function my_listener.onconnect(conn)
        sessions[conn] = {};
        conn:write("Hello!\n");
    end
 
    function my_listener.onincoming(conn, data)
        local session = sessions[conn];
        local last_said = session.last_said;
        session.last_said = data; -- Save for next time
        if last_said then
            conn:write("But last time you said "..last_said.."\n");
        else
            conn:write("Ok.\n");
        end
    end
 
    function my_listener.ondisconnect(conn, err)
       sessions[conn] = nil; -- Don't forget this!
       module:log("info", "Connection closed: %s", err or "no error");
    end