Modifying the Tunneling Mechanism

try { OutputStream out = response.getOutputStream ; out.writebuffer; out.flush ; } catch IOException e { throw new ServletServerExceptionerror writi ng response; } } } There are three important points to notice about ServletForwarder . First, it uses sockets and streams to forward the body of the HTTP message to the RMI server and then simply pipes what the RMI server returns back into HttpServletResponse s output stream. There is no magical or mysterious code here, and HTTP tunneling involves nothing that you hadnt seen by the end of Chapt er 2 . The second important point is that ServletForwarder forwards the message without demarshalling the data or understanding the message at all. Even though the body of the HTTP request contains serialized instances of classes, ServletForwarder doesnt need to have the classes on its classpath or treat the serialized instances as anything other than bytes to be copied from one stream to another. This means that HTTP tunneling is easy to deploy and doesnt need to be updated as the application evolves. The final point is that, all tolled, this is really a simple piece of code that takes advantage of a lot of existing infrastructure. You can download the Apache web server available at ht t p: w w w .apache.or g , install the Tomcat servlet engine available at ht t p: j akar t a.apache.or g , and, in the course of an afternoon, circumvent a firewall that took experienced systems administrators months to configure and install.

22.5 Modifying the Tunneling Mechanism

The default RMI socket factory will automatically attempt to tunnel over HTTP when more straightforward ways of connecting fail. You dont need to change the server or the client code. Instead, you simply need to make sure that a third server, which forwards the requests, has been installed and everything is configured correctly. Since all the code for this server is readily available, you may think that using HTTP tunneling boils down to an exercise in configuring your application. For the most part, this is true. In many cases, using HTTP tunneling boils down to installing the software and making sure all the servers are available. However, sometimes you will need to modify the tunneling mechanism. At this point, it is helpful to observe that the HTTP tunneling mechanism naturally divides into three parts: The client Posts a request to the web server The servlet Forwards the request to the RMI servers socket, preserving the HTTP structure of the client post The server Automatically handles the HTTP post, in addition to ordinary JRMP commands These three parts can change independently. The client will automatically post to the web server if it cannot reach the RMI server directly. This will happen regardless of whether the servlet performing the tunneling is Suns implementation or a custom version you wrote. Similarly, the RMI server will accept either JRMP method invocations or HTTP posts, whether or not they came from a servlet doing HTTP tunneling on behalf of a client. You can use this fact to your advantage. For example, one of the big limitations of the default implementation of HTTP tunneling is that it assumes the RMI server is running on the same machine as the web server. This assumption is so basic to HTTP tunneling that it even effects the URL being used; a URL of the form http:cgi-binjava-rmi.cgi?forward=[portnumber] doesnt even include a destination server machine. A custom servlet that implements HTTP tunneling is free to forward the request to other machines. The change is simple: the connectToLocalServer method simply needs to replace InetAddress.getLocalHost with a more appropriate server machine. Replacing one line of code can allow messages to be forwarded to different servers running on different machines. The servlet can also look at the data it is forwarding. Instead of simply copying an instance of InputStream into an instance of OutputStream , it can examine the request and log which client requests which operations. Unfortunately, while its easy to change the forwarding mechanism, its hard to change either the client or the server. Itd be nice to be able to use SSL when connecting to the web server. However, in order to do that, you need to use a different socket factory entirely™and implementing HTTP tunneling is a fair amount of work.

22.6 The Bank via HTTP Tunneling