Mostly commenting with a few bug fixes

r1543 | dcl | 2007-02-22 16:41:03 +1100 (Thu, 22 Feb 2007) | 2 lines
This commit is contained in:
Douglas Clowes
2007-02-22 16:41:03 +11:00
parent 405981c815
commit df3b2bc1da
2 changed files with 149 additions and 39 deletions

123
nwatch.c
View File

@@ -22,19 +22,29 @@
#define NWMAGIC 51966 #define NWMAGIC 51966
/* Net Watcher control structure */
typedef struct __netwatcher_s { typedef struct __netwatcher_s {
pNWContext cq_head; pNWContext cq_head; /* head of socket context queue */
pNWContext cq_tail; pNWContext cq_tail; /* tail of socket context queue */
pNWTimer tq_head; pNWTimer tq_head; /* head of timer context queue */
pNWTimer tq_tail; pNWTimer tq_tail; /* tail of timer context queue */
long lMagic; long lMagic; /* integrity check */
} NetWatch, *pNetWatch; } NetWatch, *pNetWatch;
/* Singleton pattern */
static pNetWatch instance = NULL; static pNetWatch instance = NULL;
static int NetWatchTask(void* pData); static int NetWatchTask(void* pData);
/**
* \brief Initialises the Net Watcher singleton and starts the task
*
* \return 1=success, 0=failure
*/
int NetWatchInit(void) { int NetWatchInit(void) {
/*
* If the singleton has not yet been created, do so now
*/
if (instance == NULL) { if (instance == NULL) {
instance = (pNetWatch) malloc(sizeof(NetWatch)); instance = (pNetWatch) malloc(sizeof(NetWatch));
if (instance == NULL) if (instance == NULL)
@@ -46,55 +56,78 @@ int NetWatchInit(void) {
return 1; return 1;
} }
/*
* The timer context object private definition
*/
typedef struct __netwatchtimer { typedef struct __netwatchtimer {
pNWTimer next; pNWTimer next; /* chain to next event */
struct timeval tv; struct timeval tv; /* time when event is due */
pNWCallback func; pNWCallback func; /* function to call */
void* cntx; void* cntx; /* abstract context to pass to callback */
long vrfy; long vrfy; /* integrity check */
} NWTimer; } NWTimer;
/*
* \brief private function to insert an entry into the sorted timer queue.
*
* \param self singleton
* \param handle new timer to insert
*/
static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle)
{ {
if (self->tq_head == NULL) /* empty */ /* if the queue is empty, just stick new one in */
if (self->tq_head == NULL) {
self->tq_head = self->tq_tail = handle; self->tq_head = self->tq_tail = handle;
else if (handle->tv.tv_sec > self->tq_tail->tv.tv_sec || return 1;
}
/* if new one is later than latest one, insert after latest */
if (handle->tv.tv_sec > self->tq_tail->tv.tv_sec ||
(handle->tv.tv_sec == self->tq_tail->tv.tv_sec && (handle->tv.tv_sec == self->tq_tail->tv.tv_sec &&
handle->tv.tv_usec >= self->tq_tail->tv.tv_usec)) { handle->tv.tv_usec >= self->tq_tail->tv.tv_usec)) {
/* after last entry */
self->tq_tail->next = handle; self->tq_tail->next = handle;
self->tq_tail = handle; self->tq_tail = handle;
} else if (handle->tv.tv_sec < self->tq_tail->tv.tv_sec || return 1;
(handle->tv.tv_sec == self->tq_tail->tv.tv_sec && }
handle->tv.tv_usec <= self->tq_tail->tv.tv_usec)) { /* if new one is earlier than earliest one, insert before earliest */
/* before first entry */ if (handle->tv.tv_sec < self->tq_head->tv.tv_sec ||
(handle->tv.tv_sec == self->tq_head->tv.tv_sec &&
handle->tv.tv_usec <= self->tq_head->tv.tv_usec)) {
handle->next = self->tq_head; handle->next = self->tq_head;
self->tq_head = handle; self->tq_head = handle;
} else { return 1;
/* start at the first entry */ }
else
{
/* must be in between two so start at the first entry */
pNWTimer pNxt = self->tq_head; pNWTimer pNxt = self->tq_head;
/* go until the one after is greater */ /* follow chain until the one after this one is greater than new one */
while (pNxt->next && while (pNxt->next &&
(handle->tv.tv_sec > pNxt->next->tv.tv_sec || (handle->tv.tv_sec > pNxt->next->tv.tv_sec ||
(handle->tv.tv_sec == pNxt->next->tv.tv_sec && (handle->tv.tv_sec == pNxt->next->tv.tv_sec &&
handle->tv.tv_usec > pNxt->next->tv.tv_usec))) handle->tv.tv_usec > pNxt->next->tv.tv_usec)))
pNxt = pNxt->next; pNxt = pNxt->next;
/* slip it in */ /* slip new one in between this one and the next one */
handle = pNxt->next; handle = pNxt->next;
pNxt->next = handle ; pNxt->next = handle ;
} }
return 1; return 1;
} }
/*
* \brief private function to remove an entry from the sorted timer queue.
*
* \param self singleton
* \param handle existing timer to remove
*/
static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle) static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle)
{ {
if (handle == self->tq_head) { /* if first */ /* handle the case of first and possibly only */
self->tq_head = self->tq_head->next; if (handle == self->tq_head) {
if (handle == self->tq_tail) /* if also last */ self->tq_head = self->tq_head->next; /* may be NULL */
if (handle == self->tq_tail)
self->tq_tail = NULL; self->tq_tail = NULL;
} }
else if (handle == self->tq_tail) /* if only last */ /* handle general case */
self->tq_tail = NULL;
else { else {
pNWTimer pNxt = self->tq_head; pNWTimer pNxt = self->tq_head;
while (pNxt) { while (pNxt) {
@@ -103,6 +136,9 @@ static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle)
break; break;
} }
} }
/* It it was the last entry, point tail to its predecessor */
if (handle == self->tq_tail)
self->tq_tail = pNxt;
} }
return 1; return 1;
} }
@@ -141,16 +177,23 @@ int NetWatchRemoveTimer(pNWTimer handle)
return 1; return 1;
} }
/* private data */
typedef struct __netwatchcontext { typedef struct __netwatchcontext {
pNWContext next; pNWContext next; /* chain pointer */
int sock; int sock; /* socket to watch */
int mode; int mode; /* read or write */
int actn; int actn; /* action being invoked on this pass */
pNWCallback func; pNWCallback func; /* user supplied callback function */
void* cntx; void* cntx; /* user supplied callback context */
long vrfy; long vrfy; /* integrity check */
} NWContext; } NWContext;
/**
* \brief private function to insert entry into unsorted queue
*
* \param self singleton
* \param handle entry to insert
*/
static int NetWatchContextInsQue(pNetWatch self, pNWContext handle) static int NetWatchContextInsQue(pNetWatch self, pNWContext handle)
{ {
if (self->cq_head == NULL) /* empty */ if (self->cq_head == NULL) /* empty */
@@ -162,6 +205,12 @@ static int NetWatchContextInsQue(pNetWatch self, pNWContext handle)
return 1; return 1;
} }
/**
* \brief private function to remove entry from unsorted queue
*
* \param self singleton
* \param handle entry to insert
*/
static int NetWatchContextRemQue(pNetWatch self, pNWContext handle) static int NetWatchContextRemQue(pNetWatch self, pNWContext handle)
{ {
if (handle == self->cq_head) { /* if first */ if (handle == self->cq_head) { /* if first */
@@ -169,8 +218,6 @@ static int NetWatchContextRemQue(pNetWatch self, pNWContext handle)
if (handle == self->cq_tail) /* if also last */ if (handle == self->cq_tail) /* if also last */
self->cq_tail = NULL; self->cq_tail = NULL;
} }
else if (handle == self->cq_tail) /* if only last */
self->cq_tail = NULL;
else { else {
pNWContext pNxt = self->cq_head; pNWContext pNxt = self->cq_head;
while (pNxt) { while (pNxt) {
@@ -179,6 +226,8 @@ static int NetWatchContextRemQue(pNetWatch self, pNWContext handle)
break; break;
} }
} }
if (handle == self->cq_tail) /* if last */
self->cq_tail = pNxt;
} }
return 1; return 1;
} }
@@ -228,6 +277,9 @@ int NetWatchSetMode(pNWContext handle, int mode)
return 1; return 1;
} }
/**
* \brief the registered SICS Task to drive all this
*/
int NetWatchTask (void* pData) int NetWatchTask (void* pData)
{ {
pNetWatch self = NULL; pNetWatch self = NULL;
@@ -239,6 +291,7 @@ int NetWatchTask (void* pData)
int iCount; int iCount;
pNWContext action[FD_SETSIZE]; pNWContext action[FD_SETSIZE];
/* Check the singleton */
self = (pNetWatch) instance; self = (pNetWatch) instance;
if(!self || self->lMagic != NWMAGIC) if(!self || self->lMagic != NWMAGIC)
return 0; return 0;

View File

@@ -10,24 +10,81 @@
#ifndef SICSNETWATCHER #ifndef SICSNETWATCHER
#define SICSNETWATCHER #define SICSNETWATCHER
#define DFC_NWATCH 1
#define nwatch_read 1 #define nwatch_read 1
#define nwatch_write 2 #define nwatch_write 2
/* the callback function */ /**
* \brief network or timer callback function
*
* \param context from the network/timer registration
* \param mode
* for network, nwatch_read or nwatch_write
* for timer, zero, reserved for future use
*
* \return normally zero, for future use
*/
typedef int (*pNWCallback)(void* context, int mode); typedef int (*pNWCallback)(void* context, int mode);
/* the timer methods */ /* the abstract timer object handle */
typedef struct __netwatchtimer *pNWTimer; typedef struct __netwatchtimer *pNWTimer;
/**
* \brief register a one-shot timer event
*
* \param handle pointer to location to receive the timer object handle
* \param mSec milliseconds after which the timer should expire
* \param callback function when timer expires
* \param context abstract context passed to callback function
* \return success=1, failure=0
*/
int NetWatchRegisterTimer(pNWTimer* handle, int mSec, int NetWatchRegisterTimer(pNWTimer* handle, int mSec,
pNWCallback callback, void* context); pNWCallback callback, void* context);
/**
* \brief remove a registered timer event
*
* \param handle from the timer registration
* \return success=1, failure=0
*/
int NetWatchRemoveTimer(pNWTimer handle); int NetWatchRemoveTimer(pNWTimer handle);
/* the socket methods */ /* the abstract socket object handle */
typedef struct __netwatchcontext *pNWContext; typedef struct __netwatchcontext *pNWContext;
/**
* \brief register a socket to be watched in read mode
*
* \param handle pointer to location to receive the socket object handle
* \param iSocket file descriptor number of the socket to watch
* \param callback function when socket readable/writeable
* \param context abstract context passed to callback function
* \return success=1, failure=0
*/
int NetWatchRegisterCallback(pNWContext* handle, int iSocket, int NetWatchRegisterCallback(pNWContext* handle, int iSocket,
pNWCallback callback, void* context); pNWCallback callback, void* context);
/**
* \brief remove a socket callback registration
*
* \param handle from the socket registration
* \return success=1, failure=0
*/
int NetWatchRemoveCallback(pNWContext handle); int NetWatchRemoveCallback(pNWContext handle);
/**
* \brief retrieve the mode of a socket callback registration
*
* \param handle from the socket registration
* \return 0=failure else the mode (read and/or write)
*/
int NetWatchGetMode(pNWContext handle); int NetWatchGetMode(pNWContext handle);
/**
* \brief set the mode of a socket callback registration
*
* \param handle from the socket registration
* \param mode read and/or write
* \return 0=failure, 1=success
*/
int NetWatchSetMode(pNWContext handle, int mode); int NetWatchSetMode(pNWContext handle, int mode);
#endif /* SICSNETWATCHER */ #endif /* SICSNETWATCHER */