org.acplt.oncrpc

## Class OncRpcHttpClient

- java.lang.Object
- - org.acplt.oncrpc.OncRpcClient
  - - org.acplt.oncrpc.OncRpcHttpClient

    public class OncRpcHttpClient
    extends OncRpcClient

ONC/RPC client which communicates with ONC/RPC servers over the network using the ISO/OSI level 7 application protocol HTTP as a tunnel.

Please note that currently no standard exists about how to tunnel XDR data over HTTP connections. There are a few solutions out there, but they are more or less incompatible due to the lack of an RFC. So I'm now adding yet another proprietary solution.

The protocol which is used here is rather simple and tries to be compatible with as much firewall systems as possible. For this to achieve, both the ONC/RPC calls as well as their replies are first base64 encoded, before they are sent through the tunnel. This way, calls and replies appear to be ordinary text documents of mime type "text/plain".

Calls will appear to be something like this, carrying redirection information. Note that we do not include ONC/RPC call information in the header section, as this is already included in the ONC/RPC call itself. So including it in the header would just make it easier to play games with the header.

         CALL host name:port protocol TEA/1<CR><LF>
         B0D0EADSDEADBEEF...<CR><LF>
         ...<CR><LF>
         DEADBE==<CR><LF>

Replies do not carry the redirection head, but only the base64 encoded data of the ONC/RPC reply:

         B0D0EADSDEADBEEF...<CR><LF>
         ...<CR><LF>
         DEADBE==<CR><LF>

The decoding from the base64 encoded data is carried out by the `XdrHttpDecodingStream` class.

I'm not using eecks-emm-ell on purpose (net yet). While it is surely fun to play with and it has its merits, just to create yet another RPC tunnel parsing XML is still too large an overhead to accept. Despite cynics pointing out that the Internet is already that slow so that XML overhead will not be visible at all, I nevertheless disagree. On the other hand, XML would be really fine to be misused for yet another proprietary and misguided ASCII, pardon UTF-8, data format...

         <?xml version="1.0"?>
         <!DOCTYPE oncrpc-call SYSTEM "oncrpc-call.dtd">
         <oncrpc-call server="foo.bar.com" protocol="tcp">
             B0D0EADSDEADBEEF...<CR><LF>
             ...<CR><LF>
             DEADBE==<CR><LF>
         </oncrpc-call>

The answer then could be represented as follows:

         <?xml version="1.0"?>
         <!DOCTYPE oncrpc-reply SYSTEM "oncrpc-reply.dtd">
         <oncrpc-reply>
             B0D0EADSDEADBEEF...<CR><LF>
             ...<CR><LF>
             DEADBE==<CR><LF>
         </oncrpc-reply>

So it should be fairly easy to switch over to XML if someone will insist on it. Reminds me of my Xmas lecture about "Internet Technologies -- Sacred Land of the Automation Industry?"...

Version:
  $Revision: 1.5 $ $Date: 2005/11/11 21:18:43 $ $State: Exp $ $Locker: $
Author:
  Harald Albrecht
See Also:
  `XdrHttpDecodingStream`, `HttpClientConnection`

### Field Summary

Fields
`private java.lang.String` `cgiHandlerPath` Path of cgi program redirecting ONC/RPC calls to the appropriate ONC/RPC servers.
`private java.lang.String` `hostname` DNS name of host where to contact HTTP server.
`private HttpClientConnection` `httpClient` The HTTP client responsible for handling the HTTP connection.
`private int` `httpPort` Port number where the HTTP server can be contacted.
`private java.lang.String` `oncrpcHostname` DNS name of ONC/RPC server receiving the calls.
`private int` `oncrpcProtocol` Transport protocol to be used by the other end of the tunnel to contact the ONC/RPC server.
`private XdrHttpDecodingStream` `receivingXdr` XDR decoding stream used when receiving replies via an HTTP tunnel from an ONC/RPC server.
`private XdrBufferEncodingStream` `sendingXdr` FIXME: use the right encoding stream! XDR encoding stream used for sending requests via UDP/IP to an ONC/RPC server.

### Fields inherited from class org.acplt.oncrpc.OncRpcClient

`auth, host, port, program, timeout, version, xid`

### Constructor Summary

