mirror of
https://github.com/lxsang/ant-http
synced 2024-11-18 01:08:21 +01:00
cont.
This commit is contained in:
parent
353323f93a
commit
a86a2d150e
5
httpd.c
5
httpd.c
@ -140,11 +140,6 @@ void configure_context(SSL_CTX *ctx)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void schedule_task(antd_task_t* task)
|
|
||||||
{
|
|
||||||
antd_add_task(&scheduler, task);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void stop_serve(int dummy) {
|
void stop_serve(int dummy) {
|
||||||
UNUSED(dummy);
|
UNUSED(dummy);
|
||||||
|
119
lib/h2.c
119
lib/h2.c
@ -1,9 +1,57 @@
|
|||||||
#include "h2.h"
|
#include "h2.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
|
|
||||||
|
static int antd_h2_read_frame_header(antd_client_t* cl, antd_h2_frame_header_t* frame)
|
||||||
|
{
|
||||||
|
frame->length = 0;
|
||||||
|
frame->type = 0;
|
||||||
|
frame->flags = 0;
|
||||||
|
frame->identifier= 0;
|
||||||
|
uint8_t header[9];
|
||||||
|
if( antd_recv(cl,& header,sizeof(header)) != sizeof(header)) return 0;
|
||||||
|
// network byte order is big endian
|
||||||
|
// read frame length
|
||||||
|
frame->length = (*header << 16) + (*(header + 1)<< 8) + *(header+2);
|
||||||
|
// frame type
|
||||||
|
frame->type = *(header + 3);
|
||||||
|
// frame flags
|
||||||
|
frame->flags = *(header + 4);
|
||||||
|
// frame identifier
|
||||||
|
frame->identifier = ((*(header + 5) & 0x7F) << 24) + (*(header + 6)<< 16) + (*(header + 7)<< 8) + *(header + 8);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int process_frame(void* source, antd_h2_frame_header_t* frame_h)
|
||||||
|
{
|
||||||
|
// verify frame
|
||||||
|
printf("Frame type: %d\n", frame_h->type & 0xff);
|
||||||
|
printf("Frame flag: %d\n",frame_h->flags);
|
||||||
|
printf("frame identifier: %d\n", frame_h->identifier);
|
||||||
|
uint8_t* frame_data = (uint8_t*)malloc(frame_h->length);
|
||||||
|
if(!frame_data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
antd_request_t* rq = (antd_request_t*) source;
|
||||||
|
if(antd_recv(rq->client,frame_data,frame_h->length) != frame_h->length)
|
||||||
|
{
|
||||||
|
// TODO error
|
||||||
|
// go away
|
||||||
|
ERROR("Cannot read all frame data");
|
||||||
|
free(frame_data);
|
||||||
|
return H2_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(frame_data);
|
||||||
|
return H2_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
void* antd_h2_preface_ck(void* data)
|
void* antd_h2_preface_ck(void* data)
|
||||||
{
|
{
|
||||||
char buf[25];
|
char buf[25];
|
||||||
|
antd_h2_frame_header_t frame_h;
|
||||||
antd_request_t* rq = (antd_request_t*) data;
|
antd_request_t* rq = (antd_request_t*) data;
|
||||||
int count = antd_recv(rq->client,buf,24);
|
int count = antd_recv(rq->client,buf,24);
|
||||||
if(count != 24)
|
if(count != 24)
|
||||||
@ -11,7 +59,7 @@ void* antd_h2_preface_ck(void* data)
|
|||||||
// TODO servers MUST treat an invalid connection preface as a
|
// TODO servers MUST treat an invalid connection preface as a
|
||||||
// connection error (Section 5.4.1) of type PROTOCOL_ERROR
|
// connection error (Section 5.4.1) of type PROTOCOL_ERROR
|
||||||
ERROR("Unable to read preface for client %d: [%s]",rq->client->sock,buf);
|
ERROR("Unable to read preface for client %d: [%s]",rq->client->sock,buf);
|
||||||
return antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
|
return antd_empty_task((void *)rq,rq->client->last_io);
|
||||||
}
|
}
|
||||||
buf[24] = '\0';
|
buf[24] = '\0';
|
||||||
if(strcmp(buf, H2_CONN_PREFACE) != 0)
|
if(strcmp(buf, H2_CONN_PREFACE) != 0)
|
||||||
@ -19,8 +67,19 @@ void* antd_h2_preface_ck(void* data)
|
|||||||
ERROR("Connection preface is not correct for client %d: [%s]",rq->client->sock,buf);
|
ERROR("Connection preface is not correct for client %d: [%s]",rq->client->sock,buf);
|
||||||
// TODO servers MUST treat an invalid connection preface as a
|
// TODO servers MUST treat an invalid connection preface as a
|
||||||
// connection error (Section 5.4.1) of type PROTOCOL_ERROR
|
// connection error (Section 5.4.1) of type PROTOCOL_ERROR
|
||||||
return antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
|
return antd_empty_task((void *)rq, rq->client->last_io);
|
||||||
}
|
}
|
||||||
|
// read the setting frame
|
||||||
|
if(!antd_h2_read_frame_header(rq->client, &frame_h) || frame_h.type != H2_FRM_SETTINGS)
|
||||||
|
{
|
||||||
|
// TODO: frame error
|
||||||
|
//
|
||||||
|
// send go away with PROTOCOL_ERROR
|
||||||
|
printf("error reading setting frame\n");
|
||||||
|
ERROR("Unable to read setting frame from client %d",rq->client->sock);
|
||||||
|
return antd_empty_task((void *)rq, rq->client->last_io);
|
||||||
|
}
|
||||||
|
process_frame(rq, &frame_h);
|
||||||
return antd_create_task(antd_h2_handle, (void *)rq, NULL, rq->client->last_io);
|
return antd_create_task(antd_h2_handle, (void *)rq, NULL, rq->client->last_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,15 +89,11 @@ void* antd_h2_handle(void* data)
|
|||||||
antd_task_t* task;
|
antd_task_t* task;
|
||||||
if(rq->client->flags & CLIENT_FL_READABLE)
|
if(rq->client->flags & CLIENT_FL_READABLE)
|
||||||
{
|
{
|
||||||
task = antd_create_task(antd_h2_read,(void *)rq, NULL, rq->client->last_io);
|
antd_h2_read(data);
|
||||||
task->priority++;
|
|
||||||
schedule_task(task);
|
|
||||||
}
|
}
|
||||||
if(rq->client->flags & CLIENT_FL_WRITABLE)
|
if(rq->client->flags & CLIENT_FL_WRITABLE)
|
||||||
{
|
{
|
||||||
task = antd_create_task(antd_h2_write,(void *)rq, NULL, rq->client->last_io);
|
antd_h2_write(data);
|
||||||
task->priority++;
|
|
||||||
schedule_task(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
|
task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
|
||||||
@ -46,56 +101,26 @@ void* antd_h2_handle(void* data)
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int antd_h2_read_frame(antd_client_t* cl, antd_h2_frame_t* frame)
|
|
||||||
{
|
|
||||||
uint8_t tmp;
|
|
||||||
frame->length = 0;
|
|
||||||
frame->type = 0;
|
|
||||||
frame->flags = 0;
|
|
||||||
frame->identifier= 0;
|
|
||||||
if( antd_recv(cl,& frame->length,24) != 24) return 0;
|
|
||||||
printf("length is %d\n", frame->length);
|
|
||||||
// TODO:
|
|
||||||
// Values greater than 2^14 (16,384) MUST NOT be
|
|
||||||
// sent unless the receiver has set a larger value for
|
|
||||||
// SETTINGS_MAX_FRAME_SIZE.
|
|
||||||
if( antd_recv(cl,& frame->type,8) != 8) return 0;
|
|
||||||
printf("type is %d\n", frame->type);
|
|
||||||
if( antd_recv(cl,& frame->flags,8) != 8) return 0;
|
|
||||||
if( antd_recv(cl,& tmp,1) != 1) return 0;
|
|
||||||
// identifier
|
|
||||||
if( antd_recv(cl,& frame->identifier,31) != 31) return 0;
|
|
||||||
frame->data = (uint8_t*) malloc(frame->length);
|
|
||||||
if(!frame->data) return 0;
|
|
||||||
if( antd_recv(cl,frame->data, frame->length) != frame->length)
|
|
||||||
{
|
|
||||||
free(frame->data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void* antd_h2_read(void* data)
|
void* antd_h2_read(void* data)
|
||||||
{
|
{
|
||||||
antd_h2_frame_t frame;
|
antd_h2_frame_header_t frame_h;
|
||||||
antd_request_t* rq = (antd_request_t*) data;
|
antd_request_t* rq = (antd_request_t*) data;
|
||||||
antd_task_t* task;
|
if(!antd_h2_read_frame_header(rq->client, &frame_h))
|
||||||
if(!antd_h2_read_frame(rq->client, &frame))
|
|
||||||
{
|
{
|
||||||
// TODO: frame error
|
// TODO: frame error
|
||||||
printf("error reading frame\n");
|
// send goaway frame
|
||||||
ERROR("Unable to read frame from client %d",rq->client->sock);
|
ERROR("Unable to read frame from client %d",rq->client->sock);
|
||||||
task = antd_create_task(NULL, (void *)rq, NULL, time(NULL));
|
return antd_empty_task(data, rq->client->last_io);
|
||||||
task->priority++;
|
|
||||||
return task;
|
|
||||||
}
|
}
|
||||||
// verify frame
|
process_frame(data, &frame_h);
|
||||||
printf("Frame type: %d\n", frame.type & 0xff);
|
return antd_empty_task(data, rq->client->last_io);
|
||||||
return antd_create_task(NULL, data, NULL, time(NULL));
|
|
||||||
}
|
}
|
||||||
void* antd_h2_write(void* data)
|
void* antd_h2_write(void* data)
|
||||||
{
|
{
|
||||||
|
antd_request_t* rq = (antd_request_t*) data;
|
||||||
printf("write task\n");
|
printf("write task\n");
|
||||||
return antd_create_task(NULL, data, NULL, time(NULL));
|
return antd_empty_task(data, rq->client->last_io);
|
||||||
}
|
}
|
82
lib/h2.h
82
lib/h2.h
@ -16,6 +16,81 @@
|
|||||||
#define H2_FRM_WINDOW_UPDATE 0x8
|
#define H2_FRM_WINDOW_UPDATE 0x8
|
||||||
#define H2_FRM_CONTINUATION 0x9
|
#define H2_FRM_CONTINUATION 0x9
|
||||||
|
|
||||||
|
// ERROR code
|
||||||
|
/*
|
||||||
|
The associated condition is not a result of an
|
||||||
|
error. For example, a GOAWAY might include this code to indicate
|
||||||
|
graceful shutdown of a connection.
|
||||||
|
*/
|
||||||
|
#define H2_NO_ERROR 0x0
|
||||||
|
/*
|
||||||
|
The endpoint detected an unspecific protocol
|
||||||
|
error. This error is for use when a more specific error code is
|
||||||
|
not available.
|
||||||
|
*/
|
||||||
|
#define H2_PROTOCOL_ERROR 0x1
|
||||||
|
/*
|
||||||
|
The endpoint encountered an unexpected
|
||||||
|
internal error.
|
||||||
|
*/
|
||||||
|
#define H2_INTERNAL_ERROR 0x2
|
||||||
|
/*
|
||||||
|
The endpoint detected that its peer
|
||||||
|
violated the flow-control protocol.
|
||||||
|
*/
|
||||||
|
#define H2_FLOW_CONTROL_ERROR 0x3
|
||||||
|
/*
|
||||||
|
The endpoint sent a SETTINGS frame but did
|
||||||
|
not receive a response in a timely manner. See Section 6.5.3
|
||||||
|
("Settings Synchronization").
|
||||||
|
*/
|
||||||
|
#define H2_SETTINGS_TIMEOUT 0x4
|
||||||
|
/*
|
||||||
|
The endpoint received a frame after a stream
|
||||||
|
was half-closed.
|
||||||
|
*/
|
||||||
|
#define H2_STREAM_CLOSED 0x5
|
||||||
|
/*
|
||||||
|
The endpoint received a frame with an invalid size.
|
||||||
|
*/
|
||||||
|
#define H2_FRAME_SIZE_ERROR 0x6
|
||||||
|
/*
|
||||||
|
The endpoint refused the stream prior to
|
||||||
|
performing any application processing (see Section 8.1.4 for
|
||||||
|
details).
|
||||||
|
*/
|
||||||
|
#define H2_REFUSED_STREAM 0x7
|
||||||
|
/*
|
||||||
|
Used by the endpoint to indicate that the stream is no
|
||||||
|
longer needed.
|
||||||
|
*/
|
||||||
|
#define H2_CANCEL 0x8
|
||||||
|
/*
|
||||||
|
The endpoint is unable to maintain the
|
||||||
|
header compression context for the connection.
|
||||||
|
*/
|
||||||
|
#define H2_COMPRESSION_ERROR 0x9
|
||||||
|
/*
|
||||||
|
The connection established in response to a CONNECT request (Section 8.3) was reset or abnormally closed.
|
||||||
|
*/
|
||||||
|
#define H2_CONNECT_ERROR 0xa
|
||||||
|
/*
|
||||||
|
The endpoint detected that its peer is
|
||||||
|
exhibiting a behavior that might be generating excessive load.
|
||||||
|
*/
|
||||||
|
#define H2_ENHANCE_YOUR_CALM 0xb
|
||||||
|
/*
|
||||||
|
The underlying transport has properties
|
||||||
|
that do not meet minimum security requirements (see Section 9.2).
|
||||||
|
*/
|
||||||
|
#define H2_INADEQUATE_SECURITY 0xc
|
||||||
|
/*
|
||||||
|
The endpoint requires that HTTP/1.1 be used
|
||||||
|
instead of HTTP/2.
|
||||||
|
*/
|
||||||
|
#define H2_HTTP_1_1_REQUIRED 0xd
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct that holds a
|
* Struct that holds a
|
||||||
* h2 connection
|
* h2 connection
|
||||||
@ -33,7 +108,7 @@ typedef struct {
|
|||||||
} antd_h2_stream_t;
|
} antd_h2_stream_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a H2 frame
|
* a H2 frame header
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// 24 bits length
|
// 24 bits length
|
||||||
@ -44,8 +119,9 @@ typedef struct {
|
|||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
// 31 bits identifier
|
// 31 bits identifier
|
||||||
unsigned int identifier;
|
unsigned int identifier;
|
||||||
uint8_t* data;
|
} antd_h2_frame_header_t;
|
||||||
} antd_h2_frame_t;
|
|
||||||
|
|
||||||
|
|
||||||
void* antd_h2_read(void* rq);
|
void* antd_h2_read(void* rq);
|
||||||
void* antd_h2_write(void* rq);
|
void* antd_h2_write(void* rq);
|
||||||
|
@ -83,11 +83,6 @@ int compressable(char* ctype)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void schedule_task(antd_task_t* task)
|
|
||||||
{
|
|
||||||
UNUSED(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
void htdocs(antd_request_t* rq, char* dest)
|
void htdocs(antd_request_t* rq, char* dest)
|
||||||
{
|
{
|
||||||
dictionary_t xheader = (dictionary_t)dvalue(rq->request, "REQUEST_HEADER");
|
dictionary_t xheader = (dictionary_t)dvalue(rq->request, "REQUEST_HEADER");
|
||||||
|
@ -122,7 +122,6 @@ void __attribute__((weak)) dbdir(char* dest);
|
|||||||
void __attribute__((weak)) tmpdir(char* dest);
|
void __attribute__((weak)) tmpdir(char* dest);
|
||||||
void __attribute__((weak)) plugindir(char* dest);
|
void __attribute__((weak)) plugindir(char* dest);
|
||||||
int __attribute__((weak)) compressable(char* ctype);
|
int __attribute__((weak)) compressable(char* ctype);
|
||||||
void __attribute__((weak)) schedule_task(antd_task_t* task);
|
|
||||||
|
|
||||||
void set_nonblock(int socket);
|
void set_nonblock(int socket);
|
||||||
//void set_block(int socket);
|
//void set_block(int socket);
|
||||||
|
@ -379,3 +379,10 @@ void antd_scheduler_wait(antd_scheduler_t* scheduler)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
antd_task_t* antd_empty_task(void* data,time_t t)
|
||||||
|
{
|
||||||
|
antd_task_t* task = antd_create_task(NULL,data,NULL,t);
|
||||||
|
task->priority++;
|
||||||
|
return task;
|
||||||
|
}
|
@ -115,6 +115,8 @@ void antd_scheduler_destroy(antd_scheduler_t *);
|
|||||||
*/
|
*/
|
||||||
antd_task_t *antd_create_task(void *(*handle)(void *), void *data, void *(*callback)(void *), time_t);
|
antd_task_t *antd_create_task(void *(*handle)(void *), void *data, void *(*callback)(void *), time_t);
|
||||||
|
|
||||||
|
antd_task_t* antd_empty_task(void* data, time_t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
add a task
|
add a task
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user