コード例 #1
0
 // for ( refreshesLeft )
 /// <summary>Issues a batched call for a remote procedure to an ONC/RPC server.</summary>
 /// <remarks>
 /// Issues a batched call for a remote procedure to an ONC/RPC server.
 /// Below is a small example (exception handling ommited for clarity):
 /// <pre>
 /// OncRpcTcpClient client = new OncRpcTcpClient(
 /// InetAddress.getByName("localhost"),
 /// myprogramnumber, myprogramversion,
 /// OncRpcProtocols.ONCRPC_TCP);
 /// client.callBatch(42, myparams, false);
 /// client.callBatch(42, myotherparams, false);
 /// client.callBatch(42, myfinalparams, true);
 /// </pre>
 /// In the example above, three calls are batched in a row and only be sent
 /// all together with the third call. Note that batched calls must not expect
 /// replies, with the only exception being the last call in a batch:
 /// <pre>
 /// client.callBatch(42, myparams, false);
 /// client.callBatch(42, myotherparams, false);
 /// client.call(43, myfinalparams, myfinalresult);
 /// </pre>
 /// </remarks>
 /// <param name="procedureNumber">Procedure number of the procedure to call.</param>
 /// <param name="params">
 /// The parameters of the procedure to call, contained
 /// in an object which implements the
 /// <see cref="XdrAble">XdrAble</see>
 /// interface.
 /// </param>
 /// <param name="flush">
 /// Make sure that all pending batched calls are sent to
 /// the server.
 /// </param>
 /// <exception cref="OncRpcException">if an ONC/RPC error occurs.</exception>
 /// <exception cref="org.acplt.oncrpc.OncRpcException"></exception>
 public virtual void batchCall(int procedureNumber, org.acplt.oncrpc.XdrAble @params
                               , bool flush)
 {
     lock (this)
     {
         //
         // First, build the ONC/RPC call header. Then put the sending
         // stream into a known state and encode the parameters to be
         // sent. Finally tell the encoding stream to send all its data
         // to the server. We don't then need to wait for an answer. And
         // we don't need to take care of credential refreshes either.
         //
         nextXid();
         org.acplt.oncrpc.OncRpcClientCallMessage callHeader = new org.acplt.oncrpc.OncRpcClientCallMessage
                                                                   (xid, program, version, procedureNumber, auth);
         //
         // Send call message to server. If we receive an IOException,
         // then we'll throw the appropriate ONC/RPC (client) exception.
         // Note that we use a connected stream, so we don't need to
         // specify a destination when beginning serialization.
         //
         try
         {
             socket.SendTimeout = transmissionTimeout;
             sendingXdr.beginEncoding(null, 0);
             callHeader.xdrEncode(sendingXdr);
             @params.xdrEncode(sendingXdr);
             sendingXdr.endEncoding(flush);
         }
         catch (System.IO.IOException e)
         {
             throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTSEND
                                                         , e.Message));
         }
     }
 }
コード例 #2
0
 /// <summary>Calls a remote procedure on an ONC/RPC server.</summary>
 /// <remarks>
 /// Calls a remote procedure on an ONC/RPC server.
 /// <p>Please note that while this method supports call batching by
 /// setting the communication timeout to zero
 /// (<code>setTimeout(0)</code>) you should better use
 /// <see cref="batchCall(int, XdrAble, bool)">batchCall(int, XdrAble, bool)</see>
 /// as it provides better control over when the
 /// batch should be flushed to the server.
 /// </remarks>
 /// <param name="procedureNumber">Procedure number of the procedure to call.</param>
 /// <param name="versionNumber">Protocol version number.</param>
 /// <param name="params">
 /// The parameters of the procedure to call, contained
 /// in an object which implements the
 /// <see cref="XdrAble">XdrAble</see>
 /// interface.
 /// </param>
 /// <param name="result">The object receiving the result of the procedure call.</param>
 /// <exception cref="OncRpcException">if an ONC/RPC error occurs.</exception>
 /// <exception cref="org.acplt.oncrpc.OncRpcException"></exception>
 public override void call(int procedureNumber, int versionNumber, org.acplt.oncrpc.XdrAble
                           @params, org.acplt.oncrpc.XdrAble result)
 {
     lock (this)
     {
         // Refresh:
         for (int refreshesLeft = 1; refreshesLeft >= 0; --refreshesLeft)
         {
             //
             // First, build the ONC/RPC call header. Then put the sending
             // stream into a known state and encode the parameters to be
             // sent. Finally tell the encoding stream to send all its data
             // to the server. Then wait for an answer, receive it and decode
             // it. So that's the bottom line of what we do right here.
             //
             nextXid();
             org.acplt.oncrpc.OncRpcClientCallMessage callHeader = new org.acplt.oncrpc.OncRpcClientCallMessage
                                                                       (xid, program, versionNumber, procedureNumber, auth);
             org.acplt.oncrpc.OncRpcClientReplyMessage replyHeader = new org.acplt.oncrpc.OncRpcClientReplyMessage
                                                                         (auth);
             //
             // Send call message to server. If we receive an IOException,
             // then we'll throw the appropriate ONC/RPC (client) exception.
             // Note that we use a connected stream, so we don't need to
             // specify a destination when beginning serialization.
             //
             try
             {
                 socket.ReceiveTimeout = transmissionTimeout;
                 sendingXdr.beginEncoding(null, 0);
                 callHeader.xdrEncode(sendingXdr);
                 @params.xdrEncode(sendingXdr);
                 if (timeout != 0)
                 {
                     sendingXdr.endEncoding();
                 }
                 else
                 {
                     sendingXdr.endEncoding(false);
                 }
             }
             catch (System.IO.IOException e)
             {
                 throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTSEND
                                                             , e.Message));
             }
             //
             // Receive reply message from server -- at least try to do so...
             // In case of batched calls we don't need no stinkin' answer, so
             // we can do other, more interesting things.
             //
             if (timeout == 0)
             {
                 return;
             }
             try
             {
                 //
                 // Keep receiving until we get the matching reply.
                 //
                 while (true)
                 {
                     socket.ReceiveTimeout = timeout;
                     receivingXdr.beginDecoding();
                     socket.ReceiveTimeout = transmissionTimeout;
                     //
                     // First, pull off the reply message header of the
                     // XDR stream. In case we also received a verifier
                     // from the server and this verifier was invalid, broken
                     // or tampered with, we will get an
                     // OncRpcAuthenticationException right here, which will
                     // propagate up to the caller. If the server reported
                     // an authentication problem itself, then this will
                     // be handled as any other rejected ONC/RPC call.
                     //
                     try
                     {
                         replyHeader.xdrDecode(receivingXdr);
                     }
                     catch (org.acplt.oncrpc.OncRpcException e)
                     {
                         //
                         // ** SF bug #1262106 **
                         //
                         // We ran into some sort of trouble. Usually this will have
                         // been a buffer underflow. Whatever, end the decoding process
                         // and ensure this way that the next call has a chance to start
                         // from a clean state.
                         //
                         receivingXdr.endDecoding();
                         throw (e);
                     }
                     //
                     // Only deserialize the result, if the reply matches the
                     // call. Otherwise skip this record.
                     //
                     if (replyHeader.messageId == callHeader.messageId)
                     {
                         break;
                     }
                     receivingXdr.endDecoding();
                 }
                 //
                 // Make sure that the call was accepted. In case of unsuccessful
                 // calls, throw an exception, if it's not an authentication
                 // exception. In that case try to refresh the credential first.
                 //
                 if (!replyHeader.successfullyAccepted())
                 {
                     receivingXdr.endDecoding();
                     //
                     // Check whether there was an authentication
                     // problem. In this case first try to refresh the
                     // credentials.
                     //
                     if ((refreshesLeft > 0) && (replyHeader.replyStatus == org.acplt.oncrpc.OncRpcReplyStatus
                                                 .ONCRPC_MSG_DENIED) && (replyHeader.rejectStatus == org.acplt.oncrpc.OncRpcRejectStatus
                                                                         .ONCRPC_AUTH_ERROR) && (auth != null) && auth.canRefreshCred())
                     {
                         // continue Refresh;
                         continue;
                     }
                     //
                     // Nope. No chance. This gets tough.
                     //
                     throw (replyHeader.newException());
                 }
                 try
                 {
                     result.xdrDecode(receivingXdr);
                 }
                 catch (org.acplt.oncrpc.OncRpcException e)
                 {
                     //
                     // ** SF bug #1262106 **
                     //
                     // We ran into some sort of trouble. Usually this will have
                     // been a buffer underflow. Whatever, end the decoding process
                     // and ensure this way that the next call has a chance to start
                     // from a clean state.
                     //
                     receivingXdr.endDecoding();
                     throw (e);
                 }
                 //
                 // Free pending resources of buffer and exit the call loop,
                 // returning the reply to the caller through the result
                 // object.
                 //
                 receivingXdr.endDecoding();
                 return;
             }
             catch (System.IO.IOException e)
             {
                 //
                 // Argh. Trouble with the transport. Seems like we can't
                 // receive data. Gosh. Go away!
                 //
                 throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTRECV
                                                             , e.Message));
             }
         }
     }
 }
コード例 #3
0
 // for ( refreshesLeft )
 /// <summary>Broadcast a remote procedure call to several ONC/RPC servers.</summary>
 /// <remarks>
 /// Broadcast a remote procedure call to several ONC/RPC servers. For this
 /// you'll need to specify either a multicast address or the subnet's
 /// broadcast address when creating a <code>OncRpcUdpClient</code>. For
 /// every reply received, an event containing the reply is sent to the
 /// OncRpcBroadcastListener <code>listener</code>, which is the last
 /// parameter to the this method.
 /// <p>In contrast to the
 /// <see cref="OncRpcClient.call(int, XdrAble, XdrAble)">OncRpcClient.call(int, XdrAble, XdrAble)
 ///     </see>
 /// method,
 /// <code>broadcastCall</code> will only send the ONC/RPC call once. It
 /// will then wait for answers until the timeout as set by
 /// <see cref="OncRpcClient.setTimeout(int)">OncRpcClient.setTimeout(int)</see>
 /// expires without resending the reply.
 /// <p>Note that you might experience unwanted results when using
 /// authentication types other than
 /// <see cref="OncRpcClientAuthNone">OncRpcClientAuthNone</see>
 /// , causing
 /// messed up authentication protocol handling objects. This depends on
 /// the type of authentication used. For <code>AUTH_UNIX</code> nothing
 /// bad happens as long as none of the servers replies with a shorthand
 /// verifier. If it does, then this shorthand will be used on all subsequent
 /// ONC/RPC calls, something you probably do not want at all.
 /// </remarks>
 /// <param name="procedureNumber">Procedure number of the procedure to call.</param>
 /// <param name="params">
 /// The parameters of the procedure to call, contained
 /// in an object which implements the
 /// <see cref="XdrAble">XdrAble</see>
 /// interface.
 /// </param>
 /// <param name="result">
 /// The object receiving the result of the procedure call.
 /// Note that this object is reused to deserialize all incomming replies
 /// one after another.
 /// </param>
 /// <param name="listener">
 /// Listener which will get an
 /// <see cref="OncRpcBroadcastEvent">OncRpcBroadcastEvent</see>
 /// for every reply received.
 /// </param>
 /// <exception cref="OncRpcException">if an ONC/RPC error occurs.</exception>
 /// <exception cref="org.acplt.oncrpc.OncRpcException"></exception>
 public virtual void broadcastCall(int procedureNumber, org.acplt.oncrpc.XdrAble @params
                                   , org.acplt.oncrpc.XdrAble result, org.acplt.oncrpc.OncRpcBroadcastListener listener
                                   )
 {
     lock (this)
     {
         //
         // First, build the ONC/RPC call header. Then put the sending
         // stream into a known state and encode the parameters to be
         // sent. Finally tell the encoding stream to broadcast all its data.
         // Then wait for answers, receive and decode them one at a time.
         //
         nextXid();
         org.acplt.oncrpc.OncRpcClientCallMessage callHeader = new org.acplt.oncrpc.OncRpcClientCallMessage
                                                                   (xid, program, version, procedureNumber, auth);
         org.acplt.oncrpc.OncRpcClientReplyMessage replyHeader = new org.acplt.oncrpc.OncRpcClientReplyMessage
                                                                     (auth);
         //
         // Broadcast the call. Note that we send the call only once and will
         // never resend it.
         //
         try
         {
             //
             // Send call message to server. Remember that we've already
             // "connected" the datagram socket, so java.net knows whom
             // to send the datagram packets.
             //
             sendingXdr.beginEncoding(host, port);
             callHeader.xdrEncode(sendingXdr);
             @params.xdrEncode(sendingXdr);
             sendingXdr.endEncoding();
         }
         catch (System.IO.IOException e)
         {
             throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTSEND
                                                         , e.Message));
         }
         //
         // Now enter the great loop where sit waiting for replies to our
         // broadcast call to come in. In every case, we wait until the
         // (total) timeout expires.
         //
         DateTime stopTime = DateTime.Now + new TimeSpan(timeout);
         do
         {
             try
             {
                 //
                 // Calculate timeout until the total timeout is reached, so
                 // we can try to meet the overall deadline.
                 //
                 TimeSpan currentTimeout = (stopTime - DateTime.Now);
                 if (currentTimeout.Ticks < 0)
                 {
                     currentTimeout = new TimeSpan(0);
                 }
                 socket.ReceiveTimeout = currentTimeout.Seconds;
                 //
                 // Then wait for datagrams to arrive...
                 //
                 receivingXdr.beginDecoding();
                 replyHeader.xdrDecode(receivingXdr);
                 //
                 // Only deserialize the result, if the reply matches the call
                 // and if the reply signals a successful call. In case of an
                 // unsuccessful call (which mathes our call nevertheless) throw
                 // an exception.
                 //
                 if (replyHeader.messageId == callHeader.messageId)
                 {
                     if (!replyHeader.successfullyAccepted())
                     {
                         //
                         // We got a notification of a rejected call. We silently
                         // ignore such replies and continue listening for other
                         // replies.
                         //
                         receivingXdr.endDecoding();
                     }
                     result.xdrDecode(receivingXdr);
                     //
                     // Notify a potential listener of the reply.
                     //
                     if (listener != null)
                     {
                         org.acplt.oncrpc.OncRpcBroadcastEvent evt = new org.acplt.oncrpc.OncRpcBroadcastEvent
                                                                         (this, receivingXdr.getSenderAddress(), procedureNumber, @params, result);
                         listener.replyReceived(evt);
                     }
                     //
                     // Free pending resources of buffer and exit the call loop,
                     // returning the reply to the caller through the result
                     // object.
                     //
                     receivingXdr.endDecoding();
                 }
                 else
                 {
                     //
                     // This should raise no exceptions, when skipping the UDP
                     // record. So if one is raised, we will rethrow an ONC/RPC
                     // exception instead.
                     //
                     try
                     {
                         receivingXdr.endDecoding();
                     }
                     catch (System.IO.IOException e)
                     {
                         throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTRECV
                                                                     , e.Message));
                     }
                 }
             }
             catch (SocketException)
             {
             }
             catch (System.IO.IOException e)
             {
                 //
                 // Note that we only catch timeouts here, but no other
                 // exceptions. Those others will go up further until someone
                 // catches them. If we get the timeout we know that it
                 // could be time to leave the stage and so we fall through
                 // to the total timeout check.
                 //
                 //
                 // Argh. Trouble with the transport. Seems like we can't
                 // receive data. Gosh. Go away!
                 //
                 throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTRECV
                                                             , e.Message));
             }
         }while (DateTime.Now < stopTime);
         return;
     }
 }
