/// <summary>Retrieves the parameters sent within an ONC/RPC call message.</summary>
 /// <remarks>
 /// Retrieves the parameters sent within an ONC/RPC call message. It also
 /// makes sure that the deserialization process is properly finished after
 /// the call parameters have been retrieved. Under the hood this method
 /// therefore calls
 /// <see cref="org.acplt.oncrpc.XdrDecodingStream.endDecoding()">org.acplt.oncrpc.XdrDecodingStream.endDecoding()
 ///     </see>
 /// to free any
 /// pending resources from the decoding stage.
 /// </remarks>
 /// <exception cref="org.acplt.oncrpc.OncRpcException">
 /// if an ONC/RPC exception occurs, like the data
 /// could not be successfully deserialized.
 /// </exception>
 /// <exception cref="System.IO.IOException">
 /// if an I/O exception occurs, like transmission
 /// failures over the network, etc.
 /// </exception>
 internal override void retrieveCall(org.acplt.oncrpc.XdrAble call)
 {
     call.xdrDecode(receivingXdr);
     if (pendingDecoding)
     {
         pendingDecoding = false;
         receivingXdr.endDecoding();
     }
 }
Ejemplo n.º 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));
             }
         }
     }
 }
Ejemplo n.º 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;
     }
 }