Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

291 lines (224 sloc) 6.257 kB
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Cherokee
*
* Authors:
* Alvaro Lopez Ortega <alvaro@alobbs.com>
*
* Copyright (C) 2001-2011 Alvaro Lopez Ortega
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "common-internal.h"
#include "fdpoll-protected.h"
#include <errno.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#ifndef INFTIM
# define INFTIM -1
#endif
/***********************************************************************/
/* This fdpoll backend is based on the select() one.. */
/* */
/* Windows lacks of getrlimit() and setrlimit(), so it isn't possible */
/* to know the length of the arrays inside the fdpoll object. This is */
/* basically a broken implementation of fdpoll-select.. suitable for */
/* for Windows boxes. */
/* */
/***********************************************************************/
typedef struct {
struct cherokee_fdpoll poll;
fd_set master_rfdset;
fd_set master_wfdset;
fd_set working_rfdset;
fd_set working_wfdset;
int *select_fds;
int maxfd;
int maxfd_recompute;
} cherokee_fdpoll_select_t;
static ret_t
_free (cherokee_fdpoll_select_t *fdp)
{
if (fdp == NULL)
return ret_ok;
/* ANSI C required, so that free() can handle NULL pointers
*/
free (fdp->select_fds);
/* Caller has to set this pointer to NULL.
*/
free (fdp);
return ret_ok;
}
static ret_t
_add (cherokee_fdpoll_select_t *fdp, int fd, int rw)
{
cherokee_fdpoll_t *nfd = FDPOLL(fdp);
/* Check the fd limit
*/
if (cherokee_fdpoll_is_full(FDPOLL(fdp))) {
PRINT_ERROR_S("win32_add: fdpoll is full !\n");
return ret_error;
}
fdp->select_fds[nfd->npollfds] = fd;
switch (rw) {
case FDPOLL_MODE_READ:
FD_SET (fd, &fdp->master_rfdset);
break;
case FDPOLL_MODE_WRITE:
FD_SET (fd, &fdp->master_wfdset);
break;
default:
break;
}
if (fd > fdp->maxfd) {
fdp->maxfd = fd;
}
nfd->npollfds++;
return ret_ok;
}
static ret_t
_del (cherokee_fdpoll_select_t *fdp, int fd)
{
cherokee_fdpoll_t *nfd = FDPOLL(fdp);
int i;
for (i=0; i < nfd->npollfds; i++) {
if (fdp->select_fds[i] != fd)
continue;
nfd->npollfds--;
fdp->select_fds[i] = fdp->select_fds[nfd->npollfds];
fdp->select_fds[nfd->npollfds] = -1;
FD_CLR (fd, &fdp->master_rfdset);
FD_CLR (fd, &fdp->master_wfdset);
if (fd >= fdp->maxfd) {
fdp->maxfd_recompute = 1;
}
return ret_ok;
}
PRINT_ERROR ("Couldn't remove fd %d\n", fd);
return ret_error;
}
static ret_t
_set_mode (cherokee_fdpoll_select_t *fdp, int fd, int rw)
{
ret_t ret;
ret = _del (fdp, fd);
if (unlikely(ret < ret_ok))
return ret;
return _add (fdp, fd, rw);
}
static int
_check (cherokee_fdpoll_select_t *fdp, int fd, int rw)
{
switch (rw) {
case FDPOLL_MODE_READ:
return FD_ISSET (fd, &fdp->working_rfdset);
case FDPOLL_MODE_WRITE:
return FD_ISSET (fd, &fdp->working_wfdset);
}
return 0;
}
static int
select_get_maxfd (cherokee_fdpoll_select_t *fdp)
{
cherokee_fdpoll_t *nfd = FDPOLL(fdp);
if (fdp->maxfd_recompute) {
int i;
fdp->maxfd = -1;
for (i = 0; i < nfd->npollfds; i++) {
if (fdp->select_fds[i] > fdp->maxfd ) {
fdp->maxfd = fdp->select_fds[i];
}
}
fdp->maxfd_recompute = 0;
}
return fdp->maxfd;
}
static int
_watch (cherokee_fdpoll_select_t *fdp, int timeout_msecs)
{
int mfd, r;
struct timeval timeout;
fdp->working_rfdset = fdp->master_rfdset;
fdp->working_wfdset = fdp->master_wfdset;
mfd = select_get_maxfd(fdp);
if (mfd < 0)
sleep(1);
if (timeout_msecs == INFTIM) {
r = select (mfd + 1, &fdp->working_rfdset, &fdp->working_wfdset, NULL, NULL);
} else {
timeout.tv_sec = timeout_msecs / 1000L;
timeout.tv_usec = ( timeout_msecs % 1000L ) * 1000L;
r = select (mfd + 1, &fdp->working_rfdset, &fdp->working_wfdset, NULL, &timeout);
}
return r;
}
static ret_t
_reset (cherokee_fdpoll_select_t *fdp, int fd)
{
return ret_ok;
}
ret_t
fdpoll_win32_get_fdlimits (cuint_t *system_fd_limit, cuint_t *fd_limit)
{
*system_fd_limit = 0;
*fd_limit = FD_SETSIZE;
return ret_ok;
}
ret_t
fdpoll_win32_new (cherokee_fdpoll_t **fdp, int system_fd_limit, int fd_limit)
{
int i;
cherokee_fdpoll_t *nfd;
CHEROKEE_CNEW_STRUCT (1, n, fdpoll_select);
/* Verify that the max. number of selectable fds
* is below the max. acceptable limit per select set.
*/
if (fd_limit > FD_SETSIZE) {
_free(n);
return ret_error;
}
nfd = FDPOLL(n);
/* Init base class properties
*/
nfd->type = cherokee_poll_win32;
nfd->nfiles = fd_limit;
nfd->system_nfiles = system_fd_limit;
nfd->npollfds = 0;
/* Init base class virtual methods
*/
nfd->free = (fdpoll_func_free_t) _free;
nfd->add = (fdpoll_func_add_t) _add;
nfd->del = (fdpoll_func_del_t) _del;
nfd->reset = (fdpoll_func_reset_t) _reset;
nfd->set_mode = (fdpoll_func_set_mode_t) _set_mode;
nfd->check = (fdpoll_func_check_t) _check;
nfd->watch = (fdpoll_func_watch_t) _watch;
/* Init properties
*/
FD_ZERO (&n->master_rfdset);
FD_ZERO (&n->master_wfdset);
n->select_fds = (int*) calloc(nfd->nfiles, sizeof(int));
n->maxfd = -1;
n->maxfd_recompute = 0;
if (n->select_fds == NULL) {
_free (n);
return ret_nomem;
}
for (i = 0; i < nfd->nfiles; ++i) {
n->select_fds[i] = -1;
}
*fdp = nfd;
return ret_ok;
}
Jump to Line
Something went wrong with that request. Please try again.