Преглед изворни кода

登录已经OK,可以向world发送消息了!

tanghai пре 13 година
родитељ
комит
b71d275677

+ 10 - 2
CSharp/App/LoginClient/ENetChannel.cs

@@ -5,6 +5,7 @@ using System.Text;
 using System.Threading.Tasks;
 using ENet;
 using Helper;
+using Log;
 
 namespace LoginClient
 {
@@ -41,8 +42,15 @@ namespace LoginClient
 				byte[] bytes = packet.Bytes;
 				const int opcodeSize = sizeof(ushort);
 				ushort opcode = BitConverter.ToUInt16(bytes, 0);
-				var messageBytes = new byte[packet.Length - opcodeSize];
-				Array.Copy(bytes, opcodeSize, messageBytes, 0, messageBytes.Length);
+				const int flagSize = sizeof (ushort);
+				ushort flag = BitConverter.ToUInt16(bytes, opcodeSize);
+				if (flag != 0)
+				{
+					Logger.Debug("packet zip");
+					throw new LoginException("packet zip!");
+				}
+				var messageBytes = new byte[packet.Length - opcodeSize - flagSize];
+				Array.Copy(bytes, opcodeSize + flagSize, messageBytes, 0, messageBytes.Length);
 				return Tuple.Create(opcode, messageBytes);
 			}
 		}

+ 39 - 11
CSharp/App/LoginClient/GateSession.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Numerics;
@@ -15,10 +16,16 @@ namespace LoginClient
 
 		public IMessageChannel IMessageChannel { get; set; }
 
+		public readonly Dictionary<ushort, Action<byte[]>> messageHandlers = 
+			new Dictionary<ushort, Action<byte[]>>();
+
+		public bool IsStop { get; set; }
+
 		public GateSession(int id, IMessageChannel eNetChannel)
 		{
 			this.ID = id;
 			this.IMessageChannel = eNetChannel;
+			this.IsStop = false;
 		}
 
 		public void Dispose()
@@ -26,14 +33,35 @@ namespace LoginClient
 			this.IMessageChannel.Dispose();
 		}
 
-		public async void Login(SRP6Client srp6Client)
+		public async Task HandleMessages()
+		{
+			while (!this.IsStop)
+			{
+				var result = await this.IMessageChannel.RecvMessage();
+				ushort opcode = result.Item1;
+				byte[] message = result.Item2;
+				if (!messageHandlers.ContainsKey(opcode))
+				{
+					Logger.Debug("not found opcode: {0}", opcode);
+					continue;
+				}
+				messageHandlers[opcode](message);
+			}
+		}
+
+		public void SendMessage<T>(ushort opcode, T message, byte channelID = 0)
+		{
+			this.IMessageChannel.SendMessage(opcode, message, channelID);
+		}
+
+		public async Task Login(SRP6Client srp6Client)
 		{
 			var smsgAuthChallenge = await this.Handle_SMSG_Auth_Challenge();
 
 			var clientSeed = (uint)TimeHelper.EpochTimeSecond();
 			byte[] digest = srp6Client.CalculateGateDigest(clientSeed, smsgAuthChallenge.Seed);
 
-			var cmsgAuthSession = new CMSG_Auth_Session()
+			var cmsgAuthSession = new CMSG_Auth_Session
 			{
 				ClientBuild = 11723,
 				ClientSeed = clientSeed,
@@ -47,7 +75,14 @@ namespace LoginClient
 			};
 			this.IMessageChannel.SendMessage(MessageOpcode.CMSG_AUTH_SESSION, cmsgAuthSession);
 
-			await Handle_SMSG_Auth_Response();
+			var smsgAuthResponse = await Handle_SMSG_Auth_Response();
+
+			if (smsgAuthResponse.ErrorCode != ErrorCode.AUTH_OK)
+			{
+				throw new LoginException(string.Format(
+					"session: {0}, SMSG_Auth_Response: {1}",
+					this.ID, JsonHelper.ToString(smsgAuthResponse)));
+			}
 
 			Logger.Trace("session: {0}, login gate OK!", this.ID);
 		}
@@ -57,6 +92,7 @@ namespace LoginClient
 			var result = await this.IMessageChannel.RecvMessage();
 			ushort opcode = result.Item1;
 			byte[] message = result.Item2;
