2 * libwebsockets-test-server - libwebsockets test implementation
4 * Copyright (C) 2010-2015 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 #include "test-server.h"
23 /* lws-mirror_protocol */
25 #define MAX_MESSAGE_QUEUE 32
32 static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
33 static int ringbuffer_head;
36 callback_lws_mirror(struct libwebsocket_context *context,
37 struct libwebsocket *wsi,
38 enum libwebsocket_callback_reasons reason,
39 void *user, void *in, size_t len)
41 struct per_session_data__lws_mirror *pss =
42 (struct per_session_data__lws_mirror *)user;
47 case LWS_CALLBACK_ESTABLISHED:
48 lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__);
49 pss->ringbuffer_tail = ringbuffer_head;
53 case LWS_CALLBACK_PROTOCOL_DESTROY:
54 lwsl_notice("%s: mirror protocol cleaning up\n", __func__);
55 for (n = 0; n < sizeof ringbuffer / sizeof ringbuffer[0]; n++)
56 if (ringbuffer[n].payload)
57 free(ringbuffer[n].payload);
60 case LWS_CALLBACK_SERVER_WRITEABLE:
63 while (pss->ringbuffer_tail != ringbuffer_head) {
65 n = libwebsocket_write(wsi, (unsigned char *)
66 ringbuffer[pss->ringbuffer_tail].payload +
67 LWS_SEND_BUFFER_PRE_PADDING,
68 ringbuffer[pss->ringbuffer_tail].len,
71 lwsl_err("ERROR %d writing to mirror socket\n", n);
74 if (n < ringbuffer[pss->ringbuffer_tail].len)
75 lwsl_err("mirror partial write %d vs %d\n",
76 n, ringbuffer[pss->ringbuffer_tail].len);
78 if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1))
79 pss->ringbuffer_tail = 0;
81 pss->ringbuffer_tail++;
83 if (((ringbuffer_head - pss->ringbuffer_tail) &
84 (MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 15))
85 libwebsocket_rx_flow_allow_all_protocol(
86 libwebsockets_get_protocol(wsi));
88 if (lws_partial_buffered(wsi) || lws_send_pipe_choked(wsi)) {
89 libwebsocket_callback_on_writable(context, wsi);
93 * for tests with chrome on same machine as client and
94 * server, this is needed to stop chrome choking
104 case LWS_CALLBACK_RECEIVE:
105 if (((ringbuffer_head - pss->ringbuffer_tail) &
106 (MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 1)) {
107 lwsl_err("dropping!\n");
111 if (ringbuffer[ringbuffer_head].payload)
112 free(ringbuffer[ringbuffer_head].payload);
114 ringbuffer[ringbuffer_head].payload =
115 malloc(LWS_SEND_BUFFER_PRE_PADDING + len +
116 LWS_SEND_BUFFER_POST_PADDING);
117 ringbuffer[ringbuffer_head].len = len;
118 memcpy((char *)ringbuffer[ringbuffer_head].payload +
119 LWS_SEND_BUFFER_PRE_PADDING, in, len);
120 if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1))
125 if (((ringbuffer_head - pss->ringbuffer_tail) &
126 (MAX_MESSAGE_QUEUE - 1)) != (MAX_MESSAGE_QUEUE - 2))
130 lwsl_debug("LWS_CALLBACK_RECEIVE: throttling %p\n", wsi);
131 libwebsocket_rx_flow_control(wsi, 0);
134 libwebsocket_callback_on_writable_all_protocol(
135 libwebsockets_get_protocol(wsi));
139 * this just demonstrates how to use the protocol filter. If you won't
140 * study and reject connections based on header content, you don't need
141 * to handle this callback
144 case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
145 dump_handshake_info(wsi);
146 /* you could return non-zero here and kill the connection */