Constructors
Constructor and Description
`OncRpcHttpClient(java.lang.String hostname, int httpPort, java.lang.String cgiHandlerPath, java.lang.String oncrpcHostname, int program, int version, int port, int protocol)` Constructs a new `OncRpcHttpClient` object, which connects to the ONC/RPC server at `host` for calling remote procedures of the given { program, version }.
`OncRpcHttpClient(java.lang.String hostname, java.lang.String cgiHandlerPath, java.lang.String oncrpcHostname, int program, int version, int port)` Constructs a new `OncRpcHttpClient` object, which connects to the ONC/RPC server at `host` for calling remote procedures of the given { program, version }.
`OncRpcHttpClient(java.lang.String hostname, java.lang.String cgiHandlerPath, java.lang.String oncrpcHostname, int program, int version, int port, int protocol)` Constructs a new `OncRpcHttpClient` object, which connects to the ONC/RPC server at `host` for calling remote procedures of the given { program, version }.

### Method Summary

Methods
`void` `call(int procedureNumber, int versionNumber, XdrAble params, XdrAble result)` Calls a remote procedure on an ONC/RPC server.
`void` `close()` Close the connection to an ONC/RPC server and free all network-related resources.
`java.lang.String` `getCharacterEncoding()` Get the character encoding for (de-)serializing strings.
`java.lang.String` `getHostname()` Returns the host name of the HTTP server we are connected to.
`int` `getHttpPort()` Returns the port of the HTTP server we are connected to.
`void` `setCharacterEncoding(java.lang.String characterEncoding)` Set the character encoding for (de-)serializing strings.

### Methods inherited from class org.acplt.oncrpc.OncRpcClient

`call, getAuth, getHost, getPort, getProgram, getTimeout, getVersion, newOncRpcClient, newOncRpcClient, nextXid, setAuth, setTimeout`

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

### Field Detail

#### hostname

    private java.lang.String hostname

DNS name of host where to contact HTTP server. Note that we can not use an `InetAddress` here as we have to support virtual hosting, where several DNS names share the same IP address.

#### httpPort

    private int httpPort

Port number where the HTTP server can be contacted.

#### cgiHandlerPath

    private java.lang.String cgiHandlerPath

Path of cgi program redirecting ONC/RPC calls to the appropriate ONC/RPC servers.

#### oncrpcHostname

    private java.lang.String oncrpcHostname

DNS name of ONC/RPC server receiving the calls.

#### oncrpcProtocol

    private int oncrpcProtocol

Transport protocol to be used by the other end of the tunnel to contact the ONC/RPC server.

#### httpClient

    private HttpClientConnection httpClient

The HTTP client responsible for handling the HTTP connection. It is a classic example of delegation, isn't it?

#### sendingXdr

    private XdrBufferEncodingStream sendingXdr

FIXME: use the right encoding stream! XDR encoding stream used for sending requests via UDP/IP to an ONC/RPC server.

#### receivingXdr

    private XdrHttpDecodingStream receivingXdr

XDR decoding stream used when receiving replies via an HTTP tunnel from an ONC/RPC server.

### Constructor Detail

#### OncRpcHttpClient

    public OncRpcHttpClient(java.lang.String hostname,
                    java.lang.String cgiHandlerPath,
                    java.lang.String oncrpcHostname,
                    int program,
                    int version,
                    int port)
                     throws OncRpcException,
                            java.io.IOException

Constructs a new `OncRpcHttpClient` object, which connects to the ONC/RPC server at `host` for calling remote procedures of the given { program, version }. At the other end of the HTTP tunnel, TCP/IP is used to call the ONC/RPC server.

Note that the HTTP connection is not build before the first ONC/RPC call is done through the `call(int, int, org.acplt.oncrpc.XdrAble, org.acplt.oncrpc.XdrAble)` method. The HTTP client tries to keep the connection alive but reconnects if necessary. Nevertheless, as it signals all failures, the caller has to handle reconnect situations -- but this is easy to achieve.

Parameters:
  `hostname` - The DNS name of the host where the ONC/RPC server resides.
  `cgiHandlerPath` - The path to the CGI Handler which will redirect ONC/RPC calls to the particular ONC/RPC servers.
  `oncrpcHostname` - The DNS name of the ONC/RPC server to contact.
  `program` - Program number of the ONC/RPC server to call.
  `version` - Program version number.
  `port` - The port number where the ONC/RPC server can be contacted. If `0`, then the other end of the HTTP tunnel will try to ask the portmapper at `host` for the port number.
Throws:
  `OncRpcException` - if an ONC/RPC error occurs.
  `java.io.IOException` - if an I/O error occurs.

#### OncRpcHttpClient

    public OncRpcHttpClient(java.lang.String hostname,
                    java.lang.String cgiHandlerPath,
                    java.lang.String oncrpcHostname,
                    int program,
                    int version,
                    int port,
                    int protocol)
                     throws OncRpcException,
                            java.io.IOException

Constructs a new `OncRpcHttpClient` object, which connects to the ONC/RPC server at `host` for calling remote procedures of the given { program, version }.

