开发自定义的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类没怎么明白好像是处理身份认证之类的东东。。。

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

开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务 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;

            }

        }

    }

}
开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务 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;

            }

        }

    }

}
开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务 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";

        }

    }

}
开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务 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;

        }

    }

}
开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务 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;

            }

        }

    }

}
开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务 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 "";

            }

        }

    }

}
开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务 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;

        }

    }

}
开发自定义的web IIS服务器 WebDev.WebHost 用控制台托起web服务 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();

欢迎大家拍砖

你可能感兴趣的:(host)