Пример #1
0
 /// <summary>
 /// 设置文件缓存
 /// </summary>
 /// <param name="path"></param>
 /// <param name="fileCache"></param>
 /// <param name="fileSize"></param>
 private void set(ref FileCacheKey path, FileCache fileCache, int fileSize)
 {
     Monitor.Enter(fileLock);
     try
     {
         fileCache.Size = fileSize;
         FileCache oldFileCache = files.Set(ref path, fileCache);
         freeCacheSize -= fileSize;
         if (oldFileCache == null)
         {
             while (freeCacheSize < 0 && files.Count > 1)
             {
                 freeCacheSize += files.UnsafePopValue().Size;
             }
         }
         else if (oldFileCache != fileCache)
         {
             freeCacheSize += oldFileCache.Size;
         }
     }
     finally { Monitor.Exit(fileLock); }
 }
Пример #2
0
 internal static void Set(ref FileCacheKey path, FileCache fileCache, int fileSize)
 {
     queues[path.HashCode & 0xff].set(ref path, fileCache, fileSize);
 }
Пример #3
0
 internal static byte Get(ref FileCacheKey path, out FileCache fileCache, bool isCopyPath)
 {
     return(queues[path.HashCode & 0xff].get(ref path, out fileCache, isCopyPath));
 }
