int rtsp_options_decode( http_client_t *hc ) { char *argv[32], *p; int i, n, what = 0; p = http_arg_get(&hc->hc_args, "Public"); if (p == NULL) return -EIO; n = http_tokenize(p, argv, 32, ','); for (i = 1; i < n; i++) { if (strcmp(argv[i], "DESCRIBE") == 0) what |= 1; else if (strcmp(argv[i], "SETUP") == 0) what |= 2; else if (strcmp(argv[i], "PLAY") == 0) what |= 4; else if (strcmp(argv[i], "TEARDOWN") == 0) what |= 8; } return (hc->hc_code != 200 && what != 0x0f) ? -EIO : HTTP_CON_OK; }
/* * 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) return 0; s = http_arg_get(&hc->hc_args, "Content-Type"); if (s) { n = http_tokenize(s, argv, ARRAY_SIZE(argv), ';'); if (n > 0 && (strcasecmp(s, "audio/mpegurl") == 0 || strcasecmp(s, "audio/x-mpegurl") == 0 || strcasecmp(s, "application/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; } 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; }
int rtsp_setup_decode( http_client_t *hc, int satip ) { char *argv[32], *argv2[2], *p; int i, n, j; #if 0 { http_arg_t *ra; TAILQ_FOREACH(ra, &hc->hc_args, link) printf(" %s: %s\n", ra->key, ra->val); } #endif rtsp_clear_session(hc); if (hc->hc_code != 200) return -EIO; p = http_arg_get(&hc->hc_args, "Session"); if (p == NULL) return -EIO; n = http_tokenize(p, argv, 32, ';'); if (n < 1) return -EIO; hc->hc_rtsp_session = strdup(argv[0]); for (i = 1; i < n; i++) { if (strncasecmp(argv[i], "timeout=", 8) == 0) { hc->hc_rtp_timeout = atoi(argv[i] + 8); if (hc->hc_rtp_timeout < 20 || hc->hc_rtp_timeout > 3600) { tvhwarn(LS_RTSP, "timeout value out of range 20-3600 (%i)", hc->hc_rtp_timeout); return -EIO; } } } if (satip) { p = http_arg_get(&hc->hc_args, "com.ses.streamID"); if (p == NULL) return -EIO; /* zero is valid stream id per specification */ while (*p && ((*p == '0' && *(p + 1) == '0') || *p < ' ')) p++; if (p[0] == '0' && p[1] == '\0') { hc->hc_rtsp_stream_id = 0; } else { hc->hc_rtsp_stream_id = atoll(p); if (hc->hc_rtsp_stream_id <= 0) return -EIO; } } p = http_arg_get(&hc->hc_args, "Transport"); if (p == NULL) return -EIO; n = http_tokenize(p, argv, 32, ';'); if (n < 2) return -EIO; hc->hc_rtp_tcp = -1; hc->hc_rtcp_tcp = -1; hc->hc_rtp_port = -1; hc->hc_rtcp_port = -1; if (!strcasecmp(argv[0], "RTP/AVP/TCP")) { for (i = 1; i < n; i++) { if (strncmp(argv[i], "interleaved=", 12) == 0) { j = http_tokenize(argv[i] + 12, argv2, 2, '-'); if (j > 0) { hc->hc_rtp_tcp = atoi(argv2[0]); if (hc->hc_rtp_tcp < 0) return -EIO; if (j > 1) { hc->hc_rtcp_tcp = atoi(argv2[1]); if (hc->hc_rtcp_tcp < 0) return -EIO; } } else { return -EIO; } } } } else if (!strcasecmp(argv[0], "RTP/AVP") || !strcasecmp(argv[0], "RTP/AVP/UDP")) { if (n < 3) return -EIO; hc->hc_rtp_multicast = strcasecmp(argv[1], "multicast") == 0; if (strcasecmp(argv[1], "unicast") && !hc->hc_rtp_multicast) return -EIO; for (i = 2; i < n; i++) { if (strncmp(argv[i], "destination=", 12) == 0) hc->hc_rtp_dest = strdup(argv[i] + 12); else if (strncmp(argv[i], "client_port=", 12) == 0) { j = http_tokenize(argv[i] + 12, argv2, 2, '-'); if (j > 0) { hc->hc_rtp_port = atoi(argv2[0]); if (hc->hc_rtp_port <= 0) return -EIO; if (j > 1) { hc->hc_rtcp_port = atoi(argv2[1]); if (hc->hc_rtcp_port <= 0) return -EIO; } } else { return -EIO; } } else if (strncmp(argv[i], "server_port=", 12) == 0) { j = http_tokenize(argv[i] + 12, argv2, 2, '-'); if (j > 1) { hc->hc_rtcp_server_port = atoi(argv2[1]); if (hc->hc_rtcp_server_port <= 0) return -EIO; } else { return -EIO; } } } } else { return -EIO; } return HTTP_CON_OK; }
static void satip_discovery_service_received (uint8_t *data, size_t len, udp_connection_t *conn, struct sockaddr_storage *storage) { char *buf, *ptr, *saveptr; char *argv[10]; char *st = NULL; char *location = NULL; char *server = NULL; char *uuid = NULL; char *bootid = NULL; char *configid = NULL; char *deviceid = NULL; char sockbuf[128]; satip_discovery_t *d; int n, i; if (len > 8191 || satip_discoveries_count > 100) return; buf = alloca(len+1); memcpy(buf, data, len); buf[len] = '\0'; ptr = strtok_r(buf, "\r\n", &saveptr); /* Request decoder */ if (ptr) { if (http_tokenize(ptr, argv, 3, -1) != 3) return; if (conn->multicast) { if (strcmp(argv[0], "NOTIFY")) return; if (strcmp(argv[1], "*")) return; if (strcmp(argv[2], "HTTP/1.1")) return; } else { if (strcmp(argv[0], "HTTP/1.1")) return; if (strcmp(argv[1], "200")) return; } ptr = strtok_r(NULL, "\r\n", &saveptr); } /* Header decoder */ while (1) { if (ptr == NULL) break; if (http_tokenize(ptr, argv, 2, ':') == 2) { if (strcmp(argv[0], "ST") == 0) st = argv[1]; else if (strcmp(argv[0], "LOCATION") == 0) location = argv[1]; else if (strcmp(argv[0], "SERVER") == 0) server = argv[1]; else if (strcmp(argv[0], "BOOTID.UPNP.ORG") == 0) bootid = argv[1]; else if (strcmp(argv[0], "CONFIGID.UPNP.ORG") == 0) configid = argv[1]; else if (strcmp(argv[0], "DEVICEID.SES.COM") == 0) deviceid = argv[1]; else if (strcmp(argv[0], "USN") == 0) { n = http_tokenize(argv[1], argv, ARRAY_SIZE(argv), ':'); for (i = 0; i < n-1; i++) if (argv[i] && strcmp(argv[i], "uuid") == 0) { uuid = argv[++i]; break; } } } ptr = strtok_r(NULL, "\r\n", &saveptr); } /* Sanity checks */ if (st == NULL || strcmp(st, "urn:ses-com:device:SatIPServer:1")) goto add_uuid; if (uuid == NULL || strlen(uuid) < 16 || satip_server_match_uuid(uuid)) goto add_uuid; if (location == NULL || strncmp(location, "http://", 7)) goto add_uuid; if (bootid == NULL || configid == NULL || server == NULL) goto add_uuid; /* Forward information to next layer */ d = calloc(1, sizeof(satip_discovery_t)); if (inet_ntop(conn->ip.ss_family, IP_IN_ADDR(conn->ip), sockbuf, sizeof(sockbuf)) == NULL) { satip_discovery_destroy(d, 0); return; } d->myaddr = strdup(sockbuf); d->location = strdup(location); d->server = strdup(server); d->uuid = strdup(uuid); d->bootid = strdup(bootid); d->configid = strdup(configid); d->deviceid = strdup(deviceid ? deviceid : ""); if (urlparse(d->location, &d->url)) { satip_discovery_destroy(d, 0); return; } pthread_mutex_lock(&global_lock); i = 1; if (!satip_discovery_find(d) && !satip_device_find(d->uuid)) { TAILQ_INSERT_TAIL(&satip_discoveries, d, disc_link); satip_discoveries_count++; gtimer_arm_ms(&satip_discovery_timerq, satip_discovery_timerq_cb, NULL, 250); i = 0; } pthread_mutex_unlock(&global_lock); if (i) /* duplicate */ satip_discovery_destroy(d, 0); return; add_uuid: if (deviceid == NULL || uuid == NULL) return; /* if new uuid was discovered, retrigger MSEARCH */ pthread_mutex_lock(&global_lock); if (!satip_device_find(uuid)) gtimer_arm(&satip_discovery_timer, satip_discovery_timer_cb, NULL, 5); pthread_mutex_unlock(&global_lock); }
static void satip_discovery_http_closed(http_client_t *hc, int errn) { satip_discovery_t *d = hc->hc_aux; char *s; htsmsg_t *xml = NULL, *tags, *root, *device; const char *friendlyname, *manufacturer, *manufacturerURL, *modeldesc; const char *modelname, *modelnum, *serialnum; const char *presentation, *tunercfg, *udn, *uuid; const char *cs, *arg; satip_device_info_t info; char errbuf[100]; char *argv[10]; int i, n; s = http_arg_get(&hc->hc_args, "Content-Type"); if (s) { n = http_tokenize(s, argv, ARRAY_SIZE(argv), ';'); if (n <= 0 || strcasecmp(s, "text/xml")) { errn = ENOENT; s = NULL; } } if (errn != 0 || s == NULL || hc->hc_code != 200 || hc->hc_data_size == 0 || hc->hc_data == NULL) { tvhlog(LOG_ERR, "satip", "Cannot get %s: %s", d->location, strerror(errn)); return; } if (tvhtrace_enabled()) { tvhtrace("satip", "received XML description from %s", hc->hc_host); tvhlog_hexdump("satip", hc->hc_data, hc->hc_data_size); } if (d->myaddr == NULL || d->myaddr[0] == '\0') { struct sockaddr_storage ip; socklen_t addrlen = sizeof(ip); errbuf[0] = '\0'; getsockname(hc->hc_fd, (struct sockaddr *)&ip, &addrlen); inet_ntop(ip.ss_family, IP_IN_ADDR(ip), errbuf, sizeof(errbuf)); free(d->myaddr); d->myaddr = strdup(errbuf); } s = hc->hc_data + hc->hc_data_size - 1; while (s != hc->hc_data && *s != '/') s--; if (s != hc->hc_data) s--; if (strncmp(s, "</root>", 7)) return; /* Parse */ xml = htsmsg_xml_deserialize(hc->hc_data, errbuf, sizeof(errbuf)); hc->hc_data = NULL; if (!xml) { tvhlog(LOG_ERR, "satip_discovery_desc", "htsmsg_xml_deserialize error %s", errbuf); goto finish; } if ((tags = htsmsg_get_map(xml, "tags")) == NULL) goto finish; if ((root = htsmsg_get_map(tags, "root")) == NULL) goto finish; if ((device = htsmsg_get_map(root, "tags")) == NULL) goto finish; if ((device = htsmsg_get_map(device, "device")) == NULL) goto finish; if ((device = htsmsg_get_map(device, "tags")) == NULL) goto finish; if ((cs = htsmsg_xml_get_cdata_str(device, "deviceType")) == NULL) goto finish; if (strcmp(cs, "urn:ses-com:device:SatIPServer:1")) goto finish; if ((friendlyname = htsmsg_xml_get_cdata_str(device, "friendlyName")) == NULL) goto finish; if ((manufacturer = htsmsg_xml_get_cdata_str(device, "manufacturer")) == NULL) goto finish; if ((manufacturerURL = htsmsg_xml_get_cdata_str(device, "manufacturerURL")) == NULL) manufacturerURL = ""; if ((modeldesc = htsmsg_xml_get_cdata_str(device, "modelDescription")) == NULL) modeldesc = ""; if ((modelname = htsmsg_xml_get_cdata_str(device, "modelName")) == NULL) goto finish; if ((modelnum = htsmsg_xml_get_cdata_str(device, "modelNumber")) == NULL) modelnum = ""; if ((serialnum = htsmsg_xml_get_cdata_str(device, "serialNumber")) == NULL) serialnum = ""; if ((presentation = htsmsg_xml_get_cdata_str(device, "presentationURL")) == NULL) presentation = ""; if ((udn = htsmsg_xml_get_cdata_str(device, "UDN")) == NULL) goto finish; if ((tunercfg = htsmsg_xml_get_cdata_str(device, "urn:ses-com:satipX_SATIPCAP")) == NULL) tunercfg = ""; uuid = NULL; n = http_tokenize((char *)udn, argv, ARRAY_SIZE(argv), ':'); for (i = 0; i < n+1; i++) if (argv[i] && strcmp(argv[i], "uuid") == 0) { uuid = argv[++i]; break; } if (uuid == NULL || (d->uuid[0] && strcmp(uuid, d->uuid))) goto finish; info.rtsp_port = 554; info.srcs = 4; arg = http_arg_get(&hc->hc_args, "X-SATIP-RTSP-Port"); if (arg) { i = atoi(arg); if (i > 0 && i < 65535) info.rtsp_port = i; } arg = http_arg_get(&hc->hc_args, "X-SATIP-Sources"); if (arg) { i = atoi(arg); if (i > 0 && i < 128) info.srcs = i; } info.myaddr = strdup(d->myaddr); info.addr = strdup(d->url.host); info.uuid = strdup(uuid); info.bootid = strdup(d->bootid); info.configid = strdup(d->configid); info.deviceid = strdup(d->deviceid); info.location = strdup(d->location); info.server = strdup(d->server); info.friendlyname = strdup(friendlyname); info.manufacturer = strdup(manufacturer); info.manufacturerURL = strdup(manufacturerURL); info.modeldesc = strdup(modeldesc); info.modelname = strdup(modelname); info.modelnum = strdup(modelnum); info.serialnum = strdup(serialnum); info.presentation = strdup(presentation); info.tunercfg = strdup(tunercfg); htsmsg_destroy(xml); xml = NULL; pthread_mutex_lock(&global_lock); if (!satip_device_find(info.uuid)) satip_device_create(&info); pthread_mutex_unlock(&global_lock); free(info.myaddr); free(info.location); free(info.server); free(info.addr); free(info.uuid); free(info.bootid); free(info.configid); free(info.deviceid); free(info.friendlyname); free(info.manufacturer); free(info.manufacturerURL); free(info.modeldesc); free(info.modelname); free(info.modelnum); free(info.serialnum); free(info.presentation); free(info.tunercfg); finish: htsmsg_destroy(xml); }
static satip_device_t * satip_device_create( satip_device_info_t *info ) { satip_device_t *sd = calloc(1, sizeof(satip_device_t)); tvh_uuid_t uuid; htsmsg_t *conf = NULL, *feconf = NULL; char *argv[10], *tunercfg; int i, j, n, m, fenum, v2, save = 0; dvb_fe_type_t type; char buf2[60]; sd->sd_inload = 1; satip_device_calc_uuid(&uuid, info->uuid); conf = hts_settings_load("input/satip/adapters/%s", uuid.hex); /* some sane defaults */ sd->sd_fast_switch = 1; sd->sd_fullmux_ok = 1; sd->sd_pids_len = 127; sd->sd_pids_max = 32; sd->sd_pids_deladd = 1; sd->sd_sig_scale = 240; sd->sd_dbus_allow = 1; if (!tvh_hardware_create0((tvh_hardware_t*)sd, &satip_device_class, uuid.hex, conf)) { /* Note: sd is freed in above fcn */ return NULL; } pthread_mutex_init(&sd->sd_tune_mutex, NULL); TAILQ_INIT(&sd->sd_frontends); /* we may check if uuid matches, but the SHA hash should be enough */ if (sd->sd_info.uuid) free(sd->sd_info.uuid); #define ASSIGN(x) sd->sd_info.x = info->x; info->x = NULL ASSIGN(myaddr); ASSIGN(addr); ASSIGN(uuid); ASSIGN(bootid); ASSIGN(configid); ASSIGN(deviceid); ASSIGN(server); ASSIGN(location); ASSIGN(friendlyname); ASSIGN(manufacturer); ASSIGN(manufacturerURL); ASSIGN(modeldesc); ASSIGN(modelname); ASSIGN(modelnum); ASSIGN(serialnum); ASSIGN(presentation); ASSIGN(tunercfg); #undef ASSIGN sd->sd_info.rtsp_port = info->rtsp_port; sd->sd_info.srcs = info->srcs; /* * device specific hacks */ satip_device_hack(sd); if (conf) feconf = htsmsg_get_map(conf, "frontends"); save = !conf || !feconf; tunercfg = sd->sd_tunercfg; if (tunercfg == NULL) tunercfg = sd->sd_tunercfg = strdup("Auto"); if (strncmp(tunercfg, "DVB", 3) && strncmp(tunercfg, "ATSC", 4)) tunercfg = sd->sd_info.tunercfg; n = http_tokenize(tvh_strdupa(tunercfg), argv, 10, ','); for (i = m = 0, fenum = 1; i < n; i++) { type = DVB_TYPE_NONE; v2 = 0; if (strncmp(argv[i], "DVBS2-", 6) == 0) { type = DVB_TYPE_S; m = atoi(argv[i] + 6); v2 = 1; } else if (strncmp(argv[i], "DVBS-", 5) == 0) { type = DVB_TYPE_S; m = atoi(argv[i] + 5); } else if (strncmp(argv[i], "DVBT2-", 6) == 0) { type = DVB_TYPE_T; m = atoi(argv[i] + 6); v2 = 1; } else if (strncmp(argv[i], "DVBT-", 5) == 0) { type = DVB_TYPE_T; m = atoi(argv[i] + 5); } else if (strncmp(argv[i], "DVBC2-", 6) == 0) { type = DVB_TYPE_C; m = atoi(argv[i] + 6); v2 = 1; } else if (strncmp(argv[i], "DVBC-", 5) == 0) { type = DVB_TYPE_C; m = atoi(argv[i] + 5); } else if (strncmp(argv[i], "ATSC-", 5) == 0) { type = DVB_TYPE_ATSC; m = atoi(argv[i] + 5); } else if (strncmp(argv[i], "DVBCB-", 6) == 0) { m = atoi(argv[i] + 6); v2 = 2; } if (type == DVB_TYPE_NONE) { tvhlog(LOG_ERR, "satip", "%s: bad tuner type [%s]", satip_device_nicename(sd, buf2, sizeof(buf2)), argv[i]); } else if (m < 0 || m > 32) { tvhlog(LOG_ERR, "satip", "%s: bad tuner count [%s]", satip_device_nicename(sd, buf2, sizeof(buf2)), argv[i]); } else { sd->sd_nosave = 1; for (j = 0; j < m; j++) if (satip_frontend_create(feconf, sd, type, v2, fenum)) fenum++; sd->sd_nosave = 0; } } if (save) satip_device_save(sd); sd->sd_inload = 0; htsmsg_destroy(conf); satip_device_dbus_notify(sd, "start"); return sd; }
static satip_device_t * satip_device_create( satip_device_info_t *info ) { satip_device_t *sd = calloc(1, sizeof(satip_device_t)); uuid_t uuid; htsmsg_t *conf = NULL, *feconf = NULL; char *argv[10]; int i, j, n, m, fenum, t2, save = 0; dvb_fe_type_t type; satip_device_calc_uuid(&uuid, info->uuid); conf = hts_settings_load("input/satip/adapters/%s", uuid.hex); /* some sane defaults */ sd->sd_fullmux_ok = 1; sd->sd_pids_len = 127; sd->sd_pids_max = 32; sd->sd_pids_deladd = 1; sd->sd_sig_scale = 240; if (!tvh_hardware_create0((tvh_hardware_t*)sd, &satip_device_class, uuid.hex, conf)) { free(sd); return NULL; } pthread_mutex_init(&sd->sd_tune_mutex, NULL); TAILQ_INIT(&sd->sd_frontends); /* we may check if uuid matches, but the SHA hash should be enough */ if (sd->sd_info.uuid) free(sd->sd_info.uuid); #define ASSIGN(x) sd->sd_info.x = info->x; info->x = NULL ASSIGN(myaddr); ASSIGN(addr); ASSIGN(uuid); ASSIGN(bootid); ASSIGN(configid); ASSIGN(deviceid); ASSIGN(server); ASSIGN(location); ASSIGN(friendlyname); ASSIGN(manufacturer); ASSIGN(manufacturerURL); ASSIGN(modeldesc); ASSIGN(modelname); ASSIGN(modelnum); ASSIGN(serialnum); ASSIGN(presentation); ASSIGN(tunercfg); #undef ASSIGN /* * device specific hacks */ satip_device_hack(sd); if (conf) feconf = htsmsg_get_map(conf, "frontends"); save = !conf || !feconf; n = http_tokenize(sd->sd_info.tunercfg, argv, 10, ','); for (i = 0, fenum = 1; i < n; i++) { type = DVB_TYPE_NONE; t2 = 0; if (strncmp(argv[i], "DVBS2-", 6) == 0) { type = DVB_TYPE_S; m = atoi(argv[i] + 6); } else if (strncmp(argv[i], "DVBT2-", 6) == 0) { type = DVB_TYPE_T; m = atoi(argv[i] + 6); t2 = 1; } else if (strncmp(argv[i], "DVBT-", 5) == 0) { type = DVB_TYPE_T; m = atoi(argv[i] + 5); } else if (strncmp(argv[i], "DVBC-", 5) == 0) { type = DVB_TYPE_C; m = atoi(argv[i] + 5); } if (type == DVB_TYPE_NONE) { tvhlog(LOG_ERR, "satip", "%s: bad tuner type [%s]", sd->sd_info.addr, argv[i]); } else if (m < 0 || m > 32) { tvhlog(LOG_ERR, "satip", "%s: bad tuner count [%s]", sd->sd_info.addr, argv[i]); } else { for (j = 0; j < m; j++) if (satip_frontend_create(feconf, sd, type, t2, fenum)) fenum++; } } if (save) satip_device_save(sd); htsmsg_destroy(conf); return sd; }