开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务

上次写了一篇ASP.NET一个简易的WebServer,用控制台程序模拟IIS 托起web服务 看见有一朋友说在中文情况下返回乱码。我平时用的都是英文开发环境,即使涉及到中文也不是乱码,但是在公司中文的vs环境下也出现了乱码。一时半会不中的怎么解决。后来想起vs内嵌的那个服务器。。。。,于是乎拿来改写一下。

先说说几个帮助类吧,我们中的http协议中请求头都是以\r\n\r\n结束的 在请求头中每个指令都是以\r\n分隔的, ByteParser就是用来分隔请求类容,再把一行的内容装到ByteString里面,ByteString主要作用是把字节转为字符。而Messages只是返回一些默认消息。Host就像原先的WebServer一样用来处理请求,Request是实现SimpleWorkerRequest的,用来真正处理用户请求。Server就是用来封装Host的暴露给调用者。至于NtlmAuth类没怎么明白好像是处理身份认证之类的东东。。。

还是吧修改后的代码贴出来吧:

ByteParser.cs
namespace Microsoft.VisualStudio.WebHost
{
    using System;

    internal sealed class ByteParser
    {
        private byte[] _bytes;
        private int _pos;

        internal ByteParser(byte[] bytes)
        {
            this._bytes = bytes;
            this._pos = 0;
        }

        internal ByteString ReadLine()
        {
            ByteString str = null;
            for (int i = this._pos; i < this._bytes.Length; i++)
            {
                if (this._bytes[i] == 10)
                {
                    int length = i - this._pos;
                    if ((length > 0) && (this._bytes[i - 1] == 13))
                    {
                        length--;
                    }
                    str = new ByteString(this._bytes, this._pos, length);
                    this._pos = i + 1;
                    return str;
                }
            }
            if (this._pos < this._bytes.Length)
            {
                str = new ByteString(this._bytes, this._pos, this._bytes.Length - this._pos);
            }
            this._pos = this._bytes.Length;
            return str;
        }

