Filter:   InfoImg
download s_bsd_select.c
Language: C
License: GPL
Copyright: (C) 2002 Hybrid Development Team
LOC: 130
Project Info
NeoStats
Server: SourceForge
Type: cvs
...stats\neostats\NeoIRCd\src\
   .cvsignore
   .depend
   adns.c
   balloc.c
   channel.c
   channel_mode.c
   class.c
   client.c
   cloak.c
   crypt.c
   descrip.mms
   dynlink.c
   event.c
   fdlist.c
   fileio.c
   getopt.c
   hash.c
   hook.c
   hostmask.c
   irc_string.c
   ircd.c
   ircd_parser.y
   ircd_signal.c
   ircdauth.c
   kdparse.c
   linebuf.c
   list.c
   listener.c
   m_error.c
   Makefile.in
   match.c
   md5.c
   memory.c
   messages.tab
   modules.c
   motd.c
   numeric.c
   packet.c
   parse.c
   restart.c
   resv.c
   rsa.c
   s_auth.c
   s_bsd.c
   s_bsd_devpoll.c
   s_bsd_kqueue.c
   s_bsd_poll.c
   s_bsd_select.c
   s_bsd_sigio.c
   s_conf.c
   s_debug.c
   s_gline.c
   s_log.c
   s_misc.c
   s_serv.c
   s_stats.c
   s_user.c
   scache.c
   send.c
   snprintf.c
   sprintf_irc.c
   ssl.c
   tools.c
   version.c.SH
   whowas.c

/*
 *  NeoIRCd: NeoStats Group. Based on Hybird7
 *  s_bsd_select.c: select() compatible network routines.
 *
 *  Originally by Adrian Chadd <adrian@creative.net.au>
 *  Copyright (C) 2002 Hybrid Development Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 *  USA
 *
 *  $Id: s_bsd_select.c,v 1.4 2003/01/29 09:28:50 fishwaldo Exp $
 */

#include "config.h"

#ifdef USE_SELECT
#include "stdinc.h"
#include "fdlist.h"
#include "s_bsd.h"
#include "class.h"
#include "client.h"
#include "common.h"
#include "irc_string.h"
#include "ircdauth.h"
#include "ircd.h"
#include "list.h"
#include "listener.h"
#include "numeric.h"
#include "packet.h"
#include "res.h"
#include "restart.h"
#include "s_auth.h"
#include "s_conf.h"
#include "s_log.h"
#include "s_serv.h"
#include "s_stats.h"
#include "send.h"
#include "s_debug.h"
#include "s_bsd.h"
#include "memory.h"


#if HARD_FDLIMIT_ >= FD_SETSIZE
#error HARD_FDLIMIT_ must be less than FD_SETSIZE(try using poll instead of select)
#endif
/*
 * Note that this is only a single list - multiple lists is kinda pointless
 * under select because the list size is a function of the highest FD :-)
 *   -- adrian
 */

fd_set select_readfds;
fd_set select_writefds;

/*
 * You know, I'd rather have these local to comm_select but for some
 * reason my gcc decides that I can't modify them at all..
 *   -- adrian
 */
fd_set tmpreadfds;
fd_set tmpwritefds;

static void select_update_selectfds(int fd, short event, PF *handler);

/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
/* Private functions */

/*
 * set and clear entries in the select array ..
 */ 
static void
select_update_selectfds(int fd, short event, PF *handler)
{  
    /* Update the read / write set */
    if (event & COMM_SELECT_READ) {
        if (handler)
            FD_SET(fd, &select_readfds);
        else
            FD_CLR(fd, &select_readfds);
    }
    if (event & COMM_SELECT_WRITE) {
        if (handler)
            FD_SET(fd, &select_writefds);
        else
            FD_CLR(fd, &select_writefds);
    }
}


/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
/* Public functions */


/*
 * init_netio
 *
 * This is a needed exported function which will be called to initialise
 * the network loop code.
 */
void init_netio(void)
{
    FD_ZERO(&select_readfds);
    FD_ZERO(&select_writefds);
}

/*
 * comm_setselect
 *
 * This is a needed exported function which will be called to register
 * and deregister interest in a pending IO state for a given FD.
 */
void
comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler,
    void *client_data, time_t timeout)
{  
    fde_t *F = &fd_table[fd];
    assert(fd >= 0);
    assert(F->flags.open);

#ifdef NOTYET
    debug(5, 5) ("commSetSelect: FD %d type %d, %s\n", fd, type, handler ? "SET"
 : "CLEAR");
#endif
    if (type & COMM_SELECT_READ) {
        F->read_handler = handler;
        F->read_data = client_data;
        select_update_selectfds(fd, COMM_SELECT_READ, handler);
    }
    if (type & COMM_SELECT_WRITE) {
        F->write_handler = handler;
        F->write_data = client_data;
        select_update_selectfds(fd, COMM_SELECT_WRITE, handler);
    }
    if (timeout)
        F->timeout = CurrentTime + (timeout / 1000);
}
 
/*
 * Check all connections for new connections and input data that is to be
 * processed. Also check for connections with data queued and whether we can
 * write it out.
 */

/*
 * comm_select
 *
 * Do IO events
 */

int
comm_select(unsigned long delay)
{
    int num;
    int fd;
    PF *hdl;
    fde_t *F;
    struct timeval to;

    /* Copy over the read/write sets so we don't have to rebuild em */
    memcpy(&tmpreadfds, &select_readfds, sizeof(fd_set));
    memcpy(&tmpwritefds, &select_writefds, sizeof(fd_set));

    for (;;) {
        to.tv_sec = 0;
        to.tv_usec = delay * 1000;
        num = select(highest_fd + 1, &tmpreadfds, &tmpwritefds, NULL, &to);
        if (num >= 0)
            break;
        if (ignoreErrno(errno))
            continue;
        set_time();
        /* error! */
        return -1;
        /* NOTREACHED */
    }
    callbacks_called += num;
    set_time();

    if (num == 0)
        return 0;

    /* XXX we *could* optimise by falling out after doing num fds ... */
    for (fd = 0; fd < highest_fd + 1; fd++) {
        F = &fd_table[fd];

        if (FD_ISSET(fd, &tmpreadfds)) {
            hdl = F->read_handler;
            F->read_handler = NULL;
            select_update_selectfds(fd, COMM_SELECT_READ, NULL);
            if (!hdl) {
                /* XXX Eek! This is another bad place! */
            } else {
                hdl(fd, F->read_data);
            }
        }
        if (FD_ISSET(fd, &tmpwritefds)) {
            hdl = F->write_handler;
            F->write_handler = NULL;
            select_update_selectfds(fd, COMM_SELECT_WRITE, NULL);
            if (!hdl) {
                /* XXX Eek! This is another bad place! */
            } else {
                hdl(fd, F->write_data);
            }
        }
    }
    return 0;
}

#else /* USE_SELECT */
/**
 * Don't let an empty compilation unit slip through.
 */
static int dummy;
#endif /* USE_SELECT */