コード例 #4
0
ファイル: OncRpcUdpClient.cs プロジェクト: zjianliu/NFSClient
        // for ( refreshesLeft )
        /// <summary>Broadcast a remote procedure call to several ONC/RPC servers.</summary>
        /// <remarks>
        /// Broadcast a remote procedure call to several ONC/RPC servers. For this
        /// you'll need to specify either a multicast address or the subnet's
        /// broadcast address when creating a <code>OncRpcUdpClient</code>. For
        /// every reply received, an event containing the reply is sent to the
        /// OncRpcBroadcastListener <code>listener</code>, which is the last
        /// parameter to the this method.
        /// <p>In contrast to the
        /// <see cref="OncRpcClient.call(int, XdrAble, XdrAble)">OncRpcClient.call(int, XdrAble, XdrAble)
        /// 	</see>
        /// method,
        /// <code>broadcastCall</code> will only send the ONC/RPC call once. It
        /// will then wait for answers until the timeout as set by
        /// <see cref="OncRpcClient.setTimeout(int)">OncRpcClient.setTimeout(int)</see>
        /// expires without resending the reply.
        /// <p>Note that you might experience unwanted results when using
        /// authentication types other than
        /// <see cref="OncRpcClientAuthNone">OncRpcClientAuthNone</see>
        /// , causing
        /// messed up authentication protocol handling objects. This depends on
        /// the type of authentication used. For <code>AUTH_UNIX</code> nothing
        /// bad happens as long as none of the servers replies with a shorthand
        /// verifier. If it does, then this shorthand will be used on all subsequent
        /// ONC/RPC calls, something you probably do not want at all.
        /// </remarks>
        /// <param name="procedureNumber">Procedure number of the procedure to call.</param>
        /// <param name="params">
        /// The parameters of the procedure to call, contained
        /// in an object which implements the
        /// <see cref="XdrAble">XdrAble</see>
        /// interface.
        /// </param>
        /// <param name="result">
        /// The object receiving the result of the procedure call.
        /// Note that this object is reused to deserialize all incomming replies
        /// one after another.
        /// </param>
        /// <param name="listener">
        /// Listener which will get an
        /// <see cref="OncRpcBroadcastEvent">OncRpcBroadcastEvent</see>
        /// for every reply received.
        /// </param>
        /// <exception cref="OncRpcException">if an ONC/RPC error occurs.</exception>
        /// <exception cref="org.acplt.oncrpc.OncRpcException"></exception>
        public virtual void broadcastCall(int procedureNumber, org.acplt.oncrpc.XdrAble @params
			, org.acplt.oncrpc.XdrAble result, org.acplt.oncrpc.OncRpcBroadcastListener listener
			)
        {
            lock (this)
            {
                //
                // First, build the ONC/RPC call header. Then put the sending
                // stream into a known state and encode the parameters to be
                // sent. Finally tell the encoding stream to broadcast all its data.
                // Then wait for answers, receive and decode them one at a time.
                //
                nextXid();
                org.acplt.oncrpc.OncRpcClientCallMessage callHeader = new org.acplt.oncrpc.OncRpcClientCallMessage
                    (xid, program, version, procedureNumber, auth);
                org.acplt.oncrpc.OncRpcClientReplyMessage replyHeader = new org.acplt.oncrpc.OncRpcClientReplyMessage
                    (auth);
                //
                // Broadcast the call. Note that we send the call only once and will
                // never resend it.
                //
                try
                {
                    //
                    // Send call message to server. Remember that we've already
                    // "connected" the datagram socket, so java.net knows whom
                    // to send the datagram packets.
                    //
                    sendingXdr.beginEncoding(host, port);
                    callHeader.xdrEncode(sendingXdr);
                    @params.xdrEncode(sendingXdr);
                    sendingXdr.endEncoding();
                }
                catch (System.IO.IOException e)
                {
                    throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTSEND
                        , e.Message));
                }
                //
                // Now enter the great loop where sit waiting for replies to our
                // broadcast call to come in. In every case, we wait until the
                // (total) timeout expires.
                //
                DateTime stopTime = DateTime.Now + new TimeSpan(timeout);
                do
                {
                    try
                    {
                        //
                        // Calculate timeout until the total timeout is reached, so
                        // we can try to meet the overall deadline.
                        //
                        TimeSpan currentTimeout = (stopTime - DateTime.Now);
                        if (currentTimeout.Ticks < 0)
                        {
                            currentTimeout = new TimeSpan(0);
                        }
                        socket.ReceiveTimeout = currentTimeout.Seconds;
                        //
                        // Then wait for datagrams to arrive...
                        //
                        receivingXdr.beginDecoding();
                        replyHeader.xdrDecode(receivingXdr);
                        //
                        // Only deserialize the result, if the reply matches the call
                        // and if the reply signals a successful call. In case of an
                        // unsuccessful call (which mathes our call nevertheless) throw
                        // an exception.
                        //
                        if (replyHeader.messageId == callHeader.messageId)
                        {
                            if (!replyHeader.successfullyAccepted())
                            {
                                //
                                // We got a notification of a rejected call. We silently
                                // ignore such replies and continue listening for other
                                // replies.
                                //
                                receivingXdr.endDecoding();
                            }
                            result.xdrDecode(receivingXdr);
                            //
                            // Notify a potential listener of the reply.
                            //
                            if (listener != null)
                            {
                                org.acplt.oncrpc.OncRpcBroadcastEvent evt = new org.acplt.oncrpc.OncRpcBroadcastEvent
                                    (this, receivingXdr.getSenderAddress(), procedureNumber, @params, result);
                                listener.replyReceived(evt);
                            }
                            //
                            // Free pending resources of buffer and exit the call loop,
                            // returning the reply to the caller through the result
                            // object.
                            //
                            receivingXdr.endDecoding();
                        }
                        else
                        {
                            //
                            // This should raise no exceptions, when skipping the UDP
                            // record. So if one is raised, we will rethrow an ONC/RPC
                            // exception instead.
                            //
                            try
                            {
                                receivingXdr.endDecoding();
                            }
                            catch (System.IO.IOException e)
                            {
                                throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTRECV
                                    , e.Message));
                            }
                        }
                    }
                    catch (SocketException)
                    {
                    }
                    catch (System.IO.IOException e)
                    {
                        //
                        // Note that we only catch timeouts here, but no other
                        // exceptions. Those others will go up further until someone
                        // catches them. If we get the timeout we know that it
                        // could be time to leave the stage and so we fall through
                        // to the total timeout check.
                        //
                        //
                        // Argh. Trouble with the transport. Seems like we can't
                        // receive data. Gosh. Go away!
                        //
                        throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTRECV
                            , e.Message));
                    }
                }
                while (DateTime.Now < stopTime);
                return;
            }
        }
