]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
IPTV: more improvements, leak fixes, better url parser for autonetwork
authorJaroslav Kysela <perex@perex.cz>
Wed, 14 Oct 2015 10:43:18 +0000 (12:43 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 14 Oct 2015 11:22:03 +0000 (13:22 +0200)
src/input/mpegts/iptv/iptv.c
src/input/mpegts/iptv/iptv_auto.c
src/input/mpegts/iptv/iptv_http.c
src/input/mpegts/iptv/iptv_mux.c
src/input/mpegts/iptv/iptv_private.h

index 46475a2128d5fd699668b3bcf339b2d3b068ff6b..695ae8fb66c8a563e8f2c524edff85888329cc87 100644 (file)
@@ -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,
index aa89685ea139ee8fa2d8f6669070b4660b173aba..0263ab2c1635c9329fd749da33f09a9f273fe116 100644 (file)
@@ -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);
+}
+
 /*
  *
  */
index 8ca7a566a67a248ef749a7ae416021424164c2c4..db228ee3490a82b5aec88c4b315546a6bba89d00 100644 (file)
@@ -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;
 }
index 4a90d017e86fa83db2d8e787a739febf32486e8f..8422e8a5b6d555df06038957db9f0c7a5af92bb6 100644 (file)
 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,
index 3a675bcfd5721bfcdfe70a35a39ec9c13c9d54d4..f1632b33122c774165d79a5e3c9ae3793e765650 100644 (file)
@@ -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 );