[vlc-devel] [RFC] httpd: fix multiple hosts handling

Pierre Ynard linkfanel at yahoo.fr
Sun Sep 25 16:10:53 CEST 2011


This is a proof of concept for a better http "host" logic. It fixes the
- currently broken - use of several hosts for different protocols, and
also restores the host reuse logic. The new design works, remains simple
and will simplify the httpd threads as there is now only one listening
socket per thread. The ugly casting just helps to make a quick and small
patch that is easier to review for now.

It would be nice to consider and discuss this before commiting more
changes in related code.


diff --git a/src/network/httpd.c b/src/network/httpd.c
index fee6e7c..bf5463b 100644
--- a/src/network/httpd.c
+++ b/src/network/httpd.c
@@ -1062,6 +1062,35 @@ static httpd_host_t *httpd_HostCreate( vlc_object_t *p_this,
         libvlc_priv (p_this->p_libvlc)->p_httpd = httpd;
     }
 
+    char *hostname = var_InheritString( p_this->p_libvlc, hostvar );
+    int port = var_InheritInteger( p_this->p_libvlc, portvar );
+    struct addrinfo hints, *res;
+
+    memset (&hints, 0, sizeof( hints ));
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+    hints.ai_flags = AI_PASSIVE;
+
+    int val = vlc_getaddrinfo(p_this, hostname, port, &hints, &res);
+    if (val)
+    {
+        msg_Err (p_this, "Cannot resolve %s port %d : %s",
+                 (hostname != NULL) ? hostname : "", port,
+                 gai_strerror (val));
+        free(hostname);
+        goto error;
+    }
+
+    httpd_host_t **hostv;
+    unsigned hostc;
+    TAB_INIT(hostc, hostv);
+
+for (struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
+{
+    char ip[NI_MAXNUMERICHOST];
+    vlc_getnameinfo( ptr->ai_addr, ptr->ai_addrlen, ip,
+                     NI_MAXNUMERICHOST, &port, NI_NUMERICHOST );
+
     /* verify if it already exist */
     for( i = httpd->i_host - 1; i >= 0; i-- )
     {
@@ -1071,6 +1100,12 @@ static httpd_host_t *httpd_HostCreate( vlc_object_t *p_this,
         if( ( httpd->host[i]->p_tls != NULL ) != ( p_tls != NULL ) )
             continue;
 
+        int port2;
+        char ip2[NI_MAXNUMERICHOST];
+        net_GetSockAddress(host->fds[0], ip2, &port2);
+        if (port != port2 || strcmp(ip, ip2))
+            continue;
+
         /* 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
@@ -1079,40 +1114,52 @@ static httpd_host_t *httpd_HostCreate( vlc_object_t *p_this,
         host->i_ref++;
         vlc_mutex_unlock( &host->lock );
 
-        vlc_mutex_unlock( &httpd_mutex );
+        TAB_APPEND(hostc, hostv, host);
+        break;
+
+#if 0
         if( p_tls != NULL )
             vlc_tls_ServerDelete( p_tls );
-        return host;
+#endif
     }
+}
+    freeaddrinfo(res);
 
     host = NULL;
 
+    int *fds = net_ListenTCP( p_this, hostname, port );
+    free( hostname );
+
+if (fds != NULL)
+for (i = 0; fds[i] != -1; i++)
+{
     /* create the new host */
     host = (httpd_host_t *)vlc_custom_create( p_this, sizeof (*host),
                                               "http host" );
     if (host == NULL)
-        goto error;
+    {
+        net_Close(fds[i]);
+        continue;
+    }
 
     host->httpd = httpd;
     vlc_mutex_init( &host->lock );
     vlc_cond_init( &host->wait );
     host->i_ref = 1;
 
-    char *hostname = var_InheritString( p_this->p_libvlc, hostvar );
-    int port = var_InheritInteger( p_this->p_libvlc, portvar );
-    host->fds = net_ListenTCP( p_this, hostname, port );
-    free( hostname );
-    if( host->fds == NULL )
-    {
-        msg_Err( p_this, "cannot create socket(s) for HTTP host" );
-        goto error;
-    }
-    for (host->nfd = 0; host->fds[host->nfd] != -1; host->nfd++);
+    host->nfd = 1;
+    host->fds = malloc(2 * sizeof(int *));
+    host->fds[0] = fds[i];
+    host->fds[1] = -1;
 
     if( vlc_object_waitpipe( VLC_OBJECT( host ) ) == -1 )
     {
         msg_Err( host, "signaling pipe error: %m" );
-        goto error;
+        net_Close(fds[i]);
+        vlc_cond_destroy( &host->wait );
+        vlc_mutex_destroy( &host->lock );
+        vlc_object_release( host );
+        continue;
     }
 
     host->i_url    = 0;
@@ -1126,16 +1173,19 @@ static httpd_host_t *httpd_HostCreate( vlc_object_t *p_this,
                    VLC_THREAD_PRIORITY_LOW ) )
     {
         msg_Err( p_this, "cannot spawn http host thread" );
-        goto error;
+        net_Close(fds[i]);
+        vlc_cond_destroy( &host->wait );
+        vlc_mutex_destroy( &host->lock );
+        vlc_object_release( host );
+        continue;
     }
 
     /* now add it to httpd */
     TAB_APPEND( httpd->i_host, httpd->host, host );
-    vlc_mutex_unlock( &httpd_mutex );
-
-    return host;
+    TAB_APPEND(hostc, hostv, host);
+}
+    free(fds);
 
-error:
     if( httpd->i_host <= 0 )
     {
         libvlc_priv (httpd->p_libvlc)->p_httpd = NULL;
@@ -1143,16 +1193,27 @@ error:
     }
     vlc_mutex_unlock( &httpd_mutex );
 
-    if( host != NULL )
+    if (hostc == 0)
     {
-        net_ListenClose( host->fds );
-        vlc_cond_destroy( &host->wait );
-        vlc_mutex_destroy( &host->lock );
-        vlc_object_release( host );
+        msg_Err( p_this, "cannot create socket(s) for HTTP host" );
+        return NULL;
     }
 
+    TAB_APPEND(hostc, hostv, NULL);
+    return (httpd_host_t *)hostv;
+
+error:
+    if( httpd->i_host <= 0 )
+    {
+        libvlc_priv (httpd->p_libvlc)->p_httpd = NULL;
+        vlc_object_release( httpd );
+    }
+    vlc_mutex_unlock( &httpd_mutex );
+
+#if 0
     if( p_tls != NULL )
         vlc_tls_ServerDelete( p_tls );
+#endif
 
     return NULL;
 }
@@ -1160,12 +1221,16 @@ error:
 /* delete a host */
 void httpd_HostDelete( httpd_host_t *host )
 {
-    httpd_t *httpd = host->httpd;
+    httpd_host_t **hostv = (httpd_host_t **)host, **hostvc = hostv;
+    httpd_t *httpd = hostv[0]->httpd;
     int i;
     bool delete = false;
 
     vlc_mutex_lock( &httpd_mutex );
 
+for (; *hostv != NULL; hostv++)
+{
+    host = *hostv;
     vlc_mutex_lock( &host->lock );
     host->i_ref--;
     if( host->i_ref == 0 )
@@ -1188,10 +1253,12 @@ void httpd_HostDelete( httpd_host_t *host )
 
     msg_Dbg( host, "HTTP host removed" );
 
+    /*
     for( i = 0; i < host->i_url; i++ )
     {
         msg_Err( host, "url still registered: %s", host->url[i]->psz_url );
     }
+    */
     for( i = 0; i < host->i_client; i++ )
     {
         httpd_client_t *cl = host->client[i];
@@ -1218,7 +1285,10 @@ void httpd_HostDelete( httpd_host_t *host )
         libvlc_priv (httpd->p_libvlc)->p_httpd = NULL;
         vlc_object_release( httpd );
     }
+}
     vlc_mutex_unlock( &httpd_mutex );
+    unsigned hostc;
+    TAB_CLEAN(hostc, hostvc);
 }
 
 /* register a new url */
@@ -1226,11 +1296,14 @@ static httpd_url_t *httpd_UrlNewPrivate( httpd_host_t *host, const char *psz_url
                                          const char *psz_user, const char *psz_password,
                                          const vlc_acl_t *p_acl, bool b_check )
 {
-    httpd_url_t *url;
+    httpd_url_t *url = NULL;
     int         i;
 
     assert( psz_url != NULL );
 
+for (httpd_host_t **hostv = (httpd_host_t **)host; *hostv != NULL; hostv++)
+{
+    httpd_host_t *host = *hostv;
     vlc_mutex_lock( &host->lock );
     if( b_check )
     {
@@ -1246,6 +1319,8 @@ static httpd_url_t *httpd_UrlNewPrivate( httpd_host_t *host, const char *psz_url
         }
     }
 
+if (url == NULL)
+{
     url = xmalloc( sizeof( httpd_url_t ) );
     url->host = host;
 
@@ -1259,10 +1334,12 @@ static httpd_url_t *httpd_UrlNewPrivate( httpd_host_t *host, const char *psz_url
         url->catch[i].cb = NULL;
         url->catch[i].p_sys = NULL;
     }
+}
 
     TAB_APPEND( host->i_url, host->url, url );
     vlc_cond_signal( &host->wait );
     vlc_mutex_unlock( &host->lock );
+}
 
     return url;
 }
@@ -1301,6 +1378,7 @@ void httpd_UrlDelete( httpd_url_t *url )
     httpd_host_t *host = url->host;
     int          i;
 
+    /* FIXME: remove from all hosts */
     vlc_mutex_lock( &host->lock );
     TAB_REMOVE( host->i_url, host->url, url );
 
-----


Regards,

-- 
Pierre Ynard
"Une âme dans un corps, c'est comme un dessin sur une feuille de papier."



More information about the vlc-devel mailing list