protocol_lws_server_status.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * libwebsockets-test-server - libwebsockets test implementation
  3. *
  4. * Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
  5. *
  6. * This file is made available under the Creative Commons CC0 1.0
  7. * Universal Public Domain Dedication.
  8. *
  9. * The person who associated a work with this deed has dedicated
  10. * the work to the public domain by waiving all of his or her rights
  11. * to the work worldwide under copyright law, including all related
  12. * and neighboring rights, to the extent allowed by law. You can copy,
  13. * modify, distribute and perform the work, even for commercial purposes,
  14. * all without asking permission.
  15. *
  16. * The test apps are intended to be adapted for use in your code, which
  17. * may be proprietary. So unlike the library itself, they are licensed
  18. * Public Domain.
  19. */
  20. #define LWS_DLL
  21. #define LWS_INTERNAL
  22. #include "../lib/libwebsockets.h"
  23. #include <string.h>
  24. #include <stdlib.h>
  25. struct lws_ss_load_sample {
  26. time_t t;
  27. int load_x100;
  28. };
  29. struct lws_ss_filepath {
  30. struct lws_ss_filepath *next;
  31. char filepath[128];
  32. };
  33. struct lws_ss_dumps {
  34. char buf[32768];
  35. int length;
  36. struct lws_ss_load_sample load[64];
  37. int load_head;
  38. int load_tail;
  39. };
  40. struct per_session_data__server_status {
  41. int ver;
  42. int pos;
  43. };
  44. struct per_vhost_data__lws_server_status {
  45. uv_timer_t timeout_watcher;
  46. struct lws_context *context;
  47. int hide_vhosts;
  48. int tow_flag;
  49. struct lws_ss_dumps d;
  50. struct lws_ss_filepath *fp;
  51. };
  52. static const struct lws_protocols protocols[1];
  53. static void
  54. uv_timeout_cb_server_status(uv_timer_t *w
  55. #if UV_VERSION_MAJOR == 0
  56. , int status
  57. #endif
  58. )
  59. {
  60. struct per_vhost_data__lws_server_status *v = lws_container_of(w,
  61. struct per_vhost_data__lws_server_status,
  62. timeout_watcher);
  63. struct lws_ss_filepath *fp;
  64. char *p = v->d.buf + LWS_PRE, contents[256], pure[256];
  65. int n, l, first = 1, fd;
  66. l = sizeof(v->d.buf) - LWS_PRE - 1;
  67. n = lws_snprintf(p, l, "{\"i\":");
  68. p += n;
  69. l -= n;
  70. n = lws_json_dump_context(v->context, p, l, v->hide_vhosts);
  71. p += n;
  72. l -= n;
  73. n = lws_snprintf(p, l, ", \"files\": [");
  74. p += n;
  75. l -= n;
  76. fp = v->fp;
  77. while (fp) {
  78. if (!first) {
  79. n = lws_snprintf(p, l, ",");
  80. p += n;
  81. l -= n;
  82. }
  83. fd = open(fp->filepath, LWS_O_RDONLY);
  84. if (fd >= 0) {
  85. n = read(fd, contents, sizeof(contents) - 1);
  86. if (n >= 0) {
  87. contents[n] = '\0';
  88. lws_json_purify(pure, contents, sizeof(pure));
  89. n = lws_snprintf(p, l, "{\"path\":\"%s\",\"val\":\"%s\"}",
  90. fp->filepath, pure);
  91. p += n;
  92. l -= n;
  93. first = 0;
  94. }
  95. close(fd);
  96. }
  97. fp = fp->next;
  98. }
  99. n = lws_snprintf(p, l, "]}");
  100. p += n;
  101. l -= n;
  102. v->d.length = p - (v->d.buf + LWS_PRE);
  103. lws_callback_on_writable_all_protocol(v->context, &protocols[0]);
  104. }
  105. static int
  106. callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason,
  107. void *user, void *in, size_t len)
  108. {
  109. const struct lws_protocol_vhost_options *pvo =
  110. (const struct lws_protocol_vhost_options *)in;
  111. struct per_vhost_data__lws_server_status *v =
  112. (struct per_vhost_data__lws_server_status *)
  113. lws_protocol_vh_priv_get(lws_get_vhost(wsi),
  114. lws_get_protocol(wsi));
  115. struct lws_ss_filepath *fp, *fp1, **fp_old;
  116. int m, period = 1000;
  117. switch (reason) {
  118. case LWS_CALLBACK_ESTABLISHED:
  119. lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__);
  120. lws_callback_on_writable(wsi);
  121. break;
  122. case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */
  123. if (v)
  124. break;
  125. lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
  126. lws_get_protocol(wsi),
  127. sizeof(struct per_vhost_data__lws_server_status));
  128. v = (struct per_vhost_data__lws_server_status *)
  129. lws_protocol_vh_priv_get(lws_get_vhost(wsi),
  130. lws_get_protocol(wsi));
  131. fp_old = &v->fp;
  132. while (pvo) {
  133. if (!strcmp(pvo->name, "hide-vhosts"))
  134. v->hide_vhosts = atoi(pvo->value);
  135. if (!strcmp(pvo->name, "update-ms"))
  136. period = atoi(pvo->value);
  137. if (!strcmp(pvo->name, "filepath")) {
  138. fp = malloc(sizeof(*fp));
  139. fp->next = NULL;
  140. lws_snprintf(&fp->filepath[0], sizeof(fp->filepath), "%s", pvo->value);
  141. *fp_old = fp;
  142. fp_old = &fp->next;
  143. }
  144. pvo = pvo->next;
  145. }
  146. v->context = lws_get_context(wsi);
  147. uv_timer_init(lws_uv_getloop(v->context, 0), &v->timeout_watcher);
  148. uv_timer_start(&v->timeout_watcher,
  149. uv_timeout_cb_server_status, 2000, period);
  150. break;
  151. case LWS_CALLBACK_PROTOCOL_DESTROY: /* per vhost */
  152. // lwsl_notice("ss: LWS_CALLBACK_PROTOCOL_DESTROY: v=%p, ctx=%p\n", v, v->context);
  153. if (!v)
  154. break;
  155. uv_timer_stop(&v->timeout_watcher);
  156. uv_close((uv_handle_t *)&v->timeout_watcher, NULL);
  157. fp = v->fp;
  158. while (fp) {
  159. fp1= fp->next;
  160. free(fp);
  161. fp = fp1;
  162. }
  163. break;
  164. case LWS_CALLBACK_SERVER_WRITEABLE:
  165. m = lws_write(wsi, (unsigned char *)v->d.buf + LWS_PRE,
  166. v->d.length, LWS_WRITE_TEXT);
  167. if (m < 0)
  168. return -1;
  169. break;
  170. default:
  171. break;
  172. }
  173. return 0;
  174. }
  175. static const struct lws_protocols protocols[] = {
  176. {
  177. "lws-server-status",
  178. callback_lws_server_status,
  179. sizeof(struct per_session_data__server_status),
  180. 1024,
  181. },
  182. };
  183. LWS_EXTERN LWS_VISIBLE int
  184. init_protocol_lws_server_status(struct lws_context *context,
  185. struct lws_plugin_capability *c)
  186. {
  187. if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
  188. lwsl_err("Plugin API %d, library API %d",
  189. LWS_PLUGIN_API_MAGIC, c->api_magic);
  190. return 1;
  191. }
  192. c->protocols = protocols;
  193. c->count_protocols = ARRAY_SIZE(protocols);
  194. c->extensions = NULL;
  195. c->count_extensions = 0;
  196. return 0;
  197. }
  198. LWS_EXTERN LWS_VISIBLE int
  199. destroy_protocol_lws_server_status(struct lws_context *context)
  200. {
  201. return 0;
  202. }