using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.IO; using System.Security.Cryptography; using Sog; using ProtoCSStruct; namespace Game { public static class ClientHotPatchSvc { static CSClientHotPatchFilePush message = new CSClientHotPatchFilePush(); static bool bCheckCreateDir = false; public static void CheckAndPushHotPatchFile(PlayerSession session, string appVersion) { //ios版本暂时先关闭热补丁更新功能 /*if(session.Platform == PlatformType.PlatformType_IOS) { return; }*/ ClientHotPatchFile file = null; if (GameServerUtils.GetServerConfig().bDebugHotOpen && LimitIPList.IsInWhiteList(session.IPAddr,session.DeviceId)) //先检查获取内测热更包 { file = GetHotPatchByVersion(appVersion, true); } if (file == null || string.IsNullOrEmpty(file.FileContent)) //没有内测热更包就检查正常版本 { file = GetHotPatchByVersion(appVersion, false); } message.Clear(); if (string.IsNullOrEmpty(file.FileContent)) { //为了兼容老的客户端,如果客户端MD5没有并且服务器没有补丁那么就不发了 if (string.IsNullOrEmpty(session.HotpatchMd5) == false) { GameServerUtils.GetLoginHandler().SendToPlayer(session, (int)CSGameMsgID.ClientHotPatchFilePush, ref message); } return; } if (file.Md5 != null) { message.Md5.SetString( file.Md5); } if (session.HotpatchMd5 == file.Md5) { session.Trace("ClientHotPatchSvc.CheckAndPushHotPatchFile uid {0} appversion {1} have same hotpatch md5 {2},skip" , session.UserID, appVersion, file.Md5); GameServerUtils.GetLoginHandler().SendToPlayer(session, (int)CSGameMsgID.ClientHotPatchFilePush, ref message); return; } session.Debug("ClientHotPatchSvc.CheckAndPushHotPatchFile uid {0} have hotpatch appversion {1},send to client" , session.UserID, appVersion); if(session.ZipHotpatch) { foreach (var onebyte in file.ZipFileContent) { message.ZipFileContent.Add(onebyte); } } else { message.PatchFileContent.SetString( file.FileContent); } GameServerUtils.GetLoginHandler().SendToPlayer(session, (int)CSGameMsgID.ClientHotPatchFilePush, ref message); } private static ClientHotPatchFile GetHotPatchByVersion(string appVersion, bool bDeubug) { var dict = bDeubug ? GameServerUtils.GetGameServerData().m_clientHotPatchFileDubugDict : GameServerUtils.GetGameServerData().m_clientHotPatchFileDict; ClientHotPatchFile patchFile = null; if (dict.ContainsKey(appVersion) == false) { patchFile = new ClientHotPatchFile(); dict.Add(appVersion, patchFile); } else { patchFile = dict[appVersion]; } //10秒钟更新一次 long nowSecond = GameServerUtils.GetTimeSecond(); if(nowSecond - patchFile.LoadTimeSecond >= 10) { ReadPathFile(appVersion, patchFile, bDeubug); } return patchFile; } private static void ReadPathFile(string appVersion, ClientHotPatchFile patchFile, bool bDebug) { string newContent = null; const string c_debugPath = "../cfg/clihotpatch_debug/"; const string c_path = "../cfg/clihotpatch/"; string path = bDebug ? c_debugPath : c_path; if(bCheckCreateDir == false) { TraceLog.Debug("ClientHotPatchSvc.ReadPathFile check try to create clihotpatch dir"); try { if (!Directory.Exists(c_debugPath)) { Directory.CreateDirectory(c_debugPath); } if (!Directory.Exists(c_path)) { Directory.CreateDirectory(c_path); } } catch (Exception) { } bCheckCreateDir = true; } try { newContent = File.ReadAllText(path + appVersion + ".lua"); } catch (Exception) { } //有变化则更新 if (newContent != patchFile.FileContent) { string zipFileName = path + appVersion + ".gz"; patchFile.FileContent = newContent; //有内容 if (string.IsNullOrEmpty(newContent) == false) { patchFile.ZipFileContent = Sog.IO.ZipUtils.CompressStringGZip(newContent); patchFile.Md5 = MD5Encrypt(patchFile.FileContent); //save zip file try { File.WriteAllBytes(zipFileName, patchFile.ZipFileContent); } catch (Exception) { } } else { patchFile.ZipFileContent = null; patchFile.Md5 = null; //delete zip file try { File.Delete(zipFileName); } catch (Exception) { } } } //不管如何,设置时间 patchFile.LoadTimeSecond = GameServerUtils.GetTimeSecond(); } public static string MD5Encrypt(string strText) { MD5 md5 = MD5.Create(); byte[] result = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(strText)); md5.Dispose(); string byte2String = null; for (int i = 0; i < result.Length; i++) { byte2String += result[i].ToString("x2"); } return byte2String; } } }