/*****************************************************************************/
/* File name: ParserResponder.java                                           */
/* Purpose: to parse a RPC message and to create a response UDP packet       */
/*          if needed                                                        */
/* Last modified: 10.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*                                                                           */
/* This program 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 General */
/* Public License for more details.                                          */
/*                                                                           */
/* This software is distributed under the terms                              */
/* of the GNU General Public License as published                            */
/* by the Free Software Foundation; either version 2, or (at your option)    */
/* any later version.                                                        */
/* See file COPYING for your rights (GNU GPL)                                */
/*****************************************************************************/

package rpc;


import java.net.*;
import java.io.*;
import java.util.*;
import io.*;


public
class

ParserResponder
{

  private final static String RCSID =
"$Header: /d/NFS/rpc/RCS/ParserResponder.java,v 1.9 1999/08/13 20:04:36 vklimov Exp $";

  protected io.UdpSocket udpSocket = null;
  protected FileOutputStream logFileOutputStream = null;
  protected BufferedOutputStream logBufferedOutputStream = null;
  protected Logable log = null;
  protected boolean logMessages = false;
  protected boolean logTransactions = false;
  public String cacheDir = null;


  public

  ParserResponder( int port,
                   java.lang.String propertiesFilePath )

                                                       throws SocketException
/*****************************************************************************/
/* Function name: ParserResponder                                            */
/* File name: ParserResponder.java                                           */
/* Purpose: constructor for the ParserResponder class                        */
/* Parameters: port                                                          */
/*             propertiesFilePath                                            */
/* Throws: SocketException                                                   */
/* Returns:                                                                  */
/* Last modified: 06.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      String logMessagesFlagString = null;
      String logTransactionsFlagString = null;
      String logFilePath = null;
      String timeZoneString = null;
      Properties properties = null;
      FileInputStream  propertiesFileInputStream = null;

                                                    /* ParserResponder */
/*---------------------------------------------------------------------------*/

      try
        {
          propertiesFileInputStream = new
            FileInputStream(
              propertiesFilePath );
          properties = new Properties();
          properties.load( propertiesFileInputStream );
          propertiesFileInputStream.close();

          timeZoneString =
            properties.
              getProperty(
                Constants.TIME_ZONE_PROPERTY );
          cacheDir =
            properties.
              getProperty(
                Constants.CACHE_DIR_PROPERTY );

          logTransactionsFlagString =
            properties.
              getProperty(
                Constants.LOG_TRANSACTIONS_FLAG_PROPERTY );
          logTransactionsFlagString =
            logTransactionsFlagString.toLowerCase();
          logMessagesFlagString =
            properties.
              getProperty(
                Constants.LOG_MESSAGES_FLAG_PROPERTY );
          logMessagesFlagString =
            logMessagesFlagString.toLowerCase();
          if ( (logMessagesFlagString == null) ||
               ( ! logMessagesFlagString.equals(
                     Constants.LOG_MESSAGES_FLAG_YES_STRING ) )
             )
            { /* don't log messages*/
            }
          else /* log messages*/
            {
              logMessages = true;
              logFilePath =
                properties.
                  getProperty(
                    Constants.LOG_MESSAGES_FILE_NAME_PROPERTY );
            }
        /*end of if*/

          if ( (logTransactionsFlagString == null) ||
               ( ! logTransactionsFlagString.equals(
                     Constants.LOG_MESSAGES_FLAG_YES_STRING ) )
             )
            { /* don't log transactions*/
            }
          else /* log transactions*/
            {
              logTransactions = true;
              logFilePath =
                properties.
                  getProperty(
                    Constants.LOG_MESSAGES_FILE_NAME_PROPERTY );
            }
        /*end of if*/

          if (logFilePath != null)
            {
              logFileOutputStream = new
                FileOutputStream( logFilePath,
                                  true         ); /* append */
              logBufferedOutputStream = new
                BufferedOutputStream( logFileOutputStream );

              log = (Logable) new
                LogToFile( (OutputStream) logBufferedOutputStream,
                           timeZoneString                          );
            }
          else
            ;
        /*end of if on logFilePath*/

        }
      catch( FileNotFoundException e )
        {
          System.out.println( "properties file " +
                              propertiesFilePath +
                              " not found"         );
        }
      catch( SecurityException e )
        {
          System.out.println( "SecurityException: " +
                              e.getMessage()          );
        }
      catch( IOException e )
        {
          System.out.println( "IOException: " +
                              e.getMessage()    );
        }
    /*end of try-catch*/

      udpSocket = new
        io.UdpSocket( port, log,
                      logMessages,
                      logTransactions );

    }
