NAL_LISTENER_NEW

Section: distcache (2)
Updated: 2004.03.23
Index Return to Main Contents
 

NAME

NAL_LISTENER_new, NAL_LISTENER_free, NAL_LISTENER_create - libnal listener functions  

SYNOPSIS

 #include <libnal/nal.h>

 NAL_LISTENER *NAL_LISTENER_new(void);
 void NAL_LISTENER_free(NAL_LISTENER *list);
 void NAL_LISTENER_reset(NAL_LISTENER *list);
 int NAL_LISTENER_create(NAL_LISTENER *list, const NAL_ADDRESS *addr);
 void NAL_LISTENER_add_to_selector(const NAL_LISTENER *list,
                                   NAL_SELECTOR *sel);
 void NAL_LISTENER_del_from_selector(const NAL_LISTENER *list,
                                     NAL_SELECTOR *sel);

 int NAL_LISTENER_set_fs_owner(NAL_LISTENER *list,
                               const char *ownername,
                               const char *groupname);
 int NAL_LISTENER_set_fs_perms(NAL_LISTENER *list,
                               const char *octal_string);

 

DESCRIPTION

NAL_LISTENER_new() allocates and initialises a new NAL_LISTENER object.

NAL_LISTENER_free() destroys a NAL_LISTENER object.

NAL_LISTENER_reset() will, if necessary, cleanup any prior state in list so that it can be reused in NAL_LISTENER_create(). Internally, there are other optimisations and benefits to using NAL_LISTENER_reset() instead of NAL_LISTENER_free() and NAL_LISTENER_new() - the implementation can try to avoid repeated reallocation and reinitialisation of state, only doing full cleanup and reinitialisation when necessary.

NAL_LISTENER_create() will attempt to create and bind a listener to the address represented by addr. Semantics of how this binding works with respect to exclusion of other listeners depends on the transport and host system. Generally, libnal should follow the standard behaviour of the underlying system.

NAL_LISTENER_add_to_selector() registers list with the selector sel for any events relevant to it. NAL_LISTENER_del_from_selector() can be used to reverse this if called before any subsequent call to NAL_SELECTOR_select().

NAL_LISTENER_set_fs_owner() and NAL_LISTENER_set_fs_perms() will only have meaning to listener objects created for address types that use the file-system (unix domain sockets). If ownername is non-NULL, the owner of the socket file is changed to the supplied user name. If groupname is non-NULL, the group of the socket file is changed to the supplied group name, and otherwise the group may be changed to the default group of the user ownername. octal_string is a base-8 number in string form specifying the permission flags to apply to the socket file, such as ``660'' for example.  

RETURN VALUES

NAL_LISTENER_new() returns a valid NAL_LISTENER object on success, NULL otherwise.

NAL_LISTENER_free(), NAL_LISTENER_reset(), NAL_LISTENER_add_to_selector(), and NAL_LISTENER_del_from_selector() have no return value.

All other NAL_LISTENER functions return zero for failure, and non-zero for success.  

EXAMPLES

A typical state-machine implementation that processes up to 10 connections at a time from a listener is illustrated here (without error-checking);

    NAL_CONNECTION *conn[10];
    int loop, conns_used = 0;
    NAL_SELECTOR *sel = NAL_SELECTOR_new();
    NAL_LISTENER *list = NAL_LISTENER_new();
    NAL_ADDRESS *addr = retrieve_the_desired_address();

    /* Setup */
    list = NAL_LISTENER_create(list, addr);
    conn[0] = NAL_CONNECTION_new();
    ...
    conn[9] = NAL_CONNECTION_new();

 loop:
    /* select for active connections and 'list' if we aren't full */
    if(conns_used < 10) NAL_LISTENER_add_to_selector(list, sel);
    for(loop = 0; loop < conns_used; loop++)
        NAL_CONNECTION_add_to_selector(conn[loop], sel);
    /* block on (relevant) network events */
    NAL_SELECTOR_select(sel);
    /* process active connections */
    for(loop = 0; loop < conns_used; loop++) {
        if(!NAL_CONNECTION_io(conn[loop], sel)) {
 user_disconnect:
            /* connection broken */
            NAL_CONNECTION_free(conn[loop]);
            /* shift the array left (if necessary) */
            if(loop < --conns_used)
                memmove(conn + loop, conn + (loop + 1),
                    (conns_used - loop) * sizeof(NAL_CONNECTION *));
            /* Recreate the empty connection slot */
            conn[conns_used] = NAL_CONNECTION_new();
            /* loop shouldn't be incremented in this case */
            loop--;
        } else {
            /* Do any logic required here using the connection's buffers and
             * disconnect if desired. */
            if(!do_user_logic(conn[loop]))
                goto user_disconnect;
        }
    }
    /* process incoming connections */
    if(NAL_CONNECTION_accept(conns[conns_used], list, sel))
        conns_used++;
    /* End of loop */
    goto loop;

The complication in the above example is mostly associated with maintaining the array of allocated NAL_CONNECTION objects, and keeping the active ones left-aligned in the array. A simpler example follows where it is assumed do_connection() is some function that will take a NAL_CONNECTION object, start a new thread for processing it, and clean up the connection object when finishing;

    NAL_CONNECTION *conn = NULL;
    NAL_SELECTOR *sel = NAL_SELECTOR_new();
    NAL_LISTENER *list = NAL_LISTENER_new();
    NAL_ADDRESS *addr = retrieve_the_desired_address();

    /* Setup */
    list = NAL_LISTENER_create(list, addr);

    while(1) {
        if(!conn) conn = NAL_CONNECTION_new();
        NAL_LISTENER_add_to_selector(list, sel);
        NAL_SELECTOR_select(sel);
        if(NAL_CONNECTION_accept(list, sel, conn)) {
            /* start worker thread for 'conn' */
            do_connection(conn);
            /* 'conn' is used, ensure a new one is created */
            conn = NULL;
        }
    }

 

SEE ALSO

NAL_ADDRESS_new(2) - Functions for the NAL_ADDRESS type.

NAL_CONNECTION_new(2) - Functions for the NAL_CONNECTION type.

NAL_SELECTOR_new(2) - Functions for the NAL_SELECTOR type.

NAL_BUFFER_new(2) - Functions for the NAL_BUFFER type.

distcache(8) - Overview of the distcache architecture.

http://www.distcache.org/ - Distcache home page.  

AUTHOR

This toolkit was designed and implemented by Geoff Thorpe for Cryptographic Appliances Incorporated. Since the project was released into open source, it has a home page and a project environment where development, mailing lists, and releases are organised. For problems with the software or this man page please check for new releases at the project web-site below, mail the users mailing list described there, or contact the author at geoff@geoffthorpe.net.

Home Page: http://www.distcache.org