/// <exception cref="MalformedMessageException">Exception is thrown in case of invalid packet format</exception> public static IByteBuffer encode(MQMessage header) { int length = header.GetLength(); IByteBuffer buf = GetBuffer(length); MessageType type = header.MessageType; switch (type) { case MessageType.CONNECT: Connect connect = (Connect)header; if (connect.Will != null && !connect.Will.IsValid()) { throw new MalformedMessageException("invalid will encoding"); } buf.SetByte(0, (byte)(((Int32)type) << 4)); buf.WriteShort(Connect.DEFAULT_PROTOCOL_LEVEL); buf.WriteBytes(Encoding.UTF8.GetBytes(connect.Name)); buf.WriteByte(connect.ProtocolLevel); byte contentFlags = 0; if (connect.CleanSession) { contentFlags += 0x02; } if (connect.Will != null) { contentFlags += 0x04; contentFlags += (byte)(((Int32)connect.Will.Topic.Qos) << 3); if (connect.Will.Retain) { contentFlags += 0x20; } } if (connect.Username != null) { contentFlags += 0x40; } if (connect.Password != null) { contentFlags += 0x80; } buf.WriteByte(contentFlags); buf.WriteShort(connect.Keepalive); buf.WriteShort(connect.ClientID.Length); buf.WriteBytes(Encoding.UTF8.GetBytes(connect.ClientID)); if (connect.Will != null) { String willTopic = connect.Will.Topic.Name; if (willTopic != null) { buf.WriteShort(willTopic.Length); buf.WriteBytes(Encoding.UTF8.GetBytes(willTopic)); } byte[] willMessage = connect.Will.Content; if (willMessage != null) { buf.WriteShort(willMessage.Length); buf.WriteBytes(willMessage); } } String username = connect.Username; if (username != null) { buf.WriteShort(username.Length); buf.WriteBytes(Encoding.UTF8.GetBytes(username)); } String password = connect.Password; if (password != null) { buf.WriteShort(password.Length); buf.WriteBytes(Encoding.UTF8.GetBytes(password)); } break; case MessageType.CONNACK: Connack connack = (Connack)header; buf.SetByte(0, (byte)(((Int32)type) << 4)); buf.WriteBoolean(connack.SessionPresent); buf.WriteByte((Int32)connack.ReturnCode); break; case MessageType.PUBLISH: Publish publish = (Publish)header; byte firstByte = (byte)(((Int32)type) << 4); if (publish.Dup) { firstByte += 0x08; } firstByte += (byte)(((Int32)publish.Topic.Qos) << 1); if (publish.Retain) { firstByte += 0x01; } buf.SetByte(0, firstByte); buf.WriteShort(publish.Topic.Name.Length); buf.WriteBytes(Encoding.UTF8.GetBytes(publish.Topic.Name)); if (publish.PacketID.HasValue) { buf.WriteShort(publish.PacketID.Value); } buf.WriteBytes(publish.Content); break; case MessageType.PUBACK: Puback puback = (Puback)header; buf.SetByte(0, (byte)(((Int32)type) << 4)); buf.WriteShort(puback.PacketID.Value); break; case MessageType.PUBREC: Pubrec pubrec = (Pubrec)header; buf.SetByte(0, (byte)(((Int32)type) << 4)); buf.WriteShort(pubrec.PacketID.Value); break; case MessageType.PUBREL: Pubrel pubrel = (Pubrel)header; buf.SetByte(0, (byte)((((Int32)type) << 4) | 0x2)); buf.WriteShort(pubrel.PacketID.Value); break; case MessageType.PUBCOMP: Pubcomp pubcomp = (Pubcomp)header; buf.SetByte(0, (byte)(((Int32)type) << 4)); buf.WriteShort(pubcomp.PacketID.Value); break; case MessageType.SUBSCRIBE: Subscribe sub = (Subscribe)header; buf.SetByte(0, (byte)((((Int32)type) << 4) | 0x2)); buf.WriteShort(sub.PacketID.Value); foreach (Topic subscription in sub.Topics) { buf.WriteShort(subscription.Name.Length); buf.WriteBytes(Encoding.UTF8.GetBytes(subscription.Name)); buf.WriteByte((Int32)subscription.Qos); } break; case MessageType.SUBACK: Suback suback = (Suback)header; buf.SetByte(0, (byte)(((Int32)type) << 4)); buf.WriteShort(suback.PacketID.Value); foreach (SubackCode code in suback.ReturnCodes) { buf.WriteByte((Int32)code); } break; case MessageType.UNSUBSCRIBE: Unsubscribe unsub = (Unsubscribe)header; buf.SetByte(0, (byte)((((Int32)type) << 4) | 0x2)); buf.WriteShort(unsub.PacketID.Value); foreach (String topic in unsub.Topics) { buf.WriteShort(topic.Length); buf.WriteBytes(Encoding.UTF8.GetBytes(topic)); } break; case MessageType.UNSUBACK: Unsuback unsuback = (Unsuback)header; buf.SetByte(0, (byte)(((Int32)type) << 4)); buf.WriteShort(unsuback.PacketID.Value); break; case MessageType.DISCONNECT: case MessageType.PINGREQ: case MessageType.PINGRESP: buf.SetByte(0, (byte)(((Int32)type) << 4)); break; default: throw new MalformedMessageException("Invalid header type: " + type); } return(buf); }