/// <summary> /// Invoked when a publish packet is received. /// </summary> /// <param name="client">The client sending the packet.</param> /// <param name="packet">The packet received from the client.</param> public static ProcessingState OnPublish(IClient client, MqttPublishPacket packet) { // Publish through emitter HandlePublish.Process(client, packet.Channel, packet.Message); // Send the ack and stop the processing if (client.Context.QoS > QoS.AtMostOnce) { client.SendMqttPuback(packet.MessageId); } return(ProcessingState.Stop); }
/// <summary> /// Sends a response to the client. /// </summary> /// <param name="client">The client to reply to.</param> /// <param name="response">The emitte response to send.</param> private static void SendResponse(IClient client, string channel, EmitterResponse response) { // Serialize the response var serialized = JsonConvert.SerializeObject(response, Formatting.Indented); if (serialized == null) { return; } // Send the message out var msg = MqttPublishPacket.Acquire(); msg.Channel = channel; msg.Message = serialized.AsUTF8().AsSegment(); client.Send(msg); }
private static MqttPacket Acquire(MqttPacketType type, IClient client) { switch (type) { case MqttPacketType.Connect: return(MqttConnectPacket.Acquire()); case MqttPacketType.Subscribe: return(MqttSubscribePacket.Acquire()); case MqttPacketType.Unsubscribe: return(MqttUnsubscribePacket.Acquire()); case MqttPacketType.PingReq: return(MqttPingReqPacket.Acquire()); case MqttPacketType.Disconnect: return(MqttDisconnectPacket.Acquire()); case MqttPacketType.Publish: return(MqttPublishPacket.Acquire()); case MqttPacketType.PubAck: return(MqttPubackPacket.Acquire()); default: Service.Logger.Log("Unknown MQTT Type: " + type); return(null); } }
/// <summary> /// Occurs when the remote client attempts to subscribe to a hub. /// </summary> /// <param name="client">The remote client.</param> /// <param name="channel">The full channel string.</param> public static EmitterEventCode Process(IClient client, string channel) { try { // Parse the channel EmitterChannel info; if (!EmitterChannel.TryParse(channel, true, out info)) { return(EmitterEventCode.BadRequest); } // Simple ACK for api subscribe. We don't really need to subscribe as // this uses request/response topology and hence the response is sent // through the same TCP connection. if (info.Key == "emitter") { return(EmitterEventCode.Success); } // Attempt to parse the key SecurityKey key; if (!SecurityKey.TryParse(info.Key, out key)) { return(EmitterEventCode.BadRequest); } // Has the key expired? if (key.IsExpired) { return(EmitterEventCode.Unauthorized); } // Have we already subscribed? //if (client[channel] != null) // return EmitterEventCode.Success; // Attempt to fetch the contract using the key. Underneath, it's cached. var contract = Services.Contract.GetByKey(key.Contract) as EmitterContract; if (contract == null) { return(EmitterEventCode.NotFound); } // Check if the payment state is valid if (contract.Status == EmitterContractStatus.Refused) { return(EmitterEventCode.PaymentRequired); } // Validate the contract if (!contract.Validate(ref key)) { return(EmitterEventCode.Unauthorized); } // Check if the key has the permission to read here if (!key.HasPermission(SecurityAccess.Read)) { return(EmitterEventCode.Unauthorized); } // Check if the key has the permission for the required channel if (key.Target != 0 && info.Target != key.Target) { return(EmitterEventCode.Unauthorized); } // Subscribe to the channel var subs = Dispatcher.Subscribe(client, key.Contract, info.Channel, SubscriptionInterest.Messages); // Check if the history was also requested and we have the permission to do so var last = 0; if (!info.RequestedLast(out last) || !key.HasPermission(SecurityAccess.Load)) { return(EmitterEventCode.Success); } // Get the ssid var ssid = EmitterChannel.Ssid(key.Contract, info.Channel); // Stream the history Services.Storage .GetLastAsync(key.Contract, ssid, last) .ContinueWith(async(t) => { // Now send each message in order var stream = t.Result; while (stream.HasNext) { // Get the message asyncronously var item = await stream.GetNext(); if (item.Count == 0) { continue; } // Increment the counter Service.MessageSent?.Invoke(contract, channel, item.Count); // Send the message out var msg = MqttPublishPacket.Acquire(); msg.Channel = info.Channel; msg.Message = item; client.Send(msg); } }); // We have successfully subscribed return(EmitterEventCode.Success); } catch (NotImplementedException) { // We've got a not implemented exception return(EmitterEventCode.NotImplemented); } catch (Exception ex) { // We need to log it Service.Logger.Log(ex); // We've got a an internal error return(EmitterEventCode.ServerError); } }
public static void SendMqttPublish(this IClient client, string channel, ArraySegment <byte> message) { client.Send( MqttPublishPacket.Acquire(channel, message) ); }