-/****************************************************************************
- * RTSP:
- ****************************************************************************/
-static rtsp_client_t *RtspClientNew( sout_stream_t *p_stream, char *psz_session )
-{
- rtsp_client_t *rtsp = malloc( sizeof( rtsp_client_t ));
-
- rtsp->psz_session = psz_session;
- rtsp->i_last = 0;
- rtsp->b_playing = VLC_FALSE;
- rtsp->i_id = 0;
- rtsp->id = NULL;
- rtsp->i_access = 0;
- rtsp->access = NULL;
-
- TAB_APPEND( p_stream->p_sys->i_rtsp, p_stream->p_sys->rtsp, rtsp );
-
- return rtsp;
-}
-static rtsp_client_t *RtspClientGet( sout_stream_t *p_stream, char *psz_session )
-{
- int i;
-
- if( psz_session ) return NULL;
-
- for( i = 0; i < p_stream->p_sys->i_rtsp; i++ )
- {
- if( !strcmp( p_stream->p_sys->rtsp[i]->psz_session, psz_session ) )
- {
- return p_stream->p_sys->rtsp[i];
- }
- }
- return NULL;
-}
-
-static void RtspClientDel( sout_stream_t *p_stream, rtsp_client_t *rtsp )
-{
- int i;
- TAB_REMOVE( p_stream->p_sys->i_rtsp, p_stream->p_sys->rtsp, rtsp );
-
- for( i = 0; i < rtsp->i_access; i++ )
- {
- sout_AccessOutDelete( rtsp->access[i] );
- }
- if( rtsp->id ) free( rtsp->id );
- if( rtsp->access ) free( rtsp->access );
-
- free( rtsp->psz_session );
- free( rtsp );
-}
-
-static int RtspSetup( sout_stream_t *p_stream, vlc_url_t *url )
-{
- sout_stream_sys_t *p_sys = p_stream->p_sys;
-
- msg_Dbg( p_stream, "rtsp setup: %s : %d / %s\n", url->psz_host, url->i_port, url->psz_path );
-
- p_sys->p_rtsp_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host, url->i_port > 0 ? url->i_port : 554 );
- if( p_sys->p_rtsp_host == NULL )
- {
- return VLC_EGENERIC;
- }
-
- p_sys->psz_rtsp_path = strdup( url->psz_path ? url->psz_path : "/" );
- p_sys->psz_rtsp_control = malloc (strlen( url->psz_host ) + 20 + strlen( p_sys->psz_rtsp_path ) + 1 );
- sprintf( p_sys->psz_rtsp_control, "rtsp://%s:%d%s",
- url->psz_host, url->i_port > 0 ? url->i_port : 554, p_sys->psz_rtsp_path );
-
- p_sys->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, p_sys->psz_rtsp_path, NULL, NULL, NULL );
- if( p_sys->p_rtsp_url == 0 )
- {
- return VLC_EGENERIC;
- }
- httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_DESCRIBE, RtspCallback, (void*)p_stream );
- httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_PLAY, RtspCallback, (void*)p_stream );
- httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_PAUSE, RtspCallback, (void*)p_stream );
- httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_TEARDOWN, RtspCallback, (void*)p_stream );
-
- return VLC_SUCCESS;
-}
-
-static int RtspCallback( httpd_callback_sys_t *p_args,
- httpd_client_t *cl,
- httpd_message_t *answer, httpd_message_t *query )
-{
- sout_stream_t *p_stream = (sout_stream_t*)p_args;
- sout_stream_sys_t *p_sys = p_stream->p_sys;
- char *psz_destination = p_sys->psz_destination;
- char *psz_session = NULL;
- char *psz_cseq = NULL;
- int i_cseq = 0;
-
- if( answer == NULL || query == NULL )
- {
- return VLC_SUCCESS;
- }
- //fprintf( stderr, "RtspCallback query: type=%d\n", query->i_type );
-
- answer->i_proto = HTTPD_PROTO_RTSP;
- answer->i_version= query->i_version;
- answer->i_type = HTTPD_MSG_ANSWER;
-
- switch( query->i_type )
- {
- case HTTPD_MSG_DESCRIBE:
- {
- char *psz_sdp = SDPGenerate( p_stream, psz_destination ? psz_destination : "0.0.0.0", VLC_TRUE );
-
- answer->i_status = 200;
- answer->psz_status = strdup( "OK" );
- httpd_MsgAdd( answer, "Content-type", "%s", "application/sdp" );
-
- answer->p_body = (uint8_t *)psz_sdp;
- answer->i_body = strlen( psz_sdp );
- break;
- }
-
- case HTTPD_MSG_PLAY:
- {
- rtsp_client_t *rtsp;
- /* for now only multicast so easy */
- answer->i_status = 200;
- answer->psz_status = strdup( "OK" );
- answer->i_body = 0;
- answer->p_body = NULL;
-
- psz_session = httpd_MsgGet( query, "Session" );
- rtsp = RtspClientGet( p_stream, psz_session );
- if( rtsp && !rtsp->b_playing )
- {
- int i_id;
- /* FIXME */
- rtsp->b_playing = VLC_TRUE;
-
- vlc_mutex_lock( &p_sys->lock_es );
- for( i_id = 0; i_id < rtsp->i_id; i_id++ )
- {
- sout_stream_id_t *id = rtsp->id[i_id];
- int i;
-
- for( i = 0; i < p_sys->i_es; i++ )
- {
- if( id == p_sys->es[i] )
- break;
- }
- if( i >= p_sys->i_es ) continue;
-
- vlc_mutex_lock( &id->lock_rtsp );
- TAB_APPEND( id->i_rtsp_access, id->rtsp_access, rtsp->access[i_id] );
- vlc_mutex_unlock( &id->lock_rtsp );
- }
- vlc_mutex_unlock( &p_sys->lock_es );
- }
- break;
- }
- case HTTPD_MSG_PAUSE:
- /* FIXME */
- return VLC_EGENERIC;
- case HTTPD_MSG_TEARDOWN:
- {
- rtsp_client_t *rtsp;
-
- /* for now only multicast so easy again */
- answer->i_status = 200;
- answer->psz_status = strdup( "OK" );
- answer->i_body = 0;
- answer->p_body = NULL;
-
- psz_session = httpd_MsgGet( query, "Session" );
- rtsp = RtspClientGet( p_stream, psz_session );
- if( rtsp )
- {
- int i_id;
-
- vlc_mutex_lock( &p_sys->lock_es );
- for( i_id = 0; i_id < rtsp->i_id; i_id++ )
- {
- sout_stream_id_t *id = rtsp->id[i_id];
- int i;
-
- for( i = 0; i < p_sys->i_es; i++ )
- {
- if( id == p_sys->es[i] )
- break;
- }
- if( i >= p_sys->i_es ) continue;
-
- vlc_mutex_lock( &id->lock_rtsp );
- TAB_REMOVE( id->i_rtsp_access, id->rtsp_access, rtsp->access[i_id] );
- vlc_mutex_unlock( &id->lock_rtsp );
- }
- vlc_mutex_unlock( &p_sys->lock_es );
-
- RtspClientDel( p_stream, rtsp );
- }
- break;
- }
-
- default:
- return VLC_EGENERIC;
- }
- httpd_MsgAdd( answer, "Server", PACKAGE_STRING );
- httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
- psz_cseq = httpd_MsgGet( query, "Cseq" );
- if( psz_cseq )
- i_cseq = atoi( psz_cseq );
- else
- i_cseq = 0;
- httpd_MsgAdd( answer, "Cseq", "%d", i_cseq );
- httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );
-
- if( psz_session )
- {
- httpd_MsgAdd( answer, "Session", "%s;timeout=5", psz_session );
- }
- return VLC_SUCCESS;
-}
-
-static int RtspCallbackId( httpd_callback_sys_t *p_args,
- httpd_client_t *cl,
- httpd_message_t *answer, httpd_message_t *query )
-{
- sout_stream_id_t *id = (sout_stream_id_t*)p_args;
- sout_stream_t *p_stream = id->p_stream;
- sout_stream_sys_t *p_sys = p_stream->p_sys;
- char *psz_session = NULL;
- char *psz_cseq = NULL;
- int i_cseq = 0;
-
-
- if( answer == NULL || query == NULL )
- {
- return VLC_SUCCESS;
- }
- //fprintf( stderr, "RtspCallback query: type=%d\n", query->i_type );
-
- answer->i_proto = HTTPD_PROTO_RTSP;
- answer->i_version= query->i_version;
- answer->i_type = HTTPD_MSG_ANSWER;
-
- switch( query->i_type )
- {
- case HTTPD_MSG_SETUP:
- {
- char *psz_transport = httpd_MsgGet( query, "Transport" );
-
- //fprintf( stderr, "HTTPD_MSG_SETUP: transport=%s\n", psz_transport );
-
- if( strstr( psz_transport, "multicast" ) && id->psz_destination )
- {
- //fprintf( stderr, "HTTPD_MSG_SETUP: multicast\n" );
- answer->i_status = 200;
- answer->psz_status = strdup( "OK" );
- answer->i_body = 0;
- answer->p_body = NULL;
- psz_session = httpd_MsgGet( query, "Session" );
- if( !psz_session )
- {
- psz_session = malloc( 100 );
- sprintf( psz_session, "%d", rand() );
- }
- httpd_MsgAdd( answer, "Transport",
- "RTP/AVP/UDP;destination=%s;port=%d-%d;ttl=%d",
- id->psz_destination, id->i_port,id->i_port+1,
- p_sys->i_ttl );
- }
- else if( strstr( psz_transport, "unicast" ) && strstr( psz_transport, "client_port=" ) )
- {
- int i_port = atoi( strstr( psz_transport, "client_port=" ) + strlen("client_port=") );
- char ip[NI_MAXNUMERICHOST], psz_access[17], psz_url[NI_MAXNUMERICHOST + 8];
-
- sout_access_out_t *p_access;
-
- rtsp_client_t *rtsp = NULL;
-
- if( httpd_ClientIP( cl, ip ) == NULL )
- {
- answer->i_status = 500;
- answer->psz_status = strdup( "Internal server error" );
- answer->i_body = 0;
- answer->p_body = NULL;
- break;
- }
-
- //fprintf( stderr, "HTTPD_MSG_SETUP: unicast ip=%s port=%d\n", ip, i_port );
-
- psz_session = httpd_MsgGet( query, "Session" );
- if( !psz_session )
- {
- psz_session = malloc( 100 );
- sprintf( psz_session, "%d", rand() );
-
- rtsp = RtspClientNew( p_stream, psz_session );
- }
- else
- {
- rtsp = RtspClientGet( p_stream, psz_session );
- if( rtsp == NULL )
- {
- answer->i_status = 454;
- answer->psz_status = strdup( "Unknown session id" );
- answer->i_body = 0;
- answer->p_body = NULL;
- break;
- }
- }
-
- /* first try to create the access out */
- if( p_sys->i_ttl )
- snprintf( psz_access, sizeof( psz_access ),
- "udp{raw,ttl=%d}", p_sys->i_ttl );
- else
- strncpy( psz_access, "udp{raw}", sizeof( psz_access ) );
- psz_access[sizeof( psz_access ) - 1] = '\0';
-
- snprintf( psz_url, sizeof( psz_url ),
- ( strchr( ip, ':' ) != NULL ) ? "[%s]:%d" : "%s:%d",
- ip, i_port );
-
- if( ( p_access = sout_AccessOutNew( p_stream->p_sout, psz_access, psz_url ) ) == NULL )
- {
- msg_Err( p_stream, "cannot create the access out for %s://%s",
- psz_access, psz_url );
- answer->i_status = 500;
- answer->psz_status = strdup( "Internal server error" );
- answer->i_body = 0;
- answer->p_body = NULL;
- break;
- }
-
- TAB_APPEND( rtsp->i_id, rtsp->id, id );
- TAB_APPEND( rtsp->i_access, rtsp->access, p_access );
-
- answer->i_status = 200;
- answer->psz_status = strdup( "OK" );
- answer->i_body = 0;
- answer->p_body = NULL;
-
- httpd_MsgAdd( answer, "Transport",
- "RTP/AVP/UDP;client_port=%d-%d", i_port, i_port + 1 );
- }
- else /* TODO strstr( psz_transport, "interleaved" ) ) */
- {
- answer->i_status = 461;
- answer->psz_status = strdup( "Unsupported Transport" );
- answer->i_body = 0;
- answer->p_body = NULL;
- }
- break;
- }
-
- default:
- return VLC_EGENERIC;
- }
- httpd_MsgAdd( answer, "Server", "VLC Server" );
- httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
- psz_cseq = httpd_MsgGet( query, "Cseq" );
- if( psz_cseq )
- i_cseq = atoi( psz_cseq );
- else
- i_cseq = 0;
- httpd_MsgAdd( answer, "Cseq", "%d", i_cseq );
- httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );
-
- if( psz_session )
- {
- httpd_MsgAdd( answer, "Session", "%s"/*;timeout=5*/, psz_session );
- }
- return VLC_SUCCESS;
-}
-