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); } }
public async Task SendMessageAsync(Message message) { try { await semaphore.DoAsync(async() => { using (var stream = new NetworkStream(socket)) { var stopwatch = Stopwatch.StartNew(); using (var byteStream = new MemoryStream()) using (var writer = new BinaryWriter(byteStream)) { NetworkEncoder.EncodeMessage(writer, message); var messageBytes = byteStream.ToArray(); await stream.WriteAsync(messageBytes, 0, messageBytes.Length); } stopwatch.Stop(); if (logger.IsTraceEnabled) { logger.Trace($"Sent {message.Command} in {stopwatch.ElapsedMilliseconds} ms\nPayload: {message.Payload.ToArray().ToHexDataString()}"); } } }); } catch (Exception e) { Fail(e); } }
public async Task SendVersion(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, UInt64 nodeId, UInt32 startBlockHeight) { var versionPayload = Messaging.ConstructVersionPayload(localEndPoint, remoteEndPoint, nodeId, startBlockHeight); var versionMessage = Messaging.ConstructMessage("version", NetworkEncoder.EncodeVersionPayload(versionPayload, withRelay: false)); await SendMessageAsync(versionMessage); }
public async Task SendGetBlocks(ImmutableArray <UInt256> blockLocatorHashes, UInt256 hashStop) { var getBlocksPayload = Messaging.ConstructGetBlocksPayload(blockLocatorHashes, hashStop); var getBlocksMessage = Messaging.ConstructMessage("getblocks", NetworkEncoder.EncodeGetBlocksPayload(getBlocksPayload)); await SendMessageAsync(getBlocksMessage); }
public async Task SendGetData(ImmutableArray <InventoryVector> invVectors) { await Task.Yield(); var getDataPayload = Messaging.ConstructInventoryPayload(invVectors); var getDataMessage = Messaging.ConstructMessage("getdata", NetworkEncoder.EncodeInventoryPayload(getDataPayload)); await SendMessageAsync(getDataMessage); }
public async Task SendInventory(ImmutableArray <InventoryVector> invVectors) { await Task.Yield(); var invPayload = Messaging.ConstructInventoryPayload(invVectors); var invMessage = Messaging.ConstructMessage("inv", NetworkEncoder.EncodeInventoryPayload(invPayload)); await SendMessageAsync(invMessage); }
private async Task <Message> WireDecodeMessage(UInt32 magic) { var command = DataDecoder.DecodeFixedString(await ReceiveExactly(12)); var payloadSize = DataDecoder.DecodeUInt32(await ReceiveExactly(4)); var payloadChecksum = DataDecoder.DecodeUInt32(await ReceiveExactly(4)); var payload = await ReceiveExactly(payloadSize.ToIntChecked()); if (!Messaging.VerifyPayloadChecksum(payloadChecksum, payload)) { throw new Exception($"Checksum failed for {command}"); } var message = new Message ( Magic: magic, Command: command, PayloadSize: payloadSize, PayloadChecksum: payloadChecksum, Payload: payload.ToImmutableArray() ); switch (message.Command) { case "addr": { var addressPayload = NetworkEncoder.DecodeAddressPayload(payload); OnReceivedAddresses?.Invoke(owner, addressPayload.NetworkAddresses); } break; case "alert": { var alertPayload = NetworkEncoder.DecodeAlertPayload(payload); } break; case "block": { var block = DataDecoder.DecodeBlock(null, payload); OnBlock?.Invoke(owner, block); } break; case "getblocks": { var getBlocksPayload = NetworkEncoder.DecodeGetBlocksPayload(payload); OnGetBlocks?.Invoke(owner, getBlocksPayload); } break; case "getheaders": { var getHeadersPayload = NetworkEncoder.DecodeGetBlocksPayload(payload); OnGetHeaders?.Invoke(owner, getHeadersPayload); } break; case "getdata": { var invPayload = NetworkEncoder.DecodeInventoryPayload(payload); OnGetData?.Invoke(owner, invPayload); } break; case "headers": { var blockHeaders = ImmutableList.CreateBuilder <BlockHeader>(); var offset = 0; var headerCount = payload.ReadVarInt(ref offset).ToIntChecked(); for (var i = 0; i < headerCount; i++) { var blockHeader = DataDecoder.DecodeBlockHeader(null, payload, ref offset); // ignore tx count var int payload.ReadVarInt(ref offset); blockHeaders.Add(blockHeader); } OnBlockHeaders?.Invoke(owner, blockHeaders.ToImmutable()); } break; case "inv": { var invPayload = NetworkEncoder.DecodeInventoryPayload(payload); OnInventoryVectors?.Invoke(owner, invPayload.InventoryVectors); } break; case "notfound": { var invPayload = NetworkEncoder.DecodeInventoryPayload(payload); OnNotFound?.Invoke(owner, invPayload.InventoryVectors); } break; case "ping": { OnPing?.Invoke(owner, payload.ToImmutableArray()); } break; case "tx": { var tx = DataDecoder.DecodeEncodedTx(null, payload); OnTransaction?.Invoke(owner, tx); } break; case "version": { var versionPayload = NetworkEncoder.DecodeVersionPayload(payload, payload.Length); OnVersion?.Invoke(owner, versionPayload); } break; case "verack": { OnVersionAcknowledged?.Invoke(owner); } break; default: { logger.Warn($"Unhandled incoming message: {message.Command}"); } break; } //TODO //if (payloadStream.Position != payloadStream.Length) //{ // var exMessage = $"Wrong number of bytes read for {message.Command}, parser error: read {payloadStream.Position} bytes from a {payloadStream.Length} byte payload"; // Debug.WriteLine(exMessage); // throw new Exception(exMessage); //} return(message); }
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); }