+			Logger.Debug("message: {0}", message.ToHex());
 			if (opcode != MessageOpcode.SMSG_AUTH_CHALLENGE)
 			{
 				throw new LoginException(string.Format(
@@ -80,14 +116,6 @@ namespace LoginClient
 			}
 
 			var smsgAuthResponse = ProtobufHelper.FromBytes<SMSG_Auth_Response>(message);
-
-			if (smsgAuthResponse.ErrorCode != 0)
-			{
-				throw new LoginException(string.Format(
-					"session: {0}, SMSG_Auth_Response: {1}",
-					this.ID, JsonHelper.ToString(smsgAuthResponse)));
-			}
-
 			return smsgAuthResponse;
 		}
 	}

+ 16 - 5
CSharp/App/LoginClient/LoginClient.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Net.Sockets;
 using ENet;
 using Log;
@@ -8,8 +9,10 @@ namespace LoginClient
 	public class LoginClient : IDisposable
     {
 		private int sessionId;
-
+		
 		private readonly ClientHost clientHost = new ClientHost();
+
+		private GateSession gateSession;
 		
 		public void Dispose()
 		{
@@ -31,9 +34,9 @@ namespace LoginClient
 		{
 			++this.sessionId;
 
+			// 登录realm
 			var tcpClient = new TcpClient();
 			await tcpClient.ConnectAsync(hostName, port);
-
 			Tuple<string, ushort, SRP6Client> realmInfo = null; // ip, port, K
 			using (var realmSession = new RealmSession(this.sessionId, new TcpChannel(tcpClient)))
 			{
@@ -43,10 +46,18 @@ namespace LoginClient
 
 			// 登录gate
 			Peer peer = await this.clientHost.ConnectAsync(realmInfo.Item1, realmInfo.Item2);
-			using (var gateSession = new GateSession(this.sessionId, new ENetChannel(peer)))
+			gateSession = new GateSession(this.sessionId, new ENetChannel(peer));
+			await gateSession.Login(realmInfo.Item3);
+			await gateSession.HandleMessages();
+		}
+
+		public void SendCommand(string command)
+		{
+			var cmsgBossGm = new CMSG_Boss_Gm
 			{
-				gateSession.Login(realmInfo.Item3);
-			}
+				Message = command
+			};
+			this.gateSession.SendMessage(MessageOpcode.CMSG_BOSS_GM, cmsgBossGm);
 		}
     }
 }

+ 25 - 9
CSharp/App/LoginClient/Messages.cs

@@ -5,7 +5,9 @@ namespace LoginClient
 {
 	public static class MessageOpcode
 	{
+		// realm message opcode
 		public const ushort CMSG_REALM_LIST = 16;
+		public const ushort CMSG_BOSS_GM = 17;
 		public const ushort CMSG_AUTH_LOGON_PERMIT = 800;
 		public const ushort CMSG_OTP_PASSWORD = 801;
 		public const ushort CMSG_PPC_PASSWORD = 802;
@@ -18,14 +20,17 @@ namespace LoginClient
 		public const ushort SMSG_PASSWORD_PROTECT_TYPE = 904;
 		public const ushort SMSG_AUTH_LOGON_PROOF_M2 = 905;
 
-		// Gate Message Opcode
+		// gate message opcode
 		public const ushort CMSG_AUTH_SESSION = 2;
 		public const ushort SMSG_AUTH_CHALLENGE = 502;
 		public const ushort SMSG_AUTH_RESPONSE = 503;
+
+		public const ushort SMSG_SERVERTIME = 510;
 	}
 
 	public static class ErrorCode
 	{
+		// realm error code
 		public const int REALM_AUTH_SUCCESS = 0;
 		// Unable to connect
 		public const int REALM_AUTH_FAILURE = 1;
@@ -71,6 +76,10 @@ namespace LoginClient
 		// Access to this account has been blocked by parental controls.
 		// Your settings may be changed in your account preferences at site.
 		public const int REALM_AUTH_PARENTAL_CONTROL = 15;
+
+
+		// 其它error code
+		public const int AUTH_OK = 12;
 	}
 
 	[DataContract]
@@ -172,28 +181,28 @@ namespace LoginClient
 		[DataMember(Order = 1, IsRequired = true)]
 		public uint ClientBuild { get; set; }
 
-		[DataMember(Order = 1, IsRequired = true)]
+		[DataMember(Order = 2, IsRequired = true)]
 		public uint Unk2 { get; set; }
 
-		[DataMember(Order = 1, IsRequired = true)]
+		[DataMember(Order = 3, IsRequired = true)]
 		public byte[] Username { get; set; }
 
-		[DataMember(Order = 1, IsRequired = true)]
+		[DataMember(Order = 4, IsRequired = true)]
 		public uint Unk3 { get; set; }
 
-		[DataMember(Order = 1, IsRequired = true)]
+		[DataMember(Order = 5, IsRequired = true)]
 		public uint ClientSeed { get; set; }
 
-		[DataMember(Order = 1, IsRequired = true)]
+		[DataMember(Order = 6, IsRequired = true)]
 		public uint Unk4 { get; set; }
 
-		[DataMember(Order = 1, IsRequired = true)]
+		[DataMember(Order = 7, IsRequired = true)]
 		public byte[] Digest { get; set; }
 
-		[DataMember(Order = 1, IsRequired = false)]
+		[DataMember(Order = 8, IsRequired = false)]
 		public byte[] Mac { get; set; }
 
-		[DataMember(Order = 1, IsRequired = false)]
+		[DataMember(Order = 9, IsRequired = false)]
 		public byte[] Hd { get; set; }
 	}
 
