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