1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2020 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#ifdef LWS_HAVE_SYS_TYPES_H 28d4afb5ceSopenharmony_ci#include <sys/types.h> 29d4afb5ceSopenharmony_ci#endif 30d4afb5ceSopenharmony_ci#include <signal.h> 31d4afb5ceSopenharmony_ci 32d4afb5ceSopenharmony_civoid 33d4afb5ceSopenharmony_cilws_ser_wu16be(uint8_t *b, uint16_t u) 34d4afb5ceSopenharmony_ci{ 35d4afb5ceSopenharmony_ci *b++ = (uint8_t)(u >> 8); 36d4afb5ceSopenharmony_ci *b = (uint8_t)u; 37d4afb5ceSopenharmony_ci} 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_civoid 40d4afb5ceSopenharmony_cilws_ser_wu32be(uint8_t *b, uint32_t u32) 41d4afb5ceSopenharmony_ci{ 42d4afb5ceSopenharmony_ci *b++ = (uint8_t)(u32 >> 24); 43d4afb5ceSopenharmony_ci *b++ = (uint8_t)(u32 >> 16); 44d4afb5ceSopenharmony_ci *b++ = (uint8_t)(u32 >> 8); 45d4afb5ceSopenharmony_ci *b = (uint8_t)u32; 46d4afb5ceSopenharmony_ci} 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_civoid 49d4afb5ceSopenharmony_cilws_ser_wu64be(uint8_t *b, uint64_t u64) 50d4afb5ceSopenharmony_ci{ 51d4afb5ceSopenharmony_ci lws_ser_wu32be(b, (uint32_t)(u64 >> 32)); 52d4afb5ceSopenharmony_ci lws_ser_wu32be(b + 4, (uint32_t)u64); 53d4afb5ceSopenharmony_ci} 54d4afb5ceSopenharmony_ci 55d4afb5ceSopenharmony_ciuint16_t 56d4afb5ceSopenharmony_cilws_ser_ru16be(const uint8_t *b) 57d4afb5ceSopenharmony_ci{ 58d4afb5ceSopenharmony_ci return (uint16_t)((b[0] << 8) | b[1]); 59d4afb5ceSopenharmony_ci} 60d4afb5ceSopenharmony_ci 61d4afb5ceSopenharmony_ciuint32_t 62d4afb5ceSopenharmony_cilws_ser_ru32be(const uint8_t *b) 63d4afb5ceSopenharmony_ci{ 64d4afb5ceSopenharmony_ci return (unsigned int)((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); 65d4afb5ceSopenharmony_ci} 66d4afb5ceSopenharmony_ci 67d4afb5ceSopenharmony_ciuint64_t 68d4afb5ceSopenharmony_cilws_ser_ru64be(const uint8_t *b) 69d4afb5ceSopenharmony_ci{ 70d4afb5ceSopenharmony_ci return (((uint64_t)lws_ser_ru32be(b)) << 32) | lws_ser_ru32be(b + 4); 71d4afb5ceSopenharmony_ci} 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_ciint 74d4afb5ceSopenharmony_cilws_vbi_encode(uint64_t value, void *buf) 75d4afb5ceSopenharmony_ci{ 76d4afb5ceSopenharmony_ci uint8_t *p = (uint8_t *)buf, b; 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_ci if (value > 0xfffffff) { 79d4afb5ceSopenharmony_ci assert(0); 80d4afb5ceSopenharmony_ci return -1; 81d4afb5ceSopenharmony_ci } 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci do { 84d4afb5ceSopenharmony_ci b = value & 0x7f; 85d4afb5ceSopenharmony_ci value >>= 7; 86d4afb5ceSopenharmony_ci if (value) 87d4afb5ceSopenharmony_ci *p++ = (0x80 | b); 88d4afb5ceSopenharmony_ci else 89d4afb5ceSopenharmony_ci *p++ = b; 90d4afb5ceSopenharmony_ci } while (value); 91d4afb5ceSopenharmony_ci 92d4afb5ceSopenharmony_ci return lws_ptr_diff(p, buf); 93d4afb5ceSopenharmony_ci} 94d4afb5ceSopenharmony_ci 95d4afb5ceSopenharmony_ciint 96d4afb5ceSopenharmony_cilws_vbi_decode(const void *buf, uint64_t *value, size_t len) 97d4afb5ceSopenharmony_ci{ 98d4afb5ceSopenharmony_ci const uint8_t *p = (const uint8_t *)buf, *end = p + len; 99d4afb5ceSopenharmony_ci uint64_t v = 0; 100d4afb5ceSopenharmony_ci int s = 0; 101d4afb5ceSopenharmony_ci 102d4afb5ceSopenharmony_ci while (p < end) { 103d4afb5ceSopenharmony_ci v |= (((uint64_t)(*p)) & 0x7f) << s; 104d4afb5ceSopenharmony_ci if (*p & 0x80) { 105d4afb5ceSopenharmony_ci *value = v; 106d4afb5ceSopenharmony_ci 107d4afb5ceSopenharmony_ci return lws_ptr_diff(p, buf); 108d4afb5ceSopenharmony_ci } 109d4afb5ceSopenharmony_ci s += 7; 110d4afb5ceSopenharmony_ci if (s >= 64) 111d4afb5ceSopenharmony_ci return 0; 112d4afb5ceSopenharmony_ci p++; 113d4afb5ceSopenharmony_ci } 114d4afb5ceSopenharmony_ci 115d4afb5ceSopenharmony_ci return 0; 116d4afb5ceSopenharmony_ci} 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_cisigned char char_to_hex(const char c) 119d4afb5ceSopenharmony_ci{ 120d4afb5ceSopenharmony_ci if (c >= '0' && c <= '9') 121d4afb5ceSopenharmony_ci return (signed char)(c - '0'); 122d4afb5ceSopenharmony_ci 123d4afb5ceSopenharmony_ci if (c >= 'a' && c <= 'f') 124d4afb5ceSopenharmony_ci return (signed char)(c - 'a' + 10); 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci if (c >= 'A' && c <= 'F') 127d4afb5ceSopenharmony_ci return (signed char)(c - 'A' + 10); 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_ci return (signed char)-1; 130d4afb5ceSopenharmony_ci} 131d4afb5ceSopenharmony_ci 132d4afb5ceSopenharmony_ciint 133d4afb5ceSopenharmony_cilws_hex_to_byte_array(const char *h, uint8_t *dest, int max) 134d4afb5ceSopenharmony_ci{ 135d4afb5ceSopenharmony_ci uint8_t *odest = dest; 136d4afb5ceSopenharmony_ci 137d4afb5ceSopenharmony_ci while (max-- && *h) { 138d4afb5ceSopenharmony_ci int t = char_to_hex(*h++), t1; 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_ci if (!*h || t < 0) 141d4afb5ceSopenharmony_ci return -1; 142d4afb5ceSopenharmony_ci 143d4afb5ceSopenharmony_ci t1 = char_to_hex(*h++); 144d4afb5ceSopenharmony_ci if (t1 < 0) 145d4afb5ceSopenharmony_ci return -1; 146d4afb5ceSopenharmony_ci 147d4afb5ceSopenharmony_ci *dest++ = (uint8_t)((t << 4) | t1); 148d4afb5ceSopenharmony_ci } 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci if (max < 0) 151d4afb5ceSopenharmony_ci return -1; 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci return lws_ptr_diff(dest, odest); 154d4afb5ceSopenharmony_ci} 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_cistatic char *hexch = "0123456789abcdef"; 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_civoid 159d4afb5ceSopenharmony_cilws_hex_from_byte_array(const uint8_t *src, size_t slen, char *dest, size_t len) 160d4afb5ceSopenharmony_ci{ 161d4afb5ceSopenharmony_ci char *end = &dest[len - 1]; 162d4afb5ceSopenharmony_ci 163d4afb5ceSopenharmony_ci while (slen-- && dest != end) { 164d4afb5ceSopenharmony_ci uint8_t b = *src++; 165d4afb5ceSopenharmony_ci *dest++ = hexch[b >> 4]; 166d4afb5ceSopenharmony_ci if (dest == end) 167d4afb5ceSopenharmony_ci break; 168d4afb5ceSopenharmony_ci *dest++ = hexch[b & 0xf]; 169d4afb5ceSopenharmony_ci } 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ci *dest = '\0'; 172d4afb5ceSopenharmony_ci} 173d4afb5ceSopenharmony_ci 174d4afb5ceSopenharmony_ciint 175d4afb5ceSopenharmony_cilws_hex_random(struct lws_context *context, char *dest, size_t len) 176d4afb5ceSopenharmony_ci{ 177d4afb5ceSopenharmony_ci size_t n = ((len - 1) / 2) + 1; 178d4afb5ceSopenharmony_ci uint8_t b, *r = (uint8_t *)dest + len - n; 179d4afb5ceSopenharmony_ci 180d4afb5ceSopenharmony_ci if (lws_get_random(context, r, n) != n) 181d4afb5ceSopenharmony_ci return 1; 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ci while (len >= 3) { 184d4afb5ceSopenharmony_ci b = *r++; 185d4afb5ceSopenharmony_ci *dest++ = hexch[b >> 4]; 186d4afb5ceSopenharmony_ci *dest++ = hexch[b & 0xf]; 187d4afb5ceSopenharmony_ci len -= 2; 188d4afb5ceSopenharmony_ci } 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_ci if (len == 2) 191d4afb5ceSopenharmony_ci *dest++ = hexch[(*r) >> 4]; 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci *dest = '\0'; 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_ci return 0; 196d4afb5ceSopenharmony_ci} 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_OPTEE) 199d4afb5ceSopenharmony_ci 200d4afb5ceSopenharmony_ci#if defined(LWS_WITH_FILE_OPS) 201d4afb5ceSopenharmony_ciint lws_open(const char *__file, int __oflag, ...) 202d4afb5ceSopenharmony_ci{ 203d4afb5ceSopenharmony_ci va_list ap; 204d4afb5ceSopenharmony_ci int n; 205d4afb5ceSopenharmony_ci 206d4afb5ceSopenharmony_ci va_start(ap, __oflag); 207d4afb5ceSopenharmony_ci if (((__oflag & O_CREAT) == O_CREAT) 208d4afb5ceSopenharmony_ci#if defined(O_TMPFILE) 209d4afb5ceSopenharmony_ci || ((__oflag & O_TMPFILE) == O_TMPFILE) 210d4afb5ceSopenharmony_ci#endif 211d4afb5ceSopenharmony_ci ) 212d4afb5ceSopenharmony_ci#if defined(WIN32) 213d4afb5ceSopenharmony_ci /* last arg is really a mode_t. But windows... */ 214d4afb5ceSopenharmony_ci n = open(__file, __oflag, va_arg(ap, uint32_t)); 215d4afb5ceSopenharmony_ci#else 216d4afb5ceSopenharmony_ci /* ... and some other toolchains... 217d4afb5ceSopenharmony_ci * 218d4afb5ceSopenharmony_ci * error: second argument to 'va_arg' is of promotable type 'mode_t' 219d4afb5ceSopenharmony_ci * (aka 'unsigned short'); this va_arg has undefined behavior because 220d4afb5ceSopenharmony_ci * arguments will be promoted to 'int' 221d4afb5ceSopenharmony_ci */ 222d4afb5ceSopenharmony_ci n = open(__file, __oflag, (mode_t)va_arg(ap, unsigned int)); 223d4afb5ceSopenharmony_ci#endif 224d4afb5ceSopenharmony_ci else 225d4afb5ceSopenharmony_ci n = open(__file, __oflag); 226d4afb5ceSopenharmony_ci va_end(ap); 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_ci if (n != -1 && lws_plat_apply_FD_CLOEXEC(n)) { 229d4afb5ceSopenharmony_ci close(n); 230d4afb5ceSopenharmony_ci 231d4afb5ceSopenharmony_ci return -1; 232d4afb5ceSopenharmony_ci } 233d4afb5ceSopenharmony_ci 234d4afb5ceSopenharmony_ci return n; 235d4afb5ceSopenharmony_ci} 236d4afb5ceSopenharmony_ci#endif 237d4afb5ceSopenharmony_ci#endif 238d4afb5ceSopenharmony_ci 239d4afb5ceSopenharmony_ciint 240d4afb5ceSopenharmony_cilws_pthread_self_to_tsi(struct lws_context *context) 241d4afb5ceSopenharmony_ci{ 242d4afb5ceSopenharmony_ci#if LWS_MAX_SMP > 1 243d4afb5ceSopenharmony_ci pthread_t ps = pthread_self(); 244d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[0]; 245d4afb5ceSopenharmony_ci int n; 246d4afb5ceSopenharmony_ci 247d4afb5ceSopenharmony_ci /* case that we have SMP build, but don't use it */ 248d4afb5ceSopenharmony_ci if (context->count_threads == 1) 249d4afb5ceSopenharmony_ci return 0; 250d4afb5ceSopenharmony_ci 251d4afb5ceSopenharmony_ci for (n = 0; n < context->count_threads; n++) { 252d4afb5ceSopenharmony_ci if (pthread_equal(ps, pt->self)) 253d4afb5ceSopenharmony_ci return n; 254d4afb5ceSopenharmony_ci pt++; 255d4afb5ceSopenharmony_ci } 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_ci return -1; 258d4afb5ceSopenharmony_ci#else 259d4afb5ceSopenharmony_ci return 0; 260d4afb5ceSopenharmony_ci#endif 261d4afb5ceSopenharmony_ci} 262d4afb5ceSopenharmony_ci 263d4afb5ceSopenharmony_civoid * 264d4afb5ceSopenharmony_cilws_context_user(struct lws_context *context) 265d4afb5ceSopenharmony_ci{ 266d4afb5ceSopenharmony_ci return context->user_space; 267d4afb5ceSopenharmony_ci} 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_civoid 270d4afb5ceSopenharmony_cilws_explicit_bzero(void *p, size_t len) 271d4afb5ceSopenharmony_ci{ 272d4afb5ceSopenharmony_ci volatile uint8_t *vp = p; 273d4afb5ceSopenharmony_ci 274d4afb5ceSopenharmony_ci while (len--) 275d4afb5ceSopenharmony_ci *vp++ = 0; 276d4afb5ceSopenharmony_ci} 277d4afb5ceSopenharmony_ci 278d4afb5ceSopenharmony_ci#if !(defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK)) 279d4afb5ceSopenharmony_ci 280d4afb5ceSopenharmony_ci/** 281d4afb5ceSopenharmony_ci * lws_now_secs() - seconds since 1970-1-1 282d4afb5ceSopenharmony_ci * 283d4afb5ceSopenharmony_ci */ 284d4afb5ceSopenharmony_ciunsigned long 285d4afb5ceSopenharmony_cilws_now_secs(void) 286d4afb5ceSopenharmony_ci{ 287d4afb5ceSopenharmony_ci struct timeval tv; 288d4afb5ceSopenharmony_ci 289d4afb5ceSopenharmony_ci gettimeofday(&tv, NULL); 290d4afb5ceSopenharmony_ci 291d4afb5ceSopenharmony_ci return (unsigned long)tv.tv_sec; 292d4afb5ceSopenharmony_ci} 293d4afb5ceSopenharmony_ci 294d4afb5ceSopenharmony_ci#endif 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 297d4afb5ceSopenharmony_ciconst char * 298d4afb5ceSopenharmony_cilws_canonical_hostname(struct lws_context *context) 299d4afb5ceSopenharmony_ci{ 300d4afb5ceSopenharmony_ci return (const char *)context->canonical_hostname; 301d4afb5ceSopenharmony_ci} 302d4afb5ceSopenharmony_ci#endif 303d4afb5ceSopenharmony_ci 304d4afb5ceSopenharmony_ciint 305d4afb5ceSopenharmony_cilws_get_count_threads(struct lws_context *context) 306d4afb5ceSopenharmony_ci{ 307d4afb5ceSopenharmony_ci return context->count_threads; 308d4afb5ceSopenharmony_ci} 309d4afb5ceSopenharmony_ci 310d4afb5ceSopenharmony_cistatic const unsigned char e0f4[] = { 311d4afb5ceSopenharmony_ci 0xa0 | ((2 - 1) << 2) | 1, /* e0 */ 312d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* e1 */ 313d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* e2 */ 314d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* e3 */ 315d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* e4 */ 316d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* e5 */ 317d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* e6 */ 318d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* e7 */ 319d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* e8 */ 320d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* e9 */ 321d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* ea */ 322d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* eb */ 323d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* ec */ 324d4afb5ceSopenharmony_ci 0x80 | ((2 - 1) << 2) | 1, /* ed */ 325d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* ee */ 326d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* ef */ 327d4afb5ceSopenharmony_ci 0x90 | ((3 - 1) << 2) | 2, /* f0 */ 328d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 2, /* f1 */ 329d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 2, /* f2 */ 330d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 2, /* f3 */ 331d4afb5ceSopenharmony_ci 0x80 | ((1 - 1) << 2) | 2, /* f4 */ 332d4afb5ceSopenharmony_ci 333d4afb5ceSopenharmony_ci 0, /* s0 */ 334d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 0, /* s2 */ 335d4afb5ceSopenharmony_ci 0x80 | ((4 - 1) << 2) | 1, /* s3 */ 336d4afb5ceSopenharmony_ci}; 337d4afb5ceSopenharmony_ci 338d4afb5ceSopenharmony_ciint 339d4afb5ceSopenharmony_cilws_check_byte_utf8(unsigned char state, unsigned char c) 340d4afb5ceSopenharmony_ci{ 341d4afb5ceSopenharmony_ci unsigned char s = state; 342d4afb5ceSopenharmony_ci 343d4afb5ceSopenharmony_ci if (!s) { 344d4afb5ceSopenharmony_ci if (c >= 0x80) { 345d4afb5ceSopenharmony_ci if (c < 0xc2 || c > 0xf4) 346d4afb5ceSopenharmony_ci return -1; 347d4afb5ceSopenharmony_ci if (c < 0xe0) 348d4afb5ceSopenharmony_ci return 0x80 | ((4 - 1) << 2); 349d4afb5ceSopenharmony_ci else 350d4afb5ceSopenharmony_ci return e0f4[c - 0xe0]; 351d4afb5ceSopenharmony_ci } 352d4afb5ceSopenharmony_ci 353d4afb5ceSopenharmony_ci return s; 354d4afb5ceSopenharmony_ci } 355d4afb5ceSopenharmony_ci if (c < (s & 0xf0) || c >= (s & 0xf0) + 0x10 + ((s << 2) & 0x30)) 356d4afb5ceSopenharmony_ci return -1; 357d4afb5ceSopenharmony_ci 358d4afb5ceSopenharmony_ci return e0f4[21 + (s & 3)]; 359d4afb5ceSopenharmony_ci} 360d4afb5ceSopenharmony_ci 361d4afb5ceSopenharmony_ciint 362d4afb5ceSopenharmony_cilws_check_utf8(unsigned char *state, unsigned char *buf, size_t len) 363d4afb5ceSopenharmony_ci{ 364d4afb5ceSopenharmony_ci unsigned char s = *state; 365d4afb5ceSopenharmony_ci 366d4afb5ceSopenharmony_ci while (len--) { 367d4afb5ceSopenharmony_ci unsigned char c = *buf++; 368d4afb5ceSopenharmony_ci 369d4afb5ceSopenharmony_ci if (!s) { 370d4afb5ceSopenharmony_ci if (c >= 0x80) { 371d4afb5ceSopenharmony_ci if (c < 0xc2 || c > 0xf4) 372d4afb5ceSopenharmony_ci return 1; 373d4afb5ceSopenharmony_ci if (c < 0xe0) 374d4afb5ceSopenharmony_ci s = 0x80 | ((4 - 1) << 2); 375d4afb5ceSopenharmony_ci else 376d4afb5ceSopenharmony_ci s = e0f4[c - 0xe0]; 377d4afb5ceSopenharmony_ci } 378d4afb5ceSopenharmony_ci } else { 379d4afb5ceSopenharmony_ci if (c < (s & 0xf0) || 380d4afb5ceSopenharmony_ci c >= (s & 0xf0) + 0x10 + ((s << 2) & 0x30)) 381d4afb5ceSopenharmony_ci return 1; 382d4afb5ceSopenharmony_ci s = e0f4[21 + (s & 3)]; 383d4afb5ceSopenharmony_ci } 384d4afb5ceSopenharmony_ci } 385d4afb5ceSopenharmony_ci 386d4afb5ceSopenharmony_ci *state = s; 387d4afb5ceSopenharmony_ci 388d4afb5ceSopenharmony_ci return 0; 389d4afb5ceSopenharmony_ci} 390d4afb5ceSopenharmony_ci 391d4afb5ceSopenharmony_ci 392d4afb5ceSopenharmony_cichar * 393d4afb5ceSopenharmony_cilws_strdup(const char *s) 394d4afb5ceSopenharmony_ci{ 395d4afb5ceSopenharmony_ci char *d = lws_malloc(strlen(s) + 1, "strdup"); 396d4afb5ceSopenharmony_ci 397d4afb5ceSopenharmony_ci if (d) 398d4afb5ceSopenharmony_ci strcpy(d, s); 399d4afb5ceSopenharmony_ci 400d4afb5ceSopenharmony_ci return d; 401d4afb5ceSopenharmony_ci} 402d4afb5ceSopenharmony_ci 403d4afb5ceSopenharmony_ciconst char * 404d4afb5ceSopenharmony_cilws_nstrstr(const char *buf, size_t len, const char *name, size_t nl) 405d4afb5ceSopenharmony_ci{ 406d4afb5ceSopenharmony_ci const char *end = buf + len - nl + 1; 407d4afb5ceSopenharmony_ci size_t n; 408d4afb5ceSopenharmony_ci 409d4afb5ceSopenharmony_ci if (nl > len) 410d4afb5ceSopenharmony_ci /* it cannot be found if the needle is longer than the haystack */ 411d4afb5ceSopenharmony_ci return NULL; 412d4afb5ceSopenharmony_ci 413d4afb5ceSopenharmony_ci while (buf < end) { 414d4afb5ceSopenharmony_ci if (*buf != name[0]) { 415d4afb5ceSopenharmony_ci buf++; 416d4afb5ceSopenharmony_ci continue; 417d4afb5ceSopenharmony_ci } 418d4afb5ceSopenharmony_ci 419d4afb5ceSopenharmony_ci if (nl == 1) 420d4afb5ceSopenharmony_ci /* single char match, we are done */ 421d4afb5ceSopenharmony_ci return buf; 422d4afb5ceSopenharmony_ci 423d4afb5ceSopenharmony_ci if (buf[nl - 1] == name[nl - 1]) { 424d4afb5ceSopenharmony_ci /* 425d4afb5ceSopenharmony_ci * This is looking interesting then... the first 426d4afb5ceSopenharmony_ci * and last chars match, let's check the insides 427d4afb5ceSopenharmony_ci */ 428d4afb5ceSopenharmony_ci n = 1; 429d4afb5ceSopenharmony_ci while (n < nl && buf[n] == name[n]) 430d4afb5ceSopenharmony_ci n++; 431d4afb5ceSopenharmony_ci 432d4afb5ceSopenharmony_ci if (n == nl) 433d4afb5ceSopenharmony_ci /* it's a hit */ 434d4afb5ceSopenharmony_ci return buf; 435d4afb5ceSopenharmony_ci } 436d4afb5ceSopenharmony_ci 437d4afb5ceSopenharmony_ci buf++; 438d4afb5ceSopenharmony_ci } 439d4afb5ceSopenharmony_ci 440d4afb5ceSopenharmony_ci return NULL; 441d4afb5ceSopenharmony_ci} 442d4afb5ceSopenharmony_ci 443d4afb5ceSopenharmony_ci/* 444d4afb5ceSopenharmony_ci * name wants to be something like "\"myname\":" 445d4afb5ceSopenharmony_ci */ 446d4afb5ceSopenharmony_ci 447d4afb5ceSopenharmony_ciconst char * 448d4afb5ceSopenharmony_cilws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen) 449d4afb5ceSopenharmony_ci{ 450d4afb5ceSopenharmony_ci size_t nl = strlen(name); 451d4afb5ceSopenharmony_ci const char *np = lws_nstrstr(buf, len, name, nl), 452d4afb5ceSopenharmony_ci *end = buf + len, *as; 453d4afb5ceSopenharmony_ci int qu = 0; 454d4afb5ceSopenharmony_ci 455d4afb5ceSopenharmony_ci if (!np) 456d4afb5ceSopenharmony_ci return NULL; 457d4afb5ceSopenharmony_ci 458d4afb5ceSopenharmony_ci np += nl; 459d4afb5ceSopenharmony_ci 460d4afb5ceSopenharmony_ci while (np < end && (*np == ' ' || *np == '\t')) 461d4afb5ceSopenharmony_ci np++; 462d4afb5ceSopenharmony_ci 463d4afb5ceSopenharmony_ci if (np >= end) 464d4afb5ceSopenharmony_ci return NULL; 465d4afb5ceSopenharmony_ci 466d4afb5ceSopenharmony_ci /* 467d4afb5ceSopenharmony_ci * The arg could be lots of things after "name": with JSON, commonly a 468d4afb5ceSopenharmony_ci * string like "mystring", true, false, null, [...] or {...} ... we want 469d4afb5ceSopenharmony_ci * to handle common, simple cases cheaply with this; the user can choose 470d4afb5ceSopenharmony_ci * a full JSON parser like lejp if it's complicated. So if no opening 471d4afb5ceSopenharmony_ci * quote, return until a terminator like , ] }. If there's an opening 472d4afb5ceSopenharmony_ci * quote, return until closing quote, handling escaped quotes. 473d4afb5ceSopenharmony_ci */ 474d4afb5ceSopenharmony_ci 475d4afb5ceSopenharmony_ci if (*np == '\"') { 476d4afb5ceSopenharmony_ci qu = 1; 477d4afb5ceSopenharmony_ci np++; 478d4afb5ceSopenharmony_ci } 479d4afb5ceSopenharmony_ci 480d4afb5ceSopenharmony_ci as = np; 481d4afb5ceSopenharmony_ci while (np < end && 482d4afb5ceSopenharmony_ci (!qu || *np != '\"') && /* end quote is EOT if quoted */ 483d4afb5ceSopenharmony_ci (qu || (*np != '}' && *np != ']' && *np != ',')) /* delimiters */ 484d4afb5ceSopenharmony_ci ) { 485d4afb5ceSopenharmony_ci if (qu && *np == '\\') /* skip next char if quoted escape */ 486d4afb5ceSopenharmony_ci np++; 487d4afb5ceSopenharmony_ci np++; 488d4afb5ceSopenharmony_ci } 489d4afb5ceSopenharmony_ci 490d4afb5ceSopenharmony_ci *alen = (unsigned int)lws_ptr_diff(np, as); 491d4afb5ceSopenharmony_ci 492d4afb5ceSopenharmony_ci return as; 493d4afb5ceSopenharmony_ci} 494d4afb5ceSopenharmony_ci 495d4afb5ceSopenharmony_ciint 496d4afb5ceSopenharmony_cilws_json_simple_strcmp(const char *buf, size_t len, const char *name, 497d4afb5ceSopenharmony_ci const char *comp) 498d4afb5ceSopenharmony_ci{ 499d4afb5ceSopenharmony_ci size_t al; 500d4afb5ceSopenharmony_ci const char *hit = lws_json_simple_find(buf, len, name, &al); 501d4afb5ceSopenharmony_ci 502d4afb5ceSopenharmony_ci if (!hit) 503d4afb5ceSopenharmony_ci return -1; 504d4afb5ceSopenharmony_ci 505d4afb5ceSopenharmony_ci if (al != strlen(comp)) 506d4afb5ceSopenharmony_ci return -1; 507d4afb5ceSopenharmony_ci 508d4afb5ceSopenharmony_ci return strncmp(hit, comp, al); 509d4afb5ceSopenharmony_ci} 510d4afb5ceSopenharmony_ci 511d4afb5ceSopenharmony_cistatic const char *hex = "0123456789ABCDEF"; 512d4afb5ceSopenharmony_ci 513d4afb5ceSopenharmony_ciconst char * 514d4afb5ceSopenharmony_cilws_sql_purify(char *escaped, const char *string, size_t len) 515d4afb5ceSopenharmony_ci{ 516d4afb5ceSopenharmony_ci const char *p = string; 517d4afb5ceSopenharmony_ci char *q = escaped; 518d4afb5ceSopenharmony_ci 519d4afb5ceSopenharmony_ci while (*p && len-- > 2) { 520d4afb5ceSopenharmony_ci if (*p == '\'') { 521d4afb5ceSopenharmony_ci *q++ = '\''; 522d4afb5ceSopenharmony_ci *q++ = '\''; 523d4afb5ceSopenharmony_ci len --; 524d4afb5ceSopenharmony_ci p++; 525d4afb5ceSopenharmony_ci } else 526d4afb5ceSopenharmony_ci *q++ = *p++; 527d4afb5ceSopenharmony_ci } 528d4afb5ceSopenharmony_ci *q = '\0'; 529d4afb5ceSopenharmony_ci 530d4afb5ceSopenharmony_ci return escaped; 531d4afb5ceSopenharmony_ci} 532d4afb5ceSopenharmony_ci 533d4afb5ceSopenharmony_ciint 534d4afb5ceSopenharmony_cilws_sql_purify_len(const char *p) 535d4afb5ceSopenharmony_ci{ 536d4afb5ceSopenharmony_ci int olen = 0; 537d4afb5ceSopenharmony_ci 538d4afb5ceSopenharmony_ci while (*p) { 539d4afb5ceSopenharmony_ci if (*p++ == '\'') 540d4afb5ceSopenharmony_ci olen++; 541d4afb5ceSopenharmony_ci olen++; 542d4afb5ceSopenharmony_ci } 543d4afb5ceSopenharmony_ci 544d4afb5ceSopenharmony_ci return olen; 545d4afb5ceSopenharmony_ci} 546d4afb5ceSopenharmony_ci 547d4afb5ceSopenharmony_ciconst char * 548d4afb5ceSopenharmony_cilws_json_purify(char *escaped, const char *string, int len, int *in_used) 549d4afb5ceSopenharmony_ci{ 550d4afb5ceSopenharmony_ci const char *p = string; 551d4afb5ceSopenharmony_ci char *q = escaped; 552d4afb5ceSopenharmony_ci 553d4afb5ceSopenharmony_ci if (!p) { 554d4afb5ceSopenharmony_ci escaped[0] = '\0'; 555d4afb5ceSopenharmony_ci return escaped; 556d4afb5ceSopenharmony_ci } 557d4afb5ceSopenharmony_ci 558d4afb5ceSopenharmony_ci while (*p && len-- > 6) { 559d4afb5ceSopenharmony_ci if (*p == '\t') { 560d4afb5ceSopenharmony_ci p++; 561d4afb5ceSopenharmony_ci *q++ = '\\'; 562d4afb5ceSopenharmony_ci *q++ = 't'; 563d4afb5ceSopenharmony_ci continue; 564d4afb5ceSopenharmony_ci } 565d4afb5ceSopenharmony_ci 566d4afb5ceSopenharmony_ci if (*p == '\n') { 567d4afb5ceSopenharmony_ci p++; 568d4afb5ceSopenharmony_ci *q++ = '\\'; 569d4afb5ceSopenharmony_ci *q++ = 'n'; 570d4afb5ceSopenharmony_ci continue; 571d4afb5ceSopenharmony_ci } 572d4afb5ceSopenharmony_ci 573d4afb5ceSopenharmony_ci if (*p == '\r') { 574d4afb5ceSopenharmony_ci p++; 575d4afb5ceSopenharmony_ci *q++ = '\\'; 576d4afb5ceSopenharmony_ci *q++ = 'r'; 577d4afb5ceSopenharmony_ci continue; 578d4afb5ceSopenharmony_ci } 579d4afb5ceSopenharmony_ci 580d4afb5ceSopenharmony_ci if (*p == '\\') { 581d4afb5ceSopenharmony_ci p++; 582d4afb5ceSopenharmony_ci *q++ = '\\'; 583d4afb5ceSopenharmony_ci *q++ = '\\'; 584d4afb5ceSopenharmony_ci continue; 585d4afb5ceSopenharmony_ci } 586d4afb5ceSopenharmony_ci 587d4afb5ceSopenharmony_ci if (*p == '\"' || *p < 0x20) { 588d4afb5ceSopenharmony_ci *q++ = '\\'; 589d4afb5ceSopenharmony_ci *q++ = 'u'; 590d4afb5ceSopenharmony_ci *q++ = '0'; 591d4afb5ceSopenharmony_ci *q++ = '0'; 592d4afb5ceSopenharmony_ci *q++ = hex[((*p) >> 4) & 15]; 593d4afb5ceSopenharmony_ci *q++ = hex[(*p) & 15]; 594d4afb5ceSopenharmony_ci len -= 5; 595d4afb5ceSopenharmony_ci p++; 596d4afb5ceSopenharmony_ci } else 597d4afb5ceSopenharmony_ci *q++ = *p++; 598d4afb5ceSopenharmony_ci } 599d4afb5ceSopenharmony_ci *q = '\0'; 600d4afb5ceSopenharmony_ci 601d4afb5ceSopenharmony_ci if (in_used) 602d4afb5ceSopenharmony_ci *in_used = lws_ptr_diff(p, string); 603d4afb5ceSopenharmony_ci 604d4afb5ceSopenharmony_ci return escaped; 605d4afb5ceSopenharmony_ci} 606d4afb5ceSopenharmony_ci 607d4afb5ceSopenharmony_ciint 608d4afb5ceSopenharmony_cilws_json_purify_len(const char *string) 609d4afb5ceSopenharmony_ci{ 610d4afb5ceSopenharmony_ci int len = 0; 611d4afb5ceSopenharmony_ci const char *p = string; 612d4afb5ceSopenharmony_ci 613d4afb5ceSopenharmony_ci while (*p) { 614d4afb5ceSopenharmony_ci if (*p == '\t' || *p == '\n' || *p == '\r') { 615d4afb5ceSopenharmony_ci p++; 616d4afb5ceSopenharmony_ci len += 2; 617d4afb5ceSopenharmony_ci continue; 618d4afb5ceSopenharmony_ci } 619d4afb5ceSopenharmony_ci 620d4afb5ceSopenharmony_ci if (*p == '\"' || *p == '\\' || *p < 0x20) { 621d4afb5ceSopenharmony_ci len += 6; 622d4afb5ceSopenharmony_ci p++; 623d4afb5ceSopenharmony_ci continue; 624d4afb5ceSopenharmony_ci } 625d4afb5ceSopenharmony_ci p++; 626d4afb5ceSopenharmony_ci len++; 627d4afb5ceSopenharmony_ci } 628d4afb5ceSopenharmony_ci 629d4afb5ceSopenharmony_ci return len; 630d4afb5ceSopenharmony_ci} 631d4afb5ceSopenharmony_ci 632d4afb5ceSopenharmony_civoid 633d4afb5ceSopenharmony_cilws_filename_purify_inplace(char *filename) 634d4afb5ceSopenharmony_ci{ 635d4afb5ceSopenharmony_ci while (*filename) { 636d4afb5ceSopenharmony_ci 637d4afb5ceSopenharmony_ci if (*filename == '.' && filename[1] == '.') { 638d4afb5ceSopenharmony_ci *filename = '_'; 639d4afb5ceSopenharmony_ci filename[1] = '_'; 640d4afb5ceSopenharmony_ci } 641d4afb5ceSopenharmony_ci 642d4afb5ceSopenharmony_ci if (*filename == ':' || 643d4afb5ceSopenharmony_ci#if !defined(WIN32) 644d4afb5ceSopenharmony_ci *filename == '\\' || 645d4afb5ceSopenharmony_ci#endif 646d4afb5ceSopenharmony_ci *filename == '$' || 647d4afb5ceSopenharmony_ci *filename == '%') 648d4afb5ceSopenharmony_ci *filename = '_'; 649d4afb5ceSopenharmony_ci 650d4afb5ceSopenharmony_ci filename++; 651d4afb5ceSopenharmony_ci } 652d4afb5ceSopenharmony_ci} 653d4afb5ceSopenharmony_ci 654d4afb5ceSopenharmony_ciconst char * 655d4afb5ceSopenharmony_cilws_urlencode(char *escaped, const char *string, int len) 656d4afb5ceSopenharmony_ci{ 657d4afb5ceSopenharmony_ci const char *p = string; 658d4afb5ceSopenharmony_ci char *q = escaped; 659d4afb5ceSopenharmony_ci 660d4afb5ceSopenharmony_ci while (*p && len-- > 3) { 661d4afb5ceSopenharmony_ci if (*p == ' ') { 662d4afb5ceSopenharmony_ci *q++ = '+'; 663d4afb5ceSopenharmony_ci p++; 664d4afb5ceSopenharmony_ci continue; 665d4afb5ceSopenharmony_ci } 666d4afb5ceSopenharmony_ci if ((*p >= '0' && *p <= '9') || 667d4afb5ceSopenharmony_ci (*p >= 'A' && *p <= 'Z') || 668d4afb5ceSopenharmony_ci (*p >= 'a' && *p <= 'z')) { 669d4afb5ceSopenharmony_ci *q++ = *p++; 670d4afb5ceSopenharmony_ci continue; 671d4afb5ceSopenharmony_ci } 672d4afb5ceSopenharmony_ci *q++ = '%'; 673d4afb5ceSopenharmony_ci *q++ = hex[(*p >> 4) & 0xf]; 674d4afb5ceSopenharmony_ci *q++ = hex[*p & 0xf]; 675d4afb5ceSopenharmony_ci 676d4afb5ceSopenharmony_ci len -= 2; 677d4afb5ceSopenharmony_ci p++; 678d4afb5ceSopenharmony_ci } 679d4afb5ceSopenharmony_ci *q = '\0'; 680d4afb5ceSopenharmony_ci 681d4afb5ceSopenharmony_ci return escaped; 682d4afb5ceSopenharmony_ci} 683d4afb5ceSopenharmony_ci 684d4afb5ceSopenharmony_ciint 685d4afb5ceSopenharmony_cilws_urldecode(char *string, const char *escaped, int len) 686d4afb5ceSopenharmony_ci{ 687d4afb5ceSopenharmony_ci int state = 0, n; 688d4afb5ceSopenharmony_ci char sum = 0; 689d4afb5ceSopenharmony_ci 690d4afb5ceSopenharmony_ci while (*escaped && len) { 691d4afb5ceSopenharmony_ci switch (state) { 692d4afb5ceSopenharmony_ci case 0: 693d4afb5ceSopenharmony_ci if (*escaped == '%') { 694d4afb5ceSopenharmony_ci state++; 695d4afb5ceSopenharmony_ci escaped++; 696d4afb5ceSopenharmony_ci continue; 697d4afb5ceSopenharmony_ci } 698d4afb5ceSopenharmony_ci if (*escaped == '+') { 699d4afb5ceSopenharmony_ci escaped++; 700d4afb5ceSopenharmony_ci *string++ = ' '; 701d4afb5ceSopenharmony_ci len--; 702d4afb5ceSopenharmony_ci continue; 703d4afb5ceSopenharmony_ci } 704d4afb5ceSopenharmony_ci *string++ = *escaped++; 705d4afb5ceSopenharmony_ci len--; 706d4afb5ceSopenharmony_ci break; 707d4afb5ceSopenharmony_ci case 1: 708d4afb5ceSopenharmony_ci n = char_to_hex(*escaped); 709d4afb5ceSopenharmony_ci if (n < 0) 710d4afb5ceSopenharmony_ci return -1; 711d4afb5ceSopenharmony_ci escaped++; 712d4afb5ceSopenharmony_ci sum = (char)(n << 4); 713d4afb5ceSopenharmony_ci state++; 714d4afb5ceSopenharmony_ci break; 715d4afb5ceSopenharmony_ci 716d4afb5ceSopenharmony_ci case 2: 717d4afb5ceSopenharmony_ci n = char_to_hex(*escaped); 718d4afb5ceSopenharmony_ci if (n < 0) 719d4afb5ceSopenharmony_ci return -1; 720d4afb5ceSopenharmony_ci escaped++; 721d4afb5ceSopenharmony_ci *string++ = (char)(sum | n); 722d4afb5ceSopenharmony_ci len--; 723d4afb5ceSopenharmony_ci state = 0; 724d4afb5ceSopenharmony_ci break; 725d4afb5ceSopenharmony_ci } 726d4afb5ceSopenharmony_ci 727d4afb5ceSopenharmony_ci } 728d4afb5ceSopenharmony_ci *string = '\0'; 729d4afb5ceSopenharmony_ci 730d4afb5ceSopenharmony_ci return 0; 731d4afb5ceSopenharmony_ci} 732d4afb5ceSopenharmony_ci 733d4afb5ceSopenharmony_ciint 734d4afb5ceSopenharmony_cilws_finalize_startup(struct lws_context *context) 735d4afb5ceSopenharmony_ci{ 736d4afb5ceSopenharmony_ci if (lws_check_opt(context->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) 737d4afb5ceSopenharmony_ci if (lws_plat_drop_app_privileges(context, 1)) 738d4afb5ceSopenharmony_ci return 1; 739d4afb5ceSopenharmony_ci 740d4afb5ceSopenharmony_ci return 0; 741d4afb5ceSopenharmony_ci} 742d4afb5ceSopenharmony_ci 743d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) 744d4afb5ceSopenharmony_civoid 745d4afb5ceSopenharmony_cilws_get_effective_uid_gid(struct lws_context *context, uid_t *uid, gid_t *gid) 746d4afb5ceSopenharmony_ci{ 747d4afb5ceSopenharmony_ci *uid = context->uid; 748d4afb5ceSopenharmony_ci *gid = context->gid; 749d4afb5ceSopenharmony_ci} 750d4afb5ceSopenharmony_ci#endif 751d4afb5ceSopenharmony_ci 752d4afb5ceSopenharmony_ciint 753d4afb5ceSopenharmony_cilws_snprintf(char *str, size_t size, const char *format, ...) 754d4afb5ceSopenharmony_ci{ 755d4afb5ceSopenharmony_ci va_list ap; 756d4afb5ceSopenharmony_ci int n; 757d4afb5ceSopenharmony_ci 758d4afb5ceSopenharmony_ci if (!size) 759d4afb5ceSopenharmony_ci return 0; 760d4afb5ceSopenharmony_ci 761d4afb5ceSopenharmony_ci va_start(ap, format); 762d4afb5ceSopenharmony_ci n = vsnprintf(str, size, format, ap); 763d4afb5ceSopenharmony_ci va_end(ap); 764d4afb5ceSopenharmony_ci 765d4afb5ceSopenharmony_ci if (n >= (int)size) 766d4afb5ceSopenharmony_ci return (int)size; 767d4afb5ceSopenharmony_ci 768d4afb5ceSopenharmony_ci return n; 769d4afb5ceSopenharmony_ci} 770d4afb5ceSopenharmony_ci 771d4afb5ceSopenharmony_cichar * 772d4afb5ceSopenharmony_cilws_strncpy(char *dest, const char *src, size_t size) 773d4afb5ceSopenharmony_ci{ 774d4afb5ceSopenharmony_ci strncpy(dest, src, size - 1); 775d4afb5ceSopenharmony_ci dest[size - 1] = '\0'; 776d4afb5ceSopenharmony_ci 777d4afb5ceSopenharmony_ci return dest; 778d4afb5ceSopenharmony_ci} 779d4afb5ceSopenharmony_ci 780d4afb5ceSopenharmony_ciint 781d4afb5ceSopenharmony_cilws_timingsafe_bcmp(const void *a, const void *b, uint32_t len) 782d4afb5ceSopenharmony_ci{ 783d4afb5ceSopenharmony_ci const uint8_t *pa = a, *pb = b; 784d4afb5ceSopenharmony_ci uint8_t sum = 0; 785d4afb5ceSopenharmony_ci 786d4afb5ceSopenharmony_ci while (len--) 787d4afb5ceSopenharmony_ci sum |= (uint8_t)(*pa++ ^ *pb++); 788d4afb5ceSopenharmony_ci 789d4afb5ceSopenharmony_ci return sum; 790d4afb5ceSopenharmony_ci} 791d4afb5ceSopenharmony_ci 792d4afb5ceSopenharmony_ci 793d4afb5ceSopenharmony_citypedef enum { 794d4afb5ceSopenharmony_ci LWS_TOKZS_LEADING_WHITESPACE, 795d4afb5ceSopenharmony_ci LWS_TOKZS_QUOTED_STRING, 796d4afb5ceSopenharmony_ci LWS_TOKZS_TOKEN, 797d4afb5ceSopenharmony_ci LWS_TOKZS_TOKEN_POST_TERMINAL 798d4afb5ceSopenharmony_ci} lws_tokenize_state; 799d4afb5ceSopenharmony_ci 800d4afb5ceSopenharmony_cilws_tokenize_elem 801d4afb5ceSopenharmony_cilws_tokenize(struct lws_tokenize *ts) 802d4afb5ceSopenharmony_ci{ 803d4afb5ceSopenharmony_ci const char *rfc7230_delims = "(),/:;<=>?@[\\]{}"; 804d4afb5ceSopenharmony_ci lws_tokenize_state state = LWS_TOKZS_LEADING_WHITESPACE; 805d4afb5ceSopenharmony_ci char c, flo = 0, d_minus = '-', d_dot = '.', d_star = '*', s_minus = '\0', 806d4afb5ceSopenharmony_ci s_dot = '\0', s_star = '\0', d_eq = '=', s_eq = '\0', skipping = 0; 807d4afb5ceSopenharmony_ci signed char num = (ts->flags & LWS_TOKENIZE_F_NO_INTEGERS) ? 0 : -1; 808d4afb5ceSopenharmony_ci int utf8 = 0; 809d4afb5ceSopenharmony_ci 810d4afb5ceSopenharmony_ci /* for speed, compute the effect of the flags outside the loop */ 811d4afb5ceSopenharmony_ci 812d4afb5ceSopenharmony_ci if (ts->flags & LWS_TOKENIZE_F_MINUS_NONTERM) { 813d4afb5ceSopenharmony_ci d_minus = '\0'; 814d4afb5ceSopenharmony_ci s_minus = '-'; 815d4afb5ceSopenharmony_ci } 816d4afb5ceSopenharmony_ci if (ts->flags & LWS_TOKENIZE_F_DOT_NONTERM) { 817d4afb5ceSopenharmony_ci d_dot = '\0'; 818d4afb5ceSopenharmony_ci s_dot = '.'; 819d4afb5ceSopenharmony_ci } 820d4afb5ceSopenharmony_ci if (ts->flags & LWS_TOKENIZE_F_ASTERISK_NONTERM) { 821d4afb5ceSopenharmony_ci d_star = '\0'; 822d4afb5ceSopenharmony_ci s_star = '*'; 823d4afb5ceSopenharmony_ci } 824d4afb5ceSopenharmony_ci if (ts->flags & LWS_TOKENIZE_F_EQUALS_NONTERM) { 825d4afb5ceSopenharmony_ci d_eq = '\0'; 826d4afb5ceSopenharmony_ci s_eq = '='; 827d4afb5ceSopenharmony_ci } 828d4afb5ceSopenharmony_ci 829d4afb5ceSopenharmony_ci ts->token = NULL; 830d4afb5ceSopenharmony_ci ts->token_len = 0; 831d4afb5ceSopenharmony_ci 832d4afb5ceSopenharmony_ci while (ts->len) { 833d4afb5ceSopenharmony_ci c = *ts->start++; 834d4afb5ceSopenharmony_ci ts->len--; 835d4afb5ceSopenharmony_ci 836d4afb5ceSopenharmony_ci utf8 = lws_check_byte_utf8((unsigned char)utf8, (unsigned char)c); 837d4afb5ceSopenharmony_ci if (utf8 < 0) 838d4afb5ceSopenharmony_ci return LWS_TOKZE_ERR_BROKEN_UTF8; 839d4afb5ceSopenharmony_ci 840d4afb5ceSopenharmony_ci if (!c) 841d4afb5ceSopenharmony_ci break; 842d4afb5ceSopenharmony_ci 843d4afb5ceSopenharmony_ci if (skipping) { 844d4afb5ceSopenharmony_ci if (c != '\r' && c != '\n') 845d4afb5ceSopenharmony_ci continue; 846d4afb5ceSopenharmony_ci else 847d4afb5ceSopenharmony_ci skipping = 0; 848d4afb5ceSopenharmony_ci } 849d4afb5ceSopenharmony_ci 850d4afb5ceSopenharmony_ci /* comment */ 851d4afb5ceSopenharmony_ci 852d4afb5ceSopenharmony_ci if (ts->flags & LWS_TOKENIZE_F_HASH_COMMENT && 853d4afb5ceSopenharmony_ci state != LWS_TOKZS_QUOTED_STRING && 854d4afb5ceSopenharmony_ci c == '#') { 855d4afb5ceSopenharmony_ci skipping = 1; 856d4afb5ceSopenharmony_ci continue; 857d4afb5ceSopenharmony_ci } 858d4afb5ceSopenharmony_ci 859d4afb5ceSopenharmony_ci /* whitespace */ 860d4afb5ceSopenharmony_ci 861d4afb5ceSopenharmony_ci if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || 862d4afb5ceSopenharmony_ci c == '\f') { 863d4afb5ceSopenharmony_ci switch (state) { 864d4afb5ceSopenharmony_ci case LWS_TOKZS_LEADING_WHITESPACE: 865d4afb5ceSopenharmony_ci case LWS_TOKZS_TOKEN_POST_TERMINAL: 866d4afb5ceSopenharmony_ci continue; 867d4afb5ceSopenharmony_ci case LWS_TOKZS_QUOTED_STRING: 868d4afb5ceSopenharmony_ci ts->token_len++; 869d4afb5ceSopenharmony_ci continue; 870d4afb5ceSopenharmony_ci case LWS_TOKZS_TOKEN: 871d4afb5ceSopenharmony_ci /* we want to scan forward to look for = */ 872d4afb5ceSopenharmony_ci 873d4afb5ceSopenharmony_ci state = LWS_TOKZS_TOKEN_POST_TERMINAL; 874d4afb5ceSopenharmony_ci continue; 875d4afb5ceSopenharmony_ci } 876d4afb5ceSopenharmony_ci } 877d4afb5ceSopenharmony_ci 878d4afb5ceSopenharmony_ci /* quoted string */ 879d4afb5ceSopenharmony_ci 880d4afb5ceSopenharmony_ci if (c == '\"') { 881d4afb5ceSopenharmony_ci if (state == LWS_TOKZS_QUOTED_STRING) 882d4afb5ceSopenharmony_ci return LWS_TOKZE_QUOTED_STRING; 883d4afb5ceSopenharmony_ci 884d4afb5ceSopenharmony_ci /* starting a quoted string */ 885d4afb5ceSopenharmony_ci 886d4afb5ceSopenharmony_ci if (ts->flags & LWS_TOKENIZE_F_COMMA_SEP_LIST) { 887d4afb5ceSopenharmony_ci if (ts->delim == LWSTZ_DT_NEED_DELIM) 888d4afb5ceSopenharmony_ci return LWS_TOKZE_ERR_COMMA_LIST; 889d4afb5ceSopenharmony_ci ts->delim = LWSTZ_DT_NEED_DELIM; 890d4afb5ceSopenharmony_ci } 891d4afb5ceSopenharmony_ci 892d4afb5ceSopenharmony_ci state = LWS_TOKZS_QUOTED_STRING; 893d4afb5ceSopenharmony_ci ts->token = ts->start; 894d4afb5ceSopenharmony_ci ts->token_len = 0; 895d4afb5ceSopenharmony_ci 896d4afb5ceSopenharmony_ci continue; 897d4afb5ceSopenharmony_ci } 898d4afb5ceSopenharmony_ci 899d4afb5ceSopenharmony_ci /* token= aggregation */ 900d4afb5ceSopenharmony_ci 901d4afb5ceSopenharmony_ci if (!(ts->flags & LWS_TOKENIZE_F_EQUALS_NONTERM) && 902d4afb5ceSopenharmony_ci c == '=' && (state == LWS_TOKZS_TOKEN_POST_TERMINAL || 903d4afb5ceSopenharmony_ci state == LWS_TOKZS_TOKEN)) { 904d4afb5ceSopenharmony_ci if (num == 1) 905d4afb5ceSopenharmony_ci return LWS_TOKZE_ERR_NUM_ON_LHS; 906d4afb5ceSopenharmony_ci /* swallow the = */ 907d4afb5ceSopenharmony_ci return LWS_TOKZE_TOKEN_NAME_EQUALS; 908d4afb5ceSopenharmony_ci } 909d4afb5ceSopenharmony_ci 910d4afb5ceSopenharmony_ci /* optional token: aggregation */ 911d4afb5ceSopenharmony_ci 912d4afb5ceSopenharmony_ci if ((ts->flags & LWS_TOKENIZE_F_AGG_COLON) && c == ':' && 913d4afb5ceSopenharmony_ci (state == LWS_TOKZS_TOKEN_POST_TERMINAL || 914d4afb5ceSopenharmony_ci state == LWS_TOKZS_TOKEN)) 915d4afb5ceSopenharmony_ci /* swallow the : */ 916d4afb5ceSopenharmony_ci return LWS_TOKZE_TOKEN_NAME_COLON; 917d4afb5ceSopenharmony_ci 918d4afb5ceSopenharmony_ci /* aggregate . in a number as a float */ 919d4afb5ceSopenharmony_ci 920d4afb5ceSopenharmony_ci if (c == '.' && !(ts->flags & LWS_TOKENIZE_F_NO_FLOATS) && 921d4afb5ceSopenharmony_ci state == LWS_TOKZS_TOKEN && num == 1) { 922d4afb5ceSopenharmony_ci if (flo) 923d4afb5ceSopenharmony_ci return LWS_TOKZE_ERR_MALFORMED_FLOAT; 924d4afb5ceSopenharmony_ci flo = 1; 925d4afb5ceSopenharmony_ci ts->token_len++; 926d4afb5ceSopenharmony_ci continue; 927d4afb5ceSopenharmony_ci } 928d4afb5ceSopenharmony_ci 929d4afb5ceSopenharmony_ci /* 930d4afb5ceSopenharmony_ci * Delimiter... by default anything that: 931d4afb5ceSopenharmony_ci * 932d4afb5ceSopenharmony_ci * - isn't matched earlier, or 933d4afb5ceSopenharmony_ci * - is [A-Z, a-z, 0-9, _], and 934d4afb5ceSopenharmony_ci * - is not a partial utf8 char 935d4afb5ceSopenharmony_ci * 936d4afb5ceSopenharmony_ci * is a "delimiter", it marks the end of a token and is itself 937d4afb5ceSopenharmony_ci * reported as a single LWS_TOKZE_DELIMITER each time. 938d4afb5ceSopenharmony_ci * 939d4afb5ceSopenharmony_ci * However with LWS_TOKENIZE_F_RFC7230_DELIMS flag, tokens may 940d4afb5ceSopenharmony_ci * contain any noncontrol character that isn't defined in 941d4afb5ceSopenharmony_ci * rfc7230_delims, and only characters listed there are treated 942d4afb5ceSopenharmony_ci * as delimiters. 943d4afb5ceSopenharmony_ci */ 944d4afb5ceSopenharmony_ci 945d4afb5ceSopenharmony_ci if (!utf8 && 946d4afb5ceSopenharmony_ci ((ts->flags & LWS_TOKENIZE_F_RFC7230_DELIMS && 947d4afb5ceSopenharmony_ci strchr(rfc7230_delims, c) && c > 32) || 948d4afb5ceSopenharmony_ci ((!(ts->flags & LWS_TOKENIZE_F_RFC7230_DELIMS) && 949d4afb5ceSopenharmony_ci (c < '0' || c > '9') && (c < 'A' || c > 'Z') && 950d4afb5ceSopenharmony_ci (c < 'a' || c > 'z') && c != '_') && 951d4afb5ceSopenharmony_ci c != s_minus && c != s_dot && c != s_star && c != s_eq) || 952d4afb5ceSopenharmony_ci c == d_minus || c == d_dot || c == d_star || c == d_eq 953d4afb5ceSopenharmony_ci ) && 954d4afb5ceSopenharmony_ci !((ts->flags & LWS_TOKENIZE_F_SLASH_NONTERM) && c == '/')) { 955d4afb5ceSopenharmony_ci switch (state) { 956d4afb5ceSopenharmony_ci case LWS_TOKZS_LEADING_WHITESPACE: 957d4afb5ceSopenharmony_ci if (ts->flags & LWS_TOKENIZE_F_COMMA_SEP_LIST) { 958d4afb5ceSopenharmony_ci if (c != ',' || 959d4afb5ceSopenharmony_ci ts->delim != LWSTZ_DT_NEED_DELIM) 960d4afb5ceSopenharmony_ci return LWS_TOKZE_ERR_COMMA_LIST; 961d4afb5ceSopenharmony_ci ts->delim = LWSTZ_DT_NEED_NEXT_CONTENT; 962d4afb5ceSopenharmony_ci } 963d4afb5ceSopenharmony_ci 964d4afb5ceSopenharmony_ci ts->token = ts->start - 1; 965d4afb5ceSopenharmony_ci ts->token_len = 1; 966d4afb5ceSopenharmony_ci return LWS_TOKZE_DELIMITER; 967d4afb5ceSopenharmony_ci 968d4afb5ceSopenharmony_ci case LWS_TOKZS_QUOTED_STRING: 969d4afb5ceSopenharmony_ci ts->token_len++; 970d4afb5ceSopenharmony_ci continue; 971d4afb5ceSopenharmony_ci 972d4afb5ceSopenharmony_ci case LWS_TOKZS_TOKEN_POST_TERMINAL: 973d4afb5ceSopenharmony_ci case LWS_TOKZS_TOKEN: 974d4afb5ceSopenharmony_ci /* report the delimiter next time */ 975d4afb5ceSopenharmony_ci ts->start--; 976d4afb5ceSopenharmony_ci ts->len++; 977d4afb5ceSopenharmony_ci goto token_or_numeric; 978d4afb5ceSopenharmony_ci } 979d4afb5ceSopenharmony_ci } 980d4afb5ceSopenharmony_ci 981d4afb5ceSopenharmony_ci /* anything that's not whitespace or delimiter is payload */ 982d4afb5ceSopenharmony_ci 983d4afb5ceSopenharmony_ci switch (state) { 984d4afb5ceSopenharmony_ci case LWS_TOKZS_LEADING_WHITESPACE: 985d4afb5ceSopenharmony_ci 986d4afb5ceSopenharmony_ci if (ts->flags & LWS_TOKENIZE_F_COMMA_SEP_LIST) { 987d4afb5ceSopenharmony_ci if (ts->delim == LWSTZ_DT_NEED_DELIM) 988d4afb5ceSopenharmony_ci return LWS_TOKZE_ERR_COMMA_LIST; 989d4afb5ceSopenharmony_ci ts->delim = LWSTZ_DT_NEED_DELIM; 990d4afb5ceSopenharmony_ci } 991d4afb5ceSopenharmony_ci 992d4afb5ceSopenharmony_ci state = LWS_TOKZS_TOKEN; 993d4afb5ceSopenharmony_ci ts->token = ts->start - 1; 994d4afb5ceSopenharmony_ci ts->token_len = 1; 995d4afb5ceSopenharmony_ci goto checknum; 996d4afb5ceSopenharmony_ci 997d4afb5ceSopenharmony_ci case LWS_TOKZS_QUOTED_STRING: 998d4afb5ceSopenharmony_ci case LWS_TOKZS_TOKEN: 999d4afb5ceSopenharmony_ci ts->token_len++; 1000d4afb5ceSopenharmony_cichecknum: 1001d4afb5ceSopenharmony_ci if (!(ts->flags & LWS_TOKENIZE_F_NO_INTEGERS)) { 1002d4afb5ceSopenharmony_ci if (c < '0' || c > '9') 1003d4afb5ceSopenharmony_ci num = 0; 1004d4afb5ceSopenharmony_ci else 1005d4afb5ceSopenharmony_ci if (num < 0) 1006d4afb5ceSopenharmony_ci num = 1; 1007d4afb5ceSopenharmony_ci } 1008d4afb5ceSopenharmony_ci continue; 1009d4afb5ceSopenharmony_ci 1010d4afb5ceSopenharmony_ci case LWS_TOKZS_TOKEN_POST_TERMINAL: 1011d4afb5ceSopenharmony_ci /* report the new token next time */ 1012d4afb5ceSopenharmony_ci ts->start--; 1013d4afb5ceSopenharmony_ci ts->len++; 1014d4afb5ceSopenharmony_ci goto token_or_numeric; 1015d4afb5ceSopenharmony_ci } 1016d4afb5ceSopenharmony_ci } 1017d4afb5ceSopenharmony_ci 1018d4afb5ceSopenharmony_ci /* we ran out of content */ 1019d4afb5ceSopenharmony_ci 1020d4afb5ceSopenharmony_ci if (utf8) /* ended partway through a multibyte char */ 1021d4afb5ceSopenharmony_ci return LWS_TOKZE_ERR_BROKEN_UTF8; 1022d4afb5ceSopenharmony_ci 1023d4afb5ceSopenharmony_ci if (state == LWS_TOKZS_QUOTED_STRING) 1024d4afb5ceSopenharmony_ci return LWS_TOKZE_ERR_UNTERM_STRING; 1025d4afb5ceSopenharmony_ci 1026d4afb5ceSopenharmony_ci if (state != LWS_TOKZS_TOKEN_POST_TERMINAL && 1027d4afb5ceSopenharmony_ci state != LWS_TOKZS_TOKEN) { 1028d4afb5ceSopenharmony_ci if ((ts->flags & LWS_TOKENIZE_F_COMMA_SEP_LIST) && 1029d4afb5ceSopenharmony_ci ts->delim == LWSTZ_DT_NEED_NEXT_CONTENT) 1030d4afb5ceSopenharmony_ci return LWS_TOKZE_ERR_COMMA_LIST; 1031d4afb5ceSopenharmony_ci 1032d4afb5ceSopenharmony_ci return LWS_TOKZE_ENDED; 1033d4afb5ceSopenharmony_ci } 1034d4afb5ceSopenharmony_ci 1035d4afb5ceSopenharmony_ci /* report the pending token */ 1036d4afb5ceSopenharmony_ci 1037d4afb5ceSopenharmony_citoken_or_numeric: 1038d4afb5ceSopenharmony_ci 1039d4afb5ceSopenharmony_ci if (num != 1) 1040d4afb5ceSopenharmony_ci return LWS_TOKZE_TOKEN; 1041d4afb5ceSopenharmony_ci if (flo) 1042d4afb5ceSopenharmony_ci return LWS_TOKZE_FLOAT; 1043d4afb5ceSopenharmony_ci 1044d4afb5ceSopenharmony_ci return LWS_TOKZE_INTEGER; 1045d4afb5ceSopenharmony_ci} 1046d4afb5ceSopenharmony_ci 1047d4afb5ceSopenharmony_ci 1048d4afb5ceSopenharmony_ciint 1049d4afb5ceSopenharmony_cilws_tokenize_cstr(struct lws_tokenize *ts, char *str, size_t max) 1050d4afb5ceSopenharmony_ci{ 1051d4afb5ceSopenharmony_ci if (ts->token_len + 1 >= max) 1052d4afb5ceSopenharmony_ci return 1; 1053d4afb5ceSopenharmony_ci 1054d4afb5ceSopenharmony_ci memcpy(str, ts->token, ts->token_len); 1055d4afb5ceSopenharmony_ci str[ts->token_len] = '\0'; 1056d4afb5ceSopenharmony_ci 1057d4afb5ceSopenharmony_ci return 0; 1058d4afb5ceSopenharmony_ci} 1059d4afb5ceSopenharmony_ci 1060d4afb5ceSopenharmony_civoid 1061d4afb5ceSopenharmony_cilws_tokenize_init(struct lws_tokenize *ts, const char *start, int flags) 1062d4afb5ceSopenharmony_ci{ 1063d4afb5ceSopenharmony_ci ts->start = start; 1064d4afb5ceSopenharmony_ci ts->len = 0x7fffffff; 1065d4afb5ceSopenharmony_ci ts->flags = (uint16_t)(unsigned int)flags; 1066d4afb5ceSopenharmony_ci ts->delim = LWSTZ_DT_NEED_FIRST_CONTENT; 1067d4afb5ceSopenharmony_ci} 1068d4afb5ceSopenharmony_ci 1069d4afb5ceSopenharmony_ci 1070d4afb5ceSopenharmony_citypedef enum { 1071d4afb5ceSopenharmony_ci LWS_EXPS_LITERAL, 1072d4afb5ceSopenharmony_ci LWS_EXPS_OPEN_OR_LIT, 1073d4afb5ceSopenharmony_ci LWS_EXPS_NAME_OR_CLOSE, 1074d4afb5ceSopenharmony_ci LWS_EXPS_DRAIN, 1075d4afb5ceSopenharmony_ci} lws_strexp_state; 1076d4afb5ceSopenharmony_ci 1077d4afb5ceSopenharmony_civoid 1078d4afb5ceSopenharmony_cilws_strexp_init(lws_strexp_t *exp, void *priv, lws_strexp_expand_cb cb, 1079d4afb5ceSopenharmony_ci char *out, size_t olen) 1080d4afb5ceSopenharmony_ci{ 1081d4afb5ceSopenharmony_ci memset(exp, 0, sizeof(*exp)); 1082d4afb5ceSopenharmony_ci exp->cb = cb; 1083d4afb5ceSopenharmony_ci exp->out = out; 1084d4afb5ceSopenharmony_ci exp->olen = olen; 1085d4afb5ceSopenharmony_ci exp->state = LWS_EXPS_LITERAL; 1086d4afb5ceSopenharmony_ci exp->priv = priv; 1087d4afb5ceSopenharmony_ci} 1088d4afb5ceSopenharmony_ci 1089d4afb5ceSopenharmony_civoid 1090d4afb5ceSopenharmony_cilws_strexp_reset_out(lws_strexp_t *exp, char *out, size_t olen) 1091d4afb5ceSopenharmony_ci{ 1092d4afb5ceSopenharmony_ci exp->out = out; 1093d4afb5ceSopenharmony_ci exp->olen = olen; 1094d4afb5ceSopenharmony_ci exp->pos = 0; 1095d4afb5ceSopenharmony_ci} 1096d4afb5ceSopenharmony_ci 1097d4afb5ceSopenharmony_ciint 1098d4afb5ceSopenharmony_cilws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len, 1099d4afb5ceSopenharmony_ci size_t *pused_in, size_t *pused_out) 1100d4afb5ceSopenharmony_ci{ 1101d4afb5ceSopenharmony_ci size_t used = 0; 1102d4afb5ceSopenharmony_ci int n; 1103d4afb5ceSopenharmony_ci 1104d4afb5ceSopenharmony_ci while (used < len) { 1105d4afb5ceSopenharmony_ci 1106d4afb5ceSopenharmony_ci switch (exp->state) { 1107d4afb5ceSopenharmony_ci case LWS_EXPS_LITERAL: 1108d4afb5ceSopenharmony_ci if (*in == '$') { 1109d4afb5ceSopenharmony_ci exp->state = LWS_EXPS_OPEN_OR_LIT; 1110d4afb5ceSopenharmony_ci break; 1111d4afb5ceSopenharmony_ci } 1112d4afb5ceSopenharmony_ci 1113d4afb5ceSopenharmony_ci if (exp->out) 1114d4afb5ceSopenharmony_ci exp->out[exp->pos] = *in; 1115d4afb5ceSopenharmony_ci exp->pos++; 1116d4afb5ceSopenharmony_ci if (exp->olen - exp->pos < 1) { 1117d4afb5ceSopenharmony_ci *pused_in = used + 1; 1118d4afb5ceSopenharmony_ci *pused_out = exp->pos; 1119d4afb5ceSopenharmony_ci return LSTRX_FILLED_OUT; 1120d4afb5ceSopenharmony_ci } 1121d4afb5ceSopenharmony_ci break; 1122d4afb5ceSopenharmony_ci 1123d4afb5ceSopenharmony_ci case LWS_EXPS_OPEN_OR_LIT: 1124d4afb5ceSopenharmony_ci if (*in == '{') { 1125d4afb5ceSopenharmony_ci exp->state = LWS_EXPS_NAME_OR_CLOSE; 1126d4afb5ceSopenharmony_ci exp->name_pos = 0; 1127d4afb5ceSopenharmony_ci exp->exp_ofs = 0; 1128d4afb5ceSopenharmony_ci break; 1129d4afb5ceSopenharmony_ci } 1130d4afb5ceSopenharmony_ci /* treat as a literal */ 1131d4afb5ceSopenharmony_ci if (exp->olen - exp->pos < 3) 1132d4afb5ceSopenharmony_ci return -1; 1133d4afb5ceSopenharmony_ci 1134d4afb5ceSopenharmony_ci if (exp->out) { 1135d4afb5ceSopenharmony_ci exp->out[exp->pos++] = '$'; 1136d4afb5ceSopenharmony_ci exp->out[exp->pos++] = *in; 1137d4afb5ceSopenharmony_ci } else 1138d4afb5ceSopenharmony_ci exp->pos += 2; 1139d4afb5ceSopenharmony_ci if (*in != '$') 1140d4afb5ceSopenharmony_ci exp->state = LWS_EXPS_LITERAL; 1141d4afb5ceSopenharmony_ci break; 1142d4afb5ceSopenharmony_ci 1143d4afb5ceSopenharmony_ci case LWS_EXPS_NAME_OR_CLOSE: 1144d4afb5ceSopenharmony_ci if (*in == '}') { 1145d4afb5ceSopenharmony_ci exp->name[exp->name_pos] = '\0'; 1146d4afb5ceSopenharmony_ci exp->state = LWS_EXPS_DRAIN; 1147d4afb5ceSopenharmony_ci goto drain; 1148d4afb5ceSopenharmony_ci } 1149d4afb5ceSopenharmony_ci if (exp->name_pos >= sizeof(exp->name) - 1) 1150d4afb5ceSopenharmony_ci return LSTRX_FATAL_NAME_TOO_LONG; 1151d4afb5ceSopenharmony_ci 1152d4afb5ceSopenharmony_ci exp->name[exp->name_pos++] = *in; 1153d4afb5ceSopenharmony_ci break; 1154d4afb5ceSopenharmony_ci 1155d4afb5ceSopenharmony_ci case LWS_EXPS_DRAIN: 1156d4afb5ceSopenharmony_cidrain: 1157d4afb5ceSopenharmony_ci *pused_in = used; 1158d4afb5ceSopenharmony_ci n = exp->cb(exp->priv, exp->name, exp->out, &exp->pos, 1159d4afb5ceSopenharmony_ci exp->olen, &exp->exp_ofs); 1160d4afb5ceSopenharmony_ci *pused_out = exp->pos; 1161d4afb5ceSopenharmony_ci if (n == LSTRX_FILLED_OUT || 1162d4afb5ceSopenharmony_ci n == LSTRX_FATAL_NAME_UNKNOWN) 1163d4afb5ceSopenharmony_ci return n; 1164d4afb5ceSopenharmony_ci 1165d4afb5ceSopenharmony_ci exp->state = LWS_EXPS_LITERAL; 1166d4afb5ceSopenharmony_ci break; 1167d4afb5ceSopenharmony_ci } 1168d4afb5ceSopenharmony_ci 1169d4afb5ceSopenharmony_ci used++; 1170d4afb5ceSopenharmony_ci in++; 1171d4afb5ceSopenharmony_ci } 1172d4afb5ceSopenharmony_ci 1173d4afb5ceSopenharmony_ci if (exp->out) 1174d4afb5ceSopenharmony_ci exp->out[exp->pos] = '\0'; 1175d4afb5ceSopenharmony_ci *pused_in = used; 1176d4afb5ceSopenharmony_ci *pused_out = exp->pos; 1177d4afb5ceSopenharmony_ci 1178d4afb5ceSopenharmony_ci return LSTRX_DONE; 1179d4afb5ceSopenharmony_ci} 1180d4afb5ceSopenharmony_ci 1181d4afb5ceSopenharmony_ciint 1182d4afb5ceSopenharmony_cilws_strcmp_wildcard(const char *wildcard, size_t wlen, const char *check, 1183d4afb5ceSopenharmony_ci size_t clen) 1184d4afb5ceSopenharmony_ci{ 1185d4afb5ceSopenharmony_ci const char *match[3], *wc[3], *wc_end = wildcard + wlen, 1186d4afb5ceSopenharmony_ci *cend = check + clen; 1187d4afb5ceSopenharmony_ci int sp = 0; 1188d4afb5ceSopenharmony_ci 1189d4afb5ceSopenharmony_ci do { 1190d4afb5ceSopenharmony_ci 1191d4afb5ceSopenharmony_ci if (wildcard == wc_end) { 1192d4afb5ceSopenharmony_ci /* 1193d4afb5ceSopenharmony_ci * We reached the end of wildcard, but not of check, 1194d4afb5ceSopenharmony_ci * and the last thing in wildcard was not a * or we 1195d4afb5ceSopenharmony_ci * would have completed already... if we can rewind, 1196d4afb5ceSopenharmony_ci * let's try that... 1197d4afb5ceSopenharmony_ci */ 1198d4afb5ceSopenharmony_ci if (sp) { 1199d4afb5ceSopenharmony_ci wildcard = wc[sp - 1]; 1200d4afb5ceSopenharmony_ci check = match[--sp]; 1201d4afb5ceSopenharmony_ci 1202d4afb5ceSopenharmony_ci continue; 1203d4afb5ceSopenharmony_ci } 1204d4afb5ceSopenharmony_ci 1205d4afb5ceSopenharmony_ci /* otherwise it's the end of the road for this one */ 1206d4afb5ceSopenharmony_ci 1207d4afb5ceSopenharmony_ci return 1; 1208d4afb5ceSopenharmony_ci } 1209d4afb5ceSopenharmony_ci 1210d4afb5ceSopenharmony_ci if (*wildcard == '*') { 1211d4afb5ceSopenharmony_ci 1212d4afb5ceSopenharmony_ci if (++wildcard == wc_end) 1213d4afb5ceSopenharmony_ci /* 1214d4afb5ceSopenharmony_ci * Wildcard ended on a *, so we know we will 1215d4afb5ceSopenharmony_ci * match unconditionally 1216d4afb5ceSopenharmony_ci */ 1217d4afb5ceSopenharmony_ci return 0; 1218d4afb5ceSopenharmony_ci 1219d4afb5ceSopenharmony_ci /* 1220d4afb5ceSopenharmony_ci * Now we need to stick wildcard here and see if there 1221d4afb5ceSopenharmony_ci * is any remaining match exists, for eg b of "a*b" 1222d4afb5ceSopenharmony_ci */ 1223d4afb5ceSopenharmony_ci 1224d4afb5ceSopenharmony_ci if (sp == LWS_ARRAY_SIZE(match)) { 1225d4afb5ceSopenharmony_ci lwsl_err("%s: exceeds * stack\n", __func__); 1226d4afb5ceSopenharmony_ci return 1; /* we can't deal with it */ 1227d4afb5ceSopenharmony_ci } 1228d4afb5ceSopenharmony_ci 1229d4afb5ceSopenharmony_ci wc[sp] = wildcard; 1230d4afb5ceSopenharmony_ci /* if we ever pop and come back here, pick up from +1 */ 1231d4afb5ceSopenharmony_ci match[sp++] = check + 1; 1232d4afb5ceSopenharmony_ci continue; 1233d4afb5ceSopenharmony_ci } 1234d4afb5ceSopenharmony_ci 1235d4afb5ceSopenharmony_ci if (*(check++) == *wildcard) { 1236d4afb5ceSopenharmony_ci 1237d4afb5ceSopenharmony_ci if (wildcard == wc_end) 1238d4afb5ceSopenharmony_ci return 0; 1239d4afb5ceSopenharmony_ci /* 1240d4afb5ceSopenharmony_ci * We're still compatible with wildcard... keep going 1241d4afb5ceSopenharmony_ci */ 1242d4afb5ceSopenharmony_ci wildcard++; 1243d4afb5ceSopenharmony_ci 1244d4afb5ceSopenharmony_ci continue; 1245d4afb5ceSopenharmony_ci } 1246d4afb5ceSopenharmony_ci 1247d4afb5ceSopenharmony_ci if (!sp) 1248d4afb5ceSopenharmony_ci /* 1249d4afb5ceSopenharmony_ci * We're just trying to match literals, and failed... 1250d4afb5ceSopenharmony_ci */ 1251d4afb5ceSopenharmony_ci return 1; 1252d4afb5ceSopenharmony_ci 1253d4afb5ceSopenharmony_ci /* we're looking for a post-* match... keep looking... */ 1254d4afb5ceSopenharmony_ci 1255d4afb5ceSopenharmony_ci } while (check < cend); 1256d4afb5ceSopenharmony_ci 1257d4afb5ceSopenharmony_ci /* 1258d4afb5ceSopenharmony_ci * We reached the end of check, if also at end of wildcard we're OK 1259d4afb5ceSopenharmony_ci */ 1260d4afb5ceSopenharmony_ci 1261d4afb5ceSopenharmony_ci return wildcard != wc_end; 1262d4afb5ceSopenharmony_ci} 1263d4afb5ceSopenharmony_ci 1264d4afb5ceSopenharmony_ci#if LWS_MAX_SMP > 1 1265d4afb5ceSopenharmony_ci 1266d4afb5ceSopenharmony_civoid 1267d4afb5ceSopenharmony_cilws_mutex_refcount_init(struct lws_mutex_refcount *mr) 1268d4afb5ceSopenharmony_ci{ 1269d4afb5ceSopenharmony_ci pthread_mutex_init(&mr->lock, NULL); 1270d4afb5ceSopenharmony_ci mr->last_lock_reason = NULL; 1271d4afb5ceSopenharmony_ci mr->lock_depth = 0; 1272d4afb5ceSopenharmony_ci mr->metadata = 0; 1273d4afb5ceSopenharmony_ci#ifdef __PTW32_H 1274d4afb5ceSopenharmony_ci /* If we use implementation of PThreads for Win that is 1275d4afb5ceSopenharmony_ci * distributed by VCPKG */ 1276d4afb5ceSopenharmony_ci memset(&mr->lock_owner, 0, sizeof(pthread_t)); 1277d4afb5ceSopenharmony_ci#else 1278d4afb5ceSopenharmony_ci mr->lock_owner = 0; 1279d4afb5ceSopenharmony_ci#endif 1280d4afb5ceSopenharmony_ci} 1281d4afb5ceSopenharmony_ci 1282d4afb5ceSopenharmony_civoid 1283d4afb5ceSopenharmony_cilws_mutex_refcount_destroy(struct lws_mutex_refcount *mr) 1284d4afb5ceSopenharmony_ci{ 1285d4afb5ceSopenharmony_ci pthread_mutex_destroy(&mr->lock); 1286d4afb5ceSopenharmony_ci} 1287d4afb5ceSopenharmony_ci 1288d4afb5ceSopenharmony_civoid 1289d4afb5ceSopenharmony_cilws_mutex_refcount_lock(struct lws_mutex_refcount *mr, const char *reason) 1290d4afb5ceSopenharmony_ci{ 1291d4afb5ceSopenharmony_ci /* if true, this sequence is atomic because our thread has the lock 1292d4afb5ceSopenharmony_ci * 1293d4afb5ceSopenharmony_ci * - if true, only guy who can race to make it untrue is our thread, 1294d4afb5ceSopenharmony_ci * and we are here. 1295d4afb5ceSopenharmony_ci * 1296d4afb5ceSopenharmony_ci * - if false, only guy who could race to make it true is our thread, 1297d4afb5ceSopenharmony_ci * and we are here 1298d4afb5ceSopenharmony_ci * 1299d4afb5ceSopenharmony_ci * - it can be false and change to a different tid that is also false 1300d4afb5ceSopenharmony_ci */ 1301d4afb5ceSopenharmony_ci#ifdef __PTW32_H 1302d4afb5ceSopenharmony_ci /* If we use implementation of PThreads for Win that is 1303d4afb5ceSopenharmony_ci * distributed by VCPKG */ 1304d4afb5ceSopenharmony_ci if (pthread_equal(mr->lock_owner, pthread_self())) 1305d4afb5ceSopenharmony_ci#else 1306d4afb5ceSopenharmony_ci if (mr->lock_owner == pthread_self()) 1307d4afb5ceSopenharmony_ci#endif 1308d4afb5ceSopenharmony_ci { 1309d4afb5ceSopenharmony_ci /* atomic because we only change it if we own the lock */ 1310d4afb5ceSopenharmony_ci mr->lock_depth++; 1311d4afb5ceSopenharmony_ci return; 1312d4afb5ceSopenharmony_ci } 1313d4afb5ceSopenharmony_ci 1314d4afb5ceSopenharmony_ci pthread_mutex_lock(&mr->lock); 1315d4afb5ceSopenharmony_ci /* atomic because only we can have the lock */ 1316d4afb5ceSopenharmony_ci mr->last_lock_reason = reason; 1317d4afb5ceSopenharmony_ci mr->lock_owner = pthread_self(); 1318d4afb5ceSopenharmony_ci mr->lock_depth = 1; 1319d4afb5ceSopenharmony_ci //lwsl_notice("tid %d: lock %s\n", mr->tid, reason); 1320d4afb5ceSopenharmony_ci} 1321d4afb5ceSopenharmony_ci 1322d4afb5ceSopenharmony_civoid 1323d4afb5ceSopenharmony_cilws_mutex_refcount_unlock(struct lws_mutex_refcount *mr) 1324d4afb5ceSopenharmony_ci{ 1325d4afb5ceSopenharmony_ci if (--mr->lock_depth) 1326d4afb5ceSopenharmony_ci /* atomic because only thread that has the lock can unlock */ 1327d4afb5ceSopenharmony_ci return; 1328d4afb5ceSopenharmony_ci 1329d4afb5ceSopenharmony_ci mr->last_lock_reason = "free"; 1330d4afb5ceSopenharmony_ci#ifdef __PTW32_H 1331d4afb5ceSopenharmony_ci /* If we use implementation of PThreads for Win that is 1332d4afb5ceSopenharmony_ci * distributed by VCPKG */ 1333d4afb5ceSopenharmony_ci memset(&mr->lock_owner, 0, sizeof(pthread_t)); 1334d4afb5ceSopenharmony_ci#else 1335d4afb5ceSopenharmony_ci mr->lock_owner = 0; 1336d4afb5ceSopenharmony_ci#endif 1337d4afb5ceSopenharmony_ci // lwsl_notice("tid %d: unlock %s\n", mr->tid, mr->last_lock_reason); 1338d4afb5ceSopenharmony_ci pthread_mutex_unlock(&mr->lock); 1339d4afb5ceSopenharmony_ci} 1340d4afb5ceSopenharmony_ci 1341d4afb5ceSopenharmony_civoid 1342d4afb5ceSopenharmony_cilws_mutex_refcount_assert_held(struct lws_mutex_refcount *mr) 1343d4afb5ceSopenharmony_ci{ 1344d4afb5ceSopenharmony_ci#ifdef __PTW32_H 1345d4afb5ceSopenharmony_ci /* If we use implementation of PThreads for Win that is 1346d4afb5ceSopenharmony_ci * distributed by VCPKG */ 1347d4afb5ceSopenharmony_ci assert(pthread_equal(mr->lock_owner, pthread_self()) && mr->lock_depth); 1348d4afb5ceSopenharmony_ci#else 1349d4afb5ceSopenharmony_ci assert(mr->lock_owner == pthread_self() && mr->lock_depth); 1350d4afb5ceSopenharmony_ci#endif 1351d4afb5ceSopenharmony_ci} 1352d4afb5ceSopenharmony_ci 1353d4afb5ceSopenharmony_ci#endif /* SMP */ 1354d4afb5ceSopenharmony_ci 1355d4afb5ceSopenharmony_ci 1356d4afb5ceSopenharmony_ciconst char * 1357d4afb5ceSopenharmony_cilws_cmdline_option(int argc, const char **argv, const char *val) 1358d4afb5ceSopenharmony_ci{ 1359d4afb5ceSopenharmony_ci size_t n = strlen(val); 1360d4afb5ceSopenharmony_ci int c = argc; 1361d4afb5ceSopenharmony_ci 1362d4afb5ceSopenharmony_ci while (--c > 0) { 1363d4afb5ceSopenharmony_ci 1364d4afb5ceSopenharmony_ci if (!strncmp(argv[c], val, n)) { 1365d4afb5ceSopenharmony_ci if (!*(argv[c] + n) && c < argc - 1) { 1366d4afb5ceSopenharmony_ci /* coverity treats unchecked argv as "tainted" */ 1367d4afb5ceSopenharmony_ci if (!argv[c + 1] || strlen(argv[c + 1]) > 1024) 1368d4afb5ceSopenharmony_ci return NULL; 1369d4afb5ceSopenharmony_ci return argv[c + 1]; 1370d4afb5ceSopenharmony_ci } 1371d4afb5ceSopenharmony_ci 1372d4afb5ceSopenharmony_ci if (argv[c][n] == '=') 1373d4afb5ceSopenharmony_ci return &argv[c][n + 1]; 1374d4afb5ceSopenharmony_ci return argv[c] + n; 1375d4afb5ceSopenharmony_ci } 1376d4afb5ceSopenharmony_ci } 1377d4afb5ceSopenharmony_ci 1378d4afb5ceSopenharmony_ci return NULL; 1379d4afb5ceSopenharmony_ci} 1380d4afb5ceSopenharmony_ci 1381d4afb5ceSopenharmony_cistatic const char * const builtins[] = { 1382d4afb5ceSopenharmony_ci "-d", 1383d4afb5ceSopenharmony_ci "--fault-injection", 1384d4afb5ceSopenharmony_ci "--fault-seed", 1385d4afb5ceSopenharmony_ci "--ignore-sigterm" 1386d4afb5ceSopenharmony_ci}; 1387d4afb5ceSopenharmony_ci 1388d4afb5ceSopenharmony_cienum opts { 1389d4afb5ceSopenharmony_ci OPT_DEBUGLEVEL, 1390d4afb5ceSopenharmony_ci OPT_FAULTINJECTION, 1391d4afb5ceSopenharmony_ci OPT_FAULT_SEED, 1392d4afb5ceSopenharmony_ci OPT_IGNORE_SIGTERM, 1393d4afb5ceSopenharmony_ci}; 1394d4afb5ceSopenharmony_ci 1395d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) 1396d4afb5ceSopenharmony_cistatic void 1397d4afb5ceSopenharmony_cilws_sigterm_catch(int sig) 1398d4afb5ceSopenharmony_ci{ 1399d4afb5ceSopenharmony_ci} 1400d4afb5ceSopenharmony_ci#endif 1401d4afb5ceSopenharmony_ci 1402d4afb5ceSopenharmony_civoid 1403d4afb5ceSopenharmony_cilws_cmdline_option_handle_builtin(int argc, const char **argv, 1404d4afb5ceSopenharmony_ci struct lws_context_creation_info *info) 1405d4afb5ceSopenharmony_ci{ 1406d4afb5ceSopenharmony_ci const char *p; 1407d4afb5ceSopenharmony_ci int n, m, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; 1408d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 1409d4afb5ceSopenharmony_ci uint64_t seed = (uint64_t)lws_now_usecs(); 1410d4afb5ceSopenharmony_ci#endif 1411d4afb5ceSopenharmony_ci 1412d4afb5ceSopenharmony_ci for (n = 0; n < (int)LWS_ARRAY_SIZE(builtins); n++) { 1413d4afb5ceSopenharmony_ci p = lws_cmdline_option(argc, argv, builtins[n]); 1414d4afb5ceSopenharmony_ci if (!p) 1415d4afb5ceSopenharmony_ci continue; 1416d4afb5ceSopenharmony_ci 1417d4afb5ceSopenharmony_ci m = atoi(p); 1418d4afb5ceSopenharmony_ci 1419d4afb5ceSopenharmony_ci switch (n) { 1420d4afb5ceSopenharmony_ci case OPT_DEBUGLEVEL: 1421d4afb5ceSopenharmony_ci logs = m; 1422d4afb5ceSopenharmony_ci break; 1423d4afb5ceSopenharmony_ci 1424d4afb5ceSopenharmony_ci case OPT_FAULTINJECTION: 1425d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_SYS_FAULT_INJECTION) 1426d4afb5ceSopenharmony_ci lwsl_err("%s: FAULT_INJECTION not built\n", __func__); 1427d4afb5ceSopenharmony_ci#endif 1428d4afb5ceSopenharmony_ci lws_fi_deserialize(&info->fic, p); 1429d4afb5ceSopenharmony_ci break; 1430d4afb5ceSopenharmony_ci 1431d4afb5ceSopenharmony_ci case OPT_FAULT_SEED: 1432d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 1433d4afb5ceSopenharmony_ci seed = (uint64_t)atoll(p); 1434d4afb5ceSopenharmony_ci#endif 1435d4afb5ceSopenharmony_ci break; 1436d4afb5ceSopenharmony_ci 1437d4afb5ceSopenharmony_ci case OPT_IGNORE_SIGTERM: 1438d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) 1439d4afb5ceSopenharmony_ci signal(SIGTERM, lws_sigterm_catch); 1440d4afb5ceSopenharmony_ci#endif 1441d4afb5ceSopenharmony_ci break; 1442d4afb5ceSopenharmony_ci } 1443d4afb5ceSopenharmony_ci } 1444d4afb5ceSopenharmony_ci 1445d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 1446d4afb5ceSopenharmony_ci lws_xos_init(&info->fic.xos, seed); 1447d4afb5ceSopenharmony_ci#endif 1448d4afb5ceSopenharmony_ci lws_set_log_level(logs, NULL); 1449d4afb5ceSopenharmony_ci 1450d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION) 1451d4afb5ceSopenharmony_ci if (info->fic.fi_owner.count) 1452d4afb5ceSopenharmony_ci lwsl_notice("%s: Fault Injection seed %llu\n", __func__, 1453d4afb5ceSopenharmony_ci (unsigned long long)seed); 1454d4afb5ceSopenharmony_ci#endif 1455d4afb5ceSopenharmony_ci} 1456d4afb5ceSopenharmony_ci 1457d4afb5ceSopenharmony_ci 1458d4afb5ceSopenharmony_ciconst lws_humanize_unit_t humanize_schema_si[] = { 1459d4afb5ceSopenharmony_ci { "Pi", LWS_PI }, { "Ti", LWS_TI }, { "Gi", LWS_GI }, 1460d4afb5ceSopenharmony_ci { "Mi", LWS_MI }, { "Ki", LWS_KI }, { "", 1 }, 1461d4afb5ceSopenharmony_ci { NULL, 0 } 1462d4afb5ceSopenharmony_ci}; 1463d4afb5ceSopenharmony_ciconst lws_humanize_unit_t humanize_schema_si_bytes[] = { 1464d4afb5ceSopenharmony_ci { "PiB", LWS_PI }, { "TiB", LWS_TI }, { "GiB", LWS_GI }, 1465d4afb5ceSopenharmony_ci { "MiB", LWS_MI }, { "KiB", LWS_KI }, { "B", 1 }, 1466d4afb5ceSopenharmony_ci { NULL, 0 } 1467d4afb5ceSopenharmony_ci}; 1468d4afb5ceSopenharmony_ciconst lws_humanize_unit_t humanize_schema_us[] = { 1469d4afb5ceSopenharmony_ci { "y", (uint64_t)365 * 24 * 3600 * LWS_US_PER_SEC }, 1470d4afb5ceSopenharmony_ci { "d", (uint64_t)24 * 3600 * LWS_US_PER_SEC }, 1471d4afb5ceSopenharmony_ci { "hr", (uint64_t)3600 * LWS_US_PER_SEC }, 1472d4afb5ceSopenharmony_ci { "min", 60 * LWS_US_PER_SEC }, 1473d4afb5ceSopenharmony_ci { "s", LWS_US_PER_SEC }, 1474d4afb5ceSopenharmony_ci { "ms", LWS_US_PER_MS }, 1475d4afb5ceSopenharmony_ci#if defined(WIN32) 1476d4afb5ceSopenharmony_ci { "us", 1 }, 1477d4afb5ceSopenharmony_ci#else 1478d4afb5ceSopenharmony_ci { "μs", 1 }, 1479d4afb5ceSopenharmony_ci#endif 1480d4afb5ceSopenharmony_ci { NULL, 0 } 1481d4afb5ceSopenharmony_ci}; 1482d4afb5ceSopenharmony_ci 1483d4afb5ceSopenharmony_ci/* biggest ull is 18446744073709551615 (20 chars) */ 1484d4afb5ceSopenharmony_ci 1485d4afb5ceSopenharmony_cistatic int 1486d4afb5ceSopenharmony_cidecim(char *r, uint64_t v, char chars, char leading) 1487d4afb5ceSopenharmony_ci{ 1488d4afb5ceSopenharmony_ci uint64_t q = 1; 1489d4afb5ceSopenharmony_ci char *ro = r; 1490d4afb5ceSopenharmony_ci int n = 1; 1491d4afb5ceSopenharmony_ci 1492d4afb5ceSopenharmony_ci while ((leading || v > (q * 10) - 1) && n < 20 && n < chars) { 1493d4afb5ceSopenharmony_ci q = q * 10; 1494d4afb5ceSopenharmony_ci n++; 1495d4afb5ceSopenharmony_ci } 1496d4afb5ceSopenharmony_ci 1497d4afb5ceSopenharmony_ci /* n is how many chars needed */ 1498d4afb5ceSopenharmony_ci 1499d4afb5ceSopenharmony_ci while (n--) { 1500d4afb5ceSopenharmony_ci *r++ = (char)('0' + (char)((v / q) % 10)); 1501d4afb5ceSopenharmony_ci q = q / 10; 1502d4afb5ceSopenharmony_ci } 1503d4afb5ceSopenharmony_ci 1504d4afb5ceSopenharmony_ci *r = '\0'; 1505d4afb5ceSopenharmony_ci 1506d4afb5ceSopenharmony_ci return lws_ptr_diff(r, ro); 1507d4afb5ceSopenharmony_ci} 1508d4afb5ceSopenharmony_ci 1509d4afb5ceSopenharmony_ciint 1510d4afb5ceSopenharmony_cilws_humanize(char *p, size_t len, uint64_t v, const lws_humanize_unit_t *schema) 1511d4afb5ceSopenharmony_ci{ 1512d4afb5ceSopenharmony_ci char *obuf = p, *end = p + len; 1513d4afb5ceSopenharmony_ci 1514d4afb5ceSopenharmony_ci do { 1515d4afb5ceSopenharmony_ci if (v >= schema->factor || schema->factor == 1) { 1516d4afb5ceSopenharmony_ci if (schema->factor == 1) { 1517d4afb5ceSopenharmony_ci p += decim(p, v, 4, 0); 1518d4afb5ceSopenharmony_ci p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), 1519d4afb5ceSopenharmony_ci "%s", schema->name); 1520d4afb5ceSopenharmony_ci return lws_ptr_diff(p, obuf); 1521d4afb5ceSopenharmony_ci } 1522d4afb5ceSopenharmony_ci 1523d4afb5ceSopenharmony_ci p += decim(p, v / schema->factor, 4, 0); 1524d4afb5ceSopenharmony_ci *p++ = '.'; 1525d4afb5ceSopenharmony_ci p += decim(p, (v % schema->factor) / 1526d4afb5ceSopenharmony_ci (schema->factor / 1000), 3, 1); 1527d4afb5ceSopenharmony_ci 1528d4afb5ceSopenharmony_ci p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), 1529d4afb5ceSopenharmony_ci "%s", schema->name); 1530d4afb5ceSopenharmony_ci return lws_ptr_diff(p, obuf); 1531d4afb5ceSopenharmony_ci } 1532d4afb5ceSopenharmony_ci schema++; 1533d4afb5ceSopenharmony_ci } while (schema->name); 1534d4afb5ceSopenharmony_ci 1535d4afb5ceSopenharmony_ci assert(0); 1536d4afb5ceSopenharmony_ci strncpy(p, "unknown value", len); 1537d4afb5ceSopenharmony_ci 1538d4afb5ceSopenharmony_ci return 0; 1539d4afb5ceSopenharmony_ci} 1540