Esempio n. 1
0
        public static void FileSynchronization(string modsDir, ModelModsFiles serverFiles)
        {
            restoreFolderTree(modsDir, serverFiles.FoldersTree);

            foreach (var serverFile in serverFiles.Files)
            {
                var fullName = Path.Combine(modsDir, serverFile.FileName);
                // Имя присутствует в списке, файл необходимо будет удалить ( или заменить)
                if (File.Exists(fullName))
                {
                    File.Delete(fullName);
                }

                if (serverFile.Hash == null)
                {
                    continue;
                }


                // Create the file, or overwrite if the file must exist.
                using (FileStream fs = File.Create(fullName))
                {
                    Loger.Log("Restore: " + fullName);

                    if (serverFile.Hash.Length > 0)
                    {
                        fs.Write(serverFile.Hash, 0, serverFile.Hash.Length);
                    }
                }
            }
        }
Esempio n. 2
0
        private ModelModsFiles checkFiles(ModelModsFiles packet, ServiceContext context)
        {
            var NoApproveWorld = ServerManager.FileHashChecker.ApproveWorldType[packet.FolderType];
            var filesDir       = ServerManager.FileHashChecker.CheckedDirAndFiles[packet.FolderType].ServerDirectory;
            var foldersTree    = ServerManager.FileHashChecker.CheckedDirAndFiles[packet.FolderType].FolderTree;
            var workDict       = ServerManager.FileHashChecker.CheckedDirAndFiles[packet.FolderType].HashFiles;
            var ignoredFiles   = ServerManager.FileHashChecker.CheckedDirAndFiles[packet.FolderType].IgrnoredFiles;

            var result         = new List <ModelFileInfo>();
            var allServerFiles = new HashSet <string>(workDict.Keys);
            var packetFiles    = packet.Files != null ? packet.Files : new List <ModelFileInfo>(0);

            long packetSize = 0;
            long totalSize  = 0;

            foreach (var modelFile in packetFiles)
            {
                var modelFileFileName = modelFile.FileName.ToLower();
                if (FileHashChecker.FileNameContainsIgnored(modelFileFileName, ignoredFiles))
                {
                    continue;
                }

                if (workDict.TryGetValue(modelFileFileName, out ModelFileInfo fileInfo))
                {
                    allServerFiles.Remove(modelFileFileName); //

                    if (!ModelFileInfo.UnsafeByteArraysEquale(modelFile.Hash, fileInfo.Hash))
                    {
                        // read file for send to Client
                        // файл  найден, но хеши не совпадают, необходимо заменить файл
                        if (packetSize < MaxPacketSize)
                        {
                            var addFile = GetFile(filesDir, fileInfo.FileName);
                            result.Add(addFile);
                            packetSize += addFile.Size;
                            totalSize  += addFile.Size;
                            //Loger.Log($"packetSize={packetSize} totalSize={totalSize}");
                        }
                        else
                        {
                            var size = GetFileSize(filesDir, fileInfo.FileName);
                            totalSize += size;
                        }
                    }
                }
                else
                {
                    // mark file for delete
                    // Если файл с таким именем не найден, помечаем файл на удаление
                    modelFile.Hash = null;
                    result.Add(modelFile);
                }
            }

            lock (context.Player)
            {
                // проверяем в обратном порядке: что бы у клиенты были все файлы
                if (allServerFiles.Any())
                {
                    context.Player.ApproveLoadWorldReason = context.Player.ApproveLoadWorldReason | ApproveLoadWorldReason.NotAllFilesOnClient;
                    foreach (var fileName in allServerFiles)
                    {
                        if (packetSize < MaxPacketSize)
                        {
                            var addFile = GetFile(filesDir, workDict[fileName].FileName); //workDict[fileName].FileName вместо fileName для восстановления заглавных
                            result.Add(addFile);
                            packetSize += addFile.Size;
                            totalSize  += addFile.Size;
                            //Loger.Log($"packetSize={packetSize} totalSize={totalSize}");
                        }
                        else
                        {
                            var size = GetFileSize(filesDir, workDict[fileName].FileName);
                            totalSize += size;
                        }
                    }
                }

                // Если файлы не прошли проверку, помечаем флагом, запрет загрузки мира
                if (result.Any())
                {
                    context.Player.ApproveLoadWorldReason = context.Player.ApproveLoadWorldReason | NoApproveWorld;
                }
            }

            if (!result.Any())
            {
                // микроптимизация: если файлы не будут восстанавливаться, не отправляем обратно список папок
                // на восстановление ( десериализацию папок также тратится время)
                foldersTree = new FoldersTree();
            }

            return(new ModelModsFiles()
            {
                Files = result,
                FolderType = packet.FolderType,
                FoldersTree = foldersTree,
                TotalSize = totalSize,
            });
        }