コード例 #5
0
		// for ( refreshesLeft )
		/// <summary>Issues a batched call for a remote procedure to an ONC/RPC server.</summary>
		/// <remarks>
		/// Issues a batched call for a remote procedure to an ONC/RPC server.
		/// Below is a small example (exception handling ommited for clarity):
		/// <pre>
		/// OncRpcTcpClient client = new OncRpcTcpClient(
		/// InetAddress.getByName("localhost"),
		/// myprogramnumber, myprogramversion,
		/// OncRpcProtocols.ONCRPC_TCP);
		/// client.callBatch(42, myparams, false);
		/// client.callBatch(42, myotherparams, false);
		/// client.callBatch(42, myfinalparams, true);
		/// </pre>
		/// In the example above, three calls are batched in a row and only be sent
		/// all together with the third call. Note that batched calls must not expect
		/// replies, with the only exception being the last call in a batch:
		/// <pre>
		/// client.callBatch(42, myparams, false);
		/// client.callBatch(42, myotherparams, false);
		/// client.call(43, myfinalparams, myfinalresult);
		/// </pre>
		/// </remarks>
		/// <param name="procedureNumber">Procedure number of the procedure to call.</param>
		/// <param name="params">
		/// The parameters of the procedure to call, contained
		/// in an object which implements the
		/// <see cref="XdrAble">XdrAble</see>
		/// interface.
		/// </param>
		/// <param name="flush">
		/// Make sure that all pending batched calls are sent to
		/// the server.
		/// </param>
		/// <exception cref="OncRpcException">if an ONC/RPC error occurs.</exception>
		/// <exception cref="org.acplt.oncrpc.OncRpcException"></exception>
		public virtual void batchCall(int procedureNumber, org.acplt.oncrpc.XdrAble @params
			, bool flush)
		{
			lock (this)
			{
				//
				// First, build the ONC/RPC call header. Then put the sending
				// stream into a known state and encode the parameters to be
				// sent. Finally tell the encoding stream to send all its data
				// to the server. We don't then need to wait for an answer. And
				// we don't need to take care of credential refreshes either.
				//
				nextXid();
				org.acplt.oncrpc.OncRpcClientCallMessage callHeader = new org.acplt.oncrpc.OncRpcClientCallMessage
					(xid, program, version, procedureNumber, auth);
				//
				// Send call message to server. If we receive an IOException,
				// then we'll throw the appropriate ONC/RPC (client) exception.
				// Note that we use a connected stream, so we don't need to
				// specify a destination when beginning serialization.
				//
				try
				{
					socket.SendTimeout = transmissionTimeout;
					sendingXdr.beginEncoding(null, 0);
					callHeader.xdrEncode(sendingXdr);
					@params.xdrEncode(sendingXdr);
					sendingXdr.endEncoding(flush);
				}
				catch (System.IO.IOException e)
				{
					throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTSEND
						, e.Message));
				}
			}
		}