        internal int CurrentOffset
        {
            get
            {
                return this._pos;
            }
        }
    }
}
ByteString.cs
namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Collections;
    using System.Reflection;
    using System.Text;

    internal sealed class ByteString
    {
        private byte[] _bytes;
        private int _length;
        private int _offset;

        public ByteString(byte[] bytes, int offset, int length)
        {
            this._bytes = bytes;
            if (((this._bytes != null) && (offset >= 0)) && ((length >= 0) && ((offset + length) <= this._bytes.Length)))
            {
                this._offset = offset;
                this._length = length;
            }
        }

        public byte[] GetBytes()
        {
            byte[] dst = new byte[this._length];
            if (this._length > 0)
            {
                Buffer.BlockCopy(this._bytes, this._offset, dst, 0, this._length);
            }
            return dst;
        }

        public string GetString()
        {
            return this.GetString(Encoding.UTF8);
        }

        public string GetString(Encoding enc)
        {
            if (this.IsEmpty)
            {
                return string.Empty;
            }
            return enc.GetString(this._bytes, this._offset, this._length);
        }

        public int IndexOf(char ch)
        {
            return this.IndexOf(ch, 0);
        }

        public int IndexOf(char ch, int offset)
        {
            for (int i = offset; i < this._length; i++)
            {
                if (this[i] == ((byte) ch))
                {
                    return i;
                }
            }
            return -1;
        }

        public ByteString[] Split(char sep)
        {
            ArrayList list = new ArrayList();
            int offset = 0;
            while (offset < this._length)
            {
                int index = this.IndexOf(sep, offset);
                if (index < 0)
                {
                    list.Add(this.Substring(offset));
                    break;
                }
                list.Add(this.Substring(offset, index - offset));
                for (offset = index + 1; (offset < this._length) && (this[offset] == ((byte) sep)); offset++)
                {
                }
            }
            int count = list.Count;
            ByteString[] strArray = new ByteString[count];
            for (int i = 0; i < count; i++)
            {
                strArray[i] = (ByteString) list[i];
            }
            return strArray;
        }

        public ByteString Substring(int offset)
        {
            return this.Substring(offset, this._length - offset);
        }

        public ByteString Substring(int offset, int len)
        {
            return new ByteString(this._bytes, this._offset + offset, len);
        }

        public byte[] Bytes
        {
            get
            {
                return this._bytes;
            }
        }

        public bool IsEmpty
        {
            get
            {
                if (this._bytes != null)
                {
                    return (this._length == 0);
                }
                return true;
            }
        }

        public byte this[int index]
        {
            get
            {
                return this._bytes[this._offset + index];
            }
        }

        public int Length
        {
            get
            {
                return this._length;
            }
        }

        public int Offset
        {
            get
            {
                return this._offset;
            }
        }
    }
}
Messages.cs
namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Globalization;
    using System.IO;
    using System.Text;
    using System.Web;

    internal class Messages
    {
        private const string _dirListingDirFormat = "{0,38:dddd, MMMM dd, yyyy hh:mm tt}        &lt;dir&gt; <A href=\"{1}/\">{2}</A>\r\n";
        private const string _dirListingFileFormat = "{0,38:dddd, MMMM dd, yyyy hh:mm tt} {1,12:n0} <A href=\"{2}\">{3}</A>\r\n";
        private const string _dirListingFormat1 = "<html>\r\n    <head>\r\n    <title>{0}</title>\r\n";
        private const string _dirListingFormat2 = "    </head>\r\n    <body bgcolor=\"white\">\r\n\r\n    <h2> <i>{0}</i> </h2></span>\r\n\r\n            <hr width=100% size=1 color=silver>\r\n\r\n<PRE>\r\n";
        private const string _dirListingParentFormat = "<A href=\"{0}\">[To Parent Directory]</A>\r\n\r\n";
        private static string _dirListingTail = ("</PRE>\r\n            <hr width=100% size=1 color=silver>\r\n\r\n              <b>{0}:</b>&nbsp;{1} " + VersionString + "\r\n\r\n            </font>\r\n\r\n    </body>\r\n</html>\r\n");
        private const string _httpErrorFormat1 = "<html>\r\n    <head>\r\n        <title>{0}</title>\r\n";
        private static string _httpErrorFormat2 = ("    </head>\r\n    <body bgcolor=\"white\">\r\n\r\n            <span><h1>{0}<hr width=100% size=1 color=silver></h1>\r\n\r\n            <h2> <i>{1}</i> </h2></span>\r\n\r\n            <hr width=100% size=1 color=silver>\r\n\r\n            <b>{2}:</b>&nbsp;{3} " + VersionString + "\r\n\r\n            </font>\r\n\r\n    </body>\r\n</html>\r\n");
        private const string _httpStyle = "        <style>\r\n        \tbody {font-family:\"Verdana\";font-weight:normal;font-size: 8pt;color:black;} \r\n        \tp {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}\r\n        \tb {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}\r\n        \th1 { font-family:\"Verdana\";font-weight:normal;font-size:18pt;color:red }\r\n        \th2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }\r\n        \tpre {font-family:\"Lucida Console\";font-size: 8pt}\r\n        \t.marker {font-weight: bold; color: black;text-decoration: none;}\r\n        \t.version {color: gray;}\r\n        \t.error {margin-bottom: 10px;}\r\n        \t.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }\r\n        </style>\r\n";
        public static string VersionString = GetVersionString();

        public static string FormatDirectoryListing(string dirPath, string parentPath, FileSystemInfo[] elements)
        {
            StringBuilder builder = new StringBuilder();
            string str = string.Format("Directory Listing -- {0}",  dirPath );
            string str2 = "Version Information";
            string str3 = "ASP.NET Development Server";
            string str4 = string.Format(CultureInfo.InvariantCulture, _dirListingTail, new object[] { str2, str3 });

            builder.Append(string.Format(CultureInfo.InvariantCulture, "<html>\r\n    <head>\r\n    <title>{0}</title>\r\n", new object[] { str }));
            builder.Append("        <style>\r\n        \tbody {font-family:\"Verdana\";font-weight:normal;font-size: 8pt;color:black;} \r\n        \tp {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}\r\n        \tb {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}\r\n        \th1 { font-family:\"Verdana\";font-weight:normal;font-size:18pt;color:red }\r\n        \th2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }\r\n        \tpre {font-family:\"Lucida Console\";font-size: 8pt}\r\n        \t.marker {font-weight: bold; color: black;text-decoration: none;}\r\n        \t.version {color: gray;}\r\n        \t.error {margin-bottom: 10px;}\r\n        \t.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }\r\n        </style>\r\n");
            builder.Append(string.Format(CultureInfo.InvariantCulture, "    </head>\r\n    <body bgcolor=\"white\">\r\n\r\n    <h2> <i>{0}</i> </h2></span>\r\n\r\n            <hr width=100% size=1 color=silver>\r\n\r\n<PRE>\r\n", new object[] { str }));
            if (parentPath != null)
            {
                if (!parentPath.EndsWith("/", StringComparison.Ordinal))
                {
                    parentPath = parentPath + "/";
                }
                builder.Append(string.Format(CultureInfo.InvariantCulture, "<A href=\"{0}\">[To Parent Directory]</A>\r\n\r\n", new object[] { parentPath }));
            }
            if (elements != null)
            {
                for (int i = 0; i < elements.Length; i++)
                {
                    if (elements[i] is FileInfo)
                    {
                        FileInfo info = (FileInfo) elements[i];
                        builder.Append(string.Format(CultureInfo.InvariantCulture, "{0,38:dddd, MMMM dd, yyyy hh:mm tt} {1,12:n0} <A href=\"{2}\">{3}</A>\r\n", new object[] { info.LastWriteTime, info.Length, info.Name, info.Name }));
                    }
                    else if (elements[i] is DirectoryInfo)
                    {
                        DirectoryInfo info2 = (DirectoryInfo) elements[i];
                        builder.Append(string.Format(CultureInfo.InvariantCulture, "{0,38:dddd, MMMM dd, yyyy hh:mm tt}        &lt;dir&gt; <A href=\"{1}/\">{2}</A>\r\n", new object[] { info2.LastWriteTime, info2.Name, info2.Name }));
                    }
                }
            }
            builder.Append(str4);
            return builder.ToString();
        }

        public static string FormatErrorMessageBody(int statusCode, string appName)
        {
            string statusDescription = HttpWorkerRequest.GetStatusDescription(statusCode);
            string str2 = string.Format("Server Error in '{0}' Application.", appName);
            string str3 = string.Format("HTTP Error {0} - {1}.", statusCode, statusDescription);
            string str4 = "Version Information";
            string str5 = "ASP.NET Development Server";
            return (string.Format(CultureInfo.InvariantCulture, "<html>\r\n    <head>\r\n        <title>{0}</title>\r\n", new object[] { statusDescription }) + "        <style>\r\n        \tbody {font-family:\"Verdana\";font-weight:normal;font-size: 8pt;color:black;} \r\n        \tp {font-family:\"Verdana\";font-weight:normal;color:black;margin-top: -5px}\r\n        \tb {font-family:\"Verdana\";font-weight:bold;color:black;margin-top: -5px}\r\n        \th1 { font-family:\"Verdana\";font-weight:normal;font-size:18pt;color:red }\r\n        \th2 { font-family:\"Verdana\";font-weight:normal;font-size:14pt;color:maroon }\r\n        \tpre {font-family:\"Lucida Console\";font-size: 8pt}\r\n        \t.marker {font-weight: bold; color: black;text-decoration: none;}\r\n        \t.version {color: gray;}\r\n        \t.error {margin-bottom: 10px;}\r\n        \t.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }\r\n        </style>\r\n" + string.Format(CultureInfo.InvariantCulture, _httpErrorFormat2, new object[] { str2, str3, str4, str5 }));
        }

        private static string GetVersionString()
        {
            return "10.0.0.0";
        }
    }
}
NtlmAuth.cs
namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Security.Principal;

    [SuppressUnmanagedCodeSecurity]
    internal sealed class NtlmAuth : IDisposable
    {
        private string _blob;
        private bool _completed;
        private SecHandle _credentialsHandle;
        private bool _credentialsHandleAcquired;
        private SecBuffer _inputBuffer;
        private SecBufferDesc _inputBufferDesc;
        private SecBuffer _outputBuffer;
        private SecBufferDesc _outputBufferDesc;
        private SecHandle _securityContext;
        private bool _securityContextAcquired;
        private uint _securityContextAttributes;
        private SecurityIdentifier _sid;
        private long _timestamp;
        private const int ISC_REQ_ALLOCATE_MEMORY = 0x100;
        private const int ISC_REQ_CONFIDENTIALITY = 0x10;
        private const int ISC_REQ_DELEGATE = 1;
        private const int ISC_REQ_MUTUAL_AUTH = 2;
        private const int ISC_REQ_PROMPT_FOR_CREDS = 0x40;
        private const int ISC_REQ_REPLAY_DETECT = 4;
        private const int ISC_REQ_SEQUENCE_DETECT = 8;
        private const int ISC_REQ_STANDARD_FLAGS = 20;
        private const int ISC_REQ_USE_SESSION_KEY = 0x20;
        private const int ISC_REQ_USE_SUPPLIED_CREDS = 0x80;
        private const int SEC_E_OK = 0;
        private const int SEC_I_COMPLETE_AND_CONTINUE = 0x90314;
        private const int SEC_I_COMPLETE_NEEDED = 0x90313;
        private const int SEC_I_CONTINUE_NEEDED = 0x90312;
        private const int SECBUFFER_DATA = 1;
        private const int SECBUFFER_EMPTY = 0;
        private const int SECBUFFER_TOKEN = 2;
        private const int SECBUFFER_VERSION = 0;
        private const int SECPKG_CRED_INBOUND = 1;
        private const int SECURITY_NETWORK_DREP = 0;

        public NtlmAuth()
        {
            if (AcquireCredentialsHandle(null, "NTLM", 1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref this._credentialsHandle, ref this._timestamp) != 0)
            {
                throw new InvalidOperationException();
            }
            this._credentialsHandleAcquired = true;
        }

        [DllImport("SECUR32.DLL", CharSet=CharSet.Unicode)]
        private static extern int AcceptSecurityContext(ref SecHandle phCredential, IntPtr phContext, ref SecBufferDesc pInput, uint fContextReq, uint TargetDataRep, ref SecHandle phNewContext, ref SecBufferDesc pOutput, ref uint pfContextAttr, ref long ptsTimeStamp);
        [DllImport("SECUR32.DLL", CharSet=CharSet.Unicode)]
        private static extern int AcquireCredentialsHandle(string pszPrincipal, string pszPackage, uint fCredentialUse, IntPtr pvLogonID, IntPtr pAuthData, IntPtr pGetKeyFn, IntPtr pvGetKeyArgument, ref SecHandle phCredential, ref long ptsExpiry);
        public unsafe bool Authenticate(string blobString)
        {
            this._blob = null;
            byte[] buffer = Convert.FromBase64String(blobString);
            byte[] inArray = new byte[0x4000];
            fixed (SecHandle* voidRef = &this._securityContext)
            {
                fixed (SecBuffer* voidRef2 = &this._inputBuffer)
                {
                    fixed (SecBuffer* voidRef3 = &this._outputBuffer)
                    {
                        fixed (void* voidRef4 = buffer)
                        {
                            fixed (void* voidRef5 = inArray)
                            {
                                IntPtr zero = IntPtr.Zero;
                                if (this._securityContextAcquired)
                                {
                                    zero = (IntPtr)voidRef;
                                }
                                this._inputBufferDesc.ulVersion = 0;
                                this._inputBufferDesc.cBuffers = 1;
                                this._inputBufferDesc.pBuffers = (IntPtr)voidRef2;
                                this._inputBuffer.cbBuffer = (uint)buffer.Length;
                                this._inputBuffer.BufferType = 2;
                                this._inputBuffer.pvBuffer = (IntPtr)voidRef4;
                                this._outputBufferDesc.ulVersion = 0;
                                this._outputBufferDesc.cBuffers = 1;
                                this._outputBufferDesc.pBuffers = (IntPtr)voidRef3;
                                this._outputBuffer.cbBuffer = (uint)inArray.Length;
                                this._outputBuffer.BufferType = 2;
                                this._outputBuffer.pvBuffer = (IntPtr)voidRef5;
                                int num = AcceptSecurityContext(ref this._credentialsHandle, zero, ref this._inputBufferDesc, 20, 0, ref this._securityContext, ref this._outputBufferDesc, ref this._securityContextAttributes, ref this._timestamp);
                                if (num == 0x90312)
                                {
                                    this._securityContextAcquired = true;
                                    this._blob = Convert.ToBase64String(inArray, 0, (int)this._outputBuffer.cbBuffer);
                                }
                                else
                                {
                                    if (num != 0)
                                    {
                                        return false;
                                    }
                                    IntPtr phToken = IntPtr.Zero;
                                    if (QuerySecurityContextToken(ref this._securityContext, ref phToken) != 0)
                                    {
                                        return false;
                                    }
                                    try
                                    {
                                        using (WindowsIdentity identity = new WindowsIdentity(phToken))
                                        {
                                            this._sid = identity.User;
                                        }
                                    }
                                    finally
                                    {
                                        CloseHandle(phToken);
                                    }
                                    this._completed = true;
                                }
                            }
                        }
                    }
                }
            }
            return true;
        }


        [DllImport("KERNEL32.DLL", CharSet=CharSet.Unicode)]
        private static extern int CloseHandle(IntPtr phToken);
        [DllImport("SECUR32.DLL", CharSet=CharSet.Unicode)]
        private static extern int DeleteSecurityContext(ref SecHandle phContext);
        ~NtlmAuth()
        {
            this.FreeUnmanagedResources();
        }

        [DllImport("SECUR32.DLL", CharSet=CharSet.Unicode)]
        private static extern int FreeCredentialsHandle(ref SecHandle phCredential);
        private void FreeUnmanagedResources()
        {
            if (this._securityContextAcquired)
            {
                DeleteSecurityContext(ref this._securityContext);
            }
            if (this._credentialsHandleAcquired)
            {
                FreeCredentialsHandle(ref this._credentialsHandle);
            }
        }

        [DllImport("SECUR32.DLL", CharSet=CharSet.Unicode)]
        private static extern int QuerySecurityContextToken(ref SecHandle phContext, ref IntPtr phToken);
        void IDisposable.Dispose()
        {
            this.FreeUnmanagedResources();
            GC.SuppressFinalize(this);
        }

        public string Blob
        {
            get
            {
                return this._blob;
            }
        }

        public bool Completed
        {
            get
            {
                return this._completed;
            }
        }

        public SecurityIdentifier SID
        {
            get
            {
                return this._sid;
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct SecBuffer
        {
            public uint cbBuffer;
            public uint BufferType;
            public IntPtr pvBuffer;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct SecBufferDesc
        {
            public uint ulVersion;
            public uint cBuffers;
            public IntPtr pBuffers;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct SecHandle
        {
            public IntPtr dwLower;
            public IntPtr dwUpper;
        }
    }
}
Host.cs
namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Security.Principal;
    using System.Threading;
    using System.Web;
    using System.Web.Hosting;

    internal sealed class Host : MarshalByRefObject, IRegisteredObject
    {
        private bool _disableDirectoryListing;
        private string _installPath;
        private string _lowerCasedClientScriptPathWithTrailingSlash;
        private string _lowerCasedVirtualPath;
        private string _lowerCasedVirtualPathWithTrailingSlash;
        //private volatile int _pendingCallsCount;
        private  int _pendingCallsCount;
        private string _physicalClientScriptPath;
        private string _physicalPath;
        private int _port;
        private bool _requireAuthentication;
        private Server _server;
        private string _virtualPath;

        public Host()
        {
            HostingEnvironment.RegisterObject(this);
        }

        private void AddPendingCall()
        {
            Interlocked.Increment(ref this._pendingCallsCount);
        }

        public void Configure(Server server, int port, string virtualPath, string physicalPath, bool requireAuthentication)
        {
            this.Configure(server, port, virtualPath, physicalPath, requireAuthentication, false);
        }

        public void Configure(Server server, int port, string virtualPath, string physicalPath, bool requireAuthentication, bool disableDirectoryListing)
        {
            this._server = server;
            this._port = port;
            this._installPath = null;
            this._virtualPath = virtualPath;
            this._requireAuthentication = requireAuthentication;
            this._disableDirectoryListing = disableDirectoryListing;
            this._lowerCasedVirtualPath = CultureInfo.InvariantCulture.TextInfo.ToLower(this._virtualPath);
            this._lowerCasedVirtualPathWithTrailingSlash = virtualPath.EndsWith("/", StringComparison.Ordinal) ? virtualPath : (virtualPath + "/");
            this._lowerCasedVirtualPathWithTrailingSlash = CultureInfo.InvariantCulture.TextInfo.ToLower(this._lowerCasedVirtualPathWithTrailingSlash);
            this._physicalPath = physicalPath;
            this._physicalClientScriptPath = HttpRuntime.AspClientScriptPhysicalPath + @"\";
            this._lowerCasedClientScriptPathWithTrailingSlash = CultureInfo.InvariantCulture.TextInfo.ToLower(HttpRuntime.AspClientScriptVirtualPath + "/");
        }

        public SecurityIdentifier GetProcessSID()
        {
            using (WindowsIdentity identity = new WindowsIdentity(this._server.GetProcessToken()))
            {
                return identity.User;
            }
        }

        public IntPtr GetProcessToken()
        {
            new SecurityPermission(PermissionState.Unrestricted).Assert();
            return this._server.GetProcessToken();
        }

        public string GetProcessUser()
        {
            return this._server.GetProcessUser();
        }

        public override object InitializeLifetimeService()
        {
            return null;
        }

        public bool IsVirtualPathAppPath(string path)
        {
            if (path == null)
            {
                return false;
            }
            path = CultureInfo.InvariantCulture.TextInfo.ToLower(path);
            if (!(path == this._lowerCasedVirtualPath))
            {
                return (path == this._lowerCasedVirtualPathWithTrailingSlash);
            }
            return true;
        }

        public bool IsVirtualPathInApp(string path)
        {
            bool flag;
            return this.IsVirtualPathInApp(path, out flag);
        }

        public bool IsVirtualPathInApp(string path, out bool isClientScriptPath)
        {
            isClientScriptPath = false;
            if (path != null)
            {
                path = CultureInfo.InvariantCulture.TextInfo.ToLower(path);
                if ((this._virtualPath == "/") && path.StartsWith("/", StringComparison.Ordinal))
                {
                    if (path.StartsWith(this._lowerCasedClientScriptPathWithTrailingSlash, StringComparison.Ordinal))
                    {
                        isClientScriptPath = true;
                    }
                    return true;
                }
                if (path.StartsWith(this._lowerCasedVirtualPathWithTrailingSlash, StringComparison.Ordinal))
                {
                    return true;
                }
                if (path == this._lowerCasedVirtualPath)
                {
                    return true;
                }
                if (path.StartsWith(this._lowerCasedClientScriptPathWithTrailingSlash, StringComparison.Ordinal))
                {
                    isClientScriptPath = true;
                    return true;
                }
            }
            return false;
        }

        public void ProcessRequest(Connection conn)
        {
            this.AddPendingCall();
            try
            {
                new Request(this, conn).Process();
            }
            finally
            {
                this.RemovePendingCall();
            }
        }

        private void RemovePendingCall()
        {
            Interlocked.Decrement(ref this._pendingCallsCount);
        }

        [SecurityPermission(SecurityAction.Assert, Unrestricted=true)]
        public void Shutdown()
        {
            HostingEnvironment.InitiateShutdown();
        }

        void IRegisteredObject.Stop(bool immediate)
        {
            if (this._server != null)
            {
                this._server.HostStopped();
            }
            this.WaitForPendingCallsToFinish();
            HostingEnvironment.UnregisterObject(this);
        }

        private void WaitForPendingCallsToFinish()
        {
            while (this._pendingCallsCount > 0)
            {
                Thread.Sleep(250);
            }
        }

        public bool DisableDirectoryListing
        {
            get
            {
                return this._disableDirectoryListing;
            }
        }

        public string InstallPath
        {
            get
            {
                return this._installPath;
            }
        }

        public string NormalizedClientScriptPath
        {
            get
            {
                return this._lowerCasedClientScriptPathWithTrailingSlash;
            }
        }

        public string NormalizedVirtualPath
        {
            get
            {
                return this._lowerCasedVirtualPathWithTrailingSlash;
            }
        }

        public string PhysicalClientScriptPath
        {
            get
            {
                return this._physicalClientScriptPath;
            }
        }

        public string PhysicalPath
        {
            get
            {
                return this._physicalPath;
            }
        }

        public int Port
        {
            get
            {
                return this._port;
            }
        }

        public bool RequireAuthentication
        {
            get
            {
                return this._requireAuthentication;
            }
        }

        public string VirtualPath
        {
            get
            {
                return this._virtualPath;
            }
        }
    }
}
Connection.cs
namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Globalization;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Web;

    internal sealed class Connection : MarshalByRefObject
    {
        private static string _defaultLoalhostIP;
        private static string _localServerIP;
        private Server _server;
        private Socket _socket;

        internal Connection(Server server, Socket socket)
        {
            this._server = server;
            this._socket = socket;
        }

        internal void Close()
        {
            try
            {
                this._socket.Shutdown(SocketShutdown.Both);
                this._socket.Close();
            }
            catch
            {
            }
            finally
            {
                this._socket = null;
            }
        }

        private string GetErrorResponseBody(int statusCode, string message)
        {
            string str = Messages.FormatErrorMessageBody(statusCode, this._server.VirtualPath);
            if ((message != null) && (message.Length > 0))
            {
                str = str + "\r\n<!--\r\n" + message + "\r\n-->";
            }
            return str;
        }

        public override object InitializeLifetimeService()
        {
            return null;
        }

        private static string MakeContentTypeHeader(string fileName)
        {
            string str = null;
            FileInfo info = new FileInfo(fileName);
            switch (info.Extension.ToLowerInvariant())
            {
                case ".bmp":
                    str = "image/bmp";
                    break;

                case ".css":
                    str = "text/css";
                    break;

                case ".gif":
                    str = "image/gif";
                    break;

                case ".ico":
                    str = "image/x-icon";
                    break;

                case ".htm":
                case ".html":
                    str = "text/html";
                    break;

                case ".jpe":
                case ".jpeg":
                case ".jpg":
                    str = "image/jpeg";
                    break;

                case ".js":
                    str = "application/x-javascript";
                    break;
            }
            if (str == null)
            {
                return null;
            }
            return ("Content-Type: " + str + "\r\n");
        }

        private static string MakeResponseHeaders(int statusCode, string moreHeaders, int contentLength, bool keepAlive)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(string.Concat(new object[] { "HTTP/1.1 ", statusCode, " ", HttpWorkerRequest.GetStatusDescription(statusCode), "\r\n" }));
            builder.Append("Server: ASP.NET Development Server/" + Messages.VersionString + "\r\n");
            builder.Append("Date: " + DateTime.Now.ToUniversalTime().ToString("R", DateTimeFormatInfo.InvariantInfo) + "\r\n");
            if (contentLength >= 0)
            {
                builder.Append("Content-Length: " + contentLength + "\r\n");
            }
            if (moreHeaders != null)
            {
                builder.Append(moreHeaders);
            }
            if (!keepAlive)
            {
                builder.Append("Connection: Close\r\n");
            }
            builder.Append("\r\n");
            return builder.ToString();
        }

        internal byte[] ReadRequestBytes(int maxBytes)
        {
            try
            {
                if (this.WaitForRequestBytes() == 0)
                {
                    return null;
                }
                int available = this._socket.Available;
                if (available > maxBytes)
                {
                    available = maxBytes;
                }
                int count = 0;
                byte[] buffer = new byte[available];
                if (available > 0)
                {
                    count = this._socket.Receive(buffer, 0, available, SocketFlags.None);
                }
                if (count < available)
                {
                    byte[] dst = new byte[count];
                    if (count > 0)
                    {
                        Buffer.BlockCopy(buffer, 0, dst, 0, count);
                    }
                    buffer = dst;
                }
                return buffer;
            }
            catch
            {
                return null;
            }
        }

        internal int WaitForRequestBytes()
        {
            int available = 0;
            try
            {
                if (this._socket.Available == 0)
                {
                    this._socket.Poll(0x186a0, SelectMode.SelectRead);
                    if ((this._socket.Available == 0) && this._socket.Connected)
                    {
                        this._socket.Poll(0x1c9c380, SelectMode.SelectRead);
                    }
                }
                available = this._socket.Available;
            }
            catch
            {
            }
            return available;
        }

        internal void Write100Continue()
        {
            this.WriteEntireResponseFromString(100, null, null, true);
        }

        internal void WriteBody(byte[] data, int offset, int length)
        {
            try
            {
                this._socket.Send(data, offset, length, SocketFlags.None);
            }
            catch (SocketException)
            {
            }
        }

        internal void WriteEntireResponseFromFile(string fileName, bool keepAlive)
        {
            if (!System.IO.File.Exists(fileName))
            {
                this.WriteErrorAndClose(0x194);
            }
            else
            {
                string moreHeaders = MakeContentTypeHeader(fileName);
                if (moreHeaders == null)
                {
                    this.WriteErrorAndClose(0x193);
                }
                else
                {
                    bool flag = false;
                    FileStream stream = null;
                    try
                    {
                        stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                        int length = (int) stream.Length;
                        byte[] buffer = new byte[length];
                        int contentLength = stream.Read(buffer, 0, length);
                        string s = MakeResponseHeaders(200, moreHeaders, contentLength, keepAlive);
                        this._socket.Send(Encoding.UTF8.GetBytes(s));
                        this._socket.Send(buffer, 0, contentLength, SocketFlags.None);
                        flag = true;
                    }
                    catch (SocketException)
                    {
                    }
                    finally
                    {
                        if (!keepAlive || !flag)
                        {
                            this.Close();
                        }
                        if (stream != null)
                        {
                            stream.Close();
                        }
                    }
                }
            }
        }

        internal void WriteEntireResponseFromString(int statusCode, string extraHeaders, string body, bool keepAlive)
        {
            try
            {
                int contentLength = (body != null) ? Encoding.UTF8.GetByteCount(body) : 0;
                string str = MakeResponseHeaders(statusCode, extraHeaders, contentLength, keepAlive);
                this._socket.Send(Encoding.UTF8.GetBytes(str + body));
            }
            catch (SocketException)
            {
            }
            finally
            {
                if (!keepAlive)
                {
                    this.Close();
                }
            }
        }

        internal void WriteErrorAndClose(int statusCode)
        {
            this.WriteErrorAndClose(statusCode, null);
        }

        internal void WriteErrorAndClose(int statusCode, string message)
        {
            this.WriteEntireResponseFromString(statusCode, "Content-type:text/html;charset=utf-8\r\n", this.GetErrorResponseBody(statusCode, message), false);
        }

        internal void WriteErrorWithExtraHeadersAndKeepAlive(int statusCode, string extraHeaders)
        {
            this.WriteEntireResponseFromString(statusCode, extraHeaders, this.GetErrorResponseBody(statusCode, null), true);
        }

        internal void WriteHeaders(int statusCode, string extraHeaders)
        {
            string s = MakeResponseHeaders(statusCode, extraHeaders, -1, false);
            try
            {
                this._socket.Send(Encoding.UTF8.GetBytes(s));
            }
            catch (SocketException)
            {
            }
        }

        internal bool Connected
        {
            get
            {
                return this._socket.Connected;
            }
        }

        private string DefaultLocalHostIP
        {
            get
            {
                if (string.IsNullOrEmpty(_defaultLoalhostIP))
                {
                    if (!Socket.OSSupportsIPv4 && Socket.OSSupportsIPv6)
                    {
                        _defaultLoalhostIP = "::1";
                    }
                    else
                    {
                        _defaultLoalhostIP = "127.0.0.1";
                    }
                }
                return _defaultLoalhostIP;
            }
        }

        internal bool IsLocal
        {
            get
            {
                string remoteIP = this.RemoteIP;
                if (string.IsNullOrEmpty(remoteIP))
                {
                    return false;
                }
                if ((!remoteIP.Equals("127.0.0.1") && !remoteIP.Equals("::1")) && !remoteIP.Equals("::ffff:127.0.0.1"))
                {
                    return LocalServerIP.Equals(remoteIP);
                }
                return true;
            }
        }

        internal string LocalIP
        {
            get
            {
                IPEndPoint localEndPoint = (IPEndPoint) this._socket.LocalEndPoint;
                if ((localEndPoint != null) && (localEndPoint.Address != null))
                {
                    return localEndPoint.Address.ToString();
                }
                return this.DefaultLocalHostIP;
            }
        }

        private static string LocalServerIP
        {
            get
            {
                if (_localServerIP == null)
                {
                    _localServerIP = Dns.GetHostEntry(Environment.MachineName).AddressList[0].ToString();
                }
                return _localServerIP;
            }
        }

        internal string RemoteIP
        {
            get
            {
                IPEndPoint remoteEndPoint = (IPEndPoint) this._socket.RemoteEndPoint;
                if ((remoteEndPoint != null) && (remoteEndPoint.Address != null))
                {
                    return remoteEndPoint.Address.ToString();
                }
                return "";
            }
        }
    }
}
Request.cs
namespace Microsoft.VisualStudio.WebHost
{
    using Microsoft.Win32.SafeHandles;
    using System;
    using System.Collections;
    using System.Globalization;
    using System.IO;
    using System.Security;
    using System.Security.Permissions;
    using System.Text;
    using System.Web;
    using System.Web.Hosting;

