Files
ChunilENG/Packages/com.tivadar.best.mqtt/Runtime/MQTT/Packets/ServerConnectAckMessage.cs
정영민 2dd5d814a7 update
2025-02-20 09:59:37 +09:00

118 lines
7.1 KiB
C#

using System;
using System.Collections.Generic;
using Best.MQTT.Packets.Utils;
namespace Best.MQTT.Packets
{
/// <summary>
/// Container for a server-sent Connect acknowledgement message.
/// <see href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901074"/>
/// </summary>
public readonly struct ServerConnectAckMessage
{
/// <summary>
/// True if the server could resume to a previous session.
/// </summary>
public readonly bool SessionPresent;
public readonly ConnectAckReasonCodes ReasonCode;
public readonly UInt32? SessionExpiryInterval;
/// <summary>
/// The Server uses this value to limit the number of QoS 1 and QoS 2 publications that it is willing to process concurrently for the Client.
/// It does not provide a mechanism to limit the QoS 0 publications that the Client might try to send.
/// If the Receive Maximum value is absent, then its value defaults to 65,535.
/// </summary>
public readonly UInt16 ReceiveMaximum;
public readonly QoSLevels MaximumQoS;
public readonly bool RetainAvailable;
/// <summary>
/// Maximum Packet Size the Server is willing to accept
/// </summary>
public readonly UInt32 MaximumPacketSize;
/// <summary>
/// Server assigned ClientId.
/// </summary>
/// <remarks>The Client Identifier which was assigned by the Server because a zero length Client Identifier was found in the CONNECT packet.</remarks>
public readonly string AssignedClientIdentifier;
public readonly UInt16 TopicAliasMaximum;
public readonly string ReasonString;
public readonly List<KeyValuePair<string, string>> UserProperties;
public readonly bool WildcardSubscriptionAvailable;
public readonly bool SubscriptionIdentifiersAvailable;
public readonly bool SharedSubscriptionAvailable;
public readonly UInt16? ServerKeepAlive;
public readonly string ResponseInformation;
public readonly string ServerReference;
public readonly string AuthenticationMethod;
public readonly Best.HTTP.Shared.PlatformSupport.Memory.BufferSegment AuthenticationData;
internal ServerConnectAckMessage(Packet packet)
{
// Session Present (https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901078)
var flags = packet.VariableHeaderFields[0].Bits;
this.SessionPresent = flags[0];
// Connect Reason Code
this.ReasonCode = (ConnectAckReasonCodes)packet.VariableHeaderFields[1].Integer;
// CONNACK Properties (https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901080)
Properties properties = packet.VariableHeaderFields.Properties;
// If the Session Expiry Interval is absent the value in the CONNECT Packet used.
this.SessionExpiryInterval = properties.TryFindData(PacketProperties.SessionExpiryInterval, DataTypes.FourByteInteger, out var data) ? data.Integer : default(UInt32?);
// If the Receive Maximum value is absent, then its value defaults to 65,535.
this.ReceiveMaximum = properties.TryFindData(PacketProperties.ReceiveMaximum, DataTypes.TwoByteInteger, out data) ? (UInt16)data.Integer : UInt16.MaxValue;
// If the Maximum QoS is absent, the Client uses a Maximum QoS of 2. (https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901084)
this.MaximumQoS = properties.TryFindData(PacketProperties.MaximumQoS, DataTypes.Byte, out data) ? (QoSLevels)data.Integer : QoSLevels.ExactlyOnceDelivery;
// A value of 0 means that retained messages are not supported. A value of 1 means retained messages are supported. If not present, then retained messages are supported.
this.RetainAvailable = properties.TryFindData(PacketProperties.RetainAvailable, DataTypes.Byte, out data) ? data.Integer > 0 : true;
// If the Maximum Packet Size is not present, there is no limit on the packet size imposed beyond the limitations in the protocol as a result of the remaining length encoding and the protocol header sizes.
this.MaximumPacketSize = properties.TryFindData(PacketProperties.MaximumPacketSize, DataTypes.FourByteInteger, out data) ? data.Integer : UInt32.MaxValue;
this.AssignedClientIdentifier = properties.TryFindData(PacketProperties.AssignedClientIdentifier, DataTypes.UTF8String, out data) ? data.UTF8String.Key : null;
// If the Topic Alias Maximum property is absent, the default value is 0.
this.TopicAliasMaximum = properties.TryFindData(PacketProperties.TopicAliasMaximum, DataTypes.TwoByteInteger, out data) ? (UInt16)data.Integer : (UInt16)0;
this.ReasonString = properties.TryFindData(PacketProperties.ReasonString, DataTypes.UTF8String, out data) ? data.UTF8String.Key : null;
// The User Property is allowed to appear multiple times to represent multiple name, value pairs.
List<KeyValuePair<string, string>> tmpList = null;
properties.ForEach(PacketProperties.UserProperty, d =>
{
if (tmpList == null)
tmpList = new List<KeyValuePair<string, string>>();
tmpList.Add(d.UTF8String);
});
this.UserProperties = tmpList;
// If not present, then Wildcard Subscriptions are supported.
this.WildcardSubscriptionAvailable = properties.TryFindData(PacketProperties.WildcardSubscriptionAvailable, DataTypes.Byte, out data) ? data.Integer > 0 : true;
// If not present, then Subscription Identifiers are supported.
this.SubscriptionIdentifiersAvailable = properties.TryFindData(PacketProperties.SubscriptionIdentifierAvailable, DataTypes.Byte, out data) ? data.Integer > 0 : true;
// If not present, then Shared Subscriptions are supported.
this.SharedSubscriptionAvailable = properties.TryFindData(PacketProperties.SharedSubscriptionAvailable, DataTypes.Byte, out data) ? data.Integer > 0 : true;
// If the Server does not send the Server Keep Alive, the Server MUST use the Keep Alive value set by the Client on CONNECT [MQTT-3.2.2-22].
this.ServerKeepAlive = properties.TryFindData(PacketProperties.ServerKeepAlive, DataTypes.TwoByteInteger, out data) ? (UInt16)data.Integer : default(UInt16?);
this.ResponseInformation = properties.TryFindData(PacketProperties.ResponseInformation, DataTypes.UTF8String, out data) ? data.UTF8String.Key : null;
this.ServerReference = properties.TryFindData(PacketProperties.ServerReference, DataTypes.UTF8String, out data) ? data.UTF8String.Key : null;
this.AuthenticationMethod = properties.TryFindData(PacketProperties.AuthenticationMethod, DataTypes.UTF8String, out data) ? data.UTF8String.Key : null;
this.AuthenticationData = properties.TryFindData(PacketProperties.AuthenticationData, DataTypes.Binary, out data) ? data.Binary : Best.HTTP.Shared.PlatformSupport.Memory.BufferSegment.Empty;
}
}
}