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

📄 http.l

📁 this is very good for teacher
💻 L
字号:
/* * http.c -- module for dealing with HTTP/1.1 persistent connection * Created: Xie Han, OS lab of Peking University. <me@pku.edu> * * You can find all you need dealing with http message! * * Created: Oct 21 6:30am 2003. version 0.1.1 *		# The data structure of http request and http response are drafted *		  out. Indeed there are serveral versions, and the final decision *		  is the most simple one. *		# The BNFs are typed, which are taken from RFC 2616 & RFC 2396. *		# An over-all designing scheme is coming to its own in my mind. *		# "We are reading the first verse of the first chapter of a book *		  whose pages are infinite..." Yes, we are just beginning. * * Updated: Oct 22 4:54am 2003. version 0.1.2 *		# I'v found the way out. We maintain a list each node of which is *		  a "struct __http_buffer_state". Each node has different sockfd. *		  It means we allocate every different sockfd a scanning buffer *		  in order not to mess up when users more than one sockfd. *		# "int sockfd" field is added to "struct __http_request" & *		  "struct __http_response" so that users need not get a sockfd when *		  they are reading message body. *		# The idea of what interfaces should be and how they work is *		  clearing up in my mind. And this module is expected to been very *		  complexed for me and very convinient for its users. * * Updated: Oct 23 4:50am 2003. version 0.1.2 *		# Everyting is different. Now, HTTP_REQUEST & HTTP_RESPONSE are *		  derived from HTTP_MESSAGE. Parsing process is made simplier *		  by getting Request-Line and Status-Line at one time. *		# A field of "state" is added to HTTP_MESSAGE in order to support *		  non-blocking IO (The message header need not to be transferred *		  at one time). *		# A field of "request_method" is added to HTTP_RESPONSE in order *		  that we can caculate the transfer length of the response. *		# I am stuck at calculating transfer length from message header. *		  It's not an easy task. */OCTET			[\0-\377]CHAR			[\0-\177]UPALPHA			[A-Z]LOALPHA			[a-z]DIGIT			[0-9]CTL				[\0-\37\177]CR				\rLF				\nSP				\bHT				\tCRLF			{CR}{LF}LWS				{CRLF}?({SP}|{HT})+TEXT			[^\0-\37\177]HEX				[A-Fa-f]|{DIGIT}token			[^\0-\37\177-\377()<>@,;:\\"/[\]?={}\b\t]+separators		[()<>@,;:\\"/[\]?={}]|{SP}|{HT}comment			"("({ctext}|{quoted-pair}|{comment})*")"ctext			[^\0-\37\177()]quoted-string	\"({qdtext}|{quoted-pair})*\"qdtext			[^\0-\37\177"]quoted-pair		"\"{CHAR}HTTP-Version	"HTTP/"{DIGIT}+"."{DIGIT}+method			{token}Request-URI		"*"|{absoluteURI}|{abs_path}|{authority}Status-Code		{DIGIT}{3}Reason-Phrase	[^\0-\37\177]*Request-Line	{method}{SP}{Request-URI}{SP}{HTTP-Version}{CRLF}Status-Line		{HTTP-Version}{SP}{Status-Code}{SP}{Reason-Phrase}{CRLF}message-header	{filed-name}":"{field-value}?field-name		{token}field-value		({field-content}|{LWS})*field-content	{TEXT}*|{token}{separators}{quoted-string}URI-reference	({absoluteURI}|{relativeURI})?("#"{fragment})?absoluteURI		{scheme}":"({hier_part}|{opaque_part})relativeURI		({net_path}|{abs_path}|{rel_path})("?"{query})?hier_part		({net_path}|{abs_path})("?"{query})?opaque_part		{uric_no_slash}{uric}*uric_no_slash	{unreserved}|{escaped}|";"|"?"|":"|"@"|"&"|"="|"+"|"$"|","net_path		"//"{authority}{abs_path}?abs_path		"/"{path_segments}rel_path		{rel_segment}{abs_path}?rel_segment		({unreserved}|{escaped}|";"|"@"|"&"|"="|"+"|"$"|",")+scheme			{alpha}({alpha}|{digit}|"+"|"-"|".")*authority		{server}|{reg_name}reg_name		({unreserved}|{escaped}|"$"|","|";"|":"|"@"|"&"|"="|"+")+server			(({userinfo}"@")?{hostport})?userinfo		({unreserved}|{escaped}|";"|":"|"&"|"="|"+"|"$"|",")*hostport		{host}(":"{port})?host			{hostname}|{IPv4address}hostname		({domainlabel}".")*{toplabel}"."?domainlabel		{alphanum}|{alphanum}({alphanum}|"-")*{alphanum}toplabel		{alpha}|{alpha}({alphanum}|"-")*{alphanum}IPv4address		{digit}+"."{digit}+"."{digit}+"."{digit}+port			{digit}*path			({abs_path}|{opaque_part})?path_segments	{segment}("/"{segment})*segment			{pchar}*(";"{param})*param			{pchar}*pchar			{unreserved}|{escaped}|":"|"@"|"&"|"="|"+"|"$"|","query			{uric}*fragment		{uric}*uric			{reserved}|{unreserved}|{escaped}reserved		";"|"/"|"?"|":"|"@"|"&"|"="|"+"|"$"|","unreserved		{alphanum}|{mark}mark			"-"|"_"|"."|"!"|"~"|"*"|"'"|"("|")"escaped			"%"{hex}{hex}hex				digit|[A-Fa-f]alphanum		{alpha}|{digit}alpha			{lowalpha}|{upalpha}lowalpha		[a-z]upalpha			[A-Z]digit			[0-9]%{#include <sys/types.h>#include <unistd.h>#include <list.h>#include "http.h"#define BUFFER_SIZE		1024struct __http_message{	int type;	int sockfd;	int state;	struct list_head message_header;	ssize_t transfer_length;};struct __http_request{	struct __http_message __base__;	struct http_request_line request_line;};struct __http_response{	struct __http_message __base__;	struct http_status_line status_line;	char *request_method;};struct __http_buffer_state{	struct list_head list;	int sockfd;	char bytes[BUFFER_SIZE];	ssize_t size;	char *curpos;	ssize_t transfer_length;};static HTTP_MESSAGE __message;static LIST_HEAD(__buffer_list);static struct __http_buffer_state *__current_buffer;%}%%<REQUEST,RESPONSE>{CRLF}	__current_buffer->curpos += yyleng;<REQUEST>.|\n		{	yyless(0);	BEGIN REQUEST_LINE;}<RESPONSE>.|\n		{	yyless(0);	BEGIN STATUS_LINE;}<REQUEST_LINE>{Request_Line}{CRLF}	{	char *pos;	pos = strchr(yytext, ' ');	if (((HTTP_REQUEST *)__message)->request_line.method =											strdupn(yytext, pos - yytext))	{		yytext = pos + 1;		pos = strchr(yytext, ' ');		if (((HTTP_REQUEST *)__message)->request_line.request_uri =											strdupn(yytext, pos - yytext))		{			yytext = pos + 1;			pos = strchr(yytext, '\r');			if (((HTTP_REQUEST *)__message)->request_line.http_version =											strdupn(yytext, pos - yytext))			{				__current_buffer->curpos += yyleng;				BEGIN (__message->state = MESSAGE_HEADER);				YY_BREAK;			}		}	}}<STATUS_LINE>{Status-Line}{CRLF}	{	char *pos;	pos = strchr(yytext, ' ');	if (((HTTP_RESPONSE *)__message)->status_line.http_version =											strdupn(yytext, pos - yytext))	{		yytext = pos + 1;		pos = strchr(yytext, ' ');		if (((HTTP_RESPONSE *)__message)->status_line.status_code =											strdupn(yytext, pos - yytext))		{			yytext = pos + 1;			pos = strchr(yytext, '\r');			if (((HTTP_RESPONSE *)__message)->status_line.reason_phrase =											strdupn(yytext, pos - yytext))			{				__current_buffer->curpos += yyleng;				BEGIN (__message->state = MESSAGE_HEADER);				YY_BREAK;			}		}	}}<MESSAGE_HEADER>{message-header}{CRLF}	{	struct __http_message_header *header;	char *colon_pos;	if (header = (struct __http_message_header *)				 malloc(sizeof (struct __http_message_header)))	{		colon_pos = strchr(yytext, ':');		if (header->field_name = strdupn(yytext, colon_pos - yytext))		{			__current_buffer->curpos += yyleng;			/* yyleng minus the field name, the colon, and the trailing			 * CRLF. If there is no blanks trailing the field value,			 * now yyleng is the length of field value. */			yyleng -= pos - yytext - 3;			yytext = pos + 1;			/* All the preceding or trailing blanks should be ignored. */			while (*yytext == ' ' || *yytext == '\t')				yytext++;			while (*(yytext + yyleng) == ' ' || *(yytext + yyleng) == '\t')				yyleng--;			if (header->field_value = strdupn(yytext, yyleng))			{				list_add_tail(&header->list, &__message->message_header);				YY_BREAK;			}			free(header->field_name);		}		free(header);	}}<MESSAGE_HEADER>{CRLF}	{	__current_buffer->curpos += yyleng;	__http_message_transfer_length(__message);	return 0;}%%int yywrap(void){	YY_BUFFER_STATE buf;	ssize_t nbytes;	if ((nbytes = read(__current_buffer->sockfd, __current_buffer->bytes,					   BUFFER_SIZE)) > 0)	{		if (buf = yy_scan_bytes(__current_buffer->octets,								__current_buffer->size))		{			yy_delete_buffer(YY_CURRENT_BUFFER);			yy_switch_to_buffer(buf);			return 0;		}	}	return 1;}ssize_t __from_header(struct list_head *list){}ssize_t __http_message_transfer_length(const HTTP_REQUEST *request){	return __from_header((HTTP_MESSAGE *)request->message_header));}ssize_t __http_response_transfer_length(const HTTP_RESPONSE *response){	char *code;	if (strcmp(response->request_method, "HEAD") == 0)		return 0;	code = response->status_line.status_code;	if (*code == '1' || strcmp(code, "204") == 0 || strcmp(code, "304") == 0)		return 0;	return __from_header((HTTP_MESSAGE *)response->message_header));}void __http_message_transfer_length(const HTTP_MESSAGE *message){	if (message->type == MT_REQUEST)		message->transfer_length =					__http_request_transfer_length((HTTP_REQUEST *)message);	else		message->transfer_length =					__http_request_transfer_length((HTTP_RESPONSE *)message);}int __http_recv(int type, int sockfd){	YY_BUFFER_STATE yy_buffer;	struct list_head *pos;	struct __http_buffer_state *http_buffer;	/* First we check whether "sockfd" is in our buffer list. */	list_for_each(pos, &__buffer_list)	{		if (sockfd ==				list_entry(pos, struct __http_buffer_state, list)->sockfd))			break;	}	if (pos == &__buffer_list)	{		/* "sockfd" is not in our buffer list. Create a new buffer for it. */		if (http_buffer = (struct __http_buffer_state *)						  malloc(sizeof (struct __http_buffer_state)))		{			INIT_LIST_HEAD(buffer->list);			http_buffer->size = 0;			http_buffer->curpos = http_buffer->octets;			http_buffer->sockfd = sockfd;			list_add_tail(&http_buffer->list, &__buffer_list);		}		else			return -1;	}	else	{		http_buffer = list_entry(pos, struct __http_buffer_state, list);		/* "sockfd" is in our buffer list and the previous transfer has		 * not completed. We should not transfer a new message. */		if (http_buffer->transfer_length != 0)			return -1;	}	if (yy_buffer = yy_scan_bytes(http_buffer->curpos, http_buffer->size -								  (http_buffer->curpos - http_buffer->octets)))		yy_switch_to_buffer(yy_buffer);	else	{		if (pos == &__buffer_list)		{			list_del(&http_buffer->list);			free(http_buffer);		}		return -1;	}	__current_buffer = http_buffer;	BEGIN type;	return yylex();}

⌨️ 快捷键说明

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