    internal sealed class Request : SimpleWorkerRequest
    {
        private string _allRawHeaders;
        private Connection _connection;
        private IStackWalk _connectionPermission;
        private int _contentLength;
        private int _endHeadersOffset;
        private string _filePath;
        private byte[] _headerBytes;
        private ArrayList _headerByteStrings;
        private bool _headersSent;
        private Host _host;
        private bool _isClientScriptPath;
        private string[] _knownRequestHeaders;
        private string _path;
        private string _pathInfo;
        private string _pathTranslated;
        private byte[] _preloadedContent;
        private int _preloadedContentLength;
        private string _prot;
        private string _queryString;
        private byte[] _queryStringBytes;
        private ArrayList _responseBodyBytes;
        private StringBuilder _responseHeadersBuilder;
        private int _responseStatus;
        private bool _specialCaseStaticFileHeaders;
        private int _startHeadersOffset;
        private string[][] _unknownRequestHeaders;
        private string _url;
        private string _verb;
        private static char[] badPathChars = new char[] { '%', '>', '<', ':', '\\' };
        private static string[] defaultFileNames = new string[] { "default.aspx", "default.htm", "default.html" };
        private static char[] IntToHex = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        private const int MaxChunkLength = 0x10000;
        private const int maxHeaderBytes = 0x8000;
        private static string[] restrictedDirs = new string[] { "/bin", "/app_browsers", "/app_code", "/app_data", "/app_localresources", "/app_globalresources", "/app_webreferences" };

