| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System.Diagnostics;
- using System.Runtime;
- using System.ServiceModel;
- using System.Threading;
- delegate void ConnectionModeCallback(ConnectionModeReader connectionModeReader);
- sealed class ConnectionModeReader : InitialServerConnectionReader
- {
- Exception readException;
- ServerModeDecoder decoder;
- byte[] buffer;
- int offset;
- int size;
- ConnectionModeCallback callback;
- static WaitCallback readCallback;
- TimeoutHelper receiveTimeoutHelper;
- public ConnectionModeReader(IConnection connection, ConnectionModeCallback callback, ConnectionClosedCallback closedCallback)
- : base(connection, closedCallback)
- {
- this.callback = callback;
- }
- public int BufferOffset
- {
- get { return offset; }
- }
- public int BufferSize
- {
- get { return size; }
- }
- public long StreamPosition
- {
- get { return decoder.StreamPosition; }
- }
- public TimeSpan GetRemainingTimeout()
- {
- return this.receiveTimeoutHelper.RemainingTime();
- }
- void Complete(Exception e)
- {
- // exception will be logged by the caller
- readException = e;
- Complete();
- }
- void Complete()
- {
- callback(this);
- }
- bool ContinueReading()
- {
- for (;;)
- {
- if (size == 0)
- {
- if (readCallback == null)
- {
- readCallback = new WaitCallback(ReadCallback);
- }
- if (Connection.BeginRead(0, Connection.AsyncReadBufferSize, GetRemainingTimeout(),
- readCallback, this) == AsyncCompletionResult.Queued)
- {
- break;
- }
- if (!GetReadResult()) // we're at EOF, bail
- {
- return false;
- }
- }
- for (;;)
- {
- int bytesDecoded;
- try
- {
- bytesDecoded = decoder.Decode(buffer, offset, size);
- }
- catch (CommunicationException e)
- {
- // see if we need to send back a framing fault
- string framingFault;
- if (FramingEncodingString.TryGetFaultString(e, out framingFault))
- {
- byte[] drainBuffer = new byte[128];
- InitialServerConnectionReader.SendFault(
- Connection, framingFault, drainBuffer, GetRemainingTimeout(),
- MaxViaSize + MaxContentTypeSize);
- base.Close(GetRemainingTimeout());
- }
- throw;
- }
- if (bytesDecoded > 0)
- {
- offset += bytesDecoded;
- size -= bytesDecoded;
- }
- if (decoder.CurrentState == ServerModeDecoder.State.Done)
- {
- return true;
- }
- if (size == 0)
- {
- break;
- }
- }
- }
- return false;
- }
- static void ReadCallback(object state)
- {
- ConnectionModeReader reader = (ConnectionModeReader)state;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- if (reader.GetReadResult())
- {
- completeSelf = reader.ContinueReading();
- }
- }
- #pragma warning suppress 56500 // [....], transferring exception to caller
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- reader.Complete(completionException);
- }
- }
- bool GetReadResult()
- {
- offset = 0;
- size = Connection.EndRead();
- if (size == 0)
- {
- if (this.decoder.StreamPosition == 0) // client timed out a cached connection
- {
- base.Close(GetRemainingTimeout());
- return false;
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
- }
- }
- // restore ExceptionEventType to Error after the initial read for cached connections
- Connection.ExceptionEventType = TraceEventType.Error;
- if (buffer == null)
- {
- buffer = Connection.AsyncReadBuffer;
- }
- return true;
- }
- public FramingMode GetConnectionMode()
- {
- if (readException != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelper(readException, Connection.ExceptionEventType);
- }
- return decoder.Mode;
- }
- public void StartReading(TimeSpan receiveTimeout, Action connectionDequeuedCallback)
- {
- this.decoder = new ServerModeDecoder();
- this.receiveTimeoutHelper = new TimeoutHelper(receiveTimeout);
- this.ConnectionDequeuedCallback = connectionDequeuedCallback;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- completeSelf = ContinueReading();
- }
- #pragma warning suppress 56500 // [....], transferring exception to caller
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- Complete(completionException);
- }
- }
- }
- }
|