/*
* Boa, an http server
* Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
* Some changes Copyright (C) 1996,97 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: request.c,v 1.112.2.3 2002/07/24 03:03:59 jnelson Exp $*/
#include "boa.h"
#include <stddef.h> /* for offsetof */
int total_connections;
struct status status;
static int sockbufsize = SOCKETBUF_SIZE;
/* function prototypes located in this file only */
static void free_request(request ** list_head_addr, request * req);
/*
* Name: new_request
* Description: Obtains a request struct off the free list, or if the
* free list is empty, allocates memory
*
* Return value: pointer to initialized request
*/
request *new_request(void)
{
request *req;
if (request_free) {
req = request_free; /* first on free list */
dequeue(&request_free, request_free); /* dequeue the head */
} else {
req = (request *) malloc(sizeof (request));
if (!req) {
log_error_time();
perror("malloc for new request");
return NULL;
}
}
memset(req, 0, offsetof(request, buffer) + 1);
return req;
}
/*
* Name: get_request
*
* Description: Polls the server socket for a request. If one exists,
* does some basic initialization and adds it to the ready queue;.
*/
void get_request(int server_s)
{
int fd; /* socket */
struct SOCKADDR remote_addr; /* address */
struct SOCKADDR salocal;
int remote_addrlen = sizeof (struct SOCKADDR);
request *conn; /* connection */
size_t len;
static int system_bufsize = 0; /* Default size of SNDBUF given by system */
remote_addr.S_FAMILY = 0xdead;
fd = accept(server_s, (struct sockaddr *) &remote_addr,
&remote_addrlen);
if (fd == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK)
/* abnormal error */
WARN("accept");
else
/* no requests */
pending_requests = 0;
return;
}
if (fd >= FD_SETSIZE) {
WARN("Got fd >= FD_SETSIZE.");
close(fd);
return;
}
#ifdef DEBUGNONINET
/* This shows up due to race conditions in some Linux kernels
when the client closes the socket sometime between
the select() and accept() syscalls.
Code and description by Larry Doolittle <ldoolitt@boa.org>
*/
#define HEX(x) (((x)>9)?(('a'-10)+(x)):('0'+(x)))
if (remote_addr.sin_family != AF_INET) {
struct sockaddr *bogus = (struct sockaddr *) &remote_addr;
char *ap, ablock[44];
int i;
close(fd);
log_error_time();
for (ap = ablock, i = 0; i < remote_addrlen && i < 14; i++) {
*ap++ = ' ';
*ap++ = HEX((bogus->sa_data[i] >> 4) & 0x0f);
*ap++ = HEX(bogus->sa_data[i] & 0x0f);
}
*ap = '\0';
fprintf(stderr, "non-INET connection attempt: socket %d, "
"sa_family = %hu, sa_data[%d] = %s\n",
fd, bogus->sa_family, remote_addrlen, ablock);
return;
}
#endif
/* XXX Either delete this, or document why it's needed */
/* Pointed out 3-Oct-1999 by Paul Saab <paul@mu.org> */
#ifdef REUSE_EACH_CLIENT_CONNECTION_SOCKET
if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt,
sizeof (sock_opt))) == -1) {
DIE("setsockopt: unable to set SO_REUSEADDR");
}
#endif
len = sizeof(salocal);
if (getsockname(fd, (struct sockaddr *) &salocal, &len) != 0) {
WARN("getsockname");
close(fd);
return;
}
conn = new_request();
if (!conn) {
close(fd);
return;
}
conn->fd = fd;
conn->status = READ_HEADER;
conn->header_line = conn->client_stream;
conn->time_last = current_time;
conn->kacount = ka_max;
ascii_sockaddr(&salocal, conn->local_ip_addr, NI_MAXHOST);
/* nonblocking socket */
if (set_nonblock_fd(conn->fd) == -1)
WARN("fcntl: unable to set new socket to non-block");
/* set close on exec to true */
if (fcntl(conn->fd, F_SETFD, 1) == -1)
WARN("fctnl: unable to set close-on-exec for new socket");
/* Increase buffer size if we have to.
* Only ask the system the buffer size on the first request,
* and assume all subsequent sockets have the same size.
*/
if (system_bufsize == 0) {
len = sizeof (system_bufsize);
if (getsockopt
(conn->fd, SOL_SOCKET, SO_SNDBUF, &system_bufsize, &len) == 0
&& len == sizeof (system_bufsize)) {
/*
fprintf(stderr, "%sgetsockopt reports SNDBUF %d\n",
get_commonlog_time(), system_bufsize);
*/
;
} else {
WARN("getsockopt(SNDBUF)");
system_bufsize = 1;
}
}
if (system_bufsize < sockbufsize) {
if (setsockopt
(conn->fd, SOL_SOCKET, SO_SNDBUF, (void *) &sockbufsize,
sizeof (sockbufsize)) == -1) {
WARN("setsockopt: unable to set socket buffer size");
#ifdef DIE_ON_ERROR_TUNING_SNDBUF
exit(errno);
#endif
}
}
/* for log file and possible use by CGI programs */
ascii_sockaddr(&remote_addr, conn->remote_ip_addr, NI_MAXHOST);
/* for possible use by CGI programs */
conn->remote_port = net_port(&remote_addr);
status.requests++;
#ifdef USE_TCPNODELAY
/* Thanks to Jef Poskanzer <jef@acme.com> for this tweak */
{
int one = 1;
if (setsockopt(conn->fd, IPPROTO_TCP, TCP_NODELAY,
(void *) &one, sizeof (one)) == -1) {
DIE("setsockopt: unable to set TCP_NODELAY");
}
}
#endif
#ifndef NO_RATE_LIMIT
if (conn->fd > max_connections) {
send_r_service_unavailable(conn);
conn->status = DONE;
pending_requests = 0;
}
#endif /* NO_RATE_LIMIT */
total_connections++;
enqueue(&request_ready, conn);
}
/*
* Name: free_request
*
* Description: Deallocates memory for a finished request and closes
* down socket.
*/
static void free_request(request ** list_head_addr, request * req)
{
int i;
/* free_request should *never* get called by anything but
process_requests */
if (req->buffer_end && req->status != DEAD) {
req->status = DONE;
return;
}
/* put request on the free list */
dequeue(list_head_addr, req); /* dequeue from ready or block list */
if (req->logline) /* access log */
log_access(req);
if (req->mmap_entry_var)
release_mmap(req->mmap_entry_var);
else if (req->data_mem)
munmap(req->data_mem, req->filesize);
if (req->data_fd)
close(req->data_fd);
if (req->post_data_fd)
close(req->post_data_fd);
if (req->response_status >= 400)
status.errors++;
for (i = COMMON_CGI_COUNT; i < req->cgi_env_index; ++i) {
if (req->cgi_env[i]) {
free(req->cgi_env[i]);
} else {
log_error_time();
fprintf(stderr, "Warning: CGI Environment contains NULL value" \
"(index %d of %d).\n", i,
没有合适的资源?快使用搜索试试~ 我知道了~
嵌入式web服务器Boa
5星 · 超过95%的资源 需积分: 32 32 下载量 103 浏览量
2009-02-01
13:26:49
上传
评论
收藏 119KB GZ 举报
温馨提示
共60个文件
c:26个
h:7个
in:3个
嵌入式Web服务器Boa 本人已经在ucLiunx下安装使用,部署很方便。 适用嵌入式设备,支持CGI boa-0.94.13.tar.gz
资源详情
资源评论
资源推荐
收起资源包目录
boa-0.94.13.tar.gz (60个子文件)
boa-0.94.13
docs
boa_banner.png 6KB
boa.8 7KB
boa.texi 27KB
Makefile 724B
examples
cgi-test.cgi 3KB
nph-test.cgi 2KB
resolver.pl 568B
ChangeLog 20KB
Gnu_License 18KB
extras
scandir.c 2KB
strutil.c 788B
alphasort.c 158B
src
pipe.c 4KB
util.c 14KB
escape.h 2KB
compat.h 3KB
cgi.c 16KB
queue.c 3KB
escape.c 3KB
boa.h 6KB
timestamp.c 1KB
aclocal.m4 2KB
webindex.pl 4KB
index_dir.c 9KB
boa_lexer.l 3KB
globals.h 6KB
ip.c 4KB
config.h.in 3KB
parse.h 1KB
log.c 6KB
.depend 1KB
select.c 6KB
boa_grammar.y 2KB
alias.c 18KB
response.c 11KB
hash.c 9KB
configure 83KB
get.c 16KB
config.c 9KB
Makefile.in 2KB
buffer.c 7KB
configure.in 4KB
boa.c 7KB
mmap_cache.c 4KB
signals.c 5KB
sublog.c 4KB
read.c 12KB
defines.h 6KB
check_struct_for.m4 1012B
acconfig.h 310B
cgi_header.c 6KB
request.c 21KB
contrib
redhat
boa.spec 3KB
boa.logrotate 70B
boa.init 783B
boa.conf 7KB
README.chroot.solaris 5KB
README 606B
CREDITS 966B
boa.conf 7KB
共 60 条
- 1
coolmomo
- 粉丝: 5
- 资源: 14
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论1