1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2000-2019
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / common tools sub-project
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #ifndef _GF_DOWNLOAD_H_
27 #define _GF_DOWNLOAD_H_
28 
29 /*!
30 \file <gpac/download.h>
31 \brief HTTP(S) Downloader.
32  */
33 
34 /*!
35 
36 \addtogroup download_grp
37 \brief HTTP Downloader
38 
39 This section documents the file downloading tools the GPAC framework. Currently HTTP and HTTPS are supported. HTTPS may not be supported depending on GPAC compilation options (HTTPS in GPAC needs OpenSSL installed on the system).
40 
41 @{
42 
43  */
44 
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 #include <gpac/tools.h>
51 #include <gpac/config_file.h>
52 #include <gpac/cache.h>
53 
54 /*!the download manager object. This is usually not used by GPAC modules*/
55 typedef struct __gf_download_manager GF_DownloadManager;
56 /*!the download manager session.*/
57 typedef struct __gf_download_session GF_DownloadSession;
58 /*!the optional filter session.*/
59 typedef struct __gf_filter_session GF_DownloadFilterSession;
60 
61 /*! URL information object*/
62 typedef struct GF_URL_Info_Struct {
63 	const char * protocol;
64 	char * server_name;
65 	char * remotePath;
66 	char * canonicalRepresentation;
67 	char * userName;
68 	char * password;
69 	u16 port;
70 } GF_URL_Info;
71 
72 /*!
73 Extracts the information from an URL. A call to gf_dm_url_info_init() must have been issue before calling this method.
74 \param url The URL to fill
75 \param info This structure will be initialized properly and filled with the data
76 \param baseURL The baseURL to use if any (can be null)
77 \return GF_OK if URL is well formed and supported by GPAC
78  */
79 GF_Err gf_dm_get_url_info(const char * url, GF_URL_Info * info, const char * baseURL);
80 
81 /**
82 Inits the GF_URL_Info structure before it can be used
83 \param info The structure to initialize
84  */
85 void gf_dm_url_info_init(GF_URL_Info * info);
86 
87 /*!
88 Frees the inner structures of a GF_URL_Info_Struct
89 \param info The info to free
90  */
91 void gf_dm_url_info_del(GF_URL_Info * info);
92 
93 /*!
94 \brief download manager constructor
95 
96 Creates a new download manager object.
97 \param fsess optional filter session. If not NULL, the filter session will be used for async downloads. Otherwise, threads will be created
98 \return the download manager object
99 */
100 GF_DownloadManager *gf_dm_new(GF_DownloadFilterSession *fsess);
101 /*!
102 \brief download manager destructor
103 
104 Deletes the download manager. All running sessions are aborted
105 \param dm the download manager object
106  */
107 void gf_dm_del(GF_DownloadManager *dm);
108 
109 /*!
110 \brief callback function for authentication
111 
112 The gf_dm_get_usr_pass type is the type for the callback of the \ref gf_dm_set_auth_callback function used for password retrieval
113 \param usr_cbk opaque user data
114 \param site_url url of the site the user and password are requested for
115 \param usr_name the user name for this site. The allocated space for this buffer is 50 bytes. \note this varaibale may already be formatted.
116 \param password the password for this site and user. The allocated space for this buffer is 50 bytes.
117 \return 0 if user didn't fill in the information which will result in an authentication failure, 1 otherwise.
118 */
119 typedef Bool (*gf_dm_get_usr_pass)(void *usr_cbk, const char *site_url, char *usr_name, char *password);
120 
121 /*!
122 \brief password retrieval assignment
123 
124 Assigns the callback function used for user password retrieval. If no such function is assigned to the download manager, all downloads requiring authentication will fail.
125 \param dm the download manager object
126 \param get_pass specifies \ref gf_dm_get_usr_pass callback function for user and password retrieval.
127 \param usr_cbk opaque user data passed to callback function
128  */
129 void gf_dm_set_auth_callback(GF_DownloadManager *dm, gf_dm_get_usr_pass get_pass, void *usr_cbk);
130 
131 /*!downloader session message types*/
132 typedef enum
133 {
134 	/*!signal that session is setup and waiting for connection request*/
135 	GF_NETIO_SETUP = 0,
136 	/*!signal that session connection is done*/
137 	GF_NETIO_CONNECTED,
138 	/*!request a protocol method from the user. Default value is "GET" for HTTP*/
139 	GF_NETIO_GET_METHOD,
140 	/*!request a header from the user. */
141 	GF_NETIO_GET_HEADER,
142 	/*!requesting content from the user, if any. Content is appended to the request*/
143 	GF_NETIO_GET_CONTENT,
144 	/*!signal that request is sent and waiting for server reply*/
145 	GF_NETIO_WAIT_FOR_REPLY,
146 	/*!signal a header to user. */
147 	GF_NETIO_PARSE_HEADER,
148 	/*!signal request reply to user. The reply is always sent after the headers*/
149 	GF_NETIO_PARSE_REPLY,
150 	/*!send data to the user*/
151 	GF_NETIO_DATA_EXCHANGE,
152 	/*!all data has been transfered*/
153 	GF_NETIO_DATA_TRANSFERED,
154 	/*!signal that the session has been deconnected*/
155 	GF_NETIO_DISCONNECTED,
156 	/*!downloader session failed (error code set) or done/destroyed (no error code)*/
157 	GF_NETIO_STATE_ERROR
158 } GF_NetIOStatus;
159 
160 /*!session download flags*/
161 typedef enum
162 {
163 	/*!session is not threaded, the user must explicitely fetch the data , either with the function gf_dm_sess_fetch_data
164 	or the function gf_dm_sess_process- if the session is threaded, the user must call gf_dm_sess_process to start the session*/
165 	GF_NETIO_SESSION_NOT_THREADED = 1,
166 	/*! session data is cached or not */
167 	GF_NETIO_SESSION_NOT_CACHED = 1<<1,
168 	/*! forces data notification even when session is threaded*/
169 	GF_NETIO_SESSION_NOTIFY_DATA = 1<<2,
170 	/*indicates that the connection to the server should be kept once the download is successfully completed*/
171 	GF_NETIO_SESSION_PERSISTENT = 1<<3,
172 	/*file is stored in memory, and the cache name is set to gpac://%u@%p, where %d is the size in bytes and %d is the the pointer to the memory.
173 	Memory cached files are destroyed upon downloader destruction*/
174 	GF_NETIO_SESSION_MEMORY_CACHE = 1<<4,
175 } GF_NetIOFlags;
176 
177 
178 /*!protocol I/O parameter*/
179 typedef struct
180 {
181 	/*!parameter message type*/
182 	GF_NetIOStatus msg_type;
183 	/*error code if any. Valid for all message types.*/
184 	GF_Err error;
185 	/*!data received or data to send. Only valid for GF_NETIO_GET_CONTENT and GF_NETIO_DATA_EXCHANGE (when no cache is setup) messages*/
186 	const u8 *data;
187 	/*!size of associated data. Only valid for GF_NETIO_GET_CONTENT and GF_NETIO_DATA_EXCHANGE messages*/
188 	u32 size;
189 	/*protocol header. Only valid for GF_NETIO_GET_HEADER, GF_NETIO_PARSE_HEADER and GF_NETIO_GET_METHOD*/
190 	const char *name;
191 	/*protocol header value or server response. Only alid for GF_NETIO_GET_HEADER, GF_NETIO_PARSE_HEADER and GF_NETIO_PARSE_REPLY*/
192 	char *value;
193 	/*message-dependend
194 		for GF_NETIO_PARSE_REPLY, response code
195 		for GF_NETIO_DATA_EXCHANGE
196 			Set to 1 in to indicate end of chunk transfer
197 			Set to 2 in GF_NETIO_DATA_EXCHANGE to indicate complete file is already received (replay of events from cache)
198 		for all other, usage is reserved
199 	*/
200 	u32 reply;
201 	/*download session for which the message is being sent*/
202 	GF_DownloadSession *sess;
203 } GF_NETIO_Parameter;
204 
205 /*!
206 \brief callback function for data reception and state signaling
207 
208 The gf_dm_user_io type is the type for the data callback function of a download session
209 \param usr_cbk opaque user data
210 \param parameter the input/output parameter structure
211 */
212 typedef void (*gf_dm_user_io)(void *usr_cbk, GF_NETIO_Parameter *parameter);
213 
214 
215 
216 /*!
217 \brief download session constructor
218 
219 Creates a new download session
220 \param dm the download manager object
221 \param url file to retrieve (no PUT/POST yet, only downloading is supported)
222 \param dl_flags combination of session download flags
223 \param user_io specifies \ref gf_dm_user_io callback function for data reception and service messages
224 \param usr_cbk opaque user data passed to callback function
225 \param error error for failure cases
226 \return the session object or NULL if error. If no error is indicated and a NULL session is returned, this means the file is local
227  */
228 GF_DownloadSession * gf_dm_sess_new(GF_DownloadManager *dm, const char *url, u32 dl_flags,
229                                     gf_dm_user_io user_io,
230                                     void *usr_cbk,
231                                     GF_Err *error);
232 
233 /*!
234 \brief download session simple constructor
235 
236 Creates a new download session
237 \param dm The download manager used to create the download session
238 \param url file to retrieve (no PUT/POST yet, only downloading is supported)
239 \param dl_flags combination of session download flags
240 \param user_io specifies \ref gf_dm_user_io callback function for data reception and service messages
241 \param usr_cbk opaque user data passed to callback function
242 \param e error for failure cases
243 \return the session object or NULL if error. If no error is indicated and a NULL session is returned, this means the file is local
244  */
245 GF_DownloadSession *gf_dm_sess_new_simple(GF_DownloadManager * dm, const char *url, u32 dl_flags,
246         gf_dm_user_io user_io,
247         void *usr_cbk,
248         GF_Err *e);
249 
250 /*!
251  \brief downloader session destructor
252 
253 Deletes the download session, cleaning the cache if indicated in the configuration file of the download manager (section "Downloader", key "CleanCache")
254 \param sess the download session
255 */
256 void gf_dm_sess_del(GF_DownloadSession * sess);
257 
258 /*!
259 \brief aborts downloading
260 
261 Aborts all operations in the session, regardless of its state. The session cannot be reused once this is called.
262 \param sess the download session
263  */
264 void gf_dm_sess_abort(GF_DownloadSession * sess);
265 
266 /*!
267 \brief gets last session error
268 
269 Gets the last error that occured in the session
270 \param sess the download session
271 \return the last error
272  */
273 GF_Err gf_dm_sess_last_error(GF_DownloadSession *sess);
274 
275 
276 /*!
277 \brief fetches data on session
278 
279 Fetches data from the server. This will also performs connections and all needed exchange with server.
280 \param sess the download session
281 \param buffer destination buffer
282 \param buffer_size destination buffer allocated size
283 \param read_size amount of data actually fetched
284 \note this can only be used when the session is not threaded
285 \return error if any
286  */
287 GF_Err gf_dm_sess_fetch_data(GF_DownloadSession * sess, char *buffer, u32 buffer_size, u32 *read_size);
288 
289 /*!
290 \brief get mime type as lower case
291 
292 Fetches the mime type of the URL this session is fetching, value will be returned lower case, so application/x-mpegURL will be returned as application/x-mpegurl
293 \param sess the download session
294 \return the mime type of the URL, or NULL if error. You should get the error with \ref gf_dm_sess_last_error
295  */
296 const char *gf_dm_sess_mime_type(GF_DownloadSession * sess);
297 
298 /*!
299 \brief sets session range
300 
301 Sets the session byte range. This shll be called before processing the session.
302 \param sess the download session
303 \param start_range HTTP download start range in byte
304 \param end_range HTTP download end range in byte
305 \param discontinue_cache If set, forces a new cache entry if byte range are not continuous. Otherwise a single cache entry is used to reconstruct the file
306 \note this can only be used when the session is not threaded
307 \return error if any
308  */
309 GF_Err gf_dm_sess_set_range(GF_DownloadSession *sess, u64 start_range, u64 end_range, Bool discontinue_cache);
310 /*!
311 \brief get cache file name
312 
313 Gets the cache file name for the session.
314 \param sess the download session
315 \return the absolute path of the cache file, or NULL if the session is not cached*/
316 const char *gf_dm_sess_get_cache_name(GF_DownloadSession * sess);
317 
318 /*!
319 \brief Marks the cache file to be deleted once the file is not used anymore by any session
320 \param dm the download manager
321 \param url The URL associate to the cache entry to be deleted
322  */
323 void gf_dm_delete_cached_file_entry(const GF_DownloadManager * dm, const char * url);
324 
325 /*!
326 Marks the cache file for this session to be deleted once the file is not used anymore by any session
327 \param sess the download session
328 \param url The URL associate to the cache entry to be deleted
329  */
330 void gf_dm_delete_cached_file_entry_session(const GF_DownloadSession * sess, const char * url);
331 
332 /*!
333 \brief get statistics
334 
335 Gets download statistics for the session. All output parameters are optional and may be set to NULL.
336 \param sess the download session
337 \param server the remote server address
338 \param path the path on the remote server
339 \param total_size the total size in bytes the file fetched, 0 if unknown.
340 \param bytes_done the amount of bytes received from the server
341 \param bytes_per_sec the average data rate in bytes per seconds
342 \param net_status the session status
343 \return error if any
344  */
345 GF_Err gf_dm_sess_get_stats(GF_DownloadSession * sess, const char **server, const char **path, u64 *total_size, u64 *bytes_done, u32 *bytes_per_sec, GF_NetIOStatus *net_status);
346 
347 /*!
348 \brief get start time
349 
350 Gets session start time in UTC. If chunk-transfer is used, the start time is reset at each chunk start
351 \param sess the download session
352 \return UTC start time
353  */
354 u64 gf_dm_sess_get_utc_start(GF_DownloadSession *sess);
355 
356 
357 /*!
358 \brief fetch session object
359 
360 Fetches the session object (process all headers and data transfer). This is only usable if the session is not threaded
361 \param sess the download session
362 \return the last error in the session or 0 if none*/
363 GF_Err gf_dm_sess_process(GF_DownloadSession *sess);
364 
365 /*!
366 \brief fetch session object headers
367 
368 Fetch the session object headers and stops after that. This is only usable if the session is not threaded
369 \param sess the download session
370 \return the last error in the session or 0 if none*/
371 GF_Err gf_dm_sess_process_headers(GF_DownloadSession * sess);
372 
373 /*!
374 \brief Get session resource url
375 
376 Returns the original resource URL associated with the session
377 \param sess the download session
378 \return the associated URL
379  */
380 const char *gf_dm_sess_get_resource_name(GF_DownloadSession *sess);
381 
382 #ifndef GPAC_DISABLE_CORE_TOOLS
383 /*!
384 Downloads a file over the network using a download manager
385 \param dm The download manager to use, function will use all associated cache ressources
386 \param url The url to download
387 \param filename The filename to download
388 \param start_range start position of a byte range
389 \param end_range end position of a byte range
390 \param redirected_url If not NULL, \p redirected_url will be allocated and filled with the URL after redirection. Caller takes ownership
391 \return GF_OK if everything went fine, an error otherwise
392  */
393 GF_Err gf_dm_wget_with_cache(GF_DownloadManager * dm, const char *url, const char *filename, u64 start_range, u64 end_range, char **redirected_url);
394 
395 /*!
396 \brief Same as gf_dm_wget_with_cache, but initializes the GF_DownloadManager by itself.
397 
398 This function is deprecated, please use gf_dm_wget_with_cache instead
399 \param url The url to download
400 \param filename The filename to download
401 \param start_range start position of a byte range
402 \param end_range end position of a byte range
403 \param redirected_url If not NULL, \p redirected_url will be allocated and filled with the URL after redirection. Caller takes ownership
404 \return GF_OK if everything went fine, an error otherwise
405  */
406 GF_Err gf_dm_wget(const char *url, const char *filename, u64 start_range, u64 end_range, char **redirected_url);
407 
408 #endif /* GPAC_DISABLE_CORE_TOOLS */
409 
410 /*!
411 Re-setup an existing, completed session to download a new URL. If same server/port/protocol is used, the same socket will be reused if the session has the GF_NETIO_SESSION_PERSISTENT flag set. This is only possible if the session is not threaded.
412 \param sess The session
413 \param url The new url for the session
414 \param allow_direct_reuse Allow reuse of cache entry without checking cache directives
415 \return GF_OK or error
416  */
417 GF_Err gf_dm_sess_setup_from_url(GF_DownloadSession *sess, const char *url, Bool allow_direct_reuse);
418 
419 /*!
420 \brief retrieves the HTTP header value for the given name
421 
422 Retrieves the HTTP header value for the given header name.
423 \param sess the current session
424 \param name the target header name
425 \return header value or NULL if not found
426  */
427 const char *gf_dm_sess_get_header(GF_DownloadSession *sess, const char *name);
428 
429 /*!
430 \brief enumerates the  HTTP headers for a session
431 
432 Retrieves the HTTP header name and value for the given header index.
433 \param sess the current session
434 \param idx index for the enumeration, must be initialized to 0 for the first call
435 \param hdr_name where name of header is stored - do not free
436 \param hdr_val where value of header is stored - do not free
437 \return error code, GF_OK or GF_EOS if no more headers
438  */
439 GF_Err gf_dm_sess_enum_headers(GF_DownloadSession *sess, u32 *idx, const char **hdr_name, const char **hdr_val);
440 
441 /*!
442 \brief sets download manager max rate per session
443 
444 Sets the maximum rate (per session only at the current time).
445 \param dm the download manager object
446 \param rate_in_bits_per_sec the new rate in bits per sec. If 0, HTTP rate will not be limited
447  */
448 void gf_dm_set_data_rate(GF_DownloadManager *dm, u32 rate_in_bits_per_sec);
449 
450 /*!
451 \brief gets download manager max rate per session
452 
453 Sets the maximum rate (per session only at the current time).
454 \param dm the download manager object
455 \return the rate in bits per sec. If 0, HTTP rate is not limited
456  */
457 u32 gf_dm_get_data_rate(GF_DownloadManager *dm);
458 
459 
460 /*!
461 \brief gets cumultaed download rate for all sessions
462 
463 Gets the cumultated bitrate in of all active sessions.
464 \param dm the download manager object
465 \return the cumulated rate in bits per sec.
466  */
467 u32 gf_dm_get_global_rate(GF_DownloadManager *dm);
468 
469 
470 /*!
471 \brief Get header sizes and times stats for the session
472 
473 Get header sizes and times stats for the session
474 \param sess the current session
475 \param req_hdr_size request header size in bytes. May be NULL.
476 \param rsp_hdr_size response header size in bytes. May be NULL.
477 \param connect_time connection time in micro seconds. May be NULL.
478 \param reply_time elapsed time between request sent and response header received, in micro seconds. May be NULL.
479 \param download_time download time since request sent, in micro seconds. May be NULL.
480 \return error code if any
481  */
482 GF_Err gf_dm_sess_get_header_sizes_and_times(GF_DownloadSession *sess, u32 *req_hdr_size, u32 *rsp_hdr_size, u32 *connect_time, u32 *reply_time, u32 *download_time);
483 
484 /*!
485 \brief Forces session to use memory storage
486 
487 Forces session to use memory storage for future downloads
488 \param sess the current session
489  */
490 void gf_dm_sess_force_memory_mode(GF_DownloadSession *sess);
491 
492 /*!
493 Registers a locacl cache provider (bypassing the http session), used when populating cache from input data (atsc for example)
494 
495 \param dm the download manager
496 \param local_cache_url_provider_cbk callback function to the cache provider. The callback function shall return GF_TRUE if the requested URL is provided by this local cache
497 \param lc_udta opaque pointer passed to the callback function
498 \return error code if any
499  */
500 GF_Err gf_dm_set_localcache_provider(GF_DownloadManager *dm, Bool (*local_cache_url_provider_cbk)(void *udta, char *url, Bool is_cache_destroy), void *lc_udta);
501 
502 /*!
503 Adds a local entry in the cache
504 
505 \param dm the download manager
506 \param szURL the URL this resource is caching
507 \param data data of the resource
508 \param size size of the resource
509 \param start_range start range of the data in the resource
510 \param end_range start range of the data in the resource. If both start_range and end_range are 0, the data is the complete resource
511 \param mime associated MIME type if any
512 \param clone_memory indicates that the data shall be cloned in the cache because the caller will discard it
513 \param download_time_ms indicates the download time of the associated resource, if known, 0 otherwise.
514 \return a cache entry structure
515  */
516 const DownloadedCacheEntry gf_dm_add_cache_entry(GF_DownloadManager *dm, const char *szURL, u8 *data, u64 size, u64 start_range, u64 end_range,  const char *mime, Bool clone_memory, u32 download_time_ms);
517 
518 /*!
519 Forces HTTP headers for a given cache entry
520 
521 \param dm the download manager
522 \param entry the cache entry to update
523 \param headers the header string, including CRLF delimiters, to force
524 \return error code if any
525 */
526 GF_Err gf_dm_force_headers(GF_DownloadManager *dm, const DownloadedCacheEntry entry, const char *headers);
527 
528 /*! HTTP methods*/
529 enum
530 {
531 	/*! unsupported*/
532 	GF_HTTP_UNKNOWN = 0,
533 	/*! GET*/
534 	GF_HTTP_GET,
535 	/*! HEAD*/
536 	GF_HTTP_HEAD,
537 	/*! OPTIONS*/
538 	GF_HTTP_OPTIONS,
539 	/*! CONNECT*/
540 	GF_HTTP_CONNECT,
541 	/*! TRACE*/
542 	GF_HTTP_TRACE,
543 	/*! PUT*/
544 	GF_HTTP_PUT,
545 	/*! POST*/
546 	GF_HTTP_POST,
547 	/*! DELETE*/
548 	GF_HTTP_DELETE
549 };
550 
551 /*! @} */
552 
553 #ifdef __cplusplus
554 }
555 #endif
556 
557 
558 #endif		/*_GF_DOWNLOAD_H_*/
559 
560