/*end of ParserResponder*/


  protected
  void

  finalize() throws Throwable
/*****************************************************************************/
/* Function name: finalize                                                   */
/* File name: ParserResponder.java                                           */
/* Purpose: to clean up                                                      */
/* Parameters:                                                               */
/* Throws: Throwable                                                         */
/* Returns:                                                                  */
/* Last modified: 11.07.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                            /* finalize */
/*---------------------------------------------------------------------------*/

      logFileOutputStream.close();
      logBufferedOutputStream.close();

    }
/*end of finalize*/


  public
  Message

  createRPCMessageAndPutSuccessPrefix(
    int ibufLength,
    ParserResponderReturnArguments
      parserResponderReturnArguments   )
/*****************************************************************************/
/* Function name: createRPCMessageAndPutSuccessPrefix                        */
/* File name: ParserResponder.java                                           */
/* Purpose: to create a new Message object and to fill it                    */
/*          with the success prefix                                          */
/* Parameters: ibufLength - length of the buffer to put the stuff into       */
/*             parserResponderReturnArguments                                */
/* Returns: the rpc Message object                                           */
/* Last modified: 18.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      byte[] ibuf = null;
      Message rpcMessage = null;
                                    /* createRPCMessageAndPutSuccessPrefix */
/*---------------------------------------------------------------------------*/

      ibuf = new byte[ ibufLength ];

      rpcMessage =
        new Message( ibuf );

      rpcMessage.
        putUnsignedInteger(
          parserResponderReturnArguments.
            transactionId                  );
      rpcMessage.
        putUnsignedInteger( (long) rpc.Constants.RPC_REPLY );
      rpcMessage.
        putUnsignedInteger( (long) rpc.Constants.MSG_ACCEPTED );

      rpcMessage.
        putEmptyOpaqueAuthentication();

      rpcMessage.
        putUnsignedInteger( (long)
          rpc.Constants.SUCCESS );

      return rpcMessage;

    }
/*end of createRPCMessageAndPutSuccessPrefix*/


  public
  void

  sendProcedureNullRPCReplyMessage(
    ParserResponderReturnArguments
      parserResponderReturnArguments    )
/*****************************************************************************/
/* Function name: sendProcedureNullRPCReplyMessage                           */
/* File name: ParserResponder.java                                           */
/* Purpose: to send RPC reply message: OK, null procedure, nothing done      */
/* Parameters: parserResponderReturnArguments                                */
/* Returns:                                                                  */
/* Last modified: 31.07.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      byte[] ibuf = null;
      InetAddress ipAddressWhereToSend = null;
      int portToSendTo = 0;
      DatagramPacket udpPacket = null;
      Message rpcMessage = null;
                                       /* sendProcedureNullRPCReplyMessage */
/*---------------------------------------------------------------------------*/

      if ( (logTransactions) &&
           (log != null)
         )
        {
          log.write( 
            "NFSPROC_NULL " +
            "transaction ID=" +
            parserResponderReturnArguments.
              transactionId                  );
        }
      else
        ;
    /*end of if*/

      rpcMessage =
        createRPCMessageAndPutSuccessPrefix(
          rpc.Constants.
            PROC_NULL_UDP_PACKET_DATA_LENGTH,
          parserResponderReturnArguments       );

      ibuf = rpcMessage.getData();

      ipAddressWhereToSend =
        parserResponderReturnArguments.
          inRPCMessage.getInetAddress();
      portToSendTo =
        parserResponderReturnArguments.
          inRPCMessage.getPort();

      udpPacket = new
        DatagramPacket( ibuf, ibuf.length,
                        ipAddressWhereToSend,
                        portToSendTo          );

      try
        {
          udpSocket.send( udpPacket,
                          parserResponderReturnArguments.transactionId,
                          "sendProcedureNullRPCReplyMessage" );
        }
      catch( IOException e )
        {
          System.out.println(
            "sendProcedureNullRPCReplyMessage: " +
            "IOException in sending reply\n" +
            e.getMessage()                              );
        }
    /*end of try-catch*/

    }
