http://sgabor.blog.51cto.com/7214420/1429673
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
struct
request {
enum
REQ_STATUS status;
/*请求状态,包括BODY_READ,BODY_WRITE,WRITE,PIPE_READ,PIPE_WRITE,IOSHUFFLE,DONE,TIMED_OUT,DEAD*/
enum
KA_STATUS keepalive;
/* keepalive status 表示连接状态,是检测死连接的一种机制 */
enum
HTTP_VERSION http_version;
enum
HTTP_METHOD method;
/* M_GET, M_POST, etc.HTTP与浏览器的交互,从url读取信息的方法 */
enum
RESPONSE_CODE response_status;
/* HTTP码应码.
1xx:信息,请求收到,继续处理
2xx:成功,行为被成功地接受、理解和采纳
3xx:重定向,为了完成请求,必须进一步执行的动作
4xx:客户端错误,请求包含语法错误或者请求无法实现
5xx:服务器错误,服务器不能实现一种明显无效的请求
*/
enum
CGI_TYPE cgi_type;
enumCGI_STATUS cgi_status;
char
*pathname;
/* 请求文件路径名 */
Range *ranges;
/* 请求内容搜索范围 */
int
data_fd;
/* 数据文件描述符 */
unsigned
long
filesize;
/* 文件大小*/
unsigned
long
filepos;
/* position in file */
unsigned
long
bytes_written;
/* 被写入长度*/
char
*data_mem;
/* 数据映射*/
char
*header_line;
/* beginning of un or incompletelyprocessed header line */
char
*header_end;
/* last known end of header, or endof processed data */
int
parse_pos;
/* how much have we parsed */
int
buffer_start;
/* buffer开始地址*/
int
buffer_end;
/* buffer结束地址 */
char
*if_modified_since;
/* 判断服务器端的资源是否被修改 */
time_t
last_modified;
/* 服务器端的资源修改时间 */
int
cgi_env_index;
/* CGI变量排序*/
/* Agent and referer for logfiles */
char
*header_host;
/*主机信息*/
char
*header_user_agent;
/*代理信息*/
char
*header_referer;
/*参考信息*/
char
*header_ifrange;
char
*host;
int
post_data_fd;
/* post数据临时文件描述符 */
/* env variable */
char
*path_info;
char
*path_translated;
char
*script_name;
char
*query_string;
char
*content_type;
char
*content_length;
struct
mmap_entry *mmap_entry_var;
int
fd;
/* 客户端套接字描述符 */
time_t
time_last;
/* 上一次时间 */
char
local_ip_addr[BOA_NI_MAXHOST];
/* 本地虚拟主机IP地址*/
char
remote_ip_addr[BOA_NI_MAXHOST];
/* 远程客户端IP地址 */
unsigned
int
remote_port;
/* 远程客户端端口号 */
unsigned
int
kacount;
/*存活连接数目*/
int
client_stream_pos;
char
buffer[BUFFER_SIZE + 1];
/* 通用I/O缓冲数据*/
char
request_uri[MAX_HEADER_LENGTH + 1];
/*uri*/
char
client_stream[CLIENT_STREAM_SIZE];
/* 客户端发送的数据流 */
char
*cgi_env[CGI_ENV_MAX + 4];
/* CGI 环境变量 */
#ifdef ACCEPT_ON
char
accept[MAX_ACCEPT_LENGTH];
/* Accept:fields */
#endif
struct
request *next;
/* 下一个请求*/
struct
request *prev;
/*上一个请求 */
};
|
1
2
3
4
5
6
7
8
9
|
conn->fd = fd;
conn->status = READ_HEADER;
conn->header_line =conn->client_stream;
conn->time_last = current_time;
conn->kacount = ka_max;
conn->remote_port = net_port(&remote_addr);
conn->http_version= HTTP10;
conn->method = M_GET;
conn->status = DONE;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
void
loop(
int
server_s)
{
FD_ZERO(BOA_READ);
//每次循环都要清空集合,否则不能检测描述符变化
FD_ZERO(BOA_WRITE);
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();
BOA_FD_CLR(req, server_s,BOA_READ);
close(server_s);
/* make sure the server isn'tin the block list */
server_s = -1;
}
if
(sigterm_flag == 2 &&!request_ready && !request_block) {
sigterm_stage2_run();
/*terminal */
}
}
else
{
if
(total_connections >max_connections) {
/*连接数太多,则清除一个文件描述符集合*/
BOA_FD_CLR(req, server_s,BOA_READ);
}
else
{
/*创建一个文件描述符集合*/
BOA_FD_SET(req, server_s,BOA_READ);
/* server always set */
}
}
pending_requests = 0;
if
(max_fd) {
struct
timeval req_timeout;
/*timeval for select */
req_timeout.tv_sec = (request_ready ? 0 :default_timeout);
req_timeout.tv_usec = 0l;
/* resettimeout */
/* 监视我们需要监视的文件描述符的变化情况,读写或异常Select函数使用参考http://genime.blog.163.com/blog/static/1671577532012418341877/ */
if
(select(max_fd + 1, BOA_READ,
BOA_WRITE, NULL,
(request_ready ||request_block ?
&req_timeout :NULL)) == -1) {
if
(
errno
== EINTR)
continue
;
/* while(1) */
else
if
(
errno
!= EBADF) {
DIE(
"select"
);
}
}
if
(!sigterm_flag &&FD_ISSET(server_s, BOA_READ)) {
pending_requests = 1;
}
time
(¤t_time);
}
max_fd = -1;
if
(request_block) {
/* 如果request_block=1,则把请求信号移到就绪链表*/
fdset_update();
}
if
(pending_requests || request_ready){
/* 有待处理请求或者就绪请求则进行请求处理*/
process_requests(server_s);
}
}
}
|
1
2
3
4
5
6
7
|
void
sigterm_stage1_run(
void
)
{
/* lame duck mode */
time
(¤t_time);
log_error_time();
fputs
(
"caught SIGTERM, starting shutdown\n"
, stderr);
sigterm_flag =2;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void
sigterm_stage2_run(
void
)
{
/* lame duckmode */
log_error_time();
fprintf
(stderr,
"exiting Boa normally (uptime %d seconds)\n"
,
(
int
)(current_time - start_time));
chdir(tempdir);
clear_common_env();
//清空环境变量
dump_mime();
//清空mime_hashtable
dump_passwd();
//清空passwd_hashtable
dump_alias();
//清空alias
free_requests();
//释放请求空间
range_pool_empty();
//清空队列
free
(server_root);
//释放服务器
free
(server_name);
server_root =NULL;
exit
(EXIT_SUCCESS);
//退出。
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
switch
(req->method) {
case
M_POST:
w =
"POST"
;
//环境变量
break
;
case
M_HEAD:
//标准输入
w =
"HEAD"
;
break
;
case
M_GET:
//命令行
w =
"GET"
;
break
;
default
:
w =
"UNKNOWN"
;
break
;
}
|