You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

425 lines
16 KiB

/*
Sog 游戏基础库
2016 by zouwei
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Sog;
using Sog.Gate;
using ProtoCSStruct;
namespace Version
{
public class VersionMsgHandler
{
private ServerApp m_app;
private VersionSvc m_versionSvc;
public VersionMsgHandler(ServerApp app)
{
m_app = app;
m_versionSvc = new VersionSvc(app);
}
public VersionSvc GetVersionSvcObj()
{
return m_versionSvc;
}
public ServerApp GetApp()
{
return m_app;
}
public void Dispose()
{
m_app = null;
m_versionSvc.Dispose();
m_versionSvc = null;
}
public void HandlerMessage(uint remoteAppID, MessageData message)
{
int iServerType = ServerIDUtils.GetServerType(remoteAppID);
if (iServerType == (int)ServerType.VersionGate)
{
TraceLog.Trace("VersionMsgHandler.HandlerMessage recv msg from gate length {0}", message.Header.Length);
HandlerGateMessage(remoteAppID, message);
return;
}
else
{
TraceLog.Trace("VersionMsgHandler.HandlerMessage recv msg from server type {0} length {1}", iServerType, message.Header.Length);
HandlerOtherServerMessage(remoteAppID, message);
return;
}
}
private void HandlerGateMessage(uint remoteAppID, MessageData message)
{
GateMsgHeader header = new GateMsgHeader();
GateMsgHeaderPacker.UnPack(message.Buffer.Data, ref header);
// trans msg to client
if (header.OpCode == (int)GateMsgOpCode.Trans)
{
HandlerClientGateMessage(remoteAppID, message);
return;
}
if (header.OpCode == (int)GateMsgOpCode.ConnectedReq)
{
OnSessionConnected(remoteAppID, header.SessionID);
return;
}
if (header.OpCode == (int)GateMsgOpCode.DisconnectedReq)
{
OnSessionDisconnected(remoteAppID, header.SessionID);
return;
}
//int headLength = GateMsgHeaderPacker.GetLength();
}
private void OnSessionConnected(uint gateServerID, long sessionID)
{
TraceLog.Trace("VersionMsgHandler.OnSessionConnected session {0} connected, new PlayerSession", sessionID);
//回应
GateMsgHeader gateHeader;
gateHeader.OpCode = (int)GateMsgOpCode.ConnectedRes;
gateHeader.SessionID = sessionID;
GateService.NotifyGateServer(m_app,gateServerID, ref gateHeader);
m_versionSvc.AddClientConnectData(gateServerID, sessionID);
}
private void OnSessionDisconnected(uint gateServerID, long sessionID)
{
TraceLog.Debug("VersionMsgHandler.OnSessionDisconnected session {0} disconnected, delete PlayerSession"
, sessionID);
m_versionSvc.RemoveClientConnectData(gateServerID, sessionID);
}
private void HandlerClientGateMessage(uint gateServerID, MessageData gateMessage)
{
long sessionID = gateMessage.Header.ObjectID;
int headLength = GateMsgHeaderPacker.GetLength();
MessageData message = new MessageData();
message.Header.Type = gateMessage.Header.Type;
message.Header.Length = gateMessage.Header.Length - headLength;
if (message.Header.Length < 0)
{
TraceLog.Trace("VersionMsgHandler.HandlerClientGateMessage recv session {0} message ,gateMessage length error ", sessionID);
return;
}
message.MallocData(message.Header.Length);
//message.Data = new byte[message.Header.Length];
Buffer.BlockCopy(gateMessage.Buffer.Data, headLength, message.Buffer.Data, 0, message.Buffer.Length);
try
{
HandlerClientMessage(gateServerID, sessionID, message);
}
finally
{
message.FreeData();
}
}
private void HandlerClientMessage(uint gateServerID, long sessionID, MessageData message)
{
try
{
StructPacket packet;
bool result = VersionServerUtils.GetProtoPacker().UnpackMessage(message, out packet);
if (result)
{
//预先判断,提高效率
if (TraceLog.GetLogLevel() <= (int)Sog.Log.LogLevel.TraceDetail
&& TraceLog.IsSkipLogMsgID(packet.MsgID) == false)
{
// log message
TraceLog.TraceDetail("VersionMsgHandler.HandlerClientMessage recv from session {0} from gateServer {1}, message type {2} length {3} : {4}->{5}"
, sessionID
, ServerIDUtils.IDToString(gateServerID)
, message.Header.Type
, message.Header.Length
, packet.MessageName()
, packet.ToString());
}
ProcessClientPacket(gateServerID, sessionID, packet);
}
}
catch (Exception ex)
{
TraceLog.Error("VersionMsgHandler.HandlerClientMessage Received from session:{0} error:{1}", sessionID, ex.Message);
TraceLog.Exception(ex);
}
}
private void HandlerOtherServerMessage(uint remoteAppID, MessageData message)
{
try
{
StructPacket packet;
bool result = VersionServerUtils.GetProtoPacker().UnpackMessage(message, out packet);
if (result)
{
if (TraceLog.GetLogLevel() <= (int)Sog.Log.LogLevel.TraceDetail
&& TraceLog.IsSkipLogMsgID(packet.MsgID) == false)
{
// log message
TraceLog.TraceDetail("VersionMsgHandler.HandlerOtherServerMessage recv message from server {0}, message type {1} length {2} : {3}->{4}"
, ServerIDUtils.IDToString(remoteAppID)
, message.Header.Type
, message.Header.Length
, packet.MessageName()
, packet.ToString());
}
ProcessServerPacket(remoteAppID, packet);
}
}
catch (Exception ex)
{
TraceLog.Error("VersionMsgHandler.HandlerOtherServerMessage Received from server:{0} error:{1}", ServerIDUtils.IDToString(remoteAppID), ex.Message);
TraceLog.Exception(ex);
}
}
private void ProcessClientPacket(uint gateServerID, long sessionID, StructPacket packet)
{
if(packet.MsgID == (int)CSMsgID.VersionReq)
{
ProcessVersionReq(gateServerID,sessionID,packet);
}
}
private void ProcessVersionReq(uint gateServerID, long sessionID, StructPacket packet)
{
ref CSVersionCheckReq req = ref packet.GetMessage<CSVersionCheckReq>();
//非法消息可以不用管
if (m_versionSvc.CheckValidVersionInfo(ref req.Version) == false)
{
TraceLog.Error("VersionMsgHandler.ProcessVersionReq versioninfo invalid! session {0}", sessionID);
return;
}
long reqVersion = AppVersion.ToIntVersion(req.Version.AppVersion.GetString());
if(reqVersion == 0)
{
TraceLog.Error("VersionMsgHandler.ProcessVersionReq versioninfo invalid, session {0}, version {1}", sessionID, req.Version.AppVersion);
return;
}
// 强行把windows版本修改成android版本, 方便unity下测试
if (req.Version.Os.Equals("win"))
{
req.Version.Os.SetString("android");
}
long currVer = m_versionSvc.GetCurrentVersion(ref req.Version);
CSVersionCheckRes res = new CSVersionCheckRes();
//最先判断服务器是否在维护
if (m_versionSvc.IsMaintenanceMode())
{
res.Ret = 0;
res.MaintenanceMode = 1;
res.MaintenanceNotice.SetString( m_versionSvc.GetMaintenanceNotice());
TraceLog.Trace("VersionMsgHandler.ProcessVersionReq server maintenance now, session {0} version {1}"
, sessionID, req.Version.AppVersion);
GateService.SendToGate(0, m_app.GetCluster(), gateServerID, sessionID, (int)CSMsgID.VersionRes, ref res);
return;
}
// 当前版本有热更包, 客户端在更新完upk后再更新hotPatch
if (m_versionSvc.HasHotPatch())
{
string currVerStr = AppVersion.ToStringVersion(currVer);
int hotPatchSize = m_versionSvc.GetHotPatchFileSizeAndMd5(ref req.Version, currVerStr, out string hotMd5);
if (hotPatchSize > 0)
{
res.HotPatchFileMd5.SetString(hotMd5);
res.HotPatchFileSize = hotPatchSize;
string hotUrl = m_versionSvc.GetHotPatchFileUrl(ref req.Version, currVerStr);
res.HotPatchDownloadUrl.SetString(hotUrl);
TraceLog.Trace("VersionMsgHandler.ProcessVersionReq hot url {0} size {1} md5 {2}"
, hotUrl, hotPatchSize, hotMd5);
}
}
int forReview = 0;
// 版本服务器配置了不更新, win版本由客户端屏蔽更新, 方便unity下测试
//if (m_versionSvc.IsSkipCheckVersion() || req.Version.Os.Equals( "win"))
if (m_versionSvc.IsSkipCheckVersion())
{
res.Ret = 0;
res.NewVersion.SetString(req.Version.AppVersion.GetPtr());
res.GateUrl.SetString( m_versionSvc.SelectGateUrl(ref req, out forReview));
res.ForReview = forReview;
TraceLog.Trace("VersionMsgHandler.ProcessVersionReq version is need not check {0} , need not update, gateUrl {1}", req.Version, res.GateUrl);
GateService.SendToGate(0,m_app.GetCluster(), gateServerID, sessionID, (int)CSMsgID.VersionRes, ref res);
return;
}
TraceLog.Debug("VersionMsgHandler.ProcessVersionReq versioninfo session {0}, Appversion {1} Os {2}, Language {3}, currVer {4}, reqVersion {5}",
sessionID, req.Version.AppVersion, req.Version.Os, req.Version.Language, currVer, reqVersion);
//版本号比当前版本大, 不需要更新
if (reqVersion >= currVer)
{
res.Ret = 0;
res.NewVersion.SetString( AppVersion.ToStringVersion(currVer));
res.GateUrl.SetString( m_versionSvc.SelectGateUrl(ref req, out forReview));
res.ForReview = forReview;
TraceLog.Trace("VersionMsgHandler.ProcessVersionReq reqVersion {0} >= curVersion {1}, need not udpate, gateUrl {2}"
, req.Version, res.NewVersion, res.GateUrl);
GateService.SendToGate(0,m_app.GetCluster(), gateServerID, sessionID, (int)CSMsgID.VersionRes, ref res);
return;
}
string strPathUrl = m_versionSvc.GetPatchFileUrl(ref req.Version, currVer, reqVersion);
int patchFileSize = m_versionSvc.GetPatchFileSizeAndMd5(ref req.Version, currVer, reqVersion, out string md5);
// 更新包不存在, 告诉客户端去商店更新apk
if (patchFileSize <= 0)
{
res.Ret = 0;
res.NewVersion.SetString(AppVersion.ToStringVersion(currVer));
res.GateUrl.SetString(m_versionSvc.SelectGateUrl(ref req, out forReview));
res.ForReview = forReview;
res.NeedUpdateApk = 1;
GateService.SendToGate(0, m_app.GetCluster(), gateServerID, sessionID, (int)CSMsgID.VersionRes, ref res);
return;
}
foreach (var item in VersionUpdateCompensateDescMgr.Instance.ItemTable)
{
long updateVer = AppVersion.ToIntVersion(item.appVersion);
TraceLog.Debug("VersionMsgHandler.ProcessVersionReq session {0} updateVer {1} currVer {2}"
, sessionID, updateVer, currVer);
long endTime = ConfigStringTimeParse.ParseConfigTime(item.endTime);
if (updateVer == currVer)
{
//没过期则有奖励
if (endTime == 0 || endTime > VersionServerUtils.GetTimeSecond())
{
res.Chip = item.chip;
res.Diamond = item.diamond;
res.ItemID = item.itemid;
res.ItemCount = item.itemcount;
}
//更新内容
if (! string.IsNullOrWhiteSpace(item.content))
{
res.Content.SetString(Sog.Lang.LanguageUtils.GetLanguageString(item.content, req.Version.Language.GetString()));
}
break;
}
}
res.Ret = 0;
res.NewVersion.SetString( AppVersion.ToStringVersion(currVer));
res.GateUrl.SetString( m_versionSvc.SelectGateUrl(ref req, out forReview));
res.ForReview = forReview;
res.DownloadUrl.SetString( strPathUrl);
res.PatchFileSize = patchFileSize;
res.PatchFileMd5.SetString( md5);
TraceLog.Trace("VersionMsgHandler.ProcessVersionReq path url is {0}, gateUrl {1} size {2} md5 {3}"
, strPathUrl, res.GateUrl, res.PatchFileSize, res.PatchFileMd5);
GateService.SendToGate(0,m_app.GetCluster(), gateServerID, sessionID, (int)CSMsgID.VersionRes, ref res);
}
private void ProcessServerPacket(uint remoteAppID, StructPacket packet)
{
switch (packet.MsgID)
{
case (int) SSMsgID.GetClientVerionReq:
OnServerGetClientVersion(remoteAppID, packet);
break;
default:
TraceLog.Error("VersionMsgHandler.ProcessServerPacket MsgID {0} not handle", packet.MsgID);
break;
}
}
private void OnServerGetClientVersion(uint remoteAppID, StructPacket packet)
{
ref SSGetClientVersionReq req = ref packet.GetMessage<SSGetClientVersionReq>();
SSGetClientVersionRes res = new SSGetClientVersionRes();
res.Version = req.Version;
res.CurrVer = m_versionSvc.GetCurrentVersion(ref req.Version);
res.CurrVerStr.SetString(AppVersion.ToStringVersion(res.CurrVer));
VersionServerUtils.GetPacketSender().SendToServerByID(remoteAppID, (int)SSMsgID.GetClientVerionRes, ref res, 0);
}
public void UpdateClientConnect()
{
var clientConnData = VersionServerUtils.GetVersionServerData().m_ClientConnectDict;
foreach (KeyValuePair<long, ClientConnectInfo> pair in clientConnData)
{
uint gateServerID = pair.Value.uGateServerID;
long sessionID = pair.Value.iConnectSessionID;
long iConnectTime = pair.Value.iConnectTime;
if (AppTime.GetNowSysMs() - iConnectTime >= 10 * 1000)
{
TraceLog.Debug("VersionMsgHandler.UpdateClientConnect TimeOut Disconnect:{0} ", sessionID);
GateService.NotifyGateServerDisconnect(GetApp(), gateServerID, sessionID);
m_versionSvc.RemoveClientConnectData(gateServerID, sessionID);
break;
}
}
}
}
}