BT

How HTML5 Web Sockets Interact With Proxy Servers

Posted by Peter Lubbers on Mar 16, 2010 |

With the recent explosion of WebSocket server implementations, a lot of questions have come up about how HTML5 Web Sockets deal with proxy servers, firewalls, and load-balancing routers. Will proxy servers automatically kill WebSocket connections? Do HTML5 Web Sockets handle firewalls and proxy server issues better than Comet? Are Web Sockets the silver bullet in seamless proxy server traversal? In this article, I’ll explain how HTML5 Web Sockets interact with proxy servers, load balancing routers, and firewalls. Additionally, I’ll explain how Kaazing WebSocket Gateway and its Web Socket emulation can add additional value.

About HTML5 Web Sockets and Proxy Servers

Let's start with some basic concepts: what exactly are HTML5 Web Sockets and proxy servers?

HTML5 Web Sockets

The HTML5 Web Sockets specification defines the Web Sockets API that enables web pages to use the Web Socket protocol for full-duplex communication with a remote host. It introduces the WebSocket interface and defines a full-duplex communication channel that operates through a single socket over the Web. HTML5 Web Sockets effectively provide a socket connection over the Web with minimal overhead. This delivers an enormous reduction in unnecessary network traffic and latency compared to legacy polling and long-polling (Comet) solutions that are often used to push real-time data to clients or even simulate a full-duplex connection by maintaining two HTTP connections.

To use HTML5 Web Sockets to connect from a Web client to a remote end-point, you create a new WebSocket instance and provide it with the URL that represents the end-point to which you want to connect. The specification defines a ws:// and a wss:// scheme to indicate WebSocket and WebSocket Secure connections, respectively. A WebSocket connection is established by upgrading from the HTTP protocol to the Web Socket protocol during the initial handshake between the client and the server, over the same underlying TCP/IP connection.

Proxy Servers

A proxy server is a server that acts as an intermediary between a client and another server (for example, a web server on the Internet). Proxy servers are commonly used for content caching, Internet connectivity, security, and enterprise content filtering. Typically, a proxy server is set up between a private network and the Internet. Proxy servers can monitor traffic and close a connection if it has been is open for too long. The problem with proxy servers for web applications that have a long-lived connection (for example, Comet HTTP streaming or HTML5 Web Sockets) is clear: HTTP proxy servers — which were originally designed for document transfer — may choose to close streaming or idle WebSocket connections, because they appear to be trying to connect with an unresponsive HTTP server. This behavior is a problem with long-lived connections such as Web Sockets. Additionally, proxy servers may also buffer unencrypted HTTP responses, thereby introducing unpredictable latency during HTTP response streaming.

HTML5 Web Sockets and Proxy Servers

Let's take a look at how HTML5 Web Sockets work with proxy servers. WebSocket connections use standard HTTP ports (80 and 443), which has prompted many to call it a "proxy server and firewall-friendly protocol." Therefore, HTML5 Web Sockets do not require new hardware to be installed, or new ports to be opened on corporate networks--two things that would stop the adoption of any new protocol dead in its tracks. Without any intermediary servers (proxy or reverse proxy servers, firewalls, load-balancing routers and so on) between the browser and the WebSocket server, a WebSocket connection can be established smoothly, as long as both the server and the client understand the Web Socket protocol. However, in real environments, lots of network traffic is routed through intermediary servers.

A picture is worth a thousand words. Figure 1 shows a simplified network topology in which clients use a browser to access back-end TCP-based services using a full-duplex HTML5 WebSocket connection. Some clients are located inside a corporate network, protected by a corporate firewall and configured to access the Internet through explicit, or known, proxy servers, which may provide content caching and security; while other clients access the WebSocket server directly over the Internet. In both cases, the client requests may be routed through transparent, or unknown, proxy servers (for example, a proxy server in a data center or a reverse proxy server in front of the remote server). It is even possible for proxy servers to have their own explicit proxy servers, increasing the number of hops the WebSocket traffic has to make.

WebSockets

Figure 1—Web Sockets architecture with explicit and transparent proxy servers

Unlike regular HTTP traffic, which uses a request/response protocol, WebSocket connections can remain open for a long time. Proxy servers may allow this and handle it gracefully, but they can also throw a monkey wrench in the works.

The WebSocket Upgrade

HTML5 Web Sockets use the HTTP Upgrade mechanism to upgrade to the Web Socket protocol. HTML5 Web Sockets feature an HTTP-compatible handshake so that HTTP servers can share their default HTTP and HTTPS ports (80 and 443) with a WebSocket server. To establish a WebSocket connection, the client and server upgrade from the HTTP protocol to the Web Socket protocol during an initial handshake, as shown in Example 1. Once established, WebSocket data frames can be sent back and forth between the client and the server in full-duplex mode.

Example 1—WebSocket upgrade handshake

Client to server:

GET /demo HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
WebSocket-Protocol: sample 

Server to client:

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://example.com
WebSocket-Location: ws://example.com/demo
WebSocket-Protocol: sample 

Unencrypted WebSocket Connections

The Web Socket protocol itself is unaware of proxy servers and firewalls; it just defines WebSocket upgrade handshake and the format for the WebSocket data frames. Let’s take a look at unencrypted WebSocket traffic in two proxy server scenarios (explicit and transparent).

Unencrypted WebSocket Connections and Explicit Proxy Servers

If a browser is configured to use an explicit proxy server then it will first issue the HTTP CONNECT method to that proxy server while establishing the WebSocket connection. For example, to connect to the server example.com using the ws:// scheme (typically over port 80), the browser client sends the HTTP CONNECT method shown in Example 2 to the proxy server.

Example 2—HTTP CONNECT method using port 80

CONNECT example.com:80 HTTP/1.1
Host: example.com 

When the explicit proxy server allows the CONNECT method, the WebSocket connection upgrade handshake can be made and when that handshake succeeds, WebSocket traffic can start flowing unimpeded through the proxy server.

Unencrypted WebSocket Connections and Transparent Proxy Servers

In case the unencrypted WebSocket traffic flows through a transparent proxy on its way to the WebSocket server, the connection is likely to fail in practice, since the browser does not issue the CONNECT method in this case. When a proxy server forwards a request to the (WebSocket) server, it is expected to strip off certain headers, including the Connection header. Therefore, a well-behaved transparent proxy server will cause the WebSocket upgrade handshake to fail almost immediately.

Not all proxy servers conform to the HTTP standard regarding expected proxy behavior. For example, some proxy servers are configured not to remove the Connection: Upgrade header and pass it on to the WebSocket server, which in turn sends the 101 Web Socket Protocol Handshake response. Problems then arise when the client or the server starts sending the first WebSocket frame. Since the frame does not resemble anything the proxy server might expect (such as regular HTTP traffic), some exception will likely occur, unless the proxy server is specifically configured to handle WebSocket traffic.

Hop-by-Hop Upgrade

During the WebSocket handshake, the Connection: Upgrade header is sent to the WebSocket server. If the proxy server has to participate in the Upgrade mechanism, additional proxy server configuration would be required, because a hop-by-hop transport is used; the Upgrade sent from the proxy server to the browser is only good for that one hop, and the proxy server must send its own Upgrade header to handle the next hop from the proxy server to the WebSocket server (or to yet another intermediary server). In addition the proxy server must stop processing the request as HTTP.

Today, most transparent proxy servers will not yet be familiar with the Web Socket protocol and these proxy servers will be unable to support the Web Socket protocol. In the future, however, proxy servers will likely become Web Sockets-aware and able to properly handle and forward WebSocket traffic.

Encrypted WebSocket Connections

Now, let’s take a look at encrypted WebSocket traffic in two proxy server scenarios (explicit and transparent).

Encrypted WebSocket Connections and Explicit Proxy Servers

If a browser is configured to use an explicit proxy server then it will first issue an HTTP CONNECT method to that proxy server while establishing the WebSocket connection. For example, to connect to the server example.com using the wss:// scheme (typically over port 443), the browser client sends the HTTP CONNECT method shown in Example 3 to the proxy server.

Example 3—HTTP CONNECT method using port 443

CONNECT example.com:443 HTTP/1.1
Host: example.com 

