Handler Functions

Description

To assist with the standard state machines, the SwitchKit API allows for incoming messages to be automatically dispatched to an application that has assigned handler functions. Using these functions, you can install functions to handle state transitions. In this way, you can avoid using multiple threads to manage different ports, because SwitchKit handles that automatically.

Important! When you write you handler functions, make sure that you register for the right sk_rcvAndDispatch() function.

Definition of Handler Functions

typedef struct {

MsgStruct *IncomingMsg;

MsgStruct *AckedMsg;

void *UserData;

} SK_Event;

Syntax

int HandlerFunc(SK_Event *evt, void *tag);

How Applications use Handler Functions

There are four ways that an application can specify the handler function that is dispatched. Three of them deal with switch-initiated messages, and the fourth deals with acknowledgments to host-initiated messages.

By using the following handler functions, SwitchKit can take care of the bookkeeping associated with a state machine. Context associated with a call is passed from one state to the next through the tag, and all acknowledgments are augmented by a pointer to the original message.

Switch-Initiated

sk_setChannelHandler();

sk_pushChannelHandler();

sk_setGroupHandler();

Acknowledgment to Host-Initiated

sk_sendMessageWithHandler();

Default Handler Functions

The default handler functions can be used to set up default handlers, to be called if no other handler is appropriate. For example, if sk_rcvAndDispatch() returned SK_NOT_HANDLED, you can add a default handler. This function can be used to set up handlers for Inter Application messages, switch-initiated messages such as polls and alarms, or as acknowledgments to any message that was sent without an explicitly-specified handler for its acknowledgment.

Default Handlers

sk_setDefaultHandler();

sk_pushDefaultHandler();

sk_popDefaultHandler();

sk_removeDefaultHandler();

 

Important! If the SK_HANDLER_BEHAVIOR bit mask has the SK_HDLR_BHVR_SAFETY_NET bit set, the default handler can also be invoked if the appropriate handler is found but returns SK_NOT_HANDLED.

Handler Function Stacks

For simple applications, it is usually sufficient to have just a single handler function associated with any channel. For more complicated applications, more power is often needed. SwitchKit allows a stack of handlers to be associated with a channel. These facilities are demonstrated in the callcard.c application included in the distribution. Multiple handler functions can be added onto a channel’s handler function stack. When a switch-initiated message arrives on that channel, the most recently added handler is called first. That handler can choose to not handle the message by returning SK_NOT_HANDLED, in which case the next handler on the stack is called.

The SK_Event that is passed to the handler function contains a UserData field. This field can be used to pass information within the stack of handler functions that are called for a single event. It is initialized to NULL.

By using a stack of handlers, a series of specialized handlers can be added that only handle a small set of messages. The first handler that is added should be a generic handler, to handle all messages that haven’t been handled at a lower level. Lower level handlers can set some state information in the UserData field of the SK_Event in order to communicate that part of an otherwise unhandled message has been processed.

Example

The sk_pushChannelHandler()function pushes the handler function, aHandlerFunc, onto the handler stack for the specified span and channel.

The sk_popChannelHandler() function removes the top of the Handler Stack for this span, channel and sets aHandlerFunc to point to this function.

The sk_removeChannelHandler() function removes the specific Handler Function, aHandlerFunc from the stack for this span, channel.

sk_pushHandler(span,chan,genericHandler);

sk_pushHandler(span,chan,h);

int genericHandler(SK_Event *e, void *tag)

{

MsgStruct *m = e->IncomingMsg;

bool beenPrinted = (bool)e->UserData;

if (!beenPrinted) {

e->UserData = (void *)1;

printMessage(m);

}

printf ("Unhandled message %s\n",sk_getMsgName(m));

}

int h(SK_Event *e, void *tag)

{

MsgStruct *m = e->IncomingMsg;

bool beenPrinted = (bool)e->UserData;

if (!beenPrinted) {

e->UserData = (void *)1;

printMessage(m);

}

SK_MSG_SWITCH(m)

{

CASE_RequestForService(rfs)

{

handleRFS(rfs);

return OK;

}

} SK_END_SWITCH;

return SK_NOT_HANDLED;

}