]> git.sesse.net Git - vlc/commitdiff
http: split loop function
authorRafaël Carré <funman@videolan.org>
Sun, 16 Feb 2014 10:29:30 +0000 (11:29 +0100)
committerRafaël Carré <funman@videolan.org>
Sun, 16 Feb 2014 11:02:43 +0000 (12:02 +0100)
src/network/httpd.c

index 765a46a9b9d6d11358ea20972d08a6f5631fe6a4..a9a76a3e85820816ef37ec63f1c5159d47060ded 100644 (file)
@@ -1923,59 +1923,52 @@ static void httpd_ClientTlsHandshake( httpd_client_t *cl )
     }
 }
 
-static void* httpd_HostThread( void *data )
+static void httpdLoop(httpd_host_t *host)
 {
-    httpd_host_t *host = data;
-    int canc = vlc_savecancel();
-
-    vlc_mutex_lock( &host->lock );
-    while( host->i_ref > 0 )
+    struct pollfd ufd[host->nfd + host->i_client];
+    unsigned nfd;
+    for( nfd = 0; nfd < host->nfd; nfd++ )
     {
-        struct pollfd ufd[host->nfd + host->i_client];
-        unsigned nfd;
-        for( nfd = 0; nfd < host->nfd; nfd++ )
-        {
-            ufd[nfd].fd = host->fds[nfd];
-            ufd[nfd].events = POLLIN;
-            ufd[nfd].revents = 0;
-        }
+        ufd[nfd].fd = host->fds[nfd];
+        ufd[nfd].events = POLLIN;
+        ufd[nfd].revents = 0;
+    }
 
-        /* add all socket that should be read/write and close dead connection */
-        while( host->i_url <= 0 )
-        {
-            mutex_cleanup_push( &host->lock );
-            vlc_restorecancel( canc );
-            vlc_cond_wait( &host->wait, &host->lock );
-            canc = vlc_savecancel();
-            vlc_cleanup_pop();
-        }
+    /* add all socket that should be read/write and close dead connection */
+    while( host->i_url <= 0 )
+    {
+        mutex_cleanup_push( &host->lock );
+        vlc_cond_wait( &host->wait, &host->lock );
+        vlc_cleanup_pop();
+    }
 
-        mtime_t now = mdate();
-        bool b_low_delay = false;
+    mtime_t now = mdate();
+    bool b_low_delay = false;
 
-        for(int i_client = 0; i_client < host->i_client; i_client++ )
+    int canc = vlc_savecancel();
+    for(int i_client = 0; i_client < host->i_client; i_client++ )
+    {
+        int64_t i_offset;
+        httpd_client_t *cl = host->client[i_client];
+        if( cl->i_ref < 0 || ( cl->i_ref == 0 &&
+                    ( cl->i_state == HTTPD_CLIENT_DEAD ||
+                      ( cl->i_activity_timeout > 0 &&
+                        cl->i_activity_date+cl->i_activity_timeout < now) ) ) )
         {
-            int64_t i_offset;
-            httpd_client_t *cl = host->client[i_client];
-            if( cl->i_ref < 0 || ( cl->i_ref == 0 &&
-                ( cl->i_state == HTTPD_CLIENT_DEAD ||
-                  ( cl->i_activity_timeout > 0 &&
-                    cl->i_activity_date+cl->i_activity_timeout < now) ) ) )
-            {
-                httpd_ClientClean( cl );
-                TAB_REMOVE( host->i_client, host->client, cl );
-                free( cl );
-                i_client--;
-                continue;
-            }
+            httpd_ClientClean( cl );
+            TAB_REMOVE( host->i_client, host->client, cl );
+            free( cl );
+            i_client--;
+            continue;
+        }
 
-            struct pollfd *pufd = ufd + nfd;
-            assert (pufd < ufd + (sizeof (ufd) / sizeof (ufd[0])));
+        struct pollfd *pufd = ufd + nfd;
+        assert (pufd < ufd + (sizeof (ufd) / sizeof (ufd[0])));
 
-            pufd->fd = cl->fd;
-            pufd->events = pufd->revents = 0;
+        pufd->fd = cl->fd;
+        pufd->events = pufd->revents = 0;
 
-            switch (cl->i_state) {
+        switch (cl->i_state) {
             case HTTPD_CLIENT_RECEIVING:
             case HTTPD_CLIENT_TLS_HS_IN:
                 pufd->events = POLLIN;
@@ -1986,8 +1979,7 @@ static void* httpd_HostThread( void *data )
                 pufd->events = POLLOUT;
                 break;
 
-            case HTTPD_CLIENT_RECEIVE_DONE:
-            {
+            case HTTPD_CLIENT_RECEIVE_DONE: {
                 httpd_message_t *answer = &cl->answer;
                 httpd_message_t *query  = &cl->query;
 
@@ -1995,158 +1987,158 @@ static void* httpd_HostThread( void *data )
 
                 /* Handle what we received */
                 switch (query->i_type) {
-                case HTTPD_MSG_ANSWER:
-                    cl->url     = NULL;
-                    cl->i_state = HTTPD_CLIENT_DEAD;
-                    break;
-
-                case HTTPD_MSG_OPTIONS:
-                    answer->i_type   = HTTPD_MSG_ANSWER;
-                    answer->i_proto  = query->i_proto;
-                    answer->i_status = 200;
-                    answer->i_body = 0;
-                    answer->p_body = NULL;
-
-                    httpd_MsgAdd( answer, "Server", "VLC/%s", VERSION );
-                    httpd_MsgAdd( answer, "Content-Length", "0" );
-
-                    switch( query->i_proto )
-                    {
-                    case HTTPD_PROTO_HTTP:
-                        answer->i_version = 1;
-                        httpd_MsgAdd(answer, "Allow", "GET,HEAD,POST,OPTIONS");
+                    case HTTPD_MSG_ANSWER:
+                        cl->url     = NULL;
+                        cl->i_state = HTTPD_CLIENT_DEAD;
                         break;
 
-                    case HTTPD_PROTO_RTSP:
-                        answer->i_version = 0;
-
-                        const char *p = httpd_MsgGet( query, "Cseq" );
-                        if( p != NULL )
-                            httpd_MsgAdd( answer, "Cseq", "%s", p );
-                        p = httpd_MsgGet( query, "Timestamp" );
-                        if( p != NULL )
-                            httpd_MsgAdd( answer, "Timestamp", "%s", p );
-
-                        p = httpd_MsgGet( query, "Require" );
-                        if( p != NULL ) {
-                            answer->i_status = 551;
-                            httpd_MsgAdd( query, "Unsupported", "%s", p );
-                        }
-
-                        httpd_MsgAdd( answer, "Public", "DESCRIBE,SETUP,"
-                                      "TEARDOWN,PLAY,PAUSE,GET_PARAMETER" );
-                        break;
-                    }
+                    case HTTPD_MSG_OPTIONS:
+                        answer->i_type   = HTTPD_MSG_ANSWER;
+                        answer->i_proto  = query->i_proto;
+                        answer->i_status = 200;
+                        answer->i_body = 0;
+                        answer->p_body = NULL;
 
-                    cl->i_buffer = -1;  /* Force the creation of the answer in
-                                         * httpd_ClientSend */
-                    cl->i_state = HTTPD_CLIENT_SENDING;
-                    break;
+                        httpd_MsgAdd( answer, "Server", "VLC/%s", VERSION );
+                        httpd_MsgAdd( answer, "Content-Length", "0" );
 
-                case HTTPD_MSG_NONE:
-                    if( query->i_proto == HTTPD_PROTO_NONE ) {
-                        cl->url = NULL;
-                        cl->i_state = HTTPD_CLIENT_DEAD;
-                    }
-                    else {
-                        /* unimplemented */
-                        answer->i_proto  = query->i_proto ;
-                        answer->i_type   = HTTPD_MSG_ANSWER;
-                        answer->i_version= 0;
-                        answer->i_status = 501;
+                        switch( query->i_proto )
+                        {
+                            case HTTPD_PROTO_HTTP:
+                                answer->i_version = 1;
+                                httpd_MsgAdd(answer, "Allow", "GET,HEAD,POST,OPTIONS");
+                                break;
 
-                        char *p;
-                        answer->i_body = httpd_HtmlError (&p, 501, NULL);
-                        answer->p_body = (uint8_t *)p;
-                        httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
+                            case HTTPD_PROTO_RTSP:
+                                answer->i_version = 0;
 
-                        cl->i_buffer = -1;  /* Force the creation of the answer in httpd_ClientSend */
-                        cl->i_state = HTTPD_CLIENT_SENDING;
-                    }
-                    break;
+                                const char *p = httpd_MsgGet( query, "Cseq" );
+                                if( p != NULL )
+                                    httpd_MsgAdd( answer, "Cseq", "%s", p );
+                                p = httpd_MsgGet( query, "Timestamp" );
+                                if( p != NULL )
+                                    httpd_MsgAdd( answer, "Timestamp", "%s", p );
 
-                default: {
-                    int i_msg = query->i_type;
-                    bool b_auth_failed = false;
-
-                    /* Search the url and trigger callbacks */
-                    for(int i = 0; i < host->i_url; i++ ) {
-                        httpd_url_t *url = host->url[i];
-
-                        if (strcmp(url->psz_url, query->psz_url))
-                            continue;
-                        if (!url->catch[i_msg].cb)
-                            continue;
-
-                        if (answer && (*url->psz_user || *url->psz_password)) {
-                            /* create the headers */
-                            const char *b64 = httpd_MsgGet(query, "Authorization"); /* BASIC id */
-                            char *user = NULL, *pass = NULL;
-
-                            if (b64 && !strncasecmp(b64, "BASIC", 5)) {
-                                b64 += 5;
-                                while (*b64 == ' ')
-                                    b64++;
-
-                                user = vlc_b64_decode( b64 );
-                                if (user) {
-                                    pass = strchr (user, ':');
-                                    if (pass)
-                                        *pass++ = '\0';
+                                p = httpd_MsgGet( query, "Require" );
+                                if( p != NULL ) {
+                                    answer->i_status = 551;
+                                    httpd_MsgAdd( query, "Unsupported", "%s", p );
                                 }
-                            }
 
-                            if (!user || strcmp (user, url->psz_user) ||
-                                !pass || strcmp (pass, url->psz_password)) {
-                                httpd_MsgAdd( answer, "WWW-Authenticate",
-                                        "Basic realm=\"VLC stream\"" );
-                                b_auth_failed = true; /* We fail for all url */
-                                free( user );
+                                httpd_MsgAdd( answer, "Public", "DESCRIBE,SETUP,"
+                                        "TEARDOWN,PLAY,PAUSE,GET_PARAMETER" );
                                 break;
-                            }
-
-                            free( user );
                         }
 
-                        if (url->catch[i_msg].cb(url->catch[i_msg].p_sys, cl, answer, query))
-                            continue;
-
-                        if( answer->i_proto == HTTPD_PROTO_NONE )
-                            cl->i_buffer = cl->i_buffer_size; /* Raw answer from a CGI */
-                        else
-                            cl->i_buffer = -1;
-
-                        /* only one url can answer */
-                        answer = NULL;
-                        if( cl->url == NULL )
-                            cl->url = url;
-                    }
-
-                    if( answer ) {
-                        answer->i_proto  = query->i_proto;
-                        answer->i_type   = HTTPD_MSG_ANSWER;
-                        answer->i_version= 0;
-
-                        if( b_auth_failed )
-                            answer->i_status = 401;
-                        else
-                            answer->i_status = 404; /* no url registered */
-
-                        char *p;
-                        answer->i_body = httpd_HtmlError (&p, answer->i_status,
-                                                          query->psz_url);
-                        answer->p_body = (uint8_t *)p;
+                        cl->i_buffer = -1;  /* Force the creation of the answer in
+                                             * httpd_ClientSend */
+                        cl->i_state = HTTPD_CLIENT_SENDING;
+                        break;
 
-                        cl->i_buffer = -1;  /* Force the creation of the answer in httpd_ClientSend */
-                        httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
-                        httpd_MsgAdd( answer, "Content-Type", "%s", "text/html" );
-                    }
+                    case HTTPD_MSG_NONE:
+                        if( query->i_proto == HTTPD_PROTO_NONE ) {
+                            cl->url = NULL;
+                            cl->i_state = HTTPD_CLIENT_DEAD;
+                        }
+                        else {
+                            /* unimplemented */
+                            answer->i_proto  = query->i_proto ;
+                            answer->i_type   = HTTPD_MSG_ANSWER;
+                            answer->i_version= 0;
+                            answer->i_status = 501;
+
+                            char *p;
+                            answer->i_body = httpd_HtmlError (&p, 501, NULL);
+                            answer->p_body = (uint8_t *)p;
+                            httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
+
+                            cl->i_buffer = -1;  /* Force the creation of the answer in httpd_ClientSend */
+                            cl->i_state = HTTPD_CLIENT_SENDING;
+                        }
+                        break;
 
-                    cl->i_state = HTTPD_CLIENT_SENDING;
-                }
+                    default: {
+                         int i_msg = query->i_type;
+                         bool b_auth_failed = false;
+
+                         /* Search the url and trigger callbacks */
+                         for(int i = 0; i < host->i_url; i++ ) {
+                             httpd_url_t *url = host->url[i];
+
+                             if (strcmp(url->psz_url, query->psz_url))
+                                 continue;
+                             if (!url->catch[i_msg].cb)
+                                 continue;
+
+                             if (answer && (*url->psz_user || *url->psz_password)) {
+                                 /* create the headers */
+                                 const char *b64 = httpd_MsgGet(query, "Authorization"); /* BASIC id */
+                                 char *user = NULL, *pass = NULL;
+
+                                 if (b64 && !strncasecmp(b64, "BASIC", 5)) {
+                                     b64 += 5;
+                                     while (*b64 == ' ')
+                                         b64++;
+
+                                     user = vlc_b64_decode( b64 );
+                                     if (user) {
+                                         pass = strchr (user, ':');
+                                         if (pass)
+                                             *pass++ = '\0';
+                                     }
+                                 }
+
+                                 if (!user || strcmp (user, url->psz_user) ||
+                                         !pass || strcmp (pass, url->psz_password)) {
+                                     httpd_MsgAdd( answer, "WWW-Authenticate",
+                                             "Basic realm=\"VLC stream\"" );
+                                     b_auth_failed = true; /* We fail for all url */
+                                     free( user );
+                                     break;
+                                 }
+
+                                 free( user );
+                             }
+
+                             if (url->catch[i_msg].cb(url->catch[i_msg].p_sys, cl, answer, query))
+                                 continue;
+
+                             if( answer->i_proto == HTTPD_PROTO_NONE )
+                                 cl->i_buffer = cl->i_buffer_size; /* Raw answer from a CGI */
+                             else
+                                 cl->i_buffer = -1;
+
+                             /* only one url can answer */
+                             answer = NULL;
+                             if( cl->url == NULL )
+                                 cl->url = url;
+                         }
+
+                         if( answer ) {
+                             answer->i_proto  = query->i_proto;
+                             answer->i_type   = HTTPD_MSG_ANSWER;
+                             answer->i_version= 0;
+
+                             if( b_auth_failed )
+                                 answer->i_status = 401;
+                             else
+                                 answer->i_status = 404; /* no url registered */
+
+                             char *p;
+                             answer->i_body = httpd_HtmlError (&p, answer->i_status,
+                                     query->psz_url);
+                             answer->p_body = (uint8_t *)p;
+
+                             cl->i_buffer = -1;  /* Force the creation of the answer in httpd_ClientSend */
+                             httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
+                             httpd_MsgAdd( answer, "Content-Type", "%s", "text/html" );
+                         }
+
+                         cl->i_state = HTTPD_CLIENT_SENDING;
+                     }
                 }
+                break;
             }
-            break;
 
             case HTTPD_CLIENT_SEND_DONE:
                 if( !cl->b_stream_mode || cl->answer.i_body_offset == 0 )
@@ -2170,10 +2162,10 @@ static void* httpd_HostThread( void *data )
                     }
 
                     if( ( ( cl->query.i_proto == HTTPD_PROTO_HTTP ) &&
-                          ( ( cl->query.i_version == 0 && b_keepalive ) ||
-                            ( cl->query.i_version == 1 && !b_connection ) ) ) ||
-                        ( ( cl->query.i_proto == HTTPD_PROTO_RTSP ) &&
-                          !b_query && !b_connection ) )
+                                ( ( cl->query.i_version == 0 && b_keepalive ) ||
+                                  ( cl->query.i_version == 1 && !b_connection ) ) ) ||
+                            ( ( cl->query.i_proto == HTTPD_PROTO_RTSP ) &&
+                              !b_query && !b_connection ) )
                     {
                         httpd_MsgClean( &cl->query );
                         httpd_MsgInit( &cl->query );
@@ -2213,7 +2205,7 @@ static void* httpd_HostThread( void *data )
                 cl->answer.i_body_offset = i_offset;
 
                 cl->url->catch[i_msg].cb( cl->url->catch[i_msg].p_sys, cl,
-                                          &cl->answer, &cl->query );
+                        &cl->answer, &cl->query );
                 if( cl->answer.i_type != HTTPD_MSG_NONE )
                 {
                     /* we have new data, so re-enter send mode */
@@ -2224,22 +2216,22 @@ static void* httpd_HostThread( void *data )
                     cl->answer.i_body = 0;
                     cl->i_state = HTTPD_CLIENT_SENDING;
                 }
-            }
-
-            if (pufd->events != 0)
-                nfd++;
-            else
-                b_low_delay = true;
         }
-        vlc_mutex_unlock( &host->lock );
-        vlc_restorecancel( canc );
 
-        /* we will wait 20ms (not too big) if HTTPD_CLIENT_WAITING */
-        int ret = poll( ufd, nfd, b_low_delay ? 20 : -1 );
+        if (pufd->events != 0)
+            nfd++;
+        else
+            b_low_delay = true;
+    }
+    vlc_mutex_unlock( &host->lock );
+    vlc_restorecancel( canc );
+
+    /* we will wait 20ms (not too big) if HTTPD_CLIENT_WAITING */
+    int ret = poll( ufd, nfd, b_low_delay ? 20 : -1 );
 
-        canc = vlc_savecancel();
-        vlc_mutex_lock( &host->lock );
-        switch( ret ) {
+    canc = vlc_savecancel();
+    vlc_mutex_lock( &host->lock );
+    switch( ret ) {
         case -1:
             if (errno != EINTR) {
                 /* Kernel on low memory or a bug: pace */
@@ -2247,66 +2239,77 @@ static void* httpd_HostThread( void *data )
                 msleep( 100000 );
             }
         case 0:
-            continue;
-        }
+            vlc_restorecancel( canc );
+            return;
+    }
 
-        /* Handle client sockets */
-        now = mdate();
-        nfd = host->nfd;
+    /* Handle client sockets */
+    now = mdate();
+    nfd = host->nfd;
 
-        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];
+    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])] );
+        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
+        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;
+        cl->i_activity_date = now;
 
