2 * libwebsockets-test-fraggle - random fragmentation test
4 * Copyright (C) 2010-2011 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,
30 #include "lws_config.h"
33 #include "../lib/libwebsockets.h"
35 #define LOCAL_RESOURCE_PATH INSTALL_DATADIR"/libwebsockets-test-server"
47 /* fraggle protocol */
50 FRAGSTATE_START_MESSAGE,
51 FRAGSTATE_RANDOM_PAYLOAD,
52 FRAGSTATE_POST_PAYLOAD_SUM,
55 struct per_session_data__fraggle {
59 enum fraggle_states state;
63 callback_fraggle(struct libwebsocket_context *context,
64 struct libwebsocket *wsi,
65 enum libwebsocket_callback_reasons reason,
66 void *user, void *in, size_t len)
69 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 8000 +
70 LWS_SEND_BUFFER_POST_PADDING];
71 struct per_session_data__fraggle *psf = user;
73 int write_mode = LWS_WRITE_CONTINUATION;
75 unsigned char *p = (unsigned char *)in;
76 unsigned char *bp = &buf[LWS_SEND_BUFFER_PRE_PADDING];
80 case LWS_CALLBACK_ESTABLISHED:
82 fprintf(stderr, "server sees client connect\n");
83 psf->state = FRAGSTATE_START_MESSAGE;
84 /* start the ball rolling */
85 libwebsocket_callback_on_writable(context, wsi);
88 case LWS_CALLBACK_CLIENT_ESTABLISHED:
90 fprintf(stderr, "client connects to server\n");
91 psf->state = FRAGSTATE_START_MESSAGE;
94 case LWS_CALLBACK_CLIENT_RECEIVE:
98 case FRAGSTATE_START_MESSAGE:
100 psf->state = FRAGSTATE_RANDOM_PAYLOAD;
102 psf->total_message = 0;
103 psf->packets_left = 0;
107 case FRAGSTATE_RANDOM_PAYLOAD:
109 for (n = 0; n < len; n++)
112 psf->total_message += len;
115 if (libwebsocket_is_final_fragment(wsi))
116 psf->state = FRAGSTATE_POST_PAYLOAD_SUM;
119 case FRAGSTATE_POST_PAYLOAD_SUM:
126 fprintf(stderr, "EOM received %d correctly "
127 "from %d fragments\n",
128 psf->total_message, psf->packets_left);
130 fprintf(stderr, "**** ERROR at EOM: "
131 "length %d, rx sum = 0x%lX, "
132 "server says it sent 0x%lX\n",
133 psf->total_message, psf->sum, sum);
135 psf->state = FRAGSTATE_START_MESSAGE;
140 case LWS_CALLBACK_SERVER_WRITEABLE:
142 switch (psf->state) {
144 case FRAGSTATE_START_MESSAGE:
146 psf->packets_left = (random() % 1024) + 1;
147 fprintf(stderr, "Spamming %d random fragments\n",
150 psf->total_message = 0;
151 write_mode = LWS_WRITE_BINARY;
152 psf->state = FRAGSTATE_RANDOM_PAYLOAD;
156 case FRAGSTATE_RANDOM_PAYLOAD:
159 * note how one chunk can be 8000, but we use the
160 * default rx buffer size of 4096, so we exercise the
161 * code for rx spill because the rx buffer is full
164 chunk = (random() % 8000) + 1;
165 psf->total_message += chunk;
167 libwebsockets_get_random(context, bp, chunk);
168 for (n = 0; n < chunk; n++)
172 if (psf->packets_left)
173 write_mode |= LWS_WRITE_NO_FIN;
175 psf->state = FRAGSTATE_POST_PAYLOAD_SUM;
177 n = libwebsocket_write(wsi, bp, chunk, write_mode);
181 lwsl_err("Partial write\n");
185 libwebsocket_callback_on_writable(context, wsi);
188 case FRAGSTATE_POST_PAYLOAD_SUM:
190 fprintf(stderr, "Spamming session over, "
191 "len = %d. sum = 0x%lX\n",
192 psf->total_message, psf->sum);
194 bp[0] = psf->sum >> 24;
195 bp[1] = psf->sum >> 16;
196 bp[2] = psf->sum >> 8;
199 n = libwebsocket_write(wsi, (unsigned char *)bp,
200 4, LWS_WRITE_BINARY);
204 lwsl_err("Partial write\n");
208 psf->state = FRAGSTATE_START_MESSAGE;
210 libwebsocket_callback_on_writable(context, wsi);
215 case LWS_CALLBACK_CLOSED:
220 /* because we are protocols[0] ... */
222 case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
223 if (strcmp(in, "deflate-stream") == 0) {
224 fprintf(stderr, "denied deflate-stream extension\n");
238 /* list of supported protocols and callbacks */
240 static struct libwebsocket_protocols protocols[] = {
244 sizeof(struct per_session_data__fraggle),
247 NULL, NULL, 0 /* End of list */
251 static struct option options[] = {
252 { "help", no_argument, NULL, 'h' },
253 { "debug", required_argument, NULL, 'd' },
254 { "port", required_argument, NULL, 'p' },
255 { "ssl", no_argument, NULL, 's' },
256 { "interface", required_argument, NULL, 'i' },
257 { "client", no_argument, NULL, 'c' },
261 int main(int argc, char **argv)
266 struct libwebsocket_context *context;
268 char interface_name[128] = "";
269 const char *iface = NULL;
270 struct libwebsocket *wsi;
272 int server_port = port;
273 struct lws_context_creation_info info;
275 memset(&info, 0, sizeof info);
277 fprintf(stderr, "libwebsockets test fraggle\n"
278 "(C) Copyright 2010-2013 Andy Green <andy@warmcat.com> "
279 "licensed under LGPL2.1\n");
282 n = getopt_long(argc, argv, "ci:hsp:d:", options, NULL);
287 lws_set_log_level(atoi(optarg), NULL);
297 strncpy(interface_name, optarg, sizeof interface_name);
298 interface_name[(sizeof interface_name) - 1] = '\0';
299 iface = interface_name;
303 fprintf(stderr, " Client mode\n");
306 fprintf(stderr, "Usage: libwebsockets-test-fraggle "
307 "[--port=<p>] [--ssl] "
308 "[-d <log bitfield>] "
315 server_port = CONTEXT_PORT_NO_LISTEN;
316 if (optind >= argc) {
317 fprintf(stderr, "Must give address of server\n");
322 info.port = server_port;
324 info.protocols = protocols;
325 #ifndef LWS_NO_EXTENSIONS
326 info.extensions = libwebsocket_get_internal_extensions();
329 info.ssl_cert_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
330 info.ssl_private_key_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
336 context = libwebsocket_create_context(&info);
337 if (context == NULL) {
338 fprintf(stderr, "libwebsocket init failed\n");
343 address = argv[optind];
344 fprintf(stderr, "Connecting to %s:%u\n", address, port);
345 wsi = libwebsocket_client_connect(context, address,
346 port, use_ssl, "/", address,
347 "origin", protocols[PROTOCOL_FRAGGLE].name,
350 fprintf(stderr, "Client connect to server failed\n");
356 while (!n && !terminate)
357 n = libwebsocket_service(context, 50);
359 fprintf(stderr, "Terminating...\n");
362 libwebsocket_context_destroy(context);