Light12306/ChatRoomServer.Main/Entities/EntityUtility.cs
2015-07-03 21:04:37 +08:00

163 lines
4.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ChatRoomServer.Main.Entities
{
using System.IO;
using System.Threading;
class EntityUtility
{
static readonly string EncryptKey = "iFishMessagePack";
static readonly byte[] EncryptKeyBuffer = Encoding.ASCII.GetBytes(EncryptKey);
static readonly int EncStart = 1;
static readonly Random Random = new Random();
public static MessageItem FromBuffer(byte[] buffer)
{
if (buffer.Length < 1 + EncryptKeyBuffer.Length || buffer[0] >= EncryptKeyBuffer.Length)
return null;
//decrypt key
var key = EncryptKeyBuffer[buffer[0]];
for (int i = EncStart; i < buffer.Length; i++)
{
var tkey = key;
key = buffer[i];
buffer[i] ^= tkey;
}
//read prefix
var index = 1;
if (Encoding.ASCII.GetString(buffer, index, EncryptKeyBuffer.Length) != EncryptKey)
return null;
index += EncryptKeyBuffer.Length;
var item = new MessageItem();
item.Action = ReadString(buffer, ref index);
item.Success = buffer[index++] == 1;
item.Time = System.FishDateTimeExtension.JsTicksStartBase.AddTicks(BitConverter.ToInt64(buffer, index) * 10000);
index += 8;
item.SystemMessage = buffer[index++] == 1;
item.SysMsgType = (SystemMessageType)BitConverter.ToInt32(buffer, index);
index += 4;
item.UserMsgType = (UserMessageType)BitConverter.ToInt32(buffer, index);
index += 4;
item.Content = ReadString(buffer, ref index);
item.Color = ReadString(buffer, ref index);
//images
var imgCount = BitConverter.ToInt32(buffer, index);
index += 4;
if (imgCount > 0)
{
item.Images = new string[imgCount];
for (int i = 0; i < imgCount; i++)
{
item.Images[i] = ReadString(buffer, ref index);
}
}
//from
item.From = ReadString(buffer, ref index);
//to
var tousersCount = BitConverter.ToInt32(buffer, index);
index += 4;
if (tousersCount > 0)
{
item.ToUsers = new string[tousersCount];
for (int i = 0; i < tousersCount; i++)
{
item.ToUsers[i] = ReadString(buffer, ref index);
}
}
return item;
}
static string ReadString(byte[] data, ref int index)
{
var unicode = data[index++] == 1;
var length = BitConverter.ToInt32(data, index);
index += 4;
var result = (unicode ? Encoding.Unicode : Encoding.ASCII).GetString(data, index, length);
index += length;
return result;
}
public static byte[] ToBuffer(MessageItem item)
{
var length = (item.Content?.Length ?? 0) * 3 + 100;
var randomKeyIndex = Random.Next(EncryptKey.Length);
var randomKey = (byte)EncryptKey[randomKeyIndex];
using (var ms = new MemoryStream(length))
{
//1. write encrypt key
ms.Write(new byte[] { (byte)randomKeyIndex });
//1. write package header
ms.Write(EncryptKeyBuffer);
//3. write action
Write(ms, item.Action, false);
//4. write success
ms.Write(new[] { (byte)(item.Success ? 1 : 0) });
//5. write time
ms.Write(item.Time.ToJsTicks());
//6. system message
ms.Write(new[] { (byte)(item.SystemMessage ? 1 : 0) });
//7.
ms.Write((int)item.SysMsgType);
//8.
ms.Write((int)item.UserMsgType);
//9. content
Write(ms, item.Content, true);
//10. color
Write(ms, item.Color, false);
//11. images
ms.Write(item.Images?.Length ?? 0);
if (item.Images != null)
{
foreach (var image in item.Images)
{
Write(ms, image, false);
}
}
//12. from user
Write(ms, item.From, false);
//13. to user
ms.Write(item.ToUsers?.Length ?? 0);
if (item.ToUsers != null)
{
foreach (var user in item.ToUsers)
{
Write(ms, user, false);
}
}
var data = ms.ToArray();
for (int i = EncStart; i < data.Length; i++)
{
randomKey = data[i] ^= randomKey;
}
return data;
}
}
static void Write(Stream stream, string text, bool unicode = true)
{
text = text ?? "";
var buffer = unicode ? Encoding.Unicode.GetBytes(text) : Encoding.ASCII.GetBytes(text);
stream.Write(new[] { (byte)(unicode ? 1 : 0) });
stream.Write(buffer.Length);
stream.Write(buffer);
}
}
}