1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include "private-lib-core.h" 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_ci#include "extension-permessage-deflate.h" 28d4afb5ceSopenharmony_ci 29d4afb5ceSopenharmony_civoid 30d4afb5ceSopenharmony_cilws_context_init_extensions(const struct lws_context_creation_info *info, 31d4afb5ceSopenharmony_ci struct lws_context *context) 32d4afb5ceSopenharmony_ci{ 33d4afb5ceSopenharmony_ci lwsl_cx_info(context, " LWS_MAX_EXTENSIONS_ACTIVE: %u", LWS_MAX_EXTENSIONS_ACTIVE); 34d4afb5ceSopenharmony_ci} 35d4afb5ceSopenharmony_ci 36d4afb5ceSopenharmony_cienum lws_ext_option_parser_states { 37d4afb5ceSopenharmony_ci LEAPS_SEEK_NAME, 38d4afb5ceSopenharmony_ci LEAPS_EAT_NAME, 39d4afb5ceSopenharmony_ci LEAPS_SEEK_VAL, 40d4afb5ceSopenharmony_ci LEAPS_EAT_DEC, 41d4afb5ceSopenharmony_ci LEAPS_SEEK_ARG_TERM 42d4afb5ceSopenharmony_ci}; 43d4afb5ceSopenharmony_ci 44d4afb5ceSopenharmony_ciint 45d4afb5ceSopenharmony_cilws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, 46d4afb5ceSopenharmony_ci void *ext_user, const struct lws_ext_options *opts, 47d4afb5ceSopenharmony_ci const char *in, int len) 48d4afb5ceSopenharmony_ci{ 49d4afb5ceSopenharmony_ci enum lws_ext_option_parser_states leap = LEAPS_SEEK_NAME; 50d4afb5ceSopenharmony_ci unsigned int match_map = 0, n, m, w = 0, count_options = 0, 51d4afb5ceSopenharmony_ci pending_close_quote = 0; 52d4afb5ceSopenharmony_ci struct lws_ext_option_arg oa; 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_ci oa.option_name = NULL; 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci while (opts[count_options].name) 57d4afb5ceSopenharmony_ci count_options++; 58d4afb5ceSopenharmony_ci while (len) { 59d4afb5ceSopenharmony_ci lwsl_wsi_ext(wsi, "'%c' %d", *in, leap); 60d4afb5ceSopenharmony_ci switch (leap) { 61d4afb5ceSopenharmony_ci case LEAPS_SEEK_NAME: 62d4afb5ceSopenharmony_ci if (*in == ' ') 63d4afb5ceSopenharmony_ci break; 64d4afb5ceSopenharmony_ci if (*in == ',') { 65d4afb5ceSopenharmony_ci len = 1; 66d4afb5ceSopenharmony_ci break; 67d4afb5ceSopenharmony_ci } 68d4afb5ceSopenharmony_ci match_map = (unsigned int)(1 << count_options) - 1; 69d4afb5ceSopenharmony_ci leap = LEAPS_EAT_NAME; 70d4afb5ceSopenharmony_ci w = 0; 71d4afb5ceSopenharmony_ci 72d4afb5ceSopenharmony_ci /* fallthru */ 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci case LEAPS_EAT_NAME: 75d4afb5ceSopenharmony_ci oa.start = NULL; 76d4afb5ceSopenharmony_ci oa.len = 0; 77d4afb5ceSopenharmony_ci m = match_map; 78d4afb5ceSopenharmony_ci n = 0; 79d4afb5ceSopenharmony_ci pending_close_quote = 0; 80d4afb5ceSopenharmony_ci while (m) { 81d4afb5ceSopenharmony_ci if (!(m & 1)) { 82d4afb5ceSopenharmony_ci m >>= 1; 83d4afb5ceSopenharmony_ci n++; 84d4afb5ceSopenharmony_ci continue; 85d4afb5ceSopenharmony_ci } 86d4afb5ceSopenharmony_ci lwsl_wsi_ext(wsi, " m=%d, n=%d, w=%d", m, n, w); 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci if (*in == opts[n].name[w]) { 89d4afb5ceSopenharmony_ci if (!opts[n].name[w + 1]) { 90d4afb5ceSopenharmony_ci oa.option_index = (int)n; 91d4afb5ceSopenharmony_ci lwsl_wsi_ext(wsi, "hit %d", 92d4afb5ceSopenharmony_ci oa.option_index); 93d4afb5ceSopenharmony_ci leap = LEAPS_SEEK_VAL; 94d4afb5ceSopenharmony_ci if (len == 1) 95d4afb5ceSopenharmony_ci goto set_arg; 96d4afb5ceSopenharmony_ci break; 97d4afb5ceSopenharmony_ci } 98d4afb5ceSopenharmony_ci } else { 99d4afb5ceSopenharmony_ci match_map &= (unsigned int)~(1 << n); 100d4afb5ceSopenharmony_ci if (!match_map) { 101d4afb5ceSopenharmony_ci lwsl_wsi_ext(wsi, "empty match map"); 102d4afb5ceSopenharmony_ci return -1; 103d4afb5ceSopenharmony_ci } 104d4afb5ceSopenharmony_ci } 105d4afb5ceSopenharmony_ci 106d4afb5ceSopenharmony_ci m >>= 1; 107d4afb5ceSopenharmony_ci n++; 108d4afb5ceSopenharmony_ci } 109d4afb5ceSopenharmony_ci w++; 110d4afb5ceSopenharmony_ci break; 111d4afb5ceSopenharmony_ci case LEAPS_SEEK_VAL: 112d4afb5ceSopenharmony_ci if (*in == ' ') 113d4afb5ceSopenharmony_ci break; 114d4afb5ceSopenharmony_ci if (*in == ',') { 115d4afb5ceSopenharmony_ci len = 1; 116d4afb5ceSopenharmony_ci break; 117d4afb5ceSopenharmony_ci } 118d4afb5ceSopenharmony_ci if (*in == ';' || len == 1) { /* ie,nonoptional */ 119d4afb5ceSopenharmony_ci if (opts[oa.option_index].type == EXTARG_DEC) 120d4afb5ceSopenharmony_ci return -1; 121d4afb5ceSopenharmony_ci leap = LEAPS_SEEK_NAME; 122d4afb5ceSopenharmony_ci goto set_arg; 123d4afb5ceSopenharmony_ci } 124d4afb5ceSopenharmony_ci if (*in == '=') { 125d4afb5ceSopenharmony_ci w = 0; 126d4afb5ceSopenharmony_ci pending_close_quote = 0; 127d4afb5ceSopenharmony_ci if (opts[oa.option_index].type == EXTARG_NONE) 128d4afb5ceSopenharmony_ci return -1; 129d4afb5ceSopenharmony_ci 130d4afb5ceSopenharmony_ci leap = LEAPS_EAT_DEC; 131d4afb5ceSopenharmony_ci break; 132d4afb5ceSopenharmony_ci } 133d4afb5ceSopenharmony_ci return -1; 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_ci case LEAPS_EAT_DEC: 136d4afb5ceSopenharmony_ci if (*in >= '0' && *in <= '9') { 137d4afb5ceSopenharmony_ci if (!w) 138d4afb5ceSopenharmony_ci oa.start = in; 139d4afb5ceSopenharmony_ci w++; 140d4afb5ceSopenharmony_ci if (len != 1) 141d4afb5ceSopenharmony_ci break; 142d4afb5ceSopenharmony_ci } 143d4afb5ceSopenharmony_ci if (!w && *in =='"') { 144d4afb5ceSopenharmony_ci pending_close_quote = 1; 145d4afb5ceSopenharmony_ci break; 146d4afb5ceSopenharmony_ci } 147d4afb5ceSopenharmony_ci if (!w) 148d4afb5ceSopenharmony_ci return -1; 149d4afb5ceSopenharmony_ci if (pending_close_quote && *in != '"' && len != 1) 150d4afb5ceSopenharmony_ci return -1; 151d4afb5ceSopenharmony_ci leap = LEAPS_SEEK_ARG_TERM; 152d4afb5ceSopenharmony_ci if (oa.start) 153d4afb5ceSopenharmony_ci oa.len = lws_ptr_diff(in, oa.start); 154d4afb5ceSopenharmony_ci if (len == 1) 155d4afb5ceSopenharmony_ci oa.len++; 156d4afb5ceSopenharmony_ci 157d4afb5ceSopenharmony_ciset_arg: 158d4afb5ceSopenharmony_ci ext->callback(lws_get_context(wsi), 159d4afb5ceSopenharmony_ci ext, wsi, LWS_EXT_CB_OPTION_SET, 160d4afb5ceSopenharmony_ci ext_user, (char *)&oa, 0); 161d4afb5ceSopenharmony_ci if (len == 1) 162d4afb5ceSopenharmony_ci break; 163d4afb5ceSopenharmony_ci if (pending_close_quote && *in == '"') 164d4afb5ceSopenharmony_ci break; 165d4afb5ceSopenharmony_ci 166d4afb5ceSopenharmony_ci /* fallthru */ 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci case LEAPS_SEEK_ARG_TERM: 169d4afb5ceSopenharmony_ci if (*in == ' ') 170d4afb5ceSopenharmony_ci break; 171d4afb5ceSopenharmony_ci if (*in == ';') { 172d4afb5ceSopenharmony_ci leap = LEAPS_SEEK_NAME; 173d4afb5ceSopenharmony_ci break; 174d4afb5ceSopenharmony_ci } 175d4afb5ceSopenharmony_ci if (*in == ',') { 176d4afb5ceSopenharmony_ci len = 1; 177d4afb5ceSopenharmony_ci break; 178d4afb5ceSopenharmony_ci } 179d4afb5ceSopenharmony_ci return -1; 180d4afb5ceSopenharmony_ci } 181d4afb5ceSopenharmony_ci len--; 182d4afb5ceSopenharmony_ci in++; 183d4afb5ceSopenharmony_ci } 184d4afb5ceSopenharmony_ci 185d4afb5ceSopenharmony_ci return 0; 186d4afb5ceSopenharmony_ci} 187d4afb5ceSopenharmony_ci 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci/* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */ 190d4afb5ceSopenharmony_ci 191d4afb5ceSopenharmony_ciint lws_ext_cb_active(struct lws *wsi, int reason, void *arg, int len) 192d4afb5ceSopenharmony_ci{ 193d4afb5ceSopenharmony_ci int n, m, handled = 0; 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_ci if (!wsi->ws) 196d4afb5ceSopenharmony_ci return 0; 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_ci for (n = 0; n < wsi->ws->count_act_ext; n++) { 199d4afb5ceSopenharmony_ci m = wsi->ws->active_extensions[n]->callback( 200d4afb5ceSopenharmony_ci lws_get_context(wsi), wsi->ws->active_extensions[n], 201d4afb5ceSopenharmony_ci wsi, (enum lws_extension_callback_reasons)reason, wsi->ws->act_ext_user[n], arg, (size_t)len); 202d4afb5ceSopenharmony_ci if (m < 0) { 203d4afb5ceSopenharmony_ci lwsl_wsi_ext(wsi, "Ext '%s' failed to handle callback %d!", 204d4afb5ceSopenharmony_ci wsi->ws->active_extensions[n]->name, reason); 205d4afb5ceSopenharmony_ci return -1; 206d4afb5ceSopenharmony_ci } 207d4afb5ceSopenharmony_ci /* valgrind... */ 208d4afb5ceSopenharmony_ci if (reason == LWS_EXT_CB_DESTROY) 209d4afb5ceSopenharmony_ci wsi->ws->act_ext_user[n] = NULL; 210d4afb5ceSopenharmony_ci if (m > handled) 211d4afb5ceSopenharmony_ci handled = m; 212d4afb5ceSopenharmony_ci } 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci return handled; 215d4afb5ceSopenharmony_ci} 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_ciint lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi, 218d4afb5ceSopenharmony_ci int reason, void *arg, int len) 219d4afb5ceSopenharmony_ci{ 220d4afb5ceSopenharmony_ci int n = 0, m, handled = 0; 221d4afb5ceSopenharmony_ci const struct lws_extension *ext; 222d4afb5ceSopenharmony_ci 223d4afb5ceSopenharmony_ci if (!wsi || !wsi->a.vhost || !wsi->ws) 224d4afb5ceSopenharmony_ci return 0; 225d4afb5ceSopenharmony_ci 226d4afb5ceSopenharmony_ci ext = wsi->a.vhost->ws.extensions; 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_ci while (ext && ext->callback && !handled) { 229d4afb5ceSopenharmony_ci m = ext->callback(context, ext, wsi, (enum lws_extension_callback_reasons)reason, 230d4afb5ceSopenharmony_ci (void *)(lws_intptr_t)n, arg, (size_t)len); 231d4afb5ceSopenharmony_ci if (m < 0) { 232d4afb5ceSopenharmony_ci lwsl_wsi_ext(wsi, "Ext '%s' failed to handle callback %d!", 233d4afb5ceSopenharmony_ci wsi->ws->active_extensions[n]->name, reason); 234d4afb5ceSopenharmony_ci return -1; 235d4afb5ceSopenharmony_ci } 236d4afb5ceSopenharmony_ci if (m) 237d4afb5ceSopenharmony_ci handled = 1; 238d4afb5ceSopenharmony_ci 239d4afb5ceSopenharmony_ci ext++; 240d4afb5ceSopenharmony_ci n++; 241d4afb5ceSopenharmony_ci } 242d4afb5ceSopenharmony_ci 243d4afb5ceSopenharmony_ci return 0; 244d4afb5ceSopenharmony_ci} 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ciint 247d4afb5ceSopenharmony_cilws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len) 248d4afb5ceSopenharmony_ci{ 249d4afb5ceSopenharmony_ci struct lws_tokens ebuf; 250d4afb5ceSopenharmony_ci int ret, m, n = 0; 251d4afb5ceSopenharmony_ci 252d4afb5ceSopenharmony_ci ebuf.token = buf; 253d4afb5ceSopenharmony_ci ebuf.len = (int)len; 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci /* 256d4afb5ceSopenharmony_ci * while we have original buf to spill ourselves, or extensions report 257d4afb5ceSopenharmony_ci * more in their pipeline 258d4afb5ceSopenharmony_ci */ 259d4afb5ceSopenharmony_ci 260d4afb5ceSopenharmony_ci ret = 1; 261d4afb5ceSopenharmony_ci while (ret == 1) { 262d4afb5ceSopenharmony_ci 263d4afb5ceSopenharmony_ci /* default to nobody has more to spill */ 264d4afb5ceSopenharmony_ci 265d4afb5ceSopenharmony_ci ret = 0; 266d4afb5ceSopenharmony_ci 267d4afb5ceSopenharmony_ci /* show every extension the new incoming data */ 268d4afb5ceSopenharmony_ci m = lws_ext_cb_active(wsi, LWS_EXT_CB_PACKET_TX_PRESEND, 269d4afb5ceSopenharmony_ci &ebuf, 0); 270d4afb5ceSopenharmony_ci if (m < 0) 271d4afb5ceSopenharmony_ci return -1; 272d4afb5ceSopenharmony_ci if (m) /* handled */ 273d4afb5ceSopenharmony_ci ret = 1; 274d4afb5ceSopenharmony_ci 275d4afb5ceSopenharmony_ci if (buf != ebuf.token) 276d4afb5ceSopenharmony_ci /* 277d4afb5ceSopenharmony_ci * extension recreated it: 278d4afb5ceSopenharmony_ci * need to buffer this if not all sent 279d4afb5ceSopenharmony_ci */ 280d4afb5ceSopenharmony_ci wsi->ws->clean_buffer = 0; 281d4afb5ceSopenharmony_ci 282d4afb5ceSopenharmony_ci /* assuming they left us something to send, send it */ 283d4afb5ceSopenharmony_ci 284d4afb5ceSopenharmony_ci if (ebuf.len) { 285d4afb5ceSopenharmony_ci n = lws_issue_raw(wsi, ebuf.token, (size_t)ebuf.len); 286d4afb5ceSopenharmony_ci if (n < 0) { 287d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "closing from ext access"); 288d4afb5ceSopenharmony_ci return -1; 289d4afb5ceSopenharmony_ci } 290d4afb5ceSopenharmony_ci 291d4afb5ceSopenharmony_ci /* always either sent it all or privately buffered */ 292d4afb5ceSopenharmony_ci if (wsi->ws->clean_buffer) 293d4afb5ceSopenharmony_ci len = (size_t)n; 294d4afb5ceSopenharmony_ci 295d4afb5ceSopenharmony_ci lwsl_wsi_ext(wsi, "written %d bytes to client", n); 296d4afb5ceSopenharmony_ci } 297d4afb5ceSopenharmony_ci 298d4afb5ceSopenharmony_ci /* no extension has more to spill? Then we can go */ 299d4afb5ceSopenharmony_ci 300d4afb5ceSopenharmony_ci if (!ret) 301d4afb5ceSopenharmony_ci break; 302d4afb5ceSopenharmony_ci 303d4afb5ceSopenharmony_ci /* we used up what we had */ 304d4afb5ceSopenharmony_ci 305d4afb5ceSopenharmony_ci ebuf.token = NULL; 306d4afb5ceSopenharmony_ci ebuf.len = 0; 307d4afb5ceSopenharmony_ci 308d4afb5ceSopenharmony_ci /* 309d4afb5ceSopenharmony_ci * Did that leave the pipe choked? 310d4afb5ceSopenharmony_ci * Or we had to hold on to some of it? 311d4afb5ceSopenharmony_ci */ 312d4afb5ceSopenharmony_ci 313d4afb5ceSopenharmony_ci if (!lws_send_pipe_choked(wsi) && !lws_has_buffered_out(wsi)) 314d4afb5ceSopenharmony_ci /* no we could add more, lets's do that */ 315d4afb5ceSopenharmony_ci continue; 316d4afb5ceSopenharmony_ci 317d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "choked"); 318d4afb5ceSopenharmony_ci 319d4afb5ceSopenharmony_ci /* 320d4afb5ceSopenharmony_ci * Yes, he's choked. Don't spill the rest now get a callback 321d4afb5ceSopenharmony_ci * when he is ready to send and take care of it there 322d4afb5ceSopenharmony_ci */ 323d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 324d4afb5ceSopenharmony_ci wsi->ws->extension_data_pending = 1; 325d4afb5ceSopenharmony_ci ret = 0; 326d4afb5ceSopenharmony_ci } 327d4afb5ceSopenharmony_ci 328d4afb5ceSopenharmony_ci return (int)len; 329d4afb5ceSopenharmony_ci} 330d4afb5ceSopenharmony_ci 331d4afb5ceSopenharmony_ciint 332d4afb5ceSopenharmony_cilws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r, 333d4afb5ceSopenharmony_ci void *v, size_t len) 334d4afb5ceSopenharmony_ci{ 335d4afb5ceSopenharmony_ci struct lws_context *context = wsi->a.context; 336d4afb5ceSopenharmony_ci int n, handled = 0; 337d4afb5ceSopenharmony_ci 338d4afb5ceSopenharmony_ci if (!wsi->ws) 339d4afb5ceSopenharmony_ci return 0; 340d4afb5ceSopenharmony_ci 341d4afb5ceSopenharmony_ci /* maybe an extension will take care of it for us */ 342d4afb5ceSopenharmony_ci 343d4afb5ceSopenharmony_ci for (n = 0; n < wsi->ws->count_act_ext && !handled; n++) { 344d4afb5ceSopenharmony_ci if (!wsi->ws->active_extensions[n]->callback) 345d4afb5ceSopenharmony_ci continue; 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_ci handled |= wsi->ws->active_extensions[n]->callback(context, 348d4afb5ceSopenharmony_ci wsi->ws->active_extensions[n], wsi, 349d4afb5ceSopenharmony_ci r, wsi->ws->act_ext_user[n], v, len); 350d4afb5ceSopenharmony_ci } 351d4afb5ceSopenharmony_ci 352d4afb5ceSopenharmony_ci return handled; 353d4afb5ceSopenharmony_ci} 354d4afb5ceSopenharmony_ci 355d4afb5ceSopenharmony_ciint 356d4afb5ceSopenharmony_cilws_set_extension_option(struct lws *wsi, const char *ext_name, 357d4afb5ceSopenharmony_ci const char *opt_name, const char *opt_val) 358d4afb5ceSopenharmony_ci{ 359d4afb5ceSopenharmony_ci struct lws_ext_option_arg oa; 360d4afb5ceSopenharmony_ci int idx = 0; 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ci if (!wsi->ws) 363d4afb5ceSopenharmony_ci return 0; 364d4afb5ceSopenharmony_ci 365d4afb5ceSopenharmony_ci /* first identify if the ext is active on this wsi */ 366d4afb5ceSopenharmony_ci while (idx < wsi->ws->count_act_ext && 367d4afb5ceSopenharmony_ci strcmp(wsi->ws->active_extensions[idx]->name, ext_name)) 368d4afb5ceSopenharmony_ci idx++; 369d4afb5ceSopenharmony_ci 370d4afb5ceSopenharmony_ci if (idx == wsi->ws->count_act_ext) 371d4afb5ceSopenharmony_ci return -1; /* request ext not active on this wsi */ 372d4afb5ceSopenharmony_ci 373d4afb5ceSopenharmony_ci oa.option_name = opt_name; 374d4afb5ceSopenharmony_ci oa.option_index = 0; 375d4afb5ceSopenharmony_ci oa.start = opt_val; 376d4afb5ceSopenharmony_ci oa.len = 0; 377d4afb5ceSopenharmony_ci 378d4afb5ceSopenharmony_ci return wsi->ws->active_extensions[idx]->callback(wsi->a.context, 379d4afb5ceSopenharmony_ci wsi->ws->active_extensions[idx], wsi, 380d4afb5ceSopenharmony_ci LWS_EXT_CB_NAMED_OPTION_SET, wsi->ws->act_ext_user[idx], 381d4afb5ceSopenharmony_ci &oa, 0); 382d4afb5ceSopenharmony_ci} 383