Browse Source

nghttp2: separate function for setting response headers

Daniel-Constantin Mierla 1 year ago
parent
commit
ec847027ef

+ 136 - 191
src/modules/nghttp2/nghttp2_mod.c

@@ -48,11 +48,8 @@ int _nghttp2_server_pid = -1;
 static int nghttp2_route_no = -1;
 static int nghttp2_route_no = -1;
 static str nghttp2_event_callback = STR_NULL;
 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 mod_init(void);
 static int child_init(int);
 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_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);
 int pv_parse_nghttp2_name(pv_spec_p sp, str *in);
 
 
+ksr_nghttp2_ctx_t _ksr_nghttp2_ctx = {0};
+
 /* clang-format off */
 /* clang-format off */
 static pv_export_t mod_pvs[] = {
 static pv_export_t mod_pvs[] = {
 	{{"nghttp2", (sizeof("nghttp2") - 1)}, PVT_OTHER, pv_get_nghttp2, 0,
 	{{"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[] = {
 static cmd_export_t cmds[] = {
 	{"nghttp2_reply",    (cmd_function)w_nghttp2_send_reply,
 	{"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}
 	{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)
  * parse the name of the $nghttp2(name)
  */
  */
@@ -249,18 +248,15 @@ error:
  */
  */
 int pv_get_nghttp2(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
 int pv_get_nghttp2(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
 {
 {
-	struct sockaddr *srcaddr = NULL;
 	const char *hdrval = NULL;
 	const char *hdrval = NULL;
 
 
 	if(param == NULL) {
 	if(param == NULL) {
 		return -1;
 		return -1;
 	}
 	}
-	if(_ksr_nghttp2_ctx.connection == NULL) {
+	if(_ksr_nghttp2_ctx.session == NULL) {
 		return pv_get_null(msg, param, res);
 		return pv_get_null(msg, param, res);
 	}
 	}
 	if(param->pvn.u.isname.type == PVT_HDR) {
 	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) {
 		if(hdrval == NULL) {
 			return pv_get_null(msg, param, res);
 			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) {
 			if(_ksr_nghttp2_ctx.srcip.len > 0) {
 				return pv_get_strval(msg, param, res, &_ksr_nghttp2_ctx.srcip);
 				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:
 		default:
 			return pv_get_null(msg, param, res);
 			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;
 		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;
 		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 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;
 		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;
 		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;
 		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;
 		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;
 		return -1;
 	}
 	}
 
 
@@ -408,134 +436,46 @@ static int w_nghttp2_send_reply(
 		return -1;
 		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;
 	sr_kemi_eng_t *keng = NULL;
-	str evname = str_init("microhttpd:request");
+	str evname = str_init("nghttp2:request");
 	sip_msg_t *fmsg = NULL;
 	sip_msg_t *fmsg = NULL;
 	run_act_ctx_t ctx;
 	run_act_ctx_t ctx;
 	int rtb;
 	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) {
 	if(faked_msg_init() < 0) {
-		return MHD_NO;
+		return;
 	}
 	}
 	fmsg = faked_msg_next();
 	fmsg = faked_msg_next();
 	rtb = get_route_type();
 	rtb = get_route_type();
 	set_route_type(REQUEST_ROUTE);
 	set_route_type(REQUEST_ROUTE);
 	init_run_actions_ctx(&ctx);
 	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 {
 	} else {
 		keng = sr_kemi_eng_get();
 		keng = sr_kemi_eng_get();
 		if(keng != NULL) {
 		if(keng != NULL) {
 			if(sr_kemi_ctx_route(keng, &ctx, fmsg, EVENT_ROUTE,
 			if(sr_kemi_ctx_route(keng, &ctx, fmsg, EVENT_ROUTE,
-					   &microhttpd_event_callback, &evname)
+					   &nghttp2_event_callback, &evname)
 					< 0) {
 					< 0) {
 				LM_ERR("error running event route kemi callback\n");
 				LM_ERR("error running event route kemi callback\n");
-				return MHD_NO;
+				return;
 			}
 			}
 		}
 		}
 	}
 	}
 	set_route_type(rtb);
 	set_route_type(rtb);
 	if(ctx.run_flags & DROP_R_F) {
 	if(ctx.run_flags & DROP_R_F) {
 		LM_ERR("exit due to 'drop' in event route\n");
 		LM_ERR("exit due to 'drop' in event route\n");
-		return MHD_NO;
-	}
-
-	return MHD_YES;
-}
-
-#define KSR_MICROHTTPD_PAGE               \
-	"<html><head><title>Kamailio</title>" \
-	"</head><body>Thanks for flying Kamailio!</body></html>"
-/**
- *
- */
-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[] = {
 static sr_kemi_t sr_kemi_nghttp2_exports[] = {
 	{ str_init("nghttp2"), str_init("nghttp2_reply"),
 	{ str_init("nghttp2"), str_init("nghttp2_reply"),
 		SR_KEMIP_INT, ksr_nghttp2_send_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 } }
 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }

+ 35 - 69
src/modules/nghttp2/nghttp2_server.c

@@ -35,31 +35,6 @@
 				sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE      \
 				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 unsigned char next_proto_list[256];
 static size_t next_proto_list_len;
 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;
 	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| */
 /* Returns int value of hex string character |c| */
 static uint8_t hex_to_uint(uint8_t 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;
 	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[] = "<html><head><title>404</title></head>"
 static const char ERROR_HTML[] = "<html><head><title>404</title></head>"
 								 "<body><h1>404 Not Found</h1></body></html>";
 								 "<body><h1>404 Not Found</h1></body></html>";
 
 
@@ -494,23 +477,9 @@ static int on_begin_headers_callback(
 	return 0;
 	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,
 static int on_request_recv(nghttp2_session *session,
 		http2_session_data *session_data, http2_stream_data *stream_data)
 		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(!stream_data->request_path) {
 		if(error_reply(session, stream_data) != 0) {
 		if(error_reply(session, stream_data) != 0) {
 			return NGHTTP2_ERR_CALLBACK_FAILURE;
 			return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -518,28 +487,25 @@ static int on_request_recv(nghttp2_session *session,
 		return 0;
 		return 0;
 	}
 	}
 	LM_DBG("%s GET %s\n", session_data->client_addr, stream_data->request_path);
 	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 NGHTTP2_ERR_CALLBACK_FAILURE;
 	}
 	}
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 36 - 5
src/modules/nghttp2/nghttp2_server.h

@@ -62,18 +62,45 @@
 #include "../../core/str.h"
 #include "../../core/str.h"
 #include "../../core/ip_addr.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
 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 method;
 	str url;
 	str url;
 	str httpversion;
 	str httpversion;
 	str data;
 	str data;
-	//const union MHD_ConnectionInfo *cinfo;
-	void *cinfo;
 	char srcipbuf[IP_ADDR_MAX_STR_SIZE];
 	char srcipbuf[IP_ADDR_MAX_STR_SIZE];
 	str srcip;
 	str srcip;
 } ksr_nghttp2_ctx_t;
 } ksr_nghttp2_ctx_t;
@@ -83,7 +110,11 @@ extern str _nghttp2_listen_addr;
 extern str _nghttp2_tls_public_key;
 extern str _nghttp2_tls_public_key;
 extern str _nghttp2_tls_private_key;
 extern str _nghttp2_tls_private_key;
 extern int _nghttp2_server_pid;
 extern int _nghttp2_server_pid;
+extern ksr_nghttp2_ctx_t _ksr_nghttp2_ctx;
 
 
 int nghttp2_server_run(void);
 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
 #endif