Files
acceptance-tests
data
debian
docs
external
ikvm-native
llvm
m4
man
mcs
build
class
Accessibility
Commons.Xml.Relaxng
Cscompmgd
CustomMarshalers
Facades
I18N
IBM.Data.DB2
ICSharpCode.SharpZipLib
Microsoft.Build
Microsoft.Build.Engine
Microsoft.Build.Framework
Microsoft.Build.Tasks
Microsoft.Build.Utilities
Microsoft.CSharp
Microsoft.NuGet.Build.Tasks
Microsoft.VisualC
Microsoft.Web.Infrastructure
MicrosoftAjaxLibrary
Mono.Btls.Interface
Mono.C5
Mono.CSharp
Mono.Cairo
Mono.Cecil
Mono.Cecil.Mdb
Mono.CodeContracts
Mono.CompilerServices.SymbolWriter
Mono.Data.Sqlite
Mono.Data.Tds
Mono.Debugger.Soft
Mono.Http
Mono.Management
Mono.Messaging
Mono.Messaging.RabbitMQ
Mono.Options
Mono.Parallel
Mono.Posix
Mono.Profiler.Log
Mono.Runtime.Tests
Mono.Security
Mono.Security.Win32
Mono.Simd
Mono.Tasklets
Mono.WebBrowser
Mono.XBuild.Tasks
Novell.Directory.Ldap
PEAPI
RabbitMQ.Client
SMDiagnostics
System
System.ComponentModel.Composition.4.5
System.ComponentModel.DataAnnotations
System.Configuration
System.Configuration.Install
System.Core
System.Data
System.Data.DataSetExtensions
System.Data.Entity
System.Data.Linq
System.Data.OracleClient
System.Data.Services
System.Data.Services.Client
System.Deployment
System.Design
System.DirectoryServices
System.DirectoryServices.Protocols
System.Drawing
System.Drawing.Design
System.Dynamic
System.EnterpriseServices
System.IO.Compression
System.IO.Compression.FileSystem
System.IdentityModel
System.IdentityModel.Selectors
System.Json
System.Json.Microsoft
System.Management
System.Messaging
System.Net
System.Net.Http
System.Net.Http.Formatting
System.Net.Http.WebRequest
System.Net.Http.WinHttpHandler
System.Numerics
System.Numerics.Vectors
System.Reactive.Core
System.Reactive.Debugger
System.Reactive.Experimental
System.Reactive.Interfaces
System.Reactive.Linq
System.Reactive.Observable.Aliases
System.Reactive.PlatformServices
System.Reactive.Providers
System.Reactive.Runtime.Remoting
System.Reactive.Windows.Forms
System.Reactive.Windows.Threading
System.Reflection.Context
System.Runtime.Caching
System.Runtime.CompilerServices.Unsafe
System.Runtime.DurableInstancing
System.Runtime.Remoting
System.Runtime.Serialization
System.Runtime.Serialization.Formatters.Soap
System.Security
System.ServiceModel
System.ServiceModel.Activation
System.ServiceModel.Discovery
System.ServiceModel.Internals
System.ServiceModel.Routing
System.ServiceModel.Web
System.ServiceProcess
System.Threading.Tasks.Dataflow
System.Transactions
System.Web
System.Web.Abstractions
System.Web.ApplicationServices
System.Web.DynamicData
System.Web.Extensions
System.Web.Extensions.Design
System.Web.Http
System.Web.Http.SelfHost
System.Web.Http.WebHost
System.Web.Mobile
System.Web.Mvc3
System.Web.Razor
System.Web.RegularExpressions
System.Web.Routing
System.Web.Services
System.Web.WebPages
System.Web.WebPages.Deployment
System.Web.WebPages.Razor
System.Windows
System.Windows.Forms
System.Windows.Forms.DataVisualization
System.Workflow.Activities
System.Workflow.ComponentModel
System.Workflow.Runtime
System.XML
System.Xaml
System.Xml.Linq
System.Xml.Serialization
SystemWebTestShim
WebMatrix.Data
WindowsBase
aot-compiler
corlib
dlr
doc
legacy
lib
monodoc
notes
reference-assemblies
referencesource
SMDiagnostics
System
System.Activities
System.Activities.Core.Presentation
System.Activities.DurableInstancing
System.Activities.Presentation
System.ComponentModel.DataAnnotations
System.Configuration
System.Core
System.Data
System.Data.DataSetExtensions
System.Data.Entity
System.Data.Entity.Design
System.Data.Linq
System.Data.SqlXml
System.IdentityModel
System.IdentityModel.Selectors
System.Net
System.Numerics
System.Runtime.Caching
System.Runtime.DurableInstancing
System.Runtime.Serialization
System.ServiceModel
InternalApis
Serialization
System
Collections
ServiceModel
Activation
Administration
Channels
AddressHeader.cs
AddressHeaderCollection.cs
Addressing.cs
AddressingVersion.cs
AppContainerInfo.cs
ApplicationContainerSettings.cs
AsymmetricSecurityBindingElement.cs
AuthenticationSchemesBindingParameter.cs
AuthenticationSchemesHelper.cs
BaseUriWithWildcard.cs
BinaryMessageEncoder.cs
BinaryMessageEncodingBindingElement.cs
BinaryVersion.cs
Binding.cs
BindingContext.cs
BindingElement.cs
BindingElementCollection.cs
BindingParameterCollection.cs
BodyWriter.cs
BufferManager.cs
BufferManagerOutputStream.cs
BufferedConnection.cs
BufferedMessageData.cs
BufferedMessageWriter.cs
BufferedOutputAsyncStream.cs
BufferedReceiveMessageProperty.cs
BufferedRequestContext.cs
CallbackContextMessageHeader.cs
CallbackContextMessageProperty.cs
ChainedAsyncResult.cs
ChannelAcceptor.cs
ChannelBase.cs
ChannelBindingMessageProperty.cs
ChannelBindingProviderHelper.cs
ChannelBindingUtility.cs
ChannelBuilder.cs
ChannelDemuxer.cs.REMOVED.git-id
ChannelFactoryBase.cs
ChannelListenerBase.cs
ChannelManagerBase.cs
ChannelParameterCollection.cs
ChannelPool.cs
ChannelPoolSettings.cs
ChannelReliableSession.cs
ChannelRequirements.cs
ChannelTracker.cs
ClientContextProtocol.cs
ClientReliableChannelBinder.cs
ClientWebSocketFactory.cs
ClientWebSocketTransportDuplexSessionChannel.cs
CloseCollectionAsyncResult.cs
CloseSequence.cs
CloseSequenceResponse.cs
CommunicationObject.cs
CommunicationObjectManager.cs
CompositeDuplexBindingElement.cs
CompositeDuplexBindingElementImporter.cs
CompressionFormat.cs
CompressionFormatHelper.cs
ConnectAlgorithms.cs
Connection.cs
ConnectionAcceptor.cs
ConnectionBufferPool.cs
ConnectionDemuxer.cs
ConnectionDumpInitiator.cs
ConnectionModeReader.cs
ConnectionOrientedTransportBindingElement.cs
ConnectionOrientedTransportChannelFactory.cs
ConnectionOrientedTransportChannelListener.cs
ConnectionOrientedTransportManager.cs
ConnectionPool.cs
ConnectionPoolRegistry.cs
ContentOnlyMessage.cs
ContextAddressHeader.cs
ContextBindingElement.cs
ContextBindingElementImporter.cs
ContextBindingElementPolicy.cs
ContextChannelFactory.cs
ContextChannelListener.cs
ContextChannelRequestContext.cs
ContextDictionary.cs
ContextDuplexSessionChannel.cs
ContextExchangeCorrelationHelper.cs
ContextExchangeMechanism.cs
ContextExchangeMechanismHelper.cs
ContextInputChannel.cs
ContextInputChannelBase.cs
ContextInputSessionChannel.cs
ContextMessageHeader.cs
ContextMessageProperty.cs
ContextOutputChannel.cs
ContextOutputChannelBase.cs
ContextOutputSessionChannel.cs
ContextProtocol.cs
ContextReplyChannel.cs
ContextReplySessionChannel.cs
ContextRequestChannel.cs
ContextRequestChannelBase.cs
ContextRequestSessionChannel.cs
CorrelationCallbackMessageProperty.cs
CorrelationDataDescription.cs
CorrelationDataMessageProperty.cs
CorrelationDataSourceHelper.cs
CorrelationKey.cs
CorrelationMessageProperty.cs
CreateSequence.cs
CreateSequenceResponse.cs
CustomBinding.cs
DatagramAdapter.cs
DefaultWebSocketConnectionHandler.cs
DelegatingChannelListener.cs
DelegatingMessage.cs
DelegatingStream.cs
DeliveryFailure.cs
DeliveryStatus.cs
DeliveryStrategy.cs
DetectEofStream.cs
DirectionalAction.cs
DnsCache.cs
DoneReceivingAsyncResult.cs
DuplexChannel.cs
EncoderHelpers.cs
EndpointSettings.cs
ExclusiveNamedPipeTransportManager.cs
ExclusiveTcpTransportManager.cs
FaultConverter.cs
FramingChannels.cs
FramingDecoders.cs
FramingEncoders.cs
FramingFormat.cs
HttpAnonymousUriPrefixMatcher.cs
HttpChannelFactory.cs
HttpChannelHelpers.cs.REMOVED.git-id
HttpChannelListener.cs
HttpCookieContainerBindingElement.cs
HttpCookieContainerManager.cs
HttpHeaderInfo.cs
HttpHeadersWebHeaderCollection.cs
HttpMessageHandlerFactory.cs
HttpMessageSettings.cs
HttpPipeline.cs
HttpPipelineCancellationTokenSource.cs
HttpRequestContext.cs
HttpRequestMessageExtensionMethods.cs
HttpRequestMessageProperty.cs
HttpResponseMessageExtensionMethods.cs
HttpResponseMessageProperty.cs
HttpTransportBindingElement.cs
HttpTransportManager.cs
HttpsChannelFactory.cs
HttpsChannelListener.cs
HttpsTransportBindingElement.cs
IAnonymousUriPrefixMatcher.cs
IBindingDeliveryCapabilities.cs
IBindingMulticastCapabilities.cs
IBindingRuntimePreferences.cs
IChannel.cs
IChannelAcceptor.cs
IChannelBindingProvider.cs
IChannelFactory.cs
IChannelListener.cs
ICompressedMessageEncoder.cs
IContextBindingElement.cs
IContextManager.cs
ICorrelationDataSource.cs
ICorrelatorKey.cs
IDuplexChannel.cs
IDuplexSession.cs
IDuplexSessionChannel.cs
IHttpCookieContainerManager.cs
IInputChannel.cs
IInputSession.cs
IInputSessionChannel.cs
ILockingQueue.cs
IMergeEnabledMessageProperty.cs
IMessageProperty.cs
IMessageSource.cs
IOutputChannel.cs
IOutputSession.cs
IOutputSessionChannel.cs
IPeerNeighbor.cs
IPoisonHandlingStrategy.cs
IReceiveContextSettings.cs
IReliableChannelBinder.cs
IReliableFactorySettings.cs
IReplyChannel.cs
IReplySessionChannel.cs
IRequestChannel.cs
IRequestReplyCorrelator.cs
IRequestSessionChannel.cs
ISecurityCapabilities.cs
ISession.cs
ISessionChannel.cs
IStreamUpgradeChannelBindingProvider.cs
IStreamedMessageEncoder.cs
ITransactedBindingElement.cs
ITransactionChannelManager.cs
ITransportCompressionSupport.cs
ITransportFactorySettings.cs
ITransportTokenAssertionProvider.cs
IWebMessageEncoderHelper.cs
IWebsocketCloseDetails.cs
IdlingCommunicationPool.cs
InitialServerConnectionReader.cs
InputChannel.cs
InputChannelAcceptor.cs
InputQueueChannel.cs
InputQueueChannelAcceptor.cs
InternalDuplexBindingElement.cs
InternalDuplexChannelFactory.cs
InternalDuplexChannelListener.cs
InvalidChannelBindingException.cs
LateBoundChannelParameterCollection.cs
LayeredChannel.cs
LayeredChannelFactory.cs
LayeredChannelListener.cs
LifetimeManager.cs
LocalClientSecuritySettings.cs
LocalServiceSecuritySettings.cs
LockHelper.cs
MaxMessageSizeStream.cs
Message.cs
MessageBuffer.cs
MessageEncoder.cs
MessageEncoderCompressionHandler.cs
MessageEncoderFactory.cs
MessageEncodingBindingElement.cs
MessageEncodingBindingElementImporter.cs
MessageFault.cs
MessageHeader.cs
MessageHeaderInfo.cs
MessageHeaders.cs
MessageProperties.cs
MessageState.cs
MessageVersion.cs
Msmq.cs
Msmq3PoisonHandler.cs
Msmq4PoisonHandler.cs
Msmq4SubqueuePoisonHandler.cs
MsmqBindingElementBase.cs
MsmqBindingFilter.cs
MsmqBindingMonitor.cs
MsmqChannelFactory.cs
MsmqChannelFactoryBase.cs
MsmqChannelListenerBase.cs
MsmqDecodeHelper.cs
MsmqDefaultLockingQueue.cs
MsmqDiagnostics.cs
MsmqInputChannel.cs
MsmqInputChannelBase.cs
MsmqInputChannelListener.cs
MsmqInputChannelListenerBase.cs
MsmqInputMessage.cs
MsmqInputMessagePool.cs
MsmqInputSessionChannel.cs
MsmqInputSessionChannelListener.cs
MsmqMessageProperty.cs
MsmqNonTransactedPoisonHandler.cs
MsmqOutputChannel.cs
MsmqOutputMessage.cs
MsmqOutputSessionChannel.cs
MsmqQueue.cs
MsmqReceiveContext.cs
MsmqReceiveContextLockManager.cs
MsmqReceiveHelper.cs
MsmqReceiveParameters.cs
MsmqSubqueueLockingQueue.cs
MsmqTransportBindingElement.cs
MsmqTransportReceiveParameters.cs
MsmqUri.cs
MsmqVerifier.cs
MtomMessageEncoder.cs
MtomMessageEncodingBindingElement.cs
NamedPipeChannelFactory.cs
NamedPipeChannelListener.cs
NamedPipeConnectionPool.cs
NamedPipeConnectionPoolSettings.cs
NamedPipeSettings.cs
NamedPipeTransportBindingElement.cs
NamedPipeTransportManager.cs
NativeMsmqMessage.cs
OneWayBindingElement.cs
OneWayBindingElementImporter.cs
OneWayChannelFactory.cs
OneWayChannelListener.cs
OpaqueContent.cs
OpenCollectionAsyncResult.cs
OutputChannel.cs
OverlappedContext.cs
PeerChannelFactory.cs
PeerChannelListener.cs
PeerConnector.cs
PeerCustomResolverBindingElement.cs
PeerDuplexChannel.cs
PeerDuplexChannelListener.cs
PeerFlooder.cs
PeerHelpers.cs
PeerIPHelper.cs
PeerInputChannel.cs
PeerInputChannelListener.cs
PeerMaintainer.cs
PeerMessageDispatcher.cs
PeerNeighborManager.cs
PeerNodeImplementation.cs
PeerNodeStateManager.cs
PeerOutputChannel.cs
PeerResolverBindingElement.cs
PeerSecurityHelpers.cs
PeerSecurityManager.cs
PeerService.cs
PeerServiceMessageContracts.cs
PeerTransportBindingElement.cs
PeerUnsafeNativeCryptMethods.cs
PeerUnsafeNativeMethods.cs
PipeConnection.cs.REMOVED.git-id
PipeException.cs
PnrpPeerResolver.cs.REMOVED.git-id
PnrpPeerResolverBindingElement.cs
PrivacyNoticeBindingElement.cs
PrivacyNoticeBindingElementImporter.cs
QueuedObjectPool.cs
ReceiveContext.cs
ReceiveContextState.cs
RedirectionConstants.cs
RedirectionDuration.cs
RedirectionException.cs
RedirectionLocation.cs
RedirectionScope.cs
RedirectionType.cs
RedirectionUtility.cs
ReliableChannelBinder.cs.REMOVED.git-id
ReliableChannelFactory.cs
ReliableChannelListener.cs
ReliableDuplexSessionChannel.cs
ReliableInputConnection.cs
ReliableInputSessionChannel.cs
ReliableMessagingHelpers.cs.REMOVED.git-id
ReliableOutputConnection.cs
ReliableOutputSessionChannel.cs
ReliableReplySessionChannel.cs
ReliableRequestSessionChannel.cs
ReliableSessionBindingElement.cs
ReliableSessionBindingElementImporter.cs
RemoteEndpointMessageProperty.cs
ReplyAdapterChannelListener.cs
ReplyChannel.cs
ReplyChannelAcceptor.cs
RequestChannel.cs
RequestContext.cs
RequestContextBase.cs
RequestReplyCorrelator.cs
RetryException.cs
SafeNativeMethods.cs
SecurityAttributeGenerationHelper.cs
SecurityBindingElement.cs.REMOVED.git-id
SecurityBindingElementImporter.cs
SecurityCapabilities.cs
SecurityChannelFactory.cs
SecurityChannelFaultConverter.cs
SecurityChannelListener.cs
SecurityHeaderLayout.cs
SelfSignedCertificate.cs
SequenceRange.cs
SequenceRangeCollection.cs
ServerReliableChannelBinder.cs
ServerWebSocketTransportDuplexSessionChannel.cs
ServiceChannel.cs
ServiceChannelFactory.cs
ServiceChannelProxy.cs
ServiceContextProtocol.cs
ServiceWebSocketContext.cs
SessionConnectionReader.cs
SessionOpenNotification.cs
SharedConnectionListener.cs
SharedHttpTransportManager.cs
SharedHttpsTransportManager.cs
SharedTcpTransportManager.cs
SingletonChannelAcceptor.cs
SingletonConnectionReader.cs
SocketAsyncEventArgsPool.cs
SocketConnection.cs
SslStreamSecurityBindingElement.cs
SslStreamSecurityUpgradeProvider.cs
StandardBindingImporter.cs
StreamSecurityUpgradeAcceptor.cs
StreamSecurityUpgradeAcceptorAsyncResult.cs
StreamSecurityUpgradeAcceptorBase.cs
StreamSecurityUpgradeInitiator.cs
StreamSecurityUpgradeInitiatorAsyncResult.cs
StreamSecurityUpgradeInitiatorBase.cs
StreamSecurityUpgradeProvider.cs
StreamUpgradeAcceptor.cs
StreamUpgradeBindingElement.cs
StreamUpgradeInitiator.cs
StreamUpgradeProvider.cs
StreamedFramingRequestChannel.cs
SupportedAddressingMode.cs
SymmetricSecurityBindingElement.cs
SynchronizedMessageSource.cs
TcpChannelFactory.cs
TcpChannelListener.cs
TcpConnectionPool.cs
TcpConnectionPoolSettings.cs
TcpTransportBindingElement.cs
TcpTransportManager.cs
TerminateSequence.cs
TerminateSequenceResponse.cs
TextMessageEncoder.cs
TextMessageEncodingBindingElement.cs
TimeoutStream.cs
TracingConnection.cs
TracingConnectionInitiator.cs
TracingConnectionListener.cs
TransactionChannel.cs
TransactionChannelFactory.cs
TransactionChannelFaultConverter.cs
TransactionChannelListener.cs
TransactionFlowBindingElement.cs
TransactionFlowBindingElementImporter.cs
TransactionFlowProperty.cs
TransferSession.cs
TransmissionStrategy.cs
TransportBindingElement.cs
TransportBindingElementImporter.cs
TransportChannelFactory.cs
TransportChannelListener.cs
TransportDefaults.cs
TransportDuplexSessionChannel.cs
TransportManager.cs
TransportOutputChannel.cs
TransportReplyChannelAcceptor.cs
TransportSecurityBindingElement.cs
TransportSecurityHelpers.cs
UnderstoodHeaders.cs
UniqueTransportManagerRegistration.cs
UnrecognizedAssertionsBindingElement.cs
UnsafeNativeMethods.cs
UriGenerator.cs
UriHelper.cs
UriPrefixTable.cs
UseManagedPresentationBindingElement.cs
UseManagedPresentationBindingElementImporter.cs
UtilityExtension.cs
WebSocketConnectionHandler.cs
WebSocketHelper.cs
WebSocketMessageProperty.cs
WebSocketTransportDuplexSessionChannel.cs
WebSocketTransportSettings.cs
WebSocketTransportUsage.cs
WebSocketTransportUsageHelper.cs
WindowsStreamSecurityBindingElement.cs
WindowsStreamSecurityUpgradeProvider.cs
WrappedOptions.cs
WsrmFault.cs
WsrmMessageInfo.cs
XmlSerializerImportOptions.cs
ComIntegration
Configuration
Description
Diagnostics
Dispatcher
MsmqIntegration
PeerResolvers
Security
Syndication
Transactions
XamlIntegration
ActionMismatchAddressingException.cs
ActionNotSupportedException.cs
AddressAccessDeniedException.cs
AddressAlreadyInUseException.cs
AddressFilterMode.cs
AppContextDefaultValues.Default.cs
AuditLevel.cs
AuditLogLocation.cs
BasicHttpBinding.cs
BasicHttpContextBinding.cs
BasicHttpMessageCredentialType.cs
BasicHttpMessageSecurity.cs
BasicHttpSecurity.cs
BasicHttpSecurityMode.cs
BasicHttpsBinding.cs
BasicHttpsSecurity.cs
BasicHttpsSecurityMode.cs
CacheSetting.cs
CallbackBehaviorAttribute.cs
ChannelFactory.cs
ChannelFactoryRefCache.cs
ChannelTerminatedException.cs
ClientBase.cs
CommunicationException.cs
CommunicationObjectAbortedException.cs
CommunicationObjectFaultedException.cs
CommunicationState.cs
ConcurrencyMode.cs
ConfigurationEndpointTrait.cs
DXD.cs
DataContractFormatAttribute.cs
DeadLetterQueue.cs
DeliveryRequirementsAttribute.cs
DnsEndpointIdentity.cs
DuplexChannelFactory.cs
DuplexClientBase.cs
EmptyArray.cs
EndpointAddress.cs
EndpointAddress10.cs
EndpointAddressAugust2004.cs
EndpointIdentity.cs
EndpointNotFoundException.cs
EndpointTrait.cs
EnvelopeVersion.cs
ExceptionDetail.cs
ExceptionMapper.cs
ExtensionCollection.cs
FaultCode.cs
FaultCodeConstants.cs
FaultContractAttribute.cs
FaultException.cs
FaultImportOptions.cs
FaultReason.cs
FaultReasonText.cs
FederatedMessageSecurityOverHttp.cs
GeneralEndpointIdentity.cs
HostnameComparisonMode.cs
HttpBindingBase.cs
HttpClientCredentialType.cs
HttpProxyCredentialType.cs
HttpTransportSecurity.cs
IChannelBaseProxy.cs
IClientChannel.cs
ICommunicationObject.cs
IContextChannel.cs
IContextSessionProvider.cs
IDefaultCommunicationTimeouts.cs
IDuplexContextChannel.cs
IExtensibleObject.cs
IExtension.cs
IExtensionCollection.cs
IOnlineStatus.cs
IOperationContractAttributeProvider.cs
IServiceChannel.cs
ImpersonationOption.cs
InstanceContext.cs
InstanceContextMode.cs
InvalidMessageContractException.cs
KeyedByTypeCollection.cs
LocalAppContextSwitches.cs
MessageBodyMemberAttribute.cs
MessageContractAttribute.cs
MessageContractMemberAttribute.cs
MessageCredentialType.cs
MessageHeaderArrayAttribute.cs
MessageHeaderAttribute.cs
MessageHeaderException.cs
MessageHeaderT.cs
MessageParameterAttribute.cs
MessagePropertyAttribute.cs
MessageSecurityOverHttp.cs
MessageSecurityOverMsmq.cs
MessageSecurityOverTcp.cs
MessageSecurityVersion.cs
MostlySingletonList.cs
MsmqAuthenticationMode.cs
MsmqBindingBase.cs
MsmqEncryptionAlgorithm.cs
MsmqException.cs
MsmqPoisonMessageException.cs
MsmqSecureHashAlgorithm.cs
MsmqTransportSecurity.cs
MustUnderstandSoapException.cs
NamedPipeTransportSecurity.cs
NetHttpBinding.cs
NetHttpMessageEncoding.cs
NetHttpMessageEncodingHelper.cs
NetHttpsBinding.cs
NetMsmqBinding.cs
NetMsmqSecurity.cs
NetMsmqSecurityMode.cs
NetNamedPipeBinding.cs
NetNamedPipeSecurity.cs
NetNamedPipeSecurityMode.cs
NetPeerTcpBinding.cs
NetTcpBinding.cs
NetTcpContextBinding.cs
NetTcpSecurity.cs
NonDualMessageSecurityOverHttp.cs
OSEnvironmentHelper.cs
OSVersion.cs
OperationBehaviorAttribute.cs
OperationContext.cs
OperationContextScope.cs
OperationContractAttribute.cs
OperationFormatStyle.cs
OperationFormatUse.cs
PeerHopCountAttribute.cs
PeerMessageOrigination.cs
PeerMessagePropagation.cs
PeerMessagePropagationFilter.cs
PeerNode.cs
PeerNodeAddress.cs
PeerResolver.cs
PeerSecuritySettings.cs
PeerTransportCredentialType.cs
PeerTransportSecuritySettings.cs
PoisonMessageException.cs
Pool.cs
ProgrammaticEndpointTrait.cs
ProtocolException.cs
QueueTransferProtocol.cs
QueuedDeliveryRequirementsMode.cs
QuotaExceededException.cs
ReceiveContextEnabledAttribute.cs
ReceiveErrorHandling.cs
ReleaseInstanceMode.cs
ReliableMessagingVersion.cs
ReliableSession.cs
RsaEndpointIdentity.cs
SecurityMode.cs
ServerTooBusyException.cs
ServiceActivationException.cs
ServiceAuthenticationManager.cs
ServiceAuthorizationManager.cs
ServiceBehaviorAttribute.cs
ServiceChannelManager.cs
ServiceConfiguration.cs
ServiceContractAttribute.cs
ServiceDefaults.cs
ServiceEndpointTrait.cs
ServiceHost.cs
ServiceKnownTypeAttribute.cs
ServiceModelAppSettings.cs
ServiceModelAttributeTargets.cs
ServiceModelDictionary.cs
ServiceModelStrings.cs
ServiceModelStringsVersion1.cs
ServiceSecurityContext.cs
SessionMode.cs
SpnEndpointIdentity.cs
StringUtil.cs
SynchronizedCollection.cs
SynchronizedDisposablePool.cs
SynchronizedKeyedCollection.cs
SynchronizedReadOnlyCollection.cs
TcpClientCredentialType.cs
TcpTransportSecurity.cs
ThreadTrace.cs
TimeSpanHelper.cs
TransactionFlowAttribute.cs
TransactionFlowOption.cs
TransactionProtocol.cs
TransferMode.cs
UnifiedSecurityMode.cs
UnknownMessageReceivedEventArgs.cs
UpnEndpointIdentity.cs
UriSchemeKeyedCollection.cs
WS2007FederationHttpBinding.cs
WS2007HttpBinding.cs
WSAddressing10ProblemHeaderQNameFault.cs
WSDualHttpBinding.cs
WSDualHttpSecurity.cs
WSDualHttpSecurityMode.cs
WSFederationHttpBinding.cs
WSFederationHttpSecurity.cs
WSFederationHttpSecurityMode.cs
WSHttpBinding.cs
WSHttpBindingBase.cs
WSHttpContextBinding.cs
WSHttpSecurity.cs
WSMessageEncoding.cs
WrappedDispatcherException.cs
X509CertificateEndpointIdentity.cs
XD.cs.REMOVED.git-id
XPathMessageQuery.cs
XmlBuffer.cs
XmlSerializerFormatAttribute.cs
XmlUtil.cs
UriTemplate.cs
UriTemplateCompoundPathSegment.cs
UriTemplateEquivalenceComparer.cs
UriTemplateHelpers.cs
UriTemplateLiteralPathSegment.cs
UriTemplateLiteralQueryValue.cs
UriTemplateMatch.cs
UriTemplateMatchException.cs
UriTemplatePartType.cs
UriTemplatePathPartiallyEquivalentSet.cs
UriTemplatePathSegment.cs
UriTemplateQueryValue.cs
UriTemplateTable.cs
UriTemplateTableMatchCandidate.cs
UriTemplateTrieIntraNodeLocation.cs
UriTemplateTrieLocation.cs
UriTemplateTrieNode.cs
UriTemplateVariablePathSegment.cs
UriTemplateVariableQueryValue.cs
AssemblyInfo.cs
System.ServiceModel.txt.REMOVED.git-id
TD.Designer.cs.REMOVED.git-id
System.ServiceModel.Activation
System.ServiceModel.Activities
System.ServiceModel.Channels
System.ServiceModel.Discovery
System.ServiceModel.Internals
System.ServiceModel.Routing
System.ServiceModel.WasHosting
System.ServiceModel.Web
System.Web
System.Web.ApplicationServices
System.Web.DataVisualization
System.Web.DynamicData
System.Web.Entity
System.Web.Entity.Design
System.Web.Extensions
System.Web.Mobile
System.Web.Routing
System.Web.Services
System.Workflow.Activities
System.Workflow.ComponentModel
System.Workflow.Runtime
System.WorkflowServices
System.Xaml.Hosting
System.Xml
System.Xml.Linq
XamlBuildTask
mscorlib
LICENSE.txt
PATENTS.TXT
README.Mono.md
README.md
test-helpers
LICENSE
Makefile
Open.snk
README
ecma.pub
mono.pub
mono.snk
msfinal.pub
reactive.pub
silverlight.pub
winfx.pub
winfx3.pub
docs
errors
ilasm
jay
mcs
packages
tests
tools
AUTHORS
COPYING
INSTALL.txt
Makefile
MonoIcon.png
README
ScalableMonoIcon.svg
mkinstalldirs
mk
mono
msvc
netcore
po
runtime
samples
scripts
support
tools
COPYING.LIB
LICENSE
Makefile.am
Makefile.in
NEWS
README.md
acinclude.m4
aclocal.m4
autogen.sh
code_of_conduct.md
compile
config.guess
config.h.in
config.rpath
config.sub
configure.REMOVED.git-id
configure.ac.REMOVED.git-id
depcomp
install-sh
ltmain.sh.REMOVED.git-id
missing
mkinstalldirs
mono-uninstalled.pc.in
test-driver
winconfig.h
linux-packaging-mono/mcs/class/referencesource/System.ServiceModel/System/ServiceModel/Channels/SingletonConnectionReader.cs

