mirror of
https://github.com/lxsang/ant-http
synced 2024-11-18 01:08:21 +01:00
126 lines
3.8 KiB
C
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);
|
|
} |