67 lines
3.0 KiB
C
67 lines
3.0 KiB
C
/* Потоковый HTTP/1.x codec локального proxy. Не владеет сокетами/DNS/ETCP.
|
|
* Заголовки проверяются целиком до пересылки; тело передаётся ограниченными порциями.
|
|
* emit получает исходное число байт для возврата ETCP credit после доставки результата.
|
|
* Возврат feed: 0=нужно продолжение, 1=сообщение завершено, <0=HTTP error status. */
|
|
#ifndef HTTP_PROXY_H
|
|
#define HTTP_PROXY_H
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#define HTTP_PROXY_LINE_LIMIT 8192
|
|
#define HTTP_PROXY_HEADER_LIMIT 32768
|
|
#define HTTP_PROXY_FIELDS_LIMIT 512
|
|
|
|
typedef int (*http_proxy_emit)(void* arg, const uint8_t* data, size_t len, size_t source_len);
|
|
|
|
struct http_proxy_field { char* name; char* value; };
|
|
enum http_proxy_body_state { HTTP_BODY_NONE, HTTP_BODY_LENGTH, HTTP_BODY_EOF, HTTP_BODY_CHUNK_SIZE,
|
|
HTTP_BODY_CHUNK_DATA, HTTP_BODY_CHUNK_CRLF, HTTP_BODY_TRAILERS, HTTP_BODY_DONE };
|
|
|
|
struct http_proxy_message {
|
|
char headers[HTTP_PROXY_HEADER_LIMIT + 1];
|
|
size_t header_len;
|
|
size_t first_line_len;
|
|
struct http_proxy_field fields[HTTP_PROXY_FIELDS_LIMIT];
|
|
unsigned field_count;
|
|
uint8_t headers_done;
|
|
uint8_t minor;
|
|
uint8_t close;
|
|
uint8_t chunked;
|
|
uint8_t has_length;
|
|
uint8_t upgrade;
|
|
uint8_t decode_chunks;
|
|
unsigned status;
|
|
uint64_t length;
|
|
enum http_proxy_body_state body;
|
|
uint64_t remaining;
|
|
char line[HTTP_PROXY_LINE_LIMIT + 1];
|
|
size_t line_len;
|
|
size_t trailer_len;
|
|
unsigned crlf_pos;
|
|
};
|
|
|
|
struct http_proxy_request {
|
|
char host[256];
|
|
char authority[264];
|
|
char upgrade[HTTP_PROXY_LINE_LIMIT + 1];
|
|
uint16_t port;
|
|
uint8_t connect;
|
|
uint8_t head;
|
|
uint8_t close;
|
|
uint8_t minor;
|
|
};
|
|
|
|
// Накапливает только заголовки; хвост входа остаётся у вызывающей стороны.
|
|
int http_proxy_headers_feed(struct http_proxy_message* m, const uint8_t* data, size_t len, size_t* used);
|
|
// Проверяет запрос и отправляет реконструированные заголовки через emit (кроме CONNECT).
|
|
int http_proxy_request_parse(struct http_proxy_message* m, struct http_proxy_request* r, http_proxy_emit emit, void* arg);
|
|
// Проверяет ответ, учитывает HEAD/Upgrade и формирует собственные connection headers.
|
|
int http_proxy_response_parse(struct http_proxy_message* m, const struct http_proxy_request* r,
|
|
int close_client, http_proxy_emit emit, void* arg);
|
|
// Определяет точную границу тела, фильтрует trailers; поддерживает произвольные TCP-разбиения.
|
|
int http_proxy_body_feed(struct http_proxy_message* m, const uint8_t* data, size_t len, size_t* used,
|
|
http_proxy_emit emit, void* arg);
|
|
|
|
#endif
|