When the explicit proxy server allows the CONNECT method, the TLS handshake is sent, followed by the WebSocket connection upgrade handshake. After those handshakes succeed, WebSocket traffic can start flowing unimpeded through the proxy server. HTTPS (HTTP over TLS) work the same way; the use of encryption typically triggers the HTTP CONNECT method.

Encrypted WebSocket Connections and Transparent Proxy Servers

In the case of transparent proxy servers, the browser is unaware of the proxy server, so no HTTP CONNECT method is sent. However, since the wire traffic is encrypted, intermediate transparent proxy servers may simply allow the encrypted traffic through, so there is a much better chance that the WebSocket connection will succeed if Web Sockets Secure is used. Therefore, it is always best to use Web Sockets Secure with TLS encryption to connect to a WebSocket server, unless you're absolutely certain there are no intermediaries. While this has the added benefit of being more secure, TLS encryption does increase CPU consumption on both the client and the server, although this is usually not a dramatic increase and with hardware SSL/TLS acceleration, it can be reduced to near-zero.

Let's recap. Figure 2 shows the decisions that are made during the setup of a WebSocket connection between the browser and the WebSocket server. The figure shows the different connections scenarios in both the WebSocket (ws://) and WebSocket Secure (wss://) cases with explicit and transparent proxy servers.

WebSockets

Figure 2—Proxy server traversal decision tree

