Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / ManagedLibraries / Remoting / Channels / TCP / TcpClientChannel.cs / 1305376 / TcpClientChannel.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //============================================================================ // File: TcpClientChannel.cs // // Summary: Implements a channel that transmits method calls over TCP. // //========================================================================= using System; using System.Collections; using System.IO; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Messaging; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Text; using System.Globalization; #if !FEATURE_PAL using System.Security.Authentication; #endif using System.Security.Principal; using System.Security.Permissions; namespace System.Runtime.Remoting.Channels.Tcp { public class TcpClientChannel : IChannelSender, ISecurableChannel { private int _channelPriority = 1; // channel priority private String _channelName = "tcp"; // channel name private bool _secure = false; private IDictionary _prop = null; private IClientChannelSinkProvider _sinkProvider = null; // sink chain provider public TcpClientChannel() { SetupChannel(); } // TcpClientChannel public TcpClientChannel(String name, IClientChannelSinkProvider sinkProvider) { _channelName = name; _sinkProvider = sinkProvider; SetupChannel(); } // constructor used by config file public TcpClientChannel(IDictionary properties, IClientChannelSinkProvider sinkProvider) { if (properties != null) { _prop = properties; foreach (DictionaryEntry entry in properties) { switch ((String)entry.Key) { case "name": _channelName = (String)entry.Value; break; case "priority": _channelPriority = Convert.ToInt32(entry.Value, CultureInfo.InvariantCulture); break; case "secure": _secure = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture); break; default: break; } } } _sinkProvider = sinkProvider; SetupChannel(); } // TcpClientChannel private void SetupChannel() { if (_sinkProvider != null) { CoreChannel.AppendProviderToClientProviderChain( _sinkProvider, new TcpClientTransportSinkProvider(_prop)); } else _sinkProvider = CreateDefaultClientProviderChain(); } // SetupChannel // // ISecurableChannel implementation // public bool IsSecured { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] get { return _secure; } [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] set { _secure = value; } } // // IChannel implementation // public int ChannelPriority { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] get { return _channelPriority; } } public String ChannelName { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] get { return _channelName; } } // returns channelURI and places object uri into out parameter [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] public String Parse(String url, out String objectURI) { return TcpChannelHelper.ParseURL(url, out objectURI); } // Parse // // end of IChannel implementation // // // IChannelSender implementation // [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] public virtual IMessageSink CreateMessageSink(String url, Object remoteChannelData, out String objectURI) { // Set the out parameters objectURI = null; String channelURI = null; if (url != null) // Is this a well known object? { // Parse returns null if this is not one of our url's channelURI = Parse(url, out objectURI); } else // determine if we want to connect based on the channel data { if (remoteChannelData != null) { if (remoteChannelData is IChannelDataStore) { IChannelDataStore cds = (IChannelDataStore)remoteChannelData; // see if this is an tcp uri String simpleChannelUri = Parse(cds.ChannelUris[0], out objectURI); if (simpleChannelUri != null) channelURI = cds.ChannelUris[0]; } } } if (null != channelURI) { if (url == null) url = channelURI; IClientChannelSink sink = _sinkProvider.CreateSink(this, url, remoteChannelData); // return sink after making sure that it implements IMessageSink IMessageSink msgSink = sink as IMessageSink; if ((sink != null) && (msgSink == null)) { throw new RemotingException( CoreChannel.GetResourceString( "Remoting_Channels_ChannelSinkNotMsgSink")); } return msgSink; } return null; } // CreateMessageSink // // end of IChannelSender implementation // private IClientChannelSinkProvider CreateDefaultClientProviderChain() { IClientChannelSinkProvider chain = new BinaryClientFormatterSinkProvider(); IClientChannelSinkProvider sink = chain; sink.Next = new TcpClientTransportSinkProvider(_prop); return chain; } // CreateDefaultClientProviderChain } // class TcpClientChannel internal class TcpClientTransportSinkProvider : IClientChannelSinkProvider { IDictionary _prop = null; internal TcpClientTransportSinkProvider(IDictionary properties) { _prop = properties; } public IClientChannelSink CreateSink(IChannelSender channel, String url, Object remoteChannelData) { // url is set to the channel uri in CreateMessageSink TcpClientTransportSink sink = new TcpClientTransportSink(url, (TcpClientChannel) channel); if (_prop != null) { // Tansfer all properties from the channel to the sink foreach(Object key in _prop.Keys) { sink[key] = _prop[key]; } } return sink; } public IClientChannelSinkProvider Next { get { return null; } set { throw new NotSupportedException(); } } } // class TcpClientTransportSinkProvider internal class TcpClientTransportSink : BaseChannelSinkWithProperties, IClientChannelSink { // socket cache internal SocketCache ClientSocketCache; private bool authSet = false; private SocketHandler CreateSocketHandler( Socket socket, SocketCache socketCache, String machinePortAndSid) { Stream netStream = new SocketStream(socket); // Check if authentication is requested if(_channel.IsSecured) { #if !FEATURE_PAL netStream = CreateAuthenticatedStream(netStream, machinePortAndSid); #else throw new NotSupportedException(); #endif } return new TcpClientSocketHandler(socket, machinePortAndSid, netStream, this); } // CreateSocketHandler #if !FEATURE_PAL private Stream CreateAuthenticatedStream(Stream netStream, String machinePortAndSid) { //Check for explicitly set userName, and authenticate using it NetworkCredential credentials = null; NegotiateStream negoClient = null; if (_securityUserName != null) { credentials = new NetworkCredential(_securityUserName, _securityPassword, _securityDomain); } //else use default Credentials else { credentials = (NetworkCredential)CredentialCache.DefaultCredentials; } try { negoClient = new NegotiateStream(netStream); negoClient.AuthenticateAsClient(credentials, _spn, _protectionLevel, _tokenImpersonationLevel); } catch(IOException e){ throw new RemotingException( String.Format(CultureInfo.CurrentCulture, CoreChannel.GetResourceString("Remoting_Tcp_AuthenticationFailed")), e); } return negoClient; } #endif // !FEATURE_PAL // returns the connectiongroupname else the Sid for current credentials private String GetSid() { if (_connectionGroupName != null) { return _connectionGroupName; } #if !FEATURE_PAL return CoreChannel.GetCurrentSidString(); #else return null; #endif } // transport sink state private String m_machineName; private int m_port; private TcpClientChannel _channel = null; private String _machineAndPort; private const String UserNameKey = "username"; private const String PasswordKey = "password"; private const String DomainKey = "domain"; private const String ProtectionLevelKey = "protectionlevel"; private const String ConnectionGroupNameKey = "connectiongroupname"; #if !FEATURE_PAL private const String TokenImpersonationLevelKey = "tokenimpersonationlevel"; #endif // !FEATURE_PAL private const String SocketCacheTimeoutKey = "socketcachetimeout"; private const String ReceiveTimeoutKey = "timeout"; private const String SocketCachePolicyKey = "socketcachepolicy"; private const String SPNKey = "serviceprincipalname"; private const String RetryCountKey = "retrycount"; // property values private String _securityUserName = null; private String _securityPassword = null; private String _securityDomain = null; private String _connectionGroupName = null; private TimeSpan _socketCacheTimeout = TimeSpan.FromSeconds(10); // default timeout is 5 seconds private int _receiveTimeout = 0; // default timeout is infinite private SocketCachePolicy _socketCachePolicy = SocketCachePolicy.Default; // default is v1.0 behaviour private String _spn = string.Empty; private int _retryCount = 1; // defualt retry is 1 to keep it equivalent with v1.1 #if !FEATURE_PAL private TokenImpersonationLevel _tokenImpersonationLevel = TokenImpersonationLevel.Identification; // default is no authentication #endif // !FEATURE_PAL private ProtectionLevel _protectionLevel = ProtectionLevel.EncryptAndSign; private static ICollection s_keySet = null; internal TcpClientTransportSink(String channelURI, TcpClientChannel channel) { String objectURI; _channel = channel; String simpleChannelUri = TcpChannelHelper.ParseURL(channelURI, out objectURI); ClientSocketCache = new SocketCache(new SocketHandlerFactory(this.CreateSocketHandler), _socketCachePolicy, _socketCacheTimeout); // extract machine name and port Uri uri = new Uri(simpleChannelUri); if (uri.IsDefaultPort) { // If there is no colon, then there is no port number. throw new RemotingException( String.Format( CultureInfo.CurrentCulture, CoreChannel.GetResourceString( "Remoting_Tcp_UrlMustHavePort"), channelURI)); } m_machineName = uri.Host; m_port = uri.Port; _machineAndPort = m_machineName + ":" + m_port; } // TcpClientTransportSink public void ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, out ITransportHeaders responseHeaders, out Stream responseStream) { InternalRemotingServices.RemotingTrace("TcpClientTransportSink::ProcessMessage"); // the call to SendRequest can block a func eval, so we want to notify the debugger that we're // about to call a blocking operation. System.Diagnostics.Debugger.NotifyOfCrossThreadDependency(); TcpClientSocketHandler clientSocket = SendRequestWithRetry(msg, requestHeaders, requestStream); // receive response responseHeaders = clientSocket.ReadHeaders(); responseStream = clientSocket.GetResponseStream(); // The client socket will be returned to the cache // when the response stream is closed. } // ProcessMessage public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream) { InternalRemotingServices.RemotingTrace("TcpClientTransportSink::AsyncProcessRequest"); TcpClientSocketHandler clientSocket = SendRequestWithRetry(msg, headers, stream); if (clientSocket.OneWayRequest) { clientSocket.ReturnToCache(); } else { // do an async read on the reply clientSocket.DataArrivedCallback = new WaitCallback(this.ReceiveCallback); clientSocket.DataArrivedCallbackState = sinkStack; clientSocket.BeginReadMessage(); } } // AsyncProcessRequest public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, Object state, ITransportHeaders headers, Stream stream) { // We don't have to implement this since we are always last in the chain. throw new NotSupportedException(); } // AsyncProcessRequest public Stream GetRequestStream(IMessage msg, ITransportHeaders headers) { // Currently, we require a memory stream be handed to us since we need // the length before sending. return null; } // GetRequestStream public IClientChannelSink NextChannelSink { get { return null; } } // Next private TcpClientSocketHandler SendRequestWithRetry(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream) { // If the stream is seekable, we can retry once on a failure to write. long initialPosition = 0; bool sendException = true; bool bCanSeek = requestStream.CanSeek; if (bCanSeek) initialPosition = requestStream.Position; TcpClientSocketHandler clientSocket = null; // Add the sid string only if the channel is secure. String machinePortAndSid = _machineAndPort + (_channel.IsSecured ? "/" + GetSid() : null); // The authentication config entries are only valid if secure is true if (authSet && !_channel.IsSecured) throw new RemotingException(CoreChannel.GetResourceString( "Remoting_Tcp_AuthenticationConfigClient")); // If explicitUserName is set but connectionGroupName isnt we will need to authenticate on each call bool openNewAlways = (_channel.IsSecured) && (_securityUserName != null) && (_connectionGroupName == null); try { clientSocket = (TcpClientSocketHandler)ClientSocketCache.GetSocket(machinePortAndSid, openNewAlways); clientSocket.SendRequest(msg, requestHeaders, requestStream); } catch (SocketException) { // Retry sending if socketexception occured, stream is seekable, retrycount times for(int count = 0; (count < _retryCount) && (bCanSeek && sendException); count++) { // retry sending if possible try { // reset position... requestStream.Position = initialPosition; // ...and try again. clientSocket = (TcpClientSocketHandler) ClientSocketCache.GetSocket(machinePortAndSid, openNewAlways); clientSocket.SendRequest(msg, requestHeaders, requestStream); sendException = false; } catch(SocketException) { } } if (sendException){ throw; } } requestStream.Close(); return clientSocket; } // SendRequestWithRetry private void ReceiveCallback(Object state) { TcpClientSocketHandler clientSocket = null; IClientChannelSinkStack sinkStack = null; try { clientSocket = (TcpClientSocketHandler)state; sinkStack = (IClientChannelSinkStack)clientSocket.DataArrivedCallbackState; ITransportHeaders responseHeaders = clientSocket.ReadHeaders(); Stream responseStream = clientSocket.GetResponseStream(); // call down the sink chain sinkStack.AsyncProcessResponse(responseHeaders, responseStream); } catch (Exception e) { try { if (sinkStack != null) sinkStack.DispatchException(e); } catch { // Fatal Error.. ignore } } // The client socket will be returned to the cache // when the response stream is closed. } // ReceiveCallback // // Properties // public override Object this[Object key] { get { String keyStr = key as String; if (keyStr == null) return null; switch (keyStr.ToLower(CultureInfo.InvariantCulture)) { case UserNameKey: return _securityUserName; case PasswordKey: return null; // Intentionally refuse to return password. case DomainKey: return _securityDomain; case SocketCacheTimeoutKey: return _socketCacheTimeout; case ReceiveTimeoutKey: return _receiveTimeout; case SocketCachePolicyKey: return _socketCachePolicy.ToString(); case RetryCountKey: return _retryCount; case ConnectionGroupNameKey: return _connectionGroupName; #if !FEATURE_PAL case TokenImpersonationLevelKey: if (authSet) return _tokenImpersonationLevel.ToString(); break; #endif // !FEATURE_PAL case ProtectionLevelKey: if (authSet) return _protectionLevel.ToString(); break; } // switch (keyStr.ToLower(CultureInfo.InvariantCulture)) return null; } set { String keyStr = key as String; if (keyStr == null) return; switch (keyStr.ToLower(CultureInfo.InvariantCulture)) { case UserNameKey: _securityUserName = (String)value; break; case PasswordKey: _securityPassword = (String)value; break; case DomainKey: _securityDomain = (String)value; break; case SocketCacheTimeoutKey: int timeout = Convert.ToInt32(value, CultureInfo.InvariantCulture); if (timeout < 0) throw new RemotingException( CoreChannel.GetResourceString( "Remoting_Tcp_SocketTimeoutNegative")); _socketCacheTimeout = TimeSpan.FromSeconds(timeout); ClientSocketCache.SocketTimeout = _socketCacheTimeout; break; case ReceiveTimeoutKey: _receiveTimeout = Convert.ToInt32(value, CultureInfo.InvariantCulture); ClientSocketCache.ReceiveTimeout = _receiveTimeout; break; case SocketCachePolicyKey: _socketCachePolicy = (SocketCachePolicy)(value is SocketCachePolicy ? value : Enum.Parse(typeof(SocketCachePolicy), (String)value, true)); ClientSocketCache.CachePolicy = _socketCachePolicy; break; case RetryCountKey: _retryCount = Convert.ToInt32(value, CultureInfo.InvariantCulture); break; case ConnectionGroupNameKey: _connectionGroupName = (String)value; break; #if !FEATURE_PAL case TokenImpersonationLevelKey: _tokenImpersonationLevel = (TokenImpersonationLevel)(value is TokenImpersonationLevel ? value : Enum.Parse(typeof(TokenImpersonationLevel), (String)value, true)); authSet = true; break; #endif // !FEATURE_PAL case ProtectionLevelKey: _protectionLevel = (ProtectionLevel)(value is ProtectionLevel ? value : Enum.Parse(typeof(ProtectionLevel), (String)value, true)); authSet = true; break; case SPNKey: _spn = (String)value; authSet = true; break; } // switch (keyStr.ToLower(CultureInfo.InvariantCulturey)) } } // this[] public override ICollection Keys { get { if (s_keySet == null) { // Don't need to synchronize. Doesn't matter if the list gets // generated twice. ArrayList keys = new ArrayList(6); keys.Add(UserNameKey); keys.Add(PasswordKey); keys.Add(DomainKey); keys.Add(SocketCacheTimeoutKey); keys.Add(SocketCachePolicyKey); keys.Add(RetryCountKey); #if !FEATURE_PAL keys.Add(TokenImpersonationLevelKey); #endif // !FEATURE_PAL keys.Add(ProtectionLevelKey); keys.Add(ConnectionGroupNameKey); keys.Add(ReceiveTimeoutKey); s_keySet = keys; } return s_keySet; } } // Keys // // end of Properties // } // class TcpClientTransportSink } // namespace namespace System.Runtime.Remoting.Channels.Tcp // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TemplateKey.cs
- EntityProviderServices.cs
- WebConfigurationManager.cs
- Int64Animation.cs
- ProjectionCamera.cs
- FixedSOMImage.cs
- DrawTreeNodeEventArgs.cs
- Int64KeyFrameCollection.cs
- ThreadExceptionEvent.cs
- VScrollBar.cs
- FloaterBaseParaClient.cs
- ButtonColumn.cs
- SmtpFailedRecipientException.cs
- AppSecurityManager.cs
- ISFClipboardData.cs
- SiteMapNodeItem.cs
- UInt32Converter.cs
- MailMessageEventArgs.cs
- wmiprovider.cs
- KnownTypeHelper.cs
- EndpointDispatcher.cs
- XmlSchemaFacet.cs
- InternalSafeNativeMethods.cs
- JournalEntryStack.cs
- MergablePropertyAttribute.cs
- MulticastNotSupportedException.cs
- EntityModelBuildProvider.cs
- ObjectListSelectEventArgs.cs
- OrderedDictionaryStateHelper.cs
- PeerHelpers.cs
- Metadata.cs
- Vector3dCollection.cs
- ThreadStaticAttribute.cs
- CultureInfoConverter.cs
- PenThreadWorker.cs
- PaperSource.cs
- DataBinding.cs
- SmtpLoginAuthenticationModule.cs
- XmlSiteMapProvider.cs
- PermissionSetEnumerator.cs
- HMACSHA1.cs
- BaseCollection.cs
- SafeEventLogWriteHandle.cs
- ThreadInterruptedException.cs
- ArgumentValueSerializer.cs
- FixedDSBuilder.cs
- TriggerActionCollection.cs
- XmlException.cs
- WebPartMenuStyle.cs
- ResXDataNode.cs
- NetTcpSecurityElement.cs
- SecurityCriticalDataForSet.cs
- WpfKnownType.cs
- MSHTMLHost.cs
- ListControlStringCollectionEditor.cs
- PropertyDescriptorCollection.cs
- WebPartManagerInternals.cs
- basenumberconverter.cs
- OdbcConnectionStringbuilder.cs
- CookieParameter.cs
- SqlCommandAsyncResult.cs
- RelationshipNavigation.cs
- XPathBuilder.cs
- RuntimeHandles.cs
- BitmapDecoder.cs
- HebrewCalendar.cs
- OutArgumentConverter.cs
- EntitySetDataBindingList.cs
- PieceDirectory.cs
- DataRowCollection.cs
- SchemaTableOptionalColumn.cs
- MarkupExtensionReturnTypeAttribute.cs
- ComponentCommands.cs
- ManipulationStartingEventArgs.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- ApplyHostConfigurationBehavior.cs
- OperationPickerDialog.designer.cs
- UnauthorizedWebPart.cs
- InternalConfigRoot.cs
- StylusEventArgs.cs
- GlobalEventManager.cs
- xml.cs
- PageAsyncTask.cs
- HuffModule.cs
- Label.cs
- AgileSafeNativeMemoryHandle.cs
- BmpBitmapEncoder.cs
- Cursors.cs
- AttachedPropertyMethodSelector.cs
- FilterElement.cs
- ComIntegrationManifestGenerator.cs
- WpfKnownMemberInvoker.cs
- UseManagedPresentationBindingElement.cs
- Package.cs
- IndexingContentUnit.cs
- XPathNavigatorReader.cs
- MD5CryptoServiceProvider.cs
- WizardStepBase.cs
- ValidatedControlConverter.cs
- LayoutTable.cs