Note that the HTTP connection is not build before the first ONC/RPC call is done through the `call(int, int, org.acplt.oncrpc.XdrAble, org.acplt.oncrpc.XdrAble)` method. The HTTP client tries to keep the connection alive but reconnects if necessary. Nevertheless, as it signals all failures, the caller has to handle reconnect situations -- but this is easy to achieve.

Parameters:
  `hostname` - The DNS name of the host where the ONC/RPC server resides.
  `cgiHandlerPath` - The path to the CGI Handler which will redirect ONC/RPC calls to the particular ONC/RPC servers.
  `oncrpcHostname` - The DNS name of the ONC/RPC server to contact.
  `program` - Program number of the ONC/RPC server to call.
  `version` - Program version number.
  `port` - The port number where the ONC/RPC server can be contacted. If `0`, then the other end of the HTTP tunnel will try to ask the portmapper at `host` for the port number.
  `protocol` - Transport protocol to be used by the other end of the tunnel to call the ONC/RPC server.
Throws:
  `OncRpcException` - if an ONC/RPC error occurs.
  `java.io.IOException` - if an I/O error occurs.

#### OncRpcHttpClient

    public OncRpcHttpClient(java.lang.String hostname,
                    int httpPort,
                    java.lang.String cgiHandlerPath,
                    java.lang.String oncrpcHostname,
                    int program,
                    int version,
                    int port,
                    int protocol)
                     throws OncRpcException,
                            java.io.IOException

Constructs a new `OncRpcHttpClient` object, which connects to the ONC/RPC server at `host` for calling remote procedures of the given { program, version }.

Note that the HTTP connection is not build before the first ONC/RPC call is done through the `call(int, int, org.acplt.oncrpc.XdrAble, org.acplt.oncrpc.XdrAble)` method. The HTTP client tries to keep the connection alive but reconnects if necessary. Nevertheless, as it signals all failures, the caller has to handle reconnect situations -- but this is easy to achieve.

Parameters:
  `hostname` - The DNS name of the host where the ONC/RPC server resides.
  `httpPort` - The port number where the HTTP server is to be contacted.
  `cgiHandlerPath` - The path to the CGI Handler which will redirect ONC/RPC calls to the particular ONC/RPC servers.
  `oncrpcHostname` - The DNS name of the ONC/RPC server to contact.
  `program` - Program number of the ONC/RPC server to call.
  `version` - Program version number.
  `port` - The port number where the ONC/RPC server can be contacted. If `0`, then the other end of the HTTP tunnel will try to ask the portmapper at `host` for the port number.
  `protocol` - Transport protocol to be used by the other end of the tunnel to call the ONC/RPC server.
Throws:
  `OncRpcException` - if an ONC/RPC error occurs.
  `java.io.IOException` - if an I/O error occurs.

### Method Detail

#### close

    public void close()
               throws OncRpcException

Close the connection to an ONC/RPC server and free all network-related resources. Well -- at least hope, that the Java VM will sometimes free some resources. Sigh.

Overrides:
  `close` in class `OncRpcClient`
Throws:
  `OncRpcException` - if an ONC/RPC error occurs.

#### call

    public void call(int procedureNumber,
            int versionNumber,
            XdrAble params,
            XdrAble result)
              throws OncRpcException

Calls a remote procedure on an ONC/RPC server.

FIXME: timeout control?

Specified by:
  `call` in class `OncRpcClient`
Parameters:
  `procedureNumber` - Procedure number of the procedure to call.
  `versionNumber` - Protocol version number.
  `params` - The parameters of the procedure to call, contained in an object which implements the `XdrAble` interface.
  `result` - The object receiving the result of the procedure call.
Throws:
  `OncRpcException` - if an ONC/RPC error occurs.

#### setCharacterEncoding

    public void setCharacterEncoding(java.lang.String characterEncoding)

Set the character encoding for (de-)serializing strings.

Specified by:
  `setCharacterEncoding` in class `OncRpcClient`
Parameters:
  `characterEncoding` - the encoding to use for (de-)serializing strings. If `null`, the system's default encoding is to be used.

#### getCharacterEncoding

    public java.lang.String getCharacterEncoding()

Get the character encoding for (de-)serializing strings.

Specified by:
  `getCharacterEncoding` in class `OncRpcClient`
Returns:
  the encoding currently used for (de-)serializing strings. If `null`, then the system's default encoding is used.

#### getHostname

    public java.lang.String getHostname()

Returns the host name of the HTTP server we are connected to.

Returns:
  host name.

#### getHttpPort

    public int getHttpPort()

Returns the port of the HTTP server we are connected to.

Returns:
  port number.