static void gst_curl_http_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstCurlHttpSink *sink; g_return_if_fail (GST_IS_CURL_HTTP_SINK (object)); sink = GST_CURL_HTTP_SINK (object); switch (prop_id) { case PROP_PROXY: g_value_set_string (value, sink->proxy); break; case PROP_PROXY_PORT: g_value_set_int (value, sink->proxy_port); break; case PROP_PROXY_USER_NAME: g_value_set_string (value, sink->proxy_user); break; case PROP_PROXY_USER_PASSWD: g_value_set_string (value, sink->proxy_passwd); break; case PROP_USE_CONTENT_LENGTH: g_value_set_boolean (value, sink->use_content_length); break; case PROP_CONTENT_TYPE: g_value_set_string (value, sink->content_type); break; default: GST_DEBUG_OBJECT (sink, "invalid property id"); break; } }
static gboolean gst_curl_http_sink_set_options_unlocked (GstCurlBaseSink * bcsink) { GstCurlHttpSink *sink = GST_CURL_HTTP_SINK (bcsink); GstCurlTlsSinkClass *parent_class; /* proxy settings */ if (sink->proxy != NULL && strlen (sink->proxy)) { if (!proxy_setup (bcsink)) { return FALSE; } } curl_easy_setopt (bcsink->curl, CURLOPT_POST, 1L); /* FIXME: check user & passwd */ curl_easy_setopt (bcsink->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); parent_class = GST_CURL_TLS_SINK_GET_CLASS (sink); if (g_str_has_prefix (bcsink->url, "https://")) { return parent_class->set_options_unlocked (bcsink); } return TRUE; }
static gboolean gst_curl_http_sink_set_header_unlocked (GstCurlBaseSink * bcsink) { GstCurlHttpSink *sink = GST_CURL_HTTP_SINK (bcsink); gchar *tmp; CURLcode res; if (sink->header_list) { curl_slist_free_all (sink->header_list); sink->header_list = NULL; } if (!sink->proxy_headers_set && sink->use_proxy) { sink->header_list = curl_slist_append (sink->header_list, "Content-Length: 0"); sink->proxy_headers_set = TRUE; goto set_headers; } if (sink->use_content_length) { /* if content length is used we assume that every buffer is one * entire file, which is the case when uploading several jpegs */ tmp = g_strdup_printf ("Content-Length: %d", (int) bcsink->transfer_buf->len); sink->header_list = curl_slist_append (sink->header_list, tmp); g_free (tmp); } else { /* when sending a POST request to a HTTP 1.1 server, you can send data * without knowing the size before starting the POST if you use chunked * encoding */ sink->header_list = curl_slist_append (sink->header_list, "Transfer-Encoding: chunked"); } tmp = g_strdup_printf ("Content-Type: %s", sink->content_type); sink->header_list = curl_slist_append (sink->header_list, tmp); g_free (tmp); set_headers: tmp = g_strdup_printf ("Content-Disposition: attachment; filename=" "\"%s\"", bcsink->file_name); sink->header_list = curl_slist_append (sink->header_list, tmp); g_free (tmp); res = curl_easy_setopt (bcsink->curl, CURLOPT_HTTPHEADER, sink->header_list); if (res != CURLE_OK) { bcsink->error = g_strdup_printf ("failed to set HTTP headers: %s", curl_easy_strerror (res)); return FALSE; } return TRUE; }
// FIXME check this: why critical when no mime is set??? static void gst_curl_http_sink_set_mime_type (GstCurlBaseSink * bcsink, GstCaps * caps) { GstCurlHttpSink *sink = GST_CURL_HTTP_SINK (bcsink); GstStructure *structure; const gchar *mime_type; if (sink->content_type != NULL) { return; } structure = gst_caps_get_structure (caps, 0); mime_type = gst_structure_get_name (structure); sink->content_type = g_strdup (mime_type); }
static gboolean gst_curl_http_sink_transfer_verify_response_code (GstCurlBaseSink * bcsink) { GstCurlHttpSink *sink = GST_CURL_HTTP_SINK (bcsink); glong resp; curl_easy_getinfo (bcsink->curl, CURLINFO_RESPONSE_CODE, &resp); GST_DEBUG_OBJECT (sink, "response code: %ld", resp); if (resp < 100 || resp >= 300) { bcsink->error = g_strdup_printf ("HTTP response error: (received: %ld)", resp); return FALSE; } return TRUE; }
static void gst_curl_http_sink_finalize (GObject * gobject) { GstCurlHttpSink *this = GST_CURL_HTTP_SINK (gobject); GST_DEBUG ("finalizing curlhttpsink"); g_free (this->proxy); g_free (this->proxy_user); g_free (this->proxy_passwd); g_free (this->content_type); if (this->header_list) { curl_slist_free_all (this->header_list); this->header_list = NULL; } G_OBJECT_CLASS (parent_class)->finalize (gobject); }
static void gst_curl_http_sink_transfer_prepare_poll_wait (GstCurlBaseSink * bcsink) { GstCurlHttpSink *sink = GST_CURL_HTTP_SINK (bcsink); if (!sink->proxy_conn_established && (sink->proxy_resp != RESPONSE_CONNECT_PROXY) && sink->proxy_auth) { curl_easy_getinfo (bcsink->curl, CURLINFO_HTTP_CONNECTCODE, &sink->proxy_resp); if (sink->proxy_resp == RESPONSE_CONNECT_PROXY) { GST_LOG ("received HTTP/1.0 200 Connection Established"); /* Workaround: redefine HTTP headers before connecting to HTTP server. * When talking to proxy, the Content-Length: 0 is send with the request. */ curl_multi_remove_handle (bcsink->multi_handle, bcsink->curl); gst_curl_http_sink_set_header_unlocked (bcsink); curl_multi_add_handle (bcsink->multi_handle, bcsink->curl); sink->proxy_conn_established = TRUE; } } }
static gboolean gst_curl_http_sink_set_options_unlocked (GstCurlBaseSink * bcsink) { GstCurlHttpSink *sink = GST_CURL_HTTP_SINK (bcsink); GstCurlTlsSinkClass *parent_class; CURLcode res; /* proxy settings */ if (sink->proxy != NULL) { if (!proxy_setup (bcsink)) { return FALSE; } } res = curl_easy_setopt (bcsink->curl, CURLOPT_POST, 1L); if (res != CURLE_OK) { bcsink->error = g_strdup_printf ("failed to set HTTP POST: %s", curl_easy_strerror (res)); return FALSE; } /* FIXME: check user & passwd */ res = curl_easy_setopt (bcsink->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); if (res != CURLE_OK) { bcsink->error = g_strdup_printf ("failed to set HTTP authentication methods: %s", curl_easy_strerror (res)); return FALSE; } parent_class = GST_CURL_TLS_SINK_GET_CLASS (sink); if (g_str_has_prefix (bcsink->url, "https://")) { return parent_class->set_options_unlocked (bcsink); } return TRUE; }
static gboolean proxy_setup (GstCurlBaseSink * bcsink) { GstCurlHttpSink *sink = GST_CURL_HTTP_SINK (bcsink); if (curl_easy_setopt (bcsink->curl, CURLOPT_PROXY, sink->proxy) != CURLE_OK) { return FALSE; } if (curl_easy_setopt (bcsink->curl, CURLOPT_PROXYPORT, sink->proxy_port) != CURLE_OK) { return FALSE; } if (sink->proxy_user != NULL && strlen (sink->proxy_user) && sink->proxy_passwd != NULL && strlen (sink->proxy_passwd)) { curl_easy_setopt (bcsink->curl, CURLOPT_PROXYUSERNAME, sink->proxy_user); curl_easy_setopt (bcsink->curl, CURLOPT_PROXYPASSWORD, sink->proxy_passwd); curl_easy_setopt (bcsink->curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY); sink->proxy_auth = TRUE; } if (g_str_has_prefix (bcsink->url, "https://")) { /* tunnel all operations through a given HTTP proxy */ if (curl_easy_setopt (bcsink->curl, CURLOPT_HTTPPROXYTUNNEL, 1L) != CURLE_OK) { return FALSE; } } sink->use_proxy = TRUE; return TRUE; }
static gboolean proxy_setup (GstCurlBaseSink * bcsink) { GstCurlHttpSink *sink = GST_CURL_HTTP_SINK (bcsink); CURLcode res; res = curl_easy_setopt (bcsink->curl, CURLOPT_PROXY, sink->proxy); if (res != CURLE_OK) { bcsink->error = g_strdup_printf ("failed to set proxy: %s", curl_easy_strerror (res)); return FALSE; } res = curl_easy_setopt (bcsink->curl, CURLOPT_PROXYPORT, sink->proxy_port); if (res != CURLE_OK) { bcsink->error = g_strdup_printf ("failed to set proxy port: %s", curl_easy_strerror (res)); return FALSE; } if (sink->proxy_user != NULL && strlen (sink->proxy_user) && sink->proxy_passwd != NULL && strlen (sink->proxy_passwd)) { res = curl_easy_setopt (bcsink->curl, CURLOPT_PROXYUSERNAME, sink->proxy_user); if (res != CURLE_OK) { bcsink->error = g_strdup_printf ("failed to set proxy user name: %s", curl_easy_strerror (res)); return FALSE; } res = curl_easy_setopt (bcsink->curl, CURLOPT_PROXYPASSWORD, sink->proxy_passwd); if (res != CURLE_OK) { bcsink->error = g_strdup_printf ("failed to set proxy password: %s", curl_easy_strerror (res)); return FALSE; } res = curl_easy_setopt (bcsink->curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY); if (res != CURLE_OK) { bcsink->error = g_strdup_printf ("failed to set proxy authentication method: %s", curl_easy_strerror (res)); return FALSE; } sink->proxy_auth = TRUE; } if (g_str_has_prefix (bcsink->url, "https://")) { /* tunnel all operations through a given HTTP proxy */ res = curl_easy_setopt (bcsink->curl, CURLOPT_HTTPPROXYTUNNEL, 1L); if (res != CURLE_OK) { bcsink->error = g_strdup_printf ("failed to set HTTP proxy tunnel: %s", curl_easy_strerror (res)); return FALSE; } } sink->use_proxy = TRUE; return TRUE; }
static void gst_curl_http_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstCurlHttpSink *sink; GstState cur_state; g_return_if_fail (GST_IS_CURL_HTTP_SINK (object)); sink = GST_CURL_HTTP_SINK (object); gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0); if (cur_state != GST_STATE_PLAYING && cur_state != GST_STATE_PAUSED) { GST_OBJECT_LOCK (sink); switch (prop_id) { case PROP_PROXY: g_free (sink->proxy); sink->proxy = g_value_dup_string (value); GST_DEBUG_OBJECT (sink, "proxy set to %s", sink->proxy); break; case PROP_PROXY_PORT: sink->proxy_port = g_value_get_int (value); GST_DEBUG_OBJECT (sink, "proxy port set to %d", sink->proxy_port); break; case PROP_PROXY_USER_NAME: g_free (sink->proxy_user); sink->proxy_user = g_value_dup_string (value); GST_DEBUG_OBJECT (sink, "proxy user set to %s", sink->proxy_user); break; case PROP_PROXY_USER_PASSWD: g_free (sink->proxy_passwd); sink->proxy_passwd = g_value_dup_string (value); GST_DEBUG_OBJECT (sink, "proxy password set to %s", sink->proxy_passwd); break; case PROP_USE_CONTENT_LENGTH: sink->use_content_length = g_value_get_boolean (value); GST_DEBUG_OBJECT (sink, "use_content_length set to %d", sink->use_content_length); break; case PROP_CONTENT_TYPE: g_free (sink->content_type); sink->content_type = g_value_dup_string (value); GST_DEBUG_OBJECT (sink, "content type set to %s", sink->content_type); break; default: GST_DEBUG_OBJECT (sink, "invalid property id %d", prop_id); break; } GST_OBJECT_UNLOCK (sink); return; } /* in PLAYING or PAUSED state */ GST_OBJECT_LOCK (sink); switch (prop_id) { case PROP_CONTENT_TYPE: g_free (sink->content_type); sink->content_type = g_value_dup_string (value); GST_DEBUG_OBJECT (sink, "content type set to %s", sink->content_type); break; default: GST_WARNING_OBJECT (sink, "cannot set property when PLAYING"); break; } GST_OBJECT_UNLOCK (sink); }