⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 select.c

📁 boa 一个简小的web服务器 资源占用极少
💻 C
字号:
/*
 *  Boa, an http server
 *  Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
 *  Some changes Copyright (C) 1996 Charles F. Randall <crandall@goldsys.com>
 *  Some changes Copyright (C) 1996 Larry Doolittle <ldoolitt@boa.org>
 *  Some changes Copyright (C) 1996-2002 Jon Nelson <jnelson@boa.org>
 *
 *  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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/* $Id: select.c,v 1.1.2.2 2002/07/23 15:54:52 jnelson Exp $*/

#include "boa.h"
/*-->changed by dxw 2005-10-23*/
extern int gflag;
extern time_t cgi_last_time;
/*<--*/

static void fdset_update(void);
fd_set block_read_fdset;
fd_set block_write_fdset;
static struct timeval req_timeout;     /* timeval for select */

void select_loop(int server_s)
{
    FD_ZERO(&block_read_fdset);
    FD_ZERO(&block_write_fdset);
    /* set server_s and req_timeout */
    req_timeout.tv_sec = (ka_timeout ? ka_timeout : REQUEST_TIMEOUT);
    req_timeout.tv_usec = 0l;   /* reset timeout */

    /* preset max_fd */
    max_fd = -1;

    while (1) {	 
        if (sighup_flag)
            sighup_run();
        if (sigchld_flag)
            sigchld_run();
        if (sigalrm_flag)
            sigalrm_run();

        if (sigterm_flag) {
            if (sigterm_flag == 1)
                sigterm_stage1_run(server_s);
            if (sigterm_flag == 2 && !request_ready && !request_block) {
                sigterm_stage2_run();
            }
        }

        /* reset max_fd */
        max_fd = -1;

	/*-->changed by dxw 2005-10-23*/
	if(gflag){
		time_t currenttime;
		(void) time(&currenttime);
		if(currenttime-cgi_last_time>=60)gflag=0;
	}
	/*<--*/

        if (request_block)
            /* move selected req's from request_block to request_ready */
            fdset_update();

        /* any blocked req's move from request_ready to request_block */
        process_requests(server_s);

        if (!sigterm_flag && total_connections < (max_connections - 10)) {
            BOA_FD_SET(server_s, &block_read_fdset); /* server always set */
        }

	/*-->changed by dxw 2005-10-23*/
	if(request_ready&&gflag){ /*还有其它cgi请求*/
		req_timeout.tv_sec=0;
		req_timeout.tv_usec=100;
	}
	else{
        req_timeout.tv_sec = (request_ready ? 0 :
                              (ka_timeout ? ka_timeout : REQUEST_TIMEOUT));
        req_timeout.tv_usec = 0l;   /* reset timeout */
	}
	/*<--*/

        if (select(max_fd + 1, &block_read_fdset,
                   &block_write_fdset, NULL,
                   (request_ready|| request_block ? &req_timeout : NULL)) == -1) {
            /* what is the appropriate thing to do here on EBADF */
            if (errno == EINTR)
                continue;   /* while(1) */
            else if (errno != EBADF) {
                DIE("select");
            }
        }

        time(&current_time);
        if (FD_ISSET(server_s, &block_read_fdset))
            pending_requests = 1;
    }
}

/*
 * Name: fdset_update
 *
 * Description: iterate through the blocked requests, checking whether
 * that file descriptor has been set by select.  Update the fd_set to
 * reflect current status.
 *
 * Here, we need to do some things:
 *  - keepalive timeouts simply close
 *    (this is special:: a keepalive timeout is a timeout where
       keepalive is active but nothing has been read yet)
 *  - regular timeouts close + error
 *  - stuff in buffer and fd ready?  write it out
 *  - fd ready for other actions?  do them
 */

static void fdset_update(void)
{
    request *current, *next;

    for(current = request_block;current;current = next) {		
        time_t time_since = current_time - current->time_last;
        next = current->next;

        /* hmm, what if we are in "the middle" of a request and not
         * just waiting for a new one... perhaps check to see if anything
         * has been read via header position, etc... */
       if (current->kacount < ka_max && /* we *are* in a keepalive */
            (time_since >= ka_timeout) && /* ka timeout */
            !current->logline)  /* haven't read anything yet */
    	{
		current->status = DEAD; /* connection keepalive timed out */
	}
       else if (time_since >= REQUEST_TIMEOUT) 
	{
            log_error_doc(current);
            fputs("connection timed out\n", stderr);		 
	     /*-->added by gxx 2007-03-05*/	
	    //如果不加以下条件,当修改系统时间的时候每次都会
	    //打出超时信息,为了避免,增加以下条件
	     if (time_since == REQUEST_TIMEOUT )
	     {
	     	char time_out_re[100] = "Request timed out!";
	     	int bytes_written = write(current->fd, time_out_re, sizeof(time_out_re));
	     }
	     if(time_since < 2*REQUEST_TIMEOUT)//当超过两分钟即认为是修改了系统时间
	     {
		 current->status = DEAD;//断掉连接
	      }
	     /*<--*/
        }
	   
        if (current->buffer_end && current->status < DEAD) {
            if (FD_ISSET(current->fd, &block_write_fdset))
                ready_request(current);
            else {
                BOA_FD_SET(current->fd, &block_write_fdset);
            }
        } else {
            switch (current->status) {
            case WRITE:
            case PIPE_WRITE:
                if (FD_ISSET(current->fd, &block_write_fdset))
                    ready_request(current);
                else {
                    BOA_FD_SET(current->fd, &block_write_fdset);
                }
                break;
            case BODY_WRITE:
                if (FD_ISSET(current->post_data_fd, &block_write_fdset))
                    ready_request(current);
                else {
                    BOA_FD_SET(current->post_data_fd, &block_write_fdset);
                }
                break;
            case PIPE_READ:
                if (FD_ISSET(current->data_fd, &block_read_fdset))
                    ready_request(current);
                else {
                    BOA_FD_SET(current->data_fd, &block_read_fdset);
                }
                break;
            case DONE:
                if (FD_ISSET(current->fd, &block_write_fdset))
                    ready_request(current);
                else {
                    BOA_FD_SET(current->fd, &block_write_fdset);
                }
                break;
            case DEAD:
                ready_request(current);
                break;
            default:
                if (FD_ISSET(current->fd, &block_read_fdset))
                    ready_request(current);
                else {
                    BOA_FD_SET(current->fd, &block_read_fdset);
                }
                break;
            }
        }
        current = next;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -