1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2021 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 31d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_OPTEE) 32d4afb5ceSopenharmony_civoid lwsl_emit_optee(int level, const char *line); 33d4afb5ceSopenharmony_ci#endif 34d4afb5ceSopenharmony_ci 35d4afb5ceSopenharmony_cilws_log_cx_t log_cx = { 36d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_OPTEE) 37d4afb5ceSopenharmony_ci .u.emit = lwsl_emit_stderr, 38d4afb5ceSopenharmony_ci#else 39d4afb5ceSopenharmony_ci .u.emit = lwsl_emit_optee, 40d4afb5ceSopenharmony_ci#endif 41d4afb5ceSopenharmony_ci .lll_flags = LLL_ERR | LLL_WARN | LLL_NOTICE, 42d4afb5ceSopenharmony_ci}; 43d4afb5ceSopenharmony_ci 44d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NO_LOGS) 45d4afb5ceSopenharmony_cistatic const char * log_level_names ="EWNIDPHXCLUT??"; 46d4afb5ceSopenharmony_ci#endif 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci/* 49d4afb5ceSopenharmony_ci * Name an instance tag and attach to a group 50d4afb5ceSopenharmony_ci */ 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_civoid 53d4afb5ceSopenharmony_ci__lws_lc_tag(struct lws_context *context, lws_lifecycle_group_t *grp, 54d4afb5ceSopenharmony_ci lws_lifecycle_t *lc, const char *format, ...) 55d4afb5ceSopenharmony_ci{ 56d4afb5ceSopenharmony_ci va_list ap; 57d4afb5ceSopenharmony_ci int n = 1; 58d4afb5ceSopenharmony_ci 59d4afb5ceSopenharmony_ci if (*lc->gutag == '[') { 60d4afb5ceSopenharmony_ci /* appending inside [] */ 61d4afb5ceSopenharmony_ci 62d4afb5ceSopenharmony_ci char *cp = strchr(lc->gutag, ']'); 63d4afb5ceSopenharmony_ci char rend[96]; 64d4afb5ceSopenharmony_ci size_t ll, k; 65d4afb5ceSopenharmony_ci int n; 66d4afb5ceSopenharmony_ci 67d4afb5ceSopenharmony_ci if (!cp) 68d4afb5ceSopenharmony_ci return; 69d4afb5ceSopenharmony_ci 70d4afb5ceSopenharmony_ci /* length of closing brace and anything else after it */ 71d4afb5ceSopenharmony_ci k = strlen(cp); 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_ci /* compute the remaining gutag unused */ 74d4afb5ceSopenharmony_ci ll = sizeof(lc->gutag) - lws_ptr_diff_size_t(cp, lc->gutag) - k - 1; 75d4afb5ceSopenharmony_ci if (ll > sizeof(rend) - 1) 76d4afb5ceSopenharmony_ci ll = sizeof(rend) - 1; 77d4afb5ceSopenharmony_ci va_start(ap, format); 78d4afb5ceSopenharmony_ci n = vsnprintf(rend, ll, format, ap); 79d4afb5ceSopenharmony_ci va_end(ap); 80d4afb5ceSopenharmony_ci 81d4afb5ceSopenharmony_ci if ((unsigned int)n > ll) 82d4afb5ceSopenharmony_ci n = (int)ll; 83d4afb5ceSopenharmony_ci 84d4afb5ceSopenharmony_ci /* shove the trailer up by what we added */ 85d4afb5ceSopenharmony_ci memmove(cp + n, cp, k); 86d4afb5ceSopenharmony_ci assert(k + (unsigned int)n < sizeof(lc->gutag)); 87d4afb5ceSopenharmony_ci cp[k + (unsigned int)n] = '\0'; 88d4afb5ceSopenharmony_ci /* copy what we added into place */ 89d4afb5ceSopenharmony_ci memcpy(cp, rend, (unsigned int)n); 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci return; 92d4afb5ceSopenharmony_ci } 93d4afb5ceSopenharmony_ci 94d4afb5ceSopenharmony_ci assert(grp); 95d4afb5ceSopenharmony_ci assert(grp->tag_prefix); /* lc group must have a tag prefix string */ 96d4afb5ceSopenharmony_ci 97d4afb5ceSopenharmony_ci lc->gutag[0] = '['; 98d4afb5ceSopenharmony_ci 99d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) /* ie, will have getpid if set */ 100d4afb5ceSopenharmony_ci n += lws_snprintf(&lc->gutag[n], sizeof(lc->gutag) - 101d4afb5ceSopenharmony_ci (unsigned int)n - 1u, "%u|", getpid()); 102d4afb5ceSopenharmony_ci#endif 103d4afb5ceSopenharmony_ci n += lws_snprintf(&lc->gutag[n], sizeof(lc->gutag) - 104d4afb5ceSopenharmony_ci (unsigned int)n - 1u, "%s|%lx|", 105d4afb5ceSopenharmony_ci grp->tag_prefix, 106d4afb5ceSopenharmony_ci (unsigned long)grp->ordinal++); 107d4afb5ceSopenharmony_ci 108d4afb5ceSopenharmony_ci va_start(ap, format); 109d4afb5ceSopenharmony_ci n += vsnprintf(&lc->gutag[n], sizeof(lc->gutag) - (unsigned int)n - 110d4afb5ceSopenharmony_ci 1u, format, ap); 111d4afb5ceSopenharmony_ci va_end(ap); 112d4afb5ceSopenharmony_ci 113d4afb5ceSopenharmony_ci if (n < (int)sizeof(lc->gutag) - 2) { 114d4afb5ceSopenharmony_ci lc->gutag[n++] = ']'; 115d4afb5ceSopenharmony_ci lc->gutag[n++] = '\0'; 116d4afb5ceSopenharmony_ci } else { 117d4afb5ceSopenharmony_ci lc->gutag[sizeof(lc->gutag) - 2] = ']'; 118d4afb5ceSopenharmony_ci lc->gutag[sizeof(lc->gutag) - 1] = '\0'; 119d4afb5ceSopenharmony_ci } 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ci lc->us_creation = (uint64_t)lws_now_usecs(); 122d4afb5ceSopenharmony_ci lws_dll2_add_tail(&lc->list, &grp->owner); 123d4afb5ceSopenharmony_ci 124d4afb5ceSopenharmony_ci lwsl_refcount_cx(lc->log_cx, 1); 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci#if defined(LWS_LOG_TAG_LIFECYCLE) 127d4afb5ceSopenharmony_ci lwsl_cx_notice(context, " ++ %s (%d)", lc->gutag, (int)grp->owner.count); 128d4afb5ceSopenharmony_ci#endif 129d4afb5ceSopenharmony_ci} 130d4afb5ceSopenharmony_ci 131d4afb5ceSopenharmony_ci/* 132d4afb5ceSopenharmony_ci * Normally we want to set the tag one time at creation. But sometimes we 133d4afb5ceSopenharmony_ci * don't have enough information at that point to give it a meaningful tag, eg, 134d4afb5ceSopenharmony_ci * it's an accepted, served connection but we haven't read data from it yet 135d4afb5ceSopenharmony_ci * to find out what it wants to be. 136d4afb5ceSopenharmony_ci * 137d4afb5ceSopenharmony_ci * This allows you to append some extra info to the tag in those cases, the 138d4afb5ceSopenharmony_ci * initial tag remains the same on the lhs so it can be tracked correctly. 139d4afb5ceSopenharmony_ci */ 140d4afb5ceSopenharmony_ci 141d4afb5ceSopenharmony_civoid 142d4afb5ceSopenharmony_ci__lws_lc_tag_append(lws_lifecycle_t *lc, const char *app) 143d4afb5ceSopenharmony_ci{ 144d4afb5ceSopenharmony_ci int n = (int)strlen(lc->gutag); 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_ci if (n && lc->gutag[n - 1] == ']') 147d4afb5ceSopenharmony_ci n--; 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_ci n += lws_snprintf(&lc->gutag[n], sizeof(lc->gutag) - 2u - 150d4afb5ceSopenharmony_ci (unsigned int)n, "|%s]", app); 151d4afb5ceSopenharmony_ci 152d4afb5ceSopenharmony_ci if ((unsigned int)n >= sizeof(lc->gutag) - 2u) { 153d4afb5ceSopenharmony_ci lc->gutag[sizeof(lc->gutag) - 2] = ']'; 154d4afb5ceSopenharmony_ci lc->gutag[sizeof(lc->gutag) - 1] = '\0'; 155d4afb5ceSopenharmony_ci } 156d4afb5ceSopenharmony_ci} 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci/* 159d4afb5ceSopenharmony_ci * Remove instance from group 160d4afb5ceSopenharmony_ci */ 161d4afb5ceSopenharmony_ci 162d4afb5ceSopenharmony_civoid 163d4afb5ceSopenharmony_ci__lws_lc_untag(struct lws_context *context, lws_lifecycle_t *lc) 164d4afb5ceSopenharmony_ci{ 165d4afb5ceSopenharmony_ci //lws_lifecycle_group_t *grp; 166d4afb5ceSopenharmony_ci char buf[24]; 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci if (!lc->gutag[0]) { /* we never tagged this object... */ 169d4afb5ceSopenharmony_ci lwsl_cx_err(context, "%s never tagged", lc->gutag); 170d4afb5ceSopenharmony_ci assert(0); 171d4afb5ceSopenharmony_ci return; 172d4afb5ceSopenharmony_ci } 173d4afb5ceSopenharmony_ci 174d4afb5ceSopenharmony_ci if (!lc->list.owner) { /* we already untagged this object... */ 175d4afb5ceSopenharmony_ci lwsl_cx_err(context, "%s untagged twice", lc->gutag); 176d4afb5ceSopenharmony_ci assert(0); 177d4afb5ceSopenharmony_ci return; 178d4afb5ceSopenharmony_ci } 179d4afb5ceSopenharmony_ci 180d4afb5ceSopenharmony_ci //grp = lws_container_of(lc->list.owner, lws_lifecycle_group_t, owner); 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci lws_humanize(buf, sizeof(buf), 183d4afb5ceSopenharmony_ci (uint64_t)lws_now_usecs() - lc->us_creation, 184d4afb5ceSopenharmony_ci humanize_schema_us); 185d4afb5ceSopenharmony_ci 186d4afb5ceSopenharmony_ci#if defined(LWS_LOG_TAG_LIFECYCLE) 187d4afb5ceSopenharmony_ci lwsl_cx_notice(context, " -- %s (%d) %s", lc->gutag, 188d4afb5ceSopenharmony_ci (int)lc->list.owner->count - 1, buf); 189d4afb5ceSopenharmony_ci#endif 190d4afb5ceSopenharmony_ci 191d4afb5ceSopenharmony_ci lws_dll2_remove(&lc->list); 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci lwsl_refcount_cx(lc->log_cx, -1); 194d4afb5ceSopenharmony_ci} 195d4afb5ceSopenharmony_ci 196d4afb5ceSopenharmony_ciconst char * 197d4afb5ceSopenharmony_cilws_lc_tag(lws_lifecycle_t *lc) 198d4afb5ceSopenharmony_ci{ 199d4afb5ceSopenharmony_ci return lc->gutag; 200d4afb5ceSopenharmony_ci} 201d4afb5ceSopenharmony_ci 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ciint 204d4afb5ceSopenharmony_cilwsl_timestamp(int level, char *p, size_t len) 205d4afb5ceSopenharmony_ci{ 206d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NO_LOGS) 207d4afb5ceSopenharmony_ci time_t o_now; 208d4afb5ceSopenharmony_ci unsigned long long now; 209d4afb5ceSopenharmony_ci struct timeval tv; 210d4afb5ceSopenharmony_ci struct tm *ptm = NULL; 211d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_LOCALTIME_R) 212d4afb5ceSopenharmony_ci struct tm tm; 213d4afb5ceSopenharmony_ci#endif 214d4afb5ceSopenharmony_ci int n; 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci gettimeofday(&tv, NULL); 217d4afb5ceSopenharmony_ci o_now = tv.tv_sec; 218d4afb5ceSopenharmony_ci now = ((unsigned long long)tv.tv_sec * 10000) + 219d4afb5ceSopenharmony_ci (unsigned int)(tv.tv_usec / 100); 220d4afb5ceSopenharmony_ci 221d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_LOCALTIME_R) 222d4afb5ceSopenharmony_ci ptm = localtime_r(&o_now, &tm); 223d4afb5ceSopenharmony_ci#else 224d4afb5ceSopenharmony_ci ptm = localtime(&o_now); 225d4afb5ceSopenharmony_ci#endif 226d4afb5ceSopenharmony_ci p[0] = '\0'; 227d4afb5ceSopenharmony_ci for (n = 0; n < LLL_COUNT; n++) { 228d4afb5ceSopenharmony_ci if (level != (1 << n)) 229d4afb5ceSopenharmony_ci continue; 230d4afb5ceSopenharmony_ci 231d4afb5ceSopenharmony_ci if (ptm) 232d4afb5ceSopenharmony_ci n = lws_snprintf(p, len, 233d4afb5ceSopenharmony_ci "[%04d/%02d/%02d %02d:%02d:%02d:%04d] %c: ", 234d4afb5ceSopenharmony_ci ptm->tm_year + 1900, 235d4afb5ceSopenharmony_ci ptm->tm_mon + 1, 236d4afb5ceSopenharmony_ci ptm->tm_mday, 237d4afb5ceSopenharmony_ci ptm->tm_hour, 238d4afb5ceSopenharmony_ci ptm->tm_min, 239d4afb5ceSopenharmony_ci ptm->tm_sec, 240d4afb5ceSopenharmony_ci (int)(now % 10000), log_level_names[n]); 241d4afb5ceSopenharmony_ci else 242d4afb5ceSopenharmony_ci n = lws_snprintf(p, len, "[%llu:%04d] %c: ", 243d4afb5ceSopenharmony_ci (unsigned long long) now / 10000, 244d4afb5ceSopenharmony_ci (int)(now % 10000), log_level_names[n]); 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS) 247d4afb5ceSopenharmony_ci n += lws_snprintf(p + n, len - n, "%6u: ", 248d4afb5ceSopenharmony_ci#if defined(LWS_AMAZON_RTOS) 249d4afb5ceSopenharmony_ci (unsigned int)xPortGetFreeHeapSize()); 250d4afb5ceSopenharmony_ci#else 251d4afb5ceSopenharmony_ci (unsigned int)esp_get_free_heap_size()); 252d4afb5ceSopenharmony_ci#endif 253d4afb5ceSopenharmony_ci#endif 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci return n; 256d4afb5ceSopenharmony_ci } 257d4afb5ceSopenharmony_ci#else 258d4afb5ceSopenharmony_ci p[0] = '\0'; 259d4afb5ceSopenharmony_ci#endif 260d4afb5ceSopenharmony_ci 261d4afb5ceSopenharmony_ci return 0; 262d4afb5ceSopenharmony_ci} 263d4afb5ceSopenharmony_ci 264d4afb5ceSopenharmony_ci#ifndef LWS_PLAT_OPTEE 265d4afb5ceSopenharmony_cistatic const char * const colours[] = { 266d4afb5ceSopenharmony_ci "[31;1m", /* LLL_ERR */ 267d4afb5ceSopenharmony_ci "[36;1m", /* LLL_WARN */ 268d4afb5ceSopenharmony_ci "[35;1m", /* LLL_NOTICE */ 269d4afb5ceSopenharmony_ci "[32;1m", /* LLL_INFO */ 270d4afb5ceSopenharmony_ci "[34;1m", /* LLL_DEBUG */ 271d4afb5ceSopenharmony_ci "[33;1m", /* LLL_PARSER */ 272d4afb5ceSopenharmony_ci "[33m", /* LLL_HEADER */ 273d4afb5ceSopenharmony_ci "[33m", /* LLL_EXT */ 274d4afb5ceSopenharmony_ci "[33m", /* LLL_CLIENT */ 275d4afb5ceSopenharmony_ci "[33;1m", /* LLL_LATENCY */ 276d4afb5ceSopenharmony_ci "[0;1m", /* LLL_USER */ 277d4afb5ceSopenharmony_ci "[31m", /* LLL_THREAD */ 278d4afb5ceSopenharmony_ci}; 279d4afb5ceSopenharmony_ci 280d4afb5ceSopenharmony_cistatic char tty; 281d4afb5ceSopenharmony_ci 282d4afb5ceSopenharmony_cistatic void 283d4afb5ceSopenharmony_ci_lwsl_emit_stderr(int level, const char *line) 284d4afb5ceSopenharmony_ci{ 285d4afb5ceSopenharmony_ci int n, m = LWS_ARRAY_SIZE(colours) - 1; 286d4afb5ceSopenharmony_ci 287d4afb5ceSopenharmony_ci if (!tty) 288d4afb5ceSopenharmony_ci tty = (char)(isatty(2) | 2); 289d4afb5ceSopenharmony_ci 290d4afb5ceSopenharmony_ci if (tty == 3) { 291d4afb5ceSopenharmony_ci n = 1 << (LWS_ARRAY_SIZE(colours) - 1); 292d4afb5ceSopenharmony_ci while (n) { 293d4afb5ceSopenharmony_ci if (level & n) 294d4afb5ceSopenharmony_ci break; 295d4afb5ceSopenharmony_ci m--; 296d4afb5ceSopenharmony_ci n >>= 1; 297d4afb5ceSopenharmony_ci } 298d4afb5ceSopenharmony_ci fprintf(stderr, "%c%s%s%c[0m", 27, colours[m], line, 27); 299d4afb5ceSopenharmony_ci } else 300d4afb5ceSopenharmony_ci fprintf(stderr, "%s", line); 301d4afb5ceSopenharmony_ci} 302d4afb5ceSopenharmony_ci 303d4afb5ceSopenharmony_civoid 304d4afb5ceSopenharmony_cilwsl_emit_stderr(int level, const char *line) 305d4afb5ceSopenharmony_ci{ 306d4afb5ceSopenharmony_ci _lwsl_emit_stderr(level, line); 307d4afb5ceSopenharmony_ci} 308d4afb5ceSopenharmony_ci 309d4afb5ceSopenharmony_civoid 310d4afb5ceSopenharmony_cilwsl_emit_stderr_notimestamp(int level, const char *line) 311d4afb5ceSopenharmony_ci{ 312d4afb5ceSopenharmony_ci _lwsl_emit_stderr(level, line); 313d4afb5ceSopenharmony_ci} 314d4afb5ceSopenharmony_ci 315d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) 316d4afb5ceSopenharmony_ci 317d4afb5ceSopenharmony_ci/* 318d4afb5ceSopenharmony_ci * Helper to emit to a file 319d4afb5ceSopenharmony_ci */ 320d4afb5ceSopenharmony_ci 321d4afb5ceSopenharmony_civoid 322d4afb5ceSopenharmony_cilws_log_emit_cx_file(struct lws_log_cx *cx, int level, const char *line, 323d4afb5ceSopenharmony_ci size_t len) 324d4afb5ceSopenharmony_ci{ 325d4afb5ceSopenharmony_ci int fd = (int)(intptr_t)cx->stg; 326d4afb5ceSopenharmony_ci 327d4afb5ceSopenharmony_ci if (fd >= 0) 328d4afb5ceSopenharmony_ci if (write(fd, line, (unsigned int)len) != (ssize_t)len) 329d4afb5ceSopenharmony_ci fprintf(stderr, "Unable to write log to file\n"); 330d4afb5ceSopenharmony_ci} 331d4afb5ceSopenharmony_ci 332d4afb5ceSopenharmony_ci/* 333d4afb5ceSopenharmony_ci * Helper to use a .refcount_cb to store logs in a file 334d4afb5ceSopenharmony_ci */ 335d4afb5ceSopenharmony_ci 336d4afb5ceSopenharmony_civoid 337d4afb5ceSopenharmony_cilws_log_use_cx_file(struct lws_log_cx *cx, int _new) 338d4afb5ceSopenharmony_ci{ 339d4afb5ceSopenharmony_ci int fd; 340d4afb5ceSopenharmony_ci 341d4afb5ceSopenharmony_ci if (_new > 0 && cx->refcount == 1) { 342d4afb5ceSopenharmony_ci fd = open((const char *)cx->opaque, 343d4afb5ceSopenharmony_ci LWS_O_CREAT | LWS_O_TRUNC | LWS_O_WRONLY, 0600); 344d4afb5ceSopenharmony_ci if (fd < 0) 345d4afb5ceSopenharmony_ci fprintf(stderr, "Unable to open log %s: errno %d\n", 346d4afb5ceSopenharmony_ci (const char *)cx->opaque, errno); 347d4afb5ceSopenharmony_ci cx->stg = (void *)(intptr_t)fd; 348d4afb5ceSopenharmony_ci 349d4afb5ceSopenharmony_ci return; 350d4afb5ceSopenharmony_ci } 351d4afb5ceSopenharmony_ci 352d4afb5ceSopenharmony_ci fd = (int)(intptr_t)cx->stg; 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ci if (_new <= 0 && cx->refcount == 0 && fd >= 0) { 355d4afb5ceSopenharmony_ci close(fd); 356d4afb5ceSopenharmony_ci cx->stg = (void *)(intptr_t)-1; 357d4afb5ceSopenharmony_ci } 358d4afb5ceSopenharmony_ci} 359d4afb5ceSopenharmony_ci 360d4afb5ceSopenharmony_ci#endif 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ci#endif 363d4afb5ceSopenharmony_ci 364d4afb5ceSopenharmony_ci#if !(defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK)) 365d4afb5ceSopenharmony_civoid 366d4afb5ceSopenharmony_ci__lws_logv(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, 367d4afb5ceSopenharmony_ci int filter, const char *_fun, const char *format, va_list vl) 368d4afb5ceSopenharmony_ci{ 369d4afb5ceSopenharmony_ci#if LWS_MAX_SMP == 1 && !defined(LWS_WITH_THREADPOOL) 370d4afb5ceSopenharmony_ci /* this is incompatible with multithreaded logging */ 371d4afb5ceSopenharmony_ci static char buf[256]; 372d4afb5ceSopenharmony_ci#else 373d4afb5ceSopenharmony_ci char buf[1024]; 374d4afb5ceSopenharmony_ci#endif 375d4afb5ceSopenharmony_ci char *p = buf, *end = p + sizeof(buf) - 1; 376d4afb5ceSopenharmony_ci lws_log_cx_t *cxp; 377d4afb5ceSopenharmony_ci int n, back = 0; 378d4afb5ceSopenharmony_ci 379d4afb5ceSopenharmony_ci /* 380d4afb5ceSopenharmony_ci * We need to handle NULL wsi etc at the wrappers as gracefully as 381d4afb5ceSopenharmony_ci * possible 382d4afb5ceSopenharmony_ci */ 383d4afb5ceSopenharmony_ci 384d4afb5ceSopenharmony_ci if (!cx) { 385d4afb5ceSopenharmony_ci lws_strncpy(p, "NULL log cx: ", sizeof(buf) - 1); 386d4afb5ceSopenharmony_ci p += 13; 387d4afb5ceSopenharmony_ci /* use the processwide one for lack of anything better */ 388d4afb5ceSopenharmony_ci cx = &log_cx; 389d4afb5ceSopenharmony_ci } 390d4afb5ceSopenharmony_ci 391d4afb5ceSopenharmony_ci cxp = cx; 392d4afb5ceSopenharmony_ci 393d4afb5ceSopenharmony_ci if (!(cx->lll_flags & (uint32_t)filter)) 394d4afb5ceSopenharmony_ci /* 395d4afb5ceSopenharmony_ci * logs may be produced and built in to the code but disabled 396d4afb5ceSopenharmony_ci * at runtime 397d4afb5ceSopenharmony_ci */ 398d4afb5ceSopenharmony_ci return; 399d4afb5ceSopenharmony_ci 400d4afb5ceSopenharmony_ci#if !defined(LWS_LOGS_TIMESTAMP) 401d4afb5ceSopenharmony_ci if (cx->lll_flags & LLLF_LOG_TIMESTAMP) 402d4afb5ceSopenharmony_ci#endif 403d4afb5ceSopenharmony_ci { 404d4afb5ceSopenharmony_ci buf[0] = '\0'; 405d4afb5ceSopenharmony_ci lwsl_timestamp(filter, buf, sizeof(buf)); 406d4afb5ceSopenharmony_ci p += strlen(buf); 407d4afb5ceSopenharmony_ci } 408d4afb5ceSopenharmony_ci 409d4afb5ceSopenharmony_ci /* 410d4afb5ceSopenharmony_ci * prepend parent log ctx content first 411d4afb5ceSopenharmony_ci * top level cx also gets an opportunity to prepend 412d4afb5ceSopenharmony_ci */ 413d4afb5ceSopenharmony_ci 414d4afb5ceSopenharmony_ci while (cxp->parent) { 415d4afb5ceSopenharmony_ci cxp = cxp->parent; 416d4afb5ceSopenharmony_ci back++; 417d4afb5ceSopenharmony_ci } 418d4afb5ceSopenharmony_ci 419d4afb5ceSopenharmony_ci do { 420d4afb5ceSopenharmony_ci int b = back; 421d4afb5ceSopenharmony_ci 422d4afb5ceSopenharmony_ci cxp = cx; 423d4afb5ceSopenharmony_ci while (b--) 424d4afb5ceSopenharmony_ci cxp = cxp->parent; 425d4afb5ceSopenharmony_ci if (cxp->prepend) 426d4afb5ceSopenharmony_ci cxp->prepend(cxp, NULL, &p, end); 427d4afb5ceSopenharmony_ci 428d4afb5ceSopenharmony_ci back--; 429d4afb5ceSopenharmony_ci } while (back > 0); 430d4afb5ceSopenharmony_ci 431d4afb5ceSopenharmony_ci if (prep) 432d4afb5ceSopenharmony_ci prep(cxp, obj, &p, end); 433d4afb5ceSopenharmony_ci 434d4afb5ceSopenharmony_ci if (_fun) 435d4afb5ceSopenharmony_ci p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%s: ", _fun); 436d4afb5ceSopenharmony_ci 437d4afb5ceSopenharmony_ci /* 438d4afb5ceSopenharmony_ci * The actual log content 439d4afb5ceSopenharmony_ci */ 440d4afb5ceSopenharmony_ci 441d4afb5ceSopenharmony_ci n = vsnprintf(p, lws_ptr_diff_size_t(end, p), format, vl); 442d4afb5ceSopenharmony_ci 443d4afb5ceSopenharmony_ci /* vnsprintf returns what it would have written, even if truncated */ 444d4afb5ceSopenharmony_ci if (p + n > end - 2) { 445d4afb5ceSopenharmony_ci p = end - 5; 446d4afb5ceSopenharmony_ci *p++ = '.'; 447d4afb5ceSopenharmony_ci *p++ = '.'; 448d4afb5ceSopenharmony_ci *p++ = '.'; 449d4afb5ceSopenharmony_ci *p++ = '\n'; 450d4afb5ceSopenharmony_ci *p++ = '\0'; 451d4afb5ceSopenharmony_ci } else 452d4afb5ceSopenharmony_ci if (n > 0) { 453d4afb5ceSopenharmony_ci p += n; 454d4afb5ceSopenharmony_ci if (p[-1] != '\n') 455d4afb5ceSopenharmony_ci *p++ = '\n'; 456d4afb5ceSopenharmony_ci *p = '\0'; 457d4afb5ceSopenharmony_ci } 458d4afb5ceSopenharmony_ci 459d4afb5ceSopenharmony_ci /* 460d4afb5ceSopenharmony_ci * The actual emit 461d4afb5ceSopenharmony_ci */ 462d4afb5ceSopenharmony_ci 463d4afb5ceSopenharmony_ci if (cx->lll_flags & LLLF_LOG_CONTEXT_AWARE) 464d4afb5ceSopenharmony_ci cx->u.emit_cx(cx, filter, buf, lws_ptr_diff_size_t(p, buf)); 465d4afb5ceSopenharmony_ci else 466d4afb5ceSopenharmony_ci cx->u.emit(filter, buf); 467d4afb5ceSopenharmony_ci} 468d4afb5ceSopenharmony_ci 469d4afb5ceSopenharmony_civoid _lws_logv(int filter, const char *format, va_list vl) 470d4afb5ceSopenharmony_ci{ 471d4afb5ceSopenharmony_ci __lws_logv(&log_cx, NULL, NULL, filter, NULL, format, vl); 472d4afb5ceSopenharmony_ci} 473d4afb5ceSopenharmony_ci 474d4afb5ceSopenharmony_civoid _lws_log(int filter, const char *format, ...) 475d4afb5ceSopenharmony_ci{ 476d4afb5ceSopenharmony_ci va_list ap; 477d4afb5ceSopenharmony_ci 478d4afb5ceSopenharmony_ci va_start(ap, format); 479d4afb5ceSopenharmony_ci __lws_logv(&log_cx, NULL, NULL, filter, NULL, format, ap); 480d4afb5ceSopenharmony_ci va_end(ap); 481d4afb5ceSopenharmony_ci} 482d4afb5ceSopenharmony_ci 483d4afb5ceSopenharmony_civoid _lws_log_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, 484d4afb5ceSopenharmony_ci int filter, const char *_fun, const char *format, ...) 485d4afb5ceSopenharmony_ci{ 486d4afb5ceSopenharmony_ci va_list ap; 487d4afb5ceSopenharmony_ci 488d4afb5ceSopenharmony_ci if (!cx) 489d4afb5ceSopenharmony_ci cx = &log_cx; 490d4afb5ceSopenharmony_ci 491d4afb5ceSopenharmony_ci va_start(ap, format); 492d4afb5ceSopenharmony_ci __lws_logv(cx, prep, obj, filter, _fun, format, ap); 493d4afb5ceSopenharmony_ci va_end(ap); 494d4afb5ceSopenharmony_ci} 495d4afb5ceSopenharmony_ci#endif 496d4afb5ceSopenharmony_ci 497d4afb5ceSopenharmony_civoid 498d4afb5ceSopenharmony_cilws_set_log_level(int flags, lws_log_emit_t func) 499d4afb5ceSopenharmony_ci{ 500d4afb5ceSopenharmony_ci log_cx.lll_flags = (uint32_t)(flags & (~LLLF_LOG_CONTEXT_AWARE)); 501d4afb5ceSopenharmony_ci 502d4afb5ceSopenharmony_ci if (func) 503d4afb5ceSopenharmony_ci log_cx.u.emit = func; 504d4afb5ceSopenharmony_ci} 505d4afb5ceSopenharmony_ci 506d4afb5ceSopenharmony_ciint lwsl_visible(int level) 507d4afb5ceSopenharmony_ci{ 508d4afb5ceSopenharmony_ci return !!(log_cx.lll_flags & (uint32_t)level); 509d4afb5ceSopenharmony_ci} 510d4afb5ceSopenharmony_ci 511d4afb5ceSopenharmony_ciint lwsl_visible_cx(lws_log_cx_t *cx, int level) 512d4afb5ceSopenharmony_ci{ 513d4afb5ceSopenharmony_ci return !!(cx->lll_flags & (uint32_t)level); 514d4afb5ceSopenharmony_ci} 515d4afb5ceSopenharmony_ci 516d4afb5ceSopenharmony_civoid 517d4afb5ceSopenharmony_cilwsl_refcount_cx(lws_log_cx_t *cx, int _new) 518d4afb5ceSopenharmony_ci{ 519d4afb5ceSopenharmony_ci#if LWS_MAX_SMP > 1 520d4afb5ceSopenharmony_ci volatile lws_log_cx_t *vcx = (volatile lws_log_cx_t *)cx; 521d4afb5ceSopenharmony_ci#endif 522d4afb5ceSopenharmony_ci 523d4afb5ceSopenharmony_ci if (!cx) 524d4afb5ceSopenharmony_ci return; 525d4afb5ceSopenharmony_ci 526d4afb5ceSopenharmony_ci#if LWS_MAX_SMP > 1 527d4afb5ceSopenharmony_ci if (!vcx->inited) { 528d4afb5ceSopenharmony_ci vcx->inited = 1; 529d4afb5ceSopenharmony_ci lws_pthread_mutex_init(&cx->refcount_lock); 530d4afb5ceSopenharmony_ci vcx->inited = 2; 531d4afb5ceSopenharmony_ci } 532d4afb5ceSopenharmony_ci while (vcx->inited != 2) 533d4afb5ceSopenharmony_ci ; 534d4afb5ceSopenharmony_ci lws_pthread_mutex_lock(&cx->refcount_lock); 535d4afb5ceSopenharmony_ci#endif 536d4afb5ceSopenharmony_ci 537d4afb5ceSopenharmony_ci if (_new > 0) 538d4afb5ceSopenharmony_ci cx->refcount++; 539d4afb5ceSopenharmony_ci else { 540d4afb5ceSopenharmony_ci assert(cx->refcount); 541d4afb5ceSopenharmony_ci cx->refcount--; 542d4afb5ceSopenharmony_ci } 543d4afb5ceSopenharmony_ci 544d4afb5ceSopenharmony_ci if (cx->refcount_cb) 545d4afb5ceSopenharmony_ci cx->refcount_cb(cx, _new); 546d4afb5ceSopenharmony_ci 547d4afb5ceSopenharmony_ci#if LWS_MAX_SMP > 1 548d4afb5ceSopenharmony_ci lws_pthread_mutex_unlock(&cx->refcount_lock); 549d4afb5ceSopenharmony_ci#endif 550d4afb5ceSopenharmony_ci} 551d4afb5ceSopenharmony_ci 552d4afb5ceSopenharmony_civoid 553d4afb5ceSopenharmony_cilwsl_hexdump_level_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, 554d4afb5ceSopenharmony_ci int hexdump_level, const void *vbuf, size_t len) 555d4afb5ceSopenharmony_ci{ 556d4afb5ceSopenharmony_ci unsigned char *buf = (unsigned char *)vbuf; 557d4afb5ceSopenharmony_ci unsigned int n; 558d4afb5ceSopenharmony_ci 559d4afb5ceSopenharmony_ci if (!lwsl_visible_cx(cx, hexdump_level)) 560d4afb5ceSopenharmony_ci return; 561d4afb5ceSopenharmony_ci 562d4afb5ceSopenharmony_ci if (!len) { 563d4afb5ceSopenharmony_ci _lws_log_cx(cx, prep, obj, hexdump_level, NULL, 564d4afb5ceSopenharmony_ci "(hexdump: zero length)\n"); 565d4afb5ceSopenharmony_ci return; 566d4afb5ceSopenharmony_ci } 567d4afb5ceSopenharmony_ci 568d4afb5ceSopenharmony_ci if (!vbuf) { 569d4afb5ceSopenharmony_ci _lws_log_cx(cx, prep, obj, hexdump_level, NULL, 570d4afb5ceSopenharmony_ci "(hexdump: NULL ptr)\n"); 571d4afb5ceSopenharmony_ci return; 572d4afb5ceSopenharmony_ci } 573d4afb5ceSopenharmony_ci 574d4afb5ceSopenharmony_ci _lws_log_cx(cx, prep, obj, hexdump_level, NULL, "\n"); 575d4afb5ceSopenharmony_ci 576d4afb5ceSopenharmony_ci for (n = 0; n < len;) { 577d4afb5ceSopenharmony_ci unsigned int start = n, m; 578d4afb5ceSopenharmony_ci char line[80], *p = line; 579d4afb5ceSopenharmony_ci 580d4afb5ceSopenharmony_ci p += lws_snprintf(p, 10, "%04X: ", start); 581d4afb5ceSopenharmony_ci 582d4afb5ceSopenharmony_ci for (m = 0; m < 16 && n < len; m++) 583d4afb5ceSopenharmony_ci p += lws_snprintf(p, 5, "%02X ", buf[n++]); 584d4afb5ceSopenharmony_ci while (m++ < 16) 585d4afb5ceSopenharmony_ci p += lws_snprintf(p, 5, " "); 586d4afb5ceSopenharmony_ci 587d4afb5ceSopenharmony_ci p += lws_snprintf(p, 6, " "); 588d4afb5ceSopenharmony_ci 589d4afb5ceSopenharmony_ci for (m = 0; m < 16 && (start + m) < len; m++) { 590d4afb5ceSopenharmony_ci if (buf[start + m] >= ' ' && buf[start + m] < 127) 591d4afb5ceSopenharmony_ci *p++ = (char)buf[start + m]; 592d4afb5ceSopenharmony_ci else 593d4afb5ceSopenharmony_ci *p++ = '.'; 594d4afb5ceSopenharmony_ci } 595d4afb5ceSopenharmony_ci while (m++ < 16) 596d4afb5ceSopenharmony_ci *p++ = ' '; 597d4afb5ceSopenharmony_ci 598d4afb5ceSopenharmony_ci *p++ = '\n'; 599d4afb5ceSopenharmony_ci *p = '\0'; 600d4afb5ceSopenharmony_ci _lws_log_cx(cx, prep, obj, hexdump_level, NULL, "%s", line); 601d4afb5ceSopenharmony_ci (void)line; 602d4afb5ceSopenharmony_ci } 603d4afb5ceSopenharmony_ci 604d4afb5ceSopenharmony_ci _lws_log_cx(cx, prep, obj, hexdump_level, NULL, "\n"); 605d4afb5ceSopenharmony_ci} 606d4afb5ceSopenharmony_ci 607d4afb5ceSopenharmony_civoid 608d4afb5ceSopenharmony_cilwsl_hexdump_level(int hexdump_level, const void *vbuf, size_t len) 609d4afb5ceSopenharmony_ci{ 610d4afb5ceSopenharmony_ci lwsl_hexdump_level_cx(&log_cx, NULL, NULL, hexdump_level, vbuf, len); 611d4afb5ceSopenharmony_ci} 612d4afb5ceSopenharmony_ci 613d4afb5ceSopenharmony_civoid 614d4afb5ceSopenharmony_cilwsl_hexdump(const void *vbuf, size_t len) 615d4afb5ceSopenharmony_ci{ 616d4afb5ceSopenharmony_ci#if defined(_DEBUG) 617d4afb5ceSopenharmony_ci lwsl_hexdump_level(LLL_DEBUG, vbuf, len); 618d4afb5ceSopenharmony_ci#endif 619d4afb5ceSopenharmony_ci} 620