/*end of sendProcedureNullRPCReplyMessage*/


  public
  void

  sendProcedureUnavailableRPCReplyMessage(
    ParserResponderReturnArguments
      parserResponderReturnArguments,
    java.lang.String remoteProcedureName )
/*****************************************************************************/
/* Function name: sendProcedureUnavailableRPCReplyMessage                    */
/* File name: ParserResponder.java                                           */
/* Purpose: to send RPC reply message: the wanted procedure is not available */
/* Parameters: parserResponderReturnArguments                                */
/*             remoteProcedureName                                           */
/* Returns:                                                                  */
/* Last modified: 31.07.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      byte[] ibuf = null;
      int ilength = 0;
      InetAddress ipAddressWhereToSend = null;
      int portToSendTo = 0;
      DatagramPacket udpPacket = null;
      Message rpcMessageProgramUnavailable = null;
                                  /* sendProcedureUnavailableRPCReplyMessage */
/*---------------------------------------------------------------------------*/

      if ( (logTransactions) &&
           (log != null)
         )
        {
          log.write( 
            "sendProcedureNullRPCReplyMessage: " +
            remoteProcedureName +
            " transaction ID=" +
            parserResponderReturnArguments.
              transactionId                 );
        }
      else
        ;
    /*end of if*/

      ibuf = new byte[
              rpc.Constants.
                PROGRAM_UNAVAILABLE_UDP_PACKET_DATA_LENGTH ];

      rpcMessageProgramUnavailable =
        new Message( ibuf );

      rpcMessageProgramUnavailable.
        putUnsignedInteger(
          parserResponderReturnArguments.
            transactionId                  );
      rpcMessageProgramUnavailable.
        putUnsignedInteger( (long) rpc.Constants.RPC_REPLY );
      rpcMessageProgramUnavailable.
        putUnsignedInteger( (long) rpc.Constants.MSG_ACCEPTED );

      rpcMessageProgramUnavailable.
        putEmptyOpaqueAuthentication();

      rpcMessageProgramUnavailable.
        putUnsignedInteger( (long)
          rpc.Constants.PROC_UNAVAIL );

      ipAddressWhereToSend =
        parserResponderReturnArguments.
          inRPCMessage.getInetAddress();
      portToSendTo =
        parserResponderReturnArguments.
          inRPCMessage.getPort();

      udpPacket = new
        DatagramPacket( ibuf, ibuf.length,
                        ipAddressWhereToSend,
                        portToSendTo          );

      try
        {
          udpSocket.send( udpPacket,
                          parserResponderReturnArguments.transactionId,
                          "sendProcedureUnavailableRPCReplyMessage"     );
        }
      catch( IOException e )
        {
          System.out.println(
            "sendProcedureUnavailableRPCReplyMessage: " +
            "IOException in sending reply\n" +
            e.getMessage()                              );
        }
    /*end of try-catch*/

    }
/*end of sendProcedureUnavailableRPCReplyMessage*/


  public
  void

  sendProgramVersionMismatchRPCReplyMessage(
    ParserResponderReturnArguments
      parserResponderReturnArguments,
    long lowestVersionSupported,
    long highestVersionSupported               )
