/* Smaskwait.c: this file contains code which allows one to wait until data * is present given a mask * Authors: Charles E. Campbell, Jr. * Terry McRoberts * Copyright: Copyright (C) 1999-2005 Charles E. Campbell, Jr. {{{1 * Permission is hereby granted to use and distribute this code, * with or without modifications, provided that this copyright * notice is copied with it. Like anything else that's free, * Smaskwait.c is provided *as is* and comes with no warranty * of any kind, either expressed or implied. By using this * software, you agree that in no event will the copyright * holder be liable for any damages resulting from the use * of this software. * Date: Aug 22, 2005 */ #include #include "xtdio.h" #define SSLNEEDTIME #include "sockets.h" /* --------------------------------------------------------------------- * Local Variables: */ static int waitall = 0; static fd_set mask; /* mask last-used by Smaskwait, etc */ static struct timeval *timeptr = NULL; static struct timeval timewait; static fd_set rmask; /* set by Smaskwait */ static int first = 1; /* --------------------------------------------------------------------- * Local Prototypes: */ /* --------------------------------------------------------------------- * Source Code: */ /* Smaskwait: this function waits until some Socket specified to the * Smaskset() function receives something. * * Returns: < 0: error * ==0: timeout * > 0: communication data awaiting * * NOTE: THE MASK IS NOT RESET TO ZERO - THE MASK IS RETAINED!!! */ #ifdef __PROTOTYPE__ int Smaskwait() #else int Smaskwait() #endif { fd_set wmask; /* write mask */ fd_set emask; /* error mask */ short result; FD_ZERO(&wmask); FD_ZERO(&emask); /* test if something is available for reading on the socket. This form * will block (sleep) until something arrives */ rmask = mask; result = select(waitall, &rmask,&wmask,&emask,timeptr); if(result < 0) { /* error */ return result; } /* result > 0: socket has something waiting * result == 0: timeout */ return result; } /* --------------------------------------------------------------------- */ /* Smaskset: this function sets up the mask * A null skt clears the mask */ #ifdef __PROTOTYPE__ void Smaskset(Socket *skt) #else void Smaskset(skt) Socket *skt; #endif { if(first) { FD_ZERO(&mask); first= 0; } if(skt) { FD_SET(skt->skt,&mask); if(skt->skt >= waitall) waitall= skt->skt + 1; } else { waitall= 0; FD_ZERO(&mask); } } /* --------------------------------------------------------------------- */ /* Smaskfdset: this function sets up the mask with a "file descriptor" * which may be associated with devices other than Sockets */ #ifdef __PROTOTYPE__ void Smaskfdset(int fd) #else void Smaskfdset(fd) int fd; #endif { if(first) { FD_ZERO(&mask); first= 0; } if(0 <= fd && fd < FD_SETSIZE) { /* fd must be a legal file descriptor */ FD_SET(fd,&mask); if(fd >= waitall) waitall= fd + 1; } } /* --------------------------------------------------------------------- */ /* Smasktime: this function sets up a timeval structure - specifies a * time limit for waiting. Note: if seconds < 0 or useconds < 0, * or seconds == useconds == 0, then there will be no timeout waiting. */ #ifdef __PROTOTYPE__ void Smasktime(long seconds,long useconds) #else void Smasktime(seconds,useconds) long seconds; /* time in seconds */ long useconds; /* time in micro-seconds */ #endif { if(seconds < 0 || useconds < 0 || (seconds == 0 && useconds == 0)) { /* no timeout (ie. infinite wait) */ timewait.tv_sec = 0L; timewait.tv_usec= 0L; timeptr = (struct timeval *) NULL; } else { /* set up specified timeout */ timewait.tv_sec = seconds; timewait.tv_usec= useconds; timeptr = &timewait; } } /* --------------------------------------------------------------------- */ /* Smasktest: this function allows one to test if any Socket in the * mask has something on it * Returns: < 0: error * ==0: timeout * > 0: communication data awaiting */ int Smasktest() { int ret; struct timeval timewait_hold; struct timeval *timeptr_hold=NULL; /* save current time info */ timewait_hold = timewait; timeptr_hold = timeptr; /* set up for new time info */ timewait.tv_sec = 0L; timewait.tv_usec= 0L; timeptr = &timewait; ret= Smaskwait(); /* restore time info */ timewait= timewait_hold; timeptr = timeptr_hold; return ret; } /* --------------------------------------------------------------------- */ /* Smaskunset: this function sets up the mask * A null skt clears the mask */ #ifdef __PROTOTYPE__ void Smaskunset(Socket *skt) #else void Smaskunset(skt) Socket *skt; #endif { if(skt) { FD_CLR(skt->skt,&mask); } else { waitall= 0; FD_ZERO(&mask); } } /* --------------------------------------------------------------------- */ /* Smaskunfdset: this function sets up the mask * A null skt clears the mask */ #ifdef __PROTOTYPE__ void Smaskunfdset(int fd) #else void Smaskunfdset(fd) int fd; #endif { if(fd) FD_CLR(fd,&mask); else { waitall= 0; FD_ZERO(&mask); } } /* --------------------------------------------------------------------- */ /* Smaskget: this function returns the current mask */ #ifdef __PROTOTYPE__ Smask Smaskget() #else Smask Smaskget() #endif { Smask smask; smask.mask = mask; smask.waitall= waitall; return smask; } /* --------------------------------------------------------------------- */ /* Smaskuse: this function sets up the mask with the provided mask */ #ifdef __PROTOTYPE__ void Smaskuse(Smask usermask) #else void Smaskuse(usermask) Smask usermask; #endif { mask = usermask.mask; waitall= usermask.waitall; } /* --------------------------------------------------------------------- */ typedef struct MaskStack_str MaskStack; struct MaskStack_str { Smask mask; MaskStack *nxt,*prv; }; static MaskStack *mshd=NULL,*mstl=NULL; /* Smaskpush: this function pushes the current mask down on a stack * ALSO: the current mask is *cleared*!!! */ void Smaskpush() { MaskStack *m; /* allocate */ m= (MaskStack *) malloc(sizeof(MaskStack)); /* link */ if(mstl) mstl->nxt= m; else mshd = m; m->prv= mstl; mstl = m; /* initialize */ mstl->mask.mask = mask; mstl->mask.waitall= waitall; Smaskset((Socket *) NULL); } /* --------------------------------------------------------------------- */ /* Smaskpop: this function pops the stack (or, if the stack is empty, * it will set the current mask to null) */ void Smaskpop() { if(mstl) { MaskStack *old=mstl; Smaskuse(mstl->mask); /* delink current tail */ if(mstl->prv) mstl->prv->nxt= NULL; else mshd = NULL; mstl= mstl->prv; free((char *) old); } else Smaskset((Socket *) NULL); } /* --------------------------------------------------------------------- */ /* Smaskisset: this function tests if a specific Socket is read-ready. * Assumption: function is called after a Smaskwait() so that the * rmask has been set up. */ #ifdef __PROTOTYPE__ int Smaskisset(Socket *skt) #else int Smaskisset(skt) Socket *skt; #endif { return FD_ISSET(skt->skt,&rmask); } /* --------------------------------------------------------------------- */ /* Smaskfdisset: this function tests if a specific file descriptor is * read-ready */ #ifdef __PROTOTYPE__ int Smaskfdisset(int fd) #else int Smaskfdisset(fd) int fd; #endif { return FD_ISSET(fd,&rmask); } /* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- * vim: ts=4 */