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

📄 httpd.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
                    p = strchr( p, '\n' );                }                if( p )                {                    while( *p == '\n' || *p == '\r' )                    {                        p++;                    }                    while( p && *p != '\0' )                    {                        char *line = p;                        char *eol = p = strchr( p, '\n' );                        char *colon;                        while( eol && eol >= line && ( *eol == '\n' || *eol == '\r' ) )                        {                            *eol-- = '\0';                        }                        if( ( colon = strchr( line, ':' ) ) )                        {                            char *name;                            char *value;                            *colon++ = '\0';                            while( *colon == ' ' )                            {                                colon++;                            }                            name = strdup( line );                            value = strdup( colon );                            TAB_APPEND( cl->query.i_name, cl->query.name, name );                            TAB_APPEND( cl->query.i_value,cl->query.value,value);                            if( !strcasecmp( name, "Content-Length" ) )                            {                                cl->query.i_body = atol( value );                            }                        }                        if( p )                        {                            p++;                            while( *p == '\n' || *p == '\r' )                            {                                p++;                            }                        }                    }                }                if( cl->query.i_body > 0 )                {                    /* TODO Mhh, handle the case client will only send a                     * request and close the connection                     * to mark and of body (probably only RTSP) */                    cl->query.p_body = malloc( cl->query.i_body );                    cl->i_buffer = 0;                }                else                {                    cl->i_state = HTTPD_CLIENT_RECEIVE_DONE;                }            }        }    }    /* check if the client is to be set to dead */#if defined( WIN32 ) || defined( UNDER_CE )    if( ( i_len < 0 && WSAGetLastError() != WSAEWOULDBLOCK ) || ( i_len == 0 ) )#else    if( ( i_len < 0 && errno != EAGAIN ) || ( i_len == 0 ) )#endif    {        if( cl->query.i_proto != HTTPD_PROTO_NONE && cl->query.i_type != HTTPD_MSG_NONE )        {            /* connection closed -> end of data */            if( cl->query.i_body > 0 )            {                cl->query.i_body = cl->i_buffer;            }            cl->i_state = HTTPD_CLIENT_RECEIVE_DONE;        }        else        {            cl->i_state = HTTPD_CLIENT_DEAD;        }    }    /* XXX: for QT I have to disable timeout. Try to find why */    if( cl->query.i_proto == HTTPD_PROTO_RTSP )        cl->i_activity_timeout = 0;#if 0 /* Debugging only */    if( cl->i_state == HTTPD_CLIENT_RECEIVE_DONE )    {        int i;        fprintf( stderr, "received new request\n" );        fprintf( stderr, "  - proto=%s\n",                 cl->query.i_proto == HTTPD_PROTO_HTTP ? "HTTP" : "RTSP" );        fprintf( stderr, "  - version=%d\n", cl->query.i_version );        fprintf( stderr, "  - msg=%d\n", cl->query.i_type );        if( cl->query.i_type == HTTPD_MSG_ANSWER )        {            fprintf( stderr, "  - answer=%d '%s'\n", cl->query.i_status,                     cl->query.psz_status );        }        else if( cl->query.i_type != HTTPD_MSG_NONE )        {            fprintf( stderr, "  - url=%s\n", cl->query.psz_url );        }        for( i = 0; i < cl->query.i_name; i++ )        {            fprintf( stderr, "  - option name='%s' value='%s'\n",                     cl->query.name[i], cl->query.value[i] );        }    }#endif}static void httpd_ClientSend( httpd_client_t *cl ){    int i;    int i_len;    if( cl->i_buffer < 0 )    {        /* We need to create the header */        int i_size = 0;        char *p;        const char *psz_status = httpd_ReasonFromCode( cl->answer.i_status );        i_size = strlen( "HTTP/1.") + 10 + 10 + strlen( psz_status ) + 5;        for( i = 0; i < cl->answer.i_name; i++ )        {            i_size += strlen( cl->answer.name[i] ) + 2 +                      strlen( cl->answer.value[i] ) + 2;        }        if( cl->i_buffer_size < i_size )        {            cl->i_buffer_size = i_size;            free( cl->p_buffer );            cl->p_buffer = malloc( i_size );        }        p = (char *)cl->p_buffer;        p += sprintf( p, "%s.%u %d %s\r\n",                      cl->answer.i_proto ==  HTTPD_PROTO_HTTP ? "HTTP/1" : "RTSP/1",                      cl->answer.i_version,                      cl->answer.i_status, psz_status );        for( i = 0; i < cl->answer.i_name; i++ )        {            p += sprintf( p, "%s: %s\r\n", cl->answer.name[i],                          cl->answer.value[i] );        }        p += sprintf( p, "\r\n" );        cl->i_buffer = 0;        cl->i_buffer_size = (uint8_t*)p - cl->p_buffer;        /*fprintf( stderr, "sending answer\n" );        fprintf( stderr, "%s",  cl->p_buffer );*/    }    i_len = httpd_NetSend( cl, &cl->p_buffer[cl->i_buffer],                           cl->i_buffer_size - cl->i_buffer );    if( i_len >= 0 )    {        cl->i_buffer += i_len;        if( cl->i_buffer >= cl->i_buffer_size )        {            if( cl->answer.i_body == 0  && cl->answer.i_body_offset > 0 &&                !cl->b_read_waiting )            {                /* catch more body data */                int     i_msg = cl->query.i_type;                int64_t i_offset = cl->answer.i_body_offset;                httpd_MsgClean( &cl->answer );                cl->answer.i_body_offset = i_offset;                cl->url->catch[i_msg].cb( cl->url->catch[i_msg].p_sys, cl,                                          &cl->answer, &cl->query );            }            if( cl->answer.i_body > 0 )            {                /* send the body data */                free( cl->p_buffer );                cl->p_buffer = cl->answer.p_body;                cl->i_buffer_size = cl->answer.i_body;                cl->i_buffer = 0;                cl->answer.i_body = 0;                cl->answer.p_body = NULL;            }            else            {                /* send finished */                cl->i_state = HTTPD_CLIENT_SEND_DONE;            }        }    }    else    {#if defined( WIN32 ) || defined( UNDER_CE )        if( ( i_len < 0 && WSAGetLastError() != WSAEWOULDBLOCK ) || ( i_len == 0 ) )#else        if( ( i_len < 0 && errno != EAGAIN ) || ( i_len == 0 ) )#endif        {            /* error */            cl->i_state = HTTPD_CLIENT_DEAD;        }    }}static void httpd_ClientTlsHsIn( httpd_client_t *cl ){    switch( tls_SessionContinueHandshake( cl->p_tls ) )    {        case 0:            cl->i_state = HTTPD_CLIENT_RECEIVING;            break;        case -1:            cl->i_state = HTTPD_CLIENT_DEAD;            cl->p_tls = NULL;            break;        case 2:            cl->i_state = HTTPD_CLIENT_TLS_HS_OUT;    }}static void httpd_ClientTlsHsOut( httpd_client_t *cl ){    switch( tls_SessionContinueHandshake( cl->p_tls ) )    {        case 0:            cl->i_state = HTTPD_CLIENT_RECEIVING;            break;        case -1:            cl->i_state = HTTPD_CLIENT_DEAD;            cl->p_tls = NULL;            break;        case 1:            cl->i_state = HTTPD_CLIENT_TLS_HS_IN;            break;    }}static void* httpd_HostThread( vlc_object_t *p_this ){    httpd_host_t *host = (httpd_host_t *)p_this;    tls_session_t *p_tls = NULL;    counter_t *p_total_counter = stats_CounterCreate( host, VLC_VAR_INTEGER, STATS_COUNTER );    counter_t *p_active_counter = stats_CounterCreate( host, VLC_VAR_INTEGER, STATS_COUNTER );    int evfd;    bool b_die;retry:    vlc_object_lock( host );    evfd = vlc_object_waitpipe( VLC_OBJECT( host ) );    b_die = !vlc_object_alive( host );    vlc_object_unlock( host );    while( !b_die )    {        if( host->i_url <= 0 )        {            /* 0.2s (FIXME: use a condition variable) */            msleep( 200000 );            goto retry;        }        /* prepare a new TLS session */        if( ( p_tls == NULL ) && ( host->p_tls != NULL ) )            p_tls = tls_ServerSessionPrepare( host->p_tls );        struct pollfd ufd[host->nfd + host->i_client + 1];        unsigned nfd;        for( nfd = 0; nfd < host->nfd; nfd++ )        {            ufd[nfd].fd = host->fds[nfd];            ufd[nfd].events = POLLIN;            ufd[nfd].revents = 0;        }        /* add all socket that should be read/write and close dead connection */        vlc_mutex_lock( &host->lock );        mtime_t now = mdate();        bool b_low_delay = false;        for(int i_client = 0; i_client < host->i_client; i_client++ )        {            httpd_client_t *cl = host->client[i_client];            if( cl->i_ref < 0 || ( cl->i_ref == 0 &&                ( cl->i_state == HTTPD_CLIENT_DEAD ||                  ( cl->i_activity_timeout > 0 &&                    cl->i_activity_date+cl->i_activity_timeout < now) ) ) )            {                httpd_ClientClean( cl );                stats_UpdateInteger( host, p_active_counter, -1, NULL );                TAB_REMOVE( host->i_client, host->client, cl );                free( cl );                i_client--;                continue;            }            struct pollfd *pufd = ufd + nfd;            assert (pufd < ufd + (sizeof (ufd) / sizeof (ufd[0])));            pufd->fd = cl->fd;            pufd->events = pufd->revents = 0;            if( ( cl->i_state == HTTPD_CLIENT_RECEIVING )                  || ( cl->i_state == HTTPD_CLIENT_TLS_HS_IN ) )            {                pufd->events = POLLIN;            }            else if( ( cl->i_state == HTTPD_CLIENT_SENDING )                  || ( cl->i_state == HTTPD_CLIENT_TLS_HS_OUT ) )            {                pufd->events = POLLOUT;            }            else if( cl->i_state == HTTPD_CLIENT_RECEIVE_DONE )            {                httpd_message_t *answer = &cl->answer;                httpd_message_t *query  = &cl->query;                int i_msg = query->i_type;                httpd_MsgInit( answer );                /* Handle what we received */                if( (cl->i_mode != HTTPD_CLIENT_BIDIR) &&                    (i_msg == HTTPD_MSG_ANSWER || i_msg == HTTPD_MSG_CHANNEL) )                {                    /* we can only receive request from client when not                     * in BIDIR mode */                    cl->url     = NULL;                    cl->i_state = HTTPD_CLIENT_DEAD;                }                else if( i_msg == HTTPD_MSG_ANSWER )                {                    /* We are in BIDIR mode, trigger the callback and then                     * check for new data */                    if( cl->url && cl->url->catch[i_msg].cb )                    {                        cl->url->catch[i_msg].cb( cl->url->catch[i_msg].p_sys,                                                  cl, NULL, query );                    }                    cl->i_state = HTTPD_CLIENT_WAITING;                }                else if( i_msg == HTTPD_MSG_CHANNEL )                {                    /* We are in BIDIR mode, trigger the callback and then                     * check for new data */                    if( cl->url && cl->url->catch[i_msg].cb )                    {                        cl->url->catch[i_msg].cb( cl->url->catch[i_msg].p_sys,                                                  cl, NULL, query );                    }                    cl->i_state = HTTPD_CLIENT_WAITING;                }                else if( i_msg == HTTPD_MSG_OPTIONS )                {                    answer->i_type   = HTTPD_MSG_ANSWER;                    answer->i_proto  = query->i_proto;                    answer->i_status = 200;                    answer->i_body = 0;                    answer->p_body = NULL;                    httpd_MsgAdd( answer, "Server", "%s", PACKAGE_STRING );                    httpd_MsgAdd( answer, "Content-Length", "0" );                    switch( query->i_proto )                    {                        case HTTPD_PROTO_HTTP:                            answer->i_version = 1;                            httpd_MsgAdd( answer, "Allow",                                          "GET,HEAD,POST,OPTIONS" );                            break;                        case HTTPD_PROTO_RTSP:                        {                            const char *p;                            answer->i_version = 0;                            p = httpd_MsgGet( query, "Cseq" );                            if( p != NULL )                                httpd_MsgAdd( answer, "Cseq", "%s", p );                            p = httpd_MsgGet( query, "Timestamp" );                            if( p != NULL )                                httpd_MsgAdd( answer, "Timestamp", "%s", p );                            p = httpd_MsgGet( query, "Require" );                            if( p != NULL )                            {                                answer->i_status = 551;                                httpd_MsgAdd( query, "Unsupported", "%s", p );                            }                            httpd_MsgAdd( answer, "Public", "DESCRIBE,SETUP,"                                          "TEARDOWN,PLAY,PAUSE,GET_PARAMETER" );                            break;                        }                    }                    cl->i_buffer = -1;  /* Force the creation of the answer in                                         * httpd_ClientSend */                    cl->i_state = HTTPD_CLIENT_SENDING;                }                else if( i_msg == HTTPD_MSG_NONE )                {                    if( query->i_proto == HTTPD_PROTO_NONE )                    {                        cl->url = NULL;                        cl->i_state = HTTPD_CLIENT_DEAD;                    }                    else                    {                        char *p;                        /* unimplemented */                        answer->i_proto  = query->i_proto ;                        answer->i_type   = HTTPD_MSG_ANSWER;                        answer->i_version= 0;                        answer->i_status = 501;                        answer->i_body = httpd_HtmlError (&p, 501, NULL);                        answer

⌨️ 快捷键说明

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