jsdw_ios/Pods/CocoaMQTT/Source/CocoaMQTTProperty.swift

190 lines
6.1 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// CocoaMQTTPropertyType.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/7/6.
//
import Foundation
public enum CocoaMQTTPropertyName: UInt8 {
case payloadFormatIndicator = 0x01
case willExpiryInterval = 0x02
case contentType = 0x03
case responseTopic = 0x08
case correlationData = 0x09
case subscriptionIdentifier = 0x0B
case sessionExpiryInterval = 0x11
case assignedClientIdentifier = 0x12
case serverKeepAlive = 0x13
case authenticationMethod = 0x15
case authenticationData = 0x16
case requestProblemInformation = 0x17
case willDelayInterval = 0x18
case requestResponseInformation = 0x19
case responseInformation = 0x1A
case serverReference = 0x1C
case reasonString = 0x1F
case receiveMaximum = 0x21
case topicAliasMaximum = 0x22
case topicAlias = 0x23
case maximumQoS = 0x24
case retainAvailable = 0x25
case userProperty = 0x26
case maximumPacketSize = 0x27
case wildcardSubscriptionAvailable = 0x28
case subscriptionIdentifiersAvailable = 0x29
case sharedSubscriptionAvailable = 0x2A
}
public enum formatInt: Int {
case formatUint8 = 0x11
case formatUint16 = 0x12
case formatUint32 = 0x14
case formatSint8 = 0x21
case formatSint16 = 0x22
case formatSint32 = 0x24
}
func getMQTTPropertyData(type: UInt8, value: [UInt8]) -> [UInt8] {
var properties = [UInt8]()
properties.append(UInt8(type))
properties += value
return properties
}
func getMQTTPropertyLength(type: UInt8, value: [UInt8]) -> [UInt8] {
var properties = [UInt8]()
properties.append(UInt8(type))
properties += value
return properties
}
func integerCompute(data: [UInt8], formatType: Int, offset: Int) -> (res: Int, newOffset: Int)? {
switch formatType {
case formatInt.formatUint8.rawValue:
return (unsignedByteToInt(data: data[offset]), offset + 1)
case formatInt.formatUint16.rawValue:
return (unsignedBytesToInt(data0: data[offset], data1: data[offset + 1]), offset + 2)
case formatInt.formatUint32.rawValue:
return (unsignedBytesToInt(data0: data[offset], data1: data[offset + 1], data2: data[offset + 2], data3: data[offset + 3]), offset + 4)
case formatInt.formatSint8.rawValue:
return (unsignedToSigned(unsign: unsignedByteToInt(data: data[offset]), size: 8), offset + 1)
case formatInt.formatSint16.rawValue:
return (unsignedToSigned(unsign: unsignedBytesToInt(data0: data[offset], data1: data[offset + 1]), size: 16), offset + 2)
case formatInt.formatSint32.rawValue:
return (unsignedToSigned(unsign: unsignedBytesToInt(data0: data[offset], data1: data[offset + 1], data2: data[offset + 2], data3: data[offset + 3]), size: 32), offset + 4)
default:
printDebug("integerCompute nothing")
}
return nil
}
func unsignedByteToInt(data: UInt8) -> (Int) {
return (Int)(data & 0xFF)
}
func unsignedBytesToInt(data0: UInt8, data1: UInt8) -> (Int) {
return (unsignedByteToInt(data: data0) << 8) + unsignedByteToInt(data: data1)
}
func unsignedBytesToInt(data0: UInt8, data1: UInt8, data2: UInt8, data3: UInt8) -> (Int) {
return unsignedByteToInt(data: data3) + (unsignedByteToInt(data: data2) << 8) + (unsignedByteToInt(data: data1) << 16) + (unsignedByteToInt(data: data0) << 24)
}
func unsignedToSigned(unsign: NSInteger, size: NSInteger) -> (Int) {
var res = unsign
if (res & (1 << size-1)) != 0 {
res = -1 * ((1 << size-1) - (res & ((1 << size-1) - 1)))
}
return res
}
func unsignedByteToString(data: [UInt8], offset: Int) -> (resStr: String, newOffset: Int)? {
var newOffset = offset
if offset + 1 > data.count {
return nil
}
var length = 0
let comRes = integerCompute(data: data, formatType: formatInt.formatUint16.rawValue, offset: newOffset)
length = comRes!.res
newOffset = comRes!.newOffset
var stringData = Data()
for _ in 0 ..< length {
stringData.append(data[newOffset])
newOffset += 1
}
guard let res = String(data: stringData, encoding: .utf8) else {
return nil
}
return (res, newOffset)
}
func unsignedByteToBinary(data: [UInt8], offset: Int) -> (resStr: [UInt8], newOffset: Int)? {
var newOffset = offset
if offset + 1 > data.count {
return nil
}
var length = 0
let comRes = integerCompute(data: data, formatType: formatInt.formatUint16.rawValue, offset: newOffset)
length = comRes!.res
newOffset = comRes!.newOffset
var res = [UInt8]()
for _ in 0 ..< length {
res.append(data[newOffset])
newOffset += 1
}
return (res, newOffset)
}
// 1.5.5 Variable Byte Integer
// The Variable Byte Integer is encoded using an encoding scheme which uses a single byte for values up to 127. Larger values are handled as follows. The least significant seven bits of each byte encode the data, and the most significant bit is used to indicate whether there are bytes following in the representation. Thus, each byte encodes 128 values and a "continuation bit". The maximum number of bytes in the Variable Byte Integer field is four. The encoded value MUST use the minimum number of bytes necessary to represent the value [MQTT-1.5.5-1]. This is shown in Table 11 Size of Variable Byte Integer.
func decodeVariableByteInteger(data: [UInt8], offset: Int) -> (res: Int, newOffset: Int) {
var newOffset = offset
var count = 0
var res: Int = 0
while newOffset < data.count {
let newValue = Int(data[newOffset] & 0x7f) << count
res += newValue
if (data[newOffset] & 0x80) == 0 || count >= 21 {
newOffset += 1
break
}
newOffset += 1
count += 7
}
return (res, newOffset)
}
func beVariableByteInteger(length: Int) -> [UInt8] {
var res = [UInt8]()
var tmpLen: Int = length
repeat {
var d: UInt8 = UInt8(tmpLen % 128)
tmpLen /= 128
if tmpLen > 0 {
d |= 0x80
}
res.append(d)
} while(tmpLen > 0)
return res
}
func beVariableByteInteger(_ data: UInt32) -> [UInt8]? {
if data > 0x0fffffff {
return nil
}
return beVariableByteInteger(length: Int(data))
}