http_client_basic_auth(hc, h, url->user, url->pass);
}
+int
+http_client_simple_reconnect ( http_client_t *hc, const url_t *u )
+{
+ http_arg_list_t h;
+ tvhpoll_t *efd;
+ int r;
+
+ if (strcmp(u->scheme, hc->hc_scheme) ||
+ strcmp(u->host, hc->hc_host) ||
+ http_port(hc, u->scheme, u->port) != hc->hc_port ||
+ !hc->hc_keepalive) {
+ efd = hc->hc_efd;
+ http_client_shutdown(hc, 1, 1);
+ r = http_client_reconnect(hc, hc->hc_version,
+ u->scheme, u->host, u->port);
+ if (r < 0)
+ return r;
+ r = hc->hc_verify_peer;
+ hc->hc_verify_peer = -1;
+ http_client_ssl_peer_verify(hc, r);
+ hc->hc_efd = efd;
+ }
+
+ http_client_flush(hc, 0);
+
+ http_client_basic_args(hc, &h, u, hc->hc_keepalive);
+ hc->hc_reconnected = 1;
+ hc->hc_shutdown = 0;
+ hc->hc_pevents = 0;
+
+ r = http_client_send(hc, hc->hc_cmd, u->path, u->query, &h, NULL, 0);
+ if (r < 0)
+ return r;
+
+ hc->hc_reconnected = 1;
+ return HTTP_CON_RECEIVING;
+}
+
static int
http_client_redirected ( http_client_t *hc )
{
char *location, *location2;
- http_arg_list_t h;
- tvhpoll_t *efd;
url_t u;
int r;
}
free(location);
- if (strcmp(u.scheme, hc->hc_scheme) ||
- strcmp(u.host, hc->hc_host) ||
- http_port(hc, u.scheme, u.port) != hc->hc_port ||
- !hc->hc_keepalive) {
- efd = hc->hc_efd;
- http_client_shutdown(hc, 1, 1);
- r = http_client_reconnect(hc, hc->hc_version,
- u.scheme, u.host, u.port);
- if (r < 0) {
- urlreset(&u);
- return r;
- }
- r = hc->hc_verify_peer;
- hc->hc_verify_peer = -1;
- http_client_ssl_peer_verify(hc, r);
- hc->hc_efd = efd;
- }
-
- http_client_flush(hc, 0);
+ r = http_client_simple_reconnect(hc, &u);
- http_client_basic_args(hc, &h, &u, hc->hc_keepalive);
- hc->hc_reconnected = 1;
- hc->hc_shutdown = 0;
- hc->hc_pevents = 0;
-
- r = http_client_send(hc, hc->hc_cmd, u.path, u.query, &h, NULL, 0);
- if (r < 0) {
- urlreset(&u);
- return r;
- }
-
- hc->hc_reconnected = 1;
urlreset(&u);
- return 1;
+ return r;
}
int
#include "iptv_private.h"
#include "http.h"
+/*
+ * M3U parser
+ */
+static char *
+iptv_http_m3u(char *data)
+{
+ char *url;
+
+ while (*data && *data != '\n') data++;
+ if (*data) data++;
+ while (*data) {
+ if (strncmp(data, "#EXTINF:", 8) == 0) {
+ while (*data && *data != '\n') data++;
+ if (*data) { *data = '\0'; data++; }
+ continue;
+ }
+ while (*data && *data <= ' ') data++;
+ url = data;
+ while (*data && *data != '\n') data++;
+ if (*data) { *data = '\0'; data++; }
+ if (*url)
+ return strdup(url);
+ }
+ return NULL;
+}
+
/*
* Connected
*/
static int
iptv_http_header ( http_client_t *hc )
{
+ iptv_mux_t *im = hc->hc_aux;
+ char *argv[3], *s;
+ int n;
+
if (hc->hc_aux == NULL)
return 0;
/* multiple headers for redirections */
- if (hc->hc_code == HTTP_STATUS_OK) {
- pthread_mutex_lock(&global_lock);
- iptv_input_mux_started(hc->hc_aux);
- pthread_mutex_unlock(&global_lock);
+ if (hc->hc_code != HTTP_STATUS_OK)
+ return 0;
+
+ 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)) {
+ if (im->im_m3u_header > 10) {
+ im->im_m3u_header = 0;
+ return 0;
+ }
+ im->im_m3u_header++;
+ return 0;
+ }
}
+
+ im->im_m3u_header = 0;
+ pthread_mutex_lock(&global_lock);
+ iptv_input_mux_started(hc->hc_aux);
+ pthread_mutex_unlock(&global_lock);
return 0;
}
{
iptv_mux_t *im = hc->hc_aux;
- if (im == NULL)
+ if (im == NULL || hc->hc_code != HTTP_STATUS_OK)
+ return 0;
+
+ if (im->im_m3u_header) {
+ sbuf_append(&im->mm_iptv_buffer, buf, len);
return 0;
+ }
pthread_mutex_lock(&iptv_lock);
- tsdebug_write((mpegts_mux_t *)im, buf, len);
sbuf_append(&im->mm_iptv_buffer, buf, len);
+ tsdebug_write((mpegts_mux_t *)im, buf, len);
if (len > 0)
iptv_input_recv_packets(im, len);
return 0;
}
+/*
+ * Complete data
+ */
+static int
+iptv_http_complete
+ ( http_client_t *hc )
+{
+ iptv_mux_t *im = hc->hc_aux;
+ char *url;
+ url_t u;
+ int r;
+
+ if (im->im_m3u_header) {
+ im->im_m3u_header = 0;
+ sbuf_append(&im->mm_iptv_buffer, "", 1);
+ url = iptv_http_m3u((char *)im->mm_iptv_buffer.sb_data);
+ if (url == NULL) {
+ tvherror("iptv", "m3u contents parsing failed");
+ return 0;
+ }
+ memset(&u, 0, sizeof(u));
+ if (!urlparse(url, &u)) {
+ hc->hc_keepalive = 0;
+ r = http_client_simple_reconnect(hc, &u);
+ if (r < 0)
+ tvherror("iptv", "cannot reopen http client: %d'", r);
+ } else {
+ tvherror("iptv", "m3u url invalid '%s'", url);
+ }
+ free(url);
+ return 0;
+ }
+ return 0;
+}
+
/*
* Setup HTTP(S) connection
*/
return SM_CODE_TUNING_FAILED;
hc->hc_hdr_received = iptv_http_header;
hc->hc_data_received = iptv_http_data;
+ hc->hc_data_complete = iptv_http_complete;
hc->hc_handle_location = 1; /* allow redirects */
hc->hc_io_size = 128*1024; /* increase buffering */
http_client_register(hc); /* register to the HTTP thread */