You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			256 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			256 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|   | // <copyright> | |||
|  | // Copyright (c) Microsoft Corporation.  All rights reserved. | |||
|  | // </copyright> | |||
|  | 
 | |||
|  | namespace System.ServiceModel.Channels | |||
|  | { | |||
|  |     using System.Collections.Generic; | |||
|  |     using System.Diagnostics.CodeAnalysis; | |||
|  |     using System.Net; | |||
|  |     using System.Runtime; | |||
|  |     using System.ServiceModel; | |||
|  | 
 | |||
|  |     internal sealed class UdpReplyChannel : UdpChannelBase<RequestContext>, IReplyChannel | |||
|  |     { | |||
|  |         public UdpReplyChannel(UdpReplyChannelListener listener, UdpSocket[] sockets, EndpointAddress localAddress, Uri via, bool isMulticast) | |||
|  |             : base( | |||
|  |             listener,  | |||
|  |             listener.MessageEncoderFactory.Encoder,  | |||
|  |             listener.BufferManager, | |||
|  |             sockets,  | |||
|  |             listener.UdpTransportBindingElement.RetransmissionSettings, | |||
|  |             listener.UdpTransportBindingElement.MaxPendingMessagesTotalSize, | |||
|  |             localAddress, | |||
|  |             via, | |||
|  |             isMulticast, | |||
|  |             (int)listener.UdpTransportBindingElement.MaxReceivedMessageSize) | |||
|  |         { | |||
|  |             UdpOutputChannel udpOutputChannel = new ServerUdpOutputChannel( | |||
|  |                 listener, | |||
|  |                 listener.MessageEncoderFactory.Encoder, | |||
|  |                 listener.BufferManager, | |||
|  |                 sockets, | |||
|  |                 listener.UdpTransportBindingElement.RetransmissionSettings, | |||
|  |                 via, | |||
|  |                 isMulticast); | |||
|  | 
 | |||
|  |             this.SetOutputChannel(udpOutputChannel); | |||
|  |         } | |||
|  | 
 | |||
|  |         protected override bool IgnoreSerializationException | |||
|  |         { | |||
|  |             get | |||
|  |             { | |||
|  |                 return true; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         [SuppressMessage("Microsoft.StyleCop.CSharp.ReadabilityRules", "SA1100:DoNotPrefixCallsWithBaseUnlessLocalImplementationExists", Justification = "StyleCop 4.5 does not validate this rule properly.")] | |||
|  |         public override T GetProperty<T>() | |||
|  |         { | |||
|  |             if (typeof(T) == typeof(IReplyChannel)) | |||
|  |             { | |||
|  |                 return (T)(object)this; | |||
|  |             } | |||
|  | 
 | |||
|  |             return base.GetProperty<T>(); | |||
|  |         } | |||
|  | 
 | |||
|  |         public RequestContext ReceiveRequest() | |||
|  |         { | |||
|  |             return this.ReceiveRequest(this.DefaultReceiveTimeout); | |||
|  |         } | |||
|  | 
 | |||
|  |         public RequestContext ReceiveRequest(TimeSpan timeout) | |||
|  |         { | |||
|  |             if (timeout < TimeSpan.Zero) | |||
|  |             { | |||
|  |                 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); | |||
|  |             } | |||
|  | 
 | |||
|  |             this.ThrowPending(); | |||
|  |             return UdpReplyChannel.HelpReceiveRequest(this, timeout); | |||
|  |         } | |||
|  | 
 | |||
|  |         public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state) | |||
|  |         { | |||
|  |             return this.BeginReceiveRequest(this.DefaultReceiveTimeout, callback, state); | |||
|  |         } | |||
|  | 
 | |||
|  |         public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) | |||
|  |         { | |||
|  |             if (timeout < TimeSpan.Zero) | |||
|  |             { | |||
|  |                 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); | |||
|  |             } | |||
|  | 
 | |||
|  |             this.ThrowPending(); | |||
|  |             return UdpReplyChannel.HelpBeginReceiveRequest(this, timeout, callback, state); | |||
|  |         } | |||
|  | 
 | |||
|  |         public RequestContext EndReceiveRequest(IAsyncResult result) | |||
|  |         { | |||
|  |             return UdpReplyChannel.HelpEndReceiveRequest(result); | |||
|  |         } | |||
|  | 
 | |||
|  |         public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context) | |||
|  |         { | |||
|  |             if (timeout < TimeSpan.Zero) | |||
|  |             { | |||
|  |                 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); | |||
|  |             } | |||
|  | 
 | |||
|  |             this.ThrowPending(); | |||
|  |             return this.Dequeue(timeout, out context); | |||
|  |         } | |||
|  | 
 | |||
|  |         public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) | |||
|  |         { | |||
|  |             if (timeout < TimeSpan.Zero) | |||
|  |             { | |||
|  |                 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); | |||
|  |             } | |||
|  | 
 | |||
|  |             this.ThrowPending(); | |||
|  |             return this.BeginDequeue(timeout, callback, state); | |||
|  |         } | |||
|  | 
 | |||
|  |         public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context) | |||
|  |         { | |||
|  |             return this.EndDequeue(result, out context); | |||
|  |         } | |||
|  | 
 | |||
|  |         public bool WaitForRequest(TimeSpan timeout) | |||
|  |         { | |||
|  |             if (timeout < TimeSpan.Zero) | |||
|  |             { | |||
|  |                 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); | |||
|  |             } | |||
|  | 
 | |||
|  |             this.ThrowPending(); | |||
|  |             return this.WaitForItem(timeout); | |||
|  |         } | |||
|  | 
 | |||
