163 lines
4.1 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|