[vlc-devel] [PATCH 11/14] contrib: patch libupnp to expose HTTP headers

Rémi Denis-Courmont remi at remlab.net
Fri Mar 19 14:42:42 UTC 2021


Le perjantaina 19. maaliskuuta 2021, 13.40.06 EET Alaric Senat a écrit :
> This patch exposes the extra unrecognized HTTP headers to the upnp API
> ActionRequest interface, thus allowing the upnp server module to adapt
> its behavior depending on what client he's responding to.
> 
> Upstreamed to libupnp by 508930f56cca885d82b94e6e7abf588d0e46faa4

Well maybe but:

1) It seems like a dangerous idea from forward compatibility standpoint. It 
creates an implicit dependency on the set of headers that the library manages 
or not, which might easily break on updates.

2) The version dependencies in contrib and configure *must* reflect the API 
requirements.

> ---
>  contrib/src/upnp/extra-http-headers.patch | 290 ++++++++++++++++++++++
>  contrib/src/upnp/rules.mak                |   1 +
>  2 files changed, 291 insertions(+)
>  create mode 100644 contrib/src/upnp/extra-http-headers.patch
> 
> diff --git a/contrib/src/upnp/extra-http-headers.patch
> b/contrib/src/upnp/extra-http-headers.patch new file mode 100644
> index 0000000000..207c314ef9
> --- /dev/null
> +++ b/contrib/src/upnp/extra-http-headers.patch
> @@ -0,0 +1,290 @@
> +From efc92015f23caa2ad22831d3453d6be7c86ef407 Mon Sep 17 00:00:00 2001
> +From: Alaric Senat <dev.asenat at posteo.net>
> +Date: Thu, 4 Mar 2021 11:35:11 +0100
> +Subject: action_request: Expose extra http headers
> +
> +Api users might want to process some http headers that are not
> +recognized by the pupnp webserver. A similar behavior is already
> +implemented for the upnp http io callbacks in the FileInfo interface.
> +---
> + upnp/inc/ActionRequest.h              |  1 +
> + upnp/src/genlib/net/http/httpparser.c | 79 +++++++++++++++++++++++++++
> + upnp/src/genlib/net/http/webserver.c  | 69 +----------------------
> + upnp/src/inc/httpparser.h             | 30 ++++++++++
> + upnp/src/soap/soap_device.c           |  9 +++
> + 5 files changed, 121 insertions(+), 67 deletions(-)
> +
> +diff --git a/upnp/inc/ActionRequest.h b/upnp/inc/ActionRequest.h
> +index f889fa1..4e1e376 100644
> +--- a/upnp/inc/ActionRequest.h
> ++++ b/upnp/inc/ActionRequest.h
> +@@ -29,6 +29,7 @@
> + 	EXPAND_CLASS_MEMBER_INT(CLASS, SoapHeader, IXML_Document *) \
> + 	EXPAND_CLASS_MEMBER_BUFFER(CLASS, CtrlPtIPAddr, struct 
sockaddr_storage)
> \ + 	EXPAND_CLASS_MEMBER_STRING(CLASS, Os) \
> ++	EXPAND_CLASS_MEMBER_LIST(CLASS, ExtraHeadersList) \
> +
> + #include "TemplateInclude.h"
> +
> +diff --git a/upnp/src/genlib/net/http/httpparser.c
> b/upnp/src/genlib/net/http/httpparser.c +index 4f8da7a..f03e365 100644
> +--- a/upnp/src/genlib/net/http/httpparser.c
> ++++ b/upnp/src/genlib/net/http/httpparser.c
> +@@ -46,6 +46,8 @@
> + #include "httpparser.h"
> + #include "statcodes.h"
> + #include "unixutil.h"
> ++#include "ExtraHeaders.h"
> ++#include "list.h"
> + #include "upnpdebug.h"
> +
> + #include <assert.h>
> +@@ -2194,6 +2196,83 @@ const char *method_to_str(http_method_t method)
> +     return index == -1 ? NULL : Http_Method_Table[index].name;
> + }
> +
> ++/************************************************************************
> ++* Function: parser_get_unknown_headers
> ++*
> ++* Parameters:
> ++*	IN http_message_t req ;		HTTP request
> ++*	INOUT UpnpListHead list ;   Extra headers list
> ++*
> ++* Description: Append unknown HTTP headers to the list.
> ++*
> ++* Returns:
> ++*	HTTP_OK
> ++*	HTTP_INTERNAL_SERVER_ERROR
> ++************************************************************************/
> ++int parser_get_unknown_headers(http_message_t *req, UpnpListHead *list)
> ++{
> ++	http_header_t *header;
> ++	ListNode *node;
> ++	int index;
> ++	UpnpExtraHeaders *extraHeader;
> ++	UpnpListHead *extraHeaderNode;
> ++
> ++	node = ListHead(&req->headers);
> ++	while (node != NULL) {
> ++		header = (http_header_t *)node->item;
> ++		/* find header type. */
> ++		index = map_str_to_int((const char *)header->name.buf,
> ++			header->name.length,
> ++			Http_Header_Names,
> ++			NUM_HTTP_HEADER_NAMES,
> ++			0);
> ++		if (index < 0) {
> ++			extraHeader = UpnpExtraHeaders_new();
> ++			if (!extraHeader) {
> ++				free_http_headers_list(list);
> ++				return HTTP_INTERNAL_SERVER_ERROR;
> ++			}
> ++			extraHeaderNode =
> ++				(UpnpListHead 
*)UpnpExtraHeaders_get_node(
> ++					extraHeader);
> ++			UpnpListInsert(list, UpnpListEnd(list), 
extraHeaderNode);
> ++			UpnpExtraHeaders_strncpy_name(extraHeader,
> ++				header->name.buf,
> ++				header->name.length);
> ++			UpnpExtraHeaders_strncpy_value(extraHeader,
> ++				header->value.buf,
> ++				header->value.length);
> ++		}
> ++		node = ListNext(&req->headers, node);
> ++	}
> ++
> ++	return HTTP_OK;
> ++}
> ++
> ++/************************************************************************
> ++* Function: free_http_headers_list
> ++*
> ++* Parameters:
> ++*	IN UpnpListHead list ;   Extra headers list
> ++*
> ++* Description: Free all extra headers nodes in the given list.
> ++*
> ++* Returns:
> ++*	HTTP_OK
> ++*	HTTP_INTERNAL_SERVER_ERROR
> ++************************************************************************/
> ++void free_http_headers_list(UpnpListHead *list)
> ++{
> ++	UpnpListIter pos;
> ++	UpnpExtraHeaders *extra;
> ++
> ++	for (pos = UpnpListBegin(list);
> ++		pos != UpnpListEnd(list);) {
> ++		extra = (UpnpExtraHeaders *)pos;
> ++		pos = UpnpListErase(list, pos);
> ++		UpnpExtraHeaders_delete(extra);
> ++	}
> ++}
> +
> + #ifdef DEBUG
> + void print_http_headers(http_message_t *hmsg)
> +diff --git a/upnp/src/genlib/net/http/webserver.c
> b/upnp/src/genlib/net/http/webserver.c +index 09bc97e..6fb7351 100644
> +--- a/upnp/src/genlib/net/http/webserver.c
> ++++ b/upnp/src/genlib/net/http/webserver.c
> +@@ -1054,71 +1054,6 @@ static int CheckOtherHTTPHeaders(
> + 	return RetCode;
> + }
> +
> +-static void FreeExtraHTTPHeaders(
> +-	/*! [in] extra HTTP headers to free. */
> +-	UpnpListHead *extraHeadersList)
> +-{
> +-	UpnpListIter pos;
> +-	UpnpExtraHeaders *extra;
> +-
> +-	for (pos = UpnpListBegin(extraHeadersList);
> +-		pos != UpnpListEnd(extraHeadersList);) {
> +-		extra = (UpnpExtraHeaders *)pos;
> +-		pos = UpnpListErase(extraHeadersList, pos);
> +-		UpnpExtraHeaders_delete(extra);
> +-	}
> +-}
> +-
> +-/*!
> +- * \brief Build an array of unrecognized headers.
> +- *
> +- * \return nothing
> +- */
> +-static int ExtraHTTPHeaders(
> +-	/*! [in] HTTP Request message. */
> +-	http_message_t *Req,
> +-	UpnpListHead *extraHeadersList)
> +-{
> +-	http_header_t *header;
> +-	ListNode *node;
> +-	int index;
> +-	UpnpExtraHeaders *extraHeader;
> +-	UpnpListHead *extraHeaderNode;
> +-
> +-	node = ListHead(&Req->headers);
> +-	while (node != NULL) {
> +-		header = (http_header_t *)node->item;
> +-		/* find header type. */
> +-		index = map_str_to_int((const char *)header->name.buf,
> +-			header->name.length,
> +-			Http_Header_Names,
> +-			NUM_HTTP_HEADER_NAMES,
> +-			0);
> +-		if (index < 0) {
> +-			extraHeader = UpnpExtraHeaders_new();
> +-			if (!extraHeader) {
> +-				
FreeExtraHTTPHeaders(extraHeadersList);
> +-				return 
HTTP_INTERNAL_SERVER_ERROR;
> +-			}
> +-			extraHeaderNode =
> +-				(UpnpListHead 
*)UpnpExtraHeaders_get_node(
> +-					extraHeader);
> +-			UpnpListInsert(extraHeadersList,
> +-				UpnpListEnd(extraHeadersList),
> +-				extraHeaderNode);
> +-			UpnpExtraHeaders_strncpy_name(extraHeader,
> +-				header->name.buf,
> +-				header->name.length);
> +-			UpnpExtraHeaders_strncpy_value(extraHeader,
> +-				header->value.buf,
> +-				header->value.length);
> +-		}
> +-		node = ListNext(&Req->headers, node);
> +-	}
> +-
> +-	return HTTP_OK;
> +-}
> +-
> + /*!
> +  * \brief Processes the request and returns the result in the output
> parameters. +  *
> +@@ -1227,7 +1162,7 @@ static int process_request(
> + 	}
> + 	if (using_virtual_dir) {
> + 		if (req->method != HTTPMETHOD_POST) {
> +-			if ((code = ExtraHTTPHeaders(req,
> ++			if ((code = parser_get_unknown_headers(req,
> + 				     (UpnpListHead *)
> + 					     
UpnpFileInfo_get_ExtraHeadersList(
> + 						     
finfo))) != HTTP_OK) {
> +@@ -1509,7 +1444,7 @@ static int process_request(
> +
> + error_handler:
> + 	free(request_doc);
> +-	FreeExtraHTTPHeaders(
> ++	free_http_headers_list(
> + 		(UpnpListHead 
*)UpnpFileInfo_get_ExtraHeadersList(finfo));
> + 	UpnpFileInfo_delete(finfo);
> + 	if (err_code != HTTP_OK && alias_grabbed) {
> +diff --git a/upnp/src/inc/httpparser.h b/upnp/src/inc/httpparser.h
> +index 99c3f2e..8cac3a7 100644
> +--- a/upnp/src/inc/httpparser.h
> ++++ b/upnp/src/inc/httpparser.h
> +@@ -419,6 +419,36 @@ parse_status_t
> parser_get_entity_read_method(http_parser_t *parser); + parse_status_t
> parser_append(
> + 	http_parser_t *parser, const char *buf, size_t buf_length);
> +
> ++/************************************************************************
> ++* Function: parser_get_unknown_headers
> ++*
> ++* Parameters:
> ++*	IN http_message_t req ;		HTTP request
> ++*	INOUT UpnpListHead list ;   Extra headers list
> ++*
> ++* Description: Append unknown HTTP headers to the list.
> ++*
> ++* Returns:
> ++*	HTTP_OK
> ++*	HTTP_INTERNAL_SERVER_ERROR
> ++************************************************************************/
> ++
> ++int parser_get_unknown_headers(http_message_t *req, UpnpListHead *list);
> ++
> ++/************************************************************************
> ++* Function: free_http_headers_list
> ++*
> ++* Parameters:
> ++*	IN UpnpListHead list ;   Extra headers list
> ++*
> ++* Description: Free all extra headers nodes in the given list.
> ++*
> ++* Returns:
> ++*	HTTP_OK
> ++*	HTTP_INTERNAL_SERVER_ERROR
> ++************************************************************************/
> ++void free_http_headers_list(UpnpListHead *list);
> ++
> + /************************************************************************
> +  * Function: matchstr
> +  *
> +diff --git a/upnp/src/soap/soap_device.c b/upnp/src/soap/soap_device.c
> +index cd2ad38..e0fb1bd 100644
> +--- a/upnp/src/soap/soap_device.c
> ++++ b/upnp/src/soap/soap_device.c
> +@@ -429,6 +429,13 @@ static void handle_invoke_action(
> + 		UpnpActionRequest_strncpy_Os(action, hdr_value.buf, 
hdr_value.length);
> + 	}
> +
> ++	if ((err_code = parser_get_unknown_headers(request,
> ++		     (UpnpListHead 
*)UpnpActionRequest_get_ExtraHeadersList(
> ++			     action))) != HTTP_OK) {
> ++		err_code = SOAP_ACTION_FAILED;
> ++		goto error_handler;
> ++	}
> ++
> + 	UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__, "Calling 
Callback\n");
> + 	soap_info->callback(
> + 		UPNP_CONTROL_ACTION_REQUEST, action, soap_info-
>cookie);
> +@@ -457,6 +464,8 @@ error_handler:
> + 	ixmlDocument_free(actionResultDoc);
> + 	ixmlDocument_free(actionRequestDoc);
> + 	ixmlFreeDOMString(act_node);
> ++	free_http_headers_list(
> ++		(UpnpListHead 
*)UpnpActionRequest_get_ExtraHeadersList(action));
> + 	/* restore */
> + 	action_name.buf[action_name.length] = save_char;
> + 	if (err_code != 0)
> +--
> +2.29.2
> +
> diff --git a/contrib/src/upnp/rules.mak b/contrib/src/upnp/rules.mak
> index 9e5afb2fd9..1cc6bce33c 100644
> --- a/contrib/src/upnp/rules.mak
> +++ b/contrib/src/upnp/rules.mak
> @@ -44,6 +44,7 @@ ifdef HAVE_WIN32
>  endif
>  	$(APPLY) $(SRC)/upnp/miniserver.patch
>  	$(APPLY) $(SRC)/upnp/upnp-no-debugfile.patch
> +	$(APPLY) $(SRC)/upnp/extra-http-headers.patch
>  	$(UPDATE_AUTOCONFIG) && cd $(UNPACK_DIR) && mv config.guess 
config.sub
> build-aux/ $(MOVE)


-- 
レミ・デニ-クールモン
http://www.remlab.net/





More information about the vlc-devel mailing list