void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e) { MqttClient client = (MqttClient)sender; if (!mqttBridge.OnPublish(client, e)) return; // create PUBLISH message to publish // [v3.1.1] DUP flag from an incoming PUBLISH message is not propagated to subscribers // It should be set in the outgoing PUBLISH message based on transmission for each subscriber MqttMsgPublish publish = new MqttMsgPublish(e.Topic, e.Message, false, e.QosLevel, e.Retain); // publish message through publisher manager this.publisherManager.Publish(publish); }
public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, Socket socket) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgPublish msg = new MqttMsgPublish(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(socket); buffer = new byte[remainingLength]; // read bytes from socket... socket.Receive(buffer); // topic name topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++]; topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length; msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8)); // read QoS level from fixed header msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // read retain flag from fixed header msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01); // message id is valid only with QOS level 1 or QOS level 2 if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); } // get payload with message data msg.message = new byte[remainingLength - index]; Array.Copy(buffer, index, msg.message, 0, msg.message.Length); return(msg); }
public virtual void PublishToMqttClients(MqttMsgPublish message) { ((MqttManager)Composable.GetExport<IXSocketController>(typeof(MqttManager))).publisherManager.Publish(message); }
/// <summary> /// Parse bytes for a PUBLISH message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PUBLISH message instance</returns> public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgPublish msg = new MqttMsgPublish(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... int received = channel.Receive(buffer); // topic name topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++]; topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length; msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8)); // read QoS level from fixed header msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // read retain flag from fixed header msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01); // message id is valid only with QOS level 1 or QOS level 2 if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); } // get payload with message data int messageSize = remainingLength - index; int remaining = messageSize; int messageOffset = 0; msg.message = new byte[messageSize]; // BUG FIX 26/07/2013 : receiving large payload // copy first part of payload data received Array.Copy(buffer, index, msg.message, messageOffset, received - index); remaining -= (received - index); messageOffset += (received - index); // if payload isn't finished while (remaining > 0) { // receive other payload data received = channel.Receive(buffer); Array.Copy(buffer, 0, msg.message, messageOffset, received); remaining -= received; messageOffset += received; } return(msg); }
/// <summary> /// Wrapper method for raising PUBLISH message received event /// </summary> /// <param name="publish">PUBLISH message received</param> private void OnMqttMsgPublishReceived(MqttMsgPublish publish) { if (this.MqttMsgPublishReceived != null) { this.MqttMsgPublishReceived(this, new MqttMsgPublishEventArgs(publish.Topic, publish.Message, publish.QosLevel, publish.Retain)); } }
/// <summary> /// Publish a message to the broker /// </summary> /// <param name="topic">Message topic</param> /// <param name="message">Message data (payload)</param> /// <param name="qosLevel">QoS Level</param> /// <param name="retain">Retain flag</param> /// <returns>Message Id related to PUBLISH message</returns> public ushort Publish(string topic, byte[] message, byte qosLevel = MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, bool retain = false) { ushort messageId = 0; int attempts = 0; bool acknowledged = false; MqttMsgPublish publish = new MqttMsgPublish(topic, message, false, qosLevel, retain); // based on QoS level, the messages flow between client and broker changes switch (qosLevel) { // QoS Level 0, no answer from broker case MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE: this.Send(publish.GetBytes()); break; // QoS Level 1, waiting for PUBACK message from broker case MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE: attempts = 0; acknowledged = false; do { MqttMsgPuback puback = null; try { // try publish puback = (MqttMsgPuback)this.SendReceive(publish.GetBytes()); acknowledged = true; } catch (MqttTimeoutException) { // no PUBACK message received in time, retry with duplicate flag attempts++; publish.DupFlag = true; // delay before retry if (attempts < MQTT_ATTEMPTS_RETRY) Thread.Sleep(MQTT_DELAY_RETRY); } } while ((attempts < MQTT_ATTEMPTS_RETRY) && !acknowledged); if (acknowledged) messageId = publish.MessageId; break; // QoS Level 2, waiting for PUBREC message from broker, // send PUBREL message and waiting for PUBCOMP message from broker case MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE: attempts = 0; acknowledged = false; do { MqttMsgPubrec pubrec = null; try { // try publish pubrec = (MqttMsgPubrec)this.SendReceive(publish.GetBytes()); acknowledged = true; } catch (MqttTimeoutException) { // no PUBREC message received in time, retry with duplicate flag attempts++; publish.DupFlag = true; // delay before retry if (attempts < MQTT_ATTEMPTS_RETRY) Thread.Sleep(MQTT_DELAY_RETRY); } } while ((attempts < MQTT_ATTEMPTS_RETRY) && !acknowledged); // first phase ok if (acknowledged) { attempts = 0; acknowledged = false; do { // set publish message identifier into PUBREL message MqttMsgPubrel pubrel = new MqttMsgPubrel(); pubrel.MessageId = publish.MessageId; MqttMsgPubcomp pubcomp = null; try { // try send PUBREL message pubcomp = (MqttMsgPubcomp)this.SendReceive(pubrel.GetBytes()); acknowledged = true; } catch (MqttTimeoutException) { // no PUBCOMP message received in time, retry with duplicate flag attempts++; pubrel.DupFlag = true; // delay before retry if (attempts < MQTT_ATTEMPTS_RETRY) Thread.Sleep(MQTT_DELAY_RETRY); } } while ((attempts < MQTT_ATTEMPTS_RETRY) && !acknowledged); if (acknowledged) messageId = publish.MessageId; } break; default: throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); } return messageId; }
/// <summary> /// Close a client /// </summary> /// <param name="client">Client to close</param> private void CloseClient(MqttClient client) { if (this.clients.Contains(client)) { // if client is connected and it has a will message if (!client.IsConnected && client.WillFlag) { // create the will PUBLISH message MqttMsgPublish publish = new MqttMsgPublish(client.WillTopic, Encoding.UTF8.GetBytes(client.WillMessage), false, client.WillQosLevel, false); // publish message through publisher manager this.publisherManager.Publish(publish); } // if not clean session if (!client.CleanSession) { List<MqttSubscription> subscriptions = this.subscriberManager.GetSubscriptionsByClient(client.ClientId); if ((subscriptions != null) && (subscriptions.Count > 0)) { this.sessionManager.SaveSession(client.ClientId, client.Session, subscriptions); // TODO : persist client session if broker close } } // delete client from runtime subscription this.subscriberManager.Unsubscribe(client); // close the client client.Close(); // remove client from the collection this.clients.Remove(client); mqttBridge.OnClientDisconnect(client); } }
/// <summary> /// Publish a message asynchronously /// </summary> /// <param name="topic">Message topic</param> /// <param name="message">Message data (payload)</param> /// <param name="qosLevel">QoS Level</param> /// <param name="retain">Retain flag</param> /// <returns>Message Id related to PUBLISH message</returns> public ushort Publish(string topic, byte[] message, byte qosLevel, bool retain) { MqttMsgPublish publish = new MqttMsgPublish(topic, message, false, qosLevel, retain); publish.MessageId = this.GetMessageId(); // enqueue message to publish into the inflight queue this.EnqueueInflight(publish, MqttMsgFlow.ToPublish); return publish.MessageId; }
public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, Socket socket) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgPublish msg = new MqttMsgPublish(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(socket); buffer = new byte[remainingLength]; // read bytes from socket... socket.Receive(buffer); // topic name topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++]; topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length; msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8)); // read QoS level from fixed header msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // read retain flag from fixed header msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01); // message id is valid only with QOS level 1 or QOS level 2 if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); } // get payload with message data msg.message = new byte[remainingLength - index]; Array.Copy(buffer, index, msg.message, 0, msg.message.Length); return msg; }
/// <summary> /// Parse bytes for a PUBLISH message /// </summary> /// <param name="fixedHeaderFirstByte">First fixed header byte</param> /// <param name="protocolVersion">Protocol Version</param> /// <param name="channel">Channel connected to the broker</param> /// <returns>PUBLISH message instance</returns> public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { byte[] buffer; int index = 0; byte[] topicUtf8; int topicUtf8Length; MqttMsgPublish msg = new MqttMsgPublish(); // get remaining length and allocate buffer int remainingLength = MqttMsgBase.decodeRemainingLength(channel); buffer = new byte[remainingLength]; // read bytes from socket... int received = channel.Receive(buffer); // topic name topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++]; topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length; msg.topic = new String(Encoding.UTF8.GetChars(topicUtf8)); // read QoS level from fixed header msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); // check wrong QoS level (both bits can't be set 1) if (msg.qosLevel > QOS_LEVEL_EXACTLY_ONCE) throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); // read DUP flag from fixed header msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); // read retain flag from fixed header msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01); // message id is valid only with QOS level 1 or QOS level 2 if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { // message id msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.messageId |= (buffer[index++]); } // get payload with message data int messageSize = remainingLength - index; int remaining = messageSize; int messageOffset = 0; msg.message = new byte[messageSize]; // BUG FIX 26/07/2013 : receiving large payload // copy first part of payload data received Array.Copy(buffer, index, msg.message, messageOffset, received - index); remaining -= (received - index); messageOffset += (received - index); // if payload isn't finished while (remaining > 0) { // receive other payload data received = channel.Receive(buffer); Array.Copy(buffer, 0, msg.message, messageOffset, received); remaining -= received; messageOffset += received; } return msg; }
/// <summary> /// Publish message /// </summary> /// <param name="publish">Message to publish</param> public void Publish(MqttMsgPublish publish) { if (publish.Retain) { lock (this.retainedMessages) { // retained message already exists for the topic if (retainedMessages.ContainsKey(publish.Topic)) { // if empty message, remove current retained message if (publish.Message.Length == 0) retainedMessages.Remove(publish.Topic); // set new retained message for the topic else retainedMessages[publish.Topic] = publish; } else { // add new topic with related retained message retainedMessages.Add(publish.Topic, publish); } } } // enqueue lock (this.publishQueue) { this.publishQueue.Enqueue(publish); } // unlock thread for sending messages to the subscribers this.publishQueueWaitHandle.Set(); }
void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e) { MqttClient client = (MqttClient)sender; // create PUBLISH message to publish // [v3.1.1] DUP flag from an incoming PUBLISH message is not propagated to subscribers // It should be set in the outgoing PUBLISH message based on transmission for each subscriber MqttMsgPublish publish = new MqttMsgPublish(e.Topic, e.Message, false, e.QosLevel, e.Retain); // Authenticate this client can communicate with this topic if (this.uacManager.PubSubAuthentication(true, client.ClientId, e.Topic)) { // publish message through publisher manager this.publisherManager.Publish(publish); } }
public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) { int num1 = 0; MqttMsgPublish mqttMsgPublish1 = new MqttMsgPublish(); int length1 = MqttMsgBase.decodeRemainingLength(channel); byte[] buffer = new byte[length1]; int num2 = channel.Receive(buffer); byte[] numArray1 = buffer; int index1 = num1; int num3 = checked (index1 + 1); int num4 = (int)numArray1[index1] << 8 & 65280; byte[] numArray2 = buffer; int index2 = num3; int sourceIndex1 = checked (index2 + 1); int num5 = (int)numArray2[index2]; int length2 = num4 | num5; byte[] bytes = new byte[length2]; Array.Copy((Array)buffer, sourceIndex1, (Array)bytes, 0, length2); int sourceIndex2 = checked (sourceIndex1 + length2); mqttMsgPublish1.topic = new string(Encoding.UTF8.GetChars(bytes)); mqttMsgPublish1.qosLevel = checked ((byte)(((int)fixedHeaderFirstByte & 6) >> 1)); if (mqttMsgPublish1.qosLevel > (byte)2) { throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); } mqttMsgPublish1.dupFlag = ((int)fixedHeaderFirstByte & 8) >> 3 == 1; mqttMsgPublish1.retain = ((int)fixedHeaderFirstByte & 1) == 1; if (mqttMsgPublish1.qosLevel == (byte)1 || mqttMsgPublish1.qosLevel == (byte)2) { MqttMsgPublish mqttMsgPublish2 = mqttMsgPublish1; byte[] numArray3 = buffer; int index3 = sourceIndex2; int num6 = checked (index3 + 1); int num7 = (int)checked ((ushort)((int)numArray3[index3] << 8 & 65280)); mqttMsgPublish2.messageId = (ushort)num7; MqttMsgPublish mqttMsgPublish3 = mqttMsgPublish1; int messageId = (int)mqttMsgPublish3.messageId; byte[] numArray4 = buffer; int index4 = num6; sourceIndex2 = checked (index4 + 1); int num8 = (int)numArray4[index4]; mqttMsgPublish3.messageId = (ushort)(messageId | num8); } int length3 = checked (length1 - sourceIndex2); int num9 = length3; int destinationIndex1 = 0; mqttMsgPublish1.message = new byte[length3]; Array.Copy((Array)buffer, sourceIndex2, (Array)mqttMsgPublish1.message, destinationIndex1, checked (num2 - sourceIndex2)); int num10 = checked (num9 - num2 - sourceIndex2); int destinationIndex2 = checked (destinationIndex1 + num2 - sourceIndex2); while (num10 > 0) { int length4 = channel.Receive(buffer); Array.Copy((Array)buffer, 0, (Array)mqttMsgPublish1.message, destinationIndex2, length4); checked { num10 -= length4; } checked { destinationIndex2 += length4; } } return(mqttMsgPublish1); }