X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Fhttpd.c;h=90eef947240d4974cc1a058fa41f23187b84d71a;hb=6051a4ee3a6192231112a18add101a5e33abc74e;hp=71c217a4a81181978b54ad10231640ef0501a049;hpb=d7cd4a07e11006ede0a06ef118de676f448cbab9;p=vlc diff --git a/modules/misc/httpd.c b/modules/misc/httpd.c index 71c217a4a8..90eef94724 100644 --- a/modules/misc/httpd.c +++ b/modules/misc/httpd.c @@ -2,7 +2,7 @@ * httpd.c ***************************************************************************** * Copyright (C) 2001-2003 VideoLAN - * $Id: httpd.c,v 1.9 2003/03/17 23:42:12 fenrir Exp $ + * $Id: httpd.c,v 1.31 2004/02/05 19:51:46 fenrir Exp $ * * Authors: Laurent Aimar * @@ -23,17 +23,18 @@ /***************************************************************************** * Preamble + * + * TODO: + * - make that two distinct host:port use different daemon *****************************************************************************/ #include +#include -#include #include -#include #include #include -#include #include "httpd.h" #ifdef HAVE_SYS_TIME_H @@ -74,6 +75,7 @@ #define HTTPD_MAX_CONNECTION 512 #define HTTPD_CONNECTION_MAX_UNUSED 10000000 + #define FREE( p ) if( p ) { free( p); (p) = NULL; } #if defined( WIN32 ) || defined( UNDER_CE ) @@ -95,6 +97,7 @@ vlc_module_begin(); set_description( _("HTTP 1.0 daemon") ); set_capability( "httpd", 42 ); set_callbacks( Open, Close ); + var_Create( p_module->p_libvlc, "httpd", VLC_VAR_MUTEX ); vlc_module_end(); /***************************************************************************** @@ -111,14 +114,16 @@ static httpd_file_t *RegisterFile ( httpd_t *, httpd_file_callback_args_t *p_args ); static void UnregisterFile ( httpd_t *, httpd_file_t * ); -//#define httpd_stream_t httpd_file_t +#if 0 + #define httpd_stream_t httpd_file_t +#endif static httpd_stream_t *RegisterStream ( httpd_t *, char *psz_file, char *psz_mime, char *psz_user, char *psz_password ); static int SendStream ( httpd_t *, httpd_stream_t *, uint8_t *, int ); static int HeaderStream ( httpd_t *, httpd_stream_t *, uint8_t *, int ); static void UnregisterStream( httpd_t *, httpd_stream_t* ); - +static int Control ( httpd_t *, int , void*, void* ); /***************************************************************************** * Internal definitions *****************************************************************************/ @@ -134,10 +139,15 @@ struct httpd_host_t }; -#define HTTPD_AUTHENTICATE_NONE 0 -#define HTTPD_AUTHENTICATE_BASIC 1 +enum httpd_authenticate_e +{ + HTTPD_AUTHENTICATE_NONE = 0, + HTTPD_AUTHENTICATE_BASIC = 1 +}; -//typedef httpd_file_t httpd_stream_t; +#if 0 + typedef httpd_file_t httpd_stream_t; +#endif struct httpd_file_t { @@ -163,7 +173,7 @@ struct httpd_file_t 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 */ - int i_buffer_last_pos; /* a new connection will start with that */ + int64_t i_buffer_last_pos; /* a new connection will start with that */ /* data to be send at connection time (if any) */ int i_header_size; @@ -171,14 +181,24 @@ struct httpd_file_t }; -#define HTTPD_CONNECTION_RECEIVING_REQUEST 1 -#define HTTPD_CONNECTION_SENDING_HEADER 2 -#define HTTPD_CONNECTION_SENDING_FILE 3 -#define HTTPD_CONNECTION_SENDING_STREAM 4 -#define HTTPD_CONNECTION_TO_BE_CLOSED 5 +enum httpd_connection_state_e +{ + HTTPD_CONNECTION_RECEIVING_REQUEST = 1, + HTTPD_CONNECTION_SENDING_HEADER = 2, + HTTPD_CONNECTION_SENDING_FILE = 3, + HTTPD_CONNECTION_SENDING_STREAM = 4, + HTTPD_CONNECTION_TO_BE_CLOSED = 5 +}; + +enum httpd_connection_method_e +{ + HTTPD_CONNECTION_METHOD_GET = 1, + HTTPD_CONNECTION_METHOD_POST = 2, + HTTPD_CONNECTION_METHOD_HEAD = 3, + /* cludgy, only used when parsing connection request */ + HTTPD_CONNECTION_METHOD_ASFHEAD = 4 +}; -#define HTTPD_CONNECTION_METHOD_GET 1 -#define HTTPD_CONNECTION_METHOD_POST 2 typedef struct httpd_connection_s { struct httpd_connection_s *p_next; @@ -191,12 +211,12 @@ typedef struct httpd_connection_s int i_state; int i_method; /* get/post */ - char *psz_file; // file to be send - int i_http_error; // error to be send with the file - char *psz_user; // if Authorization in the request header + char *psz_file; /* file to be send */ + int i_http_error; /* error to be send with the file */ + char *psz_user; /* if Authorization in the request header */ char *psz_password; - uint8_t *p_request; // whith get: ?<*>, with post: main data + uint8_t *p_request; /* whith get: ?<*>, with post: main data */ int i_request_size; httpd_file_t *p_file; @@ -210,6 +230,15 @@ typedef struct httpd_connection_s int64_t i_stream_pos; /* absolute pos in stream */ } httpd_connection_t; +/* Linked List of banned IP */ +typedef struct httpd_banned_ip_s +{ + struct httpd_banned_ip_s *p_next; + struct httpd_banned_ip_s *p_prev; + + char *psz_ip; + +} httpd_banned_ip_t; /* * The httpd thread */ @@ -228,11 +257,20 @@ struct httpd_sys_t vlc_mutex_t connection_lock; int i_connection_count; httpd_connection_t *p_first_connection; + + vlc_mutex_t ban_lock; + int i_banned_ip_count; + httpd_banned_ip_t *p_first_banned_ip; }; static void httpd_Thread( httpd_sys_t *p_httpt ); static void httpd_ConnnectionNew( httpd_sys_t *, int , struct sockaddr_in * ); static void httpd_ConnnectionClose( httpd_sys_t *, httpd_connection_t * ); +static int httpd_UnbanIP( httpd_sys_t *, httpd_banned_ip_t *); +#if 0 +static int httpd_BanIP( httpd_sys_t *, char *); +#endif +static httpd_banned_ip_t *httpd_GetbannedIP( httpd_sys_t *, char * ); /***************************************************************************** * Open: @@ -254,18 +292,39 @@ static int Open( vlc_object_t *p_this ) p_httpt->b_error= 0; /* init httpt_t structure */ - vlc_mutex_init( p_httpd, &p_httpt->host_lock ); + if( vlc_mutex_init( p_httpd, &p_httpt->host_lock ) ) + { + msg_Err( p_httpd, "Error in mutex creation"); + return( VLC_EGENERIC ); + } p_httpt->i_host_count = 0; p_httpt->host = NULL; - vlc_mutex_init( p_httpd, &p_httpt->file_lock ); + if( vlc_mutex_init( p_httpd, &p_httpt->file_lock ) ) + { + msg_Err( p_httpd, "Error in mutex creation"); + return( VLC_EGENERIC ); + } p_httpt->i_file_count = 0; p_httpt->file = NULL; - vlc_mutex_init( p_httpd, &p_httpt->connection_lock ); + if( vlc_mutex_init( p_httpd, &p_httpt->connection_lock ) ) + { + msg_Err( p_httpd, "Error in mutex creation"); + return( VLC_EGENERIC ); + } p_httpt->i_connection_count = 0; p_httpt->p_first_connection = NULL; + if( vlc_mutex_init( p_httpd, &p_httpt->ban_lock ) ) + { + msg_Err( p_httpd, "Error in mutex creation"); + return( VLC_EGENERIC ); + } + + p_httpt->i_banned_ip_count = 0; + p_httpt->p_first_banned_ip = NULL; + /* start the thread */ if( vlc_thread_create( p_httpt, "httpd thread", httpd_Thread, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) @@ -275,6 +334,7 @@ static int Open( vlc_object_t *p_this ) vlc_mutex_destroy( &p_httpt->host_lock ); vlc_mutex_destroy( &p_httpt->file_lock ); vlc_mutex_destroy( &p_httpt->connection_lock ); + vlc_mutex_destroy( &p_httpt->ban_lock ); vlc_object_destroy( p_httpt ); return( VLC_EGENERIC ); @@ -291,6 +351,7 @@ static int Open( vlc_object_t *p_this ) p_httpd->pf_header_stream = HeaderStream; p_httpd->pf_send_stream = SendStream; p_httpd->pf_unregister_stream=UnregisterStream; + p_httpd->pf_control = Control; return( VLC_SUCCESS ); } @@ -304,6 +365,8 @@ static void Close( vlc_object_t * p_this ) httpd_sys_t *p_httpt = p_httpd->p_sys; httpd_connection_t *p_con; + httpd_banned_ip_t *p_banned_ip; + int i; p_httpt->b_die = 1; @@ -360,6 +423,13 @@ static void Close( vlc_object_t * p_this ) httpd_ConnnectionClose( p_httpt, p_con ); } + /* Free all banned IP */ + vlc_mutex_destroy( &p_httpt->ban_lock ); + while( ( p_banned_ip = p_httpt->p_first_banned_ip)) + { + httpd_UnbanIP(p_httpt,p_banned_ip); + } + msg_Info( p_httpd, "httpd instance closed" ); vlc_object_destroy( p_httpt ); } @@ -436,7 +506,8 @@ static httpd_host_t *_RegisterHost( httpd_sys_t *p_httpt, char *psz_host_addr, i for( i = 0; i < p_httpt->i_host_count; i++ ) { if( p_httpt->host[i]->sock.sin_port == sock.sin_port && - p_httpt->host[i]->sock.sin_addr.s_addr == sock.sin_addr.s_addr ) + ( p_httpt->host[i]->sock.sin_addr.s_addr == INADDR_ANY || + p_httpt->host[i]->sock.sin_addr.s_addr == sock.sin_addr.s_addr ) ) { break; } @@ -509,9 +580,24 @@ static httpd_host_t *_RegisterHost( httpd_sys_t *p_httpt, char *psz_host_addr, i { p_httpt->host = malloc( sizeof( httpd_host_t *) ); } + if( !p_httpt->host ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } p_host = malloc( sizeof( httpd_host_t ) ); + if( !p_host ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } p_host->i_ref = 1; p_host->psz_host_addr = strdup( psz_host_addr ); + if( !p_host->psz_host_addr ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } p_host->i_port = i_port; p_host->sock = sock; p_host->fd = fd; @@ -592,6 +678,11 @@ static void _UnregisterHost( httpd_sys_t *p_httpt, httpd_host_t *p_ho p_httpt->i_host_count--; p_httpt->host = realloc( p_httpt->host, p_httpt->i_host_count * sizeof( httpd_host_t * ) ); + if( !p_httpt->host ) + { + msg_Err( p_httpt, "Out of memory" ); + return; + } } vlc_mutex_unlock( &p_httpt->host_lock ); @@ -613,7 +704,10 @@ static void __RegisterFile( httpd_sys_t *p_httpt, httpd_file_t *p_file ) { p_httpt->file = malloc( sizeof( httpd_file_t *) ); } - + if( !p_httpt->file ) + { + return; + } p_httpt->file[p_httpt->i_file_count++] = p_file; } @@ -643,14 +737,29 @@ static httpd_file_t *_RegisterFile( httpd_sys_t *p_httpt, } p_file = malloc( sizeof( httpd_file_t ) ); + if( !p_file ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } p_file->i_ref = 0; p_file->psz_file = strdup( psz_file ); p_file->psz_mime = strdup( psz_mime ); + if( !p_file->psz_file || !p_file->psz_mime ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } if( psz_user && *psz_user ) { p_file->i_authenticate_method = HTTPD_AUTHENTICATE_BASIC; p_file->psz_user = strdup( psz_user ); p_file->psz_password = strdup( psz_password ); + if( !p_file->psz_user || !p_file->psz_password ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } } else { @@ -713,14 +822,29 @@ static httpd_stream_t *_RegisterStream( httpd_sys_t *p_httpt, } p_stream = malloc( sizeof( httpd_stream_t ) ); + if( !p_stream ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } p_stream->i_ref = 0; p_stream->psz_file = strdup( psz_file ); p_stream->psz_mime = strdup( psz_mime ); + if( !p_stream->psz_file || !p_stream->psz_mime ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } if( psz_user && *psz_user ) { p_stream->i_authenticate_method = HTTPD_AUTHENTICATE_BASIC; p_stream->psz_user = strdup( psz_user ); p_stream->psz_password = strdup( psz_password ); + if( !p_stream->psz_user || !p_stream->psz_password ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } } else { @@ -734,10 +858,15 @@ static httpd_stream_t *_RegisterStream( httpd_sys_t *p_httpt, p_stream->pf_get = NULL; p_stream->pf_post = NULL; - p_stream->i_buffer_size = 1024*1024; + p_stream->i_buffer_size = 5*1024*1024; p_stream->i_buffer_pos = 0; p_stream->i_buffer_last_pos = 0; p_stream->p_buffer = malloc( p_stream->i_buffer_size ); + if( !p_stream->p_buffer ) + { + msg_Err( p_httpt, "Out of memory" ); + return NULL; + } p_stream->i_header_size = 0; p_stream->p_header = NULL; @@ -850,8 +979,9 @@ static int _SendStream( httpd_sys_t *p_httpt, httpd_stream_t *p_stre { return( VLC_SUCCESS ); } - //fprintf( stderr, "## i_data=%d pos=%lld\n", i_data, p_stream->i_buffer_pos ); - +#if 0 + fprintf( stderr, "## i_data=%d pos=%lld\n", i_data, p_stream->i_buffer_pos ); +#endif vlc_mutex_lock( &p_httpt->file_lock ); /* save this pointer (to be used by new connection) */ @@ -865,6 +995,7 @@ static int _SendStream( httpd_sys_t *p_httpt, httpd_stream_t *p_stre i_copy = __MIN( i_count, p_stream->i_buffer_size - i_pos ); + /* Ok, we can't go past the end of our buffer */ memcpy( &p_stream->p_buffer[i_pos], p_data, i_copy ); @@ -879,6 +1010,7 @@ static int _SendStream( httpd_sys_t *p_httpt, httpd_stream_t *p_stre return( VLC_SUCCESS ); } + static int SendStream( httpd_t *p_httpd, httpd_stream_t *p_stream, uint8_t *p_data, int i_data ) { return( _SendStream( p_httpd->p_sys, p_stream, p_data, i_data ) ); @@ -899,6 +1031,11 @@ static int HeaderStream( httpd_t *p_httpd, httpd_stream_t *p_stream, { p_stream->i_header_size = i_data; p_stream->p_header = malloc( i_data ); + if( !p_stream->p_header ) + { + msg_Err( p_httpt, "Out of memory" ); + return( VLC_ENOMEM ); + } memcpy( p_stream->p_header, p_data, i_data ); @@ -908,28 +1045,169 @@ static int HeaderStream( httpd_t *p_httpd, httpd_stream_t *p_stream, return( VLC_SUCCESS ); } +static void httpd_info_add_ss( httpd_info_t *p_info, char *name, char *value ) +{ + if( p_info->i_count == 0 ) + { + p_info->info = malloc( sizeof( httpd_val_t ) ); + } + else + { + p_info->info = + realloc( p_info->info, + sizeof( httpd_val_t ) * ( p_info->i_count + 1 ) ); + } + if( !p_info->info ) + { + return; + } + p_info->info[p_info->i_count].psz_name = strdup( name ); + if( ! p_info->info[p_info->i_count].psz_name ) + { + return; + } + p_info->info[p_info->i_count].psz_value = strdup( value ? value : "(null)"); + p_info->i_count++; +} + +static void httpd_info_add_si( httpd_info_t *p_info, char *name, int i_value ) +{ + char v[40]; /* Ok, int is not so long */ + + sprintf( v, "%d", i_value ); + httpd_info_add_ss( p_info, name, v ); +} + +static void httpd_info_add_sp( httpd_info_t *p_info, char *name, void *value ) +{ + char v[40]; + + sprintf( v, "%p", value ); + httpd_info_add_ss( p_info, name, v ); +} + + +static int Control( httpd_t *p_httpd, + int i_query, void *arg1, void *arg2 ) +{ + httpd_sys_t *p_httpt = p_httpd->p_sys; + httpd_info_t *p_info; + httpd_connection_t *p_con; + int i; + void *id; + + switch( i_query ) + { + case HTTPD_GET_HOSTS: + p_info = arg1; + p_info->i_count = 0; + vlc_mutex_lock( &p_httpt->host_lock ); + for( i = 0; i < p_httpt->i_host_count; i++ ) + { + httpd_info_add_sp( p_info, + "id", p_httpt->host[i] ); + httpd_info_add_ss( p_info, + "host", p_httpt->host[i]->psz_host_addr ); + httpd_info_add_ss( p_info, + "ip", + inet_ntoa(p_httpt->host[i]->sock.sin_addr)); + httpd_info_add_si( p_info, + "port", p_httpt->host[i]->i_port ); + } + vlc_mutex_unlock( &p_httpt->host_lock ); + return VLC_SUCCESS; + case HTTPD_GET_URLS: + p_info = arg1; + p_info->i_count = 0; + /* we can't take file_lock */ + for( i = 0; i < p_httpt->i_file_count; i++ ) + { + httpd_info_add_sp( p_info, + "id", p_httpt->file[i] ); + httpd_info_add_si( p_info, + "stream", p_httpt->file[i]->b_stream ? 1 : 0 ); + httpd_info_add_ss( p_info, + "url", p_httpt->file[i]->psz_file ); + httpd_info_add_ss( p_info, + "mime", p_httpt->file[i]->psz_mime ); + httpd_info_add_si( p_info, + "protected", p_httpt->file[i]->psz_user ? 1 : 0 ); + httpd_info_add_si( p_info, + "used", p_httpt->file[i]->i_ref ); + } + return VLC_SUCCESS; + case HTTPD_GET_CONNECTIONS: + p_info = arg1; + p_info->i_count = 0; + /* we can't take lock */ + for( p_con = p_httpt->p_first_connection;p_con != NULL; p_con = p_con->p_next ) + { + if( p_con->i_state != HTTPD_CONNECTION_TO_BE_CLOSED ) + { + httpd_info_add_sp( p_info, + "id", p_con ); + httpd_info_add_ss( p_info, + "ip", inet_ntoa( p_con->sock.sin_addr ) ); + httpd_info_add_ss( p_info, + "url", p_con->psz_file ); + httpd_info_add_si( p_info, + "status", p_con->i_http_error ); + } + } + return VLC_SUCCESS; + case HTTPD_GET_ACL: + p_info = arg1; + p_info->i_count = 0; + return VLC_EGENERIC; + + case HTTPD_SET_CLOSE: + sscanf( arg1, "%p", &id ); + fprintf( stderr, "Control: HTTPD_SET_CLOSE: id=%p", id ); + + for( p_con = p_httpt->p_first_connection;p_con != NULL; p_con = p_con->p_next ) + { + if( (void*)p_con == id ) + { + /* XXX don't free p_con as it could be the one that it is sending ... */ + p_con->i_state = HTTPD_CONNECTION_TO_BE_CLOSED; + return VLC_SUCCESS; + } + } + return VLC_EGENERIC; + + case HTTPD_SET_ACL: + sscanf( arg1, "%p", &id ); + fprintf( stderr, "Control: %p", id ); + default: + return VLC_EGENERIC; + } +} + /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ -static int httpd_page_401_get( httpd_file_callback_args_t *p_args, +static int httpd_page_400_get( httpd_file_callback_args_t *p_args, uint8_t *p_request, int i_request, uint8_t **pp_data, int *pi_data ) { char *p; p = *pp_data = malloc( 1024 ); - + if( !p ) + { + return VLC_ENOMEM ; + } p += sprintf( p, "\n" ); p += sprintf( p, "\n" ); - p += sprintf( p, "Error 401\n" ); + p += sprintf( p, "Error 400\n" ); p += sprintf( p, "\n" ); p += sprintf( p, "\n" ); - p += sprintf( p, "

