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