curlbasesink: Add curl seek callback

Adding functionality to handle SEEK_SET enables rewinding of sent data.
In the HTTP case, this happens after an HTTP 401 has been received from
the other end. This will result in the sent data being resent.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1616>
This commit is contained in:
Lars Lundqvist 2019-10-02 11:17:09 +02:00 committed by GStreamer Merge Bot
parent 97e648a738
commit 9ded00bcf0

View file

@ -121,6 +121,8 @@ static size_t gst_curl_base_sink_transfer_read_cb (void *ptr, size_t size,
size_t nmemb, void *stream); size_t nmemb, void *stream);
static size_t gst_curl_base_sink_transfer_write_cb (void *ptr, size_t size, static size_t gst_curl_base_sink_transfer_write_cb (void *ptr, size_t size,
size_t nmemb, void *stream); size_t nmemb, void *stream);
static int gst_curl_base_sink_transfer_seek_cb (void *user_p, curl_off_t offset,
int origin);
static size_t gst_curl_base_sink_transfer_data_buffer (GstCurlBaseSink * sink, static size_t gst_curl_base_sink_transfer_data_buffer (GstCurlBaseSink * sink,
void *curl_ptr, size_t block_size, guint * last_chunk); void *curl_ptr, size_t block_size, guint * last_chunk);
#ifndef GST_DISABLE_GST_DEBUG #ifndef GST_DISABLE_GST_DEBUG
@ -705,6 +707,21 @@ gst_curl_base_sink_transfer_set_common_options_unlocked (GstCurlBaseSink * sink)
curl_easy_strerror (res)); curl_easy_strerror (res));
return FALSE; return FALSE;
} }
res = curl_easy_setopt (sink->curl, CURLOPT_SEEKDATA, sink);
if (res != CURLE_OK) {
sink->error = g_strdup_printf ("failed to set seek user data: %s",
curl_easy_strerror (res));
return FALSE;
}
res = curl_easy_setopt (sink->curl, CURLOPT_SEEKFUNCTION,
gst_curl_base_sink_transfer_seek_cb);
if (res != CURLE_OK) {
sink->error = g_strdup_printf ("failed to set seek function: %s",
curl_easy_strerror (res));
return FALSE;
}
/* Time out in case transfer speed in bytes per second stay below /* Time out in case transfer speed in bytes per second stay below
* CURLOPT_LOW_SPEED_LIMIT during CURLOPT_LOW_SPEED_TIME */ * CURLOPT_LOW_SPEED_LIMIT during CURLOPT_LOW_SPEED_TIME */
res = curl_easy_setopt (sink->curl, CURLOPT_LOW_SPEED_LIMIT, 1L); res = curl_easy_setopt (sink->curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
@ -883,6 +900,45 @@ gst_curl_base_sink_transfer_write_cb (void G_GNUC_UNUSED * ptr, size_t size,
return realsize; return realsize;
} }
static int
gst_curl_base_sink_transfer_seek_cb (void *stream, curl_off_t offset,
int origin)
{
GstCurlBaseSink *sink;
curl_off_t buf_size;
/*
* Origin is SEEK_SET, SEEK_CUR or SEEK_END,
* libcurl currently only passes SEEK_SET.
*/
sink = (GstCurlBaseSink *) stream;
GST_OBJECT_LOCK (sink);
buf_size = sink->transfer_buf->offset + sink->transfer_buf->len;
switch (origin) {
case SEEK_SET:
if ((0 <= offset) && (offset <= buf_size)) {
sink->transfer_buf->offset = offset;
sink->transfer_buf->len = buf_size - offset;
} else {
GST_OBJECT_UNLOCK (sink);
return CURL_SEEKFUNC_FAIL;
}
break;
case SEEK_CUR:
case SEEK_END:
default:
GST_OBJECT_UNLOCK (sink);
return CURL_SEEKFUNC_FAIL;
break;
}
GST_OBJECT_UNLOCK (sink);
return CURL_SEEKFUNC_OK;
}
CURLcode CURLcode
gst_curl_base_sink_transfer_check (GstCurlBaseSink * sink) gst_curl_base_sink_transfer_check (GstCurlBaseSink * sink)
{ {