<p>Kevin Harwell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/17471">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">http.c: Add an http test server<br><br>This patch adds the ability to start and stop an http server from<br>unit tests, if TEST_FRAMWORK is enabled. This will only start and<br>stop a server if one has not already been enabled through standard<br>configuration.<br><br>Change-Id: Ic5fb5f11e62c019a1c51310f4667b32a4dae52f5<br>---<br>M include/asterisk/http.h<br>M main/http.c<br>2 files changed, 125 insertions(+), 21 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/71/17471/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/http.h b/include/asterisk/http.h</span><br><span>index 63fb223..340645e 100644</span><br><span>--- a/include/asterisk/http.h</span><br><span>+++ b/include/asterisk/http.h</span><br><span>@@ -354,4 +354,25 @@</span><br><span> int ast_http_header_match_in(const char *name, const char *expected_name,</span><br><span>                           const char *value, const char *expected_value);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+/*!\brief Resolve given address, and start an HTTP server listening on it</span><br><span style="color: hsl(120, 100%, 40%);">+ *        only if a server has not been enabled in the config file.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param args Optional session arguments</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param bindaddr Optional address to bind server to (defaults to 127.0.0.1)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param bindport Optional port (defaults to 8088)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 if success, -1 if an error occurred and server not started</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_http_test_server_resolve_and_start(struct ast_tcptls_session_args *args,</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *bindaddr, uint32_t bindport);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!\brief Stop a test server</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param args Optional session arguments</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_http_test_server_stop(struct ast_tcptls_session_args *args);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif /* _ASTERISK_SRV_H */</span><br><span>diff --git a/main/http.c b/main/http.c</span><br><span>index a0f15f43..9446f10 100644</span><br><span>--- a/main/http.c</span><br><span>+++ b/main/http.c</span><br><span>@@ -2074,6 +2074,107 @@</span><br><span>         AST_RWLIST_UNLOCK(&uri_redirects);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int http_server_start(struct ast_tcptls_session_args *args,</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_sockaddr *addr, uint32_t bindport)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_sockaddr_copy(&args->local_address, addr);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_sockaddr_port(&args->local_address)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_sockaddr_set_port(&args->local_address, bindport);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_tcptls_server_start(args);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (args->accept_fd == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_WARNING, "Failed to start HTTP server for address %s\n", ast_sockaddr_stringify(addr));</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_sockaddr_setnull(&args->local_address);</span><br><span style="color: hsl(120, 100%, 40%);">+            return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_verb(1, "Bound HTTP server to address %s\n", ast_sockaddr_stringify(addr));</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int http_server_start_available(struct ast_tcptls_session_args *args,</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_sockaddr *addrs, int num_addrs, uint32_t bindport)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < num_addrs; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!http_server_start(args, &addrs[i], bindport)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return i == num_addrs ? -1 : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int http_server_resolve_and_start(struct ast_tcptls_session_args *args,</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *bindaddr, uint32_t bindport)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_sockaddr *addrs = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    int num_addrs;</span><br><span style="color: hsl(120, 100%, 40%);">+        int res;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!(num_addrs = ast_sockaddr_resolve(&addrs, bindaddr, 0, AST_AF_UNSPEC))) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "Invalid bind address %s\n", bindaddr);</span><br><span style="color: hsl(120, 100%, 40%);">+                return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (bindport == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          bindport = DEFAULT_PORT;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   res = http_server_start_available(args, addrs, num_addrs, bindport);</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_free(addrs);</span><br><span style="color: hsl(120, 100%, 40%);">+      return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_tcptls_session_args http_test_args = {</span><br><span style="color: hsl(120, 100%, 40%);">+   .accept_fd = -1,</span><br><span style="color: hsl(120, 100%, 40%);">+      .master = AST_PTHREADT_NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+  .tls_cfg = NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+      .poll_timeout = -1,</span><br><span style="color: hsl(120, 100%, 40%);">+   .name = "http test server",</span><br><span style="color: hsl(120, 100%, 40%);">+ .accept_fn = ast_tcptls_server_root,</span><br><span style="color: hsl(120, 100%, 40%);">+  .worker_fn = httpd_helper_thread,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_http_test_server_resolve_and_start(struct ast_tcptls_session_args *args,</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *bindaddr, uint32_t bindport)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!args) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!ast_sockaddr_isnull(&http_desc.old_address)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* An http server is already enabled, just use that one */</span><br><span style="color: hsl(120, 100%, 40%);">+                    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Disabled in config, so enable one for testing */</span><br><span style="color: hsl(120, 100%, 40%);">+           args = &http_test_args;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_strlen_zero(bindaddr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              bindaddr = "127.0.0.1";</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return http_server_resolve_and_start(args, bindaddr, bindport);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_http_test_server_stop(struct ast_tcptls_session_args *args)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!args) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!ast_sockaddr_isnull(&http_desc.old_address)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* The config enabled server was used, so don't stop */</span><br><span style="color: hsl(120, 100%, 40%);">+                   return;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           args = &http_test_args;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_tcptls_server_stop(args);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int __ast_http_load(int reload)</span><br><span> {</span><br><span>    struct ast_config *cfg;</span><br><span>@@ -2086,9 +2187,8 @@</span><br><span>      struct http_uri_redirect *redirect;</span><br><span>  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };</span><br><span>  uint32_t bindport = DEFAULT_PORT;</span><br><span style="color: hsl(0, 100%, 40%);">-       RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">- int num_addrs = 0;</span><br><span>   int http_tls_was_enabled = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *bindaddr = NULL;</span><br><span> </span><br><span>   cfg = ast_config_load2("http.conf", "http", config_flags);</span><br><span>       if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {</span><br><span>@@ -2169,9 +2269,7 @@</span><br><span>                                      v->value, DEFAULT_PORT);</span><br><span>                  }</span><br><span>            } else if (!strcasecmp(v->name, "bindaddr")) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     if (!(num_addrs = ast_sockaddr_resolve(&addrs, v->value, 0, AST_AF_UNSPEC))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                           ast_log(LOG_WARNING, "Invalid bind address %s\n", v->value);</span><br><span style="color: hsl(0, 100%, 40%);">-                       }</span><br><span style="color: hsl(120, 100%, 40%);">+                     bindaddr = ast_strdupa(v->value);</span><br><span>                 } else if (!strcasecmp(v->name, "prefix")) {</span><br><span>                    if (!ast_strlen_zero(v->value)) {</span><br><span>                                 newprefix[0] = '/';</span><br><span>@@ -2213,22 +2311,7 @@</span><br><span> </span><br><span>     ast_copy_string(http_server_name, server_name, sizeof(http_server_name));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (num_addrs && enabled) {</span><br><span style="color: hsl(0, 100%, 40%);">-             int i;</span><br><span style="color: hsl(0, 100%, 40%);">-          for (i = 0; i < num_addrs; ++i) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_sockaddr_copy(&http_desc.local_address, &addrs[i]);</span><br><span style="color: hsl(0, 100%, 40%);">-                 if (!ast_sockaddr_port(&http_desc.local_address)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                         ast_sockaddr_set_port(&http_desc.local_address, bindport);</span><br><span style="color: hsl(0, 100%, 40%);">-                  }</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_tcptls_server_start(&http_desc);</span><br><span style="color: hsl(0, 100%, 40%);">-                        if (http_desc.accept_fd == -1) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                ast_log(LOG_WARNING, "Failed to start HTTP server for address %s\n", ast_sockaddr_stringify(&addrs[i]));</span><br><span style="color: hsl(0, 100%, 40%);">-                          ast_sockaddr_setnull(&http_desc.local_address);</span><br><span style="color: hsl(0, 100%, 40%);">-                     } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                ast_verb(1, "Bound HTTP server to address %s\n", ast_sockaddr_stringify(&addrs[i]));</span><br><span style="color: hsl(0, 100%, 40%);">-                              break;</span><br><span style="color: hsl(0, 100%, 40%);">-                  }</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (enabled && !http_server_resolve_and_start(&http_desc, bindaddr, bindport)) {</span><br><span>                 /* When no specific TLS bindaddr is specified, we just use</span><br><span>            * the non-TLS bindaddress here.</span><br><span>              */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/17471">change 17471</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/17471"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ic5fb5f11e62c019a1c51310f4667b32a4dae52f5 </div>
<div style="display:none"> Gerrit-Change-Number: 17471 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>