ant-http/lib/h2.c
2020-02-14 11:31:52 +01:00

126 lines
3.8 KiB
C

#include "h2.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)
{
char buf[25];
antd_h2_frame_header_t frame_h;
antd_request_t* rq = (antd_request_t*) data;
int count = antd_recv(rq->client,buf,24);
if(count != 24)
{
// TODO servers MUST treat an invalid connection preface as a
// connection error (Section 5.4.1) of type PROTOCOL_ERROR
ERROR("Unable to read preface for client %d: [%s]",rq->client->sock,buf);
return antd_empty_task((void *)rq,rq->client->last_io);
}
buf[24] = '\0';
if(strcmp(buf, H2_CONN_PREFACE) != 0)
{
ERROR("Connection preface is not correct for client %d: [%s]",rq->client->sock,buf);
// TODO servers MUST treat an invalid connection preface as a
// connection error (Section 5.4.1) of type PROTOCOL_ERROR
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);
}
void* antd_h2_handle(void* data)
{
antd_request_t* rq = (antd_request_t*) data;
antd_task_t* task;
if(rq->client->flags & CLIENT_FL_READABLE)
{
antd_h2_read(data);
}
if(rq->client->flags & CLIENT_FL_WRITABLE)
{
antd_h2_write(data);
}
task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
task->priority++;
return task;
}
void* antd_h2_read(void* data)
{
antd_h2_frame_header_t frame_h;
antd_request_t* rq = (antd_request_t*) data;
if(!antd_h2_read_frame_header(rq->client, &frame_h))
{
// TODO: frame error
// send goaway frame
ERROR("Unable to read frame from client %d",rq->client->sock);
return antd_empty_task(data, rq->client->last_io);
}
process_frame(data, &frame_h);
return antd_empty_task(data, rq->client->last_io);
}
void* antd_h2_write(void* data)
{
antd_request_t* rq = (antd_request_t*) data;
printf("write task\n");
return antd_empty_task(data, rq->client->last_io);
}