Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / ManagedLibraries / Remoting / Channels / HTTP / HttpServerChannel.cs / 1305376 / HttpServerChannel.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //========================================================================== // File: HttpServerChannel.cs // // Summary: Implements a client channel that transmits method calls over HTTP. // // Classes: public HttpClientChannel // internal HttpClientTransportSink // //========================================================================= using System; using System.Collections; using System.IO; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Metadata; using System.Runtime.Remoting.MetadataServices; using System.Security.Cryptography.X509Certificates; using System.Security.Principal; using System.Text; using System.Threading; using System.Runtime.InteropServices; using System.Globalization; using System.Security.Permissions; namespace System.Runtime.Remoting.Channels.Http { public class HttpServerChannel : BaseChannelWithProperties, IChannelReceiver, IChannelReceiverHook { private int _channelPriority = 1; // priority of channel (default=1) private String _channelName = "http server"; // channel name private String _machineName = null; // machine name private int _port = -1; // port to listen on private ChannelDataStore _channelData = null; // channel data private String _forcedMachineName = null; // an explicitly configured machine name private bool _bUseIpAddress = true; // by default, we'll use the ip address. //Assumption is Socket.OSSupportsIPv4 will be false only on OS >= Vista with IPv4 turned off. private IPAddress _bindToAddr = (Socket.OSSupportsIPv4) ? IPAddress.Any : IPAddress.IPv6Any; // address to bind to. private bool _bSuppressChannelData = false; // should we hand out null for our channel data private IServerChannelSinkProvider _sinkProvider = null; private HttpServerTransportSink _transportSink = null; private IServerChannelSink _sinkChain = null; private bool _wantsToListen = true; private bool _bHooked = false; // has anyone hooked into the channel? private ExclusiveTcpListener _tcpListener; private bool _bExclusiveAddressUse = true; private Thread _listenerThread; private bool _bListening = false; // are we listening at the moment? private Exception _startListeningException = null; // if an exception happens on the listener thread when attempting // to start listening, that will get set here. private AutoResetEvent _waitForStartListening = new AutoResetEvent(false); public HttpServerChannel() : base() { SetupMachineName(); SetupChannel(); } public HttpServerChannel(int port) : base() { _port = port; SetupMachineName(); SetupChannel(); } // HttpServerChannel() public HttpServerChannel(String name, int port) : base() { _channelName = name; _port = port; SetupMachineName(); SetupChannel(); } // HttpServerChannel() public HttpServerChannel(String name, int port, IServerChannelSinkProvider sinkProvider) : base() { _channelName = name; _port = port; _sinkProvider = sinkProvider; SetupMachineName(); SetupChannel(); } // HttpServerChannel() public HttpServerChannel(IDictionary properties, IServerChannelSinkProvider sinkProvider) : base() { if (properties != null) { foreach (DictionaryEntry entry in properties) { switch ((String)entry.Key) { case "name": _channelName = (String)entry.Value; break; case "bindTo": _bindToAddr = IPAddress.Parse((String)entry.Value); break; case "listen": _wantsToListen = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture); break; case "machineName": _forcedMachineName = (String)entry.Value; break; case "port": _port = Convert.ToInt32(entry.Value, CultureInfo.InvariantCulture); break; case "priority": _channelPriority = Convert.ToInt32(entry.Value, CultureInfo.InvariantCulture); break; case "suppressChannelData": _bSuppressChannelData = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture); break; case "useIpAddress": _bUseIpAddress = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture); break; case "exclusiveAddressUse": _bExclusiveAddressUse = Convert.ToBoolean(entry.Value, CultureInfo.InvariantCulture); break; default: break; } } } _sinkProvider = sinkProvider; SetupMachineName(); SetupChannel(); } // HttpServerChannel internal bool IsSecured { get { return false; } set { if (_port >= 0 && value == true) throw new RemotingException(CoreChannel.GetResourceString("Remoting_Http_UseIISToSecureHttpServer")); } } private void SetupMachineName() { if (_forcedMachineName != null) { // an explicitly configured machine name was used _machineName = CoreChannel.DecodeMachineName(_forcedMachineName); } else { if (!_bUseIpAddress) _machineName = CoreChannel.GetMachineName(); else { if (_bindToAddr == IPAddress.Any || _bindToAddr == IPAddress.IPv6Any) { _machineName = CoreChannel.GetMachineIp(); } else { _machineName = _bindToAddr.ToString(); } // Add [] around the ipadress for IPv6 if (_bindToAddr.AddressFamily == AddressFamily.InterNetworkV6) _machineName = "[" + _machineName + "]"; } } } // SetupMachineName private void SetupChannel() { // set channel data // (These get changed inside of StartListening(), in the case where the listen // port is 0, because we can't determine the port number until after the // TcpListener starts.) _channelData = new ChannelDataStore(null); if (_port > 0) { String channelUri = GetChannelUri(); _channelData.ChannelUris = new String[1]; _channelData.ChannelUris[0] = channelUri; _wantsToListen = false; } // set default provider (soap formatter) if no provider has been set if (_sinkProvider == null) _sinkProvider = CreateDefaultServerProviderChain(); CoreChannel.CollectChannelDataFromServerSinkProviders(_channelData, _sinkProvider); // construct sink chain _sinkChain = ChannelServices.CreateServerChannelSinkChain(_sinkProvider, this); _transportSink = new HttpServerTransportSink(_sinkChain); // set sink properties on base class, so that properties will be chained. SinksWithProperties = _sinkChain; if (_port >= 0) { // Open a TCP port and create a thread to start listening _tcpListener = new ExclusiveTcpListener(_bindToAddr, _port); ThreadStart t = new ThreadStart(this.Listen); _listenerThread = new Thread(t); _listenerThread.IsBackground = true; // Wait for thread to spin up StartListening(null); } } // SetupChannel private IServerChannelSinkProvider CreateDefaultServerProviderChain() { IServerChannelSinkProvider chain = new SdlChannelSinkProvider(); IServerChannelSinkProvider sink = chain; sink.Next = new SoapServerFormatterSinkProvider(); sink = sink.Next; sink.Next = new BinaryServerFormatterSinkProvider(); return chain; } // CreateDefaultServerProviderChain // // 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 HttpChannelHelper.ParseURL(url, out objectURI); } // Parse // // end of IChannel implementation // // // IChannelReceiver implementation // public Object ChannelData { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] get { if (!_bSuppressChannelData && (_bListening || _bHooked)) { return _channelData; } else { return null; } } } // ChannelData public String GetChannelUri() { if ((_channelData != null) && (_channelData.ChannelUris != null)) { return _channelData.ChannelUris[0]; } else { return "http://" + _machineName + ":" + _port; } } // GetChannelURI [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] public virtual String[] GetUrlsForUri(String objectUri) { String[] retVal = new String[1]; if (!objectUri.StartsWith("/", StringComparison.Ordinal)) objectUri = "/" + objectUri; retVal[0] = GetChannelUri() + objectUri; return retVal; } // GetURLsforURI [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] public void StartListening(Object data) { InternalRemotingServices.RemotingTrace("HttpChannel.StartListening"); if (_port >= 0) { if (_listenerThread.IsAlive == false) { _listenerThread.Start(); _waitForStartListening.WaitOne(); // listener thread will signal this after starting TcpListener if (_startListeningException != null) { // An exception happened when we tried to start listening (such as "socket already in use) Exception e = _startListeningException; _startListeningException = null; throw e; } _bListening = true; // get new port assignment if a port of 0 was used to auto-select a port if (_port == 0) { _port = ((IPEndPoint)_tcpListener.LocalEndpoint).Port; if (_channelData != null) { String channelUri = GetChannelUri(); _channelData.ChannelUris = new String[1]; _channelData.ChannelUris[0] = channelUri; } } } } } // StartListening [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] public void StopListening(Object data) { InternalRemotingServices.RemotingTrace("HTTPChannel.StopListening"); if (_port > 0) { _bListening = false; // Ask the TCP listener to stop listening on the port if(null != _tcpListener) { _tcpListener.Stop(); } } } // StopListening // // end of IChannelReceiver implementation // // // IChannelReceiverHook implementation // public String ChannelScheme { [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] get { return "http"; } } public bool WantsToListen { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] get { return _wantsToListen; } set { _wantsToListen = value; } } // WantsToListen public IServerChannelSink ChannelSinkChain { [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] get { return _sinkChain; } } [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure, Infrastructure=true)] public void AddHookChannelUri(String channelUri) { if (_channelData.ChannelUris != null) { throw new RemotingException( CoreChannel.GetResourceString("Remoting_Http_LimitListenerOfOne")); } else { // replace machine name with explicitly configured // machine name or ip address if necessary if (_forcedMachineName != null) { channelUri = HttpChannelHelper.ReplaceMachineNameWithThisString(channelUri, _forcedMachineName); } else if (_bUseIpAddress) { channelUri = HttpChannelHelper.ReplaceMachineNameWithThisString(channelUri, CoreChannel.GetMachineIp()); } _channelData.ChannelUris = new String[] { channelUri }; _wantsToListen = false; _bHooked = true; } } // AddHookChannelUri // // end of IChannelReceiverHook implementation // // Thread for listening void Listen() { bool bOkToListen = false; try { _tcpListener.Start(_bExclusiveAddressUse); bOkToListen = true; } catch (Exception e) { _startListeningException = e; } _waitForStartListening.Set(); // allow main thread to continue now that we have tried to start the socket InternalRemotingServices.RemotingTrace( "Waiting to Accept the Socket on Port: " + _port); // // Wait for an incoming socket // Socket socket; while (bOkToListen) { InternalRemotingServices.RemotingTrace("TCPChannel::Listen - tcpListen.Pending() == true"); try { socket = _tcpListener.AcceptSocket(); if (socket == null) { throw new RemotingException( String.Format( CultureInfo.CurrentCulture, CoreChannel.GetResourceString("Remoting_Socket_Accept"), Marshal.GetLastWin32Error().ToString(CultureInfo.InvariantCulture))); } else { // disable nagle delay socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1); // Set keepalive flag, so that inactive sockets can be cleaned up socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1); // set linger option LingerOption lingerOption = new LingerOption(true, 3); socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption); Stream netStream = new SocketStream(socket); HttpServerSocketHandler streamManager = null; //Create the socket Handler streamManager = new HttpServerSocketHandler(socket, CoreChannel.RequestQueue, netStream); // @ streamManager.DataArrivedCallback = new WaitCallback(_transportSink.ServiceRequest); streamManager.BeginReadMessage(); } } catch (Exception e) { if (!_bListening) { // We called Stop() on the tcp listener, so gracefully exit. bOkToListen = false; } else { // we want the exception to show up as unhandled since this // is an unexpected failure. if (!(e is SocketException)) { // < } } } } // while (bOkToListen) } // // Support for properties (through BaseChannelWithProperties) // public override Object this[Object key] { get { return null; } set { } } // this[] public override ICollection Keys { get { return new ArrayList(); } } } // HttpServerChannel internal class HttpServerTransportSink : IServerChannelSink { private static String s_serverHeader = "MS .NET Remoting, MS .NET CLR " + System.Environment.Version.ToString(); // sink state private IServerChannelSink _nextSink; public HttpServerTransportSink(IServerChannelSink nextSink) { _nextSink = nextSink; } // IServerChannelSink internal void ServiceRequest(Object state) { HttpServerSocketHandler streamManager = (HttpServerSocketHandler)state; ITransportHeaders headers = streamManager.ReadHeaders(); Stream requestStream = streamManager.GetRequestStream(); headers["__CustomErrorsEnabled"] = streamManager.CustomErrorsEnabled(); // process request ServerChannelSinkStack sinkStack = new ServerChannelSinkStack(); sinkStack.Push(this, streamManager); IMessage responseMessage; ITransportHeaders responseHeaders; Stream responseStream; ServerProcessing processing = _nextSink.ProcessMessage(sinkStack, null, headers, requestStream, out responseMessage, out responseHeaders, out responseStream); // handle response switch (processing) { case ServerProcessing.Complete: { // Send the response. Call completed synchronously. sinkStack.Pop(this); streamManager.SendResponse(responseStream, "200", "OK", responseHeaders); break; } // case ServerProcessing.Complete case ServerProcessing.OneWay: { // Just send back a 200 OK streamManager.SendResponse(null, "202", "Accepted", responseHeaders); break; } // case ServerProcessing.OneWay case ServerProcessing.Async: { sinkStack.StoreAndDispatch(this, streamManager); break; }// case ServerProcessing.Async } // switch (processing) // async processing will take care if handling this later if (processing != ServerProcessing.Async) { if (streamManager.CanServiceAnotherRequest()) streamManager.BeginReadMessage(); else streamManager.Close(); } } // ServiceRequest // // IServerChannelSink implementation // public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream) { // NOTE: This doesn't have to be implemented because the server transport // sink is always first. throw new NotSupportedException(); } // ProcessMessage public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, Object state, IMessage msg, ITransportHeaders headers, Stream stream) { HttpServerSocketHandler streamManager = null; streamManager = (HttpServerSocketHandler)state; // send the response streamManager.SendResponse(stream, "200", "OK", headers); if (streamManager.CanServiceAnotherRequest()) streamManager.BeginReadMessage(); else streamManager.Close(); } // AsyncProcessResponse public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, Object state, IMessage msg, ITransportHeaders headers) { HttpServerSocketHandler streamManager = (HttpServerSocketHandler)state; if (streamManager.AllowChunkedResponse) return streamManager.GetResponseStream("200", "OK", headers); else return null; } // GetResponseStream public IServerChannelSink NextChannelSink { get { return _nextSink; } } public IDictionary Properties { get { return null; } } // Properties // // end of IServerChannelSink implementation // internal static String ServerHeader { get { return s_serverHeader; } } } // HttpServerTransportSink internal class ErrorMessage: IMethodCallMessage { // IMessage public IDictionary Properties { get{ return null;} } // IMethodMessage public String Uri { get{ return m_URI; } } public String MethodName { get{ return m_MethodName; }} public String TypeName { get{ return m_TypeName; } } public Object MethodSignature { get { return m_MethodSignature;} } public MethodBase MethodBase { get { return null; }} public int ArgCount { get { return m_ArgCount;} } public String GetArgName(int index) { return m_ArgName; } public Object GetArg(int argNum) { return null;} public Object[] Args { get { return null;} } public bool HasVarArgs { get { return false;} } public LogicalCallContext LogicalCallContext { get { return null; }} // IMethodCallMessage public int InArgCount { get { return m_ArgCount;} } public String GetInArgName(int index) { return null; } public Object GetInArg(int argNum) { return null;} public Object[] InArgs { get { return null; }} String m_URI = "Exception"; String m_MethodName = "Unknown"; String m_TypeName = "Unknown"; Object m_MethodSignature = null; int m_ArgCount = 0; String m_ArgName = "Unknown"; } // ErrorMessage } // namespace System.Runtime.Remoting.Channels.Http // 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
- HtmlTextArea.cs
- srgsitem.cs
- TripleDES.cs
- ClassGenerator.cs
- NamespaceList.cs
- XmlAutoDetectWriter.cs
- SoundPlayer.cs
- ToolStripDropDownClosedEventArgs.cs
- TemplateControl.cs
- TextEndOfSegment.cs
- FlowThrottle.cs
- PageAdapter.cs
- EventLogHandle.cs
- ObjectDataSource.cs
- ResourceSetExpression.cs
- InstallerTypeAttribute.cs
- DataGridHyperlinkColumn.cs
- MimeMapping.cs
- ConfigXmlElement.cs
- ReadOnlyCollection.cs
- CommandBinding.cs
- PagesChangedEventArgs.cs
- SystemGatewayIPAddressInformation.cs
- Deflater.cs
- HttpException.cs
- ProviderConnectionPoint.cs
- ListBindingConverter.cs
- TcpHostedTransportConfiguration.cs
- BufferedGraphics.cs
- Point3DCollectionConverter.cs
- XmlSchemaDatatype.cs
- TextEditorTables.cs
- PrePrepareMethodAttribute.cs
- PeerName.cs
- CqlWriter.cs
- DataControlFieldHeaderCell.cs
- BasicHttpBinding.cs
- FloaterParaClient.cs
- PersistChildrenAttribute.cs
- PointCollection.cs
- CodeCastExpression.cs
- XmlWrappingReader.cs
- ListViewItem.cs
- DataBinder.cs
- DefaultTextStoreTextComposition.cs
- RegionIterator.cs
- WebPartDisplayMode.cs
- AlphabeticalEnumConverter.cs
- CodeEntryPointMethod.cs
- MatrixTransform3D.cs
- ConfigXmlElement.cs
- ColorConverter.cs
- cookie.cs
- Screen.cs
- XmlCharType.cs
- XpsFilter.cs
- cookieexception.cs
- TabControlCancelEvent.cs
- BitmapEffectGroup.cs
- DescendantQuery.cs
- Bits.cs
- WebFormDesignerActionService.cs
- MasterPageBuildProvider.cs
- DynamicRenderer.cs
- TextBlock.cs
- RangeValueProviderWrapper.cs
- TempFiles.cs
- HttpBindingExtension.cs
- StrongNameMembershipCondition.cs
- SecurityManager.cs
- SymmetricAlgorithm.cs
- IsolationInterop.cs
- HttpResponseMessageProperty.cs
- Evidence.cs
- _ListenerAsyncResult.cs
- FormViewInsertedEventArgs.cs
- OutputCacheEntry.cs
- Base64Decoder.cs
- WebHeaderCollection.cs
- SQLBytesStorage.cs
- GridViewActionList.cs
- AspProxy.cs
- SignatureHelper.cs
- UpdateExpressionVisitor.cs
- ChangeTracker.cs
- Geometry.cs
- ClientScriptManagerWrapper.cs
- MD5CryptoServiceProvider.cs
- SymDocumentType.cs
- InteropBitmapSource.cs
- TraceLog.cs
- WorkflowViewElement.cs
- ContextMenuService.cs
- WindowsFont.cs
- ADRole.cs
- Compress.cs
- CssClassPropertyAttribute.cs
- MarginCollapsingState.cs
- Size3D.cs
- SqlDataSource.cs