1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
4 namespace System.ServiceModel.Channels
6 using System.Diagnostics;
8 using System.ServiceModel;
9 using System.Threading;
11 delegate void ConnectionModeCallback(ConnectionModeReader connectionModeReader);
13 sealed class ConnectionModeReader : InitialServerConnectionReader
15 Exception readException;
16 ServerModeDecoder decoder;
20 ConnectionModeCallback callback;
21 static WaitCallback readCallback;
22 TimeoutHelper receiveTimeoutHelper;
24 public ConnectionModeReader(IConnection connection, ConnectionModeCallback callback, ConnectionClosedCallback closedCallback)
25 : base(connection, closedCallback)
27 this.callback = callback;
30 public int BufferOffset
32 get { return offset; }
40 public long StreamPosition
42 get { return decoder.StreamPosition; }
45 public TimeSpan GetRemainingTimeout()
47 return this.receiveTimeoutHelper.RemainingTime();
50 void Complete(Exception e)
52 // exception will be logged by the caller
62 bool ContinueReading()
68 if (readCallback == null)
70 readCallback = new WaitCallback(ReadCallback);
73 if (Connection.BeginRead(0, Connection.AsyncReadBufferSize, GetRemainingTimeout(),
74 readCallback, this) == AsyncCompletionResult.Queued)
78 if (!GetReadResult()) // we're at EOF, bail
89 bytesDecoded = decoder.Decode(buffer, offset, size);
91 catch (CommunicationException e)
93 // see if we need to send back a framing fault
95 if (FramingEncodingString.TryGetFaultString(e, out framingFault))
97 byte[] drainBuffer = new byte[128];
98 InitialServerConnectionReader.SendFault(
99 Connection, framingFault, drainBuffer, GetRemainingTimeout(),
100 MaxViaSize + MaxContentTypeSize);
101 base.Close(GetRemainingTimeout());
106 if (bytesDecoded > 0)
108 offset += bytesDecoded;
109 size -= bytesDecoded;
111 if (decoder.CurrentState == ServerModeDecoder.State.Done)
125 static void ReadCallback(object state)
127 ConnectionModeReader reader = (ConnectionModeReader)state;
128 bool completeSelf = false;
129 Exception completionException = null;
132 if (reader.GetReadResult())
134 completeSelf = reader.ContinueReading();
137 #pragma warning suppress 56500 // Microsoft, transferring exception to caller
146 completionException = e;
151 reader.Complete(completionException);
158 size = Connection.EndRead();
161 if (this.decoder.StreamPosition == 0) // client timed out a cached connection
163 base.Close(GetRemainingTimeout());
168 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
172 // restore ExceptionEventType to Error after the initial read for cached connections
173 Connection.ExceptionEventType = TraceEventType.Error;
177 buffer = Connection.AsyncReadBuffer;
183 public FramingMode GetConnectionMode()
185 if (readException != null)
187 throw DiagnosticUtility.ExceptionUtility.ThrowHelper(readException, Connection.ExceptionEventType);
193 public void StartReading(TimeSpan receiveTimeout, Action connectionDequeuedCallback)
195 this.decoder = new ServerModeDecoder();
196 this.receiveTimeoutHelper = new TimeoutHelper(receiveTimeout);
197 this.ConnectionDequeuedCallback = connectionDequeuedCallback;
198 bool completeSelf = false;
199 Exception completionException = null;
202 completeSelf = ContinueReading();
204 #pragma warning suppress 56500 // Microsoft, transferring exception to caller
213 completionException = e;
218 Complete(completionException);