// Notifies a peer with a command, no response expected internal void Reply(LevinPeer Peer, int CommandCode, byte[] Data, bool RequestSuccessul = false, bool ResponseRequired = false) { // Form message header BucketHead2 Header = new BucketHead2 { Signature = GlobalsConfig.LEVIN_SIGNATURE, ResponseRequired = ResponseRequired, PayloadSize = (ulong)Data.Length, CommandCode = (uint)CommandCode, ProtocolVersion = GlobalsConfig.LEVIN_VERSION, Flags = LEVIN_PACKET_RESPONSE, ReturnCode = RequestSuccessul? LEVIN_RETCODE_SUCCESS : LEVIN_RETCODE_FAILURE }; // Debug Logger?.Log(Level.DEBUG, "Sending header:"); Logger?.Log(Level.DEBUG, " - Signature: {0}", Header.Signature); Logger?.Log(Level.DEBUG, " - Payload Size: {0}", Header.PayloadSize); Logger?.Log(Level.DEBUG, " - Response Required: {0}", Header.ResponseRequired); Logger?.Log(Level.DEBUG, " - Command Code: {0}", Header.CommandCode); Logger?.Log(Level.DEBUG, " - Return Code: {0}", Header.ReturnCode); Logger?.Log(Level.DEBUG, " - Flags: {0}", Header.Flags); Logger?.Log(Level.DEBUG, " - Protocol Version: {0}", Header.ProtocolVersion); // Send header packet if (Server.SendMessage(Peer.Connection, Header.Serialize())) { // Send body packet Server.SendMessage(Peer.Connection, Data); } }
// Notifies a peer with a command, no response expected public void Reply(LevinPeer Peer, int CommandCode, byte[] Data, bool RequestSuccessul = false, bool ResponseRequired = false) { // Form message header BucketHead2 Header = new BucketHead2 { Signature = GlobalsConfig.LEVIN_SIGNATURE, ResponseRequired = ResponseRequired, PayloadSize = (ulong)Data.Length, CommandCode = (uint)CommandCode, ProtocolVersion = GlobalsConfig.LEVIN_VERSION, Flags = LEVIN_PACKET_RESPONSE, ReturnCode = RequestSuccessul? LEVIN_RETCODE_SUCCESS : LEVIN_RETCODE_FAILURE }; // Debug ConsoleMessage.WriteLine(ConsoleMessage.DefaultColor, "Sending header:", LogLevel.DEBUG); ConsoleMessage.WriteLine(ConsoleMessage.DefaultColor, " - Signature: " + Header.Signature, LogLevel.DEBUG); ConsoleMessage.WriteLine(ConsoleMessage.DefaultColor, " - Payload Size: " + Header.PayloadSize, LogLevel.DEBUG); ConsoleMessage.WriteLine(ConsoleMessage.DefaultColor, " - Response Required: " + Header.ResponseRequired, LogLevel.DEBUG); ConsoleMessage.WriteLine(ConsoleMessage.DefaultColor, " - Command Code: " + Header.CommandCode, LogLevel.DEBUG); ConsoleMessage.WriteLine(ConsoleMessage.DefaultColor, " - Return Code: " + Header.ReturnCode, LogLevel.DEBUG); ConsoleMessage.WriteLine(ConsoleMessage.DefaultColor, " - Flags: " + Header.Flags, LogLevel.DEBUG); ConsoleMessage.WriteLine(ConsoleMessage.DefaultColor, " - Protocol Version: " + Header.ProtocolVersion, LogLevel.DEBUG); // Send header packet if (Server.SendMessage(Peer.Connection, Header.Serialize())) { // Send body packet Server.SendMessage(Peer.Connection, Data); } }
// Deserializes the header information from a byte array internal static BucketHead2 Deserialize(byte[] Data) { try { // Create a header object BucketHead2 Head = new BucketHead2(); // Create a working byte array byte[] CurrentBytes = new byte[0]; // Decode signature CurrentBytes = new byte[8]; Buffer.BlockCopy(Data, 0, CurrentBytes, 0, CurrentBytes.Length); Head.Signature = Encoding.ByteArrayToInteger <ulong>(CurrentBytes); // Decode payload size CurrentBytes = new byte[8]; Buffer.BlockCopy(Data, 8, CurrentBytes, 0, CurrentBytes.Length); Head.PayloadSize = Encoding.ByteArrayToInteger <ulong>(CurrentBytes); // Decode response required CurrentBytes = new byte[1]; Buffer.BlockCopy(Data, 16, CurrentBytes, 0, CurrentBytes.Length); Head.ResponseRequired = Convert.ToBoolean(CurrentBytes[0]); // Decode command code CurrentBytes = new byte[4]; Buffer.BlockCopy(Data, 17, CurrentBytes, 0, CurrentBytes.Length); Head.CommandCode = Encoding.ByteArrayToInteger <uint>(CurrentBytes); // Decode return code CurrentBytes = new byte[4]; Buffer.BlockCopy(Data, 21, CurrentBytes, 0, CurrentBytes.Length); Head.ReturnCode = Encoding.ByteArrayToInteger <int>(CurrentBytes); // Decode flags CurrentBytes = new byte[4]; Buffer.BlockCopy(Data, 25, CurrentBytes, 0, CurrentBytes.Length); Head.Flags = Encoding.ByteArrayToInteger <uint>(CurrentBytes); // Decode protocol version CurrentBytes = new byte[4]; Buffer.BlockCopy(Data, 29, CurrentBytes, 0, CurrentBytes.Length); Head.ProtocolVersion = Encoding.ByteArrayToInteger <uint>(CurrentBytes); // Return header object return(Head); } catch { return(default(BucketHead2)); } }
// Notifies all peers with a command, no response expected internal void NotifyAll(int CommandCode, byte[] Data) { // Form message header BucketHead2 Header = new BucketHead2 { Signature = GlobalsConfig.LEVIN_SIGNATURE, ResponseRequired = false, PayloadSize = (ulong)Data.Length, CommandCode = (uint)CommandCode, ProtocolVersion = GlobalsConfig.LEVIN_VERSION, Flags = LEVIN_PACKET_REQUEST }; // Send header packet Server.Broadcast(Header.Serialize()); // Send body packet Server.Broadcast(Data); }
// Notifies a peer with a command, no response expected internal void Notify(PeerConnection Peer, int CommandCode, byte[] Data) { // Form message header BucketHead2 Header = new BucketHead2 { Signature = GlobalsConfig.LEVIN_SIGNATURE, ResponseRequired = false, PayloadSize = (ulong)Data.Length, CommandCode = (uint)CommandCode, ProtocolVersion = LEVIN_PROTOCOL_VER_1, Flags = LEVIN_PACKET_REQUEST }; // Send header packet if (Server.SendMessage(Peer, Header.Serialize())) { // Send body packet Server.SendMessage(Peer, Data); } }
// Data received private void OnDataReceived(object sender, EventArgs e) { // Get packet data Packet Packet = (Packet)sender; LevinPeer Peer = Peers[Packet.Peer]; // Read header if (Peer.ReadStatus == PacketReadStatus.Head) { // Decode header try { Peer.Header = BucketHead2.Deserialize(Packet.Data); } catch { Logger?.Log(Level.DEBUG, "Could not deserialize incoming packet header, incorrect format"); return; } // Set peer data Peer.Data = Packet.Data; // Debug /*Logger?.Log(Level.DEBUG, "Received header:"); * Logger?.Log(Level.DEBUG, " - Signature: {0}", Peers[Packet.Peer].Header.Signature); * Logger?.Log(Level.DEBUG, " - Payload Size: {0}", Peers[Packet.Peer].Header.PayloadSize); * Logger?.Log(Level.DEBUG, " - Response Required: {0}", Peers[Packet.Peer].Header.ResponseRequired); * Logger?.Log(Level.DEBUG, " - Command Code: {0}", Peers[Packet.Peer].Header.CommandCode); * Logger?.Log(Level.DEBUG, " - Return Code: {0}", Peers[Packet.Peer].Header.ReturnCode); * Logger?.Log(Level.DEBUG, " - Flags: {0}", Peers[Packet.Peer].Header.Flags); * Logger?.Log(Level.DEBUG, " - Protocol Version: {0}", Peers[Packet.Peer].Header.ProtocolVersion);*/ // Check that signature matches if (Peer.Header.Signature != GlobalsConfig.LEVIN_SIGNATURE) { Logger?.Log(Level.DEBUG, "Incoming packet signature mismatch, expected {0}, received {1}", GlobalsConfig.LEVIN_SIGNATURE, Peers[Packet.Peer].Header.Signature); return; } // Check packet size if (Peer.Header.PayloadSize > GlobalsConfig.LEVIN_MAX_PACKET_SIZE) { Logger?.Log(Level.DEBUG, "Incoming packet size is too big, max size is {0}, received {1}", GlobalsConfig.LEVIN_MAX_PACKET_SIZE, Packet.Data.Length); return; } // Set new read status if (Peer.Header.PayloadSize > 0) { Peers[Packet.Peer].ReadStatus = PacketReadStatus.Body; } } // Add data to peer buffer if reading message body else { // Add bytes to peer buffer byte[] NewData = new byte[Peer.Data.Length + Packet.Data.Length]; Buffer.BlockCopy(Peer.Data, 0, NewData, 0, Peer.Data.Length); Buffer.BlockCopy(Packet.Data, 0, NewData, Peer.Data.Length, Packet.Data.Length); Peer.Data = NewData; } // Check if data size matches payload size and that a header has been decoded if (Peer.ReadStatus == PacketReadStatus.Body && (ulong)Peer.Data.Length >= Peer.Header.PayloadSize) { // Get header BucketHead2 Header = Peer.Header; // Decode command Command Command = new Command { CommandCode = Header.CommandCode, IsNotification = !Header.ResponseRequired, IsResponse = (Header.Flags & LEVIN_PACKET_RESPONSE) == LEVIN_PACKET_RESPONSE, Data = Encoding.SplitByteArray(Peers[Packet.Peer].Data, 33, (int)Peers[Packet.Peer].Header.PayloadSize) }; // Check if peer requires a handshake if (Command.CommandCode == Commands.Handshake.Id) { Commands.Handshake.Invoke(this, Peer, Command); // 1001 } else if (Peer.State == PeerState.Verified) { // Invoke other commands if (Command.CommandCode == Commands.Ping.Id) { Commands.Ping.Invoke(this, Peer, Command); // 1002 } else if (Command.CommandCode == Commands.TimedSync.Id) { Commands.TimedSync.Invoke(this, Peer, Command); // 1003 } else if (Command.CommandCode == Commands.NotifyRequestChain.Id) { Commands.NotifyRequestChain.Invoke(this, Peer, Command); // 2006 } else if (Command.CommandCode == Commands.RequestTxPool.Id) { Commands.RequestTxPool.Invoke(this, Peer, Command); // 2008 } } // Debug else if (Peer.State == PeerState.Unverified) { Logger?.Log(Level.DEBUG, "[IN] Received command:"); Logger?.Log(Level.DEBUG, " - Command Code: {0}", Command.CommandCode); Logger?.Log(Level.DEBUG, " - Is Notification: {0}", Command.IsNotification); Logger?.Log(Level.DEBUG, " - Is Response: {0}", Command.IsResponse); Logger?.Log(Level.DEBUG, " - Data: {0} Bytes", Command.Data.Length); Logger?.Log(Level.DEBUG, Encoding.ByteArrayToHexString(Command.Data)); } // Set new read status and clear previous request Peer.ReadStatus = PacketReadStatus.Head; Peer.Header = default(BucketHead2); Peer.Data = new byte[0]; } }