1 //---------------------------------------------------------------- 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //---------------------------------------------------------------- 4 5 namespace System.ServiceModel.Channels 6 { 7 using System; 8 using System.Collections.Generic; 9 using System.Globalization; 10 using System.Net; 11 using System.Net.Sockets; 12 using System.Runtime; 13 using System.Runtime.Diagnostics; 14 using System.ServiceModel.Diagnostics; 15 using System.Threading; 16 using System.Xml; 17 18 abstract class UdpDuplexChannel : UdpChannelBase<Message>, IDuplexChannel 19 { UdpDuplexChannel( ChannelManagerBase channelMananger, MessageEncoder encoder, BufferManager bufferManager, UdpSocket[] sendSockets, UdpRetransmissionSettings retransmissionSettings, long maxPendingMessagesTotalSize, EndpointAddress localAddress, Uri via, bool isMulticast, int maxReceivedMessageSize)20 protected UdpDuplexChannel( 21 ChannelManagerBase channelMananger, 22 MessageEncoder encoder, 23 BufferManager bufferManager, 24 UdpSocket[] sendSockets, 25 UdpRetransmissionSettings retransmissionSettings, 26 long maxPendingMessagesTotalSize, 27 EndpointAddress localAddress, 28 Uri via, 29 bool isMulticast, 30 int maxReceivedMessageSize) 31 : base(channelMananger, encoder, bufferManager, sendSockets, retransmissionSettings, maxPendingMessagesTotalSize, localAddress, via, isMulticast, maxReceivedMessageSize) 32 { 33 } 34 35 public virtual EndpointAddress RemoteAddress 36 { 37 get { return null; } 38 } 39 GetProperty()40 public override T GetProperty<T>() 41 { 42 if (typeof(T) == typeof(IDuplexChannel)) 43 { 44 return (T)(object)this; 45 } 46 47 return base.GetProperty<T>(); 48 } 49 BeginSend(Message message, AsyncCallback callback, object state)50 public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state) 51 { 52 return this.BeginSend(message, this.DefaultSendTimeout, callback, state); 53 } 54 BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)55 public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state) 56 { 57 ThrowIfDisposedOrNotOpen(); 58 59 if (message is NullMessage) 60 { 61 return new CompletedAsyncResult(callback, state); 62 } 63 AddHeadersTo(message); 64 return this.UdpOutputChannel.BeginSend(message, timeout, callback, state); 65 } 66 EndSend(IAsyncResult result)67 public void EndSend(IAsyncResult result) 68 { 69 if (result is CompletedAsyncResult) 70 { 71 CompletedAsyncResult.End(result); 72 } 73 else 74 { 75 this.UdpOutputChannel.EndSend(result); 76 } 77 } 78 Send(Message message)79 public void Send(Message message) 80 { 81 this.Send(message, this.DefaultSendTimeout); 82 } 83 Send(Message message, TimeSpan timeout)84 public void Send(Message message, TimeSpan timeout) 85 { 86 if (message is NullMessage) 87 { 88 return; 89 } 90 91 this.UdpOutputChannel.Send(message, timeout); 92 } 93 Receive()94 public Message Receive() 95 { 96 return this.Receive(this.DefaultReceiveTimeout); 97 } 98 Receive(TimeSpan timeout)99 public Message Receive(TimeSpan timeout) 100 { 101 if (timeout < TimeSpan.Zero) 102 { 103 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); 104 } 105 106 this.ThrowPending(); 107 return InputChannel.HelpReceive(this, timeout); 108 } 109 BeginReceive(AsyncCallback callback, object state)110 public IAsyncResult BeginReceive(AsyncCallback callback, object state) 111 { 112 return this.BeginReceive(this.DefaultReceiveTimeout, callback, state); 113 } 114 BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)115 public IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state) 116 { 117 if (timeout < TimeSpan.Zero) 118 { 119 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); 120 } 121 122 this.ThrowPending(); 123 return InputChannel.HelpBeginReceive(this, timeout, callback, state); 124 } 125 EndReceive(IAsyncResult result)126 public Message EndReceive(IAsyncResult result) 127 { 128 return InputChannel.HelpEndReceive(result); 129 } 130 TryReceive(TimeSpan timeout, out Message message)131 public bool TryReceive(TimeSpan timeout, out Message message) 132 { 133 if (timeout < TimeSpan.Zero) 134 { 135 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); 136 } 137 138 this.ThrowPending(); 139 return base.Dequeue(timeout, out message); 140 } 141 BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)142 public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state) 143 { 144 if (timeout < TimeSpan.Zero) 145 { 146 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); 147 } 148 149 this.ThrowPending(); 150 return base.BeginDequeue(timeout, callback, state); 151 } 152 EndTryReceive(IAsyncResult result, out Message message)153 public bool EndTryReceive(IAsyncResult result, out Message message) 154 { 155 return base.EndDequeue(result, out message); 156 } 157 WaitForMessage(TimeSpan timeout)158 public bool WaitForMessage(TimeSpan timeout) 159 { 160 if (timeout < TimeSpan.Zero) 161 { 162 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); 163 } 164 165 this.ThrowPending(); 166 return base.WaitForItem(timeout); 167 } 168 BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)169 public IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state) 170 { 171 if (timeout < TimeSpan.Zero) 172 { 173 throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("timeout", timeout, SR.TimeoutOutOfRange0)); 174 } 175 176 this.ThrowPending(); 177 return base.BeginWaitForItem(timeout, callback, state); 178 } 179 EndWaitForMessage(IAsyncResult result)180 public bool EndWaitForMessage(IAsyncResult result) 181 { 182 return base.EndWaitForItem(result); 183 } 184 FinishEnqueueMessage(Message message, Action dequeuedCallback, bool canDispatchOnThisThread)185 internal override void FinishEnqueueMessage(Message message, Action dequeuedCallback, bool canDispatchOnThisThread) 186 { 187 if (!this.IsMulticast) 188 { 189 //When using Multicast, we can't assume that receiving one message means that we are done receiving messages. 190 //For example, Discovery will send one message out and receive n responses that match. Because of this, we 191 //can only short circuit retransmission when using unicast. 192 this.UdpOutputChannel.CancelRetransmission(message.Headers.RelatesTo); 193 } 194 this.EnqueueAndDispatch(message, dequeuedCallback, canDispatchOnThisThread); 195 } 196 } 197 } 198