public virtual void Route(byte[] messageData, T session) { try { MqttMessage incoming = MqttMessage.CreateFrom(messageData); switch (incoming.Header.MessageType) { case MqttMessageType.Publish: PublishReceived(session, (MqttPublishMessage)incoming); break; case MqttMessageType.Subscribe: SubscribeReceived(session, (MqttSubscribeMessage)incoming); break; case MqttMessageType.Unsubscribe: RemoveSubscriptions(session, ((MqttUnsubscribeMessage)incoming).Payload.Subscriptions); var unsubAck = new MqttUnsubscribeAckMessage().WithMessageIdentifier(((MqttPublishReceivedMessage)incoming).VariableHeader.MessageIdentifier); session.Write(unsubAck); break; case MqttMessageType.PublishAck: string messageId = session.PublishAcknowledged(((MqttPublishAckMessage)incoming).VariableHeader.MessageIdentifier); if (messageId != null) { storageProvider.ReleaseMessage(messageId); } break; case MqttMessageType.PublishReceived: messageId = session.PublishReceived(((MqttPublishReceivedMessage)incoming).VariableHeader.MessageIdentifier); if (messageId != null) { storageProvider.ReleaseMessage(messageId); } break; case MqttMessageType.PublishRelease: session.RemoveQoS2(((MqttPublishReleaseMessage)incoming).VariableHeader.MessageIdentifier); var pubComp = new MqttPublishCompleteMessage().WithMessageIdentifier(((MqttPublishReleaseMessage)incoming).VariableHeader.MessageIdentifier); session.Write(pubComp); break; case MqttMessageType.PublishComplete: session.PublishCompleted(((MqttPublishCompleteMessage)incoming).VariableHeader.MessageIdentifier); break; } } catch (TargetInvocationException ex) { var inner = ex.InnerException as HttpException; session.Write(inner != null ? new ErrorMessage(inner.GetHttpCode(), inner.Message) : new ErrorMessage((ex.InnerException ?? ex).Message)); } catch (HttpException ex) { session.Write(new ErrorMessage(ex.Message)); } catch (Exception ex) { session.Write(new ErrorMessage(ex.Message)); } }
private async void handleConnection(TcpClient connection) { var ep = connection.Client.RemoteEndPoint; Console.WriteLine("New Connection from {0}", ep); NetworkStream stream = connection.GetStream(); MqttMessage message = await MqttMessage.Read(stream, 5); if (message.Type != MessageType.Connect) { throw new MqttProtocolException("First packet not connect"); } //TODO: Non-clean sessions ConnAckMessage connAck = new ConnAckMessage(0, false); await connAck.Write(stream); ConnectMessage connectMessage = (ConnectMessage)message; double keepalive = ((ConnectMessage)message).KeepAlive * 1.5; String clientId = ((ConnectMessage)message).ClientId; if (String.IsNullOrEmpty(clientId)) { clientId = Guid.NewGuid().ToString(); } IMqttSession session = await sessionProvider.NewSession(clientId); Console.WriteLine("Client {0} connected from {1} ({2},{3})", clientId, ep, connectMessage.CleanSession, connectMessage.KeepAlive); connections.Add(session, connection); Task <MqttMessage> incoming = MqttMessage.Read(stream); Task <PendingMessage> outgoing = session.NextPending(null, 0); while (connection.Connected) { try { if (await Task.WhenAny(incoming, outgoing) == incoming) { try { message = incoming.Result; } catch (AggregateException e) { Console.WriteLine(e.InnerException.Message); connections.Remove(session); connection.Close(); continue; } catch (Exception e) { Console.WriteLine(e.Message); connections.Remove(session); connection.Close(); continue; } switch (message.Type) { case MessageType.Publish: await PublishReceived(session, stream, (PublishMessage)message); break; case MessageType.Disconnect: Console.WriteLine("Client {0} disconnected cleanly", clientId); connections.Remove(session); connection.Close(); //Skip reading the next message. Loop should exit. continue; case MessageType.Subscribe: await SubscribeReceived(session, stream, (SubscribeMessage)message); break; case MessageType.Unsubscribe: await sessionProvider.RemoveSubscriptions(session, ((UnsubscribeMessage)message).TopicFilters); await new UnsubAckMessage(((UnsubscribeMessage)message).PacketId).Write(stream); break; case MessageType.PubAck: string messageId = await session.PublishAcknowledged(((PubAckMessage)message).PacketId); if (messageId != null) { await storageProvider.ReleaseMessage(messageId); } break; case MessageType.PubRec: messageId = await session.PublishReceived(((PubRecMessage)message).PacketId); if (messageId != null) { await storageProvider.ReleaseMessage(messageId); } break; case MessageType.PubRel: await session.RemoveQoS2(((PubRelMessage)message).PacketId); await new PubCompMessage(((PubRelMessage)message).PacketId).Write(stream); break; case MessageType.PubComp: await session.PublishCompleted(((PubCompMessage)message).PacketId); break; case MessageType.PingReq: await new PingRespMessage().Write(stream); break; } incoming = MqttMessage.Read(stream); } else { PendingMessage pendingMessage = outgoing.Result; PendingPublishMessage pendingPublish = pendingMessage as PendingPublishMessage; if (pendingPublish != null) { var messageInfo = await storageProvider.GetMessage(pendingPublish.MessageId); message = new PublishMessage(pendingPublish.Duplicate, false, pendingPublish.QoS, messageInfo.Topic, messageInfo.Payload, pendingPublish.PacketId); } else { message = new PubRelMessage(pendingMessage.PacketId); } await message.Write(stream); outgoing = session.NextPending(pendingMessage, 5000); } } catch (Exception e) { Console.Out.WriteLine(e.Message); } } await sessionProvider.CloseSession(session); }