270 lines
9.0 KiB
C#
270 lines
9.0 KiB
C#
using System;
|
||
using System.IO;
|
||
using System.Net;
|
||
using UnityEngine;
|
||
using zlib;
|
||
|
||
namespace BF
|
||
{
|
||
/// <summary>
|
||
/// @TODO GC
|
||
/// </summary>
|
||
internal class NetChannelMessageService : INetChannelMessageService
|
||
{
|
||
private readonly bool isLittleEndian;
|
||
private readonly bool isCompress;
|
||
|
||
private NetAesEncrypt encrypt;
|
||
private NetAesEncrypt decrypt;
|
||
|
||
/// <summary>
|
||
/// 数据包的头部长度,version + Compress + Seq + Group + Cmd 共8位
|
||
/// </summary>
|
||
private int HeaderLength => 4;
|
||
|
||
/// <summary>
|
||
/// 数据包头部长度,使用int类型表示,四个字节
|
||
/// </summary>
|
||
private int HeaderLengthBytesSize => 4;
|
||
|
||
public NetChannelMessageService()
|
||
{
|
||
isLittleEndian = BitConverter.IsLittleEndian;
|
||
isCompress = false;
|
||
}
|
||
|
||
public void SetEncrypt(NetAesEncrypt encrypt)
|
||
{
|
||
this.encrypt = encrypt;
|
||
}
|
||
|
||
public void SetDecrypt(NetAesEncrypt decrypt)
|
||
{
|
||
this.decrypt = decrypt;
|
||
}
|
||
|
||
public int ReadBodyLength(CircularBuffer circularBuffer)
|
||
{
|
||
int bodyLength = 0;
|
||
if (circularBuffer.HowManyCanRead >= HeaderLengthBytesSize)
|
||
{
|
||
byte[] head1 = circularBuffer.Read(HeaderLengthBytesSize);
|
||
byte[] head = new byte[4];
|
||
head[0] = head1[3];
|
||
head[1] = head1[2];
|
||
head[2] = head1[1];
|
||
head[3] = head1[0];
|
||
bodyLength = BitConverter.ToInt32(head, 0);
|
||
if (isLittleEndian)
|
||
{
|
||
bodyLength = IPAddress.NetworkToHostOrder(bodyLength);
|
||
}
|
||
if (bodyLength <= 0)
|
||
{
|
||
bodyLength = -1;
|
||
}
|
||
}
|
||
return bodyLength;
|
||
}
|
||
|
||
public bool Serialize(NetOutgoingMessage message, MemoryStream destination)
|
||
{
|
||
try
|
||
{
|
||
//first write data package size, packageSize = header.length + data.length
|
||
byte[] packageLengthData = null;
|
||
// short packageLength = 0;
|
||
int packageLength = 0;
|
||
if (message.Group != 0)
|
||
{
|
||
// packageLength = (short)(message.PackDataLength + HeaderLength);
|
||
packageLength = message.PackDataLength + HeaderLength*2;
|
||
}
|
||
else
|
||
{
|
||
// packageLength = (short)message.PackDataLength;
|
||
packageLength = message.PackDataLength;
|
||
}
|
||
|
||
if (isLittleEndian)
|
||
{
|
||
packageLengthData = BitConverter.GetBytes(packageLength);
|
||
}
|
||
else
|
||
{
|
||
packageLengthData = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(packageLength));
|
||
}
|
||
|
||
destination.Write(packageLengthData, 0, packageLengthData.Length);
|
||
|
||
var realSendBuffer = SerializeRaw(message);
|
||
|
||
//is need encrypt
|
||
if (message.Group != 0)
|
||
{
|
||
if (encrypt == null)
|
||
{
|
||
throw new NotImplementedException("Serialize Error! NetAesEncrypt is null");
|
||
}
|
||
encrypt.Encrypt(realSendBuffer, 0, realSendBuffer.Length, realSendBuffer, 0);
|
||
}
|
||
|
||
destination.Write(realSendBuffer, 0, realSendBuffer.Length);
|
||
return true;
|
||
|
||
}
|
||
catch (Exception)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
internal byte[] SerializeRaw(NetOutgoingMessage message)
|
||
{
|
||
if (message.Group != 0)
|
||
{
|
||
byte[] realSendBuffer = new byte[message.PackDataLength + HeaderLength*2];
|
||
byte[] seqBytes = null;
|
||
if (isLittleEndian)
|
||
{
|
||
seqBytes = BitConverter.GetBytes(message.Seq);
|
||
}
|
||
else
|
||
{
|
||
seqBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(message.Seq));
|
||
}
|
||
|
||
Array.Copy(seqBytes, 0, realSendBuffer, 0, HeaderLength);
|
||
|
||
//create send buffer
|
||
if (BitConverter.IsLittleEndian)
|
||
{
|
||
realSendBuffer[7] = (byte)((message.Group >> 24) & 0xFF);
|
||
realSendBuffer[6] = (byte)((message.Group >> 16) & 0xFF);
|
||
realSendBuffer[5] = (byte)((message.Group >> 8) & 0xFF);
|
||
realSendBuffer[4] = (byte)(message.Group & 0xFF);
|
||
}
|
||
else
|
||
{
|
||
realSendBuffer[4] = (byte)((message.Group >> 24) & 0xFF);
|
||
realSendBuffer[5] = (byte)((message.Group >> 16) & 0xFF);
|
||
realSendBuffer[6] = (byte)((message.Group >> 8) & 0xFF);
|
||
realSendBuffer[7] = (byte)(message.Group & 0xFF);
|
||
}
|
||
|
||
//write data
|
||
Array.Copy(message.Data, 0, realSendBuffer, HeaderLength*2, message.PackDataLength);
|
||
return realSendBuffer;
|
||
}
|
||
else
|
||
{
|
||
//create send buffer
|
||
byte[] realSendBuffer = new byte[message.PackDataLength];
|
||
|
||
Array.Copy(message.Data, 0, realSendBuffer, 0, message.PackDataLength);
|
||
|
||
return realSendBuffer;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// @TODO Array GC
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
/// <returns></returns>
|
||
public bool Deserialize(NetIncomingMessage message, uint receiveSeq)
|
||
{
|
||
try
|
||
{
|
||
decrypt.Decrypt(message.buffer, 0, message.buffer.Length, message.buffer, 0);
|
||
DeserializeRaw(message, receiveSeq);
|
||
if (message.IsCompress)
|
||
{
|
||
message.buffer = DeCompressBuffer(message.buffer);
|
||
}
|
||
|
||
return true;
|
||
|
||
}
|
||
catch (Exception)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
internal void DeserializeRaw(NetIncomingMessage message, uint receiveSeq)
|
||
{
|
||
//head
|
||
// message.Version = message.buffer[0];
|
||
// message.IsCompress = message.buffer[1] != 0;
|
||
// message.Group = message.buffer[2];
|
||
// message.CMD = message.buffer[3];
|
||
|
||
message.Group = (uint)(((message.buffer[7] & 0xFF) << 24)
|
||
| ((message.buffer[6] & 0xFF) << 16)
|
||
| ((message.buffer[5] & 0xFF) << 8)
|
||
| (message.buffer[4] & 0xFF));
|
||
|
||
message.CMD = receiveSeq;
|
||
var seq = BitConverter.ToInt32(message.buffer, 0);
|
||
if (isLittleEndian)
|
||
{
|
||
message.Seq = (uint) seq;
|
||
}
|
||
else
|
||
{
|
||
message.Seq = (uint) IPAddress.NetworkToHostOrder(seq);
|
||
}
|
||
|
||
//data, @TODO only copy
|
||
Array.Reverse(message.buffer);
|
||
Array.Resize(ref message.buffer, message.buffer.Length - HeaderLength*2);
|
||
Array.Reverse(message.buffer);
|
||
}
|
||
|
||
private byte[] DeCompressBuffer(byte[] byteArray)
|
||
{
|
||
using (MemoryStream outMemoryStream = new MemoryStream())
|
||
{
|
||
using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream))
|
||
{
|
||
using (Stream inMemoryStream = new MemoryStream(byteArray))
|
||
{
|
||
byte[] buffer = new byte[inMemoryStream.Length];
|
||
int len;
|
||
while ((len = inMemoryStream.Read(buffer, 0, buffer.Length)) > 0)
|
||
{
|
||
outZStream.Write(buffer, 0, len);
|
||
}
|
||
outZStream.Flush();
|
||
outZStream.finish();
|
||
return outMemoryStream.ToArray();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private byte[] CompressBuffer(byte[] byteArray)
|
||
{
|
||
using (MemoryStream outMemoryStream = new MemoryStream())
|
||
{
|
||
using (ZInputStream zInputStream = new ZInputStream(outMemoryStream))
|
||
{
|
||
using (Stream inMemoryStream = new MemoryStream(byteArray))
|
||
{
|
||
byte[] buffer = new byte[inMemoryStream.Length];
|
||
int len;
|
||
while ((len = inMemoryStream.Read(buffer, 0, buffer.Length)) > 0)
|
||
{
|
||
zInputStream.Read(buffer, 0, len);
|
||
}
|
||
|
||
inMemoryStream.Flush();
|
||
return outMemoryStream.ToArray();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
} |