[Libwebsockets] Some help wanted explaining how the dumb-increment-protocol works

Andy Green andy at warmcat.com
Sun May 8 23:06:44 CEST 2016



On May 9, 2016 3:38:47 AM GMT+08:00, Colin Adams <colinpauladams at gmail.com> wrote:
>I'm writing a wrapper around libwebsocket v2 for the Idris programming
>language. I started by writing an Idris version of the
>test-server-v2.0,
>but using the distributed plugins (i.e. as compiled from C).

This is the best way to do things generally.

>Once I got that working nicely (early this morning, UK time), I tried
>to
>implement the dumb-increment-protocol in Idris (but not a plugin, since
>I
>don't think I can currently use Idris to create shared objects), so I'm

Okay... but it basically means you have to deal with things in the pre-v2.0 way.

>looking at test-server-dumb-increment.c as an implementation template.
>I've got this roughly 1/4 working. Only one
>LWS_CALLBACK_SERVER_WRITEABLE

It sounds like you are not generating lws_callback_on_writable_all_protocol() to regulate those callbacks.

>gets seen by my handler, and debugging shows it writes one byte (a "1")

OK... if by 'write' we mean calls lws_write()

>successfully, But the number doesn't get displayed in the web page. The
>request Server Close button DOES work (debugging shows my handler
>receives
>the message, but it never receives a reset\n message when I press the
>reset
>button.

Sounds like your code for sending stuff has something wrong.

>So I'm a little puzzled as to what's going on. In particular, I don't
>understand where the 20Hz refresh rate is supposed to come from. If you
>could explain that, it will probably be enough for me to work out what
>I
>have done wrong.

There are two basic server styles in lws now

 - pre-2.0: everything is in user code.  The examples for this are, eg, ./test-server/test-server.c, ./test-server/test-server-dumb-increment.c, etc.  These are all linked together to form the test app.

 - post-2.0: ws protocol handlers go in generic plugins.  Rather than cut-and-paste them, you can pass them name:value per-vhost configuration options in info.pvo to adapt them.  Mounts can be used to eliminate http boilerplate and get things served by the library.

In the plugins style, the plugin .so is responsible for arranging anything it needs like 20Hz callbacks, because the server app may not be aware it exists or not.  To facilitate that in a crossplatform way, libuv is mandatory if you use plugins.  So in the selfcontained, plugin version of dumb increment, it sets up a 50ms libuv timer per-vhost at the protocol init callback

		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);

and in the callback for that (still part of the plugin) he requests the writable callback for all dumb-increment connections on that vhost

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);
}

This method has the big advantage a completely generic lws server wrapper around lws like lwsws can use new plugins without any code changes in the server part.  Options in the plugin can be set per-vhost generically from JSON with lwsws, which are available as a linked-list of name:value pairs at the protocol plugin's per-vhost LWS_CALLBACK_PROTOCOL_INIT.  But otherwise the plugin is responsible to set up and take down whatever is needed by it.

If you can't do plugins, you have to use the pre-2.0 way.  There, the ws protocol code is mixed in with the server app.  So the server app deals with any requirements of the protocol code, and is cutomized each time.  In that case in the event loop (the code is different depending on which event loop) it must do the regulation of dumb-increment callbacks, eg in ./test-server/test-server.c in his poll() loop

		ms = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
		if ((ms - oldms) > 50) {
			lws_callback_on_writable_all_protocol(context,
				&protocols[PROTOCOL_DUMB_INCREMENT]);
			oldms = ms;
		}

-Andy

>
>------------------------------------------------------------------------
>
>_______________________________________________
>Libwebsockets mailing list
>Libwebsockets at ml.libwebsockets.org
>http://libwebsockets.org/mailman/listinfo/libwebsockets




More information about the Libwebsockets mailing list