]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_http_websocket: Add a client connection timeout
authorKevin Harwell <kharwell@sangoma.com>
Thu, 13 Jan 2022 22:31:27 +0000 (16:31 -0600)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Mon, 31 Jan 2022 13:04:21 +0000 (07:04 -0600)
Previously there was no way to specify a connection timeout when
attempting to connect a websocket client to a server. This patch
makes it possible to now do such.

Change-Id: I5812f6f28d3d13adbc246517f87af177fa20ee9d

include/asterisk/http_websocket.h
res/res_http_websocket.c

index 2a55e6006a99e83c97da4d2261e58aeb3a28c19a..ee7f9b8c1ba08391b98b9a3f81b7df3f6d0e652a 100644 (file)
@@ -440,6 +440,55 @@ AST_OPTIONAL_API(struct ast_websocket *, ast_websocket_client_create,
                  struct ast_tls_config *tls_cfg,
                  enum ast_websocket_result *result), { return NULL;});
 
+/*!
+ * \brief Options used for a websocket client
+ */
+struct ast_websocket_client_options {
+       /*!
+        * The URI to connect to
+        *
+        * Expected uri form:
+        *     \verbatim ws[s]://<address>[:port][/<path>] \endverbatim
+        *     The address (can be a host name) and port are parsed out and used to connect
+        *     to the remote server.  If multiple IPs are returned during address
+        *     resolution then the first one is chosen.
+        */
+       const char *uri;
+       /*!
+        * A comma separated string of supported protocols
+        */
+       const char *protocols;
+       /*!
+        * Optional connection timeout
+        *
+        * How long (in milliseconds) to attempt to connect (-1 equals infinite)
+        */
+       int timeout;
+       /*!
+        * Secure websocket credentials
+        */
+       struct ast_tls_config *tls_cfg;
+};
+
+/*!
+ * \brief Create, and connect, a websocket client using given options.
+ *
+ * If the client websocket successfully connects, then the accepted protocol can be
+ * checked via a call to ast_websocket_client_accept_protocol.
+ *
+ * \note While connecting this *will* block until a response is received
+ *       from the remote host, or the connection timeout is reached
+ *
+ * \param options Websocket client options
+ * \param result result code set on client failure
+ *
+ * \return a client websocket.
+ * \retval NULL if object could not be created or connected
+ */
+AST_OPTIONAL_API(struct ast_websocket *, ast_websocket_client_create_with_options,
+       (struct ast_websocket_client_options *options,
+       enum ast_websocket_result *result), { return NULL;});
+
 /*!
  * \brief Retrieve the server accepted sub-protocol on the client.
  *
index 624f20cd4dd15d3b85257f0d37a7876207d97823..05efee9ec3e3764d79b1fecb12f7c8e5ce46d6ef 100644 (file)
@@ -1223,8 +1223,7 @@ static void websocket_client_destroy(void *obj)
 }
 
 static struct ast_websocket * websocket_client_create(
-       const char *uri, const char *protocols, struct ast_tls_config *tls_cfg,
-       enum ast_websocket_result *result)
+       struct ast_websocket_client_options *options, enum ast_websocket_result *result)
 {
        struct ast_websocket *ws = ao2_alloc(sizeof(*ws), session_destroy_fn);
 
@@ -1248,18 +1247,18 @@ static struct ast_websocket * websocket_client_create(
        }
 
        if (websocket_client_parse_uri(
-                   uri, &ws->client->host, &ws->client->resource_name)) {
+                   options->uri, &ws->client->host, &ws->client->resource_name)) {
                ao2_ref(ws, -1);
                *result = WS_URI_PARSE_ERROR;
                return NULL;
        }
 
        if (!(ws->client->args = websocket_client_args_create(
-                     ws->client->host, tls_cfg, result))) {
+                     ws->client->host, options->tls_cfg, result))) {
                ao2_ref(ws, -1);
                return NULL;
        }
-       ws->client->protocols = ast_strdup(protocols);
+       ws->client->protocols = ast_strdup(options->protocols);
 
        ws->client->version = 13;
        ws->opcode = -1;
@@ -1395,13 +1394,13 @@ static enum ast_websocket_result websocket_client_handshake(
        return websocket_client_handshake_get_response(client);
 }
 
-static enum ast_websocket_result websocket_client_connect(struct ast_websocket *ws)
+static enum ast_websocket_result websocket_client_connect(struct ast_websocket *ws, int timeout)
 {
        enum ast_websocket_result res;
        /* create and connect the client - note client_start
           releases the session instance on failure */
-       if (!(ws->client->ser = ast_tcptls_client_start(
-                     ast_tcptls_client_create(ws->client->args)))) {
+       if (!(ws->client->ser = ast_tcptls_client_start_timeout(
+                     ast_tcptls_client_create(ws->client->args), timeout))) {
                return WS_CLIENT_START_ERROR;
        }
 
@@ -1422,14 +1421,26 @@ struct ast_websocket *AST_OPTIONAL_API_NAME(ast_websocket_client_create)
        (const char *uri, const char *protocols, struct ast_tls_config *tls_cfg,
         enum ast_websocket_result *result)
 {
-       struct ast_websocket *ws = websocket_client_create(
-               uri, protocols, tls_cfg, result);
+       struct ast_websocket_client_options options = {
+               .uri = uri,
+               .protocols = protocols,
+               .timeout = -1,
+               .tls_cfg = tls_cfg,
+       };
+
+       return ast_websocket_client_create_with_options(&options, result);
+}
+
+struct ast_websocket *AST_OPTIONAL_API_NAME(ast_websocket_client_create_with_options)
+       (struct ast_websocket_client_options *options, enum ast_websocket_result *result)
+{
+       struct ast_websocket *ws = websocket_client_create(options, result);
 
        if (!ws) {
                return NULL;
        }
 
-       if ((*result = websocket_client_connect(ws)) != WS_OK) {
+       if ((*result = websocket_client_connect(ws, options->timeout)) != WS_OK) {
                ao2_ref(ws, -1);
                return NULL;
        }