X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fnetwork%2Fhttpd.c;h=cd384587a50a7ff850ce07856fd7eba38f3f5213;hb=c2cc636a89448401bf25d6bf4738dc8439a35d21;hp=7bd37020a92663cf9d7a0f7553bfe87c02529ace;hpb=e732cff5c58c4ef4df7f7869405f7002aed94036;p=vlc diff --git a/src/network/httpd.c b/src/network/httpd.c index 7bd37020a9..cd384587a5 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 @@ -35,6 +36,7 @@ #include #include #include +#include #include "../libvlc.h" #include @@ -94,10 +96,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,63 +188,6 @@ 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; @@ -706,6 +647,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 ) { @@ -1209,7 +1151,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" ); @@ -2016,11 +1958,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 +1974,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 +1997,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--; @@ -2211,7 +2150,7 @@ static void httpd_HostThread( httpd_host_t *host ) { /* create the headers */ const char *b64 = httpd_MsgGet( query, "Authorization" ); /* BASIC id */ - char *auth; + char *auth = NULL; char *id; asprintf( &id, "%s:%s", url->psz_user, url->psz_password ); @@ -2223,15 +2162,10 @@ static void httpd_HostThread( httpd_host_t *host ) { b64++; } - auth = malloc( strlen(b64) + 1 ); - b64_decode( auth, b64 ); - } - else - { - auth = strdup( "" ); + auth = vlc_b64_decode( b64 ); } - if( strcmp( id, auth ) ) + if( (auth == NULL) || strcmp( id, auth ) ) { httpd_MsgAdd( answer, "WWW-Authenticate", "Basic realm=\"%s\"", url->psz_user ); /* We fail for all url */ @@ -2414,7 +2348,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 +2361,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]; + + 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 ); - /* accept new connections */ - for (nfd = 0; nfd < host->nfd; nfd++) + /* 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 +2441,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 */