Hi! Thanks for the patch. It's probably usefull for other stuff as well. But I still have a problem.
If I post the request via telnet, I now get the missing 8 bytes by reading from the channel. If I try to connect with Chrome via WebSockets I still get nothing. Even if I'm feeding the request into the telnet client with telnet www.dcon.at 80 < ws_req.txt I don't get the 8 bytes. Maybe there is a race condition involved? I know, that you can't start a thread per client when one expects thousands of clients, but I think this would not be too hard to solve, either by ns_proxy, tcl threads or the background module Tom and Gustaf mentioned. I'll post my working solution with some benchmarking as soon as I can connect with Chrome. wiwo On 1 Nov., 23:51, 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. > > readahead.patch > 1KAnzeigenHerunterladen > > index.tcl > < 1 KBAnzeigenHerunterladen -- 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.
