| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System;
- using System.Diagnostics;
- using System.Net;
- using System.Runtime;
- using System.Runtime.CompilerServices;
- using System.Security.Authentication.ExtendedProtection;
- using System.ServiceModel;
- using System.ServiceModel.Activation;
- using System.ServiceModel.Description;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Dispatcher;
- using System.ServiceModel.Security;
- using System.Threading;
- using System.Xml;
- using System.ServiceModel.Diagnostics.Application;
- delegate void ServerSessionPreambleCallback(ServerSessionPreambleConnectionReader serverSessionPreambleReader);
- delegate void ServerSessionPreambleDemuxCallback(ServerSessionPreambleConnectionReader serverSessionPreambleReader, ConnectionDemuxer connectionDemuxer);
- interface ISessionPreambleHandler
- {
- void HandleServerSessionPreamble(ServerSessionPreambleConnectionReader serverSessionPreambleReader,
- ConnectionDemuxer connectionDemuxer);
- }
- // reads everything we need in order to match a channel (i.e. up to the via)
- class ServerSessionPreambleConnectionReader : InitialServerConnectionReader
- {
- ServerSessionDecoder decoder;
- byte[] connectionBuffer;
- int offset;
- int size;
- TransportSettingsCallback transportSettingsCallback;
- ServerSessionPreambleCallback callback;
- static WaitCallback readCallback;
- IConnectionOrientedTransportFactorySettings settings;
- Uri via;
- Action<Uri> viaDelegate;
- TimeoutHelper receiveTimeoutHelper;
- IConnection rawConnection;
- static AsyncCallback onValidate;
- public ServerSessionPreambleConnectionReader(IConnection connection, Action connectionDequeuedCallback,
- long streamPosition, int offset, int size, TransportSettingsCallback transportSettingsCallback,
- ConnectionClosedCallback closedCallback, ServerSessionPreambleCallback callback)
- : base(connection, closedCallback)
- {
- this.rawConnection = connection;
- this.decoder = new ServerSessionDecoder(streamPosition, MaxViaSize, MaxContentTypeSize);
- this.offset = offset;
- this.size = size;
- this.transportSettingsCallback = transportSettingsCallback;
- this.callback = callback;
- this.ConnectionDequeuedCallback = connectionDequeuedCallback;
- }
- public int BufferOffset
- {
- get { return offset; }
- }
- public int BufferSize
- {
- get { return size; }
- }
- public ServerSessionDecoder Decoder
- {
- get { return decoder; }
- }
- public IConnection RawConnection
- {
- get { return rawConnection; }
- }
- public Uri Via
- {
- get { return this.via; }
- }
- TimeSpan GetRemainingTimeout()
- {
- return this.receiveTimeoutHelper.RemainingTime();
- }
- static void ReadCallback(object state)
- {
- ServerSessionPreambleConnectionReader reader = (ServerSessionPreambleConnectionReader)state;
- bool success = false;
- try
- {
- reader.GetReadResult();
- reader.ContinueReading();
- success = true;
- }
- catch (CommunicationException exception)
- {
- DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
- }
- catch (TimeoutException exception)
- {
- if (TD.ReceiveTimeoutIsEnabled())
- {
- TD.ReceiveTimeout(exception.Message);
- }
- DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (!ExceptionHandler.HandleTransportExceptionHelper(e))
- {
- throw;
- }
- // containment -- all errors abort the reader, no additional containment action needed
- }
- finally
- {
- if (!success)
- {
- reader.Abort();
- }
- }
- }
- void GetReadResult()
- {
- offset = 0;
- size = Connection.EndRead();
- if (size == 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
- }
- }
- void ContinueReading()
- {
- bool success = false;
- try
- {
- for (;;)
- {
- if (size == 0)
- {
- if (readCallback == null)
- {
- readCallback = new WaitCallback(ReadCallback);
- }
- if (Connection.BeginRead(0, connectionBuffer.Length, GetRemainingTimeout(), readCallback, this)
- == AsyncCompletionResult.Queued)
- {
- break;
- }
- GetReadResult();
- }
- int bytesDecoded = decoder.Decode(connectionBuffer, offset, size);
- if (bytesDecoded > 0)
- {
- offset += bytesDecoded;
- size -= bytesDecoded;
- }
- if (decoder.CurrentState == ServerSessionDecoder.State.PreUpgradeStart)
- {
- if (onValidate == null)
- {
- onValidate = Fx.ThunkCallback(new AsyncCallback(OnValidate));
- }
- this.via = decoder.Via;
- IAsyncResult result = this.Connection.BeginValidate(this.via, onValidate, this);
- if (result.CompletedSynchronously)
- {
- if (!VerifyValidationResult(result))
- {
- // This goes through the failure path (Abort) even though it doesn't throw.
- return;
- }
- }
- break; //exit loop, set success=true;
- }
- }
- success = true;
- }
- catch (CommunicationException exception)
- {
- DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
- }
- catch (TimeoutException exception)
- {
- if (TD.ReceiveTimeoutIsEnabled())
- {
- TD.ReceiveTimeout(exception.Message);
- }
- DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (!ExceptionHandler.HandleTransportExceptionHelper(e))
- {
- throw;
- }
- // containment -- all exceptions abort the reader, no additional containment action necessary
- }
- finally
- {
- if (!success)
- {
- Abort();
- }
- }
- }
- //returns true if validation was successful
- bool VerifyValidationResult(IAsyncResult result)
- {
- return this.Connection.EndValidate(result) && this.ContinuePostValidationProcessing();
- }
- static void OnValidate(IAsyncResult result)
- {
- bool success = false;
- ServerSessionPreambleConnectionReader thisPtr = (ServerSessionPreambleConnectionReader)result.AsyncState;
- try
- {
- if (!result.CompletedSynchronously)
- {
- if (!thisPtr.VerifyValidationResult(result))
- {
- // This goes through the failure path (Abort) even though it doesn't throw.
- return;
- }
- }
- success = true;
- }
- catch (CommunicationException exception)
- {
- DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
- }
- catch (TimeoutException exception)
- {
- if (TD.ReceiveTimeoutIsEnabled())
- {
- TD.ReceiveTimeout(exception.Message);
- }
- DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- }
- finally
- {
- if (!success)
- {
- thisPtr.Abort();
- }
- }
- }
- //returns false if the connection should be aborted
- bool ContinuePostValidationProcessing()
- {
- if (viaDelegate != null)
- {
- try
- {
- viaDelegate(via);
- }
- catch (ServiceActivationException e)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- // return fault and close connection
- SendFault(FramingEncodingString.ServiceActivationFailedFault);
- return true;
- }
- }
- this.settings = transportSettingsCallback(via);
- if (settings == null)
- {
- EndpointNotFoundException e = new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, decoder.Via));
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- SendFault(FramingEncodingString.EndpointNotFoundFault);
- return false;
- }
- // we have enough information to hand off to a channel. Our job is done
- callback(this);
- return true;
- }
- public void SendFault(string faultString)
- {
- InitialServerConnectionReader.SendFault(
- Connection, faultString, this.connectionBuffer, GetRemainingTimeout(),
- TransportDefaults.MaxDrainSize);
- base.Close(GetRemainingTimeout());
- }
- public void StartReading(Action<Uri> viaDelegate, TimeSpan receiveTimeout)
- {
- this.viaDelegate = viaDelegate;
- this.receiveTimeoutHelper = new TimeoutHelper(receiveTimeout);
- this.connectionBuffer = Connection.AsyncReadBuffer;
- ContinueReading();
- }
- public IDuplexSessionChannel CreateDuplexSessionChannel(ConnectionOrientedTransportChannelListener channelListener, EndpointAddress localAddress, bool exposeConnectionProperty, ConnectionDemuxer connectionDemuxer)
- {
- return new ServerFramingDuplexSessionChannel(channelListener, this, localAddress, exposeConnectionProperty, connectionDemuxer);
- }
- class ServerFramingDuplexSessionChannel : FramingDuplexSessionChannel
- {
- ConnectionOrientedTransportChannelListener channelListener;
- ConnectionDemuxer connectionDemuxer;
- ServerSessionConnectionReader sessionReader;
- ServerSessionDecoder decoder;
- IConnection rawConnection;
- byte[] connectionBuffer;
- int offset;
- int size;
- StreamUpgradeAcceptor upgradeAcceptor;
- IStreamUpgradeChannelBindingProvider channelBindingProvider;
- public ServerFramingDuplexSessionChannel(ConnectionOrientedTransportChannelListener channelListener, ServerSessionPreambleConnectionReader preambleReader,
- EndpointAddress localAddress, bool exposeConnectionProperty, ConnectionDemuxer connectionDemuxer)
- : base(channelListener, localAddress, preambleReader.Via, exposeConnectionProperty)
- {
- this.channelListener = channelListener;
- this.connectionDemuxer = connectionDemuxer;
- this.Connection = preambleReader.Connection;
- this.decoder = preambleReader.Decoder;
- this.connectionBuffer = preambleReader.connectionBuffer;
- this.offset = preambleReader.BufferOffset;
- this.size = preambleReader.BufferSize;
- this.rawConnection = preambleReader.RawConnection;
- StreamUpgradeProvider upgrade = channelListener.Upgrade;
- if (upgrade != null)
- {
- this.channelBindingProvider = upgrade.GetProperty<IStreamUpgradeChannelBindingProvider>();
- this.upgradeAcceptor = upgrade.CreateUpgradeAcceptor();
- }
- }
- protected override void ReturnConnectionIfNecessary(bool abort, TimeSpan timeout)
- {
- IConnection localConnection = null;
- if (this.sessionReader != null)
- {
- lock (ThisLock)
- {
- localConnection = this.sessionReader.GetRawConnection();
- }
- }
- if (localConnection != null)
- {
- if (abort)
- {
- localConnection.Abort();
- }
- else
- {
- this.connectionDemuxer.ReuseConnection(localConnection, timeout);
- }
- this.connectionDemuxer = null;
- }
- }
- public override T GetProperty<T>()
- {
- if (typeof(T) == typeof(IChannelBindingProvider))
- {
- return (T)(object)this.channelBindingProvider;
- }
- return base.GetProperty<T>();
- }
- protected override void PrepareMessage(Message message)
- {
- channelListener.RaiseMessageReceived();
- base.PrepareMessage(message);
- }
- // perform security handshake and ACK connection
- protected override void OnOpen(TimeSpan timeout)
- {
- bool success = false;
- try
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- // first validate our content type
- ValidateContentType(ref timeoutHelper);
- // next read any potential upgrades and finish consuming the preamble
- for (;;)
- {
- if (size == 0)
- {
- offset = 0;
- size = Connection.Read(connectionBuffer, 0, connectionBuffer.Length, timeoutHelper.RemainingTime());
- if (size == 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
- }
- }
- for (;;)
- {
- DecodeBytes();
- switch (decoder.CurrentState)
- {
- case ServerSessionDecoder.State.UpgradeRequest:
- ProcessUpgradeRequest(ref timeoutHelper);
- // accept upgrade
- Connection.Write(ServerSessionEncoder.UpgradeResponseBytes, 0, ServerSessionEncoder.UpgradeResponseBytes.Length, true, timeoutHelper.RemainingTime());
- IConnection connectionToUpgrade = this.Connection;
- if (this.size > 0)
- {
- connectionToUpgrade = new PreReadConnection(connectionToUpgrade, this.connectionBuffer, this.offset, this.size);
- }
- try
- {
- this.Connection = InitialServerConnectionReader.UpgradeConnection(connectionToUpgrade, upgradeAcceptor, this);
- if (this.channelBindingProvider != null && this.channelBindingProvider.IsChannelBindingSupportEnabled)
- {
- this.SetChannelBinding(this.channelBindingProvider.GetChannelBinding(this.upgradeAcceptor, ChannelBindingKind.Endpoint));
- }
- this.connectionBuffer = Connection.AsyncReadBuffer;
- }
- #pragma warning suppress 56500
- catch (Exception exception)
- {
- if (Fx.IsFatal(exception))
- throw;
- // Audit Authentication Failure
- WriteAuditFailure(upgradeAcceptor as StreamSecurityUpgradeAcceptor, exception);
- throw;
- }
- break;
- case ServerSessionDecoder.State.Start:
- SetupSecurityIfNecessary();
- // we've finished the preamble. Ack and return.
- Connection.Write(ServerSessionEncoder.AckResponseBytes, 0,
- ServerSessionEncoder.AckResponseBytes.Length, true, timeoutHelper.RemainingTime());
- SetupSessionReader();
- success = true;
- return;
- }
- if (size == 0)
- break;
- }
- }
- }
- finally
- {
- if (!success)
- {
- Connection.Abort();
- }
- }
- }
- void AcceptUpgradedConnection(IConnection upgradedConnection)
- {
- this.Connection = upgradedConnection;
- if (this.channelBindingProvider != null && this.channelBindingProvider.IsChannelBindingSupportEnabled)
- {
- this.SetChannelBinding(this.channelBindingProvider.GetChannelBinding(this.upgradeAcceptor, ChannelBindingKind.Endpoint));
- }
- this.connectionBuffer = Connection.AsyncReadBuffer;
- }
- void ValidateContentType(ref TimeoutHelper timeoutHelper)
- {
- this.MessageEncoder = channelListener.MessageEncoderFactory.CreateSessionEncoder();
- if (!this.MessageEncoder.IsContentTypeSupported(decoder.ContentType))
- {
- SendFault(FramingEncodingString.ContentTypeInvalidFault, ref timeoutHelper);
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(
- SR.ContentTypeMismatch, decoder.ContentType, this.MessageEncoder.ContentType)));
- }
- ICompressedMessageEncoder compressedMessageEncoder = this.MessageEncoder as ICompressedMessageEncoder;
- if (compressedMessageEncoder != null && compressedMessageEncoder.CompressionEnabled)
- {
- compressedMessageEncoder.SetSessionContentType(this.decoder.ContentType);
- }
- }
- void DecodeBytes()
- {
- int bytesDecoded = decoder.Decode(connectionBuffer, offset, size);
- if (bytesDecoded > 0)
- {
- offset += bytesDecoded;
- size -= bytesDecoded;
- }
- }
- void ProcessUpgradeRequest(ref TimeoutHelper timeoutHelper)
- {
- if (this.upgradeAcceptor == null)
- {
- SendFault(FramingEncodingString.UpgradeInvalidFault, ref timeoutHelper);
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ProtocolException(SR.GetString(SR.UpgradeRequestToNonupgradableService, decoder.Upgrade)));
- }
- if (!this.upgradeAcceptor.CanUpgrade(decoder.Upgrade))
- {
- SendFault(FramingEncodingString.UpgradeInvalidFault, ref timeoutHelper);
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ProtocolException(SR.GetString(SR.UpgradeProtocolNotSupported, decoder.Upgrade)));
- }
- }
- void SendFault(string faultString, ref TimeoutHelper timeoutHelper)
- {
- InitialServerConnectionReader.SendFault(Connection, faultString,
- connectionBuffer, timeoutHelper.RemainingTime(), TransportDefaults.MaxDrainSize);
- }
- void SetupSecurityIfNecessary()
- {
- StreamSecurityUpgradeAcceptor securityUpgradeAcceptor = this.upgradeAcceptor as StreamSecurityUpgradeAcceptor;
- if (securityUpgradeAcceptor != null)
- {
- this.RemoteSecurity = securityUpgradeAcceptor.GetRemoteSecurity();
- if (this.RemoteSecurity == null)
- {
- Exception securityFailedException = new ProtocolException(
- SR.GetString(SR.RemoteSecurityNotNegotiatedOnStreamUpgrade, this.Via));
- WriteAuditFailure(securityUpgradeAcceptor, securityFailedException);
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(securityFailedException);
- }
- else
- {
- // Audit Authentication Success
- WriteAuditEvent(securityUpgradeAcceptor, AuditLevel.Success, null);
- }
- }
- }
- void SetupSessionReader()
- {
- this.sessionReader = new ServerSessionConnectionReader(this);
- base.SetMessageSource(this.sessionReader);
- }
- protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
- {
- return new OpenAsyncResult(this, timeout, callback, state);
- }
- protected override void OnEndOpen(IAsyncResult result)
- {
- OpenAsyncResult.End(result);
- }
- #region Transport Security Auditing
- void WriteAuditFailure(StreamSecurityUpgradeAcceptor securityUpgradeAcceptor, Exception exception)
- {
- try
- {
- WriteAuditEvent(securityUpgradeAcceptor, AuditLevel.Failure, exception);
- }
- #pragma warning suppress 56500 // covered by FxCop
- catch (Exception auditException)
- {
- if (Fx.IsFatal(auditException))
- {
- throw;
- }
- DiagnosticUtility.TraceHandledException(auditException, TraceEventType.Error);
- }
- }
- void WriteAuditEvent(StreamSecurityUpgradeAcceptor securityUpgradeAcceptor, AuditLevel auditLevel, Exception exception)
- {
- if ((this.channelListener.AuditBehavior.MessageAuthenticationAuditLevel & auditLevel) != auditLevel)
- {
- return;
- }
- if (securityUpgradeAcceptor == null)
- {
- return;
- }
- String primaryIdentity = String.Empty;
- SecurityMessageProperty clientSecurity = securityUpgradeAcceptor.GetRemoteSecurity();
- if (clientSecurity != null)
- {
- primaryIdentity = GetIdentityNameFromContext(clientSecurity);
- }
- ServiceSecurityAuditBehavior auditBehavior = this.channelListener.AuditBehavior;
- if (auditLevel == AuditLevel.Success)
- {
- SecurityAuditHelper.WriteTransportAuthenticationSuccessEvent(auditBehavior.AuditLogLocation,
- auditBehavior.SuppressAuditFailure, null, this.LocalVia, primaryIdentity);
- }
- else
- {
- SecurityAuditHelper.WriteTransportAuthenticationFailureEvent(auditBehavior.AuditLogLocation,
- auditBehavior.SuppressAuditFailure, null, this.LocalVia, primaryIdentity, exception);
- }
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- static string GetIdentityNameFromContext(SecurityMessageProperty clientSecurity)
- {
- return SecurityUtils.GetIdentityNamesFromContext(
- clientSecurity.ServiceSecurityContext.AuthorizationContext);
- }
- #endregion
- class OpenAsyncResult : AsyncResult
- {
- ServerFramingDuplexSessionChannel channel;
- TimeoutHelper timeoutHelper;
- static WaitCallback readCallback;
- static WaitCallback onWriteAckResponse;
- static WaitCallback onWriteUpgradeResponse;
- static AsyncCallback onUpgradeConnection;
- public OpenAsyncResult(ServerFramingDuplexSessionChannel channel, TimeSpan timeout,
- AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.channel = channel;
- this.timeoutHelper = new TimeoutHelper(timeout);
- bool completeSelf = false;
- bool success = false;
- try
- {
- channel.ValidateContentType(ref this.timeoutHelper);
- completeSelf = ContinueReading();
- success = true;
- }
- finally
- {
- if (!success)
- {
- CleanupOnError();
- }
- }
- if (completeSelf)
- {
- base.Complete(true);
- }
- }
- public static void End(IAsyncResult result)
- {
- AsyncResult.End<OpenAsyncResult>(result);
- }
- void CleanupOnError()
- {
- this.channel.Connection.Abort();
- }
- bool ContinueReading()
- {
- for (;;)
- {
- if (channel.size == 0)
- {
- if (readCallback == null)
- {
- readCallback = new WaitCallback(ReadCallback);
- }
- if (channel.Connection.BeginRead(0, channel.connectionBuffer.Length, timeoutHelper.RemainingTime(),
- readCallback, this) == AsyncCompletionResult.Queued)
- {
- return false;
- }
- GetReadResult();
- }
- for (;;)
- {
- channel.DecodeBytes();
- switch (channel.decoder.CurrentState)
- {
- case ServerSessionDecoder.State.UpgradeRequest:
- channel.ProcessUpgradeRequest(ref this.timeoutHelper);
- // accept upgrade
- if (onWriteUpgradeResponse == null)
- {
- onWriteUpgradeResponse = Fx.ThunkCallback(new WaitCallback(OnWriteUpgradeResponse));
- }
- AsyncCompletionResult writeResult = channel.Connection.BeginWrite(
- ServerSessionEncoder.UpgradeResponseBytes, 0, ServerSessionEncoder.UpgradeResponseBytes.Length,
- true, timeoutHelper.RemainingTime(), onWriteUpgradeResponse, this);
- if (writeResult == AsyncCompletionResult.Queued)
- {
- return false;
- }
- if (!HandleWriteUpgradeResponseComplete())
- {
- return false;
- }
- break;
- case ServerSessionDecoder.State.Start:
- channel.SetupSecurityIfNecessary();
- // we've finished the preamble. Ack and return.
- if (onWriteAckResponse == null)
- {
- onWriteAckResponse = Fx.ThunkCallback(new WaitCallback(OnWriteAckResponse));
- }
- AsyncCompletionResult writeAckResult =
- channel.Connection.BeginWrite(ServerSessionEncoder.AckResponseBytes, 0,
- ServerSessionEncoder.AckResponseBytes.Length, true, timeoutHelper.RemainingTime(),
- onWriteAckResponse, this);
- if (writeAckResult == AsyncCompletionResult.Queued)
- {
- return false;
- }
- return HandleWriteAckComplete();
- }
- if (channel.size == 0)
- break;
- }
- }
- }
- void GetReadResult()
- {
- channel.offset = 0;
- channel.size = channel.Connection.EndRead();
- if (channel.size == 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(channel.decoder.CreatePrematureEOFException());
- }
- }
- bool HandleWriteUpgradeResponseComplete()
- {
- channel.Connection.EndWrite();
- IConnection connectionToUpgrade = channel.Connection;
- if (channel.size > 0)
- {
- connectionToUpgrade = new PreReadConnection(connectionToUpgrade, channel.connectionBuffer, channel.offset, channel.size);
- }
- if (onUpgradeConnection == null)
- {
- onUpgradeConnection = Fx.ThunkCallback(new AsyncCallback(OnUpgradeConnection));
- }
- try
- {
- IAsyncResult upgradeConnectionResult = InitialServerConnectionReader.BeginUpgradeConnection(
- connectionToUpgrade, channel.upgradeAcceptor, channel, onUpgradeConnection, this);
- if (!upgradeConnectionResult.CompletedSynchronously)
- {
- return false;
- }
- return HandleUpgradeConnectionComplete(upgradeConnectionResult);
- }
- #pragma warning suppress 56500
- catch (Exception exception)
- {
- if (Fx.IsFatal(exception))
- {
- throw;
- }
- // Audit Authentication Failure
- this.channel.WriteAuditFailure(channel.upgradeAcceptor as StreamSecurityUpgradeAcceptor, exception);
- throw;
- }
- }
- bool HandleUpgradeConnectionComplete(IAsyncResult result)
- {
- channel.AcceptUpgradedConnection(InitialServerConnectionReader.EndUpgradeConnection(result));
- return true;
- }
- bool HandleWriteAckComplete()
- {
- channel.Connection.EndWrite();
- channel.SetupSessionReader();
- return true;
- }
- static void ReadCallback(object state)
- {
- OpenAsyncResult thisPtr = (OpenAsyncResult)state;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- thisPtr.GetReadResult();
- completeSelf = thisPtr.ContinueReading();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- thisPtr.CleanupOnError();
- }
- if (completeSelf)
- {
- thisPtr.Complete(false, completionException);
- }
- }
- static void OnWriteUpgradeResponse(object asyncState)
- {
- OpenAsyncResult thisPtr = (OpenAsyncResult)asyncState;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- completeSelf = thisPtr.HandleWriteUpgradeResponseComplete();
- if (completeSelf)
- {
- completeSelf = thisPtr.ContinueReading();
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- completeSelf = true;
- thisPtr.CleanupOnError();
- // Audit Authentication Failure
- thisPtr.channel.WriteAuditFailure(thisPtr.channel.upgradeAcceptor as StreamSecurityUpgradeAcceptor, e);
- }
- if (completeSelf)
- {
- thisPtr.Complete(false, completionException);
- }
- }
- static void OnUpgradeConnection(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- OpenAsyncResult thisPtr = (OpenAsyncResult)result.AsyncState;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- completeSelf = thisPtr.HandleUpgradeConnectionComplete(result);
- if (completeSelf)
- {
- completeSelf = thisPtr.ContinueReading();
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- completeSelf = true;
- thisPtr.CleanupOnError();
- // Audit Authentication Failure
- thisPtr.channel.WriteAuditFailure(thisPtr.channel.upgradeAcceptor as StreamSecurityUpgradeAcceptor, e);
- }
- if (completeSelf)
- {
- thisPtr.Complete(false, completionException);
- }
- }
- static void OnWriteAckResponse(object asyncState)
- {
- OpenAsyncResult thisPtr = (OpenAsyncResult)asyncState;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- completeSelf = thisPtr.HandleWriteAckComplete();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- completeSelf = true;
- thisPtr.CleanupOnError();
- }
- if (completeSelf)
- {
- thisPtr.Complete(false, completionException);
- }
- }
- }
- class ServerSessionConnectionReader : SessionConnectionReader
- {
- ServerSessionDecoder decoder;
- int maxBufferSize;
- BufferManager bufferManager;
- MessageEncoder messageEncoder;
- string contentType;
- IConnection rawConnection;
- public ServerSessionConnectionReader(ServerFramingDuplexSessionChannel channel)
- : base(channel.Connection, channel.rawConnection, channel.offset, channel.size, channel.RemoteSecurity)
- {
- this.decoder = channel.decoder;
- this.contentType = this.decoder.ContentType;
- this.maxBufferSize = channel.channelListener.MaxBufferSize;
- this.bufferManager = channel.channelListener.BufferManager;
- this.messageEncoder = channel.MessageEncoder;
- this.rawConnection = channel.rawConnection;
- }
- protected override void EnsureDecoderAtEof()
- {
- if (!(decoder.CurrentState == ServerSessionDecoder.State.End || decoder.CurrentState == ServerSessionDecoder.State.EnvelopeEnd))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
- }
- }
- protected override Message DecodeMessage(byte[] buffer, ref int offset, ref int size, ref bool isAtEof, TimeSpan timeout)
- {
- while (!isAtEof && size > 0)
- {
- int bytesRead = decoder.Decode(buffer, offset, size);
- if (bytesRead > 0)
- {
- if (EnvelopeBuffer != null)
- {
- if (!object.ReferenceEquals(buffer, EnvelopeBuffer))
- {
- System.Buffer.BlockCopy(buffer, offset, EnvelopeBuffer, EnvelopeOffset, bytesRead);
- }
- EnvelopeOffset += bytesRead;
- }
- offset += bytesRead;
- size -= bytesRead;
- }
- switch (decoder.CurrentState)
- {
- case ServerSessionDecoder.State.EnvelopeStart:
- int envelopeSize = decoder.EnvelopeSize;
- if (envelopeSize > maxBufferSize)
- {
- base.SendFault(FramingEncodingString.MaxMessageSizeExceededFault, timeout);
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- MaxMessageSizeStream.CreateMaxReceivedMessageSizeExceededException(maxBufferSize));
- }
- EnvelopeBuffer = bufferManager.TakeBuffer(envelopeSize);
- EnvelopeOffset = 0;
- EnvelopeSize = envelopeSize;
- break;
- case ServerSessionDecoder.State.EnvelopeEnd:
- if (EnvelopeBuffer != null)
- {
- using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity(true) : null)
- {
- if (DiagnosticUtility.ShouldUseActivity)
- {
- ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityProcessingMessage, TraceUtility.RetrieveMessageNumber()), ActivityType.ProcessMessage);
- }
- Message message = null;
- try
- {
- message = messageEncoder.ReadMessage(new ArraySegment<byte>(EnvelopeBuffer, 0, EnvelopeSize), bufferManager, this.contentType);
- }
- catch (XmlException xmlException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ProtocolException(SR.GetString(SR.MessageXmlProtocolError), xmlException));
- }
- if (DiagnosticUtility.ShouldUseActivity)
- {
- TraceUtility.TransferFromTransport(message);
- }
- EnvelopeBuffer = null;
- return message;
- }
- }
- break;
- case ServerSessionDecoder.State.End:
- isAtEof = true;
- break;
- }
- }
- return null;
- }
- protected override void PrepareMessage(Message message)
- {
- base.PrepareMessage(message);
- IPEndPoint remoteEndPoint = this.rawConnection.RemoteIPEndPoint;
- // pipes will return null
- if (remoteEndPoint != null)
- {
- RemoteEndpointMessageProperty remoteEndpointProperty = new RemoteEndpointMessageProperty(remoteEndPoint);
- message.Properties.Add(RemoteEndpointMessageProperty.Name, remoteEndpointProperty);
- }
- }
- }
- }
- }
- abstract class SessionConnectionReader : IMessageSource
- {
- bool isAtEOF;
- bool usingAsyncReadBuffer;
- IConnection connection;
- byte[] buffer;
- int offset;
- int size;
- byte[] envelopeBuffer;
- int envelopeOffset;
- int envelopeSize;
- bool readIntoEnvelopeBuffer;
- WaitCallback onAsyncReadComplete;
- Message pendingMessage;
- Exception pendingException;
- WaitCallback pendingCallback;
- object pendingCallbackState;
- SecurityMessageProperty security;
- TimeoutHelper readTimeoutHelper;
- // Raw connection that we will revert to after end handshake
- IConnection rawConnection;
- protected SessionConnectionReader(IConnection connection, IConnection rawConnection,
- int offset, int size, SecurityMessageProperty security)
- {
- this.offset = offset;
- this.size = size;
- if (size > 0)
- {
- this.buffer = connection.AsyncReadBuffer;
- }
- this.connection = connection;
- this.rawConnection = rawConnection;
- this.onAsyncReadComplete = new WaitCallback(OnAsyncReadComplete);
- this.security = security;
- }
- Message DecodeMessage(TimeSpan timeout)
- {
- if (DiagnosticUtility.ShouldUseActivity &&
- ServiceModelActivity.Current != null &&
- ServiceModelActivity.Current.ActivityType == ActivityType.ProcessAction)
- {
- ServiceModelActivity.Current.Resume();
- }
- if (!readIntoEnvelopeBuffer)
- {
- return DecodeMessage(buffer, ref offset, ref size, ref isAtEOF, timeout);
- }
- else
- {
- // decode from the envelope buffer
- int dummyOffset = this.envelopeOffset;
- return DecodeMessage(envelopeBuffer, ref dummyOffset, ref size, ref isAtEOF, timeout);
- }
- }
- protected abstract Message DecodeMessage(byte[] buffer, ref int offset, ref int size, ref bool isAtEof, TimeSpan timeout);
- protected byte[] EnvelopeBuffer
- {
- get { return envelopeBuffer; }
- set { envelopeBuffer = value; }
- }
- protected int EnvelopeOffset
- {
- get { return envelopeOffset; }
- set { envelopeOffset = value; }
- }
- protected int EnvelopeSize
- {
- get { return envelopeSize; }
- set { envelopeSize = value; }
- }
- public IConnection GetRawConnection()
- {
- IConnection result = null;
- if (this.rawConnection != null)
- {
- result = this.rawConnection;
- this.rawConnection = null;
- if (size > 0)
- {
- PreReadConnection preReadConnection = result as PreReadConnection;
- if (preReadConnection != null) // make sure we don't keep wrapping
- {
- preReadConnection.AddPreReadData(this.buffer, this.offset, this.size);
- }
- else
- {
- result = new PreReadConnection(result, this.buffer, this.offset, this.size);
- }
- }
- }
- return result;
- }
- public AsyncReceiveResult BeginReceive(TimeSpan timeout, WaitCallback callback, object state)
- {
- if (pendingMessage != null || pendingException != null)
- {
- return AsyncReceiveResult.Completed;
- }
- this.readTimeoutHelper = new TimeoutHelper(timeout);
- for (;;)
- {
- if (isAtEOF)
- {
- return AsyncReceiveResult.Completed;
- }
- if (size > 0)
- {
- pendingMessage = DecodeMessage(readTimeoutHelper.RemainingTime());
- if (pendingMessage != null)
- {
- PrepareMessage(pendingMessage);
- return AsyncReceiveResult.Completed;
- }
- else if (isAtEOF) // could have read the END record under DecodeMessage
- {
- return AsyncReceiveResult.Completed;
- }
- }
- if (size != 0)
- {
- throw Fx.AssertAndThrow("BeginReceive: DecodeMessage() should consume the outstanding buffer or return a message.");
- }
- if (!usingAsyncReadBuffer)
- {
- buffer = connection.AsyncReadBuffer;
- usingAsyncReadBuffer = true;
- }
- pendingCallback = callback;
- pendingCallbackState = state;
- bool throwing = true;
- AsyncCompletionResult asyncReadResult;
- try
- {
- asyncReadResult =
- connection.BeginRead(0, buffer.Length, readTimeoutHelper.RemainingTime(), onAsyncReadComplete, null);
- throwing = false;
- }
- finally
- {
- if (throwing)
- {
- pendingCallback = null;
- pendingCallbackState = null;
- }
- }
- if (asyncReadResult == AsyncCompletionResult.Queued)
- {
- return AsyncReceiveResult.Pending;
- }
- pendingCallback = null;
- pendingCallbackState = null;
- int bytesRead = connection.EndRead();
- HandleReadComplete(bytesRead, false);
- }
- }
- public Message Receive(TimeSpan timeout)
- {
- Message message = GetPendingMessage();
- if (message != null)
- {
- return message;
- }
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- for (;;)
- {
- if (isAtEOF)
- {
- return null;
- }
- if (size > 0)
- {
- message = DecodeMessage(timeoutHelper.RemainingTime());
- if (message != null)
- {
- PrepareMessage(message);
- return message;
- }
- else if (isAtEOF) // could have read the END record under DecodeMessage
- {
- return null;
- }
- }
- if (size != 0)
- {
- throw Fx.AssertAndThrow("Receive: DecodeMessage() should consume the outstanding buffer or return a message.");
- }
- if (buffer == null)
- {
- buffer = DiagnosticUtility.Utility.AllocateByteArray(connection.AsyncReadBufferSize);
- }
- int bytesRead;
- if (EnvelopeBuffer != null &&
- (EnvelopeSize - EnvelopeOffset) >= buffer.Length)
- {
- bytesRead = connection.Read(EnvelopeBuffer, EnvelopeOffset, buffer.Length, timeoutHelper.RemainingTime());
- HandleReadComplete(bytesRead, true);
- }
- else
- {
- bytesRead = connection.Read(buffer, 0, buffer.Length, timeoutHelper.RemainingTime());
- HandleReadComplete(bytesRead, false);
- }
- }
- }
- public Message EndReceive()
- {
- return GetPendingMessage();
- }
- Message GetPendingMessage()
- {
- if (pendingException != null)
- {
- Exception exception = pendingException;
- pendingException = null;
- throw TraceUtility.ThrowHelperError(exception, pendingMessage);
- }
- if (pendingMessage != null)
- {
- Message message = pendingMessage;
- pendingMessage = null;
- return message;
- }
- return null;
- }
- public AsyncReceiveResult BeginWaitForMessage(TimeSpan timeout, WaitCallback callback, object state)
- {
- try
- {
- return BeginReceive(timeout, callback, state);
- }
- catch (TimeoutException e)
- {
- pendingException = e;
- return AsyncReceiveResult.Completed;
- }
- }
- public bool EndWaitForMessage()
- {
- try
- {
- Message message = EndReceive();
- this.pendingMessage = message;
- return true;
- }
- catch (TimeoutException e)
- {
- if (TD.ReceiveTimeoutIsEnabled())
- {
- TD.ReceiveTimeout(e.Message);
- }
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- return false;
- }
- }
- public bool WaitForMessage(TimeSpan timeout)
- {
- try
- {
- Message message = Receive(timeout);
- this.pendingMessage = message;
- return true;
- }
- catch (TimeoutException e)
- {
- if (TD.ReceiveTimeoutIsEnabled())
- {
- TD.ReceiveTimeout(e.Message);
- }
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- return false;
- }
- }
- protected abstract void EnsureDecoderAtEof();
- void HandleReadComplete(int bytesRead, bool readIntoEnvelopeBuffer)
- {
- this.readIntoEnvelopeBuffer = readIntoEnvelopeBuffer;
- if (bytesRead == 0)
- {
- EnsureDecoderAtEof();
- isAtEOF = true;
- }
- else
- {
- this.offset = 0;
- this.size = bytesRead;
- }
- }
- void OnAsyncReadComplete(object state)
- {
- try
- {
- for (;;)
- {
- int bytesRead = connection.EndRead();
- HandleReadComplete(bytesRead, false);
- if (isAtEOF)
- {
- break;
- }
- Message message = DecodeMessage(this.readTimeoutHelper.RemainingTime());
- if (message != null)
- {
- PrepareMessage(message);
- this.pendingMessage = message;
- break;
- }
- else if (isAtEOF) // could have read the END record under DecodeMessage
- {
- break;
- }
- if (size != 0)
- {
- throw Fx.AssertAndThrow("OnAsyncReadComplete: DecodeMessage() should consume the outstanding buffer or return a message.");
- }
- if (connection.BeginRead(0, buffer.Length, this.readTimeoutHelper.RemainingTime(),
- onAsyncReadComplete, null) == AsyncCompletionResult.Queued)
- {
- return;
- }
- }
- }
- #pragma warning suppress 56500 // [....], transferring exception to caller
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- pendingException = e;
- }
- WaitCallback callback = pendingCallback;
- object callbackState = pendingCallbackState;
- pendingCallback = null;
- pendingCallbackState = null;
- callback(callbackState);
- }
- protected virtual void PrepareMessage(Message message)
- {
- if (security != null)
- {
- message.Properties.Security = (SecurityMessageProperty)security.CreateCopy();
- }
- }
- protected void SendFault(string faultString, TimeSpan timeout)
- {
- byte[] drainBuffer = new byte[128];
- InitialServerConnectionReader.SendFault(
- connection, faultString, drainBuffer, timeout,
- TransportDefaults.MaxDrainSize);
- }
- }
- class ClientDuplexConnectionReader : SessionConnectionReader
- {
- ClientDuplexDecoder decoder;
- int maxBufferSize;
- BufferManager bufferManager;
- MessageEncoder messageEncoder;
- ClientFramingDuplexSessionChannel channel;
- public ClientDuplexConnectionReader(ClientFramingDuplexSessionChannel channel, IConnection connection, ClientDuplexDecoder decoder,
- IConnectionOrientedTransportFactorySettings settings, MessageEncoder messageEncoder)
- : base(connection, null, 0, 0, null)
- {
- this.decoder = decoder;
- this.maxBufferSize = settings.MaxBufferSize;
- this.bufferManager = settings.BufferManager;
- this.messageEncoder = messageEncoder;
- this.channel = channel;
- }
- protected override void EnsureDecoderAtEof()
- {
- if (!(decoder.CurrentState == ClientFramingDecoderState.End
- || decoder.CurrentState == ClientFramingDecoderState.EnvelopeEnd
- || decoder.CurrentState == ClientFramingDecoderState.ReadingUpgradeRecord
- || decoder.CurrentState == ClientFramingDecoderState.UpgradeResponse))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
- }
- }
- static IDisposable CreateProcessActionActivity()
- {
- IDisposable retval = null;
- if (DiagnosticUtility.ShouldUseActivity)
- {
- if ((ServiceModelActivity.Current != null) &&
- (ServiceModelActivity.Current.ActivityType == ActivityType.ProcessAction))
- {
- // Do nothing-- we are already OK
- }
- else if ((ServiceModelActivity.Current != null) &&
- (ServiceModelActivity.Current.PreviousActivity != null) &&
- (ServiceModelActivity.Current.PreviousActivity.ActivityType == ActivityType.ProcessAction))
- {
- retval = ServiceModelActivity.BoundOperation(ServiceModelActivity.Current.PreviousActivity);
- }
- else
- {
- ServiceModelActivity activity = ServiceModelActivity.CreateBoundedActivity(true);
- ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityProcessingMessage, TraceUtility.RetrieveMessageNumber()), ActivityType.ProcessMessage);
- retval = activity;
- }
- }
- return retval;
- }
- protected override Message DecodeMessage(byte[] buffer, ref int offset, ref int size, ref bool isAtEOF, TimeSpan timeout)
- {
- while (size > 0)
- {
- int bytesRead = decoder.Decode(buffer, offset, size);
- if (bytesRead > 0)
- {
- if (EnvelopeBuffer != null)
- {
- if (!object.ReferenceEquals(buffer, EnvelopeBuffer))
- System.Buffer.BlockCopy(buffer, offset, EnvelopeBuffer, EnvelopeOffset, bytesRead);
- EnvelopeOffset += bytesRead;
- }
- offset += bytesRead;
- size -= bytesRead;
- }
- switch (decoder.CurrentState)
- {
- case ClientFramingDecoderState.Fault:
- channel.Session.CloseOutputSession(channel.InternalCloseTimeout);
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(FaultStringDecoder.GetFaultException(decoder.Fault, channel.RemoteAddress.Uri.ToString(), messageEncoder.ContentType));
- case ClientFramingDecoderState.End:
- isAtEOF = true;
- return null; // we're done
- case ClientFramingDecoderState.EnvelopeStart:
- int envelopeSize = decoder.EnvelopeSize;
- if (envelopeSize > maxBufferSize)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- MaxMessageSizeStream.CreateMaxReceivedMessageSizeExceededException(maxBufferSize));
- }
- EnvelopeBuffer = bufferManager.TakeBuffer(envelopeSize);
- EnvelopeOffset = 0;
- EnvelopeSize = envelopeSize;
- break;
- case ClientFramingDecoderState.EnvelopeEnd:
- if (EnvelopeBuffer != null)
- {
- Message message = null;
- try
- {
- IDisposable activity = ClientDuplexConnectionReader.CreateProcessActionActivity();
- using (activity)
- {
- message = messageEncoder.ReadMessage(new ArraySegment<byte>(EnvelopeBuffer, 0, EnvelopeSize), bufferManager);
- if (DiagnosticUtility.ShouldUseActivity)
- {
- TraceUtility.TransferFromTransport(message);
- }
- }
- }
- catch (XmlException xmlException)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ProtocolException(SR.GetString(SR.MessageXmlProtocolError), xmlException));
- }
- EnvelopeBuffer = null;
- return message;
- }
- break;
- }
- }
- return null;
- }
- }
- }
|