SAT>IP server: handle streams correctly, add more RTSP headers

This commit is contained in:
Jaroslav Kysela 2015-02-25 20:24:38 +01:00
parent 78e4ddf86e
commit da6eb2c4b3
2 changed files with 84 additions and 34 deletions

View file

@ -520,7 +520,9 @@ void satip_rtp_init(void)
void satip_rtp_done(void)
{
assert(TAILQ_EMPTY(&satip_rtp_sessions));
satip_rtcp_run = 0;
pthread_kill(satip_rtcp_tid, SIGTERM);
pthread_join(satip_rtcp_tid, NULL);
if (satip_rtcp_run) {
satip_rtcp_run = 0;
pthread_kill(satip_rtcp_tid, SIGTERM);
pthread_join(satip_rtcp_tid, NULL);
}
}

View file

@ -49,6 +49,7 @@ typedef struct session {
} session_t;
static uint32_t session_number;
static uint16_t stream_id;
static char *rtsp_ip = NULL;
static int rtsp_port = -1;
static void *rtsp_server = NULL;
@ -99,15 +100,19 @@ result:
*
*/
static struct session *
rtsp_new_session(int delsys)
rtsp_new_session(int delsys, uint32_t nsession, int session)
{
struct session *rs = calloc(1, sizeof(*rs));
if (rs == NULL)
return NULL;
rs->delsys = delsys;
rs->nsession = session_number;
rs->nsession = nsession ?: session_number;
snprintf(rs->session, sizeof(rs->session), "%08X", session_number);
session_number += 9876;
if (nsession) {
session_number += 9876;
if (session_number == 0)
session_number += 9876;
}
TAILQ_INSERT_TAIL(&rtsp_sessions, rs, link);
return rs;
}
@ -116,16 +121,20 @@ rtsp_new_session(int delsys)
*
*/
static struct session *
rtsp_find_session(http_connection_t *hc)
rtsp_find_session(http_connection_t *hc, int stream)
{
struct session *rs;
struct session *rs, *first = NULL;
if (hc->hc_session == NULL)
return NULL;
TAILQ_FOREACH(rs, &rtsp_sessions, link)
if (!strcmp(rs->session, hc->hc_session))
return rs;
return NULL;
if (!strcmp(rs->session, hc->hc_session)) {
if (stream == rs->stream)
return rs;
if (first == NULL)
first = rs;
}
return first;
}
/*
@ -271,11 +280,11 @@ rtsp_clean(session_t *rs)
*
*/
static int
rtsp_start(http_connection_t *hc, session_t *rs)
rtsp_start(http_connection_t *hc, session_t *rs, char *addrbuf)
{
mpegts_network_t *mn;
dvb_network_t *ln;
char buf[256], addrbuf[50];
char buf[256];
int res = HTTP_STATUS_SERVICE, qsize = 3000000;
if (rs->mux)
@ -307,7 +316,6 @@ rtsp_start(http_connection_t *hc, session_t *rs)
}
if (profile_chain_raw_open(&rs->prch, (mpegts_mux_t *)rs->mux, qsize))
goto endclean;
tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrbuf, sizeof(addrbuf));
rs->subs = subscription_create_from_mux(&rs->prch, NULL,
config_get_int("satip_weight", 100),
"SAT>IP",
@ -316,14 +324,6 @@ rtsp_start(http_connection_t *hc, session_t *rs)
http_arg_get(&hc->hc_args, "User-Agent"), NULL);
if (!rs->subs)
goto endclean;
memset(&rs->udp_rtp, 0, sizeof(rs->udp_rtp));
memset(&rs->udp_rtcp, 0, sizeof(rs->udp_rtcp));
if (udp_bind_double(&rs->udp_rtp, &rs->udp_rtcp,
"satips", "rtsp", "rtcp",
addrbuf, 0, NULL,
4*1024, 4*1024,
RTP_BUFSIZE, RTCP_BUFSIZE))
goto endclean;
satip_rtp_queue((void *)(intptr_t)rs->nsession,
rs->subs, &rs->prch.prch_sq,
hc->hc_peer, ntohs(IP_PORT(rs->udp_rtp->ip)),
@ -348,19 +348,30 @@ rtsp_process_options(http_connection_t *hc)
http_arg_list_t args;
char *u = tvh_strdupa(hc->hc_url);
session_t *rs;
int found;
if ((u = rtsp_check_urlbase(u)) == NULL)
goto error;
if (*u)
goto error;
pthread_mutex_lock(&rtsp_lock);
rs = rtsp_find_session(hc);
if (rs)
rtsp_rearm_session_timer(rs);
pthread_mutex_unlock(&rtsp_lock);
if (hc->hc_session) {
found = 0;
pthread_mutex_lock(&rtsp_lock);
TAILQ_FOREACH(rs, &rtsp_sessions, link)
if (!strcmp(rs->session, hc->hc_session)) {
rtsp_rearm_session_timer(rs);
found = 1;
}
pthread_mutex_unlock(&rtsp_lock);
if (!found) {
http_error(hc, HTTP_STATUS_BAD_SESSION);
return 0;
}
}
http_arg_init(&args);
http_arg_set(&args, "Public", "OPTIONS,DESCRIBE,SETUP,PLAY,TEARDOWN");
http_arg_set(&args, "Session", hc->hc_session);
http_send_header(hc, HTTP_STATUS_OK, NULL, 0, NULL, NULL, 0, NULL, NULL, &args);
http_arg_flush(&args);
return 0;
@ -571,7 +582,10 @@ rtsp_process_play(http_connection_t *hc, int setup)
char *pids, *addpids, *delpids;
int16_t _pids[RTSP_PIDS+1], _addpids[RTSP_PIDS+1], _delpids[RTSP_PIDS+1];
dvb_mux_conf_t *dmc;
char buf[256];
char buf[256], addrbuf[50];
http_arg_list_t args;
tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrbuf, sizeof(addrbuf));
u = tvh_strdupa(hc->hc_url);
if ((u = rtsp_check_urlbase(u)) == NULL ||
@ -596,7 +610,7 @@ rtsp_process_play(http_connection_t *hc, int setup)
pthread_mutex_lock(&rtsp_lock);
rs = rtsp_find_session(hc);
rs = rtsp_find_session(hc, stream);
if (fe > 0) {
delsys = rtsp_delsys(fe, &findex);
@ -608,7 +622,9 @@ rtsp_process_play(http_connection_t *hc, int setup)
if (msys == DVB_SYS_NONE)
goto error;
if (!rs)
rs = rtsp_new_session(msys);
rs = rtsp_new_session(msys, 0, -1);
else if (stream != rs->stream)
rs = rtsp_new_session(msys, rs->nsession, stream);
else
rtsp_close_session(rs);
} else {
@ -721,11 +737,27 @@ rtsp_process_play(http_connection_t *hc, int setup)
}
dvb_mux_conf_str(dmc, buf, sizeof(buf));
tvhdebug("satips", "%i: setup %s", rs->frontend, buf);
tvhdebug("satips", "%i/%s/%d: setup %s", rs->frontend, rs->session, rs->stream, buf);
dmc->dmc_fe_freq = freq;
dmc->dmc_fe_modulation = mtype;
stream_id++;
if (stream_id == 0)
stream_id++;
rs->stream = stream_id % 0x7fff;
memset(&rs->udp_rtp, 0, sizeof(rs->udp_rtp));
memset(&rs->udp_rtcp, 0, sizeof(rs->udp_rtcp));
if (udp_bind_double(&rs->udp_rtp, &rs->udp_rtcp,
"satips", "rtsp", "rtcp",
addrbuf, 0, NULL,
4*1024, 4*1024,
RTP_BUFSIZE, RTCP_BUFSIZE)) {
errcode = HTTP_STATUS_INTERNAL;
goto error;
}
if (setup) {
if (pids)
rtsp_addpids(rs, _pids);
@ -737,13 +769,25 @@ play:
rtsp_delpids(rs, _delpids);
if (addpids)
rtsp_addpids(rs, _addpids);
if ((r = rtsp_start(hc, rs)) < 0) {
if ((r = rtsp_start(hc, rs, addrbuf)) < 0) {
errcode = r;
goto error;
}
tvhdebug("satips", "%i: play", rs->frontend);
tvhdebug("satips", "%i/%s/%d: play", rs->frontend, rs->session, rs->stream);
end:
http_arg_init(&args);
snprintf(buf, sizeof(buf), "%s;timeout=%d", rs->session, RTSP_TIMEOUT);
http_arg_set(&args, "Session", buf);
r = IP_PORT(rs->udp_rtp->ip);
snprintf(buf, sizeof(buf), "RTP/AVP;unicast;client_port=%d-%d", r, r+1);
http_arg_set(&args, "Transport", buf);
snprintf(buf, sizeof(buf), "%d", rs->stream);
http_arg_set(&args, "com.ses.streamID", buf);
http_send_header(hc, HTTP_STATUS_OK, NULL, 0, NULL, NULL, 0, NULL, NULL, &args);
http_arg_flush(&args);
pthread_mutex_unlock(&rtsp_lock);
return 0;
@ -762,6 +806,7 @@ rtsp_process_teardown(http_connection_t *hc)
{
char *u = tvh_strdupa(hc->hc_url);
struct session *rs = NULL;
http_arg_list_t args;
int stream;
if ((u = rtsp_check_urlbase(u)) == NULL ||
@ -771,7 +816,7 @@ rtsp_process_teardown(http_connection_t *hc)
}
pthread_mutex_lock(&rtsp_lock);
rs = rtsp_find_session(hc);
rs = rtsp_find_session(hc, stream);
if (!rs || stream != rs->stream) {
pthread_mutex_unlock(&rtsp_lock);
http_error(hc, !rs ? HTTP_STATUS_BAD_SESSION : HTTP_STATUS_NOT_FOUND);
@ -779,7 +824,10 @@ rtsp_process_teardown(http_connection_t *hc)
rtsp_close_session(rs);
pthread_mutex_unlock(&rtsp_lock);
rtsp_free_session(rs);
http_arg_init(&args);
http_arg_set(&args, "Session", rs->session);
http_send_header(hc, HTTP_STATUS_OK, NULL, 0, NULL, NULL, 0, NULL, NULL, NULL);
http_arg_flush(&args);
}
return 0;
}