1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * lws-minimal-http-server-eventlib-custom 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Written in 2010-2021 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 a minimal http server using lws, on top of a custom "event 10d4afb5ceSopenharmony_ci * library" that uses an existing application POLL loop. 11d4afb5ceSopenharmony_ci * 12d4afb5ceSopenharmony_ci * To keep it simple, it serves stuff from the subdirectory "./mount-origin" of 13d4afb5ceSopenharmony_ci * the dir it was started in. Change mount.origin to serve from elsewhere. 14d4afb5ceSopenharmony_ci */ 15d4afb5ceSopenharmony_ci 16d4afb5ceSopenharmony_ci#include <libwebsockets.h> 17d4afb5ceSopenharmony_ci#include <string.h> 18d4afb5ceSopenharmony_ci#include <signal.h> 19d4afb5ceSopenharmony_ci 20d4afb5ceSopenharmony_cistatic int interrupted; 21d4afb5ceSopenharmony_cistatic struct lws_context *context; 22d4afb5ceSopenharmony_ci 23d4afb5ceSopenharmony_ci#define MAX_CUSTOM_POLLFDS 64 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci/* this represents the existing application poll loop context we want lws 26d4afb5ceSopenharmony_ci * to cooperate with */ 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_citypedef struct custom_poll_ctx { 29d4afb5ceSopenharmony_ci struct lws_pollfd pollfds[MAX_CUSTOM_POLLFDS]; 30d4afb5ceSopenharmony_ci int count_pollfds; 31d4afb5ceSopenharmony_ci} custom_poll_ctx_t; 32d4afb5ceSopenharmony_ci 33d4afb5ceSopenharmony_ci/* for this example we just have the one, but it is passed into lws as a 34d4afb5ceSopenharmony_ci * foreign loop pointer, and all callbacks have access to it via that, so it 35d4afb5ceSopenharmony_ci * is not needed to be defined at file scope. */ 36d4afb5ceSopenharmony_cistatic custom_poll_ctx_t a_cpcx; 37d4afb5ceSopenharmony_ci 38d4afb5ceSopenharmony_ci/* 39d4afb5ceSopenharmony_ci * These are the custom event loop operators that just make the custom event 40d4afb5ceSopenharmony_ci * loop able to work by itself. These would already exist in some form in an 41d4afb5ceSopenharmony_ci * existing application. 42d4afb5ceSopenharmony_ci */ 43d4afb5ceSopenharmony_ci 44d4afb5ceSopenharmony_cistatic struct lws_pollfd * 45d4afb5ceSopenharmony_cicustom_poll_find_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd) 46d4afb5ceSopenharmony_ci{ 47d4afb5ceSopenharmony_ci int n; 48d4afb5ceSopenharmony_ci 49d4afb5ceSopenharmony_ci for (n = 0; n < cpcx->count_pollfds; n++) 50d4afb5ceSopenharmony_ci if (cpcx->pollfds[n].fd == fd) 51d4afb5ceSopenharmony_ci return &cpcx->pollfds[n]; 52d4afb5ceSopenharmony_ci 53d4afb5ceSopenharmony_ci return NULL; 54d4afb5ceSopenharmony_ci} 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_cistatic int 57d4afb5ceSopenharmony_cicustom_poll_add_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd, int events) 58d4afb5ceSopenharmony_ci{ 59d4afb5ceSopenharmony_ci struct lws_pollfd *pfd; 60d4afb5ceSopenharmony_ci 61d4afb5ceSopenharmony_ci lwsl_info("%s: ADD fd %d, ev %d\n", __func__, fd, events); 62d4afb5ceSopenharmony_ci 63d4afb5ceSopenharmony_ci pfd = custom_poll_find_fd(cpcx, fd); 64d4afb5ceSopenharmony_ci if (pfd) { 65d4afb5ceSopenharmony_ci lwsl_err("%s: ADD fd %d already in ext table\n", __func__, fd); 66d4afb5ceSopenharmony_ci return 1; 67d4afb5ceSopenharmony_ci } 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_ci if (cpcx->count_pollfds == LWS_ARRAY_SIZE(cpcx->pollfds)) { 70d4afb5ceSopenharmony_ci lwsl_err("%s: no room left\n", __func__); 71d4afb5ceSopenharmony_ci return 1; 72d4afb5ceSopenharmony_ci } 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci pfd = &cpcx->pollfds[cpcx->count_pollfds++]; 75d4afb5ceSopenharmony_ci pfd->fd = fd; 76d4afb5ceSopenharmony_ci pfd->events = (short)events; 77d4afb5ceSopenharmony_ci pfd->revents = 0; 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci return 0; 80d4afb5ceSopenharmony_ci} 81d4afb5ceSopenharmony_ci 82d4afb5ceSopenharmony_cistatic int 83d4afb5ceSopenharmony_cicustom_poll_del_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd) 84d4afb5ceSopenharmony_ci{ 85d4afb5ceSopenharmony_ci struct lws_pollfd *pfd; 86d4afb5ceSopenharmony_ci 87d4afb5ceSopenharmony_ci lwsl_info("%s: DEL fd %d\n", __func__, fd); 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_ci pfd = custom_poll_find_fd(cpcx, fd); 90d4afb5ceSopenharmony_ci if (!pfd) { 91d4afb5ceSopenharmony_ci lwsl_err("%s: DEL fd %d missing in ext table\n", __func__, fd); 92d4afb5ceSopenharmony_ci return 1; 93d4afb5ceSopenharmony_ci } 94d4afb5ceSopenharmony_ci 95d4afb5ceSopenharmony_ci if (cpcx->count_pollfds > 1) 96d4afb5ceSopenharmony_ci *pfd = cpcx->pollfds[cpcx->count_pollfds - 1]; 97d4afb5ceSopenharmony_ci 98d4afb5ceSopenharmony_ci cpcx->count_pollfds--; 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci return 0; 101d4afb5ceSopenharmony_ci} 102d4afb5ceSopenharmony_ci 103d4afb5ceSopenharmony_cistatic int 104d4afb5ceSopenharmony_cicustom_poll_change_fd(custom_poll_ctx_t *cpcx, lws_sockfd_type fd, 105d4afb5ceSopenharmony_ci int events_add, int events_remove) 106d4afb5ceSopenharmony_ci{ 107d4afb5ceSopenharmony_ci struct lws_pollfd *pfd; 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_ci lwsl_info("%s: CHG fd %d, ev_add %d, ev_rem %d\n", __func__, fd, 110d4afb5ceSopenharmony_ci events_add, events_remove); 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_ci pfd = custom_poll_find_fd(cpcx, fd); 113d4afb5ceSopenharmony_ci if (!pfd) 114d4afb5ceSopenharmony_ci return 1; 115d4afb5ceSopenharmony_ci 116d4afb5ceSopenharmony_ci pfd->events = (short)((pfd->events & (~events_remove)) | events_add); 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci return 0; 119d4afb5ceSopenharmony_ci} 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ciint 122d4afb5ceSopenharmony_cicustom_poll_run(custom_poll_ctx_t *cpcx) 123d4afb5ceSopenharmony_ci{ 124d4afb5ceSopenharmony_ci int n; 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci while (!interrupted) { 127d4afb5ceSopenharmony_ci 128d4afb5ceSopenharmony_ci /* 129d4afb5ceSopenharmony_ci * Notice that the existing loop must consult with lws about 130d4afb5ceSopenharmony_ci * the maximum wait timeout to use. Lws will reduce the 131d4afb5ceSopenharmony_ci * timeout to the earliest scheduled event time if any earlier 132d4afb5ceSopenharmony_ci * than the provided timeout. 133d4afb5ceSopenharmony_ci */ 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_ci n = lws_service_adjust_timeout(context, 5000, 0); 136d4afb5ceSopenharmony_ci 137d4afb5ceSopenharmony_ci lwsl_debug("%s: entering poll wait %dms\n", __func__, n); 138d4afb5ceSopenharmony_ci 139d4afb5ceSopenharmony_ci n = poll(cpcx->pollfds, (nfds_t)cpcx->count_pollfds, n); 140d4afb5ceSopenharmony_ci 141d4afb5ceSopenharmony_ci lwsl_debug("%s: exiting poll ret %d\n", __func__, n); 142d4afb5ceSopenharmony_ci 143d4afb5ceSopenharmony_ci if (n <= 0) 144d4afb5ceSopenharmony_ci continue; 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_ci for (n = 0; n < cpcx->count_pollfds; n++) { 147d4afb5ceSopenharmony_ci lws_sockfd_type fd = cpcx->pollfds[n].fd; 148d4afb5ceSopenharmony_ci int m; 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci if (!cpcx->pollfds[n].revents) 151d4afb5ceSopenharmony_ci continue; 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci m = lws_service_fd(context, &cpcx->pollfds[n]); 154d4afb5ceSopenharmony_ci 155d4afb5ceSopenharmony_ci /* if something closed, retry this slot since may have been 156d4afb5ceSopenharmony_ci * swapped with end fd */ 157d4afb5ceSopenharmony_ci if (m && cpcx->pollfds[n].fd != fd) 158d4afb5ceSopenharmony_ci n--; 159d4afb5ceSopenharmony_ci 160d4afb5ceSopenharmony_ci if (m < 0) 161d4afb5ceSopenharmony_ci /* lws feels something bad happened, but 162d4afb5ceSopenharmony_ci * the outer application may not care */ 163d4afb5ceSopenharmony_ci continue; 164d4afb5ceSopenharmony_ci if (!m) { 165d4afb5ceSopenharmony_ci /* check if it is an fd owned by the 166d4afb5ceSopenharmony_ci * application */ 167d4afb5ceSopenharmony_ci } 168d4afb5ceSopenharmony_ci } 169d4afb5ceSopenharmony_ci } 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ci return 0; 172d4afb5ceSopenharmony_ci} 173d4afb5ceSopenharmony_ci 174d4afb5ceSopenharmony_ci 175d4afb5ceSopenharmony_ci/* 176d4afb5ceSopenharmony_ci * These is the custom "event library" interface layer between lws event lib 177d4afb5ceSopenharmony_ci * support and the custom loop implementation above. We only need to support 178d4afb5ceSopenharmony_ci * a few key apis. 179d4afb5ceSopenharmony_ci * 180d4afb5ceSopenharmony_ci * We are user code, so all the internal lws objects are opaque. But there are 181d4afb5ceSopenharmony_ci * enough public helpers to get everything done. 182d4afb5ceSopenharmony_ci */ 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci/* one of these is appended to each pt for our use */ 185d4afb5ceSopenharmony_cistruct pt_eventlibs_custom { 186d4afb5ceSopenharmony_ci custom_poll_ctx_t *io_loop; 187d4afb5ceSopenharmony_ci}; 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci/* 190d4afb5ceSopenharmony_ci * During lws context creation, we get called with the foreign loop pointer 191d4afb5ceSopenharmony_ci * that was passed in the creation info struct. Stash it in our private part 192d4afb5ceSopenharmony_ci * of the pt, so we can reference it in the other callbacks subsequently. 193d4afb5ceSopenharmony_ci */ 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_cistatic int 196d4afb5ceSopenharmony_ciinit_pt_custom(struct lws_context *cx, void *_loop, int tsi) 197d4afb5ceSopenharmony_ci{ 198d4afb5ceSopenharmony_ci struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *) 199d4afb5ceSopenharmony_ci lws_evlib_tsi_to_evlib_pt(cx, tsi); 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci /* store the loop we are bound to in our private part of the pt */ 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci priv->io_loop = (custom_poll_ctx_t *)_loop; 204d4afb5ceSopenharmony_ci 205d4afb5ceSopenharmony_ci return 0; 206d4afb5ceSopenharmony_ci} 207d4afb5ceSopenharmony_ci 208d4afb5ceSopenharmony_cistatic int 209d4afb5ceSopenharmony_cisock_accept_custom(struct lws *wsi) 210d4afb5ceSopenharmony_ci{ 211d4afb5ceSopenharmony_ci struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *) 212d4afb5ceSopenharmony_ci lws_evlib_wsi_to_evlib_pt(wsi); 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci return custom_poll_add_fd(priv->io_loop, lws_get_socket_fd(wsi), POLLIN); 215d4afb5ceSopenharmony_ci} 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_cistatic void 218d4afb5ceSopenharmony_ciio_custom(struct lws *wsi, unsigned int flags) 219d4afb5ceSopenharmony_ci{ 220d4afb5ceSopenharmony_ci struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *) 221d4afb5ceSopenharmony_ci lws_evlib_wsi_to_evlib_pt(wsi); 222d4afb5ceSopenharmony_ci int e_add = 0, e_remove = 0; 223d4afb5ceSopenharmony_ci 224d4afb5ceSopenharmony_ci if (flags & LWS_EV_START) { 225d4afb5ceSopenharmony_ci if (flags & LWS_EV_WRITE) 226d4afb5ceSopenharmony_ci e_add |= POLLOUT; 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_ci if (flags & LWS_EV_READ) 229d4afb5ceSopenharmony_ci e_add |= POLLIN; 230d4afb5ceSopenharmony_ci } else { 231d4afb5ceSopenharmony_ci if (flags & LWS_EV_WRITE) 232d4afb5ceSopenharmony_ci e_remove |= POLLOUT; 233d4afb5ceSopenharmony_ci 234d4afb5ceSopenharmony_ci if (flags & LWS_EV_READ) 235d4afb5ceSopenharmony_ci e_remove |= POLLIN; 236d4afb5ceSopenharmony_ci } 237d4afb5ceSopenharmony_ci 238d4afb5ceSopenharmony_ci custom_poll_change_fd(priv->io_loop, lws_get_socket_fd(wsi), 239d4afb5ceSopenharmony_ci e_add, e_remove); 240d4afb5ceSopenharmony_ci} 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_cistatic int 243d4afb5ceSopenharmony_ciwsi_logical_close_custom(struct lws *wsi) 244d4afb5ceSopenharmony_ci{ 245d4afb5ceSopenharmony_ci struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *) 246d4afb5ceSopenharmony_ci lws_evlib_wsi_to_evlib_pt(wsi); 247d4afb5ceSopenharmony_ci return custom_poll_del_fd(priv->io_loop, lws_get_socket_fd(wsi)); 248d4afb5ceSopenharmony_ci} 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_cistatic const struct lws_event_loop_ops event_loop_ops_custom = { 251d4afb5ceSopenharmony_ci .name = "custom", 252d4afb5ceSopenharmony_ci 253d4afb5ceSopenharmony_ci .init_pt = init_pt_custom, 254d4afb5ceSopenharmony_ci .init_vhost_listen_wsi = sock_accept_custom, 255d4afb5ceSopenharmony_ci .sock_accept = sock_accept_custom, 256d4afb5ceSopenharmony_ci .io = io_custom, 257d4afb5ceSopenharmony_ci .wsi_logical_close = wsi_logical_close_custom, 258d4afb5ceSopenharmony_ci 259d4afb5ceSopenharmony_ci .evlib_size_pt = sizeof(struct pt_eventlibs_custom) 260d4afb5ceSopenharmony_ci}; 261d4afb5ceSopenharmony_ci 262d4afb5ceSopenharmony_cistatic const lws_plugin_evlib_t evlib_custom = { 263d4afb5ceSopenharmony_ci .hdr = { 264d4afb5ceSopenharmony_ci "custom event loop", 265d4afb5ceSopenharmony_ci "lws_evlib_plugin", 266d4afb5ceSopenharmony_ci LWS_BUILD_HASH, 267d4afb5ceSopenharmony_ci LWS_PLUGIN_API_MAGIC 268d4afb5ceSopenharmony_ci }, 269d4afb5ceSopenharmony_ci 270d4afb5ceSopenharmony_ci .ops = &event_loop_ops_custom 271d4afb5ceSopenharmony_ci}; 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci/* 274d4afb5ceSopenharmony_ci * The rest is just the normal minimal example for lws, with a couple of extra 275d4afb5ceSopenharmony_ci * lines wiring up the custom event library handlers above. 276d4afb5ceSopenharmony_ci */ 277d4afb5ceSopenharmony_ci 278d4afb5ceSopenharmony_cistatic const struct lws_http_mount mount = { 279d4afb5ceSopenharmony_ci /* .mount_next */ NULL, /* linked-list "next" */ 280d4afb5ceSopenharmony_ci /* .mountpoint */ "/", /* mountpoint URL */ 281d4afb5ceSopenharmony_ci /* .origin */ "./mount-origin", /* serve from dir */ 282d4afb5ceSopenharmony_ci /* .def */ "index.html", /* default filename */ 283d4afb5ceSopenharmony_ci /* .protocol */ NULL, 284d4afb5ceSopenharmony_ci /* .cgienv */ NULL, 285d4afb5ceSopenharmony_ci /* .extra_mimetypes */ NULL, 286d4afb5ceSopenharmony_ci /* .interpret */ NULL, 287d4afb5ceSopenharmony_ci /* .cgi_timeout */ 0, 288d4afb5ceSopenharmony_ci /* .cache_max_age */ 0, 289d4afb5ceSopenharmony_ci /* .auth_mask */ 0, 290d4afb5ceSopenharmony_ci /* .cache_reusable */ 0, 291d4afb5ceSopenharmony_ci /* .cache_revalidate */ 0, 292d4afb5ceSopenharmony_ci /* .cache_intermediaries */ 0, 293d4afb5ceSopenharmony_ci /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ 294d4afb5ceSopenharmony_ci /* .mountpoint_len */ 1, /* char count */ 295d4afb5ceSopenharmony_ci /* .basic_auth_login_file */ NULL, 296d4afb5ceSopenharmony_ci}; 297d4afb5ceSopenharmony_ci 298d4afb5ceSopenharmony_ci/* 299d4afb5ceSopenharmony_ci * This demonstrates a client connection operating on the same loop 300d4afb5ceSopenharmony_ci * It's optional... 301d4afb5ceSopenharmony_ci */ 302d4afb5ceSopenharmony_ci 303d4afb5ceSopenharmony_cistatic int 304d4afb5ceSopenharmony_cicallback_http(struct lws *wsi, enum lws_callback_reasons reason, 305d4afb5ceSopenharmony_ci void *user, void *in, size_t len) 306d4afb5ceSopenharmony_ci{ 307d4afb5ceSopenharmony_ci switch (reason) { 308d4afb5ceSopenharmony_ci 309d4afb5ceSopenharmony_ci case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: 310d4afb5ceSopenharmony_ci lwsl_user("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: resp %u\n", 311d4afb5ceSopenharmony_ci lws_http_client_http_response(wsi)); 312d4afb5ceSopenharmony_ci break; 313d4afb5ceSopenharmony_ci 314d4afb5ceSopenharmony_ci /* because we are protocols[0] ... */ 315d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: 316d4afb5ceSopenharmony_ci lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", 317d4afb5ceSopenharmony_ci in ? (char *)in : "(null)"); 318d4afb5ceSopenharmony_ci break; 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ci /* chunks of chunked content, with header removed */ 321d4afb5ceSopenharmony_ci case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: 322d4afb5ceSopenharmony_ci lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len); 323d4afb5ceSopenharmony_ci lwsl_hexdump_info(in, len); 324d4afb5ceSopenharmony_ci return 0; /* don't passthru */ 325d4afb5ceSopenharmony_ci 326d4afb5ceSopenharmony_ci /* uninterpreted http content */ 327d4afb5ceSopenharmony_ci case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: 328d4afb5ceSopenharmony_ci { 329d4afb5ceSopenharmony_ci char buffer[1024 + LWS_PRE]; 330d4afb5ceSopenharmony_ci char *px = buffer + LWS_PRE; 331d4afb5ceSopenharmony_ci int lenx = sizeof(buffer) - LWS_PRE; 332d4afb5ceSopenharmony_ci 333d4afb5ceSopenharmony_ci if (lws_http_client_read(wsi, &px, &lenx) < 0) 334d4afb5ceSopenharmony_ci return -1; 335d4afb5ceSopenharmony_ci } 336d4afb5ceSopenharmony_ci return 0; /* don't passthru */ 337d4afb5ceSopenharmony_ci 338d4afb5ceSopenharmony_ci case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: 339d4afb5ceSopenharmony_ci lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP %s\n", 340d4afb5ceSopenharmony_ci lws_wsi_tag(wsi)); 341d4afb5ceSopenharmony_ci break; 342d4afb5ceSopenharmony_ci 343d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLOSED_CLIENT_HTTP: 344d4afb5ceSopenharmony_ci lwsl_info("%s: closed: %s\n", __func__, lws_wsi_tag(wsi)); 345d4afb5ceSopenharmony_ci break; 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_ci default: 348d4afb5ceSopenharmony_ci break; 349d4afb5ceSopenharmony_ci } 350d4afb5ceSopenharmony_ci 351d4afb5ceSopenharmony_ci return lws_callback_http_dummy(wsi, reason, user, in, len); 352d4afb5ceSopenharmony_ci} 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_cistatic const struct lws_protocols protocols[] = { 355d4afb5ceSopenharmony_ci { "httptest", callback_http, 0, 0, 0, NULL, 0}, 356d4afb5ceSopenharmony_ci LWS_PROTOCOL_LIST_TERM 357d4afb5ceSopenharmony_ci}; 358d4afb5ceSopenharmony_ci 359d4afb5ceSopenharmony_cistatic int 360d4afb5ceSopenharmony_cido_client_conn(void) 361d4afb5ceSopenharmony_ci{ 362d4afb5ceSopenharmony_ci struct lws_client_connect_info i; 363d4afb5ceSopenharmony_ci 364d4afb5ceSopenharmony_ci memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ 365d4afb5ceSopenharmony_ci 366d4afb5ceSopenharmony_ci i.context = context; 367d4afb5ceSopenharmony_ci 368d4afb5ceSopenharmony_ci i.ssl_connection = LCCSCF_USE_SSL; 369d4afb5ceSopenharmony_ci i.port = 443; 370d4afb5ceSopenharmony_ci i.address = "warmcat.com"; 371d4afb5ceSopenharmony_ci 372d4afb5ceSopenharmony_ci i.ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR | 373d4afb5ceSopenharmony_ci LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; 374d4afb5ceSopenharmony_ci i.path = "/"; 375d4afb5ceSopenharmony_ci i.host = i.address; 376d4afb5ceSopenharmony_ci i.origin = i.address; 377d4afb5ceSopenharmony_ci i.method = "GET"; 378d4afb5ceSopenharmony_ci i.protocol = protocols[0].name; 379d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 380d4afb5ceSopenharmony_ci i.fi_wsi_name = "user"; 381d4afb5ceSopenharmony_ci#endif 382d4afb5ceSopenharmony_ci 383d4afb5ceSopenharmony_ci if (!lws_client_connect_via_info(&i)) { 384d4afb5ceSopenharmony_ci lwsl_err("Client creation failed\n"); 385d4afb5ceSopenharmony_ci 386d4afb5ceSopenharmony_ci return 1; 387d4afb5ceSopenharmony_ci } 388d4afb5ceSopenharmony_ci 389d4afb5ceSopenharmony_ci lwsl_notice("Client creation OK\n"); 390d4afb5ceSopenharmony_ci 391d4afb5ceSopenharmony_ci return 0; 392d4afb5ceSopenharmony_ci} 393d4afb5ceSopenharmony_ci 394d4afb5ceSopenharmony_ci/* 395d4afb5ceSopenharmony_ci * End of client part 396d4afb5ceSopenharmony_ci * 397d4afb5ceSopenharmony_ci * Initialization part --> 398d4afb5ceSopenharmony_ci */ 399d4afb5ceSopenharmony_ci 400d4afb5ceSopenharmony_civoid sigint_handler(int sig) 401d4afb5ceSopenharmony_ci{ 402d4afb5ceSopenharmony_ci interrupted = 1; 403d4afb5ceSopenharmony_ci} 404d4afb5ceSopenharmony_ci 405d4afb5ceSopenharmony_ciint main(int argc, const char **argv) 406d4afb5ceSopenharmony_ci{ 407d4afb5ceSopenharmony_ci struct lws_context_creation_info info; 408d4afb5ceSopenharmony_ci const char *p; 409d4afb5ceSopenharmony_ci int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; 410d4afb5ceSopenharmony_ci void *foreign_loops[1]; 411d4afb5ceSopenharmony_ci 412d4afb5ceSopenharmony_ci signal(SIGINT, sigint_handler); 413d4afb5ceSopenharmony_ci 414d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-d"))) 415d4afb5ceSopenharmony_ci logs = atoi(p); 416d4afb5ceSopenharmony_ci 417d4afb5ceSopenharmony_ci /* 418d4afb5ceSopenharmony_ci * init the existing custom event loop here if anything to do, don't 419d4afb5ceSopenharmony_ci * run it yet. In our example, no init required. 420d4afb5ceSopenharmony_ci */ 421d4afb5ceSopenharmony_ci 422d4afb5ceSopenharmony_ci lws_set_log_level(logs, NULL); 423d4afb5ceSopenharmony_ci lwsl_user("LWS minimal http server | visit http://localhost:7681\n"); 424d4afb5ceSopenharmony_ci 425d4afb5ceSopenharmony_ci memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ 426d4afb5ceSopenharmony_ci info.port = 7681; 427d4afb5ceSopenharmony_ci info.mounts = &mount; 428d4afb5ceSopenharmony_ci info.error_document_404 = "/404.html"; 429d4afb5ceSopenharmony_ci info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | 430d4afb5ceSopenharmony_ci LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; 431d4afb5ceSopenharmony_ci 432d4afb5ceSopenharmony_ci info.event_lib_custom = &evlib_custom; /* bind lws to our custom event 433d4afb5ceSopenharmony_ci * lib implementation above */ 434d4afb5ceSopenharmony_ci foreign_loops[0] = &a_cpcx; /* pass in the custom poll object as the 435d4afb5ceSopenharmony_ci * foreign loop object we will bind to */ 436d4afb5ceSopenharmony_ci info.foreign_loops = foreign_loops; 437d4afb5ceSopenharmony_ci 438d4afb5ceSopenharmony_ci /* optional to demonstrate client connection */ 439d4afb5ceSopenharmony_ci info.protocols = protocols; 440d4afb5ceSopenharmony_ci 441d4afb5ceSopenharmony_ci context = lws_create_context(&info); 442d4afb5ceSopenharmony_ci if (!context) { 443d4afb5ceSopenharmony_ci lwsl_err("lws init failed\n"); 444d4afb5ceSopenharmony_ci return 1; 445d4afb5ceSopenharmony_ci } 446d4afb5ceSopenharmony_ci 447d4afb5ceSopenharmony_ci /* optional to demonstrate client connection */ 448d4afb5ceSopenharmony_ci do_client_conn(); 449d4afb5ceSopenharmony_ci 450d4afb5ceSopenharmony_ci /* 451d4afb5ceSopenharmony_ci * We're going to run the custom loop now, instead of the lws loop. 452d4afb5ceSopenharmony_ci * We have told lws to cooperate with this loop to get stuff done. 453d4afb5ceSopenharmony_ci * 454d4afb5ceSopenharmony_ci * We only come back from this when interrupted gets set by SIGINT 455d4afb5ceSopenharmony_ci */ 456d4afb5ceSopenharmony_ci 457d4afb5ceSopenharmony_ci custom_poll_run(&a_cpcx); 458d4afb5ceSopenharmony_ci 459d4afb5ceSopenharmony_ci /* clean up lws part */ 460d4afb5ceSopenharmony_ci 461d4afb5ceSopenharmony_ci lws_context_destroy(context); 462d4afb5ceSopenharmony_ci 463d4afb5ceSopenharmony_ci return 0; 464d4afb5ceSopenharmony_ci} 465