Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / Channels / StreamedFramingRequestChannel.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5 namespace System.ServiceModel.Channels
6 {
7     using System.Runtime;
8     using System.Security.Authentication.ExtendedProtection;
9     using System.ServiceModel;
10     using System.ServiceModel.Security;
11     using System.Threading;
12
13     class StreamedFramingRequestChannel : RequestChannel
14     {
15         IConnectionInitiator connectionInitiator;
16         ConnectionPool connectionPool;
17         MessageEncoder messageEncoder;
18         IConnectionOrientedTransportFactorySettings settings;
19         byte[] startBytes;
20         StreamUpgradeProvider upgrade;
21         ChannelBinding channelBindingToken;
22
23         public StreamedFramingRequestChannel(ChannelManagerBase factory, IConnectionOrientedTransportChannelFactorySettings settings,
24             EndpointAddress remoteAddresss, Uri via, IConnectionInitiator connectionInitiator, ConnectionPool connectionPool)
25             : base(factory, remoteAddresss, via, settings.ManualAddressing)
26         {
27             this.settings = settings;
28             this.connectionInitiator = connectionInitiator;
29             this.connectionPool = connectionPool;
30
31             this.messageEncoder = settings.MessageEncoderFactory.Encoder;
32             this.upgrade = settings.Upgrade;
33         }
34
35         byte[] Preamble
36         {
37             get { return this.startBytes; }
38         }
39
40         protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
41         {
42             return new CompletedAsyncResult(callback, state);
43         }
44
45         protected override void OnEndOpen(IAsyncResult result)
46         {
47             CompletedAsyncResult.End(result);
48         }
49
50         protected override void OnOpen(TimeSpan timeout)
51         {
52         }
53
54         protected override void OnOpened()
55         {
56             // setup our preamble which we'll use for all connections we establish
57             EncodedVia encodedVia = new EncodedVia(this.Via.AbsoluteUri);
58             EncodedContentType encodedContentType = EncodedContentType.Create(settings.MessageEncoderFactory.Encoder.ContentType);
59             int startSize = ClientSingletonEncoder.ModeBytes.Length + ClientSingletonEncoder.CalcStartSize(encodedVia, encodedContentType);
60             int preambleEndOffset = 0;
61             if (this.upgrade == null)
62             {
63                 preambleEndOffset = startSize;
64                 startSize += ClientDuplexEncoder.PreambleEndBytes.Length;
65             }
66             this.startBytes = DiagnosticUtility.Utility.AllocateByteArray(startSize);
67             Buffer.BlockCopy(ClientSingletonEncoder.ModeBytes, 0, startBytes, 0, ClientSingletonEncoder.ModeBytes.Length);
68             ClientSingletonEncoder.EncodeStart(this.startBytes, ClientSingletonEncoder.ModeBytes.Length, encodedVia, encodedContentType);
69             if (preambleEndOffset > 0)
70             {
71                 Buffer.BlockCopy(ClientSingletonEncoder.PreambleEndBytes, 0, startBytes, preambleEndOffset, ClientSingletonEncoder.PreambleEndBytes.Length);
72             }
73
74             // and then transition to the Opened state
75             base.OnOpened();
76         }
77
78         protected override IAsyncRequest CreateAsyncRequest(Message message, AsyncCallback callback, object state)
79         {
80             return new StreamedFramingAsyncRequest(this, callback, state);
81         }
82
83         protected override IRequest CreateRequest(Message message)
84         {
85             return new StreamedFramingRequest(this);
86         }
87
88         IConnection SendPreamble(IConnection connection, ref TimeoutHelper timeoutHelper,
89             ClientFramingDecoder decoder, out SecurityMessageProperty remoteSecurity)
90         {
91             connection.Write(Preamble, 0, Preamble.Length, true, timeoutHelper.RemainingTime());
92
93             if (upgrade != null)
94             {
95                 IStreamUpgradeChannelBindingProvider channelBindingProvider = upgrade.GetProperty<IStreamUpgradeChannelBindingProvider>();
96
97                 StreamUpgradeInitiator upgradeInitiator = upgrade.CreateUpgradeInitiator(this.RemoteAddress, this.Via);
98
99                 if (!ConnectionUpgradeHelper.InitiateUpgrade(upgradeInitiator, ref connection, decoder,
100                     this, ref timeoutHelper))
101                 {
102                     ConnectionUpgradeHelper.DecodeFramingFault(decoder, connection, Via, messageEncoder.ContentType, ref timeoutHelper);
103                 }
104
105                 if (channelBindingProvider != null && channelBindingProvider.IsChannelBindingSupportEnabled)
106                 {
107                     this.channelBindingToken = channelBindingProvider.GetChannelBinding(upgradeInitiator, ChannelBindingKind.Endpoint);
108                 }
109
110                 remoteSecurity = StreamSecurityUpgradeInitiator.GetRemoteSecurity(upgradeInitiator);
111
112                 connection.Write(ClientSingletonEncoder.PreambleEndBytes, 0,
113                     ClientSingletonEncoder.PreambleEndBytes.Length, true, timeoutHelper.RemainingTime());
114             }
115             else
116             {
117                 remoteSecurity = null;
118             }
119
120             // read ACK
121             byte[] ackBuffer = new byte[1];
122             int ackBytesRead = connection.Read(ackBuffer, 0, ackBuffer.Length, timeoutHelper.RemainingTime());
123             if (!ConnectionUpgradeHelper.ValidatePreambleResponse(ackBuffer, ackBytesRead, decoder, this.Via))
124             {
125                 ConnectionUpgradeHelper.DecodeFramingFault(decoder, connection, Via, messageEncoder.ContentType, ref timeoutHelper);
126             }
127
128             return connection;
129         }
130
131         protected override void OnClose(TimeSpan timeout)
132         {
133             base.WaitForPendingRequests(timeout);
134         }
135
136         protected override void OnClosed()
137         {
138             base.OnClosed();
139
140             // clean up the CBT after transitioning to the closed state
141             ChannelBindingUtility.Dispose(ref this.channelBindingToken);
142         }
143
144         protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
145         {
146             return base.BeginWaitForPendingRequests(timeout, callback, state);
147         }
148
149         protected override void OnEndClose(IAsyncResult result)
150         {
151             base.EndWaitForPendingRequests(result);
152         }
153
154         internal class StreamedConnectionPoolHelper : ConnectionPoolHelper
155         {
156             StreamedFramingRequestChannel channel;
157             ClientSingletonDecoder decoder;
158             SecurityMessageProperty remoteSecurity;
159
160             public StreamedConnectionPoolHelper(StreamedFramingRequestChannel channel)
161                 : base(channel.connectionPool, channel.connectionInitiator, channel.Via)
162             {
163                 this.channel = channel;
164             }
165
166             public ClientSingletonDecoder Decoder
167             {
168                 get { return this.decoder; }
169             }
170
171             public SecurityMessageProperty RemoteSecurity
172             {
173                 get { return this.remoteSecurity; }
174             }
175
176             protected override TimeoutException CreateNewConnectionTimeoutException(TimeSpan timeout, TimeoutException innerException)
177             {
178                 return new TimeoutException(SR.GetString(SR.RequestTimedOutEstablishingTransportSession,
179                         timeout, channel.Via.AbsoluteUri), innerException);
180             }
181
182             protected override IConnection AcceptPooledConnection(IConnection connection, ref TimeoutHelper timeoutHelper)
183             {
184                 this.decoder = new ClientSingletonDecoder(0);
185                 return channel.SendPreamble(connection, ref timeoutHelper, this.decoder, out this.remoteSecurity);
186             }
187
188             protected override IAsyncResult BeginAcceptPooledConnection(IConnection connection, ref TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
189             {
190                 this.decoder = new ClientSingletonDecoder(0);
191                 return new SendPreambleAsyncResult(channel, connection, ref timeoutHelper, decoder, callback, state);
192             }
193
194             protected override IConnection EndAcceptPooledConnection(IAsyncResult result)
195             {
196                 return SendPreambleAsyncResult.End(result, out this.remoteSecurity);
197             }
198
199             class SendPreambleAsyncResult : AsyncResult
200             {
201                 StreamedFramingRequestChannel channel;
202                 IConnection connection;
203                 ClientFramingDecoder decoder;
204                 StreamUpgradeInitiator upgradeInitiator;
205                 SecurityMessageProperty remoteSecurity;
206                 TimeoutHelper timeoutHelper;
207                 static WaitCallback onWritePreamble = Fx.ThunkCallback(new WaitCallback(OnWritePreamble));
208                 static WaitCallback onWritePreambleEnd;
209                 static WaitCallback onReadPreambleAck = new WaitCallback(OnReadPreambleAck);
210                 static AsyncCallback onUpgrade;
211                 static AsyncCallback onFailedUpgrade;
212                 IStreamUpgradeChannelBindingProvider channelBindingProvider;
213
214                 public SendPreambleAsyncResult(StreamedFramingRequestChannel channel, IConnection connection,
215                     ref TimeoutHelper timeoutHelper, ClientFramingDecoder decoder, AsyncCallback callback, object state)
216                     : base(callback, state)
217                 {
218                     this.channel = channel;
219                     this.connection = connection;
220                     this.timeoutHelper = timeoutHelper;
221                     this.decoder = decoder;
222
223                     AsyncCompletionResult writePreambleResult = connection.BeginWrite(channel.Preamble, 0, channel.Preamble.Length,
224                         true, timeoutHelper.RemainingTime(), onWritePreamble, this);
225
226                     if (writePreambleResult == AsyncCompletionResult.Queued)
227                     {
228                         return;
229                     }
230
231                     if (HandleWritePreamble())
232                     {
233                         base.Complete(true);
234                     }
235                 }
236
237                 public static IConnection End(IAsyncResult result, out SecurityMessageProperty remoteSecurity)
238                 {
239                     SendPreambleAsyncResult thisPtr = AsyncResult.End<SendPreambleAsyncResult>(result);
240                     remoteSecurity = thisPtr.remoteSecurity;
241                     return thisPtr.connection;
242                 }
243
244                 bool HandleWritePreamble()
245                 {
246                     connection.EndWrite();
247
248                     if (channel.upgrade == null)
249                     {
250                         return ReadPreambleAck();
251                     }
252                     else
253                     {
254                         this.channelBindingProvider = channel.upgrade.GetProperty<IStreamUpgradeChannelBindingProvider>();
255                         this.upgradeInitiator = channel.upgrade.CreateUpgradeInitiator(channel.RemoteAddress, channel.Via);
256                         if (onUpgrade == null)
257                         {
258                             onUpgrade = Fx.ThunkCallback(new AsyncCallback(OnUpgrade));
259                         }
260
261                         IAsyncResult initiateUpgradeResult = ConnectionUpgradeHelper.BeginInitiateUpgrade(channel.settings, channel.RemoteAddress,
262                             connection, decoder, this.upgradeInitiator, channel.messageEncoder.ContentType, null,
263                             this.timeoutHelper, onUpgrade, this);
264
265                         if (!initiateUpgradeResult.CompletedSynchronously)
266                         {
267                             return false;
268                         }
269                         return HandleUpgrade(initiateUpgradeResult);
270                     }
271                 }
272
273                 bool HandleUpgrade(IAsyncResult result)
274                 {
275                     connection = ConnectionUpgradeHelper.EndInitiateUpgrade(result);
276
277                     if (this.channelBindingProvider != null && this.channelBindingProvider.IsChannelBindingSupportEnabled)
278                     {
279                         this.channel.channelBindingToken = this.channelBindingProvider.GetChannelBinding(this.upgradeInitiator, ChannelBindingKind.Endpoint);
280                     }
281
282                     this.remoteSecurity = StreamSecurityUpgradeInitiator.GetRemoteSecurity(this.upgradeInitiator);
283                     this.upgradeInitiator = null; // we're done with the initiator
284                     if (onWritePreambleEnd == null)
285                     {
286                         onWritePreambleEnd = Fx.ThunkCallback(new WaitCallback(OnWritePreambleEnd));
287                     }
288
289                     AsyncCompletionResult writePreambleResult = connection.BeginWrite(
290                         ClientSingletonEncoder.PreambleEndBytes, 0, ClientSingletonEncoder.PreambleEndBytes.Length, true,
291                         timeoutHelper.RemainingTime(), onWritePreambleEnd, this);
292
293                     if (writePreambleResult == AsyncCompletionResult.Queued)
294                     {
295                         return false;
296                     }
297
298                     connection.EndWrite();
299                     return ReadPreambleAck();
300                 }
301
302                 bool ReadPreambleAck()
303                 {
304                     AsyncCompletionResult readAckResult = connection.BeginRead(0, 1,
305                         timeoutHelper.RemainingTime(), onReadPreambleAck, this);
306
307                     if (readAckResult == AsyncCompletionResult.Queued)
308                     {
309                         return false;
310                     }
311
312                     return HandlePreambleAck();
313                 }
314
315                 bool HandlePreambleAck()
316                 {
317                     int ackBytesRead = connection.EndRead();
318                     if (!ConnectionUpgradeHelper.ValidatePreambleResponse(
319                         connection.AsyncReadBuffer, ackBytesRead, decoder, channel.Via))
320                     {
321                         if (onFailedUpgrade == null)
322                         {
323                             onFailedUpgrade = Fx.ThunkCallback(new AsyncCallback(OnFailedUpgrade));
324                         }
325                         IAsyncResult decodeFaultResult = ConnectionUpgradeHelper.BeginDecodeFramingFault(decoder,
326                             connection, channel.Via, channel.messageEncoder.ContentType, ref timeoutHelper,
327                             onFailedUpgrade, this);
328
329                         if (!decodeFaultResult.CompletedSynchronously)
330                         {
331                             return false;
332                         }
333
334                         ConnectionUpgradeHelper.EndDecodeFramingFault(decodeFaultResult);
335                         return true;
336                     }
337
338                     return true;
339                 }
340
341                 static void OnWritePreamble(object asyncState)
342                 {
343                     SendPreambleAsyncResult thisPtr = (SendPreambleAsyncResult)asyncState;
344
345                     Exception completionException = null;
346                     bool completeSelf;
347                     try
348                     {
349                         completeSelf = thisPtr.HandleWritePreamble();
350                     }
351 #pragma warning suppress 56500 // [....], transferring exception to another thread
352                     catch (Exception e)
353                     {
354                         if (Fx.IsFatal(e))
355                         {
356                             throw;
357                         }
358
359                         completeSelf = true;
360                         completionException = e;
361                     }
362
363                     if (completeSelf)
364                     {
365                         thisPtr.Complete(false, completionException);
366                     }
367                 }
368
369                 static void OnWritePreambleEnd(object asyncState)
370                 {
371                     SendPreambleAsyncResult thisPtr = (SendPreambleAsyncResult)asyncState;
372
373                     Exception completionException = null;
374                     bool completeSelf;
375                     try
376                     {
377                         thisPtr.connection.EndWrite();
378                         completeSelf = thisPtr.ReadPreambleAck();
379                     }
380 #pragma warning suppress 56500 // [....], transferring exception to another thread
381                     catch (Exception e)
382                     {
383                         if (Fx.IsFatal(e))
384                         {
385                             throw;
386                         }
387
388                         completeSelf = true;
389                         completionException = e;
390                     }
391
392                     if (completeSelf)
393                     {
394                         thisPtr.Complete(false, completionException);
395                     }
396                 }
397
398                 static void OnReadPreambleAck(object state)
399                 {
400                     SendPreambleAsyncResult thisPtr = (SendPreambleAsyncResult)state;
401
402                     Exception completionException = null;
403                     bool completeSelf;
404                     try
405                     {
406                         completeSelf = thisPtr.HandlePreambleAck();
407                     }
408 #pragma warning suppress 56500 // [....], transferring exception to another thread
409                     catch (Exception e)
410                     {
411                         if (Fx.IsFatal(e))
412                         {
413                             throw;
414                         }
415
416                         completeSelf = true;
417                         completionException = e;
418                     }
419
420                     if (completeSelf)
421                     {
422                         thisPtr.Complete(false, completionException);
423                     }
424                 }
425
426                 static void OnUpgrade(IAsyncResult result)
427                 {
428                     if (result.CompletedSynchronously)
429                     {
430                         return;
431                     }
432
433                     SendPreambleAsyncResult thisPtr = (SendPreambleAsyncResult)result.AsyncState;
434
435                     Exception completionException = null;
436                     bool completeSelf;
437                     try
438                     {
439                         completeSelf = thisPtr.HandleUpgrade(result);
440                     }
441 #pragma warning suppress 56500 // [....], transferring exception to another thread
442                     catch (Exception e)
443                     {
444                         if (Fx.IsFatal(e))
445                         {
446                             throw;
447                         }
448
449                         completeSelf = true;
450                         completionException = e;
451                     }
452
453                     if (completeSelf)
454                     {
455                         thisPtr.Complete(false, completionException);
456                     }
457                 }
458
459                 static void OnFailedUpgrade(IAsyncResult result)
460                 {
461                     if (result.CompletedSynchronously)
462                     {
463                         return;
464                     }
465
466                     SendPreambleAsyncResult thisPtr = (SendPreambleAsyncResult)result.AsyncState;
467
468                     Exception completionException = null;
469                     try
470                     {
471                         ConnectionUpgradeHelper.EndDecodeFramingFault(result);
472                     }
473 #pragma warning suppress 56500 // [....], transferring exception to another thread
474                     catch (Exception e)
475                     {
476                         if (Fx.IsFatal(e))
477                         {
478                             throw;
479                         }
480
481                         completionException = e;
482                     }
483
484                     thisPtr.Complete(false, completionException);
485                 }
486             }
487         }
488
489         class ClientSingletonConnectionReader : SingletonConnectionReader
490         {
491             StreamedConnectionPoolHelper connectionPoolHelper;
492
493             public ClientSingletonConnectionReader(IConnection connection, StreamedConnectionPoolHelper connectionPoolHelper,
494                 IConnectionOrientedTransportFactorySettings settings)
495                 : base(connection, 0, 0, connectionPoolHelper.RemoteSecurity, settings, null)
496             {
497                 this.connectionPoolHelper = connectionPoolHelper;
498             }
499
500             protected override long StreamPosition
501             {
502                 get { return connectionPoolHelper.Decoder.StreamPosition; }
503             }
504
505             protected override bool DecodeBytes(byte[] buffer, ref int offset, ref int size, ref bool isAtEof)
506             {
507                 while (size > 0)
508                 {
509                     int bytesRead = connectionPoolHelper.Decoder.Decode(buffer, offset, size);
510                     if (bytesRead > 0)
511                     {
512                         offset += bytesRead;
513                         size -= bytesRead;
514                     }
515
516                     switch (connectionPoolHelper.Decoder.CurrentState)
517                     {
518                         case ClientFramingDecoderState.EnvelopeStart:
519                             // we're at the envelope
520                             return true;
521
522                         case ClientFramingDecoderState.End:
523                             isAtEof = true;
524                             return false;
525                     }
526                 }
527
528                 return false;
529             }
530
531             protected override void OnClose(TimeSpan timeout)
532             {
533                 connectionPoolHelper.Close(timeout);
534             }
535         }
536
537         class StreamedFramingRequest : IRequest
538         {
539             StreamedFramingRequestChannel channel;
540             StreamedConnectionPoolHelper connectionPoolHelper;
541             IConnection connection;
542
543             public StreamedFramingRequest(StreamedFramingRequestChannel channel)
544             {
545                 this.channel = channel;
546                 this.connectionPoolHelper = new StreamedConnectionPoolHelper(channel);
547             }
548
549             public void SendRequest(Message message, TimeSpan timeout)
550             {
551                 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
552
553                 try
554                 {
555                     this.connection = connectionPoolHelper.EstablishConnection(timeoutHelper.RemainingTime());
556
557                     ChannelBindingUtility.TryAddToMessage(this.channel.channelBindingToken, message, false);
558
559                     bool success = false;
560                     try
561                     {
562                         StreamingConnectionHelper.WriteMessage(message, this.connection, true, channel.settings, ref timeoutHelper);
563                         success = true;
564                     }
565                     finally
566                     {
567                         if (!success)
568                         {
569                             connectionPoolHelper.Abort();
570                         }
571                     }
572                 }
573                 catch (TimeoutException exception)
574                 {
575                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
576                         new TimeoutException(SR.GetString(SR.TimeoutOnRequest, timeout), exception));
577                 }
578             }
579
580             public Message WaitForReply(TimeSpan timeout)
581             {
582                 ClientSingletonConnectionReader connectionReader = new ClientSingletonConnectionReader(
583                     connection, connectionPoolHelper, channel.settings);
584
585                 connectionReader.DoneSending(TimeSpan.Zero); // we still need to receive
586                 Message message = connectionReader.Receive(timeout);
587
588                 if (message != null)
589                 {
590                     ChannelBindingUtility.TryAddToMessage(this.channel.channelBindingToken, message, false);
591                 }
592
593                 return message;
594             }
595
596             void Cleanup()
597             {
598                 this.connectionPoolHelper.Abort();
599             }
600
601             public void Abort(RequestChannel requestChannel)
602             {
603                 Cleanup();
604             }
605
606             public void Fault(RequestChannel requestChannel)
607             {
608                 Cleanup();
609             }
610
611             public void OnReleaseRequest()
612             {                
613             }
614         }
615
616         class StreamedFramingAsyncRequest : AsyncResult, IAsyncRequest
617         {
618             StreamedFramingRequestChannel channel;
619             IConnection connection;
620             StreamedConnectionPoolHelper connectionPoolHelper;
621             Message message;
622             Message replyMessage;
623             TimeoutHelper timeoutHelper;
624             static AsyncCallback onEstablishConnection = Fx.ThunkCallback(new AsyncCallback(OnEstablishConnection));
625             static AsyncCallback onWriteMessage = Fx.ThunkCallback(new AsyncCallback(OnWriteMessage));
626             static AsyncCallback onReceiveReply = Fx.ThunkCallback(new AsyncCallback(OnReceiveReply));
627             ClientSingletonConnectionReader connectionReader;
628
629             public StreamedFramingAsyncRequest(StreamedFramingRequestChannel channel, AsyncCallback callback, object state)
630                 : base(callback, state)
631             {
632                 this.channel = channel;
633                 this.connectionPoolHelper = new StreamedConnectionPoolHelper(channel);
634             }
635
636             public void BeginSendRequest(Message message, TimeSpan timeout)
637             {
638                 this.timeoutHelper = new TimeoutHelper(timeout);
639                 this.message = message;
640
641                 bool completeSelf = false;
642                 bool success = false;
643                 try
644                 {
645                     try
646                     {
647                         IAsyncResult result = connectionPoolHelper.BeginEstablishConnection(timeoutHelper.RemainingTime(), onEstablishConnection, this);
648                         if (result.CompletedSynchronously)
649                         {
650                             completeSelf = HandleEstablishConnection(result);
651                         }
652                     }
653                     catch (TimeoutException exception)
654                     {
655                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
656                             new TimeoutException(SR.GetString(SR.TimeoutOnRequest, timeout), exception));
657                     }
658
659                     success = true;
660                 }
661                 finally
662                 {
663                     if (!success)
664                     {
665                         Cleanup();
666                     }
667                 }
668
669                 if (completeSelf)
670                 {
671                     base.Complete(true);
672                 }
673             }
674
675             bool HandleEstablishConnection(IAsyncResult result)
676             {
677                 this.connection = connectionPoolHelper.EndEstablishConnection(result);
678
679                 ChannelBindingUtility.TryAddToMessage(this.channel.channelBindingToken, this.message, false);
680
681                 IAsyncResult writeResult = StreamingConnectionHelper.BeginWriteMessage(this.message, this.connection, true, this.channel.settings, ref timeoutHelper, onWriteMessage, this);
682                 if (!writeResult.CompletedSynchronously)
683                 {
684                     return false;
685                 }
686
687                 return HandleWriteMessage(writeResult);
688             }
689
690             public Message End()
691             {
692                 try
693                 {
694                     AsyncResult.End<StreamedFramingAsyncRequest>(this);
695                 }
696                 catch (TimeoutException exception)
697                 {
698                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
699                         new TimeoutException(SR.GetString(SR.TimeoutOnRequest, this.timeoutHelper.OriginalTimeout), exception));
700                 }
701                 return replyMessage;
702             }
703
704             public void Abort(RequestChannel requestChannel)
705             {
706                 Cleanup();
707             }
708
709             public void Fault(RequestChannel requestChannel)
710             {
711                 Cleanup();
712             }
713
714             void Cleanup()
715             {
716                 connectionPoolHelper.Abort();
717             }
718
719             bool HandleWriteMessage(IAsyncResult result)
720             {
721                 // write out the streamed message
722                 StreamingConnectionHelper.EndWriteMessage(result);
723
724                 connectionReader = new ClientSingletonConnectionReader(connection, connectionPoolHelper, channel.settings);
725                 connectionReader.DoneSending(TimeSpan.Zero); // we still need to receive
726
727                 IAsyncResult receiveResult = connectionReader.BeginReceive(timeoutHelper.RemainingTime(), onReceiveReply, this);
728
729                 if (!receiveResult.CompletedSynchronously)
730                 {
731                     return false;
732                 }
733
734                 return CompleteReceiveReply(receiveResult);
735             }
736
737             bool CompleteReceiveReply(IAsyncResult result)
738             {
739                 this.replyMessage = connectionReader.EndReceive(result);
740
741                 if (this.replyMessage != null)
742                 {
743                     ChannelBindingUtility.TryAddToMessage(this.channel.channelBindingToken, this.replyMessage, false);
744                 }
745
746                 return true;
747             }
748
749             static void OnEstablishConnection(IAsyncResult result)
750             {
751                 if (result.CompletedSynchronously)
752                 {
753                     return;
754                 }
755
756                 StreamedFramingAsyncRequest thisPtr = (StreamedFramingAsyncRequest)result.AsyncState;
757
758                 Exception completionException = null;
759                 bool completeSelf;
760                 bool throwing = true;
761                 try
762                 {
763                     completeSelf = thisPtr.HandleEstablishConnection(result);
764                     throwing = false;
765                 }
766 #pragma warning suppress 56500 // [....], transferring exception to another thread
767                 catch (Exception e)
768                 {
769                     if (Fx.IsFatal(e))
770                     {
771                         throw;
772                     }
773
774                     completeSelf = true;
775                     completionException = e;
776                 }
777                 finally
778                 {
779                     if (throwing)
780                     {
781                         thisPtr.Cleanup();
782                     }
783                 }
784
785                 if (completeSelf)
786                 {
787                     thisPtr.Complete(false, completionException);
788                 }
789             }
790
791             static void OnWriteMessage(IAsyncResult result)
792             {
793                 if (result.CompletedSynchronously)
794                 {
795                     return;
796                 }
797
798                 StreamedFramingAsyncRequest thisPtr = (StreamedFramingAsyncRequest)result.AsyncState;
799
800                 Exception completionException = null;
801                 bool completeSelf;
802                 bool throwing = true;
803                 try
804                 {
805                     completeSelf = thisPtr.HandleWriteMessage(result);
806                     throwing = false;
807                 }
808 #pragma warning suppress 56500 // [....], transferring exception to another thread
809                 catch (Exception e)
810                 {
811                     if (Fx.IsFatal(e))
812                     {
813                         throw;
814                     }
815
816                     completeSelf = true;
817                     completionException = e;
818                 }
819                 finally
820                 {
821                     if (throwing)
822                     {
823                         thisPtr.Cleanup();
824                     }
825                 }
826
827                 if (completeSelf)
828                 {
829                     thisPtr.Complete(false, completionException);
830                 }
831             }
832
833             static void OnReceiveReply(IAsyncResult result)
834             {
835                 StreamedFramingAsyncRequest thisPtr = (StreamedFramingAsyncRequest)result.AsyncState;
836
837                 Exception completionException = null;
838                 bool completeSelf;
839                 bool throwing = true;
840                 try
841                 {
842                     completeSelf = thisPtr.CompleteReceiveReply(result);
843                     throwing = false;
844                 }
845 #pragma warning suppress 56500 // [....], transferring exception to another thread
846                 catch (Exception e)
847                 {
848                     if (Fx.IsFatal(e))
849                     {
850                         throw;
851                     }
852
853                     completeSelf = true;
854                     completionException = e;
855                 }
856                 finally
857                 {
858                     if (throwing)
859                     {
860                         thisPtr.Cleanup();
861                     }
862                 }
863
864                 if (completeSelf)
865                 {
866                     thisPtr.Complete(false, completionException);
867                 }
868             }
869
870             public void OnReleaseRequest()
871             {                
872             }
873         }
874     }
875 }