/*****************************************************************************/
/* Function name: sendProgramVersionMismatchRPCReplyMessage                  */
/* File name: ParserResponder.java                                           */
/* Purpose: to send RPC reply message: the requested program version         */
/*          is not supported                                                 */
/* Parameters: parserResponderReturnArguments                                */
/*             lowestVersionSupported                                        */
/*             highestVersionSupported                                       */
/* Returns:                                                                  */
/* Last modified: 30.07.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      byte[] ibuf = null;
      int ilength = 0;
      InetAddress ipAddressWhereToSend = null;
      int portToSendTo = 0;
      DatagramPacket udpPacket = null;
      Message rpcMessageProgramVersionMismatch = null;

                            /* sendProgramVersionMismatchRPCReplyMessage */
/*---------------------------------------------------------------------------*/

      ibuf = new byte[
              Constants.
                PROGRAM_MISMATCH_UDP_PACKET_DATA_LENGTH ];

      rpcMessageProgramVersionMismatch =
        new Message( ibuf );

      rpcMessageProgramVersionMismatch.
        putUnsignedInteger(
          parserResponderReturnArguments.
            transactionId                  );
      rpcMessageProgramVersionMismatch.
        putUnsignedInteger( (long) rpc.Constants.RPC_REPLY );
      rpcMessageProgramVersionMismatch.
        putUnsignedInteger( (long) rpc.Constants.MSG_ACCEPTED );

      rpcMessageProgramVersionMismatch.
        putEmptyOpaqueAuthentication();

      rpcMessageProgramVersionMismatch.
        putUnsignedInteger(
          rpc.Constants.PROG_MISMATCH );

      rpcMessageProgramVersionMismatch.
        putUnsignedInteger( lowestVersionSupported );
      rpcMessageProgramVersionMismatch.
        putUnsignedInteger( highestVersionSupported );

      ipAddressWhereToSend =
        parserResponderReturnArguments.
          inRPCMessage.getInetAddress();
      portToSendTo =
        parserResponderReturnArguments.
          inRPCMessage.getPort();

      udpPacket = new
        DatagramPacket( ibuf, ibuf.length,
                        ipAddressWhereToSend,
                        portToSendTo          );

      try
        {
          udpSocket.send( udpPacket,
                          parserResponderReturnArguments.transactionId,
                          "sendProgramVersionMismatchRPCReplyMessage"  );
        }
      catch( IOException e )
        {
          System.out.println(
            "sendProgramVersionMismatchRPCReplyMessage: " +
            "IOException in sending reply\n" +
            e.getMessage()                              );
        }
    /*end of try-catch*/

    }
/*end of sendProgramVersionMismatchRPCReplyMessage*/


  public
  void

  sendRPCVersionMismatchRPCReplyMessage(
    ParserResponderReturnArguments
      parserResponderReturnArguments    )
/*****************************************************************************/
/* Function name: sendRPCVersionMismatchRPCReplyMessage                      */
/* File name: ParserResponder.java                                           */
/* Purpose: to send RPC reply message: the RPC version is not supported      */
/* Parameters: parserResponderReturnArguments                                */
/* Returns:                                                                  */
/* Last modified: 30.07.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      byte[] ibuf = null;
      int ilength = 0;
      InetAddress ipAddressWhereToSend = null;
      int portToSendTo = 0;
      DatagramPacket udpPacket = null;
      Message rpcMessage = null;

                                  /* sendRPCVersionMismatchRPCReplyMessage */
