[Libwebsockets] polling for file descriptor i/o

Andy Green andy at warmcat.com
Thu Mar 2 00:04:39 CET 2017

On March 2, 2017 7:41:51 AM GMT+09:00, Per Bothner <per at bothner.com> wrote:
>On 03/01/2017 01:33 PM, Andy Green wrote:
>> On March 2, 2017 6:07:35 AM GMT+09:00, Per Bothner <per at bothner.com>
>>> I tried using lws_adopt_descriptor_vhost:
>>>      lws_adopt_descriptor_vhost(lws_get_vhost(wsi), 0, fd,
>>> I do get a LWS_CALLBACK_RAW_RX_FILE callback, and I can read valid
>>> data from thefrom the pty.
>> Good...
>>> However, the 'user' parameter in the callback function is NULL.
>>> I kludged around it using a static variable, but I need a better
>>> solution, obviously.  Could/should lws_adopt_descriptor_vhost
>>> take an extra user_data parameter?
>> We can do that, or have it allocate (and free) based on the user data
>size given in the protocols struct... does the latter make any trouble
>if we fixed it that way?
>But I want the same user object for LWS_CALLBACK_RAW_RX_FILE as I want
>for the WS protocol handler.  At least the way it is currently done:

They are two different wsi.  Because they manage two independent descriptors.

As I mentioned cgi is done similarly inside lws already.  3 fd wsi are children of one http mode wsi.  If you bind the wsi like that, parents can find their children and a child wsi can get a pointer to his parent.

 * lws_get_parent() - get parent wsi or NULL
 * \param wsi: lws connection
 * Specialized wsi like cgi stdin/out/err are associated to a parent wsi,
 * this allows you to get their parent.
lws_get_parent(const struct lws *wsi);

 * lws_get_child() - get child wsi or NULL
 * \param wsi: lws connection
 * Allows you to find a related wsi from the parent wsi.
lws_get_child(const struct lws *wsi);

In the wsi there are these

	struct lws *parent; /* points to parent, if any */
	struct lws *child_list; /* points to first child */
	struct lws *sibling_list; /* subsequent children at same level */

You can use this but you'll have to hack in set accessors.

>LWS_CALLBACK_RAW_RX_FILE reads (from the pty child) into a buffer, but
>waits to write the data out on the WebSocket.  I could defer the read
>from the child until the WebSocket is writeable, but would that be

Yes, in fact it's ideal, but you will have to use the rx flow control api to modulate POLLIN, otherwise it will keep tapping you on the shoulder until you consume the read data when the ws wsi is writable.  You'd reenable the file desc flow control after you read as much as you wanted, it'll come back around if there's more, at whatever rate the outgoing ws connection can cope with.

>>> In case LWS_CALLBACK_RAW_RX_FILE I read the data into a buffer, and
>>> then
>>> call lws_callback_on_writable(wsi).  I do *not* get a
>>> event; instead I get a LWS_CALLBACK_RAW_WRITEABLE_FILE. Calling
>> That bit is good... you might have the same protocol callback
>handling ws and raw file side, so they have different callback reasons.
>That doesn't seem right.  I'm not trying to write to the raw file; I'm
>to do an lws_write when the WebSocket server is writeable.  So
>I'm trying to copy - reading from a raw file descriptor, and writing to
>the browser
>using WebSockets.
>>> lws_write
>> ... but this isn't I guess it's some missing handling somewhere.
>> Is there a clue what happens?  You should use LWS_WRITE_HTTP as it
>stands (nearest thing to raw atm)
>HTTP is not involved (except to the extent that WebSockets is based on

I misunderstood... you are writing on the file wsi when you must do it on the ws wsi, in the usual TEXT or BINARY mode.

You need to bind the two wsi by parent/child or other way.


>Once the resources (html, css, js) have been loaded, it's all
>I can single-step the lws_write with gdb - but I'm really doubtful that
>is correct.

More information about the Libwebsockets mailing list