This commit is contained in:
lxsang 2020-01-24 16:52:44 +01:00
parent 353323f93a
commit a86a2d150e
7 changed files with 160 additions and 61 deletions

View File

@ -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
View File

@ -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);
} }

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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;
}

View File

@ -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
*/ */