/*---------------------------------------------------------------------------*/

      ibuf = new byte[
              Constants.
                VERSION_MISMATCH_UDP_PACKET_DATA_LENGTH ];

      rpcMessage =
        new Message( ibuf );

      rpcMessage.
        putUnsignedInteger(
          parserResponderReturnArguments.
            transactionId                  );
      rpcMessage.
        putUnsignedInteger( (long) rpc.Constants.RPC_REPLY );
      rpcMessage.
        putUnsignedInteger( (long) rpc.Constants.MSG_DENIED );
      rpcMessage.
        putUnsignedInteger( (long) Constants.RPC_MISMATCH );
      rpcMessage.
        putUnsignedInteger( (long)
          Constants.LOWEST_RPC_PROTOCOL_VERSION_SUPPORTED );
      rpcMessage.
        putUnsignedInteger( (long)
          Constants.HIGHEST_RPC_PROTOCOL_VERSION_SUPPORTED );

      ipAddressWhereToSend =
        parserResponderReturnArguments.
          inRPCMessage.getInetAddress();
      portToSendTo =
        parserResponderReturnArguments.
          inRPCMessage.getPort();

      if (portToSendTo <= 0)
        {
          return;                                      /* return ! */
        }
      else
        ;
    /*end of if*/

      udpPacket = new
        DatagramPacket( ibuf, ibuf.length,
                        ipAddressWhereToSend,
                        portToSendTo          );

      try
        {
          udpSocket.send( udpPacket,
                          parserResponderReturnArguments.transactionId,
                          "sendRPCVersionMismatchRPCReplyMessage"       );
        }
      catch( IOException e )
        {
          System.out.println(
            "sendRPCVersionMismatchRPCReplyMessage: " +
            "IOException in sending reply\n" +
            e.getMessage()                              );
        }
    /*end of try-catch*/

    }
/*end of sendRPCVersionMismatchRPCReplyMessage*/


  public
  void

  sendProgramUnavailableRPCReplyMessage(
    ParserResponderReturnArguments
      parserResponderReturnArguments    )
/*****************************************************************************/
/* Function name: sendProgramUnavailableRPCReplyMessage                      */
/* File name: ParserResponder.java                                           */
/* Purpose: to send RPC reply message: the requested program is not available*/
/* Parameters: parserResponderReturnArguments                                */
/* Returns:                                                                  */
/* Last modified: 30.07.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      byte[] ibuf = null;
      int ilength = 0;
      InetAddress ipAddressWhereToSend = null;
      int portToSendTo = 0;
      DatagramPacket udpPacket = null;
      Message rpcMessageProgramUnavailable = null;
                                  /* sendProgramUnavailableRPCReplyMessage */
/*---------------------------------------------------------------------------*/

      ibuf = new byte[
              Constants.
                PROGRAM_UNAVAILABLE_UDP_PACKET_DATA_LENGTH ];

      rpcMessageProgramUnavailable =
        new Message( ibuf );

      rpcMessageProgramUnavailable.
        putUnsignedInteger(
          parserResponderReturnArguments.
            transactionId                  );
      rpcMessageProgramUnavailable.
        putUnsignedInteger( (long) rpc.Constants.RPC_REPLY );
      rpcMessageProgramUnavailable.
        putUnsignedInteger( (long) rpc.Constants.MSG_ACCEPTED );

      rpcMessageProgramUnavailable.
        putEmptyOpaqueAuthentication();

      rpcMessageProgramUnavailable.
        putUnsignedInteger( (long)
          rpc.Constants.PROG_UNAVAIL );

      ipAddressWhereToSend =
        parserResponderReturnArguments.
          inRPCMessage.getInetAddress();
      portToSendTo =
        parserResponderReturnArguments.
          inRPCMessage.getPort();

      if (portToSendTo <= 0)
        {
          return;                                      /* return ! */
        }
      else
        ;
    /*end of if*/

      udpPacket = new
        DatagramPacket( ibuf, ibuf.length,
                        ipAddressWhereToSend,
                        portToSendTo          );

      try
        {
          udpSocket.send( udpPacket,
                          parserResponderReturnArguments.transactionId,
                          "sendProgramUnavailableRPCReplyMessage"       );
        }
      catch( IOException e )
        {
          System.out.println(
            "sendProgramUnavailableRPCReplyMessage: " +
            "IOException in sending reply\n" +
            e.getMessage()                              );
        }
    /*end of try-catch*/

    }
/*end of sendProgramUnavailableRPCReplyMessage*/


  public
  boolean

  processGeneralErrors( ParserResponderReturnArguments
                          parserResponderReturnArguments,
                        long programNumber,
                        long versionLow,
                        long versionHigh                  )
