1 //----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------------------
4 namespace System.ServiceModel.Channels
5 {
6     using System.Collections.Generic;
7     using System.Runtime;
8     using System.ServiceModel;
9     using System.ServiceModel.Description;
10     using System.ServiceModel.Diagnostics;
11     using System.ServiceModel.Security;
12 
13     sealed class TransactionChannelListener<TChannel> : DelegatingChannelListener<TChannel>, ITransactionChannelManager
14         where TChannel : class, IChannel
15     {
16         TransactionFlowOption flowIssuedTokens;
17         Dictionary<DirectionalAction, TransactionFlowOption> dictionary;
18         SecurityStandardsManager standardsManager;
19         TransactionProtocol transactionProtocol;
20 
TransactionChannelListener(TransactionProtocol transactionProtocol, IDefaultCommunicationTimeouts timeouts, Dictionary<DirectionalAction, TransactionFlowOption> dictionary, IChannelListener<TChannel> innerListener)21         public TransactionChannelListener(TransactionProtocol transactionProtocol, IDefaultCommunicationTimeouts timeouts, Dictionary<DirectionalAction, TransactionFlowOption> dictionary, IChannelListener<TChannel> innerListener)
22             : base(timeouts, innerListener)
23         {
24             this.dictionary = dictionary;
25             this.TransactionProtocol = transactionProtocol;
26             this.Acceptor = new TransactionChannelAcceptor(this, innerListener);
27 
28             this.standardsManager = SecurityStandardsHelper.CreateStandardsManager(this.TransactionProtocol);
29         }
30 
31         public TransactionProtocol TransactionProtocol
32         {
33             get
34             {
35                 return this.transactionProtocol;
36             }
37             set
38             {
39                 if (!TransactionProtocol.IsDefined(value))
40                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
41                         new ArgumentException(SR.GetString(SR.SFxBadTransactionProtocols)));
42                 this.transactionProtocol = value;
43             }
44         }
45 
46         public TransactionFlowOption FlowIssuedTokens
47         {
48             get { return this.flowIssuedTokens; }
49             set { this.flowIssuedTokens = value; }
50         }
51 
52         public SecurityStandardsManager StandardsManager
53         {
54             get { return this.standardsManager; }
55             set { this.standardsManager = (value != null ? value : SecurityStandardsHelper.CreateStandardsManager(this.transactionProtocol)); }
56         }
57 
58         public IDictionary<DirectionalAction, TransactionFlowOption> Dictionary
59         {
60             get { return this.dictionary; }
61         }
62 
GetTransaction(MessageDirection direction, string action)63         public TransactionFlowOption GetTransaction(MessageDirection direction, string action)
64         {
65             TransactionFlowOption txFlow;
66             if (dictionary.TryGetValue(new DirectionalAction(direction, action), out txFlow))
67                 return txFlow;
68 
69             // Look for the wildcard action
70             if (dictionary.TryGetValue(new DirectionalAction(direction, MessageHeaders.WildcardAction), out txFlow))
71                 return txFlow;
72 
73             return TransactionFlowOption.NotAllowed;
74         }
75 
76         class TransactionChannelAcceptor : LayeredChannelAcceptor<TChannel, TChannel>
77         {
78             TransactionChannelListener<TChannel> listener;
79 
TransactionChannelAcceptor(TransactionChannelListener<TChannel> listener, IChannelListener<TChannel> innerListener)80             public TransactionChannelAcceptor(TransactionChannelListener<TChannel> listener, IChannelListener<TChannel> innerListener)
81                 : base(listener, innerListener)
82             {
83                 this.listener = listener;
84             }
85 
OnAcceptChannel(TChannel innerChannel)86             override protected TChannel OnAcceptChannel(TChannel innerChannel)
87             {
88                 if (typeof(TChannel) == typeof(IInputSessionChannel))
89                 {
90                     return (TChannel)(object)new TransactionInputSessionChannel(this.listener, (IInputSessionChannel)innerChannel);
91                 }
92                 if (typeof(TChannel) == typeof(IDuplexSessionChannel))
93                 {
94                     return (TChannel)(object)new TransactionDuplexSessionChannel(this.listener, (IDuplexSessionChannel)innerChannel);
95                 }
96                 else if (typeof(TChannel) == typeof(IInputChannel))
97                 {
98                     return (TChannel)(object)new TransactionInputChannel(this.listener, (IInputChannel)innerChannel);
99                 }
100                 else if (typeof(TChannel) == typeof(IReplyChannel))
101                 {
102                     return (TChannel)(object)new TransactionReplyChannel(this.listener, (IReplyChannel)innerChannel);
103                 }
104                 else if (typeof(TChannel) == typeof(IReplySessionChannel))
105                 {
106                     return (TChannel)(object)new TransactionReplySessionChannel(this.listener, (IReplySessionChannel)innerChannel);
107                 }
108                 else if (typeof(TChannel) == typeof(IDuplexChannel))
109                 {
110                     return (TChannel)(object)new TransactionDuplexChannel(this.listener, (IDuplexChannel)innerChannel);
111                 }
112                 else
113                 {
114                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(listener.CreateChannelTypeNotSupportedException(typeof(TChannel)));
115                 }
116             }
117         }
118 
119 
120         //==============================================================
121         //                Transaction channel classes
122         //==============================================================
123 
124         sealed class TransactionInputChannel : TransactionReceiveChannelGeneric<IInputChannel>
125         {
TransactionInputChannel(ChannelManagerBase channelManager, IInputChannel innerChannel)126             public TransactionInputChannel(ChannelManagerBase channelManager, IInputChannel innerChannel)
127                 : base(channelManager, innerChannel, MessageDirection.Input)
128             {
129             }
130         }
131 
132         sealed class TransactionReplyChannel : TransactionReplyChannelGeneric<IReplyChannel>
133         {
TransactionReplyChannel(ChannelManagerBase channelManager, IReplyChannel innerChannel)134             public TransactionReplyChannel(ChannelManagerBase channelManager, IReplyChannel innerChannel)
135                 : base(channelManager, innerChannel)
136             {
137             }
138         }
139 
140         sealed class TransactionDuplexChannel : TransactionInputDuplexChannelGeneric<IDuplexChannel>
141         {
TransactionDuplexChannel(ChannelManagerBase channelManager, IDuplexChannel innerChannel)142             public TransactionDuplexChannel(ChannelManagerBase channelManager, IDuplexChannel innerChannel)
143                 : base(channelManager, innerChannel)
144             {
145             }
146         }
147 
148         sealed class TransactionInputSessionChannel : TransactionReceiveChannelGeneric<IInputSessionChannel>, IInputSessionChannel
149         {
TransactionInputSessionChannel(ChannelManagerBase channelManager, IInputSessionChannel innerChannel)150             public TransactionInputSessionChannel(ChannelManagerBase channelManager, IInputSessionChannel innerChannel)
151                 : base(channelManager, innerChannel, MessageDirection.Input)
152             {
153             }
154 
155             public IInputSession Session { get { return InnerChannel.Session; } }
156         }
157 
158         sealed class TransactionReplySessionChannel : TransactionReplyChannelGeneric<IReplySessionChannel>, IReplySessionChannel
159         {
TransactionReplySessionChannel(ChannelManagerBase channelManager, IReplySessionChannel innerChannel)160             public TransactionReplySessionChannel(ChannelManagerBase channelManager, IReplySessionChannel innerChannel)
161                 : base(channelManager, innerChannel)
162             {
163             }
164 
165             public IInputSession Session { get { return InnerChannel.Session; } }
166         }
167 
168         sealed class TransactionDuplexSessionChannel : TransactionInputDuplexChannelGeneric<IDuplexSessionChannel>, IDuplexSessionChannel
169         {
TransactionDuplexSessionChannel(ChannelManagerBase channelManager, IDuplexSessionChannel innerChannel)170             public TransactionDuplexSessionChannel(ChannelManagerBase channelManager, IDuplexSessionChannel innerChannel)
171                 : base(channelManager, innerChannel)
172             {
173             }
174 
175             public IDuplexSession Session { get { return InnerChannel.Session; } }
176         }
177     }
178 
179 
180     sealed class TransactionRequestContext : RequestContextBase
181     {
182         ITransactionChannel transactionChannel;
183         RequestContext innerContext;
184 
TransactionRequestContext(ITransactionChannel transactionChannel, ChannelBase channel, RequestContext innerContext, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout)185         public TransactionRequestContext(ITransactionChannel transactionChannel, ChannelBase channel, RequestContext innerContext,
186             TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout)
187             : base(innerContext.RequestMessage, defaultCloseTimeout, defaultSendTimeout)
188         {
189             this.transactionChannel = transactionChannel;
190             this.innerContext = innerContext;
191         }
192 
OnAbort()193         protected override void OnAbort()
194         {
195             if (this.innerContext == null)
196             {
197                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName));
198             }
199 
200             this.innerContext.Abort();
201         }
202 
OnBeginReply(Message message, TimeSpan timeout, AsyncCallback callback, object state)203         protected override IAsyncResult OnBeginReply(Message message, TimeSpan timeout, AsyncCallback callback, object state)
204         {
205             if (this.innerContext == null)
206             {
207                 throw TraceUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName), message);
208             }
209 
210             if (message != null)
211             {
212                 this.transactionChannel.WriteIssuedTokens(message, MessageDirection.Output);
213             }
214             return this.innerContext.BeginReply(message, timeout, callback, state);
215         }
216 
217 
OnClose(TimeSpan timeout)218         protected override void OnClose(TimeSpan timeout)
219         {
220             if (this.innerContext == null)
221             {
222                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName));
223             }
224 
225             this.innerContext.Close(timeout);
226         }
227 
OnEndReply(IAsyncResult result)228         protected override void OnEndReply(IAsyncResult result)
229         {
230             if (this.innerContext == null)
231             {
232                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName));
233             }
234 
235             this.innerContext.EndReply(result);
236         }
237 
OnReply(Message message, TimeSpan timeout)238         protected override void OnReply(Message message, TimeSpan timeout)
239         {
240             if (this.innerContext == null)
241             {
242                 throw TraceUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName), message);
243             }
244 
245             if (message != null)
246             {
247                 this.transactionChannel.WriteIssuedTokens(message, MessageDirection.Output);
248             }
249             this.innerContext.Reply(message, timeout);
250         }
251     }
252 
253 
254 
255     //==============================================================
256     //                Transaction channel base generic classes
257     //==============================================================
258 
259     class TransactionReceiveChannelGeneric<TChannel> : TransactionChannel<TChannel>, IInputChannel
260         where TChannel : class, IInputChannel
261     {
262         MessageDirection receiveMessageDirection;
263 
TransactionReceiveChannelGeneric(ChannelManagerBase channelManager, TChannel innerChannel, MessageDirection direction)264         public TransactionReceiveChannelGeneric(ChannelManagerBase channelManager, TChannel innerChannel, MessageDirection direction)
265             : base(channelManager, innerChannel)
266         {
267             this.receiveMessageDirection = direction;
268         }
269 
270         public EndpointAddress LocalAddress
271         {
272             get
273             {
274                 return InnerChannel.LocalAddress;
275             }
276         }
277 
Receive()278         public Message Receive()
279         {
280             return this.Receive(this.DefaultReceiveTimeout);
281         }
282 
Receive(TimeSpan timeout)283         public Message Receive(TimeSpan timeout)
284         {
285             return InputChannel.HelpReceive(this, timeout);
286         }
287 
BeginReceive(AsyncCallback callback, object state)288         public IAsyncResult BeginReceive(AsyncCallback callback, object state)
289         {
290             return this.BeginReceive(this.DefaultReceiveTimeout, callback, state);
291         }
292 
BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)293         public IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)
294         {
295             return InputChannel.HelpBeginReceive(this, timeout, callback, state);
296         }
297 
EndReceive(IAsyncResult result)298         public Message EndReceive(IAsyncResult result)
299         {
300             return InputChannel.HelpEndReceive(result);
301         }
302 
BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)303         public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
304         {
305             return InnerChannel.BeginTryReceive(timeout, callback, state);
306         }
307 
EndTryReceive(IAsyncResult asyncResult, out Message message)308         public virtual bool EndTryReceive(IAsyncResult asyncResult, out Message message)
309         {
310             if (!InnerChannel.EndTryReceive(asyncResult, out message))
311             {
312                 return false;
313             }
314 
315             if (message != null)
316             {
317                 ReadTransactionDataFromMessage(message, this.receiveMessageDirection);
318             }
319 
320             return true;
321         }
322 
TryReceive(TimeSpan timeout, out Message message)323         public virtual bool TryReceive(TimeSpan timeout, out Message message)
324         {
325             if (!InnerChannel.TryReceive(timeout, out message))
326             {
327                 return false;
328             }
329 
330             if (message != null)
331             {
332                 ReadTransactionDataFromMessage(message, this.receiveMessageDirection);
333             }
334 
335             return true;
336         }
337 
WaitForMessage(TimeSpan timeout)338         public bool WaitForMessage(TimeSpan timeout)
339         {
340             return InnerChannel.WaitForMessage(timeout);
341         }
342 
BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)343         public IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)
344         {
345             return InnerChannel.BeginWaitForMessage(timeout, callback, state);
346         }
347 
EndWaitForMessage(IAsyncResult result)348         public bool EndWaitForMessage(IAsyncResult result)
349         {
350             return InnerChannel.EndWaitForMessage(result);
351         }
352     }
353 
354 
355     //-------------------------------------------------------------
356     class TransactionReplyChannelGeneric<TChannel> : TransactionChannel<TChannel>, IReplyChannel
357         where TChannel : class, IReplyChannel
358     {
359 
TransactionReplyChannelGeneric(ChannelManagerBase channelManager, TChannel innerChannel)360         public TransactionReplyChannelGeneric(ChannelManagerBase channelManager, TChannel innerChannel)
361             : base(channelManager, innerChannel)
362         {
363         }
364 
365         public EndpointAddress LocalAddress
366         {
367             get
368             {
369                 return InnerChannel.LocalAddress;
370             }
371         }
372 
ReceiveRequest()373         public RequestContext ReceiveRequest()
374         {
375             return this.ReceiveRequest(this.DefaultReceiveTimeout);
376         }
377 
ReceiveRequest(TimeSpan timeout)378         public RequestContext ReceiveRequest(TimeSpan timeout)
379         {
380             return ReplyChannel.HelpReceiveRequest(this, timeout);
381         }
382 
BeginReceiveRequest(AsyncCallback callback, object state)383         public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state)
384         {
385             return this.BeginReceiveRequest(this.DefaultReceiveTimeout, callback, state);
386         }
387 
BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)388         public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
389         {
390             return ReplyChannel.HelpBeginReceiveRequest(this, timeout, callback, state);
391         }
392 
EndReceiveRequest(IAsyncResult result)393         public RequestContext EndReceiveRequest(IAsyncResult result)
394         {
395             return ReplyChannel.HelpEndReceiveRequest(result);
396         }
397 
BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)398         public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
399         {
400             ReceiveTimeoutAsyncResult result = new ReceiveTimeoutAsyncResult(timeout, callback, state);
401             result.InnerResult = this.InnerChannel.BeginTryReceiveRequest(timeout, result.InnerCallback, result.InnerState);
402             return result;
403         }
404 
FinishReceiveRequest(RequestContext innerContext, TimeSpan timeout)405         RequestContext FinishReceiveRequest(RequestContext innerContext, TimeSpan timeout)
406         {
407             if (innerContext == null)
408                 return null;
409 
410             try
411             {
412                 this.ReadTransactionDataFromMessage(innerContext.RequestMessage, MessageDirection.Input);
413             }
414             catch (FaultException fault)
415             {
416                 string faultAction = fault.Action ?? innerContext.RequestMessage.Version.Addressing.DefaultFaultAction;
417                 Message reply = Message.CreateMessage(innerContext.RequestMessage.Version, fault.CreateMessageFault(), faultAction);
418                 try
419                 {
420                     innerContext.Reply(reply, timeout);
421                 }
422                 finally
423                 {
424                     reply.Close();
425                 }
426                 throw;
427             }
428 
429             return new TransactionRequestContext(this, this, innerContext, this.DefaultCloseTimeout, this.DefaultSendTimeout);
430         }
431 
432 
EndTryReceiveRequest(IAsyncResult asyncResult, out RequestContext requestContext)433         public bool EndTryReceiveRequest(IAsyncResult asyncResult, out RequestContext requestContext)
434         {
435             if (asyncResult == null)
436                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("asyncResult");
437 
438             ReceiveTimeoutAsyncResult result = asyncResult as ReceiveTimeoutAsyncResult;
439             if (result == null)
440                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.AsyncEndCalledWithAnIAsyncResult)));
441 
442             RequestContext innerContext;
443             if (InnerChannel.EndTryReceiveRequest(result.InnerResult, out innerContext))
444             {
445                 requestContext = FinishReceiveRequest(innerContext, result.TimeoutHelper.RemainingTime());
446                 return true;
447             }
448             else
449             {
450                 requestContext = null;
451                 return false;
452             }
453         }
454 
TryReceiveRequest(TimeSpan timeout, out RequestContext requestContext)455         public bool TryReceiveRequest(TimeSpan timeout, out RequestContext requestContext)
456         {
457             TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
458 
459             RequestContext innerContext;
460             if (InnerChannel.TryReceiveRequest(timeoutHelper.RemainingTime(), out innerContext))
461             {
462                 requestContext = FinishReceiveRequest(innerContext, timeoutHelper.RemainingTime());
463                 return true;
464             }
465             else
466             {
467                 requestContext = null;
468                 return false;
469             }
470         }
471 
WaitForRequest(TimeSpan timeout)472         public bool WaitForRequest(TimeSpan timeout)
473         {
474             return InnerChannel.WaitForRequest(timeout);
475         }
476 
BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)477         public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)
478         {
479             return InnerChannel.BeginWaitForRequest(timeout, callback, state);
480         }
481 
EndWaitForRequest(IAsyncResult result)482         public bool EndWaitForRequest(IAsyncResult result)
483         {
484             return InnerChannel.EndWaitForRequest(result);
485         }
486     }
487 
488 
489     //-------------------------------------------------------------
490     class TransactionInputDuplexChannelGeneric<TChannel> : TransactionDuplexChannelGeneric<TChannel>
491         where TChannel : class, IDuplexChannel
492     {
TransactionInputDuplexChannelGeneric(ChannelManagerBase channelManager, TChannel innerChannel)493         public TransactionInputDuplexChannelGeneric(ChannelManagerBase channelManager, TChannel innerChannel)
494             : base(channelManager, innerChannel, MessageDirection.Input)
495         {
496         }
497     }
498 
499 
500     //-------------------------------------------------------------
501     class TransactionDuplexChannelGeneric<TChannel> : TransactionReceiveChannelGeneric<TChannel>, IDuplexChannel
502         where TChannel : class, IDuplexChannel
503     {
504         MessageDirection sendMessageDirection;
505 
TransactionDuplexChannelGeneric(ChannelManagerBase channelManager, TChannel innerChannel, MessageDirection direction)506         public TransactionDuplexChannelGeneric(ChannelManagerBase channelManager, TChannel innerChannel, MessageDirection direction)
507             : base(channelManager, innerChannel, direction)
508         {
509             if (direction == MessageDirection.Input)
510             {
511                 this.sendMessageDirection = MessageDirection.Output;
512             }
513             else
514             {
515                 this.sendMessageDirection = MessageDirection.Input;
516             }
517         }
518 
519         public EndpointAddress RemoteAddress
520         {
521             get
522             {
523                 return InnerChannel.RemoteAddress;
524             }
525         }
526 
527         public Uri Via
528         {
529             get
530             {
531                 return InnerChannel.Via;
532             }
533         }
534 
ReadTransactionDataFromMessage(Message message, MessageDirection direction)535         public override void ReadTransactionDataFromMessage(Message message, MessageDirection direction)
536         {
537             try
538             {
539                 base.ReadTransactionDataFromMessage(message, direction);
540             }
541             catch (FaultException fault)
542             {
543                 Message reply = Message.CreateMessage(message.Version, fault.CreateMessageFault(), fault.Action);
544 
545                 System.ServiceModel.Channels.RequestReplyCorrelator.AddressReply(reply, message);
546                 System.ServiceModel.Channels.RequestReplyCorrelator.PrepareReply(reply, message.Headers.MessageId);
547 
548                 try
549                 {
550                     this.Send(reply);
551                 }
552                 finally
553                 {
554                     reply.Close();
555                 }
556 
557                 throw;
558             }
559         }
560 
BeginSend(Message message, AsyncCallback callback, object state)561         public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state)
562         {
563             return this.BeginSend(message, this.DefaultSendTimeout, callback, state);
564         }
565 
BeginSend(Message message, TimeSpan timeout, AsyncCallback asyncCallback, object state)566         public virtual IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback asyncCallback, object state)
567         {
568             TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
569             WriteTransactionDataToMessage(message, sendMessageDirection);
570             return InnerChannel.BeginSend(message, timeoutHelper.RemainingTime(), asyncCallback, state);
571         }
572 
EndSend(IAsyncResult result)573         public void EndSend(IAsyncResult result)
574         {
575             InnerChannel.EndSend(result);
576         }
577 
Send(Message message)578         public void Send(Message message)
579         {
580             this.Send(message, this.DefaultSendTimeout);
581         }
582 
Send(Message message, TimeSpan timeout)583         public virtual void Send(Message message, TimeSpan timeout)
584         {
585             TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
586             WriteTransactionDataToMessage(message, sendMessageDirection);
587             InnerChannel.Send(message, timeoutHelper.RemainingTime());
588         }
589     }
590 
591 
592     //==============================================================
593     //                async helper classes
594     //==============================================================
595 
596     class ReceiveTimeoutAsyncResult : AsyncResult
597     {
598         TimeoutHelper timeoutHelper;
599         IAsyncResult innerResult;
600         static AsyncCallback innerCallback = Fx.ThunkCallback(new AsyncCallback(Callback));
601 
ReceiveTimeoutAsyncResult(TimeSpan timeout, AsyncCallback callback, object state)602         internal ReceiveTimeoutAsyncResult(TimeSpan timeout, AsyncCallback callback, object state)
603             : base(callback, state)
604         {
605             this.timeoutHelper = new TimeoutHelper(timeout);
606         }
607 
608         internal TimeoutHelper TimeoutHelper
609         {
610             get { return this.timeoutHelper; }
611         }
612 
613         internal AsyncCallback InnerCallback
614         {
615             get
616             {
617                 if (ReceiveTimeoutAsyncResult.innerCallback == null)
618                     ReceiveTimeoutAsyncResult.innerCallback = Fx.ThunkCallback(new AsyncCallback(Callback));
619                 return ReceiveTimeoutAsyncResult.innerCallback;
620             }
621         }
622 
623         internal IAsyncResult InnerResult
624         {
625             get
626             {
627                 if (!(this.innerResult != null))
628                 {
629                     // tx processing requires failfast when state is inconsistent
630                     DiagnosticUtility.FailFast("ReceiveTimeoutAsyncResult.InnerResult: (this.innerResult != null)");
631                 }
632                 return this.innerResult;
633             }
634             set
635             {
636                 if (value == null)
637                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
638 
639                 if (this.innerResult == null)
640                 {
641                     this.innerResult = value;
642                 }
643                 else if (this.innerResult != value)
644                 {
645                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxAsyncResultsDontMatch0)));
646                 }
647             }
648         }
649 
650         internal object InnerState
651         {
652             get { return this; }
653         }
654 
Callback(IAsyncResult result)655         static void Callback(IAsyncResult result)
656         {
657             if (result == null)
658                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("result");
659 
660             ReceiveTimeoutAsyncResult outerResult = (ReceiveTimeoutAsyncResult)result.AsyncState;
661 
662             outerResult.InnerResult = result;
663             outerResult.Complete(result.CompletedSynchronously);
664         }
665     }
666 
667 
668 }
669