Package org.acplt.oncrpc.server

ONC/RPC Server support package.

See:
          Description

Interface Summary
OncRpcDispatchable Tags classes as being able to dispatch and handle ONC/RPC requests from clients.
 

Class Summary
OncRpcCallInformation Objects of class OncRpcCallInformation contain information about individual ONC/RPC calls.
OncRpcServerAcceptedCallMessage The OncRpcServerAcceptedCallMessage class represents (on the sender's side) an accepted ONC/RPC call.
OncRpcServerAuth The OncRpcServerAuth class is the base class and factory for handling all protocol issues of ONC/RPC authentication on the server side.
OncRpcServerAuthNone The OncRpcServerAuthNone class handles all protocol issues of the ONC/RPC authentication AUTH_NONE on the server side.
OncRpcServerAuthShort The OncRpcServerAuthShort class handles all protocol issues of the ONC/RPC authentication AUTH_SHORT on the server side.
OncRpcServerAuthUnix The OncRpcServerAuthNone class handles all protocol issues of the ONC/RPC authentication AUTH_UNIX on the server side.
OncRpcServerCallMessage The OncRpcServerCallMessage class represents an ONC/RPC call message on the server side.
OncRpcServerReplyMessage The OncRpcReplyMessage class represents an ONC/RPC reply message as defined by ONC/RPC in RFC 1831.
OncRpcServerStub The abstract OncRpcServerStub class is the base class to build ONC/RPC-program specific servers upon.
OncRpcServerTransport Instances of class OncRpcServerTransport encapsulate XDR streams of ONC/RPC servers.
OncRpcServerTransportRegistrationInfo The class OncRpcServerTransportRegistrationInfo holds information about (possibly multiple) registration of server transports for individual program and version numbers.
OncRpcTcpConnectionServerTransport Instances of class OncRpcTcpServerTransport encapsulate TCP/IP-based XDR streams of ONC/RPC servers.
OncRpcTcpServerTransport Instances of class OncRpcTcpServerTransport encapsulate TCP/IP-based XDR streams of ONC/RPC servers.
OncRpcUdpServerTransport Instances of class OncRpcUdpServerTransport encapsulate UDP/IP-based XDR streams of ONC/RPC servers.
 

Package org.acplt.oncrpc.server Description

ONC/RPC Server support package.

This package implements classes needed to write ONC/RPC servers according to Sun's ONC/RPC Remote Procedure Call specification (see RFC 1831, RFC 1832, RFC 1833).

Here is a short introduction to writing ONC/RPC servers. However, at the moment this might be not as convenient as you would like it to be, but rather low-level. Nevertheless, here are the basic steps to write a simple ONC/RPC server. Please also take a look at src/tests/org/acplt/oncrpc/ServerTest.java.

To implement an ONC/RPC server, you need to implement the OncRpcDispatchable interface. This requires implementing the dispatchOncRpcCall method, which handles incoming ONC/RPC calls. In the following code snippet we show how to handle the ping request (ONC/RPC procedure number 0):

public void dispatchOncRpcCall(OncRpcCallInformation call,
                               int program, int version, int procedure)
       throws OncRpcException, IOException {
    System.out.println("Incomming call for program "
                       + Integer.toHexString(program)
                       + "; version " + version
                       + "; procedure " + Integer.toHexString(procedure));
    switch ( procedure ) {
    //
    // Implement ping call...
    //
    case 0:
        call.retrieveCall(XdrVoid.XDR_VOID);
        call.reply(XdrVoid.XDR_VOID);
        break;
    //
    // For all unknown calls, send back an error reply.
    //
    default:
        call.failProcedureUnavailable();
    }
}

For every incoming ONC/RPC call, you'll receive some information about the call through the call parameter (of class OncRpcCallInformation). The call object is necessary to retrieve the parameters of the call as well as to sent back the reply. For the ping call (procedure number 0), the ONC/RPC dispatcher shown above simply retrieves the parameters using retrieveCall(XdrAble). Because the call expects no parameters, we supply the static void object XdrVoid.XDR_VOID to the retrieveCall method.

To send back the reply for the ping call, we use OncRpcCallInformation(XdrAble). Again, the caller does not expect any reply, so we specify the static void object XdrVoid.XDR_VOID once more. Then, we simply return and let the ONC/RPC magic sending back the reply.

In case we receive an ONC/RPC call for an unknown procedure (and / or version) we simply call the failProcedureUnavailable() method of the call object.

Now that we have solved the handling of ONC/RPC calls, we can now set up the stage, also known as an ONC/RPC server. To receive incoming calls, you first need to create so-called ONC/RPC server transports. In our example we will create one transport for each the UDP/IP and TCP/IP protocols. When creating a server transport, you need to specify in the call to the constructor:

OncRpcUdpServerTransport udpTrans =
    new OncRpcUdpServerTransport(this, 55555, 0x49679, 1, 8192);
OncRpcTcpServerTransport tcpTrans =
    new OncRpcTcpServerTransport(this, 55555, 0x49679, 1, 8192);

When you're ready, you should first register your ONC/RPC server with the (local) portmapper by calling the register() method on all server transports you created during the previous step. Then start listening on these transports by calling their listen() methods.

udpTrans.register();
tcpTrans.register();

tcpTrans.listen();
udpTrans.listen();

System.out.println("Server started.");

Note that the listen() methods will create new threads, which then will be responsible for handling incoming ONC/RPC calls. Note that you may need to make your ONC/RPC dispatch handler (OncRpcDispatchable) synchronized if you can not handle simultaneous calls from multiple threads at the same time.

The tricky part is stopping the server somehow. Unfortunately, this is not an easy issue on Java platforms and up to you. For an example, look at the source of the src/tests/org/acplt/oncrpc/ServerTest.java example. Basically, this example uses the ONC/RPC call 42 to shut down a server.

After you have received the shutdown notification you can shut down the server transports (for instance) from your main thread using the close() method:

tcpTrans.unregister();
tcpTrans.close();

udpTrans.unregister();
udpTrans.close();

System.out.println("Server shut down.");

You should also deregister your server from the portmapper at the same time you're closing the transports. Note that the OncRpcTcpServerTransport.close() method also closes all currently open TCP/IP transports which have been created to handle individual TCP/IP connections from individual clients.

Now that's basically all you need to know to write ONC/RPC servers. However, if you plan to mess with authentication, read on...

ONC/RPC authentication on the server side is done within the call dispatcher. Before executing an ONC/RPC call, first check the authentication object for kosher information:

public void dispatchOncRpcCall(OncRpcCallInformation call,
                               int program, int version, int procedure)
       throws OncRpcException, IOException {
    switch ( call.callMessage.auth.getAuthenticationType() )
    case OncRpcAuthType.ONCRPC_AUTH_UNIX:
        ...
        break;
    case OncRpcAuthType.ONCRPC_AUTH_SHORT:
        ...
        break;
    case OncRpcAuthType.ONCRPC_AUTH_NONE:
    default:
        throw(new OncRpcAuthenticationException(
                      OncRpcAuthStatus.ONCRPC_AUTH_BADCRED));
    }

The example above is a very restrictive one in that it even forbids ONC/RPC clients to ping the server without proper authentication.

In a more elaborate example below you can see how to handle authentication of type AUTH_UNIX. It also shows how to use shorthand credentials, if you like.

public void dispatchOncRpcCall(OncRpcCallInformation call,
                               int program, int version, int procedure)
       throws OncRpcException, IOException {
    switch ( call.callMessage.auth.getAuthenticationType() )
    case OncRpcAuthType.ONCRPC_AUTH_UNIX:
        OncRpcServerAuthUnix auth = (OncRpcServerAuthUnix) call.callMessage.auth;
        if ( (auth.uid != 42)
             && (auth.gid != 815) ) {
            throw(new OncRpcAuthenticationException(
                          OncRpcAuthStatus.ONCRPC_AUTH_BADCRED));
        }
        //
        // Suggest shorthand authentication...
        //
        XdrBufferEncodingStream xdr = new XdrBufferEncodingStream(8);
        xdr.beginEncoding(null, 0);
        xdr.xdrEncodeInt(42);
        xdr.xdrEncodeInt(~42);
        xdr.endEncoding();
        //
        // ATTENTION: this will return the *whole* buffer created by the
        // constructor of XdrBufferEncodingStream(len) above. So make sure
        // that you really want to return the whole buffer!
        //
        auth.setShorthandVerifier(xdr.getXdrData());
        break;

    case OncRpcAuthType.ONCRPC_AUTH_SHORT:
        //
        // Check shorthand credentials.
        //
        OncRpcServerAuthShort auth = (OncRpcServerAuthShort) call.callMessage.auth;
        XdrBufferDecodingStream xdr =
            new XdrBufferDecodingStream(auth.getShorthandCred());
        xdr.beginDecoding();
        int credv1 = xdr.xdrDecodeInt();
        int credv2 = xdr.xdrDecodeInt();
        xdr.endDecoding();
        if ( credv1 != ~credv2 ) {
            throw(new OncRpcAuthenticationException(
                          OncRpcAuthStatus.ONCRPC_AUTH_REJECTEDCRED));
        }
        if ( (++shorthandCredCounter % 3) == 0 ) {
            throw(new OncRpcAuthenticationException(
                          OncRpcAuthStatus.ONCRPC_AUTH_REJECTEDCRED));
        }
        break;

    case OncRpcAuthType.ONCRPC_AUTH_NONE:
        if ( procedure != 0 ) {
            throw(new OncRpcAuthenticationException(
                          OncRpcAuthStatus.ONCRPC_AUTH_BADCRED));
        }

    default:
        throw(new OncRpcAuthenticationException(
                      OncRpcAuthStatus.ONCRPC_AUTH_BADCRED));
    }
    
    switch ( procedure ) {
        ...
    }
}

This package is part of the ACPLT/KS ACPLTea Java Library package.

(c) 1999, 2006 Harald Albrecht.
(c) 1999 Lehrstuhl für Prozeßleittechnik, Aachen University of Technology, Germany.

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details.

You should have received a copy of the GNU Library General Public License along with this program (see the file COPYING.LIB for more details); if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.