/*****************************************************************************/
/* Function name: processGeneralErrors                                       */
/* File name: ParserResponder.java                                           */
/* Purpose: to process general errors in a RPC message                       */
/* Parameters: parserResponderReturnArguments                                */
/*             programNumber                                                 */
/*             versionLow                                                    */
/*             versionHigh                                                   */
/* Returns: true -  if there was an error                                    */
/*          false - if everything is OK                                      */
/* Last modified: 09.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                               /* processGeneralErrors */
/*---------------------------------------------------------------------------*/

      if (parserResponderReturnArguments.
            rpcVersionMismatch == true     )
        {
          sendRPCVersionMismatchRPCReplyMessage(
            parserResponderReturnArguments       );
          return true;                                       /* return ! */
        }
      else
        ;
    /*end of if on rpcVersionMismatch*/

      if (parserResponderReturnArguments.
            remoteProgramNumber           !=
          programNumber                      )
        {
          sendProgramUnavailableRPCReplyMessage(
            parserResponderReturnArguments       );
          return true;                                       /* return ! */
        }
      else
        ;
    /*end of if on NFS_PROG*/

      if ( (parserResponderReturnArguments.
              remoteProgramVersion         <
            versionLow                )       ||
           (parserResponderReturnArguments.
              remoteProgramVersion         >
            versionHigh               )
         )
        {
          sendProgramVersionMismatchRPCReplyMessage(
            parserResponderReturnArguments,
            versionLow,
            versionHigh                              );
          return true;                                       /* return ! */
        }
      else
        ;
    /*end of if on remoteProgramVersion*/

      return false;                                    /* no errors, OK */

    }
/*end of processGeneralErrors*/


  public
  boolean

  processRPCCall( long transactionId,
                  long messageType,
                  Message rpcMessage,
                  ParserResponderReturnArguments
                    parserResponderReturnArguments )
/*****************************************************************************/
/* Function name: processRPCCall                                             */
/* File name: ParserResponder.java                                           */
/* Purpose: to process a RPC call message                                    */
/* Parameters: transactionId                                                 */
/*             messageType                                                   */
/*             rpcMessage                                                    */
/*             parserResponderReturnArguments                                */
/* Returns: true - if everything is OK and it's possible now to process      */
/*                 the parameters to the remote procedure if there are any   */
/*          false - if there was an error.                                   */
/*                  In that case if replyUDPPacket is not null then it's     */
/*                  a reply datagram to be sent to the client                */
/* Last modified: 09.06.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      long rpcProtocolVersion;
      long remoteProgramNumber;
      long remoteProgramVersion;
      long remoteProcedureNumber;
      OpaqueAuthentication credentials;
      OpaqueAuthentication verifier;
      boolean result = true;
                                                       /* processRPCCall */
/*---------------------------------------------------------------------------*/

      rpcProtocolVersion = rpcMessage.getUnsignedInteger();
      remoteProgramNumber = rpcMessage.getUnsignedInteger();
      remoteProgramVersion = rpcMessage.getUnsignedInteger();
      remoteProcedureNumber = rpcMessage.getUnsignedInteger();
      credentials = rpcMessage.getOpaqueAuthentication();
      verifier = rpcMessage.getOpaqueAuthentication();

      if ( (rpcProtocolVersion <                          /* RPC_MISMATCH */
            Constants.LOWEST_RPC_PROTOCOL_VERSION_SUPPORTED) ||
           (rpcProtocolVersion >
            Constants.HIGHEST_RPC_PROTOCOL_VERSION_SUPPORTED)
         )
        {
          parserResponderReturnArguments.
            rpcVersionMismatch = true;

          result = false;
        }
      else
        ;
    /*end of if*/

      parserResponderReturnArguments.
        byteArrayContainingParametersToRemoteProcedure =
          rpcMessage.getUnparsedData();

      parserResponderReturnArguments.
        remoteProgramNumber = remoteProgramNumber;
      parserResponderReturnArguments.
        remoteProgramVersion = remoteProgramVersion;
      parserResponderReturnArguments.
        remoteProcedureNumber = remoteProcedureNumber;

      return result;

    }
/*end of processRPCCall*/


  public
  boolean

  processRPCReply( long transactionId,
                   long messageType,
                   Message rpcMessage,
                   ParserResponderReturnArguments
                     parserResponderReturnArguments )
