async void RetransmitPublishMessage(IChannelHandlerContext context, IMessage message, AckPendingMessageState messageInfo) { try { using (message) { string topicName; message.Properties[TemplateParameters.DeviceIdTemplateParam] = this.DeviceId; if (!this.messageRouter.TryRouteOutgoingMessage(RouteSourceType.Notification, message, out topicName)) { throw new InvalidOperationException("Route mapping failed on retransmission."); } PublishPacket packet = await Util.ComposePublishPacketAsync(context, message, messageInfo.QualityOfService, topicName, context.Channel.Allocator); messageInfo.ResetMessage(message); await this.publishPubAckProcessor.RetransmitAsync(context, packet, messageInfo); } } catch (Exception ex) { // todo: log more details ShutdownOnError(context, "<- PUBLISH (retransmission)", ex); } }
public static PubRecPacket InResponseTo(PublishPacket publishPacket) { return(new PubRecPacket { PacketId = publishPacket.PacketId }); }
async Task SendMessageAsync(IChannelHandlerContext context, Message message) { string topicName = string.Format(TelemetryTopicFormat, this.deviceId); PublishPacket packet = await Util.ComposePublishPacketAsync(context, message, this.mqttTransportSettings.PublishToServerQoS, topicName); var publishCompletion = new TaskCompletionSource(); var workItem = new PublishWorkItem { Completion = publishCompletion, Value = packet }; switch (this.mqttTransportSettings.PublishToServerQoS) { case QualityOfService.AtMostOnce: this.serviceBoundOneWayProcessor.Post(context, workItem); break; case QualityOfService.AtLeastOnce: this.serviceBoundTwoWayProcessor.Post(context, workItem); break; default: throw new NotSupportedException($"Unsupported telemetry QoS: '{this.mqttTransportSettings.PublishToServerQoS}'"); } await publishCompletion.Task; }
/// <summary> /// Closes channel /// </summary> /// <param name="context"></param> /// <param name="graceful"></param> async void Shutdown(IChannelHandlerContext context, bool graceful) { if (this.IsInState(StateFlags.Closed)) { return; } try { this.stateFlags |= StateFlags.Closed; // "or" not to interfere with ongoing logic which has to honor Closed state when it's right time to do (case by case) PerformanceCounters.ConnectionsCurrent.Decrement(); Queue <Packet> connectQueue = this.connectPendingQueue; if (connectQueue != null) { while (connectQueue.Count > 0) { Packet packet = connectQueue.Dequeue(); ReferenceCountUtil.Release(packet); } } PublishPacket will = !graceful && this.IsInState(StateFlags.Connected) ? this.willPacket : null; this.CloseIotHubConnection(context, will); await context.CloseAsync(); } catch (Exception ex) { MqttIotHubAdapterEventSource.Log.Warning("Error occurred while shutting down the channel.", ex); } }
Task AcceptMessageAsync(IChannelHandlerContext context, PublishPacket publish) { if (Logging.IsEnabled) { Logging.Enter(this, context.Name, publish, nameof(AcceptMessageAsync)); } Message message; try { var bodyStream = new ReadOnlyByteBufferStream(publish.Payload, true); message = new Message(bodyStream, true); Util.PopulateMessagePropertiesFromPacket(message, publish); message.MqttTopicName = publish.TopicName; } catch (Exception ex) when(!ex.IsFatal()) { ShutdownOnError(context, ex); return(TaskConstants.Completed); } this.mqttIotHubEventHandler.OnMessageReceived(message); if (Logging.IsEnabled) { Logging.Exit(this, context.Name, publish, nameof(AcceptMessageAsync)); } return(TaskConstants.Completed); }
static void DecodePublishPacket(IByteBuffer buffer, PublishPacket packet, ref int remainingLength) { string topicName = DecodeString(buffer, ref remainingLength, 1); Util.ValidateTopicName(topicName); packet.TopicName = topicName; if (packet.QualityOfService > QualityOfService.AtMostOnce) { DecodePacketIdVariableHeader(buffer, packet, ref remainingLength); } IByteBuffer payload; if (remainingLength > 0) { payload = buffer.ReadSlice(remainingLength); payload.Retain(); remainingLength = 0; } else { payload = Unpooled.Empty; } packet.Payload = payload; }
public static PubAckPacket InResponseTo(PublishPacket publishPacket) { return new PubAckPacket { PacketId = publishPacket.PacketId }; }
public async Task PublishAsync(string topic, byte[] payload, QualityOfService qos = QualityOfService.AtMostOnce, bool retain = false) { TaskCompletionSource <object> future = new TaskCompletionSource <object>(); PublishPacket packet = new PublishPacket(qos, false, retain); packet.TopicName = topic; packet.PacketId = PacketIdProvider.NewPacketId(); packet.Payload = Unpooled.WrappedBuffer(payload); packet.Retain(); WriteResult result = await sendAndFlushAsync(packet); if (!result.Success) { packet.Release();//needed? future.SetException(result.Exception); } else if (qos == QualityOfService.AtLeastOnce) { packet.Release(); //needed? future.SetResult(null); //We don't get an ACK for QOS 0 } else { PendingPublish pendingPublish = new PendingPublish(packet, future);//return after PubAct(QoS=1)/PubRel(QoS=2) received. pendingPublishes.TryAdd(packet.PacketId, pendingPublish); pendingPublish.RetransmitPublish(eventLoopGroup.GetNext(), sendAndFlushAsync); } await future.Task; }
private Task ProcessReceivedPublishPacketAsync(PublishPacket publishPacket) { OnMessageReceived?.Invoke(new Message { Topic = publishPacket.TopicName, Payload = publishPacket.Payload, Qos = publishPacket.Qos, Retain = publishPacket.Retain }); switch (publishPacket.Qos) { case MqttQos.AtMostOnce: return(Task.CompletedTask); case MqttQos.AtLeastOnce: return(_clientChannel.WriteAndFlushAsync(new PubAckPacket(publishPacket.PacketId))); case MqttQos.ExactlyOnce: return(_clientChannel.WriteAndFlushAsync(new PubRecPacket(publishPacket.PacketId))); default: throw new MqttException("Received a not supported QoS level."); } }
static void EncodePublishMessage(IByteBufferAllocator bufferAllocator, PublishPacket packet, List <object> output) { IByteBuffer payload = packet.Payload ?? Unpooled.Empty; string topicName = packet.TopicName; Util.ValidateTopicName(topicName); byte[] topicNameBytes = EncodeStringInUtf8(topicName); int variableHeaderBufferSize = StringSizeLength + topicNameBytes.Length + (packet.QualityOfService > QualityOfService.AtMostOnce ? PacketIdLength : 0); int payloadBufferSize = payload.ReadableBytes; int variablePartSize = variableHeaderBufferSize + payloadBufferSize; int fixedHeaderBufferSize = 1 + MaxVariableLength; IByteBuffer buf = bufferAllocator.Buffer(fixedHeaderBufferSize + variablePartSize); buf.WriteByte(CalculateFirstByteOfFixedHeader(packet)); WriteVariableLengthInt(buf, variablePartSize); buf.WriteShort(topicNameBytes.Length); buf.WriteBytes(topicNameBytes); if (packet.QualityOfService > QualityOfService.AtMostOnce) { buf.WriteShort(packet.PacketId); } output.Add(buf); if (payload.IsReadable()) { output.Add(payload.Retain()); } }
public static void PopulateMessagePropertiesFromPacket(Message message, PublishPacket publish) { message.LockToken = publish.QualityOfService == QualityOfService.AtLeastOnce ? publish.PacketId.ToString() : null; // Device bound messages could be in 2 formats, depending on whether it is going to the device, or to a module endpoint // Format 1 - going to the device - devices/{deviceId}/messages/devicebound/{properties}/ // Format 2 - going to module endpoint - devices/{deviceId}/modules/{moduleId/endpoints/{endpointId}/{properties}/ // So choose the right format to deserialize properties. string[] topicSegments = publish.TopicName.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); string propertiesSegment = topicSegments.Length > 6 ? topicSegments[6] : topicSegments[4]; Dictionary <string, string> properties = UrlEncodedDictionarySerializer.Deserialize(propertiesSegment, 0); foreach (KeyValuePair <string, string> property in properties) { string propertyName; if (ToSystemPropertiesMap.TryGetValue(property.Key, out propertyName)) { message.SystemProperties[propertyName] = ConvertToSystemProperty(property); } else { message.Properties[property.Key] = property.Value; } } }
async Task IrisSub() { var dic = new Dictionary <string, object> { { "seq_id", SeqId.ToString() }, { "sub", new List <string>() }, { "snapshot_at_ms", SnapshotAt.ToUnixTimeMiliSeconds() } }; var json = JsonConvert.SerializeObject(dic); var bytes = Encoding.UTF8.GetBytes(json); var dataStream = new MemoryStream(512); using (var zlibStream = new ZlibStream(dataStream, CompressionMode.Compress, CompressionLevel.Level9, true)) { await zlibStream.WriteAsync(bytes, 0, bytes.Length); } var compressed = dataStream.GetWindowsRuntimeBuffer(0, (int)dataStream.Length); var publishPacket = new PublishPacket(QualityOfService.AtLeastOnce, false, false) { Payload = compressed, PacketId = (ushort)CryptographicBuffer.GenerateRandomNumber(), TopicName = "/ig_sub_iris" }; await FbnsPacketEncoder.EncodePacket(publishPacket, _outboundWriter); }
async Task PubSub() { var user = _instaApi.GetLoggedUser().LoggedInUser; var dic = new Dictionary <string, List <string> > { { "sub", new List <string> { SkyWalker.DirectSubscribe(user?.Pk.ToString()), SkyWalker.LiveSubscribe(user?.Pk.ToString()), } } }; var json = JsonConvert.SerializeObject(dic); var bytes = Encoding.UTF8.GetBytes(json); var dataStream = new MemoryStream(512); using (var zlibStream = new ZlibStream(dataStream, CompressionMode.Compress, CompressionLevel.Level9, true)) { await zlibStream.WriteAsync(bytes, 0, bytes.Length); } var compressed = dataStream.GetWindowsRuntimeBuffer(0, (int)dataStream.Length); var publishPacket = new PublishPacket(QualityOfService.AtLeastOnce, false, false) { Payload = compressed, PacketId = (ushort)CryptographicBuffer.GenerateRandomNumber(), TopicName = "/pubsub" }; await FbnsPacketEncoder.EncodePacket(publishPacket, _outboundWriter); }
async Task RealtimeSub() { var user = _instaApi.GetLoggedUser().LoggedInUser; var dic = new Dictionary <string, List <string> > { { "sub", new List <string> { GraphQLSubscriptions.GetAppPresenceSubscription(), GraphQLSubscriptions.GetZeroProvisionSubscription(_instaApi.GetCurrentDevice().DeviceGuid.ToString()), GraphQLSubscriptions.GetDirectStatusSubscription(), GraphQLSubscriptions.GetDirectTypingSubscription(user?.Pk.ToString()), GraphQLSubscriptions.GetAsyncAdSubscription(user?.Pk.ToString()) } } }; var json = JsonConvert.SerializeObject(dic); var bytes = Encoding.UTF8.GetBytes(json); var dataStream = new MemoryStream(512); using (var zlibStream = new ZlibStream(dataStream, CompressionMode.Compress, CompressionLevel.Level9, true)) { await zlibStream.WriteAsync(bytes, 0, bytes.Length); } var compressed = dataStream.GetWindowsRuntimeBuffer(0, (int)dataStream.Length); var publishPacket = new PublishPacket(QualityOfService.AtLeastOnce, false, false) { Payload = compressed, PacketId = (ushort)CryptographicBuffer.GenerateRandomNumber(), TopicName = "/ig_realtime_sub" }; await FbnsPacketEncoder.EncodePacket(publishPacket, _outboundWriter); }
async void RetransmitPublishMessage(IChannelHandlerContext context, Message message, AckPendingMessageState messageInfo) { try { using (message) { string topicName; var completeContext = new ReadOnlyMergeDictionary <string, string>(this.sessionContext, message.Properties); if (!this.topicNameRouter.TryMapRouteToTopicName(RouteSourceType.Notification, completeContext, out topicName)) { throw new InvalidOperationException("Route mapping failed on retransmission."); } PublishPacket packet = await Util.ComposePublishPacketAsync(context, message, messageInfo.QualityOfService, topicName); messageInfo.ResetMessage(message); await this.publishPubAckProcessor.RetransmitAsync(context, packet, messageInfo); } } catch (Exception ex) { // todo: log more details ShutdownOnError(context, "<- PUBLISH (retransmission)", ex); } }
public static PublishPacket ComposePublishPacket(IChannelHandlerContext context, IMessage message, QualityOfService qos, IByteBufferAllocator allocator) { bool duplicate = message.DeliveryCount > 0; var packet = new PublishPacket(qos, duplicate, false); packet.TopicName = message.Address; if (qos > QualityOfService.AtMostOnce) { int packetId = unchecked ((int)message.SequenceNumber) & 0x3FFF; // clear bits #14 and #15 switch (qos) { case QualityOfService.AtLeastOnce: break; case QualityOfService.ExactlyOnce: packetId |= 0x8000; // set bit #15 break; default: throw new ArgumentOutOfRangeException(nameof(qos), qos, null); } packet.PacketId = packetId + 1; } message.Payload.Retain(); packet.Payload = message.Payload; return(packet); }
private ushort Publish(PublishPacket packet) { if (packet.QosLevel != MqttQos.AtMostOnce) { if (packet.PacketId == 0) { packet.PacketId = this.GetNextPacketId(); } Persistence.RegisterOutgoingFlow(new OutgoingFlow() { PacketId = packet.PacketId, Topic = packet.Topic, Qos = packet.QosLevel, Payload = packet.Message }); } try { IsPublishing = true; Send(packet); return(packet.PacketId); } catch { IsPublishing = false; throw; } }
public void OnPublish(IChannelHandlerContext context, PublishPacket packet) { switch (packet.QualityOfService) { case QualityOfService.AtMostOnce: publishCallback(packet); break; case QualityOfService.AtLeastOnce: publishCallback(packet); if (packet.PacketId != -1) { context.WriteAndFlushAsync(PubAckPacket.InResponseTo(packet)); } break; case QualityOfService.ExactlyOnce: if (packet.PacketId != -1) { var pubRecPacket = PubRecPacket.InResponseTo(packet); PendingQoS2Publish pendingQoS2Publish = new PendingQoS2Publish(packet, pubRecPacket); pendingIncomingQoS2Publishes.TryAdd(pubRecPacket.PacketId, pendingQoS2Publish); packet.Retain(); pendingQoS2Publish.Retransmit(eventLoopGroup.GetNext(), sendAndFlushAsync); context.WriteAndFlushAsync(pubRecPacket); } break; } }
static void EncodePublishMessage(DataWriter writer, PublishPacket packet) { IBuffer payload = packet.Payload; string topicName = packet.TopicName; // Util.ValidateTopicName(topicName); byte[] topicNameBytes = EncodeStringInUtf8(topicName); int variableHeaderBufferSize = STRING_SIZE_LENGTH + topicNameBytes.Length + (packet.QualityOfService > QualityOfService.AtMostOnce ? PACKET_ID_LENGTH : 0); int payloadBufferSize = (int)payload.Length; int variablePartSize = variableHeaderBufferSize + payloadBufferSize; writer.WriteByte(CalculateFirstByteOfFixedHeader(packet)); WriteVariableLengthInt(writer, variablePartSize); writer.WriteInt16((short)topicNameBytes.Length); writer.WriteBytes(topicNameBytes); if (packet.QualityOfService > QualityOfService.AtMostOnce) { writer.WriteInt16((short)packet.PacketId); } writer.WriteBuffer(payload); }
void ProcessPublish(IChannelHandlerContext context, PublishPacket packet) { if (Logging.IsEnabled) { Logging.Enter(this, context.Name, packet, nameof(ProcessPublish)); } if (this.IsInState(StateFlags.Closed)) { return; } switch (packet.QualityOfService) { case QualityOfService.AtMostOnce: this.deviceBoundOneWayProcessor.Post(context, packet); break; case QualityOfService.AtLeastOnce: this.deviceBoundTwoWayProcessor.Post(context, packet); break; default: throw new NotSupportedException($"Unexpected QoS: '{packet.QualityOfService}'"); } this.ResumeReadingIfNecessary(context); if (Logging.IsEnabled) { Logging.Exit(this, context.Name, packet, nameof(ProcessPublish)); } }
IEnumerable <TestScenarioStep> GetPart2SpecificSteps(Func <object> currentMessageFunc) { yield return(TestScenarioStep.ReadMore()); var packets = new Packet[2]; for (int i = packets.Length - 1; i >= 0; i--) { packets[i] = Assert.IsAssignableFrom <Packet>(currentMessageFunc()); if (i > 0) { yield return(TestScenarioStep.ReadMore()); } } PublishPacket qos1Packet = Assert.Single(packets.OfType <PublishPacket>()); Assert.Equal(QualityOfService.AtLeastOnce, qos1Packet.QualityOfService); this.AssertPacketCoreValue(qos1Packet, Encoding.ASCII.GetString(qos1Packet.Payload.ToArray())); PubRelPacket pubRelQos2Packet = Assert.Single(packets.OfType <PubRelPacket>()); yield return(TestScenarioStep.Write( false, PubAckPacket.InResponseTo(qos1Packet), PubCompPacket.InResponseTo(pubRelQos2Packet), DisconnectPacket.Instance)); }
/// <summary> /// Indicate activity /// </summary> /// <param name="threadId">Thread id</param> /// <param name="isActive">Active status</param> public async Task <IResult <bool> > IndicateActivityAsync(string threadId, bool isActive) { try { var token = ExtensionHelper.GetThreadToken(); var data = new Dictionary <string, string> { { "action", "indicate_activity" }, { "item_type", "indicate_activity" }, { "thread_id", threadId }, { "client_context", token }, { "activity_status", isActive ? "1" : "0" }, }; var json = JsonConvert.SerializeObject(data); var bytes = Encoding.UTF8.GetBytes(json); var publishPacket = new PublishPacket(QualityOfService.AtLeastOnce, false, false) { Payload = ZlibHelper.Compress(bytes).AsBuffer(), PacketId = (ushort)CryptographicBuffer.GenerateRandomNumber(), TopicName = "132" }; await FbnsPacketEncoder.EncodePacket(publishPacket, _outboundWriter); return(Result.Success(true)); } catch (SocketException socketException) { return(Result.Fail(socketException, default(bool), ResponseType.NetworkProblem)); } catch (Exception exception) { return(Result.Fail <bool>(exception)); } }
async Task CompletePublishAsync(IChannelHandlerContext context, PublishPacket will) { if (will == null) { return; } var sendingClient = this.ResolveSendingClient(will.TopicName); MessageAsyncProcessor <PublishPacket> publishProcessor; if (this.publishProcessors.TryGetValue(sendingClient, out publishProcessor)) { await publishProcessor.Completion; } try { await this.PublishToServerAsync(context, sendingClient, will, MessageTypes.Will); } catch (Exception ex) { CommonEventSource.Log.Warning("Failed sending Will Message.", ex); } }
private async Task PublishRegisterAsync(IChannelHandlerContext context) { IByteBuffer packagePayload = Unpooled.Empty; if (_message.Payload != null && _message.Payload.Length > 0) { var deviceRegistration = new DeviceRegistration { Payload = new JRaw(_message.Payload) }; using var customContentStream = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(deviceRegistration))); long streamLength = customContentStream.Length; int length = (int)streamLength; packagePayload = context.Channel.Allocator.Buffer(length, length); await packagePayload.WriteBytesAsync(customContentStream, length).ConfigureAwait(false); } int packetId = GetNextPacketId(); var message = new PublishPacket(Qos, false, false) { TopicName = string.Format(CultureInfo.InvariantCulture, RegisterTopic, packetId), PacketId = packetId, Payload = packagePayload }; await context.WriteAndFlushAsync(message).ConfigureAwait(false); }
async void Connect(IChannelHandlerContext context) { var connectPacket = new ConnectPacket { ClientId = this.deviceId, HasUsername = true, Username = this.iotHubHostName + "/" + this.deviceId, HasPassword = true, Password = this.password, KeepAliveInSeconds = this.mqttTransportSettings.KeepAliveInSeconds, CleanSession = this.mqttTransportSettings.CleanSession, HasWill = this.mqttTransportSettings.HasWill }; if (connectPacket.HasWill) { Message message = this.willMessage.Message; QualityOfService publishToServerQoS = this.mqttTransportSettings.PublishToServerQoS; string topicName = string.Format(TelemetryTopicFormat, this.deviceId); PublishPacket will = await Util.ComposePublishPacketAsync(context, message, publishToServerQoS, topicName); connectPacket.WillMessage = will.Payload; connectPacket.WillQualityOfService = this.willMessage.QoS; connectPacket.WillRetain = false; connectPacket.WillTopicName = will.TopicName; } this.stateFlags = StateFlags.Connecting; await Util.WriteMessageAsync(context, connectPacket, ShutdownOnWriteErrorHandler); this.lastChannelActivityTime = DateTime.UtcNow; this.ScheduleKeepConnectionAlive(context); this.ScheduleCheckConnectTimeout(context); }
async void CloseIotHubConnection(IChannelHandlerContext context, PublishPacket will) { if (!this.ConnectedToHub) { // closure happened before IoT Hub connection was established or it was initiated due to disconnect return; } try { this.publishProcessor.Complete(); this.publishPubAckProcessor.Complete(); this.publishPubRecProcessor.Complete(); this.pubRelPubCompProcessor.Complete(); await Task.WhenAll( this.CompletePublishAsync(context, will), this.publishPubAckProcessor.Completion, this.publishPubRecProcessor.Completion, this.pubRelPubCompProcessor.Completion); IMessagingServiceClient hub = this.messagingServiceClient; this.messagingServiceClient = null; await hub.DisposeAsync(); } catch (Exception ex) { MqttIotHubAdapterEventSource.Log.Info("Failed to close IoT Hub Client cleanly.", ex.ToString()); } }
Task AcceptMessageAsync(IChannelHandlerContext context, PublishPacket publish) { Message message; try { var buffer = new byte[publish.Payload.ReadableBytes]; publish.Payload.GetBytes(0, buffer); var bodyStream = new MemoryStream(buffer); bodyStream.Position = 0; message = new Message(bodyStream); Util.PopulateMessagePropertiesFromPacket(message, publish); } catch (Exception ex) { ShutdownOnError(context, ex); return(TaskConstants.Completed); } finally { publish.Release(); } this.onMessageReceived(message); return(TaskConstants.Completed); }
async Task CompletePublishAsync(IChannelHandlerContext context, PublishPacket will) { var completionTasks = new List <Task>(); foreach (var publishProcessorRecord in this.publishProcessors) { publishProcessorRecord.Value.Close(); completionTasks.Add(publishProcessorRecord.Value.Closed); } await Task.WhenAll(completionTasks); IMessagingServiceClient sendingClient = null; if (will != null) { sendingClient = this.ResolveSendingClient(will.TopicName); try { await this.PublishToServerAsync(context, sendingClient, will, MessageTypes.Will); } catch (Exception ex) { CommonEventSource.Log.Warning("Failed sending Will Message.", ex, this.ChannelId, this.Id); } } }
private static void EncodePublishPacket(PublishPacket packet, DataWriter writer) { var payload = packet.Payload; string topicName = packet.TopicName; byte[] topicNameBytes = EncodeStringInUtf8(topicName); uint variableHeaderBufferSize = (uint)(STRING_SIZE_LENGTH + topicNameBytes.Length + (packet.QualityOfService > QualityOfService.AtMostOnce ? PACKET_ID_LENGTH : 0)); uint payloadBufferSize = payload?.Length ?? 0; uint variablePartSize = variableHeaderBufferSize + payloadBufferSize; writer.WriteByte(CalculateFirstByteOfFixedHeader(packet)); WriteVariableLengthInt(writer, variablePartSize); writer.WriteUInt16((ushort)topicNameBytes.Length); writer.WriteBytes(topicNameBytes); if (packet.QualityOfService > QualityOfService.AtMostOnce) { writer.WriteUInt16(packet.PacketId); } if (payload != null) { writer.WriteBuffer(payload); } }
static void DecodePublishPacket(DataReader reader, PublishPacket packet, ref uint remainingLength) { string topicName = DecodeString(reader, ref remainingLength); packet.TopicName = topicName; if (packet.QualityOfService > QualityOfService.AtMostOnce) { DecodePacketIdVariableHeader(reader, packet, ref remainingLength); } IBuffer payload; if (remainingLength > 0) { try { Debug.WriteLine("UnconsumedBufferLength: " + reader.UnconsumedBufferLength); if (reader.UnconsumedBufferLength < remainingLength) { remainingLength = reader.UnconsumedBufferLength; } payload = reader.ReadBuffer(remainingLength); remainingLength = 0; } catch { payload = null; } } else { payload = null; } packet.Payload = payload; }
public static PublishPacket DecodePublish(byte[] data) { var r = new Reader(data); var type = r.ReadByte(); Guard.Assert((byte)PacketType.Publish, type, "Type"); var length = r.ReadInt32Vlq(out _); if (length + 2 > data.Length) { throw new InvalidOperationException("Packet too short"); } const int topicLengthBytes = 2; var topicLength = r.ReadInt16BigEndian(); var topic = Encoding.GetString(r.ReadBytes(topicLength)); var remaining = length - topicLengthBytes - topicLength; var payload = r.ReadBytes(remaining); var result = new PublishPacket { Topic = topic, Payload = payload.ToArray(), }; ProcessTTR(r, result); Guard.Assert(r.Position, data.Length); return(result); }