• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GstCurlHttpSrc
3  * Copyright 2017 British Broadcasting Corporation - Research and Development
4  *
5  * Author: Sam Hurst <samuelh@rd.bbc.co.uk>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  * Alternatively, the contents of this file may be used under the
26  * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
27  * which case the following provisions apply instead of the ones
28  * mentioned above:
29  *
30  * This library is free software; you can redistribute it and/or
31  * modify it under the terms of the GNU Library General Public
32  * License as published by the Free Software Foundation; either
33  * version 2 of the License, or (at your option) any later version.
34  *
35  * This library is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
38  * Library General Public License for more details.
39  *
40  * You should have received a copy of the GNU Library General Public
41  * License along with this library; if not, write to the
42  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
43  * Boston, MA 02111-1307, USA.
44  */
45 
46 #include "gstcurlqueue.h"
47 
48 /**
49  * gst_curl_http_src_add_queue_item:
50  *
51  * Function to add an item to a queue. If the queue is empty (i.e. NULL), then
52  * it creates the new head of the queue, otherwise it scans to the end and adds
53  * the entry there.
54  * @param queue The queue to add an item to. Can be NULL.
55  * @param s The item to be added to the queue.
56  * @return Returns TRUE (0) on success, FALSE (!0) is an error.
57  */
58 gboolean
gst_curl_http_src_add_queue_item(GstCurlHttpSrcQueueElement ** queue,GstCurlHttpSrc * s)59 gst_curl_http_src_add_queue_item (GstCurlHttpSrcQueueElement ** queue,
60     GstCurlHttpSrc * s)
61 {
62   GstCurlHttpSrcQueueElement *insert_point;
63 
64   if (*queue == NULL) {
65     /* Queue is currently empty, so create a new item on the head */
66     *queue = (GstCurlHttpSrcQueueElement *)
67         g_malloc (sizeof (GstCurlHttpSrcQueueElement));
68     if (*queue == NULL) {
69       return FALSE;
70     }
71     insert_point = *queue;
72   } else {
73     insert_point = *queue;
74 #ifdef OHOS_OPT_COMPAT
75     /**
76      * ohos.opt.compat.0033
77      * When remove the GstCurlHttpSrc instance from queue, only the one item will be removed, but
78      * add_queue_item allow to push same instance multi-time, which will lead to the remove_queue_item
79      * can not remove all items of the specified instance. So, if the instance has already exist in
80      * the queue, return directly.
81      */
82     GstCurlHttpSrcQueueElement *prev_point = NULL;
83     while (insert_point != NULL) {
84       if (insert_point->p == s) {
85         g_atomic_int_set (&insert_point->running, 0);
86         s->connection_status = GSTCURL_CONNECTED;
87         return TRUE;
88       }
89       prev_point = insert_point;
90       insert_point = insert_point->next;
91     }
92     insert_point = (GstCurlHttpSrcQueueElement *)
93       g_malloc (sizeof (GstCurlHttpSrcQueueElement));
94     if (insert_point == NULL) {
95       return FALSE;
96     }
97     prev_point->next = insert_point;
98 #else
99     while (insert_point->next != NULL) {
100       insert_point = insert_point->next;
101     }
102     insert_point->next = (GstCurlHttpSrcQueueElement *)
103         g_malloc (sizeof (GstCurlHttpSrcQueueElement));
104     if (insert_point->next == NULL) {
105       return FALSE;
106     }
107     insert_point = insert_point->next;
108 #endif
109   }
110 
111   insert_point->p = s;
112   g_atomic_int_set (&insert_point->running, 0);
113   insert_point->next = NULL;
114   s->connection_status = GSTCURL_CONNECTED;
115   return TRUE;
116 }
117 
118 /**
119  * gst_curl_http_src_remove_queue_item:
120  *
121  * Function to remove an item from a queue.
122  * @param queue The queue to remove an item from.
123  * @param s The item to be removed.
124  * @return Returns TRUE if item removed, FALSE if item couldn't be found.
125  */
126 gboolean
gst_curl_http_src_remove_queue_item(GstCurlHttpSrcQueueElement ** queue,GstCurlHttpSrc * s)127 gst_curl_http_src_remove_queue_item (GstCurlHttpSrcQueueElement ** queue,
128     GstCurlHttpSrc * s)
129 {
130   GstCurlHttpSrcQueueElement *prev_qelement, *this_qelement;
131 
132   prev_qelement = NULL;
133   this_qelement = *queue;
134   while (this_qelement && (this_qelement->p != s)) {
135     prev_qelement = this_qelement;
136     this_qelement = this_qelement->next;
137   }
138   if (this_qelement == NULL) {
139     /* Reached end of list without finding anything */
140     return FALSE;
141   }
142 
143   /* First queue item matched. */
144   if (prev_qelement == NULL) {
145     /* First and only element? If so, free the element and make queue NULL */
146     if (this_qelement->next == NULL) {
147       g_free (*queue);
148       *queue = NULL;
149       return TRUE;
150     } else {
151       *queue = this_qelement->next;
152     }
153   } else {
154     prev_qelement->next = this_qelement->next;
155   }
156   g_free (this_qelement);
157   s->connection_status = GSTCURL_NOT_CONNECTED;
158   return TRUE;
159 }
160 
161 /**
162  * gst_curl_http_src_remove_queue_handle:
163  *
164  * Convenience function to remove an item from a queue by it's contained curl
165  * handle. Only ever called from within the multi loop when the CURL handle
166  * returns, so it's safe to assume that the transfer completed and the result
167  * can be set as GSTCURL_RETURN_DONE (which doesn't necessarily mean that the
168  * transfer was a success, just that CURL is finished with it)
169  * @param queue The queue to remove an item from.
170  * @param s The item to be removed.
171  * @return Returns TRUE if item removed, FALSE if item couldn't be found.
172  */
173 gboolean
gst_curl_http_src_remove_queue_handle(GstCurlHttpSrcQueueElement ** queue,CURL * handle,CURLcode result)174 gst_curl_http_src_remove_queue_handle (GstCurlHttpSrcQueueElement ** queue,
175     CURL * handle, CURLcode result)
176 {
177   GstCurlHttpSrcQueueElement *prev_qelement, *this_qelement;
178 
179   prev_qelement = NULL;
180   this_qelement = *queue;
181   while (this_qelement && (this_qelement->p->curl_handle != handle)) {
182     prev_qelement = this_qelement;
183     this_qelement = this_qelement->next;
184   }
185   if (this_qelement == NULL) {
186     /* Reached end of list without finding anything */
187     return FALSE;
188   }
189 
190   /*GST_DEBUG_OBJECT (this_qelement->p,
191      "Removing queue item via curl handle for URI %s",
192      this_qelement->p->uri); */
193   /* First, signal the transfer owner thread to wake up */
194   g_mutex_lock (&this_qelement->p->buffer_mutex);
195   g_cond_signal (&this_qelement->p->buffer_cond);
196   if (this_qelement->p->state != GSTCURL_UNLOCK) {
197     this_qelement->p->state = GSTCURL_DONE;
198   } else {
199     this_qelement->p->pending_state = GSTCURL_DONE;
200   }
201   this_qelement->p->connection_status = GSTCURL_NOT_CONNECTED;
202   this_qelement->p->curl_result = result;
203   g_mutex_unlock (&this_qelement->p->buffer_mutex);
204 
205   /* First queue item matched. */
206   if (prev_qelement == NULL) {
207     /* First and only element? If so, free the element and make queue NULL */
208     if (this_qelement->next == NULL) {
209       g_free (*queue);
210       *queue = NULL;
211       return TRUE;
212     } else {
213       *queue = this_qelement->next;
214     }
215   } else {
216     prev_qelement->next = this_qelement->next;
217   }
218   g_free (this_qelement);
219   return TRUE;
220 }
221