|  |         public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state) | |||
|  |         { | |||
|  |             if (timeout < TimeSpan.Zero) | |||
|  |             { | |||
|  |                 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); | |||
|  |             } | |||
|  | 
 | |||
|  |             this.ThrowPending(); | |||
|  |             return this.BeginWaitForItem(timeout, callback, state); | |||
|  |         } | |||
|  | 
 | |||
|  |         public bool EndWaitForRequest(IAsyncResult result) | |||
|  |         { | |||
|  |             return this.EndWaitForItem(result); | |||
|  |         } | |||
|  | 
 | |||
|  |         internal override void FinishEnqueueMessage(Message message, Action dequeuedCallback, bool canDispatchOnThisThread) | |||
|  |         { | |||
|  |             UdpRequestContext udpRequestContext = new UdpRequestContext(this.UdpOutputChannel, message); | |||
|  |             this.EnqueueAndDispatch(udpRequestContext, dequeuedCallback, canDispatchOnThisThread); | |||
|  |         } | |||
|  | 
 | |||
|  |         private static RequestContext HelpReceiveRequest(IReplyChannel channel, TimeSpan timeout) | |||
|  |         { | |||
|  |             RequestContext requestContext; | |||
|  |             if (channel.TryReceiveRequest(timeout, out requestContext)) | |||
|  |             { | |||
|  |                 return requestContext; | |||
|  |             } | |||
|  |             else | |||
|  |             { | |||
|  |                 throw FxTrace.Exception.AsError(UdpReplyChannel.CreateReceiveRequestTimedOutException(channel, timeout)); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         private static IAsyncResult HelpBeginReceiveRequest(IReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state) | |||
|  |         { | |||
|  |             return new HelpReceiveRequestAsyncResult(channel, timeout, callback, state); | |||
|  |         } | |||
|  | 
 | |||
|  |         private static RequestContext HelpEndReceiveRequest(IAsyncResult result) | |||
|  |         { | |||
|  |             return HelpReceiveRequestAsyncResult.End(result); | |||
|  |         } | |||
|  | 
 | |||
|  |         private static Exception CreateReceiveRequestTimedOutException(IReplyChannel channel, TimeSpan timeout) | |||
|  |         { | |||
|  |             if (channel.LocalAddress != null) | |||
|  |             { | |||
|  |                 return new TimeoutException(SR.ReceiveRequestTimedOut(channel.LocalAddress.Uri.AbsoluteUri, timeout)); | |||
|  |             } | |||
|  |             else | |||
|  |             { | |||
|  |                 return new TimeoutException(SR.ReceiveRequestTimedOutNoLocalAddress(timeout)); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         private class HelpReceiveRequestAsyncResult : AsyncResult | |||
|  |         { | |||
|  |             private static AsyncCallback onReceiveRequest = Fx.ThunkCallback(new AsyncCallback(OnReceiveRequest)); | |||
|  |             private IReplyChannel channel; | |||
|  |             private TimeSpan timeout; | |||
|  |             private RequestContext requestContext; | |||
|  | 
 | |||
|  |             public HelpReceiveRequestAsyncResult(IReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state) | |||
|  |                 : base(callback, state) | |||
|  |             { | |||
|  |                 this.channel = channel; | |||
|  |                 this.timeout = timeout; | |||
|  |                 IAsyncResult result = channel.BeginTryReceiveRequest(timeout, onReceiveRequest, this); | |||
|  | 
 | |||
|  |                 if (!result.CompletedSynchronously) | |||
|  |                 { | |||
|  |                     return; | |||
|  |                 } | |||
|  | 
 | |||
|  |                 this.HandleReceiveRequestComplete(result); | |||
|  |                 this.Complete(true); | |||
|  |             } | |||
|  | 
 | |||
|  |             public static RequestContext End(IAsyncResult result) | |||
|  |             { | |||
|  |                 HelpReceiveRequestAsyncResult thisPtr = AsyncResult.End<HelpReceiveRequestAsyncResult>(result); | |||
|  |                 return thisPtr.requestContext; | |||
|  |             } | |||
|  | 
 | |||
|  |             private static void OnReceiveRequest(IAsyncResult result) | |||
|  |             { | |||
|  |                 if (result.CompletedSynchronously) | |||
|  |                 { | |||
|  |                     return; | |||
|  |                 } | |||
|  | 
 | |||
|  |                 HelpReceiveRequestAsyncResult thisPtr = (HelpReceiveRequestAsyncResult)result.AsyncState; | |||
|  |                 Exception completionException = null; | |||
|  |                 try | |||
|  |                 { | |||
|  |                     thisPtr.HandleReceiveRequestComplete(result); | |||
|  |                 } | |||
|  |                 catch (Exception e) | |||
|  |                 { | |||
|  |                     if (Fx.IsFatal(e)) | |||
|  |                     { | |||
|  |                         throw; | |||
|  |                     } | |||
|  | 
 | |||
|  |                     completionException = e; | |||
|  |                 } | |||
|  | 
 | |||
|  |                 thisPtr.Complete(false, completionException); | |||
|  |             } | |||
|  | 
 | |||
|  |             private void HandleReceiveRequestComplete(IAsyncResult result) | |||
|  |             { | |||
|  |                 if (!this.channel.EndTryReceiveRequest(result, out this.requestContext)) | |||
|  |                 { | |||
|  |                     throw FxTrace.Exception.AsError(UdpReplyChannel.CreateReceiveRequestTimedOutException(this.channel, this.timeout)); | |||
|  |                 } | |||
|  |             } | |||
|  |         } | |||
|  |     } | |||
|  | } |