test-server-mirror.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. /* lws-mirror_protocol */
  22. #define MAX_MESSAGE_QUEUE 512
  23. struct a_message {
  24. void *payload;
  25. size_t len;
  26. };
  27. static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
  28. static int ringbuffer_head;
  29. int
  30. callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
  31. void *user, void *in, size_t len)
  32. {
  33. struct per_session_data__lws_mirror *pss =
  34. (struct per_session_data__lws_mirror *)user;
  35. int n, m;
  36. switch (reason) {
  37. case LWS_CALLBACK_ESTABLISHED:
  38. lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__);
  39. pss->ringbuffer_tail = ringbuffer_head;
  40. pss->wsi = wsi;
  41. break;
  42. case LWS_CALLBACK_PROTOCOL_DESTROY:
  43. lwsl_notice("%s: mirror protocol cleaning up\n", __func__);
  44. for (n = 0; n < sizeof ringbuffer / sizeof ringbuffer[0]; n++)
  45. if (ringbuffer[n].payload)
  46. free(ringbuffer[n].payload);
  47. break;
  48. case LWS_CALLBACK_SERVER_WRITEABLE:
  49. if (close_testing)
  50. break;
  51. while (pss->ringbuffer_tail != ringbuffer_head) {
  52. m = ringbuffer[pss->ringbuffer_tail].len;
  53. n = lws_write(wsi, (unsigned char *)
  54. ringbuffer[pss->ringbuffer_tail].payload +
  55. LWS_PRE, m, LWS_WRITE_TEXT);
  56. if (n < 0) {
  57. lwsl_err("ERROR %d writing to mirror socket\n", n);
  58. return -1;
  59. }
  60. if (n < m)
  61. lwsl_err("mirror partial write %d vs %d\n", n, m);
  62. if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1))
  63. pss->ringbuffer_tail = 0;
  64. else
  65. pss->ringbuffer_tail++;
  66. if (((ringbuffer_head - pss->ringbuffer_tail) &
  67. (MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 15))
  68. lws_rx_flow_allow_all_protocol(lws_get_context(wsi),
  69. lws_get_protocol(wsi));
  70. if (lws_send_pipe_choked(wsi)) {
  71. lws_callback_on_writable(wsi);
  72. break;
  73. }
  74. }
  75. break;
  76. case LWS_CALLBACK_RECEIVE:
  77. if (((ringbuffer_head - pss->ringbuffer_tail) &
  78. (MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 1)) {
  79. lwsl_err("dropping!\n");
  80. goto choke;
  81. }
  82. if (ringbuffer[ringbuffer_head].payload)
  83. free(ringbuffer[ringbuffer_head].payload);
  84. ringbuffer[ringbuffer_head].payload = malloc(LWS_PRE + len);
  85. ringbuffer[ringbuffer_head].len = len;
  86. memcpy((char *)ringbuffer[ringbuffer_head].payload +
  87. LWS_PRE, in, len);
  88. if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1))
  89. ringbuffer_head = 0;
  90. else
  91. ringbuffer_head++;
  92. if (((ringbuffer_head - pss->ringbuffer_tail) &
  93. (MAX_MESSAGE_QUEUE - 1)) != (MAX_MESSAGE_QUEUE - 2))
  94. goto done;
  95. choke:
  96. lwsl_debug("LWS_CALLBACK_RECEIVE: throttling %p\n", wsi);
  97. lws_rx_flow_control(wsi, 0);
  98. done:
  99. lws_callback_on_writable_all_protocol(lws_get_context(wsi),
  100. lws_get_protocol(wsi));
  101. break;
  102. /*
  103. * this just demonstrates how to use the protocol filter. If you won't
  104. * study and reject connections based on header content, you don't need
  105. * to handle this callback
  106. */
  107. case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
  108. dump_handshake_info(wsi);
  109. /* you could return non-zero here and kill the connection */
  110. break;
  111. default:
  112. break;
  113. }
  114. return 0;
  115. }