| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System.Diagnostics;
- using System.IO;
- using System.Net;
- using System.Runtime;
- using System.ServiceModel;
- using System.Threading;
- using System.ServiceModel.Diagnostics.Application;
- // Low level abstraction for a socket/pipe
- interface IConnection
- {
- byte[] AsyncReadBuffer { get; }
- int AsyncReadBufferSize { get; }
- TraceEventType ExceptionEventType { get; set; }
- IPEndPoint RemoteIPEndPoint { get; }
- void Abort();
- void Close(TimeSpan timeout, bool asyncAndLinger);
- void Shutdown(TimeSpan timeout);
- AsyncCompletionResult BeginWrite(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout,
- WaitCallback callback, object state);
- void EndWrite();
- void Write(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout);
- void Write(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout, BufferManager bufferManager);
- int Read(byte[] buffer, int offset, int size, TimeSpan timeout);
- AsyncCompletionResult BeginRead(int offset, int size, TimeSpan timeout, WaitCallback callback, object state);
- int EndRead();
- // very ugly listener stuff
- object DuplicateAndClose(int targetProcessId);
- object GetCoreTransport();
- IAsyncResult BeginValidate(Uri uri, AsyncCallback callback, object state);
- bool EndValidate(IAsyncResult result);
- }
- // Low level abstraction for connecting a socket/pipe
- interface IConnectionInitiator
- {
- IConnection Connect(Uri uri, TimeSpan timeout);
- IAsyncResult BeginConnect(Uri uri, TimeSpan timeout, AsyncCallback callback, object state);
- IConnection EndConnect(IAsyncResult result);
- }
- // Low level abstraction for listening for sockets/pipes
- interface IConnectionListener : IDisposable
- {
- void Listen();
- IAsyncResult BeginAccept(AsyncCallback callback, object state);
- IConnection EndAccept(IAsyncResult result);
- }
- abstract class DelegatingConnection : IConnection
- {
- IConnection connection;
- protected DelegatingConnection(IConnection connection)
- {
- this.connection = connection;
- }
- public virtual byte[] AsyncReadBuffer
- {
- get { return connection.AsyncReadBuffer; }
- }
- public virtual int AsyncReadBufferSize
- {
- get { return connection.AsyncReadBufferSize; }
- }
- public TraceEventType ExceptionEventType
- {
- get { return connection.ExceptionEventType; }
- set { connection.ExceptionEventType = value; }
- }
- protected IConnection Connection
- {
- get { return connection; }
- }
- public IPEndPoint RemoteIPEndPoint
- {
- get { return connection.RemoteIPEndPoint; }
- }
- public virtual void Abort()
- {
- connection.Abort();
- }
- public virtual void Close(TimeSpan timeout, bool asyncAndLinger)
- {
- connection.Close(timeout, asyncAndLinger);
- }
- public virtual void Shutdown(TimeSpan timeout)
- {
- connection.Shutdown(timeout);
- }
- public virtual object DuplicateAndClose(int targetProcessId)
- {
- return connection.DuplicateAndClose(targetProcessId);
- }
- public virtual object GetCoreTransport()
- {
- return connection.GetCoreTransport();
- }
- public virtual IAsyncResult BeginValidate(Uri uri, AsyncCallback callback, object state)
- {
- return connection.BeginValidate(uri, callback, state);
- }
- public virtual bool EndValidate(IAsyncResult result)
- {
- return connection.EndValidate(result);
- }
- public virtual AsyncCompletionResult BeginWrite(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout,
- WaitCallback callback, object state)
- {
- return connection.BeginWrite(buffer, offset, size, immediate, timeout, callback, state);
- }
- public virtual void EndWrite()
- {
- connection.EndWrite();
- }
- public virtual void Write(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout)
- {
- connection.Write(buffer, offset, size, immediate, timeout);
- }
- public virtual void Write(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout, BufferManager bufferManager)
- {
- connection.Write(buffer, offset, size, immediate, timeout, bufferManager);
- }
- public virtual int Read(byte[] buffer, int offset, int size, TimeSpan timeout)
- {
- return connection.Read(buffer, offset, size, timeout);
- }
- public virtual AsyncCompletionResult BeginRead(int offset, int size, TimeSpan timeout,
- WaitCallback callback, object state)
- {
- return connection.BeginRead(offset, size, timeout, callback, state);
- }
- public virtual int EndRead()
- {
- return connection.EndRead();
- }
- }
- class PreReadConnection : DelegatingConnection
- {
- int asyncBytesRead;
- byte[] preReadData;
- int preReadOffset;
- int preReadCount;
- public PreReadConnection(IConnection innerConnection, byte[] initialData)
- : this(innerConnection, initialData, 0, initialData.Length)
- {
- }
- public PreReadConnection(IConnection innerConnection, byte[] initialData, int initialOffset, int initialSize)
- : base(innerConnection)
- {
- this.preReadData = initialData;
- this.preReadOffset = initialOffset;
- this.preReadCount = initialSize;
- }
- public void AddPreReadData(byte[] initialData, int initialOffset, int initialSize)
- {
- if (this.preReadCount > 0)
- {
- byte[] tempBuffer = this.preReadData;
- this.preReadData = DiagnosticUtility.Utility.AllocateByteArray(initialSize + this.preReadCount);
- Buffer.BlockCopy(tempBuffer, this.preReadOffset, this.preReadData, 0, this.preReadCount);
- Buffer.BlockCopy(initialData, initialOffset, this.preReadData, this.preReadCount, initialSize);
- this.preReadOffset = 0;
- this.preReadCount += initialSize;
- }
- else
- {
- this.preReadData = initialData;
- this.preReadOffset = initialOffset;
- this.preReadCount = initialSize;
- }
- }
- public override int Read(byte[] buffer, int offset, int size, TimeSpan timeout)
- {
- ConnectionUtilities.ValidateBufferBounds(buffer, offset, size);
- if (this.preReadCount > 0)
- {
- int bytesToCopy = Math.Min(size, this.preReadCount);
- Buffer.BlockCopy(this.preReadData, this.preReadOffset, buffer, offset, bytesToCopy);
- this.preReadOffset += bytesToCopy;
- this.preReadCount -= bytesToCopy;
- return bytesToCopy;
- }
- return base.Read(buffer, offset, size, timeout);
- }
- public override AsyncCompletionResult BeginRead(int offset, int size, TimeSpan timeout, WaitCallback callback, object state)
- {
- ConnectionUtilities.ValidateBufferBounds(AsyncReadBufferSize, offset, size);
- if (this.preReadCount > 0)
- {
- int bytesToCopy = Math.Min(size, this.preReadCount);
- Buffer.BlockCopy(this.preReadData, this.preReadOffset, AsyncReadBuffer, offset, bytesToCopy);
- this.preReadOffset += bytesToCopy;
- this.preReadCount -= bytesToCopy;
- this.asyncBytesRead = bytesToCopy;
- return AsyncCompletionResult.Completed;
- }
- return base.BeginRead(offset, size, timeout, callback, state);
- }
- public override int EndRead()
- {
- if (this.asyncBytesRead > 0)
- {
- int retValue = this.asyncBytesRead;
- this.asyncBytesRead = 0;
- return retValue;
- }
- return base.EndRead();
- }
- }
- class ConnectionStream : Stream
- {
- TimeSpan closeTimeout;
- int readTimeout;
- int writeTimeout;
- IConnection connection;
- bool immediate;
- public ConnectionStream(IConnection connection, IDefaultCommunicationTimeouts defaultTimeouts)
- {
- this.connection = connection;
- this.closeTimeout = defaultTimeouts.CloseTimeout;
- this.ReadTimeout = TimeoutHelper.ToMilliseconds(defaultTimeouts.ReceiveTimeout);
- this.WriteTimeout = TimeoutHelper.ToMilliseconds(defaultTimeouts.SendTimeout);
- immediate = true;
- }
- public IConnection Connection
- {
- get { return connection; }
- }
- public override bool CanRead
- {
- get { return true; }
- }
- public override bool CanSeek
- {
- get { return false; }
- }
- public override bool CanTimeout
- {
- get { return true; }
- }
- public override bool CanWrite
- {
- get { return true; }
- }
- public TimeSpan CloseTimeout
- {
- get { return closeTimeout; }
- set { this.closeTimeout = value; }
- }
- public override int ReadTimeout
- {
- get { return this.readTimeout; }
- set
- {
- if (value < -1)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
- SR.GetString(SR.ValueMustBeInRange, -1, int.MaxValue)));
- }
- this.readTimeout = value;
- }
- }
- public override int WriteTimeout
- {
- get { return this.writeTimeout; }
- set
- {
- if (value < -1)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
- SR.GetString(SR.ValueMustBeInRange, -1, int.MaxValue)));
- }
- this.writeTimeout = value;
- }
- }
- public bool Immediate
- {
- get { return immediate; }
- set { immediate = value; }
- }
- public override long Length
- {
- get
- {
- #pragma warning suppress 56503 // [....], required by the Stream.Length contract
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupported)));
- }
- }
- public override long Position
- {
- get
- {
- #pragma warning suppress 56503 // [....], required by the Stream.Position contract
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupported)));
- }
- set
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupported)));
- }
- }
- public TraceEventType ExceptionEventType
- {
- get { return connection.ExceptionEventType; }
- set { connection.ExceptionEventType = value; }
- }
- public void Abort()
- {
- connection.Abort();
- }
- public override void Close()
- {
- connection.Close(this.CloseTimeout, false);
- }
- public override void Flush()
- {
- // NOP
- }
- public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- return new WriteAsyncResult(this.connection, buffer, offset, count, this.Immediate, TimeoutHelper.FromMilliseconds(this.WriteTimeout), callback, state);
- }
- public override void EndWrite(IAsyncResult asyncResult)
- {
- WriteAsyncResult.End(asyncResult);
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- connection.Write(buffer, offset, count, this.Immediate, TimeoutHelper.FromMilliseconds(this.WriteTimeout));
- }
- public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- return new ReadAsyncResult(connection, buffer, offset, count, TimeoutHelper.FromMilliseconds(this.ReadTimeout), callback, state);
- }
- public override int EndRead(IAsyncResult asyncResult)
- {
- return ReadAsyncResult.End(asyncResult);
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- return this.Read(buffer, offset, count, TimeoutHelper.FromMilliseconds(this.ReadTimeout));
- }
- protected int Read(byte[] buffer, int offset, int count, TimeSpan timeout)
- {
- return connection.Read(buffer, offset, count, timeout);
- }
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupported)));
- }
- public override void SetLength(long value)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupported)));
- }
- public void Shutdown(TimeSpan timeout)
- {
- connection.Shutdown(timeout);
- }
- public IAsyncResult BeginValidate(Uri uri, AsyncCallback callback, object state)
- {
- return this.connection.BeginValidate(uri, callback, state);
- }
- public bool EndValidate(IAsyncResult result)
- {
- return this.connection.EndValidate(result);
- }
- abstract class IOAsyncResult : AsyncResult
- {
- static WaitCallback onAsyncIOComplete;
- IConnection connection;
- protected IOAsyncResult(IConnection connection, AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.connection = connection;
- }
- protected WaitCallback GetWaitCompletion()
- {
- if (onAsyncIOComplete == null)
- {
- onAsyncIOComplete = new WaitCallback(OnAsyncIOComplete);
- }
- return onAsyncIOComplete;
- }
- protected abstract void HandleIO(IConnection connection);
- static void OnAsyncIOComplete(object state)
- {
- IOAsyncResult thisPtr = (IOAsyncResult)state;
- Exception completionException = null;
- try
- {
- thisPtr.HandleIO(thisPtr.connection);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- }
- thisPtr.Complete(false, completionException);
- }
- }
- sealed class ReadAsyncResult : IOAsyncResult
- {
- int bytesRead;
- byte[] buffer;
- int offset;
- public ReadAsyncResult(IConnection connection, byte[] buffer, int offset, int count, TimeSpan timeout,
- AsyncCallback callback, object state)
- : base(connection, callback, state)
- {
- this.buffer = buffer;
- this.offset = offset;
- AsyncCompletionResult readResult = connection.BeginRead(0, Math.Min(count, connection.AsyncReadBufferSize),
- timeout, GetWaitCompletion(), this);
- if (readResult == AsyncCompletionResult.Completed)
- {
- HandleIO(connection);
- base.Complete(true);
- }
- }
- protected override void HandleIO(IConnection connection)
- {
- bytesRead = connection.EndRead();
- Buffer.BlockCopy(connection.AsyncReadBuffer, 0, buffer, offset, bytesRead);
- }
- public static int End(IAsyncResult result)
- {
- ReadAsyncResult thisPtr = AsyncResult.End<ReadAsyncResult>(result);
- return thisPtr.bytesRead;
- }
- }
- sealed class WriteAsyncResult : IOAsyncResult
- {
- public WriteAsyncResult(IConnection connection, byte[] buffer, int offset, int count, bool immediate, TimeSpan timeout, AsyncCallback callback, object state)
- : base(connection, callback, state)
- {
- AsyncCompletionResult writeResult = connection.BeginWrite(buffer, offset, count, immediate, timeout, GetWaitCompletion(), this);
- if (writeResult == AsyncCompletionResult.Completed)
- {
- HandleIO(connection);
- base.Complete(true);
- }
- }
- protected override void HandleIO(IConnection connection)
- {
- connection.EndWrite();
- }
- public static void End(IAsyncResult result)
- {
- AsyncResult.End<WriteAsyncResult>(result);
- }
- }
- }
- class StreamConnection : IConnection
- {
- byte[] asyncReadBuffer;
- int bytesRead;
- ConnectionStream innerStream;
- AsyncCallback onRead;
- AsyncCallback onWrite;
- IAsyncResult readResult;
- IAsyncResult writeResult;
- WaitCallback readCallback;
- WaitCallback writeCallback;
- Stream stream;
- public StreamConnection(Stream stream, ConnectionStream innerStream)
- {
- Fx.Assert(stream != null, "StreamConnection: Stream cannot be null.");
- Fx.Assert(innerStream != null, "StreamConnection: Inner stream cannot be null.");
- this.stream = stream;
- this.innerStream = innerStream;
- onRead = Fx.ThunkCallback(new AsyncCallback(OnRead));
- onWrite = Fx.ThunkCallback(new AsyncCallback(OnWrite));
- }
- public byte[] AsyncReadBuffer
- {
- get
- {
- if (this.asyncReadBuffer == null)
- {
- lock (ThisLock)
- {
- if (this.asyncReadBuffer == null)
- {
- this.asyncReadBuffer = DiagnosticUtility.Utility.AllocateByteArray(innerStream.Connection.AsyncReadBufferSize);
- }
- }
- }
- return this.asyncReadBuffer;
- }
- }
- public int AsyncReadBufferSize
- {
- get { return innerStream.Connection.AsyncReadBufferSize; }
- }
- public Stream Stream
- {
- get { return this.stream; }
- }
- public object ThisLock
- {
- get { return this; }
- }
- public TraceEventType ExceptionEventType
- {
- get { return innerStream.ExceptionEventType; }
- set { innerStream.ExceptionEventType = value; }
- }
- public IPEndPoint RemoteIPEndPoint
- {
- get
- {
- #pragma warning suppress 56503 // Not publicly accessible and this should never be called.
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
- }
- }
- public void Abort()
- {
- innerStream.Abort();
- }
- Exception ConvertIOException(IOException ioException)
- {
- if (ioException.InnerException is TimeoutException)
- {
- return new TimeoutException(ioException.InnerException.Message, ioException);
- }
- else if (ioException.InnerException is CommunicationObjectAbortedException)
- {
- return new CommunicationObjectAbortedException(ioException.InnerException.Message, ioException);
- }
- else if (ioException.InnerException is CommunicationException)
- {
- return new CommunicationException(ioException.InnerException.Message, ioException);
- }
- else
- {
- return new CommunicationException(SR.GetString(SR.StreamError), ioException);
- }
- }
- public void Close(TimeSpan timeout, bool asyncAndLinger)
- {
- innerStream.CloseTimeout = timeout;
- try
- {
- stream.Close();
- }
- catch (IOException ioException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ConvertIOException(ioException));
- }
- }
- public void Shutdown(TimeSpan timeout)
- {
- innerStream.Shutdown(timeout);
- }
- public object DuplicateAndClose(int targetProcessId)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
- }
- public virtual object GetCoreTransport()
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
- }
- public IAsyncResult BeginValidate(Uri uri, AsyncCallback callback, object state)
- {
- return this.innerStream.BeginValidate(uri, callback, state);
- }
- public bool EndValidate(IAsyncResult result)
- {
- return this.innerStream.EndValidate(result);
- }
- public AsyncCompletionResult BeginWrite(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout,
- WaitCallback callback, object state)
- {
- if (callback == null)
- {
- Fx.AssertAndThrow("Cannot call BeginWrite without a callback");
- }
- if (this.writeCallback != null)
- {
- Fx.AssertAndThrow("BeginWrite cannot be called twice");
- }
- this.writeCallback = callback;
- bool throwing = true;
- try
- {
- innerStream.Immediate = immediate;
- SetWriteTimeout(timeout);
- IAsyncResult localResult = stream.BeginWrite(buffer, offset, size, this.onWrite, state);
- if (!localResult.CompletedSynchronously)
- {
- throwing = false;
- return AsyncCompletionResult.Queued;
- }
- throwing = false;
- stream.EndWrite(localResult);
- }
- catch (IOException ioException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ConvertIOException(ioException));
- }
- finally
- {
- if (throwing)
- {
- this.writeCallback = null;
- }
- }
- return AsyncCompletionResult.Completed;
- }
- public void EndWrite()
- {
- IAsyncResult localResult = this.writeResult;
- this.writeResult = null;
- this.writeCallback = null;
- if (localResult != null)
- {
- try
- {
- stream.EndWrite(localResult);
- }
- catch (IOException ioException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ConvertIOException(ioException));
- }
- }
- }
- void OnWrite(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- if (this.writeResult != null)
- {
- throw Fx.AssertAndThrow("StreamConnection: OnWrite called twice.");
- }
- this.writeResult = result;
- this.writeCallback(result.AsyncState);
- }
- public void Write(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout)
- {
- try
- {
- innerStream.Immediate = immediate;
- SetWriteTimeout(timeout);
- stream.Write(buffer, offset, size);
- }
- catch (IOException ioException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ConvertIOException(ioException));
- }
- }
- public void Write(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout, BufferManager bufferManager)
- {
- Write(buffer, offset, size, immediate, timeout);
- bufferManager.ReturnBuffer(buffer);
- }
- void SetReadTimeout(TimeSpan timeout)
- {
- int timeoutInMilliseconds = TimeoutHelper.ToMilliseconds(timeout);
- if (stream.CanTimeout)
- {
- stream.ReadTimeout = timeoutInMilliseconds;
- }
- innerStream.ReadTimeout = timeoutInMilliseconds;
- }
- void SetWriteTimeout(TimeSpan timeout)
- {
- int timeoutInMilliseconds = TimeoutHelper.ToMilliseconds(timeout);
- if (stream.CanTimeout)
- {
- stream.WriteTimeout = timeoutInMilliseconds;
- }
- innerStream.WriteTimeout = timeoutInMilliseconds;
- }
- public int Read(byte[] buffer, int offset, int size, TimeSpan timeout)
- {
- try
- {
- SetReadTimeout(timeout);
- return stream.Read(buffer, offset, size);
- }
- catch (IOException ioException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ConvertIOException(ioException));
- }
- }
- public AsyncCompletionResult BeginRead(int offset, int size, TimeSpan timeout, WaitCallback callback, object state)
- {
- ConnectionUtilities.ValidateBufferBounds(AsyncReadBufferSize, offset, size);
- readCallback = callback;
- try
- {
- SetReadTimeout(timeout);
- IAsyncResult localResult = stream.BeginRead(AsyncReadBuffer, offset, size, onRead, state);
- if (!localResult.CompletedSynchronously)
- {
- return AsyncCompletionResult.Queued;
- }
- bytesRead = stream.EndRead(localResult);
- }
- catch (IOException ioException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ConvertIOException(ioException));
- }
- return AsyncCompletionResult.Completed;
- }
- public int EndRead()
- {
- IAsyncResult localResult = this.readResult;
- this.readResult = null;
- if (localResult != null)
- {
- try
- {
- bytesRead = stream.EndRead(localResult);
- }
- catch (IOException ioException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ConvertIOException(ioException));
- }
- }
- return bytesRead;
- }
- void OnRead(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- if (this.readResult != null)
- {
- throw Fx.AssertAndThrow("StreamConnection: OnRead called twice.");
- }
- this.readResult = result;
- readCallback(result.AsyncState);
- }
- }
- class ConnectionMessageProperty
- {
- IConnection connection;
- public ConnectionMessageProperty(IConnection connection)
- {
- this.connection = connection;
- }
- public static string Name
- {
- get { return "iconnection"; }
- }
- public IConnection Connection
- {
- get { return this.connection; }
- }
- }
- static class ConnectionUtilities
- {
- internal static void CloseNoThrow(IConnection connection, TimeSpan timeout)
- {
- bool success = false;
- try
- {
- connection.Close(timeout, false);
- success = true;
- }
- catch (TimeoutException e)
- {
- if (TD.CloseTimeoutIsEnabled())
- {
- TD.CloseTimeout(e.Message);
- }
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- }
- catch (CommunicationException e)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- }
- finally
- {
- if (!success)
- {
- connection.Abort();
- }
- }
- }
- internal static void ValidateBufferBounds(ArraySegment<byte> buffer)
- {
- ValidateBufferBounds(buffer.Array, buffer.Offset, buffer.Count);
- }
- internal static void ValidateBufferBounds(byte[] buffer, int offset, int size)
- {
- if (buffer == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
- }
- ValidateBufferBounds(buffer.Length, offset, size);
- }
- internal static void ValidateBufferBounds(int bufferSize, int offset, int size)
- {
- if (offset < 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", offset, SR.GetString(
- SR.ValueMustBeNonNegative)));
- }
- if (offset > bufferSize)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", offset, SR.GetString(
- SR.OffsetExceedsBufferSize, bufferSize)));
- }
- if (size <= 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("size", size, SR.GetString(
- SR.ValueMustBePositive)));
- }
- int remainingBufferSpace = bufferSize - offset;
- if (size > remainingBufferSpace)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("size", size, SR.GetString(
- SR.SizeExceedsRemainingBufferSpace, remainingBufferSpace)));
- }
- }
- }
- }
|