1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * lws-minimal-http-client hugeurl 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 http client using lws. 10d4afb5ceSopenharmony_ci * 11d4afb5ceSopenharmony_ci * It visits https://warmcat.com/?fakeparam=<2KB> and receives the html 12d4afb5ceSopenharmony_ci * page there. You can dump the page data by changing the #if 0 below. 13d4afb5ceSopenharmony_ci */ 14d4afb5ceSopenharmony_ci 15d4afb5ceSopenharmony_ci#include <libwebsockets.h> 16d4afb5ceSopenharmony_ci#include <string.h> 17d4afb5ceSopenharmony_ci#include <signal.h> 18d4afb5ceSopenharmony_ci 19d4afb5ceSopenharmony_cistatic int interrupted, bad = 1, status; 20d4afb5ceSopenharmony_cistatic struct lws *client_wsi; 21d4afb5ceSopenharmony_ci 22d4afb5ceSopenharmony_cistatic const char * const uri = 23d4afb5ceSopenharmony_ci "/?fakeparam=" 24d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" 25d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" 26d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" 27d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" 28d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" 29d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" 30d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" 31d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" 32d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" 33d4afb5ceSopenharmony_ci "00000000000000000000000000000000000000000000000000" /* 500 */ 34d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" 35d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" 36d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" 37d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" 38d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" 39d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" 40d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" 41d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" 42d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" 43d4afb5ceSopenharmony_ci "11111111111111111111111111111111111111111111111111" /* 1000 */ 44d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" 45d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" 46d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" 47d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" 48d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" 49d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" 50d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" 51d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" 52d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" 53d4afb5ceSopenharmony_ci "22222222222222222222222222222222222222222222222222" /* 1500 */ 54d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" 55d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" 56d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" 57d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" 58d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" 59d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" 60d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" 61d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" 62d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" 63d4afb5ceSopenharmony_ci "33333333333333333333333333333333333333333333333333" /* 2000 */ 64d4afb5ceSopenharmony_ci; 65d4afb5ceSopenharmony_ci 66d4afb5ceSopenharmony_cistatic int 67d4afb5ceSopenharmony_cicallback_http(struct lws *wsi, enum lws_callback_reasons reason, 68d4afb5ceSopenharmony_ci void *user, void *in, size_t len) 69d4afb5ceSopenharmony_ci{ 70d4afb5ceSopenharmony_ci switch (reason) { 71d4afb5ceSopenharmony_ci 72d4afb5ceSopenharmony_ci /* because we are protocols[0] ... */ 73d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: 74d4afb5ceSopenharmony_ci lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", 75d4afb5ceSopenharmony_ci in ? (char *)in : "(null)"); 76d4afb5ceSopenharmony_ci client_wsi = NULL; 77d4afb5ceSopenharmony_ci break; 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: 80d4afb5ceSopenharmony_ci status = (int)lws_http_client_http_response(wsi); 81d4afb5ceSopenharmony_ci lwsl_user("Connected with server response: %d\n", status); 82d4afb5ceSopenharmony_ci break; 83d4afb5ceSopenharmony_ci 84d4afb5ceSopenharmony_ci /* chunks of chunked content, with header removed */ 85d4afb5ceSopenharmony_ci case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: 86d4afb5ceSopenharmony_ci lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len); 87d4afb5ceSopenharmony_ci#if 0 /* enable to dump the html */ 88d4afb5ceSopenharmony_ci { 89d4afb5ceSopenharmony_ci const char *p = in; 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci while (len--) 92d4afb5ceSopenharmony_ci if (*p < 0x7f) 93d4afb5ceSopenharmony_ci putchar(*p++); 94d4afb5ceSopenharmony_ci else 95d4afb5ceSopenharmony_ci putchar('.'); 96d4afb5ceSopenharmony_ci } 97d4afb5ceSopenharmony_ci#endif 98d4afb5ceSopenharmony_ci return 0; /* don't passthru */ 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci /* uninterpreted http content */ 101d4afb5ceSopenharmony_ci case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: 102d4afb5ceSopenharmony_ci { 103d4afb5ceSopenharmony_ci char buffer[1024 + LWS_PRE]; 104d4afb5ceSopenharmony_ci char *px = buffer + LWS_PRE; 105d4afb5ceSopenharmony_ci int lenx = sizeof(buffer) - LWS_PRE; 106d4afb5ceSopenharmony_ci 107d4afb5ceSopenharmony_ci if (lws_http_client_read(wsi, &px, &lenx) < 0) 108d4afb5ceSopenharmony_ci return -1; 109d4afb5ceSopenharmony_ci } 110d4afb5ceSopenharmony_ci return 0; /* don't passthru */ 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_ci case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: 113d4afb5ceSopenharmony_ci client_wsi = NULL; 114d4afb5ceSopenharmony_ci bad = status != 200; 115d4afb5ceSopenharmony_ci lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ 116d4afb5ceSopenharmony_ci break; 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLOSED_CLIENT_HTTP: 119d4afb5ceSopenharmony_ci client_wsi = NULL; 120d4afb5ceSopenharmony_ci bad = status != 200; 121d4afb5ceSopenharmony_ci lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ 122d4afb5ceSopenharmony_ci break; 123d4afb5ceSopenharmony_ci 124d4afb5ceSopenharmony_ci default: 125d4afb5ceSopenharmony_ci break; 126d4afb5ceSopenharmony_ci } 127d4afb5ceSopenharmony_ci 128d4afb5ceSopenharmony_ci return lws_callback_http_dummy(wsi, reason, user, in, len); 129d4afb5ceSopenharmony_ci} 130d4afb5ceSopenharmony_ci 131d4afb5ceSopenharmony_cistatic const struct lws_protocols protocols[] = { 132d4afb5ceSopenharmony_ci { 133d4afb5ceSopenharmony_ci "http", 134d4afb5ceSopenharmony_ci callback_http, 135d4afb5ceSopenharmony_ci 0, 0, 0, NULL, 0 136d4afb5ceSopenharmony_ci }, 137d4afb5ceSopenharmony_ci LWS_PROTOCOL_LIST_TERM 138d4afb5ceSopenharmony_ci}; 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_cistatic void 141d4afb5ceSopenharmony_cisigint_handler(int sig) 142d4afb5ceSopenharmony_ci{ 143d4afb5ceSopenharmony_ci interrupted = 1; 144d4afb5ceSopenharmony_ci} 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_ciint main(int argc, const char **argv) 147d4afb5ceSopenharmony_ci{ 148d4afb5ceSopenharmony_ci struct lws_context_creation_info info; 149d4afb5ceSopenharmony_ci struct lws_client_connect_info i; 150d4afb5ceSopenharmony_ci struct lws_context *context; 151d4afb5ceSopenharmony_ci int n = 0; 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci signal(SIGINT, sigint_handler); 154d4afb5ceSopenharmony_ci 155d4afb5ceSopenharmony_ci memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ 156d4afb5ceSopenharmony_ci lws_cmdline_option_handle_builtin(argc, argv, &info); 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci lwsl_user("LWS minimal http client hugeurl [-d <verbosity>] [-l] [--h1]\n"); 159d4afb5ceSopenharmony_ci 160d4afb5ceSopenharmony_ci info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; 161d4afb5ceSopenharmony_ci info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ 162d4afb5ceSopenharmony_ci info.protocols = protocols; 163d4afb5ceSopenharmony_ci info.pt_serv_buf_size = 8192; 164d4afb5ceSopenharmony_ci info.timeout_secs = 10; 165d4afb5ceSopenharmony_ci info.connect_timeout_secs = 30; 166d4afb5ceSopenharmony_ci /* 167d4afb5ceSopenharmony_ci * since we know this lws context is only ever going to be used with 168d4afb5ceSopenharmony_ci * one client wsis / fds / sockets at a time, let lws know it doesn't 169d4afb5ceSopenharmony_ci * have to use the default allocations for fd tables up to ulimit -n. 170d4afb5ceSopenharmony_ci * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we 171d4afb5ceSopenharmony_ci * will use. 172d4afb5ceSopenharmony_ci */ 173d4afb5ceSopenharmony_ci info.fd_limit_per_thread = 1 + 1 + 1; 174d4afb5ceSopenharmony_ci 175d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) 176d4afb5ceSopenharmony_ci /* 177d4afb5ceSopenharmony_ci * OpenSSL uses the system trust store. mbedTLS has to be told which 178d4afb5ceSopenharmony_ci * CA to trust explicitly. 179d4afb5ceSopenharmony_ci */ 180d4afb5ceSopenharmony_ci info.client_ssl_ca_filepath = "./warmcat.com.cer"; 181d4afb5ceSopenharmony_ci#endif 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ci context = lws_create_context(&info); 184d4afb5ceSopenharmony_ci if (!context) { 185d4afb5ceSopenharmony_ci lwsl_err("lws init failed\n"); 186d4afb5ceSopenharmony_ci return 1; 187d4afb5ceSopenharmony_ci } 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ 190d4afb5ceSopenharmony_ci i.context = context; 191d4afb5ceSopenharmony_ci i.ssl_connection = LCCSCF_USE_SSL; 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci if (lws_cmdline_option(argc, argv, "-l")) { 194d4afb5ceSopenharmony_ci i.port = 7681; 195d4afb5ceSopenharmony_ci i.address = "localhost"; 196d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED; 197d4afb5ceSopenharmony_ci } else { 198d4afb5ceSopenharmony_ci i.port = 443; 199d4afb5ceSopenharmony_ci i.address = "warmcat.com"; 200d4afb5ceSopenharmony_ci } 201d4afb5ceSopenharmony_ci 202d4afb5ceSopenharmony_ci if (lws_cmdline_option(argc, argv, "--h1")) 203d4afb5ceSopenharmony_ci i.alpn = "http/1.1"; 204d4afb5ceSopenharmony_ci 205d4afb5ceSopenharmony_ci i.path = uri; 206d4afb5ceSopenharmony_ci i.host = i.address; 207d4afb5ceSopenharmony_ci i.origin = i.address; 208d4afb5ceSopenharmony_ci i.method = "GET"; 209d4afb5ceSopenharmony_ci i.protocol = protocols[0].name; 210d4afb5ceSopenharmony_ci i.pwsi = &client_wsi; 211d4afb5ceSopenharmony_ci 212d4afb5ceSopenharmony_ci lws_client_connect_via_info(&i); 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci while (n >= 0 && client_wsi && !interrupted) 215d4afb5ceSopenharmony_ci n = lws_service(context, 0); 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_ci lws_context_destroy(context); 218d4afb5ceSopenharmony_ci lwsl_user("Completed: %s\n", bad? "failed": "OK"); 219d4afb5ceSopenharmony_ci 220d4afb5ceSopenharmony_ci return bad; 221d4afb5ceSopenharmony_ci} 222