401 authentification needed

\n" ); + p += sprintf( p, "

400 Bad Request

\n" ); p += sprintf( p, "
\n" ); - p += sprintf( p, "VideoLAN\n" ); + p += sprintf( p, "VideoLAN\n" ); p += sprintf( p, "\n" ); p += sprintf( p, "\n" ); @@ -937,22 +1215,27 @@ static int httpd_page_401_get( httpd_file_callback_args_t *p_args, return VLC_SUCCESS; } -static int httpd_page_404_get( httpd_file_callback_args_t *p_args, + +static int httpd_page_401_get( httpd_file_callback_args_t *p_args, uint8_t *p_request, int i_request, uint8_t **pp_data, int *pi_data ) { char *p; p = *pp_data = malloc( 1024 ); + if( !p ) + { + return VLC_ENOMEM ; + } p += sprintf( p, "\n" ); p += sprintf( p, "\n" ); - p += sprintf( p, "Error 404\n" ); + p += sprintf( p, "Error 401\n" ); p += sprintf( p, "\n" ); p += sprintf( p, "\n" ); - p += sprintf( p, "

404 Ressource not found

\n" ); + p += sprintf( p, "

401 authentification needed

\n" ); p += sprintf( p, "
\n" ); - p += sprintf( p, "VideoLAN\n" ); + p += sprintf( p, "VideoLAN\n" ); p += sprintf( p, "\n" ); p += sprintf( p, "\n" ); @@ -960,270 +1243,128 @@ static int httpd_page_404_get( httpd_file_callback_args_t *p_args, return VLC_SUCCESS; } - - -static int _httpd_page_admin_get_status( httpd_file_callback_args_t *p_args, - uint8_t **pp_data, int *pi_data ) +static int httpd_page_404_get( httpd_file_callback_args_t *p_args, + uint8_t *p_request, int i_request, + uint8_t **pp_data, int *pi_data ) { - httpd_sys_t *p_httpt = (httpd_sys_t*)p_args; - httpd_connection_t *p_con; - int i; char *p; - /* FIXME FIXME do not use static size FIXME FIXME*/ - p = *pp_data = malloc( 8096 ); - - p += sprintf( p, "\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "VideoLAN Client Stream Output\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "

