diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 00000000..8e71e630 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,85 @@ +excluded: + - Pods + - .build + +line_length: 160 + +identifier_name: + max_length: + warning: 45 + error: 60 + min_length: + warning: 1 + +analyzer_rules: +disabled_rules: + - cyclomatic_complexity + - file_length + - force_cast + - function_body_length + - todo + - type_body_length + +opt_in_rules: + - array_init + - closure_end_indentation + - closure_spacing + - collection_alignment + - contains_over_filter_count + - contains_over_filter_is_empty + - contains_over_first_not_nil + - discouraged_object_literal + - empty_count + - empty_string + - empty_xctest_method + - explicit_init + - extension_access_modifier + - fallthrough + # - file_header + # - file_name + - first_where + - flatmap_over_map_reduce + - identical_operands + - joined_default_parameter + - legacy_random + - let_var_whitespace + - last_where + - literal_expression_end_indentation + - lower_acl_than_parent + # - modifier_order + - nimble_operator + - nslocalizedstring_key + - number_separator + # - object_literal + - operator_usage_whitespace + - overridden_super_call + - override_in_extension + - pattern_matching_keywords + - private_action + - private_outlet + # - prohibited_interface_builder + - prohibited_super_call + - quick_discouraged_call + - quick_discouraged_focused_test + - quick_discouraged_pending_test + - reduce_into + - redundant_nil_coalescing + - redundant_type_annotation + - single_test_class + # - sorted_first_last + - sorted_imports + - static_operator + # - strong_iboutlet + - toggle_bool + - unavailable_function + - unneeded_parentheses_in_closure_argument + - unowned_variable_capture + - untyped_error_in_catch + - vertical_parameter_alignment_on_call + - vertical_whitespace_closing_braces + - vertical_whitespace_opening_braces + - xct_specific_matcher + - yoda_condition + +number_separator: + minimum_length: 5 diff --git a/CocoaMQTTTests/CocoaMQTTDeliverTests.swift b/CocoaMQTTTests/CocoaMQTTDeliverTests.swift index 9108e6d9..b84bbc31 100644 --- a/CocoaMQTTTests/CocoaMQTTDeliverTests.swift +++ b/CocoaMQTTTests/CocoaMQTTDeliverTests.swift @@ -6,192 +6,175 @@ // Copyright © 2019 emqtt.io. All rights reserved. // -import XCTest @testable import CocoaMQTT +import XCTest class CocoaMQTTDeliverTests: XCTestCase { - - override func setUp() { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - func testSerialDeliver() { let caller = Caller() let deliver = CocoaMQTTDeliver() - + let frames = [FramePublish(topic: "t/0", payload: [0x00], qos: .qos0), FramePublish(topic: "t/1", payload: [0x01], qos: .qos1, msgid: 1), FramePublish(topic: "t/2", payload: [0x02], qos: .qos2, msgid: 2)] - + deliver.delegate = caller for f in frames { _ = deliver.add(f) } ms_sleep(100) - + XCTAssertEqual(frames.count, caller.frames.count) for i in 0 ..< frames.count { assertEqual(frames[i], caller.frames[i]) } - } - + func testAckMessage() { let caller = Caller() let deliver = CocoaMQTTDeliver() - + let frames = [FramePublish(topic: "t/0", payload: [0x00], qos: .qos0), FramePublish(topic: "t/1", payload: [0x01], qos: .qos1, msgid: 1), FramePublish(topic: "t/2", payload: [0x02], qos: .qos2, msgid: 2)] - + deliver.delegate = caller for f in frames { _ = deliver.add(f) } ms_sleep(100) - + XCTAssertEqual(frames.count, caller.frames.count) for i in 0 ..< frames.count { assertEqual(frames[i], caller.frames[i]) } - + var inflights = deliver.t_inflightFrames() XCTAssertEqual(inflights.count, 2) XCTAssertEqual(deliver.t_queuedFrames().count, 0) for i in 0 ..< inflights.count { - assertEqual(inflights[i], frames[i+1]) + assertEqual(inflights[i], frames[i + 1]) } - + deliver.ack(by: FramePubAck(msgid: 1)) deliver.ack(by: FramePubRec(msgid: 2)) ms_sleep(100) - + inflights = deliver.t_inflightFrames() XCTAssertEqual(inflights.count, 1) XCTAssertEqual(deliver.t_queuedFrames().count, 0) assertEqual(inflights[0], FramePubRel(msgid: 2)) - + deliver.ack(by: FramePubComp(msgid: 2)) ms_sleep(100) - + inflights = deliver.t_inflightFrames() XCTAssertEqual(inflights.count, 0) - + // Assert sent assertEqual(caller.frames[3], FramePubRel(msgid: 2)) } - + func testQueueAndInflightReDeliver() { let caller = Caller() let deliver = CocoaMQTTDeliver() - + let frames = [FramePublish(topic: "t/0", payload: [0x00], qos: .qos0), FramePublish(topic: "t/1", payload: [0x01], qos: .qos1, msgid: 1), FramePublish(topic: "t/2", payload: [0x02], qos: .qos2, msgid: 2)] - + deliver.retryTimeInterval = 1000 deliver.inflightWindowSize = 1 deliver.mqueueSize = 1 deliver.delegate = caller - - XCTAssertEqual(true, deliver.add(frames[1])) + + XCTAssertTrue(deliver.add(frames[1])) ms_sleep(100) // Wait the message transfer to inflight-window - XCTAssertEqual(true, deliver.add(frames[2])) - XCTAssertEqual(false, deliver.add(frames[0])) - + XCTAssertTrue(deliver.add(frames[2])) + XCTAssertFalse(deliver.add(frames[0])) + ms_sleep(1100) // Wait for re-delivering timeout XCTAssertEqual(caller.frames.count, 2) assertEqual(caller.frames[0], frames[1]) assertEqual(caller.frames[1], frames[1]) - + deliver.ack(by: FramePubAck(msgid: 1)) ms_sleep(100) // Waiting for the frame in the mqueue transfer to inflight window - + var inflights = deliver.t_inflightFrames() XCTAssertEqual(inflights.count, 1) assertEqual(inflights[0], frames[2]) - + deliver.ack(by: FramePubRec(msgid: 2)) ms_sleep(2000) // Waiting for re-delivering timeout deliver.ack(by: FramePubComp(msgid: 2)) ms_sleep(100) - + inflights = deliver.t_inflightFrames() XCTAssertEqual(inflights.count, 0) - + let sents: [Frame] = [frames[1], frames[1], frames[2], FramePubRel(msgid: 2), FramePubRel(msgid: 2)] XCTAssertEqual(caller.frames.count, sents.count) for i in 0 ..< sents.count { assertEqual(caller.frames[i], sents[i]) } } - + func testStorage() { - let clientID = "deliver-unit-testing" let caller = Caller() let deliver = CocoaMQTTDeliver() - + let frames = [FramePublish(topic: "t/0", payload: [0x00], qos: .qos0), FramePublish(topic: "t/1", payload: [0x01], qos: .qos1, msgid: 1), FramePublish(topic: "t/2", payload: [0x02], qos: .qos2, msgid: 2)] - + guard let storage = CocoaMQTTStorage(by: clientID) else { XCTAssert(false, "Initial storage failed") return } - + deliver.delegate = caller deliver.recoverSessionBy(storage) - + for f in frames { _ = deliver.add(f) } - + var saved = storage.readAll() XCTAssertEqual(saved.count, 2) - - + deliver.ack(by: FramePubAck(msgid: 1)) ms_sleep(100) saved = storage.readAll() XCTAssertEqual(saved.count, 1) - + deliver.ack(by: FramePubRec(msgid: 2)) ms_sleep(100) saved = storage.readAll() XCTAssertEqual(saved.count, 1) assertEqual(saved[0], FramePubRel(msgid: 2)) - - + deliver.ack(by: FramePubComp(msgid: 2)) ms_sleep(100) saved = storage.readAll() XCTAssertEqual(saved.count, 0) - + caller.reset() _ = storage.write(frames[1]) deliver.recoverSessionBy(storage) ms_sleep(100) XCTAssertEqual(caller.frames.count, 1) assertEqual(caller.frames[0], frames[1]) - - + deliver.ack(by: FramePubAck(msgid: 1)) ms_sleep(100) XCTAssertEqual(storage.readAll().count, 0) } - - func testTODO() { - // TODO: How to test large of messages combined qos0/qos1/qos2 - } - - + + // TODO: How to test large of messages combined qos0/qos1/qos2 + // Helper for assert equality for Frame private func assertEqual(_ f1: Frame, _ f2: Frame, _ lines: Int = #line) { if let pub1 = f1 as? FramePublish, @@ -200,45 +183,43 @@ class CocoaMQTTDeliverTests: XCTestCase { XCTAssertEqual(pub1.payload(), pub2.payload()) XCTAssertEqual(pub1.msgid, pub2.msgid) XCTAssertEqual(pub1.qos, pub2.qos) - } - else if let rel1 = f1 as? FramePubRel, - let rel2 = f2 as? FramePubRel{ + } else if let rel1 = f1 as? FramePubRel, + let rel2 = f2 as? FramePubRel { XCTAssertEqual(rel1.msgid, rel2.msgid) } else { XCTAssert(false, "Assert equal failed line: \(lines)") } } - + private func ms_sleep(_ ms: Int) { usleep(useconds_t(ms * 1000)) } } private class Caller: CocoaMQTTDeliverProtocol { - - private let delegate_queue_key = DispatchSpecificKey() - private let delegate_queue_val = "_custom_delegate_queue_" - + private let delegateQueueKey = DispatchSpecificKey() + private let delegateQueueVal = "_custom_delegate_queue_" + var delegateQueue: DispatchQueue - + var frames = [Frame]() - + init() { delegateQueue = DispatchQueue(label: "caller.deliver.test") - delegateQueue.setSpecific(key: delegate_queue_key, value: delegate_queue_val) + delegateQueue.setSpecific(key: delegateQueueKey, value: delegateQueueVal) } - + func reset() { frames = [] } - + func deliver(_ deliver: CocoaMQTTDeliver, wantToSend frame: Frame) { assert_in_del_queue() frames.append(frame) } - + private func assert_in_del_queue() { - XCTAssertEqual(delegate_queue_val, DispatchQueue.getSpecific(key: delegate_queue_key)) + XCTAssertEqual(delegateQueueVal, DispatchQueue.getSpecific(key: delegateQueueKey)) } } diff --git a/CocoaMQTTTests/CocoaMQTTStorageTests.swift b/CocoaMQTTTests/CocoaMQTTStorageTests.swift index 772042a0..1dabe8b8 100644 --- a/CocoaMQTTTests/CocoaMQTTStorageTests.swift +++ b/CocoaMQTTTests/CocoaMQTTStorageTests.swift @@ -6,35 +6,26 @@ // Copyright © 2019 emqtt.io. All rights reserved. // -import XCTest @testable import CocoaMQTT +import XCTest class CocoaMQTTStorageTests: XCTestCase { - var clientId = "c1" - override func setUp() { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - func testStorage() { let frames = [FramePublish(topic: "t/1", payload: [0x01], qos: .qos1, msgid: 1), FramePublish(topic: "t/2", payload: [0x01], qos: .qos1, msgid: 2), - FramePublish(topic: "t/3", payload: [0x01], qos: .qos1, msgid: 3),] - + FramePublish(topic: "t/3", payload: [0x01], qos: .qos1, msgid: 3) ] + var storage: CocoaMQTTStorage? = CocoaMQTTStorage(by: clientId) - + for f in frames { XCTAssertEqual(true, storage?.write(f)) } - + storage?.remove(frames[1]) storage = nil - + storage = CocoaMQTTStorage(by: clientId) let should = [frames[0], frames[2]] let saved = storage?.readAll() @@ -42,16 +33,16 @@ class CocoaMQTTStorageTests: XCTestCase { for i in 0 ..< should.count { assertEqual(should[i], saved?[i]) } - + let taken = storage?.takeAll() XCTAssertEqual(should.count, taken?.count) for i in 0 ..< should.count { assertEqual(should[i], taken?[i]) } - + XCTAssertEqual(storage?.readAll().count, 0) } - + private func assertEqual(_ f1: Frame?, _ f2: Frame?) { if let pub1 = f1 as? FramePublish, let pub2 = f2 as? FramePublish { @@ -59,9 +50,8 @@ class CocoaMQTTStorageTests: XCTestCase { XCTAssertEqual(pub1.payload(), pub2.payload()) XCTAssertEqual(pub1.msgid, pub2.msgid) XCTAssertEqual(pub1.qos, pub2.qos) - } - else if let rel1 = f1 as? FramePubRel, - let rel2 = f2 as? FramePubRel{ + } else if let rel1 = f1 as? FramePubRel, + let rel2 = f2 as? FramePubRel { XCTAssertEqual(rel1.msgid, rel2.msgid) } else { XCTAssert(false) diff --git a/CocoaMQTTTests/CocoaMQTTTests.swift b/CocoaMQTTTests/CocoaMQTTTests.swift index 255acb9b..0e38fc1f 100644 --- a/CocoaMQTTTests/CocoaMQTTTests.swift +++ b/CocoaMQTTTests/CocoaMQTTTests.swift @@ -6,8 +6,8 @@ // Copyright © 2015年 emqx.io. All rights reserved. // -import XCTest @testable import CocoaMQTT +import XCTest #if IS_SWIFT_PACKAGE @testable import CocoaMQTTWebSocket #endif @@ -17,23 +17,22 @@ private let port: UInt16 = 1883 private let sslport: UInt16 = 8883 private let clientID = "ClientForUnitTesting-" + randomCode(length: 6) -private let delegate_queue_key = DispatchSpecificKey() -private let delegate_queue_val = "_custom_delegate_queue_" +private let delegateQueueKey = DispatchSpecificKey() +private let delegateQueueVal = "_custom_delegate_queue_" class CocoaMQTTTests: XCTestCase { - var deleQueue: DispatchQueue! - + override func setUp() { deleQueue = DispatchQueue(label: "cttest") - deleQueue.setSpecific(key: delegate_queue_key, value: delegate_queue_val) + deleQueue.setSpecific(key: delegateQueueKey, value: delegateQueueVal) super.setUp() } - + override func tearDown() { super.tearDown() } - + func testConnect() { let caller = Caller() let mqtt = CocoaMQTT(clientID: clientID, host: host, port: port) @@ -41,7 +40,7 @@ class CocoaMQTTTests: XCTestCase { mqtt.delegate = caller mqtt.logLevel = .error mqtt.autoReconnect = false - + _ = mqtt.connect() wait_for { caller.isConnected } XCTAssertEqual(mqtt.connState, .connected) @@ -70,7 +69,7 @@ class CocoaMQTTTests: XCTestCase { } return false } - + mqtt.unsubscribe(topics[0]) mqtt.unsubscribe(topics[1]) mqtt.unsubscribe(topics[2]) @@ -83,9 +82,8 @@ class CocoaMQTTTests: XCTestCase { caller.isConnected == false } XCTAssertEqual(mqtt.connState, .disconnected) - } - + // This is a basic test of the websocket authentication used by AWS IoT Custom Authorizers // https://docs.aws.amazon.com/iot/latest/developerguide/custom-authorizer.html func testWebsocketAuthConnect() { @@ -94,9 +92,10 @@ class CocoaMQTTTests: XCTestCase { let websocket = CocoaMQTTWebSocket(uri: "/mqtt") websocket.headers = [ "x-amz-customauthorizer-name": "tokenAuthorizer", + // swiftlint:disable:next line_length "x-amz-customauthorizer-signature": "qnQ+T1i2ahSuispDMbjBPn/bN91jDpOmiRAVfTqfXTVvrEP6mNroYJLeVm6vrCp0dODgoiNYKWjwXANuseVafMALL18rMVyQOCaRTStI7xh/pFKVtnK+pdJroPto8ElJhia4cfETwmCdHq7rXLUqdvUGFiVh4+67M5R6088bfhZnjwjgcvhvG8mpTo2yONOkqDK9eA9XZcJhjrURF8DHsPrpIjIihYHq7LdsL5nFJ9FM11mA2AUj51fHZHO7uOfegprFgIeI32Tcn5KEWEDGrD3shvOrqUtDuodrfkALGtNjpGdWNOp/8XKK19KsbUJJrMaH6CDk3j6pn7S1lilz2Q==", "token": "3c7a880d-0868-40dc-8183-8870323803fa", - "Sec-WebSocket-Protocol": "mqttv3.1", + "Sec-WebSocket-Protocol": "mqttv3.1" ] websocket.enableSSL = true let mqtt = CocoaMQTT(clientID: clientID, host: "XXXXXXXXXXXX-ats.iot.eu-west-1.amazonaws.com", port: 443, socket: websocket) @@ -127,7 +126,7 @@ class CocoaMQTTTests: XCTestCase { return false } } - + func testWebsocketConnect() { let caller = Caller() let websocket = CocoaMQTTWebSocket(uri: "/mqtt") @@ -136,7 +135,7 @@ class CocoaMQTTTests: XCTestCase { mqtt.delegate = caller mqtt.logLevel = .error mqtt.autoReconnect = false - //mqtt.enableSSL = true + // mqtt.enableSSL = true _ = mqtt.connect() wait_for { caller.isConnected } @@ -166,7 +165,7 @@ class CocoaMQTTTests: XCTestCase { } return false } - + mqtt.unsubscribe(topics[0]) mqtt.unsubscribe(topics[1]) mqtt.unsubscribe(topics[2]) @@ -189,26 +188,26 @@ class CocoaMQTTTests: XCTestCase { mqtt.logLevel = .error mqtt.autoReconnect = true mqtt.autoReconnectTimeInterval = 1 - + _ = mqtt.connect() wait_for { caller.isConnected } XCTAssertEqual(mqtt.connState, .connected) - + mqtt.internal_disconnect() wait_for { caller.isConnected == false } - + // Waiting for auto-reconnect wait_for { caller.isConnected } - + mqtt.disconnect() wait_for { caller.isConnected == false } XCTAssertEqual(mqtt.connState, .disconnected) } - + func testLongString() { let caller = Caller() let mqtt = CocoaMQTT(clientID: clientID, host: host, port: port) @@ -216,7 +215,7 @@ class CocoaMQTTTests: XCTestCase { mqtt.delegate = caller mqtt.logLevel = .error mqtt.autoReconnect = false - + _ = mqtt.connect() wait_for { caller.isConnected } XCTAssertEqual(mqtt.connState, .connected) @@ -228,18 +227,18 @@ class CocoaMQTTTests: XCTestCase { mqtt.publish("t/1", withString: longStringGen(), qos: .qos2) wait_for { - guard caller.recvs.count > 0 else { + guard !caller.recvs.isEmpty else { return false } XCTAssertEqual(caller.recvs[0].topic, "t/1") return true } - + mqtt.disconnect() wait_for { caller.isConnected == false } XCTAssertEqual(mqtt.connState, .disconnected) } - + func testProcessSafePub() { let caller = Caller() let mqtt = CocoaMQTT(clientID: clientID, host: host, port: port) @@ -247,20 +246,19 @@ class CocoaMQTTTests: XCTestCase { mqtt.delegate = caller mqtt.logLevel = .error mqtt.autoReconnect = false - + _ = mqtt.connect() wait_for { caller.isConnected } XCTAssertEqual(mqtt.connState, .connected) - mqtt.subscribe("t/#", qos: .qos1) wait_for { caller.subs == ["t/#"] } - + mqtt.inflightWindowSize = 10 mqtt.messageQueueSize = 100 - + let concurrentQueue = DispatchQueue(label: "tests.cocoamqtt.emqx", qos: .default, attributes: .concurrent) for i in 0 ..< 100 { concurrentQueue.async { @@ -270,12 +268,12 @@ class CocoaMQTTTests: XCTestCase { wait_for { caller.recvs.count == 100 } - + mqtt.disconnect() wait_for { caller.isConnected == false } XCTAssertEqual(mqtt.connState, .disconnected) } - + func testOnyWaySSL() { let caller = Caller() let mqtt = CocoaMQTT(clientID: clientID, host: host, port: sslport) @@ -284,17 +282,17 @@ class CocoaMQTTTests: XCTestCase { mqtt.logLevel = .error mqtt.enableSSL = true mqtt.allowUntrustCACertificate = true - + _ = mqtt.connect() wait_for { caller.isConnected } - XCTAssertEqual(caller.isSSL, true) + XCTAssertTrue(caller.isSSL) XCTAssertEqual(mqtt.connState, .connected) - + mqtt.disconnect() wait_for { caller.isConnected == false } XCTAssertEqual(mqtt.connState, .disconnected) } - + func testTwoWaySLL() { let caller = Caller() let mqtt = CocoaMQTT(clientID: clientID, host: host, port: sslport) @@ -303,23 +301,22 @@ class CocoaMQTTTests: XCTestCase { mqtt.logLevel = .error mqtt.enableSSL = true mqtt.allowUntrustCACertificate = true - + let clientCertArray = getClientCertFromP12File(certName: "client-keycert", certPassword: "MySecretPassword") var sslSettings: [String: NSObject] = [:] sslSettings[kCFStreamSSLCertificates as String] = clientCertArray - + mqtt.sslSettings = sslSettings - + _ = mqtt.connect() wait_for { caller.isConnected } - XCTAssertEqual(caller.isSSL, true) + XCTAssertTrue(caller.isSSL) XCTAssertEqual(mqtt.connState, .connected) - + mqtt.disconnect() wait_for { caller.isConnected == false } XCTAssertEqual(mqtt.connState, .disconnected) - } } @@ -340,14 +337,14 @@ extension CocoaMQTTTests { wait(for: [exp], timeout: TimeInterval(t)) thrd.cancel() } - + private func ms_sleep(_ ms: Int) { usleep(useconds_t(ms * 1000)) } - + func getClientCertFromP12File(certName: String, certPassword: String) -> CFArray? { let testBundle = Bundle(for: type(of: self)) - + // get p12 file path let resourcePath = testBundle.path(forResource: certName, ofType: "p12") @@ -358,9 +355,9 @@ extension CocoaMQTTTests { // create key dictionary for reading p12 file let key = kSecImportExportPassphrase as String - let options : NSDictionary = [key: certPassword] + let options: NSDictionary = [key: certPassword] - var items : CFArray? + var items: CFArray? let securityError = SecPKCS12Import(p12Data, options, &items) guard securityError == errSecSuccess else { @@ -387,100 +384,98 @@ extension CocoaMQTTTests { } private class Caller: CocoaMQTTDelegate { - var recvs = [FramePublish]() - + var sents = [UInt16]() - + var acks = [UInt16]() - + var subs = [String]() - + var isConnected = false - + var isSSL = false - + func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) { assert_in_del_queue() if ack == .accept { isConnected = true } } - + func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) { assert_in_del_queue() - + sents.append(id) } - + func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16) { assert_in_del_queue() - + acks.append(id) } - + func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) { assert_in_del_queue() - - var frame = message.t_pub_frame + + var frame = message.tPubFrame frame.msgid = id recvs.append(frame) } - + func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String]) { assert_in_del_queue() - - subs = subs + (success.allKeys as! [String]) + + subs += (success.allKeys as! [String]) } - + func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopics topics: [String]) { assert_in_del_queue() - - subs = subs.filter { (e) -> Bool in + + subs = subs.filter { e -> Bool in !topics.contains(e) } } - + func mqttDidPing(_ mqtt: CocoaMQTT) { assert_in_del_queue() } - + func mqttDidReceivePong(_ mqtt: CocoaMQTT) { assert_in_del_queue() } - + func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) { assert_in_del_queue() - + isConnected = false } - + func mqtt(_ mqtt: CocoaMQTT, didStateChangeTo state: CocoaMQTTConnState) { assert_in_del_queue() } - + func mqtt(_ mqtt: CocoaMQTT, didPublishComplete id: UInt16) { assert_in_del_queue() } - + func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) { assert_in_del_queue() - + isSSL = true - + completionHandler(true) } func assert_in_del_queue() { - XCTAssertEqual(delegate_queue_val, DispatchQueue.getSpecific(key: delegate_queue_key)) + XCTAssertEqual(delegateQueueVal, DispatchQueue.getSpecific(key: delegateQueueKey)) } } // tools - private func randomCode(length: Int) -> String { let base62chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" var code = "" for _ in 0.. String { "燕燕于飞,颉之颃之。之子于归,远于将之。瞻望弗及,伫立以泣。\n" + "燕燕于飞,下上其音。之子于归,远送于南。瞻望弗及,实劳我心。\n" + "仲氏任只,其心塞渊。终温且惠,淑慎其身。先君之思,以勗寡人。\n" - + for _ in 1...100 { string.append(shijing) } diff --git a/CocoaMQTTTests/FrameTests.swift b/CocoaMQTTTests/FrameTests.swift index 600b7765..b54261ee 100644 --- a/CocoaMQTTTests/FrameTests.swift +++ b/CocoaMQTTTests/FrameTests.swift @@ -6,22 +6,21 @@ // Copyright © 2018 emqx.io. All rights reserved. // -import XCTest @testable import CocoaMQTT +import XCTest class FrameTests: XCTestCase { - func testFrameConnect() { var conn = FrameConnect(clientID: "sheep") conn.keepAlive = 60 conn.cleansess = true - + XCTAssertEqual(conn.packetFixedHeaderType, 0x10) XCTAssertEqual(conn.type, FrameType.connect) - XCTAssertEqual(conn.dup, false) + XCTAssertFalse(conn.dup) XCTAssertEqual(conn.qos, .qos0) - XCTAssertEqual(conn.retained, false) - + XCTAssertFalse(conn.retained) + XCTAssertEqual(conn.bytes(version: "3.1.1"), [0x10, 0x11, 0x00, 0x04, 0x4D, 0x51, 0x54, 0x54, // MQTT @@ -29,12 +28,12 @@ class FrameTests: XCTestCase { 0x02, // Connect Flags 0x00, 0x3C, // Keepalive - 60 0x00, 0x05, 0x73, 0x68, 0x65, 0x65, 0x70]) // ClientID - sheep - + conn.username = "abcd" conn.password = "pwd" conn.willMsg = CocoaMQTTMessage(topic: "t/1", string: "Banalana", qos: .qos2, retained: true) conn.cleansess = false - + XCTAssertEqual(conn.bytes(version: "3.1.1"), [0x10, 0x2B, 0x00, 0x04, 0x4D, 0x51, 0x54, 0x54, // MQTT @@ -47,30 +46,29 @@ class FrameTests: XCTestCase { 0x00, 0x04, 0x61, 0x62, 0x63, 0x64, // Username - abcd 0x00, 0x03, 0x70, 0x77, 0x64]) // Password - pwd } - + func testFrameConAck() { var connack = FrameConnAck(returnCode: .accept) var bytes = [UInt8](connack.bytes(version: "3.1.1")[2...]) var connack2 = FrameConnAck(packetFixedHeaderType: FrameType.connack.rawValue, bytes: bytes) - + XCTAssertEqual(connack.returnCode, connack2?.returnCode) XCTAssertEqual(connack.sessPresent, connack2?.sessPresent) - + connack.returnCode = .notAuthorized connack.sessPresent = true bytes = [UInt8](connack.bytes(version: "3.1.1")[2...]) connack2 = FrameConnAck(packetFixedHeaderType: FrameType.connack.rawValue, bytes: bytes) - + XCTAssertEqual(connack.returnCode, connack2?.returnCode) XCTAssertEqual(connack.sessPresent, connack2?.sessPresent) } - + func testFramePublish() { - var publish = FramePublish(topic: "t/a", payload: "aaa".utf8 + [], qos: .qos0, msgid: 0x0010) var bytes = [UInt8](publish.bytes(version: "3.1.1")[2...]) var publish2 = FramePublish(packetFixedHeaderType: FrameType.publish.rawValue, bytes: bytes) - + XCTAssertEqual(publish.dup, publish2?.dup) XCTAssertEqual(publish.qos, publish2?.qos) XCTAssertEqual(publish.retained, publish2?.retained) @@ -78,25 +76,23 @@ class FrameTests: XCTestCase { XCTAssertEqual(publish.msgid, 0x0010) XCTAssertEqual(publish2?.msgid, 0) XCTAssertEqual(publish.payload(), publish2?.payload()) - publish.dup = false publish.retained = true publish.qos = .qos2 publish.topic = "t/b" publish._payload = "bbb".utf8 + [] - + bytes = [UInt8](publish.bytes(version: "3.1.1")[2...]) publish2 = FramePublish(packetFixedHeaderType: 0x35, bytes: bytes) - + XCTAssertEqual(publish.dup, publish2?.dup) XCTAssertEqual(publish.qos, publish2?.qos) XCTAssertEqual(publish.retained, publish2?.retained) XCTAssertEqual(publish.topic, publish2?.topic) XCTAssertEqual(publish.msgid, publish2?.msgid) XCTAssertEqual(publish.payload(), publish2?.payload()) - - + // -- Property GET/SET // PUBLISH - QOS2 - DUP - RETAINED guard var f0 = FramePublish(packetFixedHeaderType: 0x3D, @@ -109,23 +105,23 @@ class FrameTests: XCTestCase { XCTAssertEqual(f0.packetFixedHeaderType, 0x3D) XCTAssertEqual(f0.type, FrameType.publish) // TODO: Fix dup - XCTAssertEqual(f0.dup, true) + XCTAssertTrue(f0.dup) XCTAssertEqual(f0.qos, .qos2) - XCTAssertEqual(f0.retained, true) - + XCTAssertTrue(f0.retained) + XCTAssertEqual(f0.topic, "t/a") XCTAssertEqual(f0.msgid, 16) XCTAssertEqual(f0.payload(), [0x61, 0x61, 0x61]) - + f0.dup = false f0.qos = CocoaMQTTQoS.qos0 f0.retained = false - + f0.dup = true - XCTAssertEqual(f0.dup, true) + XCTAssertTrue(f0.dup) f0.dup = false - XCTAssertEqual(f0.dup, false) - + XCTAssertFalse(f0.dup) + XCTAssertEqual(f0.qos, .qos0) f0.qos = CocoaMQTTQoS.qos1 XCTAssertEqual(f0.qos, .qos1) @@ -134,114 +130,117 @@ class FrameTests: XCTestCase { f0.qos = CocoaMQTTQoS.qos0 XCTAssertEqual(f0.qos, .qos0) - XCTAssertEqual(f0.retained, false) + XCTAssertFalse(f0.retained) f0.retained = true - XCTAssertEqual(f0.retained, true) + XCTAssertTrue(f0.retained) f0.retained = false - XCTAssertEqual(f0.retained, false) - - let f1 = FramePublish(packetFixedHeaderType: 0x30, bytes:[0, 60, 47, 114, 101, 109, 111, 116, 101, 97, 112, 112, 47, 109, 111, 98, 105, 108, 101, 47, 98, 114, 111, 97, 100, 99, 97, 115, 116, 47, 112, 108, 97, 116, 102, 111, 114, 109, 95, 115, 101, 114, 118, 105, 99, 101, 47, 97, 99, 116, 105, 111, 110, 115, 47, 116, 118, 115, 108, 101, 101, 112]) + XCTAssertFalse(f0.retained) + + let f1 = FramePublish(packetFixedHeaderType: 0x30, bytes: [ + 0, 60, 47, 114, 101, 109, 111, 116, 101, 97, 112, 112, 47, 109, 111, 98, 105, + 108, 101, 47, 98, 114, 111, 97, 100, 99, 97, 115, 116, 47, 112, 108, 97, 116, + 102, 111, 114, 109, 95, 115, 101, 114, 118, 105, 99, 101, 47, 97, 99, 116, 105, + 111, 110, 115, 47, 116, 118, 115, 108, 101, 101, 112 + ]) XCTAssertEqual(f1?.payload().count, 0) } - + func testFramePubAck() { - var puback = FramePubAck(msgid: 0x1010) var bytes = [UInt8](puback.bytes(version: "3.1.1")[2...]) var puback2 = FramePubAck(packetFixedHeaderType: FrameType.puback.rawValue, bytes: bytes) - + XCTAssertEqual(puback.packetFixedHeaderType, puback2?.packetFixedHeaderType) XCTAssertEqual(puback.msgid, puback2?.msgid) - + XCTAssertEqual(puback2?.packetFixedHeaderType, 0x40) XCTAssertEqual(puback2?.msgid, 0x1010) XCTAssertEqual(puback2?.bytes(version: "3.1.1"), [0x40, 0x02, 0x10, 0x10]) - + puback.msgid = 0x1011 bytes = [UInt8](puback.bytes(version: "3.1.1")[2...]) puback2 = FramePubAck(packetFixedHeaderType: FrameType.puback.rawValue, bytes: bytes) - + XCTAssertEqual(puback.packetFixedHeaderType, puback2?.packetFixedHeaderType) XCTAssertEqual(puback.msgid, puback2?.msgid) - + XCTAssertEqual(puback2?.packetFixedHeaderType, 0x40) XCTAssertEqual(puback2?.msgid, 0x1011) XCTAssertEqual(puback2?.bytes(version: "3.1.1"), [0x40, 0x02, 0x10, 0x11]) } - + func testFramePubRec() { var pubrec = FramePubRec(msgid: 0x1010) var bytes = [UInt8](pubrec.bytes(version: "3.1.1")[2...]) var pubrec2 = FramePubRec(packetFixedHeaderType: FrameType.pubrec.rawValue, bytes: bytes) - + XCTAssertEqual(pubrec.packetFixedHeaderType, pubrec2?.packetFixedHeaderType) XCTAssertEqual(pubrec.msgid, pubrec2?.msgid) - + XCTAssertEqual(pubrec2?.packetFixedHeaderType, 0x50) XCTAssertEqual(pubrec2?.msgid, 0x1010) XCTAssertEqual(pubrec2?.bytes(version: "3.1.1"), [0x50, 0x02, 0x10, 0x10]) - + pubrec.msgid = 0x1011 bytes = [UInt8](pubrec.bytes(version: "3.1.1")[2...]) pubrec2 = FramePubRec(packetFixedHeaderType: FrameType.pubrec.rawValue, bytes: bytes) - + XCTAssertEqual(pubrec.packetFixedHeaderType, pubrec2?.packetFixedHeaderType) XCTAssertEqual(pubrec.msgid, pubrec2?.msgid) - + XCTAssertEqual(pubrec2?.packetFixedHeaderType, 0x50) XCTAssertEqual(pubrec2?.msgid, 0x1011) XCTAssertEqual(pubrec2?.bytes(version: "3.1.1"), [0x50, 0x02, 0x10, 0x11]) } - + func testFramePubRel() { - var pubrel = FramePubRel(msgid: 0x1010) var bytes = [UInt8](pubrel.bytes(version: "3.1.1")[2...]) var pubrel2 = FramePubRel(packetFixedHeaderType: 0x62, bytes: bytes) - + XCTAssertEqual(pubrel.packetFixedHeaderType, pubrel2?.packetFixedHeaderType) XCTAssertEqual(pubrel.msgid, pubrel2?.msgid) - + XCTAssertEqual(pubrel2?.packetFixedHeaderType, 0x62) XCTAssertEqual(pubrel2?.msgid, 0x1010) XCTAssertEqual(pubrel2?.bytes(version: "3.1.1"), [0x62, 0x02, 0x10, 0x10]) - + pubrel.msgid = 0x1011 bytes = [UInt8](pubrel.bytes(version: "3.1.1")[2...]) pubrel2 = FramePubRel(packetFixedHeaderType: 0x62, bytes: bytes) - + XCTAssertEqual(pubrel.packetFixedHeaderType, pubrel2?.packetFixedHeaderType) XCTAssertEqual(pubrel.msgid, pubrel2?.msgid) - + XCTAssertEqual(pubrel2?.packetFixedHeaderType, 0x62) XCTAssertEqual(pubrel2?.msgid, 0x1011) XCTAssertEqual(pubrel2?.bytes(version: "3.1.1"), [0x62, 0x02, 0x10, 0x11]) } - + func testFramePubComp() { var pubcomp = FramePubComp(msgid: 0x1010) var bytes = [UInt8](pubcomp.bytes(version: "3.1.1")[2...]) var pubcomp2 = FramePubComp(packetFixedHeaderType: FrameType.pubcomp.rawValue, bytes: bytes) - + XCTAssertEqual(pubcomp.packetFixedHeaderType, pubcomp2?.packetFixedHeaderType) XCTAssertEqual(pubcomp.msgid, pubcomp2?.msgid) - + XCTAssertEqual(pubcomp2?.packetFixedHeaderType, 0x70) XCTAssertEqual(pubcomp2?.msgid, 0x1010) XCTAssertEqual(pubcomp2?.bytes(version: "3.1.1"), [0x70, 0x02, 0x10, 0x10]) - + pubcomp.msgid = 0x1011 bytes = [UInt8](pubcomp.bytes(version: "3.1.1")[2...]) pubcomp2 = FramePubComp(packetFixedHeaderType: FrameType.pubcomp.rawValue, bytes: bytes) - + XCTAssertEqual(pubcomp.packetFixedHeaderType, pubcomp2?.packetFixedHeaderType) XCTAssertEqual(pubcomp.msgid, pubcomp2?.msgid) - + XCTAssertEqual(pubcomp2?.packetFixedHeaderType, 0x70) XCTAssertEqual(pubcomp2?.msgid, 0x1011) XCTAssertEqual(pubcomp2?.bytes(version: "3.1.1"), [0x70, 0x02, 0x10, 0x11]) } - + func testFrameSubscribe() throws { let subscribe = FrameSubscribe(msgid: 0x1010, topic: "topic", reqos: .qos1) XCTAssertEqual(subscribe.packetFixedHeaderType, 0x82) @@ -259,36 +258,34 @@ class FrameTests: XCTestCase { 0x00, 0x05, 0x74, 0x6F, 0x70, 0x69, 0x63, 0x01]) } - + func testFrameSubAck() { - var suback = FrameSubAck(msgid: 0x1010, grantedQos: [.qos0, .FAILURE, .qos2]) var bytes = [UInt8](suback.bytes(version: "3.1.1")[2...]) var suback2 = FrameSubAck(packetFixedHeaderType: FrameType.suback.rawValue, bytes: bytes) - + XCTAssertEqual(suback.packetFixedHeaderType, suback2?.packetFixedHeaderType) XCTAssertEqual(suback.msgid, suback2?.msgid) XCTAssertEqual(suback.grantedQos, suback2?.grantedQos) - + XCTAssertEqual(suback2?.type, .suback) XCTAssertEqual(suback2?.qos, .qos0) XCTAssertEqual(suback2?.dup, false) XCTAssertEqual(suback2?.retained, false) XCTAssertEqual(suback2?.msgid, 0x1010) XCTAssertEqual(suback2?.grantedQos, [.qos0, .FAILURE, .qos2]) - + suback.msgid = 0x1011 suback.grantedQos = [.qos0] bytes = [UInt8](suback.bytes(version: "3.1.1")[2...]) suback2 = FrameSubAck(packetFixedHeaderType: FrameType.suback.rawValue, bytes: bytes) - + XCTAssertEqual(suback.packetFixedHeaderType, suback2?.packetFixedHeaderType) XCTAssertEqual(suback.msgid, suback2?.msgid) XCTAssertEqual(suback.grantedQos, suback2?.grantedQos) } - + func testFrameUnsubscribe() { - let unsub = FrameUnsubscribe(msgid: 0x1010, topics: ["topic", "t2"]) XCTAssertEqual(unsub.packetFixedHeaderType, 0xA2) XCTAssertEqual(unsub.msgid, 0x1010) @@ -299,24 +296,23 @@ class FrameTests: XCTestCase { 0x00, 0x05, 0x74, 0x6F, 0x70, 0x69, 0x63, 0x00, 0x02, 0x74, 0x32]) } - + func testFrameUnsubAck() { - var unsuback = FrameUnsubAck(msgid: 0x1010, payload: []) var bytes = [UInt8](unsuback.bytes(version: "3.1.1")[2...]) var unsuback2 = FrameUnsubAck(packetFixedHeaderType: FrameType.unsuback.rawValue, bytes: bytes) - + XCTAssertEqual(unsuback.packetFixedHeaderType, unsuback2?.packetFixedHeaderType) XCTAssertEqual(unsuback.msgid, unsuback2?.msgid) XCTAssertEqual(unsuback2?.type, .unsuback) XCTAssertEqual(unsuback2?.dup, false) XCTAssertEqual(unsuback2?.qos, .qos0) XCTAssertEqual(unsuback2?.retained, false) - + unsuback.msgid = 0x1011 bytes = [UInt8](unsuback.bytes(version: "3.1.1")[2...]) unsuback2 = FrameUnsubAck(packetFixedHeaderType: FrameType.unsuback.rawValue, bytes: bytes) - + XCTAssertEqual(unsuback.packetFixedHeaderType, unsuback2?.packetFixedHeaderType) XCTAssertEqual(unsuback.msgid, unsuback2?.msgid) XCTAssertEqual(unsuback2?.type, .unsuback) @@ -324,29 +320,26 @@ class FrameTests: XCTestCase { XCTAssertEqual(unsuback2?.qos, .qos0) XCTAssertEqual(unsuback2?.retained, false) } - + func testFramePing() { - let ping = FramePingReq() - + XCTAssertEqual(ping.packetFixedHeaderType, 0xC0) XCTAssertEqual(ping.bytes(version: "3.1.1"), [0xC0, 0x00]) } - + func testFramePong() { - let pong = FramePingResp() let bytes = [UInt8](pong.bytes(version: "3.1.1")[2...]) let pong2 = FramePingResp(packetFixedHeaderType: FrameType.pingresp.rawValue, bytes: bytes) - + XCTAssertEqual(pong.packetFixedHeaderType, pong2?.packetFixedHeaderType) XCTAssertEqual(pong.bytes(version: "3.1.1"), [0xD0, 0x00]) } - + func testFrameDisconnect() { - let disconn = FrameDisconnect() - + XCTAssertEqual(disconn.packetFixedHeaderType, 0xE0) XCTAssertEqual(disconn.bytes(version: "3.1.1"), [0xE0, 0x00]) } diff --git a/Example/Example/AppDelegate.swift b/Example/Example/AppDelegate.swift index db86c902..297dcdb5 100644 --- a/Example/Example/AppDelegate.swift +++ b/Example/Example/AppDelegate.swift @@ -10,37 +10,43 @@ import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } func applicationWillResignActive(_ application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + // Sent when the application is about to move from active to inactive state. + // This can occur for certain types of temporary interruptions (such as an + // incoming phone call or SMS message) or when the user quits the application + // and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down + // OpenGL ES frame rates. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + // Use this method to release shared resources, save user data, invalidate timers, + // and store enough application state information to restore your application to + // its current state in case it is terminated later. + // If your application supports background execution, this method is called instead + // of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + // Called as part of the transition from the background to the inactive state; + // here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + // Restart any tasks that were paused (or not yet started) while the application + // was inactive. If the application was previously in the background, optionally + // refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + // Called when the application is about to terminate. Save data if appropriate. + // See also applicationDidEnterBackground:. } - - } - diff --git a/Example/Example/ChatLeftMessageCell.swift b/Example/Example/ChatLeftMessageCell.swift index e921773a..20243c4d 100644 --- a/Example/Example/ChatLeftMessageCell.swift +++ b/Example/Example/ChatLeftMessageCell.swift @@ -8,15 +8,14 @@ import UIKit - class ChatLeftMessageCell: UITableViewCell { - @IBOutlet weak var contentLabel: UILabel! { + @IBOutlet private weak var contentLabel: UILabel! { didSet { contentLabel.numberOfLines = 0 } } - @IBOutlet weak var avatarImageView: UIImageView! - + @IBOutlet private weak var avatarImageView: UIImageView! + override func awakeFromNib() { super.awakeFromNib() selectionStyle = UITableViewCell.SelectionStyle.none diff --git a/Example/Example/ChatMessage.swift b/Example/Example/ChatMessage.swift index b069e02c..9f6196dd 100644 --- a/Example/Example/ChatMessage.swift +++ b/Example/Example/ChatMessage.swift @@ -9,7 +9,6 @@ import Foundation class ChatMessage { - let id: UInt16 let sender: String let content: String diff --git a/Example/Example/ChatRightMessageCell.swift b/Example/Example/ChatRightMessageCell.swift index 5c3e9270..88c8e70c 100644 --- a/Example/Example/ChatRightMessageCell.swift +++ b/Example/Example/ChatRightMessageCell.swift @@ -8,14 +8,13 @@ import UIKit - class ChatRightMessageCell: UITableViewCell { - @IBOutlet weak var contentLabel: UILabel! { + @IBOutlet private weak var contentLabel: UILabel! { didSet { contentLabel.numberOfLines = 0 } } - @IBOutlet weak var avatarImageView: UIImageView! + @IBOutlet private weak var avatarImageView: UIImageView! override func awakeFromNib() { super.awakeFromNib() diff --git a/Example/Example/ChatViewController.swift b/Example/Example/ChatViewController.swift index 9ebc6b0e..2b77c689 100644 --- a/Example/Example/ChatViewController.swift +++ b/Example/Example/ChatViewController.swift @@ -6,9 +6,8 @@ // Copyright © 2015年 emqtt.io. All rights reserved. // -import UIKit import CocoaMQTT - +import UIKit class ChatViewController: UIViewController { var animal: String? { @@ -40,28 +39,26 @@ class ChatViewController: UIViewController { scrollToBottom() } } - - @IBOutlet weak var tableView: UITableView! - @IBOutlet weak var messageTextView: UITextView! { + + @IBOutlet private weak var tableView: UITableView! + @IBOutlet private weak var messageTextView: UITextView! { didSet { messageTextView.layer.cornerRadius = 5 } } - @IBOutlet weak var animalAvatarImageView: UIImageView! - @IBOutlet weak var sloganLabel: UILabel! - - @IBOutlet weak var messageTextViewHeightConstraint: NSLayoutConstraint! - @IBOutlet weak var inputViewBottomConstraint: NSLayoutConstraint! - - @IBOutlet weak var sendMessageButton: UIButton! { + @IBOutlet private weak var animalAvatarImageView: UIImageView! + @IBOutlet private weak var sloganLabel: UILabel! + + @IBOutlet private weak var messageTextViewHeightConstraint: NSLayoutConstraint! + @IBOutlet private weak var inputViewBottomConstraint: NSLayoutConstraint! + + @IBOutlet private weak var sendMessageButton: UIButton! { didSet { sendMessageButton.isEnabled = false } } - - @IBAction func sendMessage() { - + @IBAction private func sendMessage() { let message = messageTextView.text let publishProperties = MqttPublishProperties() @@ -69,10 +66,10 @@ class ChatViewController: UIViewController { if mqttVersion == "3.1.1" { mqtt!.publish("chat/room/animals/client/" + animal!, withString: message!, qos: .qos1) - }else if mqttVersion == "5.0" { + } else if mqttVersion == "5.0" { mqtt5!.publish("chat/room/animals/client/" + animal!, withString: message!, qos: .qos1, DUP: true, retained: false, properties: publishProperties) } - + messageTextView.text = "" sendMessageButton.isEnabled = false messageTextViewHeightConstraint.constant = messageTextView.contentSize.height @@ -80,19 +77,18 @@ class ChatViewController: UIViewController { view.endEditing(true) } - @IBAction func disconnect() { - + @IBAction private func disconnect() { if mqttVersion == "3.1.1" { mqtt!.disconnect() - }else if mqttVersion == "5.0" { + } else if mqttVersion == "5.0" { mqtt5!.disconnect() - //or - //mqtt5!.disconnect(reasonCode: CocoaMQTTDISCONNECTReasonCode.disconnectWithWillMessage, userProperties: ["userone":"hi"]) + // or + // mqtt5!.disconnect(reasonCode: CocoaMQTTDISCONNECTReasonCode.disconnectWithWillMessage, userProperties: ["userone":"hi"]) } _ = navigationController?.popViewController(animated: true) } - + override func viewDidLoad() { super.viewDidLoad() navigationController?.navigationBar.isHidden = true @@ -110,29 +106,38 @@ class ChatViewController: UIViewController { tableView.dataSource = self tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 50 - + let name = NSNotification.Name(rawValue: "MQTTMessageNotification" + animal!) if mqttVersion == "3.1.1" { NotificationCenter.default.addObserver(self, selector: #selector(ChatViewController.receivedMessage(notification:)), name: name, object: nil) - }else if mqttVersion == "5.0" { + } else if mqttVersion == "5.0" { NotificationCenter.default.addObserver(self, selector: #selector(ChatViewController.receivedMqtt5Message(notification:)), name: name, object: nil) } let disconnectNotification = NSNotification.Name(rawValue: "MQTTMessageNotificationDisconnect") - NotificationCenter.default.addObserver(self, selector: #selector(ChatViewController.disconnectMessage(notification:)), name: disconnectNotification, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(ChatViewController.keyboardChanged(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil) + NotificationCenter.default.addObserver( + self, + selector: #selector(ChatViewController.disconnectMessage(notification:)), + name: disconnectNotification, object: nil + ) + NotificationCenter.default.addObserver( + self, + selector: #selector(ChatViewController.keyboardChanged(notification:)), + name: UIResponder.keyboardWillChangeFrameNotification, object: nil + ) } - + deinit { NotificationCenter.default.removeObserver(self) } - + @objc func keyboardChanged(notification: NSNotification) { let userInfo = notification.userInfo as! [String: AnyObject] let keyboardValue = userInfo["UIKeyboardFrameEndUserInfoKey"] - let bottomDistance = UIScreen.main.bounds.size.height - (navigationController?.navigationBar.frame.height)! - keyboardValue!.cgRectValue.origin.y - + let bottomDistance = UIScreen.main.bounds.size.height - + (navigationController?.navigationBar.frame.height)! - keyboardValue!.cgRectValue.origin.y + if bottomDistance > 0 { inputViewBottomConstraint.constant = bottomDistance } else { @@ -141,12 +146,10 @@ class ChatViewController: UIViewController { view.layoutIfNeeded() } - @objc func disconnectMessage(notification: NSNotification) { disconnect() } - @objc func receivedMessage(notification: NSNotification) { let userInfo = notification.userInfo as! [String: AnyObject] let content = userInfo["message"] as! String @@ -162,7 +165,7 @@ class ChatViewController: UIViewController { let message = userInfo["message"] as! String let topic = userInfo["topic"] as! String let id = UInt16(userInfo["id"] as! UInt16) - //let sender = userInfo["animal"] as! String + // let sender = userInfo["animal"] as! String let sender = topic.replacingOccurrences(of: "chat/room/animals/client/", with: "") let content = String(message.filter { !"\0".contains($0) }) let chatMessage = ChatMessage(sender: sender, content: content, id: id) @@ -170,7 +173,6 @@ class ChatViewController: UIViewController { messages.append(chatMessage) } - func scrollToBottom() { let count = messages.count if count > 3 { @@ -180,7 +182,6 @@ class ChatViewController: UIViewController { } } - extension ChatViewController: UITextViewDelegate { func textViewDidChange(_ textView: UITextView) { if textView.contentSize.height != textView.frame.size.height { @@ -190,8 +191,8 @@ extension ChatViewController: UITextViewDelegate { textView.layoutIfNeeded() } } - - if textView.text == "" { + + if textView.text.isEmpty { sendMessageButton.isEnabled = false } else { sendMessageButton.isEnabled = true @@ -203,10 +204,11 @@ extension ChatViewController: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return messages.count } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let message = messages[indexPath.row] - print("message.sender: \(message.sender) animal:\(String(describing: tabBarController?.selectedViewController?.tabBarItem.title!)) message.content:\( message.content)" ) + let animal = String(describing: tabBarController?.selectedViewController?.tabBarItem.title!) + print("message.sender: \(message.sender) animal:\(animal) message.content:\( message.content)" ) if message.sender == animal { let cell = tableView.dequeueReusableCell(withIdentifier: "rightMessageCell", for: indexPath) as! ChatRightMessageCell @@ -220,7 +222,7 @@ extension ChatViewController: UITableViewDataSource, UITableViewDelegate { return cell } } - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { view.endEditing(true) } diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift index 066f4601..94572324 100644 --- a/Example/Example/ViewController.swift +++ b/Example/Example/ViewController.swift @@ -6,15 +6,13 @@ // Copyright © 2015年 emqtt.io. All rights reserved. // -import UIKit import CocoaMQTT - +import UIKit class ViewController: UIViewController { - - //let defaultHost = "localhost" - //OR - //TEST Broker + // let defaultHost = "localhost" + // OR + // TEST Broker let defaultHost = "broker-cn.emqx.io" var mqtt5: CocoaMQTT5? @@ -22,39 +20,38 @@ class ViewController: UIViewController { var animal: String? var mqttVesion: String? - @IBOutlet weak var versionControl: UISegmentedControl! - @IBOutlet weak var connectButton: UIButton! - @IBOutlet weak var animalsImageView: UIImageView! { + @IBOutlet private weak var versionControl: UISegmentedControl! + @IBOutlet private weak var connectButton: UIButton! + @IBOutlet private weak var animalsImageView: UIImageView! { didSet { animalsImageView.clipsToBounds = true animalsImageView.layer.borderWidth = 1.0 animalsImageView.layer.cornerRadius = animalsImageView.frame.width / 2.0 } } - - @IBAction func connectToServer() { + + @IBAction private func connectToServer() { if mqttVesion == "3.1.1" { _ = mqtt!.connect() - }else if mqttVesion == "5.0"{ + } else if mqttVesion == "5.0"{ _ = mqtt5!.connect() } - } - - @IBAction func mqttVersionControl(_ sender: UISegmentedControl) { + + @IBAction private func mqttVersionControl(_ sender: UISegmentedControl) { animal = tabBarController?.selectedViewController?.tabBarItem.title mqttVesion = versionControl.titleForSegment(at: versionControl.selectedSegmentIndex) mqttSettingList() - + print("welcome to MQTT \(String(describing: mqttVesion)) \(String(describing: animal))") } - func sendAuthToServer(){ + func sendAuthToServer() { let authProperties = MqttAuthProperties() mqtt5!.auth(reasonCode: CocoaMQTTAUTHReasonCode.continueAuthentication, authProperties: authProperties) } - + override func viewDidLoad() { super.viewDidLoad() navigationController?.interactivePopGestureRecognizer?.isEnabled = false @@ -65,27 +62,23 @@ class ViewController: UIViewController { mqttSettingList() print("welcome to MQTT \(String(describing: mqttVesion)) \(String(describing: animal))") - } - + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) navigationController?.navigationBar.isHidden = false } - - func mqttSettingList(){ + func mqttSettingList() { mqttSetting() - //selfSignedSSLSetting() - //simpleSSLSetting() - //mqttWebsocketsSetting() - //mqttWebsocketSSLSetting() + // selfSignedSSLSetting() + // simpleSSLSetting() + // mqttWebsocketsSetting() + // mqttWebsocketSSLSetting() } - func mqttSetting() { - if mqttVesion == "3.1.1" { - let clientID = "CocoaMQTT-\(animal!)-" + String(ProcessInfo().processIdentifier) mqtt = CocoaMQTT(clientID: clientID, host: defaultHost, port: 1883) mqtt!.logLevel = .debug @@ -94,10 +87,9 @@ class ViewController: UIViewController { mqtt!.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout") mqtt!.keepAlive = 60 mqtt!.delegate = self - //mqtt!.autoReconnect = true - - }else if mqttVesion == "5.0" { + // mqtt!.autoReconnect = true + } else if mqttVesion == "5.0" { let clientID = "CocoaMQTT5-\(animal!)-" + String(ProcessInfo().processIdentifier) mqtt5 = CocoaMQTT5(clientID: clientID, host: defaultHost, port: 1883) mqtt5!.logLevel = .debug @@ -121,16 +113,13 @@ class ViewController: UIViewController { mqtt5!.willMessage = lastWillMessage mqtt5!.keepAlive = 60 mqtt5!.delegate = self - //mqtt5!.autoReconnect = true + // mqtt5!.autoReconnect = true } - } - - func simpleSSLSetting() { + func simpleSSLSetting() { if mqttVesion == "3.1.1" { - let clientID = "CocoaMQTT-\(animal!)-" + String(ProcessInfo().processIdentifier) mqtt = CocoaMQTT(clientID: clientID, host: defaultHost, port: 8883) mqtt!.username = "" @@ -139,9 +128,7 @@ class ViewController: UIViewController { mqtt!.keepAlive = 60 mqtt!.delegate = self mqtt!.enableSSL = true - - }else if mqttVesion == "5.0" { - + } else if mqttVesion == "5.0" { let clientID = "CocoaMQTT5-\(animal!)-" + String(ProcessInfo().processIdentifier) mqtt5 = CocoaMQTT5(clientID: clientID, host: defaultHost, port: 8883) @@ -160,14 +147,11 @@ class ViewController: UIViewController { mqtt5!.delegate = self mqtt5!.enableSSL = true - } - } - + func selfSignedSSLSetting() { if mqttVesion == "3.1.1" { - let clientID = "CocoaMQTT-\(animal!)-" + String(ProcessInfo().processIdentifier) mqtt = CocoaMQTT(clientID: clientID, host: defaultHost, port: 8883) mqtt!.username = "" @@ -184,9 +168,7 @@ class ViewController: UIViewController { sslSettings[kCFStreamSSLCertificates as String] = clientCertArray mqtt!.sslSettings = sslSettings - - }else if mqttVesion == "5.0" { - + } else if mqttVesion == "5.0" { let clientID = "CocoaMQTT5-\(animal!)-" + String(ProcessInfo().processIdentifier) mqtt5 = CocoaMQTT5(clientID: clientID, host: defaultHost, port: 8883) @@ -211,14 +193,11 @@ class ViewController: UIViewController { sslSettings[kCFStreamSSLCertificates as String] = clientCertArray mqtt5!.sslSettings = sslSettings - } - } - + func mqttWebsocketsSetting() { if mqttVesion == "3.1.1" { - let clientID = "CocoaMQTT-\(animal!)-" + String(ProcessInfo().processIdentifier) let websocket = CocoaMQTTWebSocket(uri: "/mqtt") mqtt = CocoaMQTT(clientID: clientID, host: defaultHost, port: 8083, socket: websocket) @@ -227,9 +206,7 @@ class ViewController: UIViewController { mqtt!.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout") mqtt!.keepAlive = 60 mqtt!.delegate = self - - }else if mqttVesion == "5.0" { - + } else if mqttVesion == "5.0" { let clientID = "CocoaMQTT5-\(animal!)-" + String(ProcessInfo().processIdentifier) let websocket = CocoaMQTTWebSocket(uri: "/mqtt") mqtt5 = CocoaMQTT5(clientID: clientID, host: defaultHost, port: 8083, socket: websocket) @@ -254,14 +231,11 @@ class ViewController: UIViewController { mqtt5!.willMessage = lastWillMessage mqtt5!.keepAlive = 60 mqtt5!.delegate = self - } - } - + func mqttWebsocketSSLSetting() { if mqttVesion == "3.1.1" { - let clientID = "CocoaMQTT-\(animal!)-" + String(ProcessInfo().processIdentifier) let websocket = CocoaMQTTWebSocket(uri: "/mqtt") mqtt = CocoaMQTT(clientID: clientID, host: defaultHost, port: 8084, socket: websocket) @@ -271,9 +245,7 @@ class ViewController: UIViewController { mqtt!.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout") mqtt!.keepAlive = 60 mqtt!.delegate = self - - }else if mqttVesion == "5.0" { - + } else if mqttVesion == "5.0" { let clientID = "CocoaMQTT5-\(animal!)-" + String(ProcessInfo().processIdentifier) let websocket = CocoaMQTTWebSocket(uri: "/mqtt") mqtt5 = CocoaMQTT5(clientID: clientID, host: defaultHost, port: 8084, socket: websocket) @@ -292,28 +264,25 @@ class ViewController: UIViewController { mqtt5!.willMessage = CocoaMQTT5Message(topic: "/will", string: "dieout") mqtt5!.keepAlive = 60 mqtt5!.delegate = self - } - - } - + func getClientCertFromP12File(certName: String, certPassword: String) -> CFArray? { // get p12 file path let resourcePath = Bundle.main.path(forResource: certName, ofType: "p12") - + guard let filePath = resourcePath, let p12Data = NSData(contentsOfFile: filePath) else { print("Failed to open the certificate file: \(certName).p12") return nil } - + // create key dictionary for reading p12 file let key = kSecImportExportPassphrase as String - let options : NSDictionary = [key: certPassword] - - var items : CFArray? + let options: NSDictionary = [key: certPassword] + + var items: CFArray? let securityError = SecPKCS12Import(p12Data, options, &items) - + guard securityError == errSecSuccess else { if securityError == errSecAuthFailed { print("ERROR: SecPKCS12Import returned errSecAuthFailed. Incorrect password?") @@ -322,32 +291,30 @@ class ViewController: UIViewController { } return nil } - + guard let theArray = items, CFArrayGetCount(theArray) > 0 else { return nil } - + let dictionary = (theArray as NSArray).object(at: 0) guard let identity = (dictionary as AnyObject).value(forKey: kSecImportItemIdentity as String) else { return nil } let certArray = [identity] as CFArray - + return certArray } - } extension ViewController: CocoaMQTT5Delegate { - func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveDisconnectReasonCode reasonCode: CocoaMQTTDISCONNECTReasonCode) { print("disconnect res : \(reasonCode)") } - + func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveAuthReasonCode reasonCode: CocoaMQTTAUTHReasonCode) { print("auth res : \(reasonCode)") } - + // Optional ssl CocoaMQTT5Delegate func mqtt5(_ mqtt5: CocoaMQTT5, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) { TRACE("trust: \(trust)") @@ -362,91 +329,97 @@ extension ViewController: CocoaMQTT5Delegate { /// } completionHandler(true) } - + func mqtt5(_ mqtt5: CocoaMQTT5, didConnectAck ack: CocoaMQTTCONNACKReasonCode, connAckData: MqttDecodeConnAck?) { TRACE("ack: \(ack)") if ack == .success { - if(connAckData != nil){ + if connAckData != nil { print("properties maximumPacketSize: \(String(describing: connAckData!.maximumPacketSize))") print("properties topicAliasMaximum: \(String(describing: connAckData!.topicAliasMaximum))") } mqtt5.subscribe("chat/room/animals/client/+", qos: CocoaMQTTQoS.qos0) - //or - //let subscriptions : [MqttSubscription] = [MqttSubscription(topic: "chat/room/animals/client/+"),MqttSubscription(topic: "chat/room/foods/client/+"),MqttSubscription(topic: "chat/room/trees/client/+")] - //mqtt.subscribe(subscriptions) + // or + // let subscriptions : [MqttSubscription] = [ + // MqttSubscription(topic: "chat/room/animals/client/+"), + // MqttSubscription(topic: "chat/room/foods/client/+"), + // MqttSubscription(topic: "chat/room/trees/client/+") + // ] + mqtt.subscribe(subscriptions) let chatViewController = storyboard?.instantiateViewController(withIdentifier: "ChatViewController") as? ChatViewController chatViewController?.mqtt5 = mqtt5 chatViewController?.mqttVersion = mqttVesion navigationController!.pushViewController(chatViewController!, animated: true) - } } - + func mqtt5(_ mqtt5: CocoaMQTT5, didStateChangeTo state: CocoaMQTTConnState) { TRACE("new state: \(state)") if state == .disconnected { - } } - + func mqtt5(_ mqtt5: CocoaMQTT5, didPublishMessage message: CocoaMQTT5Message, id: UInt16) { TRACE("message: \(message.description), id: \(id)") } - + func mqtt5(_ mqtt5: CocoaMQTT5, didPublishAck id: UInt16, pubAckData: MqttDecodePubAck?) { TRACE("id: \(id)") - if(pubAckData != nil){ + if pubAckData != nil { print("pubAckData reasonCode: \(String(describing: pubAckData!.reasonCode))") } } func mqtt5(_ mqtt5: CocoaMQTT5, didPublishRec id: UInt16, pubRecData: MqttDecodePubRec?) { TRACE("id: \(id)") - if(pubRecData != nil){ + if pubRecData != nil { print("pubRecData reasonCode: \(String(describing: pubRecData!.reasonCode))") } } - func mqtt5(_ mqtt5: CocoaMQTT5, didPublishComplete id: UInt16, pubCompData: MqttDecodePubComp?){ + func mqtt5(_ mqtt5: CocoaMQTT5, didPublishComplete id: UInt16, pubCompData: MqttDecodePubComp?) { TRACE("id: \(id)") - if(pubCompData != nil){ + if pubCompData != nil { print("pubCompData reasonCode: \(String(describing: pubCompData!.reasonCode))") } } - func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveMessage message: CocoaMQTT5Message, id: UInt16, publishData: MqttDecodePublish?){ - if(publishData != nil){ + func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveMessage message: CocoaMQTT5Message, id: UInt16, publishData: MqttDecodePublish?) { + if publishData != nil { print("publish.contentType \(String(describing: publishData!.contentType))") } - + TRACE("message: \(message.string.description), id: \(id)") let name = NSNotification.Name(rawValue: "MQTTMessageNotification" + animal!) - NotificationCenter.default.post(name: name, object: self, userInfo: ["message": message.string!, "topic": message.topic, "id": id, "animal": animal as Any]) + NotificationCenter.default.post( + name: name, + object: self, + userInfo: ["message": message.string!, "topic": message.topic, "id": id, "animal": animal as Any] + ) } - + func mqtt5(_ mqtt5: CocoaMQTT5, didSubscribeTopics success: NSDictionary, failed: [String], subAckData: MqttDecodeSubAck?) { TRACE("subscribed: \(success), failed: \(failed)") - if(subAckData != nil){ + if subAckData != nil { print("subAckData.reasonCodes \(String(describing: subAckData!.reasonCodes))") } } - - func mqtt5(_ mqtt5: CocoaMQTT5, didUnsubscribeTopics topics: [String], UnsubAckData: MqttDecodeUnsubAck?) { + + func mqtt5(_ mqtt5: CocoaMQTT5, didUnsubscribeTopics topics: [String], unsubAckData: MqttDecodeUnsubAck?) { TRACE("topic: \(topics)") - if(UnsubAckData != nil){ - print("UnsubAckData.reasonCodes \(String(describing: UnsubAckData!.reasonCodes))") + if unsubAckData != nil { + print("unsubAckData.reasonCodes \(String(describing: unsubAckData!.reasonCodes))") } print("----------------------") } - + func mqtt5DidPing(_ mqtt5: CocoaMQTT5) { TRACE() } - + func mqtt5DidReceivePong(_ mqtt5: CocoaMQTT5) { TRACE() } @@ -461,15 +434,15 @@ extension ViewController: CocoaMQTT5Delegate { let myCert = "myCert" extension ViewController: CocoaMQTTDelegate { - // self signed delegate - func mqttUrlSession(_ mqtt: CocoaMQTT, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void){ - if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) { - + func mqttUrlSession(_ mqtt: CocoaMQTT, didReceiveTrust trust: SecTrust, didReceiveChallenge + challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { let certData = Data(base64Encoded: myCert as String)! if let trust = challenge.protectionSpace.serverTrust, - let cert = SecCertificateCreateWithData(nil, certData as CFData) { + let cert = SecCertificateCreateWithData(nil, certData as CFData) { let certs = [cert] SecTrustSetAnchorCertificates(trust, certs as CFArray) @@ -479,10 +452,8 @@ extension ViewController: CocoaMQTTDelegate { } completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil) - } - func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) { TRACE("ack: \(ack)") @@ -535,7 +506,6 @@ extension ViewController: CocoaMQTTDelegate { } } - extension ViewController: UITabBarControllerDelegate { // Prevent automatic popToRootViewController on double-tap of UITabBarController func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { @@ -556,7 +526,7 @@ extension ViewController { } else { prettyName = names[1] } - + if fun == "mqttDidDisconnect(_:withError:)" { prettyName = "didDisconnect" } @@ -574,5 +544,3 @@ extension Optional { return "" } } - - diff --git a/Package.swift b/Package.swift index 67eca23e..9ba0e09e 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/leeway1208/MqttCocoaAsyncSocket", from: "1.0.8"), - .package(url: "https://github.com/daltoniam/Starscream.git", from: "3.1.1"), + .package(url: "https://github.com/daltoniam/Starscream.git", from: "3.1.1") ], targets: [ .target(name: "CocoaMQTT", diff --git a/Source/CocoaMQTT.swift b/Source/CocoaMQTT.swift index 1dc57177..eef6f7c3 100644 --- a/Source/CocoaMQTT.swift +++ b/Source/CocoaMQTT.swift @@ -13,14 +13,14 @@ import MqttCocoaAsyncSocket * Conn Ack */ @objc public enum CocoaMQTTConnAck: UInt8, CustomStringConvertible { - case accept = 0 + case accept = 0 case unacceptableProtocolVersion case identifierRejected case serverUnavailable case badUsernameOrPassword case notAuthorized case reserved - + public init(byte: UInt8) { switch byte { case CocoaMQTTConnAck.accept.rawValue.. Void) - @objc optional func mqttUrlSession(_ mqtt: CocoaMQTT, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + @objc optional func mqttUrlSession(_ mqtt: CocoaMQTT, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) /// @objc optional func mqtt(_ mqtt: CocoaMQTT, didPublishComplete id: UInt16) - + /// @objc optional func mqtt(_ mqtt: CocoaMQTT, didStateChangeTo state: CocoaMQTTConnState) } /// set mqtt version to 3.1.1 -public func setMqtt3Version(){ +public func setMqtt3Version() { if let storage = CocoaMQTTStorage() { storage.setMQTTVersion("3.1.1") } } - /** * Blueprint of the MQTT Client */ protocol CocoaMQTTClient { - /* Basic Properties */ var host: String { get set } @@ -110,60 +108,58 @@ protocol CocoaMQTTClient { var cleanSession: Bool {get set} var keepAlive: UInt16 {get set} var willMessage: CocoaMQTTMessage? {get set} - + /* Basic Properties */ /* CONNNEC/DISCONNECT */ - + func connect() -> Bool - func connect(timeout:TimeInterval) -> Bool + func connect(timeout: TimeInterval) -> Bool func disconnect() func ping() - + /* CONNNEC/DISCONNECT */ /* PUBLISH/SUBSCRIBE */ - + func subscribe(_ topic: String, qos: CocoaMQTTQoS) func subscribe(_ topics: [(String, CocoaMQTTQoS)]) - + func unsubscribe(_ topic: String) func unsubscribe(_ topics: [String]) - + func publish(_ topic: String, withString string: String, qos: CocoaMQTTQoS, retained: Bool) -> Int func publish(_ message: CocoaMQTTMessage) -> Int /* PUBLISH/SUBSCRIBE */ } - /// MQTT Client /// /// - Note: MGCDAsyncSocket need delegate to extend NSObject public class CocoaMQTT: NSObject, CocoaMQTTClient { - public weak var delegate: CocoaMQTTDelegate? private var version = "3.1.1" public var host = "localhost" - + public var port: UInt16 = 1883 - + public var clientID: String - + public var username: String? - + public var password: String? - + /// Clean Session flag. Default is true /// /// - TODO: What's behavior each Clean Session flags??? public var cleanSession = true - + /// Setup a **Last Will Message** to client before connecting to broker public var willMessage: CocoaMQTTMessage? - + /// Enable backgounding socket if running on iOS platform. Default is true /// /// - Note: @@ -171,30 +167,30 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { get { return (self.socket as? CocoaMQTTSocket)?.backgroundOnSocket ?? true } set { (self.socket as? CocoaMQTTSocket)?.backgroundOnSocket = newValue } } - + /// Delegate Executed queue. Default is `DispatchQueue.main` /// /// The delegate/closure callback function will be committed asynchronously to it public var delegateQueue = DispatchQueue.main - + public var connState = CocoaMQTTConnState.disconnected { didSet { - __delegate_queue { + executeOnDelegateQueue { self.delegate?.mqtt?(self, didStateChangeTo: self.connState) self.didChangeState(self, self.connState) } } } - + // deliver private var deliver = CocoaMQTTDeliver() - + /// Re-deliver the un-acked messages public var deliverTimeout: Double { get { return deliver.retryTimeInterval } set { deliver.retryTimeInterval = newValue } } - + /// Message queue size. default 1000 /// /// The new publishing messages of Qos1/Qos2 will be drop, if the queue is full @@ -202,37 +198,37 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { get { return deliver.mqueueSize } set { deliver.mqueueSize = newValue } } - + /// In-flight window size. default 10 public var inflightWindowSize: UInt { get { return deliver.inflightWindowSize } set { deliver.inflightWindowSize = newValue } } - + /// Keep alive time interval public var keepAlive: UInt16 = 60 private var aliveTimer: CocoaMQTTTimer? - + /// Enable auto-reconnect mechanism public var autoReconnect = false - + /// Reconnect time interval /// /// - note: This value will be increased with `autoReconnectTimeInterval *= 2` /// if reconnect failed public var autoReconnectTimeInterval: UInt16 = 1 // starts from 1 second - + /// Maximum auto reconnect time interval /// /// The timer starts from `autoReconnectTimeInterval` second and grows exponentially until this value /// After that, it uses this value for subsequent requests. public var maxAutoReconnectTimeInterval: UInt16 = 128 // 128 seconds - + private var reconnectTimeInterval: UInt16 = 0 - + private var autoReconnTimer: CocoaMQTTTimer? - private var is_internal_disconnected = false - + private var isInternalDisconnected = false + /// Console log level public var logLevel: CocoaMQTTLoggerLevel { get { @@ -242,19 +238,19 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { CocoaMQTTLogger.logger.minLevel = newValue } } - + /// Enable SSL connection public var enableSSL: Bool { get { return self.socket.enableSSL } set { socket.enableSSL = newValue } } - + /// public var sslSettings: [String: NSObject]? { - get { return (self.socket as? CocoaMQTTSocket)?.sslSettings ?? nil } + get { return (self.socket as? CocoaMQTTSocket)?.sslSettings } set { (self.socket as? CocoaMQTTSocket)?.sslSettings = newValue } } - + /// Allow self-signed ca certificate. /// /// Default is false @@ -262,13 +258,12 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { get { return (self.socket as? CocoaMQTTSocket)?.allowUntrustCACertificate ?? false } set { (self.socket as? CocoaMQTTSocket)?.allowUntrustCACertificate = newValue } } - + /// The subscribed topics in current communication public var subscriptions: [String: CocoaMQTTQoS] = [:] - + fileprivate var subscriptionsWaitingAck: [UInt16: [(String, CocoaMQTTQoS)]] = [:] fileprivate var unsubscriptionsWaitingAck: [UInt16: [String]] = [:] - /// Sending messages fileprivate var sendingMessages: [UInt16: CocoaMQTTMessage] = [:] @@ -277,7 +272,7 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { private var _msgid: UInt16 = 0 fileprivate var socket: CocoaMQTTSocketProtocol fileprivate var reader: CocoaMQTTReader? - + // Closures public var didConnectAck: (CocoaMQTT, CocoaMQTTConnAck) -> Void = { _, _ in } public var didPublishMessage: (CocoaMQTT, CocoaMQTTMessage, UInt16) -> Void = { _, _, _ in } @@ -291,7 +286,7 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { public var didReceiveTrust: (CocoaMQTT, SecTrust, @escaping (Bool) -> Swift.Void) -> Void = { _, _, _ in } public var didCompletePublish: (CocoaMQTT, UInt16) -> Void = { _, _ in } public var didChangeState: (CocoaMQTT, CocoaMQTTConnState) -> Void = { _, _ in } - + /// Initial client object /// /// - Parameters: @@ -315,7 +310,7 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { deinit { aliveTimer?.suspend() autoReconnTimer?.suspend() - + socket.setDelegate(nil, delegateQueue: nil) socket.disconnect() } @@ -327,14 +322,13 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { } fileprivate func sendConnectFrame() { - var connect = FrameConnect(clientID: clientID) connect.keepAlive = keepAlive connect.username = username connect.password = password connect.willMsg = willMessage connect.cleansess = cleanSession - + send(connect) reader!.start() } @@ -358,7 +352,7 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { default: return } } - + /// Connect to MQTT broker /// /// - Returns: @@ -367,7 +361,7 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { public func connect() -> Bool { return connect(timeout: -1) } - + /// Connect to MQTT broker /// - Parameters: /// - timeout: Connect timeout @@ -383,19 +377,19 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { } else { try socket.connect(toHost: self.host, onPort: self.port) } - + delegateQueue.async { [weak self] in guard let self = self else { return } self.connState = .connecting } - + return true } catch let error as NSError { printError("socket connect error: \(error.description)") return false } } - + /// Send a DISCONNECT packet to the broker then close the connection /// /// - Note: Only can be called from outside. @@ -404,25 +398,25 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { public func disconnect() { internal_disconnect() } - + /// Disconnect unexpectedly func internal_disconnect() { - is_internal_disconnected = true + isInternalDisconnected = true send(FrameDisconnect(), tag: -0xE0) socket.disconnect() } - + /// Send a PING request to broker public func ping() { printDebug("ping") send(FramePingReq(), tag: -0xC0) - - __delegate_queue { + + executeOnDelegateQueue { self.delegate?.mqttDidPing(self) self.didPing(self) } } - + /// Publish a message to broker /// /// - Parameters: @@ -447,20 +441,20 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { @discardableResult public func publish(_ message: CocoaMQTTMessage) -> Int { let msgid: UInt16 - + if message.qos == .qos0 { msgid = 0 } else { msgid = nextMessageID() } - + var frame = FramePublish(topic: message.topic, payload: message.payload, qos: message.qos, msgid: msgid) - + frame.retained = message.retained - + delegateQueue.async { self.sendingMessages[msgid] = message } @@ -484,7 +478,7 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { public func subscribe(_ topic: String, qos: CocoaMQTTQoS = .qos1) { return subscribe([(topic, qos)]) } - + /// Subscribe a lists of topics /// /// - Parameters: @@ -503,7 +497,7 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { public func unsubscribe(_ topic: String) { return unsubscribe([topic]) } - + /// Unsubscribe a list of topics /// /// - Parameters: @@ -518,23 +512,22 @@ public class CocoaMQTT: NSObject, CocoaMQTTClient { // MARK: CocoaMQTTDeliverProtocol extension CocoaMQTT: CocoaMQTTDeliverProtocol { - func deliver(_ deliver: CocoaMQTTDeliver, wantToSend frame: Frame) { if let publish = frame as? FramePublish { let msgid = publish.msgid - - var message: CocoaMQTTMessage? = nil - + + var message: CocoaMQTTMessage? + if let sendingMessage = sendingMessages[msgid] { message = sendingMessage - //printError("Want send \(frame), but not found in CocoaMQTT cache") - + // printError("Want send \(frame), but not found in CocoaMQTT cache") + } else { message = CocoaMQTTMessage(topic: publish.topic, payload: publish.payload()) } - + send(publish, tag: Int(msgid)) - + if let message = message { self.delegate?.mqtt(self, didPublishMessage: message, id: msgid) self.didPublishMessage(self, message, msgid) @@ -547,10 +540,9 @@ extension CocoaMQTT: CocoaMQTTDeliverProtocol { } extension CocoaMQTT { - - func __delegate_queue(_ fun: @escaping () -> Void) { + func executeOnDelegateQueue(_ fun: @escaping () -> Void) { delegateQueue.async { [weak self] in - guard let _ = self else { return } + guard self != nil else { return } fun() } } @@ -558,22 +550,21 @@ extension CocoaMQTT { // MARK: - CocoaMQTTSocketDelegate extension CocoaMQTT: CocoaMQTTSocketDelegate { - public func socketConnected(_ socket: CocoaMQTTSocketProtocol) { sendConnectFrame() } - + public func socket(_ socket: CocoaMQTTSocketProtocol, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Swift.Void) { - printDebug("Call the SSL/TLS manually validating function") - + delegate?.mqtt?(self, didReceive: trust, completionHandler: completionHandler) didReceiveTrust(self, trust, completionHandler) } - public func socketUrlSession(_ socket: CocoaMQTTSocketProtocol, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + public func socketUrlSession(_ socket: CocoaMQTTSocketProtocol, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { printDebug("Call the SSL/TLS manually validating function - socketUrlSession") delegate?.mqttUrlSession?(self, didReceiveTrust: trust, didReceiveChallenge: challenge, completionHandler: completionHandler) @@ -611,18 +602,18 @@ extension CocoaMQTT: CocoaMQTTSocketDelegate { delegate?.mqttDidDisconnect(self, withError: err) didDisconnect(self, err) - guard !is_internal_disconnected else { + guard !isInternalDisconnected else { return } guard autoReconnect else { return } - + if reconnectTimeInterval == 0 { reconnectTimeInterval = autoReconnectTimeInterval } - + // Start reconnector once socket error occurred printInfo("Try reconnect to server after \(reconnectTimeInterval)s") autoReconnTimer = CocoaMQTTTimer.after(Double(reconnectTimeInterval), name: "autoReconnTimer", { [weak self] in @@ -639,22 +630,20 @@ extension CocoaMQTT: CocoaMQTTSocketDelegate { // MARK: - CocoaMQTTReaderDelegate extension CocoaMQTT: CocoaMQTTReaderDelegate { - func didReceive(_ reader: CocoaMQTTReader, connack: FrameConnAck) { printDebug("RECV: \(connack)") if connack.returnCode == .accept { - // Disable auto-reconnect - + reconnectTimeInterval = 0 autoReconnTimer = nil - is_internal_disconnected = false - + isInternalDisconnected = false + // Start keepalive timer - - let interval = Double(keepAlive <= 0 ? 60: keepAlive) - + + let interval = Double(keepAlive <= 0 ? 60 : keepAlive) + aliveTimer = CocoaMQTTTimer.every(interval, name: "aliveTimer") { [weak self] in guard let self = self else { return } self.delegateQueue.async { @@ -665,9 +654,9 @@ extension CocoaMQTT: CocoaMQTTReaderDelegate { self.ping() } } - + // recover session if enable - + if cleanSession { deliver.cleanAll() } else { @@ -679,7 +668,6 @@ extension CocoaMQTT: CocoaMQTTReaderDelegate { } connState = .connected - } else { connState = .disconnected internal_disconnect() @@ -691,15 +679,15 @@ extension CocoaMQTT: CocoaMQTTReaderDelegate { func didReceive(_ reader: CocoaMQTTReader, publish: FramePublish) { printDebug("RECV: \(publish)") - + let message = CocoaMQTTMessage(topic: publish.topic, payload: publish.payload(), qos: publish.qos, retained: publish.retained) - + message.duplicated = publish.dup - + printInfo("Received message: \(message)") delegate?.mqtt(self, didReceiveMessage: message, id: publish.msgid) didReceiveMessage(self, message, publish.msgid) - + if message.qos == .qos1 { puback(FrameType.puback, msgid: publish.msgid) } else if message.qos == .qos2 { @@ -709,16 +697,16 @@ extension CocoaMQTT: CocoaMQTTReaderDelegate { func didReceive(_ reader: CocoaMQTTReader, puback: FramePubAck) { printDebug("RECV: \(puback)") - + deliver.ack(by: puback) - + delegate?.mqtt(self, didPublishAck: puback.msgid) didPublishAck(self, puback.msgid) } - + func didReceive(_ reader: CocoaMQTTReader, pubrec: FramePubRec) { printDebug("RECV: \(pubrec)") - + deliver.ack(by: pubrec) } @@ -732,7 +720,7 @@ extension CocoaMQTT: CocoaMQTTReaderDelegate { printDebug("RECV: \(pubcomp)") deliver.ack(by: pubcomp) - + delegate?.mqtt?(self, didPublishComplete: pubcomp.msgid) didCompletePublish(self, pubcomp.msgid) } @@ -743,15 +731,15 @@ extension CocoaMQTT: CocoaMQTTReaderDelegate { printWarning("UNEXPECT SUBACK Received: \(suback)") return } - + guard topicsAndQos.count == suback.grantedQos.count else { printWarning("UNEXPECT SUBACK Recivied: \(suback)") return } - - let success: NSMutableDictionary = NSMutableDictionary() + + let success = NSMutableDictionary() var failed = [String]() - for (idx,(topic, _)) in topicsAndQos.enumerated() { + for (idx, (topic, _)) in topicsAndQos.enumerated() { if suback.grantedQos[idx] != .FAILURE { subscriptions[topic] = suback.grantedQos[idx] success[topic] = suback.grantedQos[idx].rawValue @@ -763,10 +751,10 @@ extension CocoaMQTT: CocoaMQTTReaderDelegate { delegate?.mqtt(self, didSubscribeTopics: success, failed: failed) didSubscribeTopics(self, success, failed) } - + func didReceive(_ reader: CocoaMQTTReader, unsuback: FrameUnsubAck) { printDebug("RECV: \(unsuback)") - + guard let topics = unsubscriptionsWaitingAck.removeValue(forKey: unsuback.msgid) else { printWarning("UNEXPECT UNSUBACK Received: \(unsuback.msgid)") return @@ -781,7 +769,7 @@ extension CocoaMQTT: CocoaMQTTReaderDelegate { func didReceive(_ reader: CocoaMQTTReader, pingresp: FramePingResp) { printDebug("RECV: \(pingresp)") - + delegate?.mqttDidReceivePong(self) didReceivePong(self) } diff --git a/Source/CocoaMQTT5.swift b/Source/CocoaMQTT5.swift index 7ee063d9..460b52b2 100644 --- a/Source/CocoaMQTT5.swift +++ b/Source/CocoaMQTT5.swift @@ -26,10 +26,8 @@ import MqttCocoaAsyncSocket } } - /// CocoaMQTT5 Delegate @objc public protocol CocoaMQTT5Delegate { - /// func mqtt5(_ mqtt5: CocoaMQTT5, didConnectAck ack: CocoaMQTTCONNACKReasonCode, connAckData: MqttDecodeConnAck?) @@ -49,11 +47,11 @@ import MqttCocoaAsyncSocket func mqtt5(_ mqtt5: CocoaMQTT5, didSubscribeTopics success: NSDictionary, failed: [String], subAckData: MqttDecodeSubAck?) /// - func mqtt5(_ mqtt5: CocoaMQTT5, didUnsubscribeTopics topics: [String], UnsubAckData: MqttDecodeUnsubAck?) - + func mqtt5(_ mqtt5: CocoaMQTT5, didUnsubscribeTopics topics: [String], unsubAckData: MqttDecodeUnsubAck?) + /// func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveDisconnectReasonCode reasonCode: CocoaMQTTDISCONNECTReasonCode) - + /// func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveAuthReasonCode reasonCode: CocoaMQTTAUTHReasonCode) @@ -65,34 +63,33 @@ import MqttCocoaAsyncSocket /// func mqtt5DidDisconnect(_ mqtt5: CocoaMQTT5, withError err: Error?) - + /// Manually validate SSL/TLS server certificate. /// /// This method will be called if enable `allowUntrustCACertificate` @objc optional func mqtt5(_ mqtt5: CocoaMQTT5, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) - @objc optional func mqtt5UrlSession(_ mqtt: CocoaMQTT5, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + @objc optional func mqtt5UrlSession(_ mqtt: CocoaMQTT5, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) /// - @objc optional func mqtt5(_ mqtt5: CocoaMQTT5, didPublishComplete id: UInt16, pubCompData: MqttDecodePubComp?) + @objc optional func mqtt5(_ mqtt5: CocoaMQTT5, didPublishComplete id: UInt16, pubCompData: MqttDecodePubComp?) /// @objc optional func mqtt5(_ mqtt5: CocoaMQTT5, didStateChangeTo state: CocoaMQTTConnState) } /// set mqtt version to 5.0 -public func setMqtt5Version(){ +public func setMqtt5Version() { if let storage = CocoaMQTTStorage() { storage.setMQTTVersion("5.0") } } - /** * Blueprint of the MQTT Client */ protocol CocoaMQTT5Client { - /* Basic Properties */ var host: String { get set } @@ -105,13 +102,13 @@ protocol CocoaMQTT5Client { var willMessage: CocoaMQTT5Message? {get set} var connectProperties: MqttConnectProperties? {get set} var authProperties: MqttAuthProperties? {get set} - + /* Basic Properties */ /* CONNNEC/DISCONNECT */ func connect() -> Bool - func connect(timeout:TimeInterval) -> Bool + func connect(timeout: TimeInterval) -> Bool func disconnect() func ping() @@ -125,18 +122,17 @@ protocol CocoaMQTT5Client { func unsubscribe(_ topic: String) func unsubscribe(_ topics: [MqttSubscription]) - func publish(_ topic: String, withString string: String, qos: CocoaMQTTQoS, DUP: Bool, retained: Bool, properties: MqttPublishProperties) -> Int + // swiftlint:disable:next function_parameter_count + func publish(_ topic: String, withString string: String, qos: CocoaMQTTQoS, DUP: Bool, retained: Bool, properties: MqttPublishProperties) -> Int func publish(_ message: CocoaMQTT5Message, DUP: Bool, retained: Bool, properties: MqttPublishProperties) -> Int /* PUBLISH/SUBSCRIBE */ } - /// MQTT Client /// /// - Note: MGCDAsyncSocket need delegate to extend NSObject public class CocoaMQTT5: NSObject, CocoaMQTT5Client { - public weak var delegate: CocoaMQTT5Delegate? private var version = "5.0" @@ -174,7 +170,7 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { public var connState = CocoaMQTTConnState.disconnected { didSet { - __delegate_queue { + executeOnDelegateQueue { self.delegate?.mqtt5?(self, didStateChangeTo: self.connState) self.didChangeState(self, self.connState) } @@ -223,7 +219,6 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { /// After that, it uses this value for subsequent requests. public var maxAutoReconnectTimeInterval: UInt16 = 128 // 128 seconds - /// 3.1.2.11 CONNECT Properties public var connectProperties: MqttConnectProperties? @@ -233,8 +228,7 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { private var reconnectTimeInterval: UInt16 = 0 private var autoReconnTimer: CocoaMQTTTimer? - private var is_internal_disconnected = false - + private var isInternalDisconnected = false /// Console log level public var logLevel: CocoaMQTTLoggerLevel { @@ -254,7 +248,7 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { /// public var sslSettings: [String: NSObject]? { - get { return (self.socket as? CocoaMQTTSocket)?.sslSettings ?? nil } + get { return (self.socket as? CocoaMQTTSocket)?.sslSettings } set { (self.socket as? CocoaMQTTSocket)?.sslSettings = newValue } } @@ -272,7 +266,6 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { fileprivate var subscriptionsWaitingAck: [UInt16: [MqttSubscription]] = [:] fileprivate var unsubscriptionsWaitingAck: [UInt16: [MqttSubscription]] = [:] - /// Sending messages fileprivate var sendingMessages: [UInt16: CocoaMQTT5Message] = [:] @@ -317,7 +310,7 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { printWarning("Localstorage initial failed for key: \(clientID)") } } - + deinit { aliveTimer?.suspend() autoReconnTimer?.suspend() @@ -330,12 +323,10 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { printDebug("SEND: \(frame)") let data = frame.bytes(version: version) - socket.write(Data(bytes: data, count: data.count), withTimeout: 5, tag: tag) } fileprivate func sendConnectFrame() { - var connect = FrameConnect(clientID: clientID) connect.keepAlive = keepAlive connect.username = username @@ -415,19 +406,19 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { internal_disconnect() } - public func disconnect(reasonCode : CocoaMQTTDISCONNECTReasonCode,userProperties : [String: String] ) { - internal_disconnect_withProperties(reasonCode: reasonCode,userProperties: userProperties) + public func disconnect(reasonCode: CocoaMQTTDISCONNECTReasonCode, userProperties: [String: String] ) { + internal_disconnect_withProperties(reasonCode: reasonCode, userProperties: userProperties) } /// Disconnect unexpectedly func internal_disconnect() { - is_internal_disconnected = true + isInternalDisconnected = true send(FrameDisconnect(disconnectReasonCode: CocoaMQTTDISCONNECTReasonCode.normalDisconnection), tag: -0xE0) socket.disconnect() } - func internal_disconnect_withProperties(reasonCode : CocoaMQTTDISCONNECTReasonCode,userProperties : [String: String] ) { - is_internal_disconnected = true + func internal_disconnect_withProperties(reasonCode: CocoaMQTTDISCONNECTReasonCode, userProperties: [String: String] ) { + isInternalDisconnected = true var frameDisconnect = FrameDisconnect(disconnectReasonCode: reasonCode) frameDisconnect.userProperties = userProperties send(frameDisconnect, tag: -0xE0) @@ -438,7 +429,7 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { printDebug("ping") send(FramePingReq(), tag: -0xC0) - __delegate_queue { + executeOnDelegateQueue { self.delegate?.mqtt5DidPing(self) self.didPing(self) } @@ -457,9 +448,10 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { /// - 1-65535 will be returned, if the messages's qos is qos1/qos2 /// - -1 will be returned, if the messages queue is full @discardableResult - public func publish(_ topic: String, withString string: String, qos: CocoaMQTTQoS = .qos1, DUP: Bool = false, retained: Bool = false, properties: MqttPublishProperties) -> Int { + public func publish(_ topic: String, withString string: String, qos: CocoaMQTTQoS = .qos1, DUP: Bool = false, + retained: Bool = false, properties: MqttPublishProperties) -> Int { var fixQus = qos - if !DUP{ + if !DUP { fixQus = .qos0 } let message = CocoaMQTT5Message(topic: topic, string: string, qos: fixQus, retained: retained) @@ -482,7 +474,7 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { } printDebug("message.topic \(message.topic ) = message.payload \(message.payload)") - + var frame = FramePublish(topic: message.topic, payload: message.payload, qos: message.qos, @@ -548,11 +540,10 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { send(frame, tag: Int(msgid)) } - /// Authentication exchange /// /// - public func auth(reasonCode : CocoaMQTTAUTHReasonCode,authProperties : MqttAuthProperties) { + public func auth(reasonCode: CocoaMQTTAUTHReasonCode, authProperties: MqttAuthProperties) { printDebug("auth") let frame = FrameAuth(reasonCode: reasonCode, authProperties: authProperties) @@ -562,21 +553,20 @@ public class CocoaMQTT5: NSObject, CocoaMQTT5Client { // MARK: CocoaMQTTDeliverProtocol extension CocoaMQTT5: CocoaMQTTDeliverProtocol { - func deliver(_ deliver: CocoaMQTTDeliver, wantToSend frame: Frame) { if let publish = frame as? FramePublish { let msgid = publish.msgid - var message: CocoaMQTT5Message? = nil - + var message: CocoaMQTT5Message? + if let sendingMessage = sendingMessages[msgid] { message = sendingMessage - //printError("Want send \(frame), but not found in CocoaMQTT cache") + // printError("Want send \(frame), but not found in CocoaMQTT cache") } else { message = CocoaMQTT5Message(topic: publish.topic, payload: publish.payload()) } - + send(publish, tag: Int(msgid)) - + if let message = message { self.delegate?.mqtt5(self, didPublishMessage: message, id: msgid) self.didPublishMessage(self, message, msgid) @@ -589,10 +579,9 @@ extension CocoaMQTT5: CocoaMQTTDeliverProtocol { } extension CocoaMQTT5 { - - func __delegate_queue(_ fun: @escaping () -> Void) { + func executeOnDelegateQueue(_ fun: @escaping () -> Void) { delegateQueue.async { [weak self] in - guard let _ = self else { return } + guard self != nil else { return } fun() } } @@ -600,7 +589,6 @@ extension CocoaMQTT5 { // MARK: - CocoaMQTTSocketDelegate extension CocoaMQTT5: CocoaMQTTSocketDelegate { - public func socketConnected(_ socket: CocoaMQTTSocketProtocol) { sendConnectFrame() } @@ -608,14 +596,14 @@ extension CocoaMQTT5: CocoaMQTTSocketDelegate { public func socket(_ socket: CocoaMQTTSocketProtocol, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Swift.Void) { - printDebug("Call the SSL/TLS manually validating function") delegate?.mqtt5?(self, didReceive: trust, completionHandler: completionHandler) didReceiveTrust(self, trust, completionHandler) } - public func socketUrlSession(_ socket: CocoaMQTTSocketProtocol, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + public func socketUrlSession(_ socket: CocoaMQTTSocketProtocol, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { printDebug("Call the SSL/TLS manually validating function - socketUrlSession") delegate?.mqtt5UrlSession?(self, didReceiveTrust: trust, didReceiveChallenge: challenge, completionHandler: completionHandler) @@ -654,7 +642,7 @@ extension CocoaMQTT5: CocoaMQTTSocketDelegate { delegate?.mqtt5DidDisconnect(self, withError: err) didDisconnect(self, err) - guard !is_internal_disconnected else { + guard !isInternalDisconnected else { return } @@ -682,31 +670,29 @@ extension CocoaMQTT5: CocoaMQTTSocketDelegate { // MARK: - CocoaMQTTReaderDelegate extension CocoaMQTT5: CocoaMQTTReaderDelegate { - func didReceive(_ reader: CocoaMQTTReader, disconnect: FrameDisconnect) { delegate?.mqtt5(self, didReceiveDisconnectReasonCode: disconnect.receiveReasonCode!) didDisconnectReasonCode(self, disconnect.receiveReasonCode!) } - + func didReceive(_ reader: CocoaMQTTReader, auth: FrameAuth) { delegate?.mqtt5(self, didReceiveAuthReasonCode: auth.receiveReasonCode!) didAuthReasonCode(self, auth.receiveReasonCode!) } - + func didReceive(_ reader: CocoaMQTTReader, connack: FrameConnAck) { printDebug("RECV: \(connack)") if connack.reasonCode == .success { - // Disable auto-reconnect reconnectTimeInterval = 0 autoReconnTimer = nil - is_internal_disconnected = false + isInternalDisconnected = false // Start keepalive timer - let interval = Double(keepAlive <= 0 ? 60: keepAlive) + let interval = Double(keepAlive <= 0 ? 60 : keepAlive) aliveTimer = CocoaMQTTTimer.every(interval, name: "aliveTimer") { [weak self] in guard let self = self else { return } @@ -732,15 +718,13 @@ extension CocoaMQTT5: CocoaMQTTReaderDelegate { } connState = .connected - } else { connState = .disconnected internal_disconnect() } - - delegate?.mqtt5(self, didConnectAck: connack.reasonCode!, connAckData: connack.connackProperties ?? nil) - didConnectAck(self, connack.reasonCode!, connack.connackProperties ?? nil) + delegate?.mqtt5(self, didConnectAck: connack.reasonCode!, connAckData: connack.connackProperties) + didConnectAck(self, connack.reasonCode!, connack.connackProperties) } func didReceive(_ reader: CocoaMQTTReader, publish: FramePublish) { @@ -751,8 +735,8 @@ extension CocoaMQTT5: CocoaMQTTReaderDelegate { message.duplicated = publish.dup printInfo("Received message: \(message)") - delegate?.mqtt5(self, didReceiveMessage: message, id: publish.msgid, publishData: publish.publishRecProperties ?? nil) - didReceiveMessage(self, message, publish.msgid, publish.publishRecProperties ?? nil) + delegate?.mqtt5(self, didReceiveMessage: message, id: publish.msgid, publishData: publish.publishRecProperties) + didReceiveMessage(self, message, publish.msgid, publish.publishRecProperties) if message.qos == .qos1 { puback(FrameType.puback, msgid: publish.msgid) @@ -766,8 +750,8 @@ extension CocoaMQTT5: CocoaMQTTReaderDelegate { deliver.ack(by: puback) - delegate?.mqtt5(self, didPublishAck: puback.msgid, pubAckData: puback.pubAckProperties ?? nil) - didPublishAck(self, puback.msgid, puback.pubAckProperties ?? nil) + delegate?.mqtt5(self, didPublishAck: puback.msgid, pubAckData: puback.pubAckProperties) + didPublishAck(self, puback.msgid, puback.pubAckProperties) } func didReceive(_ reader: CocoaMQTTReader, pubrec: FramePubRec) { @@ -775,8 +759,8 @@ extension CocoaMQTT5: CocoaMQTTReaderDelegate { deliver.ack(by: pubrec) - delegate?.mqtt5(self, didPublishRec: pubrec.msgid, pubRecData: pubrec.pubRecProperties ?? nil) - didPublishRec(self, pubrec.msgid, pubrec.pubRecProperties ?? nil) + delegate?.mqtt5(self, didPublishRec: pubrec.msgid, pubRecData: pubrec.pubRecProperties) + didPublishRec(self, pubrec.msgid, pubrec.pubRecProperties) } func didReceive(_ reader: CocoaMQTTReader, pubrel: FramePubRel) { @@ -790,8 +774,8 @@ extension CocoaMQTT5: CocoaMQTTReaderDelegate { deliver.ack(by: pubcomp) - delegate?.mqtt5?(self, didPublishComplete: pubcomp.msgid, pubCompData: pubcomp.pubCompProperties ?? nil) - didCompletePublish(self, pubcomp.msgid, pubcomp.pubCompProperties ?? nil) + delegate?.mqtt5?(self, didPublishComplete: pubcomp.msgid, pubCompData: pubcomp.pubCompProperties) + didCompletePublish(self, pubcomp.msgid, pubcomp.pubCompProperties) } func didReceive(_ reader: CocoaMQTTReader, suback: FrameSubAck) { @@ -806,9 +790,9 @@ extension CocoaMQTT5: CocoaMQTTReaderDelegate { return } - let success: NSMutableDictionary = NSMutableDictionary() + let success = NSMutableDictionary() var failed = [String]() - for (idx,subscriptionList) in topicsAndQos.enumerated() { + for (idx, subscriptionList) in topicsAndQos.enumerated() { if suback.grantedQos[idx] != .FAILURE { subscriptions[subscriptionList.topic] = suback.grantedQos[idx] success[subscriptionList.topic] = suback.grantedQos[idx].rawValue @@ -817,8 +801,8 @@ extension CocoaMQTT5: CocoaMQTTReaderDelegate { } } - delegate?.mqtt5(self, didSubscribeTopics: success, failed: failed, subAckData: suback.subAckProperties ?? nil) - didSubscribeTopics(self, success, failed, suback.subAckProperties ?? nil) + delegate?.mqtt5(self, didSubscribeTopics: success, failed: failed, subAckData: suback.subAckProperties) + didSubscribeTopics(self, success, failed, suback.subAckProperties) } func didReceive(_ reader: CocoaMQTTReader, unsuback: FrameUnsubAck) { @@ -829,14 +813,14 @@ extension CocoaMQTT5: CocoaMQTTReaderDelegate { return } // Remove local subscription - var removeTopics : [String] = [] + var removeTopics: [String] = [] for t in topics { removeTopics.append(t.topic) subscriptions.removeValue(forKey: t.topic) } - delegate?.mqtt5(self, didUnsubscribeTopics: removeTopics, UnsubAckData: unsuback.unSubAckProperties ?? nil) - didUnsubscribeTopics(self, removeTopics, unsuback.unSubAckProperties ?? nil) + delegate?.mqtt5(self, didUnsubscribeTopics: removeTopics, unsubAckData: unsuback.unSubAckProperties) + didUnsubscribeTopics(self, removeTopics, unsuback.unSubAckProperties) } func didReceive(_ reader: CocoaMQTTReader, pingresp: FramePingResp) { @@ -846,4 +830,3 @@ extension CocoaMQTT5: CocoaMQTTReaderDelegate { didReceivePong(self) } } - diff --git a/Source/CocoaMQTT5Message.swift b/Source/CocoaMQTT5Message.swift index 11412c2f..4e31c65c 100644 --- a/Source/CocoaMQTT5Message.swift +++ b/Source/CocoaMQTT5Message.swift @@ -8,51 +8,44 @@ import Foundation - /// MQTT Message public class CocoaMQTT5Message: NSObject { - public var qos = CocoaMQTTQoS.qos1 - + public var topic: String public var payload: [UInt8] - + public var retained = false - + /// The `duplicated` property show that this message maybe has be received before /// /// - note: Readonly property public var duplicated = false - - ///3.1.3.2.3 Payload Format Indicator - public var isUTF8EncodedData: Bool = true - ///3.1.3.2.2 Will Delay Interval + /// 3.1.3.2.3 Payload Format Indicator + public var isUTF8EncodedData = true + /// 3.1.3.2.2 Will Delay Interval public var willDelayInterval: UInt32? = 0 - ///3.1.3.2.4 Message Expiry Interval + /// 3.1.3.2.4 Message Expiry Interval public var willExpiryInterval: UInt32? = .max - ///3.1.3.2.5 Content Type + /// 3.1.3.2.5 Content Type public var contentType: String? - ///3.1.3.2.6 Response Topic + /// 3.1.3.2.6 Response Topic public var willResponseTopic: String? - ///3.1.3.2.7 Correlation Data + /// 3.1.3.2.7 Correlation Data public var willCorrelationData: [UInt8]? - ///3.1.3.2.8 User Property + /// 3.1.3.2.8 User Property public var willUserProperty: [String: String]? - + /// Return the payload as a utf8 string if possible /// /// It will return nil if the payload is not a valid utf8 string public var string: String? { - - get { - return NSString(bytes: payload, length: payload.count, encoding: String.Encoding.utf8.rawValue) as String? - } + return NSString(bytes: payload, length: payload.count, encoding: String.Encoding.utf8.rawValue) as String? } public var properties: [UInt8] { - var properties = [UInt8]() var retVal = [UInt8]() @@ -69,7 +62,7 @@ public class CocoaMQTT5Message: NSObject { /// 3.1.3.2.3 Payload Format Indicator if isUTF8EncodedData { properties += [1, 1] - }else{ + } else { properties += [1, 0] } @@ -88,7 +81,7 @@ public class CocoaMQTT5Message: NSObject { } properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.responseTopic.rawValue, value: willResponseTopic.bytesWithLength) } - + /// 3.1.3.2.7 Correlation Data if let willCorrelationData = self.willCorrelationData { let buff = UInt16(willCorrelationData.count).hlBytes + willCorrelationData @@ -114,9 +107,8 @@ public class CocoaMQTT5Message: NSObject { retVal += properties return retVal } - + public init(topic: String, string: String, qos: CocoaMQTTQoS = .qos1, retained: Bool = false) { - self.topic = topic self.payload = [UInt8](string.utf8) self.qos = qos @@ -124,7 +116,6 @@ public class CocoaMQTT5Message: NSObject { } public init(topic: String, payload: [UInt8], qos: CocoaMQTTQoS = .qos1, retained: Bool = false) { - self.topic = topic self.payload = payload self.qos = qos @@ -132,21 +123,18 @@ public class CocoaMQTT5Message: NSObject { } } -extension CocoaMQTT5Message { - - public override var description: String { +public extension CocoaMQTT5Message { + override var description: String { return "CocoaMQTT5Message(topic: \(topic), qos: \(qos), payload: \(payload.summary))" } } // For test extension CocoaMQTT5Message { - - var t_pub_frame: FramePublish { + var tPubFrame: FramePublish { var frame = FramePublish(topic: topic, payload: payload, qos: qos, msgid: 0) frame.retained = retained frame.dup = duplicated return frame } - } diff --git a/Source/CocoaMQTTDeliver.swift b/Source/CocoaMQTTDeliver.swift index 41343307..15971038 100644 --- a/Source/CocoaMQTTDeliver.swift +++ b/Source/CocoaMQTTDeliver.swift @@ -6,27 +6,25 @@ // Copyright © 2019 emqx.io. All rights reserved. // -import Foundation import Dispatch +import Foundation protocol CocoaMQTTDeliverProtocol: AnyObject { - var delegateQueue: DispatchQueue { get set } - + func deliver(_ deliver: CocoaMQTTDeliver, wantToSend frame: Frame) } private struct InflightFrame { - /// The infligth frame maybe a `FramePublish` or `FramePubRel` var frame: Frame - + var timestamp: TimeInterval - + init(frame: Frame) { - self.init(frame: frame, timestamp: Date.init(timeIntervalSinceNow: 0).timeIntervalSince1970) + self.init(frame: frame, timestamp: Date(timeIntervalSinceNow: 0).timeIntervalSince1970) } - + init(frame: Frame, timestamp: TimeInterval) { self.frame = frame self.timestamp = timestamp @@ -34,7 +32,6 @@ private struct InflightFrame { } extension Array where Element == InflightFrame { - func filterMap(isIncluded: (Element) -> (Bool, Element)) -> [Element] { var tmp = [Element]() for e in self { @@ -49,39 +46,37 @@ extension Array where Element == InflightFrame { // CocoaMQTTDeliver class CocoaMQTTDeliver: NSObject { - /// The dispatch queue is used by delivering frames in serially - private var deliverQueue = DispatchQueue.init(label: "deliver.cocoamqtt.emqx", qos: .default) - + private var deliverQueue = DispatchQueue(label: "deliver.cocoamqtt.emqx", qos: .default) + weak var delegate: CocoaMQTTDeliverProtocol? - + fileprivate var inflight = [InflightFrame]() - + fileprivate var mqueue = [Frame]() - + var mqueueSize: UInt = 1000 - + var inflightWindowSize: UInt = 10 - + /// Retry time interval millisecond var retryTimeInterval: Double = 5000 - + private var awaitingTimer: CocoaMQTTTimer? - - var isQueueEmpty: Bool { get { return mqueue.count == 0 }} - var isQueueFull: Bool { get { return mqueue.count >= mqueueSize }} - var isInflightFull: Bool { get { return inflight.count >= inflightWindowSize }} - var isInflightEmpty: Bool { get { return inflight.count == 0 }} - + + var isQueueEmpty: Bool { return mqueue.isEmpty } + var isQueueFull: Bool { return mqueue.count >= mqueueSize } + var isInflightFull: Bool { return inflight.count >= inflightWindowSize } + var isInflightEmpty: Bool { return inflight.isEmpty } + var storage: CocoaMQTTStorage? - + func recoverSessionBy(_ storage: CocoaMQTTStorage) { - let frames = storage.takeAll() - guard frames.count >= 0 else { - return - } - + // guard frames.count >= 0 else { + // return + // } + // Sync to push the frame to mqueue for avoiding overcommit deliverQueue.sync { for f in frames { @@ -91,13 +86,13 @@ class CocoaMQTTDeliver: NSObject { printInfo("Deliver recover \(frames.count) msgs") printDebug("Recover message \(frames)") } - + deliverQueue.async { [weak self] in guard let self = self else { return } self.tryTransport() } } - + /// Add a FramePublish to the message queue to wait for sending /// /// return false means the frame is rejected because of the buffer is full @@ -106,34 +101,39 @@ class CocoaMQTTDeliver: NSObject { printError("Sending buffer is full, frame \(frame) has been rejected to add.") return false } - + // Sync to push the frame to mqueue for avoiding overcommit deliverQueue.sync { mqueue.append(frame) _ = storage?.write(frame) } - + deliverQueue.async { [weak self] in guard let self = self else { return } self.tryTransport() } - + return true } /// Acknowledge a PUBLISH/PUBREL by msgid func ack(by frame: Frame) { var msgid: UInt16 - - if let puback = frame as? FramePubAck { msgid = puback.msgid } - else if let pubrec = frame as? FramePubRec { msgid = pubrec.msgid } - else if let pubcom = frame as? FramePubComp { msgid = pubcom.msgid } - else { return } - + + if let puback = frame as? FramePubAck { + msgid = puback.msgid + } else if let pubrec = frame as? FramePubRec { + msgid = pubrec.msgid + } else if let pubcom = frame as? FramePubComp { + msgid = pubcom.msgid + } else { + return + } + deliverQueue.async { [weak self] in guard let self = self else { return } let acked = self.ackInflightFrame(withMsgid: msgid, type: frame.type) - if acked.count == 0 { + if acked.isEmpty { printWarning("Acknowledge by \(frame), but not found in inflight window") } else { // TODO: ACK DONT DELETE PUBREL @@ -147,7 +147,7 @@ class CocoaMQTTDeliver: NSObject { } } } - + /// Clean Inflight content to prevent message blocked, when next connection established /// /// !!Warning: it's a temporary method for hotfix #221 @@ -162,21 +162,20 @@ class CocoaMQTTDeliver: NSObject { // MARK: Private Funcs extension CocoaMQTTDeliver { - // try transport a frame from mqueue to inflight private func tryTransport() { if isQueueEmpty || isInflightFull { return } - + // take out the earliest frame if mqueue.isEmpty { return } let frame = mqueue.remove(at: 0) - + deliver(frame) - + // keep trying after a transport self.tryTransport() } - + /// Try to deliver a frame private func deliver(_ frame: Frame) { if frame.qos == .qos0 { @@ -184,10 +183,9 @@ extension CocoaMQTTDeliver { // TODO: A retrict deliver mode is need? sendfun(frame) } else { - sendfun(frame) inflight.append(InflightFrame(frame: frame)) - + // Start a retry timer for resending it if it not receive PUBACK or PUBREC if awaitingTimer == nil { awaitingTimer = CocoaMQTTTimer.every(retryTimeInterval / 1000.0, name: "awaitingTimer") { [weak self] in @@ -199,7 +197,7 @@ extension CocoaMQTTDeliver { } } } - + /// Attempt to redeliver in-flight messages private func redeliver() { if isInflightEmpty { @@ -207,20 +205,17 @@ extension CocoaMQTTDeliver { awaitingTimer = nil return } - + let nowTimestamp = Date(timeIntervalSinceNow: 0).timeIntervalSince1970 - for (idx, frame) in inflight.enumerated() { - if (nowTimestamp - frame.timestamp) >= (retryTimeInterval/1000.0) { - - var duplicatedFrame = frame - duplicatedFrame.frame.dup = true - duplicatedFrame.timestamp = nowTimestamp - - inflight[idx] = duplicatedFrame - - printInfo("Re-delivery frame \(duplicatedFrame.frame)") - sendfun(duplicatedFrame.frame) - } + for (idx, frame) in inflight.enumerated() where (nowTimestamp - frame.timestamp) >= (retryTimeInterval / 1000.0) { + var duplicatedFrame = frame + duplicatedFrame.frame.dup = true + duplicatedFrame.timestamp = nowTimestamp + + inflight[idx] = duplicatedFrame + + printInfo("Re-delivery frame \(duplicatedFrame.frame)") + sendfun(duplicatedFrame.frame) } } @@ -228,21 +223,19 @@ extension CocoaMQTTDeliver { private func ackInflightFrame(withMsgid msgid: UInt16, type: FrameType) -> [Frame] { var ackedFrames = [Frame]() inflight = inflight.filterMap { frame in - // -- ACK for PUBLISH if let publish = frame.frame as? FramePublish, publish.msgid == msgid { - if publish.qos == .qos2 && type == .pubrec { // -- Replace PUBLISH with PUBREL let pubrel = FramePubRel(msgid: publish.msgid) - + var nframe = frame nframe.frame = pubrel nframe.timestamp = Date(timeIntervalSinceNow: 0).timeIntervalSince1970 - + _ = storage?.write(pubrel) sendfun(pubrel) - + ackedFrames.append(publish) return (true, nframe) } else if publish.qos == .qos1 && type == .puback { @@ -250,40 +243,37 @@ extension CocoaMQTTDeliver { return (false, frame) } } - + // -- ACK for PUBREL if let pubrel = frame.frame as? FramePubRel, pubrel.msgid == msgid && type == .pubcomp { - ackedFrames.append(pubrel) return (false, frame) } return (true, frame) } - + return ackedFrames } - + private func sendfun(_ frame: Frame) { guard let delegate = self.delegate else { printError("The deliver delegate is nil!!! the frame will be drop: \(frame)") return } - + if frame.qos == .qos0 { if let p = frame as? FramePublish { storage?.remove(p) } } - + delegate.delegateQueue.async { delegate.deliver(self, wantToSend: frame) } } } - // For tests extension CocoaMQTTDeliver { - func t_inflightFrames() -> [Frame] { var frames = [Frame]() for f in inflight { @@ -291,7 +281,7 @@ extension CocoaMQTTDeliver { } return frames } - + func t_queuedFrames() -> [Frame] { return mqueue } diff --git a/Source/CocoaMQTTLogger.swift b/Source/CocoaMQTTLogger.swift index 1294ef46..692680db 100644 --- a/Source/CocoaMQTTLogger.swift +++ b/Source/CocoaMQTTLogger.swift @@ -25,42 +25,39 @@ func printError(_ message: String) { CocoaMQTTLogger.logger.error(message) } - // Enum log levels public enum CocoaMQTTLoggerLevel: Int { case debug = 0, info, warning, error, off } - open class CocoaMQTTLogger: NSObject { - // Singleton public static var logger = CocoaMQTTLogger() + public override init() { super.init() } // min level var minLevel: CocoaMQTTLoggerLevel = .warning - + // logs open func log(level: CocoaMQTTLoggerLevel, message: String) { guard level.rawValue >= minLevel.rawValue else { return } print("CocoaMQTT(\(level)): \(message)") } - + func debug(_ message: String) { log(level: .debug, message: message) } - + func info(_ message: String) { log(level: .info, message: message) } - + func warning(_ message: String) { log(level: .warning, message: message) } - + func error(_ message: String) { log(level: .error, message: message) } - } diff --git a/Source/CocoaMQTTMessage.swift b/Source/CocoaMQTTMessage.swift index e1a7cb7f..bf206e95 100644 --- a/Source/CocoaMQTTMessage.swift +++ b/Source/CocoaMQTTMessage.swift @@ -10,29 +10,26 @@ import Foundation /// MQTT Message public class CocoaMQTTMessage: NSObject { - public var qos = CocoaMQTTQoS.qos1 - + public var topic: String - + public var payload: [UInt8] - + public var retained = false - + /// The `duplicated` property show that this message maybe has be received before /// /// - note: Readonly property public var duplicated = false - + /// Return the payload as a utf8 string if possible /// /// It will return nil if the payload is not a valid utf8 string public var string: String? { - get { - return NSString(bytes: payload, length: payload.count, encoding: String.Encoding.utf8.rawValue) as String? - } + return NSString(bytes: payload, length: payload.count, encoding: String.Encoding.utf8.rawValue) as String? } - + public init(topic: String, string: String, qos: CocoaMQTTQoS = .qos1, retained: Bool = false) { self.topic = topic self.payload = [UInt8](string.utf8) @@ -48,21 +45,18 @@ public class CocoaMQTTMessage: NSObject { } } -extension CocoaMQTTMessage { - - public override var description: String { +public extension CocoaMQTTMessage { + override var description: String { return "CocoaMQTTMessage(topic: \(topic), qos: \(qos), payload: \(payload.summary))" } } // For test extension CocoaMQTTMessage { - - var t_pub_frame: FramePublish { + var tPubFrame: FramePublish { var frame = FramePublish(topic: topic, payload: payload, qos: qos, msgid: 0) frame.retained = retained frame.dup = duplicated return frame } - } diff --git a/Source/CocoaMQTTProperty.swift b/Source/CocoaMQTTProperty.swift index 226c45b0..7e75c8c0 100644 --- a/Source/CocoaMQTTProperty.swift +++ b/Source/CocoaMQTTProperty.swift @@ -37,49 +37,47 @@ public enum CocoaMQTTPropertyName: UInt8 { 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; +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] { +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] { +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)?{ - +func integerCompute(data: [UInt8], formatType: Int, offset: Int) -> (res: Int, newOffset: Int)? { switch formatType { - case formatInt.formatUint8.rawValue: + case FormatInt.formatUint8.rawValue: return (unsignedByteToInt(data: data[offset]), offset + 1) - case formatInt.formatUint16.rawValue: + case FormatInt.formatUint16.rawValue: return (unsignedBytesToInt(data0: data[offset], data1: data[offset + 1]), offset + 2) - case formatInt.formatUint32.rawValue: + 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: + case FormatInt.formatSint8.rawValue: return (unsignedToSigned(unsign: unsignedByteToInt(data: data[offset]), size: 8), offset + 1) - case formatInt.formatSint16.rawValue: + 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) + 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") } @@ -87,30 +85,30 @@ func integerCompute(data:[UInt8], formatType:Int, offset:Int) -> (res: Int, newO return nil } -func unsignedByteToInt(data: UInt8) -> (Int){ - return (Int)(data & 0xFF); +func unsignedByteToInt(data: UInt8) -> (Int) { + return (Int)(data & 0xFF) } -func unsignedBytesToInt(data0: UInt8, data1: UInt8) -> (Int){ +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 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){ +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))); + if (res & (1 << size - 1)) != 0 { + res = -1 * ((1 << size - 1) - (res & ((1 << size - 1) - 1))) } - return res; + return res } - -func unsignedByteToString(data:[UInt8], offset:Int) -> (resStr: String, newOffset: Int)?{ +func unsignedByteToString(data: [UInt8], offset: Int) -> (resStr: String, newOffset: Int)? { var newOffset = offset if offset + 1 > data.count { @@ -118,11 +116,10 @@ func unsignedByteToString(data:[UInt8], offset:Int) -> (resStr: String, newOffse } var length = 0 - let comRes = integerCompute(data: data, formatType: formatInt.formatUint16.rawValue, offset: newOffset) + 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]) @@ -135,8 +132,7 @@ func unsignedByteToString(data:[UInt8], offset:Int) -> (resStr: String, newOffse return (res, newOffset) } - -func unsignedByteToBinary(data:[UInt8], offset:Int) -> (resStr: [UInt8], newOffset: Int)?{ +func unsignedByteToBinary(data: [UInt8], offset: Int) -> (resStr: [UInt8], newOffset: Int)? { var newOffset = offset if offset + 1 > data.count { @@ -144,11 +140,10 @@ func unsignedByteToBinary(data:[UInt8], offset:Int) -> (resStr: [UInt8], newOffs } var length = 0 - let comRes = integerCompute(data: data, formatType: formatInt.formatUint16.rawValue, offset: newOffset) + 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]) @@ -158,10 +153,14 @@ func unsignedByteToBinary(data:[UInt8], offset:Int) -> (resStr: [UInt8], newOffs 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 1‑1 Size of Variable Byte Integer. +// 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 1‑1 Size of Variable Byte Integer. func decodeVariableByteInteger(data: [UInt8], offset: Int) -> (res: Int, newOffset: Int) { var newOffset = offset var count = 0 @@ -181,11 +180,11 @@ func decodeVariableByteInteger(data: [UInt8], offset: Int) -> (res: Int, newOffs func beVariableByteInteger(length: Int) -> [UInt8] { var res = [UInt8]() - var tmpLen:Int = length - repeat{ - var d:UInt8 = UInt8(tmpLen % 128) + var tmpLen: Int = length + repeat { + var d = UInt8(tmpLen % 128) tmpLen /= 128 - if(tmpLen > 0) { + if tmpLen > 0 { d |= 0x80 } res.append(d) diff --git a/Source/CocoaMQTTReader.swift b/Source/CocoaMQTTReader.swift index 239accd2..64426b7e 100644 --- a/Source/CocoaMQTTReader.swift +++ b/Source/CocoaMQTTReader.swift @@ -17,7 +17,6 @@ enum CocoaMQTTReadTag: Int { /// protocol CocoaMQTTReaderDelegate: AnyObject { - func didReceive(_ reader: CocoaMQTTReader, connack: FrameConnAck) func didReceive(_ reader: CocoaMQTTReader, publish: FramePublish) @@ -38,7 +37,6 @@ protocol CocoaMQTTReaderDelegate: AnyObject { } class CocoaMQTTReader { - private var socket: CocoaMQTTSocketProtocol private weak var delegate: CocoaMQTTReaderDelegate? @@ -80,7 +78,7 @@ class CocoaMQTTReader { let result = multiply.multipliedReportingOverflow(by: 128) if !result.overflow { multiply = result.partialValue - }else{ + } else { reset() } readLength() @@ -107,7 +105,6 @@ class CocoaMQTTReader { } private func frameReady() { - guard let frameType = FrameType(rawValue: UInt8(header & 0xF0)) else { printError("Received unknown frame type, header: \(header), data:\(data)") readHeader() diff --git a/Source/CocoaMQTTReasonCode.swift b/Source/CocoaMQTTReasonCode.swift index e677e3ef..9da52112 100644 --- a/Source/CocoaMQTTReasonCode.swift +++ b/Source/CocoaMQTTReasonCode.swift @@ -10,7 +10,7 @@ import Foundation @objc public enum CocoaMQTTAUTHReasonCode: UInt8 { case success = 0x00 case continueAuthentication = 0x18 - case ReAuthenticate = 0x19 + case reAuthenticate = 0x19 } @objc public enum CocoaMQTTCONNACKReasonCode: UInt8 { diff --git a/Source/CocoaMQTTSocket.swift b/Source/CocoaMQTTSocket.swift index 9dbf9142..7477f27c 100644 --- a/Source/CocoaMQTTSocket.swift +++ b/Source/CocoaMQTTSocket.swift @@ -13,16 +13,16 @@ import MqttCocoaAsyncSocket public protocol CocoaMQTTSocketDelegate: AnyObject { func socketConnected(_ socket: CocoaMQTTSocketProtocol) func socket(_ socket: CocoaMQTTSocketProtocol, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Swift.Void) - func socketUrlSession(_ socket: CocoaMQTTSocketProtocol, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + func socketUrlSession(_ socket: CocoaMQTTSocketProtocol, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) func socket(_ socket: CocoaMQTTSocketProtocol, didWriteDataWithTag tag: Int) func socket(_ socket: CocoaMQTTSocketProtocol, didRead data: Data, withTag tag: Int) func socketDidDisconnect(_ socket: CocoaMQTTSocketProtocol, withError err: Error?) } public protocol CocoaMQTTSocketProtocol { - var enableSSL: Bool { get set } - + func setDelegate(_ theDelegate: CocoaMQTTSocketDelegate?, delegateQueue: DispatchQueue?) func connect(toHost host: String, onPort port: UInt16) throws func connect(toHost host: String, onPort port: UInt16, withTimeout timeout: TimeInterval) throws @@ -34,22 +34,21 @@ public protocol CocoaMQTTSocketProtocol { // MARK: - CocoaMQTTSocket public class CocoaMQTTSocket: NSObject { - public var backgroundOnSocket = true public var enableSSL = false - + /// public var sslSettings: [String: NSObject]? - + /// Allow self-signed ca certificate. /// /// Default is false public var allowUntrustCACertificate = false - + fileprivate let reference = MGCDAsyncSocket() fileprivate weak var delegate: CocoaMQTTSocketDelegate? - + public override init() { super.init() } } @@ -58,23 +57,23 @@ extension CocoaMQTTSocket: CocoaMQTTSocketProtocol { delegate = theDelegate reference.setDelegate((delegate != nil ? self : nil), delegateQueue: delegateQueue) } - + public func connect(toHost host: String, onPort port: UInt16) throws { try connect(toHost: host, onPort: port, withTimeout: -1) } - + public func connect(toHost host: String, onPort port: UInt16, withTimeout timeout: TimeInterval) throws { try reference.connect(toHost: host, onPort: port, withTimeout: timeout) } - + public func disconnect() { reference.disconnect() } - + public func readData(toLength length: UInt, withTimeout timeout: TimeInterval, tag: Int) { reference.readData(toLength: length, withTimeout: timeout, tag: tag) } - + public func write(_ data: Data, withTimeout timeout: TimeInterval, tag: Int) { reference.write(data, withTimeout: timeout, tag: tag) } @@ -83,7 +82,7 @@ extension CocoaMQTTSocket: CocoaMQTTSocketProtocol { extension CocoaMQTTSocket: MGCDAsyncSocketDelegate { public func socket(_ sock: MGCDAsyncSocket, didConnectToHost host: String, port: UInt16) { printInfo("Connected to \(host) : \(port)") - + #if os(iOS) if backgroundOnSocket { sock.perform { @@ -95,7 +94,7 @@ extension CocoaMQTTSocket: MGCDAsyncSocketDelegate { } } #endif - + if enableSSL { var setting = sslSettings ?? [:] if allowUntrustCACertificate { diff --git a/Source/CocoaMQTTStorage.swift b/Source/CocoaMQTTStorage.swift index 2af103a6..764082ab 100644 --- a/Source/CocoaMQTTStorage.swift +++ b/Source/CocoaMQTTStorage.swift @@ -9,7 +9,6 @@ import Foundation protocol CocoaMQTTStorageProtocol { - var clientId: String { get set } init?(by clientId: String) @@ -29,14 +28,13 @@ protocol CocoaMQTTStorageProtocol { } final class CocoaMQTTStorage: CocoaMQTTStorageProtocol { - var clientId: String = "" - var userDefault: UserDefaults = UserDefaults() + var userDefault = UserDefaults() - var versionDefault: UserDefaults = UserDefaults() + var versionDefault = UserDefaults() - init?(){ + init?() { versionDefault = UserDefaults() } @@ -54,7 +52,7 @@ final class CocoaMQTTStorage: CocoaMQTTStorageProtocol { versionDefault.synchronize() } - func setMQTTVersion(_ version : String) { + func setMQTTVersion(_ version: String) { versionDefault.set(version, forKey: "cocoamqtt.emqx.version") } @@ -62,7 +60,6 @@ final class CocoaMQTTStorage: CocoaMQTTStorageProtocol { return versionDefault.string(forKey: "cocoamqtt.emqx.version") ?? "3.1.1" } - func write(_ frame: FramePublish) -> Bool { guard frame.qos > .qos0 else { return false @@ -97,11 +94,11 @@ final class CocoaMQTTStorage: CocoaMQTTStorageProtocol { } func readAll() -> [Frame] { - return __read(needDelete: false) + return read(needDelete: false) } func takeAll() -> [Frame] { - return __read(needDelete: true) + return read(needDelete: true) } private func key(_ msgid: UInt16) -> String { @@ -118,18 +115,16 @@ final class CocoaMQTTStorage: CocoaMQTTStorageProtocol { return nil } /// bytes 1..<5 may be 'Remaining Length' - for i in 1 ..< min(5, bytes.count){ - if (bytes[i] & 0x80) == 0 { - return (bytes[0], Array(bytes.suffix(from: i+1))) - } + for i in 1 ..< min(5, bytes.count) where (bytes[i] & 0x80) == 0 { + return (bytes[0], Array(bytes.suffix(from: i + 1))) } return nil } - private func __read(needDelete: Bool) -> [Frame] { + private func read(needDelete: Bool) -> [Frame] { var frames = [Frame]() - let allObjs = userDefault.dictionaryRepresentation().sorted { (k1, k2) in + let allObjs = userDefault.dictionaryRepresentation().sorted { k1, k2 in return k1.key < k2.key } for (k, v) in allObjs { @@ -148,6 +143,4 @@ final class CocoaMQTTStorage: CocoaMQTTStorageProtocol { } return frames } - } - diff --git a/Source/CocoaMQTTTimer.swift b/Source/CocoaMQTTTimer.swift index 9d770278..761f50ba 100644 --- a/Source/CocoaMQTTTimer.swift +++ b/Source/CocoaMQTTTimer.swift @@ -14,12 +14,11 @@ import Foundation /// crashes that occur from calling resume multiple times on a timer that is /// already resumed (noted by https://github.com/SiftScience/sift-ios/issues/52) class CocoaMQTTTimer { - let timeInterval: TimeInterval let startDelay: TimeInterval let name: String - - init(delay:TimeInterval?=nil, name: String, timeInterval: TimeInterval) { + + init(delay: TimeInterval? = nil, name: String, timeInterval: TimeInterval) { self.name = name self.timeInterval = timeInterval if let delay = delay { @@ -28,14 +27,14 @@ class CocoaMQTTTimer { self.startDelay = timeInterval } } - + class func every(_ interval: TimeInterval, name: String, _ block: @escaping () -> Void) -> CocoaMQTTTimer { let timer = CocoaMQTTTimer(name: name, timeInterval: interval) timer.eventHandler = block timer.resume() return timer } - + @discardableResult class func after(_ interval: TimeInterval, name: String, _ block: @escaping () -> Void) -> CocoaMQTTTimer { let timer: CocoaMQTTTimer? = CocoaMQTTTimer(delay: interval, name: name, timeInterval: 0) @@ -47,13 +46,13 @@ class CocoaMQTTTimer { timer?.resume() return timer! } - - /// Execute the tasks concurrently on the target_queue with default QOS - private static let target_queue = DispatchQueue(label: "io.emqx.CocoaMQTT.TimerQueue", qos: .default, attributes: .concurrent) - + + /// Execute the tasks concurrently on the targetQueue with default QOS + private static let targetQueue = DispatchQueue(label: "io.emqx.CocoaMQTT.TimerQueue", qos: .default, attributes: .concurrent) + /// Execute each timer tasks serially and use the target queue for concurrency among timers private lazy var timer: DispatchSourceTimer = { - let queue = DispatchQueue(label: "io.emqx.CocoaMQTT." + name, target: CocoaMQTTTimer.target_queue) + let queue = DispatchQueue(label: "io.emqx.CocoaMQTT." + name, target: CocoaMQTTTimer.targetQueue) let t = DispatchSource.makeTimerSource(flags: .strict, queue: queue) t.schedule(deadline: .now() + self.startDelay, repeating: self.timeInterval > 0 ? Double(self.timeInterval) : Double.infinity) t.setEventHandler(handler: { [weak self] in @@ -61,17 +60,17 @@ class CocoaMQTTTimer { }) return t }() - + var eventHandler: (() -> Void)? - + private enum State { case suspended case resumed case canceled } - + private var state: State = .suspended - + deinit { timer.setEventHandler {} timer.cancel() @@ -82,7 +81,7 @@ class CocoaMQTTTimer { resume() eventHandler = nil } - + func resume() { if state == .resumed { return @@ -90,7 +89,7 @@ class CocoaMQTTTimer { state = .resumed timer.resume() } - + func suspend() { if state == .suspended { return @@ -98,7 +97,7 @@ class CocoaMQTTTimer { state = .suspended timer.suspend() } - + /// Manually cancel timer func cancel() { if state == .canceled { diff --git a/Source/CocoaMQTTTypes.swift b/Source/CocoaMQTTTypes.swift index 4c465e99..ce4cd038 100644 --- a/Source/CocoaMQTTTypes.swift +++ b/Source/CocoaMQTTTypes.swift @@ -14,37 +14,35 @@ extension UInt16 { private var highByte: UInt8 { return UInt8( (self & 0xFF00) >> 8) } - + /// Least Significant Byte (LSB) private var lowByte: UInt8 { return UInt8(self & 0x00FF) } - + var hlBytes: [UInt8] { return [highByte, lowByte] } } - extension String { /// String with two bytes length var bytesWithLength: [UInt8] { return UInt16(utf8.count).hlBytes + utf8 } - + var stringUTF8: String { let data = self.data(using: .nonLossyASCII) return String(data: data!, encoding: .utf8) ?? "" } } - extension Bool { /// Bool to bit of UInt8 var bit: UInt8 { return self ? 1 : 0 } - + /// Initial a bool with a bit init(bit: UInt8) { self = (bit == 0) ? false : true @@ -58,18 +56,16 @@ extension UInt8 { } } - public enum CocoaMQTTError: Error { case invalidURL case readTimeout case writeTimeout @available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) - public enum FoundationConnection : Error { + public enum FoundationConnection: Error { case closed(URLSessionWebSocketTask.CloseCode) } } - extension Array where Element == UInt8 { var summary: String { if self.count <= 10 { @@ -84,12 +80,10 @@ extension Array where Element == UInt8 { } } - - extension Data { var uint8: UInt8 { var number: UInt8 = 0 - self.copyBytes(to:&number, count: MemoryLayout.size) + self.copyBytes(to: &number, count: MemoryLayout.size) return number } @@ -105,7 +99,7 @@ extension Data { var uuid: NSUUID? { var bytes = [UInt8](repeating: 0, count: self.count) - self.copyBytes(to:&bytes, count: self.count * MemoryLayout.size) + self.copyBytes(to: &bytes, count: self.count * MemoryLayout.size) return NSUUID(uuidBytes: bytes) } var stringASCII: String? { @@ -125,10 +119,8 @@ extension Data { let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx" return map { String(format: format, $0) }.joined() } - } - extension Int { var data: Data { var int = self @@ -165,5 +157,3 @@ extension UInt32 { ] } } - - diff --git a/Source/CocoaMQTTWebSocket.swift b/Source/CocoaMQTTWebSocket.swift index 6f2e480e..bafba80f 100644 --- a/Source/CocoaMQTTWebSocket.swift +++ b/Source/CocoaMQTTWebSocket.swift @@ -14,56 +14,50 @@ import CocoaMQTT // MARK: - Interfaces public protocol CocoaMQTTWebSocketConnectionDelegate: AnyObject { - func connection(_ conn: CocoaMQTTWebSocketConnection, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Swift.Void) - func urlSessionConnection(_ conn: CocoaMQTTWebSocketConnection, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) - + func urlSessionConnection(_ conn: CocoaMQTTWebSocketConnection, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + func connectionOpened(_ conn: CocoaMQTTWebSocketConnection) - + func connectionClosed(_ conn: CocoaMQTTWebSocketConnection, withError error: Error?) - + func connection(_ conn: CocoaMQTTWebSocketConnection, receivedString string: String) - + func connection(_ conn: CocoaMQTTWebSocketConnection, receivedData data: Data) } public protocol CocoaMQTTWebSocketConnection: NSObjectProtocol { - var delegate: CocoaMQTTWebSocketConnectionDelegate? { get set } - + var queue: DispatchQueue { get set } - + func connect() - + func disconnect() - + func write(data: Data, handler: @escaping (Error?) -> Void) } public protocol CocoaMQTTWebSocketConnectionBuilder { - func buildConnection(forURL url: URL, withHeaders headers: [String: String]) throws -> CocoaMQTTWebSocketConnection - } // MARK: - CocoaMQTTWebSocket public class CocoaMQTTWebSocket: CocoaMQTTSocketProtocol { - public var enableSSL = false public var shouldConnectWithURIOnly = false - + public var headers: [String: String] = [:] public typealias ConnectionBuilder = CocoaMQTTWebSocketConnectionBuilder - + public struct DefaultConnectionBuilder: ConnectionBuilder { - public init() {} - - + public func buildConnection(forURL url: URL, withHeaders headers: [String: String]) throws -> CocoaMQTTWebSocketConnection { if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) { let config = URLSessionConfiguration.default @@ -71,39 +65,40 @@ public class CocoaMQTTWebSocket: CocoaMQTTSocketProtocol { return CocoaMQTTWebSocket.FoundationConnection(url: url, config: config) } else { var request = URLRequest(url: url) - headers.forEach { request.setValue($1, forHTTPHeaderField: $0)} + headers.forEach { request.setValue($1, forHTTPHeaderField: $0) } return CocoaMQTTWebSocket.StarscreamConnection(request: request) } } } - + public func setDelegate(_ theDelegate: CocoaMQTTSocketDelegate?, delegateQueue: DispatchQueue?) { internalQueue.async { self.delegate = theDelegate self.delegateQueue = delegateQueue } } + let uri: String let builder: ConnectionBuilder + public init(uri: String = "", builder: ConnectionBuilder = CocoaMQTTWebSocket.DefaultConnectionBuilder()) { self.uri = uri self.builder = builder } - + public func connect(toHost host: String, onPort port: UInt16) throws { try connect(toHost: host, onPort: port, withTimeout: -1) } - - public func connect(toHost host: String, onPort port: UInt16, withTimeout timeout: TimeInterval) throws { + public func connect(toHost host: String, onPort port: UInt16, withTimeout timeout: TimeInterval) throws { var urlStr = "" if shouldConnectWithURIOnly { urlStr = "\(uri)" } else { - urlStr = "\(enableSSL ? "wss": "ws")://\(host):\(port)\(uri)" + urlStr = "\(enableSSL ? "wss" : "ws")://\(host):\(port)\(uri)" } - + guard let url = URL(string: urlStr) else { throw CocoaMQTTError.invalidURL } try internalQueue.sync { connection?.disconnect() @@ -115,14 +110,14 @@ public class CocoaMQTTWebSocket: CocoaMQTTSocketProtocol { newConnection.connect() } } - + public func disconnect() { internalQueue.async { - //self.reset() + // self.reset() self.closeConnection(withError: nil) } } - + public func readData(toLength length: UInt, withTimeout timeout: TimeInterval, tag: Int) { internalQueue.async { let newRead = ReadItem(tag: tag, length: length, timeout: (timeout > 0.0) ? .now() + timeout : .distantFuture) @@ -130,7 +125,7 @@ public class CocoaMQTTWebSocket: CocoaMQTTSocketProtocol { self.checkScheduledReads() } } - + public func write(_ data: Data, withTimeout timeout: TimeInterval, tag: Int) { internalQueue.async { let newWrite = WriteItem(tag: tag, timeout: (timeout > 0.0) ? .now() + timeout : .distantFuture) @@ -147,41 +142,41 @@ public class CocoaMQTTWebSocket: CocoaMQTTSocketProtocol { } } } - + internal var delegate: CocoaMQTTSocketDelegate? internal var delegateQueue: DispatchQueue? internal var internalQueue = DispatchQueue(label: "CocoaMQTTWebSocket") private var connection: CocoaMQTTWebSocketConnection? - + private func reset() { connection?.delegate = nil connection?.disconnect() connection = nil - + readBuffer.removeAll() scheduledReads.removeAll() readTimeoutTimer.reset() - + scheduledWrites.removeAll() writeTimeoutTimer.reset() } - + private func closeConnection(withError error: Error?) { reset() - __delegate_queue { + executeOnDelegateQueue { self.delegate?.socketDidDisconnect(self, withError: error) } } - + private class ReusableTimer { let queue: DispatchQueue var timer: DispatchSourceTimer? - + init(queue: DispatchQueue) { self.queue = queue } - + func schedule(wallDeadline: DispatchWallTime, handler: @escaping () -> Void) { reset() let newTimer = DispatchSource.makeTimerSource(flags: .strict, queue: queue) @@ -190,24 +185,25 @@ public class CocoaMQTTWebSocket: CocoaMQTTSocketProtocol { newTimer.setEventHandler(handler: handler) newTimer.resume() } - + func reset() { - if(timer != nil){ + if timer != nil { timer?.cancel() timer = nil } } } - + private struct ReadItem { let tag: Int let length: UInt let timeout: DispatchWallTime } - + private var readBuffer = Data() private var scheduledReads: [ReadItem] = [] private lazy var readTimeoutTimer = ReusableTimer(queue: internalQueue) + private func checkScheduledReads() { guard let theDelegate = delegate else { return } guard let delegateQueue = delegateQueue else { return } @@ -222,9 +218,9 @@ public class CocoaMQTTWebSocket: CocoaMQTTSocketProtocol { theDelegate.socket(self, didRead: readData, withTag: nextRead.tag) } } - - guard let closestTimeout = scheduledReads.sorted(by: { a,b in a.timeout < b.timeout }).first?.timeout else { return } - + + guard let closestTimeout = scheduledReads.sorted(by: { a, b in a.timeout < b.timeout }).first?.timeout else { return } + if closestTimeout < .now() { closeConnection(withError: CocoaMQTTError.readTimeout) } else { @@ -233,20 +229,23 @@ public class CocoaMQTTWebSocket: CocoaMQTTSocketProtocol { } } } - + private struct WriteItem: Hashable { let uuid = UUID() let tag: Int let timeout: DispatchWallTime + func hash(into hasher: inout Hasher) { hasher.combine(uuid) } } + private var scheduledWrites = Set() private lazy var writeTimeoutTimer = ReusableTimer(queue: internalQueue) + private func checkScheduledWrites() { writeTimeoutTimer.reset() - guard let closestTimeout = scheduledWrites.sorted(by: { a,b in a.timeout < b.timeout }).first?.timeout else { return } + guard let closestTimeout = scheduledWrites.sorted(by: { a, b in a.timeout < b.timeout }).first?.timeout else { return } if closestTimeout < .now() { closeConnection(withError: CocoaMQTTError.writeTimeout) } else { @@ -258,9 +257,11 @@ public class CocoaMQTTWebSocket: CocoaMQTTSocketProtocol { } extension CocoaMQTTWebSocket: CocoaMQTTWebSocketConnectionDelegate { - public func urlSessionConnection(_ conn: CocoaMQTTWebSocketConnection, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + public func urlSessionConnection(_ conn: CocoaMQTTWebSocketConnection, didReceiveTrust trust: SecTrust, + didReceiveChallenge challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { if let del = delegate { - __delegate_queue { + executeOnDelegateQueue { del.socketUrlSession(self, didReceiveTrust: trust, didReceiveChallenge: challenge, completionHandler: completionHandler) } } else { @@ -270,7 +271,7 @@ extension CocoaMQTTWebSocket: CocoaMQTTWebSocketConnectionDelegate { public func connection(_ conn: CocoaMQTTWebSocketConnection, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) { if let del = delegate { - __delegate_queue { + executeOnDelegateQueue { del.socket(self, didReceive: trust, completionHandler: completionHandler) } } else { @@ -309,32 +310,31 @@ extension CocoaMQTTWebSocket: CocoaMQTTWebSocketConnectionDelegate { @available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) public extension CocoaMQTTWebSocket { class FoundationConnection: NSObject, CocoaMQTTWebSocketConnection { - public weak var delegate: CocoaMQTTWebSocketConnectionDelegate? public lazy var queue = DispatchQueue(label: "CocoaMQTTFoundationWebSocketConnection-\(self.hashValue)") - + var session: URLSession? var task: URLSessionWebSocketTask? - + public init(url: URL, config: URLSessionConfiguration) { super.init() let theSession = URLSession(configuration: config, delegate: self, delegateQueue: nil) session = theSession task = theSession.webSocketTask(with: url, protocols: ["mqtt"]) } - + public func connect() { task?.resume() scheduleRead() } - + public func disconnect() { task?.cancel() session = nil task = nil delegate = nil } - + public func write(data: Data, handler: @escaping (Error?) -> Void) { task?.send(.data(data)) { possibleError in self.queue.async { @@ -342,7 +342,7 @@ public extension CocoaMQTTWebSocket { } } } - + func scheduleRead() { queue.async { guard let task = self.task else { return } @@ -371,14 +371,15 @@ public extension CocoaMQTTWebSocket { @available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) extension CocoaMQTTWebSocket.FoundationConnection: URLSessionWebSocketDelegate { - public func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + public func urlSession(_ session: URLSession, task: URLSessionTask, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { queue.async { if let trust = challenge.protectionSpace.serverTrust, let delegate = self.delegate { delegate.connection(self, didReceive: trust) { shouldTrust in completionHandler(shouldTrust ? .performDefaultHandling : .rejectProtectionSpace, nil) } delegate.urlSessionConnection(self, didReceiveTrust: trust, didReceiveChallenge: challenge, completionHandler: completionHandler) - } else { completionHandler(.performDefaultHandling, nil) } @@ -391,7 +392,8 @@ extension CocoaMQTTWebSocket.FoundationConnection: URLSessionWebSocketDelegate { } } - public func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) { + public func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, + didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) { queue.async { self.delegate?.connectionClosed(self, withError: CocoaMQTTError.FoundationConnection.closed(closeCode)) } @@ -408,21 +410,21 @@ public extension CocoaMQTTWebSocket { get { reference.callbackQueue } set { reference.callbackQueue = newValue } } - + public init(request: URLRequest) { reference = WebSocket(request: request, protocols: ["mqtt"], stream: FoundationStream()) super.init() reference.delegate = self } - + public func connect() { reference.connect() } - + public func disconnect() { reference.disconnect() } - + public func write(data: Data, handler: @escaping (Error?) -> Void) { reference.write(data: data) { handler(nil) @@ -434,7 +436,7 @@ public extension CocoaMQTTWebSocket { extension CocoaMQTTWebSocket.StarscreamConnection: SSLTrustValidator { public func isValid(_ trust: SecTrust, domain: String?) -> Bool { guard let delegate = self.delegate else { return false } - + var shouldAccept = false let semaphore = DispatchSemaphore(value: 0) delegate.connection(self, didReceive: trust) { result in @@ -442,13 +444,12 @@ extension CocoaMQTTWebSocket.StarscreamConnection: SSLTrustValidator { semaphore.signal() } semaphore.wait() - + return shouldAccept } } extension CocoaMQTTWebSocket.StarscreamConnection: WebSocketDelegate { - public func websocketDidConnect(socket: WebSocketClient) { delegate?.connectionOpened(self) } @@ -469,10 +470,9 @@ extension CocoaMQTTWebSocket.StarscreamConnection: WebSocketDelegate { // MARK: - Helper extension CocoaMQTTWebSocket { - - func __delegate_queue(_ fun: @escaping () -> Void) { + func executeOnDelegateQueue(_ fun: @escaping () -> Void) { delegateQueue?.async { [weak self] in - guard let _ = self else { return } + guard self != nil else { return } fun() } } diff --git a/Source/Frame.swift b/Source/Frame.swift index 67363df0..a45a7410 100644 --- a/Source/Frame.swift +++ b/Source/Frame.swift @@ -12,16 +12,16 @@ import Foundation @objc public enum CocoaMQTTQoS: UInt8, CustomStringConvertible { /// At most once delivery case qos0 = 0 - + /// At least once delivery case qos1 - + /// Exactly once delivery case qos2 - + /// !!! Used SUBACK frame only case FAILURE = 0x80 - + public var description: String { switch self { case .qos0: return "qos0" @@ -33,19 +33,18 @@ import Foundation } extension CocoaMQTTQoS: Comparable { - public static func < (lhs: CocoaMQTTQoS, rhs: CocoaMQTTQoS) -> Bool { return lhs.rawValue < rhs.rawValue } - + public static func <= (lhs: CocoaMQTTQoS, rhs: CocoaMQTTQoS) -> Bool { return lhs.rawValue <= rhs.rawValue } - + public static func > (lhs: CocoaMQTTQoS, rhs: CocoaMQTTQoS) -> Bool { return lhs.rawValue > rhs.rawValue } - + public static func >= (lhs: CocoaMQTTQoS, rhs: CocoaMQTTQoS) -> Bool { return lhs.rawValue >= rhs.rawValue } @@ -73,14 +72,11 @@ enum FrameType: UInt8 { /// The frame can be initialized with a bytes protocol InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) } - /// MQTT Frame protocol protocol Frame { - /// Each MQTT Control Packet contains a fixed header /// MQTT 3.1.1 var packetFixedHeaderType: UInt8 {get set} @@ -94,7 +90,10 @@ protocol Frame { /// MQTT 5.0 func variableHeader5() -> [UInt8] - /// MQTT 5.0 The last field in the Variable Header of the CONNECT, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, DISCONNECT, and AUTH packet is a set of Properties. In the CONNECT packet there is also an optional set of Properties in the Will Properties field with the Payload. + /// MQTT 5.0 The last field in the Variable Header of the CONNECT, CONNACK, + /// PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, + /// UNSUBACK, DISCONNECT, and AUTH packet is a set of Properties. In the CONNECT + /// packet there is also an optional set of Properties in the Will Properties field with the Payload. func properties() -> [UInt8] /// Some MQTT Control Packets contain a payload as the final part of the packet @@ -109,10 +108,8 @@ protocol Frame { } extension Frame { - /// Pack struct to binary func bytes(version: String) -> [UInt8] { - if version == "5.0" { let fixedHeader = self.fixedHeader() let variableHeader5 = self.variableHeader5() @@ -130,8 +127,7 @@ extension Frame { printDebug("=============================================================") return [packetFixedHeaderType] + remainingLen(len: len5) + variableHeader5 + properties + payload5 - }else { - + } else { let variableHeader = self.variableHeader() let payload = self.payload() @@ -143,34 +139,32 @@ extension Frame { printDebug("variableHeader \(variableHeader)") printDebug("payload \(payload)") printDebug("=============================================================") - + return [packetFixedHeaderType] + remainingLen(len: len) + variableHeader + payload } - } - + private func remainingLen(len: UInt32) -> [UInt8] { var bytes: [UInt8] = [] var digit: UInt8 = 0 - + var len = len repeat { digit = UInt8(len % 128) - len = len / 128 + len /= 128 // if there are more digits to encode, set the top bit of this digit if len > 0 { digit = digit | 0x80 } bytes.append(digit) } while len > 0 - + return bytes } } /// Fixed Header Attributes extension Frame { - /// The Fixed Header consist of the following attritutes /// /// +---------+----------+-------+--------+ @@ -178,23 +172,22 @@ extension Frame { /// +---------+----------+-------+--------+ /// | Type | DUP flag | QoS | RETAIN | /// +-------------------------------------+ - - + /// The type of the Frame var type: FrameType { return FrameType(rawValue: packetFixedHeaderType & 0xF0)! } - + /// Dup flag var dup: Bool { get { return ((packetFixedHeaderType & 0x08) >> 3) == 0 ? false : true } set { - packetFixedHeaderType = (packetFixedHeaderType & 0xF7) | (newValue.bit << 3) + packetFixedHeaderType = (packetFixedHeaderType & 0xF7) | (newValue.bit << 3) } } - + /// Qos level var qos: CocoaMQTTQoS { get { @@ -204,7 +197,7 @@ extension Frame { packetFixedHeaderType = (packetFixedHeaderType & 0xF9) | (newValue.rawValue << 1) } } - + /// Retained flag var retained: Bool { get { @@ -215,5 +208,3 @@ extension Frame { } } } - - diff --git a/Source/FrameAuth.swift b/Source/FrameAuth.swift index 882b3c37..5dae80a1 100644 --- a/Source/FrameAuth.swift +++ b/Source/FrameAuth.swift @@ -8,29 +8,26 @@ import Foundation struct FrameAuth: Frame { - var packetFixedHeaderType: UInt8 = FrameType.auth.rawValue - //3.15.2.1 Authenticate Reason Code + // 3.15.2.1 Authenticate Reason Code var sendReasonCode: CocoaMQTTAUTHReasonCode? var receiveReasonCode: CocoaMQTTAUTHReasonCode? - - //3.15.2.2 AUTH Properties + + // 3.15.2.2 AUTH Properties var authProperties: MqttAuthProperties? - init(reasonCode: CocoaMQTTAUTHReasonCode,authProperties: MqttAuthProperties) { + init(reasonCode: CocoaMQTTAUTHReasonCode, authProperties: MqttAuthProperties) { self.sendReasonCode = reasonCode self.authProperties = authProperties } - } extension FrameAuth { - func fixedHeader() -> [UInt8] { var header = [UInt8]() header += [FrameType.auth.rawValue] - //header += [UInt8(variableHeader5().count)] + // header += [UInt8(variableHeader5().count)] return header } @@ -38,9 +35,9 @@ extension FrameAuth { func variableHeader5() -> [UInt8] { var header = [UInt8]() header += [sendReasonCode!.rawValue] - //MQTT 5.0 + // MQTT 5.0 header += beVariableByteInteger(length: self.properties().count) - + return header } @@ -48,7 +45,6 @@ extension FrameAuth { func properties() -> [UInt8] { return authProperties?.properties ?? [] - } func allData() -> [UInt8] { @@ -68,10 +64,7 @@ extension FrameAuth { } extension FrameAuth: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { - receiveReasonCode = CocoaMQTTAUTHReasonCode(rawValue: bytes[0]) } - } diff --git a/Source/FrameConnAck.swift b/Source/FrameConnAck.swift index 9e15781b..e7e3f91a 100644 --- a/Source/FrameConnAck.swift +++ b/Source/FrameConnAck.swift @@ -9,53 +9,50 @@ import Foundation struct FrameConnAck: Frame { - var packetFixedHeaderType: UInt8 = FrameType.connack.rawValue - + // --- Attributes - ///MQTT 3.1.1 + /// MQTT 3.1.1 var returnCode: CocoaMQTTConnAck? - ///MQTT 5.0 + /// MQTT 5.0 var reasonCode: CocoaMQTTCONNACKReasonCode? - //3.2.2.1.1 Session Present - var sessPresent: Bool = false - + // 3.2.2.1.1 Session Present + var sessPresent = false + // --- Attributes End - //3.2.2.3 CONNACK Properties + // 3.2.2.3 CONNACK Properties var connackProperties: MqttDecodeConnAck? var propertiesBytes: [UInt8]? - //3.2.3 CONNACK Payload - //The CONNACK packet has no Payload. + // 3.2.3 CONNACK Payload + // The CONNACK packet has no Payload. - ///MQTT 3.1.1 + /// MQTT 3.1.1 init(returnCode: CocoaMQTTConnAck) { self.returnCode = returnCode } - ///MQTT 5.0 + /// MQTT 5.0 init(code: CocoaMQTTCONNACKReasonCode) { reasonCode = code } - } extension FrameConnAck { - func fixedHeader() -> [UInt8] { var header = [UInt8]() header += [FrameType.connack.rawValue] - + return header } func variableHeader5() -> [UInt8] { return [sessPresent.bit, reasonCode!.rawValue] } - + func payload5() -> [UInt8] { return [] } func properties() -> [UInt8] { return propertiesBytes ?? [] } @@ -79,22 +76,21 @@ extension FrameConnAck { } extension FrameConnAck: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { guard packetFixedHeaderType == FrameType.connack.rawValue else { return nil } - + guard bytes.count >= 2 else { return nil } sessPresent = Bool(bit: bytes[0] & 0x01) - + let mqtt5ack = CocoaMQTTCONNACKReasonCode(rawValue: bytes[1]) reasonCode = mqtt5ack - let ack = CocoaMQTTConnAck(byte: bytes[1]) + let ack = CocoaMQTTConnAck(byte: bytes[1]) returnCode = ack propertiesBytes = bytes diff --git a/Source/FrameConnect.swift b/Source/FrameConnect.swift index 4906d0b9..b7b110bb 100644 --- a/Source/FrameConnect.swift +++ b/Source/FrameConnect.swift @@ -10,44 +10,43 @@ import Foundation /// MQTT CONNECT Frame struct FrameConnect: Frame { - var packetFixedHeaderType: UInt8 = FrameType.connect.rawValue - ///MQTT 3.1.1 - private let PROTOCOL_LEVEL = UInt8(4) - private let PROTOCOL_VERSION: String = "MQTT/3.1.1" - private let PROTOCOL_MAGIC: String = "MQTT" + /// MQTT 3.1.1 + private let kProtocolLevel = UInt8(4) + // private let kProtocolVersion: String = "MQTT/3.1.1" + private let kProtocolMagic: String = "MQTT" // --- Attributes - //3.1.2.1 + // 3.1.2.1 let protocolName: String = "MQTT" - //3.1.2.2 Protocol Version + // 3.1.2.2 Protocol Version let protocolVersion = UInt8(5) - //3.1.2.5 Will Flag + // 3.1.2.5 Will Flag var willMsg: CocoaMQTTMessage? var willMsg5: CocoaMQTT5Message? - //3.1.2.6 Will QoS + // 3.1.2.6 Will QoS var willQoS: UInt8? - //3.1.2.7 Will Retain - var willRetain: Bool = true - //3.1.2.8 User Name Flag + // 3.1.2.7 Will Retain + var willRetain = true + // 3.1.2.8 User Name Flag var username: String? - //3.1.2.9 Password Flag + // 3.1.2.9 Password Flag var password: String? - //3.1.2.10 Keep Alive + // 3.1.2.10 Keep Alive var keepAlive: UInt16 = 10 - var cleansess: Bool = true + var cleansess = true - //3.1.2 - //3.1.2.11 CONNECT Properties + // 3.1.2 + // 3.1.2.11 CONNECT Properties var connectProperties: MqttConnectProperties? var authenticationData: Data? - //3.1.3.1 Client Identifier (ClientID) + // 3.1.3.1 Client Identifier (ClientID) var clientID: String // --- Attributes End @@ -58,9 +57,7 @@ struct FrameConnect: Frame { } extension FrameConnect { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.connect.rawValue] @@ -68,29 +65,27 @@ extension FrameConnect { } func variableHeader5() -> [UInt8] { - var header = [UInt8]() var flags = ConnFlags() - - //3.1.2.1 Protocol Name + + // 3.1.2.1 Protocol Name header += protocolName.bytesWithLength - //3.1.2.2 Protocol Version + // 3.1.2.2 Protocol Version header.append(protocolVersion) - - //3.1.2.3 Connect Flags + // 3.1.2.3 Connect Flags if let will = willMsg5 { flags.flagWill = true flags.flagWillQoS = will.qos.rawValue flags.flagWillRetain = will.retained } - if let _ = username { + if username != nil { flags.flagUsername = true // Append password attribute if username presented - if let _ = password { + if password != nil { flags.flagPassword = true } } @@ -100,9 +95,8 @@ extension FrameConnect { header.append(flags.rawValue) header += keepAlive.hlBytes - //MQTT 5.0 + // MQTT 5.0 header += beVariableByteInteger(length: self.properties().count) - return header } @@ -117,7 +111,6 @@ extension FrameConnect { payload += clientID.bytesWithLength if let will = willMsg5 { - payload += beVariableByteInteger(length: willMsg5!.properties.count) payload += will.properties payload += will.topic.bytesWithLength @@ -126,7 +119,6 @@ extension FrameConnect { } if let username = username { - payload += username.bytesWithLength // Append password attribute if username presented @@ -135,13 +127,10 @@ extension FrameConnect { } } - return payload } - func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -152,15 +141,13 @@ extension FrameConnect { return allData } - func variableHeader() -> [UInt8] { - var header = [UInt8]() var flags = ConnFlags() // variable header - header += PROTOCOL_MAGIC.bytesWithLength - header.append(PROTOCOL_LEVEL) + header += kProtocolMagic.bytesWithLength + header.append(kProtocolLevel) if let will = willMsg { flags.flagWill = true @@ -168,11 +155,11 @@ extension FrameConnect { flags.flagWillRetain = will.retained } - if let _ = username { + if username != nil { flags.flagUsername = true // Append password attribute if username presented - if let _ = password { + if password != nil { flags.flagPassword = true } } @@ -186,7 +173,6 @@ extension FrameConnect { } func payload() -> [UInt8] { - var payload = [UInt8]() payload += clientID.bytesWithLength @@ -219,7 +205,6 @@ extension FrameConnect: CustomStringConvertible { /// Connect Flags private struct ConnFlags { - /// These Flags consist of following flags: /// /// +----------+----------+------------+--------------------+--------------+----------+ @@ -242,7 +227,7 @@ private struct ConnFlags { var flagPassword: Bool { get { - return Bool(bit:(rawValue >> 6) & 0x01) + return Bool(bit: (rawValue >> 6) & 0x01) } set { @@ -272,7 +257,7 @@ private struct ConnFlags { var flagWill: Bool { get { - return Bool(bit:(rawValue >> 2) & 0x01) + return Bool(bit: (rawValue >> 2) & 0x01) } set { @@ -287,8 +272,6 @@ private struct ConnFlags { set { rawValue = (rawValue & 0xFD) | (newValue.bit << 1) - } } } - diff --git a/Source/FrameDisconnect.swift b/Source/FrameDisconnect.swift index 22fe9acf..b8027223 100644 --- a/Source/FrameDisconnect.swift +++ b/Source/FrameDisconnect.swift @@ -10,74 +10,69 @@ import Foundation /// MQTT Disconnect packet struct FrameDisconnect: Frame { - var packetFixedHeaderType: UInt8 = FrameType.disconnect.rawValue - //3.14.2 DISCONNECT Variable Header - public var sendReasonCode: CocoaMQTTDISCONNECTReasonCode? - public var receiveReasonCode: CocoaMQTTDISCONNECTReasonCode? - - //3.14.2.2.2 Session Expiry Interval - public var sessionExpiryInterval: UInt32? - - //3.14.2.2.3 Reason String - public var reasonString: String? - //3.14.2.2.4 User Property - public var userProperties: [String: String]? - //3.14.2.2.5 Server Reference - public var serverReference: String? - - ///MQTT 3.1.1 + // 3.14.2 DISCONNECT Variable Header + var sendReasonCode: CocoaMQTTDISCONNECTReasonCode? + var receiveReasonCode: CocoaMQTTDISCONNECTReasonCode? + + // 3.14.2.2.2 Session Expiry Interval + var sessionExpiryInterval: UInt32? + + // 3.14.2.2.3 Reason String + var reasonString: String? + // 3.14.2.2.4 User Property + var userProperties: [String: String]? + // 3.14.2.2.5 Server Reference + var serverReference: String? + + /// MQTT 3.1.1 init() { /* Nothing to do */ } - ///MQTT 5.0 + /// MQTT 5.0 init(disconnectReasonCode: CocoaMQTTDISCONNECTReasonCode) { self.sendReasonCode = disconnectReasonCode } } extension FrameDisconnect { - func fixedHeader() -> [UInt8] { var header = [UInt8]() header += [FrameType.disconnect.rawValue] return header } - + func variableHeader5() -> [UInt8] { - var header = [UInt8]() header += [sendReasonCode!.rawValue] - //MQTT 5.0 + // MQTT 5.0 header += beVariableByteInteger(length: self.properties().count) - return header } - + func payload5() -> [UInt8] { return [] } func properties() -> [UInt8] { - var properties = [UInt8]() - //3.14.2.2.2 Session Expiry Interval + // 3.14.2.2.2 Session Expiry Interval if let sessionExpiryInterval = self.sessionExpiryInterval { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.sessionExpiryInterval.rawValue, value: sessionExpiryInterval.byteArrayLittleEndian) } - //3.14.2.2.3 Reason String + // 3.14.2.2.3 Reason String if let reasonString = self.reasonString { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength) } - //3.14.2.2.4 User Property + // 3.14.2.2.4 User Property if let userProperty = self.userProperties { for (key, value) in userProperty { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.userProperty.rawValue, value: key.bytesWithLength + value.bytesWithLength) } } - //3.14.2.2.5 Server Reference + // 3.14.2.2.5 Server Reference if let serverReference = self.serverReference { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.serverReference.rawValue, value: serverReference.bytesWithLength) } @@ -86,7 +81,6 @@ extension FrameDisconnect { } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -103,21 +97,18 @@ extension FrameDisconnect { } extension FrameDisconnect: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { - - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ - if bytes.count > 0 { + if protocolVersion == "5.0" { + if !bytes.isEmpty { receiveReasonCode = CocoaMQTTDISCONNECTReasonCode(rawValue: bytes[0]) } } } - } extension FrameDisconnect: CustomStringConvertible { diff --git a/Source/FramePingReq.swift b/Source/FramePingReq.swift index e285c11c..609bbde2 100644 --- a/Source/FramePingReq.swift +++ b/Source/FramePingReq.swift @@ -9,30 +9,26 @@ import Foundation struct FramePingReq: Frame { - var packetFixedHeaderType: UInt8 = FrameType.pingreq.rawValue - + init() { /* Nothing to do */ } } extension FramePingReq { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.pingreq.rawValue] - + return header } - + func variableHeader5() -> [UInt8] { return [] } - + func payload5() -> [UInt8] { return [] } func properties() -> [UInt8] { return [] } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -46,7 +42,6 @@ extension FramePingReq { func variableHeader() -> [UInt8] { return [] } func payload() -> [UInt8] { return [] } - } extension FramePingReq: CustomStringConvertible { diff --git a/Source/FramePingResp.swift b/Source/FramePingResp.swift index aa46074f..86ce94b5 100644 --- a/Source/FramePingResp.swift +++ b/Source/FramePingResp.swift @@ -10,30 +10,26 @@ import Foundation /// MQTT PINGRESP packet struct FramePingResp: Frame { - var packetFixedHeaderType: UInt8 = FrameType.pingresp.rawValue - + init() { /* Nothing to do */ } } extension FramePingResp { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.pingresp.rawValue] return header } - + func variableHeader5() -> [UInt8] { return [] } - + func payload5() -> [UInt8] { return [] } - + func properties() -> [UInt8] { return [] } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -43,21 +39,19 @@ extension FramePingResp { return allData } - + func variableHeader() -> [UInt8] { return [] } func payload() -> [UInt8] { return [] } } extension FramePingResp: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { - guard packetFixedHeaderType == FrameType.pingresp.rawValue else { return nil } - - guard bytes.count == 0 else { + + guard bytes.isEmpty else { return nil } } diff --git a/Source/FramePubAck.swift b/Source/FramePubAck.swift index 9926950c..ba014967 100644 --- a/Source/FramePubAck.swift +++ b/Source/FramePubAck.swift @@ -10,31 +10,30 @@ import Foundation /// MQTT PUBACK packet struct FramePubAck: Frame { - var packetFixedHeaderType: UInt8 = FrameType.puback.rawValue // --- Attributes - + var msgid: UInt16 - + // --- Attributes End - //3.4.2.1 PUBACK Reason Code - public var reasonCode: CocoaMQTTPUBACKReasonCode? + // 3.4.2.1 PUBACK Reason Code + var reasonCode: CocoaMQTTPUBACKReasonCode? - //3.4.2.2 PUBACK Properties - public var pubAckProperties: MqttDecodePubAck? - //3.4.2.2.2 Reason String - public var reasonString: String? - //3.4.2.2.3 User Property - public var userProperties: [String: String]? + // 3.4.2.2 PUBACK Properties + var pubAckProperties: MqttDecodePubAck? + // 3.4.2.2.2 Reason String + var reasonString: String? + // 3.4.2.2.3 User Property + var userProperties: [String: String]? - ///MQTT 3.1.1 + /// MQTT 3.1.1 init(msgid: UInt16) { self.msgid = msgid } - ///MQTT 5.0 + /// MQTT 5.0 init(msgid: UInt16, reasonCode: CocoaMQTTPUBACKReasonCode) { self.msgid = msgid self.reasonCode = reasonCode @@ -42,51 +41,46 @@ struct FramePubAck: Frame { } extension FramePubAck { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.puback.rawValue] return header } - + func variableHeader5() -> [UInt8] { - - //3.4.2 MSB+LSB + // 3.4.2 MSB+LSB var header = msgid.hlBytes - //3.4.2.1 PUBACK Reason Code + // 3.4.2.1 PUBACK Reason Code header += [reasonCode!.rawValue] - //MQTT 5.0 + // MQTT 5.0 header += beVariableByteInteger(length: self.properties().count) - + return header } - + func payload5() -> [UInt8] { return [] } func properties() -> [UInt8] { - var properties = [UInt8]() - //3.4.2.2.2 Reason String + // 3.4.2.2.2 Reason String if let reasonString = self.reasonString { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength) } - //3.4.2.2.3 User Property + // 3.4.2.2.3 User Property if let userProperty = self.userProperties { for (key, value) in userProperty { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.userProperty.rawValue, value: key.bytesWithLength + value.bytesWithLength) } } - return properties; + return properties } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -103,23 +97,22 @@ extension FramePubAck { } extension FramePubAck: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { guard packetFixedHeaderType == FrameType.puback.rawValue else { return nil } - - //MQTT 5.0 bytes.count == 4 + + // MQTT 5.0 bytes.count == 4 guard bytes.count >= 2 else { return nil } - if bytes.count > 2{ + if bytes.count > 2 { self.reasonCode = CocoaMQTTPUBACKReasonCode(rawValue: bytes[2]) self.pubAckProperties = MqttDecodePubAck() self.pubAckProperties!.decodePubAck(fixedHeader: packetFixedHeaderType, pubAckData: bytes) } - + msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1]) } } diff --git a/Source/FramePubComp.swift b/Source/FramePubComp.swift index 5cd26852..112f86e6 100644 --- a/Source/FramePubComp.swift +++ b/Source/FramePubComp.swift @@ -11,84 +11,77 @@ import Foundation /// ublish complete (QoS 2 delivery part 3) /// The PUBCOMP packet is the response to a PUBREL packet. It is the fourth and final packet of the QoS 2 protocol exchange. struct FramePubComp: Frame { - var packetFixedHeaderType: UInt8 = FrameType.pubcomp.rawValue - + // --- Attributes - + var msgid: UInt16 - - // --- Attributes End + // --- Attributes End - //3.7.2.1 PUBCOMP Reason Code - public var reasonCode: CocoaMQTTPUBCOMPReasonCode? + // 3.7.2.1 PUBCOMP Reason Code + var reasonCode: CocoaMQTTPUBCOMPReasonCode? - //3.7.2.2 PUBCOMP Properties - public var pubCompProperties: MqttDecodePubComp? - //3.7.2.2.2 Reason String - public var reasonString: String? - //3.7.2.2.3 User Property - public var userProperties: [String: String]? + // 3.7.2.2 PUBCOMP Properties + var pubCompProperties: MqttDecodePubComp? + // 3.7.2.2.2 Reason String + var reasonString: String? + // 3.7.2.2.3 User Property + var userProperties: [String: String]? - ///MQTT 3.1.1 + /// MQTT 3.1.1 init(msgid: UInt16) { self.msgid = msgid } - ///MQTT 5.0 - init(msgid: UInt16, reasonCode: CocoaMQTTPUBCOMPReasonCode) { + /// MQTT 5.0 + init(msgid: UInt16, reasonCode: CocoaMQTTPUBCOMPReasonCode) { self.msgid = msgid self.reasonCode = reasonCode } } extension FramePubComp { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.pubcomp.rawValue] return header } - + func variableHeader5() -> [UInt8] { - - //3.7.2 MSB+LSB + // 3.7.2 MSB+LSB var header = msgid.hlBytes - //3.7.2.1 PUBACK Reason Code + // 3.7.2.1 PUBACK Reason Code header += [reasonCode!.rawValue] - //MQTT 5.0 + // MQTT 5.0 header += beVariableByteInteger(length: self.properties().count) - + return header } - + func payload5() -> [UInt8] { return [] } func properties() -> [UInt8] { - var properties = [UInt8]() - //3.7.2.2.2 Reason String + // 3.7.2.2.2 Reason String if let reasonString = self.reasonString { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength) } - //3.7.2.2.3 User Property + // 3.7.2.2.3 User Property if let userProperty = self.userProperties { for (key, value) in userProperty { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.userProperty.rawValue, value: key.bytesWithLength + value.bytesWithLength) } } - return properties; + return properties } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -98,24 +91,22 @@ extension FramePubComp { return allData } - + func variableHeader() -> [UInt8] { return msgid.hlBytes } func payload() -> [UInt8] { return [] } } extension FramePubComp: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { - guard packetFixedHeaderType == FrameType.pubcomp.rawValue else { return nil } - + guard bytes.count >= 2 else { return nil } - + msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1]) self.pubCompProperties = MqttDecodePubComp() diff --git a/Source/FramePubRec.swift b/Source/FramePubRec.swift index ed787a6f..5612f5af 100644 --- a/Source/FramePubRec.swift +++ b/Source/FramePubRec.swift @@ -10,31 +10,30 @@ import Foundation /// MQTT PUBREC packet struct FramePubRec: Frame { - var packetFixedHeaderType: UInt8 = FrameType.pubrec.rawValue - + // --- Attributes - + var msgid: UInt16 - + // --- Attributes End - //3.5.2.1 PUBREC Reason Code - public var reasonCode: CocoaMQTTPUBRECReasonCode? + // 3.5.2.1 PUBREC Reason Code + var reasonCode: CocoaMQTTPUBRECReasonCode? - //3.5.2.2 PUBREC Properties - public var pubRecProperties: MqttDecodePubRec? - //3.5.2.2.2 Reason String - public var reasonString: String? - //3.5.2.2.3 User Property - public var userProperties: [String: String]? + // 3.5.2.2 PUBREC Properties + var pubRecProperties: MqttDecodePubRec? + // 3.5.2.2.2 Reason String + var reasonString: String? + // 3.5.2.2.3 User Property + var userProperties: [String: String]? - ///MQTT 3.1.1 + /// MQTT 3.1.1 init(msgid: UInt16) { self.msgid = msgid } - ///MQTT 5.0 + /// MQTT 5.0 init(msgid: UInt16, reasonCode: CocoaMQTTPUBRECReasonCode) { self.msgid = msgid self.reasonCode = reasonCode @@ -42,52 +41,46 @@ struct FramePubRec: Frame { } extension FramePubRec { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.pubrec.rawValue] return header } - + func variableHeader5() -> [UInt8] { - - //3.5.2 MSB+LSB + // 3.5.2 MSB+LSB var header = msgid.hlBytes - //3.5.2.1 PUBACK Reason Code + // 3.5.2.1 PUBACK Reason Code header += [reasonCode!.rawValue] - //MQTT 5.0 + // MQTT 5.0 header += beVariableByteInteger(length: self.properties().count) - return header } - + func payload5() -> [UInt8] { return [] } func properties() -> [UInt8] { - var properties = [UInt8]() - //3.5.2.2.2 Reason String + // 3.5.2.2.2 Reason String if let reasonString = self.reasonString { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength) } - //3.5.2.2.3 User Property + // 3.5.2.2.3 User Property if let userProperty = self.userProperties { for (key, value) in userProperty { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.userProperty.rawValue, value: key.bytesWithLength + value.bytesWithLength) } } - return properties; + return properties } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -97,26 +90,22 @@ extension FramePubRec { return allData } - + func variableHeader() -> [UInt8] { return msgid.hlBytes } func payload() -> [UInt8] { return [] } } - extension FramePubRec: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { - guard packetFixedHeaderType == FrameType.pubrec.rawValue else { return nil } guard bytes.count >= 2 else { return nil } - - msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1]) + msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1]) self.pubRecProperties = MqttDecodePubRec() self.pubRecProperties!.decodePubRec(fixedHeader: packetFixedHeaderType, pubAckData: bytes) diff --git a/Source/FramePubRel.swift b/Source/FramePubRel.swift index 4e326af4..c591743a 100644 --- a/Source/FramePubRel.swift +++ b/Source/FramePubRel.swift @@ -11,80 +11,71 @@ import Foundation /// MQTT PUBREL packet /// A PUBREL packet is the response to a PUBREC packet. It is the third packet of the QoS 2 protocol exchange. struct FramePubRel: Frame { - - var packetFixedHeaderType: UInt8 = UInt8(FrameType.pubrel.rawValue + 2) - + var packetFixedHeaderType = UInt8(FrameType.pubrel.rawValue + 2) + // --- Attributes - - var msgid: UInt16 - - // --- Attributes End + var msgid: UInt16 - //3.6.2.1 PUBREL Reason Code - public var reasonCode: CocoaMQTTPUBRELReasonCode = .success + // --- Attributes End + // 3.6.2.1 PUBREL Reason Code + var reasonCode: CocoaMQTTPUBRELReasonCode = .success - //3.6.2.2 PUBREL Properties - public var pubRelProperties: MqttDecodePubRel? - //3.6.2.2.2 Reason String - public var reasonString: String? - //3.6.2.2.3 User Property - public var userProperties: [String: String]? + // 3.6.2.2 PUBREL Properties + var pubRelProperties: MqttDecodePubRel? + // 3.6.2.2.2 Reason String + var reasonString: String? + // 3.6.2.2.3 User Property + var userProperties: [String: String]? init(msgid: UInt16) { self.msgid = msgid - + qos = .qos1 } } extension FramePubRel { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.pubrel.rawValue] return header } - + func variableHeader5() -> [UInt8] { - - //3.6.2 MSB+LSB + // 3.6.2 MSB+LSB var header = msgid.hlBytes - //3.6.2.1 PUBACK Reason Code + // 3.6.2.1 PUBACK Reason Code header += [reasonCode.rawValue] - //MQTT 5.0 + // MQTT 5.0 header += beVariableByteInteger(length: self.properties().count) - return header } - + func payload5() -> [UInt8] { return [] } - + func properties() -> [UInt8] { - var properties = [UInt8]() - //3.6.2.2.2 Reason String + // 3.6.2.2.2 Reason String if let reasonString = self.reasonString { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength) } - //3.6.2.2.3 User Property + // 3.6.2.2.3 User Property if let userProperty = self.userProperties { for (key, value) in userProperty { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.userProperty.rawValue, value: key.bytesWithLength + value.bytesWithLength) } } - return properties; + return properties } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -94,14 +85,13 @@ extension FramePubRel { return allData } - + func variableHeader() -> [UInt8] { return msgid.hlBytes } func payload() -> [UInt8] { return [] } } extension FramePubRel: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { guard packetFixedHeaderType == 0x62 else { return nil @@ -109,11 +99,10 @@ extension FramePubRel: InitialWithBytes { guard bytes.count >= 2 else { return nil } - + self.packetFixedHeaderType = packetFixedHeaderType msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1]) - self.pubRelProperties = MqttDecodePubRel() self.pubRelProperties!.decodePubRel(fixedHeader: packetFixedHeaderType, pubAckData: bytes) } diff --git a/Source/FramePublish.swift b/Source/FramePublish.swift index d5c99bae..59b91f01 100644 --- a/Source/FramePublish.swift +++ b/Source/FramePublish.swift @@ -10,36 +10,34 @@ import Foundation // MQTT PUBLISH Frame struct FramePublish: Frame { + // 3.3.1.4 Remaining Length + var remainingLength: UInt32? - //3.3.1.4 Remaining Length - public var remainingLength: UInt32? + // 3.3.2.1 Topic Name + var topicName: String? + // 3.3.2.2 Packet Identifier + var packetIdentifier: UInt16? - //3.3.2.1 Topic Name - public var topicName: String? - //3.3.2.2 Packet Identifier - public var packetIdentifier: UInt16? - - //3.3.2.3 PUBLISH Properties - public var publishProperties: MqttPublishProperties? - public var publishRecProperties: MqttDecodePublish? + // 3.3.2.3 PUBLISH Properties + var publishProperties: MqttPublishProperties? + var publishRecProperties: MqttDecodePublish? var packetFixedHeaderType: UInt8 = FrameType.publish.rawValue - + // --- Attributes - + var msgid: UInt16 - - var topic: String = ""; - - var _payload: [UInt8] = [] - var mqtt5Topic: String = ""; + var topic: String = "" + // swiftlint:disable:next identifier_name + var _payload: [UInt8] = [] + + var mqtt5Topic: String = "" // --- Attributes End - - init(topic: String, payload: [UInt8], qos: CocoaMQTTQoS = .qos0, msgid: UInt16 = 0){ - + + init(topic: String, payload: [UInt8], qos: CocoaMQTTQoS = .qos0, msgid: UInt16 = 0) { self.topic = topic self._payload = payload self.msgid = msgid @@ -48,43 +46,37 @@ struct FramePublish: Frame { } extension FramePublish { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.publish.rawValue] return header } - - func variableHeader5() -> [UInt8] { - //3.3.2.1 Topic Name + func variableHeader5() -> [UInt8] { + // 3.3.2.1 Topic Name var header = self.topic.bytesWithLength - //3.3.2.2 Packet Identifier qos1 or qos2 + // 3.3.2.2 Packet Identifier qos1 or qos2 if qos > .qos0 { header += msgid.hlBytes // header.append(UInt8(0)) // header.append(QoS.rawValue) } - //MQTT 5.0 + // MQTT 5.0 header += beVariableByteInteger(length: self.properties().count) - return header } - + func payload5() -> [UInt8] { return _payload } func properties() -> [UInt8] { - // Properties return publishProperties?.properties ?? [] } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -96,7 +88,6 @@ extension FramePublish { } func variableHeader() -> [UInt8] { - var header = topic.bytesWithLength if qos > .qos0 { @@ -110,9 +101,7 @@ extension FramePublish { } extension FramePublish: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { - guard packetFixedHeaderType & 0xF0 == FrameType.publish.rawValue else { return nil } @@ -150,8 +139,8 @@ extension FramePublish: InitialWithBytes { } self.packetFixedHeaderType = flags - /// Packet Identifier - /// The Packet Identifier field is only present in PUBLISH packets where the QoS level is 1 or 2. + // Packet Identifier + // The Packet Identifier field is only present in PUBLISH packets where the QoS level is 1 or 2. // parse topic if bytes.count < 2 { @@ -160,7 +149,7 @@ extension FramePublish: InitialWithBytes { let len = UInt16(bytes[0]) << 8 + UInt16(bytes[1]) - //2 is packetFixedHeaderType length + // 2 is packetFixedHeaderType length var pos = 2 + Int(len) if bytes.count < pos { @@ -174,22 +163,21 @@ extension FramePublish: InitialWithBytes { if bytes.count < pos + 2 { return nil } - msgid = UInt16(bytes[pos]) << 8 + UInt16(bytes[pos+1]) + msgid = UInt16(bytes[pos]) << 8 + UInt16(bytes[pos + 1]) pos += 2 } - - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { let data = MqttDecodePublish() - data.decodePublish(fixedHeader: packetFixedHeaderType ,publishData: bytes) + data.decodePublish(fixedHeader: packetFixedHeaderType, publishData: bytes) pos += 1 - if(data.propertyLength != 0){ + if data.propertyLength != 0 { pos += data.propertyLength! } @@ -197,21 +185,19 @@ extension FramePublish: InitialWithBytes { self.mqtt5Topic = data.topic self.packetIdentifier = data.packetIdentifier self.publishRecProperties = data - - }else{ + } else { // MQTT 3.1.1 - topic = NSString(bytes: [UInt8](bytes[2...(pos-1)]), length: Int(len), encoding: String.Encoding.utf8.rawValue)! as String + topic = NSString(bytes: [UInt8](bytes[2...(pos - 1)]), length: Int(len), encoding: String.Encoding.utf8.rawValue)! as String } // payload - if (pos == bytes.count) { + if pos == bytes.count { _payload = [] - } else if (pos < bytes.count) { + } else if pos < bytes.count { _payload = [UInt8](bytes[pos.. [UInt8] { - var header = [UInt8]() header += [FrameType.suback.rawValue] return header } - + func variableHeader5() -> [UInt8] { return msgid.hlBytes } - + func payload5() -> [UInt8] { - var payload = [UInt8]() - + for qos in grantedQos { payload.append(qos.rawValue) } - + return payload } - + func properties() -> [UInt8] { return [] } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -75,11 +68,10 @@ extension FrameSubAck { return allData } - + func variableHeader() -> [UInt8] { return msgid.hlBytes } func payload() -> [UInt8] { - var payload = [UInt8]() for qos in grantedQos { @@ -91,17 +83,15 @@ extension FrameSubAck { } extension FrameSubAck: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { - self.packetFixedHeaderType = packetFixedHeaderType - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { // the bytes length must bigger than 3 guard bytes.count >= 4 else { return nil @@ -126,8 +116,7 @@ extension FrameSubAck: InitialWithBytes { self.subAckProperties = MqttDecodeSubAck() self.subAckProperties!.decodeSubAck(fixedHeader: packetFixedHeaderType, pubAckData: bytes) - - }else{ + } else { // the bytes length must bigger than 3 guard bytes.count >= 3 else { return nil @@ -141,9 +130,7 @@ extension FrameSubAck: InitialWithBytes { } self.grantedQos.append(qos) } - } - } } diff --git a/Source/FrameSubscribe.swift b/Source/FrameSubscribe.swift index c4f02234..b1e74542 100644 --- a/Source/FrameSubscribe.swift +++ b/Source/FrameSubscribe.swift @@ -10,31 +10,29 @@ import Foundation /// MQTT SUBSCRIBE Frame struct FrameSubscribe: Frame { - - var packetFixedHeaderType: UInt8 = UInt8(FrameType.subscribe.rawValue + 2) - + var packetFixedHeaderType = UInt8(FrameType.subscribe.rawValue + 2) + // --- Attributes - + var msgid: UInt16? - + var topics: [(String, CocoaMQTTQoS)]? - - // --- Attributes End + // --- Attributes End - //3.8.2 SUBSCRIBE Variable Header - public var packetIdentifier: UInt16? + // 3.8.2 SUBSCRIBE Variable Header + var packetIdentifier: UInt16? - //3.8.2.1.2 Subscription Identifier - public var subscriptionIdentifier: UInt32? + // 3.8.2.1.2 Subscription Identifier + var subscriptionIdentifier: UInt32? - //3.8.2.1.3 User Property - public var userProperty: [String: String]? + // 3.8.2.1.3 User Property + var userProperty: [String: String]? - //3.8.3 SUBSCRIBE Payload - public var topicFilters: [MqttSubscription]? + // 3.8.3 SUBSCRIBE Payload + var topicFilters: [MqttSubscription]? - ///MQTT 3.1.1 + /// MQTT 3.1.1 init(msgid: UInt16, topic: String, reqos: CocoaMQTTQoS) { self.init(msgid: msgid, topics: [(topic, reqos)]) } @@ -47,40 +45,34 @@ struct FrameSubscribe: Frame { qos = CocoaMQTTQoS.qos1 } - ///MQTT 5.0 + /// MQTT 5.0 init(msgid: UInt16, subscriptionList: [MqttSubscription]) { self.msgid = msgid self.topicFilters = subscriptionList } - } extension FrameSubscribe { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.subscribe.rawValue] return header } - - func variableHeader5() -> [UInt8] { - - //3.8.2 SUBSCRIBE Variable Header - //The Variable Header of the SUBSCRIBE Packet contains the following fields in the order: Packet Identifier, and Properties. + func variableHeader5() -> [UInt8] { + // 3.8.2 SUBSCRIBE Variable Header + // The Variable Header of the SUBSCRIBE Packet contains the following fields in the order: Packet Identifier, and Properties. - //MQTT 5.0 + // MQTT 5.0 var header = [UInt8]() header = msgid!.hlBytes header += beVariableByteInteger(length: self.properties().count) return header } - + func payload5() -> [UInt8] { - var payload = [UInt8]() for subscription in self.topicFilters! { @@ -92,15 +84,14 @@ extension FrameSubscribe { } func properties() -> [UInt8] { - var properties = [UInt8]() - //3.8.2.1.2 Subscription Identifier + // 3.8.2.1.2 Subscription Identifier if let subscriptionIdentifier = self.subscriptionIdentifier { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.subscriptionIdentifier.rawValue, value: subscriptionIdentifier.byteArrayLittleEndian) } - //3.8.2.1.3 User Property + // 3.8.2.1.3 User Property if let userProperty = self.userProperty { let dictValues = [String](userProperty.values) for (value) in dictValues { @@ -109,11 +100,9 @@ extension FrameSubscribe { } return properties - } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -123,11 +112,10 @@ extension FrameSubscribe { return allData } - + func variableHeader() -> [UInt8] { return msgid!.hlBytes } func payload() -> [UInt8] { - var payload = [UInt8]() for (topic, qos) in topics! { @@ -140,14 +128,13 @@ extension FrameSubscribe { } extension FrameSubscribe: CustomStringConvertible { - var description: String { - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { var desc = "" if let unwrappedList = topicFilters, !unwrappedList.isEmpty { for subscription in unwrappedList { @@ -155,7 +142,7 @@ extension FrameSubscribe: CustomStringConvertible { } } return desc - }else{ + } else { return "SUBSCRIBE(id: \(String(describing: msgid)), topics: \(String(describing: topics)))" } } diff --git a/Source/FrameUnsubAck.swift b/Source/FrameUnsubAck.swift index e3d60f4f..a6a722aa 100644 --- a/Source/FrameUnsubAck.swift +++ b/Source/FrameUnsubAck.swift @@ -8,25 +8,24 @@ import Foundation - /// MQTT UNSUBACK packet struct FrameUnsubAck: Frame { - var packetFixedHeaderType: UInt8 = FrameType.unsuback.rawValue // --- Attributes - + var msgid: UInt16 - + // --- Attributes End - //3.10.2.1 UNSUBSCRIBE Properties - public var unSubAckProperties: MqttDecodeUnsubAck? - //3.11.2 Property - public var userProperty: [String: String]? - //3.11.2.1.2 Reason String - public var reasonString: String? + // 3.10.2.1 UNSUBSCRIBE Properties + var unSubAckProperties: MqttDecodeUnsubAck? + // 3.11.2 Property + var userProperty: [String: String]? + // 3.11.2.1.2 Reason String + var reasonString: String? + // swiftlint:disable:next identifier_name var _payload: [UInt8] = [] init(msgid: UInt16, payload: [UInt8]) { @@ -36,38 +35,34 @@ struct FrameUnsubAck: Frame { } extension FrameUnsubAck { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.unsuback.rawValue] return header } - + func variableHeader5() -> [UInt8] { - - //3.11.2 MSB+LSB + // 3.11.2 MSB+LSB var header = msgid.hlBytes - //MQTT 5.0 + // MQTT 5.0 header += beVariableByteInteger(length: self.properties().count) return header } - + func payload5() -> [UInt8] { return _payload } func properties() -> [UInt8] { - var properties = [UInt8]() - //3.11.2.1.2 Reason String + // 3.11.2.1.2 Reason String if let reasonString = self.reasonString { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength) } - //3.11.2.1.3 User Property + // 3.11.2.1.3 User Property if let userProperty = self.userProperty { let dictValues = [String](userProperty.values) for (value) in dictValues { @@ -75,11 +70,10 @@ extension FrameUnsubAck { } } - return properties; + return properties } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -95,14 +89,12 @@ extension FrameUnsubAck { func payload() -> [UInt8] { return [] } } - extension FrameUnsubAck: InitialWithBytes { - init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) { guard packetFixedHeaderType == FrameType.unsuback.rawValue else { return nil } - + guard bytes.count >= 2 else { return nil } @@ -111,7 +103,6 @@ extension FrameUnsubAck: InitialWithBytes { self.unSubAckProperties = MqttDecodeUnsubAck() self.unSubAckProperties!.decodeUnSubAck(fixedHeader: packetFixedHeaderType, pubAckData: bytes) - } } diff --git a/Source/FrameUnsubscribe.swift b/Source/FrameUnsubscribe.swift index c250990e..8783c276 100644 --- a/Source/FrameUnsubscribe.swift +++ b/Source/FrameUnsubscribe.swift @@ -10,26 +10,24 @@ import Foundation /// MQTT UNSUBSCRIBE packet struct FrameUnsubscribe: Frame { - - var packetFixedHeaderType: UInt8 = UInt8(FrameType.unsubscribe.rawValue + 2) - + var packetFixedHeaderType = UInt8(FrameType.unsubscribe.rawValue + 2) + // --- Attributes - + var msgid: UInt16? - ///MQTT 3.1.1 + /// MQTT 3.1.1 var topics: [String]? - ///MQTT 5.0 + /// MQTT 5.0 var topicFilters: [MqttSubscription]? - + // --- Attribetes end - //3.10.2.1.2 User Property - public var userProperty: [String: String]? + // 3.10.2.1.2 User Property + var userProperty: [String: String]? - - ///MQTT 3.1.1 + /// MQTT 3.1.1 init(msgid: UInt16, topics: [String]) { self.msgid = msgid self.topics = topics @@ -37,40 +35,34 @@ struct FrameUnsubscribe: Frame { qos = CocoaMQTTQoS.qos1 } - ///MQTT 5.0 + /// MQTT 5.0 init(msgid: UInt16, topics: [MqttSubscription]) { self.msgid = msgid self.topicFilters = topics qos = CocoaMQTTQoS.qos1 } - - } extension FrameUnsubscribe { - func fixedHeader() -> [UInt8] { - var header = [UInt8]() header += [FrameType.unsubscribe.rawValue] return header } - + func variableHeader5() -> [UInt8] { - - //MQTT 5.0 + // MQTT 5.0 var header = [UInt8]() header = msgid!.hlBytes header += beVariableByteInteger(length: self.properties().count) return header } - + func payload5() -> [UInt8] { - var payload = [UInt8]() - + for subscription in topicFilters! { subscription.subscriptionOptions = false payload += subscription.subscriptionData @@ -79,9 +71,7 @@ extension FrameUnsubscribe { return payload } - func properties() -> [UInt8] { - var properties = [UInt8]() // 3.10.2.1.2 User Property @@ -96,7 +86,6 @@ extension FrameUnsubscribe { } func allData() -> [UInt8] { - var allData = [UInt8]() allData += fixedHeader() @@ -110,7 +99,6 @@ extension FrameUnsubscribe { func variableHeader() -> [UInt8] { return msgid!.hlBytes } func payload() -> [UInt8] { - var payload = [UInt8]() for t in topics! { @@ -119,18 +107,16 @@ extension FrameUnsubscribe { return payload } - } extension FrameUnsubscribe: CustomStringConvertible { - var description: String { - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { var desc = "" if let unwrappedList = topicFilters, !unwrappedList.isEmpty { for subscription in unwrappedList { @@ -138,7 +124,7 @@ extension FrameUnsubscribe: CustomStringConvertible { } } return desc - }else{ + } else { return "UNSUBSCRIBE(id: \(String(describing: msgid)), topics: \(String(describing: topics)))" } } diff --git a/Source/MqttAuthProperties.swift b/Source/MqttAuthProperties.swift index 3969f164..a704bec6 100644 --- a/Source/MqttAuthProperties.swift +++ b/Source/MqttAuthProperties.swift @@ -8,41 +8,37 @@ import Foundation public class MqttAuthProperties: NSObject { - - - //3.15.2.2.2 Authentication Method + // 3.15.2.2.2 Authentication Method public var authenticationMethod: String? - //3.15.2.2.3 Authentication Data + // 3.15.2.2.3 Authentication Data public var authenticationData: [UInt8]? - //3.15.2.2.4 Reason String + // 3.15.2.2.4 Reason String public var reasonString: String? - //3.15.2.2.5 User Property + // 3.15.2.2.5 User Property public var userProperties: [String: String]? public var properties: [UInt8] { var properties = [UInt8]() - //3.15.2.2.2 Authentication Method + // 3.15.2.2.2 Authentication Method if let authenticationMethod = self.authenticationMethod { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.authenticationMethod.rawValue, value: authenticationMethod.bytesWithLength) } - //3.15.2.2.3 Authentication Data + // 3.15.2.2.3 Authentication Data if let authenticationData = self.authenticationData { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.authenticationData.rawValue, value: authenticationData) } - //3.15.2.2.4 Reason String + // 3.15.2.2.4 Reason String if let reasonString = self.reasonString { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength) } - //3.15.2.2.5 User Property + // 3.15.2.2.5 User Property if let userProperty = self.userProperties { for (key, value) in userProperty { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.userProperty.rawValue, value: key.bytesWithLength + value.bytesWithLength) } } - - + return properties } - } diff --git a/Source/MqttConnectProperties.swift b/Source/MqttConnectProperties.swift index bb08c494..ab65d2c7 100644 --- a/Source/MqttConnectProperties.swift +++ b/Source/MqttConnectProperties.swift @@ -8,33 +8,31 @@ import Foundation public class MqttConnectProperties: NSObject { - - - //3.1.2.11.1 Property Length - //public var propertyLength: UInt8? - //3.1.2.11.2 Session Expiry Interval + // 3.1.2.11.1 Property Length + // public var propertyLength: UInt8? + // 3.1.2.11.2 Session Expiry Interval public var sessionExpiryInterval: UInt32? - //3.1.2.11.3 Receive Maximum + // 3.1.2.11.3 Receive Maximum public var receiveMaximum: UInt16? - //3.1.2.11.4 Maximum Packet Size + // 3.1.2.11.4 Maximum Packet Size public var maximumPacketSize: UInt32? - //3.1.2.11.5 Topic Alias Maximum + // 3.1.2.11.5 Topic Alias Maximum public var topicAliasMaximum: UInt16? - //3.1.2.11.6 Request Response Information + // 3.1.2.11.6 Request Response Information public var requestResponseInformation: UInt8? - //3.1.2.11.7 Request Problem Information + // 3.1.2.11.7 Request Problem Information public var requestProblemInfomation: UInt8? - //3.1.2.11.8 User Property + // 3.1.2.11.8 User Property public var userProperties: [String: String]? - //3.1.2.11.9 Authentication Method + // 3.1.2.11.9 Authentication Method public var authenticationMethod: String? - //3.1.2.11.10 Authentication Data + // 3.1.2.11.10 Authentication Data public var authenticationData: [UInt8]? public var properties: [UInt8] { var properties = [UInt8]() - //3.1.2.11.2 Session Expiry Interval + // 3.1.2.11.2 Session Expiry Interval if let sessionExpiryInterval = self.sessionExpiryInterval { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.sessionExpiryInterval.rawValue, value: sessionExpiryInterval.byteArrayLittleEndian) } @@ -77,10 +75,6 @@ public class MqttConnectProperties: NSObject { properties += authenticationData } - return properties } - - - } diff --git a/Source/MqttDecodeConnAck.swift b/Source/MqttDecodeConnAck.swift index 443e1ffe..68d26e71 100644 --- a/Source/MqttDecodeConnAck.swift +++ b/Source/MqttDecodeConnAck.swift @@ -8,67 +8,64 @@ import Foundation public class MqttDecodeConnAck: NSObject { - // var connackData: [UInt8] // // init(connackData: [UInt8]) { // connackData = connackData // } - //3.2.2.3 CONNACK Properties - //3.2.2.3.1 Property Length + // 3.2.2.3 CONNACK Properties + // 3.2.2.3.1 Property Length public var propertyLength: Int? - //3.2.2.3.2 Session Expiry Interval + // 3.2.2.3.2 Session Expiry Interval public var sessionExpiryInterval: UInt32? - //3.2.2.3.3 Receive Maximum + // 3.2.2.3.3 Receive Maximum public var receiveMaximum: UInt16? - //3.2.2.3.4 Maximum QoS + // 3.2.2.3.4 Maximum QoS public var maximumQoS: CocoaMQTTQoS? - //3.2.2.3.5 Retain Available + // 3.2.2.3.5 Retain Available public var retainAvailable: Bool? - //3.2.2.3.6 Maximum Packet Size + // 3.2.2.3.6 Maximum Packet Size public var maximumPacketSize: UInt32? - //3.2.2.3.7 Assigned Client Identifier + // 3.2.2.3.7 Assigned Client Identifier public var assignedClientIdentifier: String? - //3.2.2.3.8 Topic Alias Maximum + // 3.2.2.3.8 Topic Alias Maximum public var topicAliasMaximum: UInt16? - //3.2.2.3.9 Reason String + // 3.2.2.3.9 Reason String public var reasonString: String? - //3.2.2.3.10 User Property + // 3.2.2.3.10 User Property public var userProperty: [String: String]? - //3.2.2.3.11 Wildcard Subscription Available + // 3.2.2.3.11 Wildcard Subscription Available public var wildcardSubscriptionAvailable: Bool? - //3.2.2.3.12 Subscription Identifiers Available + // 3.2.2.3.12 Subscription Identifiers Available public var subscriptionIdentifiersAvailable: Bool? - //3.2.2.3.13 Shared Subscription Available + // 3.2.2.3.13 Shared Subscription Available public var sharedSubscriptionAvailable: Bool? - //3.2.2.3.14 Server Keep Alive + // 3.2.2.3.14 Server Keep Alive public var serverKeepAlive: UInt16? - //3.2.2.3.15 Response Information + // 3.2.2.3.15 Response Information public var responseInformation: String? - //3.2.2.3.16 Server Reference + // 3.2.2.3.16 Server Reference public var serverReference: String? - //3.2.2.3.17 Authentication Method + // 3.2.2.3.17 Authentication Method public var authenticationMethod: String? - //3.2.2.3.18 Authentication Data + // 3.2.2.3.18 Authentication Data public var authenticationData = [UInt8]() - - - public func properties(connackData: [UInt8]){ - //3.2.2.3 CONNACK Properties - var index = 2 //sessPresent 0 reasonCode 1 + public func properties(connackData: [UInt8]) { + // 3.2.2.3 CONNACK Properties + var index = 2 // sessPresent 0 reasonCode 1 let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: connackData, offset: index) propertyLength = propertyLengthVariableByteInteger.res index = propertyLengthVariableByteInteger.newOffset let occupyIndex = index - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { // properties while index - occupyIndex < propertyLength! { let resVariableByteInteger = decodeVariableByteInteger(data: connackData, offset: index) @@ -79,16 +76,15 @@ public class MqttDecodeConnAck: NSObject { } switch propertyName.rawValue { - case CocoaMQTTPropertyName.sessionExpiryInterval.rawValue: - let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint32.rawValue, offset: index) + let comRes = integerCompute(data: connackData, formatType: FormatInt.formatUint32.rawValue, offset: index) sessionExpiryInterval = UInt32(comRes!.res) index = comRes!.newOffset case CocoaMQTTPropertyName.receiveMaximum.rawValue: - let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint16.rawValue, offset: index) + let comRes = integerCompute(data: connackData, formatType: FormatInt.formatUint16.rawValue, offset: index) receiveMaximum = UInt16(comRes!.res) index = comRes!.newOffset @@ -105,7 +101,7 @@ public class MqttDecodeConnAck: NSObject { index += 1 case CocoaMQTTPropertyName.retainAvailable.rawValue: - if index > connackData.count { + if index > connackData.count { break } if connackData[index] & 0x01 > 0 { @@ -118,7 +114,7 @@ public class MqttDecodeConnAck: NSObject { case CocoaMQTTPropertyName.maximumPacketSize.rawValue: - let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint32.rawValue, offset: index) + let comRes = integerCompute(data: connackData, formatType: FormatInt.formatUint32.rawValue, offset: index) maximumPacketSize = UInt32(comRes!.res) index = comRes!.newOffset @@ -131,7 +127,7 @@ public class MqttDecodeConnAck: NSObject { case CocoaMQTTPropertyName.topicAliasMaximum.rawValue: - let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint16.rawValue, offset: index) + let comRes = integerCompute(data: connackData, formatType: FormatInt.formatUint16.rawValue, offset: index) topicAliasMaximum = UInt16(comRes!.res) index = comRes!.newOffset @@ -143,8 +139,8 @@ public class MqttDecodeConnAck: NSObject { index = result.newOffset case CocoaMQTTPropertyName.userProperty.rawValue: - var key:String? - var value:String? + var key: String? + var value: String? guard let keyRes = unsignedByteToString(data: connackData, offset: index) else { break } @@ -160,7 +156,7 @@ public class MqttDecodeConnAck: NSObject { userProperty![key!] = value case CocoaMQTTPropertyName.wildcardSubscriptionAvailable.rawValue: - if index > connackData.count { + if index > connackData.count { break } if connackData[index] & 0x01 > 0 { @@ -171,7 +167,7 @@ public class MqttDecodeConnAck: NSObject { index += 1 case CocoaMQTTPropertyName.subscriptionIdentifiersAvailable.rawValue: - if index > connackData.count { + if index > connackData.count { break } if connackData[index] & 0x01 > 0 { @@ -182,7 +178,7 @@ public class MqttDecodeConnAck: NSObject { index += 1 case CocoaMQTTPropertyName.sharedSubscriptionAvailable.rawValue: - if index > connackData.count { + if index > connackData.count { break } if connackData[index] & 0x01 > 0 { @@ -194,7 +190,7 @@ public class MqttDecodeConnAck: NSObject { case CocoaMQTTPropertyName.serverKeepAlive.rawValue: - let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint16.rawValue, offset: index) + let comRes = integerCompute(data: connackData, formatType: FormatInt.formatUint16.rawValue, offset: index) serverKeepAlive = UInt16(comRes!.res) index = comRes!.newOffset @@ -226,16 +222,10 @@ public class MqttDecodeConnAck: NSObject { authenticationData = valRes.resStr index = valRes.newOffset - default: break } - - } - } - } - } diff --git a/Source/MqttDecodePubAck.swift b/Source/MqttDecodePubAck.swift index fcfd81d7..00958c66 100644 --- a/Source/MqttDecodePubAck.swift +++ b/Source/MqttDecodePubAck.swift @@ -8,7 +8,6 @@ import Foundation public class MqttDecodePubAck: NSObject { - var totalCount = 0 var dataIndex = 0 var propertyLength: Int = 0 @@ -18,21 +17,18 @@ public class MqttDecodePubAck: NSObject { public var reasonString: String? public var userProperty: [String: String]? - - - - - public func decodePubAck(fixedHeader: UInt8, pubAckData: [UInt8]){ + public func decodePubAck(fixedHeader: UInt8, pubAckData: [UInt8]) { totalCount = pubAckData.count dataIndex = 0 - //msgid - let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex) + // msgid + let msgidResult = integerCompute(data: pubAckData, formatType: FormatInt.formatUint16.rawValue, offset: dataIndex) msgid = UInt16(msgidResult!.res) dataIndex = msgidResult!.newOffset // 3.4.2.1 PUBACK Reason Code - // The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) and there are no Properties. In this case the PUBACK has a Remaining Length of 2. + // The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) + // and there are no Properties. In this case the PUBACK has a Remaining Length of 2. if dataIndex + 1 > pubAckData.count { return } @@ -43,12 +39,12 @@ public class MqttDecodePubAck: NSObject { reasonCode = ack dataIndex += 1 - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { // 3.4.2.2 PUBACK Properties // 3.4.2.2.1 Property Length let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) @@ -58,7 +54,6 @@ public class MqttDecodePubAck: NSObject { let occupyIndex = dataIndex while dataIndex < occupyIndex + propertyLength { - let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) dataIndex = resVariableByteInteger.newOffset let propertyNameByte = resVariableByteInteger.res @@ -77,8 +72,8 @@ public class MqttDecodePubAck: NSObject { // 3.4.2.2.3 User Property case CocoaMQTTPropertyName.userProperty.rawValue: - var key:String? - var value:String? + var key: String? + var value: String? guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else { break } @@ -93,14 +88,10 @@ public class MqttDecodePubAck: NSObject { userProperty![key!] = value - default: return } - } - } - } } diff --git a/Source/MqttDecodePubComp.swift b/Source/MqttDecodePubComp.swift index 2e969e54..ee3aa7d3 100644 --- a/Source/MqttDecodePubComp.swift +++ b/Source/MqttDecodePubComp.swift @@ -8,7 +8,6 @@ import Foundation public class MqttDecodePubComp: NSObject { - var totalCount = 0 var dataIndex = 0 var propertyLength: Int = 0 @@ -18,19 +17,18 @@ public class MqttDecodePubComp: NSObject { public var reasonString: String? public var userProperty: [String: String]? - - - public func decodePubComp(fixedHeader: UInt8, pubAckData: [UInt8]){ + public func decodePubComp(fixedHeader: UInt8, pubAckData: [UInt8]) { totalCount = pubAckData.count dataIndex = 0 - //msgid - let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex) + // msgid + let msgidResult = integerCompute(data: pubAckData, formatType: FormatInt.formatUint16.rawValue, offset: dataIndex) msgid = UInt16(msgidResult!.res) dataIndex = msgidResult!.newOffset // 3.6.2.1 PUBREL Reason Code - //The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) and there are no Properties. In this case the PUBACK has a Remaining Length of 2. + // The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) + // and there are no Properties. In this case the PUBACK has a Remaining Length of 2. if dataIndex + 1 > pubAckData.count { return } @@ -41,12 +39,12 @@ public class MqttDecodePubComp: NSObject { reasonCode = ack dataIndex += 1 - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { // 3.6.2.2 PUBREL Properties // 3.6.2.2.1 Property Length let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) @@ -56,7 +54,6 @@ public class MqttDecodePubComp: NSObject { let occupyIndex = dataIndex while dataIndex < occupyIndex + propertyLength { - let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) dataIndex = resVariableByteInteger.newOffset let propertyNameByte = resVariableByteInteger.res @@ -74,8 +71,8 @@ public class MqttDecodePubComp: NSObject { dataIndex = result.newOffset // 3.6.2.2.3 User Property - var key:String? - var value:String? + var key: String? + var value: String? guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else { break } @@ -90,15 +87,10 @@ public class MqttDecodePubComp: NSObject { userProperty![key!] = value - default: return } - } - } - } - } diff --git a/Source/MqttDecodePubRec.swift b/Source/MqttDecodePubRec.swift index ccaf7d85..76dad3cb 100644 --- a/Source/MqttDecodePubRec.swift +++ b/Source/MqttDecodePubRec.swift @@ -8,7 +8,6 @@ import Foundation public class MqttDecodePubRec: NSObject { - var totalCount = 0 var dataIndex = 0 var propertyLength: Int = 0 @@ -18,19 +17,18 @@ public class MqttDecodePubRec: NSObject { public var reasonString: String? public var userProperty: [String: String]? - - - public func decodePubRec(fixedHeader: UInt8, pubAckData: [UInt8]){ + public func decodePubRec(fixedHeader: UInt8, pubAckData: [UInt8]) { totalCount = pubAckData.count - dataIndex = 0; - //msgid - let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex) + dataIndex = 0 + // msgid + let msgidResult = integerCompute(data: pubAckData, formatType: FormatInt.formatUint16.rawValue, offset: dataIndex) msgid = UInt16(msgidResult!.res) dataIndex = msgidResult!.newOffset // 3.5.2.1 PUBREC Reason Code - //The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) and there are no Properties. In this case the PUBACK has a Remaining Length of 2. + // The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) + // and there are no Properties. In this case the PUBACK has a Remaining Length of 2. if dataIndex + 1 > pubAckData.count { return } @@ -41,12 +39,12 @@ public class MqttDecodePubRec: NSObject { reasonCode = ack dataIndex += 1 - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { // 3.5.2.2 PUBACK Properties // 3.5.2.2.1 Property Length let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) @@ -56,7 +54,6 @@ public class MqttDecodePubRec: NSObject { let occupyIndex = dataIndex while dataIndex < occupyIndex + propertyLength { - let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) dataIndex = resVariableByteInteger.newOffset let propertyNameByte = resVariableByteInteger.res @@ -75,8 +72,8 @@ public class MqttDecodePubRec: NSObject { // 3.5.2.2.3 User Property case CocoaMQTTPropertyName.userProperty.rawValue: - var key:String? - var value:String? + var key: String? + var value: String? guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else { break } @@ -91,13 +88,10 @@ public class MqttDecodePubRec: NSObject { userProperty![key!] = value - default: return } } } - } - } diff --git a/Source/MqttDecodePubRel.swift b/Source/MqttDecodePubRel.swift index f110e139..ca6c830b 100644 --- a/Source/MqttDecodePubRel.swift +++ b/Source/MqttDecodePubRel.swift @@ -8,7 +8,6 @@ import Foundation public class MqttDecodePubRel: NSObject { - var totalCount = 0 var dataIndex = 0 var propertyLength: Int = 0 @@ -18,19 +17,18 @@ public class MqttDecodePubRel: NSObject { public var reasonString: String? public var userProperty: [String: String]? - - - public func decodePubRel(fixedHeader: UInt8, pubAckData: [UInt8]){ + public func decodePubRel(fixedHeader: UInt8, pubAckData: [UInt8]) { totalCount = pubAckData.count dataIndex = 0 - //msgid - let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex) + // msgid + let msgidResult = integerCompute(data: pubAckData, formatType: FormatInt.formatUint16.rawValue, offset: dataIndex) msgid = UInt16(msgidResult!.res) dataIndex = msgidResult!.newOffset // 3.6.2.1 PUBREL Reason Code - //The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) and there are no Properties. In this case the PUBACK has a Remaining Length of 2. + // The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) + // and there are no Properties. In this case the PUBACK has a Remaining Length of 2. if dataIndex + 1 > pubAckData.count { return } @@ -41,12 +39,12 @@ public class MqttDecodePubRel: NSObject { reasonCode = ack dataIndex += 1 - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { // 3.6.2.2 PUBREL Properties // 3.6.2.2.1 Property Length let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) @@ -56,7 +54,6 @@ public class MqttDecodePubRel: NSObject { let occupyIndex = dataIndex while dataIndex < occupyIndex + propertyLength { - let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) dataIndex = resVariableByteInteger.newOffset let propertyNameByte = resVariableByteInteger.res @@ -74,8 +71,8 @@ public class MqttDecodePubRel: NSObject { dataIndex = result.newOffset // 3.6.2.2.3 User Property - var key:String? - var value:String? + var key: String? + var value: String? guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else { break } @@ -90,15 +87,10 @@ public class MqttDecodePubRel: NSObject { userProperty![key!] = value - default: return } - } - } - } - } diff --git a/Source/MqttDecodePublish.swift b/Source/MqttDecodePublish.swift index 0638b409..df730934 100644 --- a/Source/MqttDecodePublish.swift +++ b/Source/MqttDecodePublish.swift @@ -8,37 +8,34 @@ import Foundation public class MqttDecodePublish: NSObject { - - //3.3.2.3 PUBLISH Properties - //3.3.2.3.1 Property Length + // 3.3.2.3 PUBLISH Properties + // 3.3.2.3.1 Property Length public var propertyLength: Int? - //3.3.2.3.2 Payload Format Indicator + // 3.3.2.3.2 Payload Format Indicator public var payloadFormatIndicator: PayloadFormatIndicator? - //3.3.2.3.3 Message Expiry Interval + // 3.3.2.3.3 Message Expiry Interval public var messageExpiryInterval: UInt32? - //3.3.2.3.4 Topic Alias + // 3.3.2.3.4 Topic Alias public var topicAlias: UInt16? - //3.3.2.3.5 Response Topic + // 3.3.2.3.5 Response Topic public var responseTopic: String? - //3.3.2.3.6 Correlation Data + // 3.3.2.3.6 Correlation Data public var correlationData: [UInt8]? - //3.3.2.3.7 Property + // 3.3.2.3.7 Property public var userProperty: [String: String]? - //3.3.2.3.8 Subscription Identifier + // 3.3.2.3.8 Subscription Identifier public var subscriptionIdentifier: Int = 0 - //3.3.2.3.9 Content Type + // 3.3.2.3.9 Content Type public var contentType: String? - //public var applicationMessage: [UInt8]? + // public var applicationMessage: [UInt8]? - //3.3.2.1 Topic Name + // 3.3.2.1 Topic Name public var topic: String = "" - //3.3.2.2 Packet Identifier + // 3.3.2.2 Packet Identifier public var packetIdentifier: UInt16? - - - public func decodePublish(fixedHeader: UInt8, publishData: [UInt8]){ + public func decodePublish(fixedHeader: UInt8, publishData: [UInt8]) { // Topic Name // 3.3.2.1 Topic Name var dataIndex = 0 @@ -57,19 +54,18 @@ public class MqttDecodePublish: NSObject { // 3.3.2.2 Packet Identifier // Packet Identifier if recQos == .qos1 || recQos == .qos2 { - let IdentifierResult = integerCompute(data: publishData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex) - packetIdentifier = UInt16(IdentifierResult!.res) - dataIndex = IdentifierResult!.newOffset + let identifierResult = integerCompute(data: publishData, formatType: FormatInt.formatUint16.rawValue, offset: dataIndex) + packetIdentifier = UInt16(identifierResult!.res) + dataIndex = identifierResult!.newOffset } - - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ - //3.3.2.3.1 Property Length + if protocolVersion == "5.0" { + // 3.3.2.3.1 Property Length // propertyLength let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: publishData, offset: dataIndex) propertyLength = propertyLengthVariableByteInteger.res @@ -78,7 +74,6 @@ public class MqttDecodePublish: NSObject { let occupyIndex = dataIndex while dataIndex < occupyIndex + (propertyLength ?? 0) { - let resVariableByteInteger = decodeVariableByteInteger(data: publishData, offset: dataIndex) dataIndex = resVariableByteInteger.newOffset let propertyNameByte = resVariableByteInteger.res @@ -97,13 +92,13 @@ public class MqttDecodePublish: NSObject { // 3.3.2.3.3 Message Expiry Interval case CocoaMQTTPropertyName.willExpiryInterval.rawValue: - let comRes = integerCompute(data: publishData, formatType: formatInt.formatUint32.rawValue, offset: dataIndex) + let comRes = integerCompute(data: publishData, formatType: FormatInt.formatUint32.rawValue, offset: dataIndex) messageExpiryInterval = UInt32(comRes!.res) dataIndex = comRes!.newOffset // 3.3.2.3.4 Topic Alias case CocoaMQTTPropertyName.topicAlias.rawValue: - let comRes = integerCompute(data: publishData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex) + let comRes = integerCompute(data: publishData, formatType: FormatInt.formatUint16.rawValue, offset: dataIndex) topicAlias = UInt16(comRes!.res) dataIndex = comRes!.newOffset @@ -125,8 +120,8 @@ public class MqttDecodePublish: NSObject { // 3.3.2.3.7 User Property case CocoaMQTTPropertyName.userProperty.rawValue: - var key:String? - var value:String? + var key: String? + var value: String? guard let keyRes = unsignedByteToString(data: publishData, offset: dataIndex) else { break } @@ -138,7 +133,7 @@ public class MqttDecodePublish: NSObject { } value = valRes.resStr dataIndex = valRes.newOffset - + if userProperty == nil { userProperty = [:] } @@ -162,11 +157,7 @@ public class MqttDecodePublish: NSObject { default: return } - } } - } - - } diff --git a/Source/MqttDecodeSubAck.swift b/Source/MqttDecodeSubAck.swift index a40d162c..610595e9 100644 --- a/Source/MqttDecodeSubAck.swift +++ b/Source/MqttDecodeSubAck.swift @@ -8,32 +8,30 @@ import Foundation public class MqttDecodeSubAck: NSObject { - var totalCount = 0 var dataIndex = 0 var propertyLength: Int = 0 public var reasonCodes: [CocoaMQTTSUBACKReasonCode] = [] - //public var reasonCode: CocoaMQTTSUBACKReasonCode? + // public var reasonCode: CocoaMQTTSUBACKReasonCode? public var msgid: UInt16 = 0 public var reasonString: String? public var userProperty: [String: String]? - - public func decodeSubAck(fixedHeader: UInt8, pubAckData: [UInt8]){ + public func decodeSubAck(fixedHeader: UInt8, pubAckData: [UInt8]) { totalCount = pubAckData.count dataIndex = 0 - //msgid - let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex) + // msgid + let msgidResult = integerCompute(data: pubAckData, formatType: FormatInt.formatUint16.rawValue, offset: dataIndex) msgid = UInt16(msgidResult!.res) dataIndex = msgidResult!.newOffset - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { // 3.9.2.1 SUBACK Properties // 3.9.2.1.1 Property Length let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) @@ -49,7 +47,6 @@ public class MqttDecodeSubAck: NSObject { break } - switch propertyName.rawValue { // 3.9.2.1.2 Reason String case CocoaMQTTPropertyName.reasonString.rawValue: @@ -61,8 +58,8 @@ public class MqttDecodeSubAck: NSObject { // 3.9.2.1.3 User Property case CocoaMQTTPropertyName.userProperty.rawValue: - var key:String? - var value:String? + var key: String? + var value: String? guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else { break } @@ -77,14 +74,12 @@ public class MqttDecodeSubAck: NSObject { userProperty![key!] = value - default: return } } } - if dataIndex < totalCount { while dataIndex < totalCount { guard let reasonCode = CocoaMQTTSUBACKReasonCode(rawValue: pubAckData[dataIndex]) else { @@ -94,9 +89,5 @@ public class MqttDecodeSubAck: NSObject { dataIndex += 1 } } - } - } - - diff --git a/Source/MqttDecodeUnsubAck.swift b/Source/MqttDecodeUnsubAck.swift index 1ccad341..663e1a21 100644 --- a/Source/MqttDecodeUnsubAck.swift +++ b/Source/MqttDecodeUnsubAck.swift @@ -8,7 +8,6 @@ import Foundation public class MqttDecodeUnsubAck: NSObject { - var totalCount = 0 var dataIndex = 0 var propertyLength: Int = 0 @@ -19,21 +18,20 @@ public class MqttDecodeUnsubAck: NSObject { public var reasonString: String? public var userProperty: [String: String]? - - public func decodeUnSubAck(fixedHeader: UInt8, pubAckData: [UInt8]){ + public func decodeUnSubAck(fixedHeader: UInt8, pubAckData: [UInt8]) { totalCount = pubAckData.count dataIndex = 0 - //msgid - let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex) + // msgid + let msgidResult = integerCompute(data: pubAckData, formatType: FormatInt.formatUint16.rawValue, offset: dataIndex) msgid = UInt16(msgidResult!.res) dataIndex = msgidResult!.newOffset - var protocolVersion = ""; + var protocolVersion = "" if let storage = CocoaMQTTStorage() { protocolVersion = storage.queryMQTTVersion() } - if (protocolVersion == "5.0"){ + if protocolVersion == "5.0" { // 3.11.2.1 UNSUBACK Properties // 3.11.2.1.1 Property Length let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex) @@ -49,7 +47,6 @@ public class MqttDecodeUnsubAck: NSObject { break } - switch propertyName.rawValue { // 3.11.2.1.2 Reason String case CocoaMQTTPropertyName.reasonString.rawValue: @@ -61,8 +58,8 @@ public class MqttDecodeUnsubAck: NSObject { // 3.11.2.1.3 User Property case CocoaMQTTPropertyName.userProperty.rawValue: - var key:String? - var value:String? + var key: String? + var value: String? guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else { break } @@ -77,14 +74,12 @@ public class MqttDecodeUnsubAck: NSObject { userProperty![key!] = value - default: return } } } - if dataIndex < totalCount { while dataIndex < totalCount { guard let reasonCode = CocoaMQTTUNSUBACKReasonCode(rawValue: pubAckData[dataIndex]) else { @@ -94,9 +89,5 @@ public class MqttDecodeUnsubAck: NSObject { dataIndex += 1 } } - } - } - - diff --git a/Source/MqttPublishProperties.swift b/Source/MqttPublishProperties.swift index 64c0540d..921a260e 100644 --- a/Source/MqttPublishProperties.swift +++ b/Source/MqttPublishProperties.swift @@ -8,26 +8,24 @@ import Foundation public class MqttPublishProperties: NSObject { - - - //3.3.2.3 PUBLISH Properties - //3.3.2.3.1 Property Length + // 3.3.2.3 PUBLISH Properties + // 3.3.2.3.1 Property Length public var propertyLength: Int? - //3.3.2.3.2 Payload Format Indicator + // 3.3.2.3.2 Payload Format Indicator public var payloadFormatIndicator: PayloadFormatIndicator? - //3.3.2.3.3 Message Expiry Interval + // 3.3.2.3.3 Message Expiry Interval public var messageExpiryInterval: UInt32? - //3.3.2.3.4 Topic Alias + // 3.3.2.3.4 Topic Alias public var topicAlias: UInt16? - //3.3.2.3.5 Response Topic + // 3.3.2.3.5 Response Topic public var responseTopic: String? - //3.3.2.3.6 Correlation Data + // 3.3.2.3.6 Correlation Data public var correlationData: [UInt8]? - //3.3.2.3.7 Property + // 3.3.2.3.7 Property public var userProperty: [String: String]? - //3.3.2.3.8 Subscription Identifier + // 3.3.2.3.8 Subscription Identifier public var subscriptionIdentifier: UInt32? - //3.3.2.3.9 Content Type + // 3.3.2.3.9 Content Type public var contentType: String? public init( @@ -55,45 +53,42 @@ public class MqttPublishProperties: NSObject { public var properties: [UInt8] { var properties = [UInt8]() - //3.3.2.3.2 Payload Format Indicator + // 3.3.2.3.2 Payload Format Indicator if let payloadFormatIndicator = self.payloadFormatIndicator { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.payloadFormatIndicator.rawValue, value: [payloadFormatIndicator.rawValue]) } - //3.3.2.3.3 Message Expiry Interval + // 3.3.2.3.3 Message Expiry Interval if let messageExpiryInterval = self.messageExpiryInterval { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.willExpiryInterval.rawValue, value: messageExpiryInterval.byteArrayLittleEndian) } - //3.3.2.3.4 Topic Alias + // 3.3.2.3.4 Topic Alias if let topicAlias = self.topicAlias { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.topicAlias.rawValue, value: topicAlias.hlBytes) } - //3.3.2.3.5 Response Topic + // 3.3.2.3.5 Response Topic if let responseTopic = self.responseTopic { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.responseTopic.rawValue, value: responseTopic.bytesWithLength) } - //3.3.2.3.6 Correlation Data + // 3.3.2.3.6 Correlation Data if let correlationData = self.correlationData { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.correlationData.rawValue, value: correlationData) } - //3.3.2.3.7 Property Length User Property + // 3.3.2.3.7 Property Length User Property if let userProperty = self.userProperty { let dictValues = [String](userProperty.values) for (value) in dictValues { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.userProperty.rawValue, value: value.bytesWithLength) } } - //3.3.2.3.8 Subscription Identifier + // 3.3.2.3.8 Subscription Identifier if let subscriptionIdentifier = self.subscriptionIdentifier { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.subscriptionIdentifier.rawValue, value: subscriptionIdentifier.byteArrayLittleEndian) } - //3.3.2.3.9 Content Type + // 3.3.2.3.9 Content Type if let contentType = self.contentType { properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.contentType.rawValue, value: contentType.bytesWithLength) } - - - return properties } } diff --git a/Source/MqttSubscription.swift b/Source/MqttSubscription.swift index 34f6e938..226429a3 100644 --- a/Source/MqttSubscription.swift +++ b/Source/MqttSubscription.swift @@ -7,15 +7,14 @@ import Foundation -///3.8.3.1 Subscription Options +/// 3.8.3.1 Subscription Options public class MqttSubscription { - public var topic: String public var qos = CocoaMQTTQoS.qos1 - public var noLocal: Bool = false - public var retainAsPublished: Bool = false + public var noLocal = false + public var retainAsPublished = false public var retainHandling: CocoaRetainHandlingOption - public var subscriptionOptions: Bool = false + public var subscriptionOptions = false public init(topic: String) { self.topic = topic @@ -33,12 +32,12 @@ public class MqttSubscription { self.retainHandling = CocoaRetainHandlingOption.none } - var subscriptionData:[UInt8]{ + var subscriptionData: [UInt8] { var data = [UInt8]() data += topic.bytesWithLength - var options:Int = 0; + var options: Int = 0 switch self.qos { case .qos0: options = options | 0b0000_0000 @@ -73,13 +72,10 @@ public class MqttSubscription { options = options | 0b0000_0000 } - if subscriptionOptions { data += [UInt8(options)] } - return data } - }