I have an example of using the background module. I think it is
compatible with the 4.5.1 patch. The main difference is that my
version of the C code is a module with additional core API added to
nsd. The Tcl code should work the same.

Here is the link (the init.tcl shows how to use the thread package):

http://junom.com/gitweb/gitweb.perl?p=aolserver.git;a=tree;f=aolserver/nsbgwrite;hb=HEAD

I'll look at the patch. It seems useful even for more than the current issue.

Also, it might be possible to use the new registered filter point:
prequeue to completely avoid using a conn thread.

tom jackson

On Mon, Nov 1, 2010 at 3:51 PM, Jeff Rogers <[email protected]> wrote:
> It looks like my previous answer was, at best, partially right.  It looks
> lke [ns_conn channel] does in fact give you a read/write channel.    The
> effect of the missing content-length header is to discard any data that was
> read past the headers.   Attached is a patch (readahead.patch) to change
> that behavior.   The patch does 2 things: one, if the request includes
> 'upgrade' in the connection header, it doesn't read past the header (and
> doesn't throw away what it has read).  Two, when [ns_conn channel] is
> called, it will insert into the channel buffer any data that was already
> read (and not processed) on the socket.  Combined, it means that on an
> upgrade connection you can get the entire body, even if there was no
> content-length header sent.
>
> Also attached is a tcl file (index.tcl) that looks for an upgrade header,
> and when it gets one it forks a background tcl thread that echoes everything
> read back to the sender.  Every new request will get a new thread.  It also
> probably needs some tweaking to get a second request to work at all (since
> it's using shared channels to give the socket to the background thread).
>
> Importantly, this design of thread-per-connection is not scalable - your
> server will fall down and start crying once you start up a few dozen
> threads. (perhaps more; a really rough guess is that each tcl thread
> consumes 2M of memory before doing anything).  What you really want to do is
> to transfer each new websocket to a single existing background thread, but
> I'm not sure how to send stuff into another thread's event loop using the
> aolserver thread tools.  The standard tcl thread package is more powerful
> (with thread::send and thread::wait) but I don't know if those play nice
> inside AOLserver.
>
> -J
>
>
>
> wiwo wrote:
>>
>> Hi!
>>
>> I just tried the following:
>>
>> I've been telneting to our server and was feeding it this request:
>>
>> GET /test/ns_chan HTTP/1.1
>> Host: www.dcon.at
>> Connection: Upgrade
>> Sec-WebSocket-Key2: 12998 5 Y3 1  .P00
>> Sec-WebSocket-Protocol: sample
>> Content-Length: 8
>> Upgrade: WebSocket
>> Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5
>> Origin: http://example.com
>>
>> ^n:ds[4U
>>
>> Notice the "Content-Length" header. As Jeff told me, I've now been
>> able to output the 8 byte "body" of the request.
>>
>> Then I was creating an ns_chan with:
>>
>> set ch [ns_conn channel]
>> ns_chan create $ch $chan_name
>>
>> and getting it back with:
>> set ch [ns_chan get $chan_name]
>>
>> The I tried to write my WebSocket server handshake with:
>>
>> puts $ch "
>> HTTP/1.1 101 WebSocket Protocol Handshake
>> Upgrade: WebSocket
>> Connection: Upgrade
>> Sec-WebSocket-Origin: http://[util::host]
>> Sec-WebSocket-Location: ws://[util::host]/[ns_conn url]
>> Sec-WebSocket-Protocol: sample
>>
>> $ret
>> "
>>
>> which showed up in the telnet client.
>>
>> Then I tried to read again
>>
>> set str [read $x 10]
>> ns_log notice $str
>>
>> and typed 10 characters in the telnet client which showed up in the
>> log.
>>
>> So far so good! I could now write my own proposal for changing the
>> WebSocket Client and make Google and Apple change their
>> implementations of the protocol. Unfortunately my relationship with
>> Steve and Larry cooled down the last few months, so this could take a
>> while :-)
>>
>> Or I could get my hands dirty and mess around with the code in
>> driver.c.
>>
>> As far as I can see, the crucial code is in
>> static ReadErr SockReadLine(Driver *drvPtr, Ns_Sock *sock, Conn
>> *connPtr)
>> somewhere at line 1878 where the content length is read. I could
>> simply check for the "Upgrade: WebSocket" header and set the length to
>> the magic number of 8.
>>
>> Of course I have no idea when I'm talking about AOLserver C code, but
>> maybe someone with a clue can give me his/her thoughts here.
>>
>> wiwo
>>
>>
>>> I'm pretty sure it's not possible to implement websockets in AOLserver
>>> without some C-level work, and if you could you wouldn't want to.
>>>
>>> You can't, because the driver reads the entire request, including
>>> content, before handing it off to the connection thread.  And it only
>>> reads past the headers if there is a 'Content-length' header.  (You can
>>> hook into the content-reading with a read filter, but that won't help
>>> because with no content-length it won't ever try to read it).
>>>
>>> You wouldn't want to, because you would attach a conn thread to a single
>>> persistent websocket, which would severely limit how many you could
>>> handle.  Doing it as a background tcl thread would be little better,
>>> because you'd still need a thread per connection.  Handling all
>>> websockets with a single background thread using tcl event handling
>>> would work, if you could get read/write handles to the sockets (which
>>> currently you can't - I think the background delivery patch only creates
>>> a writable channel).
>>>
>>> So what else can you do?
>>>
>>> For starters, you could check the current state of naviserver - I'm not
>>> up to date on what has changed there lately, but a r/w version of
>>> 'ns_conn channel' might have been implemented.
>>>
>>> Otherwise, you need to get your hands dirty in the C code and implement
>>> 'Upgrade' handling.  If you do take this approach, I'd suggest
>>> implementing just enough logic to transfer control elsewhere - that is,
>>> in the driver, don't try to handle websockets, rather set it up to
>>> recognize the upgrade protocol ("Connection: upgrade" and "Upgrade:
>>> something" headers) and call a registered procedure and forget about the
>>> connection (leaving it to the registered proc to actually do anything
>>> with it).
>>>
>>> -J
>>>
>>> --
>>> AOLserver -http://www.aolserver.com/
>>>
>>> To Remove yourself from this list, simply send an email to
>>> <[email protected]> with the
>>> body of "SIGNOFF AOLSERVER" in the email message. You can leave the
>>> Subject: field of your email blank.
>>
>>
>> --
>> AOLserver - http://www.aolserver.com/
>>
>> To Remove yourself from this list, simply send an email to
>> <[email protected]> with the
>> body of "SIGNOFF AOLSERVER" in the email message. You can leave the
>> Subject: field of your email blank.
>
>
>
> --
> AOLserver - http://www.aolserver.com/
>
> To Remove yourself from this list, simply send an email to
> <[email protected]> with the
> body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject:
> field of your email blank.
>


--
AOLserver - http://www.aolserver.com/

To Remove yourself from this list, simply send an email to 
<[email protected]> with the
body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: 
field of your email blank.

Reply via email to