<p>Kevin Harwell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/17926">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_http_websocket: Add a client connection timeout<br><br>Previously there was no way to specify a connection timeout when<br>attempting to connect a websocket client to a server. This patch<br>makes it possible to now do such.<br><br>Change-Id: I5812f6f28d3d13adbc246517f87af177fa20ee9d<br>---<br>M include/asterisk/http_websocket.h<br>M res/res_http_websocket.c<br>2 files changed, 71 insertions(+), 11 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/26/17926/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/http_websocket.h b/include/asterisk/http_websocket.h</span><br><span>index 2a55e60..ee7f9b8 100644</span><br><span>--- a/include/asterisk/http_websocket.h</span><br><span>+++ b/include/asterisk/http_websocket.h</span><br><span>@@ -441,6 +441,55 @@</span><br><span>              enum ast_websocket_result *result), { return NULL;});</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Options used for a websocket client</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_websocket_client_options {</span><br><span style="color: hsl(120, 100%, 40%);">+ /*!</span><br><span style="color: hsl(120, 100%, 40%);">+    * The URI to connect to</span><br><span style="color: hsl(120, 100%, 40%);">+       *</span><br><span style="color: hsl(120, 100%, 40%);">+     * Expected uri form:</span><br><span style="color: hsl(120, 100%, 40%);">+  *     \verbatim ws[s]://<address>[:port][/<path>] \endverbatim</span><br><span style="color: hsl(120, 100%, 40%);">+    *     The address (can be a host name) and port are parsed out and used to connect</span><br><span style="color: hsl(120, 100%, 40%);">+    *     to the remote server.  If multiple IPs are returned during address</span><br><span style="color: hsl(120, 100%, 40%);">+      *     resolution then the first one is chosen.</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *uri;</span><br><span style="color: hsl(120, 100%, 40%);">+      /*!</span><br><span style="color: hsl(120, 100%, 40%);">+    * A comma separated string of supported protocols</span><br><span style="color: hsl(120, 100%, 40%);">+     */</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *protocols;</span><br><span style="color: hsl(120, 100%, 40%);">+        /*!</span><br><span style="color: hsl(120, 100%, 40%);">+    * Optional connection timeout</span><br><span style="color: hsl(120, 100%, 40%);">+         *</span><br><span style="color: hsl(120, 100%, 40%);">+     * How long (in milliseconds) to attempt to connect (-1 equals infinite)</span><br><span style="color: hsl(120, 100%, 40%);">+       */</span><br><span style="color: hsl(120, 100%, 40%);">+   int timeout;</span><br><span style="color: hsl(120, 100%, 40%);">+  /*!</span><br><span style="color: hsl(120, 100%, 40%);">+    * Secure websocket credentials</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_tls_config *tls_cfg;</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%);">+ * \brief Create, and connect, a websocket client using given options.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * If the client websocket successfully connects, then the accepted protocol can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * checked via a call to ast_websocket_client_accept_protocol.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note While connecting this *will* block until a response is received</span><br><span style="color: hsl(120, 100%, 40%);">+ *       from the remote host, or the connection timeout is reached</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param options Websocket client options</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param result result code set on client failure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return a client websocket.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL if object could not be created or connected</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+AST_OPTIONAL_API(struct ast_websocket *, ast_websocket_client_create_with_options,</span><br><span style="color: hsl(120, 100%, 40%);">+  (struct ast_websocket_client_options *options,</span><br><span style="color: hsl(120, 100%, 40%);">+        enum ast_websocket_result *result), { return NULL;});</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \brief Retrieve the server accepted sub-protocol on the client.</span><br><span>  *</span><br><span>  * \param ws the websocket client</span><br><span>diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c</span><br><span>index 879762e..d0a5ea7 100644</span><br><span>--- a/res/res_http_websocket.c</span><br><span>+++ b/res/res_http_websocket.c</span><br><span>@@ -1223,8 +1223,7 @@</span><br><span> }</span><br><span> </span><br><span> static struct ast_websocket * websocket_client_create(</span><br><span style="color: hsl(0, 100%, 40%);">-   const char *uri, const char *protocols, struct ast_tls_config *tls_cfg,</span><br><span style="color: hsl(0, 100%, 40%);">- enum ast_websocket_result *result)</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_websocket_client_options *options, enum ast_websocket_result *result)</span><br><span> {</span><br><span>        struct ast_websocket *ws = ao2_alloc(sizeof(*ws), session_destroy_fn);</span><br><span> </span><br><span>@@ -1248,18 +1247,18 @@</span><br><span>         }</span><br><span> </span><br><span>        if (websocket_client_parse_uri(</span><br><span style="color: hsl(0, 100%, 40%);">-             uri, &ws->client->host, &ws->client->resource_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    options->uri, &ws->client->host, &ws->client->resource_name)) {</span><br><span>           ao2_ref(ws, -1);</span><br><span>             *result = WS_URI_PARSE_ERROR;</span><br><span>                return NULL;</span><br><span>         }</span><br><span> </span><br><span>        if (!(ws->client->args = websocket_client_args_create(</span><br><span style="color: hsl(0, 100%, 40%);">-                  ws->client->host, tls_cfg, result))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  ws->client->host, options->tls_cfg, result))) {</span><br><span>               ao2_ref(ws, -1);</span><br><span>             return NULL;</span><br><span>         }</span><br><span style="color: hsl(0, 100%, 40%);">-       ws->client->protocols = ast_strdup(protocols);</span><br><span style="color: hsl(120, 100%, 40%);">+  ws->client->protocols = ast_strdup(options->protocols);</span><br><span> </span><br><span>         ws->client->version = 13;</span><br><span>      ws->opcode = -1;</span><br><span>@@ -1395,13 +1394,13 @@</span><br><span>        return websocket_client_handshake_get_response(client);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static enum ast_websocket_result websocket_client_connect(struct ast_websocket *ws)</span><br><span style="color: hsl(120, 100%, 40%);">+static enum ast_websocket_result websocket_client_connect(struct ast_websocket *ws, int timeout)</span><br><span> {</span><br><span>   enum ast_websocket_result res;</span><br><span>       /* create and connect the client - note client_start</span><br><span>            releases the session instance on failure */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!(ws->client->ser = ast_tcptls_client_start(</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_tcptls_client_create(ws->client->args)))) {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!(ws->client->ser = ast_tcptls_client_start_timeout(</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_tcptls_client_create(ws->client->args), timeout))) {</span><br><span>                 return WS_CLIENT_START_ERROR;</span><br><span>        }</span><br><span> </span><br><span>@@ -1422,14 +1421,26 @@</span><br><span>      (const char *uri, const char *protocols, struct ast_tls_config *tls_cfg,</span><br><span>      enum ast_websocket_result *result)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        struct ast_websocket *ws = websocket_client_create(</span><br><span style="color: hsl(0, 100%, 40%);">-             uri, protocols, tls_cfg, result);</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_websocket_client_options options = {</span><br><span style="color: hsl(120, 100%, 40%);">+               .uri = uri,</span><br><span style="color: hsl(120, 100%, 40%);">+           .protocols = protocols,</span><br><span style="color: hsl(120, 100%, 40%);">+               .timeout = -1,</span><br><span style="color: hsl(120, 100%, 40%);">+                .tls_cfg = tls_cfg,</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 ast_websocket_client_create_with_options(&options, result);</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%);">+struct ast_websocket *AST_OPTIONAL_API_NAME(ast_websocket_client_create_with_options)</span><br><span style="color: hsl(120, 100%, 40%);">+    (struct ast_websocket_client_options *options, enum ast_websocket_result *result)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_websocket *ws = websocket_client_create(options, result);</span><br><span> </span><br><span>     if (!ws) {</span><br><span>           return NULL;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if ((*result = websocket_client_connect(ws)) != WS_OK) {</span><br><span style="color: hsl(120, 100%, 40%);">+      if ((*result = websocket_client_connect(ws, options->timeout)) != WS_OK) {</span><br><span>                ao2_ref(ws, -1);</span><br><span>             return NULL;</span><br><span>         }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/17926">change 17926</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/+/17926"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: I5812f6f28d3d13adbc246517f87af177fa20ee9d </div>
<div style="display:none"> Gerrit-Change-Number: 17926 </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>