        public Request(Host host, Connection connection) : base(string.Empty, string.Empty, null)
        {
            this._connectionPermission = new PermissionSet(PermissionState.Unrestricted);
            this._host = host;
            this._connection = connection;
        }

        public override void CloseConnection()
        {
            this._connectionPermission.Assert();
            this._connection.Close();
        }

        public override void EndOfRequest()
        {
        }

        public override void FlushResponse(bool finalFlush)
        {
            if ((((this._responseStatus != 0x194) || this._headersSent) || (!finalFlush || (this._verb != "GET"))) || !this.ProcessDirectoryListingRequest())
            {
                this._connectionPermission.Assert();
                if (!this._headersSent)
                {
                    this._connection.WriteHeaders(this._responseStatus, this._responseHeadersBuilder.ToString());
                    this._headersSent = true;
                }
                for (int i = 0; i < this._responseBodyBytes.Count; i++)
                {
                    byte[] data = (byte[]) this._responseBodyBytes[i];
                    this._connection.WriteBody(data, 0, data.Length);
                }
                this._responseBodyBytes = new ArrayList();
                if (finalFlush)
                {
                    this._connection.Close();
                }
            }
        }

        public override string GetAppPath()
        {
            return this._host.VirtualPath;
        }

        public override string GetAppPathTranslated()
        {
            return this._host.PhysicalPath;
        }

