⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsp.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
    answer->i_version= 0;    answer->i_type   = HTTPD_MSG_ANSWER;    answer->i_body = 0;    answer->p_body = NULL;    httpd_MsgAdd( answer, "Server", "%s", PACKAGE_STRING );    /* Date: is always allowed, and sometimes mandatory with RTSP/2.0. */    struct tm ut;    if (gmtime_r (&now, &ut) != NULL)    {   /* RFC1123 format, GMT is mandatory */        static const char wdays[7][4] = {            "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };        static const char mons[12][4] = {            "Jan", "Feb", "Mar", "Apr", "May", "Jun",            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };        httpd_MsgAdd (answer, "Date", "%s, %02u %s %04u %02u:%02u:%02u GMT",                      wdays[ut.tm_wday], ut.tm_mday, mons[ut.tm_mon],                      1900 + ut.tm_year, ut.tm_hour, ut.tm_min, ut.tm_sec);    }    if( query->i_proto != HTTPD_PROTO_RTSP )    {        answer->i_status = 505;    }    else    if( httpd_MsgGet( query, "Require" ) != NULL )    {        answer->i_status = 551;        httpd_MsgAdd( answer, "Unsupported", "%s",                      httpd_MsgGet( query, "Require" ) );    }    else    switch( query->i_type )    {        case HTTPD_MSG_DESCRIBE:        {   /* Aggregate-only */            if( id != NULL )            {                answer->i_status = 460;                break;            }            answer->i_status = 200;            httpd_MsgAdd( answer, "Content-Type",  "%s", "application/sdp" );            httpd_MsgAdd( answer, "Content-Base",  "%s", control );            answer->p_body = (uint8_t *)SDPGenerate( rtsp->owner, control );            if( answer->p_body != NULL )                answer->i_body = strlen( (char *)answer->p_body );            else                answer->i_status = 500;            break;        }        case HTTPD_MSG_SETUP:            /* Non-aggregate-only */            if( id == NULL )            {                answer->i_status = 459;                break;            }            psz_session = httpd_MsgGet( query, "Session" );            answer->i_status = 461;            for( const char *tpt = httpd_MsgGet( query, "Transport" );                 tpt != NULL;                 tpt = transport_next( tpt ) )            {                bool b_multicast = true, b_unsupp = false;                unsigned loport = 5004, hiport = 5005; /* from RFC3551 */                /* Check transport protocol. */                /* Currently, we only support RTP/AVP over UDP */                if( strncmp( tpt, "RTP/AVP", 7 ) )                    continue;                tpt += 7;                if( strncmp( tpt, "/UDP", 4 ) == 0 )                    tpt += 4;                if( strchr( ";,", *tpt ) == NULL )                    continue;                /* Parse transport options */                for( const char *opt = parameter_next( tpt );                     opt != NULL;                     opt = parameter_next( opt ) )                {                    if( strncmp( opt, "multicast", 9 ) == 0)                        b_multicast = true;                    else                    if( strncmp( opt, "unicast", 7 ) == 0 )                        b_multicast = false;                    else                    if( sscanf( opt, "client_port=%u-%u", &loport, &hiport )                                == 2 )                        ;                    else                    if( strncmp( opt, "mode=", 5 ) == 0 )                    {                        if( strncasecmp( opt + 5, "play", 4 )                         && strncasecmp( opt + 5, "\"PLAY\"", 6 ) )                        {                            /* Not playing?! */                            b_unsupp = true;                            break;                        }                    }                    else                    if( strncmp( opt,"destination=", 12 ) == 0 )                    {                        answer->i_status = 403;                        b_unsupp = true;                    }                    else                    {                    /*                     * Every other option is unsupported:                     *                     * "source" and "append" are invalid (server-only);                     * "ssrc" also (as clarified per RFC2326bis).                     *                     * For multicast, "port", "layers", "ttl" are set by the                     * stream output configuration.                     *                     * For unicast, we want to decide "server_port" values.                     *                     * "interleaved" is not implemented.                     */                        b_unsupp = true;                        break;                    }                }                if( b_unsupp )                    continue;                if( b_multicast )                {                    const char *dst = id->dst;                    if( dst == NULL )                        continue;                    if( psz_session == NULL )                    {                        /* Create a dummy session ID */                        snprintf( psz_sesbuf, sizeof( psz_sesbuf ), "%d",                                  rand() );                        psz_session = psz_sesbuf;                    }                    answer->i_status = 200;                    httpd_MsgAdd( answer, "Transport",                                  "RTP/AVP/UDP;destination=%s;port=%u-%u;"                                  "ttl=%d;mode=play",                                  dst, id->loport, id->hiport,                                  ( id->ttl > 0 ) ? id->ttl : 1 );                }                else                {                    char ip[NI_MAXNUMERICHOST], src[NI_MAXNUMERICHOST];                    rtsp_session_t *ses = NULL;                    rtsp_strack_t track = { id->sout_id, -1, false };                    int sport;                    if( httpd_ClientIP( cl, ip ) == NULL )                    {                        answer->i_status = 500;                        continue;                    }                    track.fd = net_ConnectDgram( p_stream, ip, loport, -1,                                                 IPPROTO_UDP );                    if( track.fd == -1 )                    {                        msg_Err( p_stream,                                 "cannot create RTP socket for %s port %u",                                 ip, loport );                        answer->i_status = 500;                        continue;                    }                    net_GetSockAddress( track.fd, src, &sport );                    vlc_mutex_lock( &rtsp->lock );                    if( psz_session == NULL )                    {                        ses = RtspClientNew( rtsp );                        snprintf( psz_sesbuf, sizeof( psz_sesbuf ), "%"PRIx64,                                  ses->id );                        psz_session = psz_sesbuf;                    }                    else                    {                        /* FIXME: we probably need to remove an access out,                         * if there is already one for the same ID */                        ses = RtspClientGet( rtsp, psz_session );                        if( ses == NULL )                        {                            answer->i_status = 454;                            vlc_mutex_unlock( &rtsp->lock );                            continue;                        }                    }                    INSERT_ELEM( ses->trackv, ses->trackc, ses->trackc,                                 track );                    vlc_mutex_unlock( &rtsp->lock );                    httpd_ServerIP( cl, ip );                    if( strcmp( src, ip ) )                    {                        /* Specify source IP if it is different from the RTSP                         * control connection server address */                        char *ptr = strchr( src, '%' );                        if( ptr != NULL ) *ptr = '\0'; /* remove scope ID */                        httpd_MsgAdd( answer, "Transport",                                      "RTP/AVP/UDP;unicast;source=%s;"                                      "client_port=%u-%u;server_port=%u-%u;"                                      "ssrc=%08X;mode=play",                                      src, loport, loport + 1, sport,                                      sport + 1, id->ssrc );                    }                    else                    {                        httpd_MsgAdd( answer, "Transport",                                      "RTP/AVP/UDP;unicast;"                                      "client_port=%u-%u;server_port=%u-%u;"                                      "ssrc=%08X;mode=play",                                      loport, loport + 1, sport, sport + 1,                                      id->ssrc );                    }                    answer->i_status = 200;                }                break;            }            break;        case HTTPD_MSG_PLAY:        {            rtsp_session_t *ses;            answer->i_status = 200;            psz_session = httpd_MsgGet( query, "Session" );            const char *range = httpd_MsgGet (query, "Range");            if (range && strncmp (range, "npt=", 4))            {                answer->i_status = 501;                break;            }            vlc_mutex_lock( &rtsp->lock );            ses = RtspClientGet( rtsp, psz_session );            if( ses != NULL )            {                /* FIXME: we really need to limit the number of tracks... */                char info[ses->trackc * ( strlen( control )                                  + sizeof("/trackID=123;seq=65535, ") ) + 1];                size_t infolen = 0;                for( int i = 0; i < ses->trackc; i++ )                {                    rtsp_strack_t *tr = ses->trackv + i;                    if( ( id == NULL ) || ( tr->id == id->sout_id ) )                    {                        if( !tr->playing )                        {                            tr->playing = true;                            rtp_add_sink( tr->id, tr->fd, false );                        }                        infolen += sprintf( info + infolen,                                            "%s/trackID=%u;seq=%u, ", control,                                            rtp_get_num( tr->id ),                                            rtp_get_seq( tr->id ) );                    }                }                if( infolen > 0 )                {                    info[infolen - 2] = '\0'; /* remove trailing ", " */                    httpd_MsgAdd( answer, "RTP-Info", "%s", info );                }            }            vlc_mutex_unlock( &rtsp->lock );            if( httpd_MsgGet( query, "Scale" ) != NULL )                httpd_MsgAdd( answer, "Scale", "1." );            break;        }        case HTTPD_MSG_PAUSE:            answer->i_status = 405;            httpd_MsgAdd( answer, "Allow",                          "%s, TEARDOWN, PLAY, GET_PARAMETER",                          ( id != NULL ) ? "SETUP" : "DESCRIBE" );            break;        case HTTPD_MSG_GETPARAMETER:            if( query->i_body > 0 )            {                answer->i_status = 451;                break;            }            psz_session = httpd_MsgGet( query, "Session" );            answer->i_status = 200;            break;        case HTTPD_MSG_TEARDOWN:        {            rtsp_session_t *ses;            answer->i_status = 200;            psz_session = httpd_MsgGet( query, "Session" );            vlc_mutex_lock( &rtsp->lock );            ses = RtspClientGet( rtsp, psz_session );            if( ses != NULL )            {                if( id == NULL ) /* Delete the entire session */                    RtspClientDel( rtsp, ses );                else /* Delete one track from the session */                for( int i = 0; i < ses->trackc; i++ )                {                    if( ses->trackv[i].id == id->sout_id )                    {                        rtp_del_sink( id->sout_id, ses->trackv[i].fd );                        REMOVE_ELEM( ses->trackv, ses->trackc, i );                    }                }            }            vlc_mutex_unlock( &rtsp->lock );            break;        }        default:            return VLC_EGENERIC;    }    if( psz_session )        httpd_MsgAdd( answer, "Session", "%s"/*;timeout=5*/, psz_session );    httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );    httpd_MsgAdd( answer, "Cache-Control", "no-cache" );    psz = httpd_MsgGet( query, "Cseq" );    if( psz != NULL )        httpd_MsgAdd( answer, "Cseq", "%s", psz );    psz = httpd_MsgGet( query, "Timestamp" );    if( psz != NULL )        httpd_MsgAdd( answer, "Timestamp", "%s", psz );    return VLC_SUCCESS;}/** Aggregate RTSP callback */static int RtspCallback( httpd_callback_sys_t *p_args,                         httpd_client_t *cl,                         httpd_message_t *answer,                         const httpd_message_t *query ){    return RtspHandler( (rtsp_stream_t *)p_args, NULL, cl, answer, query );}/** Non-aggregate RTSP callback */static int RtspCallbackId( httpd_callback_sys_t *p_args,                           httpd_client_t *cl,                           httpd_message_t *answer,                           const httpd_message_t *query ){    rtsp_stream_id_t *id = (rtsp_stream_id_t *)p_args;    return RtspHandler( id->stream, id, cl, answer, query );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -