async Task RunMqttClientScenarioAsync(IChannel channel, ReadListeningHandler readListener) { await channel.WriteAndFlushAsync(new ConnectPacket { ClientId = ClientId, Username = "******", Password = "******", WillTopicName = "last/word", WillMessage = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("oops")) }); var connAckPacket = Assert.IsType <ConnAckPacket>(await readListener.ReceiveAsync()); Assert.Equal(ConnectReturnCode.Accepted, connAckPacket.ReturnCode); int subscribePacketId = GetRandomPacketId(); int unsubscribePacketId = GetRandomPacketId(); await channel.WriteAndFlushManyAsync( new SubscribePacket(subscribePacketId, new SubscriptionRequest(SubscribeTopicFilter1, QualityOfService.ExactlyOnce), new SubscriptionRequest(SubscribeTopicFilter2, QualityOfService.AtLeastOnce), new SubscriptionRequest("for/unsubscribe", QualityOfService.AtMostOnce)), new UnsubscribePacket(unsubscribePacketId, "for/unsubscribe")); var subAckPacket = Assert.IsType <SubAckPacket>(await readListener.ReceiveAsync()); Assert.Equal(subscribePacketId, subAckPacket.PacketId); Assert.Equal(3, subAckPacket.ReturnCodes.Count); Assert.Equal(QualityOfService.ExactlyOnce, subAckPacket.ReturnCodes[0]); Assert.Equal(QualityOfService.AtLeastOnce, subAckPacket.ReturnCodes[1]); Assert.Equal(QualityOfService.AtMostOnce, subAckPacket.ReturnCodes[2]); var unsubAckPacket = Assert.IsType <UnsubAckPacket>(await readListener.ReceiveAsync()); Assert.Equal(unsubscribePacketId, unsubAckPacket.PacketId); int publishQoS1PacketId = GetRandomPacketId(); await channel.WriteAndFlushManyAsync( new PublishPacket(QualityOfService.AtMostOnce, false, false) { TopicName = PublishC2STopic, Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(PublishC2SQos0Payload)) }, new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = publishQoS1PacketId, TopicName = PublishC2SQos1Topic, Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(PublishC2SQos1Payload)) }); //new PublishPacket(QualityOfService.AtLeastOnce, false, false) { TopicName = "feedback/qos/One", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("QoS 1 test. Different data length.")) }); var pubAckPacket = Assert.IsType <PubAckPacket>(await readListener.ReceiveAsync()); Assert.Equal(publishQoS1PacketId, pubAckPacket.PacketId); var publishPacket = Assert.IsType <PublishPacket>(await readListener.ReceiveAsync()); Assert.Equal(QualityOfService.AtLeastOnce, publishPacket.QualityOfService); Assert.Equal(PublishS2CQos1Topic, publishPacket.TopicName); Assert.Equal(PublishS2CQos1Payload, publishPacket.Payload.ToString(Encoding.UTF8)); await channel.WriteAndFlushManyAsync( PubAckPacket.InResponseTo(publishPacket), DisconnectPacket.Instance); }
Packet DecodePacketInternal(IByteBuffer buffer, int packetSignature, ref int remainingLength, IChannelHandlerContext context) { if (Signatures.IsPublish(packetSignature)) { var qualityOfService = (QualityOfService)((packetSignature >> 1) & 0x3); // take bits #1 and #2 ONLY and convert them into QoS value if (qualityOfService == QualityOfService.Reserved) { throw new DecoderException(string.Format("Unexpected QoS value of {0} for {1} packet.", (int)qualityOfService, PacketType.PUBLISH)); } bool duplicate = (packetSignature & 0x8) == 0x8; // test bit#3 bool retain = (packetSignature & 0x1) != 0; // test bit#0 var packet = new PublishPacket(qualityOfService, duplicate, retain); DecodePublishPacket(buffer, packet, ref remainingLength); return(packet); } switch (packetSignature) // strict match checks for valid message type + correct values in flags part { case Signatures.PubAck: var pubAckPacket = new PubAckPacket(); DecodePacketIdVariableHeader(buffer, pubAckPacket, ref remainingLength); return(pubAckPacket); case Signatures.PubRec: var pubRecPacket = new PubRecPacket(); DecodePacketIdVariableHeader(buffer, pubRecPacket, ref remainingLength); return(pubRecPacket); case Signatures.PubRel: var pubRelPacket = new PubRelPacket(); DecodePacketIdVariableHeader(buffer, pubRelPacket, ref remainingLength); return(pubRelPacket); case Signatures.PubComp: var pubCompPacket = new PubCompPacket(); DecodePacketIdVariableHeader(buffer, pubCompPacket, ref remainingLength); return(pubCompPacket); case Signatures.PingReq: this.ValidateServerPacketExpected(packetSignature); return(PingReqPacket.Instance); case Signatures.Subscribe: this.ValidateServerPacketExpected(packetSignature); var subscribePacket = new SubscribePacket(); DecodePacketIdVariableHeader(buffer, subscribePacket, ref remainingLength); DecodeSubscribePayload(buffer, subscribePacket, ref remainingLength); return(subscribePacket); case Signatures.Unsubscribe: this.ValidateServerPacketExpected(packetSignature); var unsubscribePacket = new UnsubscribePacket(); DecodePacketIdVariableHeader(buffer, unsubscribePacket, ref remainingLength); DecodeUnsubscribePayload(buffer, unsubscribePacket, ref remainingLength); return(unsubscribePacket); case Signatures.Connect: this.ValidateServerPacketExpected(packetSignature); var connectPacket = new ConnectPacket(); DecodeConnectPacket(buffer, connectPacket, ref remainingLength, context); return(connectPacket); case Signatures.Disconnect: this.ValidateServerPacketExpected(packetSignature); return(DisconnectPacket.Instance); case Signatures.ConnAck: this.ValidateClientPacketExpected(packetSignature); var connAckPacket = new ConnAckPacket(); DecodeConnAckPacket(buffer, connAckPacket, ref remainingLength); return(connAckPacket); case Signatures.SubAck: this.ValidateClientPacketExpected(packetSignature); var subAckPacket = new SubAckPacket(); DecodePacketIdVariableHeader(buffer, subAckPacket, ref remainingLength); DecodeSubAckPayload(buffer, subAckPacket, ref remainingLength); return(subAckPacket); case Signatures.UnsubAck: this.ValidateClientPacketExpected(packetSignature); var unsubAckPacket = new UnsubAckPacket(); DecodePacketIdVariableHeader(buffer, unsubAckPacket, ref remainingLength); return(unsubAckPacket); case Signatures.PingResp: this.ValidateClientPacketExpected(packetSignature); return(PingRespPacket.Instance); default: throw new DecoderException(string.Format("First packet byte value of `{0}` is invalid.", packetSignature)); } }
private async Task OnPacketReceived(Packet msg) { if (!Running) { return; } var writer = _outboundWriter; try { switch (msg.PacketType) { case PacketType.CONNACK: this.Log("Received CONNACK"); ConnectionData.UpdateAuth(((FbnsConnAckPacket)msg).Authentication); await RegisterMqttClient(); break; case PacketType.PUBLISH: this.Log("Received PUBLISH"); var publishPacket = (PublishPacket)msg; if (publishPacket.Payload == null) { throw new Exception($"{nameof(PushClient)}: Publish packet received but payload is null"); } if (publishPacket.QualityOfService == QualityOfService.AtLeastOnce) { await FbnsPacketEncoder.EncodePacket(PubAckPacket.InResponseTo(publishPacket), writer); } var payload = DecompressPayload(publishPacket.Payload); var json = Encoding.UTF8.GetString(payload); this.Log($"MQTT json: {json}"); switch (Enum.Parse(typeof(TopicIds), publishPacket.TopicName)) { case TopicIds.Message: try { var message = JsonConvert.DeserializeObject <PushReceivedEventArgs>(json); message.Json = json; if (message.NotificationContent.CollapseKey == "direct_v2_message") { MessageReceived?.Invoke(this, message); } } catch (Exception e) { // If something wrong happens here we don't need to shut down the whole push client DebugLogger.LogException(e); } break; case TopicIds.RegResp: await OnRegisterResponse(json); StartKeepAliveLoop(); break; default: this.Log($"Unknown topic received: {publishPacket.TopicName}"); break; } break; case PacketType.PUBACK: this.Log("Received PUBACK"); _waitingForPubAck = false; break; case PacketType.PINGRESP: this.Log("Received PINGRESP"); break; default: throw new NotSupportedException($"Packet type {msg.PacketType} is not supported."); } } catch (Exception e) { DebugLogger.LogException(e); } }
public static Packet DecodePacket(DataReader reader) { reader.ByteOrder = ByteOrder.BigEndian; int signature = reader.ReadByte(); int remainingLength = DecodeRemainingLength(reader); if (Signatures.IsPublish(signature)) { var qualityOfService = (QualityOfService)((signature >> 1) & 0x3); // take bits #1 and #2 ONLY and convert them into QoS value if (qualityOfService == QualityOfService.Reserved) { throw new Exception( $"Unexpected QoS value of {(int)qualityOfService} for {PacketType.PUBLISH} packet."); } bool duplicate = (signature & 0x8) == 0x8; // test bit#3 bool retain = (signature & 0x1) != 0; // test bit#0 var packet = new PublishPacket(qualityOfService, duplicate, retain); DecodePublishPacket(reader, packet, ref remainingLength); return(packet); } switch (signature & 240) // We don't care about flags for these packets { // case Signatures.Subscribe & 240: // var subscribePacket = new SubscribePacket(); // DecodePacketIdVariableHeader(reader, subscribePacket, ref remainingLength); // DecodeSubscribePayload(buffer, subscribePacket, ref remainingLength); // return subscribePacket; case Signatures.Connect: var connectPacket = new ConnectPacket(); DecodeConnectPacket(reader, connectPacket, ref remainingLength); return(connectPacket); case Signatures.PubAck: var pubAckPacket = new PubAckPacket(); DecodePacketIdVariableHeader(reader, pubAckPacket, ref remainingLength); return(pubAckPacket); case Signatures.ConnAck: var connAckPacket = new FbnsConnAckPacket(); DecodeConnAckPacket(reader, connAckPacket, ref remainingLength); return(connAckPacket); case Signatures.SubAck: var subAckPacket = new SubAckPacket(); DecodePacketIdVariableHeader(reader, subAckPacket, ref remainingLength); DecodeSubAckPayload(reader, subAckPacket, ref remainingLength); return(subAckPacket); case Signatures.UnsubAck: var unsubAckPacket = new UnsubAckPacket(); DecodePacketIdVariableHeader(reader, unsubAckPacket, ref remainingLength); return(unsubAckPacket); case Signatures.PingResp: return(PingRespPacket.Instance); default: throw new Exception($"Packet type {signature} not supported"); } }
Packet DecodePacketInternal(IByteBuffer buffer, int packetSignature, ref int remainingLength, IChannelHandlerContext context) { if (Signatures.IsPublish(packetSignature)) { var qualityOfService = (QualityOfService)((packetSignature >> 1) & 0x3); // take bits #1 and #2 ONLY and convert them into QoS value if (qualityOfService == QualityOfService.Reserved) { ThrowHelper.ThrowDecoderException_UnexpectedQoSValueForPublish(qualityOfService); } bool duplicate = (packetSignature & 0x8) == 0x8; // test bit#3 bool retain = (packetSignature & 0x1) != 0; // test bit#0 var packet = new PublishPacket(qualityOfService, duplicate, retain); DecodePublishPacket(buffer, packet, ref remainingLength); return(packet); } switch (packetSignature) // strict match checks for valid message type + correct values in flags part { case Signatures.PubAck: var pubAckPacket = new PubAckPacket(); DecodePacketIdVariableHeader(buffer, pubAckPacket, ref remainingLength); return(pubAckPacket); case Signatures.PubRec: var pubRecPacket = new PubRecPacket(); DecodePacketIdVariableHeader(buffer, pubRecPacket, ref remainingLength); return(pubRecPacket); case Signatures.PubRel: var pubRelPacket = new PubRelPacket(); DecodePacketIdVariableHeader(buffer, pubRelPacket, ref remainingLength); return(pubRelPacket); case Signatures.PubComp: var pubCompPacket = new PubCompPacket(); DecodePacketIdVariableHeader(buffer, pubCompPacket, ref remainingLength); return(pubCompPacket); case Signatures.PingReq: if (!_isServer) { ValidateServerPacketExpected(packetSignature); } return(PingReqPacket.Instance); case Signatures.Subscribe: if (!_isServer) { ValidateServerPacketExpected(packetSignature); } var subscribePacket = new SubscribePacket(); DecodePacketIdVariableHeader(buffer, subscribePacket, ref remainingLength); DecodeSubscribePayload(buffer, subscribePacket, ref remainingLength); return(subscribePacket); case Signatures.Unsubscribe: if (!_isServer) { ValidateServerPacketExpected(packetSignature); } var unsubscribePacket = new UnsubscribePacket(); DecodePacketIdVariableHeader(buffer, unsubscribePacket, ref remainingLength); DecodeUnsubscribePayload(buffer, unsubscribePacket, ref remainingLength); return(unsubscribePacket); case Signatures.Connect: if (!_isServer) { ValidateServerPacketExpected(packetSignature); } var connectPacket = new ConnectPacket(); DecodeConnectPacket(buffer, connectPacket, ref remainingLength, context); return(connectPacket); case Signatures.Disconnect: if (!_isServer) { ValidateServerPacketExpected(packetSignature); } return(DisconnectPacket.Instance); case Signatures.ConnAck: if (_isServer) { ValidateClientPacketExpected(packetSignature); } var connAckPacket = new ConnAckPacket(); DecodeConnAckPacket(buffer, connAckPacket, ref remainingLength); return(connAckPacket); case Signatures.SubAck: if (_isServer) { ValidateClientPacketExpected(packetSignature); } var subAckPacket = new SubAckPacket(); DecodePacketIdVariableHeader(buffer, subAckPacket, ref remainingLength); DecodeSubAckPayload(buffer, subAckPacket, ref remainingLength); return(subAckPacket); case Signatures.UnsubAck: if (_isServer) { ValidateClientPacketExpected(packetSignature); } var unsubAckPacket = new UnsubAckPacket(); DecodePacketIdVariableHeader(buffer, unsubAckPacket, ref remainingLength); return(unsubAckPacket); case Signatures.PingResp: if (_isServer) { ValidateClientPacketExpected(packetSignature); } return(PingRespPacket.Instance); default: return(ThrowHelper.FromDecoderException_FirstPacketByteValueIsInvalid(packetSignature)); } }
private void HandlePuback(PubAckPacket message) { }
async Task GetPart1SpecificSteps(IChannel channel, ReadListeningHandler readHandler) { int publishQoS1PacketId = GetRandomPacketId(); await channel.WriteAndFlushManyAsync( new PublishPacket(QualityOfService.AtMostOnce, false, false) { //TopicName = string.Format("devices/{0}/messages/log/verbose/", clientId), TopicName = $"devices/{this.clientId}/messages/events", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry-QoS0\"}")) }, new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = publishQoS1PacketId, TopicName = $"devices/{this.clientId}/messages/events", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry\"}")) }); Packet[] packets = (await Task.WhenAll(Enumerable.Repeat(0, 5).Select(_ => readHandler.ReceiveAsync()))) .Select(Assert.IsAssignableFrom <Packet>) .ToArray(); PubAckPacket pubAckPacket = Assert.Single(packets.OfType <PubAckPacket>()); Assert.Equal(publishQoS1PacketId, pubAckPacket.PacketId); PublishPacket publishQoS0Packet = Assert.Single(packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtMostOnce)); this.AssertPacketCoreValue(publishQoS0Packet, NotificationQoS0Content); PublishPacket publishQoS1Packet = Assert.Single(packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtLeastOnce)); this.AssertPacketCoreValue(publishQoS1Packet, NotificationQoS1Content); PublishPacket[] publishQoS2Packets = packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.ExactlyOnce).ToArray(); Assert.Equal(2, publishQoS2Packets.Length); PublishPacket publishQoS2Packet1 = publishQoS2Packets[0]; this.AssertPacketCoreValue(publishQoS2Packet1, NotificationQoS2Content); PublishPacket publishQoS2Packet2 = publishQoS2Packets[1]; this.AssertPacketCoreValue(publishQoS2Packet2, NotificationQoS2Content2); await channel.WriteAndFlushManyAsync( PubAckPacket.InResponseTo(publishQoS1Packet), PubRecPacket.InResponseTo(publishQoS2Packet1), PubRecPacket.InResponseTo(publishQoS2Packet2)); var pubRelQoS2Packet1 = Assert.IsAssignableFrom <PubRelPacket>(await readHandler.ReceiveAsync()); Assert.Equal(publishQoS2Packet1.PacketId, pubRelQoS2Packet1.PacketId); var pubRelQoS2Packet2 = Assert.IsAssignableFrom <PubRelPacket>(await readHandler.ReceiveAsync()); Assert.Equal(publishQoS2Packet2.PacketId, pubRelQoS2Packet2.PacketId); await channel.WriteAndFlushManyAsync( PubCompPacket.InResponseTo(pubRelQoS2Packet1), DisconnectPacket.Instance); // device queue still contains QoS 2 packet 2 which was PUBRECed but not PUBCOMPed. }
IEnumerable <TestScenarioStep> GetPart1SpecificSteps(Func <object> currentMessageFunc) { int publishQoS1PacketId = GetRandomPacketId(); yield return(TestScenarioStep.Write( new PublishPacket(QualityOfService.AtMostOnce, false, false) { //TopicName = string.Format("devices/{0}/messages/log/verbose/", clientId), TopicName = $"devices/{this.clientId}/messages/events", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry-QoS0\"}")) }, new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = publishQoS1PacketId, TopicName = $"devices/{this.clientId}/messages/events", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry\"}")) })); var packets = new Packet[5]; for (int i = packets.Length - 1; i >= 0; i--) { packets[i] = Assert.IsAssignableFrom <Packet>(currentMessageFunc()); if (i > 0) { yield return(TestScenarioStep.ReadMore()); } } PubAckPacket pubAckPacket = Assert.Single(packets.OfType <PubAckPacket>()); Assert.Equal(publishQoS1PacketId, pubAckPacket.PacketId); PublishPacket publishQoS0Packet = Assert.Single(packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtMostOnce)); this.AssertPacketCoreValue(publishQoS0Packet, NotificationQoS0Content); PublishPacket publishQoS1Packet = Assert.Single(packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtLeastOnce)); this.AssertPacketCoreValue(publishQoS1Packet, NotificationQoS1Content); PublishPacket[] publishQoS2Packets = packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.ExactlyOnce).Reverse().ToArray(); Assert.Equal(2, publishQoS2Packets.Length); PublishPacket publishQoS2Packet1 = publishQoS2Packets[0]; this.AssertPacketCoreValue(publishQoS2Packet1, NotificationQoS2Content); PublishPacket publishQoS2Packet2 = publishQoS2Packets[1]; this.AssertPacketCoreValue(publishQoS2Packet2, NotificationQoS2Content2); yield return(TestScenarioStep.Write( PubAckPacket.InResponseTo(publishQoS1Packet), PubRecPacket.InResponseTo(publishQoS2Packet1), PubRecPacket.InResponseTo(publishQoS2Packet2))); var pubRelQoS2Packet1 = Assert.IsAssignableFrom <PubRelPacket>(currentMessageFunc()); Assert.Equal(publishQoS2Packet1.PacketId, pubRelQoS2Packet1.PacketId); yield return(TestScenarioStep.ReadMore()); var pubRelQoS2Packet2 = Assert.IsAssignableFrom <PubRelPacket>(currentMessageFunc()); Assert.Equal(publishQoS2Packet2.PacketId, pubRelQoS2Packet2.PacketId); yield return(TestScenarioStep.Write( false, // it is a final step and we do not expect response PubCompPacket.InResponseTo(pubRelQoS2Packet1), DisconnectPacket.Instance)); // device queue still contains QoS 2 packet 2 which was PUBRECed but not PUBCOMPed. }
private async Task OnPacketReceived(Packet msg) { try { switch (msg.PacketType) { case PacketType.CONNACK: Log($"[{_instaApi.GetLoggedUser().UserName}] " + "Received CONNACK"); ConnectionData.UpdateAuth(((FbnsConnAckPacket)msg).Authentication); await RegisterMqttClient(); break; case PacketType.PUBLISH: Log($"[{_instaApi.GetLoggedUser().UserName}] " + "Received PUBLISH"); var publishPacket = (PublishPacket)msg; if (publishPacket.Payload == null) { throw new Exception($"{nameof(PushClient)}: Publish packet received but payload is null"); } if (publishPacket.QualityOfService == QualityOfService.AtLeastOnce) { await FbnsPacketEncoder.EncodePacket(PubAckPacket.InResponseTo(publishPacket), _outboundWriter); } var payload = DecompressPayload(publishPacket.Payload); var json = Encoding.UTF8.GetString(payload); Log($"[{_instaApi.GetLoggedUser().UserName}] " + $"MQTT json: {json}"); switch (Enum.Parse(typeof(TopicIds), publishPacket.TopicName)) { case TopicIds.Message: var message = JsonConvert.DeserializeObject <PushReceivedEventArgs>(json); message.Json = json; message.InstaApi = _instaApi; MessageReceived?.Invoke(this, message); break; case TopicIds.RegResp: await OnRegisterResponse(json); StartKeepAliveLoop(); break; default: Log($"[{_instaApi.GetLoggedUser().UserName}] " + $"Unknown topic received: {publishPacket.TopicName}"); break; } break; case PacketType.PUBACK: Log($"[{_instaApi.GetLoggedUser().UserName}] " + "Received PUBACK"); _waitingForPubAck = false; break; // todo: PingResp never arrives even though data was received. Decoder problem? case PacketType.PINGRESP: Log($"[{_instaApi.GetLoggedUser().UserName}] " + "Received PINGRESP"); break; default: return; //throw new NotSupportedException($"Packet type {msg.PacketType} is not supported."); } } catch (Exception) { Shutdown(); } }
public abstract void PubAck(IChannelHandlerContext context, PubAckPacket packet);
static IEnumerable <TestScenarioStep> GetClientScenario(Func <object> currentMessageFunc, string clientId, string password) { yield return(TestScenarioStep.Write(new ConnectPacket { ClientId = clientId, HasUsername = true, Username = clientId, HasPassword = true, Password = password, KeepAliveInSeconds = 120, HasWill = true, WillTopicName = "last/word", WillMessage = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("oops")) })); var connAckPacket = Assert.IsType <ConnAckPacket>(currentMessageFunc()); Assert.Equal(ConnectReturnCode.Accepted, connAckPacket.ReturnCode); int subscribePacketId = GetRandomPacketId(); yield return(TestScenarioStep.Write(new SubscribePacket { PacketId = subscribePacketId, Requests = new[] { new SubscriptionRequest(string.Format("devices/{0}/messages/devicebound/#", clientId), QualityOfService.ExactlyOnce) } })); var subAckPacket = Assert.IsType <SubAckPacket>(currentMessageFunc()); Assert.Equal(subscribePacketId, subAckPacket.PacketId); Assert.Equal(1, subAckPacket.ReturnCodes.Count); Assert.Equal(QualityOfService.ExactlyOnce, subAckPacket.ReturnCodes[0]); int publishQoS1PacketId = GetRandomPacketId(); yield return(TestScenarioStep.Write( new PublishPacket(QualityOfService.AtMostOnce, false, false) { //TopicName = string.Format("devices/{0}/messages/log/verbose/", clientId), TopicName = string.Format("devices/{0}/messages/events", clientId), Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry-QoS0\"}")) }, new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = publishQoS1PacketId, TopicName = string.Format("devices/{0}/messages/events", clientId), Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("{\"test\": \"telemetry\"}")) })); var packets = new Packet[4]; for (int i = packets.Length - 1; i >= 0; i--) { packets[i] = Assert.IsAssignableFrom <Packet>(currentMessageFunc()); if (i > 0) { yield return(TestScenarioStep.ReadMore()); } } PubAckPacket pubAckPacket = Assert.Single(packets.OfType <PubAckPacket>()); Assert.Equal(publishQoS1PacketId, pubAckPacket.PacketId); PublishPacket publishQoS0Packet = Assert.Single(packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtMostOnce)); //Assert.Equal(string.Format("devices/{0}/messages/devicebound/tips", clientId), publishQoS0Packet.TopicName); Assert.Equal(string.Format("devices/{0}/messages/devicebound", clientId), publishQoS0Packet.TopicName); Assert.Equal(NotificationQoS0Content, Encoding.UTF8.GetString(publishQoS0Packet.Payload.ToArray())); PublishPacket publishQoS1Packet = Assert.Single(packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.AtLeastOnce)); //Assert.Equal(string.Format("devices/{0}/messages/devicebound/firmware-update", clientId), publishQoS1Packet.TopicName); Assert.Equal(string.Format("devices/{0}/messages/devicebound", clientId), publishQoS1Packet.TopicName); Assert.Equal(NotificationQoS1Content, Encoding.UTF8.GetString(publishQoS1Packet.Payload.ToArray())); PublishPacket publishQoS2Packet = Assert.Single(packets.OfType <PublishPacket>().Where(x => x.QualityOfService == QualityOfService.ExactlyOnce)); //Assert.Equal(string.Format("devices/{0}/messages/devicebound/critical-alert", clientId), publishQoS2Packet.TopicName); Assert.Equal(string.Format("devices/{0}/messages/devicebound", clientId), publishQoS2Packet.TopicName); Assert.Equal(NotificationQoS2Content, Encoding.UTF8.GetString(publishQoS2Packet.Payload.ToArray())); yield return(TestScenarioStep.Write( PubAckPacket.InResponseTo(publishQoS1Packet), PubRecPacket.InResponseTo(publishQoS2Packet))); var pubRelQoS2Packet = Assert.IsAssignableFrom <PubRelPacket>(currentMessageFunc()); Assert.Equal(publishQoS2Packet.PacketId, pubRelQoS2Packet.PacketId); yield return(TestScenarioStep.Write( false, // it is a final step and we do not expect response PubCompPacket.InResponseTo(pubRelQoS2Packet), DisconnectPacket.Instance)); }
private async Task OnPacketReceived(Packet msg) { if (!Running) { return; } var writer = _outboundWriter; try { switch (msg.PacketType) { case PacketType.CONNACK: this.Log("Received CONNACK"); await SubscribeForDM(); await RealtimeSub(); await PubSub(); if (SnapshotAt != null && SeqId <= 0) { await IrisSub(); } StartKeepAliveLoop(); break; case PacketType.PUBLISH: this.Log("Received PUBLISH"); var publishPacket = (PublishPacket)msg; if (publishPacket.Payload == null) { throw new Exception($"{nameof(RealtimeClient)}: Publish packet received but payload is null"); } if (publishPacket.QualityOfService == QualityOfService.AtLeastOnce) { await FbnsPacketEncoder.EncodePacket(PubAckPacket.InResponseTo(publishPacket), writer); } var payload = DecompressPayload(publishPacket.Payload); var json = await GetJsonFromThrift(payload); this.Log($"MQTT json: {json}"); if (string.IsNullOrEmpty(json)) { break; } try { Debug.WriteLine(""); Debug.WriteLine($"Unknown topic received:{msg.PacketType} : {publishPacket.TopicName} : {json}"); Debug.WriteLine(""); Debug.WriteLine(json); switch (publishPacket.TopicName) { case "150": break; case "133": // /ig_send_message_response try { Responses.AddItem(JsonConvert.DeserializeObject <InstaDirectRespondResponse>(json)); } catch { try { var o = JsonConvert.DeserializeObject <InstaDirectRespondV2Response>(json); Responses.AddItem(new InstaDirectRespondResponse { Action = o.Action, Message = o.Message, Status = o.Status, StatusCode = o.StatusCode, Payload = o.Payload[0] }); } catch { } } break; case "88": { var obj = JsonConvert.DeserializeObject <InstaRealtimeRespondResponse>(json); if (obj?.Data?.Length > 0) { var typing = new List <InstaRealtimeTypingEventArgs>(); var dm = new List <InstaDirectInboxItem>(); for (int i = 0; i < obj.Data.Length; i++) { var item = obj.Data[i]; if (item != null) { if (item.IsTyping) { var typingResponse = JsonConvert.DeserializeObject <InstaRealtimeTypingResponse>(item.Value); if (typingResponse != null) { try { var tr = new InstaRealtimeTypingEventArgs { SenderId = typingResponse.SenderId, ActivityStatus = typingResponse.ActivityStatus, RealtimeOp = item.Op, RealtimePath = item.Path, TimestampUnix = typingResponse.Timestamp, Timestamp = DateTimeHelper.FromUnixTimeMiliSeconds(typingResponse.Timestamp), Ttl = typingResponse.Ttl }; typing.Add(tr); } catch { } } } else if (item.IsThreadItem || item.IsThreadParticipants) { if (item.HasItemInValue) { var directItemResponse = JsonConvert.DeserializeObject <InstaDirectInboxItemResponse>(item.Value); if (directItemResponse != null) { try { var dI = ConvertersFabric.Instance.GetDirectThreadItemConverter(directItemResponse).Convert(); dI.RealtimeOp = item.Op; dI.RealtimePath = item.Path; dm.Add(dI); } catch { } } } else { var dI = new InstaDirectInboxItem { RealtimeOp = item.Op, RealtimePath = item.Path, ItemId = item.Value }; dm.Add(dI); } } } } if (typing.Count > 0) { OnTypingChanged(typing); } if (dm.Count > 0) { OnDirectItemChanged(dm); } } } break; } } catch { } break; case PacketType.PUBACK: this.Log("Received PUBACK"); break; case PacketType.PINGRESP: this.Log("Received PINGRESP"); break; default: Debug.WriteLine($"Unknown topic received:{msg.PacketType}"); break; } } catch (Exception e) { DebugLogger.LogExceptionX(e); } }
protected override async void ChannelRead0(IChannelHandlerContext ctx, Packet msg) { try { _context = ctx; // Save context for manual Ping later switch (msg.PacketType) { case PacketType.CONNACK: Debug.WriteLine($"{nameof(PushClient)}:\tCONNACK received."); ConnectionData.UpdateAuth(((FbnsConnAckPacket)msg).Authentication); RegisterMqttClient(ctx); break; case PacketType.PUBLISH: Debug.WriteLine($"{nameof(PushClient)}:\tPUBLISH received."); var publishPacket = (PublishPacket)msg; if (publishPacket.QualityOfService == QualityOfService.AtLeastOnce) { await ctx.WriteAndFlushAsync(PubAckPacket.InResponseTo(publishPacket)); } var payload = DecompressPayload(publishPacket.Payload); var json = Encoding.UTF8.GetString(payload); Debug.WriteLine($"{nameof(PushClient)}:\tMQTT json: {json}"); switch (Enum.Parse(typeof(TopicIds), publishPacket.TopicName)) { case TopicIds.Message: var message = JsonConvert.DeserializeObject <PushReceivedEventArgs>(json); message.Json = json; OnMessageReceived(message); break; case TopicIds.RegResp: OnRegisterResponse(json); try { await _context.Executor.Schedule(KeepAliveLoop, TimeSpan.FromSeconds(KEEP_ALIVE - 60)); } catch (TaskCanceledException) { // pass } break; default: Debug.WriteLine($"Unknown topic received: {publishPacket.TopicName}", "Warning"); break; } break; case PacketType.PUBACK: Debug.WriteLine($"{nameof(PushClient)}:\tPUBACK received."); _waitingForPubAck = false; break; // todo: PingResp never arrives even though data was received. Decoder problem? case PacketType.PINGRESP: Debug.WriteLine($"{nameof(PushClient)}:\tPINGRESP received."); break; default: throw new NotSupportedException($"Packet type {msg.PacketType} is not supported."); } } catch (Exception e) { // Something went wrong with Push client. Shutting down. #if !DEBUG Crashes.TrackError(e); #endif await Shutdown().ConfigureAwait(false); } }
private async void OnMessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args) { if (_pinging?.IsCancellationRequested ?? false) { return; } try { var dataReader = args.GetDataReader(); var outStream = sender.OutputStream; var loggedInUser = _instaApi.Session.LoggedInUser; Packet packet; try { packet = StandalonePacketDecoder.DecodePacket(dataReader); } catch (Exception e) { Debug.WriteLine(e); Debug.WriteLine($"{nameof(SyncClient)}: Failed to decode packet."); return; } switch (packet.PacketType) { case PacketType.CONNACK: Debug.WriteLine($"{nameof(SyncClient)}: " + packet.PacketType); var subscribePacket = new SubscribePacket( _packetId++, new SubscriptionRequest("/ig_message_sync", QualityOfService.AtMostOnce), new SubscriptionRequest("/ig_send_message_response", QualityOfService.AtMostOnce) ); await WriteAndFlushPacketAsync(subscribePacket, outStream); var unsubPacket = new UnsubscribePacket(_packetId++, "/ig_sub_iris_response"); await WriteAndFlushPacketAsync(unsubPacket, outStream); subscribePacket = new SubscribePacket(_packetId++, new SubscriptionRequest("/ig_sub_iris_response", QualityOfService.AtMostOnce)); await WriteAndFlushPacketAsync(subscribePacket, outStream); var random = new Random(); var json = new JObject( new JProperty("seq_id", _seqId), new JProperty("snapshot_at_ms", _snapshotAt.ToUnixTimeMilliseconds()), new JProperty("snapshot_app_version", "web"), new JProperty("subscription_type", "message")); var jsonBytes = GetJsonBytes(json); var irisPublishPacket = new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = _packetId++, TopicName = "/ig_sub_iris", Payload = Unpooled.CopiedBuffer(jsonBytes) }; await WriteAndFlushPacketAsync(irisPublishPacket, outStream); json = new JObject(new JProperty("unsub", new JArray($"ig/u/v1/{loggedInUser.Pk}"))); jsonBytes = GetJsonBytes(json); var pubsubPublishPacket = new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = _packetId++, TopicName = "/pubsub", Payload = Unpooled.CopiedBuffer(jsonBytes) }; await WriteAndFlushPacketAsync(pubsubPublishPacket, outStream); unsubPacket = new UnsubscribePacket(_packetId++, "/pubsub"); await WriteAndFlushPacketAsync(unsubPacket, outStream); subscribePacket = new SubscribePacket(_packetId++, new SubscriptionRequest("/pubsub", QualityOfService.AtMostOnce)); await WriteAndFlushPacketAsync(subscribePacket, outStream); json = new JObject(new JProperty("sub", new JArray($"ig/u/v1/{loggedInUser.Pk}"))); jsonBytes = GetJsonBytes(json); pubsubPublishPacket = new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = _packetId++, TopicName = "/pubsub", Payload = Unpooled.CopiedBuffer(jsonBytes) }; await WriteAndFlushPacketAsync(pubsubPublishPacket, outStream); Debug.WriteLine($"{nameof(SyncClient)}: " + packet.PacketType); _ = Task.Run(async() => { while (!_pinging.IsCancellationRequested) { try { await Task.Delay(TimeSpan.FromSeconds(8), _pinging.Token); var pingPacket = PingReqPacket.Instance; var pingBuffer = StandalonePacketEncoder.EncodePacket(pingPacket); await sender.OutputStream.WriteAsync(pingBuffer); await sender.OutputStream.FlushAsync(); } catch (TaskCanceledException) { Debug.WriteLine("Stopped pinging sync server"); return; } } }); return; case PacketType.PUBLISH: var publishPacket = (PublishPacket)packet; var payload = publishPacket.Payload.ReadString(publishPacket.Payload.ReadableBytes, Encoding.UTF8); if (publishPacket.TopicName == "/ig_message_sync") { var messageSyncPayload = JsonConvert.DeserializeObject <List <MessageSyncEventArgs> >(payload); var latest = messageSyncPayload.Last(); if (latest.SeqId > _seqId || latest.Data[0].Item.Timestamp > _snapshotAt) { _seqId = latest.SeqId; _snapshotAt = latest.Data[0].Item.Timestamp; } MessageReceived?.Invoke(this, messageSyncPayload); } Debug.WriteLine($"{nameof(SyncClient)} pub to {publishPacket.TopicName} payload: {payload}"); if (publishPacket.QualityOfService == QualityOfService.AtLeastOnce) { await WriteAndFlushPacketAsync(PubAckPacket.InResponseTo(publishPacket), outStream); } return; case PacketType.PINGRESP: Debug.WriteLine("Got pong from Sync Client"); break; default: Debug.WriteLine($"{nameof(SyncClient)}: " + packet.PacketType); break; } } catch (Exception e) { #if !DEBUG Crashes.TrackError(e); #endif Debug.WriteLine("Exception occured when processing incoming sync message."); Debug.WriteLine(e); } }
Task SendAckAsync(IChannelHandlerContext context, PublishPacket publish) { this.ResumeReadingIfNecessary(context); return(Util.WriteMessageAsync(context, PubAckPacket.InResponseTo(publish), ShutdownOnWriteErrorHandler)); }
IEnumerable <TestScenarioStep> GetMqttClientScenario(Func <object> currentMessageFunc) { yield return(TestScenarioStep.Message(new ConnectPacket { ClientId = ClientId, Username = "******", Password = "******", WillTopicName = "last/word", WillMessage = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("oops")) })); var connAckPacket = Assert.IsType <ConnAckPacket>(currentMessageFunc()); Assert.Equal(ConnectReturnCode.Accepted, connAckPacket.ReturnCode); int subscribePacketId = GetRandomPacketId(); int unsubscribePacketId = GetRandomPacketId(); yield return(TestScenarioStep.Messages( new SubscribePacket(subscribePacketId, new SubscriptionRequest(SubscribeTopicFilter1, QualityOfService.ExactlyOnce), new SubscriptionRequest(SubscribeTopicFilter2, QualityOfService.AtLeastOnce), new SubscriptionRequest("for/unsubscribe", QualityOfService.AtMostOnce)), new UnsubscribePacket(unsubscribePacketId, "for/unsubscribe"))); var subAckPacket = Assert.IsType <SubAckPacket>(currentMessageFunc()); Assert.Equal(subscribePacketId, subAckPacket.PacketId); Assert.Equal(3, subAckPacket.ReturnCodes.Count); Assert.Equal(QualityOfService.ExactlyOnce, subAckPacket.ReturnCodes[0]); Assert.Equal(QualityOfService.AtLeastOnce, subAckPacket.ReturnCodes[1]); Assert.Equal(QualityOfService.AtMostOnce, subAckPacket.ReturnCodes[2]); yield return(TestScenarioStep.MoreFeedbackExpected()); var unsubAckPacket = Assert.IsType <UnsubAckPacket>(currentMessageFunc()); Assert.Equal(unsubscribePacketId, unsubAckPacket.PacketId); int publishQoS1PacketId = GetRandomPacketId(); yield return(TestScenarioStep.Messages( new PublishPacket(QualityOfService.AtMostOnce, false, false) { TopicName = PublishC2STopic, Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(PublishC2SQos0Payload)) }, new PublishPacket(QualityOfService.AtLeastOnce, false, false) { PacketId = publishQoS1PacketId, TopicName = PublishC2SQos1Topic, Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(PublishC2SQos1Payload)) })); //new PublishPacket(QualityOfService.AtLeastOnce, false, false) { TopicName = "feedback/qos/One", Payload = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes("QoS 1 test. Different data length.")) }); var pubAckPacket = Assert.IsType <PubAckPacket>(currentMessageFunc()); Assert.Equal(publishQoS1PacketId, pubAckPacket.PacketId); yield return(TestScenarioStep.MoreFeedbackExpected()); var publishPacket = Assert.IsType <PublishPacket>(currentMessageFunc()); Assert.Equal(QualityOfService.AtLeastOnce, publishPacket.QualityOfService); Assert.Equal(PublishS2CQos1Topic, publishPacket.TopicName); Assert.Equal(PublishS2CQos1Payload, publishPacket.Payload.ToString(Encoding.UTF8)); yield return(TestScenarioStep.Messages( PubAckPacket.InResponseTo(publishPacket), DisconnectPacket.Instance)); }
private Packet DecodePacketInternal(IByteBuffer buffer, int packetSignature, ref int remainingLength) { if (Signatures.IsPublish(packetSignature)) { var qualityOfService = (QualityOfService)((packetSignature >> 1) & 0x3); // take bits #1 and #2 ONLY and convert them into QoS value if (qualityOfService == QualityOfService.Reserved) { throw new DecoderException( $"Unexpected QoS value of {(int) qualityOfService} for {PacketType.PUBLISH} packet."); } bool duplicate = (packetSignature & 0x8) == 0x8; // test bit#3 bool retain = (packetSignature & 0x1) != 0; // test bit#0 var packet = new PublishPacket(qualityOfService, duplicate, retain); DecodePublishPacket(buffer, packet, ref remainingLength); return(packet); } switch (packetSignature & 240) // We don't care about flags for these packets { case Signatures.Subscribe& 240: var subscribePacket = new SubscribePacket(); DecodePacketIdVariableHeader(buffer, subscribePacket, ref remainingLength); DecodeSubscribePayload(buffer, subscribePacket, ref remainingLength); return(subscribePacket); case Signatures.Connect: var connectPacket = new FbnsConnectPacket(); DecodeConnectPacket(buffer, connectPacket, ref remainingLength); return(connectPacket); case Signatures.PubAck: var pubAckPacket = new PubAckPacket(); DecodePacketIdVariableHeader(buffer, pubAckPacket, ref remainingLength); return(pubAckPacket); case Signatures.ConnAck: var connAckPacket = new FbnsConnAckPacket(); DecodeConnAckPacket(buffer, connAckPacket, ref remainingLength); return(connAckPacket); case Signatures.SubAck: var subAckPacket = new SubAckPacket(); DecodePacketIdVariableHeader(buffer, subAckPacket, ref remainingLength); DecodeSubAckPayload(buffer, subAckPacket, ref remainingLength); return(subAckPacket); case Signatures.Unsubscribe& 240: var unsubscribePacket = new UnsubscribePacket(); DecodePacketIdVariableHeader(buffer, unsubscribePacket, ref remainingLength); DecodeUnsubscribePayload(buffer, unsubscribePacket, ref remainingLength); return(unsubscribePacket); case Signatures.PingResp: return(PingRespPacket.Instance); default: throw new DecoderException($"Packet type {packetSignature} not supported"); } }
private void ProcessMessage(PubAckPacket message) { }