Esempio n. 3
0
        private ModelModsFiles checkFiles(ModelModsFiles packet, ServiceContext context)
        {
            var modsDir        = packet.IsSteam ? ServerManager.ServerSettings.SteamWorkShopModsDir : ServerManager.ServerSettings.ModsDirectory;
            var NoApproveWorld = packet.IsSteam ? ApproveLoadWorldReason.ModsSteamWorkShopFail : ApproveLoadWorldReason.ModsFilesFail;
            var workDict       = packet.IsSteam ? ServerManager.SteamFilesDict : ServerManager.ModFilesDict;
            var foldersTree    = packet.IsSteam ? ServerManager.ServerSettings.SteamDirConfig.FoldersTree : ServerManager.ServerSettings.ModsDirConfig.FoldersTree;

            var result = new List <ModelFileInfo>();

            var allServerFiles = new HashSet <string>(workDict.Keys);

            foreach (var file in packet.Files)
            {
                if (workDict.TryGetValue(file.FileName, out ModelFileInfo fileInfo))
                {
                    allServerFiles.Remove(file.FileName); //

                    if (!ModelFileInfo.UnsafeByteArraysEquale(file.Hash, fileInfo.Hash))
                    {
                        // read file for send to Client
                        // файл  найден, но хеши не совпадают, необходимо заменить файл
                        result.Add(GetFile(modsDir, fileInfo.FileName));
                    }
                }
                else
                {
                    // mark file for delete
                    // Если файл с таким именем не найден, помечаем файл на удаление
                    file.Hash = null;
                    result.Add(file);
                }
            }

            lock (context.Player)
            {
                // проверяем в обратном порядке: что бы у клиенты были все файлы
                if (allServerFiles.Any())
                {
                    context.Player.ApproveLoadWorldReason = context.Player.ApproveLoadWorldReason | ApproveLoadWorldReason.NotAllFilesOnClient;
                    foreach (var fileName in allServerFiles)
                    {
                        result.Add(GetFile(modsDir, fileName));
                    }
                }

                // Если файлы не прошли проверку, помечаем флагом, запрет загрузки мира
                if (result.Any())
                {
                    context.Player.ApproveLoadWorldReason = context.Player.ApproveLoadWorldReason | NoApproveWorld;
                }
            }

            if (!result.Any())
            {
                // микроптимизация: если файлы не будут восстанавливаться, не отправляем обратно список папок
                // на восстановление ( десериализацию папок также тратится время)
                foldersTree = new FoldersTree();
            }

            return(new ModelModsFiles()
            {
                Files = result,
                IsSteam = packet.IsSteam,
                FoldersTree = foldersTree
            });
        }
Esempio n. 4
0
        /// <summary>
        /// Генерируем запрос серверу в зависимости от контекста
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public ApproveLoadWorldReason GenerateRequestAndDoJob(object context)
        {
            // each request - response Client-Server-Client ~100-200 ms, get all check hash in one request
            // каждый запрос-отклик к серверу ~100-200 мс, получаем за один запрос все файлы
            // ~40 000 files *512 SHA key ~ size of package ~ 2,5 Mb

            ApproveLoadWorldReason result = ApproveLoadWorldReason.LoginOk;
            bool downloading  = true;
            long totalSize    = 0;
            long downloadSize = 0;

            while (downloading)
            {
                var clientFileChecker = (ClientFileChecker)context;
                var model             = new ModelModsFiles()
                {
                    Files      = clientFileChecker.FilesHash,
                    FolderType = clientFileChecker.FolderType,
                };

                UpdateModsWindow.Title       = "OC_Hash_Downloading".Translate();
                UpdateModsWindow.HashStatus  = "";
                UpdateModsWindow.SummaryList = null;
                Loger.Log($"Send hash {clientFileChecker.Folder}");

                var res = _sessionClient.TransObject2 <ModelModsFiles>(model, RequestTypePackage, ResponseTypePackage);

                if (res.Files.Count > 0)
                {
                    if (totalSize == 0)
                    {
                        totalSize = res.TotalSize;
                    }
                    downloadSize += res.Files.Sum(f => f.Size);
                    Loger.Log($"Files that need for a change: {downloadSize}/{totalSize} count={res.Files.Count}");
                    var pr = downloadSize > totalSize || totalSize == 0 ? 100 : downloadSize * 100 / totalSize;
                    UpdateModsWindow.HashStatus = "OC_Hash_Downloading_Finish".Translate()
                                                  + pr.ToString() + "%";

                    result = result | ApproveLoadWorldReason.ModsFilesFail;
                    //Loger.Log("TTTTT 0");
                    FileChecker.FileSynchronization(clientFileChecker.Folder, res);
                    //Loger.Log("TTTTT 1");
                    clientFileChecker.RecalculateHash(res.Files.Select(f => f.FileName).ToList());
                    //Loger.Log("TTTTT 2");

                    var addList = res.Files
                                  .Select(f => f.FileName)
                                  .Where(f => f.Contains("\\"))
                                  .Select(f => f.Substring(0, f.IndexOf("\\")))
                                  //.Distinct() //вместо дистинкта группируем без разницы заглавных букв, но сохраняем оригинальное название
                                  .Select(f => new { orig = f, comp = f.ToLower() })
                                  .GroupBy(p => p.comp)
                                  .Select(g => g.Max(p => p.orig))
                                  .Where(f => UpdateModsWindow.SummaryList == null || !UpdateModsWindow.SummaryList.Any(sl => sl == f))
                                  .ToList();
                    if (UpdateModsWindow.SummaryList == null)
                    {
                        UpdateModsWindow.SummaryList = addList;
                    }
                    else
                    {
                        UpdateModsWindow.SummaryList.AddRange(addList);
                    }
                }
                downloading = res.TotalSize != 0;
            }
            return(result);
        }