Пример #4
0
        /// <summary>
        /// HTTP文件请求处理
        /// </summary>
        /// <param name="path">请求路径</param>
        /// <param name="ifModifiedSince">文件修改时间</param>
        /// <param name="response">HTTP响应输出</param>
        /// <param name="isCopyPath">是否复制请求路径</param>
        /// <returns>文件缓存</returns>
        protected unsafe FileCache file(byte[] path, SubArray <byte> ifModifiedSince, ref Http.Response response, bool isCopyPath)
        {
            string cacheFileName = null;

            try
            {
                if (path.Length != 0 && WorkPath.Length + path.Length <= AutoCSer.IO.File.MaxFullNameLength)
                {
                    byte[] contentType = null;
                    bool   isCompress  = true;
                    fixed(byte *pathFixed = path)
                    {
                        byte *pathStart = pathFixed, pathEnd = pathStart + path.Length;

                        if (isFile(pathEnd, ref contentType, ref isCompress) == 0)
                        {
                            if (*pathStart == '/')
                            {
                                ++pathStart;
                            }
                            for (byte *formatStart = pathStart; formatStart != pathEnd; ++formatStart)
                            {
                                if (*formatStart == ':')
                                {
                                    response = Http.Response.Blank;
                                    return(null);
                                }
                            }
                            int          cachePathLength = (int)(pathEnd - pathStart);
                            FileCacheKey cacheKey        = new FileCacheKey(pathIdentity, path, (int)(pathStart - pathFixed), cachePathLength);
                            FileCache    fileCache       = FileCacheQueue.Get(ref cacheKey);
                            if (fileCache == null)
                            {
                                cacheFileName = StringExtension.FastAllocateString(WorkPath.Length + cachePathLength);
                                fixed(char *nameFixed = cacheFileName)
                                {
                                    char *write = nameFixed + WorkPath.Length;
                                    char  directorySeparatorChar = Path.DirectorySeparatorChar;

                                    StringExtension.CopyNotNull(WorkPath, nameFixed);
                                    for (byte *start = pathStart; start != pathEnd; ++start)
                                    {
                                        *write++ = *start == '/' ? directorySeparatorChar : (char)*start;
                                    }
                                }
                                FileInfo file = new FileInfo(cacheFileName);
                                if (file.Exists)
                                {
                                    string fileName = file.FullName;
                                    if (fileName.Length > WorkPath.Length && WorkPath.equalCaseNotNull(fileName, WorkPath.Length))
                                    {
                                        if (fileName.Length <= AutoCSer.IO.File.MaxFullNameLength && file.Length <= FileCacheQueue.MaxFileSize)
                                        {
                                            if (FileCacheQueue.Get(ref cacheKey, out fileCache, isCopyPath) != 0)
                                            {
                                                try
                                                {
                                                    fileCache.LastModified = file.LastWriteTimeUtc.UniversalNewBytes();
                                                    int             extensionNameLength = (int)(pathEnd - getExtensionNameStart(pathEnd));
                                                    SubArray <byte> fileData            = readCacheFile(new SubString {
                                                        String = fileName, Start = fileName.Length - extensionNameLength, Length = extensionNameLength
                                                    });
                                                    FileCacheQueue.Set(ref cacheKey, fileCache, fileCache.Set(ref fileData, contentType, cacheControl, isCompress));
                                                    if (ifModifiedSince.Length == fileCache.LastModified.Length)
                                                    {
                                                        fixed(byte *ifModifiedSinceFixed = ifModifiedSince.Array)
                                                        {
                                                            if (Memory.EqualNotNull(fileCache.LastModified, ifModifiedSinceFixed + ifModifiedSince.Start, ifModifiedSince.Length))
                                                            {
                                                                response = Http.Response.NotChanged304;
                                                                return(null);
                                                            }
                                                        }
                                                    }
                                                }
                                                finally
                                                {
                                                    if (fileCache.IsData == 0)
                                                    {
                                                        fileCache.PulseAll();
                                                        fileCache = null;
                                                        FileCacheQueue.RemoveOnly(ref cacheKey);
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (ifModifiedSince.Length == Date.ToByteLength && Date.UniversalByteEquals(file.LastWriteTimeUtc, ifModifiedSince) == 0)
                                            {
                                                response = Http.Response.NotChanged304;
                                                return(null);
                                            }
                                            response = Http.Response.Get();
                                            //response.State = Http.ResponseState.Ok200;
                                            response.SetBodyFile(file);
                                            response.CacheControl = cacheControl;
                                            response.ContentType  = contentType;
                                            response.SetLastModified(file.LastWriteTimeUtc.UniversalNewBytes());
                                            return(null);
                                        }
                                    }
                                }
                            }
                            return(fileCache);
                        }
                    }
                }
            }
            catch (Exception error)
            {
                RegisterServer.TcpServer.Log.Add(AutoCSer.Log.LogType.Error, error, cacheFileName);
            }
            return(null);
        }
Пример #5
0
        /// <summary>
        /// 创建错误输出数据
        /// </summary>
        protected unsafe virtual void createErrorResponse()
        {
            KeyValue <Http.Response, Http.Response>[] errorResponses = new KeyValue <Http.Response, Http.Response> [EnumAttribute <Http.ResponseState> .GetMaxValue(-1) + 1];
            int isResponse = 0;

            try
            {
                byte[] path = new byte[9];
                fixed(byte *pathFixed = path)
                {
                    *pathFixed = (byte)'/';
                    *(int *)(pathFixed + sizeof(int)) = '.' + ('h' << 8) + ('t' << 16) + ('m' << 24);
                    *(pathFixed + sizeof(int) * 2)    = (byte)'l';
                    foreach (Http.ResponseState type in System.Enum.GetValues(typeof(Http.ResponseState)))
                    {
                        Http.ResponseStateAttribute state = EnumAttribute <Http.ResponseState, Http.ResponseStateAttribute> .Array((int)type);

                        if (state != null && state.IsError)
                        {
                            int stateValue = state.Number, value = stateValue / 100;
                            *(pathFixed + 1) = (byte)(value + '0');
                            stateValue      -= value * 100;
                            *(pathFixed + 2) = (byte)((value = stateValue / 10) + '0');
                            *(pathFixed + 3) = (byte)((stateValue - value * 10) + '0');
                            Http.Response response  = null;
                            FileCache     fileCache = file(path, default(SubArray <byte>), ref response, true);
                            if (fileCache == null)
                            {
                                if (response != null)
                                {
                                    response.CancelPool();
                                    errorResponses[(int)type].Set(response, response);
                                    isResponse = 1;
                                }
                            }
                            else
                            {
                                Http.Response gzipResponse;
                                if ((response = fileCache.Response) == null)
                                {
                                    response     = Http.Response.New();
                                    gzipResponse = Http.Response.New();
                                    SubArray <byte> data = fileCache.Data, gzipData = fileCache.GZipData;
                                    if (FileCacheQueue.IsFileCacheHeader && data.Start == FileCache.HttpHeaderSize)
                                    {
                                        response.SetCanHeaderSize(ref data);
                                        gzipResponse.SetCanHeaderSize(ref gzipData);
                                    }
                                    else
                                    {
                                        response.SetBody(ref data);
                                        gzipResponse.SetBody(ref gzipData);
                                    }
                                    gzipResponse.SetContentEncoding(Http.Response.GZipEncoding);
                                }
                                else
                                {
                                    gzipResponse = fileCache.GZipResponse ?? response;
                                }
                                response.SetState(type);
                                gzipResponse.SetState(type);
                                errorResponses[(int)type].Set(response, gzipResponse);
                                isResponse = 1;
                            }
                        }
                    }
                }
            }
            catch (Exception error)
            {
                RegisterServer.TcpServer.Log.Add(AutoCSer.Log.LogType.Error, error);
            }
            if (isResponse != 0)
            {
                this.errorResponses = errorResponses;
            }
        }
Пример #6
0
        /// <summary>
        /// HTTP文件请求处理
        /// </summary>
        /// <param name="header">请求头部信息</param>
        /// <param name="fileCache">文件输出信息</param>
        /// <param name="response">HTTP响应</param>
        protected unsafe void file(Http.Header header, FileCache fileCache, ref Http.Response response)
        {
            Http.HeaderFlag headerFlag = header.Flag;
            if (fileCache == null)
            {
                if (response != null)
                {
                    if (response.Type == Http.ResponseType.File)
                    {
                        if ((headerFlag & Http.HeaderFlag.IsRange) != 0 && !header.FormatRange(response.BodySize))
                        {
                            response = Http.Response.RangeNotSatisfiable416;
                            return;
                        }
                        if ((headerFlag & Http.HeaderFlag.IsVersion) != 0 || isStaticFileCacheControl(header.Path))
                        {
                            response.CacheControl = AutoCSer.Net.Http.Response.StaticFileCacheControl;
                        }
                    }
                    if ((response.Flag & Http.ResponseFlag.IsPool) != 0 && (headerFlag & Http.HeaderFlag.IsSetOrigin) != 0 && this.isOrigin(header.Origin, (headerFlag & Http.HeaderFlag.IsSsl) != 0))
                    {
                        response.SetAccessControlAllowOrigin(header.OriginIndex);
                    }
                }
                return;
            }
            if ((headerFlag & Http.HeaderFlag.IsRange) != 0 && !header.FormatRange(fileCache.Data.Length))
            {
                response = Http.Response.RangeNotSatisfiable416;
                return;
            }
            byte[] cacheControl = (headerFlag & Http.HeaderFlag.IsVersion) != 0 || isStaticFileCacheControl(header.Path) ? AutoCSer.Net.Http.Response.StaticFileCacheControl : this.cacheControl;
            bool   isOrigin = (headerFlag & Http.HeaderFlag.IsSetOrigin) != 0 && this.isOrigin(header.Origin, (headerFlag & Http.HeaderFlag.IsSsl) != 0), isHeader = !isOrigin && (headerFlag & Http.HeaderFlag.IsRange) == 0 && FileCacheQueue.IsFileCacheHeader;

            if (isHeader && (response = (headerFlag & Http.HeaderFlag.IsGZip) == 0 ? fileCache.Response : fileCache.GZipResponse) != null && response.IsCacheControl(cacheControl))
            {
                return;
            }
            SubArray <byte> body = (headerFlag & Http.HeaderFlag.IsGZip) != 0 && (headerFlag & Http.HeaderFlag.IsRange) == 0 ? fileCache.GZipData : fileCache.Data;

            response = Http.Response.Get();
            //response.State = Http.ResponseState.Ok200;
            if (isHeader && body.Start == FileCache.HttpHeaderSize)
            {
                response.SetCanHeaderSize(ref body);
            }
            else
            {
                response.SetBody(ref body);
            }
            response.CacheControl = cacheControl;
            response.ContentType  = fileCache.ContentType;
            if (body.Array != fileCache.Data.Array)
            {
                response.SetContentEncoding(Http.Response.GZipEncoding);
            }
            response.SetLastModified(fileCache.LastModified);
            if (isOrigin)
            {
                response.SetAccessControlAllowOrigin(header.OriginIndex);
            }
            return;
        }
Пример #7
0
        /// <summary>
        /// HTTP文件请求处理
        /// </summary>
        /// <param name="header">请求头部</param>
        /// <param name="response">HTTP响应输出</param>
        /// <returns>文件缓存</returns>
        protected unsafe FileCache file(Http.Header header, ref Http.Response response)
        {
            SubArray <byte> path          = header.Path;
            string          cacheFileName = null;

            try
            {
                if (path.Length != 0 && WorkPath.Length + path.Length <= AutoCSer.IO.File.MaxFullNameLength)
                {
                    byte[] contentType = null;
                    bool   isCompress  = true;
                    fixed(byte *pathFixed = path.GetFixedBuffer())
                    {
                        byte *pathStart = pathFixed + path.Start, pathEnd = pathStart + path.Length;

                        if (isFile(pathEnd, ref contentType, ref isCompress) == 0)
                        {
                            if (*pathStart == '/')
                            {
                                ++pathStart;
                            }
                            for (byte *formatStart = pathStart; formatStart != pathEnd; ++formatStart)
                            {
                                if (*formatStart == ':')
                                {
                                    response = Http.Response.Blank;
                                    return(null);
                                }
#if !MONO
                                if ((uint)(*formatStart - 'A') < 26)
                                {
                                    *formatStart |= 0x20;
                                }
#endif
                            }
                            int          cachePathLength = (int)(pathEnd - pathStart);
                            FileCacheKey cacheKey        = new FileCacheKey(pathIdentity, path.Array, (int)(pathStart - pathFixed), cachePathLength);
                            FileCache    fileCache       = FileCacheQueue.Get(ref cacheKey);
                            if (fileCache == null)
                            {
                                cacheFileName = StringExtension.FastAllocateString(WorkPath.Length + cachePathLength);
                                fixed(char *nameFixed = cacheFileName)
                                {
                                    char *write = nameFixed + WorkPath.Length;
                                    char  directorySeparatorChar = Path.DirectorySeparatorChar;

                                    StringExtension.CopyNotNull(WorkPath, nameFixed);
                                    for (byte *start = pathStart; start != pathEnd; ++start)
                                    {
                                        *write++ = *start == '/' ? directorySeparatorChar : (char)*start;
                                    }
                                }
                                FileInfo file = new FileInfo(cacheFileName);
                                bool     isFileExists = file.Exists, isCopyPath = true;
                                if (!isFileExists && cacheFileName.IndexOf('%') >= WorkPath.Length)
                                {
                                    cacheKey.CopyPath();
                                    isCopyPath = false;
                                    string newPath = AutoCSer.Net.Http.Header.UnescapeUtf8(pathStart, cachePathLength, path.Array, (int)(pathStart - pathFixed));
                                    if (Path.DirectorySeparatorChar != '/')
                                    {
                                        newPath.replaceNotNull('/', Path.DirectorySeparatorChar);
                                    }
                                    FileInfo newFile = new FileInfo(WorkPath + newPath);
                                    if (newFile.Exists)
                                    {
                                        file         = newFile;
                                        isFileExists = true;
                                    }
                                }
                                if (isFileExists)
                                {
                                    string fileName = file.FullName;
                                    if (fileName.Length > WorkPath.Length && WorkPath.equalCaseNotNull(fileName, WorkPath.Length))
                                    {
                                        if (fileName.Length <= AutoCSer.IO.File.MaxFullNameLength && file.Length <= FileCacheQueue.MaxFileSize)
                                        {
                                            if (FileCacheQueue.Get(ref cacheKey, out fileCache, isCopyPath) != 0)
                                            {
                                                try
                                                {
                                                    fileCache.LastModified = file.LastWriteTimeUtc.UniversalNewBytes();
                                                    int             extensionNameLength = (int)(pathEnd - getExtensionNameStart(pathEnd));
                                                    SubArray <byte> fileData            = readCacheFile(new SubString {
                                                        String = fileName, Start = fileName.Length - extensionNameLength, Length = extensionNameLength
                                                    });
                                                    FileCacheQueue.Set(ref cacheKey, fileCache, fileCache.Set(ref fileData, contentType, cacheControl, isCompress));
                                                    if ((header.Flag & Http.HeaderFlag.IsSetIfModifiedSince) != 0 && header.IfModifiedSinceIndex.Length == fileCache.LastModified.Length)
                                                    {
                                                        if (AutoCSer.Memory.Common.EqualNotNull(fileCache.LastModified, pathFixed + header.Buffer.StartIndex + header.IfModifiedSinceIndex.StartIndex, header.IfModifiedSinceIndex.Length))
                                                        {
                                                            response = Http.Response.NotChanged304;
                                                            return(null);
                                                        }
                                                    }
                                                }
                                                finally
                                                {
                                                    if (fileCache.IsData == 0)
                                                    {
                                                        fileCache.PulseAll();
                                                        fileCache = null;
                                                        FileCacheQueue.RemoveOnly(ref cacheKey);
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if ((header.Flag & Http.HeaderFlag.IsSetIfModifiedSince) != 0 && header.IfModifiedSinceIndex.Length == Date.ToByteLength && Date.UniversalByteEquals(file.LastWriteTimeUtc, header.IfModifiedSince) == 0)
                                            {
                                                response = Http.Response.NotChanged304;
                                                return(null);
                                            }
                                            response = Http.Response.Get();
                                            //response.State = Http.ResponseState.Ok200;
                                            response.SetBodyFile(file);
                                            response.CacheControl = cacheControl;
                                            response.ContentType  = contentType;
                                            response.SetLastModified(file.LastWriteTimeUtc.UniversalNewBytes());
                                            return(null);
                                        }
                                    }
                                }
                            }
                            return(fileCache);
                        }
                    }
                }
            }
            catch (Exception error)
            {
                RegisterServer.TcpServer.Log.Exception(error, cacheFileName, LogLevel.Exception | LogLevel.AutoCSer);
            }
            return(null);
        }