add a new http.conf option, sslbindaddr.
[asterisk/asterisk.git] / main / http.c
index ab70df5..96cb8d1 100644 (file)
@@ -72,7 +72,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #ifdef DO_SSL
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #ifdef DO_SSL
 #include <openssl/ssl.h>
 #include <openssl/err.h>
-SSL_CTX* ssl_ctx;
+static SSL_CTX* ssl_ctx;
 #endif /* DO_SSL */
 
 /* SSL support */
 #endif /* DO_SSL */
 
 /* SSL support */
@@ -92,7 +92,7 @@ struct server_instance {
        SSL *ssl;       /* ssl state */
 #endif
        struct sockaddr_in requestor;
        SSL *ssl;       /* ssl state */
 #endif
        struct sockaddr_in requestor;
-       ast_http_callback callback;
+       struct server_args *parent;
 };
 
 /*!
 };
 
 /*!
@@ -484,14 +484,14 @@ static int ssl_close(void *cookie)
 }
 #endif /* DO_SSL */
 
 }
 #endif /* DO_SSL */
 
-static void *httpd_helper_thread(void *data)
+/*!
+ * creates a FILE * from the fd passed by the accept thread.
+ * This operation is potentially expensive (certificate verification),
+ * so we do it in the child thread context.
+ */
+static void *make_file_from_fd(void *data)
 {
 {
-       char buf[4096];
-       char cookie[4096];
        struct server_instance *ser = data;
        struct server_instance *ser = data;
-       struct ast_variable *var, *prev=NULL, *vars=NULL;
-       char *uri, *c, *title=NULL;
-       int status = 200, contentlength = 0;
 
        /*
         * open a FILE * as appropriate.
 
        /*
         * open a FILE * as appropriate.
@@ -524,8 +524,20 @@ static void *httpd_helper_thread(void *data)
        if (!ser->f) {
                close(ser->fd);
                ast_log(LOG_WARNING, "FILE * open failed!\n");
        if (!ser->f) {
                close(ser->fd);
                ast_log(LOG_WARNING, "FILE * open failed!\n");
-               goto done;
+               free(ser);
+               return NULL;
        }
        }
+       return ser->parent->worker_fn(ser);
+}
+
+static void *httpd_helper_thread(void *data)
+{
+       char buf[4096];
+       char cookie[4096];
+       struct server_instance *ser = data;
+       struct ast_variable *var, *prev=NULL, *vars=NULL;
+       char *uri, *c, *title=NULL;
+       int status = 200, contentlength = 0;
 
        if (!fgets(buf, sizeof(buf), ser->f))
                goto done;
 
        if (!fgets(buf, sizeof(buf), ser->f))
                goto done;
@@ -675,12 +687,13 @@ static void *http_root(void *data)
                fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
                ser->fd = fd;
                ser->is_ssl = desc->is_ssl;
                fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
                ser->fd = fd;
                ser->is_ssl = desc->is_ssl;
+               ser->parent = desc;
                memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
 
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                        
                memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
 
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                        
-               if (ast_pthread_create_background(&launched, &attr, desc->worker_fn, ser)) {
+               if (ast_pthread_create_background(&launched, &attr, make_file_from_fd, ser)) {
                        ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
                        close(ser->fd);
                        free(ser);
                        ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
                        close(ser->fd);
                        free(ser);
@@ -811,6 +824,7 @@ static int __ast_http_load(int reload)
        struct hostent *hp;
        struct ast_hostent ahp;
        char newprefix[MAX_PREFIX];
        struct hostent *hp;
        struct ast_hostent ahp;
        char newprefix[MAX_PREFIX];
+       int have_sslbindaddr = 0;
 
        /* default values */
        memset(&http_desc.sin, 0, sizeof(http_desc.sin));
 
        /* default values */
        memset(&http_desc.sin, 0, sizeof(http_desc.sin));
@@ -849,10 +863,16 @@ static int __ast_http_load(int reload)
                                newenablestatic = ast_true(v->value);
                        else if (!strcasecmp(v->name, "bindport"))
                                http_desc.sin.sin_port = htons(atoi(v->value));
                                newenablestatic = ast_true(v->value);
                        else if (!strcasecmp(v->name, "bindport"))
                                http_desc.sin.sin_port = htons(atoi(v->value));
-                       else if (!strcasecmp(v->name, "bindaddr")) {
+                       else if (!strcasecmp(v->name, "sslbindaddr")) {
                                if ((hp = ast_gethostbyname(v->value, &ahp))) {
                                if ((hp = ast_gethostbyname(v->value, &ahp))) {
-                                       memcpy(&http_desc.sin.sin_addr, hp->h_addr, sizeof(http_desc.sin.sin_addr));
                                        memcpy(&https_desc.sin.sin_addr, hp->h_addr, sizeof(https_desc.sin.sin_addr));
                                        memcpy(&https_desc.sin.sin_addr, hp->h_addr, sizeof(https_desc.sin.sin_addr));
+                                       have_sslbindaddr = 1;
+                               } else {
+                                       ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
+                               }
+                       } else if (!strcasecmp(v->name, "bindaddr")) {
+                               if ((hp = ast_gethostbyname(v->value, &ahp))) {
+                                       memcpy(&http_desc.sin.sin_addr, hp->h_addr, sizeof(http_desc.sin.sin_addr));
                                } else {
                                        ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
                                }
                                } else {
                                        ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
                                }
@@ -869,6 +889,8 @@ static int __ast_http_load(int reload)
                }
                ast_config_destroy(cfg);
        }
                }
                ast_config_destroy(cfg);
        }
+       if (!have_sslbindaddr)
+               https_desc.sin.sin_addr = http_desc.sin.sin_addr;
        if (enabled)
                http_desc.sin.sin_family = https_desc.sin.sin_family = AF_INET;
        if (strcmp(prefix, newprefix))
        if (enabled)
                http_desc.sin.sin_family = https_desc.sin.sin_family = AF_INET;
        if (strcmp(prefix, newprefix))