From: Jaroslav Kysela Date: Wed, 14 Oct 2015 10:43:18 +0000 (+0200) Subject: IPTV: more improvements, leak fixes, better url parser for autonetwork X-Git-Tag: v4.2.1~1919 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=316edf195850a0c817c3ed87634d155bcffb5164;p=thirdparty%2Ftvheadend.git IPTV: more improvements, leak fixes, better url parser for autonetwork --- diff --git a/src/input/mpegts/iptv/iptv.c b/src/input/mpegts/iptv/iptv.c index 46475a212..695ae8fb6 100644 --- a/src/input/mpegts/iptv/iptv.c +++ b/src/input/mpegts/iptv/iptv.c @@ -464,8 +464,7 @@ void iptv_input_mux_started ( iptv_mux_t *im ) { /* Allocate input buffer */ - sbuf_init_fixed(&im->mm_iptv_buffer, IPTV_BUF_SIZE); - im->mm_iptv_rtp_seq = -1; + sbuf_reset_and_alloc(&im->mm_iptv_buffer, IPTV_BUF_SIZE); if (iptv_input_fd_started(im)) return; @@ -481,7 +480,8 @@ static void iptv_network_delete ( mpegts_network_t *mn, int delconf ) { iptv_network_t *in = (iptv_network_t*)mn; - char *s = in->in_url; + char *url = in->in_url; + char *sane_url = in->in_url_sane; if (in->mn_id.in_class == &iptv_auto_network_class) iptv_auto_network_done(in); @@ -495,7 +495,8 @@ iptv_network_delete ( mpegts_network_t *mn, int delconf ) free(in->in_remove_args); mpegts_network_delete(mn, delconf); - free(s); + free(sane_url); + free(url); } /* ************************************************************************** @@ -556,6 +557,19 @@ const idclass_t iptv_network_class = { } }; +static int +iptv_auto_network_class_url_set( void *in, const void *v ) +{ + iptv_network_t *mn = in; + return iptv_url_set(&mn->in_url, &mn->in_url_sane, v, 1, 0); +} + +static void +iptv_auto_network_class_notify_url( void *in, const char *lang ) +{ + iptv_auto_network_trigger(in); +} + const idclass_t iptv_auto_network_class = { .ic_super = &iptv_network_class, .ic_class = "iptv_auto_network", @@ -566,6 +580,9 @@ const idclass_t iptv_auto_network_class = { .id = "url", .name = N_("URL"), .off = offsetof(iptv_network_t, in_url), + .set = iptv_auto_network_class_url_set, + .notify = iptv_auto_network_class_notify_url, + .opts = PO_MULTILINE }, { .type = PT_S64, diff --git a/src/input/mpegts/iptv/iptv_auto.c b/src/input/mpegts/iptv/iptv_auto.c index aa89685ea..0263ab2c1 100644 --- a/src/input/mpegts/iptv/iptv_auto.c +++ b/src/input/mpegts/iptv/iptv_auto.c @@ -369,9 +369,12 @@ iptv_auto_network_fetch(void *aux) memset(&u, 0, sizeof(u)); + if (in->in_url == NULL) + goto done; + if (strncmp(in->in_url, "file://", 7) == 0) { iptv_auto_network_file(in, in->in_url + 7); - goto arm; + goto done; } gtimer_disarm(&in->in_auto_timer); @@ -382,12 +385,12 @@ iptv_auto_network_fetch(void *aux) if (urlparse(in->in_url, &u) < 0) { tvherror("iptv", "wrong url for network '%s'", in->mn_network_name); - goto arm; + goto done; } hc = http_client_connect(in, HTTP_VERSION_1_1, u.scheme, u.host, u.port, NULL); if (hc == NULL) { tvherror("iptv", "unable to open http client for network '%s'", in->mn_network_name); - goto arm; + goto done; } hc->hc_handle_location = 1; hc->hc_data_limit = 1024*1024; @@ -397,26 +400,35 @@ iptv_auto_network_fetch(void *aux) if (http_client_simple(hc, &u) < 0) { http_client_close(hc); tvherror("iptv", "unable to send http command for network '%s'", in->mn_network_name); - goto arm; + goto done; } in->in_http_client = hc; -arm: - urlreset(&u); gtimer_arm(&in->in_auto_timer, iptv_auto_network_fetch, in, MAX(1, in->in_refetch_period) * 60); +done: + urlreset(&u); } /* * */ void -iptv_auto_network_init( iptv_network_t *in ) +iptv_auto_network_trigger( iptv_network_t *in ) { gtimer_arm(&in->in_auto_timer, iptv_auto_network_fetch, in, 0); } +/* + * + */ +void +iptv_auto_network_init( iptv_network_t *in ) +{ + iptv_auto_network_trigger(in); +} + /* * */ diff --git a/src/input/mpegts/iptv/iptv_http.c b/src/input/mpegts/iptv/iptv_http.c index 8ca7a566a..db228ee34 100644 --- a/src/input/mpegts/iptv/iptv_http.c +++ b/src/input/mpegts/iptv/iptv_http.c @@ -67,10 +67,11 @@ iptv_http_header ( http_client_t *hc ) s = http_arg_get(&hc->hc_args, "Content-Type"); if (s) { n = http_tokenize(s, argv, ARRAY_SIZE(argv), ';'); - printf("mime: '%s'\n", s); if (n > 0 && (strcasecmp(s, "audio/mpegurl") == 0 || - strcasecmp(s, "audio/x-mpegurl") == 0)) { + strcasecmp(s, "audio/x-mpegurl") == 0 || + strcasecmp(s, "application/apple.vnd.mpegurl") == 0 || + strcasecmp(s, "application/vnd.apple.mpegurl") == 0)) { if (im->im_m3u_header > 10) { im->im_m3u_header = 0; return 0; @@ -133,6 +134,7 @@ iptv_http_complete im->im_m3u_header = 0; sbuf_append(&im->mm_iptv_buffer, "", 1); url = iptv_http_m3u((char *)im->mm_iptv_buffer.sb_data); + sbuf_reset(&im->mm_iptv_buffer, IPTV_BUF_SIZE); if (url == NULL) { tvherror("iptv", "m3u contents parsing failed"); return 0; @@ -178,6 +180,7 @@ iptv_http_start return SM_CODE_TUNING_FAILED; } im->im_data = hc; + sbuf_init_fixed(&im->mm_iptv_buffer, IPTV_BUF_SIZE); return 0; } diff --git a/src/input/mpegts/iptv/iptv_mux.c b/src/input/mpegts/iptv/iptv_mux.c index 4a90d017e..8422e8a5b 100644 --- a/src/input/mpegts/iptv/iptv_mux.c +++ b/src/input/mpegts/iptv/iptv_mux.c @@ -27,65 +27,73 @@ extern const idclass_t mpegts_mux_class; extern const idclass_t mpegts_mux_instance_class; -static int -iptv_mux_url_set ( void *p, const void *v ) +static inline void +iptv_url_set0 ( char **url, char **sane_url, + const char *url1, const char *sane_url1 ) { - iptv_mux_t *im = p; - const char *str = v, *x; + free(*url); + free(*sane_url); + *url = url1 ? strdup(url1) : NULL; + *sane_url = sane_url1 ? strdup(sane_url1) : NULL; +} + +int +iptv_url_set ( char **url, char **sane_url, const char *str, int allow_file, int allow_pipe ) +{ + const char *x; char *buf, port[16] = ""; size_t len; - url_t url; + url_t u; - if (strcmp(str ?: "", im->mm_iptv_url ?: "")) { - if (str == NULL || *str == '\0') { - free(im->mm_iptv_url); - free(im->mm_iptv_url_sane); - im->mm_iptv_url = NULL; - im->mm_iptv_url_sane = NULL; - return 1; - } - if (!strncmp(str, "pipe://", 7)) { - x = str + strlen(str); - while (x != str && *x <= ' ') - x--; - ((char *)x)[1] = '\0'; - free(im->mm_iptv_url); - free(im->mm_iptv_url_sane); - im->mm_iptv_url = strdup(str); - im->mm_iptv_url_sane = strdup(str); - return 1; - } - memset(&url, 0, sizeof(url)); - if (!urlparse(str, &url)) { - free(im->mm_iptv_url); - free(im->mm_iptv_url_sane); - im->mm_iptv_url = strdup(str); - if (im->mm_iptv_url) { - len = (url.scheme ? strlen(url.scheme) + 3 : 0) + - (url.host ? strlen(url.host) + 1 : 0) + - /* port */ 16 + - (url.path ? strlen(url.path) + 1 : 0) + - (url.query ? strlen(url.query) + 2 : 0); - buf = alloca(len); - if (url.port > 0 && url.port <= 65535) - snprintf(port, sizeof(port), ":%d", url.port); - snprintf(buf, len, "%s%s%s%s%s%s%s", - url.scheme ?: "", url.scheme ? "://" : "", - url.host ?: "", port, - url.path ?: "", url.query ? "?" : "", - url.query ?: ""); - im->mm_iptv_url_sane = strdup(buf); - } else { - im->mm_iptv_url_sane = NULL; - } - urlreset(&url); - return 1; - } - urlreset(&url); + if (strcmp(str ?: "", *url ?: "") == 0) + return 0; + + if (str == NULL || *str == '\0') { + iptv_url_set0(url, sane_url, NULL, NULL); + return 1; + } + if (allow_file && !strncmp(str, "file://", 7)) { + iptv_url_set0(url, sane_url, str, str); + return 1; } + if (allow_pipe && !strncmp(str, "pipe://", 7)) { + x = str + strlen(str); + while (x != str && *x <= ' ') + x--; + ((char *)x)[1] = '\0'; + iptv_url_set0(url, sane_url, str, str); + return 1; + } + memset(&u, 0, sizeof(u)); + if (!urlparse(str, &u)) { + len = (u.scheme ? strlen(u.scheme) + 3 : 0) + + (u.host ? strlen(u.host) + 1 : 0) + + /* port */ 16 + + (u.path ? strlen(u.path) + 1 : 0) + + (u.query ? strlen(u.query) + 2 : 0); + buf = alloca(len); + if (u.port > 0 && u.port <= 65535) + snprintf(port, sizeof(port), ":%d", u.port); + snprintf(buf, len, "%s%s%s%s%s%s%s", + u.scheme ?: "", u.scheme ? "://" : "", + u.host ?: "", port, + u.path ?: "", (u.query && u.query[0]) ? "?" : "", + u.query ?: ""); + iptv_url_set0(url, sane_url, str, buf); + urlreset(&u); + return 1; + } + return 0; } +static int +iptv_mux_url_set ( void *p, const void *v ) +{ + iptv_mux_t *im = p; + return iptv_url_set(&im->mm_iptv_url, &im->mm_iptv_url_sane, v, 0, 1); +} + static htsmsg_t * iptv_muxdvr_class_kill_list ( void *o, const char *lang ) { @@ -276,6 +284,8 @@ iptv_mux_create0 ( iptv_network_t *in, const char *uuid, htsmsg_t *conf ) if (!im->mm_iptv_kill_timeout) im->mm_iptv_kill_timeout = 5; + sbuf_init(&im->mm_iptv_buffer); + /* Create Instance */ (void)mpegts_mux_instance_create(mpegts_mux_instance, NULL, (mpegts_input_t*)iptv_input, diff --git a/src/input/mpegts/iptv/iptv_private.h b/src/input/mpegts/iptv/iptv_private.h index 3a675bcfd..f1632b331 100644 --- a/src/input/mpegts/iptv/iptv_private.h +++ b/src/input/mpegts/iptv/iptv_private.h @@ -82,6 +82,7 @@ struct iptv_network uint32_t in_max_timeout; char *in_url; + char *in_url_sane; int64_t in_channel_number; uint32_t in_refetch_period; int in_ssl_peer_verify; @@ -152,8 +153,11 @@ extern const idclass_t iptv_auto_network_class; extern iptv_input_t *iptv_input; extern iptv_network_t *iptv_network; +int iptv_url_set ( char **url, char **sane_url, const char *str, int allow_file, int allow_pipe ); + void iptv_mux_load_all ( void ); +void iptv_auto_network_trigger( iptv_network_t *in ); void iptv_auto_network_init( iptv_network_t *in ); void iptv_auto_network_done( iptv_network_t *in );