コード例 #1
0
 /// <summary>Calls a remote procedure on an ONC/RPC server.</summary>
 /// <remarks>
 /// Calls a remote procedure on an ONC/RPC server.
 /// <p>The <code>OncRpcUdpClient</code> uses a similar timeout scheme as
 /// the genuine Sun C implementation of ONC/RPC: it starts with a timeout
 /// of one second when waiting for a reply. If no reply is received within
 /// this time frame, the client doubles the timeout, sends a new request
 /// and then waits again for a reply. In every case the client will wait
 /// no longer than the total timeout set through the
 /// <see cref="OncRpcClient.setTimeout(int)">OncRpcClient.setTimeout(int)</see>
 /// method.
 /// </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, XdrAble
                           @params, XdrAble result)
 {
     lock (this)
     {
         //Refresh:
         for (int refreshesLeft = 1; refreshesLeft >= 0; --refreshesLeft)
         {
             bool refreshFlag = false;
             //
             // 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();
             //
             // We only create our request message once and reuse it in case
             // retransmission should be necessary -- with the exception being
             // credential refresh. In this case we need to create a new
             // request message.
             //
             OncRpcClientCallMessage callHeader = new OncRpcClientCallMessage
                                                      (xid, program, versionNumber, procedureNumber, auth);
             OncRpcClientReplyMessage replyHeader = new OncRpcClientReplyMessage
                                                        (auth);
             long stopTime      = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) + timeout;
             int  resendTimeout = retransmissionTimeout;
             do
             {
                 //
                 // Now enter the great loop where we send calls out to the server
                 // and then sit there waiting for a reply. If none comes, we first
                 // resend our call after one second, then two seconds, four seconds,
                 // and so on, until we have reached the timeout for the call in total.
                 // Note that this setting only applies if exponential back-off
                 // retransmission has been selected. Per default we do not retransmit
                 // any more, in order to be in line with the SUNRPC implementations.
                 //
                 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 OncRpcException(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;
                 }
                 //
                 // Wait for an answer to arrive...
                 //
                 for (; ;)
                 {
                     try
                     {
                         long currentTimeout = stopTime - (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond);
                         if (currentTimeout > resendTimeout)
                         {
                             currentTimeout = resendTimeout;
                         }
                         else
                         {
                             if (currentTimeout < 1)
                             {
                                 //
                                 // as setSoTimeout interprets a timeout of zero as
                                 // infinite (?§$@%&!!!) we need to ensure that we
                                 // have a finite timeout, albeit maybe an infinitesimal
                                 // finite one.
                                 currentTimeout = 1;
                             }
                         }
                         socket.ReceiveTimeout = (int)currentTimeout;
                         receivingXdr.beginDecoding();
                         //
                         // Only accept incomming reply if it comes from the same
                         // address we've sent the ONC/RPC call to. Otherwise throw
                         // away the datagram packet containing the reply and start
                         // over again, waiting for the next reply to arrive.
                         //
                         if (host.Equals(receivingXdr.getSenderAddress()))
                         {
                             //
                             // 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
                             // 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())
                                 {
                                     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())
                                     {
                                         //
                                         // Think about using a TAB size of four ;)
                                         //
                                         // Another instance of "CONTINUE considered
                                         // useful"...
                                         //
                                         refreshFlag = true;
                                         break;
                                     }
                                     //  continue Refresh;
                                     //
                                     // Nope. No chance. This gets tough.
                                     //
                                     throw (replyHeader.newException());
                                 }
                                 //
                                 // The reply header is okay and the call had been
                                 // accepted by the ONC/RPC server, so we can now
                                 // proceed to decode the outcome of the RPC.
                                 //
                                 try
                                 {
                                     result.xdrDecode(receivingXdr);
                                 }
                                 catch (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 (SocketException)
                     {
                         //
                         // The message id did no match -- probably some
                         // old UDP datagram which just popped up from the
                         // middle of the Internet.
                         //
                         // Yet another case of "CONTINUE considered not
                         // harmful"...
                         //
                         // [Nothing to do here, just wait for the next datagram]
                         //
                         // IP address of received UDP datagram is not the same
                         // as the IP address of the ONC/RPC server.
                         //
                         // [Nothing to do here, just wait for the next datagram]
                         //
                         // Note that we only catch timeouts here, but no other
                         // exceptions. Those others will go up further until someone
                         // catches them. The timeouts are caught, so they can do no
                         // damage but instead we start another round of sending a
                         // request and waiting for a reply. Reminds me of NASA and
                         // their "Mars Polar Lander"...
                         //
                         // Note that we need to leave the inner waiting loop here,
                         // as we might need to resend the (lost) RPC request
                         // datagram.
                         //
                         //Console.Out.WriteLine("This is supposed to be ignored");
                         //Console.Out.WriteLine(e.Message);
                         //Console.Out.WriteLine(e.StackTrace);
                         break;
                     }
                     catch (IOException e)
                     {
                         //
                         // Argh. Trouble with the transport. Seems like we can't
                         // receive data. Gosh. Go away!
                         //
                         try
                         {
                             receivingXdr.endDecoding();
                         }
                         catch (IOException)
                         {
                         }
                         // skip UDP record
                         throw (new OncRpcException(OncRpcException.RPC_CANTRECV
                                                    , e.Message));
                     }
                     catch (org.acplt.oncrpc.OncRpcException e)
                     {
                         //
                         // Ooops. An ONC/RPC exception. Let us rethrow this one,
                         // as we won't have nothin' to do with it...
                         //
                         try
                         {
                             receivingXdr.endDecoding();
                         }
                         catch (System.IO.IOException)
                         {
                         }
                         // skip UDP record
                         //
                         // Well, in case we got not a *reply* RPC message back,
                         // we keep listening for messages.
                         //
                         if (e.getReason() != org.acplt.oncrpc.OncRpcException.RPC_WRONGMESSAGE)
                         {
                             throw (e);
                         }
                     }
                     //
                     // We can not make use of the reply we just received, so
                     // we need to dump it.
                     //
                     // 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 OncRpcException(OncRpcException.RPC_CANTRECV
                                                    , e.Message));
                     }
                 }
                 // jmw 12/18/2009 fix for refresh/continue in Java code
                 if (refreshFlag)
                 {
                     break;
                 }
                 //
                 // We only reach this code part beyond the inner waiting
                 // loop if we run in a timeout and might need to retransmit
                 //
                 // According to the retransmission strategy choosen, update the
                 // current retransmission (resending) timeout.
                 //
                 if (retransmissionMode == org.acplt.oncrpc.OncRpcUdpRetransmissionMode.EXPONENTIAL)
                 {
                     resendTimeout *= 2;
                 }
             }while (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond < stopTime);
             // jmw 12/18/2009 don't want to throw an exception here
             if (refreshFlag)
             {
                 continue;
             }
             //
             // That's it -- this shitty server does not talk to us. Now, due to
             // the indecent language used in the previous sentence, this software
             // can not be exported any longer to some countries of the world.
             // But this is surely not my problem, but rather theirs. So go away
             // and hide yourself in the dark with all your zombies (or maybe
             // kangaroos).
             //
             throw (new OncRpcTimeoutException());
         }
     }
 }