/*****************************************************************************/
/* Function name: processRPCReply                                            */
/* File name: ParserResponder.java                                           */
/* Purpose: to process a RPC reply message                                   */
/* Parameters: transactionId                                                 */
/*             messageType                                                   */
/*             rpcMessage                                                    */
/*             parserResponderReturnArguments                                */
/* Returns: true - if everything is OK and it's possible now to process      */
/*                 the parameters to the remote procedure if there are any   */
/*          false - if there was an error.                                   */
/*                  In that case if replyUDPPacket is not null then it's     */
/*                  a reply datagram to be sent to the client                */
/* Last modified: 31.07.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      long replyStat;
      long rejectStat;
      long acceptStat;
      long lowestProgramVersionSupportedByServer;
      long highestProgramVersionSupportedByServer;
      long lowestProtocolVersionSupportedByServer;
      long highestProtocolVersionSupportedByServer;
      long authenticationStat;
      OpaqueAuthentication verifier;
      boolean result = false;
      String stringToPrintOut = "";
                                                       /* processRPCReply */
/*---------------------------------------------------------------------------*/

      replyStat = rpcMessage.getUnsignedInteger();

      parserResponderReturnArguments.
        replyStat = replyStat;

      switch( (int) replyStat )
        {
        case (int) Constants.MSG_ACCEPTED:
          verifier = rpcMessage.getOpaqueAuthentication();
          acceptStat = rpcMessage.getUnsignedInteger();

          parserResponderReturnArguments.
            acceptStat = acceptStat;

          switch( (int) acceptStat )
            {
            case (int) Constants.SUCCESS:
              parserResponderReturnArguments.
                byteArrayContainingParametersToRemoteProcedure =
                  rpcMessage.getUnparsedData();
              result = true;
              break;
            case (int) Constants.PROG_MISMATCH:
              lowestProgramVersionSupportedByServer =
                rpcMessage.getUnsignedInteger();
              highestProgramVersionSupportedByServer =
                rpcMessage.getUnsignedInteger();
              parserResponderReturnArguments.
                lowestProgramVersionSupportedByServer =
                lowestProgramVersionSupportedByServer;
              parserResponderReturnArguments.
                highestProgramVersionSupportedByServer =
                highestProgramVersionSupportedByServer;
              if ( (logTransactions) &&
                   (log != null)
                 )
                {
                  stringToPrintOut +=
                    "ParserResponder, processRPCReply\n";
                  stringToPrintOut +=
                    "PROG_MISMATCH,\n" +
                    "lowestProgramVersionSupportedByServer=" +
                    lowestProgramVersionSupportedByServer    +
                    "\nhighestProgramVersionSupportedByServer=" +
                    highestProgramVersionSupportedByServer + "\n";
                  log.write( stringToPrintOut );
                }
              else
                ;
            /*end of if*/

              break;

            default: /* no additional data */
              if ( (logTransactions) &&
                   (log != null)
                 )
                {
                  stringToPrintOut +=
                    "ParserResponder, processRPCReply\n";
                  stringToPrintOut +=
                    "no SUCCESS: acceptStat=" +
                    acceptStat + "\n";
                  log.write( stringToPrintOut );
                }
              else
                ;
            /*end of if*/

              break;

            }
        /*end of switch on acceptStat*/

          break;

        case (int) Constants.MSG_DENIED:

          rejectStat = rpcMessage.getUnsignedInteger();

          parserResponderReturnArguments.
            rejectStat = rejectStat;

          switch( (int) rejectStat )
            {
            case (int) Constants.RPC_MISMATCH:
              lowestProtocolVersionSupportedByServer =
                rpcMessage.getUnsignedInteger();
              highestProtocolVersionSupportedByServer =
                rpcMessage.getUnsignedInteger();
              parserResponderReturnArguments.
                lowestProtocolVersionSupportedByServer =
                lowestProtocolVersionSupportedByServer;
              parserResponderReturnArguments.
                highestProtocolVersionSupportedByServer =
                highestProtocolVersionSupportedByServer;
              if ( (logTransactions) &&
                   (log != null)
                 )
                {
                  stringToPrintOut +=
                    "ParserResponder, processRPCReply\n";
                  stringToPrintOut +=
                    "RPC_MISMATCH:\n" +
                    "lowestProtocolVersionSupportedByServer=" +
                    lowestProtocolVersionSupportedByServer    +
                    "\nhighestProtocolVersionSupportedByServer" +
                    highestProtocolVersionSupportedByServer + "\n";
                  log.write( stringToPrintOut );
                }
              else
                ;
            /*end of if*/

              break;

            case (int) Constants.AUTH_ERROR:
              authenticationStat =
                rpcMessage.getUnsignedInteger();
              parserResponderReturnArguments.
                authenticationStat = authenticationStat;
              if ( (logTransactions) &&
                   (log != null)
                 )
                {
                  stringToPrintOut +=
                    "ParserResponder, processRPCReply\n";
                  stringToPrintOut +=
                    "AUTH_ERROR:\n" +
                    "authenticationStat=" +
                    authenticationStat + "\n";
                  log.write( stringToPrintOut );
                }
              else
                ;
            /*end of if*/

              break;

            }
        /*end of switch on rejectStat*/

          break;

        default:
          return false;                                /* return ! */
        }
    /*end of switch on replyStat*/

      return result;

    }
