Beispiel #1
2
        public async Task SendMessageAsync(Message message)
        {
            try
            {
                await semaphore.DoAsync(async () =>
                {
                    using (var stream = new NetworkStream(this.socket))
                    {
                        var stopwatch = new Stopwatch();
                        stopwatch.Start();

                        var byteStream = new MemoryStream();
                        NetworkEncoder.EncodeMessage(byteStream, message);

                        var messageBytes = byteStream.ToArray();
                        await stream.WriteAsync(messageBytes, 0, messageBytes.Length);

                        stopwatch.Stop();
                        //Debug.WriteLine("-------------------------");
                        //Debug.WriteLine(string.Format("Sent {0} in {1} ms\nPayload: {2}", message.Command, stopwatch.ElapsedMilliseconds, message.Payload.ToHexDataString()));
                    }
                });
            }
            catch (Exception e)
            {
                Fail(e);
            }
        }
Beispiel #2
0
        public static Message ConstructMessage(string command, byte[] payload)
        {
            var message = new Message
            (
                Magic: Messaging.Magic,
                Command: command,
                PayloadSize: (UInt32)payload.Length,
                PayloadChecksum: CalculatePayloadChecksum(payload),
                Payload: payload.ToImmutableArray()
            );

            return message;
        }
Beispiel #3
0
 public static void EncodeMessage(Stream stream, Message message)
 {
     using (var writer = new BinaryWriter(stream, Encoding.ASCII, leaveOpen: true))
     {
         writer.Write4Bytes(message.Magic);
         writer.WriteFixedString(12, message.Command);
         writer.Write4Bytes(message.PayloadSize);
         writer.Write4Bytes(message.PayloadChecksum);
         writer.WriteBytes(message.PayloadSize.ToIntChecked(), message.Payload.ToArray());
     }
 }
Beispiel #4
0
 public static byte[] EncodeMessage(Message message)
 {
     var stream = new MemoryStream();
     EncodeMessage(stream, message);
     return stream.ToArray();
 }
Beispiel #5
0
        private Message WireDecodeMessage(UInt32 magic, Stream stream)
        {
            byte[] payload;
            Message message;
            using (var reader = new BinaryReader(stream, Encoding.ASCII, leaveOpen: true))
            {
                var command = reader.ReadFixedString(12);
                var payloadSize = reader.Read4Bytes();
                var payloadChecksum = reader.Read4Bytes();

                payload = reader.ReadBytes(payloadSize.ToIntChecked());

                if (!Messaging.VerifyPayloadChecksum(payloadChecksum, payload))
                    throw new Exception(string.Format("Checksum failed for {0}", command));

                message = new Message
                (
                    Magic: magic,
                    Command: command,
                    PayloadSize: payloadSize,
                    PayloadChecksum: payloadChecksum,
                    Payload: payload.ToImmutableArray()
                );
            }

            switch (message.Command)
            {
                case "addr":
                    {
                        var addressPayload = NetworkEncoder.DecodeAddressPayload(payload.ToMemoryStream());

                        var handler = this.OnReceivedAddresses;
                        if (handler != null)
                            handler(addressPayload.NetworkAddresses);
                    }
                    break;

                case "alert":
                    {
                        var alertPayload = NetworkEncoder.DecodeAlertPayload(payload.ToMemoryStream());
                    }
                    break;

                case "block":
                    {
                        var block = NetworkEncoder.DecodeBlock(payload.ToMemoryStream());

                        var handler = this.OnBlock;
                        if (handler != null)
                            handler(block);
                    }
                    break;

                case "getblocks":
                    {
                        var getBlocksPayload = NetworkEncoder.DecodeGetBlocksPayload(payload.ToMemoryStream());

                        var handler = this.OnGetBlocks;
                        if (handler != null)
                            handler(getBlocksPayload);
                    }
                    break;

                case "getheaders":
                    {
                        var getHeadersPayload = NetworkEncoder.DecodeGetBlocksPayload(payload.ToMemoryStream());

                        var handler = this.OnGetHeaders;
                        if (handler != null)
                            handler(getHeadersPayload);
                    }
                    break;

                case "headers":
                    {
                        var headerStream = payload.ToMemoryStream();
                        using (var reader = new BinaryReader(headerStream))
                        {
                            var headerCount = reader.ReadVarInt().ToIntChecked();

                            for (var i = 0; i < headerCount; i++)
                            {
                                var blockHeader = NetworkEncoder.DecodeBlockHeader(headerStream);
                                //TODO wiki says this is a byte and a var int, which is it?
                                var txCount = reader.ReadVarInt();

                                var handler = this.OnBlockHeader;
                                if (handler != null)
                                    handler(blockHeader);
                            }
                        }
                    }
                    break;

                case "inv":
                    {
                        var invPayload = NetworkEncoder.DecodeInventoryPayload(payload.ToMemoryStream());

                        var handler = this.OnInventoryVectors;
                        if (handler != null)
                            handler(invPayload.InventoryVectors);
                    }
                    break;

                case "notfound":
                    {
                        var invPayload = NetworkEncoder.DecodeInventoryPayload(payload.ToMemoryStream());

                        var handler = this.OnNotFound;
                        if (handler != null)
                            handler(invPayload.InventoryVectors);
                    }
                    break;

                case "ping":
                    {
                        var handler = this.OnPing;
                        if (handler != null)
                            handler(payload.ToImmutableArray());
                    }
                    break;

                case "tx":
                    {
                        var tx = NetworkEncoder.DecodeTransaction(payload.ToMemoryStream());

                        var handler = this.OnTransaction;
                        if (handler != null)
                            handler(tx);
                    }
                    break;

                case "version":
                    {
                        var versionPayload = NetworkEncoder.DecodeVersionPayload(payload.ToMemoryStream(), payload.Length);
                        //Debug.WriteLine(string.Format("{0}, {1}", versionPayload.RemoteAddress.ToIPEndPoint(), this.socket.RemoteEndPoint));

                        var handler = this.OnVersion;
                        if (handler != null)
                            handler(versionPayload);
                    }
                    break;

                case "verack":
                    {
                        var handler = this.OnVersionAcknowledged;
                        if (handler != null)
                            handler();
                    }
                    break;

                default:
                    {
                        Debug.WriteLine("Unhandled incoming message: {0}".Format2(message.Command));
                    }
                    break;
            }

            //TODO
            //if (payloadStream.Position != payloadStream.Length)
            //{
            //    var exMessage = string.Format("Wrong number of bytes read for {0}, parser error: read {1} bytes from a {2} byte payload", message.Command, payloadStream.Position, payloadStream.Length);
            //    Debug.WriteLine(exMessage);
            //    throw new Exception(exMessage);
            //}

            return message;
        }