mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-16 00:00:07 +01:00

RFC6724 defines an ipv6-centric DNS result sorting algorithm, that takes route and source address route information for the results given by the DNS resolution, and sorts them in order of preferability, which defines the order they should be tried in. If LWS_WITH_NETLINK, then lws takes care about collecting and monitoring the interface, route and source address information, and uses it to perform the RFC6724 sorting to re-sort the DNS before trying to make the connections.
216 lines
5.3 KiB
C
216 lines
5.3 KiB
C
/*
|
|
* lws-minimal-ws-client
|
|
*
|
|
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
|
|
*
|
|
* This file is made available under the Creative Commons CC0 1.0
|
|
* Universal Public Domain Dedication.
|
|
*
|
|
* This demonstrates a ws client that connects by default to libwebsockets.org
|
|
* dumb increment ws server.
|
|
*/
|
|
|
|
#include <libwebsockets.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
|
|
/*
|
|
* This represents your object that "contains" the client connection and has
|
|
* the client connection bound to it
|
|
*/
|
|
|
|
static struct my_conn {
|
|
lws_sorted_usec_list_t sul; /* schedule connection retry */
|
|
struct lws *wsi; /* related wsi if any */
|
|
uint16_t retry_count; /* count of consequetive retries */
|
|
} mco;
|
|
|
|
static struct lws_context *context;
|
|
static int interrupted, port = 443, ssl_connection = LCCSCF_USE_SSL;
|
|
static const char *server_address = "libwebsockets.org",
|
|
*pro = "dumb-increment-protocol";
|
|
|
|
/*
|
|
* The retry and backoff policy we want to use for our client connections
|
|
*/
|
|
|
|
static const uint32_t backoff_ms[] = { 1000, 2000, 3000, 4000, 5000 };
|
|
|
|
static const lws_retry_bo_t retry = {
|
|
.retry_ms_table = backoff_ms,
|
|
.retry_ms_table_count = LWS_ARRAY_SIZE(backoff_ms),
|
|
.conceal_count = LWS_ARRAY_SIZE(backoff_ms),
|
|
|
|
.secs_since_valid_ping = 3, /* force PINGs after secs idle */
|
|
.secs_since_valid_hangup = 10, /* hangup after secs idle */
|
|
|
|
.jitter_percent = 20,
|
|
};
|
|
|
|
/*
|
|
* Scheduled sul callback that starts the connection attempt
|
|
*/
|
|
|
|
static void
|
|
connect_client(lws_sorted_usec_list_t *sul)
|
|
{
|
|
struct my_conn *mco = lws_container_of(sul, struct my_conn, sul);
|
|
struct lws_client_connect_info i;
|
|
|
|
memset(&i, 0, sizeof(i));
|
|
|
|
i.context = context;
|
|
i.port = port;
|
|
i.address = server_address;
|
|
i.path = "/";
|
|
i.host = i.address;
|
|
i.origin = i.address;
|
|
i.ssl_connection = ssl_connection;
|
|
i.protocol = pro;
|
|
i.local_protocol_name = "lws-minimal-client";
|
|
i.pwsi = &mco->wsi;
|
|
i.retry_and_idle_policy = &retry;
|
|
i.userdata = mco;
|
|
|
|
if (!lws_client_connect_via_info(&i))
|
|
/*
|
|
* Failed... schedule a retry... we can't use the _retry_wsi()
|
|
* convenience wrapper api here because no valid wsi at this
|
|
* point.
|
|
*/
|
|
if (lws_retry_sul_schedule(context, 0, sul, &retry,
|
|
connect_client, &mco->retry_count)) {
|
|
lwsl_err("%s: connection attempts exhausted\n", __func__);
|
|
interrupted = 1;
|
|
}
|
|
}
|
|
|
|
static int
|
|
callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
|
|
void *user, void *in, size_t len)
|
|
{
|
|
struct my_conn *mco = (struct my_conn *)user;
|
|
|
|
switch (reason) {
|
|
|
|
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
|
lwsl_err("CLIENT_CONNECTION_ERROR: %s\n",
|
|
in ? (char *)in : "(null)");
|
|
goto do_retry;
|
|
break;
|
|
|
|
case LWS_CALLBACK_CLIENT_RECEIVE:
|
|
lwsl_hexdump_notice(in, len);
|
|
break;
|
|
|
|
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
|
lwsl_user("%s: established\n", __func__);
|
|
break;
|
|
|
|
case LWS_CALLBACK_CLIENT_CLOSED:
|
|
goto do_retry;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
|
|
|
do_retry:
|
|
/*
|
|
* retry the connection to keep it nailed up
|
|
*
|
|
* For this example, we try to conceal any problem for one set of
|
|
* backoff retries and then exit the app.
|
|
*
|
|
* If you set retry.conceal_count to be larger than the number of
|
|
* elements in the backoff table, it will never give up and keep
|
|
* retrying at the last backoff delay plus the random jitter amount.
|
|
*/
|
|
if (lws_retry_sul_schedule_retry_wsi(wsi, &mco->sul, connect_client,
|
|
&mco->retry_count)) {
|
|
lwsl_err("%s: connection attempts exhausted\n", __func__);
|
|
interrupted = 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct lws_protocols protocols[] = {
|
|
{ "lws-minimal-client", callback_minimal, 0, 0, },
|
|
{ NULL, NULL, 0, 0 }
|
|
};
|
|
|
|
static void
|
|
sigint_handler(int sig)
|
|
{
|
|
interrupted = 1;
|
|
}
|
|
|
|
int main(int argc, const char **argv)
|
|
{
|
|
struct lws_context_creation_info info;
|
|
const char *p;
|
|
int n = 0;
|
|
|
|
signal(SIGINT, sigint_handler);
|
|
memset(&info, 0, sizeof info);
|
|
lws_cmdline_option_handle_builtin(argc, argv, &info);
|
|
|
|
lwsl_user("LWS minimal ws client\n");
|
|
|
|
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
|
info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
|
|
info.protocols = protocols;
|
|
|
|
#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL)
|
|
/*
|
|
* OpenSSL uses the system trust store. mbedTLS has to be told which
|
|
* CA to trust explicitly.
|
|
*/
|
|
info.client_ssl_ca_filepath = "./libwebsockets.org.cer";
|
|
#endif
|
|
|
|
if ((p = lws_cmdline_option(argc, argv, "--protocol")))
|
|
pro = p;
|
|
|
|
if ((p = lws_cmdline_option(argc, argv, "-s")))
|
|
server_address = p;
|
|
|
|
if ((p = lws_cmdline_option(argc, argv, "-p")))
|
|
port = atoi(p);
|
|
|
|
if (lws_cmdline_option(argc, argv, "-n"))
|
|
ssl_connection &= ~LCCSCF_USE_SSL;
|
|
|
|
if (lws_cmdline_option(argc, argv, "-j"))
|
|
ssl_connection |= LCCSCF_ALLOW_SELFSIGNED;
|
|
|
|
if (lws_cmdline_option(argc, argv, "-k"))
|
|
ssl_connection |= LCCSCF_ALLOW_INSECURE;
|
|
|
|
if (lws_cmdline_option(argc, argv, "-m"))
|
|
ssl_connection |= LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
|
|
|
|
if (lws_cmdline_option(argc, argv, "-e"))
|
|
ssl_connection |= LCCSCF_ALLOW_EXPIRED;
|
|
|
|
info.fd_limit_per_thread = 1 + 1 + 1;
|
|
|
|
context = lws_create_context(&info);
|
|
if (!context) {
|
|
lwsl_err("lws init failed\n");
|
|
return 1;
|
|
}
|
|
|
|
/* schedule the first client connection attempt to happen immediately */
|
|
lws_sul_schedule(context, 0, &mco.sul, connect_client, 1);
|
|
|
|
while (n >= 0 && !interrupted)
|
|
n = lws_service(context, 0);
|
|
|
|
lws_context_destroy(context);
|
|
lwsl_user("Completed\n");
|
|
|
|
return 0;
|
|
}
|