ILD

boa学习
作者:Yuan Jianpeng 邮箱:785147217@qq.com
发布时间:2020-2-28 站点:Inside Linux Development

boa是小巧、高效的web服务器,非常适合嵌入式系统。


命令行参数

-c server_root,用来改变working directory,默认是/etc/boa,

                        默认配置文件是boa.conf,所以修改working directory,会影响默认配置文件的读取。

-d 不fork

-f 指定配置文件的文件名。

-r chroot和chdir到那个目录,chroot后,所有的绝对路径都相对于设置的路径。


main入口

解析参数,设置server root,读取配置文件,打开log,创建server套接字,初始化信号处理函数,fork,进入loop循环。


log

有两种log,在参数里面对应:ErrorLog/AccessLog。前者会打开,并将标准错误绑定到它,如果ErrorLog为空,则保持标准错误不动。AccessLog会打开,并讲标准输出绑定到它,如果AccessLog为空,则使用/dev/null。


还有一个CGILog,如果有,则打开。


request

一个请求,有两个请求队列,blocked和ready。在loop中,如果request的某个状态的文件描述符是可读/写的,那么其从blocked队列放入ready队列。如果request完成了数据的响应,则将其放入blocked队列,直到loop再次将其放回ready队列进行处理。


loop有两种select和poll,以select为例:在select返回,执行fdset_update(),这这个里面,根据request的status,找到对应的fd,看其是否fdset,如果是,将其移到ready队列。注意:这里一个状态只对应一个fd,因此对于cgi这种中继的数据方式,会在PIPE_READ状态和PIPE_WRITE状态来回切。


status有下面这些

READ_HEADER

ONE_CR

ONE_LF

TWO_CR

BODY_READ

BODY_WRITE

WRITE

PIPE_READ

PIPE_WRITE

IOSHUFFLE

DONE

TIMEOUT

DEAD


WRITE/PIPE_WRITE

将响应写入fd(请求套接字)


BODY_WRITE

将POST请求的数据,写入post_data_fd(一个临时文件)


PIPE_READ

从data_fd(pipe,接受cgi的响应),读取数据,将来通过PIPE_WRITE写给client。


get_request(),accept新请求,然后分配一个新的请求,将fd设置到request->fd。将status初始化为READ

_HEADER。


process_request()

首先如果status小于TIMED_OUT,且有数据要写给client,则调用req_flush写数据,返回-1表示blocked,返回N,则表示写入了一些,还剩下多少。

接着,根据各个状态执行对应的处理函数:

READ_HEADER

ONE_CR

ONE_LF

TWO_CR

read_header()
BODY_READ
read_body()
BODY_WRITE
write_body()
WRITE
process_get()
PIPE_READ
read_from_pipe()
PIPE_WRITE
write_from_pipe()


read_header()

一个while循环,一个字符一个字符的解析,一个\r,则进入ONE_CR,接着一个\n,则进入ONE_LF,在跟着一个\r,则进入TWO_CR,在跟着一个\n,则进入BODY_READ。


如果状态是ONE_LF,则处理一个头,调用process_option_line()或process_logline(),后者是处理http的第一行,


如果状态是BODY_READ,则调用process_header_end()。


process_header_end()它解析请求的路径,根据document_root,确定对应的文件的路径,调用translate_uri,解析alias,如果是script,则解析对应的脚本的路径。如果是POST(只有cgi才允许POST),则创建临时文件,文件描述符post_data_fd并返回,如果是GET请求的cgi,则调用cgi,如果是GET请求静态页面,则status变为write,调用init_get,打开静态文件。


read_body()

从套接字读取数据到缓存,读到一些数据后,将状态设置为BODY_WRITE。


write_body()

将read_body读取的数据,写入临时文件(post_data_fd)。如果写完了,就调用了init_cgi,启动cgi进程。


init_cgi()

创建pipe,对于boa,读端fd存储在data_fd,对于fork出来的cgi进程,写端fd,绑定到标准输出。如果是POST请求,post_data_fd绑定到标准输入。


read_from_pipe()

从data_fd,读取cgi的输出,


write_from_pipe()

将从pipe读到的数据写入客户端套接字。


还有个IOSHUFFLE的状态,它处理partial request。



Copyright © insidelinuxdev.net 2017-2021. Some Rights Reserved.