コード例 #6
0
		/// <summary>Calls a remote procedure on an ONC/RPC server.</summary>
		/// <remarks>
		/// Calls a remote procedure on an ONC/RPC server.
		/// <p>Please note that while this method supports call batching by
		/// setting the communication timeout to zero
		/// (<code>setTimeout(0)</code>) you should better use
		/// <see cref="batchCall(int, XdrAble, bool)">batchCall(int, XdrAble, bool)</see>
		/// as it provides better control over when the
		/// batch should be flushed to the server.
		/// </remarks>
		/// <param name="procedureNumber">Procedure number of the procedure to call.</param>
		/// <param name="versionNumber">Protocol version number.</param>
		/// <param name="params">
		/// The parameters of the procedure to call, contained
		/// in an object which implements the
		/// <see cref="XdrAble">XdrAble</see>
		/// interface.
		/// </param>
		/// <param name="result">The object receiving the result of the procedure call.</param>
		/// <exception cref="OncRpcException">if an ONC/RPC error occurs.</exception>
		/// <exception cref="org.acplt.oncrpc.OncRpcException"></exception>
		public override void call(int procedureNumber, int versionNumber, org.acplt.oncrpc.XdrAble
			 @params, org.acplt.oncrpc.XdrAble result)
		{
			lock (this)
			{
				// Refresh:
				for (int refreshesLeft = 1; refreshesLeft >= 0; --refreshesLeft)
				{
					//
					// First, build the ONC/RPC call header. Then put the sending
					// stream into a known state and encode the parameters to be
					// sent. Finally tell the encoding stream to send all its data
					// to the server. Then wait for an answer, receive it and decode
					// it. So that's the bottom line of what we do right here.
					//
					nextXid();
					org.acplt.oncrpc.OncRpcClientCallMessage callHeader = new org.acplt.oncrpc.OncRpcClientCallMessage
						(xid, program, versionNumber, procedureNumber, auth);
					org.acplt.oncrpc.OncRpcClientReplyMessage replyHeader = new org.acplt.oncrpc.OncRpcClientReplyMessage
						(auth);
					//
					// Send call message to server. If we receive an IOException,
					// then we'll throw the appropriate ONC/RPC (client) exception.
					// Note that we use a connected stream, so we don't need to
					// specify a destination when beginning serialization.
					//
					try
					{
                        socket.ReceiveTimeout = transmissionTimeout;
						sendingXdr.beginEncoding(null, 0);
						callHeader.xdrEncode(sendingXdr);
						@params.xdrEncode(sendingXdr);
						if (timeout != 0)
						{
							sendingXdr.endEncoding();
						}
						else
						{
							sendingXdr.endEncoding(false);
						}
					}
					catch (System.IO.IOException e)
					{
						throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTSEND
							, e.Message));
					}
					//
					// Receive reply message from server -- at least try to do so...
					// In case of batched calls we don't need no stinkin' answer, so
					// we can do other, more interesting things.
					//
					if (timeout == 0)
					{
						return;
					}
					try
					{
						//
						// Keep receiving until we get the matching reply.
						//
						while (true)
						{
                            socket.ReceiveTimeout = timeout;
							receivingXdr.beginDecoding();
                            socket.ReceiveTimeout = transmissionTimeout;
							//
							// First, pull off the reply message header of the
							// XDR stream. In case we also received a verifier
							// from the server and this verifier was invalid, broken
							// or tampered with, we will get an
							// OncRpcAuthenticationException right here, which will
							// propagate up to the caller. If the server reported
							// an authentication problem itself, then this will
							// be handled as any other rejected ONC/RPC call.
							//
							try
							{
								replyHeader.xdrDecode(receivingXdr);
							}
							catch (org.acplt.oncrpc.OncRpcException e)
							{
								//
								// ** SF bug #1262106 **
								//
								// We ran into some sort of trouble. Usually this will have
								// been a buffer underflow. Whatever, end the decoding process
								// and ensure this way that the next call has a chance to start
								// from a clean state.
								//
								receivingXdr.endDecoding();
								throw (e);
							}
							//
							// Only deserialize the result, if the reply matches the
							// call. Otherwise skip this record.
							//
							if (replyHeader.messageId == callHeader.messageId)
							{
								break;
							}
							receivingXdr.endDecoding();
						}
						//
						// Make sure that the call was accepted. In case of unsuccessful
						// calls, throw an exception, if it's not an authentication
						// exception. In that case try to refresh the credential first.
						//
						if (!replyHeader.successfullyAccepted())
						{
							receivingXdr.endDecoding();
							//
							// Check whether there was an authentication
							// problem. In this case first try to refresh the
							// credentials.
							//
							if ((refreshesLeft > 0) && (replyHeader.replyStatus == org.acplt.oncrpc.OncRpcReplyStatus
								.ONCRPC_MSG_DENIED) && (replyHeader.rejectStatus == org.acplt.oncrpc.OncRpcRejectStatus
								.ONCRPC_AUTH_ERROR) && (auth != null) && auth.canRefreshCred())
							{
								// continue Refresh;
								continue;
							}
							//
							// Nope. No chance. This gets tough.
							//
							throw (replyHeader.newException());
						}
						try
						{
							result.xdrDecode(receivingXdr);
						}
						catch (org.acplt.oncrpc.OncRpcException e)
						{
							//
							// ** SF bug #1262106 **
							//
							// We ran into some sort of trouble. Usually this will have
							// been a buffer underflow. Whatever, end the decoding process
							// and ensure this way that the next call has a chance to start
							// from a clean state.
							//
							receivingXdr.endDecoding();
							throw (e);
						}
						//
						// Free pending resources of buffer and exit the call loop,
						// returning the reply to the caller through the result
						// object.
						//
						receivingXdr.endDecoding();
						return;
					}
					catch (System.IO.IOException e)
					{
						//
						// Argh. Trouble with the transport. Seems like we can't
						// receive data. Gosh. Go away!
						//
						throw (new org.acplt.oncrpc.OncRpcException(org.acplt.oncrpc.OncRpcException.RPC_CANTRECV
							, e.Message));
					}
				}
			}
		}