        public override string GetFilePath()
        {
            return this._filePath;
        }

        public override string GetFilePathTranslated()
        {
            return this._pathTranslated;
        }

        public override string GetHttpVerbName()
        {
            return this._verb;
        }

        public override string GetHttpVersion()
        {
            return this._prot;
        }

        public override string GetKnownRequestHeader(int index)
        {
            return this._knownRequestHeaders[index];
        }

        public override string GetLocalAddress()
        {
            this._connectionPermission.Assert();
            return this._connection.LocalIP;
        }

        public override int GetLocalPort()
        {
            return this._host.Port;
        }

        public override string GetPathInfo()
        {
            return this._pathInfo;
        }

        public override byte[] GetPreloadedEntityBody()
        {
            return this._preloadedContent;
        }

        public override string GetQueryString()
        {
            return this._queryString;
        }

        public override byte[] GetQueryStringRawBytes()
        {
            return this._queryStringBytes;
        }

        public override string GetRawUrl()
        {
            return this._url;
        }

        public override string GetRemoteAddress()
        {
            this._connectionPermission.Assert();
            return this._connection.RemoteIP;
        }

        public override int GetRemotePort()
        {
            return 0;
        }

        public override string GetServerName()
        {
            string localAddress = this.GetLocalAddress();
            if ((!localAddress.Equals("127.0.0.1") && !localAddress.Equals("::1")) && !localAddress.Equals("::ffff:127.0.0.1"))
            {
                return localAddress;
            }
            return "localhost";
        }

        public override string GetServerVariable(string name)
        {
            string processUser = string.Empty;
            string str2 = name;
            if (str2 == null)
            {
                return processUser;
            }
            if (!(str2 == "ALL_RAW"))
            {
                if (str2 != "SERVER_PROTOCOL")
                {
                    if (str2 == "LOGON_USER")
                    {
                        if (this.GetUserToken() != IntPtr.Zero)
                        {
                            processUser = this._host.GetProcessUser();
                        }
                        return processUser;
                    }
                    if ((str2 == "AUTH_TYPE") && (this.GetUserToken() != IntPtr.Zero))
                    {
                        processUser = "NTLM";
                    }
                    return processUser;
                }
            }
            else
            {
                return this._allRawHeaders;
            }
            return this._prot;
        }

        public override string GetUnknownRequestHeader(string name)
        {
            int length = this._unknownRequestHeaders.Length;
            for (int i = 0; i < length; i++)
            {
                if (string.Compare(name, this._unknownRequestHeaders[i][0], StringComparison.OrdinalIgnoreCase) == 0)
                {
                    return this._unknownRequestHeaders[i][1];
                }
            }
            return null;
        }

        public override string[][] GetUnknownRequestHeaders()
        {
            return this._unknownRequestHeaders;
        }

        public override string GetUriPath()
        {
            return this._path;
        }

        public override IntPtr GetUserToken()
        {
            return this._host.GetProcessToken();
        }

        public override bool HeadersSent()
        {
            return this._headersSent;
        }

        private bool IsBadPath()
        {
            return ((this._path.IndexOfAny(badPathChars) >= 0) || ((CultureInfo.InvariantCulture.CompareInfo.IndexOf(this._path, "..", CompareOptions.Ordinal) >= 0) || (CultureInfo.InvariantCulture.CompareInfo.IndexOf(this._path, "//", CompareOptions.Ordinal) >= 0)));
        }

        public override bool IsClientConnected()
        {
            this._connectionPermission.Assert();
            return this._connection.Connected;
        }

        public override bool IsEntireEntityBodyIsPreloaded()
        {
            return (this._contentLength == this._preloadedContentLength);
        }

        private bool IsRequestForRestrictedDirectory()
        {
            string str = CultureInfo.InvariantCulture.TextInfo.ToLower(this._path);
            if (this._host.VirtualPath != "/")
            {
                str = str.Substring(this._host.VirtualPath.Length);
            }
            foreach (string str2 in restrictedDirs)
            {
                if (str.StartsWith(str2, StringComparison.Ordinal) && ((str.Length == str2.Length) || (str[str2.Length] == '/')))
                {
                    return true;
                }
            }
            return false;
        }

