[Libwebsockets] How to set the "user" callback parameter for adopted sockets?

Alan Conway aconway at redhat.com
Thu Nov 24 16:25:20 CET 2016


On Thu, 2016-11-24 at 23:10 +0800, Andy Green wrote:
> 
> On November 24, 2016 10:42:02 PM GMT+08:00, Alan Conway <aconway at redh
> at.com> wrote:
> > 
> > On Wed, 2016-11-23 at 23:19 +0800, Andy Green wrote:
> > > 
> > > 
> > > On November 23, 2016 10:53:57 PM GMT+08:00, Alan Conway <aconway@
> > > redh
> > > at.com> wrote:
> > > > 
> > > > 
> > > > On Wed, 2016-11-23 at 09:46 -0500, Alan Conway wrote:
> > > > > 
> > > > > 
> > > > > On Wed, 2016-11-23 at 08:50 +0800, Andy Green wrote:
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > On Tue, 2016-11-22 at 19:02 -0500, Alan Conway wrote:
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > I'm making progress! I can crash my router from a web
> > > > > > > brower
> > > > > > > :)
> > > > > > > 
> > > > > > > I can't figure out how to set the "user" parameter for
> > > > > > > lws
> > > > > > > callbacks
> > > > > > > for a socket adopted with lws_adopt_socket(). I can
> > > > > > > access
> > > > > > > the
> > > > > > 
> > > > > > That's not what *user_space is for.
> > > > > > 
> > > > > > It's for protocol-specific local data, per-
> > > > > > connection.  When
> > > > > > the
> > > > > > protocol changes, which it may often do with a http/1.1
> > > > > > keepalive
> > > > > > connection visiting urls that map on to different plugins,
> > > > > > the
> > > > > > user
> > > > > > data allocation is destroyed by lws and a new one sized
> > > > > > appropriately
> > > > > > for the new protocol allocated.
> > > > > 
> > > > > For me, the protocol starts as "http" and may change to
> > > > > "binary"
> > > > > or
> > > > > "amqp" (which I treat as both "amqp"). Does that mean that if
> > > > > I
> > > > > store
> > > > > context for the http protocol, it will be wiped out in the
> > > > > upgrade?
> > > > > Is
> > > > > there any way to preserve some per-connection data between
> > > > > the
> > > > > two or
> > > > > is each protocol session treated as entirely separate from
> > > > > previous
> > > > > ones?
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > allocated space *after* the adopt call with
> > > > > > > lws_wsi_user(),
> > > > > > > but
> > > > > > > lws_adopt_socket() itself is firing my callbacks so
> > > > > > > that's
> > > > > > > too
> > > > > > > late.
> > > > > > > 
> > > > > > > The docs mention setting up your session data on the
> > > > > > > LWS_CALLBACK_ESTABLISHED event, but at that point I have
> > > > > > > nothing
> > > > > > > I
> > > > > > > can
> > > > > > > use to find data from my application.
> > > > > > 
> > > > > > LWS doesn't have this concept of external shadowed data
> > > > > > per-
> > > > > > connection
> > > > > > built-in.
> > > > > > 
> > > > > > You have two ways to do it
> > > > > > 
> > > > > >  - add a new opaque void * in struct lws and set it at
> > > > > > adopt-
> > > > > > time,
> > > > > > provide an accessor to get it from the wsi.  This is a bit
> > > > > > of a
> > > > > > burden
> > > > > > for everyone who doesn't care about this then.
> > > > > 
> > > > > For current purposes I need to use a released, packaged
> > > > > version
> > > > > of
> > > > > lws
> > > > > so modifying it isn't an option - I do hope to make
> > > > > contributions
> > > > > later...
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > >  - Set the context user pointer at context creation
> > > > > > time.  You
> > > > > > can
> > > > > > get
> > > > > > this from a wsi in the callback.  You can then use this
> > > > > > context-
> > > > > > wide
> > > > > > pointer to dereference the wsi pointer to your private
> > > > > > connection
> > > > > > pointer on your side, entirely outside of lws.
> > > > > 
> > > > > I could use either the fd or the wsi pointer to look up my
> > > > > application
> > > > > data, but it's an expensive lookup that requires a map of all
> > > > > the
> > > > > known
> > > > > fds/wsi-pointers. I could use thread-local storage as a hack
> > > > > to
> > > > > get
> > > > > my
> > > > > context into the initial "http" established callback, but
> > > > > that
> > > > > doesn't
> > > > > help if it will get wiped out in the upgrade to "amqp"...
> > > > > Hmmm.
> > > > > 
> > > > 
> > > > What if I use a separate context per connection? I know you
> > > > said I
> > > 
> > > No, that is a very bad idea.
> > 
> > Why? What will go wrong?
> 
> Did you look at what goes on in the context + vhost structs you will
> be spawning one of per connection to see why it's a bad idea?
> 

OK, so am I safe to call lws_process_fd() for different fds on the same
shared context concurrently? If so then a lookup table of some sort for
the application data will work. If there's any chance of race on the
context then I'd rather waste memory than figure out the race
conditions - in the short term.

I know there are better solutions if we modify lws, but not for my
upcoming release.

Cheers,
Alan.



More information about the Libwebsockets mailing list