blob: 76e2f09c2464f55f728363b9c8a3b86667243b2a [file] [log] [blame]
/*
* ws protocol handler plugin for "lws-minimal-pmd-bulk"
*
* Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* The protocol shows how to send and receive bulk messages over a ws connection
* that optionally may have the permessage-deflate extension negotiated on it.
*/
#if !defined (LWS_PLUGIN_STATIC)
#define LWS_DLL
#define LWS_INTERNAL
#include <libwebsockets.h>
#endif
#include <string.h>
/*
* We will produce a large ws message either from this text repeated many times,
* or from 0x40 + a 6-bit pseudorandom number
*/
static const char * const redundant_string =
"No one would have believed in the last years of the nineteenth "
"century that this world was being watched keenly and closely by "
"intelligences greater than man's and yet as mortal as his own; that as "
"men busied themselves about their various concerns they were "
"scrutinised and studied, perhaps almost as narrowly as a man with a "
"microscope might scrutinise the transient creatures that swarm and "
"multiply in a drop of water. With infinite complacency men went to "
"and fro over this globe about their little affairs, serene in their "
"assurance of their empire over matter. It is possible that the "
"infusoria under the microscope do the same. No one gave a thought to "
"the older worlds of space as sources of human danger, or thought of "
"them only to dismiss the idea of life upon them as impossible or "
"improbable. It is curious to recall some of the mental habits of "
"those departed days. At most terrestrial men fancied there might be "
"other men upon Mars, perhaps inferior to themselves and ready to "
"welcome a missionary enterprise. Yet across the gulf of space, minds "
"that are to our minds as ours are to those of the beasts that perish, "
"intellects vast and cool and unsympathetic, regarded this earth with "
"envious eyes, and slowly and surely drew their plans against us. And "
"early in the twentieth century came the great disillusionment. "
;
/* this reflects the length of the string above */
#define REPEAT_STRING_LEN 1337
/* this is the total size of the ws message we will send */
#define MESSAGE_SIZE (100 * REPEAT_STRING_LEN)
/* this is how much we will send each time the connection is writable */
#define MESSAGE_CHUNK_SIZE (1 * 1024)
/* one of these is created for each client connecting to us */
struct per_session_data__minimal_pmd_bulk {
int position; /* byte position we got up to sending the message */
uint64_t rng;
};
static int
callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
struct per_session_data__minimal_pmd_bulk *pss =
(struct per_session_data__minimal_pmd_bulk *)user;
uint8_t buf[LWS_PRE + MESSAGE_CHUNK_SIZE], *p;
int n, m, msg_flag;
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
pss->position = 0;
pss->rng = 4;
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
if (pss->position == MESSAGE_SIZE)
break;
if (!pss->position)
msg_flag = LWS_WRITE_TEXT;
else
msg_flag = LWS_WRITE_CONTINUATION;
/* fill up one chunk's worth of message content */
p = &buf[LWS_PRE];
n = MESSAGE_CHUNK_SIZE;
if (n > MESSAGE_SIZE - pss->position)
n = MESSAGE_SIZE - pss->position;
/*
* select between producing compressible repeated text,
* or uncompressible PRNG output
*/
#if 0
while (n) {
m = pss->position % REPEAT_STRING_LEN;
s = REPEAT_STRING_LEN - m;
if (s > n)
s = n;
memcpy(p, &redundant_string[m], s);
pss->position += s;
p += s;
n -= s;
}
#else
pss->position += n;
while (n--) {
pss->rng ^= pss->rng << 21;
pss->rng ^= pss->rng >> 35;
pss->rng ^= pss->rng << 4;
*p++ = 0x40 + ((pss->rng >> (n & 15)) & 0x3f);
}
#endif
if (pss->position != MESSAGE_SIZE) /* if not the end, no FIN */
msg_flag |= LWS_WRITE_NO_FIN;
n = lws_ptr_diff(p, &buf[LWS_PRE]);
m = lws_write(wsi, &buf[LWS_PRE], n, msg_flag);
if (m < n) {
lwsl_err("ERROR %d writing ws\n", n);
return -1;
}
if (pss->position != MESSAGE_SIZE) /* if more to do... */
lws_callback_on_writable(wsi);
break;
default:
break;
}
return 0;
}
#define LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK \
{ \
"lws-minimal-pmd-bulk", \
callback_minimal_pmd_bulk, \
sizeof(struct per_session_data__minimal_pmd_bulk), \
4096, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK
};
LWS_EXTERN LWS_VISIBLE int
init_protocol_minimal_pmd_bulk(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_EXTERN LWS_VISIBLE int
destroy_protocol_minimal_pmd_bulk(struct lws_context *context)
{
return 0;
}
#endif