This source file includes following definitions.
- RP_SendFailure
- RP_ProcessResponse
- RP_GetCommand
- RP_RemoveCommand
- RP_ProcessCommands
- RP_FindChannel
- RP_CheckSession
- RP_NewSession
- RP_AddStream
- RP_RemoveStream
- RP_ResetSession
- RP_DelSession
- RP_SendMessage
#include "rtp_in.h"
#ifndef GPAC_DISABLE_STREAMING
void RP_SendFailure(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e)
{
char sMsg[1000];
sprintf(sMsg, "Cannot send %s", com->method);
RP_SendMessage(sess->owner->service, e, sMsg);
}
GF_Err RP_ProcessResponse(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e)
{
if (!strcmp(com->method, GF_RTSP_DESCRIBE))
return RP_ProcessDescribe(sess, com, e);
else if (!strcmp(com->method, GF_RTSP_SETUP))
RP_ProcessSetup(sess, com, e);
else if (!strcmp(com->method, GF_RTSP_TEARDOWN))
RP_ProcessTeardown(sess, com, e);
else if (!strcmp(com->method, GF_RTSP_PLAY) || !strcmp(com->method, GF_RTSP_PAUSE))
RP_ProcessUserCommand(sess, com, e);
return GF_OK;
}
static GF_RTSPCommand *RP_GetCommand(RTSPSession *sess)
{
GF_RTSPCommand *com;
gf_mx_p(sess->owner->mx);
com = (GF_RTSPCommand *)gf_list_get(sess->rtsp_commands, 0);
gf_mx_v(sess->owner->mx);
return com;
}
static void RP_RemoveCommand(RTSPSession *sess)
{
gf_mx_p(sess->owner->mx);
gf_list_rem(sess->rtsp_commands, 0);
gf_mx_v(sess->owner->mx);
}
void RP_ProcessCommands(RTSPSession *sess)
{
GF_RTSPCommand *com;
GF_Err e;
u32 time;
com = RP_GetCommand(sess);
if ((com && !(sess->flags & RTSP_WAIT_REPLY) ) || (sess->flags & RTSP_TCP_FLUSH) ) {
while (1) {
e = gf_rtsp_session_read(sess->session);
if (e) break;
}
sess->flags &= ~RTSP_TCP_FLUSH;
}
if ( (com && (sess->flags & RTSP_WAIT_REPLY) ) ) {
e = gf_rtsp_get_response(sess->session, sess->rtsp_rsp);
if (e!= GF_IP_NETWORK_EMPTY) {
e = RP_ProcessResponse(sess, com, e);
if (e!=GF_OK) {
RP_RemoveCommand(sess);
gf_rtsp_command_del(com);
gf_service_connect_ack(sess->owner->service, NULL, e);
return;
}
RP_RemoveCommand(sess);
gf_rtsp_command_del(com);
sess->flags &= ~RTSP_WAIT_REPLY;
sess->command_time = 0;
} else {
u32 time_out = sess->owner->time_out;
time = gf_sys_clock() - sess->command_time;
if (!strcmp(com->method, GF_RTSP_DESCRIBE) && (time_out < 10000) ) time_out = 10000;
else if (!strcmp(com->method, GF_RTSP_TEARDOWN) && (time>=500) ) time = time_out;
if (time >= time_out) {
if (!strcmp(com->method, GF_RTSP_TEARDOWN)) {
gf_rtsp_session_reset(sess->session, GF_TRUE);
} else {
GF_LOG(GF_LOG_WARNING, GF_LOG_RTP, ("[RTP] Request Timeout for command %s after %d ms\n", com->method, time));
}
RP_ProcessResponse(sess, com, GF_IP_NETWORK_FAILURE);
RP_RemoveCommand(sess);
gf_rtsp_command_del(com);
sess->flags &= ~RTSP_WAIT_REPLY;
sess->command_time = 0;
gf_rtsp_reset_aggregation(sess->session);
}
}
return;
}
if (!com) return;
switch (gf_rtsp_get_session_state(sess->session)) {
case GF_RTSP_STATE_WAITING:
case GF_RTSP_STATE_WAIT_FOR_CONTROL:
return;
case GF_RTSP_STATE_INVALIDATED:
RP_SendFailure(sess, com, GF_IP_NETWORK_FAILURE);
RP_RemoveCommand(sess);
gf_rtsp_command_del(com);
sess->flags &= ~RTSP_WAIT_REPLY;
sess->command_time = 0;
return;
}
com->User_Agent = (char*)gf_modules_get_option((GF_BaseInterface *) gf_service_get_interface(sess->owner->service), "Downloader", "UserAgent");
if (!com->User_Agent) com->User_Agent = "GPAC " GPAC_VERSION " RTSP Client";
com->Accept_Language = RTSP_LANGUAGE;
if (sess->session_id && !com->Session)
com->Session = sess->session_id;
if (!strcmp(com->method, GF_RTSP_DESCRIBE)) {
com->Session = NULL;
if (!RP_PreprocessDescribe(sess, com)) {
e = GF_BAD_PARAM;
goto exit;
}
}
if (!strcmp(com->method, GF_RTSP_PLAY)
|| !strcmp(com->method, GF_RTSP_PAUSE)
|| !strcmp(com->method, GF_RTSP_TEARDOWN)) {
if (!RP_PreprocessUserCom(sess, com)) {
e = GF_BAD_PARAM;
goto exit;
}
}
e = gf_rtsp_send_command(sess->session, com);
if (e) {
RP_SendFailure(sess, com, e);
RP_ProcessResponse(sess, com, e);
} else {
sess->command_time = gf_sys_clock();
sess->flags |= RTSP_WAIT_REPLY;
}
exit:
com->User_Agent = NULL;
com->Accept_Language = NULL;
com->Session = NULL;
if (e) {
RP_RemoveCommand(sess);
gf_rtsp_command_del(com);
sess->flags &= ~RTSP_WAIT_REPLY;
sess->command_time = 0;
}
}
RTPStream *RP_FindChannel(RTPClient *rtp, LPNETCHANNEL ch, u32 ES_ID, char *es_control, Bool remove_stream)
{
u32 i=0;
RTPStream *st;
while ((st = (RTPStream *)gf_list_enum(rtp->channels, &i))) {
if (ch && (st->channel==ch)) goto found;
if (ES_ID && (st->ES_ID==ES_ID)) goto found;
if (es_control && st->control) {
char *ctrl_start = strstr(es_control, st->control);
if (ctrl_start && !strcmp(ctrl_start, st->control)) goto found;
}
}
return NULL;
found:
if (remove_stream) gf_list_rem(rtp->channels, i-1);
return st;
}
RTSPSession *RP_CheckSession(RTPClient *rtp, char *control)
{
u32 i;
RTSPSession *sess;
if (!control) return NULL;
if (!strcmp(control, "*")) control = (char *) gf_service_get_url(rtp->service);
i=0;
while ( (sess = (RTSPSession *)gf_list_enum(rtp->sessions, &i)) ) {
if (gf_rtsp_is_my_session(sess->session, control)) return sess;
}
return NULL;
}
RTSPSession *RP_NewSession(RTPClient *rtp, char *session_control)
{
char *szCtrl, *szExt;
RTSPSession *tmp;
GF_RTSPSession *rtsp;
if (!session_control) return NULL;
szCtrl = gf_strdup(session_control);
szExt = szCtrl ? strrchr(szCtrl, '.') : NULL;
if (szExt) {
szExt = strchr(szExt, '/');
if (szExt) {
if (!strnicmp(szExt+1, "trackID=", 8) || !strnicmp(szExt+1, "ESID=", 5) || !strnicmp(szExt+1, "ES_ID=", 6)) szExt[0] = 0;
}
}
rtsp = gf_rtsp_session_new(szCtrl, rtp->default_port);
gf_free(szCtrl);
if (!rtsp) return NULL;
GF_SAFEALLOC(tmp, RTSPSession);
if (!tmp) return NULL;
tmp->owner = rtp;
tmp->session = rtsp;
szCtrl = (char *)gf_modules_get_option((GF_BaseInterface *) gf_service_get_interface(rtp->service), "Network", "MobileIPEnabled");
if (szCtrl && !strcmp(szCtrl, "yes")) {
char *ip = (char *)gf_modules_get_option((GF_BaseInterface *) gf_service_get_interface(rtp->service), "Network", "MobileIP");
gf_rtsp_set_mobile_ip(rtsp, ip);
}
if (rtp->transport_mode) {
gf_rtsp_set_buffer_size(rtsp, RTSP_TCP_BUFFER_SIZE);
} else {
gf_rtsp_set_buffer_size(rtsp, RTSP_BUFFER_SIZE);
}
tmp->rtsp_commands = gf_list_new();
tmp->rtsp_rsp = gf_rtsp_response_new();
gf_list_add(rtp->sessions, tmp);
return tmp;
}
GF_Err RP_AddStream(RTPClient *rtp, RTPStream *stream, char *session_control)
{
Bool has_aggregated_control;
char *service_name, *ctrl;
RTSPSession *in_session = RP_CheckSession(rtp, session_control);
has_aggregated_control = GF_FALSE;
if (session_control) {
if (session_control) has_aggregated_control = GF_TRUE;
}
if (in_session) {
in_session->flags |= RTSP_AGG_CONTROL;
stream->rtsp = in_session;
gf_list_add(rtp->channels, stream);
return GF_OK;
}
if (stream->control) {
if (strnicmp(stream->control, "rtsp://", 7) && strnicmp(stream->control, "rtspu://", 8) && strnicmp(stream->control, "satip://", 8)) {
if (!in_session) in_session = RP_CheckSession(rtp, session_control ? session_control : "*");
if (!in_session) in_session = RP_NewSession(rtp, session_control);
}
else {
in_session = RP_CheckSession(rtp, stream->control);
if (!in_session) in_session = RP_CheckSession(rtp, session_control);
if (!in_session) {
if (session_control && strstr(stream->control, session_control))
in_session = RP_NewSession(rtp, session_control);
else
in_session = RP_NewSession(rtp, stream->control);
if (!in_session) return GF_SERVICE_ERROR;
}
service_name = gf_rtsp_get_service_name(in_session->session);
ctrl = strstr(stream->control, service_name);
if (ctrl && (strlen(ctrl) != strlen(service_name)) ) {
ctrl += strlen(service_name) + 1;
service_name = gf_strdup(ctrl);
gf_free(stream->control);
stream->control = service_name;
}
}
}
else {
in_session = NULL;
}
if (in_session) {
if (has_aggregated_control)
in_session->flags |= RTSP_AGG_CONTROL;
} else if (stream->control) {
gf_free(stream->control);
stream->control = NULL;
}
stream->rtsp = in_session;
gf_list_add(rtp->channels, stream);
return GF_OK;
}
void RP_RemoveStream(RTPClient *rtp, RTPStream *ch)
{
u32 i=0;
RTPStream *st;
gf_mx_p(rtp->mx);
while ((st = (RTPStream *)gf_list_enum(rtp->channels, &i))) {
if (st == ch) {
gf_list_rem(rtp->channels, i-1);
break;
}
}
gf_mx_v(rtp->mx);
}
void RP_ResetSession(RTSPSession *sess, GF_Err e)
{
GF_RTSPCommand *com;
while (gf_list_count(sess->rtsp_commands)) {
com = (GF_RTSPCommand *)gf_list_get(sess->rtsp_commands, 0);
gf_list_rem(sess->rtsp_commands, 0);
gf_rtsp_command_del(com);
}
gf_rtsp_session_reset(sess->session, GF_TRUE);
sess->flags &= ~RTSP_WAIT_REPLY;
}
void RP_DelSession(RTSPSession *sess)
{
RP_ResetSession(sess, GF_OK);
gf_list_del(sess->rtsp_commands);
gf_rtsp_response_del(sess->rtsp_rsp);
gf_rtsp_session_del(sess->session);
if (sess->control) gf_free(sess->control);
if (sess->session_id) gf_free(sess->session_id);
if (sess->satip_server) gf_free(sess->satip_server);
gf_free(sess);
}
void RP_SendMessage(GF_ClientService *service, GF_Err e, const char *message)
{
GF_NetworkCommand com;
memset(&com, 0, sizeof(com));
com.command_type = GF_NET_SERVICE_EVENT;
com.send_event.evt.type = GF_EVENT_MESSAGE;
com.send_event.evt.message.message = message;
com.send_event.evt.message.error = e;
gf_service_command(service, &com, GF_OK);
}
#endif