-            switch (cl->i_state) {
+        switch (cl->i_state) {
             case HTTPD_CLIENT_RECEIVING: httpd_ClientRecv( cl ); break;
             case HTTPD_CLIENT_SENDING:   httpd_ClientSend( cl ); break;
             case HTTPD_CLIENT_TLS_HS_IN:
             case HTTPD_CLIENT_TLS_HS_OUT: httpd_ClientTlsHandshake( cl ); break;
-            }
         }
+    }
 
-        /* Handle server sockets (accept new connections) */
-        for( nfd = 0; nfd < host->nfd; nfd++ )
-        {
-            httpd_client_t *cl;
-            int fd = ufd[nfd].fd;
+    /* Handle server sockets (accept new connections) */
+    for( nfd = 0; nfd < host->nfd; nfd++ )
+    {
+        httpd_client_t *cl;
+        int fd = ufd[nfd].fd;
 
-            assert (fd == host->fds[nfd]);
+        assert (fd == host->fds[nfd]);
 
-            if( ufd[nfd].revents == 0 )
-                continue;
+        if( ufd[nfd].revents == 0 )
+            continue;
 
-            /* */
-            fd = vlc_accept (fd, NULL, NULL, true);
-            if (fd == -1)
-                continue;
-            setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
-                        &(int){ 1 }, sizeof(int));
+        /* */
+        fd = vlc_accept (fd, NULL, NULL, true);
+        if (fd == -1)
+            continue;
+        setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
+                &(int){ 1 }, sizeof(int));
 
-            vlc_tls_t *p_tls;
+        vlc_tls_t *p_tls;
 
-            if( host->p_tls != NULL )
-                p_tls = vlc_tls_SessionCreate( host->p_tls, fd, NULL );
-            else
-                p_tls = NULL;
+        if( host->p_tls != NULL )
+            p_tls = vlc_tls_SessionCreate( host->p_tls, fd, NULL );
+        else
+            p_tls = NULL;
 
-            cl = httpd_ClientNew( fd, p_tls, now );
+        cl = httpd_ClientNew( fd, p_tls, now );
 
-            TAB_APPEND( host->i_client, host->client, cl );
-        }
+        TAB_APPEND( host->i_client, host->client, cl );
     }
+
+    vlc_restorecancel(canc);
+}
+
+static void* httpd_HostThread( void *data )
+{
+    httpd_host_t *host = data;
+
+    vlc_mutex_lock( &host->lock );
+    while( host->i_ref > 0 )
+        httpdLoop(host);
     vlc_mutex_unlock( &host->lock );
     return NULL;
 }