1.1 bitset数据结构
bitset数据结构提供对bit位操作的封装。提供对bit的置位操作,清位操作,测试位操作等常用位操作。
相关部分源码:
bitset.h
bitset.c
在高版本的lighttpd源码中已经删除。
1.2 buffer数据结构
1.2.1 结构说明
buffer结构体以及其相关实现函数替lighttpd管理者字符串的内存使用与操作。在Web服务器中,很多的处理
都是针对字符串进行的,比如客户端请求的URI地址,发送的query参数、post提交的数据、服务器的响应内容等
都是一些字符串的集合。因此提供对字符串的灵活操作以及封装对字符串的高效处理,不管是对前期的lighttpd功能
开发还是对后期lighttpd实际执行的效率都有着至关重要的作用。
相关部分源码:
buffer.h
buffer.c
1.2.2 结构定义
/* generic string + binary data container; contains a terminating 0 in both
* cases
*
* used == 0 indicates a special "empty" state (unset config values); ptr
* might be NULL too then. otherwise an empty string has used == 1 (and ptr[0]
* == 0);
*
* copy/append functions will ensure used >= 1 (i.e. never leave it in the
* special empty state); only buffer_copy_buffer will copy the special empty
* state.
*/
typedef struct {
char *ptr;
/* "used" includes a terminating 0 */
size_t used;
/* size of allocated buffer at *ptr */
size_t size;
} buffer;
1.3 data_xxxxx数据结构
1.3.1 结构说明
data_xxxxx数据结构体表示的是一类数据结构体,总览lighttpd的137个源文件,不难发现有几个文件命名
很一致的源文件,它们是data_array.c,data_config.c,data_count.c、data_fastcgi.c、data_integer.c、data_string.c.,这
些文件实现的是lighttpd中非常重要的基础数据结构部分、本节就来分析它们是怎么组织的,它们之间到底是什么关系。
本节相关部分源码:
array.h
array.c
1.3.2 结构定义
data_xxxxx数据结构全部都定义在array.h头文件内、包括有data_unset、data_array、data_config、data_count、
data_fastcgi、data_integer、data_string。data_unset是基础,首先查看data_unset结构体,很简单,里面就一个
DATA_UNSET宏,将其展开后就是其结构体元素。另外的几个结构体,也都是第一个元素为DATA_UNSET宏,另外各个
结构体再包含有自己特有的一些属性元素。在结构体的初始化函数data_xxxxx_ini()内,各自结构体实现源文件内提供的
接口函数都将赋值给对应的结构体函数指针字段,这样在对data_unset操作时会根据其实际类型而调用不同的函数,如果
利用面向对象的思想来看待这些结构体,很容易想到把data_unset看做基类,而其他data_array等看作子类,这实现的
就是所谓的继承和多态效果,这样一来我们可以画出他们之间的UML图,如下所示。lighttpd开发者利用C语言来模拟面
向对象的实现,一方面使得程序数据结构扩展灵活,具有面向对象技术的优势,另一方面又拥有C语言本身操作数据的
便利。在lighttpd源代码的其它地方,还可以看到作者的这种灵活设计。
#define DATA_IS_STRING(x) (x->type == TYPE_STRING)
typedef enum { TYPE_UNSET, TYPE_STRING, TYPE_OTHER, TYPE_ARRAY, TYPE_INTEGER, TYPE_DONOTUSE, TYPE_CONFIG } data_type_t;
#define DATA_UNSET \
data_type_t type; \
buffer *key; \
int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
struct data_unset *(*copy)(const struct data_unset *src); \
void (* free)(struct data_unset *p); \
void (* reset)(struct data_unset *p); \
int (*insert_dup)(struct data_unset *dst, struct data_unset *src); \
void (*print)(const struct data_unset *p, int depth)
typedef struct data_unset {
DATA_UNSET;
} data_unset;
typedef struct {
data_unset **data;
size_t *sorted;
size_t used; /* <= SSIZE_MAX */
size_t size;
size_t unique_ndx;
} array;
typedef struct {
DATA_UNSET;
buffer *value;
} data_string;
data_string *data_string_init(void);
data_string *data_response_init(void);
typedef struct {
DATA_UNSET;
array *value;
} data_array;
data_array *data_array_init(void);
/**
* possible compare ops in the configfile parser
*/
typedef enum {
CONFIG_COND_UNSET,
CONFIG_COND_EQ, /** == */
CONFIG_COND_MATCH, /** =~ */
CONFIG_COND_NE, /** != */
CONFIG_COND_NOMATCH, /** !~ */
CONFIG_COND_ELSE /** (always true if reached) */
} config_cond_t;
/**
* possible fields to match against
*/
typedef enum {
COMP_UNSET,
COMP_SERVER_SOCKET,
COMP_HTTP_URL,
COMP_HTTP_HOST,
COMP_HTTP_REFERER, /*(subsumed by COMP_HTTP_REQUEST_HEADER)*/
COMP_HTTP_USER_AGENT, /*(subsumed by COMP_HTTP_REQUEST_HEADER)*/
COMP_HTTP_LANGUAGE, /*(subsumed by COMP_HTTP_REQUEST_HEADER)*/
COMP_HTTP_COOKIE, /*(subsumed by COMP_HTTP_REQUEST_HEADER)*/
COMP_HTTP_REMOTE_IP,
COMP_HTTP_QUERY_STRING,
COMP_HTTP_SCHEME,
COMP_HTTP_REQUEST_METHOD,
COMP_HTTP_REQUEST_HEADER,
COMP_LAST_ELEMENT
} comp_key_t;
/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
* for print: comp_key op string
* for compare: comp cond string/regex
*/
typedef struct data_config data_config;
DEFINE_TYPED_VECTOR_NO_RELEASE(config_weak, data_config*);
struct data_config {
DATA_UNSET;
array *value;
buffer *comp_tag;
buffer *comp_key;
comp_key_t comp;
config_cond_t cond;
buffer *op;
int context_ndx; /* more or less like an id */
vector_config_weak children;
/* nested */
data_config *parent;
/* for chaining only */
data_config *prev;
data_config *next;
buffer *string;
#ifdef HAVE_PCRE_H
pcre *regex;
pcre_extra *regex_study;
#endif
};
data_config *data_config_init(void);
typedef struct {
DATA_UNSET;
int value;
} data_integer;
1.4 chunk数据结构
1.4.1 结构说明
chunk结构体是lighttpd源码内另一个极其重要的数据结构,lighttpd接受客户端请求的数据以及对客户端
发送响应的数据就是通过chunk结构体来组织的,本节将分析这个数据结构体。
本节相关部分源码:
chunk.h
chunk.c
1.4.2 结定义
chunk指定了两种块类型,一种是MEM_CHUNK,一种是FILE_CHUNK,对于各自块类型给出了相应的数据保存结构字
段。另外有个next字段可以将各个chunk结构体连接起来组成链表。chunk数据结构定义在对应的chunk.h头文件内。
typedef struct chunk {
enum { MEM_CHUNK, FILE_CHUNK } type;
buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
struct {
/* filechunk */
buffer *name; /* name of the file */
off_t start; /* starting offset in the file */
off_t length; /* octets to send from the starting offset */
int fd;
struct {
char *start; /* the start pointer of the mmap'ed area */
size_t length; /* size of the mmap'ed area */
off_t offset; /* start is <n> octet away from the start of the file */
} mmap;
int is_temp; /* file is temporary and will be deleted if on cleanup */
} file;
/* the size of the chunk is either:
* - mem-chunk: buffer_string_length(chunk::mem)
* - file-chunk: chunk::file.length
*/
off_t offset; /* octets sent from this chunk */
struct chunk *next;
} chunk;
typedef struct {
chunk *first;
chunk *last;
chunk *unused;
size_t unused_chunks;
off_t bytes_in, bytes_out;
array *tempdirs;
unsigned int upload_temp_file_size;
unsigned int tempdir_idx;
} chunkqueue;
1.5 keyvalue数据结构
1.5.1 结构说明
keyvalue结构体正如其命名所示,主要用来将两个值(一个整型key,一个字符串类型value)一一对应地关联起来,并
提供相应的结构使我们可以从key找到对应的value,也可以从value获取到对应的可以,这主要用于在人阅读(字符串类型使
得人更容易理解)与机器操作(整型对于机器来说更容易操作)至二级进行快速切换,下面来分析这个数据结构体。
本节相关部分源码:
keyvalue.h
keyvalue.c
1.5.2 结定义
keyvalue仅包含两个字段,在对应的keyvalue.h头文件内定义,但是另外几个keyvalue类型的数组在后面第10章要经常
看到,这里也列出来,结构清单如下:
struct server;
struct cond_cache_t;
/* sources:
* - [RFC2616], Section 9
* (or http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-22)
* - http://tools.ietf.org/html/draft-ietf-httpbis-method-registrations-11, Appendix A
*
* http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-22, Section 8.1 defines
* a new registry (not available yet):
* http://www.iana.org/assignments/http-methods
*/
typedef enum {
HTTP_METHOD_UNSET = -1,
HTTP_METHOD_GET, /* [RFC2616], Section 9.3 */
HTTP_METHOD_HEAD, /* [RFC2616], Section 9.4 */
HTTP_METHOD_POST, /* [RFC2616], Section 9.5 */
HTTP_METHOD_PUT, /* [RFC2616], Section 9.6 */
HTTP_METHOD_DELETE, /* [RFC2616], Section 9.7 */
HTTP_METHOD_CONNECT, /* [RFC2616], Section 9.9 */
HTTP_METHOD_OPTIONS, /* [RFC2616], Section 9.2 */
HTTP_METHOD_TRACE, /* [RFC2616], Section 9.8 */
HTTP_METHOD_ACL, /* [RFC3744], Section 8.1 */
HTTP_METHOD_BASELINE_CONTROL, /* [RFC3253], Section 12.6 */
HTTP_METHOD_BIND, /* [RFC5842], Section 4 */
HTTP_METHOD_CHECKIN, /* [RFC3253], Section 4.4 and [RFC3253], Section 9.4 */
HTTP_METHOD_CHECKOUT, /* [RFC3253], Section 4.3 and [RFC3253], Section 8.8 */
HTTP_METHOD_COPY, /* [RFC4918], Section 9.8 */
HTTP_METHOD_LABEL, /* [RFC3253], Section 8.2 */
HTTP_METHOD_LINK, /* [RFC2068], Section 19.6.1.2 */
HTTP_METHOD_LOCK, /* [RFC4918], Section 9.10 */
HTTP_METHOD_MERGE, /* [RFC3253], Section 11.2 */
HTTP_METHOD_MKACTIVITY, /* [RFC3253], Section 13.5 */
HTTP_METHOD_MKCALENDAR, /* [RFC4791], Section 5.3.1 */
HTTP_METHOD_MKCOL, /* [RFC4918], Section 9.3 */
HTTP_METHOD_MKREDIRECTREF, /* [RFC4437], Section 6 */
HTTP_METHOD_MKWORKSPACE, /* [RFC3253], Section 6.3 */
HTTP_METHOD_MOVE, /* [RFC4918], Section 9.9 */
HTTP_METHOD_ORDERPATCH, /* [RFC3648], Section 7 */
HTTP_METHOD_PATCH, /* [RFC5789], Section 2 */
HTTP_METHOD_PROPFIND, /* [RFC4918], Section 9.1 */
HTTP_METHOD_PROPPATCH, /* [RFC4918], Section 9.2 */
HTTP_METHOD_REBIND, /* [RFC5842], Section 6 */
HTTP_METHOD_REPORT, /* [RFC3253], Section 3.6 */
HTTP_METHOD_SEARCH, /* [RFC5323], Section 2 */
HTTP_METHOD_UNBIND, /* [RFC5842], Section 5 */
HTTP_METHOD_UNCHECKOUT, /* [RFC3253], Section 4.5 */
HTTP_METHOD_UNLINK, /* [RFC2068], Section 19.6.1.3 */
HTTP_METHOD_UNLOCK, /* [RFC4918], Section 9.11 */
HTTP_METHOD_UPDATE, /* [RFC3253], Section 7.1 */
HTTP_METHOD_UPDATEREDIRECTREF, /* [RFC4437], Section 7 */
HTTP_METHOD_VERSION_CONTROL /* [RFC3253], Section 3.5 */
} http_method_t;
typedef enum { HTTP_VERSION_UNSET = -1, HTTP_VERSION_1_0, HTTP_VERSION_1_1 } http_version_t;
typedef struct {
int key;
const char *value;
} keyvalue;
typedef struct {
#ifdef HAVE_PCRE_H
pcre *key;
pcre_extra *key_extra;
#endif
buffer *value;
} pcre_keyvalue;
typedef struct {
pcre_keyvalue **kv;
size_t used;
size_t size;
} pcre_keyvalue_buffer;