static char *get_mime_type(GF_Terminal *term, const char *url, GF_Err *ret_code, GF_DownloadSession **the_session) { char * ret = NULL; GF_DownloadSession * sess; (*ret_code) = GF_OK; if (strnicmp(url, "http", 4)) return NULL; /*don't use any NetIO and don't issue a HEAD command, always go for GET and store the session */ sess = gf_dm_sess_new(term->downloader, (char *) url, GF_NETIO_SESSION_NOT_THREADED | GF_NETIO_SESSION_NOT_CACHED, NULL, NULL, ret_code); if (!sess) { if (strstr(url, "rtsp://") || strstr(url, "rtp://") || strstr(url, "udp://") || strstr(url, "tcp://") ) (*ret_code) = GF_OK; return NULL; } else { /*start processing the resource, and stop if error or as soon as we get data*/ while (1) { *ret_code = gf_dm_sess_process_headers(sess); if (*ret_code) break; if (gf_dm_sess_get_status(sess)>=GF_NETIO_DATA_EXCHANGE) { const char * mime = gf_dm_sess_mime_type(sess); /* The mime type is returned lower case */ if (mime){ ret = gf_strdup(mime); } break; } } } if (the_session && (*ret_code == GF_OK)) { *the_session = sess; } else { gf_dm_sess_del(sess); } return ret; }
void gf_term_delete_net_service(GF_ClientService *ns) { const char *sOpt = gf_cfg_get_key(ns->term->user->config, "StreamingCache", "AutoSave"); if (ns->cache) gf_term_service_cache_close(ns, (sOpt && !stricmp(sOpt, "yes")) ? 1 : 0); if (ns->pending_service_session) gf_dm_sess_del(ns->pending_service_session); assert(!ns->nb_odm_users); assert(!ns->nb_ch_users); assert(!ns->owner); gf_modules_close_interface((GF_BaseInterface *)ns->ifce); gf_free(ns->url); /*delete all the clocks*/ while (gf_list_count(ns->Clocks)) { GF_Clock *ck = (GF_Clock *)gf_list_get(ns->Clocks, 0); gf_list_rem(ns->Clocks, 0); gf_clock_del(ck); } gf_list_del(ns->Clocks); assert(!gf_list_count(ns->dnloads)); gf_list_del(ns->dnloads); gf_free(ns); }
void gf_term_service_del(GF_ClientService *ns) { /*this is a downloader session*/ if (! * (u32 *) ns) { gf_dm_sess_del((GF_DownloadSession * ) ns); } else { gf_term_delete_net_service(ns); } }
void gf_dm_del(GF_DownloadManager *dm) { /*destroy all pending sessions*/ while (gf_list_count(dm->sessions)) { GF_DownloadSession *sess = (GF_DownloadSession *) gf_list_get(dm->sessions, 0); gf_dm_sess_del(sess); } gf_list_del(dm->sessions); free(dm->cache_directory); #ifdef GPAC_HAS_SSL if (dm->ssl_ctx) SSL_CTX_free(dm->ssl_ctx); #endif free(dm); }
GF_DownloadSession *gf_dm_sess_new(GF_DownloadManager *dm, char *url, u32 dl_flags, gf_dm_user_io user_io, void *usr_cbk, GF_Err *e) { GF_DownloadSession *sess; *e = GF_OK; if (gf_dm_is_local(dm, url)) return NULL; if (!gf_dm_can_handle_url(dm, url)) { *e = GF_NOT_SUPPORTED; return NULL; } if (!user_io) { *e = GF_BAD_PARAM; return NULL; } sess = (GF_DownloadSession *)malloc(sizeof(GF_DownloadSession)); memset((void *)sess, 0, sizeof(GF_DownloadSession)); sess->flags = dl_flags; sess->user_proc = user_io; sess->usr_cbk = usr_cbk; sess->dm = dm; gf_list_add(dm->sessions, sess); *e = gf_dm_setup_from_url(sess, url); if (*e) { gf_dm_sess_del(sess); return NULL; } if (!(sess->flags & GF_NETIO_SESSION_NOT_THREADED) ) { sess->th = gf_th_new(); sess->mx = gf_mx_new(); gf_th_run(sess->th, gf_dm_session_thread, sess); } sess->num_retry = SESSION_RETRY_COUNT; return sess; }
static GF_InputService *gf_term_can_handle_service(GF_Terminal *term, const char *url, const char *parent_url, Bool no_mime_check, char **out_url, GF_Err *ret_code, GF_DownloadSession **the_session) { u32 i; GF_Err e; char *sURL, *qm, *frag, *ext, *mime_type, *url_res; char szExt[50]; const char *force_module = NULL; GF_InputService *ifce; Bool skip_mime = 0; memset(szExt, 0, sizeof(szExt)); (*ret_code) = GF_OK; ifce = NULL; mime_type = NULL; GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Looking for plugin for URL %s\n", url)); *out_url = NULL; sURL = NULL; if (!url || !strncmp(url, "\\\\", 2) ) { (*ret_code) = GF_URL_ERROR; goto exit; } if (!strnicmp(url, "libplayer://", 12)) { force_module = "LibPlayer"; } /*used by GUIs scripts to skip URL concatenation*/ if (!strncmp(url, "gpac://", 7)) sURL = gf_strdup(url+7); /*opera-style localhost URLs*/ else if (!strncmp(url, "file://localhost", 16)) sURL = gf_strdup(url+16); else if (parent_url) sURL = gf_url_concatenate(parent_url, url); /*path absolute*/ if (!sURL) sURL = gf_strdup(url); if (gf_url_is_local(sURL)) gf_url_to_fs_path(sURL); if (the_session) *the_session = NULL; if (no_mime_check) { mime_type = NULL; } else { /*fetch a mime type if any. If error don't even attempt to open the service TRYTOFIXME: it would be nice to reuse the downloader created while fetching the mime type, however we don't know if the plugin will want it threaded or not.... */ mime_type = get_mime_type(term, sURL, &e, the_session); if (e) { (*ret_code) = e; goto exit; } } if (mime_type && (!stricmp(mime_type, "text/plain") || !stricmp(mime_type, "video/quicktime") || !stricmp(mime_type, "application/octet-stream") ) ) { skip_mime = 1; } ifce = NULL; /*load from mime type*/ if (mime_type && !skip_mime) { const char *sPlug = gf_cfg_get_key(term->user->config, "MimeTypes", mime_type); GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Mime type found: %s\n", mime_type)); if (!sPlug) { gf_free(mime_type); mime_type=NULL; } if (sPlug) sPlug = strrchr(sPlug, '"'); if (sPlug) { sPlug += 2; GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("%s:%d FOUND matching module %s\n", __FILE__, __LINE__, sPlug)); ifce = (GF_InputService *) gf_modules_load_interface_by_name(term->user->modules, sPlug, GF_NET_CLIENT_INTERFACE); if (force_module && ifce && !strstr(ifce->module_name, force_module)) { gf_modules_close_interface((GF_BaseInterface *) ifce); ifce = NULL; } if (ifce && !net_check_interface(ifce) ) { gf_modules_close_interface((GF_BaseInterface *) ifce); ifce = NULL; } } } /* The file extension, if any, is before '?' if any or before '#' if any.*/ url_res = strrchr(sURL, '/'); if (!url_res) url_res = strrchr(sURL, '\\'); if (!url_res) url_res = sURL; qm = strchr(url_res, '?'); if (qm) { qm[0] = 0; ext = strrchr(url_res, '.'); qm[0] = '?'; } else { frag = strchr(url_res, '#'); if (frag) { frag[0] = 0; ext = strrchr(url_res, '.'); frag[0] = '#'; } else { ext = strrchr(url_res, '.'); } } if (ext && !stricmp(ext, ".gz")) { char *anext; ext[0] = 0; anext = strrchr(sURL, '.'); ext[0] = '.'; ext = anext; } /*no mime type: either local or streaming. If streaming discard extension checking*/ if (!ifce && !mime_type && strstr(sURL, "://") && strnicmp(sURL, "file://", 7)) ext = NULL; /*browse extensions for prefered module*/ if (!ifce && ext) { u32 keyCount; strncpy(szExt, &ext[1], 49); ext = strrchr(szExt, '?'); if (ext) ext[0] = 0; ext = strrchr(szExt, '#'); if (ext) ext[0] = 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] No mime type found - checking by extension %s\n", szExt)); assert( term && term->user && term->user->modules); keyCount = gf_cfg_get_key_count(term->user->config, "MimeTypes"); for (i=0; i<keyCount; i++) { char *sPlug; const char *sKey; const char *sMime; sMime = gf_cfg_get_key_name(term->user->config, "MimeTypes", i); if (!sMime) continue; sKey = gf_cfg_get_key(term->user->config, "MimeTypes", sMime); if (!sKey) continue; if (!check_extension(sKey, szExt)) continue; sPlug = strrchr(sKey, '"'); if (!sPlug) continue; /*bad format entry*/ sPlug += 2; GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Trying module[%i]=%s, mime=%s\n", i, sPlug, sMime)); ifce = (GF_InputService *) gf_modules_load_interface_by_name(term->user->modules, sPlug, GF_NET_CLIENT_INTERFACE); if (!ifce){ GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] module[%i]=%s, mime=%s, cannot be loaded for GF_NET_CLIENT_INTERFACE.\n", i, sPlug, sMime)); continue; } if (force_module && ifce && !strstr(ifce->module_name, force_module)) { gf_modules_close_interface((GF_BaseInterface *) ifce); ifce = NULL; continue; } if (ifce && !net_check_interface(ifce)) { gf_modules_close_interface((GF_BaseInterface *) ifce); ifce = NULL; continue; } break; } } /*browse all modules*/ if (!ifce) { GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Not found any interface, trying browsing all modules...\n")); for (i=0; i< gf_modules_get_count(term->user->modules); i++) { ifce = (GF_InputService *) gf_modules_load_interface(term->user->modules, i, GF_NET_CLIENT_INTERFACE); if (!ifce) continue; GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Checking if module %s supports URL %s\n", ifce->module_name, sURL)); if (force_module && ifce && !strstr(ifce->module_name, force_module)) { } else if (net_check_interface(ifce) && ifce->CanHandleURL(ifce, sURL)) { break; } gf_modules_close_interface((GF_BaseInterface *) ifce); ifce = NULL; } } exit: if (!ifce){ GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Terminal] Did not find any input plugin for URL %s (%s)\n", sURL ? sURL : url, mime_type ? mime_type : "no mime type")); if (sURL) gf_free(sURL); if ( (*ret_code) == GF_OK) (*ret_code) = GF_NOT_SUPPORTED; *out_url = NULL; if (the_session && *the_session) { gf_dm_sess_del(*the_session); } } else { *out_url = sURL; GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[Terminal] Found input plugin %s for URL %s (%s)\n", ifce->module_name, sURL, mime_type ? mime_type : "no mime type")); } if (mime_type) gf_free(mime_type); mime_type = NULL; return ifce; }