using System; using System.Collections.Generic; using System.Text; using CommonNetwork.Sockets; using CommonLang.Protocol; using RoomService.Net.BsServer; using CommonLang.Log; using RoomService.Net.BsClient; using CommonAI.ZoneClient; using CommonAI.Zone; using CommonLang.IO; using CommonAI.Zone.ZoneEditor; using CommonAI.ZoneServer; using CommonLang.Concurrent; using CommonNetwork.Net; using CommonLang.Property; using CommonAI.Zone.Helper; using CommonLang; using CommonAI; using System.IO; namespace CommonAIClient.Client { public class BattleClientProxy : BattleClient { private static Logger log = LoggerFactory.GetLogger("BattleClientProxy"); private INetSession proxy_session; private enum Status : int { ON_LINE, OFF_LINE, } private AtomicState<Status> status = new AtomicState<Status>(Status.OFF_LINE); public override INetSession Session { get { return proxy_session; } } public BattleClientProxy( INetSession netSession, EditorTemplates data_root, MessageFactoryGenerator msgFactory, PlayerWillConnectResponseB2R room, PlayerWillConnectRequestR2B testToken, string token) : base(data_root, msgFactory, room, testToken, token) { this.proxy_session = netSession; } public BattleClientProxy( ProxyNetSession proxySession, string proxySessionConnectString, EditorTemplates data_root, MessageFactoryGenerator msgFactory, PlayerWillConnectResponseB2R room, PlayerWillConnectRequestR2B testToken, string token) : base(data_root, msgFactory, room, testToken, token) { this.proxy_session = proxySession; this.proxy_session.Open(proxySessionConnectString, new SynchronizedBattleCodec(DataRoot.Templates), new DirectProxyListener(this)); } protected override void Disposing() { this.Stop(); base.Disposing(); } public override void Start() { if (status.ChangeState(Status.ON_LINE)) { proxy_session.OnMessageReceived += proxy_session_OnMessageReceived; proxy_session.OnMessageSent += proxy_session_OnMessageSent; proxy_session.OnError += proxy_session_OnError; proxy_session.Send(new ConnectToProxy(room.Room.ClientConnectString)); base.callback_sessionOpened(proxy_session); } } public override void Stop() { if (status.ChangeState(Status.OFF_LINE)) { proxy_session.OnMessageReceived -= proxy_session_OnMessageReceived; proxy_session.OnMessageSent -= proxy_session_OnMessageSent; proxy_session.OnError -= proxy_session_OnError; base.callback_sessionClosed(proxy_session); } } //---------------------------------------------------------------------------------------------------- private void proxy_session_OnMessageReceived(INetSession session, object data) { if (data is DisconnectFromProxy) { Stop(); } else { base.callback_messageReceived(session, data); } } private void proxy_session_OnMessageSent(INetSession session, object data) { base.callback_messageSent(session, data); } private void proxy_session_OnError(INetSession session, Exception err) { base.callback_onError(session, err); } //---------------------------------------------------------------------------------------------------- class DirectProxyListener : INetSessionListener { private BattleClientProxy mClient; public DirectProxyListener(BattleClientProxy client) { this.mClient = client; } public void sessionOpened(INetSession session) { } public void sessionClosed(INetSession session) { } public void messageReceived(INetSession session, object data) { } public void messageSent(INetSession session, object data) { } public void onError(INetSession session, Exception err) { } } //---------------------------------------------------------------------------------------------------- /// <summary> /// 将游戏服和战斗服合并成一个连接,需要连接代理服务器 /// </summary> public abstract class ProxyNetSession : NetSession { public readonly byte TYPE_GS = 1; public readonly byte TYPE_BS = 2; public static int DEFAULT_BUFFER_SIZE = 1024; public ProxyNetSession(byte type_gs_header = 1, byte type_bs_header = 2) { this.TYPE_GS = type_gs_header; this.TYPE_BS = type_bs_header; } protected override bool doEncode(Stream output, object message, out int writeBytes) { if (IsMessageTypeGS(message)) { return doEncodeGS(output, message, out writeBytes); } else if (message is IMessage) { return doEncodeBS(output, message as IMessage, out writeBytes); } writeBytes = 0; return false; } protected override bool doDecode(Stream input, out object message, out int readBytes) { int b0 = input.ReadByte(); int b1 = input.ReadByte(); int b2 = input.ReadByte(); int ServerID = input.ReadByte(); int BodySize = (int)(b0 | (b1 << 8) | (b2 << 16)); bool ret = false; object msg = null; if (ServerID == TYPE_BS) { ret = doDecodeBS(input, BodySize, out msg); } else if (ServerID == TYPE_GS) { ret = doDecodeGS(input, BodySize, out msg); } message = msg; readBytes = BodySize + 4; return ret; } protected virtual bool doDecodeBS(Stream input, int bodysize, out object message) { byte[] h_body = IOUtil.ReadExpect(input, bodysize); using (MemoryStream ms = new MemoryStream(h_body)) { if (mCodec.doDecode(ms, out message)) { return true; } } return false; } protected virtual bool doEncodeBS(Stream output, IMessage send_msg, out int sendBytes) { sendBytes = 0; using (MemoryStream ms = new MemoryStream(DEFAULT_BUFFER_SIZE)) { if (mCodec.doEncode(ms, send_msg)) { byte[] h_body = ms.GetBuffer(); int length = (int)ms.Position; { int BodySize = (int)(length); if (length > 0x00FFFFFF) { throw new Exception("Size Overflow"); } int b0 = ((BodySize & 0x000000FF)); int b1 = ((BodySize & 0x0000FF00) >> 8); int b2 = ((BodySize & 0x00FF0000) >> 16); output.WriteByte((byte)b0); output.WriteByte((byte)b1); output.WriteByte((byte)b2); output.WriteByte((byte)TYPE_BS); } output.Write(h_body, 0, length); sendBytes = length + 4; return true; } } return false; } public abstract bool IsMessageTypeGS(object msg); protected virtual bool doDecodeGS(Stream input, int bodysize, out object message) { message = null; return false; } protected virtual bool doEncodeGS(Stream output, object protocol, out int writeBytes) { writeBytes = 0; return false; } } } }