/// <summary>Send back an ONC/RPC reply to the original caller.</summary>
		/// <remarks>
		/// Send back an ONC/RPC reply to the original caller. This is rather a
		/// low-level method, typically not used by applications. Dispatcher handling
		/// ONC/RPC calls have to use the
		/// <see cref="OncRpcCallInformation.reply(org.acplt.oncrpc.XdrAble)">OncRpcCallInformation.reply(org.acplt.oncrpc.XdrAble)
		/// 	</see>
		/// method instead on the
		/// call object supplied to the handler.
		/// </remarks>
		/// <param name="callInfo">
		/// information about the original call, which are necessary
		/// to send back the reply to the appropriate caller.
		/// </param>
		/// <param name="state">
		/// ONC/RPC reply message header indicating success or failure
		/// and containing associated state information.
		/// </param>
		/// <param name="reply">
		/// If not <code>null</code>, then this parameter references
		/// the reply to be serialized after the reply message header.
		/// </param>
		/// <exception cref="org.acplt.oncrpc.OncRpcException">
		/// if an ONC/RPC exception occurs, like the data
		/// could not be successfully serialized.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// if an I/O exception occurs, like transmission
		/// failures over the network, etc.
		/// </exception>
		/// <seealso cref="OncRpcCallInformation">OncRpcCallInformation</seealso>
		/// <seealso cref="OncRpcDispatchable">OncRpcDispatchable</seealso>
		internal override void reply(org.acplt.oncrpc.server.OncRpcCallInformation callInfo
			, org.acplt.oncrpc.server.OncRpcServerReplyMessage state, org.acplt.oncrpc.XdrAble
			 reply)
		{
			beginEncoding(callInfo, state);
			if (reply != null)
			{
				reply.xdrEncode(sendingXdr);
			}
			endEncoding();
		}
		/// <summary>Begins the sending phase for ONC/RPC replies.</summary>
		/// <remarks>
		/// Begins the sending phase for ONC/RPC replies.
		/// This method belongs to the lower-level access pattern when handling
		/// ONC/RPC calls.
		/// </remarks>
		/// <param name="callInfo">
		/// Information about ONC/RPC call for which we are about
		/// to send back the reply.
		/// </param>
		/// <param name="state">ONC/RPC reply header indicating success or failure.</param>
		/// <exception cref="org.acplt.oncrpc.OncRpcException">
		/// if an ONC/RPC exception occurs, like the data
		/// could not be successfully serialized.
		/// </exception>
		/// <exception cref="System.IO.IOException">if an I/O exception occurs, like transmission
		/// 	</exception>
		internal override void beginEncoding(org.acplt.oncrpc.server.OncRpcCallInformation
			 callInfo, org.acplt.oncrpc.server.OncRpcServerReplyMessage state)
		{
			//
			// In case decoding has not been properly finished, do it now to
			// free up pending resources, etc.
			//
			if (pendingDecoding)
			{
				pendingDecoding = false;
				receivingXdr.endDecoding();
			}
			//
			// Now start encoding using the reply message header first...
			//
			pendingEncoding = true;
			sendingXdr.beginEncoding(callInfo.peerAddress, callInfo.peerPort);
			state.xdrEncode(sendingXdr);
		}
示例#3
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));
				}
			}
		}
示例#4
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;
            }
        }
示例#5
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));
					}
				}
			}
		}