AgNet - silverware Networking Interface Kit

by silver Harloe

Doc Index / ClientKey Specification

ClientKey Implementations

Perl

C - clientkey.[ch], clientlist.[ch]

(incomplete, does not cover lists yet)

Unless you're writing a listener or editing the multiplexer, all you need to know about ClientKeys is how to receive them, use them as hash keys, and pass them back out. So here's how to do those steps in C. The one thing to keep in mind is that no ClientKey in C is ever mallocd by the libraries provided, and so most of these functions require a client key as a 'buffer'. The buffer can and probably will be modified to nonsense if the function returns an error, so always check the return value before trusting the buffer. The type of ClientKeys is 'struct clientkey'.

When you know a message argument is supposed to be a ClientKey (and you aren't using the base server, which does this for you), this will get the ClientKey:


    struct clientkey ckbuffer, *ckptr;

    ckptr = msg2ck(&ckbuffer, decomposedmessagebuffer.arg1len, 
                   decomposedmessagebuffer.arg1);
    if (ckptr == NULL) {
        /* error condition handling here */
    }

To pass a client key into a message (assuming you aren't using one of the handy methods in serverfuncs.c which composes a message given a 'struct clientkey *' argument directly):


    /* assuming int msgid, struct clientkey *ckptr. Use &ckbuffer if you
       do not already have a pointer. */
    char ckmessagebuf[CLIENTKEY_MSGBUF_SIZE];

    composebinarymessage(msgid, 
                         ck2msg_size(ckptr), ck2msg(ckmessagebuf, ckptr),
                         0, NULL, 0, NULL, 0, NULL); /* or other args,
                                                        as needed, of course */

Finally, given a ClientKey, this is how you get the 'string form' which makes a great hash key (or something to print to debugging logs):


    /* assuming struct clientkey *ckptr. Use &ckbuffer if you do not already 
       have a pointer. */
    char ckidbuf[CLIENTKEY_STRINGBUF_SIZE], *ckidptr;

    if ((ckidptr = ck2string(ckidbuf, ckptr)) == NULL) {
        /* error condition handling here */
    }

You can copy a and compare ClientKeys with the following code bits. There currently no notion of ordering ClientKeys (as hash keys, they do not need an ordering).


    /* assuming struct clientkey *ckptr. Use &ckbuffer if you do not already 
       have a pointer. */
    struct clientkey newckbuffer, *newckptr;

    if ((newckptr = copy_ck(&newckbuffer, ckptr)) == NULL) {
        /* error condition handling here */
    }

    if (ck_equals(ckptr, newckptr) == 0) {
        /* copy failed in a more interesting way */
    }

When writing a listener, if you get a client key, you probably want to do the the following. The important functions are 'ck_numlevels' and 'ck_top_level'.


    struct clientkey ckbuffer, *ckptr;
    int realclientnumber = -1, listnumber = -1;

    ckptr = msg2ck(&ckbuffer, decomposedmessagebuffer.arg1len, 
                   decomposedmessagebuffer.arg1);
    if (ckptr == NULL) {
        /* error condition handling here */
    }
    
    if (ck_numlevels(ckptr) == 1) {
        realclientnumber = ck_top_level(ckptr);       
    } else if ((ck_numlevels(ckptr) == 2) && (ck_top_level(ckptr) == 255)) {
        ck_drop_level(ckptr);
	listnumber = ck_top_level(ckptr);
    } else {
        /* error - clientkey on listener must be a list or only have 1 level */
    }

The other thing you'll need to do when writing a listener is turn your base integers representing end-user ids into ClientKeys to pass up to the multiplexer. This is accomplished thusly:


    /* assuming int userid */
    struct clientkey ckbuffer, *ckptr;

    ckptr = new_ck(&ckbuffer, userid);
    if (ckptr == NULL) {
        /* error condition handling here */
    }

When working on the multiplexer, there will be some amount of dropping levels from ClientKeys before passing them along to listeners. There is a function 'ck_can_drop_a_level' for checking validity there, and a more complicated function 'ck_remainder' which takes a new buffer and returns a new ClientKey with one fewer levels than the passed in ClientKey. When passing ClientKeys back up to the multiplexer, the inverse functions 'ck_can_add_a_level' and 'ck_add_level' will be used (since there is no copy-while-adding operation corresponding to 'ck_remainder', one will have to use 'copy_ck', as shown above, first). Relevant sample code can be found in the multiplexer by searching for those function names.

Perl - ClientKey.pm

Doc Index / ClientKey Specification


This project is hosted by sourceforge.net: SourceForge.net Logo project homepage silver's homepage