using System; using System.Collections.Generic; using ZeroLevel; using ZeroLevel.Services.HashFunctions; using ZeroLevel.Services.Serialization; namespace Server { public class Info : IBinarySerializable { public uint Id; public uint Length; public uint Checksum; public void Deserialize(IBinaryReader reader) { this.Id = reader.ReadUInt32(); this.Length = reader.ReadUInt32(); this.Checksum = reader.ReadUInt32(); } public void Serialize(IBinaryWriter writer) { writer.WriteUInt32(this.Id); writer.WriteUInt32(this.Length); writer.WriteUInt32(this.Checksum); } } public class Fragment : IBinarySerializable { public uint Id; public uint Offset; public uint Checksum; public byte[] Payload; public void Deserialize(IBinaryReader reader) { this.Id = reader.ReadUInt32(); this.Offset = reader.ReadUInt32(); this.Checksum = reader.ReadUInt32(); this.Payload = reader.ReadBytes(); } public void Serialize(IBinaryWriter writer) { writer.WriteUInt32(this.Id); writer.WriteUInt32(this.Offset); writer.WriteUInt32(this.Checksum); writer.WriteBytes(this.Payload); } } public class Data { public uint Checksum; public uint Length; public uint ActualLength; public byte[] Payload; } class Program { private readonly static Dictionary _incoming = new Dictionary(); private readonly static XXHashUnsafe _hash = new XXHashUnsafe(667); static void Main(string[] args) { Log.AddConsoleLogger(ZeroLevel.Logging.LogLevel.Warning); var ex = Bootstrap.CreateExchange(); var port = ReadPort(); var server = ex.UseHost(port); server.RegisterInbox("time", (c, s) => { Log.Info($"Request time: [{s}]"); return DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"); }); server.RegisterInbox("whois", (c, s) => { Log.Info($"Request whois: [{s}]"); return $"[{Environment.MachineName}] {Environment.UserDomainName}\\{Environment.UserName}"; }); server.RegisterInbox("start", (c, i) => { Start(i); return true; }); server.RegisterInbox("part", (c, p) => { return WriteFragment(p); }); server.RegisterInbox("complete", (c, id) => Complete(id)); Log.Warning("Started"); server.OnConnect += Server_OnConnect; server.OnDisconnect += Server_OnDisconnect; Console.ReadKey(); } private static void Start(Info info) { var data = new Data { Checksum = info.Checksum, ActualLength = 0, Length = info.Length, Payload = new byte[info.Length] }; _incoming.Add(info.Id, data); Log.Info($"Start incoming data id '{info.Id}'. {info.Length} bytes. Checksum: {info.Checksum}"); } private static bool WriteFragment(Fragment fragment) { var checksum = _hash.Hash(fragment.Payload); if (checksum != fragment.Checksum) { Log.Warning($"[WriteFragment] Wrong checksum (checksum: {checksum} expected: {fragment.Checksum})! ID: '{fragment.Id}'. Offset: '{fragment.Offset}'. Length: '{fragment.Payload.Length}' bytes."); return false; } if (!_incoming.ContainsKey(fragment.Id)) { Log.Warning($"[WriteFragment] Data ID: '{fragment.Id}' not found. Offset: '{fragment.Offset}'. Length: '{fragment.Payload.Length}' bytes."); return false; } Array.Copy(fragment.Payload, 0, _incoming[fragment.Id].Payload, fragment.Offset, fragment.Payload.Length); return true; } private static void Complete(uint id) { if (_incoming.ContainsKey(id)) { var checksum = _hash.Hash(_incoming[id].Payload); if (checksum != _incoming[id].Checksum) { Log.Warning($"[Complete] Wrong checksum (checksum: {checksum} expected: {_incoming[id].Checksum})! ID: '{id}'"); } else { Log.Info($"Data '{id}' successfully received"); } _incoming.Remove(id); } else { Log.Warning($"[Complete] Data ID '{id}' not found"); } } private static void Server_OnDisconnect(ZeroLevel.Network.ISocketClient obj) { Log.Info($"Client disconnected: {obj.Endpoint.Address}:{obj.Endpoint.Port}"); } private static void Server_OnConnect(ZeroLevel.Network.IClient obj) { Log.Info($"Client connected: {obj.Endpoint.Address}:{obj.Endpoint.Port}"); } static int ReadPort() { int port = -1; do { Console.WriteLine("PORT>"); var port_line = Console.ReadLine(); if (int.TryParse(port_line, out port) == false || port <= 0) { port = -1; Console.WriteLine($"Incorrect port '{port_line}'"); } } while (port <= 0); return port; } } }