/* * ws protocol handler plugin for "dumb increment" * * Copyright (C) 2010-2016 Andy Green * * 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. */ #if !defined (LWS_PLUGIN_STATIC) #define LWS_DLL #define LWS_INTERNAL #include "../lib/libwebsockets.h" #endif #include #if defined(LWS_WITH_ESP8266) #define DUMB_PERIOD 50 #else #define DUMB_PERIOD 50 #endif 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 + 20]; 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, DUMB_PERIOD, DUMB_PERIOD); break; case LWS_CALLBACK_PROTOCOL_DESTROY: if (!vhd) break; lwsl_notice("di: LWS_CALLBACK_PROTOCOL_DESTROY: v=%p, ctx=%p\n", vhd, vhd->context); uv_timer_stop(&vhd->timeout_watcher); uv_close((uv_handle_t *)&vhd->timeout_watcher, NULL); break; case LWS_CALLBACK_ESTABLISHED: pss->number = 0; break; case LWS_CALLBACK_SERVER_WRITEABLE: n = lws_snprintf((char *)p, sizeof(buf) - LWS_PRE, "%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; } #define LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT \ { \ "dumb-increment-protocol", \ callback_dumb_increment, \ sizeof(struct per_session_data__dumb_increment), \ 10, /* rx buf size must be >= permessage-deflate rx size */ \ } #if !defined (LWS_PLUGIN_STATIC) static const struct lws_protocols protocols[] = { LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT }; LWS_EXTERN LWS_VISIBLE int init_protocol_dumb_increment(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_dumb_increment(struct lws_context *context) { return 0; } #endif