        public override string MapPath(string path)
        {
            string physicalPath = string.Empty;
            bool isClientScriptPath = false;
            if (((path == null) || (path.Length == 0)) || path.Equals("/"))
            {
                if (this._host.VirtualPath == "/")
                {
                    physicalPath = this._host.PhysicalPath;
                }
                else
                {
                    physicalPath = Environment.SystemDirectory;
                }
            }
            else if (this._host.IsVirtualPathAppPath(path))
            {
                physicalPath = this._host.PhysicalPath;
            }
            else if (this._host.IsVirtualPathInApp(path, out isClientScriptPath))
            {
                if (isClientScriptPath)
                {
                    physicalPath = this._host.PhysicalClientScriptPath + path.Substring(this._host.NormalizedClientScriptPath.Length);
                }
                else
                {
                    physicalPath = this._host.PhysicalPath + path.Substring(this._host.NormalizedVirtualPath.Length);
                }
            }
            else if (path.StartsWith("/", StringComparison.Ordinal))
            {
                physicalPath = this._host.PhysicalPath + path.Substring(1);
            }
            else
            {
                physicalPath = this._host.PhysicalPath + path;
            }
            physicalPath = physicalPath.Replace('/', '\\');
            if (physicalPath.EndsWith(@"\", StringComparison.Ordinal) && !physicalPath.EndsWith(@":\", StringComparison.Ordinal))
            {
                physicalPath = physicalPath.Substring(0, physicalPath.Length - 1);
            }
            return physicalPath;
        }

        private void ParseHeaders()
        {
            this._knownRequestHeaders = new string[40];
            ArrayList list = new ArrayList();
            for (int i = 1; i < this._headerByteStrings.Count; i++)
            {
                string str = ((ByteString) this._headerByteStrings[i]).GetString();
                int index = str.IndexOf(':');
                if (index >= 0)
                {
                    string header = str.Substring(0, index).Trim();
                    string str3 = str.Substring(index + 1).Trim();
                    int knownRequestHeaderIndex = HttpWorkerRequest.GetKnownRequestHeaderIndex(header);
                    if (knownRequestHeaderIndex >= 0)
                    {
                        this._knownRequestHeaders[knownRequestHeaderIndex] = str3;
                    }
                    else
                    {
                        list.Add(header);
                        list.Add(str3);
                    }
                }
            }
            int num4 = list.Count / 2;
            this._unknownRequestHeaders = new string[num4][];
            int num5 = 0;
            for (int j = 0; j < num4; j++)
            {
                this._unknownRequestHeaders[j] = new string[] { (string) list[num5++], (string) list[num5++] };
            }
            if (this._headerByteStrings.Count > 1)
            {
                this._allRawHeaders = Encoding.UTF8.GetString(this._headerBytes, this._startHeadersOffset, this._endHeadersOffset - this._startHeadersOffset);
            }
            else
            {
                this._allRawHeaders = string.Empty;
            }
        }

        private void ParsePostedContent()
        {
            this._contentLength = 0;
            this._preloadedContentLength = 0;
            string s = this._knownRequestHeaders[11];
            if (s != null)
            {
                try
                {
                    this._contentLength = int.Parse(s, CultureInfo.InvariantCulture);
                }
                catch
                {
                }
            }
            if (this._headerBytes.Length > this._endHeadersOffset)
            {
                this._preloadedContentLength = this._headerBytes.Length - this._endHeadersOffset;
                if (this._preloadedContentLength > this._contentLength)
                {
                    this._preloadedContentLength = this._contentLength;
                }
                if (this._preloadedContentLength > 0)
                {
                    this._preloadedContent = new byte[this._preloadedContentLength];
                    Buffer.BlockCopy(this._headerBytes, this._endHeadersOffset, this._preloadedContent, 0, this._preloadedContentLength);
                }
            }
        }

        private void ParseRequestLine()
        {
            ByteString[] strArray = ((ByteString) this._headerByteStrings[0]).Split(' ');
            if (((strArray == null) || (strArray.Length < 2)) || (strArray.Length > 3))
            {
                this._connection.WriteErrorAndClose(400);
            }
            else
            {
                this._verb = strArray[0].GetString();
                ByteString str2 = strArray[1];
                this._url = str2.GetString();
                if (this._url.IndexOf((char)0xfffd) >= 0)
                {
                    this._url = str2.GetString(Encoding.Default);
                }
                if (strArray.Length == 3)
                {
                    this._prot = strArray[2].GetString();
                }
                else
                {
                    this._prot = "HTTP/1.0";
                }
                int index = str2.IndexOf('?');
                if (index > 0)
                {
                    this._queryStringBytes = str2.Substring(index + 1).GetBytes();
                }
                else
                {
                    this._queryStringBytes = new byte[0];
                }
                index = this._url.IndexOf('?');
                if (index > 0)
                {
                    this._path = this._url.Substring(0, index);
                    this._queryString = this._url.Substring(index + 1);
                }
                else
                {
                    this._path = this._url;
                    this._queryString = string.Empty;
                }
                if (this._path.IndexOf('%') >= 0)
                {
                    this._path = HttpUtility.UrlDecode(this._path, Encoding.UTF8);
                    index = this._url.IndexOf('?');
                    if (index >= 0)
                    {
                        this._url = this._path + this._url.Substring(index);
                    }
                    else
                    {
                        this._url = this._path;
                    }
                }
                int startIndex = this._path.LastIndexOf('.');
                int num3 = this._path.LastIndexOf('/');
                if (((startIndex >= 0) && (num3 >= 0)) && (startIndex < num3))
                {
                    int length = this._path.IndexOf('/', startIndex);
                    this._filePath = this._path.Substring(0, length);
                    this._pathInfo = this._path.Substring(length);
                }
                else
                {
                    this._filePath = this._path;
                    this._pathInfo = string.Empty;
                }
                this._pathTranslated = this.MapPath(this._filePath);
            }
        }

        private void PrepareResponse()
        {
            this._headersSent = false;
            this._responseStatus = 200;
            this._responseHeadersBuilder = new StringBuilder();
            this._responseBodyBytes = new ArrayList();
        }

        [AspNetHostingPermission(SecurityAction.Assert, Level=AspNetHostingPermissionLevel.Medium)]
        public void Process()
        {
            if (this.TryParseRequest())
            {
                if (((this._verb == "POST") && (this._contentLength > 0)) && (this._preloadedContentLength < this._contentLength))
                {
                    this._connection.Write100Continue();
                }
                if (!this._host.RequireAuthentication || this.TryNtlmAuthenticate())
                {
                    if (this._isClientScriptPath)
                    {
                        this._connection.WriteEntireResponseFromFile(this._host.PhysicalClientScriptPath + this._path.Substring(this._host.NormalizedClientScriptPath.Length), false);
                    }
                    else if (this.IsRequestForRestrictedDirectory())
                    {
                        this._connection.WriteErrorAndClose(0x193);
                    }
                    else if (!this.ProcessDefaultDocumentRequest())
                    {
                        this.PrepareResponse();
                        HttpRuntime.ProcessRequest(this);
                    }
                }
            }
        }

        private bool ProcessDefaultDocumentRequest()
        {
            if (this._verb == "GET")
            {
                string path = this._pathTranslated;
                if (this._pathInfo.Length > 0)
                {
                    path = this.MapPath(this._path);
                }
                if (!Directory.Exists(path))
                {
                    return false;
                }
                if (!this._path.EndsWith("/", StringComparison.Ordinal))
                {
                    string str2 = this._path + "/";
                    string extraHeaders = "Location: " + UrlEncodeRedirect(str2) + "\r\n";
                    string body = "<html><head><title>Object moved</title></head><body>\r\n<h2>Object moved to <a href='" + str2 + "'>here</a>.</h2>\r\n</body></html>\r\n";
                    this._connection.WriteEntireResponseFromString(0x12e, extraHeaders, body, false);
                    return true;
                }
                foreach (string str5 in defaultFileNames)
                {
                    string str6 = path + @"\" + str5;
                    if (File.Exists(str6))
                    {
                        this._path = this._path + str5;
                        this._filePath = this._path;
                        this._url = (this._queryString != null) ? (this._path + "?" + this._queryString) : this._path;
                        this._pathTranslated = str6;
                        return false;
                    }
                }
            }
            return false;
        }

        private bool ProcessDirectoryListingRequest()
        {
            if (this._verb != "GET")
            {
                return false;
            }
            string path = this._pathTranslated;
            if (this._pathInfo.Length > 0)
            {
                path = this.MapPath(this._path);
            }
            if (!Directory.Exists(path))
            {
                return false;
            }
            if (this._host.DisableDirectoryListing)
            {
                return false;
            }
            FileSystemInfo[] elements = null;
            try
            {
                elements = new DirectoryInfo(path).GetFileSystemInfos();
            }
            catch
            {
            }
            string str2 = null;
            if (this._path.Length > 1)
            {
                int length = this._path.LastIndexOf('/', this._path.Length - 2);
                str2 = (length > 0) ? this._path.Substring(0, length) : "/";
                if (!this._host.IsVirtualPathInApp(str2))
                {
                    str2 = null;
                }
            }
            this._connection.WriteEntireResponseFromString(200, "Content-type: text/html; charset=utf-8\r\n", Messages.FormatDirectoryListing(this._path, str2, elements), false);
            return true;
        }

        private void ReadAllHeaders()
        {
            this._headerBytes = null;
            do
            {
                if (!this.TryReadAllHeaders())
                {
                    return;
                }
            }
            while (this._endHeadersOffset < 0);
        }

        public override int ReadEntityBody(byte[] buffer, int size)
        {
            int count = 0;
            this._connectionPermission.Assert();
            byte[] src = this._connection.ReadRequestBytes(size);
            if ((src != null) && (src.Length > 0))
            {
                count = src.Length;
                Buffer.BlockCopy(src, 0, buffer, 0, count);
            }
            return count;
        }

        private void Reset()
        {
            this._headerBytes = null;
            this._startHeadersOffset = 0;
            this._endHeadersOffset = 0;
            this._headerByteStrings = null;
            this._isClientScriptPath = false;
            this._verb = null;
            this._url = null;
            this._prot = null;
            this._path = null;
            this._filePath = null;
            this._pathInfo = null;
            this._pathTranslated = null;
            this._queryString = null;
            this._queryStringBytes = null;
            this._contentLength = 0;
            this._preloadedContentLength = 0;
            this._preloadedContent = null;
            this._allRawHeaders = null;
            this._unknownRequestHeaders = null;
            this._knownRequestHeaders = null;
            this._specialCaseStaticFileHeaders = false;
        }

        public override void SendCalculatedContentLength(int contentLength)
        {
            if (!this._headersSent)
            {
                this._responseHeadersBuilder.Append("Content-Length: ");
                this._responseHeadersBuilder.Append(contentLength.ToString(CultureInfo.InvariantCulture));
                this._responseHeadersBuilder.Append("\r\n");
            }
        }

        public override void SendKnownResponseHeader(int index, string value)
        {
            if (!this._headersSent)
            {
                switch (index)
                {
                    case 1:
                    case 2:
                    case 0x1a:
                        return;

                    case 0x12:
                    case 0x13:
                        if (!this._specialCaseStaticFileHeaders)
                        {
                            break;
                        }
                        return;

                    case 20:
                        if (!(value == "bytes"))
                        {
                            break;
                        }
                        this._specialCaseStaticFileHeaders = true;
                        return;
                }
                this._responseHeadersBuilder.Append(HttpWorkerRequest.GetKnownResponseHeaderName(index));
                this._responseHeadersBuilder.Append(": ");
                this._responseHeadersBuilder.Append(value);
                this._responseHeadersBuilder.Append("\r\n");
            }
        }

        public override void SendResponseFromFile(IntPtr handle, long offset, long length)
        {
            if (length != 0)
            {
                FileStream f = null;
                try
                {
                    SafeFileHandle handle2 = new SafeFileHandle(handle, false);
                    f = new FileStream(handle2, FileAccess.Read);
                    this.SendResponseFromFileStream(f, offset, length);
                }
                finally
                {
                    if (f != null)
                    {
                        f.Close();
                        f = null;
                    }
                }
            }
        }

        public override void SendResponseFromFile(string filename, long offset, long length)
        {
            if (length != 0)
            {
                FileStream f = null;
                try
                {
                    f = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
                    this.SendResponseFromFileStream(f, offset, length);
                }
                finally
                {
                    if (f != null)
                    {
                        f.Close();
                    }
                }
            }
        }

        private void SendResponseFromFileStream(FileStream f, long offset, long length)
        {
            long num = f.Length;
            if (length == -1)
            {
                length = num - offset;
            }
            if (((length != 0) && (offset >= 0)) && (length <= (num - offset)))
            {
                if (offset > 0)
                {
                    f.Seek(offset, SeekOrigin.Begin);
                }
                if (length <= 0x10000)
                {
                    byte[] buffer = new byte[(int) length];
                    int num2 = f.Read(buffer, 0, (int) length);
                    this.SendResponseFromMemory(buffer, num2);
                }
                else
                {
                    byte[] buffer2 = new byte[0x10000];
                    int num3 = (int) length;
                    while (num3 > 0)
                    {
                        int count = (num3 < 0x10000) ? num3 : 0x10000;
                        int num5 = f.Read(buffer2, 0, count);
                        this.SendResponseFromMemory(buffer2, num5);
                        num3 -= num5;
                        if ((num3 > 0) && (num5 > 0))
                        {
                            this.FlushResponse(false);
                        }
                    }
                }
            }
        }

        public override void SendResponseFromMemory(byte[] data, int length)
        {
            if (length > 0)
            {
                byte[] dst = new byte[length];
                Buffer.BlockCopy(data, 0, dst, 0, length);
                this._responseBodyBytes.Add(dst);
            }
        }

        public override void SendStatus(int statusCode, string statusDescription)
        {
            this._responseStatus = statusCode;
        }

        public override void SendUnknownResponseHeader(string name, string value)
        {
            if (!this._headersSent)
            {
                this._responseHeadersBuilder.Append(name);
                this._responseHeadersBuilder.Append(": ");
                this._responseHeadersBuilder.Append(value);
                this._responseHeadersBuilder.Append("\r\n");
            }
        }

        private void SkipAllPostedContent()
        {
            if ((this._contentLength > 0) && (this._preloadedContentLength < this._contentLength))
            {
                byte[] buffer;
                for (int i = this._contentLength - this._preloadedContentLength; i > 0; i -= buffer.Length)
                {
                    buffer = this._connection.ReadRequestBytes(i);
                    if ((buffer == null) || (buffer.Length == 0))
                    {
                        return;
                    }
                }
            }
        }

        [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true), SecurityPermission(SecurityAction.Assert, ControlPrincipal=true)]
        private bool TryNtlmAuthenticate()
        {
            try
            {
                using (NtlmAuth auth = new NtlmAuth())
                {
                    do
                    {
                        string blobString = null;
                        string extraHeaders = this._knownRequestHeaders[0x18];
                        if ((extraHeaders != null) && extraHeaders.StartsWith("NTLM ", StringComparison.Ordinal))
                        {
                            blobString = extraHeaders.Substring(5);
                        }
                        if (blobString != null)
                        {
                            if (!auth.Authenticate(blobString))
                            {
                                this._connection.WriteErrorAndClose(0x193);
                                return false;
                            }
                            if (auth.Completed)
                            {
                                goto Label_009A;
                            }
                            extraHeaders = "WWW-Authenticate: NTLM " + auth.Blob + "\r\n";
                        }
                        else
                        {
                            extraHeaders = "WWW-Authenticate: NTLM\r\n";
                        }
                        this.SkipAllPostedContent();
                        this._connection.WriteErrorWithExtraHeadersAndKeepAlive(0x191, extraHeaders);
                    }
                    while (this.TryParseRequest());
                    return false;
                Label_009A:
                    if (this._host.GetProcessSID() != auth.SID)
                    {
                        this._connection.WriteErrorAndClose(0x193);
                        return false;
                    }
                }
            }
            catch
            {
                try
                {
                    this._connection.WriteErrorAndClose(500);
                }
                catch
                {
                }
                return false;
            }
            return true;
        }

        private bool TryParseRequest()
        {
            this.Reset();
            this.ReadAllHeaders();
            //if (!this._connection.IsLocal)
            //{
            //    this._connection.WriteErrorAndClose(0x193);
            //    return false;
            //}
            if (((this._headerBytes == null) || (this._endHeadersOffset < 0)) || ((this._headerByteStrings == null) || (this._headerByteStrings.Count == 0)))
            {
                this._connection.WriteErrorAndClose(400);
                return false;
            }
            this.ParseRequestLine();
            if (this.IsBadPath())
            {
                this._connection.WriteErrorAndClose(400);
                return false;
            }
            if (!this._host.IsVirtualPathInApp(this._path, out this._isClientScriptPath))
            {
                this._connection.WriteErrorAndClose(0x194);
                return false;
            }
            this.ParseHeaders();
            this.ParsePostedContent();
            return true;
        }

        private bool TryReadAllHeaders()
        {
            byte[] src = this._connection.ReadRequestBytes(0x8000);
            if ((src == null) || (src.Length == 0))
            {
                return false;
            }
            if (this._headerBytes != null)
            {
                int num = src.Length + this._headerBytes.Length;
                if (num > 0x8000)
                {
                    return false;
                }
                byte[] dst = new byte[num];
                Buffer.BlockCopy(this._headerBytes, 0, dst, 0, this._headerBytes.Length);
                Buffer.BlockCopy(src, 0, dst, this._headerBytes.Length, src.Length);
                this._headerBytes = dst;
            }
            else
            {
                this._headerBytes = src;
            }
            this._startHeadersOffset = -1;
            this._endHeadersOffset = -1;
            this._headerByteStrings = new ArrayList();
            ByteParser parser = new ByteParser(this._headerBytes);
            while (true)
            {
                ByteString str = parser.ReadLine();
                if (str == null)
                {
                    break;
                }
                if (this._startHeadersOffset < 0)
                {
                    this._startHeadersOffset = parser.CurrentOffset;
                }
                if (str.IsEmpty)
                {
                    this._endHeadersOffset = parser.CurrentOffset;
                    break;
                }
                this._headerByteStrings.Add(str);
            }
            return true;
        }

        private static string UrlEncodeRedirect(string path)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(path);
            int length = bytes.Length;
            int num2 = 0;
            for (int i = 0; i < length; i++)
            {
                if ((bytes[i] & 0x80) != 0)
                {
                    num2++;
                }
            }
            if (num2 > 0)
            {
                byte[] buffer2 = new byte[length + (num2 * 2)];
                int num4 = 0;
                for (int j = 0; j < length; j++)
                {
                    byte num6 = bytes[j];
                    if ((num6 & 0x80) == 0)
                    {
                        buffer2[num4++] = num6;
                    }
                    else
                    {
                        buffer2[num4++] = 0x25;
                        buffer2[num4++] = (byte) IntToHex[(num6 >> 4) & 15];
                        buffer2[num4++] = (byte) IntToHex[num6 & 15];
                    }
                }
                path = Encoding.ASCII.GetString(buffer2);
            }
            if (path.IndexOf(' ') >= 0)
            {
                path = path.Replace(" ", "%20");
            }
            return path;
        }
    }
}
Server.cs
namespace Microsoft.VisualStudio.WebHost
{
    using System;
    using System.Globalization;
    using System.Net;
    using System.Net.Sockets;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Security.Principal;
    using System.Threading;
    using System.Web.Hosting;
    using System.Web;
    using System.Reflection;

