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

📄 httpd.c

📁 网络流量采集及分析软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*! \file   httpd.c  Based on webfs Copyright (C) 1999-2001  Gerd Knorr  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 with  the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL;  if not, write to the Free Software Foundation, Inc., 59 Temple Place,  Suite 330, Boston, MA  02111-1307  USA  Description:  httpd main functions  $Id: httpd.c,v 1.1.1.1 2004/12/23 05:52:34 s_zander Exp $*/#include "config.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <signal.h>#include <syslog.h>#include <fcntl.h>#include <time.h>#include <pwd.h>#include <grp.h>#include <sys/time.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/signal.h>#include <sys/utsname.h>#include <sys/socket.h>#include <sys/un.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <arpa/inet.h>#include <netdb.h>#include "httpd.h"/* public variables - server configuration *//* mime definitions */#define MIMEFILE "/etc/mime.types"/* configuration */static int     timeout        = 60; /* network timeout */static int     keepalive_time = 5;  /* keepalive time for connections */static char    *mimetypes     = MIMEFILE;static int     max_conn       = 32; /* max simulatneous connections *//* globals */static int     tcp_port       = 0;  /* port number */static char    server_host[256];    /* server name */static int     slisten = -1;/* connection list */static struct REQUEST *conns = NULL;/* number of connections */static int curr_conn = 0;#ifdef HTTPD_USE_THREADSstatic int       nthreads = 1;static pthread_t *threads;#endif/* public stuff */char    *server_name = NULL; /* our name used in responses */time_t  now = 0;#ifdef USE_SSLint	with_ssl = 0;#endif/* callback functions */access_check_func_t access_check_func = NULL;parse_request_func_t parse_request_func = NULL;log_request_func_t log_request_func = NULL;log_error_func_t log_error_func = NULL;/* queue a OK response for request req   */int httpd_send_response(struct REQUEST *req, fd_sets_t *fds){    time_t now;    if (req->body != NULL) {        now = time(NULL);        req->lbody = strlen(req->body);        /* 200 OK */        mkheader(req,200,now);    } else {        mkerror(req,500,1);    }    if (req->state == STATE_WRITE_HEADER) {        // switch to writing        FD_CLR(req->fd, &fds->rset);        FD_SET(req->fd, &fds->wset);    }    return 0;}  /* immediatly send back an OK response to request req   can be used for short transactions which require no   further processing of the app */int httpd_send_immediate_response(struct REQUEST *req){    time_t now;    if (req->body != NULL) {        now = time(NULL);        req->lbody = strlen(req->body);        /* 200 OK */        mkheader(req,200,now);    } else {        mkerror(req,500,1);    }    return 0;}    /* handle a file descriptor event */int httpd_handle_event(fd_set *rset, fd_set *wset, fd_sets_t *fds){       struct REQUEST      *req, *prev, *tmp;    int                 length;    int opt = 0;       now = time(NULL);    /* new connection ? */    if ((rset != NULL) && FD_ISSET(slisten, rset)) {        req = malloc(sizeof(struct REQUEST));        if (NULL == req) {            /* oom: let the request sit in the listen queue */#ifdef DEBUG            fprintf(stderr,"oom\n");#endif        } else {            memset(req,0,sizeof(struct REQUEST));            if ((req->fd = accept(slisten,NULL,&opt)) == -1) {                if (EAGAIN != errno) {                    log_error_func(1, LOG_WARNING,"accept",NULL);                }                free(req);            } else {                fcntl(req->fd,F_SETFL,O_NONBLOCK);                req->bfd = -1;                req->state = STATE_READ_HEADER;                req->ping = now;                req->lifespan = -1;                req->next = conns;                conns = req;                curr_conn++;#ifdef DEBUG                fprintf(stderr,"%03d/%d: new request (%d)\n",req->fd,req->state,curr_conn);#endif#ifdef USE_SSL                if (with_ssl) {                    open_ssl_session(req);                }#endif                length = sizeof(req->peer);                if (getpeername(req->fd,(struct sockaddr*)&(req->peer),&length) == -1) {                    log_error_func(1, LOG_WARNING,"getpeername",NULL);                    req->state = STATE_CLOSE;                }                getnameinfo((struct sockaddr*)&req->peer,length,                            req->peerhost,64,req->peerserv,8,                            NI_NUMERICHOST | NI_NUMERICSERV);#ifdef DEBUG                fprintf(stderr,"%03d/%d: connect from (%s)\n",                        req->fd,req->state,req->peerhost);#endif                /* host auth callback */                if (access_check_func != NULL) {                    if (access_check_func(req->peerhost, NULL) < 0) {                        /* read request */                        read_header(req,0);                        req->ping = now;                        /* reply with access denied and close connection */                        mkerror(req,403,0);                        write_request(req);	                             req->state = STATE_CLOSE;                    }                }	                 FD_SET(req->fd, &fds->rset);                 if (req->fd > fds->max) {                    fds->max = req->fd;                }            }        }    }        /* check active connections */    for (req = conns, prev = NULL; req != NULL;) {        /* I/O */        if ((rset != NULL) && FD_ISSET(req->fd, rset)) {            if (req->state == STATE_KEEPALIVE) {                req->state = STATE_READ_HEADER;            }            if (req->state == STATE_READ_HEADER) {                while (read_header(req,0) > 0);            }                      if (req->state == STATE_READ_BODY) {                while (read_body(req, 0) >0);            }                        req->ping = now;        }              if ((wset != NULL) && FD_ISSET(req->fd, wset)) {            write_request(req);            req->ping = now;        }        /* check timeouts */        if (req->state == STATE_KEEPALIVE) {            if (now > req->ping + keepalive_time ||                curr_conn > max_conn * 9 / 10) {#ifdef DEBUG                fprintf(stderr,"%03d/%d: keepalive timeout\n",req->fd,req->state);#endif                req->state = STATE_CLOSE;            }        } else {            if (now > req->ping + timeout) {                if ((req->state == STATE_READ_HEADER) ||                    (req->state == STATE_READ_BODY)) {                    mkerror(req,408,0);                } else {                    log_error_func(0,LOG_INFO,"network timeout",req->peerhost);                    req->state = STATE_CLOSE;                }            }        }        /* parsing */      parsing:              if (req->state == STATE_PARSE_HEADER) {            parse_request(req, server_host);        }        /* body parsing */        if (req->state == STATE_PARSE_BODY) {            parse_request_body(req);        }        if (req->state == STATE_WRITE_HEADER) {            /* switch to writing */            FD_CLR(req->fd, &fds->rset);            FD_SET(req->fd, &fds->wset);                        write_request(req);        }                /* handle finished requests */        if (req->state == STATE_FINISHED && !req->keep_alive) {            req->state = STATE_CLOSE;        }        if (req->state == STATE_FINISHED) {            /* access log hook */            if (log_request_func != NULL) {                log_request_func(req, now);            }            /* switch to reading */            FD_CLR(req->fd, &fds->wset);            FD_SET(req->fd, &fds->rset);                        /* cleanup */            req->auth[0]       = 0;            req->if_modified   = 0;            req->if_unmodified = 0;            req->if_range      = 0;            req->range_hdr     = NULL;            req->ranges        = 0;            if (req->r_start) {                 free(req->r_start);                 req->r_start = NULL;             }            if (req->r_end) {                 free(req->r_end);                   req->r_end   = NULL;             }            if (req->r_head) {                 free(req->r_head);                  req->r_head  = NULL;             }            if (req->r_hlen) {                 free(req->r_hlen);                  req->r_hlen  = NULL;             }            list_free(&req->header);	            if (req->bfd != -1) {                close(req->bfd);                req->bfd  = -1;            }	            /* free memory of response body */            if ((req->status<400) && (req->body != NULL)) {                free(req->body);                req->body = NULL;            }            req->written   = 0;            req->head_only = 0;            req->rh        = 0;            req->rb        = 0;            req->hostname[0] = 0;            req->path[0]     = 0;            req->query[0]    = 0;            req->lifespan = -1;            if (req->hdata == (req->lreq + req->lbreq)) {                /* ok, wait for the next one ... */#ifdef DEBUG                fprintf(stderr,"%03d/%d: keepalive wait\n",req->fd,req->state);#endif                req->state = STATE_KEEPALIVE;                req->hdata = 0;                req->lreq  = 0;                req->lbreq = 0;#ifdef TCP_CORK                if (req->tcp_cork == 1) {                    req->tcp_cork = 0;#ifdef DEBUG

⌨️ 快捷键说明

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