From 5b2010cc8d2ba44d196d340992ba7b05ddb9e938 Mon Sep 17 00:00:00 2001 From: Manatsawin Hanmongkolchai Date: Tue, 17 Aug 2021 11:30:33 +0700 Subject: [PATCH] Added ALPN support --- MQTTClient/MQTTClient/MQTTCFSocketTransport.h | 4 ++++ MQTTClient/MQTTClient/MQTTCFSocketTransport.m | 21 ++++++++++++++++++- .../MQTTSSLSecurityPolicyTransport.m | 17 +++++++++++++++ MQTTClient/MQTTClient/MQTTSessionManager.h | 4 ++++ MQTTClient/MQTTClient/MQTTSessionManager.m | 1 + 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/MQTTClient/MQTTClient/MQTTCFSocketTransport.h b/MQTTClient/MQTTClient/MQTTCFSocketTransport.h index 87519f3d..e6664bdd 100644 --- a/MQTTClient/MQTTClient/MQTTCFSocketTransport.h +++ b/MQTTClient/MQTTClient/MQTTCFSocketTransport.h @@ -42,6 +42,10 @@ /// A Boolean value indicating whether the transport should send data over the cell network. Defaults to `YES`. @property (nonatomic) BOOL allowsCellularAccess; +/** ALPN to use, default to not use ALPN + */ +@property (strong, nonatomic) NSArray *alpn; + /** Require for VoIP background service * defaults to NO */ diff --git a/MQTTClient/MQTTClient/MQTTCFSocketTransport.m b/MQTTClient/MQTTClient/MQTTCFSocketTransport.m index 06b95baa..f7bbb593 100644 --- a/MQTTClient/MQTTClient/MQTTCFSocketTransport.m +++ b/MQTTClient/MQTTClient/MQTTCFSocketTransport.m @@ -27,6 +27,7 @@ @implementation MQTTCFSocketTransport @synthesize streamSSLLevel; @synthesize host; @synthesize port; +@synthesize alpn; - (instancetype)init { self = [super init]; @@ -34,6 +35,7 @@ - (instancetype)init { self.port = 1883; self.tls = false; self.allowsCellularAccess = YES; + self.alpn = nil; self.voip = false; self.certificates = nil; self.queue = dispatch_get_main_queue(); @@ -95,8 +97,25 @@ - (void)open { code:errSSLInternal userInfo:@{NSLocalizedDescriptionKey : @"Fail to init ssl output stream!"}]; } + + if (@available(iOS 11, *)) { + if (self.alpn != nil && [self.alpn count] > 0) { + OSStatus err; + SSLContextRef sslContext = CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLContext); + if ((err = SSLSetALPNProtocols(sslContext, (__bridge CFArrayRef) self.alpn))) { + connectError = [NSError errorWithDomain:@"MQTT" code:err userInfo:@{ + NSLocalizedDescriptionKey : @"ALPN error"}]; + } + + sslContext = CFWriteStreamCopyProperty(writeStream, kCFStreamPropertySSLContext); + if ((err = SSLSetALPNProtocols(sslContext, (__bridge CFArrayRef) self.alpn))) { + connectError = [NSError errorWithDomain:@"MQTT" code:err userInfo:@{ + NSLocalizedDescriptionKey : @"ALPN error"}]; + } + } + } } - + if (!self.allowsCellularAccess) { CFReadStreamSetProperty(readStream, kCFStreamPropertyNoCellular, kCFBooleanTrue); CFWriteStreamSetProperty(writeStream, kCFStreamPropertyNoCellular, kCFBooleanTrue); diff --git a/MQTTClient/MQTTClient/MQTTSSLSecurityPolicyTransport.m b/MQTTClient/MQTTClient/MQTTSSLSecurityPolicyTransport.m index 6698efb1..98e93347 100644 --- a/MQTTClient/MQTTClient/MQTTSSLSecurityPolicyTransport.m +++ b/MQTTClient/MQTTClient/MQTTSSLSecurityPolicyTransport.m @@ -65,6 +65,23 @@ - (void)open { code:errSSLInternal userInfo:@{NSLocalizedDescriptionKey : @"Fail to init ssl output stream!"}]; } + + if (@available(iOS 11, *)) { + if (self.alpn != nil && [self.alpn count] > 0) { + OSStatus err; + SSLContextRef sslContext = CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLContext); + if ((err = SSLSetALPNProtocols(sslContext, (__bridge CFArrayRef) self.alpn))) { + connectError = [NSError errorWithDomain:@"MQTT" code:err userInfo:@{ + NSLocalizedDescriptionKey : @"ALPN error"}]; + } + + sslContext = CFWriteStreamCopyProperty(writeStream, kCFStreamPropertySSLContext); + if ((err = SSLSetALPNProtocols(sslContext, (__bridge CFArrayRef) self.alpn))) { + connectError = [NSError errorWithDomain:@"MQTT" code:err userInfo:@{ + NSLocalizedDescriptionKey : @"ALPN error"}]; + } + } + } } if (!connectError) { diff --git a/MQTTClient/MQTTClient/MQTTSessionManager.h b/MQTTClient/MQTTClient/MQTTSessionManager.h index dc2fafb6..d56cb616 100644 --- a/MQTTClient/MQTTClient/MQTTSessionManager.h +++ b/MQTTClient/MQTTClient/MQTTSessionManager.h @@ -90,6 +90,10 @@ typedef NS_ENUM(int, MQTTSessionManagerState) { */ @property (readonly) UInt32 port; +/** alpn to negotiate in TLS sessions + */ +@property (strong, nonatomic) NSArray *alpn; + /** the delegate receiving incoming messages */ @property (weak, nonatomic) id delegate; diff --git a/MQTTClient/MQTTClient/MQTTSessionManager.m b/MQTTClient/MQTTClient/MQTTSessionManager.m index f5b91a0f..0732c54c 100644 --- a/MQTTClient/MQTTClient/MQTTSessionManager.m +++ b/MQTTClient/MQTTClient/MQTTSessionManager.m @@ -354,6 +354,7 @@ - (void)connectToInternal:(MQTTConnectHandler)connectHandler { transport.voip = self.session.voip; transport.queue = self.queue; transport.streamSSLLevel = self.streamSSLLevel; + transport.alpn = self.alpn; self.session.transport = transport; [self.session connectWithConnectHandler:connectHandler]; }