From 1ee309f247e737962a95868ac025600c77f328c3 Mon Sep 17 00:00:00 2001
From: Maxim Razin <maxim.razin@rumble.com>
Date: Fri, 8 Dec 2023 12:50:50 -0500
Subject: [PATCH] libavformat: Verify HTTP reply headers on POST/PUT

Verify HTTP code when the reply headers arrived during POST/PUT.
The check is done before each write, and at shutdown, whenever the headers arrive.
Fixes https://trac.ffmpeg.org/ticket/10721
---
 libavformat/http.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/libavformat/http.c b/libavformat/http.c
index c0fe7c36d9..067034b430 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -21,6 +21,7 @@
 
 #include "config.h"
 #include "config_components.h"
+#include "os_support.h"
 
 #include <time.h>
 #if CONFIG_ZLIB
@@ -1816,6 +1817,23 @@ static int http_read(URLContext *h, uint8_t *buf, int size)
     return size;
 }
 
+static int http_check_header_available(HTTPContext *s) {
+    int fd;
+    if (s->line_count > 0) {
+        /* already received input headers */
+        return 0;
+    }
+    fd = ffurl_get_file_handle(s->hd);
+    if (fd < 0)
+        return AVERROR(EIO);
+    struct pollfd p = { .fd = fd, .events = POLLIN };
+    int ret = poll(&p, 1, 0);
+    if (ret < 0)
+        return AVERROR(errno);
+    if (p.revents & POLLIN) return 1;
+    return 0;
+}
+
 /* used only when posting data */
 static int http_write(URLContext *h, const uint8_t *buf, int size)
 {
@@ -1824,6 +1842,16 @@ static int http_write(URLContext *h, const uint8_t *buf, int size)
     char crlf[] = "\r\n";
     HTTPContext *s = h->priv_data;
 
+    ret = http_check_header_available(s);
+    if (ret < 0)
+        return ret;
+    if (ret > 0) {
+        av_log(h, AV_LOG_WARNING, "Received reply header, likely server reported error.\n");
+        ret = http_read_header(h);
+        if (ret < 0)
+            return ret;
+    }
+
     if (!s->chunked_post) {
         /* non-chunked data is sent without any special encoding */
         return ffurl_write(s->hd, buf, size);
@@ -1868,6 +1896,13 @@ static int http_shutdown(URLContext *h, int flags)
         }
         s->end_chunked_post = 1;
     }
+    if (ret < 0)
+        return ret;
+
+    if ((flags & AVIO_FLAG_WRITE) && s->line_count == 0) {
+        av_log(h, AV_LOG_TRACE, "Analyzing reply header after transmission finished.\n");
+        ret = http_read_header(h);
+    }
 
     return ret;
 }
-- 
2.39.2 (Apple Git-143)