コード例 #2
0
ファイル: OncRpcUdpClient.cs プロジェクト: zjianliu/NFSClient
        /// <summary>Calls a remote procedure on an ONC/RPC server.</summary>
        /// <remarks>
        /// Calls a remote procedure on an ONC/RPC server.
        /// <p>The <code>OncRpcUdpClient</code> uses a similar timeout scheme as
        /// the genuine Sun C implementation of ONC/RPC: it starts with a timeout
        /// of one second when waiting for a reply. If no reply is received within
        /// this time frame, the client doubles the timeout, sends a new request
        /// and then waits again for a reply. In every case the client will wait
        /// no longer than the total timeout set through the
        /// <see cref="OncRpcClient.setTimeout(int)">OncRpcClient.setTimeout(int)</see>
        /// method.
        /// </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, XdrAble
			 @params, XdrAble result)
        {
            lock (this)
            {
                //Refresh:
                for (int refreshesLeft = 1; refreshesLeft >= 0; --refreshesLeft)
                {
                    bool refreshFlag = false;
                    //
                    // 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();
                    //
                    // We only create our request message once and reuse it in case
                    // retransmission should be necessary -- with the exception being
                    // credential refresh. In this case we need to create a new
                    // request message.
                    //
                    OncRpcClientCallMessage callHeader = new OncRpcClientCallMessage
                        (xid, program, versionNumber, procedureNumber, auth);
                    OncRpcClientReplyMessage replyHeader = new OncRpcClientReplyMessage
                        (auth);
                    long stopTime = (DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond) + timeout;
                    int resendTimeout = retransmissionTimeout;
                    do
                    {
                        //
                        // Now enter the great loop where we send calls out to the server
                        // and then sit there waiting for a reply. If none comes, we first
                        // resend our call after one second, then two seconds, four seconds,
                        // and so on, until we have reached the timeout for the call in total.
                        // Note that this setting only applies if exponential back-off
                        // retransmission has been selected. Per default we do not retransmit
                        // any more, in order to be in line with the SUNRPC implementations.
                        //
                        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 OncRpcException(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;
                        }
                        //
                        // Wait for an answer to arrive...
                        //
                        for (; ; )
                        {
                            try
                            {
                                long currentTimeout = stopTime - (DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond);
                                if (currentTimeout > resendTimeout)
                                {
                                    currentTimeout = resendTimeout;
                                }
                                else
                                {
                                    if (currentTimeout < 1)
                                    {
                                        //
                                        // as setSoTimeout interprets a timeout of zero as
                                        // infinite (?§$@%&!!!) we need to ensure that we
                                        // have a finite timeout, albeit maybe an infinitesimal
                                        // finite one.
                                        currentTimeout = 1;
                                    }
                                }
                                socket.ReceiveTimeout = (int) currentTimeout;
                                receivingXdr.beginDecoding();
                                //
                                // Only accept incomming reply if it comes from the same
                                // address we've sent the ONC/RPC call to. Otherwise throw
                                // away the datagram packet containing the reply and start
                                // over again, waiting for the next reply to arrive.
                                //
                                if (host.Equals(receivingXdr.getSenderAddress()))
                                {
                                    //
                                    // 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
                                    // 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())
                                        {
                                            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())
                                            {
                                                //
                                                // Think about using a TAB size of four ;)
                                                //
                                                // Another instance of "CONTINUE considered
                                                // useful"...
                                                //
                                                refreshFlag = true;
                                                break;
                                            }
                                            //  continue Refresh;
                                            //
                                            // Nope. No chance. This gets tough.
                                            //
                                            throw (replyHeader.newException());
                                        }
                                        //
                                        // The reply header is okay and the call had been
                                        // accepted by the ONC/RPC server, so we can now
                                        // proceed to decode the outcome of the RPC.
                                        //
                                        try
                                        {
                                            result.xdrDecode(receivingXdr);
                                        }
                                        catch (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 (SocketException)
                            {
                                //
                                // The message id did no match -- probably some
                                // old UDP datagram which just popped up from the
                                // middle of the Internet.
                                //
                                // Yet another case of "CONTINUE considered not
                                // harmful"...
                                //
                                // [Nothing to do here, just wait for the next datagram]
                                //
                                // IP address of received UDP datagram is not the same
                                // as the IP address of the ONC/RPC server.
                                //
                                // [Nothing to do here, just wait for the next datagram]
                                //
                                // Note that we only catch timeouts here, but no other
                                // exceptions. Those others will go up further until someone
                                // catches them. The timeouts are caught, so they can do no
                                // damage but instead we start another round of sending a
                                // request and waiting for a reply. Reminds me of NASA and
                                // their "Mars Polar Lander"...
                                //
                                // Note that we need to leave the inner waiting loop here,
                                // as we might need to resend the (lost) RPC request
                                // datagram.
                                //
                                //Console.Out.WriteLine("This is supposed to be ignored");
                                //Console.Out.WriteLine(e.Message);
                                //Console.Out.WriteLine(e.StackTrace);
                                break;
                            }
                            catch (IOException e)
                            {
                                //
                                // Argh. Trouble with the transport. Seems like we can't
                                // receive data. Gosh. Go away!
                                //
                                try
                                {
                                    receivingXdr.endDecoding();
                                }
                                catch (IOException)
                                {
                                }
                                // skip UDP record
                                throw (new OncRpcException(OncRpcException.RPC_CANTRECV
                                    , e.Message));
                            }
                            catch (org.acplt.oncrpc.OncRpcException e)
                            {
                                //
                                // Ooops. An ONC/RPC exception. Let us rethrow this one,
                                // as we won't have nothin' to do with it...
                                //
                                try
                                {
                                    receivingXdr.endDecoding();
                                }
                                catch (System.IO.IOException)
                                {
                                }
                                // skip UDP record
                                //
                                // Well, in case we got not a *reply* RPC message back,
                                // we keep listening for messages.
                                //
                                if (e.getReason() != org.acplt.oncrpc.OncRpcException.RPC_WRONGMESSAGE)
                                {
                                    throw (e);
                                }
                            }
                            //
                            // We can not make use of the reply we just received, so
                            // we need to dump it.
                            //
                            // 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 OncRpcException(OncRpcException.RPC_CANTRECV
                                    , e.Message));
                            }
                        }
                        // jmw 12/18/2009 fix for refresh/continue in Java code
                        if (refreshFlag)
                        {
                            break;
                        }
                        //
                        // We only reach this code part beyond the inner waiting
                        // loop if we run in a timeout and might need to retransmit
                        //
                        // According to the retransmission strategy choosen, update the
                        // current retransmission (resending) timeout.
                        //
                        if (retransmissionMode == org.acplt.oncrpc.OncRpcUdpRetransmissionMode.EXPONENTIAL)
                        {
                            resendTimeout *= 2;
                        }
                    }
                    while (DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond < stopTime);
                    // jmw 12/18/2009 don't want to throw an exception here
                    if (refreshFlag)
                    {
                        continue;
                    }
                    //
                    // That's it -- this shitty server does not talk to us. Now, due to
                    // the indecent language used in the previous sentence, this software
                    // can not be exported any longer to some countries of the world.
                    // But this is surely not my problem, but rather theirs. So go away
                    // and hide yourself in the dark with all your zombies (or maybe
                    // kangaroos).
                    //
                    throw (new OncRpcTimeoutException());
                }
            }
        }