#include <stdio.h>
#include <stdlib.h>
#include "httpparser.h"
#include "../public/nsapi.h"
HttpParser* http_parser_new(HTTPRequest *request) {
HttpParser *parser = calloc(
1,
sizeof(HttpParser));
parser->request = request;
parser->state =
0;
parser->start_line.ptr = (
char*)request->netbuf->inbuf;
parser->start_line.length =
0;
parser->offset =
0;
return parser;
}
void http_parser_free(HttpParser *parser) {
free(parser);
}
int http_parser_process(HttpParser *parser) {
switch(parser->state) {
case 0: {
int r = get_start_line(parser);
switch(r) {
case 0:
break;
default:
return r;
}
parse_request_line(parser);
parser->state++;
}
case 1: {
return http_parser_parse_header(parser);
}
case 2: {
return 0;
}
}
return -
1;
}
int http_parser_validate(HttpParser *parser) {
HTTPRequest *req = parser->request;
if(
!req->method.ptr || req->method.length ==
0
|| !req->uri.ptr || req->uri.length ==
0
|| !req->httpv.ptr || req->httpv.length ==
0)
{
return 0;
}
return 1;
}
int get_start_line(HttpParser *parser) {
netbuf *buf = parser->request->netbuf;
while(buf->pos < buf->cursize) {
unsigned char c = buf->inbuf[buf->pos];
if(c ==
'\n') {
size_t lnlen = buf->pos - parser->offset +
1;
if(lnlen <=
2) {
if(lnlen ==
1 || buf->inbuf[buf->pos-
1] ==
'\r') {
buf->pos++;
parser->offset = buf->pos;
return 1;
}
return 2;
}
if(buf->inbuf[buf->pos -
1] ==
'\r') {
parser->start_line.length = lnlen -
1;
}
else {
parser->start_line.length = lnlen;
}
parser->start_line.ptr = (
char*)buf->inbuf + parser->offset;
buf->pos++;
return 0;
}
buf->pos++;
}
return 1;
}
int http_parser_parse_header(HttpParser *parser) {
netbuf *buf = parser->request->netbuf;
parser->offset = buf->pos;
parser->name.ptr =
NULL;
parser->name.length =
0;
parser->value.ptr =
NULL;
parser->value.length =
0;
while(
1) {
if(buf->pos >= buf->cursize) {
return 1;
}
char c = (
char)buf->inbuf[buf->pos++];
if(c >
32) {
parser->wl =
0;
if(c ==
':' && parser->value.ptr ==
NULL) {
parser->name.ptr = (
char*)buf->inbuf + parser->offset;
parser->name.length = buf->pos - parser->offset -
1;
}
else if(parser->name.ptr !=
NULL && parser->value.ptr ==
NULL) {
parser->value.ptr = (
char*)buf->inbuf + buf->pos -
1;
}
}
else if(c ==
'\n') {
if(parser->wl) {
parser->state++;
return 0;
}
else {
parser->offset = buf->pos;
if(parser->name.length !=
0) {
if(parser->value.ptr) {
parser->value.length = (buf->inbuf + buf->pos -
1)
- (
unsigned char*)parser->value.ptr;
if(buf->inbuf[buf->pos-
2] ==
'\r') {
parser->value.length--;
}
}
else {
parser->value.ptr =
"";
}
header_add(
parser->request->headers,
parser->name,
parser->value);
}
else {
return 2;
}
parser->name.ptr =
NULL;
parser->value.ptr =
NULL;
parser->name.length =
0;
parser->value.length =
0;
parser->wl =
1;
}
}
}
}
int parse_request_line(HttpParser *parser) {
cxmutstr line = parser->start_line;
parser->request->request_line = line;
int i =
0;
int ns =
0;
parser->request->method.ptr = line.ptr;
for(;i<line.length;i++) {
if(!ns && line.ptr[i] ==
' ') {
ns =
1;
parser->request->method.length = i;
}
else if(ns) {
if(line.ptr[i] !=
' ') {
break;
}
}
}
parser->request->uri.ptr = line.ptr + i;
ns =
0;
int s = i;
for(;i<line.length;i++) {
if(!ns && isspace(line.ptr[i])) {
ns =
1;
parser->request->uri.length = i - s;
}
else if(ns) {
if(line.ptr[i] >
32) {
break;
}
}
}
parser->request->httpv.ptr = line.ptr + i;
ns =
0;
s = i;
for(;i<line.length;i++) {
if(!ns && isspace(line.ptr[i])) {
ns =
1;
parser->request->httpv.length = i - s;
}
else if(ns) {
if(line.ptr[i] >
32) {
break;
}
}
}
return 0;
}