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

📄 httpd.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 5 页
字号:
                        }                        p2 = strchr( p, ' ' );                        if( p2 )                        {                            *p2++ = '\0';                        }                        if( !strncasecmp( p, "rtsp:", 5 ) )                        {                            /* for rtsp url, you have rtsp://localhost:port/path */                            p += 5;                            while( *p == '/' ) p++;                            while( *p && *p != '/' ) p++;                        }                        cl->query.psz_url = strdup( p );                        if( ( p3 = strchr( cl->query.psz_url, '?' ) )  )                        {                            *p3++ = '\0';                            cl->query.psz_args = strdup( p3 );                        }                        if( p2 )                        {                            while( *p2 == ' ' )                            {                                p2++;                            }                            if( !strncasecmp( p2, "HTTP/1.", 7 ) )                            {                                cl->query.i_proto = HTTPD_PROTO_HTTP;                                cl->query.i_version = atoi( p2+7 );                            }                            else if( !strncasecmp( p2, "RTSP/1.", 7 ) )                            {                                cl->query.i_proto = HTTPD_PROTO_RTSP;                                cl->query.i_version = atoi( p2+7 );                            }                        }                        p = p2;                    }                }                if( p )                {                    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 && errno != EINTR ) || ( 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;        }    }    cl->i_activity_date = mdate();    /* 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;    /* 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] );        }    }*/}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;        i_size = strlen( "HTTP/1.") + 10 + 10 +                 strlen( cl->answer.psz_status ? cl->answer.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 = cl->p_buffer;        p += sprintf( p, "%s/1.%d %d %s\r\n",                      cl->answer.i_proto ==  HTTPD_PROTO_HTTP ? "HTTP" : "RTSP",                      cl->answer.i_version,                      cl->answer.i_status, cl->answer.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_activity_date = mdate();        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 && errno != EINTR ) || ( 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( httpd_host_t *host ){    tls_session_t *p_tls = NULL;    while( !host->b_die )    {        struct timeval  timeout;        fd_set          fds_read;        fd_set          fds_write;        int             i_handle_max = 0;        int             i_ret;        int             i_client;        int             b_low_delay = 0;        if( host->i_url <= 0 )        {            /* 0.2s */            msleep( 200000 );            continue;        }        /* built a set of handle to select */        FD_ZERO( &fds_read );        FD_ZERO( &fds_write );        FD_SET( host->fd, &fds_read );        i_handle_max = host->fd;        /* prepare a new TLS session */        if( ( p_tls == NULL ) && ( host->p_tls != NULL ) )            p_tls = tls_ServerSessionPrepare( host->p_tls );        /* add all socket that should be read/write and close dead connection */        vlc_mutex_lock( &host->lock );        for( 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 < mdate()) ) ) )            {                char *ip;                // FIXME: it sucks to allocate memory on the stack for debug                ip = httpd_ClientIP( cl );                msg_Dbg( host, "connection closed(%s)",                         (ip != NULL) ? ip : "unknown" );                free( ip );                httpd_ClientClean( cl );                TAB_REMOVE( host->i_client, host->client, cl );                free( cl );                i_client--;                continue;            }            else if( ( cl->i_state == HTTPD_CLIENT_RECEIVING )                  || ( cl->i_state == HTTPD_CLIENT_TLS_HS_IN ) )            {                FD_SET( cl->fd, &fds_read );                i_handle_max = __MAX( i_handle_max, cl->fd );            }            else if( ( cl->i_state == HTTPD_CLIENT_SENDING )                  || ( cl->i_state == HTTPD_CLIENT_TLS_HS_OUT ) )            {                FD_SET( cl->fd, &fds_write );                i_handle_max = __MAX( i_handle_max, cl->fd );            }            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 )                {                    int i_cseq;                    /* unimplemented */                    answer->i_proto  = query->i_proto ;                    answer->i_type   = HTTPD_MSG_ANSWER;                    answer->i_version= 0;                    answer->i_status = 200;                    answer->psz_status = strdup( "Ok" );                    answer->i_body = 0;                    answer->p_body = NULL;                    i_cseq = atoi( httpd_MsgGet( query, "Cseq" ) );                    httpd_MsgAdd( answer, "Cseq", "%d", i_cseq );                    httpd_MsgAdd( answer, "Server", "VLC Server" );                    httpd_MsgAdd( answer, "Public", "DESCRIBE, SETUP, "                                 "TEARDOWN, PLAY, PAUSE" );                    httpd_MsgAdd( answer, "Content-Length", "%d",                                  answer->i_body );                    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 )               

⌨️ 快捷键说明

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