    [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust"), PermissionSet(SecurityAction.LinkDemand, Name = "Everything")]
    public class Server : MarshalByRefObject
    {
        private ApplicationManager _appManager;
        private bool _disableDirectoryListing;
        private Host _host;
        private object _lockObject;
        private WaitCallback _onSocketAccept;
        private WaitCallback _onStart;
        private string _physicalPath;
        private int _port;
        private IntPtr _processToken;
        private string _processUser;
        private bool _requireAuthentication;
        private bool _shutdownInProgress;
        private Socket _socketIpv4;
        private Socket _socketIpv6;
        private string _virtualPath;
        private const int SecurityImpersonation = 2;
        private const int TOKEN_ALL_ACCESS = 0xf01ff;
        private const int TOKEN_EXECUTE = 0x20000;
        private const int TOKEN_IMPERSONATE = 4;
        private const int TOKEN_READ = 0x20008;

        public Server(int port, string virtualPath, string physicalPath)
            : this(port, virtualPath, physicalPath, false, false)
        {
        }

        public Server(int port, string virtualPath, string physicalPath, bool requireAuthentication)
            : this(port, virtualPath, physicalPath, requireAuthentication, false)
        {
        }

        public Server(int port, string virtualPath, string physicalPath, bool requireAuthentication, bool disableDirectoryListing)
        {
            this._lockObject = new object();
            this._port = port;
            this._virtualPath = virtualPath;
            this._physicalPath = physicalPath.EndsWith(@"\", StringComparison.Ordinal) ? physicalPath : (physicalPath + @"\");
            this._requireAuthentication = requireAuthentication;
            this._disableDirectoryListing = disableDirectoryListing;
            this._onSocketAccept = new WaitCallback(this.OnSocketAccept);
            this._onStart = new WaitCallback(this.OnStart);
            this._appManager = ApplicationManager.GetApplicationManager();
            this.ObtainProcessToken();
        }

        private Socket CreateSocketBindAndListen(AddressFamily family, IPAddress ipAddress, int port)
        {
            Socket socket = new Socket(family, SocketType.Stream, ProtocolType.Tcp)
            {
                ExclusiveAddressUse = false
            };
            try
            {
                socket.Bind(new IPEndPoint(ipAddress, port));
            }
            catch
            {
                socket.Close();
                socket = null;
                throw;
            }
            socket.Listen(0x7fffffff);
            return socket;
        }

        [DllImport("KERNEL32.DLL", SetLastError = true)]
        private static extern IntPtr GetCurrentThread();
        private Host GetHost()
        {
            if (this._shutdownInProgress)
            {
                return null;
            }
            Host host = this._host;
            if (host == null)
            {
                lock (this._lockObject)
                {
                    host = this._host;
                    if (host == null)
                    {
                        string appId = (this._virtualPath + this._physicalPath).ToLowerInvariant().GetHashCode().ToString("x", CultureInfo.InvariantCulture);
                        //this._host = (Host) this._appManager.CreateObject(appId, typeof(Host), this._virtualPath, this._physicalPath, false);
                        Type hostType = typeof(Host);
                        var buildManagerHostType = typeof(HttpRuntime).Assembly.GetType("System.Web.Compilation.BuildManagerHost");
                        var buildManagerHost = _appManager.CreateObject(appId, buildManagerHostType, _virtualPath, _physicalPath, false);
                        buildManagerHostType.InvokeMember("RegisterAssembly", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic, null, buildManagerHost, new object[] { hostType.Assembly.FullName, hostType.Assembly.Location });
                       
                        this._host = (Host) this._appManager.CreateObject(appId, hostType, this._virtualPath, this._physicalPath, false);
                        this._host.Configure(this, this._port, this._virtualPath, this._physicalPath, this._requireAuthentication, this._disableDirectoryListing);
                        host = this._host;
                    }
                }
            }
            return host;
        }
      
        public IntPtr GetProcessToken()
        {
            return this._processToken;
        }

        public string GetProcessUser()
        {
            return this._processUser;
        }

        internal void HostStopped()
        {
            this._host = null;
        }

        [DllImport("ADVAPI32.DLL", SetLastError = true)]
        private static extern bool ImpersonateSelf(int level);
        public override object InitializeLifetimeService()
        {
            return null;
        }

        private void ObtainProcessToken()
        {
            if (ImpersonateSelf(2))
            {
                OpenThreadToken(GetCurrentThread(), 0xf01ff, true, ref this._processToken);
                RevertToSelf();
                this._processUser = WindowsIdentity.GetCurrent().Name;
            }
        }

        private void OnSocketAccept(object acceptedSocket)
        {
            if (!this._shutdownInProgress)
            {
                Microsoft.VisualStudio.WebHost.Connection conn = new Microsoft.VisualStudio.WebHost.Connection(this, (Socket)acceptedSocket);
                if (conn.WaitForRequestBytes() == 0)
                {
                    conn.WriteErrorAndClose(400);
                }
                else
                {
                    Host host = this.GetHost();
                    if (host == null)
                    {
                        conn.WriteErrorAndClose(500);
                    }
                    else
                    {
                        host.ProcessRequest(conn);
                    }
                }
            }
        }

        private void OnStart(object listeningSocket)
        {
            while (!this._shutdownInProgress)
            {
                try
                {
                    if (listeningSocket != null)
                    {
                        Socket state = ((Socket)listeningSocket).Accept();
                        ThreadPool.QueueUserWorkItem(this._onSocketAccept, state);
                    }
                    continue;
                }
                catch
                {
                    Thread.Sleep(100);
                    continue;
                }
            }
        }

        [DllImport("ADVAPI32.DLL", SetLastError = true)]
        private static extern int OpenThreadToken(IntPtr thread, int access, bool openAsSelf, ref IntPtr hToken);
        [DllImport("ADVAPI32.DLL", SetLastError = true)]
        private static extern int RevertToSelf();
        public void Start()
        {
            bool flag = false;
            flag = Socket.OSSupportsIPv4;
            if (Socket.OSSupportsIPv6)
            {
                try
                {
                    this._socketIpv6 = this.CreateSocketBindAndListen(AddressFamily.InterNetworkV6, IPAddress.IPv6Loopback, this._port);
                }
                catch (SocketException exception)
                {
                    if ((exception.SocketErrorCode == SocketError.AddressAlreadyInUse) || !flag)
                    {
                        throw;
                    }
                }
            }
            if (flag)
            {
                try
                {
                  // Environment.MachineName
                    IPHostEntry hosts = Dns.GetHostByName(Environment.MachineName);
                    IPAddress address = IPAddress.Loopback;
                    if (hosts.AddressList.Length > 0)
                        address = hosts.AddressList[0];
                    this._socketIpv4 = this.CreateSocketBindAndListen(AddressFamily.InterNetwork, address, this._port);
                }
                catch (SocketException)
                {
                    if (this._socketIpv6 == null)
                    {
                        throw;
                    }
                }
            }
            if (this._socketIpv6 != null)
            {
                ThreadPool.QueueUserWorkItem(this._onStart, this._socketIpv6);
            }
            if (this._socketIpv4 != null)
            {
                ThreadPool.QueueUserWorkItem(this._onStart, this._socketIpv4);
            }
        }

        public void Stop()
        {
            this._shutdownInProgress = true;
            try
            {
                if (this._socketIpv4 != null)
                {
                    this._socketIpv4.Close();
                }
                if (this._socketIpv6 != null)
                {
                    this._socketIpv6.Close();
                }
            }
            catch
            {
            }
            finally
            {
                this._socketIpv4 = null;
                this._socketIpv6 = null;
            }
            try
            {
                if (this._host != null)
                {
                    this._host.Shutdown();
                }
                while (this._host != null)
                {
                    Thread.Sleep(100);
                }
            }
            catch
            {
            }
            finally
            {
                this._host = null;
            }
        }

        public string PhysicalPath
        {
            get
            {
                return this._physicalPath;
            }
        }

        public int Port
        {
            get
            {
                return this._port;
            }
        }

        public string RootUrl
        {
            get
            {
                if (this._port != 80)
                {
                    return ("http://localhost:" + this._port + this._virtualPath);
                }
                return ("http://localhost" + this._virtualPath);
            }
        }

        public string VirtualPath
        {
            get
            {
                return this._virtualPath;
            }
        }
    }
}

调用代码:

     Server s = new Server(49152, "/", @"C:\Users\majiang\Documents\Visual Studio 2010\Projects\ConsoleApp\WebApp");
            s.Start();

欢迎大家拍砖

posted on 2012-09-07 09:19  dz45693  阅读(1050)  评论(0编辑  收藏  举报

导航