1992 lines
77 KiB
C#
Raw Normal View History

//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Channels
{
using System;
using System.Diagnostics;
using System.IO;
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 ServerSingletonPreambleCallback(ServerSingletonPreambleConnectionReader serverSingletonPreambleReader);
delegate ISingletonChannelListener SingletonPreambleDemuxCallback(ServerSingletonPreambleConnectionReader serverSingletonPreambleReader);
interface ISingletonChannelListener
{
TimeSpan ReceiveTimeout { get; }
void ReceiveRequest(RequestContext requestContext, Action callback, bool canDispatchOnThisThread);
}
class ServerSingletonPreambleConnectionReader : InitialServerConnectionReader
{
ServerSingletonDecoder decoder;
ServerSingletonPreambleCallback callback;
WaitCallback onAsyncReadComplete;
IConnectionOrientedTransportFactorySettings transportSettings;
TransportSettingsCallback transportSettingsCallback;
SecurityMessageProperty security;
Uri via;
IConnection rawConnection;
byte[] connectionBuffer;
bool isReadPending;
int offset;
int size;
TimeoutHelper receiveTimeoutHelper;
Action<Uri> viaDelegate;
ChannelBinding channelBindingToken;
static AsyncCallback onValidate;
public ServerSingletonPreambleConnectionReader(IConnection connection, Action connectionDequeuedCallback,
long streamPosition, int offset, int size, TransportSettingsCallback transportSettingsCallback,
ConnectionClosedCallback closedCallback, ServerSingletonPreambleCallback callback)
: base(connection, closedCallback)
{
this.decoder = new ServerSingletonDecoder(streamPosition, MaxViaSize, MaxContentTypeSize);
this.offset = offset;
this.size = size;
this.callback = callback;
this.transportSettingsCallback = transportSettingsCallback;
this.rawConnection = connection;
this.ConnectionDequeuedCallback = connectionDequeuedCallback;
}
public ChannelBinding ChannelBinding
{
get
{
return this.channelBindingToken;
}
}
public int BufferOffset
{
get { return this.offset; }
}
public int BufferSize
{
get { return this.size; }
}
public ServerSingletonDecoder Decoder
{
get { return this.decoder; }
}
public IConnection RawConnection
{
get { return this.rawConnection; }
}
public Uri Via
{
get { return this.via; }
}
public IConnectionOrientedTransportFactorySettings TransportSettings
{
get { return this.transportSettings; }
}
public SecurityMessageProperty Security
{
get { return this.security; }
}
TimeSpan GetRemainingTimeout()
{
return this.receiveTimeoutHelper.RemainingTime();
}
void ReadAndDispatch()
{
bool success = false;
try
{
while ((size > 0 || !isReadPending) && !IsClosed)
{
if (size == 0)
{
isReadPending = true;
if (onAsyncReadComplete == null)
{
onAsyncReadComplete = new WaitCallback(OnAsyncReadComplete);
}
if (Connection.BeginRead(0, connectionBuffer.Length, GetRemainingTimeout(),
onAsyncReadComplete, null) == AsyncCompletionResult.Queued)
{
break;
}
HandleReadComplete();
}
int bytesRead = decoder.Decode(connectionBuffer, offset, size);
if (bytesRead > 0)
{
offset += bytesRead;
size -= bytesRead;
}
if (decoder.CurrentState == ServerSingletonDecoder.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 -- we abort ourselves for any error, no extra containment needed
}
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;
ServerSingletonPreambleConnectionReader thisPtr = (ServerSingletonPreambleConnectionReader)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.transportSettings = transportSettingsCallback(via);
if (transportSettings == null)
{
EndpointNotFoundException e = new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, decoder.Via));
DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
// return fault and close connection
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)
{
SendFault(faultString, ref this.receiveTimeoutHelper);
}
void SendFault(string faultString, ref TimeoutHelper timeoutHelper)
{
InitialServerConnectionReader.SendFault(Connection, faultString,
connectionBuffer, timeoutHelper.RemainingTime(), TransportDefaults.MaxDrainSize);
}
public IAsyncResult BeginCompletePreamble(TimeSpan timeout, AsyncCallback callback, object state)
{
return new CompletePreambleAsyncResult(timeout, this, callback, state);
}
public IConnection EndCompletePreamble(IAsyncResult result)
{
return CompletePreambleAsyncResult.End(result);
}
class CompletePreambleAsyncResult : TypedAsyncResult<IConnection>
{
static WaitCallback onReadCompleted = new WaitCallback(OnReadCompleted);
static WaitCallback onWriteCompleted = new WaitCallback(OnWriteCompleted);
static AsyncCallback onUpgradeComplete = Fx.ThunkCallback(OnUpgradeComplete);
TimeoutHelper timeoutHelper;
ServerSingletonPreambleConnectionReader parent;
StreamUpgradeAcceptor upgradeAcceptor;
StreamUpgradeProvider upgrade;
IStreamUpgradeChannelBindingProvider channelBindingProvider;
IConnection currentConnection;
UpgradeState upgradeState = UpgradeState.None;
public CompletePreambleAsyncResult(TimeSpan timeout, ServerSingletonPreambleConnectionReader parent, AsyncCallback callback, object state)
: base(callback, state)
{
this.timeoutHelper = new TimeoutHelper(timeout);
this.parent = parent;
Initialize();
if (ContinueWork(null))
{
Complete(this.currentConnection, true);
}
}
byte[] ConnectionBuffer
{
get
{
return this.parent.connectionBuffer;
}
set
{
this.parent.connectionBuffer = value;
}
}
int Offset
{
get
{
return this.parent.offset;
}
set
{
this.parent.offset = value;
}
}
int Size
{
get
{
return this.parent.size;
}
set
{
this.parent.size = value;
}
}
bool CanReadAndDecode
{
get
{
//ok to read/decode before we start the upgrade
//and between UpgradeComplete/WritingPreambleAck
return this.upgradeState == UpgradeState.None
|| this.upgradeState == UpgradeState.UpgradeComplete;
}
}
ServerSingletonDecoder Decoder
{
get
{
return this.parent.decoder;
}
}
void Initialize()
{
if (!this.parent.transportSettings.MessageEncoderFactory.Encoder.IsContentTypeSupported(Decoder.ContentType))
{
SendFault(FramingEncodingString.ContentTypeInvalidFault, ref timeoutHelper);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(
SR.ContentTypeMismatch, Decoder.ContentType, parent.transportSettings.MessageEncoderFactory.Encoder.ContentType)));
}
upgrade = this.parent.transportSettings.Upgrade;
if (upgrade != null)
{
channelBindingProvider = upgrade.GetProperty<IStreamUpgradeChannelBindingProvider>();
upgradeAcceptor = upgrade.CreateUpgradeAcceptor();
}
this.currentConnection = this.parent.Connection;
}
void SendFault(string faultString, ref TimeoutHelper timeoutHelper)
{
this.parent.SendFault(faultString, ref timeoutHelper);
}
bool BeginRead()
{
this.Offset = 0;
return this.currentConnection.BeginRead(0, this.ConnectionBuffer.Length, timeoutHelper.RemainingTime(), onReadCompleted, this) == AsyncCompletionResult.Completed;
}
void EndRead()
{
this.Size = currentConnection.EndRead();
if (this.Size == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.Decoder.CreatePrematureEOFException());
}
}
bool ContinueWork(IAsyncResult upgradeAsyncResult)
{
if (upgradeAsyncResult != null)
{
Fx.AssertAndThrow(this.upgradeState == UpgradeState.EndUpgrade, "upgradeAsyncResult should only be passed in from OnUpgradeComplete callback");
}
for (;;)
{
if (Size == 0 && this.CanReadAndDecode)
{
if (BeginRead())
{
EndRead();
}
else
{
//when read completes, we will re-enter this loop.
break;
}
}
for (;;)
{
if (this.CanReadAndDecode)
{
int bytesRead = Decoder.Decode(ConnectionBuffer, Offset, Size);
if (bytesRead > 0)
{
Offset += bytesRead;
Size -= bytesRead;
}
}
switch (Decoder.CurrentState)
{
case ServerSingletonDecoder.State.UpgradeRequest:
switch (this.upgradeState)
{
case UpgradeState.None:
//change the state so that we don't read/decode until it is safe
ChangeUpgradeState(UpgradeState.VerifyingUpgradeRequest);
break;
case UpgradeState.VerifyingUpgradeRequest:
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)));
}
ChangeUpgradeState(UpgradeState.WritingUpgradeAck);
// accept upgrade
if (this.currentConnection.BeginWrite(ServerSingletonEncoder.UpgradeResponseBytes, 0, ServerSingletonEncoder.UpgradeResponseBytes.Length,
true, timeoutHelper.RemainingTime(), onWriteCompleted, this) == AsyncCompletionResult.Queued)
{
//OnWriteCompleted will:
// 1) set upgradeState to UpgradeAckSent
// 2) call EndWrite
return false;
}
else
{
this.currentConnection.EndWrite();
}
ChangeUpgradeState(UpgradeState.UpgradeAckSent);
break;
case UpgradeState.UpgradeAckSent:
IConnection connectionToUpgrade = this.currentConnection;
if (Size > 0)
{
connectionToUpgrade = new PreReadConnection(connectionToUpgrade, ConnectionBuffer, Offset, Size);
}
ChangeUpgradeState(UpgradeState.BeginUpgrade);
break;
case UpgradeState.BeginUpgrade:
try
{
if (!BeginUpgrade(out upgradeAsyncResult))
{
//OnUpgradeComplete will set upgradeState to EndUpgrade
return false;
}
ChangeUpgradeState(UpgradeState.EndUpgrade);
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
throw;
this.parent.WriteAuditFailure(upgradeAcceptor as StreamSecurityUpgradeAcceptor, exception);
throw;
}
break;
case UpgradeState.EndUpgrade://Must be a different state here than UpgradeComplete so that we don't try to read from the connection
try
{
EndUpgrade(upgradeAsyncResult);
ChangeUpgradeState(UpgradeState.UpgradeComplete);
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
throw;
this.parent.WriteAuditFailure(upgradeAcceptor as StreamSecurityUpgradeAcceptor, exception);
throw;
}
break;
case UpgradeState.UpgradeComplete:
//Client is doing more than one upgrade, reset the state
ChangeUpgradeState(UpgradeState.VerifyingUpgradeRequest);
break;
}
break;
case ServerSingletonDecoder.State.Start:
this.parent.SetupSecurityIfNecessary(upgradeAcceptor);
if (this.upgradeState == UpgradeState.UpgradeComplete //We have done at least one upgrade, but we are now done.
|| this.upgradeState == UpgradeState.None)//no upgrade, just send the preample end bytes
{
ChangeUpgradeState(UpgradeState.WritingPreambleEnd);
// we've finished the preamble. Ack and return.
if (this.currentConnection.BeginWrite(ServerSessionEncoder.AckResponseBytes, 0, ServerSessionEncoder.AckResponseBytes.Length,
true, timeoutHelper.RemainingTime(), onWriteCompleted, this) == AsyncCompletionResult.Queued)
{
//OnWriteCompleted will:
// 1) set upgradeState to PreambleEndSent
// 2) call EndWrite
return false;
}
else
{
this.currentConnection.EndWrite();
}
//terminal state
ChangeUpgradeState(UpgradeState.PreambleEndSent);
}
//we are done, this.currentConnection is the upgraded connection
return true;
}
if (Size == 0)
{
break;
}
}
}
return false;
}
bool BeginUpgrade(out IAsyncResult upgradeAsyncResult)
{
upgradeAsyncResult = InitialServerConnectionReader.BeginUpgradeConnection(this.currentConnection, upgradeAcceptor, this.parent.transportSettings, onUpgradeComplete, this);
if (!upgradeAsyncResult.CompletedSynchronously)
{
upgradeAsyncResult = null; //caller shouldn't use this out param unless completed sync.
return false;
}
return true;
}
void EndUpgrade(IAsyncResult upgradeAsyncResult)
{
this.currentConnection = InitialServerConnectionReader.EndUpgradeConnection(upgradeAsyncResult);
this.ConnectionBuffer = this.currentConnection.AsyncReadBuffer;
if (this.channelBindingProvider != null
&& this.channelBindingProvider.IsChannelBindingSupportEnabled
&& this.parent.channelBindingToken == null)//first one wins in the case of multiple upgrades.
{
this.parent.channelBindingToken = channelBindingProvider.GetChannelBinding(this.upgradeAcceptor, ChannelBindingKind.Endpoint);
}
}
void ChangeUpgradeState(UpgradeState newState)
{
switch (newState)
{
case UpgradeState.None:
throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
case UpgradeState.VerifyingUpgradeRequest:
if (this.upgradeState != UpgradeState.None //starting first upgrade
&& this.upgradeState != UpgradeState.UpgradeComplete)//completing one upgrade and starting another
{
throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
}
break;
case UpgradeState.WritingUpgradeAck:
if (this.upgradeState != UpgradeState.VerifyingUpgradeRequest)
{
throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
}
break;
case UpgradeState.UpgradeAckSent:
if (this.upgradeState != UpgradeState.WritingUpgradeAck)
{
throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
}
break;
case UpgradeState.BeginUpgrade:
if (this.upgradeState != UpgradeState.UpgradeAckSent)
{
throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
}
break;
case UpgradeState.EndUpgrade:
if (this.upgradeState != UpgradeState.BeginUpgrade)
{
throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
}
break;
case UpgradeState.UpgradeComplete:
if (this.upgradeState != UpgradeState.EndUpgrade)
{
throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
}
break;
case UpgradeState.WritingPreambleEnd:
if (this.upgradeState != UpgradeState.None //no upgrade being used
&& this.upgradeState != UpgradeState.UpgradeComplete)//upgrades are now complete, end the preamble handshake.
{
throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
}
break;
case UpgradeState.PreambleEndSent:
if (this.upgradeState != UpgradeState.WritingPreambleEnd)
{
throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
}
break;
default:
throw Fx.AssertAndThrow("Unexpected Upgrade State: " + newState);
}
this.upgradeState = newState;
}
static void OnReadCompleted(object state)
{
CompletePreambleAsyncResult thisPtr = (CompletePreambleAsyncResult)state;
Exception completionException = null;
bool completeSelf = false;
try
{
thisPtr.EndRead();
completeSelf = thisPtr.ContinueWork(null);
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
completionException = ex;
completeSelf = true;
}
if (completeSelf)
{
if (completionException != null)
{
thisPtr.Complete(false, completionException);
}
else
{
thisPtr.Complete(thisPtr.currentConnection, false);
}
}
}
static void OnWriteCompleted(object state)
{
CompletePreambleAsyncResult thisPtr = (CompletePreambleAsyncResult)state;
Exception completionException = null;
bool completeSelf = false;
try
{
thisPtr.currentConnection.EndWrite();
switch (thisPtr.upgradeState)
{
case UpgradeState.WritingUpgradeAck:
thisPtr.ChangeUpgradeState(UpgradeState.UpgradeAckSent);
break;
case UpgradeState.WritingPreambleEnd:
thisPtr.ChangeUpgradeState(UpgradeState.PreambleEndSent);
break;
}
completeSelf = thisPtr.ContinueWork(null);
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
completionException = ex;
completeSelf = true;
}
if (completeSelf)
{
if (completionException != null)
{
thisPtr.Complete(false, completionException);
}
else
{
thisPtr.Complete(thisPtr.currentConnection, false);
}
}
}
static void OnUpgradeComplete(IAsyncResult result)
{
if (result.CompletedSynchronously)
{
return;
}
CompletePreambleAsyncResult thisPtr = (CompletePreambleAsyncResult)result.AsyncState;
Exception completionException = null;
bool completeSelf = false;
try
{
thisPtr.ChangeUpgradeState(UpgradeState.EndUpgrade);
completeSelf = thisPtr.ContinueWork(result);
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
completionException = ex;
completeSelf = true;
}
if (completeSelf)
{
if (completionException != null)
{
thisPtr.Complete(false, completionException);
}
else
{
thisPtr.Complete(thisPtr.currentConnection, false);
}
}
}
enum UpgradeState
{
None,
VerifyingUpgradeRequest,
WritingUpgradeAck,
UpgradeAckSent,
BeginUpgrade,
EndUpgrade,
UpgradeComplete,
WritingPreambleEnd,
PreambleEndSent,
}
}
void SetupSecurityIfNecessary(StreamUpgradeAcceptor upgradeAcceptor)
{
StreamSecurityUpgradeAcceptor securityUpgradeAcceptor = upgradeAcceptor as StreamSecurityUpgradeAcceptor;
if (securityUpgradeAcceptor != null)
{
this.security = securityUpgradeAcceptor.GetRemoteSecurity();
if (this.security == null)
{
Exception securityFailedException = new ProtocolException(
SR.GetString(SR.RemoteSecurityNotNegotiatedOnStreamUpgrade, this.Via));
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(securityFailedException);
}
// Audit Authentication Success
WriteAuditEvent(securityUpgradeAcceptor, AuditLevel.Success, null);
}
}
#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.transportSettings.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.transportSettings.AuditBehavior;
if (auditLevel == AuditLevel.Success)
{
SecurityAuditHelper.WriteTransportAuthenticationSuccessEvent(auditBehavior.AuditLogLocation,
auditBehavior.SuppressAuditFailure, null, this.Via, primaryIdentity);
}
else
{
SecurityAuditHelper.WriteTransportAuthenticationFailureEvent(auditBehavior.AuditLogLocation,
auditBehavior.SuppressAuditFailure, null, this.Via, primaryIdentity, exception);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
static string GetIdentityNameFromContext(SecurityMessageProperty clientSecurity)
{
return SecurityUtils.GetIdentityNamesFromContext(
clientSecurity.ServiceSecurityContext.AuthorizationContext);
}
#endregion
void HandleReadComplete()
{
offset = 0;
size = Connection.EndRead();
isReadPending = false;
if (size == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
}
}
void OnAsyncReadComplete(object state)
{
bool success = false;
try
{
HandleReadComplete();
ReadAndDispatch();
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 -- we abort ourselves for any error, no extra containment needed
}
finally
{
if (!success)
{
Abort();
}
}
}
public void StartReading(Action<Uri> viaDelegate, TimeSpan timeout)
{
this.viaDelegate = viaDelegate;
this.receiveTimeoutHelper = new TimeoutHelper(timeout);
this.connectionBuffer = Connection.AsyncReadBuffer;
ReadAndDispatch();
}
}
class ServerSingletonConnectionReader : SingletonConnectionReader
{
ConnectionDemuxer connectionDemuxer;
ServerSingletonDecoder decoder;
IConnection rawConnection;
string contentType;
ChannelBinding channelBindingToken;
public ServerSingletonConnectionReader(ServerSingletonPreambleConnectionReader preambleReader,
IConnection upgradedConnection, ConnectionDemuxer connectionDemuxer)
: base(upgradedConnection, preambleReader.BufferOffset, preambleReader.BufferSize,
preambleReader.Security, preambleReader.TransportSettings, preambleReader.Via)
{
this.decoder = preambleReader.Decoder;
this.contentType = this.decoder.ContentType;
this.connectionDemuxer = connectionDemuxer;
this.rawConnection = preambleReader.RawConnection;
this.channelBindingToken = preambleReader.ChannelBinding;
}
protected override string ContentType
{
get { return this.contentType; }
}
protected override long StreamPosition
{
get { return this.decoder.StreamPosition; }
}
protected override bool DecodeBytes(byte[] buffer, ref int offset, ref int size, ref bool isAtEof)
{
while (size > 0)
{
int bytesRead = decoder.Decode(buffer, offset, size);
if (bytesRead > 0)
{
offset += bytesRead;
size -= bytesRead;
}
switch (decoder.CurrentState)
{
case ServerSingletonDecoder.State.EnvelopeStart:
// we're at the envelope
return true;
case ServerSingletonDecoder.State.End:
isAtEof = true;
return false;
}
}
return false;
}
protected override void OnClose(TimeSpan timeout)
{
TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
// send back EOF and then recycle the connection
this.Connection.Write(SingletonEncoder.EndBytes, 0, SingletonEncoder.EndBytes.Length, true, timeoutHelper.RemainingTime());
this.connectionDemuxer.ReuseConnection(this.rawConnection, timeoutHelper.RemainingTime());
ChannelBindingUtility.Dispose(ref this.channelBindingToken);
}
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);
}
if (this.channelBindingToken != null)
{
ChannelBindingMessageProperty property = new ChannelBindingMessageProperty(this.channelBindingToken, false);
property.AddTo(message);
property.Dispose(); //message.Properties.Add() creates a copy...
}
}
}
abstract class SingletonConnectionReader
{
IConnection connection;
bool doneReceiving;
bool doneSending;
bool isAtEof;
bool isClosed;
SecurityMessageProperty security;
object thisLock = new object();
int offset;
int size;
IConnectionOrientedTransportFactorySettings transportSettings;
Uri via;
Stream inputStream;
protected SingletonConnectionReader(IConnection connection, int offset, int size, SecurityMessageProperty security,
IConnectionOrientedTransportFactorySettings transportSettings, Uri via)
{
this.connection = connection;
this.offset = offset;
this.size = size;
this.security = security;
this.transportSettings = transportSettings;
this.via = via;
}
protected IConnection Connection
{
get
{
return this.connection;
}
}
protected object ThisLock
{
get
{
return this.thisLock;
}
}
protected virtual string ContentType
{
get { return null; }
}
protected abstract long StreamPosition { get; }
public void Abort()
{
this.connection.Abort();
}
public void DoneReceiving(bool atEof)
{
DoneReceiving(atEof, this.transportSettings.CloseTimeout);
}
void DoneReceiving(bool atEof, TimeSpan timeout)
{
if (!this.doneReceiving)
{
this.isAtEof = atEof;
this.doneReceiving = true;
if (this.doneSending)
{
this.Close(timeout);
}
}
}
public void Close(TimeSpan timeout)
{
lock (ThisLock)
{
if (this.isClosed)
{
return;
}
this.isClosed = true;
}
TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
bool success = false;
try
{
// first drain our stream if necessary
if (this.inputStream != null)
{
byte[] dummy = DiagnosticUtility.Utility.AllocateByteArray(transportSettings.ConnectionBufferSize);
while (!this.isAtEof)
{
this.inputStream.ReadTimeout = TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime());
int bytesRead = this.inputStream.Read(dummy, 0, dummy.Length);
if (bytesRead == 0)
{
this.isAtEof = true;
}
}
}
OnClose(timeoutHelper.RemainingTime());
success = true;
}
finally
{
if (!success)
{
this.Abort();
}
}
}
protected abstract void OnClose(TimeSpan timeout);
public void DoneSending(TimeSpan timeout)
{
this.doneSending = true;
if (this.doneReceiving)
{
this.Close(timeout);
}
}
protected abstract bool DecodeBytes(byte[] buffer, ref int offset, ref int size, ref bool isAtEof);
protected virtual void PrepareMessage(Message message)
{
message.Properties.Via = this.via;
message.Properties.Security = (this.security != null) ? (SecurityMessageProperty)this.security.CreateCopy() : null;
}
public RequestContext ReceiveRequest(TimeSpan timeout)
{
Message requestMessage = Receive(timeout);
return new StreamedFramingRequestContext(this, requestMessage);
}
public IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)
{
return new ReceiveAsyncResult(this, timeout, callback, state);
}
public virtual Message EndReceive(IAsyncResult result)
{
return ReceiveAsyncResult.End(result);
}
public Message Receive(TimeSpan timeout)
{
byte[] buffer = DiagnosticUtility.Utility.AllocateByteArray(connection.AsyncReadBufferSize);
if (size > 0)
{
Buffer.BlockCopy(connection.AsyncReadBuffer, offset, buffer, offset, size);
}
TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
for (;;)
{
if (DecodeBytes(buffer, ref offset, ref size, ref isAtEof))
{
break;
}
if (this.isAtEof)
{
DoneReceiving(true, timeoutHelper.RemainingTime());
return null;
}
if (size == 0)
{
offset = 0;
size = connection.Read(buffer, 0, buffer.Length, timeoutHelper.RemainingTime());
if (size == 0)
{
DoneReceiving(true, timeoutHelper.RemainingTime());
return null;
}
}
}
// we're ready to read a message
IConnection singletonConnection = this.connection;
if (size > 0)
{
byte[] initialData = DiagnosticUtility.Utility.AllocateByteArray(size);
Buffer.BlockCopy(buffer, offset, initialData, 0, size);
singletonConnection = new PreReadConnection(singletonConnection, initialData);
}
Stream connectionStream = new SingletonInputConnectionStream(this, singletonConnection, this.transportSettings);
this.inputStream = new MaxMessageSizeStream(connectionStream, transportSettings.MaxReceivedMessageSize);
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 = transportSettings.MessageEncoderFactory.Encoder.ReadMessage(
this.inputStream, transportSettings.MaxBufferSize, this.ContentType);
}
catch (XmlException xmlException)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ProtocolException(SR.GetString(SR.MessageXmlProtocolError), xmlException));
}
if (DiagnosticUtility.ShouldUseActivity)
{
TraceUtility.TransferFromTransport(message);
}
PrepareMessage(message);
return message;
}
}
class ReceiveAsyncResult : AsyncResult
{
static Action<object> onReceiveScheduled = new Action<object>(OnReceiveScheduled);
Message message;
SingletonConnectionReader parent;
TimeSpan timeout;
public ReceiveAsyncResult(SingletonConnectionReader parent, TimeSpan timeout, AsyncCallback callback,
object state)
: base(callback, state)
{
this.parent = parent;
this.timeout = timeout;
//
ActionItem.Schedule(onReceiveScheduled, this);
}
public static Message End(IAsyncResult result)
{
ReceiveAsyncResult receiveAsyncResult = AsyncResult.End<ReceiveAsyncResult>(result);
return receiveAsyncResult.message;
}
static void OnReceiveScheduled(object state)
{
ReceiveAsyncResult thisPtr = (ReceiveAsyncResult)state;
Exception completionException = null;
try
{
thisPtr.message = thisPtr.parent.Receive(thisPtr.timeout);
}
#pragma warning suppress 56500 // Microsoft, transferring exception to another thread
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw;
}
completionException = exception;
}
thisPtr.Complete(false, completionException);
}
}
class StreamedFramingRequestContext : RequestContextBase
{
IConnection connection;
SingletonConnectionReader parent;
IConnectionOrientedTransportFactorySettings settings;
TimeoutHelper timeoutHelper;
public StreamedFramingRequestContext(SingletonConnectionReader parent, Message requestMessage)
: base(requestMessage, parent.transportSettings.CloseTimeout, parent.transportSettings.SendTimeout)
{
this.parent = parent;
this.connection = parent.connection;
this.settings = parent.transportSettings;
}
protected override void OnAbort()
{
this.parent.Abort();
}
protected override void OnClose(TimeSpan timeout)
{
this.parent.Close(timeout);
}
protected override void OnReply(Message message, TimeSpan timeout)
{
ICompressedMessageEncoder compressedMessageEncoder = this.settings.MessageEncoderFactory.Encoder as ICompressedMessageEncoder;
if (compressedMessageEncoder != null && compressedMessageEncoder.CompressionEnabled)
{
compressedMessageEncoder.AddCompressedMessageProperties(message, this.parent.ContentType);
}
timeoutHelper = new TimeoutHelper(timeout);
StreamingConnectionHelper.WriteMessage(message, this.connection, false, this.settings, ref timeoutHelper);
parent.DoneSending(timeoutHelper.RemainingTime());
}
protected override IAsyncResult OnBeginReply(Message message, TimeSpan timeout, AsyncCallback callback, object state)
{
ICompressedMessageEncoder compressedMessageEncoder = this.settings.MessageEncoderFactory.Encoder as ICompressedMessageEncoder;
if (compressedMessageEncoder != null && compressedMessageEncoder.CompressionEnabled)
{
compressedMessageEncoder.AddCompressedMessageProperties(message, this.parent.ContentType);
}
timeoutHelper = new TimeoutHelper(timeout);
return StreamingConnectionHelper.BeginWriteMessage(message, this.connection, false, this.settings,
ref timeoutHelper, callback, state);
}
protected override void OnEndReply(IAsyncResult result)
{
StreamingConnectionHelper.EndWriteMessage(result);
parent.DoneSending(timeoutHelper.RemainingTime());
}
}
// ensures that the reader is notified at end-of-stream, and takes care of the framing chunk headers
class SingletonInputConnectionStream : ConnectionStream
{
SingletonMessageDecoder decoder;
SingletonConnectionReader reader;
bool atEof;
byte[] chunkBuffer; // used for when we have overflow
int chunkBufferOffset;
int chunkBufferSize;
int chunkBytesRemaining;
public SingletonInputConnectionStream(SingletonConnectionReader reader, IConnection connection,
IDefaultCommunicationTimeouts defaultTimeouts)
: base(connection, defaultTimeouts)
{
this.reader = reader;
this.decoder = new SingletonMessageDecoder(reader.StreamPosition);
this.chunkBytesRemaining = 0;
this.chunkBuffer = new byte[IntEncoder.MaxEncodedSize];
}
void AbortReader()
{
this.reader.Abort();
}
public override void Close()
{
this.reader.DoneReceiving(this.atEof);
}
// run chunk data through the decoder
void DecodeData(byte[] buffer, int offset, int size)
{
while (size > 0)
{
int bytesRead = decoder.Decode(buffer, offset, size);
offset += bytesRead;
size -= bytesRead;
Fx.Assert(decoder.CurrentState == SingletonMessageDecoder.State.ReadingEnvelopeBytes || decoder.CurrentState == SingletonMessageDecoder.State.ChunkEnd, "");
}
}
// run the current data through the decoder to get valid message bytes
void DecodeSize(byte[] buffer, ref int offset, ref int size)
{
while (size > 0)
{
int bytesRead = decoder.Decode(buffer, offset, size);
if (bytesRead > 0)
{
offset += bytesRead;
size -= bytesRead;
}
switch (decoder.CurrentState)
{
case SingletonMessageDecoder.State.ChunkStart:
this.chunkBytesRemaining = decoder.ChunkSize;
// if we have overflow and we're not decoding out of our buffer, copy over
if (size > 0 && !object.ReferenceEquals(buffer, this.chunkBuffer))
{
Fx.Assert(size <= this.chunkBuffer.Length, "");
Buffer.BlockCopy(buffer, offset, this.chunkBuffer, 0, size);
this.chunkBufferOffset = 0;
this.chunkBufferSize = size;
}
return;
case SingletonMessageDecoder.State.End:
ProcessEof();
return;
}
}
}
int ReadCore(byte[] buffer, int offset, int count)
{
int bytesRead = -1;
try
{
bytesRead = base.Read(buffer, offset, count);
if (bytesRead == 0)
{
ProcessEof();
}
}
finally
{
if (bytesRead == -1) // there was an exception
{
AbortReader();
}
}
return bytesRead;
}
public override int Read(byte[] buffer, int offset, int count)
{
int result = 0;
while (true)
{
if (count == 0)
{
return result;
}
if (this.atEof)
{
return result;
}
// first deal with any residual carryover
if (this.chunkBufferSize > 0)
{
int bytesToCopy = Math.Min(chunkBytesRemaining,
Math.Min(this.chunkBufferSize, count));
Buffer.BlockCopy(this.chunkBuffer, this.chunkBufferOffset, buffer, offset, bytesToCopy);
// keep decoder up to date
DecodeData(this.chunkBuffer, this.chunkBufferOffset, bytesToCopy);
this.chunkBufferOffset += bytesToCopy;
this.chunkBufferSize -= bytesToCopy;
this.chunkBytesRemaining -= bytesToCopy;
if (this.chunkBytesRemaining == 0 && this.chunkBufferSize > 0)
{
DecodeSize(this.chunkBuffer, ref this.chunkBufferOffset, ref this.chunkBufferSize);
}
result += bytesToCopy;
offset += bytesToCopy;
count -= bytesToCopy;
}
else if (chunkBytesRemaining > 0)
{
// We're in the middle of a chunk. Try and include the next chunk size as well
int bytesToRead = count;
if (int.MaxValue - chunkBytesRemaining >= IntEncoder.MaxEncodedSize)
{
bytesToRead = Math.Min(count, chunkBytesRemaining + IntEncoder.MaxEncodedSize);
}
int bytesRead = ReadCore(buffer, offset, bytesToRead);
// keep decoder up to date
DecodeData(buffer, offset, Math.Min(bytesRead, this.chunkBytesRemaining));
if (bytesRead > chunkBytesRemaining)
{
result += this.chunkBytesRemaining;
int overflowCount = bytesRead - chunkBytesRemaining;
int overflowOffset = offset + chunkBytesRemaining;
this.chunkBytesRemaining = 0;
// read at least part of the next chunk, and put any overflow in this.chunkBuffer
DecodeSize(buffer, ref overflowOffset, ref overflowCount);
}
else
{
result += bytesRead;
this.chunkBytesRemaining -= bytesRead;
}
return result;
}
else
{
// Final case: we have a new chunk. Read the size, and loop around again
if (count < IntEncoder.MaxEncodedSize)
{
// we don't have space for MaxEncodedSize, so it's worth the copy cost to read into a temp buffer
this.chunkBufferOffset = 0;
this.chunkBufferSize = ReadCore(this.chunkBuffer, 0, this.chunkBuffer.Length);
DecodeSize(this.chunkBuffer, ref this.chunkBufferOffset, ref this.chunkBufferSize);
}
else
{
int bytesRead = ReadCore(buffer, offset, IntEncoder.MaxEncodedSize);
int sizeOffset = offset;
DecodeSize(buffer, ref sizeOffset, ref bytesRead);
}
}
}
}
void ProcessEof()
{
if (!this.atEof)
{
this.atEof = true;
if (this.chunkBufferSize > 0 || this.chunkBytesRemaining > 0
|| decoder.CurrentState != SingletonMessageDecoder.State.End)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
}
this.reader.DoneReceiving(true);
}
}
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
return new ReadAsyncResult(this, buffer, offset, count, callback, state);
}
public override int EndRead(IAsyncResult result)
{
return ReadAsyncResult.End(result);
}
public class ReadAsyncResult : AsyncResult
{
SingletonInputConnectionStream parent;
int result;
public ReadAsyncResult(SingletonInputConnectionStream parent,
byte[] buffer, int offset, int count, AsyncCallback callback, object state)
: base(callback, state)
{
this.parent = parent;
//
this.result = this.parent.Read(buffer, offset, count);
base.Complete(true);
}
public static int End(IAsyncResult result)
{
ReadAsyncResult thisPtr = AsyncResult.End<ReadAsyncResult>(result);
return thisPtr.result;
}
}
}
}
static class StreamingConnectionHelper
{
public static void WriteMessage(Message message, IConnection connection, bool isRequest,
IConnectionOrientedTransportFactorySettings settings, ref TimeoutHelper timeoutHelper)
{
byte[] endBytes = null;
if (message != null)
{
MessageEncoder messageEncoder = settings.MessageEncoderFactory.Encoder;
byte[] envelopeStartBytes = SingletonEncoder.EnvelopeStartBytes;
bool writeStreamed;
if (isRequest)
{
endBytes = SingletonEncoder.EnvelopeEndFramingEndBytes;
writeStreamed = TransferModeHelper.IsRequestStreamed(settings.TransferMode);
}
else
{
endBytes = SingletonEncoder.EnvelopeEndBytes;
writeStreamed = TransferModeHelper.IsResponseStreamed(settings.TransferMode);
}
if (writeStreamed)
{
connection.Write(envelopeStartBytes, 0, envelopeStartBytes.Length, false, timeoutHelper.RemainingTime());
Stream connectionStream = new StreamingOutputConnectionStream(connection, settings);
Stream writeTimeoutStream = new TimeoutStream(connectionStream, ref timeoutHelper);
messageEncoder.WriteMessage(message, writeTimeoutStream);
}
else
{
ArraySegment<byte> messageData = messageEncoder.WriteMessage(message,
int.MaxValue, settings.BufferManager, envelopeStartBytes.Length + IntEncoder.MaxEncodedSize);
messageData = SingletonEncoder.EncodeMessageFrame(messageData);
Buffer.BlockCopy(envelopeStartBytes, 0, messageData.Array, messageData.Offset - envelopeStartBytes.Length,
envelopeStartBytes.Length);
connection.Write(messageData.Array, messageData.Offset - envelopeStartBytes.Length,
messageData.Count + envelopeStartBytes.Length, true, timeoutHelper.RemainingTime(), settings.BufferManager);
}
}
else if (isRequest) // context handles response end bytes
{
endBytes = SingletonEncoder.EndBytes;
}
if (endBytes != null)
{
connection.Write(endBytes, 0, endBytes.Length,
true, timeoutHelper.RemainingTime());
}
}
public static IAsyncResult BeginWriteMessage(Message message, IConnection connection, bool isRequest,
IConnectionOrientedTransportFactorySettings settings, ref TimeoutHelper timeoutHelper,
AsyncCallback callback, object state)
{
return new WriteMessageAsyncResult(message, connection, isRequest, settings, ref timeoutHelper, callback, state);
}
public static void EndWriteMessage(IAsyncResult result)
{
WriteMessageAsyncResult.End(result);
}
// overrides ConnectionStream to add a Framing int at the beginning of each record
class StreamingOutputConnectionStream : ConnectionStream
{
byte[] encodedSize;
public StreamingOutputConnectionStream(IConnection connection, IDefaultCommunicationTimeouts timeouts)
: base(connection, timeouts)
{
this.encodedSize = new byte[IntEncoder.MaxEncodedSize];
}
void WriteChunkSize(int size)
{
if (size > 0)
{
int bytesEncoded = IntEncoder.Encode(size, encodedSize, 0);
base.Connection.Write(encodedSize, 0, bytesEncoded, false, TimeSpan.FromMilliseconds(this.WriteTimeout));
}
}
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
WriteChunkSize(count);
return base.BeginWrite(buffer, offset, count, callback, state);
}
public override void WriteByte(byte value)
{
WriteChunkSize(1);
base.WriteByte(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
WriteChunkSize(count);
base.Write(buffer, offset, count);
}
}
class WriteMessageAsyncResult : AsyncResult
{
IConnection connection;
MessageEncoder encoder;
BufferManager bufferManager;
Message message;
static WaitCallback onWriteBufferedMessage;
static WaitCallback onWriteStartBytes;
static Action<object> onWriteStartBytesScheduled;
static WaitCallback onWriteEndBytes =
Fx.ThunkCallback(new WaitCallback(OnWriteEndBytes));
byte[] bufferToFree;
IConnectionOrientedTransportFactorySettings settings;
TimeoutHelper timeoutHelper;
byte[] endBytes;
public WriteMessageAsyncResult(Message message, IConnection connection, bool isRequest,
IConnectionOrientedTransportFactorySettings settings, ref TimeoutHelper timeoutHelper,
AsyncCallback callback, object state)
: base(callback, state)
{
this.connection = connection;
this.encoder = settings.MessageEncoderFactory.Encoder;
this.bufferManager = settings.BufferManager;
this.timeoutHelper = timeoutHelper;
this.message = message;
this.settings = settings;
bool throwing = true;
bool completeSelf = false;
if (message == null)
{
if (isRequest) // context takes care of the end bytes on Close/reader.EOF
{
this.endBytes = SingletonEncoder.EndBytes;
}
completeSelf = WriteEndBytes();
}
else
{
try
{
byte[] envelopeStartBytes = SingletonEncoder.EnvelopeStartBytes;
bool writeStreamed;
if (isRequest)
{
this.endBytes = SingletonEncoder.EnvelopeEndFramingEndBytes;
writeStreamed = TransferModeHelper.IsRequestStreamed(settings.TransferMode);
}
else
{
this.endBytes = SingletonEncoder.EnvelopeEndBytes;
writeStreamed = TransferModeHelper.IsResponseStreamed(settings.TransferMode);
}
if (writeStreamed)
{
if (onWriteStartBytes == null)
{
onWriteStartBytes = Fx.ThunkCallback(new WaitCallback(OnWriteStartBytes));
}
AsyncCompletionResult writeStartBytesResult = connection.BeginWrite(envelopeStartBytes, 0, envelopeStartBytes.Length, true,
timeoutHelper.RemainingTime(), onWriteStartBytes, this);
if (writeStartBytesResult == AsyncCompletionResult.Completed)
{
if (onWriteStartBytesScheduled == null)
{
onWriteStartBytesScheduled = new Action<object>(OnWriteStartBytes);
}
ActionItem.Schedule(onWriteStartBytesScheduled, this);
}
}
else
{
ArraySegment<byte> messageData = settings.MessageEncoderFactory.Encoder.WriteMessage(message,
int.MaxValue, this.bufferManager, envelopeStartBytes.Length + IntEncoder.MaxEncodedSize);
messageData = SingletonEncoder.EncodeMessageFrame(messageData);
this.bufferToFree = messageData.Array;
Buffer.BlockCopy(envelopeStartBytes, 0, messageData.Array, messageData.Offset - envelopeStartBytes.Length,
envelopeStartBytes.Length);
if (onWriteBufferedMessage == null)
{
onWriteBufferedMessage = Fx.ThunkCallback(new WaitCallback(OnWriteBufferedMessage));
}
AsyncCompletionResult writeBufferedResult =
connection.BeginWrite(messageData.Array, messageData.Offset - envelopeStartBytes.Length,
messageData.Count + envelopeStartBytes.Length, true, timeoutHelper.RemainingTime(),
onWriteBufferedMessage, this);
if (writeBufferedResult == AsyncCompletionResult.Completed)
{
completeSelf = HandleWriteBufferedMessage();
}
}
throwing = false;
}
finally
{
if (throwing)
{
Cleanup();
}
}
}
if (completeSelf)
{
base.Complete(true);
}
}
public static void End(IAsyncResult result)
{
AsyncResult.End<WriteMessageAsyncResult>(result);
}
void Cleanup()
{
if (bufferToFree != null)
{
this.bufferManager.ReturnBuffer(bufferToFree);
}
}
bool HandleWriteStartBytes()
{
connection.EndWrite();
Stream connectionStream = new StreamingOutputConnectionStream(connection, settings);
Stream writeTimeoutStream = new TimeoutStream(connectionStream, ref timeoutHelper);
this.encoder.WriteMessage(message, writeTimeoutStream);
return WriteEndBytes();
}
bool HandleWriteBufferedMessage()
{
this.connection.EndWrite();
return WriteEndBytes();
}
bool WriteEndBytes()
{
if (this.endBytes == null)
{
Cleanup();
return true;
}
AsyncCompletionResult result = connection.BeginWrite(endBytes, 0,
endBytes.Length, true, timeoutHelper.RemainingTime(), onWriteEndBytes, this);
if (result == AsyncCompletionResult.Queued)
{
return false;
}
return HandleWriteEndBytes();
}
bool HandleWriteEndBytes()
{
this.connection.EndWrite();
Cleanup();
return true;
}
static void OnWriteStartBytes(object asyncState)
{
OnWriteStartBytesCallbackHelper(asyncState);
}
static void OnWriteStartBytesCallbackHelper(object asyncState)
{
WriteMessageAsyncResult thisPtr = (WriteMessageAsyncResult)asyncState;
Exception completionException = null;
bool completeSelf = false;
bool throwing = true;
try
{
completeSelf = thisPtr.HandleWriteStartBytes();
throwing = false;
}
#pragma warning suppress 56500 // Microsoft, transferring exception to another thread
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
completeSelf = true;
completionException = e;
}
finally
{
if (throwing)
{
thisPtr.Cleanup();
}
}
if (completeSelf)
{
thisPtr.Complete(false, completionException);
}
}
static void OnWriteBufferedMessage(object asyncState)
{
WriteMessageAsyncResult thisPtr = (WriteMessageAsyncResult)asyncState;
Exception completionException = null;
bool completeSelf = false;
bool throwing = true;
try
{
completeSelf = thisPtr.HandleWriteBufferedMessage();
throwing = false;
}
#pragma warning suppress 56500 // Microsoft, transferring exception to another thread
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
completeSelf = true;
completionException = e;
}
finally
{
if (throwing)
{
thisPtr.Cleanup();
}
}
if (completeSelf)
{
thisPtr.Complete(false, completionException);
}
}
static void OnWriteEndBytes(object asyncState)
{
WriteMessageAsyncResult thisPtr = (WriteMessageAsyncResult)asyncState;
Exception completionException = null;
bool completeSelf = false;
bool success = false;
try
{
completeSelf = thisPtr.HandleWriteEndBytes();
success = true;
}
#pragma warning suppress 56500 // Microsoft, transferring exception to another thread
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
completeSelf = true;
completionException = e;
}
finally
{
if (!success)
{
thisPtr.Cleanup();
}
}
if (completeSelf)
{
thisPtr.Complete(false, completionException);
}
}
}
}
}