blob: 36172d43b32e4878cdc34d31f37aaed6272bbaae [file] [log] [blame]
/*
* ws protocol handler plugin for "dumb increment"
*
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* The person who associated a work with this deed has dedicated
* the work to the public domain by waiving all of his or her rights
* to the work worldwide under copyright law, including all related
* and neighboring rights, to the extent allowed by law. You can copy,
* modify, distribute and perform the work, even for commercial purposes,
* all without asking permission.
*
* These test plugins are intended to be adapted for use in your code, which
* may be proprietary. So unlike the library itself, they are licensed
* Public Domain.
*
* This is a copy of dumb_increment adapted slightly to serve as the
* "example-standalone-protocol", to show how to build protocol plugins
* outside the library easily.
*/
#define LWS_DLL
#define LWS_INTERNAL
#include "../lib/libwebsockets.h"
#include <string.h>
struct per_vhost_data__dumb_increment {
uv_timer_t timeout_watcher;
struct lws_context *context;
struct lws_vhost *vhost;
const struct lws_protocols *protocol;
};
struct per_session_data__dumb_increment {
int number;
};
static void
uv_timeout_cb_dumb_increment(uv_timer_t *w
#if UV_VERSION_MAJOR == 0
, int status
#endif
)
{
struct per_vhost_data__dumb_increment *vhd = lws_container_of(w,
struct per_vhost_data__dumb_increment, timeout_watcher);
lws_callback_on_writable_all_protocol_vhost(vhd->vhost, vhd->protocol);
}
static int
callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
struct per_session_data__dumb_increment *pss =
(struct per_session_data__dumb_increment *)user;
struct per_vhost_data__dumb_increment *vhd =
(struct per_vhost_data__dumb_increment *)
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
lws_get_protocol(wsi));
unsigned char buf[LWS_PRE + 512];
unsigned char *p = &buf[LWS_PRE];
int n, m;
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT:
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
lws_get_protocol(wsi),
sizeof(struct per_vhost_data__dumb_increment));
vhd->context = lws_get_context(wsi);
vhd->protocol = lws_get_protocol(wsi);
vhd->vhost = lws_get_vhost(wsi);
uv_timer_init(lws_uv_getloop(vhd->context, 0),
&vhd->timeout_watcher);
uv_timer_start(&vhd->timeout_watcher,
uv_timeout_cb_dumb_increment, 50, 50);
break;
case LWS_CALLBACK_PROTOCOL_DESTROY:
if (!vhd)
break;
uv_timer_stop(&vhd->timeout_watcher);
break;
case LWS_CALLBACK_ESTABLISHED:
pss->number = 0;
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
n = sprintf((char *)p, "%d", pss->number++);
m = lws_write(wsi, p, n, LWS_WRITE_TEXT);
if (m < n) {
lwsl_err("ERROR %d writing to di socket\n", n);
return -1;
}
break;
case LWS_CALLBACK_RECEIVE:
if (len < 6)
break;
if (strcmp((const char *)in, "reset\n") == 0)
pss->number = 0;
if (strcmp((const char *)in, "closeme\n") == 0) {
lwsl_notice("dumb_inc: closing as requested\n");
lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY,
(unsigned char *)"seeya", 5);
return -1;
}
break;
default:
break;
}
return 0;
}
static const struct lws_protocols protocols[] = {
{
"example-standalone-protocol",
callback_dumb_increment,
sizeof(struct per_session_data__dumb_increment),
10, /* rx buf size must be >= permessage-deflate rx size */
},
};
LWS_VISIBLE int
init_protocol_example_standalone(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_VISIBLE int
destroy_protocol_example_standalone(struct lws_context *context)
{
return 0;
}