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

📄 httpd.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * High Level Funtions: httpd_file_t *****************************************************************************/struct httpd_file_t{    httpd_url_t *url;    char *psz_url;    char *psz_mime;    httpd_file_callback_t pf_fill;    httpd_file_sys_t      *p_sys;};static int httpd_FileCallBack( httpd_callback_sys_t *p_sys, httpd_client_t *cl, httpd_message_t *answer, httpd_message_t *query ){    httpd_file_t *file = (httpd_file_t*)p_sys;    if( answer == NULL || query == NULL )    {        return VLC_SUCCESS;    }    answer->i_proto  = HTTPD_PROTO_HTTP;    answer->i_version= query->i_version;    answer->i_type   = HTTPD_MSG_ANSWER;    answer->i_status = 200;    answer->psz_status = strdup( "OK" );    httpd_MsgAdd( answer, "Content-type",  "%s", file->psz_mime );    httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );    if( query->i_type != HTTPD_MSG_HEAD )    {        char *psz_args = query->psz_args;        if( query->i_type == HTTPD_MSG_POST )        {            /* Check that */            psz_args = query->p_body;        }        file->pf_fill( file->p_sys, file, psz_args, &answer->p_body,                       &answer->i_body );    }    /* We respect client request */    if( strcmp( httpd_MsgGet( &cl->query, "Connection" ), "" ) )    {        httpd_MsgAdd( answer, "Connection",                      httpd_MsgGet( &cl->query, "Connection" ) );    }    httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );    return VLC_SUCCESS;}httpd_file_t *httpd_FileNew( httpd_host_t *host,                             char *psz_url, char *psz_mime,                             char *psz_user, char *psz_password,                             httpd_file_callback_t pf_fill,                             httpd_file_sys_t *p_sys ){    httpd_file_t *file = malloc( sizeof( httpd_file_t ) );    if( ( file->url = httpd_UrlNewUnique( host, psz_url, psz_user,                                          psz_password ) ) == NULL )    {        free( file );        return NULL;    }    file->psz_url  = strdup( psz_url );    if( psz_mime && *psz_mime )    {        file->psz_mime = strdup( psz_mime );    }    else    {        file->psz_mime = strdup( httpd_MimeFromUrl( psz_url ) );    }    file->pf_fill = pf_fill;    file->p_sys   = p_sys;    httpd_UrlCatch( file->url, HTTPD_MSG_HEAD, httpd_FileCallBack,                    (httpd_callback_sys_t*)file );    httpd_UrlCatch( file->url, HTTPD_MSG_GET,  httpd_FileCallBack,                    (httpd_callback_sys_t*)file );    httpd_UrlCatch( file->url, HTTPD_MSG_POST, httpd_FileCallBack,                    (httpd_callback_sys_t*)file );    return file;}void httpd_FileDelete( httpd_file_t *file ){    httpd_UrlDelete( file->url );    free( file->psz_url );    free( file->psz_mime );    free( file );}/***************************************************************************** * High Level Funtions: httpd_redirect_t *****************************************************************************/struct httpd_redirect_t{    httpd_url_t *url;    char        *psz_dst;};static int httpd_RedirectCallBack( httpd_callback_sys_t *p_sys,                                   httpd_client_t *cl, httpd_message_t *answer,                                   httpd_message_t *query ){    httpd_redirect_t *rdir = (httpd_redirect_t*)p_sys;    uint8_t *p;    if( answer == NULL || query == NULL )    {        return VLC_SUCCESS;    }    answer->i_proto  = query->i_proto;    answer->i_version= query->i_version;    answer->i_type   = HTTPD_MSG_ANSWER;    answer->i_status = 301;    answer->psz_status = strdup( "Moved Permanently" );    p = answer->p_body = malloc( 1000 + strlen( rdir->psz_dst ) );    p += sprintf( p, "<html>\n" );    p += sprintf( p, "<head>\n" );    p += sprintf( p, "<title>Redirection</title>\n" );    p += sprintf( p, "</head>\n" );    p += sprintf( p, "<body>\n" );    p += sprintf( p, "<h1><center>You should be <a href=\"%s\">redirected</a></center></h1>\n", rdir->psz_dst );    p += sprintf( p, "<hr />\n" );    p += sprintf( p, "<a href=\"http://www.videolan.org\">VideoLAN</a>\n" );    p += sprintf( p, "</body>\n" );    p += sprintf( p, "</html>\n" );    answer->i_body = p - answer->p_body;    /* XXX check if it's ok or we need to set an absolute url */    httpd_MsgAdd( answer, "Location",  "%s", rdir->psz_dst );    httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );    return VLC_SUCCESS;}httpd_redirect_t *httpd_RedirectNew( httpd_host_t *host, char *psz_url_dst,                                     char *psz_url_src ){    httpd_redirect_t *rdir = malloc( sizeof( httpd_redirect_t ) );    if( !( rdir->url = httpd_UrlNewUnique( host, psz_url_src, NULL, NULL ) ) )    {        free( rdir );        return NULL;    }    rdir->psz_dst = strdup( psz_url_dst );    /* Redirect apply for all HTTP request and RTSP DESCRIBE resquest */    httpd_UrlCatch( rdir->url, HTTPD_MSG_HEAD, httpd_RedirectCallBack,                    (httpd_callback_sys_t*)rdir );    httpd_UrlCatch( rdir->url, HTTPD_MSG_GET, httpd_RedirectCallBack,                    (httpd_callback_sys_t*)rdir );    httpd_UrlCatch( rdir->url, HTTPD_MSG_POST, httpd_RedirectCallBack,                    (httpd_callback_sys_t*)rdir );    httpd_UrlCatch( rdir->url, HTTPD_MSG_DESCRIBE, httpd_RedirectCallBack,                    (httpd_callback_sys_t*)rdir );    return rdir;}void httpd_RedirectDelete( httpd_redirect_t *rdir ){    httpd_UrlDelete( rdir->url );    free( rdir->psz_dst );    free( rdir );}/***************************************************************************** * High Level Funtions: httpd_stream_t *****************************************************************************/struct httpd_stream_t{    vlc_mutex_t lock;    httpd_url_t *url;    char    *psz_mime;    /* Header to send as first packet */    uint8_t *p_header;    int     i_header;    /* circular buffer */    int         i_buffer_size;      /* buffer size, can't be reallocated smaller */    uint8_t     *p_buffer;          /* buffer */    int64_t     i_buffer_pos;       /* absolute position from begining */    int64_t     i_buffer_last_pos;  /* a new connection will start with that */};static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys,                                 httpd_client_t *cl, httpd_message_t *answer,                                 httpd_message_t *query ){    httpd_stream_t *stream = (httpd_stream_t*)p_sys;    if( answer == NULL || query == NULL || cl == NULL )    {        return VLC_SUCCESS;    }    if( answer->i_body_offset > 0 )    {        int64_t i_write;        int     i_pos;#if 0        fprintf( stderr, "httpd_StreamCallBack i_body_offset=%lld\n",                 answer->i_body_offset );#endif        if( answer->i_body_offset >= stream->i_buffer_pos )        {            /* fprintf( stderr, "httpd_StreamCallBack: no data\n" ); */            return VLC_EGENERIC;    /* wait, no data available */        }        if( answer->i_body_offset + stream->i_buffer_size <            stream->i_buffer_pos )        {            /* this client isn't fast enough */            fprintf( stderr, "fixing i_body_offset (old=%lld new=%lld)\n",                     answer->i_body_offset, stream->i_buffer_last_pos );            answer->i_body_offset = stream->i_buffer_last_pos;        }        i_pos   = answer->i_body_offset % stream->i_buffer_size;        i_write = stream->i_buffer_pos - answer->i_body_offset;        if( i_write > 10000 )        {            i_write = 10000;        }        else if( i_write <= 0 )        {            return VLC_EGENERIC;    /* wait, no data available */        }        /* Don't go past the end of the circular buffer */        i_write = __MIN( i_write, stream->i_buffer_size - i_pos );        /* using HTTPD_MSG_ANSWER -> data available */        answer->i_proto  = HTTPD_PROTO_HTTP;        answer->i_version= 0;        answer->i_type   = HTTPD_MSG_ANSWER;        answer->i_body = i_write;        answer->p_body = malloc( i_write );        memcpy( answer->p_body, &stream->p_buffer[i_pos], i_write );        answer->i_body_offset += i_write;        return VLC_SUCCESS;    }    else    {        answer->i_proto  = HTTPD_PROTO_HTTP;        answer->i_version= 0;        answer->i_type   = HTTPD_MSG_ANSWER;        answer->i_status = 200;        answer->psz_status = strdup( "OK" );        if( query->i_type != HTTPD_MSG_HEAD )        {            httpd_ClientModeStream( cl );            vlc_mutex_lock( &stream->lock );            /* Send the header */            if( stream->i_header > 0 )            {                answer->i_body = stream->i_header;                answer->p_body = malloc( stream->i_header );                memcpy( answer->p_body, stream->p_header, stream->i_header );            }            answer->i_body_offset = stream->i_buffer_last_pos;            vlc_mutex_unlock( &stream->lock );        }        else        {            httpd_MsgAdd( answer, "Content-Length", "%d", 0 );            answer->i_body_offset = 0;        }        if( !strcmp( stream->psz_mime, "video/x-ms-asf-stream" ) )        {            vlc_bool_t b_xplaystream = VLC_FALSE;            int i;            httpd_MsgAdd( answer, "Content-type", "%s",                          "application/octet-stream" );            httpd_MsgAdd( answer, "Server", "Cougar 4.1.0.3921" );            httpd_MsgAdd( answer, "Pragma", "no-cache" );            httpd_MsgAdd( answer, "Pragma", "client-id=%d", rand()&0x7fff );            httpd_MsgAdd( answer, "Pragma", "features=\"broadcast\"" );            /* Check if there is a xPlayStrm=1 */            for( i = 0; i < query->i_name; i++ )            {                if( !strcasecmp( query->name[i],  "Pragma" ) &&                    strstr( query->value[i], "xPlayStrm=1" ) )                {                    b_xplaystream = VLC_TRUE;                }            }            if( !b_xplaystream )            {                answer->i_body_offset = 0;            }        }        else        {            httpd_MsgAdd( answer, "Content-type",  "%s", stream->psz_mime );        }        httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );        return VLC_SUCCESS;    }}httpd_stream_t *httpd_StreamNew( httpd_host_t *host,                                 char *psz_url, char *psz_mime,                                 char *psz_user, char *psz_password ){    httpd_stream_t *stream = malloc( sizeof( httpd_stream_t ) );    if( ( stream->url = httpd_UrlNewUnique( host, psz_url, psz_user,                                            psz_password ) ) == NULL )    {        free( stream );        return NULL;    }    vlc_mutex_init( host, &stream->lock );    if( psz_mime && *psz_mime )    {        stream->psz_mime = strdup( psz_mime );    }    else    {        stream->psz_mime = strdup( httpd_MimeFromUrl( psz_url ) );    }    stream->i_header = 0;    stream->p_header = NULL;    stream->i_buffer_size = 5000000;    /* 5 Mo per stream */    stream->p_buffer = malloc( stream->i_buffer_size );    /* We set to 1 to make life simpler     * (this way i_body_offset can never be 0) */    stream->i_buffer_pos = 1;    stream->i_buffer_last_pos = 1;    httpd_UrlCatch( stream->url, HTTPD_MSG_HEAD, httpd_StreamCallBack,                    (httpd_callback_sys_t*)stream );    httpd_UrlCatch( stream->url, HTTPD_MSG_GET, httpd_StreamCallBack,                    (httpd_callback_sys_t*)stream );    httpd_UrlCatch( stream->url, HTTPD_MSG_POST, httpd_StreamCallBack,                    (httpd_callback_sys_t*)stream );    return stream;}int httpd_StreamHeader( httpd_stream_t *stream, uint8_t *p_data, int i_data ){    vlc_mutex_lock( &stream->lock );    if( stream->p_header )    {        free( stream->p_header );        stream->p_header = NULL;    }    stream->i_header = i_data;    if( i_data > 0 )    {        stream->p_header = malloc( i_data );        memcpy( stream->p_header, p_data, i_data );    }    vlc_mutex_unlock( &stream->lock );    return VLC_SUCCESS;}int httpd_StreamSend( httpd_stream_t *stream, uint8_t *p_data, int i_data ){    int i_count;    int i_pos;    if( i_data < 0 || p_data == NULL )    {        return VLC_SUCCESS;    }    vlc_mutex_lock( &stream->lock );    /* save this pointer (to be used by new connection) */    stream->i_buffer_last_pos = stream->i_buffer_pos;    i_pos = stream->i_buffer_pos % stream->i_buffer_size;    i_count = i_data;    while( i_count > 0)    {        int i_copy;        i_copy = __MIN( i_count, stream->i_buffer_size - i_pos );        /* Ok, we can't go past the end of our buffer */        memcpy( &stream->p_buffer[i_pos], p_data, i_copy );        i_pos = ( i_pos + i_copy ) % stream->i_buffer_size;        i_count -= i_copy;        p_data  += i_copy;    }    stream->i_buffer_pos += i_data;    vlc_mutex_unlock( &stream->lock );    return VLC_SUCCESS;}void httpd_StreamDelete( httpd_stream_t *stream ){    httpd_UrlDelete( stream->url );    vlc_mutex_destroy( &stream->lock );    if( stream->psz_mime ) free( stream->psz_mime );    if( stream->p_header ) free( stream->p_header );    if( stream->p_buffer ) free( stream->p_buffer );    free( stream );}/***************************************************************************** * Low level

⌨️ 快捷键说明

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