diff --git a/src/modules/nghttp2/nghttp2_mod.c b/src/modules/nghttp2/nghttp2_mod.c index b5b07a6d1a0..de7a13485bf 100644 --- a/src/modules/nghttp2/nghttp2_mod.c +++ b/src/modules/nghttp2/nghttp2_mod.c @@ -48,11 +48,8 @@ int _nghttp2_server_pid = -1; static int nghttp2_route_no = -1; static str nghttp2_event_callback = STR_NULL; -static int w_nghttp2_send_reply( - sip_msg_t *msg, char *pcode, char *preason, char *pctype, char *pbody); - -static int fixup_nghttp2_send_reply(void **param, int param_no); - +static int w_nghttp2_send_reply(sip_msg_t *msg, char *pcode, char *pbody); +static int w_nghttp2_reply_header(sip_msg_t *msg, char *pname, char *pbody); static int mod_init(void); static int child_init(int); @@ -61,6 +58,8 @@ static void mod_destroy(void); int pv_get_nghttp2(sip_msg_t *msg, pv_param_t *param, pv_value_t *res); int pv_parse_nghttp2_name(pv_spec_p sp, str *in); +ksr_nghttp2_ctx_t _ksr_nghttp2_ctx = {0}; + /* clang-format off */ static pv_export_t mod_pvs[] = { {{"nghttp2", (sizeof("nghttp2") - 1)}, PVT_OTHER, pv_get_nghttp2, 0, @@ -71,7 +70,9 @@ static pv_export_t mod_pvs[] = { static cmd_export_t cmds[] = { {"nghttp2_reply", (cmd_function)w_nghttp2_send_reply, - 4, fixup_nghttp2_send_reply, 0, REQUEST_ROUTE|EVENT_ROUTE}, + 2, fixup_spve_all, fixup_free_spve_all, REQUEST_ROUTE|EVENT_ROUTE}, + {"nghttp2_reply_header", (cmd_function)w_nghttp2_reply_header, + 2, fixup_spve_all, fixup_free_spve_all, REQUEST_ROUTE|EVENT_ROUTE}, {0, 0, 0, 0, 0, 0} }; @@ -177,8 +178,6 @@ static void mod_destroy(void) { } -static ksr_nghttp2_ctx_t _ksr_nghttp2_ctx = {0}; - /** * parse the name of the $nghttp2(name) */ @@ -249,18 +248,15 @@ int pv_parse_nghttp2_name(pv_spec_p sp, str *in) */ int pv_get_nghttp2(sip_msg_t *msg, pv_param_t *param, pv_value_t *res) { - struct sockaddr *srcaddr = NULL; const char *hdrval = NULL; if(param == NULL) { return -1; } - if(_ksr_nghttp2_ctx.connection == NULL) { + if(_ksr_nghttp2_ctx.session == NULL) { return pv_get_null(msg, param, res); } if(param->pvn.u.isname.type == PVT_HDR) { - //hdrval = MHD_lookup_connection_value(_ksr_mhttpd_ctx.connection, - // MHD_HEADER_KIND, param->pvn.u.isname.name.s.s + 2); if(hdrval == NULL) { return pv_get_null(msg, param, res); } @@ -283,35 +279,7 @@ int pv_get_nghttp2(sip_msg_t *msg, pv_param_t *param, pv_value_t *res) if(_ksr_nghttp2_ctx.srcip.len > 0) { return pv_get_strval(msg, param, res, &_ksr_nghttp2_ctx.srcip); } - srcaddr = NULL; - // (_ksr_nghttp2_ctx.cinfo ? _ksr_nghttp2_ctx.cinfo->client_addr - // : NULL); - if(srcaddr == NULL) { - return pv_get_null(msg, param, res); - } - switch(srcaddr->sa_family) { - case AF_INET: - if(!inet_ntop(AF_INET, - &(((struct sockaddr_in *)srcaddr)->sin_addr), - _ksr_nghttp2_ctx.srcipbuf, - IP_ADDR_MAX_STR_SIZE)) { - return pv_get_null(msg, param, res); - } - break; - case AF_INET6: - if(!inet_ntop(AF_INET6, - &(((struct sockaddr_in6 *)srcaddr)->sin6_addr), - _ksr_nghttp2_ctx.srcipbuf, - IP_ADDR_MAX_STR_SIZE)) { - return pv_get_null(msg, param, res); - } - break; - default: - return pv_get_null(msg, param, res); - } - _ksr_nghttp2_ctx.srcip.s = _ksr_nghttp2_ctx.srcipbuf; - _ksr_nghttp2_ctx.srcip.len = strlen(_ksr_nghttp2_ctx.srcipbuf); - return pv_get_strval(msg, param, res, &_ksr_nghttp2_ctx.srcip); + return pv_get_null(msg, param, res); default: return pv_get_null(msg, param, res); } @@ -320,86 +288,146 @@ int pv_get_nghttp2(sip_msg_t *msg, pv_param_t *param, pv_value_t *res) /** * */ -static int ksr_nghttp2_send_reply( - sip_msg_t *msg, int rcode, str *sreason, str *sctype, str *sbody) +static int ksr_nghttp2_send_reply(sip_msg_t *msg, str *rcode, str *sbody) { - //struct MHD_Response *response; - // int ret; + int rv; + ssize_t writelen; + int pipefd[2]; - if(_ksr_nghttp2_ctx.connection == NULL) { - LM_ERR("no connection available\n"); - return -1; - } + _ksr_nghttp2_ctx.rplhdrs_v[0].value = (uint8_t *)rcode->s; + _ksr_nghttp2_ctx.rplhdrs_v[0].valuelen = rcode->len; - if(rcode < 100 || rcode >= 700) { - LM_ERR("invalid code parameter\n"); - return -1; + if(_ksr_nghttp2_ctx.rplhdrs_n == 0) { + _ksr_nghttp2_ctx.rplhdrs_n++; } - if(sreason->s == NULL || sreason->len == 0) { - LM_ERR("invalid reason parameter\n"); - return -1; + + if(sbody == NULL || sbody->len <= 0) { + rv = nghttp2_submit_response(_ksr_nghttp2_ctx.session, + _ksr_nghttp2_ctx.stream_data->stream_id, + _ksr_nghttp2_ctx.rplhdrs_v, _ksr_nghttp2_ctx.rplhdrs_n, NULL); + if(rv != 0) { + LM_ERR("Fatal error: %s", nghttp2_strerror(rv)); + return -1; + } + return 1; } - if(sctype->s == NULL) { - LM_ERR("invalid content-type parameter\n"); - return -1; + + rv = pipe(pipefd); + if(rv != 0) { + LM_ERR("Could not create pipe"); + rv = nghttp2_submit_rst_stream(_ksr_nghttp2_ctx.session, + NGHTTP2_FLAG_NONE, _ksr_nghttp2_ctx.stream_data->stream_id, + NGHTTP2_INTERNAL_ERROR); + if(rv != 0) { + LM_ERR("Fatal error: %s", nghttp2_strerror(rv)); + return -1; + } + return 0; } - if(sbody->s == NULL) { - LM_ERR("invalid body parameter\n"); + + writelen = write(pipefd[1], sbody->s, sbody->len); + close(pipefd[1]); + + if(writelen != sbody->len) { + close(pipefd[0]); return -1; } -#if 0 - response = MHD_create_response_from_buffer( - sbody->len, sbody->s, MHD_RESPMEM_PERSISTENT); - if(response == NULL) { - LM_ERR("failed to create the response\n"); + _ksr_nghttp2_ctx.stream_data->fd = pipefd[0]; + + if(ksr_nghttp2_send_response(_ksr_nghttp2_ctx.session, + _ksr_nghttp2_ctx.stream_data->stream_id, + _ksr_nghttp2_ctx.rplhdrs_v, _ksr_nghttp2_ctx.rplhdrs_n, + pipefd[0]) + != 0) { + close(pipefd[0]); return -1; } - if(sctype->len > 0) { - MHD_add_response_header(response, "Content-Type", sctype->s); - } - ret = MHD_queue_response( - _ksr_mhttpd_ctx.connection, (unsigned int)rcode, response); - MHD_destroy_response(response); - - return (ret == MHD_YES) ? 1 : -1; -#endif - return -1; + return 1; } /** * */ -static int w_nghttp2_send_reply( - sip_msg_t *msg, char *pcode, char *preason, char *pctype, char *pbody) +static int w_nghttp2_send_reply(sip_msg_t *msg, char *pcode, char *pbody) { + str code = str_init("200"); str body = str_init(""); - str reason = str_init("OK"); - str ctype = str_init("text/plain"); - int code = 200; - if(_ksr_nghttp2_ctx.connection == NULL) { - LM_ERR("no connection available\n"); + if(pcode == 0 || pbody == 0) { + LM_ERR("invalid parameters\n"); return -1; } - if(pcode == 0 || preason == 0 || pctype == 0 || pbody == 0) { - LM_ERR("invalid parameters\n"); + if(fixup_get_svalue(msg, (gparam_t *)pcode, &code) != 0) { + LM_ERR("no reply code value\n"); return -1; } - if(fixup_get_ivalue(msg, (gparam_p)pcode, &code) != 0) { - LM_ERR("no reply code value\n"); + if(fixup_get_svalue(msg, (gparam_p)pbody, &body) != 0) { + LM_ERR("unable to get body\n"); return -1; } - if(fixup_get_svalue(msg, (gparam_p)preason, &reason) != 0) { - LM_ERR("unable to get reason\n"); + return ksr_nghttp2_send_reply(msg, &code, &body); +} + +#define KSR_NGHTTP2_STATUS_NAME ":status" +#define KSR_NGHTTP2_STATUS_CODE "204" + + +/** + * + */ +static int ksr_nghttp2_reply_header(sip_msg_t *msg, str *sname, str *sbody) +{ + if(_ksr_nghttp2_ctx.rplhdrs_n >= KSR_NGHTTP2_RPLHDRS_SIZE) { + LM_ERR("too many headers\n"); return -1; } + if(_ksr_nghttp2_ctx.rplhdrs_n == 0) { + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].name = + (uint8_t *)KSR_NGHTTP2_STATUS_NAME; + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].namelen = + sizeof(KSR_NGHTTP2_STATUS_NAME) - 1; + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].value = + (uint8_t *)KSR_NGHTTP2_STATUS_CODE; + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].valuelen = + sizeof(KSR_NGHTTP2_STATUS_CODE) - 1; + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].flags = + NGHTTP2_NV_FLAG_NONE; + _ksr_nghttp2_ctx.rplhdrs_n++; + } + + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].name = + (uint8_t *)sname->s; + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].namelen = sname->len; + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].value = + (uint8_t *)sbody->s; + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].valuelen = + sbody->len; + _ksr_nghttp2_ctx.rplhdrs_v[_ksr_nghttp2_ctx.rplhdrs_n].flags = + NGHTTP2_NV_FLAG_NONE; + _ksr_nghttp2_ctx.rplhdrs_n++; - if(fixup_get_svalue(msg, (gparam_p)pctype, &ctype) != 0) { - LM_ERR("unable to get content type\n"); + return -1; +} + +/** + * + */ +static int w_nghttp2_reply_header(sip_msg_t *msg, char *pname, char *pbody) +{ + str name = str_init(""); + str body = str_init(""); + + if(pname == 0 || pbody == 0) { + LM_ERR("invalid parameters\n"); + return -1; + } + + if(fixup_get_svalue(msg, (gparam_t *)pname, &name) != 0) { + LM_ERR("unable to get name\n"); return -1; } @@ -408,134 +436,46 @@ static int w_nghttp2_send_reply( return -1; } - return ksr_nghttp2_send_reply(msg, code, &reason, &ctype, &body); -} - -static int fixup_nghttp2_send_reply(void **param, int param_no) -{ - if(param_no == 1) { - return fixup_igp_null(param, 1); - } else if(param_no == 2) { - return fixup_spve_null(param, 1); - } else if(param_no == 3) { - return fixup_spve_null(param, 1); - } else if(param_no == 4) { - return fixup_spve_null(param, 1); - } - return 0; + return ksr_nghttp2_reply_header(msg, &name, &body); } -#if 0 -static enum MHD_Result ksr_microhttpd_request(void *cls, - struct MHD_Connection *connection, const char *url, const char *method, - const char *version, const char *upload_data, size_t *upload_data_size, - void **ptr) +void ksr_event_route(void) { - static int _first_callback; sr_kemi_eng_t *keng = NULL; - str evname = str_init("microhttpd:request"); + str evname = str_init("nghttp2:request"); sip_msg_t *fmsg = NULL; run_act_ctx_t ctx; int rtb; - if(&_first_callback != *ptr) { - /* the first time only the headers are valid, - do not respond in the first round... */ - *ptr = &_first_callback; - return MHD_YES; - } - *ptr = NULL; /* clear context pointer */ - - _ksr_mhttpd_ctx.connection = connection; - _ksr_mhttpd_ctx.method.s = (char *)method; - _ksr_mhttpd_ctx.method.len = strlen(_ksr_mhttpd_ctx.method.s); - _ksr_mhttpd_ctx.url.s = (char *)url; - _ksr_mhttpd_ctx.url.len = strlen(_ksr_mhttpd_ctx.url.s); - _ksr_mhttpd_ctx.httpversion.s = (char *)version; - _ksr_mhttpd_ctx.httpversion.len = strlen(_ksr_mhttpd_ctx.httpversion.s); - if(*upload_data_size > 0) { - _ksr_mhttpd_ctx.data.s = (char *)upload_data; - _ksr_mhttpd_ctx.data.len = (int)(*upload_data_size); - } else { - _ksr_mhttpd_ctx.data.s = NULL; - _ksr_mhttpd_ctx.data.len = 0; - } - _ksr_mhttpd_ctx.cinfo = MHD_get_connection_info( - connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS); - _ksr_mhttpd_ctx.srcip.s = NULL; - _ksr_mhttpd_ctx.srcip.len = 0; - - LM_DBG("executing event_route[%s] (%d)\n", evname.s, microhttpd_route_no); + LM_DBG("executing event_route[%s] (%d)\n", evname.s, nghttp2_route_no); if(faked_msg_init() < 0) { - return MHD_NO; + return; } fmsg = faked_msg_next(); rtb = get_route_type(); set_route_type(REQUEST_ROUTE); init_run_actions_ctx(&ctx); - if(microhttpd_route_no >= 0) { - run_top_route(event_rt.rlist[microhttpd_route_no], fmsg, &ctx); + if(nghttp2_route_no >= 0) { + run_top_route(event_rt.rlist[nghttp2_route_no], fmsg, &ctx); } else { keng = sr_kemi_eng_get(); if(keng != NULL) { if(sr_kemi_ctx_route(keng, &ctx, fmsg, EVENT_ROUTE, - µhttpd_event_callback, &evname) + &nghttp2_event_callback, &evname) < 0) { LM_ERR("error running event route kemi callback\n"); - return MHD_NO; + return; } } } set_route_type(rtb); if(ctx.run_flags & DROP_R_F) { LM_ERR("exit due to 'drop' in event route\n"); - return MHD_NO; - } - - return MHD_YES; -} - -#define KSR_MICROHTTPD_PAGE \ - "Kamailio" \ - "Thanks for flying Kamailio!" -/** - * - */ -static int microhttpd_server_run(void) -{ - - struct MHD_Daemon *d; - struct sockaddr_in address; - - if(_microhttpd_listen_addr.len > 0) { - address.sin_family = AF_INET; - address.sin_port = htons(_microhttpd_listen_port); - if(inet_pton(AF_INET, _microhttpd_listen_addr.s, &address.sin_addr) - <= 0) { - LM_ERR("failed to convert listen address\n"); - return -1; - } - LM_DBG("preparing to listen on %s :%d\n", _microhttpd_listen_addr.s, - _microhttpd_listen_port); - d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, _microhttpd_listen_port, - NULL, NULL, &ksr_microhttpd_request, KSR_MICROHTTPD_PAGE, - MHD_OPTION_SOCK_ADDR, &address, MHD_OPTION_END); - } else { - LM_DBG("preparing to listen on port: %d\n", _microhttpd_listen_port); - d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, _microhttpd_listen_port, - NULL, NULL, &ksr_microhttpd_request, KSR_MICROHTTPD_PAGE, - MHD_OPTION_END); + return; } - if(d == NULL) { - return -1; - } - while(1) { - sleep(10); - } - return 0; + return; } -#endif /** * @@ -544,8 +484,13 @@ static int microhttpd_server_run(void) static sr_kemi_t sr_kemi_nghttp2_exports[] = { { str_init("nghttp2"), str_init("nghttp2_reply"), SR_KEMIP_INT, ksr_nghttp2_send_reply, - { SR_KEMIP_INT, SR_KEMIP_STR, SR_KEMIP_STR, - SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE } + { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE, + SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } + }, + { str_init("nghttp2"), str_init("nghttp2_reply_header"), + SR_KEMIP_INT, ksr_nghttp2_reply_header, + { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE, + SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } }, { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } } diff --git a/src/modules/nghttp2/nghttp2_server.c b/src/modules/nghttp2/nghttp2_server.c index bdbec4a8c58..46b4e003462 100644 --- a/src/modules/nghttp2/nghttp2_server.c +++ b/src/modules/nghttp2/nghttp2_server.c @@ -35,31 +35,6 @@ sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE \ } -struct app_context; -typedef struct app_context app_context; - -typedef struct http2_stream_data -{ - struct http2_stream_data *prev, *next; - char *request_path; - int32_t stream_id; - int fd; -} http2_stream_data; - -typedef struct http2_session_data -{ - struct http2_stream_data root; - struct bufferevent *bev; - app_context *app_ctx; - nghttp2_session *session; - char *client_addr; -} http2_session_data; - -struct app_context -{ - SSL_CTX *ssl_ctx; - struct event_base *evbase; -}; static unsigned char next_proto_list[256]; static size_t next_proto_list_len; @@ -311,17 +286,6 @@ static ssize_t send_callback(nghttp2_session *session, const uint8_t *data, return (ssize_t)length; } -/* Returns nonzero if the string |s| ends with the substring |sub| */ -static int ends_with(const char *s, const char *sub) -{ - size_t slen = strlen(s); - size_t sublen = strlen(sub); - if(slen < sublen) { - return 0; - } - return memcmp(s + slen - sublen, sub, sublen) == 0; -} - /* Returns int value of hex string character |c| */ static uint8_t hex_to_uint(uint8_t c) { @@ -404,6 +368,25 @@ static int send_response(nghttp2_session *session, int32_t stream_id, return 0; } +int ksr_nghttp2_send_response(nghttp2_session *session, int32_t stream_id, + nghttp2_nv *nva, size_t nvlen, int fd) +{ + return send_response(session, stream_id, nva, nvlen, fd); +} + +static int send_response_204(nghttp2_session *session, int32_t stream_id) +{ + int rv; + nghttp2_nv hdrs[] = {MAKE_NV(":status", "204")}; + + rv = nghttp2_submit_response(session, stream_id, hdrs, ARRLEN(hdrs), NULL); + if(rv != 0) { + LM_ERR("Fatal error: %s", nghttp2_strerror(rv)); + return -1; + } + return 0; +} + static const char ERROR_HTML[] = "404" "

404 Not Found

"; @@ -494,23 +477,9 @@ static int on_begin_headers_callback( return 0; } -/* Minimum check for directory traversal. Returns nonzero if it is - safe. */ -static int check_path(const char *path) -{ - /* We don't like '\' in url. */ - return path[0] && path[0] == '/' && strchr(path, '\\') == NULL - && strstr(path, "/../") == NULL && strstr(path, "/./") == NULL - && !ends_with(path, "/..") && !ends_with(path, "/."); -} - static int on_request_recv(nghttp2_session *session, http2_session_data *session_data, http2_stream_data *stream_data) { - int fd; - nghttp2_nv hdrs[] = {MAKE_NV(":status", "200")}; - char *rel_path; - if(!stream_data->request_path) { if(error_reply(session, stream_data) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -518,28 +487,25 @@ static int on_request_recv(nghttp2_session *session, return 0; } LM_DBG("%s GET %s\n", session_data->client_addr, stream_data->request_path); - if(!check_path(stream_data->request_path)) { - if(error_reply(session, stream_data) != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return 0; - } - for(rel_path = stream_data->request_path; *rel_path == '/'; ++rel_path) - ; - fd = open(rel_path, O_RDONLY); - if(fd == -1) { - if(error_reply(session, stream_data) != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return 0; - } - stream_data->fd = fd; - if(send_response(session, stream_data->stream_id, hdrs, ARRLEN(hdrs), fd) - != 0) { - close(fd); + _ksr_nghttp2_ctx.rplhdrs_n = 0; + + _ksr_nghttp2_ctx.session = session; + _ksr_nghttp2_ctx.session_data = session_data; + _ksr_nghttp2_ctx.stream_data = stream_data; + + _ksr_nghttp2_ctx.url.s = stream_data->request_path; + _ksr_nghttp2_ctx.url.len = strlen(_ksr_nghttp2_ctx.url.s); + + _ksr_nghttp2_ctx.srcip.s = session_data->client_addr; + _ksr_nghttp2_ctx.srcip.len = strlen(_ksr_nghttp2_ctx.srcip.s); + + ksr_event_route(); + + if(send_response_204(session, stream_data->stream_id) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; } + return 0; } diff --git a/src/modules/nghttp2/nghttp2_server.h b/src/modules/nghttp2/nghttp2_server.h index 8570f6fd914..dc1f5f148c6 100644 --- a/src/modules/nghttp2/nghttp2_server.h +++ b/src/modules/nghttp2/nghttp2_server.h @@ -62,18 +62,45 @@ #include "../../core/str.h" #include "../../core/ip_addr.h" -typedef ptrdiff_t nghttp2_ssize; +struct app_context; +typedef struct app_context app_context; + +typedef struct http2_stream_data +{ + struct http2_stream_data *prev, *next; + char *request_path; + int32_t stream_id; + int fd; +} http2_stream_data; + +typedef struct http2_session_data +{ + struct http2_stream_data root; + struct bufferevent *bev; + app_context *app_ctx; + nghttp2_session *session; + char *client_addr; +} http2_session_data; + +struct app_context +{ + SSL_CTX *ssl_ctx; + struct event_base *evbase; +}; + +#define KSR_NGHTTP2_RPLHDRS_SIZE 16 typedef struct ksr_nghttp2_ctx { - //struct MHD_Connection *connection; - void *connection; + nghttp2_session *session; + http2_session_data *session_data; + http2_stream_data *stream_data; + nghttp2_nv rplhdrs_v[KSR_NGHTTP2_RPLHDRS_SIZE]; + int rplhdrs_n; str method; str url; str httpversion; str data; - //const union MHD_ConnectionInfo *cinfo; - void *cinfo; char srcipbuf[IP_ADDR_MAX_STR_SIZE]; str srcip; } ksr_nghttp2_ctx_t; @@ -83,7 +110,11 @@ extern str _nghttp2_listen_addr; extern str _nghttp2_tls_public_key; extern str _nghttp2_tls_private_key; extern int _nghttp2_server_pid; +extern ksr_nghttp2_ctx_t _ksr_nghttp2_ctx; int nghttp2_server_run(void); +void ksr_event_route(void); +int ksr_nghttp2_send_response(nghttp2_session *session, int32_t stream_id, + nghttp2_nv *nva, size_t nvlen, int fd); #endif