1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * lws-minimal-ws-client 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Written in 2010-2019 by Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * This file is made available under the Creative Commons CC0 1.0 7d4afb5ceSopenharmony_ci * Universal Public Domain Dedication. 8d4afb5ceSopenharmony_ci * 9d4afb5ceSopenharmony_ci * This demonstrates the a minimal ws client using lws. 10d4afb5ceSopenharmony_ci * 11d4afb5ceSopenharmony_ci * It connects to https://libwebsockets.org/ and makes a 12d4afb5ceSopenharmony_ci * wss connection to the dumb-increment protocol there. While 13d4afb5ceSopenharmony_ci * connected, it prints the numbers it is being sent by 14d4afb5ceSopenharmony_ci * dumb-increment protocol. 15d4afb5ceSopenharmony_ci */ 16d4afb5ceSopenharmony_ci 17d4afb5ceSopenharmony_ci#include <libwebsockets.h> 18d4afb5ceSopenharmony_ci#include <string.h> 19d4afb5ceSopenharmony_ci#include <signal.h> 20d4afb5ceSopenharmony_ci 21d4afb5ceSopenharmony_cistatic int interrupted, rx_seen, test; 22d4afb5ceSopenharmony_cistatic struct lws *client_wsi; 23d4afb5ceSopenharmony_ci 24d4afb5ceSopenharmony_cistatic int 25d4afb5ceSopenharmony_cicallback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, 26d4afb5ceSopenharmony_ci void *user, void *in, size_t len) 27d4afb5ceSopenharmony_ci{ 28d4afb5ceSopenharmony_ci switch (reason) { 29d4afb5ceSopenharmony_ci 30d4afb5ceSopenharmony_ci /* because we are protocols[0] ... */ 31d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: 32d4afb5ceSopenharmony_ci lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", 33d4afb5ceSopenharmony_ci in ? (char *)in : "(null)"); 34d4afb5ceSopenharmony_ci client_wsi = NULL; 35d4afb5ceSopenharmony_ci break; 36d4afb5ceSopenharmony_ci 37d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_ESTABLISHED: 38d4afb5ceSopenharmony_ci lwsl_user("%s: established\n", __func__); 39d4afb5ceSopenharmony_ci break; 40d4afb5ceSopenharmony_ci 41d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_RECEIVE: 42d4afb5ceSopenharmony_ci lwsl_user("RX: %s\n", (const char *)in); 43d4afb5ceSopenharmony_ci rx_seen++; 44d4afb5ceSopenharmony_ci if (test && rx_seen == 10) 45d4afb5ceSopenharmony_ci interrupted = 1; 46d4afb5ceSopenharmony_ci break; 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_CLOSED: 49d4afb5ceSopenharmony_ci client_wsi = NULL; 50d4afb5ceSopenharmony_ci break; 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_ci default: 53d4afb5ceSopenharmony_ci break; 54d4afb5ceSopenharmony_ci } 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci return lws_callback_http_dummy(wsi, reason, user, in, len); 57d4afb5ceSopenharmony_ci} 58d4afb5ceSopenharmony_ci 59d4afb5ceSopenharmony_cistatic const struct lws_protocols protocols[] = { 60d4afb5ceSopenharmony_ci { 61d4afb5ceSopenharmony_ci "dumb-increment-protocol", 62d4afb5ceSopenharmony_ci callback_dumb_increment, 63d4afb5ceSopenharmony_ci 0, 0, 0, NULL, 0 64d4afb5ceSopenharmony_ci }, 65d4afb5ceSopenharmony_ci LWS_PROTOCOL_LIST_TERM 66d4afb5ceSopenharmony_ci}; 67d4afb5ceSopenharmony_ci 68d4afb5ceSopenharmony_cistatic void 69d4afb5ceSopenharmony_cisigint_handler(int sig) 70d4afb5ceSopenharmony_ci{ 71d4afb5ceSopenharmony_ci interrupted = 1; 72d4afb5ceSopenharmony_ci} 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ciint main(int argc, const char **argv) 75d4afb5ceSopenharmony_ci{ 76d4afb5ceSopenharmony_ci struct lws_context_creation_info info; 77d4afb5ceSopenharmony_ci struct lws_client_connect_info i; 78d4afb5ceSopenharmony_ci struct lws_context *context; 79d4afb5ceSopenharmony_ci const char *p; 80d4afb5ceSopenharmony_ci int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE 81d4afb5ceSopenharmony_ci /* for LLL_ verbosity above NOTICE to be built into lws, lws 82d4afb5ceSopenharmony_ci * must have been configured with -DCMAKE_BUILD_TYPE=DEBUG 83d4afb5ceSopenharmony_ci * instead of =RELEASE */ 84d4afb5ceSopenharmony_ci /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ 85d4afb5ceSopenharmony_ci /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ 86d4afb5ceSopenharmony_ci /* | LLL_DEBUG */; 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci signal(SIGINT, sigint_handler); 89d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-d"))) 90d4afb5ceSopenharmony_ci logs = atoi(p); 91d4afb5ceSopenharmony_ci 92d4afb5ceSopenharmony_ci test = !!lws_cmdline_option(argc, argv, "-t"); 93d4afb5ceSopenharmony_ci 94d4afb5ceSopenharmony_ci lws_set_log_level(logs, NULL); 95d4afb5ceSopenharmony_ci lwsl_user("LWS minimal ws client rx [-d <logs>] [--h2] [-t (test)]\n"); 96d4afb5ceSopenharmony_ci 97d4afb5ceSopenharmony_ci memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ 98d4afb5ceSopenharmony_ci info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; 99d4afb5ceSopenharmony_ci info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ 100d4afb5ceSopenharmony_ci info.protocols = protocols; 101d4afb5ceSopenharmony_ci info.timeout_secs = 10; 102d4afb5ceSopenharmony_ci info.connect_timeout_secs = 30; 103d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) 104d4afb5ceSopenharmony_ci /* 105d4afb5ceSopenharmony_ci * OpenSSL uses the system trust store. mbedTLS has to be told which 106d4afb5ceSopenharmony_ci * CA to trust explicitly. 107d4afb5ceSopenharmony_ci */ 108d4afb5ceSopenharmony_ci info.client_ssl_ca_filepath = "./libwebsockets.org.cer"; 109d4afb5ceSopenharmony_ci#endif 110d4afb5ceSopenharmony_ci 111d4afb5ceSopenharmony_ci /* 112d4afb5ceSopenharmony_ci * since we know this lws context is only ever going to be used with 113d4afb5ceSopenharmony_ci * one client wsis / fds / sockets at a time, let lws know it doesn't 114d4afb5ceSopenharmony_ci * have to use the default allocations for fd tables up to ulimit -n. 115d4afb5ceSopenharmony_ci * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we 116d4afb5ceSopenharmony_ci * will use. 117d4afb5ceSopenharmony_ci */ 118d4afb5ceSopenharmony_ci info.fd_limit_per_thread = 1 + 1 + 1; 119d4afb5ceSopenharmony_ci 120d4afb5ceSopenharmony_ci context = lws_create_context(&info); 121d4afb5ceSopenharmony_ci if (!context) { 122d4afb5ceSopenharmony_ci lwsl_err("lws init failed\n"); 123d4afb5ceSopenharmony_ci return 1; 124d4afb5ceSopenharmony_ci } 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ 127d4afb5ceSopenharmony_ci i.context = context; 128d4afb5ceSopenharmony_ci i.port = 443; 129d4afb5ceSopenharmony_ci i.address = "libwebsockets.org"; 130d4afb5ceSopenharmony_ci i.path = "/"; 131d4afb5ceSopenharmony_ci i.host = i.address; 132d4afb5ceSopenharmony_ci i.origin = i.address; 133d4afb5ceSopenharmony_ci i.ssl_connection = LCCSCF_USE_SSL; 134d4afb5ceSopenharmony_ci i.protocol = protocols[0].name; /* "dumb-increment-protocol" */ 135d4afb5ceSopenharmony_ci i.pwsi = &client_wsi; 136d4afb5ceSopenharmony_ci 137d4afb5ceSopenharmony_ci if (lws_cmdline_option(argc, argv, "--h2")) 138d4afb5ceSopenharmony_ci i.alpn = "h2"; 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_ci lws_client_connect_via_info(&i); 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci while (n >= 0 && client_wsi && !interrupted) 143d4afb5ceSopenharmony_ci n = lws_service(context, 0); 144d4afb5ceSopenharmony_ci 145d4afb5ceSopenharmony_ci lws_context_destroy(context); 146d4afb5ceSopenharmony_ci 147d4afb5ceSopenharmony_ci lwsl_user("Completed %s\n", rx_seen > 10 ? "OK" : "Failed"); 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_ci return rx_seen > 10; 150d4afb5ceSopenharmony_ci} 151