
More platforms
In addition to Linux, there are now users of libwebsockets on win32, OSX and iOS that have contributed patches now in git at http://git.warmcat.com/cgi-bin/cgit/libwebsockets OSX wasn’t too hard thanks to some patches from Darin Willits, win32 was a bit tougher despite a big patch from Peter Hinz, I was really surprised to find the the Microsoft compiler doesn’t support simple C99 features like named member initialization of structs. Anyway after dumbing down the few structs that used it, and adapting a few other things it’s now possible to use libwebsockets on win32 thanks to Peter’s work.
v05 and v06 protocol support
Both v05 and v06 support was added within 12 hours of the spec being released, at the time of writing v06 is the current version.
I also added v00 client support by request from a developer using the socket.io server library which doesn’t support anything except 76 / 00. That means that in libwebsockets, both server and client support now covers all combinations of v00. v04, v05 and v06.
Extensions and deflate-stream
There’s a new extension support infrastructure added, including an implementation of zlib compression to provide the standardized “deflate-stream” extension.
The benefit of running with compression depends a lot on the payload size and content; in order to reduce latency the compression buffers are partially flushed every frame. But it is an important part of the websockets standard that libwebsockets now supports.
Integration with external poll arrays
Libwebsockets is being integrated into a fork of ircd, the daemon which runs the IRC network. The challenge there is to interoperate will the existing single poll() loop in a way that maximizes blocking and maintains serialization of poll service in a single thread to avoid the need for locking.
In addition to its default private poll array management libwebsockets now provides poll array callbacks into the user code which enables integration of websocket event loop functionality into an existing, master poll() array.
Callbacks occur into user code when file descriptors must be added, removed or have their event masks changed. There are hash tables implemented in libwebsockets to allow everything to remain opaque to the host code using just the file descriptor as an index.
With this technique, it has been possible to integrate websocket functionality into an existing irc server while keeping all details about websocket functionality and protocol versioning in the library.
I’m noticing a strange delay when receiving server packets on some machines. Actually it seems that in some cases Windows stacks around 5-10 packets into a pile before it sends them to the browser (either Firefox, Opera or Chrome).
This causes the test page’s counter to increase chunks at a time and the test canvas to lag. The test canvas receives packets steadily when you yourself are drawing (sending packets) too. This only applies to the protocol that is used for sending data, so dumb-increment-protocol count still doesn’t grow steadily even if you are sending mirror protocol packets.
However This happens on both Windows XP and 7 machines, but not on every machine, so it probably has something to do with network settings. On other operating systems this doesn’t seem to happen.
Might there be something wrong with the packet headers that makes Windows think the packet doesn’t have to be delivered instantly? I do not notice this problem with other websockets libraries.
Hi… I don’t see this problem on Linux. Maybe it’s to do with the congestion control algorithm in your Windows TCP stack.
http://smallvoid.com/article/winnt-ctcp-support.html
It might also be worth running the server on one box and the browser on a second box, so you can watch the packets and their timing go between them, maybe there’s some clue from that.
Changing the congestion provider didn’t have any effect. It must be related to some network setting though, since on some Windows instances, regardless of the version, this does not occur.
It should be possible to fix this problem on the server side, because other WebSocket libraries don’t seem to have this problem. Maybe if you try to find the differences in the packets sent by your library and other WebSocket libraries, you could find a solution to this. Since Windows users currently represent a majority of internet users, this is a pretty important issue.
The library itself is awesome. I’m sure many people appreciate your contribution. It seems to be one of the few if not the only WebSocket library for a non-interpreted programming language.
Is it possible the binaries are configured differently on the different machines, eg –enable-nofork? Or are they exactly the same binaries acting differently on different Windows machines?
Maybe antivirus hooking the packets on some boxes?
Otherwise there’s noting special about the network APIs used in libwebsocket it’s basically a poll() loop in the end.
You might try editing test-server.c and changing the poll() timeout from 50ms to something smaller, see if that impacts it. But it’s just a random guess.
The difference is with clients (in browsers using the test page). My test server is running on a Debian VPS. It does not matter if the server is running in forked mode or not.
So when one client is connected using a Windows machine affected by this problem, the dumb increment counter and the canvas only updates about 2-3 times a second, unless the client is sending data using the same protocol at the same time of receiving data. Clients that are not affected may be connected at the same time and not experience any problems.
I see. Although what you said earlier can be true that it may be possible to ‘fix’ this at the server I think we will need some idea of the kind of issue first. The fact that other clients are working well simultaneously with the same server is good news because there’s no fundamental issue going on in the server, although it can still be something subtle that can be changed that provokes the issue.
Maybe it’s easiest to tcpdump at your Debian box the traffic on the connection to the bad guy and get some idea from there.
Is it possible there are proxies or routers on the path to the bad boxes not present on the path to the good boxes?
Is the bad box experiencing high CPU load?
I used tcpdump and suprisingly the server actually sends the contents of multiple packets as one packet to the bad boxes (one header followed by 4-5 numbers of dumb-increment). To the good boxes it sent mostly everything as a separate packet, except for the first few numbers.
I don’t have any good ideas what exactly the problem could be, but I don’t have any experience with network programming. Maybe you have an idea what could cause this to happen. Obviously the server somehow decides how often it should send packets to certain clients.
Also, the bad boxes don’t have particularly high CPU load, and the network does not matter since one machine acts the same way regardless of how and where it is connected to the internet. I don’t use any proxies.
Apparently some Windows machines don’t send the TCP response immediately (about 0.3secs later). By default send() waits till it gets the response for the previous packet.
So I made it always send the data immediately. After the setsockopt that sets SO_REUSEADDR in libwebsockets.c, I added (value=1):
setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &value, sizeof(value));
I’m not sure if this is the cleanest way to fix it or the timeout should simply be lowered. At least it works for now.
Hey thanks for tracking it down and reporting it. I looked at TCP_NODELAY and it seems widely used in these situations to stop exactly what you were seeing.
I added TCP_NODELAY to client and server sockets in this commit:
http://git.warmcat.com/cgi-bin/cgit/libwebsockets/commit/?id=6c9395529ee6f5c4cc4d4a5e47c211ec7ad61644
You might want to initialize “len” in line 1085:
root@sheevaplug:~/download/libwebsockets# make
make all-recursive
make[1]: Entering directory `/root/download/libwebsockets’
Making all in lib
make[2]: Entering directory `/root/download/libwebsockets/lib’
/bin/bash ../libtool –tag=CC –mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -rdynamic -fPIC -Wall -Werror -std=gnu99 -pedantic -c -DDATADIR=\”/usr/local/share\” -DLWS_OPENSSL_CLIENT_CERTS=\”/etc/pki/tls/certs/\” -g -O2 -MT libwebsockets_la-libwebsockets.lo -MD -MP -MF .deps/libwebsockets_la-libwebsockets.Tpo -c -o libwebsockets_la-libwebsockets.lo `test -f ‘libwebsockets.c’ || echo ‘./’`libwebsockets.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -rdynamic -fPIC -Wall -Werror -std=gnu99 -pedantic -c -DDATADIR=\”/usr/local/share\” -DLWS_OPENSSL_CLIENT_CERTS=\”/etc/pki/tls/certs/\” -g -O2 -MT libwebsockets_la-libwebsockets.lo -MD -MP -MF .deps/libwebsockets_la-libwebsockets.Tpo -c libwebsockets.c -fPIC -DPIC -o .libs/libwebsockets_la-libwebsockets.o
cc1: warnings being treated as errors
libwebsockets.c: In function ‘lws_client_interpret_server_handshake’:
libwebsockets.c:1085: error: ‘len’ may be used uninitialized in this function
make[2]: *** [libwebsockets_la-libwebsockets.lo] Error 1
make[2]: Leaving directory `/root/download/libwebsockets/lib’
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/root/download/libwebsockets’
make: *** [all] Error 2
Wow thanks for pointing it out… I work with pedantic and -Wall -Werror but still Fedora Rawhide gcc –>
$ gcc –version
gcc (GCC) 4.6.0 20110603 (Red Hat 4.6.0-10)
did not find that one.
I pushed a fix to git.
Does it run on the Mac with forking enabled but without prctl?
Do you have any plans to update this to v10 of the WebSockets protocol? Chrome is dropping support for less than 10. I find it really useful but my app no longer works on the dev channel of chrome and it is only a matter of time before it will break on the beta and stable channels too. For more information see http://blog.chromium.org/2011/08/new-websocket-protocol-secure-and.html and http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10