private async Task StartReadAsync() { while (!_cancellationToken.IsCancellationRequested && (_pipe?.IsConnected == true)) { try { byte[] header = new byte[HEADER_SIZE]; await _pipe.ReadAsync(header.AsMemory(0, header.Length), _cancellationToken.Token); RpcPacketType opCode = (RpcPacketType)BitConverter.ToInt32(header.AsSpan()); int dataLength = BitConverter.ToInt32(header.AsSpan(4)); if (dataLength == 0)//if this is zero it means the pipe closed { break; } byte[] dataBuffer = new byte[dataLength]; await _pipe.ReadAsync(dataBuffer.AsMemory(0, dataBuffer.Length), _cancellationToken.Token); await ProcessPipeMessageAsync(opCode, Encoding.UTF8.GetString(dataBuffer)); } catch (Exception exc) { _logger.Error("Discord Pipe read error", exc); throw; } } _logger.Information("Stopped reading from discord pipe"); }
private DhtRpcPacket(int transactionID, NodeContact sourceNode, RpcPacketType type, RpcQueryType queryType) { _transactionID = transactionID; _sourceNode = sourceNode; _type = type; _queryType = queryType; }
private async Task ProcessPipeMessageAsync(RpcPacketType opCode, string data) { if (opCode == RpcPacketType.PING) { SendPacket(data, RpcPacketType.PONG); return; } if (opCode == RpcPacketType.HANDSHAKE) { if (string.IsNullOrEmpty(data)) { //probably close? } else { //probably restart? } //SendPacket(new { v = RPC_VERSION, client_id = clientId.Value }, RpcPacketType.HANDSHAKE); //happens when closing discord and artemis is open? //TODO: investigate } if (opCode == RpcPacketType.CLOSE) { _logger.Error("Discord pipe connection closed: {data}", data); return; } IDiscordMessage discordMessage; try { discordMessage = JsonConvert.DeserializeObject <IDiscordMessage>(data, _jsonSerializerSettings); } catch (Exception exc) { _logger.Error(exc, "Error deserializing discord message: {data}", data); return; } _logger.Verbose("Received discord message: {data}", data); if (discordMessage is DiscordResponse discordResponse) { await ProcessDiscordResponseAsync(discordResponse); } else if (discordMessage is DiscordEvent discordEvent) { await ProcessDiscordEventAsync(discordEvent); } else { _logger.Error("Received unexpected discord message: {data}", data); } }
private void SendPacket(object obj, RpcPacketType opcode = RpcPacketType.FRAME) { string stringData = JsonConvert.SerializeObject(obj, _jsonSerializerSettings); byte[] data = Encoding.UTF8.GetBytes(stringData); int dataLength = data.Length; byte[] sendBuff = new byte[dataLength + HEADER_SIZE]; BinaryWriter writer = new BinaryWriter(new MemoryStream(sendBuff)); writer.Write((int)opcode); writer.Write(dataLength); writer.Write(data); _pipe.Write(sendBuff); _logger.Verbose("Sent discord message: {stringData}", stringData); }
public DhtRpcPacket(Stream s, IPAddress nodeIP) { int version = s.ReadByte(); switch (version) { case 1: byte[] buffer = new byte[20]; OffsetStream.StreamRead(s, buffer, 0, 4); _transactionID = BitConverter.ToInt32(buffer, 0); OffsetStream.StreamRead(s, buffer, 0, 20); BinaryID nodeID = BinaryID.Clone(buffer, 0, 20); OffsetStream.StreamRead(s, buffer, 0, 2); _sourceNode = new NodeContact(nodeID, new IPEndPoint(nodeIP, BitConverter.ToUInt16(buffer, 0))); _type = (RpcPacketType)s.ReadByte(); _queryType = (RpcQueryType)s.ReadByte(); switch (_queryType) { case RpcQueryType.FIND_NODE: OffsetStream.StreamRead(s, buffer, 0, 20); _networkID = BinaryID.Clone(buffer, 0, 20); if (_type == RpcPacketType.Response) { int count = s.ReadByte(); _contacts = new NodeContact[count]; for (int i = 0; i < count; i++) { _contacts[i] = new NodeContact(s); } } break; case RpcQueryType.FIND_PEERS: OffsetStream.StreamRead(s, buffer, 0, 20); _networkID = BinaryID.Clone(buffer, 0, 20); if (_type == RpcPacketType.Response) { int count = s.ReadByte(); _contacts = new NodeContact[count]; for (int i = 0; i < count; i++) { _contacts[i] = new NodeContact(s); } count = s.ReadByte(); _peers = new PeerEndPoint[count]; for (int i = 0; i < count; i++) { _peers[i] = new PeerEndPoint(s); } OffsetStream.StreamRead(s, buffer, 0, 20); _token = new BinaryID(buffer); } break; case RpcQueryType.ANNOUNCE_PEER: OffsetStream.StreamRead(s, buffer, 0, 20); _networkID = BinaryID.Clone(buffer, 0, 20); if (_type == RpcPacketType.Query) { OffsetStream.StreamRead(s, buffer, 0, 2); _servicePort = BitConverter.ToUInt16(buffer, 0); OffsetStream.StreamRead(s, buffer, 0, 20); _token = new BinaryID(buffer); } break; } break; default: throw new IOException("DHT-RPC packet version not supported: " + version); } }