|
|
@@ -1,7 +1,8 @@
|
|
|
-using System;
|
|
|
+using System;
|
|
|
using System.IO;
|
|
|
using System.Net;
|
|
|
using System.Net.Sockets;
|
|
|
+using System.Threading.Tasks;
|
|
|
using Helper;
|
|
|
using Log;
|
|
|
using Org.BouncyCastle.Utilities.Encoders;
|
|
|
@@ -15,6 +16,7 @@ namespace Robot
|
|
|
public class RealmSession: IDisposable
|
|
|
{
|
|
|
private readonly NetworkStream networkStream;
|
|
|
+ private RealmInfo realmInfo = new RealmInfo();
|
|
|
|
|
|
public RealmSession(string host, ushort port)
|
|
|
{
|
|
|
@@ -51,7 +53,7 @@ namespace Robot
|
|
|
|
|
|
public async void SendMessage<T>(ushort opcode, T message)
|
|
|
{
|
|
|
- byte[] protoBytes = ProtobufHelper.ProtoToBytes(message);
|
|
|
+ byte[] protoBytes = ProtobufHelper.ToBytes(message);
|
|
|
var neworkBytes = new byte[sizeof(int) + sizeof(ushort) + protoBytes.Length];
|
|
|
|
|
|
int totalSize = sizeof(ushort) + protoBytes.Length;
|
|
|
@@ -67,31 +69,107 @@ namespace Robot
|
|
|
await networkStream.WriteAsync(neworkBytes, 0, neworkBytes.Length);
|
|
|
}
|
|
|
|
|
|
- public void Login(string account, string password)
|
|
|
+ public async Task<bool> Handle_CMSG_AuthLogonPermit_Response()
|
|
|
{
|
|
|
- try
|
|
|
+ var result = await RecvMessage();
|
|
|
+ ushort opcode = result.Item1;
|
|
|
+ byte[] message = result.Item2;
|
|
|
+
|
|
|
+ if (opcode == 0)
|
|
|
+ {
|
|
|
+ Logger.Trace("opcode == 0");
|
|
|
+ throw new RealmException("opcode == 0");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (opcode == MessageOpcode.SMSG_LOCK_FOR_SAFE_TIME)
|
|
|
+ {
|
|
|
+ var smsgLockForSafeTime =
|
|
|
+ ProtobufHelper.FromBytes<SMSG_Lock_For_Safe_Time>(message);
|
|
|
+ Logger.Trace("account lock time: {0}", smsgLockForSafeTime.Time);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (opcode != MessageOpcode.SMSG_PASSWORD_PROTECT_TYPE)
|
|
|
+ {
|
|
|
+ throw new RealmException(string.Format("error opcode: {0}", opcode));
|
|
|
+ }
|
|
|
+
|
|
|
+ var smsgPasswordProtectType =
|
|
|
+ ProtobufHelper.FromBytes<SMSG_Password_Protect_Type>(message);
|
|
|
+ this.realmInfo.SmsgPasswordProtectType = smsgPasswordProtectType;
|
|
|
+
|
|
|
+ Logger.Trace("message: {0}", JsonHelper.ToString(smsgPasswordProtectType));
|
|
|
+
|
|
|
+ if (smsgPasswordProtectType.Code != 200)
|
|
|
{
|
|
|
- byte[] passwordBytes = password.ToByteArray();
|
|
|
- var digest = new MD5Digest();
|
|
|
- var passwordMd5 = new byte[digest.GetDigestSize()];
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- digest.BlockUpdate(passwordBytes, 0, passwordBytes.Length);
|
|
|
- digest.DoFinal(passwordMd5, 0);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
|
|
|
- var cmsgAuthLogonPermit = new CMSG_AuthLogonPermit
|
|
|
+ public async Task<Tuple<ushort, byte[]>> RecvMessage()
|
|
|
+ {
|
|
|
+ int totalReadSize = 0;
|
|
|
+ int needReadSize = sizeof (int);
|
|
|
+ var packetBytes = new byte[needReadSize];
|
|
|
+ while (totalReadSize != needReadSize)
|
|
|
+ {
|
|
|
+ int readSize = await networkStream.ReadAsync(packetBytes, totalReadSize, packetBytes.Length);
|
|
|
+ if (readSize == 0)
|
|
|
{
|
|
|
- Account = account,
|
|
|
- PasswordMd5 = Hex.ToHexString(passwordMd5)
|
|
|
- };
|
|
|
+ return new Tuple<ushort, byte[]>(0, new byte[] {});
|
|
|
+ }
|
|
|
+ totalReadSize += readSize;
|
|
|
+ }
|
|
|
|
|
|
- Logger.Debug("password: {0}", cmsgAuthLogonPermit.PasswordMd5);
|
|
|
+ int packetSize = BitConverter.ToInt32(packetBytes, 0);
|
|
|
|
|
|
- SendMessage(MessageOpcode.CMSG_AUTHLOGONPERMIT, cmsgAuthLogonPermit);
|
|
|
+ // 读opcode和message
|
|
|
+ totalReadSize = 0;
|
|
|
+ needReadSize = packetSize;
|
|
|
+ var contentBytes = new byte[needReadSize];
|
|
|
+ while (totalReadSize != needReadSize)
|
|
|
+ {
|
|
|
+ int readSize = await networkStream.ReadAsync(contentBytes, totalReadSize, contentBytes.Length);
|
|
|
+ if (readSize == 0)
|
|
|
+ {
|
|
|
+ return new Tuple<ushort, byte[]>(0, new byte[] {});
|
|
|
+ }
|
|
|
+ totalReadSize += readSize;
|
|
|
}
|
|
|
- catch (SocketException e)
|
|
|
+ ushort opcode = BitConverter.ToUInt16(contentBytes, 0);
|
|
|
+ var messageBytes = new byte[needReadSize - sizeof(ushort)];
|
|
|
+ Array.Copy(contentBytes, sizeof (ushort), messageBytes, 0, messageBytes.Length);
|
|
|
+
|
|
|
+ return new Tuple<ushort, byte[]>(opcode, messageBytes);
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task<bool> Login(string account, string password)
|
|
|
+ {
|
|
|
+ byte[] passwordBytes = password.ToByteArray();
|
|
|
+ var digest = new MD5Digest();
|
|
|
+ var passwordMd5 = new byte[digest.GetDigestSize()];
|
|
|
+
|
|
|
+ digest.BlockUpdate(passwordBytes, 0, passwordBytes.Length);
|
|
|
+ digest.DoFinal(passwordMd5, 0);
|
|
|
+
|
|
|
+ var cmsgAuthLogonPermit = new CMSG_AuthLogonPermit
|
|
|
+ {
|
|
|
+ Account = account,
|
|
|
+ PasswordMd5 = Hex.ToHexString(passwordMd5)
|
|
|
+ };
|
|
|
+
|
|
|
+ this.SendMessage(MessageOpcode.CMSG_AUTHLOGONPERMIT, cmsgAuthLogonPermit);
|
|
|
+
|
|
|
+ bool result = await Handle_CMSG_AuthLogonPermit_Response();
|
|
|
+
|
|
|
+ if (result == false)
|
|
|
{
|
|
|
- Logger.Debug("socket exception, error: {}", e.ErrorCode);
|
|
|
+ return false;
|
|
|
}
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|
|
|
}
|