diff --git a/plugins/obs-webrtc/whip-output.cpp b/plugins/obs-webrtc/whip-output.cpp index c9f999387..9963720eb 100644 --- a/plugins/obs-webrtc/whip-output.cpp +++ b/plugins/obs-webrtc/whip-output.cpp @@ -290,7 +290,7 @@ bool WHIPOutput::Connect() } std::string read_buffer; - std::string location_header; + std::vector location_headers; char offer_sdp[4096] = {0}; rtcGetLocalDescription(peer_connection, offer_sdp, sizeof(offer_sdp)); @@ -307,7 +307,7 @@ bool WHIPOutput::Connect() curl_easy_setopt(c, CURLOPT_WRITEDATA, (void *)&read_buffer); curl_easy_setopt(c, CURLOPT_HEADERFUNCTION, curl_header_location_function); - curl_easy_setopt(c, CURLOPT_HEADERDATA, (void *)&location_header); + curl_easy_setopt(c, CURLOPT_HEADERDATA, (void *)&location_headers); curl_easy_setopt(c, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(c, CURLOPT_URL, endpoint_url.c_str()); curl_easy_setopt(c, CURLOPT_POST, 1L); @@ -323,7 +323,7 @@ bool WHIPOutput::Connect() CURLcode res = curl_easy_perform(c); if (res != CURLE_OK) { - do_log(LOG_WARNING, + do_log(LOG_ERROR, "Connect failed: CURL returned result not CURLE_OK"); cleanup(); obs_output_signal_stop(output, OBS_OUTPUT_CONNECT_FAILED); @@ -333,7 +333,7 @@ bool WHIPOutput::Connect() long response_code; curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, &response_code); if (response_code != 201) { - do_log(LOG_WARNING, + do_log(LOG_ERROR, "Connect failed: HTTP endpoint returned response code %ld", response_code); cleanup(); @@ -342,35 +342,65 @@ bool WHIPOutput::Connect() } if (read_buffer.empty()) { - do_log(LOG_WARNING, + do_log(LOG_ERROR, "Connect failed: No data returned from HTTP endpoint request"); cleanup(); obs_output_signal_stop(output, OBS_OUTPUT_CONNECT_FAILED); return false; } - if (location_header.empty()) { - do_log(LOG_WARNING, + long redirect_count = 0; + curl_easy_getinfo(c, CURLINFO_REDIRECT_COUNT, &redirect_count); + + if (location_headers.size() < static_cast(redirect_count) + 1) { + do_log(LOG_ERROR, "WHIP server did not provide a resource URL via the Location header"); - } else { - CURLU *h = curl_url(); - curl_url_set(h, CURLUPART_URL, endpoint_url.c_str(), 0); - curl_url_set(h, CURLUPART_URL, location_header.c_str(), 0); - char *url = nullptr; - CURLUcode rc = curl_url_get(h, CURLUPART_URL, &url, - CURLU_NO_DEFAULT_PORT); - if (!rc) { - resource_url = url; - curl_free(url); - do_log(LOG_DEBUG, "WHIP Resource URL is: %s", - resource_url.c_str()); - } else { - do_log(LOG_WARNING, - "Unable to process resource URL response"); - } - curl_url_cleanup(h); + cleanup(); + obs_output_signal_stop(output, OBS_OUTPUT_CONNECT_FAILED); + return false; } + CURLU *url_builder = curl_url(); + auto last_location_header = location_headers.back(); + + // If Location header doesn't start with `http` it is a relative URL. + // Construct a absolute URL using the host of the effective URL + if (last_location_header.find("http") != 0) { + char *effective_url = nullptr; + curl_easy_getinfo(c, CURLINFO_EFFECTIVE_URL, &effective_url); + if (effective_url == nullptr) { + do_log(LOG_ERROR, "Failed to build Resource URL"); + cleanup(); + obs_output_signal_stop(output, + OBS_OUTPUT_CONNECT_FAILED); + return false; + } + + curl_url_set(url_builder, CURLUPART_URL, effective_url, 0); + curl_url_set(url_builder, CURLUPART_PATH, + last_location_header.c_str(), 0); + curl_url_set(url_builder, CURLUPART_QUERY, "", 0); + } else { + curl_url_set(url_builder, CURLUPART_URL, + last_location_header.c_str(), 0); + } + + char *url = nullptr; + CURLUcode rc = curl_url_get(url_builder, CURLUPART_URL, &url, + CURLU_NO_DEFAULT_PORT); + if (rc) { + do_log(LOG_ERROR, + "WHIP server provided a invalid resource URL via the Location header"); + cleanup(); + obs_output_signal_stop(output, OBS_OUTPUT_CONNECT_FAILED); + return false; + } + + resource_url = url; + curl_free(url); + do_log(LOG_DEBUG, "WHIP Resource URL is: %s", resource_url.c_str()); + curl_url_cleanup(url_builder); + #ifdef DEBUG_SDP do_log(LOG_DEBUG, "Answer SDP:\n%s", read_buffer.c_str()); #endif diff --git a/plugins/obs-webrtc/whip-utils.h b/plugins/obs-webrtc/whip-utils.h index 5d214cd10..d8618055c 100644 --- a/plugins/obs-webrtc/whip-utils.h +++ b/plugins/obs-webrtc/whip-utils.h @@ -45,7 +45,7 @@ static size_t curl_writefunction(char *data, size_t size, size_t nmemb, static size_t curl_header_location_function(char *data, size_t size, size_t nmemb, void *priv_data) { - auto header_buffer = static_cast(priv_data); + auto header_buffer = static_cast *>(priv_data); size_t real_size = size * nmemb; @@ -54,8 +54,11 @@ static size_t curl_header_location_function(char *data, size_t size, if (!astrcmpi_n(data, "location: ", LOCATION_HEADER_LENGTH)) { char *val = data + LOCATION_HEADER_LENGTH; - header_buffer->append(val, real_size - LOCATION_HEADER_LENGTH); - *header_buffer = trim_string(*header_buffer); + auto header_temp = + std::string(val, real_size - LOCATION_HEADER_LENGTH); + + header_temp = trim_string(header_temp); + header_buffer->push_back(header_temp); } return real_size;