@@ -217,4 +226,11 @@ namespace LoginClient
 		[DataMember(Order = 1, IsRequired = true)]
 		public uint ErrorCode { get; set; }
 	}
+
+	[DataContract]
+	public class CMSG_Boss_Gm
+	{
+		[DataMember(Order = 1, IsRequired = true)]
+		public string Message { get; set; }
+	}
 }

+ 5 - 1
CSharp/App/Modules/Robot/RobotView.xaml

@@ -16,9 +16,13 @@
 				<TextBox Width="120" Text="{Binding Account}" />
 				<Label Content="Password: "></Label>
 				<TextBox Width="120" Text="{Binding Password}" />
-				<Button Name="btnStart" Content="Login" Width="80" Height="25" Click="btnLogin_Click" />
+				<Button Name="btnLogin" Content="Login" Width="80" Height="25" Click="btnLogin_Click" />
 				<TextBlock></TextBlock>
 			</StackPanel>
+			<StackPanel Orientation="Horizontal">
+				<TextBox Name="tbCommand" Width="400" Text="{Binding Command}"></TextBox>
+				<Button Name="btnSendCommand" Content="发送" Click="btnSendCommand_Click" IsEnabled="False"></Button>
+			</StackPanel>
 		</StackPanel>
 	</Grid>
 </UserControl>

+ 6 - 0
CSharp/App/Modules/Robot/RobotView.xaml.cs

@@ -31,6 +31,12 @@ namespace Modules.Robot
 		private void btnLogin_Click(object sender, RoutedEventArgs e)
 		{
 			this.ViewModel.Login();
+			this.btnSendCommand.IsEnabled = true;
+		}
+
+		private void btnSendCommand_Click(object sender, RoutedEventArgs e)
+		{
+			this.ViewModel.SendCommand();
 		}
 	}
 }

+ 23 - 1
CSharp/App/Modules/Robot/RobotViewModel.cs

@@ -14,6 +14,7 @@ namespace Modules.Robot
 		private ushort loginPort = 8888;
 		private string account = "egametang@163.com";
 		private string password = "163bio1";
+		private string command = "";
 		private readonly LoginClient.LoginClient loginClient = new LoginClient.LoginClient();
 
 		private readonly DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Normal)
@@ -87,6 +88,23 @@ namespace Modules.Robot
 			}
 		}
 
+		public string Command
+		{
+			get
+			{
+				return this.command;
+			}
+			set
+			{
+				if (this.command == value)
+				{
+					return;
+				}
+				this.command = value;
+				this.RaisePropertyChanged("Command");
+			}
+		}
+
 		public RobotViewModel()
 		{
 			this.timer.Tick += delegate { this.loginClient.RunOnce(); };
@@ -113,7 +131,6 @@ namespace Modules.Robot
 		{
 			try
 			{
-				// 登录
 				this.loginClient.Login(
 					this.LoginIP, this.LoginPort, this.Account, this.Password);
 			}
@@ -122,5 +139,10 @@ namespace Modules.Robot
 				Logger.Trace("realm exception: {0}, {1}", e.Message, e.StackTrace);
 			}
 		}
+
+		public void SendCommand()
+		{
+			this.loginClient.SendCommand(this.Command);
+		}
 	}
 }