X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fnetwork%2Fhttpd.c;h=24e5d9bb1d10a7332f673b30948b65bb873b128a;hb=bee10796b392ea8a0f708728e1e2fc59440b44e9;hp=7bd37020a92663cf9d7a0f7553bfe87c02529ace;hpb=e732cff5c58c4ef4df7f7869405f7002aed94036;p=vlc diff --git a/src/network/httpd.c b/src/network/httpd.c index 7bd37020a9..24e5d9bb1d 100644 --- a/src/network/httpd.c +++ b/src/network/httpd.c @@ -2,6 +2,7 @@ * httpd.c ***************************************************************************** * Copyright (C) 2004-2006 the VideoLAN team + * Copyright © 2004-2007 Rémi Denis-Courmont * $Id$ * * Authors: Laurent Aimar @@ -24,9 +25,6 @@ #include -#include -#include - #ifdef ENABLE_HTTPD #include @@ -35,6 +33,7 @@ #include #include #include +#include #include "../libvlc.h" #include @@ -94,10 +93,6 @@ struct httpd_host_t int *fds; unsigned nfd; - /* Statistics */ - counter_t *p_active_counter; - counter_t *p_total_counter; - vlc_mutex_t lock; /* all registered url (becarefull that 2 httpd_url_t could point at the same url) @@ -190,66 +185,9 @@ struct httpd_client_t /***************************************************************************** * Various functions *****************************************************************************/ -/*char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";*/ -static void b64_decode( char *restrict dest, const char *restrict src ) -{ - int i_level; - int last = 0; - int b64[256] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */ - 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */ - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */ - 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */ - -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */ - 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */ - }; - - for( i_level = 0; *src != '\0'; src++ ) - { - int c; - - c = b64[(unsigned int)*src]; - if( c == -1 ) - { - continue; - } - - switch( i_level ) - { - case 0: - i_level++; - break; - case 1: - *dest++ = ( last << 2 ) | ( ( c >> 4)&0x03 ); - i_level++; - break; - case 2: - *dest++ = ( ( last << 4 )&0xf0 ) | ( ( c >> 2 )&0x0f ); - i_level++; - break; - case 3: - *dest++ = ( ( last &0x03 ) << 6 ) | c; - i_level = 0; - } - last = c; - } - - *dest = '\0'; -} - static struct { - const char *psz_ext; + const char psz_ext[8]; const char *psz_mime; } http_mime[] = { @@ -292,7 +230,7 @@ static struct /* end */ - { NULL, NULL } + { "", "" } }; static const char *httpd_MimeFromUrl( const char *psz_url ) @@ -305,7 +243,7 @@ static const char *httpd_MimeFromUrl( const char *psz_url ) { int i; - for( i = 0; http_mime[i].psz_ext != NULL ; i++ ) + for( i = 0; http_mime[i].psz_ext[0] ; i++ ) { if( !strcasecmp( http_mime[i].psz_ext, psz_ext ) ) { @@ -706,6 +644,7 @@ static int httpd_RedirectCallBack( httpd_callback_sys_t *p_sys, { httpd_redirect_t *rdir = (httpd_redirect_t*)p_sys; char *p_body; + (void)cl; if( answer == NULL || query == NULL ) { @@ -1054,8 +993,8 @@ httpd_host_t *httpd_TLSHostNew( vlc_object_t *p_this, const char *psz_hostname, } /* to be sure to avoid multiple creation */ - var_Create( p_this->p_libvlc_global, "httpd_mutex", VLC_VAR_MUTEX ); - var_Get( p_this->p_libvlc_global, "httpd_mutex", &lockval ); + var_Create( p_this->p_libvlc, "httpd_mutex", VLC_VAR_MUTEX ); + var_Get( p_this->p_libvlc, "httpd_mutex", &lockval ); vlc_mutex_lock( lockval.p_address ); if( !(httpd = vlc_object_find( p_this, VLC_OBJECT_HTTPD, FIND_ANYWHERE )) ) @@ -1196,7 +1135,7 @@ void httpd_HostDelete( httpd_host_t *host ) vlc_value_t lockval; int i; - var_Get( httpd->p_libvlc_global, "httpd_mutex", &lockval ); + var_Get( httpd->p_libvlc, "httpd_mutex", &lockval ); vlc_mutex_lock( lockval.p_address ); host->i_ref--; @@ -1209,7 +1148,7 @@ void httpd_HostDelete( httpd_host_t *host ) } TAB_REMOVE( httpd->i_host, httpd->host, host ); - host->b_die = 1; + vlc_object_kill( host ); vlc_thread_join( host ); msg_Dbg( host, "HTTP host removed" ); @@ -1433,19 +1372,19 @@ void httpd_MsgAdd( httpd_message_t *msg, const char *name, const char *psz_value char *value = NULL; va_start( args, psz_value ); -#if defined(HAVE_VASPRINTF) && !defined(__APPLE__) && !defined(SYS_BEOS) - vasprintf( &value, psz_value, args ); -#else - { - int i_size = strlen( psz_value ) + 4096; /* FIXME stupid system */ - value = calloc( i_size, sizeof( char ) ); - vsnprintf( value, i_size, psz_value, args ); - value[i_size - 1] = 0; - } -#endif + if( vasprintf( &value, psz_value, args ) == -1 ) + value = NULL; va_end( args ); + if( value == NULL ) + return; + name = strdup( name ); + if( name == NULL ) + { + free( value ); + return; + } TAB_APPEND( msg->i_name, msg->name, (char*)name ); TAB_APPEND( msg->i_value, msg->value, value ); @@ -2016,11 +1955,8 @@ static void httpd_ClientTlsHsOut( httpd_client_t *cl ) static void httpd_HostThread( httpd_host_t *host ) { tls_session_t *p_tls = NULL; - - host->p_total_counter = stats_CounterCreate( host, - VLC_VAR_INTEGER, STATS_COUNTER ); - host->p_active_counter = stats_CounterCreate( host, - VLC_VAR_INTEGER, STATS_COUNTER ); + 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 ); while( !host->b_die ) { @@ -2035,9 +1971,9 @@ static void httpd_HostThread( httpd_host_t *host ) if( ( p_tls == NULL ) && ( host->p_tls != NULL ) ) p_tls = tls_ServerSessionPrepare( host->p_tls ); - struct pollfd ufd[host->nfd + host->i_client + host->nfd]; /* We have nfd listening sockets, i_client, and lay accept up to nfd new client */ + struct pollfd ufd[host->nfd + host->i_client]; unsigned nfd; - for (nfd = 0; nfd < host->nfd; nfd++) + for( nfd = 0; nfd < host->nfd; nfd++ ) { ufd[nfd].fd = host->fds[nfd]; ufd[nfd].events = POLLIN; @@ -2058,7 +1994,7 @@ static void httpd_HostThread( httpd_host_t *host ) cl->i_activity_date+cl->i_activity_timeout < now) ) ) ) { httpd_ClientClean( cl ); - stats_UpdateInteger( host, host->p_active_counter, -1, NULL ); + stats_UpdateInteger( host, p_active_counter, -1, NULL ); TAB_REMOVE( host->i_client, host->client, cl ); free( cl ); i_client--; @@ -2195,54 +2131,51 @@ static void httpd_HostThread( httpd_host_t *host ) { char ip[NI_MAXNUMERICHOST]; - if( httpd_ClientIP( cl, ip ) != NULL ) + if( ( httpd_ClientIP( cl, ip ) == NULL ) + || ACL_Check( url->p_acl, ip ) ) { - if( ACL_Check( url->p_acl, ip ) ) - { - b_hosts_failed = VLC_TRUE; - break; - } - } - else b_hosts_failed = VLC_TRUE; + break; + } } if( answer && ( *url->psz_user || *url->psz_password ) ) { /* create the headers */ const char *b64 = httpd_MsgGet( query, "Authorization" ); /* BASIC id */ - char *auth; - char *id; + char *user = NULL, *pass = NULL; - asprintf( &id, "%s:%s", url->psz_user, url->psz_password ); if( b64 != NULL - && !strncasecmp( b64, "BASIC", 5 ) ) + && !strncasecmp( b64, "BASIC", 5 ) ) { b64 += 5; while( *b64 == ' ' ) - { b64++; + + user = vlc_b64_decode( b64 ); + if (user != NULL) + { + pass = strchr (user, ':'); + if (pass != NULL) + *pass++ = '\0'; } - auth = malloc( strlen(b64) + 1 ); - b64_decode( auth, b64 ); - } - else - { - auth = strdup( "" ); } - if( strcmp( id, auth ) ) + if ((user == NULL) || (pass == NULL) + || strcmp (user, url->psz_user) + || strcmp (pass, url->psz_password)) { - httpd_MsgAdd( answer, "WWW-Authenticate", "Basic realm=\"%s\"", url->psz_user ); + httpd_MsgAdd( answer, + "WWW-Authenticate", + "Basic realm=\"%s\"", + url->psz_user ); /* We fail for all url */ b_auth_failed = VLC_TRUE; - free( id ); - free( auth ); + free( user ); break; } - free( id ); - free( auth ); + free( user ); } if( !url->catch[i_msg].cb( url->catch[i_msg].p_sys, cl, answer, query ) ) @@ -2414,7 +2347,7 @@ static void httpd_HostThread( httpd_host_t *host ) vlc_mutex_unlock( &host->lock ); /* we will wait 100ms or 20ms (not too big 'cause HTTPD_CLIENT_WAITING) */ - switch (poll (ufd, nfd, b_low_delay ? 20 : 100)) + switch( poll( ufd, nfd, b_low_delay ? 20 : 100) ) { case -1: if (errno != EINTR) @@ -2427,29 +2360,73 @@ static void httpd_HostThread( httpd_host_t *host ) continue; } + /* Handle client sockets */ + vlc_mutex_lock( &host->lock ); now = mdate(); + for( int i_client = 0; i_client < host->i_client; i_client++ ) + { + httpd_client_t *cl = host->client[i_client]; + const struct pollfd *pufd = &ufd[host->nfd + i_client]; - /* accept new connections */ - for (nfd = 0; nfd < host->nfd; nfd++) + assert( pufd < &ufd[sizeof(ufd) / sizeof(ufd[0])] ); + + if( cl->fd != pufd->fd ) + continue; // we were not waiting for this client + if( pufd->revents == 0 ) + continue; // no event received + + cl->i_activity_date = now; + + if( cl->i_state == HTTPD_CLIENT_RECEIVING ) + { + httpd_ClientRecv( cl ); + } + else if( cl->i_state == HTTPD_CLIENT_SENDING ) + { + httpd_ClientSend( cl ); + } + else if( cl->i_state == HTTPD_CLIENT_TLS_HS_IN ) + { + httpd_ClientTlsHsIn( cl ); + } + else if( cl->i_state == HTTPD_CLIENT_TLS_HS_OUT ) + { + httpd_ClientTlsHsOut( cl ); + } + + if( cl->i_mode == HTTPD_CLIENT_BIDIR && + cl->i_state == HTTPD_CLIENT_SENDING && + (pufd->revents & POLLIN) ) + { + cl->b_read_waiting = VLC_TRUE; + } + } + vlc_mutex_unlock( &host->lock ); + + /* Handle server sockets (accept new connections) */ + for( nfd = 0; nfd < host->nfd; nfd++ ) { + httpd_client_t *cl; + int i_state = -1; + assert (ufd[nfd].fd == host->fds[nfd]); - if (ufd[nfd].revents == 0) + if( ufd[nfd].revents == 0 ) continue; - int fd = net_Accept (host, host->fds, 0); - if (fd == -1) + /* */ + int kludge[] = { ufd[nfd].fd, -1 }; + int fd = net_Accept( host, kludge, 0 ); + if( fd < 0 ) continue; - int i_state = 0; - - if (p_tls != NULL) + if( p_tls != NULL ) { - switch (tls_ServerSessionHandshake (p_tls, fd)) + switch( tls_ServerSessionHandshake( p_tls, fd ) ) { case -1: msg_Err( host, "Rejecting TLS connection" ); - net_Close (fd); + net_Close( fd ); fd = -1; p_tls = NULL; break; @@ -2463,72 +2440,32 @@ static void httpd_HostThread( httpd_host_t *host ) break; } - if ((p_tls == NULL) != (host->p_tls == NULL)) + if( (p_tls == NULL) != (host->p_tls == NULL) ) break; // wasted TLS session, cannot accept() anymore } - httpd_client_t *cl; - stats_UpdateInteger( host, host->p_total_counter, 1, NULL ); - stats_UpdateInteger( host, host->p_active_counter, 1, NULL ); + stats_UpdateInteger( host, p_total_counter, 1, NULL ); + stats_UpdateInteger( host, p_active_counter, 1, NULL ); cl = httpd_ClientNew( fd, p_tls, now ); p_tls = NULL; vlc_mutex_lock( &host->lock ); TAB_APPEND( host->i_client, host->client, cl ); vlc_mutex_unlock( &host->lock ); - cl->i_state = i_state; // override state for TLS + if( i_state != -1 ) + cl->i_state = i_state; // override state for TLS if (host->p_tls != NULL) break; // cannot accept further without new TLS session } - /* now try all others socket */ - vlc_mutex_lock( &host->lock ); - - for( int i_client = 0; i_client < host->i_client; i_client++ ) - { - httpd_client_t *cl = host->client[i_client]; - const struct pollfd *pufd = ufd + nfd; - - assert (pufd < ufd + (sizeof (ufd) / sizeof (ufd[0]))); - - if (cl->fd != pufd->fd) - continue; // we were not waiting for this client - nfd++; - - if (pufd->revents == 0) - continue; // no event received - - cl->i_activity_date = now; - - if( cl->i_state == HTTPD_CLIENT_RECEIVING ) - { - httpd_ClientRecv( cl ); - } - else if( cl->i_state == HTTPD_CLIENT_SENDING ) - { - httpd_ClientSend( cl ); - } - else if( cl->i_state == HTTPD_CLIENT_TLS_HS_IN ) - { - httpd_ClientTlsHsIn( cl ); - } - else if( cl->i_state == HTTPD_CLIENT_TLS_HS_OUT ) - { - httpd_ClientTlsHsOut( cl ); - } - - if( cl->i_mode == HTTPD_CLIENT_BIDIR && - cl->i_state == HTTPD_CLIENT_SENDING && - (pufd->revents & POLLIN) ) - { - cl->b_read_waiting = VLC_TRUE; - } - } - vlc_mutex_unlock( &host->lock ); } if( p_tls != NULL ) tls_ServerSessionClose( p_tls ); + if( p_total_counter ) + stats_CounterClean( p_total_counter ); + if( p_active_counter ) + stats_CounterClean( p_active_counter ); } #else /* ENABLE_HTTPD */