//作者:京东瀚览家居官方旗舰店 <--点击关注
//文件名:Request.c
#include <sys/stat.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "request.h"
#include "keyvalue.h"
#include "log.h"
/* 判断host 格式是否正确,正确返回0 ,否则返回-1 */
static int request_check_hostname(server *srv, connection *con, buffer *host) {
enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
size_t i;
int label_len = 0;
size_t host_len;
char *colon;
int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
int level = 0;
UNUSED(srv);
UNUSED(con);
/*
* hostport = host [ ":" port ]
* host = hostname | IPv4address | IPv6address
* hostname = *( domainlabel "." ) toplabel [ "." ]
* domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
* toplabel = alpha | alpha *( alphanum | "-" ) alphanum
* IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
* IPv6address = "[" ... "]"
* port = *digit
*/
/* no Host: */
/* 空或长度为0 , 也认为符合host 格式而返回0 */
if (!host || host->used == 0) return 0;
host_len = host->used - 1;
/* IPv6 adress */
if (host->ptr[0] == '[') {
char *c = host->ptr + 1;
int colon_cnt = 0;
/* check portnumber */
for (; *c && *c != ']'; c++) {
if (*c == ':') {
if (++colon_cnt > 7) {
return -1;
}
} else if (!light_isxdigit(*c)) {
return -1;
}
}
/* missing ] */
if (!*c) {
return -1;
}
/* check port */
if (*(c+1) == ':') {
for (c += 2; *c; c++) {
if (!light_isdigit(*c)) {
return -1;
}
}
}
return 0;
}
/* IP4 地址处理*/
if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
char *c = colon + 1;
/* check portnumber */
for (; *c; c++) {
if (!light_isdigit(*c)) return -1;
}
/* 求得IP4 的host 实际长度*/
/* remove the port from the host-len */
host_len = colon - host->ptr;
}
/* Host is empty */
if (host_len == 0) return -1;
/* if the hostname ends in a "." strip it */
if (host->ptr[host_len-1] == '.') host_len -= 1;
/* scan from the right and skip the \0 */
for (i = host_len - 1; i + 1 > 0; i--) {
const char c = host->ptr[i];
switch (stage) {
case TOPLABEL:
if (c == '.') {
/* only switch stage, if this is not the last character */
if (i != host_len - 1) {
if (label_len == 0) {
return -1;
}
/* check the first character at right of the dot */
if (is_ip == 0) {
if (!light_isalpha(host->ptr[i+1])) {
return -1;
}
} else if (!light_isdigit(host->ptr[i+1])) {
is_ip = 0;
} else if ('-' == host->ptr[i+1]) {
return -1;
} else {
/* just digits */
is_ip = 1;
}
stage = DOMAINLABEL;
label_len = 0;
level++;
} else if (i == 0) {
/* just a dot and nothing else is evil */
return -1;
}
} else if (i == 0) {
/* the first character of the hostname */
if (!light_isalpha(c)) {
return -1;
}
label_len++;
} else {
if (c != '-' && !light_isalnum(c)) {
return -1;
}
if (is_ip == -1) {
if (!light_isdigit(c)) is_ip = 0;
}
label_len++;
}
break;
case DOMAINLABEL:
if (is_ip == 1) {
if (c == '.') {
if (label_len == 0) {
return -1;
}
label_len = 0;
level++;
} else if (!light_isdigit(c)) {
return -1;
} else {
label_len++;
}
} else {
if (c == '.') {
if (label_len == 0) {
return -1;
}
/* c is either - or alphanum here */
if ('-' == host->ptr[i+1]) {
return -1;
}
label_len = 0;
level++;
} else if (i == 0) {
if (!light_isalnum(c)) {
return -1;
}
label_len++;
} else {
if (c != '-' && !light_isalnum(c)) {
return -1;
}
label_len++;
}
}
break;
}
}
/* a IP has to consist of 4 parts */
if (is_ip == 1 && level != 3) {
return -1;
}
if (label_len == 0) {
return -1;
}
return 0;
}
#if 0
#define DUMP_HEADER
#endif
/* 将b内保存的类似于"val1 , val2, val3, val4" 的字符串按"," 分割*/
/* 并保存到vals 数组内, 并且会去除val 前后的空格*/
int http_request_split_value(array *vals, buffer *b) {
char *s;
size_t i;
int state = 0;
/*
* parse
*
* val1, val2, val3, val4
*
* into a array (more or less a explode() incl. striping of whitespaces
*/
if (b->used == 0) return 0;
s = b->ptr;
for (i =0; i < b->used - 1; ) {
char *start = NULL, *end = NULL;
data_string *ds;
switch (state) {
case 0: /* ws */
/* skip ws */
/* 跳过开头的空白字符*/
for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
state = 1;
break;
case 1: /* value */
start = s;
for (; *s != ',' && i < b->used - 1; i++, s++);
end = s - 1; /* 删除末尾的空白字符*/
for (; (*end == ' ' || *end == '\t') && end > start; end--);
if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
ds = data_string_init();
}
buffer_copy_string_len(ds->value, start, end-start+1);
array_insert_unique(vals, (data_unset *)ds);
if (*s == ',') {
state = 0;
i++;
s++;
} else {
/* end of string */
state = 2;
}
break;
default:
i++;
break;
}
}
return 0;
}
/* 检测c是否为合法的uri 字符*/
int request_uri_is_valid_char(unsigned char c) {
if (c <= 32) return 0;
if (c == 127) return 0;
if (c == 255) return 0;
return 1;
}
/* 解析客户端请求*/
/* 返回1 表示有后续的POST 数据到达, 就会进入CON_STATE_READ_POST 状态*/
int http_request_parse(server *srv, connection *con) {
/* 头域是由关键字( field-name)、冒号和可选值(field-value) 组成的(即message-header=field-name":"[field-value]) */
/* 这里设置is_key 用于标记区分当前处理的字符属于哪部分.*/
/* 1表示属于关键字部分, 为0表示属于field-value 部分*/
char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
char *value = NULL, *key = NULL;
enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
int line = 0;
int request_line_stage = 0;
size_t i, first;
int done = 0;
/*
* Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|))