[FFmpeg-devel,v2] avformat/http: Add option to disable send-100-continue

Submitted by Jun Li on March 19, 2019, 10:52 p.m.

Details

Message ID 20190319225215.3120-1-junli1026@gmail.com
State New
Headers show

Commit Message

Jun Li March 19, 2019, 10:52 p.m.
The current setting for send-100-continue is either
applicable or enabled, no option to disable the header.
This change is to expand the option setting to provide
more flexibility, which is useful for rstp case.
---
 libavformat/http.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

Comments

Jun Li March 19, 2019, 11:12 p.m.
On Tue, Mar 19, 2019 at 3:52 PM Jun Li <junli1026@gmail.com> wrote:

> The current setting for send-100-continue is either
> applicable or enabled, no option to disable the header.
> This change is to expand the option setting to provide
> more flexibility, which is useful for rstp case.
> ---
>  libavformat/http.c | 15 +++++++++------
>  1 file changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/libavformat/http.c b/libavformat/http.c
> index ed0eb1c875..7e74719450 100644
> --- a/libavformat/http.c
> +++ b/libavformat/http.c
> @@ -113,7 +113,7 @@ typedef struct HTTPContext {
>      uint8_t *inflate_buffer;
>  #endif /* CONFIG_ZLIB */
>      AVDictionary *chained_options;
> -    int send_expect_100;
> +    int send_expect_100;    /* -1 = try to send if applicable, 0 = always
> disabled, 1 = always enabled */
>      char *method;
>      int reconnect;
>      int reconnect_at_eof;
> @@ -155,7 +155,7 @@ static const AVOption options[] = {
>      { "auth_type", "HTTP authentication type",
> OFFSET(auth_state.auth_type), AV_OPT_TYPE_INT, { .i64 = HTTP_AUTH_NONE },
> HTTP_AUTH_NONE, HTTP_AUTH_BASIC, D | E, "auth_type"},
>      { "none", "No auth method set, autodetect", 0, AV_OPT_TYPE_CONST, {
> .i64 = HTTP_AUTH_NONE }, 0, 0, D | E, "auth_type"},
>      { "basic", "HTTP basic authentication", 0, AV_OPT_TYPE_CONST, { .i64
> = HTTP_AUTH_BASIC }, 0, 0, D | E, "auth_type"},
> -    { "send_expect_100", "Force sending an Expect: 100-continue header
> for POST", OFFSET(send_expect_100), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E
> },
> +    { "send_expect_100", "Force sending an Expect: 100-continue header
> for POST", OFFSET(send_expect_100), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1,
> E },
>      { "location", "The actual location of the data received",
> OFFSET(location), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
>      { "offset", "initial byte offset", OFFSET(off), AV_OPT_TYPE_INT64, {
> .i64 = 0 }, 0, INT64_MAX, D },
>      { "end_offset", "try to limit the request to bytes preceding this
> offset", OFFSET(end_off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D
> },
> @@ -1179,12 +1179,15 @@ static int http_connect(URLContext *h, const char
> *path, const char *local_path,
>                                                  local_path, method);
>      proxyauthstr = ff_http_auth_create_response(&s->proxy_auth_state,
> proxyauth,
>                                                  local_path, method);
> -    if (post && !s->post_data) {
> +
> +    if (s->send_expect_100 != -1) {
> +        send_expect_100 = s->send_expect_100;
> +    } else if (post && !s->post_data) {
>          send_expect_100 = s->send_expect_100;
>          /* The user has supplied authentication but we don't know the
> auth type,
> -         * send Expect: 100-continue to get the 401 response including the
> -         * WWW-Authenticate header, or an 100 continue if no auth actually
> -         * is needed. */
> +        * send Expect: 100-continue to get the 401 response including the
> +        * WWW-Authenticate header, or an 100 continue if no auth actually
> +        * is needed. */
>          if (auth && *auth &&
>              s->auth_state.auth_type == HTTP_AUTH_NONE &&
>              s->http_code != 401)
> --
> 2.17.1



This patch is for the issue I found when I test "RTSP tunnel HTTP"
(protocol defined by Apple, but no RFC found) on Bosch and Axix IP cameras.

It caused when RTP/RTSP tunnelling in HTTP, post-data is empty when sending
http header(because data for tunnel is not ready yet, rtsp.c line 1816,
function "ffurl_connect"), our http implementation will send "EXPECT:
100-continue" in the header. The post data is actually tunneled and sent
out
later in the rtsp implementation.

This header is not widely used by web server, even less for RTSP servers.
Neither Bosch and Axis cameras support that. Meanwhile, when I
go through the Apple spec, it does not have any 100-continue header at all.

I am not sure this is a regression after introducing 100-continue or not.
But based on my testing on IP cameras, it always fail when tunneling
RTSP into HTTP with credentials.


Thanks
-Jun

Patch hide | download patch | download mbox

diff --git a/libavformat/http.c b/libavformat/http.c
index ed0eb1c875..7e74719450 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -113,7 +113,7 @@  typedef struct HTTPContext {
     uint8_t *inflate_buffer;
 #endif /* CONFIG_ZLIB */
     AVDictionary *chained_options;
-    int send_expect_100;
+    int send_expect_100;    /* -1 = try to send if applicable, 0 = always disabled, 1 = always enabled */
     char *method;
     int reconnect;
     int reconnect_at_eof;
@@ -155,7 +155,7 @@  static const AVOption options[] = {
     { "auth_type", "HTTP authentication type", OFFSET(auth_state.auth_type), AV_OPT_TYPE_INT, { .i64 = HTTP_AUTH_NONE }, HTTP_AUTH_NONE, HTTP_AUTH_BASIC, D | E, "auth_type"},
     { "none", "No auth method set, autodetect", 0, AV_OPT_TYPE_CONST, { .i64 = HTTP_AUTH_NONE }, 0, 0, D | E, "auth_type"},
     { "basic", "HTTP basic authentication", 0, AV_OPT_TYPE_CONST, { .i64 = HTTP_AUTH_BASIC }, 0, 0, D | E, "auth_type"},
-    { "send_expect_100", "Force sending an Expect: 100-continue header for POST", OFFSET(send_expect_100), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+    { "send_expect_100", "Force sending an Expect: 100-continue header for POST", OFFSET(send_expect_100), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, E },
     { "location", "The actual location of the data received", OFFSET(location), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
     { "offset", "initial byte offset", OFFSET(off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D },
     { "end_offset", "try to limit the request to bytes preceding this offset", OFFSET(end_off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D },
@@ -1179,12 +1179,15 @@  static int http_connect(URLContext *h, const char *path, const char *local_path,
                                                 local_path, method);
     proxyauthstr = ff_http_auth_create_response(&s->proxy_auth_state, proxyauth,
                                                 local_path, method);
-    if (post && !s->post_data) {
+
+    if (s->send_expect_100 != -1) {
+        send_expect_100 = s->send_expect_100;
+    } else if (post && !s->post_data) {
         send_expect_100 = s->send_expect_100;
         /* The user has supplied authentication but we don't know the auth type,
-         * send Expect: 100-continue to get the 401 response including the
-         * WWW-Authenticate header, or an 100 continue if no auth actually
-         * is needed. */
+        * send Expect: 100-continue to get the 401 response including the
+        * WWW-Authenticate header, or an 100 continue if no auth actually
+        * is needed. */
         if (auth && *auth &&
             s->auth_state.auth_type == HTTP_AUTH_NONE &&
             s->http_code != 401)