// // openmapi.org - CompactTeaSharp - OnRpcClientReplyMessage.cs // // C# port Copyright 2008 by Topalis AG // // Author (C# port): mazurin, Johannes Roith // // This library is based on the RemoteTea java library: // // Author: Harald Albrecht // // Copyright (c) 1999, 2000 // Lehrstuhl fuer Prozessleittechnik (PLT), RWTH Aachen // D-52064 Aachen, Germany. All rights reserved. // // 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. // using System; namespace CompactTeaSharp { /// /// Represents an ONC/RPC reply message as defined by ONC/RPC in RFC 1831. /// Such messages are sent back by ONC/RPC to servers to clients and contain /// (in case of real success) the result of a remote procedure call. /// /// The derived classes are only provided for convinience on the server side. /// public class OncRpcClientReplyMessage : OncRpcReplyMessage { /// /// Client-side authentication protocol handling object to use when /// decoding the reply message. /// protected OncRpcClientAuth auth; /// /// Initializes a new OncRpcReplyMessage object to represent /// an invalid state. This default constructor should only be used if in the /// next step the real state of the reply message is immediately decoded /// from a XDR stream. /// /// Client-side authentication protocol handling object which /// is to be used when decoding the verifier data contained in the reply. public OncRpcClientReplyMessage (OncRpcClientAuth auth): base () { this.auth = auth; } /// /// Check whether this OncRpcReplyMessage represents an /// accepted and successfully executed remote procedure call. /// /// True if rpc call was accepted and successfully executed. public bool SuccessfullyAccepted () { return (ReplyStatus == OncRpcReplyStatus.MsgAccepted) && (AcceptStatus == OncRpcAcceptStatus.Success); } /// /// Return an appropriate exception object according to the state this /// reply message header object is in. The exception object then can be thrown. /// //// Exception object of class OncRpcException or a subclass thereof. public OncRpcException newException () { switch (ReplyStatus) { case OncRpcReplyStatus.MsgAccepted: switch (AcceptStatus) { case OncRpcAcceptStatus.Success: return new OncRpcException (OncRpcException.SUCCESS); case OncRpcAcceptStatus.ProcedureUnavailable: return new OncRpcException (OncRpcException.PROC_UNAVAIL); case OncRpcAcceptStatus.ProgMismatch: return new OncRpcException (OncRpcException.PROG_VERS_MISMATCH); case OncRpcAcceptStatus.ProgUnavail: return new OncRpcException (OncRpcException.PROG_UNAVAIL); case OncRpcAcceptStatus.GarbageArgs: return new OncRpcException (OncRpcException.CANT_DECODE_ARGS); case OncRpcAcceptStatus.SystemErr: return new OncRpcException (OncRpcException.SYSTEM_ERROR); } break; case OncRpcReplyStatus.MsgDenied: switch (RejectStatus) { case OncRpcRejectStatus.AuthenticationError: return new OncRpcAuthenticationException (AuthStatus); case OncRpcRejectStatus.RpcMismatch: return new OncRpcException (OncRpcException.FAILED); } break; } return new OncRpcException (); } /// /// Decodes a ONC/RPC message header object from an XDR stream. /// public void XdrDecode (XdrDecodingStream xdr) { MessageId = xdr.XdrDecodeInt (); // // Make sure that we are really decoding an ONC/RPC message call // header. Otherwise, throw the appropriate OncRpcException exception. // MessageType = (OncRpcMessageType) xdr.XdrDecodeInt (); if (MessageType != OncRpcMessageType.Reply) throw new OncRpcException (OncRpcException.WRONG_MESSAGE); ReplyStatus = (OncRpcReplyStatus) xdr.XdrDecodeInt (); switch (ReplyStatus) { case OncRpcReplyStatus.MsgAccepted: DecodeMsgAccepted (xdr); break; case OncRpcReplyStatus.MsgDenied: DecodeMsgDenied (xdr); break; } } private void DecodeMsgAccepted (XdrDecodingStream xdr) { // // Decode the information returned for accepted message calls. // If we have an associated client-side authentication protocol // object, we use that. Otherwise we fall back to the default // handling of only the AUTH_NONE authentication. // if (auth != null) auth.XdrDecodeVerf (xdr); else { // // If we don't have a protocol handler and the server sent its // reply using another authentication scheme than AUTH_NONE, we // will throw an exception. Also we check that no-one is // actually sending opaque information within AUTH_NONE. // if (xdr.XdrDecodeInt () != (int) OncRpcAuthType.None) throw new OncRpcAuthenticationException (OncRpcAuthStatus.Failed); if (xdr.XdrDecodeInt () != 0) throw new OncRpcAuthenticationException (OncRpcAuthStatus.Failed); } // // Even if the call was accepted by the server, it can still // indicate an error. Depending on the status of the accepted // call we will receive an indication about the range of // versions a particular program (server) supports. // AcceptStatus = (OncRpcAcceptStatus) xdr.XdrDecodeInt (); if (AcceptStatus == OncRpcAcceptStatus.ProgMismatch) { LowVersion = xdr.XdrDecodeInt (); HighVersion = xdr.XdrDecodeInt (); } else { // // Otherwise "open ended set of problem", like the author // of Sun's ONC/RPC source once wrote... // } } private void DecodeMsgDenied (XdrDecodingStream xdr) { RejectStatus = (OncRpcRejectStatus) xdr.XdrDecodeInt (); switch (RejectStatus) { case OncRpcRejectStatus.RpcMismatch: LowVersion = xdr.XdrDecodeInt (); HighVersion = xdr.XdrDecodeInt (); break; case OncRpcRejectStatus.AuthenticationError: AuthStatus = (OncRpcAuthStatus) xdr.XdrDecodeInt (); break; } } } }