25
25
#include " swoole_http2.h"
26
26
27
27
#include < nghttp2/nghttp2.h>
28
+ #include < nghttp2/nghttp2ver.h>
28
29
29
30
using namespace swoole ;
30
31
using namespace std ;
@@ -136,7 +137,6 @@ struct Http2Session {
136
137
Server *server;
137
138
std::unordered_map<int32_t , std::string> stream_paths;
138
139
std::unordered_map<int32_t , std::string> stream_data;
139
- std::unordered_map<int32_t , std::shared_ptr<File>> file_data_sources;
140
140
141
141
Http2Session (SessionId _fd, Server *_serv) : fd(_fd), session(nullptr ), server(_serv) {}
142
142
~Http2Session () {
@@ -147,7 +147,6 @@ struct Http2Session {
147
147
}
148
148
};
149
149
150
- // 错误处理宏
151
150
#define CHECK_NGHTTP2 (expr, error_msg ) \
152
151
do { \
153
152
int rv = (expr); \
@@ -171,9 +170,7 @@ static ssize_t send_callback(nghttp2_session *session, const uint8_t *data, size
171
170
return length;
172
171
}
173
172
174
- // 处理流关闭回调
175
173
static int on_stream_close_callback (nghttp2_session *session, int32_t stream_id, uint32_t error_code, void *user_data) {
176
- // 当 HTTP/2 流关闭时清理资源
177
174
return 0 ;
178
175
}
179
176
@@ -217,29 +214,23 @@ static int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame
217
214
if (frame->headers .cat == NGHTTP2_HCAT_REQUEST) {
218
215
swoole_trace_log (SW_TRACE_HTTP2, " Received HEADERS frame for stream %d" , frame->hd .stream_id );
219
216
220
- // 如果头部帧有 END_STREAM 标志,表示请求已完成(没有请求体)
221
217
if (frame->hd .flags & NGHTTP2_FLAG_END_STREAM) {
222
- // 请求已完全接收,可以生成响应
223
218
handle_request (session, frame->hd .stream_id , http2_session);
224
219
}
225
220
}
226
221
break ;
227
222
case NGHTTP2_DATA:
228
223
swoole_trace_log (SW_TRACE_HTTP2, " Received DATA frame for stream %d" , frame->hd .stream_id );
229
224
230
- // 如果数据帧有 END_STREAM 标志,表示请求已完成
231
225
if (frame->hd .flags & NGHTTP2_FLAG_END_STREAM) {
232
- // 请求已完全接收,可以生成响应
233
226
handle_request (session, frame->hd .stream_id , http2_session);
234
227
}
235
228
break ;
236
- // ... 其他 case 分支保持不变
237
229
}
238
230
239
231
return 0 ;
240
232
}
241
233
242
- // 处理数据块回调
243
234
static int on_data_chunk_recv_callback (
244
235
nghttp2_session *session, uint8_t flags, int32_t stream_id, const uint8_t *data, size_t len, void *user_data) {
245
236
auto http2_session = static_cast <Http2Session *>(user_data);
@@ -252,7 +243,6 @@ static int on_data_chunk_recv_callback(
252
243
return 0 ;
253
244
}
254
245
255
- // 添加优先级回调
256
246
static int on_frame_not_send_callback (nghttp2_session *session,
257
247
const nghttp2_frame *frame,
258
248
int lib_error_code,
@@ -262,7 +252,6 @@ static int on_frame_not_send_callback(nghttp2_session *session,
262
252
return 0 ;
263
253
}
264
254
265
- // 添加窗口更新回调
266
255
static int on_frame_send_callback (nghttp2_session *session, const nghttp2_frame *frame, void *user_data) {
267
256
if (frame->hd .type == NGHTTP2_WINDOW_UPDATE) {
268
257
DEBUG () << " Window update sent: stream=" << frame->hd .stream_id
@@ -271,7 +260,6 @@ static int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame
271
260
return 0 ;
272
261
}
273
262
274
- // 字符串数据回调
275
263
static ssize_t string_read_callback (nghttp2_session *session,
276
264
int32_t stream_id,
277
265
uint8_t *buf,
@@ -313,21 +301,17 @@ static void handle_request(nghttp2_session *session, int32_t stream_id, Http2Ses
313
301
path.c_str (),
314
302
request_body.length ());
315
303
304
+ auto header_server = " nghttp2-server/" NGHTTP2_VERSION;
316
305
// 准备响应头
317
306
nghttp2_nv hdrs[] = {{(uint8_t *) " :status" , (uint8_t *) " 200" , 7 , 3 , NGHTTP2_NV_FLAG_NONE},
318
307
{(uint8_t *) " content-type" , (uint8_t *) " text/html" , 12 , 9 , NGHTTP2_NV_FLAG_NONE},
319
- {(uint8_t *) " server" , (uint8_t *) " nghttp2-custom/1.0 " , 6 , 17 , NGHTTP2_NV_FLAG_NONE}};
308
+ {(uint8_t *) " server" , (uint8_t *) header_server , 6 , strlen (header_server) , NGHTTP2_NV_FLAG_NONE}};
320
309
321
- // 根据路径提供不同的响应
322
310
if (path == " /" || path == " /index.html" ) {
323
- // 主页响应
324
311
const char *body = " <html><body><h1>Welcome to HTTP/2 Server</h1>"
325
312
" <p>This is a simple HTTP/2 server implementation.</p>"
326
- " <link rel='stylesheet' href='/style.css'>"
327
- " <script src='/script.js'></script>"
328
313
" </body></html>" ;
329
314
330
- // 创建数据提供者
331
315
nghttp2_data_provider data_prd;
332
316
data_prd.source .ptr = (void *) body;
333
317
data_prd.read_callback = string_read_callback;
@@ -339,46 +323,12 @@ static void handle_request(nghttp2_session *session, int32_t stream_id, Http2Ses
339
323
SW_LOG_ERROR, SW_ERROR_HTTP2_INTERNAL_ERROR, " Failed to submit response: %s" , nghttp2_strerror (rv));
340
324
return ;
341
325
}
342
- // 服务器推送逻辑保持不变...
343
- } else if (path == " /about" ) {
344
- // 关于页面
345
- const char *body = " <html><body><h1>About This Server</h1>"
346
- " <p>This is a custom HTTP/2 server built with nghttp2.</p>"
347
- " </body></html>" ;
348
-
349
- nghttp2_data_provider data_prd;
350
- data_prd.source .ptr = (void *) body;
351
- data_prd.read_callback = string_read_callback;
352
-
353
- nghttp2_submit_response (session, stream_id, hdrs, sizeof (hdrs) / sizeof (hdrs[0 ]), &data_prd);
354
- } else if (path == " /style.css" || path == " /script.js" ) {
355
- // 这些资源可能已经被推送,但客户端仍可能直接请求它们
356
- nghttp2_nv content_hdrs[] = {
357
- {(uint8_t *) " :status" , (uint8_t *) " 200" , 7 , 3 , NGHTTP2_NV_FLAG_NONE},
358
- {(uint8_t *) " content-type" ,
359
- (uint8_t *) (path == " /style.css" ? " text/css" : " application/javascript" ),
360
- 12 ,
361
- (path == " /style.css" ? 8 : 22 ),
362
- NGHTTP2_NV_FLAG_NONE},
363
- {(uint8_t *) " server" , (uint8_t *) " nghttp2-custom/1.0" , 6 , 17 , NGHTTP2_NV_FLAG_NONE}};
364
-
365
- const char *content =
366
- path == " /style.css"
367
- ? " body { font-family: Arial; color: #333; max-width: 800px; margin: 0 auto; padding: 20px; }"
368
- : " console.log('HTTP/2 server push demo!');" ;
369
-
370
- nghttp2_data_provider data_prd;
371
- data_prd.source .ptr = (void *) content;
372
- data_prd.read_callback = string_read_callback;
373
-
374
- nghttp2_submit_response (
375
- session, stream_id, content_hdrs, sizeof (content_hdrs) / sizeof (content_hdrs[0 ]), &data_prd);
376
326
} else {
377
327
// 404 Not Found
378
328
nghttp2_nv error_hdrs[] = {
379
329
{(uint8_t *) " :status" , (uint8_t *) " 404" , 7 , 3 , NGHTTP2_NV_FLAG_NONE},
380
330
{(uint8_t *) " content-type" , (uint8_t *) " text/html" , 12 , 9 , NGHTTP2_NV_FLAG_NONE},
381
- {(uint8_t *) " server" , (uint8_t *) " nghttp2-custom/1.0 " , 6 , 17 , NGHTTP2_NV_FLAG_NONE}};
331
+ {(uint8_t *) " server" , (uint8_t *) header_server , 6 , 17 , NGHTTP2_NV_FLAG_NONE}};
382
332
383
333
const char *body = " <html><body><h1>404 Not Found</h1>"
384
334
" <p>The requested resource was not found on this server.</p>"
@@ -391,16 +341,14 @@ static void handle_request(nghttp2_session *session, int32_t stream_id, Http2Ses
391
341
nghttp2_submit_response (session, stream_id, error_hdrs, sizeof (error_hdrs) / sizeof (error_hdrs[0 ]), &data_prd);
392
342
}
393
343
394
- // 触发发送
395
344
nghttp2_session_send (session);
396
345
}
397
346
398
347
static void http2_send_settings (Http2Session *session_data) {
399
- // 设置 HTTP/2 服务器连接设置
400
348
nghttp2_settings_entry settings[] = {
401
349
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
402
- {NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, 1048576 }, // 1MB 初始窗口大小
403
- {NGHTTP2_SETTINGS_MAX_FRAME_SIZE, 16384 } // 16KB 最大帧大小
350
+ {NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, 1048576 },
351
+ {NGHTTP2_SETTINGS_MAX_FRAME_SIZE, 16384 }
404
352
};
405
353
406
354
auto rv = nghttp2_submit_settings (
@@ -411,37 +359,29 @@ static void http2_send_settings(Http2Session *session_data) {
411
359
return ;
412
360
}
413
361
414
- // 发送初始 SETTINGS 帧
415
362
nghttp2_session_send (session_data->session );
416
363
}
417
364
418
365
static std::shared_ptr<Http2Session> create_http2_session (Server *serv, SessionId fd) {
419
366
auto session_data = std::make_shared<Http2Session>(fd, serv);
420
367
421
- // 创建回调
422
368
nghttp2_session_callbacks *callbacks;
423
369
int rv = nghttp2_session_callbacks_new (&callbacks);
424
370
if (rv != 0 ) {
425
371
swoole_warning (" Failed to create nghttp2 callbacks: %s" , nghttp2_strerror (rv));
426
372
return nullptr ;
427
373
}
428
374
429
- // 设置回调函数
430
375
nghttp2_session_callbacks_set_send_callback (callbacks, send_callback);
431
376
nghttp2_session_callbacks_set_on_frame_recv_callback (callbacks, on_frame_recv_callback);
432
377
nghttp2_session_callbacks_set_on_stream_close_callback (callbacks, on_stream_close_callback);
433
378
nghttp2_session_callbacks_set_on_header_callback (callbacks, on_header_callback);
434
379
nghttp2_session_callbacks_set_on_begin_headers_callback (callbacks, on_begin_headers_callback);
435
380
nghttp2_session_callbacks_set_on_data_chunk_recv_callback (callbacks, on_data_chunk_recv_callback);
436
-
437
- // 在 create_http2_session 中添加此回调
438
381
nghttp2_session_callbacks_set_on_frame_not_send_callback (callbacks, on_frame_not_send_callback);
439
-
440
- // 可选:设置更多回调
441
382
nghttp2_session_callbacks_set_on_frame_send_callback (callbacks, on_frame_send_callback);
442
383
nghttp2_session_callbacks_set_on_frame_not_send_callback (callbacks, on_frame_not_send_callback);
443
384
444
- // 创建服务器会话
445
385
rv = nghttp2_session_server_new (&session_data->session , callbacks, session_data.get ());
446
386
nghttp2_session_callbacks_del (callbacks);
447
387
@@ -451,9 +391,10 @@ static std::shared_ptr<Http2Session> create_http2_session(Server *serv, SessionI
451
391
return nullptr ;
452
392
}
453
393
454
- // 存储服务器对象以便在回调中使用
455
394
nghttp2_session_set_user_data (session_data->session , session_data.get ());
456
395
396
+ // http2_send_settings(session_data.get());
397
+
457
398
return session_data;
458
399
}
459
400
@@ -500,7 +441,10 @@ static void test_ssl_http2(Server::Mode mode) {
500
441
break ;
501
442
}
502
443
444
+ int status;
445
+ ASSERT_EQ (waitpid (pid, &status, 0 ), pid);
503
446
close (_pipe);
447
+
504
448
usleep (10000 );
505
449
506
450
DEBUG () << buf.to_std_string ();
0 commit comments