diff -ruNp tvheadend_ndms.orig/src/http.c tvheadend_ndms/src/http.c --- tvheadend_ndms.orig/src/http.c 2018-02-22 22:16:01.000000000 +0300 +++ tvheadend_ndms/src/http.c 2018-02-26 04:03:51.584188821 +0300 @@ -1273,10 +1273,6 @@ process_request(http_connection_t *hc, h hc->hc_session = tvh_strdupa(v); else hc->hc_session = NULL; - if(hc->hc_cseq == 0) { - http_error(hc, HTTP_STATUS_BAD_REQUEST); - return -1; - } break; case HTTP_VERSION_1_0: @@ -1336,10 +1332,7 @@ process_request(http_connection_t *hc, h case RTSP_VERSION_1_0: if (tvhtrace_enabled()) dump_request(hc); - if (hc->hc_cseq) - rval = hc->hc_process(hc, spill); - else - http_error(hc, HTTP_STATUS_HTTP_VERSION); + rval = hc->hc_process(hc, spill); break; case HTTP_VERSION_1_0: diff -ruNp tvheadend_ndms.orig/src/http.h tvheadend_ndms/src/http.h --- tvheadend_ndms.orig/src/http.h 2018-02-22 22:16:01.000000000 +0300 +++ tvheadend_ndms/src/http.h 2018-02-26 03:19:40.457467700 +0300 @@ -162,6 +162,7 @@ typedef struct http_connection { int hc_no_output; int hc_shutdown; + int hc_stream; uint64_t hc_cseq; char *hc_session; diff -ruNp tvheadend_ndms.orig/src/satip/rtsp.c tvheadend_ndms/src/satip/rtsp.c --- tvheadend_ndms.orig/src/satip/rtsp.c 2018-02-22 22:16:01.000000000 +0300 +++ tvheadend_ndms/src/satip/rtsp.c 2018-02-26 19:07:59.113158089 +0300 @@ -92,6 +92,13 @@ static pthread_mutex_t rtsp_lock; static void rtsp_close_session(session_t *rs); static void rtsp_free_session(session_t *rs); +/* + * + */ +static inline int rtsp_is_nat_active(void) +{ + return rtsp_nat_ip[0] != '\0'; +} /* * @@ -280,9 +287,10 @@ rtsp_check_urlbase(char *u) if (strcmp(u, rtsp_ip)) { if (rtsp_nat_ip == NULL) return NULL; - if (rtsp_nat_ip[0] != '*') - if (rtsp_nat_ip[0] == '\0' || strcmp(u, rtsp_nat_ip)) + if (rtsp_is_nat_active()) { + if (rtsp_nat_ip[0] != '*' && strcmp(u, rtsp_nat_ip)) return NULL; + } } return p ? p + 1 : u + strlen(u); } @@ -455,8 +463,7 @@ static void rtsp_manage_descramble(session_t *rs) { idnode_set_t *found; - mpegts_service_t *s, *snext; - mpegts_service_t *master = (mpegts_service_t *)rs->subs->ths_raw_service; + mpegts_service_t *s, *master, *snext; slave_subscription_t *sub; mpegts_apids_t pmt_pids; size_t si; @@ -470,6 +477,8 @@ rtsp_manage_descramble(session_t *rs) if (rs->mux == NULL || rs->subs == NULL) goto end; + master = (mpegts_service_t *)rs->subs->ths_raw_service; + if (rs->pids.all) { LIST_FOREACH(s, &rs->mux->mm_services, s_dvb_mux_link) if (rtsp_validate_service(s, NULL)) @@ -861,7 +870,7 @@ parse_pids(char *p, mpegts_apids_t *pids while (1) { if (x == NULL) break; - if (strcmp(x, "all") == 0) { + if (strcmp(x, "all") == 0 || strcmp(x, "8192") == 0) { if (satip_server_conf.satip_restrict_pids_all) { pids->all = 0; for (pid = 1; pid <= 2; pid++) /* CAT, TSDT */ @@ -907,7 +916,22 @@ parse_transport(http_connection_t *hc) if (a + 1 != b) return -1; return a; - } else if ((strncmp(s, "RTP/AVP/TCP;interleaved=0-1", 27) == 0) && + } else if (strncmp(s, "RTP/AVP/UDP;unicast;client_port=", 32) == 0) { + for (s += 32, u = s; isdigit(*u); u++); + if (*u != '-') + return -1; + a = atoi(s); + for (s = ++u; isdigit(*s); s++); + if (*s != '\0' && *s != ';') + return -1; + b = atoi(u); + if (a + 1 != b) + return -1; + return a; + } else if ((strncmp(s, "RTP/AVP/TCP;unicast;interleaved=0-1", 27) == 0) && + !satip_server_conf.satip_notcp_mode) { + return RTSP_TCP_DATA; + } else if ((strncmp(s, "RTP/AVP/TCP;interleaved=0-1", 35) == 0) && !satip_server_conf.satip_notcp_mode) { return RTSP_TCP_DATA; } @@ -983,12 +1007,14 @@ rtsp_parse_cmd if (cmd == RTSP_CMD_SETUP) { if (!rs) { rs = rtsp_new_session(hc->hc_peer_ipstr, msys, 0, -1); + if (rs == NULL) goto end; if (delsys == DVB_SYS_NONE) goto end; if (msys == DVB_SYS_NONE) goto end; if (!(*valid)) goto end; alloc_stream_id = 1; } else if (stream != rs->stream) { rs = rtsp_new_session(hc->hc_peer_ipstr, msys, rs->nsession, stream); + if (rs == NULL) goto end; if (delsys == DVB_SYS_NONE) goto end; if (msys == DVB_SYS_NONE) goto end; if (!(*valid)) goto end; @@ -1017,6 +1043,8 @@ rtsp_parse_cmd rs->rtp_peer_port = r; rs->frontend = fe > 0 ? fe : 1; } else { + if (!rs && !stream && cmd == RTSP_CMD_DESCRIBE) + rs = rtsp_new_session(hc->hc_peer_ipstr, msys, 0, -1); if (!rs || stream != rs->stream) { if (rs) errcode = HTTP_STATUS_NOT_FOUND; @@ -1187,6 +1215,12 @@ play: if (mpegts_pid_dump(&rs->pids, buf + r, sizeof(buf) - r, 0, 0) == 0) tvh_strlcatf(buf, sizeof(buf), r, ""); + if (cmd == RTSP_CMD_DESCRIBE) { + hc->hc_session = rs->session; + if (!rs->stream) + rs->stream = 1; + hc->hc_stream = rs->stream; + } tvhdebug(LS_SATIPS, "%i/%s/%d: %s from %s:%d %s", rs->frontend, rs->session, rs->stream, caller, hc->hc_peer_ipstr, ntohs(IP_PORT(*hc->hc_peer)), buf); @@ -1294,7 +1328,8 @@ rtsp_describe_session(session_t *rs, hts { char buf[4096]; - htsbuf_qprintf(q, "a=control:stream=%d\r\n", rs->stream); + if (rs->stream > 0) + htsbuf_qprintf(q, "a=control:stream=%d\r\n", rs->stream); htsbuf_append_str(q, "a=tool:tvheadend\r\n"); htsbuf_append_str(q, "m=video 0 RTP/AVP 33\r\n"); if (strchr(rtsp_ip, ':')) @@ -1311,6 +1346,20 @@ rtsp_describe_session(session_t *rs, hts } } +static inline const char * +rtsp_conn_ip(http_connection_t *hc, char *buf, size_t buflen, int *port) +{ + const char *used_ip = rtsp_ip; + int used_port = rtsp_port; + + if (hc && hc->hc_self) + used_ip = tcp_get_str_from_ip(hc->hc_self, buf, buflen); + + *port = used_port > 0 ? used_port : 554; + + return used_ip; +} + /* * */ @@ -1322,9 +1371,10 @@ rtsp_process_describe(http_connection_t char *u = tvh_strdupa(hc->hc_url); session_t *rs; htsbuf_queue_t q; - char buf[96]; + char buf[96], buf1[46]; + const char *used_ip = NULL; int r = HTTP_STATUS_BAD_REQUEST; - int stream, first = 1, valid; + int stream, first = 1, valid, used_port; htsbuf_queue_init(&q, 0); @@ -1381,10 +1431,15 @@ rtsp_process_describe(http_connection_t http_arg_init(&args); if (hc->hc_session) http_arg_set(&args, "Session", hc->hc_session); - if (stream > 0) - snprintf(buf, sizeof(buf), "rtsp://%s/stream=%i", rtsp_ip, stream); + used_ip = rtsp_conn_ip(hc, buf1, sizeof(buf1), &used_port); + if ((stream > 0) && (used_port != 554)) + snprintf(buf, sizeof(buf), "rtsp://%s:%d/stream=%i", used_ip, used_port, stream); + else if ((stream > 0) && (used_port == 554)) + snprintf(buf, sizeof(buf), "rtsp://%s/stream=%i", used_ip, stream); + else if (used_port != 554) + snprintf(buf, sizeof(buf), "rtsp://%s:%d", used_ip, used_port); else - snprintf(buf, sizeof(buf), "rtsp://%s", rtsp_ip); + snprintf(buf, sizeof(buf), "rtsp://%s", used_ip); http_arg_set(&args, "Content-Base", buf); http_send_begin(hc); http_send_header(hc, HTTP_STATUS_OK, "application/sdp", q.hq_size, @@ -1408,8 +1463,9 @@ static int rtsp_process_play(http_connection_t *hc, int cmd) { session_t *rs; - int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream; - char buf[256], *u = tvh_strdupa(hc->hc_url); + int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream, used_port; + char buf[256], buf1[46], *u = tvh_strdupa(hc->hc_url); + const char *used_ip = NULL; http_arg_list_t args; http_arg_init(&args); @@ -1417,7 +1473,9 @@ rtsp_process_play(http_connection_t *hc, if ((u = rtsp_check_urlbase(u)) == NULL) goto error2; - if ((stream = rtsp_parse_args(hc, u)) < 0) +/* if ((stream = rtsp_parse_args(hc, u)) < 0) */ + stream = hc->hc_stream; + if (stream < 0) goto error2; pthread_mutex_lock(&rtsp_lock); @@ -1467,10 +1525,11 @@ rtsp_process_play(http_connection_t *hc, snprintf(buf, sizeof(buf), "%d", rs->stream); http_arg_set(&args, "com.ses.streamID", buf); } else { - if (rtsp_port != 554) - snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", rtsp_ip, rtsp_port, rs->stream); + used_ip = rtsp_conn_ip(hc, buf1, sizeof(buf1), &used_port); + if (used_port != 554) + snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", used_ip, used_port, rs->stream); else - snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", rtsp_ip, rs->stream); + snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", used_ip, rs->stream); http_arg_set(&args, "RTP-Info", buf); } @@ -1587,9 +1646,39 @@ static void rtsp_stream_status ( void *opaque, htsmsg_t *m ) { http_connection_t *hc = opaque; + struct session *rs = NULL; + htsmsg_t *c, *tcp = NULL, *udp = NULL; + int udpport, s32; + htsmsg_add_str(m, "type", "SAT>IP"); + if (hc->hc_username) htsmsg_add_str(m, "user", hc->hc_username); + + TAILQ_FOREACH(rs, &rtsp_sessions, link) { + if (hc->hc_session && + strcmp(rs->session, hc->hc_session) == 0 && + strcmp(rs->peer_ipstr, hc->hc_peer_ipstr) == 0 && + (udpport = rs->rtp_peer_port) > 0) { + if (udpport == RTSP_TCP_DATA) { + if (rs->tcp_data == hc) { + s32 = htsmsg_get_s32_or_default(m, "peer_port", -1); + if (!tcp) tcp = htsmsg_create_list(); + htsmsg_add_s32(tcp, NULL, s32); + } + } else { + if (!udp) udp = htsmsg_create_list(); + htsmsg_add_s32(udp, NULL, udpport); + htsmsg_add_s32(udp, NULL, udpport+1); + } + } + } + if (tcp || udp) { + c = htsmsg_create_map(); + if (tcp) htsmsg_add_msg(c, "tcp", tcp); + if (udp) htsmsg_add_msg(c, "udp", udp); + htsmsg_add_msg(m, "peer_extra_ports", c); + } } /* @@ -1621,6 +1710,7 @@ rtsp_serve(int fd, void **opaque, struct hc.hc_peer = peer; hc.hc_self = self; hc.hc_process = rtsp_process_request; + hc.hc_stream = -1; hc.hc_cseq = 1; http_serve_requests(&hc); @@ -1655,7 +1745,7 @@ rtsp_close_session(session_t *rs) rs->tcp_data = NULL; pthread_mutex_lock(&global_lock); mpegts_pid_reset(&rs->pids); - rtsp_clean(rs, 1); + rtsp_clean(rs, 0); mtimer_disarm(&rs->timer); pthread_mutex_unlock(&global_lock); }