/* * 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); sbuf_reset(&im->mm_iptv_buffer, IPTV_BUF_SIZE); if (url == NULL) { tvherror("iptv", "m3u contents parsing failed"); return 0; } urlinit(&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); } urlreset(&u); free(url); return 0; } return 0; }
static void download_fetch(void *aux) { download_t *dn = aux; http_client_t *hc; url_t u; urlinit(&u); if (dn->url == NULL) goto done; if (strncmp(dn->url, "file://", 7) == 0) { download_file(dn, dn->url + 7); goto done; } if (strncmp(dn->url, "pipe://", 7) == 0) { download_pipe(dn, dn->url + 7); goto done; } if (dn->http_client) { http_client_close(dn->http_client); dn->http_client = NULL; } if (urlparse(dn->url, &u) < 0) { tvherror(dn->log, "wrong url"); goto stop; } hc = http_client_connect(dn, HTTP_VERSION_1_1, u.scheme, u.host, u.port, NULL); if (hc == NULL) { tvherror(dn->log, "unable to open http client"); goto stop; } hc->hc_handle_location = 1; hc->hc_data_limit = 1024*1024; hc->hc_data_complete = download_fetch_complete; http_client_register(hc); http_client_ssl_peer_verify(hc, dn->ssl_peer_verify); if (http_client_simple(hc, &u) < 0) { http_client_close(hc); tvherror(dn->log, "unable to send http command"); goto stop; } dn->http_client = hc; goto done; stop: if (dn->stop) dn->stop(dn->aux); done: urlreset(&u); }
/* * Complete data */ static int iptv_http_complete ( http_client_t *hc ) { iptv_mux_t *im = hc->hc_aux; char *url, *url2, *s, *p; 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); sbuf_reset(&im->mm_iptv_buffer, IPTV_BUF_SIZE); if (url == NULL) { tvherror("iptv", "m3u contents parsing failed"); return 0; } urlinit(&u); if (url[0] == '/') { s = strdupa(im->mm_iptv_url_raw); if ((p = strchr(s, '/')) != NULL) *p = '\0'; if (!urlparse(s, &u)) goto invalid; url2 = malloc(512); url2[0] = '\0'; if ((p = http_arg_get(&hc->hc_args, "Host")) != NULL) { snprintf(url2, 512, "%s://%s%s", hc->hc_ssl ? "https" : "http", p, url); } else if (im->mm_iptv_url_raw) { snprintf(url2, 512, "%s%s", s, url); } free(url); url = url2; urlinit(&u); } if (!urlparse(url, &u)) { hc->hc_keepalive = 0; r = http_client_simple_reconnect(hc, &u, HTTP_VERSION_1_1); if (r < 0) tvherror("iptv", "cannot reopen http client: %d'", r); } else { invalid: tvherror("iptv", "m3u url invalid '%s'", url); } urlreset(&u); free(url); return 0; } return 0; }
int urlparse ( const char *str, url_t *url ) { regmatch_t m[16]; char buf[16]; if (str == NULL || url == NULL) return -1; urlreset(url); /* Create regexp */ if (!urlparse_exp) { urlparse_exp = calloc(1, sizeof(regex_t)); if (regcomp(urlparse_exp, URL_RE, REG_ICASE | REG_EXTENDED)) { tvherror("url", "failed to compile regexp"); exit(1); } } /* Execute */ if (regexec(urlparse_exp, str, ARRAY_SIZE(m), m, 0)) return -1; /* Extract data */ #define copy(x, i)\ {\ x = strndup(str+m[i].rm_so, m[i].rm_eo - m[i].rm_so);\ }(void)0 #define copy_static(x, i)\ {\ int len = m[i].rm_eo - m[i].rm_so;\ if (len >= sizeof(x) - 1)\ len = sizeof(x) - 1;\ memcpy(x, str+m[i].rm_so, len);\ x[len] = 0;\ }(void)0 copy(url->scheme, 1); copy(url->user, 3); copy(url->pass, 5); copy(url->host, 6); copy(url->path, 9); copy_static(buf, 8); url->port = atoi(buf); copy(url->query, 11); copy(url->frag, 13); url->raw = strdup(str); return 0; }
static int download_fetch_complete(http_client_t *hc) { download_t *dn = hc->hc_aux; const char *last_url = NULL; url_t u; switch (hc->hc_code) { case HTTP_STATUS_MOVED: case HTTP_STATUS_FOUND: case HTTP_STATUS_SEE_OTHER: case HTTP_STATUS_NOT_MODIFIED: return 0; } urlinit(&u); if (!urlparse(dn->url, &u)) { last_url = strrchr(u.path, '/'); if (last_url) last_url++; } pthread_mutex_lock(&global_lock); if (dn->http_client == NULL) goto out; if (hc->hc_code == HTTP_STATUS_OK && hc->hc_result == 0 && hc->hc_data_size > 0) dn->process(dn->aux, last_url, hc->hc_url, hc->hc_data, hc->hc_data_size); else tvherror(dn->log, "unable to fetch data from url [%d-%d/%zd]", hc->hc_code, hc->hc_result, hc->hc_data_size); /* note: http_client_close must be called outside http_client callbacks */ gtimer_arm(&dn->fetch_timer, download_fetch_done, hc, 0); out: pthread_mutex_unlock(&global_lock); urlreset(&u); return 0; }
static void satip_discovery_destroy(satip_discovery_t *d, int unlink) { if (d == NULL) return; if (unlink) { satip_discoveries_count--; TAILQ_REMOVE(&satip_discoveries, d, disc_link); } if (d->http_client) http_client_close(d->http_client); urlreset(&d->url); free(d->myaddr); free(d->location); free(d->server); free(d->uuid); free(d->bootid); free(d->configid); free(d->deviceid); free(d); }
int urlparse ( const char *str, url_t *url ) { UriParserStateA state; UriPathSegmentA *path; UriUriA uri; char *s, buf[256]; if (str == NULL || url == NULL) return -1; urlreset(url); /* Parse */ state.uri = &uri; if (uriParseUriA(&state, str) != URI_SUCCESS) { uriFreeUriMembersA(&uri); return -1; } /* Store raw */ url->raw = strdup(str); /* Copy */ #define uri_copy(y, x)\ if (x.first) {\ size_t len = x.afterLast - x.first;\ y = strndup(x.first, len);\ } #define uri_copy_static(y, x)\ if (x.first) {\ size_t len = x.afterLast - x.first;\ strncpy(y, x.first, len);\ y[len] = '\0';\ } else {\ y[0] = '\0';\ } uri_copy(url->scheme, uri.scheme); uri_copy(url->host, uri.hostText); uri_copy(url->user, uri.userInfo); uri_copy(url->query, uri.query); uri_copy(url->frag, uri.fragment); uri_copy_static(buf, uri.portText); if (*buf) url->port = atoi(buf); else url->port = 0; path = uri.pathHead; while (path) { uri_copy_static(buf, path->text); if (url->path) url->path = realloc(url->path, strlen(url->path) + strlen(buf) + 2); else url->path = calloc(1, strlen(buf) + 2); strcat(url->path, "/"); strcat(url->path, buf); path = path->next; } // TODO: query/fragment /* Split user/pass */ if (url->user) { s = strstr(url->user, ":"); if (s) { url->pass = strdup(s + 1); *s = 0; } } /* Cleanup */ uriFreeUriMembersA(&uri); return 0; }