VideoLAN Client Stream Output

\n" ); - p += sprintf( p, "

Admin page

\n" ); - - /* general */ - p += sprintf( p, "

General state

\n" ); - p += sprintf( p, "
    \n" ); - p += sprintf( p, "
  • Connection count: %d
  • \n", p_httpt->i_connection_count ); - //p += sprintf( p, "
  • Total bandwith: %d
  • \n", -1 ); - /*p += sprintf( p, "
  • \n" );*/ - p += sprintf( p, "
\n" ); - /* host list */ - vlc_mutex_lock( &p_httpt->host_lock ); - p += sprintf( p, "

Host list

\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "\n\n\n" ); - - for( i = 0; i < p_httpt->i_host_count; i++ ) - { - p += sprintf( p, "\n" ); - p += sprintf( p, "\n", p_httpt->host[i]->psz_host_addr ); - p += sprintf( p, "\n", p_httpt->host[i]->i_port ); - p += sprintf( p, "\n", inet_ntoa( p_httpt->host[i]->sock.sin_addr ) ); - p += sprintf( p, "\n" ); - } - p += sprintf( p, "
HostPortIP
%s%d%s
\n" ); - vlc_mutex_unlock( &p_httpt->host_lock ); - - /* file list */ - /* XXX do not take lock on file_lock */ - p += sprintf( p, "

File list

\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "\n\n\n" ); - - for( i = 0; i < p_httpt->i_file_count; i++ ) - { - if( !p_httpt->file[i]->b_stream ) - { - p += sprintf( p, "\n" ); - p += sprintf( p, "\n", p_httpt->file[i]->psz_file ); - p += sprintf( p, "\n", p_httpt->file[i]->psz_mime ); - p += sprintf( p, "\n", p_httpt->file[i]->psz_user ? "Yes" : "No" ); - p += sprintf( p, "\n", p_httpt->file[i]->i_ref); - p += sprintf( p, "\n" ); - } - } - p += sprintf( p, "
NameMimeProtectedUsed
%s%s%s%d
\n" ); - - /* stream list */ - /* XXX do not take lock on file_lock */ - p += sprintf( p, "

Stream list

\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "\n\n\n" ); - - for( i = 0; i < p_httpt->i_file_count; i++ ) - { - if( p_httpt->file[i]->b_stream ) - { - p += sprintf( p, "\n" ); - p += sprintf( p, "\n", p_httpt->file[i]->psz_file ); - p += sprintf( p, "\n", p_httpt->file[i]->psz_mime ); - p += sprintf( p, "\n", p_httpt->file[i]->psz_user ? "Yes" : "No" ); - p += sprintf( p, "\n", p_httpt->file[i]->i_ref); - p += sprintf( p, "\n" ); - } - } - p += sprintf( p, "
NameMimeProtectedUsed
%s%s%s%d
\n" ); - - /* connection list */ - /* XXX do not take lock on connection_lock */ - p += sprintf( p, "

Connection list

\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "\n\n\n" ); - - for( p_con = p_httpt->p_first_connection;p_con != NULL; p_con = p_con->p_next ) + p = *pp_data = malloc( 1024 ); + if( !p ) { - p += sprintf( p, "\n" ); - p += sprintf( p, "\n", inet_ntoa( p_con->sock.sin_addr ) ); - p += sprintf( p, "\n", p_con->psz_file ); - p += sprintf( p, "\n", p_con->i_http_error ); - p += sprintf( p, "\n", p_con); - p += sprintf( p, "\n" ); + return VLC_ENOMEM ; } - p += sprintf( p, "
IPRequested FileStatusAction
%s%s%d
" - "" - "" - "" - "
\n" ); - - - /* www.videolan.org */ - p += sprintf( p, "
\n" ); - p += sprintf( p, "VideoLAN\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "\n" ); - - *pi_data = strlen( *pp_data ) + 1; - - return( VLC_SUCCESS ); -} - -static int _httpd_page_admin_get_success( httpd_file_callback_args_t *p_args, - uint8_t **pp_data, int *pi_data, - char *psz_msg ) -{ - char *p; - - p = *pp_data = malloc( 8096 ); p += sprintf( p, "\n" ); p += sprintf( p, "\n" ); - p += sprintf( p, "VideoLAN Client Stream Output\n" ); + p += sprintf( p, "Error 404\n" ); p += sprintf( p, "\n" ); p += sprintf( p, "\n" ); - p += sprintf( p, "

VideoLAN Client Stream Output

\n" ); - - p += sprintf( p, "

Success=`%s'

", psz_msg ); - + p += sprintf( p, "

404 Ressource not found

\n" ); p += sprintf( p, "
\n" ); - p += sprintf( p, "VideoLAN\n" ); + p += sprintf( p, "VideoLAN\n" ); p += sprintf( p, "\n" ); p += sprintf( p, "\n" ); *pi_data = strlen( *pp_data ) + 1; - return( VLC_SUCCESS ); + return VLC_SUCCESS; } -static int _httpd_page_admin_get_error( httpd_file_callback_args_t *p_args, - uint8_t **pp_data, int *pi_data, - char *psz_error ) +#if 0 +static int httpd_BanIP( httpd_sys_t *p_httpt, char * psz_new_banned_ip) { - char *p; - - p = *pp_data = malloc( 8096 ); + httpd_banned_ip_t *p_new_banned_ip ; - p += sprintf( p, "\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "VideoLAN Client Stream Output\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "

VideoLAN Client Stream Output

\n" ); - - p += sprintf( p, "

Error=`%s'

", psz_error ); - - p += sprintf( p, "
\n" ); - p += sprintf( p, "VideoLAN\n" ); - p += sprintf( p, "\n" ); - p += sprintf( p, "\n" ); - - *pi_data = strlen( *pp_data ) + 1; + p_new_banned_ip = malloc( sizeof( httpd_banned_ip_t ) ); + if( !p_new_banned_ip ) + { + return -1; + } + p_new_banned_ip->p_next=NULL; + p_new_banned_ip->psz_ip = malloc( strlen( psz_new_banned_ip ) + 1 ); + if( !p_new_banned_ip->psz_ip ) + { + return -2; + } - return( VLC_SUCCESS ); -} + strcpy( p_new_banned_ip->psz_ip, psz_new_banned_ip ); -static void _httpd_uri_extract_value( char *psz_uri, char *psz_name, char *psz_value, int i_value_max ) -{ - char *p; + msg_Dbg( p_httpt, "Banning IP %s", psz_new_banned_ip ); - p = strstr( psz_uri, psz_name ); - if( p ) + if( p_httpt->p_first_banned_ip ) { - int i_len; - - p += strlen( psz_name ); - if( *p == '=' ) p++; + httpd_banned_ip_t *p_last; - if( strchr( p, '&' ) ) - { - i_len = strchr( p, '&' ) - p; - } - else - { - i_len = strlen( p ); - } - i_len = __MIN( i_value_max - 1, i_len ); - if( i_len > 0 ) - { - strncpy( psz_value, p, i_len ); - psz_value[i_len] = '\0'; - } - else + p_last = p_httpt->p_first_banned_ip; + while( p_last->p_next ) { - strncpy( psz_value, "", i_value_max ); + p_last = p_last->p_next; } + + p_last->p_next = p_new_banned_ip; + p_new_banned_ip->p_prev = p_last; } else { - strncpy( psz_value, "", i_value_max ); - } -} + p_new_banned_ip->p_prev = NULL; + p_httpt->p_first_banned_ip = p_new_banned_ip; + } -static int httpd_page_admin_get( httpd_file_callback_args_t *p_args, - uint8_t *p_request, int i_request, - uint8_t **pp_data, int *pi_data ) + p_httpt->i_banned_ip_count++; + return 0; +} +#endif +static httpd_banned_ip_t *httpd_GetbannedIP( httpd_sys_t *p_httpt, char *psz_ip ) { - httpd_sys_t *p_httpt = (httpd_sys_t*)p_args; - httpd_connection_t *p_con; - int i; + httpd_banned_ip_t *p_ip; + + p_ip = p_httpt->p_first_banned_ip; - if( i_request > 0) + while( p_ip) { - char action[512]; + if( strcmp( psz_ip, p_ip->psz_ip ) == 0 ) + { + return p_ip; + } + p_ip = p_ip->p_next; + } - _httpd_uri_extract_value( p_request, "action", action, 512 ); + return NULL; +} - if( !strcmp( action, "close_connection" ) ) - { - char id[128]; - void *i_id; +static int httpd_UnbanIP( httpd_sys_t *p_httpt, httpd_banned_ip_t *p_banned_ip ) +{ + if(!p_banned_ip) + { + return -1; + } - _httpd_uri_extract_value( p_request, "id", id, 512 ); - i_id = (void*)strtol( id, NULL, 0 ); - msg_Dbg( p_httpt, "requested closing connection id=%s %p", id, i_id ); - for( p_con = p_httpt->p_first_connection;p_con != NULL; p_con = p_con->p_next ) - { - if( (void*)p_con == i_id ) - { - /* XXX don't free p_con as it could be the one that it is sending ... */ - p_con->i_state = HTTPD_CONNECTION_TO_BE_CLOSED; - return( _httpd_page_admin_get_success( p_args, pp_data, pi_data, "connection closed" ) ); - } - } - return( _httpd_page_admin_get_error( p_args, pp_data, pi_data, "invalid id" ) ); - } - else if( !strcmp( action, "ban_ip" ) ) - { - msg_Dbg( p_httpt, "requested banning ip" ); - return( _httpd_page_admin_get_success( p_args, pp_data, pi_data, "ip banned" ) ); - } - else - { - return( _httpd_page_admin_get_error( p_args, pp_data, pi_data, action ) ); - } + msg_Dbg( p_httpt, "Unbanning IP %s",p_banned_ip->psz_ip); + + /* first cut out from list */ + if( p_banned_ip->p_prev ) + { + p_banned_ip->p_prev->p_next = p_banned_ip->p_next; } else { - return( _httpd_page_admin_get_status( p_args, pp_data, pi_data ) ); + p_httpt->p_first_banned_ip = p_banned_ip->p_next; } - return VLC_SUCCESS; -} + if( p_banned_ip->p_next ) + { + p_banned_ip->p_next->p_prev = p_banned_ip->p_prev; + } + + FREE( p_banned_ip->psz_ip ); + FREE( p_banned_ip ); + + p_httpt->i_banned_ip_count--; + return 0; +} static void httpd_ConnnectionNew( httpd_sys_t *p_httpt, int fd, struct sockaddr_in *p_sock ) { @@ -1231,8 +1372,21 @@ static void httpd_ConnnectionNew( httpd_sys_t *p_httpt, int fd, struct sockaddr_ msg_Dbg( p_httpt, "new connection from %s", inet_ntoa( p_sock->sin_addr ) ); + /* verify if it's a banned ip */ + if(httpd_GetbannedIP( p_httpt,inet_ntoa( p_sock->sin_addr ) ) ) + { + msg_Dbg( p_httpt, "Ip %s banned : closing connection", inet_ntoa( p_sock->sin_addr ) ); + close(fd); + return; + } + /* create a new connection and link it */ p_con = malloc( sizeof( httpd_connection_t ) ); + if( !p_con ) + { + msg_Err( p_httpt, "Out of memory" ); + return; + } p_con->i_state = HTTPD_CONNECTION_RECEIVING_REQUEST; p_con->fd = fd; p_con->i_last_activity_date = mdate(); @@ -1250,8 +1404,13 @@ static void httpd_ConnnectionNew( httpd_sys_t *p_httpt, int fd, struct sockaddr_ p_con->i_buffer = 0; p_con->i_buffer_size = 8096; p_con->p_buffer = malloc( p_con->i_buffer_size ); + if( !p_con->p_buffer ) + { + msg_Err( p_httpt, "Out of memory"); + return ; + } - p_con->i_stream_pos = 0; // updated by httpd_thread */ + p_con->i_stream_pos = 0; /* updated by httpd_thread */ p_con->p_next = NULL; if( p_httpt->p_first_connection ) @@ -1352,7 +1511,7 @@ static int httpd_RequestNextLine( char **pp_buffer, char *p_end ) return VLC_EGENERIC; } -//char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +/*char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";*/ static void b64_decode( char *dest, char *src ) { int i_level; @@ -1416,13 +1575,15 @@ static void httpd_ConnectionParseRequest( httpd_sys_t *p_httpt, httpd_connection char *p, *p_end; int i; + int b_xplaystream = VLC_FALSE; + /* Size is checked for all of these */ char command[32]; char url[1024]; char version[32]; char user[512] = ""; char password[512] = ""; - //msg_Dbg( p_httpt, "new request=\n%s", p_con->p_buffer ); + msg_Dbg( p_httpt, "new request=\n%s", p_con->p_buffer ); p = p_con->p_buffer; @@ -1431,8 +1592,9 @@ static void httpd_ConnectionParseRequest( httpd_sys_t *p_httpt, httpd_connection httpd_RequestGetWord( command, 32, &p, p_end ); httpd_RequestGetWord( url, 1024, &p, p_end ); httpd_RequestGetWord( version, 32, &p, p_end ); - //msg_Dbg( p_httpt, "ask =%s= =%s= =%s=", command, url, version ); - +#if 0 + msg_Dbg( p_httpt, "ask =%s= =%s= =%s=", command, url, version ); +#endif p_con->p_request = NULL; p_con->i_request_size = 0; if( !strcmp( command, "GET" ) ) @@ -1443,6 +1605,10 @@ static void httpd_ConnectionParseRequest( httpd_sys_t *p_httpt, httpd_connection { p_con->i_method = HTTPD_CONNECTION_METHOD_POST; } + else if( !strcmp( command, "HEAD" )) + { + p_con->i_method = HTTPD_CONNECTION_METHOD_HEAD; + } else { /* unimplemented */ @@ -1467,11 +1633,14 @@ static void httpd_ConnectionParseRequest( httpd_sys_t *p_httpt, httpd_connection if( httpd_RequestNextLine( &p, p_end ) ) { - //msg_Dbg( p_httpt, "failled new line" ); +#if 0 + msg_Dbg( p_httpt, "failled new line" ); +#endif break;; } - //msg_Dbg( p_httpt, "new line=%s", p ); - +#if 0 + msg_Dbg( p_httpt, "new line=%s", p ); +#endif httpd_RequestGetWord( header, 1024, &p, p_end ); if( !strcmp( header, "\r\n" ) || !strcmp( header, "\n" ) ) { @@ -1489,10 +1658,13 @@ static void httpd_ConnectionParseRequest( httpd_sys_t *p_httpt, httpd_connection char decoded[1024]; httpd_RequestGetWord( basic, 1024, &p, p_end ); - //msg_Dbg( p_httpt, "Authorization: basic:%s", basic ); +#if 0 + msg_Dbg( p_httpt, "Authorization: basic:%s", basic ); +#endif b64_decode( decoded, basic ); - - //msg_Dbg( p_httpt, "Authorization: decoded:%s", decoded ); +#if 0 + msg_Dbg( p_httpt, "Authorization: decoded:%s", decoded ); +#endif if( strchr( decoded, ':' ) ) { char *p = strchr( decoded, ':' ); @@ -1503,6 +1675,16 @@ static void httpd_ConnectionParseRequest( httpd_sys_t *p_httpt, httpd_connection } } } + else if( !strcmp( header, "Pragma:" ) ) + { + char method[128]; + + httpd_RequestGetWord( method, 128, &p, p_end ); + if( !strcasecmp( method, "xPlayStrm=1" ) ) + { + b_xplaystream = VLC_TRUE; + } + } } if( strchr( url, '?' ) ) @@ -1538,7 +1720,11 @@ static void httpd_ConnectionParseRequest( httpd_sys_t *p_httpt, httpd_connection { p_con->i_request_size = p_end - p_request; p_con->p_request = malloc( p_con->i_request_size + 1); - + if( !p_con->p_request) + { + msg_Err( p_httpt, "Out of memory" ); + return; + } memcpy( p_con->p_request, p_request, p_con->i_request_size ); @@ -1549,20 +1735,27 @@ static void httpd_ConnectionParseRequest( httpd_sys_t *p_httpt, httpd_connection p_con->i_http_error = 200; create_header: - //msg_Dbg( p_httpt, "ask %s %s %d", command, p_con->psz_file, p_con->i_http_error ); +#if 0 + msg_Dbg( p_httpt, "ask %s %s %d", command, p_con->psz_file, p_con->i_http_error ); +#endif FREE( p_con->p_buffer ); p_con->i_buffer = 0; p_con->i_buffer_size = 0; - //vlc_mutex_lock( &p_httpt->file_lock ); +#if 0 + vlc_mutex_lock( &p_httpt->file_lock ); +#endif search_file: /* search file */ p_con->p_file = NULL; for( i = 0; i < p_httpt->i_file_count; i++ ) { + /* Our strdup call failed */ + if( !p_con->psz_file ) return; if( !strcmp( p_httpt->file[i]->psz_file, p_con->psz_file ) ) { if( p_httpt->file[i]->b_stream || + p_con->i_method == HTTPD_CONNECTION_METHOD_HEAD || ( p_con->i_method == HTTPD_CONNECTION_METHOD_GET && p_httpt->file[i]->pf_get ) || ( p_con->i_method == HTTPD_CONNECTION_METHOD_POST && p_httpt->file[i]->pf_post ) ) { @@ -1576,33 +1769,48 @@ search_file: { p_con->psz_file = strdup( "/404.html" ); p_con->i_http_error = 404; + p_con->i_method = HTTPD_CONNECTION_METHOD_GET; /* XXX be sure that "/404.html" exist else ... */ goto search_file; } - if( p_con->p_file->i_authenticate_method == HTTPD_AUTHENTICATE_BASIC ) { - if( strcmp( user, p_con->p_file->psz_user ) || strcmp( password, p_con->p_file->psz_password ) ) + if( strcmp( user, p_con->p_file->psz_user ) || + strcmp( password, p_con->p_file->psz_password ) ) { p_con->psz_file = strdup( "/401.html" ); strcpy( user, p_con->p_file->psz_user ); p_con->i_http_error = 401; + p_con->i_method = HTTPD_CONNECTION_METHOD_GET; /* XXX do not put password on 404 else ... */ goto search_file; } } + if( !strcmp( p_con->p_file->psz_mime, "video/x-ms-asf-stream" ) && + p_con->i_method == HTTPD_CONNECTION_METHOD_POST ) + { + p_con->psz_file = strdup( "/400.html" ); + p_con->i_http_error = 400; + p_con->i_method = HTTPD_CONNECTION_METHOD_GET; + + goto search_file; + } p_con->p_file->i_ref++; -// vlc_mutex_unlock( &p_httpt->file_lock ); +#if 0 + vlc_mutex_unlock( &p_httpt->file_lock ); +#endif switch( p_con->i_http_error ) { case 200: psz_status = "OK"; break; - + case 400: + psz_status = "Bad Request"; + break; case 401: psz_status = "Authorization Required"; break; @@ -1613,27 +1821,66 @@ search_file: p_con->i_state = HTTPD_CONNECTION_SENDING_HEADER; + p_con->i_buffer_size = 4096; + p_con->i_buffer = 0; + /* we send stream header with this one */ if( p_con->i_http_error == 200 && p_con->p_file->b_stream ) { - p_con->i_buffer_size = 4096 + p_con->p_file->i_header_size; + p_con->i_buffer_size += p_con->p_file->i_header_size; } - p_con->i_buffer_size = 4096; - p_con->i_buffer = 0; p = p_con->p_buffer = malloc( p_con->i_buffer_size ); - + if( !p) + { + msg_Err( p_httpt, "Out of memory" ); + return; + } p += sprintf( p, "HTTP/1.0 %d %s\r\n", p_con->i_http_error, psz_status ); - p += sprintf( p, "Content-type: %s\r\n", p_con->p_file->psz_mime ); + + /* Special mmsh case cludgy but ...*/ + if( !strcmp( p_con->p_file->psz_mime, "video/x-ms-asf-stream" ) && + p_con->i_method == HTTPD_CONNECTION_METHOD_GET ) + { + p += sprintf( p, "Content-type: application/octet-stream\r\n" ); + p += sprintf( p, "Server: Cougar 4.1.0.3921\r\n" ); + p += sprintf( p, "Cache-Control: no-cache\r\n" ); + p += sprintf( p, "Pragma: no-cache\r\n" ); + p += sprintf( p, "Pragma: client-id=%d\r\n", rand()&0x7fff ); + p += sprintf( p, "Pragma: features=\"broadcast\"\r\n" ); + + if( !b_xplaystream ) + { + p_con->i_method = HTTPD_CONNECTION_METHOD_ASFHEAD; + } + } + else + { + p += sprintf( p, "Content-type: %s\r\n", p_con->p_file->psz_mime ); + p += sprintf( p, "Cache-Control: no-cache\r\n" ); + } if( p_con->i_http_error == 401 ) { p += sprintf( p, "WWW-Authenticate: Basic realm=\"%s\"\r\n", user ); } +#if 0 + if( p_con->i_method == HTTPD_CONNECTION_METHOD_HEAD ) + { + p += sprintf( p, "Content-Length: 0\r\n" ); + } + else if( p_con->i_method == HTTPD_CONNECTION_METHOD_ASFHEAD && + p_con->p_file->i_header_size > 0 ) + { + p += sprintf( p, "Content-Length: %d\r\n", p_con->p_file->i_header_size ); + } +#endif p += sprintf( p, "\r\n" ); p_con->i_buffer_size = strlen( p_con->p_buffer );// + 1; - if( p_con->i_http_error == 200 && p_con->p_file->b_stream && p_con->p_file->i_header_size > 0 ) + if( p_con->i_http_error == 200 && + p_con->i_method != HTTPD_CONNECTION_METHOD_HEAD && + p_con->p_file->b_stream && p_con->p_file->i_header_size > 0 ) { /* add stream header */ memcpy( &p_con->p_buffer[p_con->i_buffer_size], @@ -1642,12 +1889,18 @@ search_file: p_con->i_buffer_size += p_con->p_file->i_header_size; } - //msg_Dbg( p_httpt, "answer=\n%s", p_con->p_buffer ); + if( p_con->i_method == HTTPD_CONNECTION_METHOD_ASFHEAD ) + { + p_con->i_method = HTTPD_CONNECTION_METHOD_HEAD; + } +#if 0 + msg_Dbg( p_httpt, "answer=\n%s", p_con->p_buffer ); +#endif } #define HTTPD_STREAM_PACKET 10000 static void httpd_Thread( httpd_sys_t *p_httpt ) { - httpd_file_t *p_page_admin; + httpd_file_t *p_page_400; httpd_file_t *p_page_401; httpd_file_t *p_page_404; @@ -1655,6 +1908,13 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) msg_Info( p_httpt, "httpd started" ); + p_page_400 = _RegisterFile( p_httpt, + "/400.html", "text/html", + NULL, NULL, + httpd_page_400_get, + NULL, + (httpd_file_callback_args_t*)NULL ); + p_page_401 = _RegisterFile( p_httpt, "/401.html", "text/html", NULL, NULL, @@ -1667,12 +1927,6 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) httpd_page_404_get, NULL, (httpd_file_callback_args_t*)NULL ); - p_page_admin = _RegisterFile( p_httpt, - "/admin.html", "text/html", - "admin", "salut", - httpd_page_admin_get, - NULL, - (httpd_file_callback_args_t*)p_httpt ); while( !p_httpt->b_die ) { @@ -1738,7 +1992,7 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) timeout.tv_sec = 0; timeout.tv_usec = 500*1000; - i_ret = select( i_handle_max + 1, + i_ret = select( i_handle_max + 1, &fds_read, &fds_write, NULL, @@ -1749,9 +2003,9 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) msleep( 1000 ); continue; } + if( i_ret <= 0 ) { -// msg_Dbg( p_httpt, "waiting..." ); continue; } @@ -1801,8 +2055,12 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) p_con->p_buffer + p_con->i_buffer, p_con->i_buffer_size - p_con->i_buffer, 0 ); - if( ( i_len < 0 && errno != EAGAIN && errno != EINTR )|| - ( i_len == 0 ) ) + +#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 { httpd_connection_t *p_next = p_con->p_next; @@ -1846,10 +2104,15 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) { i_len = 0; } -// msg_Warn( p_httpt, "on %d send %d bytes %s", p_con->i_buffer_size, i_len, p_con->p_buffer + p_con->i_buffer ); +#if 0 + msg_Warn( p_httpt, "on %d send %d bytes %s", p_con->i_buffer_size, i_len, p_con->p_buffer + p_con->i_buffer ); +#endif - if( ( i_len < 0 && errno != EAGAIN && errno != EINTR )|| - ( i_len == 0 ) ) +#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 { httpd_connection_t *p_next = p_con->p_next; @@ -1869,9 +2132,9 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) p_con->i_buffer = 0; FREE( p_con->p_buffer ); - if( !p_con->p_file->b_stream ) + if( !p_con->p_file->b_stream || p_con->i_method == HTTPD_CONNECTION_METHOD_HEAD ) { - p_con->i_state = HTTPD_CONNECTION_SENDING_FILE; // be sure to out from HTTPD_CONNECTION_SENDING_HEADER + p_con->i_state = HTTPD_CONNECTION_SENDING_FILE; /* be sure to out from HTTPD_CONNECTION_SENDING_HEADER */ if( p_con->i_method == HTTPD_CONNECTION_METHOD_GET ) { p_con->p_file->pf_get( p_con->p_file->p_sys, @@ -1886,6 +2149,7 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) } else { + /* HTTPD_CONNECTION_METHOD_HEAD for example */ p_con->p_buffer = NULL; p_con->i_buffer_size = 0; } @@ -1928,7 +2192,8 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) /* check if this p_con aren't to late */ if( p_con->i_stream_pos + p_stream->i_buffer_size < p_stream->i_buffer_pos ) { - fprintf(stderr, "fixing i_stream_pos (old=%lld i_buffer_pos=%lld\n", p_con->i_stream_pos, p_stream->i_buffer_pos ); + fprintf( stderr, "fixing i_stream_pos (old=%lld i_buffer_pos=%lld\n", + p_con->i_stream_pos, p_stream->i_buffer_pos ); p_con->i_stream_pos = p_stream->i_buffer_last_pos; } @@ -1947,7 +2212,11 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) } i_send = send( p_con->fd, &p_stream->p_buffer[i_pos], i_write, 0 ); +#if defined( WIN32 ) || defined( UNDER_CE ) + if( ( i_send < 0 && WSAGetLastError() != WSAEWOULDBLOCK )|| ( i_send == 0 ) ) +#else if( ( i_send < 0 && errno != EAGAIN && errno != EINTR )|| ( i_send == 0 ) ) +#endif { httpd_connection_t *p_next = p_con->p_next; @@ -1973,9 +2242,10 @@ static void httpd_Thread( httpd_sys_t *p_httpt ) vlc_mutex_unlock( &p_httpt->file_lock ); } + msg_Info( p_httpt, "httpd stopped" ); + _UnregisterFile( p_httpt, p_page_400 ); _UnregisterFile( p_httpt, p_page_401 ); _UnregisterFile( p_httpt, p_page_404 ); - _UnregisterFile( p_httpt, p_page_admin ); }