refactor test server
[platform/upstream/libwebsockets.git] / test-server / test-server-mirror.c
1 /*
2  * libwebsockets-test-server - libwebsockets test implementation
3  *
4  * Copyright (C) 2010-2015 Andy Green <andy@warmcat.com>
5  *
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.
10  *
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.
15  *
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,
19  *  MA  02110-1301  USA
20  */
21 #include "test-server.h"
22
23 /* lws-mirror_protocol */
24
25 #define MAX_MESSAGE_QUEUE 32
26
27 struct a_message {
28         void *payload;
29         size_t len;
30 };
31
32 static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
33 static int ringbuffer_head;
34
35 int
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)
40 {
41         struct per_session_data__lws_mirror *pss =
42                         (struct per_session_data__lws_mirror *)user;
43         int n;
44
45         switch (reason) {
46
47         case LWS_CALLBACK_ESTABLISHED:
48                 lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__);
49                 pss->ringbuffer_tail = ringbuffer_head;
50                 pss->wsi = wsi;
51                 break;
52
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);
58                 break;
59
60         case LWS_CALLBACK_SERVER_WRITEABLE:
61                 if (close_testing)
62                         break;
63                 while (pss->ringbuffer_tail != ringbuffer_head) {
64
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,
69                                                                 LWS_WRITE_TEXT);
70                         if (n < 0) {
71                                 lwsl_err("ERROR %d writing to mirror socket\n", n);
72                                 return -1;
73                         }
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);
77
78                         if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1))
79                                 pss->ringbuffer_tail = 0;
80                         else
81                                 pss->ringbuffer_tail++;
82
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));
87
88                         if (lws_partial_buffered(wsi) || lws_send_pipe_choked(wsi)) {
89                                 libwebsocket_callback_on_writable(context, wsi);
90                                 break;
91                         }
92                         /*
93                          * for tests with chrome on same machine as client and
94                          * server, this is needed to stop chrome choking
95                          */
96 #ifdef _WIN32
97                         Sleep(1);
98 #else
99                         usleep(1);
100 #endif
101                 }
102                 break;
103
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");
108                         goto choke;
109                 }
110
111                 if (ringbuffer[ringbuffer_head].payload)
112                         free(ringbuffer[ringbuffer_head].payload);
113
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))
121                         ringbuffer_head = 0;
122                 else
123                         ringbuffer_head++;
124
125                 if (((ringbuffer_head - pss->ringbuffer_tail) &
126                     (MAX_MESSAGE_QUEUE - 1)) != (MAX_MESSAGE_QUEUE - 2))
127                         goto done;
128
129 choke:
130                 lwsl_debug("LWS_CALLBACK_RECEIVE: throttling %p\n", wsi);
131                 libwebsocket_rx_flow_control(wsi, 0);
132
133 done:
134                 libwebsocket_callback_on_writable_all_protocol(
135                                                libwebsockets_get_protocol(wsi));
136                 break;
137
138         /*
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
142          */
143
144         case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
145                 dump_handshake_info(wsi);
146                 /* you could return non-zero here and kill the connection */
147                 break;
148
149         default:
150                 break;
151         }
152
153         return 0;
154 }