/*end of processRPCReply*/


  public
  boolean

  processUDPPacket( DatagramPacket udpPacket,
                    ParserResponderReturnArguments
                      parserResponderReturnArguments )
/*****************************************************************************/
/* Function name: processUDPPacket                                           */
/* File name: ParserResponder.java                                           */
/* Purpose: to process a newly arrived UDP packet                            */
/* Parameters: udpPacket                                                     */
/*             parserResponderReturnArguments                                */
/* Returns: true - if everything is OK and it's possible now to process      */
/*                 the parameters to the remote procedure if there are any   */
/*          false - if there was an error.                                   */
/*                  In that case if replyUDPPacket is not null then it's     */
/*                  a reply datagram to be sent to the client                */
/* Last modified: 31.07.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int dataLength = 0;
      byte[] dataReceived;
      Message rpcMessage;
      long transactionId;
      long messageType;
      boolean nowMayProcessTheParametersToRemoteProcedure;
      String stringToPrintOut = "";

                                                       /* processUDPPacket */
/*---------------------------------------------------------------------------*/

      dataLength = udpPacket.getLength();
      dataReceived = udpPacket.getData();

      rpcMessage = new
        Message( udpPacket );

      parserResponderReturnArguments.
        inRPCMessage = rpcMessage;

      transactionId = rpcMessage.getUnsignedInteger();
      messageType = rpcMessage.getUnsignedInteger();

      parserResponderReturnArguments.
        transactionId = transactionId;
      parserResponderReturnArguments.
        messageType = messageType;

      switch( (int) messageType )
        {
        case (int) Constants.RPC_CALL:
          nowMayProcessTheParametersToRemoteProcedure =
            processRPCCall(
              transactionId, messageType,
              rpcMessage,
              parserResponderReturnArguments );
          return nowMayProcessTheParametersToRemoteProcedure; /* return ! */

        case (int) Constants.RPC_REPLY:
          nowMayProcessTheParametersToRemoteProcedure =
            processRPCReply(
              transactionId, messageType,
              rpcMessage,
              parserResponderReturnArguments );
          return nowMayProcessTheParametersToRemoteProcedure; /* return ! */
        default:
          if ( (logTransactions) &&
               (log != null)
             )
            {
              stringToPrintOut +=
                "ParserResponder, processUDPPacket\n";
              stringToPrintOut +=
                "received wrong message type=" +
                messageType + "\n";
              log.write( stringToPrintOut );
            }
          else
            ;
        /*end of if*/

          return false;                                /* return ! */

        }
    /*end of switch*/

  }
/*end of processUDPPacket*/


} /* end of ParserResponder class */

/*****************************************************************************/
/* End of file: ParserResponder.java                                         */
/*****************************************************************************/
