test-server-status.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. #include "test-server.h"
  21. #include <time.h>
  22. static unsigned char server_info[1024];
  23. static int server_info_len;
  24. static int current;
  25. static char cache[16384];
  26. static int cache_len;
  27. static struct per_session_data__lws_status *list;
  28. static int live_wsi;
  29. static void
  30. update_status(struct lws *wsi, struct per_session_data__lws_status *pss)
  31. {
  32. struct per_session_data__lws_status **pp = &list;
  33. int subsequent = 0;
  34. char *p = cache + LWS_PRE, *start = p;
  35. char date[128];
  36. time_t t;
  37. struct tm *ptm;
  38. #ifndef WIN32
  39. struct tm tm;
  40. #endif
  41. p += lws_snprintf(p, 512, " { %s, \"wsi\":\"%d\", \"conns\":[",
  42. server_info, live_wsi);
  43. /* render the list */
  44. while (*pp) {
  45. t = (*pp)->tv_established.tv_sec;
  46. #ifdef WIN32
  47. ptm = localtime(&t);
  48. if (!ptm)
  49. #else
  50. ptm = &tm;
  51. if (!localtime_r(&t, &tm))
  52. #endif
  53. strcpy(date, "unknown");
  54. else
  55. #ifdef WIN32
  56. strftime(date, sizeof(date), "%Y %H:%M %Z", ptm);
  57. #else
  58. strftime(date, sizeof(date), "%F %H:%M %Z", ptm);
  59. #endif
  60. if ((p - start) > (sizeof(cache) - 512))
  61. break;
  62. if (subsequent)
  63. *p++ = ',';
  64. subsequent = 1;
  65. p += lws_snprintf(p, sizeof(cache) - (p - start) - 1,
  66. "{\"peer\":\"%s\",\"time\":\"%s\","
  67. "\"ua\":\"%s\"}",
  68. (*pp)->ip, date, (*pp)->user_agent);
  69. pp = &((*pp)->list);
  70. }
  71. p += sprintf(p, "]}");
  72. cache_len = p - start;
  73. lwsl_err("cache_len %d\n", cache_len);
  74. *p = '\0';
  75. /* since we changed the list, increment the 'version' */
  76. current++;
  77. /* update everyone */
  78. lws_callback_on_writable_all_protocol(lws_get_context(wsi),
  79. lws_get_protocol(wsi));
  80. }
  81. /* lws-status protocol */
  82. int
  83. callback_lws_status(struct lws *wsi, enum lws_callback_reasons reason,
  84. void *user, void *in, size_t len)
  85. {
  86. struct per_session_data__lws_status *pss =
  87. (struct per_session_data__lws_status *)user,
  88. **pp;
  89. char name[128], rip[128];
  90. int m;
  91. switch (reason) {
  92. case LWS_CALLBACK_PROTOCOL_INIT:
  93. /*
  94. * Prepare the static server info
  95. */
  96. server_info_len = sprintf((char *)server_info,
  97. "\"version\":\"%s\","
  98. " \"hostname\":\"%s\"",
  99. lws_get_library_version(),
  100. lws_canonical_hostname(
  101. lws_get_context(wsi)));
  102. break;
  103. case LWS_CALLBACK_ESTABLISHED:
  104. /*
  105. * we keep a linked list of live pss, so we can walk it
  106. */
  107. pss->last = 0;
  108. pss->list = list;
  109. list = pss;
  110. live_wsi++;
  111. lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name,
  112. sizeof(name), rip, sizeof(rip));
  113. sprintf(pss->ip, "%s (%s)", name, rip);
  114. gettimeofday(&pss->tv_established, NULL);
  115. strcpy(pss->user_agent, "unknown");
  116. lws_hdr_copy(wsi, pss->user_agent, sizeof(pss->user_agent),
  117. WSI_TOKEN_HTTP_USER_AGENT);
  118. update_status(wsi, pss);
  119. break;
  120. case LWS_CALLBACK_RECEIVE:
  121. lwsl_notice("pmd test: RX len %d\n", (int)len);
  122. puts(in);
  123. break;
  124. case LWS_CALLBACK_SERVER_WRITEABLE:
  125. m = lws_write(wsi, (unsigned char *)cache + LWS_PRE, cache_len,
  126. LWS_WRITE_TEXT);
  127. if (m < server_info_len) {
  128. lwsl_err("ERROR %d writing to di socket\n", m);
  129. return -1;
  130. }
  131. break;
  132. case LWS_CALLBACK_CLOSED:
  133. /*
  134. * remove ourselves from live pss list
  135. */
  136. lwsl_err("CLOSING pss %p ********\n", pss);
  137. pp = &list;
  138. while (*pp) {
  139. if (*pp == pss) {
  140. *pp = pss->list;
  141. pss->list = NULL;
  142. live_wsi--;
  143. break;
  144. }
  145. pp = &((*pp)->list);
  146. }
  147. update_status(wsi, pss);
  148. break;
  149. default:
  150. break;
  151. }
  152. return 0;
  153. }