Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
IPTV: add basic m3u parser, fixes #3106
  • Loading branch information
perexg committed Oct 13, 2015
1 parent f59798d commit 9f21e59
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 41 deletions.
1 change: 1 addition & 0 deletions src/http.h
Expand Up @@ -358,6 +358,7 @@ int http_client_send( http_client_t *hc, http_cmd_t cmd,
http_arg_list_t *header, void *body, size_t body_size );
void http_client_basic_auth( http_client_t *hc, http_arg_list_t *h,
const char *user, const char *pass );
int http_client_simple_reconnect ( http_client_t *hc, const url_t *u );
int http_client_simple( http_client_t *hc, const url_t *url);
int http_client_clear_state( http_client_t *hc );
int http_client_run( http_client_t *hc );
Expand Down
74 changes: 40 additions & 34 deletions src/httpc.c
Expand Up @@ -1140,12 +1140,48 @@ http_client_basic_args ( http_client_t *hc, http_arg_list_t *h, const url_t *url
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;

Expand All @@ -1172,40 +1208,10 @@ http_client_redirected ( http_client_t *hc )
}
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
Expand Down
101 changes: 95 additions & 6 deletions src/input/mpegts/iptv/iptv_http.c
Expand Up @@ -21,21 +21,69 @@
#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;
}

Expand All @@ -48,13 +96,18 @@ iptv_http_data
{
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);
Expand All @@ -64,6 +117,41 @@ iptv_http_data
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
*/
Expand All @@ -79,6 +167,7 @@ iptv_http_start
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 */
Expand Down
2 changes: 1 addition & 1 deletion src/input/mpegts/iptv/iptv_private.h
Expand Up @@ -130,7 +130,7 @@ struct iptv_mux
void *im_data;

int im_delete_flag;

int im_m3u_header;
};

iptv_mux_t* iptv_mux_create0
Expand Down

0 comments on commit 9f21e59

Please sign in to comment.