尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

nghttp2 扩展帧接收注册函数 nghttp2_option_set_user_recv_extension_type 全面解析

发布时间:2026/9/17 6:32:28

资讯中心
01
ARTICLE

nghttp2 扩展帧接收注册函数 nghttp2_option_set_user_recv_extension_type 全面解析

nghttp2 扩展帧接收注册函数 nghttp2_option_set_user_recv_extension_type 全面解析
nghttp2 扩展帧接收注册函数 nghttp2_option_set_user_recv_extension_type 全面解析【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit本指南以 nghttp2-1.65.0内嵌于当前 fluent-bit 仓库lib/nghttp2-1.65.0/中的 nghttp2_option_set_user_recv_extension_type.rst 为骨架围绕nghttp2_option_set_user_recv_extension_type()这一个 API 展开讲解它如何向 nghttp2 会话注册应用程序愿意通过自定义回调接收的 HTTP/2 扩展帧类型并结合库内实现nghttp2_option.c、nghttp2_session.c、头文件声明、程序员指南示例与单元测试带你掌握扩展帧接收的完整调用链与底层原理。读完本文你将能够在自己的 nghttp2 客户端/服务端程序中正确注册、接收并解包任意自定义 HTTP/2 扩展帧。函数签名与核心语义该 API 的原型定义在公共头文件 nghttp2.h 中#include nghttp2/nghttp2.h void nghttp2_option_set_user_recv_extension_type(nghttp2_option *option, uint8_t type);其作用原文语义是设置应用程序愿意通过用户自定义回调处理的扩展帧类型。这里的用户自定义回调特指两个回调nghttp2_on_extension_chunk_recv_callback——负责逐段缓冲buffering到达的扩展帧载荷nghttp2_unpack_extension_callback——负责把缓冲好的 wire format 载荷解包unpack为应用程序可用的结构。二者在 nghttp2.h 中定义完整语义见 types.rst。核心语义要点如下type是扩展帧类型号取值范围必须严格大于0x9十进制 9若传入的type不满足上述条件该函数什么都不做静默忽略不报错可多次调用为同一个nghttp2_option注册多个扩展帧类型全部生效纯发送场景无需调用——如果应用只是通过nghttp2_submit_extension()发送扩展帧、并不打算接收对端发来的扩展帧则完全不需要调用此函数。为什么必须严格大于 0x9HTTP/2 帧类型空间HTTP/2 规范RFC 9113在帧头9 字节固定头部的第 3 字节编码帧类型8 位并预定义了 0x00x9 共 10 种标准帧类型值帧名0x0DATA0x1HEADERS0x2PRIORITY0x3RST_STREAM0x4SETTINGS0x5PUSH_PROMISE0x6PING0x7GOAWAY0x8WINDOW_UPDATE0x9CONTINUATION因此0xa10及以上的类型号才属于扩展帧类型如NGHTTP2_ALTSVC即为0xa。nghttp2_option_set_user_recv_extension_type()的参数检查正是基于这一规范约定type若落在标准帧区间内注册无意义函数直接返回。底层实现剖析位图式类型集合该函数的实现在 nghttp2_option.cstatic void set_ext_type(uint8_t *ext_types, uint8_t type) { ext_types[type / 8] (uint8_t)(ext_types[type / 8] | (1 (type 0x7))); } void nghttp2_option_set_user_recv_extension_type(nghttp2_option *option, uint8_t type) { if (type 10) { return; } option-opt_set_mask | NGHTTP2_OPT_USER_RECV_EXT_TYPES; set_ext_type(option-user_recv_ext_types, type); }从源码可以看到三个关键设计越界静默返回if (type 10) return;与文档中 must be strictly greater than 0x9. Otherwise, this function does nothing 完全对应。位图存储nghttp2_option结构体内定义了一个uint8_t user_recv_ext_types[32]数组见 nghttp2_option.h共 32×8 256 位恰好覆盖 8 位帧类型号 0255 的全部取值空间。set_ext_type通过type / 8定位字节、1 (type 0x7)定位位把对应帧类型标记进位图。由于是按位或写入多次调用天然合并无需担心覆盖。掩码标记设置opt_set_mask | NGHTTP2_OPT_USER_RECV_EXT_TYPES用于让会话创建逻辑知道该选项已被显式设置从而把位图拷贝进会话。从 option 到 session类型集合如何生效nghttp2_option只是配置载体真正在收帧时起作用的是会话内部拷贝的位图。在 nghttp2_session.c 中创建会话如nghttp2_session_client_new2时会把选项位图整体拷贝到会话memcpy((*session_ptr)-user_recv_ext_types, option-user_recv_ext_types, sizeof((*session_ptr)-user_recv_ext_types));随后库在帧释放与分发路径上通过check_ext_type_set(session-user_recv_ext_types, frame-hd.type)判断某帧是否属于应用注册的自定义扩展帧类型见 nghttp2_session.c 及 L5722 附近的收帧路径。这解释了为什么必须在创建会话之前就把扩展帧类型注册进 option并用该 option 创建会话——例如nghttp2_session_client_new2(session, callbacks, user_data, option);接收扩展帧的完整调用链与示例注册与回调装配按 programmers-guide.rst 的完整示例接收扩展帧需要四步实现on_extension_chunk_recv_callback把到达的载荷逐段缓冲到应用缓冲区实现unpack_extension_callback把缓冲内容按自定义格式解包可把结果对象存入*payload库不持有该指针应用需自行管理内存通过nghttp2_session_callbacks_set_on_extension_chunk_recv_callback()与nghttp2_session_callbacks_set_unpack_extension_callback()装配两个回调调用nghttp2_option_set_user_recv_extension_type()注册帧类型并用该 option 创建会话。以 ALTSVC帧类型0xa为例两个回调的典型实现如下来自程序员指南略作整理typedef struct { const uint8_t *origin; size_t originlen; const uint8_t *field; size_t fieldlen; } alt_svc; /* buffers incoming ALTSVC payload */ uint8_t altsvc_buffer[4096]; size_t altsvc_bufferlen 0; int on_extension_chunk_recv_callback(nghttp2_session *session, const nghttp2_frame_hd *hd, const uint8_t *data, size_t len, void *user_data) { if (sizeof(altsvc_buffer) altsvc_bufferlen len) { altsvc_bufferlen 0; return NGHTTP2_ERR_CANCEL; } memcpy(altsvc_buffer altsvc_bufferlen, data, len); altsvc_bufferlen len; return 0; } int unpack_extension_callback(nghttp2_session *session, void **payload, const nghttp2_frame_hd *hd, void *user_data) { /* ALTSVC wire format: 2-byte origin length origin field-value */ uint8_t *p altsvc_buffer, *end altsvc_buffer altsvc_bufferlen; size_t originlen ((*p) 8) *(p 1); p 2; if (p originlen end) { altsvc_bufferlen 0; return NGHTTP2_ERR_CANCEL; } alt_svc *altsvc (alt_svc *)malloc(sizeof(alt_svc)); altsvc-origin p; altsvc-originlen originlen; altsvc-field p originlen; altsvc-fieldlen end - (p originlen); *payload altsvc; /* 解包结果存入 *payload */ altsvc_bufferlen 0; return 0; }装配回调并注册帧类型nghttp2_session_callbacks_set_on_extension_chunk_recv_callback( callbacks, on_extension_chunk_recv_callback); nghttp2_session_callbacks_set_unpack_extension_callback( callbacks, unpack_extension_callback); nghttp2_option_set_user_recv_extension_type(option, 0xa); nghttp2_session_client_new2(session, callbacks, user_data, option);在 on_frame_recv_callback 中消费解包完成后库会照常调用nghttp2_on_frame_recv_callback此时*payload可通过frame-ext.payload取得应用可在该回调中读取数据并释放内存int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) { switch (frame-hd.type) { case 0xa: { alt_svc *altsvc (alt_svc *)frame-ext.payload; fprintf(stderr, ALTSVC frame received\n); fprintf(stderr, origin: %.*s\n, (int)altsvc-originlen, altsvc-origin); fprintf(stderr, field : %.*s\n, (int)altsvc-fieldlen, altsvc-field); free(altsvc); break; } } return 0; }错误处理约定两个回调的返回值约定一致见 nghttp2.h返回0表示成功返回NGHTTP2_ERR_CANCEL表示中止处理该扩展帧nghttp2_on_frame_recv_callback将不再被调用返回NGHTTP2_ERR_CALLBACK_FAILURE表示致命错误nghttp2_session_recv()与nghttp2_session_mem_recv2()会立即返回该错误码其他非零返回值目前一律按NGHTTP2_ERR_CALLBACK_FAILURE处理。与内置接收builtin类型的区别与优先级nghttp2 另提供nghttp2_option_set_builtin_recv_extension_type()用于接收库内置处理器支持的扩展帧目前包括 ALTSVC、ORIGIN 与 PRIORITY_UPDATE见 nghttp2_option.c 的 switch 实现。两者的差异见 nghttp2_option_set_builtin_recv_extension_type.rst对比维度user_recv_extension_typebuiltin_recv_extension_type处理方式用户自定义回调chunk unpack库内置 handler支持的帧类型任意 0x9的类型号256 位位图仅 ALTSVC、ORIGIN、PRIORITY_UPDATE适用场景自定义私有扩展帧标准扩展帧优先级同一类型同时注册时user 版本优先被 user 版本覆盖关键点如果同一帧类型同时通过两个函数注册后者user 版本优先生效——这是文档与 programmers-guide.rst 中明确声明、并在会话内部check_ext_type_set优先于builtin_recv_ext_types判断中体现的设计见 nghttp2_session.c。这意味着即使 nghttp2 内置了某扩展帧的处理你仍可接管该帧类型实现自己的 handler。单元测试验证仓库的会话测试 nghttp2_session_test.c 中的test_nghttp2_session_recv_extension直接覆盖了本 API 的行为nghttp2_option_new(option); nghttp2_option_set_user_recv_extension_type(option, 111); ... nghttp2_session_client_new2(session, callbacks, ud, option);测试构造了一个帧类型为1110x6f、带任意 flags 与 stream_id 的扩展帧通过nghttp2_session_mem_recv2()送入会话随后断言接收字节数正确、on_frame_recv_callback收到的hd.type 111、flags 与 stream_id 原样透传、载荷 Hello World! 完整进入缓冲。测试还分别验证了在on_extension_chunk_recv_callback和unpack_extension_callback中返回NGHTTP2_ERR_CANCEL时on_frame_recv_callback不再被调用frame_recv_cb_called 0。这三条路径共同印证了本文描述的完整调用链。使用要点与注意事项必须在创建会话前注册位图在nghttp2_session_client_new2()/nghttp2_session_server_new2()时从 option 拷贝事后修改 option 不影响已创建的会话会话生命周期内如需变更接收类型需重建会话。同一 option 可复用一个nghttp2_option可注册多个类型多次调用也可同时传给多个会话。type 参数是uint8_t帧类型号为 8 位合法范围是 102550xa0xff传入 09 会被静默忽略建议在调用前自行校验避免误解。发送不受影响仅发送扩展帧时无需任何注册只有接收路径才需要调用本函数。内存管理责任在应用unpack_extension_callback写入*payload的指针由库透传给on_frame_recv_callback的frame-ext.payload库不负责释放应用需在消费后自行free也可完全不使用*payload采用自己的机制处理。与内置类型的覆盖关系若希望覆盖内置类型如 ALTSVC的处理用本函数注册相同类型号即可user 回调优先。缓冲区需防御性检查on_extension_chunk_recv_callback可能被多次调用以传输完整载荷需自行累计长度并做越界保护参考示例中的sizeof(altsvc_buffer) altsvc_bufferlen len检查越界时返回NGHTTP2_ERR_CANCEL中止处理。参考文档索引本函数 API 文档nghttp2_option_set_user_recv_extension_type.rst内置接收对照文档nghttp2_option_set_builtin_recv_extension_type.rst头文件声明与回调定义nghttp2.h完整收发示例程序员指南programmers-guide.rst回调类型语义说明types.rst实现源码nghttp2_option.c、nghttp2_session.c单元测试nghttp2_session_test.c【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。