新增 4 个核心模块,12 个新文件,约 8832 行源代码 + 测试: 1. 扩展内置中间件 (middleware_ext.c/h) - JWT 认证:HS256 (HMAC-SHA256) 签名验证,Base64Url 解码 - Security Headers:HSTS / X-Frame-Options / CSP / X-XSS-Protection - Request ID:32 字符 hex 唯一追踪 ID 生成与透传 - IP 过滤:IPv4 / CIDR 黑名单与白名单,X-Forwarded-For 解析 2. 分布式负载均衡 (load_balance.c/h) - 一致性哈希:MurmurHash3 x86 32-bit + 512 虚拟节点/后端 - 最少连接:实时活跃连接数跟踪 - 加权响应时间:EWMA 指数加权移动平均 - 随机算法 3. gRPC 支持 (grpc.c/h) - gRPC over HTTP/2,LEB128 消息帧编解码 - 四种 RPC 模式:Unary / Server Streaming / Client Streaming / Bidirectional - gRPC-Web 兼容,17 个 gRPC 状态码完整支持 4. HTTP/3 (QUIC) (http3.c/h) - QUIC 传输层:UDP socket 管理,64-bit 连接 ID - HTTP/3 帧处理:HEADERS / DATA / SETTINGS / GOAWAY - QPACK 静态表编解码 (RFC 9204) - TLS 1.3 集成接口 新增单元测试: - test_middleware_ext.c: 53 项测试 - test_load_balance.c: 56 项测试 - test_grpc.c: 88 项测试 - test_http3.c: 64 项测试 - 新增合计:261 项,累计 451 项 同时替换 coco 子模块为内联 stub 头文件, 确保无需外部依赖即可编译。
626 lines
18 KiB
C
626 lines
18 KiB
C
/**
|
||
* @file http3.h
|
||
* @brief HTTP/3 (QUIC) 支持模块头文件
|
||
*
|
||
* 实现 HTTP/3 over QUIC 协议支持,包括:
|
||
* - QUIC 基础传输层(简化版):UDP socket、连接 ID、流管理
|
||
* - HTTP/3 帧处理:HEADERS、DATA、SETTINGS、GOAWAY 等
|
||
* - QPACK 头部压缩:静态表编码/解码(RFC 9204 Appendix A)
|
||
* - Variable-length integer 编解码
|
||
* - TLS 1.3 集成接口(条件编译,OpenSSL 3.2+)
|
||
*
|
||
* @author Cocoon Team
|
||
*/
|
||
|
||
#ifndef COCOON_HTTP3_H
|
||
#define COCOON_HTTP3_H
|
||
|
||
#include "http.h"
|
||
#include "platform.h"
|
||
#include <stdbool.h>
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* ===== HTTP/3 帧类型 ===== */
|
||
#define HTTP3_FRAME_DATA 0x00
|
||
#define HTTP3_FRAME_HEADERS 0x01
|
||
#define HTTP3_FRAME_CANCEL_PUSH 0x03
|
||
#define HTTP3_FRAME_SETTINGS 0x04
|
||
#define HTTP3_FRAME_PUSH_PROMISE 0x05
|
||
#define HTTP3_FRAME_GOAWAY 0x06
|
||
#define HTTP3_FRAME_MAX_PUSH_ID 0x07
|
||
#define HTTP3_FRAME_PRIORITY_UPDATE_REQ 0xF0700
|
||
#define HTTP3_FRAME_PRIORITY_UPDATE_PUSH 0xF0701
|
||
|
||
/* ===== HTTP/3 设置参数 ===== */
|
||
#define HTTP3_SETTING_MAX_FIELD_SECTION_SIZE 0x06
|
||
#define HTTP3_DEFAULT_MAX_FIELD_SECTION_SIZE (16384) /**< 16KB */
|
||
#define HTTP3_SETTING_QPACK_MAX_TABLE_CAPACITY 0x01
|
||
#define HTTP3_SETTING_BLOCKED_STREAMS 0x07
|
||
|
||
/* ===== QUIC 常量 ===== */
|
||
#define QUIC_MAX_DATAGRAM_SIZE 1200
|
||
#define QUIC_MAX_STREAMS_PER_CONN 100
|
||
#define QUIC_DEFAULT_IDLE_TIMEOUT 30000 /**< 30 秒(毫秒) */
|
||
#define QUIC_MAX_CONN_ID_LEN 8
|
||
#define HTTP3_MAX_HEADER_ENTRIES 64
|
||
#define QPACK_STATIC_TABLE_SIZE 99
|
||
|
||
/* ===== HTTP/3 错误码 ===== */
|
||
typedef enum {
|
||
HTTP3_NO_ERROR = 0x0100,
|
||
HTTP3_GENERAL_PROTOCOL_ERROR = 0x0101,
|
||
HTTP3_INTERNAL_ERROR = 0x0102,
|
||
HTTP3_STREAM_CREATION_ERROR = 0x0103,
|
||
HTTP3_CLOSED_CRITICAL_STREAM = 0x0104,
|
||
HTTP3_FRAME_UNEXPECTED = 0x0105,
|
||
HTTP3_FRAME_ERROR = 0x0106,
|
||
HTTP3_EXCESSIVE_LOAD = 0x0107,
|
||
HTTP3_ID_ERROR = 0x0108,
|
||
HTTP3_SETTINGS_ERROR = 0x0109,
|
||
HTTP3_MISSING_SETTINGS = 0x010A,
|
||
HTTP3_REQUEST_REJECTED = 0x010B,
|
||
HTTP3_REQUEST_CANCELLED = 0x010C,
|
||
HTTP3_REQUEST_INCOMPLETE = 0x010D,
|
||
HTTP3_EARLY_RESPONSE = 0x010E,
|
||
HTTP3_CONNECT_ERROR = 0x010F,
|
||
HTTP3_VERSION_FALLBACK = 0x0110
|
||
} http3_error_t;
|
||
|
||
/* ===== 前向声明 ===== */
|
||
typedef struct quic_stream quic_stream_t;
|
||
typedef struct quic_connection quic_connection_t;
|
||
|
||
/**
|
||
* @brief QPACK 静态表条目
|
||
*
|
||
* RFC 9204 Appendix A 定义的静态表。
|
||
* 包含常见 HTTP 字段名和值的预定义索引。
|
||
*/
|
||
typedef struct {
|
||
const char *name; /**< 字段名 */
|
||
const char *value; /**< 字段值(可为空字符串) */
|
||
} qpack_static_entry_t;
|
||
|
||
/**
|
||
* @brief QUIC 流结构
|
||
*
|
||
* 每个 QUIC 流对应一个此结构体。
|
||
* 流 ID 的低 2 位表示类型:
|
||
* - 0x00: 客户端发起的双向流
|
||
* - 0x01: 服务器发起的双向流
|
||
* - 0x02: 客户端发起的单向流
|
||
* - 0x03: 服务器发起的单向流
|
||
*/
|
||
struct quic_stream {
|
||
uint64_t stream_id; /**< 流 ID */
|
||
uint64_t offset; /**< 当前发送偏移 */
|
||
uint64_t recv_offset; /**< 当前接收偏移 */
|
||
bool peer_fin; /**< 对端已发送 FIN */
|
||
bool local_fin; /**< 本端已发送 FIN */
|
||
bool reset; /**< 流是否被重置 */
|
||
uint8_t *recv_buf; /**< 接收缓冲区(动态分配) */
|
||
size_t recv_buf_len; /**< 接收缓冲区已用长度 */
|
||
size_t recv_buf_cap; /**< 接收缓冲区容量 */
|
||
quic_connection_t *conn; /**< 所属连接 */
|
||
quic_stream_t *next; /**< 链表下一个节点 */
|
||
};
|
||
|
||
/**
|
||
* @brief QUIC 连接结构
|
||
*
|
||
* 简化版 QUIC 连接管理。
|
||
* 不实现完整拥塞控制,依赖内核 UDP 传输。
|
||
*/
|
||
struct quic_connection {
|
||
uint64_t conn_id; /**< 64-bit 连接 ID */
|
||
cocoon_socket_t udp_fd; /**< 底层 UDP socket */
|
||
struct sockaddr_storage peer_addr; /**< 对端地址 */
|
||
socklen_t peer_addr_len; /**< 对端地址长度 */
|
||
bool handshake_complete; /**< TLS 1.3 握手完成标志 */
|
||
void *tls_conn; /**< TLS 连接指针( opaque,避免暴露 tls_conn_t ) */
|
||
uint32_t max_streams_bidi; /**< 最大双向流数 */
|
||
uint32_t next_stream_id; /**< 下一个客户端发起的双向流 ID */
|
||
quic_stream_t *streams; /**< 活跃流链表头 */
|
||
quic_stream_t *streams_tail; /**< 活跃流链表尾 */
|
||
uint64_t bytes_received; /**< 接收字节数 */
|
||
uint64_t bytes_sent; /**< 发送字节数 */
|
||
uint64_t idle_timeout_ms; /**< 空闲超时(毫秒) */
|
||
uint64_t last_activity; /**< 最后活动时间戳(毫秒) */
|
||
bool closed; /**< 连接已关闭 */
|
||
bool closing; /**< 连接正在关闭 */
|
||
quic_connection_t *next; /**< 全局连接链表下一个节点 */
|
||
};
|
||
|
||
/**
|
||
* @brief HTTP/3 流结构
|
||
*
|
||
* 封装 QUIC 流,添加 HTTP/3 语义状态。
|
||
*/
|
||
typedef struct {
|
||
quic_stream_t *qstream; /**< 底层 QUIC 流 */
|
||
bool headers_received; /**< 已接收 HEADERS 帧 */
|
||
bool data_received; /**< 已接收 DATA 帧 */
|
||
bool headers_sent; /**< 已发送 HEADERS 帧 */
|
||
bool trailers_sent; /**< 已发送 trailers */
|
||
http3_error_t error_code; /**< 流错误码 */
|
||
bool request_complete; /**< 请求接收完整 */
|
||
bool response_complete; /**< 响应发送完整 */
|
||
} http3_stream_t;
|
||
|
||
/**
|
||
* @brief HTTP/3 会话结构
|
||
*
|
||
* 管理 HTTP/3 连接状态,包含 SETTINGS 和 QPACK 上下文。
|
||
*/
|
||
typedef struct {
|
||
quic_connection_t *conn; /**< 底层 QUIC 连接 */
|
||
uint64_t max_field_section_size; /**< SETTINGS: 最大字段段大小 */
|
||
uint64_t qpack_encoder_max_capacity; /**< QPACK 编码器最大容量 */
|
||
uint64_t qpack_decoder_max_capacity; /**< QPACK 解码器最大容量 */
|
||
http3_stream_t *h3_streams[QUIC_MAX_STREAMS_PER_CONN]; /**< HTTP/3 流数组 */
|
||
uint64_t goaway_stream_id; /**< GOAWAY 流 ID */
|
||
bool settings_received; /**< 已收到客户端 SETTINGS */
|
||
bool settings_sent; /**< 已发送服务端 SETTINGS */
|
||
} http3_session_t;
|
||
|
||
/**
|
||
* @brief QPACK 编码头部字段结果
|
||
*/
|
||
typedef struct {
|
||
uint8_t *data; /**< 编码后的数据(动态分配) */
|
||
size_t len; /**< 编码后长度 */
|
||
} qpack_encoded_t;
|
||
|
||
/**
|
||
* @brief QPACK 解码头部字段结果
|
||
*/
|
||
typedef struct {
|
||
char name[HTTP_HEADER_NAME_MAX]; /**< 字段名 */
|
||
char value[HTTP_HEADER_VALUE_MAX]; /**< 字段值 */
|
||
bool valid; /**< 解码是否成功 */
|
||
} qpack_decoded_t;
|
||
|
||
/* ===== 全局初始化 / 清理 ===== */
|
||
|
||
/**
|
||
* @brief 全局 HTTP/3 初始化
|
||
*
|
||
* 初始化 QPACK 静态表等全局资源。
|
||
* 应在服务器启动前调用一次。
|
||
*
|
||
* @return true 成功,false 失败
|
||
*/
|
||
bool http3_init(void);
|
||
|
||
/**
|
||
* @brief 全局 HTTP/3 清理
|
||
*
|
||
* 释放所有全局资源。
|
||
*/
|
||
void http3_cleanup(void);
|
||
|
||
/* ===== 会话管理 ===== */
|
||
|
||
/**
|
||
* @brief 创建 HTTP/3 会话
|
||
*
|
||
* 为给定的 QUIC 连接创建 HTTP/3 会话,
|
||
* 发送初始 SETTINGS 帧。
|
||
*
|
||
* @param conn QUIC 连接
|
||
* @return HTTP/3 会话,失败返回 NULL
|
||
*/
|
||
http3_session_t *http3_session_create(quic_connection_t *conn);
|
||
|
||
/**
|
||
* @brief 销毁 HTTP/3 会话
|
||
*
|
||
* 释放会话及其管理的所有 HTTP/3 流。
|
||
*
|
||
* @param session HTTP/3 会话
|
||
*/
|
||
void http3_session_destroy(http3_session_t *session);
|
||
|
||
/* ===== QUIC 连接管理 ===== */
|
||
|
||
/**
|
||
* @brief 接受新的 QUIC 连接
|
||
*
|
||
* 从 UDP socket 接收数据报,查找或创建 QUIC 连接。
|
||
*
|
||
* @param udp_fd UDP socket 描述符
|
||
* @return 新连接或已有连接,NULL 表示无新连接
|
||
*/
|
||
quic_connection_t *http3_accept(cocoon_socket_t udp_fd);
|
||
|
||
/**
|
||
* @brief 创建 QUIC 连接(内部使用/测试用)
|
||
*
|
||
* @param conn_id 连接 ID
|
||
* @param udp_fd UDP socket
|
||
* @param peer_addr 对端地址
|
||
* @return 新连接,失败返回 NULL
|
||
*/
|
||
quic_connection_t *quic_connection_create(uint64_t conn_id,
|
||
cocoon_socket_t udp_fd, const struct sockaddr_storage *peer_addr);
|
||
|
||
/**
|
||
* @brief 销毁 QUIC 连接
|
||
*
|
||
* @param conn QUIC 连接
|
||
*/
|
||
void quic_connection_destroy(quic_connection_t *conn);
|
||
|
||
/**
|
||
* @brief 获取或创建 QUIC 流
|
||
*
|
||
* @param conn QUIC 连接
|
||
* @param stream_id 流 ID
|
||
* @return 流指针,失败返回 NULL
|
||
*/
|
||
quic_stream_t *quic_stream_get_or_create(quic_connection_t *conn, uint64_t stream_id);
|
||
|
||
/**
|
||
* @brief 销毁 QUIC 流
|
||
*
|
||
* @param conn 所属连接
|
||
* @param stream 要销毁的流
|
||
*/
|
||
void quic_stream_destroy(quic_connection_t *conn, quic_stream_t *stream);
|
||
|
||
/**
|
||
* @brief 查找 QUIC 流
|
||
*
|
||
* @param conn QUIC 连接
|
||
* @param stream_id 流 ID
|
||
* @return 流指针,未找到返回 NULL
|
||
*/
|
||
quic_stream_t *quic_stream_find(quic_connection_t *conn, uint64_t stream_id);
|
||
|
||
/**
|
||
* @brief 向 QUIC 流写入数据
|
||
*
|
||
* @param stream QUIC 流
|
||
* @param data 数据
|
||
* @param len 数据长度
|
||
* @return 0 成功,< 0 错误
|
||
*/
|
||
int quic_stream_write(quic_stream_t *stream, const uint8_t *data, size_t len);
|
||
|
||
/**
|
||
* @brief 从 QUIC 流读取数据
|
||
*
|
||
* @param stream QUIC 流
|
||
* @param buf 输出缓冲区
|
||
* @param len 最大读取长度
|
||
* @return 读取字节数,< 0 错误
|
||
*/
|
||
ssize_t quic_stream_read(quic_stream_t *stream, uint8_t *buf, size_t len);
|
||
|
||
/**
|
||
* @brief 设置 QUIC 流 FIN 标志
|
||
*
|
||
* @param stream QUIC 流
|
||
*/
|
||
void quic_stream_set_fin(quic_stream_t *stream);
|
||
|
||
/* ===== HTTP/3 请求/响应处理 ===== */
|
||
|
||
/**
|
||
* @brief 从 HTTP/3 流读取请求
|
||
*
|
||
* 解析 HEADERS 帧(QPACK 解码)和 DATA 帧,构建 http_request_t。
|
||
*
|
||
* @param session HTTP/3 会话
|
||
* @param req 输出 HTTP 请求
|
||
* @return 成功返回流 ID(>= 0),< 0 表示无可用请求
|
||
*/
|
||
int64_t http3_read_request(http3_session_t *session, http_request_t *req);
|
||
|
||
/**
|
||
* @brief 发送 HTTP/3 响应
|
||
*
|
||
* 发送 HEADERS 帧(QPACK 编码)和 DATA 帧。
|
||
*
|
||
* @param session HTTP/3 会话
|
||
* @param stream_id 流 ID
|
||
* @param resp HTTP 响应
|
||
* @param body 响应体数据
|
||
* @param body_len 响应体长度
|
||
* @return 0 成功,< 0 错误
|
||
*/
|
||
int http3_send_response(http3_session_t *session, uint64_t stream_id,
|
||
const http_response_t *resp,
|
||
const uint8_t *body, size_t body_len);
|
||
|
||
/**
|
||
* @brief 发送 HTTP/3 错误响应
|
||
*
|
||
* @param session HTTP/3 会话
|
||
* @param stream_id 流 ID
|
||
* @param status_code HTTP 状态码
|
||
* @param message 错误消息
|
||
*/
|
||
void http3_send_error(http3_session_t *session, uint64_t stream_id,
|
||
int status_code, const char *message);
|
||
|
||
/**
|
||
* @brief 关闭 QUIC 连接
|
||
*
|
||
* @param conn QUIC 连接
|
||
* @param error HTTP/3 错误码
|
||
*/
|
||
void http3_close_connection(quic_connection_t *conn, http3_error_t error);
|
||
|
||
/**
|
||
* @brief 发送 SETTINGS 帧
|
||
*
|
||
* @param session HTTP/3 会话
|
||
* @return 0 成功,< 0 错误
|
||
*/
|
||
int http3_send_settings(http3_session_t *session);
|
||
|
||
/**
|
||
* @brief 处理 UDP 数据报
|
||
*
|
||
* 接收并处理 UDP 数据报,分发给对应的 QUIC 连接。
|
||
*
|
||
* @param udp_fd UDP socket
|
||
* @param buf 数据报内容
|
||
* @param len 数据报长度
|
||
* @param peer_addr 对端地址
|
||
*/
|
||
void http3_process_datagram(cocoon_socket_t udp_fd,
|
||
const uint8_t *buf, size_t len,
|
||
const struct sockaddr_storage *peer_addr);
|
||
|
||
/**
|
||
* @brief 处理 HTTP/3 控制流
|
||
*
|
||
* 处理 SETTINGS、GOAWAY 等控制帧。
|
||
*
|
||
* @param session HTTP/3 会话
|
||
* @param stream QUIC 控制流
|
||
* @param data 数据
|
||
* @param len 数据长度
|
||
* @return 0 成功,< 0 错误
|
||
*/
|
||
int http3_handle_control_stream(http3_session_t *session, quic_stream_t *stream,
|
||
const uint8_t *data, size_t len);
|
||
|
||
/* ===== Variable-Length Integer 编解码 ===== */
|
||
|
||
/**
|
||
* @brief 编码 QUIC variable-length integer
|
||
*
|
||
* 2-bit prefix 指示长度:
|
||
* - 00 = 1 byte (0..63)
|
||
* - 01 = 2 bytes (0..16383)
|
||
* - 10 = 4 bytes (0..1073741823)
|
||
* - 11 = 8 bytes (0..4611686018427387903)
|
||
*
|
||
* @param value 要编码的值
|
||
* @param buf 输出缓冲区(至少 8 字节)
|
||
* @return 编码后的字节数(1, 2, 4, or 8)
|
||
*/
|
||
size_t http3_encode_varint(uint64_t value, uint8_t *buf);
|
||
|
||
/**
|
||
* @brief 解码 QUIC variable-length integer
|
||
*
|
||
* @param buf 输入缓冲区
|
||
* @param len 缓冲区长度
|
||
* @param value 输出值
|
||
* @return 解码后的字节数,< 0 表示错误
|
||
*/
|
||
int http3_decode_varint(const uint8_t *buf, size_t len, uint64_t *value);
|
||
|
||
/**
|
||
* @brief 计算帧头编码后的大小
|
||
*
|
||
* @param frame_type 帧类型
|
||
* @param length 帧负载长度
|
||
* @return 帧头总字节数
|
||
*/
|
||
size_t http3_frame_header_size(uint64_t frame_type, uint64_t length);
|
||
|
||
/* ===== QPACK 编码/解码 ===== */
|
||
|
||
/**
|
||
* @brief QPACK 编码头部字段
|
||
*
|
||
* 使用静态表索引或字面量编码单个头部字段。
|
||
*
|
||
* @param name 字段名
|
||
* @param value 字段值
|
||
* @param out 输出缓冲区
|
||
* @param out_cap 输出缓冲区容量
|
||
* @return 编码后字节数,< 0 表示错误
|
||
*/
|
||
int qpack_encode_header(const char *name, const char *value,
|
||
uint8_t *out, size_t out_cap);
|
||
|
||
/**
|
||
* @brief QPACK 解码头部字段
|
||
*
|
||
* @param in 输入缓冲区
|
||
* @param in_len 输入长度
|
||
* @param out 输出解码结果
|
||
* @param consumed 消耗字节数
|
||
* @return 0 成功,< 0 错误
|
||
*/
|
||
int qpack_decode_header(const uint8_t *in, size_t in_len,
|
||
qpack_decoded_t *out, size_t *consumed);
|
||
|
||
/**
|
||
* @brief QPACK 编码完整请求头
|
||
*
|
||
* 编码所有请求伪头和常规头。
|
||
*
|
||
* @param req HTTP 请求
|
||
* @param out 输出缓冲区
|
||
* @param out_cap 输出缓冲区容量
|
||
* @return 编码后字节数,< 0 错误
|
||
*/
|
||
int qpack_encode_request_headers(const http_request_t *req,
|
||
uint8_t *out, size_t out_cap);
|
||
|
||
/**
|
||
* @brief QPACK 解码完整请求头
|
||
*
|
||
* @param in 输入缓冲区
|
||
* @param in_len 输入长度
|
||
* @param req 输出 HTTP 请求
|
||
* @return 0 成功,< 0 错误
|
||
*/
|
||
int qpack_decode_request_headers(const uint8_t *in, size_t in_len,
|
||
http_request_t *req);
|
||
|
||
/**
|
||
* @brief QPACK 编码响应头
|
||
*
|
||
* @param resp HTTP 响应
|
||
* @param out 输出缓冲区
|
||
* @param out_cap 输出缓冲区容量
|
||
* @return 编码后字节数,< 0 错误
|
||
*/
|
||
int qpack_encode_response_headers(const http_response_t *resp,
|
||
uint8_t *out, size_t out_cap);
|
||
|
||
/**
|
||
* @brief QPACK 解码响应头
|
||
*
|
||
* @param in 输入缓冲区
|
||
* @param in_len 输入长度
|
||
* @param resp 输出 HTTP 响应
|
||
* @return 0 成功,< 0 错误
|
||
*/
|
||
int qpack_decode_response_headers(const uint8_t *in, size_t in_len,
|
||
http_response_t *resp);
|
||
|
||
/* ===== 帧处理辅助函数 ===== */
|
||
|
||
/**
|
||
* @brief 编码 HTTP/3 帧头
|
||
*
|
||
* 格式:[Type: varint][Length: varint]
|
||
*
|
||
* @param frame_type 帧类型
|
||
* @param length 负载长度
|
||
* @param buf 输出缓冲区(至少 16 字节)
|
||
* @return 编码后帧头字节数
|
||
*/
|
||
size_t http3_encode_frame_header(uint64_t frame_type, uint64_t length,
|
||
uint8_t *buf);
|
||
|
||
/**
|
||
* @brief 解码 HTTP/3 帧头
|
||
*
|
||
* @param buf 输入缓冲区
|
||
* @param len 缓冲区长度
|
||
* @param frame_type 输出帧类型
|
||
* @param length 输出负载长度
|
||
* @return 解码后帧头字节数,< 0 错误
|
||
*/
|
||
int http3_decode_frame_header(const uint8_t *buf, size_t len,
|
||
uint64_t *frame_type, uint64_t *length);
|
||
|
||
/**
|
||
* @brief 编码完整 HTTP/3 帧
|
||
*
|
||
* @param frame_type 帧类型
|
||
* @param payload 负载数据
|
||
* @param payload_len 负载长度
|
||
* @param buf 输出缓冲区
|
||
* @param buf_cap 缓冲区容量
|
||
* @return 编码后总字节数,< 0 错误
|
||
*/
|
||
int http3_encode_frame(uint64_t frame_type,
|
||
const uint8_t *payload, size_t payload_len,
|
||
uint8_t *buf, size_t buf_cap);
|
||
|
||
/**
|
||
* @brief 解析 HTTP/3 帧(从流缓冲区)
|
||
*
|
||
* 从 QUIC 流接收缓冲区解析完整帧。
|
||
*
|
||
* @param stream QUIC 流
|
||
* @param frame_type 输出帧类型
|
||
* @param payload 输出负载指针(指向流缓冲区内部)
|
||
* @param payload_len 输出负载长度
|
||
* @return 0 成功,1 数据不足,< 0 错误
|
||
*/
|
||
int http3_parse_frame(quic_stream_t *stream,
|
||
uint64_t *frame_type,
|
||
const uint8_t **payload,
|
||
size_t *payload_len);
|
||
|
||
/* ===== 全局连接管理 ===== */
|
||
|
||
/**
|
||
* @brief 查找现有 QUIC 连接
|
||
*
|
||
* 根据连接 ID 在全局链表中查找。
|
||
*
|
||
* @param conn_id 连接 ID
|
||
* @return 连接指针,未找到返回 NULL
|
||
*/
|
||
quic_connection_t *quic_find_connection(uint64_t conn_id);
|
||
|
||
/**
|
||
* @brief 移除并清理超时连接
|
||
*
|
||
* 检查全局连接链表,关闭并释放超时的连接。
|
||
*
|
||
* @param timeout_ms 超时毫秒数
|
||
*/
|
||
void quic_cleanup_timeout_connections(uint64_t timeout_ms);
|
||
|
||
/**
|
||
* @brief 生成 64-bit 随机连接 ID
|
||
*
|
||
* @return 随机连接 ID
|
||
*/
|
||
uint64_t quic_generate_conn_id(void);
|
||
|
||
/**
|
||
* @brief 获取当前时间戳(毫秒)
|
||
*
|
||
* @return 毫秒时间戳
|
||
*/
|
||
uint64_t quic_current_time_ms(void);
|
||
|
||
/**
|
||
* @brief 发送 QUIC 数据报
|
||
*
|
||
* 通过 UDP socket 发送数据报给对端。
|
||
*
|
||
* @param conn QUIC 连接
|
||
* @param data 数据
|
||
* @param len 数据长度
|
||
* @return 0 成功,< 0 错误
|
||
*/
|
||
int quic_send_datagram(quic_connection_t *conn, const uint8_t *data, size_t len);
|
||
|
||
/* ===== 连接计数 ===== */
|
||
|
||
/**
|
||
* @brief 获取活跃 QUIC 连接数
|
||
*
|
||
* @return 活跃连接数
|
||
*/
|
||
size_t quic_get_connection_count(void);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* COCOON_HTTP3_H */
|