server.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include "private-lib-core.h"
  25. #if defined(LWS_WITH_SERVER_STATUS)
  26. void
  27. lws_sum_stats(const struct lws_context *ctx, struct lws_conn_stats *cs)
  28. {
  29. const struct lws_vhost *vh = ctx->vhost_list;
  30. while (vh) {
  31. cs->rx += vh->conn_stats.rx;
  32. cs->tx += vh->conn_stats.tx;
  33. cs->h1_conn += vh->conn_stats.h1_conn;
  34. cs->h1_trans += vh->conn_stats.h1_trans;
  35. cs->h2_trans += vh->conn_stats.h2_trans;
  36. cs->ws_upg += vh->conn_stats.ws_upg;
  37. cs->h2_upg += vh->conn_stats.h2_upg;
  38. cs->h2_alpn += vh->conn_stats.h2_alpn;
  39. cs->h2_subs += vh->conn_stats.h2_subs;
  40. cs->rejected += vh->conn_stats.rejected;
  41. vh = vh->vhost_next;
  42. }
  43. }
  44. int
  45. lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len)
  46. {
  47. #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
  48. static const char * const prots[] = {
  49. "http://",
  50. "https://",
  51. "file://",
  52. "cgi://",
  53. ">http://",
  54. ">https://",
  55. "callback://"
  56. };
  57. #endif
  58. char *orig = buf, *end = buf + len - 1, first;
  59. int n;
  60. if (len < 100)
  61. return 0;
  62. buf += lws_snprintf(buf, end - buf,
  63. "{\n \"name\":\"%s\",\n"
  64. " \"port\":\"%d\",\n"
  65. " \"use_ssl\":\"%d\",\n"
  66. " \"sts\":\"%d\",\n"
  67. " \"rx\":\"%llu\",\n"
  68. " \"tx\":\"%llu\",\n"
  69. " \"h1_conn\":\"%lu\",\n"
  70. " \"h1_trans\":\"%lu\",\n"
  71. " \"h2_trans\":\"%lu\",\n"
  72. " \"ws_upg\":\"%lu\",\n"
  73. " \"rejected\":\"%lu\",\n"
  74. " \"h2_upg\":\"%lu\",\n"
  75. " \"h2_alpn\":\"%lu\",\n"
  76. " \"h2_subs\":\"%lu\""
  77. ,
  78. vh->name, vh->listen_port,
  79. #if defined(LWS_WITH_TLS)
  80. vh->tls.use_ssl & LCCSCF_USE_SSL,
  81. #else
  82. 0,
  83. #endif
  84. !!(vh->options & LWS_SERVER_OPTION_STS),
  85. vh->conn_stats.rx, vh->conn_stats.tx,
  86. vh->conn_stats.h1_conn,
  87. vh->conn_stats.h1_trans,
  88. vh->conn_stats.h2_trans,
  89. vh->conn_stats.ws_upg,
  90. vh->conn_stats.rejected,
  91. vh->conn_stats.h2_upg,
  92. vh->conn_stats.h2_alpn,
  93. vh->conn_stats.h2_subs
  94. );
  95. #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
  96. if (vh->http.mount_list) {
  97. const struct lws_http_mount *m = vh->http.mount_list;
  98. buf += lws_snprintf(buf, end - buf, ",\n \"mounts\":[");
  99. first = 1;
  100. while (m) {
  101. if (!first)
  102. buf += lws_snprintf(buf, end - buf, ",");
  103. buf += lws_snprintf(buf, end - buf,
  104. "\n {\n \"mountpoint\":\"%s\",\n"
  105. " \"origin\":\"%s%s\",\n"
  106. " \"cache_max_age\":\"%d\",\n"
  107. " \"cache_reuse\":\"%d\",\n"
  108. " \"cache_revalidate\":\"%d\",\n"
  109. " \"cache_intermediaries\":\"%d\"\n"
  110. ,
  111. m->mountpoint,
  112. prots[m->origin_protocol],
  113. m->origin,
  114. m->cache_max_age,
  115. m->cache_reusable,
  116. m->cache_revalidate,
  117. m->cache_intermediaries);
  118. if (m->def)
  119. buf += lws_snprintf(buf, end - buf,
  120. ",\n \"default\":\"%s\"",
  121. m->def);
  122. buf += lws_snprintf(buf, end - buf, "\n }");
  123. first = 0;
  124. m = m->mount_next;
  125. }
  126. buf += lws_snprintf(buf, end - buf, "\n ]");
  127. }
  128. #endif
  129. if (vh->protocols) {
  130. n = 0;
  131. first = 1;
  132. buf += lws_snprintf(buf, end - buf, ",\n \"ws-protocols\":[");
  133. while (n < vh->count_protocols) {
  134. if (!first)
  135. buf += lws_snprintf(buf, end - buf, ",");
  136. buf += lws_snprintf(buf, end - buf,
  137. "\n {\n \"%s\":{\n"
  138. " \"status\":\"ok\"\n }\n }"
  139. ,
  140. vh->protocols[n].name);
  141. first = 0;
  142. n++;
  143. }
  144. buf += lws_snprintf(buf, end - buf, "\n ]");
  145. }
  146. buf += lws_snprintf(buf, end - buf, "\n}");
  147. return buf - orig;
  148. }
  149. int
  150. lws_json_dump_context(const struct lws_context *context, char *buf, int len,
  151. int hide_vhosts)
  152. {
  153. char *orig = buf, *end = buf + len - 1, first = 1;
  154. const struct lws_vhost *vh = context->vhost_list;
  155. const struct lws_context_per_thread *pt;
  156. int n, listening = 0, cgi_count = 0, fd;
  157. struct lws_conn_stats cs;
  158. double d = 0;
  159. #ifdef LWS_WITH_CGI
  160. struct lws_cgi * const *pcgi;
  161. #endif
  162. //#ifdef LWS_WITH_LIBUV &&
  163. // uv_uptime(&d);
  164. //#endif
  165. buf += lws_snprintf(buf, end - buf, "{ "
  166. "\"version\":\"%s\",\n"
  167. "\"uptime\":\"%ld\",\n",
  168. lws_get_library_version(),
  169. (long)d);
  170. #ifdef LWS_HAVE_GETLOADAVG
  171. #if defined(__sun)
  172. #include <sys/loadavg.h>
  173. #endif
  174. {
  175. double d[3];
  176. int m;
  177. m = getloadavg(d, 3);
  178. for (n = 0; n < m; n++) {
  179. buf += lws_snprintf(buf, end - buf,
  180. "\"l%d\":\"%.2f\",\n",
  181. n + 1, d[n]);
  182. }
  183. }
  184. #endif
  185. fd = lws_open("/proc/self/statm", LWS_O_RDONLY);
  186. if (fd >= 0) {
  187. char contents[96], pure[96];
  188. n = read(fd, contents, sizeof(contents) - 1);
  189. if (n > 0) {
  190. contents[n] = '\0';
  191. if (contents[n - 1] == '\n')
  192. contents[--n] = '\0';
  193. lws_json_purify(pure, contents, sizeof(pure), NULL);
  194. buf += lws_snprintf(buf, end - buf,
  195. "\"statm\": \"%s\",\n", pure);
  196. }
  197. close(fd);
  198. }
  199. buf += lws_snprintf(buf, end - buf, "\"heap\":%lld,\n\"contexts\":[\n",
  200. (long long)lws_get_allocated_heap());
  201. buf += lws_snprintf(buf, end - buf, "{ "
  202. "\"context_uptime\":\"%llu\",\n"
  203. "\"cgi_spawned\":\"%d\",\n"
  204. "\"pt_fd_max\":\"%d\",\n"
  205. "\"ah_pool_max\":\"%d\",\n"
  206. "\"deprecated\":\"%d\",\n"
  207. "\"wsi_alive\":\"%d\",\n",
  208. (unsigned long long)(lws_now_usecs() - context->time_up) /
  209. LWS_US_PER_SEC,
  210. context->count_cgi_spawned,
  211. context->fd_limit_per_thread,
  212. context->max_http_header_pool,
  213. context->deprecated,
  214. context->count_wsi_allocated);
  215. buf += lws_snprintf(buf, end - buf, "\"pt\":[\n ");
  216. for (n = 0; n < context->count_threads; n++) {
  217. pt = &context->pt[n];
  218. if (n)
  219. buf += lws_snprintf(buf, end - buf, ",");
  220. buf += lws_snprintf(buf, end - buf,
  221. "\n {\n"
  222. " \"fds_count\":\"%d\",\n"
  223. " \"ah_pool_inuse\":\"%d\",\n"
  224. " \"ah_wait_list\":\"%d\"\n"
  225. " }",
  226. pt->fds_count,
  227. pt->http.ah_count_in_use,
  228. pt->http.ah_wait_list_length);
  229. }
  230. buf += lws_snprintf(buf, end - buf, "]");
  231. buf += lws_snprintf(buf, end - buf, ", \"vhosts\":[\n ");
  232. first = 1;
  233. vh = context->vhost_list;
  234. listening = 0;
  235. cs = context->conn_stats;
  236. lws_sum_stats(context, &cs);
  237. while (vh) {
  238. if (!hide_vhosts) {
  239. if (!first)
  240. if(buf != end)
  241. *buf++ = ',';
  242. buf += lws_json_dump_vhost(vh, buf, end - buf);
  243. first = 0;
  244. }
  245. if (vh->lserv_wsi)
  246. listening++;
  247. vh = vh->vhost_next;
  248. }
  249. buf += lws_snprintf(buf, end - buf,
  250. "],\n\"listen_wsi\":\"%d\",\n"
  251. " \"rx\":\"%llu\",\n"
  252. " \"tx\":\"%llu\",\n"
  253. " \"h1_conn\":\"%lu\",\n"
  254. " \"h1_trans\":\"%lu\",\n"
  255. " \"h2_trans\":\"%lu\",\n"
  256. " \"ws_upg\":\"%lu\",\n"
  257. " \"rejected\":\"%lu\",\n"
  258. " \"h2_alpn\":\"%lu\",\n"
  259. " \"h2_subs\":\"%lu\",\n"
  260. " \"h2_upg\":\"%lu\"",
  261. listening, cs.rx, cs.tx,
  262. cs.h1_conn,
  263. cs.h1_trans,
  264. cs.h2_trans,
  265. cs.ws_upg,
  266. cs.rejected,
  267. cs.h2_alpn,
  268. cs.h2_subs,
  269. cs.h2_upg);
  270. #ifdef LWS_WITH_CGI
  271. for (n = 0; n < context->count_threads; n++) {
  272. pt = &context->pt[n];
  273. pcgi = &pt->http.cgi_list;
  274. while (*pcgi) {
  275. pcgi = &(*pcgi)->cgi_list;
  276. cgi_count++;
  277. }
  278. }
  279. #endif
  280. buf += lws_snprintf(buf, end - buf, ",\n \"cgi_alive\":\"%d\"\n ",
  281. cgi_count);
  282. buf += lws_snprintf(buf, end - buf, "}");
  283. buf += lws_snprintf(buf, end - buf, "]}\n ");
  284. return buf - orig;
  285. }
  286. #endif