httpd_t *httpd;
/* ref count */
- int i_ref;
+ unsigned i_ref;
/* address/port and socket for listening at connections */
char *psz_hostname;
int *fds;
unsigned nfd;
+ vlc_thread_t thread;
vlc_mutex_t lock;
+ vlc_cond_t wait;
/* all registered url (becarefull that 2 httpd_url_t could point at the same url)
* This will slow down the url research but make my live easier
{ ".mpe", "video/mpeg" },
{ ".mov", "video/quicktime" },
{ ".moov", "video/quicktime" },
+ { ".oga", "audio/ogg" },
{ ".ogg", "application/ogg" },
{ ".ogm", "application/ogg" },
- { ".ogv", "application/ogg" },
+ { ".ogv", "video/ogg" },
+ { ".ogx", "application/ogg" },
+ { ".spx", "audio/ogg" },
{ ".wav", "audio/wav" },
{ ".wma", "audio/x-ms-wma" },
{ ".wmv", "video/x-ms-wmv" },
"<a href=\"http://www.videolan.org\">VideoLAN</a>\n"
"</body>\n"
"</html>\n", errname, code, errname,
- (url ? " (" : ""), (url ?: ""), (url ? ")" : ""));
+ (url ? " (" : ""), (url ? url : ""), (url ? ")" : ""));
if (res == -1)
{
if( p != NULL )
{
+ httpd_message_t *p_msg;
p[4] = '\0';
- answer->i_body = strlen((char*)answer->p_body) + 1;
- answer->p_body = realloc( answer->p_body, answer->i_body );
+ p_msg = realloc( answer->p_body, strlen((char*)answer->p_body) + 1 );
+ if( p_msg )
+ {
+ answer->i_body = strlen((char*)answer->p_body) + 1;
+ answer->p_body = p_msg;
+ }
}
}
/*****************************************************************************
* Low level
*****************************************************************************/
-static void* httpd_HostThread( vlc_object_t * );
+static void* httpd_HostThread( void * );
/* create a new host */
httpd_host_t *httpd_HostNew( vlc_object_t *p_this, const char *psz_host,
}
static const char psz_object_type[] = "http server";
+static vlc_mutex_t httpd_mutex = VLC_STATIC_MUTEX;
httpd_host_t *httpd_TLSHostNew( vlc_object_t *p_this, const char *psz_hostname,
int i_port,
httpd_host_t *host;
tls_server_t *p_tls;
char *psz_host;
- vlc_value_t lockval, ptrval;
+ vlc_value_t ptrval;
int i;
if( psz_hostname == NULL )
return NULL;
/* to be sure to avoid multiple creation */
- 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 );
+ vlc_mutex_lock( &httpd_mutex );
httpd = libvlc_priv (p_this->p_libvlc)->p_httpd;
if( httpd == NULL )
psz_object_type );
if( httpd == NULL )
{
- vlc_mutex_unlock( lockval.p_address );
+ vlc_mutex_unlock( &httpd_mutex );
free( psz_host );
return NULL;
}
ptrval.p_address = httpd;
libvlc_priv (p_this->p_libvlc)->p_httpd = httpd;
- vlc_object_hold( httpd );
vlc_object_attach( httpd, p_this->p_libvlc );
}
|| strcmp( host->psz_hostname, psz_hostname ) )
continue;
- /* yep found */
+ /* Increase existing matching host reference count.
+ * The reference count is written under both the global httpd and the
+ * host lock. It is read with either or both locks held. The global
+ * lock is always acquired first. */
+ vlc_mutex_lock( &host->lock );
host->i_ref++;
+ vlc_mutex_unlock( &host->lock );
- vlc_mutex_unlock( lockval.p_address );
+ vlc_mutex_unlock( &httpd_mutex );
return host;
}
if (host == NULL)
goto error;
- vlc_object_lock( host );
- if( vlc_object_waitpipe( VLC_OBJECT( host ) ) == -1 )
- {
- msg_Err( host, "signaling pipe error: %m" );
- vlc_object_unlock( host );
- goto error;
- }
- vlc_object_unlock( host );
-
host->httpd = httpd;
vlc_mutex_init( &host->lock );
+ vlc_cond_init( &host->wait );
host->i_ref = 1;
host->fds = net_ListenTCP( p_this, psz_host, i_port );
}
for (host->nfd = 0; host->fds[host->nfd] != -1; host->nfd++);
+ if( vlc_object_waitpipe( VLC_OBJECT( host ) ) == -1 )
+ {
+ msg_Err( host, "signaling pipe error: %m" );
+ goto error;
+ }
+
host->i_port = i_port;
host->psz_hostname = psz_host;
host->p_tls = p_tls;
/* create the thread */
- if( vlc_thread_create( host, "httpd host thread", httpd_HostThread,
- VLC_THREAD_PRIORITY_LOW, false ) )
+ if( vlc_clone( &host->thread, httpd_HostThread, host,
+ VLC_THREAD_PRIORITY_LOW ) )
{
msg_Err( p_this, "cannot spawn http host thread" );
goto error;
/* now add it to httpd */
TAB_APPEND( httpd->i_host, httpd->host, host );
- vlc_mutex_unlock( lockval.p_address );
+ vlc_mutex_unlock( &httpd_mutex );
return host;
if( httpd->i_host <= 0 )
{
libvlc_priv (httpd->p_libvlc)->p_httpd = NULL;
- vlc_object_release( httpd );
vlc_object_detach( httpd );
vlc_object_release( httpd );
}
- vlc_mutex_unlock( lockval.p_address );
+ vlc_mutex_unlock( &httpd_mutex );
if( host != NULL )
{
net_ListenClose( host->fds );
+ vlc_cond_destroy( &host->wait );
vlc_mutex_destroy( &host->lock );
vlc_object_release( host );
}
void httpd_HostDelete( httpd_host_t *host )
{
httpd_t *httpd = host->httpd;
- vlc_value_t lockval;
int i;
- var_Get( httpd->p_libvlc, "httpd_mutex", &lockval );
- vlc_mutex_lock( lockval.p_address );
+ vlc_mutex_lock( &httpd_mutex );
+ vlc_mutex_lock( &host->lock );
host->i_ref--;
+ if( host->i_ref == 0 )
+ vlc_cond_signal( &host->wait );
+ vlc_mutex_unlock( &host->lock );
if( host->i_ref > 0 )
{
/* still used */
- vlc_mutex_unlock( lockval.p_address );
- msg_Dbg( host, "httpd_HostDelete: host still used" );
+ vlc_mutex_unlock( &httpd_mutex );
+ msg_Dbg( host, "httpd_HostDelete: host still in use" );
return;
}
TAB_REMOVE( httpd->i_host, httpd->host, host );
vlc_object_kill( host );
- vlc_thread_join( host );
+ vlc_join( host->thread, NULL );
msg_Dbg( host, "HTTP host removed" );
net_ListenClose( host->fds );
free( host->psz_hostname );
+ vlc_cond_destroy( &host->wait );
vlc_mutex_destroy( &host->lock );
vlc_object_release( host );
- vlc_object_release( httpd );
if( httpd->i_host <= 0 )
{
- msg_Dbg( httpd, "no host left, stopping httpd" );
+ msg_Dbg( httpd, "no hosts left, stopping httpd" );
libvlc_priv (httpd->p_libvlc)->p_httpd = NULL;
vlc_object_detach( httpd );
vlc_object_release( httpd );
-
}
- vlc_mutex_unlock( lockval.p_address );
+ vlc_mutex_unlock( &httpd_mutex );
}
/* register a new url */
}
TAB_APPEND( host->i_url, host->url, url );
+ vlc_cond_signal( &host->wait );
vlc_mutex_unlock( &host->lock );
return url;
}
}
-static void* httpd_HostThread( vlc_object_t *p_this )
+static void* httpd_HostThread( void *data )
{
- httpd_host_t *host = (httpd_host_t *)p_this;
+ httpd_host_t *host = data;
tls_session_t *p_tls = NULL;
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 );
- int evfd;
- bool b_die;
- int canc = vlc_savecancel ();
-
-retry:
- vlc_object_lock( host );
- evfd = vlc_object_waitpipe( VLC_OBJECT( host ) );
- b_die = !vlc_object_alive( host );
- vlc_object_unlock( host );
+ int evfd = vlc_object_waitpipe( VLC_OBJECT( host ) );
- while( !b_die )
+ for( ;; )
{
- if( host->i_url <= 0 )
- {
- /* 0.2s (FIXME: use a condition variable) */
- msleep( 200000 );
- goto retry;
- }
-
/* 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 );
+ while( host->i_url <= 0 && host->i_ref > 0 )
+ vlc_cond_wait( &host->wait, &host->lock );
+
mtime_t now = mdate();
bool b_low_delay = false;
continue;
}
- vlc_object_lock( host );
if( ufd[nfd - 1].revents )
- {
- b_die = !vlc_object_alive( host );
- if( !b_die )
- vlc_object_wait( host );
- }
- vlc_object_unlock( host );
+ break;
/* Handle client sockets */
vlc_mutex_lock( &host->lock );
stats_CounterClean( p_total_counter );
if( p_active_counter )
stats_CounterClean( p_active_counter );
- vlc_restorecancel (canc);
return NULL;
}