Figure 2 shows how using unencrypted WebSocket connections are more likely to fail in all but the simplest network topologies. It all comes down to understanding the end-to-end network topology you are deploying your WebSocket application in. Some HTTP proxy servers may restrict ports or allow access only to specific, authorized servers. A WebSocket server that is used in such a scenario must be added to the white list of servers for connections to be successful. Typically, the decision about which protocol (ws:// or wss://) to use to connect with has to be made up front by the client developer and is also based on the privacy characteristics of the WebSocket wire traffic. In the future, WebSocket gateways and servers may even be able to dynamically upgrade to Web Sockets Secure if an uncooperative proxy server is detected.

Kaazing WebSocket Gateway and Proxy Servers

Kaazing WebSocket Gateway features Web Socket emulation that makes Web Sockets available in all browsers, including those that don’t support Web Sockets. This emulation works in a pure JavaScript environment, without plugins, but also features Kaazing’s unique Opportunistic Optimization™ technology that ensures the best possible connection environment, whether or not clients and intermediate proxy servers support the latest protocols.

For example: If Kaazing WebSocket Gateway detects the presence of the Flash plugin, client libraries can take advantage of the single (Flash) TCP socket connection and if a direct connection is not possible (for example, if communication must flow through a firewall or an HTTP proxy server), then client libraries can still take advantage of the Flash runtime, minimizing the client's memory profile.

If intermediate proxy servers lie between Kaazing WebSocket Gateway and a client, then a highly optimized encrypted streaming connection is used and the proxy-server-aware gateway automatically redirects the HTTP request so that it uses an encrypted HTTP (HTTPS) connection to make the proxy server agnostic to the streaming nature of the downstream HTTP traffic. In a production environment it would be anticipated that HTTPS streaming can be used as a worst-case scenario to fall back to. However, for this to work the Gateway has to be configured with a suitable certificate for TLS encryption. Without that (this should be considered a configuration error), Kaazing will fall back to an advanced non-streaming implementation.

Kaazing’s Web Socket emulation is highly optimized and will easily outperform most legacy Comet solutions, because it can guarantee minimal latency by falling back to HTTPS streaming, thanks to Kaazing’s underlying support for cross-origin HTTP and HTTPS requests. Note that the different fall-back scenarios are only used in emulated mode. One major benefit of using Kaazing WebSocket Gateway and its Web Socket emulation is that you can code applications against the HTML5 Web Sockets standard, today, and these applications will work in all browsers.

Load-Balancing Routers and Firewalls

This section describes how HTML5 Web Sockets work with load-balancing routers and firewalls. Additionally, it explains how Kaazing WebSocket Gateway can add additional value.

HTML5 Web Sockets and Load-Balancing Routers

For this discussion, let's distinguish between two different kinds of load-balancing routers:

Ø TCP (Layer-4) load-balancing routers should work well with HTML5 Web Sockets, because they have the same connection profile: connect once up front and stay connected, rather than the HTTP document transfer request-response profile.

Ø HTTP (Layer-7) load-balancing routers expect HTTP traffic and can easily get confused by WebSocket upgrade traffic. For that reason, Layer 7 load balancing routers may need to be configured to be explicitly aware of WebSocket traffic.

HTML5 Web Sockets and Firewalls

Since firewalls normally just enforce the rules for inbound traffic rejection and outbound traffic routing (for example, through the proxy server), there are usually no specific WebSocket traffic-related firewall concerns.

Kaazing Websocket Gateway and Load-Balancing Routers

Layer-7 load-balancing routers may be confused by WebSocket protocol upgrade requests when they are placed in the critical path between a browser and multiple WebSocket servers. For this reason, services running on Kaazing WebSocket Gateway support peer load balancer awareness, which allows the load-balancing router to be configured as a peer next to WebSocket servers. This way, the load-balancing router handles only the initial client requests and discovers the best active gateway instance to route traffic to.

Once the load-balancing router has chosen a gateway instance, the gateway instance can then redirect the browser to connect directly to that active gateway instance. This means that the load-balancing router stays out of the way of the actual WebSocket traffic, thus reducing latency. In case of a hardware failure or network error, however, the clients will auto-reconnect to the load-balancing router, which automatically forwards those requests to another active Kaazing Gateway instance.

Comet and Proxy Servers

Finally, let’s take a look at how Comet deals with proxy servers. Since there is no Comet standard as such, let’s distinguish between two types of Comet implementations: long-polling and streaming.

Ø Long-polling, provided it is implemented in a robust way, will not suffer from too many proxy server issues, because it is still just using the HTTP request and response model. However, each request and response carries with it lots of unnecessary HTTP header overhead and latency. This is where HTML5 Web Sockets really shine — it can provide up to a 1000:1 reduction in unnecessary network traffic and reduce latency.

See also: our orange paper Web Sockets — a Quantum Leap in Scalability for the Web provides a detailed analysis of the dramatic reduction in unnecessary network traffic that HTML5 Web Sockets provide over legacy Comet solutions.

Ø Streaming is often a lot more efficient than long-polling, because it keeps the response open on the server and sends only the essential data to the client over the open connection. However, this approach suffers from the aforementioned proxy server issues. For example, a proxy server may be buffering the response and cause latency. Alternatively, the proxy server may be configured to disconnect HTTP connections that are kept open for a certain amount of time. This is why most legacy Comet solutions simply use long-polling.

Summary

While the HTML5 Web Socket protocol itself is unaware of proxy servers and firewalls, it features an HTTP-compatible handshake so that HTTP servers can share their default HTTP and HTTPS ports (80 and 443) with a WebSocket server. Some proxy servers are harmless and work fine with Web Sockets; others will prevent Web Sockets from working correctly, causing the connection to fail. In some cases additional proxy server configuration may be required, and certain proxy servers may need to be upgraded to support Web Sockets.

If a browser is configured to use an explicit proxy server (for both encrypted and unencrypted WebSocket connections) then it will first issue an HTTP CONNECT method to that proxy server while establishing the WebSocket connection.

If an unencrypted WebSocket connection (ws://) is used, then in the case of transparent proxy servers, the browser is unaware of the proxy server, so no HTTP CONNECT is sent. As a result, the connection is almost likely to fail in practice today.

If an encrypted WebSocket Secure connection (wss://) is used, then in the case of transparent proxy servers, the browser is unaware of the proxy server, so no HTTP CONNECT is sent. However, since the wire traffic is encrypted, intermediate transparent proxy servers may simply allow the encrypted traffic through, so there is a much better chance that the WebSocket connection will succeed if an encrypted WebSocket connection is used.

Kaazing WebSocket Gateway is a highly optimized, proxy-aware WebSocket gateway, which provides native WebSocket support as well as Web Socket emulation for older browsers. If intermediate proxy servers are detected, then a highly optimized encrypted streaming connection is used for the downstream HTTP traffic. This is made possible by Kaazing's underlying support for cross-origin HTTP and HTTPS requests. In the field, we have been able to establish a WebSocket connection — either native or emulated — to the Kaazing WebSocket Gateway 100% of the time.

About the Author

Peter Lubbers is the Director of Documentation and Training at Kaazing where he oversees all aspects of documentation and training. Peter is the co-author of the Apress book Pro HTML5 Programming and teaches HTML5 training courses. An HTML5 and WebSocket enthusiast, Peter frequently speaks at international events.

Prior to joining Kaazing, Peter worked as an information architect at Oracle, where he wrote many books, such as the award-winning Oracle Application Server Portal Configuration Guide and the Oracle Application Server Developer's Guide for Microsoft Office. Peter also develops documentation automation solutions and two of his inventions are patented.

Before joining Oracle, Peter architected and developed the internationalized Microsoft Office User Specialist Testing Framework. Peter was also a technical reviewer for the book "Pro JSF and Ajax: Building Rich Internet Components" (Apress, 2006).

Hello stranger!

You need to Register an InfoQ account or to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Proxies and WebSocket/Comet by Martin Tyler

Finally an article about WebSocket that doesn't overlook these issues with proxies etc. Some good information here.

With your 'Failure/Success?' paths in the decision tree have you managed to do much real world testing to know the outcome or is it based on theory?

One thing I don't understand is your stance on Comet. You seem to want to distance Kaazing from Comet, despite the fact that your WebSocket emulation is surely Comet. More than this though, WebSocket itself is also Comet since Comet is just a paradigm, not a any specific transport mechanism.

Re: Proxies and WebSocket/Comet by Mihai Rotaru

I agree with Martin on the fact the article tries to create an artificial distinction between Comet and WebSocket. WebSocket is just an interface for a Comet implementation for the large majority of the existing browsers.

I don't try to defend Comet as I think it is not a very well established term. But trying to present WebSocket as something different from Comet is not totally correct.

Re: Proxies and WebSocket/Comet by Peter Lubbers

Martin:
Thanks for the kind words. The Success/Fail paths are based on quite a bit of testing and deployment in the real world. The bottom line is that it is best to use WebSocket Secure and, surprisingly, the encryption does not add all that much extra overhead. We have actually seen things speed up in some scenarios.

I don't agree with you (and Mihai) when you say that WebSocket is the same as Comet. Here is how I see it:

Comet is a programming model that allows a web server to push data to a browser. This is often achieved through a long-held HTTP request, but there really is no standard or specification for Comet; it is just an umbrella term for all the different ways that can be used to achieve this.

WebSocket, on the other hand, is a well-defined API and protocol that allows for full-duplex, bidirectional communication (not just server push).

Finally, to your point about the WebSocket emulation, you're right, when WebSocket is not natively available, the Kaazing WebSocket Gateway emulates WebSocket using what is available in the browser and often it will use a highly optimized encrypted streaming connection for traffic from the server to the client, especially if it detects proxy servers. This is still better than other Comet solutions though, because those simply use (or fall back to) long-polling. Using this has the additional benefit that developers can start coding against the HTML5 WebSocket API today and their code will work in all browsers.

Regards,
Peter

Re: Proxies and WebSocket/Comet by Mihai Rotaru

Peter,

It looks like only Google Chrome supports WebSocket API. Given this reality, any WebSocket server – including Kaazing WebSocket Gateway – necessarily emulates its API using different ad-hoc techniques for the major browsers. These techniques are generally called Comet as you also state.

Concerning the encrypted streaming you mention for pushing data via proxies and firewalls. Our Comet solution Migratory Push Server also supports encrypted streaming. You can see a live demo at www.migratory.ro

Regards,
Mihai

Re: Proxies and WebSocket/Comet by Peter Lubbers

Thanks Mihai,
I'd like to point out that most WebSocket servers don't try to provide emulation at all, so to access those, you would (today) need Chrome. (Safari, Firefox, and Opera will follow soon).

Apart from emulation, which needs to use whatever is available, there is a definite difference between (native) WebSocket and Comet: Comet is a unidirectional, half-duplex push solution (actually standardized with HTML5 Server-Sent Events and the EventSource API) whereas WebSocket is a bidirectional full-duplex solution.

Re: Proxies and WebSocket/Comet by Sidda Eraiah

Comet == a bunch of hacks to push data from a server to a webclient (no specifications, no standards)

HTML5 Websockets == a W3C specification (dev.w3.org/html5/websockets/), protocol specification worked on by IETF(tools.ietf.org/html/draft-hixie-thewebsocketpro...)

Comet has been a good learning experience leading up to the need for HTML5 Websockets, but it is on its death bed now. Thanks to Google, W3C and IETF we are now moving towards a sensible and a scalable solution to achieve pushing data from server to webclients in real-time.

On one side you have Google pushing for open standards and with its kick-ass browser implementing the same (other browser vendors don't have a choice but to follow, or should I say catchup). On the other side you have a practical solution with comet, stitched together with bandages.

What would you bet your money on? What would your customers bet their money on?

Re: Proxies and WebSocket/Comet by Mihai Rotaru

Sidda,

I hope that your optimistic prediction – that all the browsers will follow Google Chrome to support WebSocket API – will come true. I also hope that all the browsers already installed will be replaced with browsers supporting WebSocket API.

But what customer will deploy a real-time web technology that supports IE6, IE7, IE8, Firefox, Opera (including mobile version), and Safari (including iPhone) through a bunch of hacks == Comet? Do you consider Kaazing's support for these browsers an unreliable bunch of hacks?

We at Migratory Data Systems consider that Comet is an established and proven technology deployed in large production systems. For our technology Migratory Push Server we implemented guaranteed end-to-end message delivery that is rock-solid.

Mihai

Re: Proxies and WebSocket/Comet by Sidda Eraiah

Mihai,

Kaazing provides an easy path for customers to move from Comet programming to standards based HTML5 WebSocket programming. To provide maximum return on customers' investments in new applications based on HTML5 WebSocket API - Kaazing emulates HTML5 WebSocket API for older browsers so customers don't have to program against a different Comet like API separately. Kaazing's implementation of the HTML5 WebSocket API emulation is better than the competition - as independently verified by a customer. Kaazing also supports the new EventSource API in HTML5 specification, for those interested in doing Comet style data fetching (from server to client only).

Web applications of the future will need the full-duplex communication channel provided by HTML5 WebSocket. Google recently announced Quake II on HTML5 technology and it uses HTML5 WebSocket for bi-directional data. This is a wonderful example of applications to come in the future - standards based and scalable.

Regards,
Sidda

Re: Proxies and WebSocket/Comet by Martin Tyler

I still disagree - I can see why some people would like to make a clean break from 'Comet hacks' but the fact is, Comet is a paradigm of getting data pushed into a browser asynchronously - the method of doing that is not important. WebSocket is just a new, more standard, way of doing that.

WebSocket is Comet, Kaazing's fallback mechanisms are Comet - however much you want to dress them up.

As Mihai says, all these comet 'hacks' are being used in full production systems by some very big players.

Unless we could get to the point of everyone having WebSocket capable browsers (years away if ever) then you will always need to use a product that hides it away from you and implements fallback connection methods.


Anyway, the reason I came back to this page was to link to this post on the hybi mailing list- www.ietf.org/mail-archive/web/hybi/current/msg0...

It shows some stats pulled together by Google on the success rate of WebSocket. It shows that even if you have a new browser, you could still have problems - the proxy issue.

Re: Proxies and WebSocket/Comet by Martin Tyler

I think I have commented on the bidirection/unidirectional argument before. The only reason that Comet focusses on server to client push is because client to server push has always been possible! Read the original article that gave Comet its name, it has arrows going in both directions. WebSocket isn't bringing any new functionality to Comet - all decent Comet implementations are bidirectional - WebSocket is just a better transport (in SOME scenarios)

Browser proxy server settings and client IP by Nizzy G

Hi Peter,

I was in HTML5 Dev Conf in SFO a week ago. I talked to Kaazing people there. I got interested in looking at HTML5 WebSocket implementation. Before, I used Flash to make socket connections and was able to by-pass the proxy settings of the browsers. I manually set my browser proxy settings with SOCKS v5 and was able to surf like that but at the same time, I was able to make socket connection through Flash. However, HTML5 does not allow me make a socket connection while the proxy setting is on in my FireFox. Is this normal by the new HTML5 WebSocket?

Second question: I was able to capture the client IP with Flash socket, but not with HTML5 WebSocket. How can I get the client IP?

Thanks Peter.
Niz

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

11 Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2013 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT