Skip to content

Commit

Permalink
feat: Implement simultaneous DNS resolution (#19)
Browse files Browse the repository at this point in the history
feat: Implement simultaneous DNS resolution to address scenarios where an IP version DNS could take too long to time out due to unavailability.
  • Loading branch information
AlejandroOrozco authored Jun 20, 2024
1 parent c1735d8 commit a39011d
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 13 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# 0.0.8 (12–06-2024)

### Improvements

- Implement simultaneous DNS resolution to address scenarios where an IP version DNS could take too long to time out due to unavailability

# 0.0.7 (3–05-2024)

### Improvements

- Add Privacy Manifest

# 0.0.6 (07–04-2024)

### Improvements

- Use GET & HTTP version 1.1 for Cellular requests, and forcing IPv4 resolution before try IPv6

# 0.0.5 (02–02-2024)

### Improvements
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ During the current phase of this project, we only support SPM. We have plans to
dependencies: [
.package(
url: "https://github.com/twilio/twilio-verify-sna-ios.git",
.upToNextMajor(from: "0.0.7")
.upToNextMajor(from: "0.0.8")
)
]
```
Expand Down
57 changes: 49 additions & 8 deletions SNASources/CellularSession.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ - (CellularSessionResult * _Nonnull)performRequest:(NSURL * _Nonnull)url {
sessionResult.status = CellularSessionUnexpectedError;

// Stores any errors that occur during execution
OSStatus status;
__block OSStatus status;

// All local (cellular interface) IP addresses of this device.
NSMutableArray<SocketAddress *> *localAddresses = [NSMutableArray array];
// All remote IP addresses that we're trying to connect to.
Expand Down Expand Up @@ -103,7 +103,7 @@ - (CellularSessionResult * _Nonnull)performRequest:(NSURL * _Nonnull)url {
ifaddrs = ifaddrs->ifa_next;
}

struct addrinfo *addrinfoPointer;
__block struct addrinfo *addrinfoPointer;
struct addrinfo *addrinfo;

// Generate "hints" for the DNS lookup (namely, search for both IPv4 and IPv6 addresses)
Expand All @@ -127,12 +127,53 @@ - (CellularSessionResult * _Nonnull)performRequest:(NSURL * _Nonnull)url {
DNSServiceRef sdRef = NULL;
DNSServiceFlags flags = kDNSServiceFlagsTimeout; // Set flags as needed

status = cellular_getaddrinfo([[url host] UTF8String], service, &hints, &addrinfoPointer, sdRef, flags, kDNSServiceProtocol_IPv4);
dispatch_group_t group = dispatch_group_create();
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__block BOOL resolutionCompleted = NO;
__block struct addrinfo *addrinfoIPv4 = NULL;
__block struct addrinfo *addrinfoIPv6 = NULL;

if (status || addrinfoPointer == NULL) {
// Retry DNS resolution with IPV6
status = cellular_getaddrinfo([[url host] UTF8String], service, &hints, &addrinfoPointer, sdRef, flags, kDNSServiceProtocol_IPv6);
}
// Start the IPv4 resolution
dispatch_group_async(group, queue, ^{
status = cellular_getaddrinfo([[url host] UTF8String], service, &hints, &addrinfoIPv4, sdRef, flags, kDNSServiceProtocol_IPv4);
if (status == 0 && addrinfoIPv4 != NULL) {
@synchronized (semaphore) {
if (!resolutionCompleted) {
addrinfoPointer = addrinfoIPv4;
resolutionCompleted = YES;
dispatch_semaphore_signal(semaphore);
}
}
}
});

// Start the IPv6 resolution
dispatch_group_async(group, queue, ^{
status = cellular_getaddrinfo([[url host] UTF8String], service, &hints, &addrinfoIPv6, sdRef, flags, kDNSServiceProtocol_IPv6);
if (status == 0 && addrinfoIPv6 != NULL) {
@synchronized (semaphore) {
if (!resolutionCompleted) {
addrinfoPointer = addrinfoIPv6;
resolutionCompleted = YES;
dispatch_semaphore_signal(semaphore);
}
}
}
});

// Wait for the first resolution to complete
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

// Clean up the other addrinfo if it was also resolved
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
if (addrinfoIPv4 && addrinfoIPv4 != addrinfoPointer) {
freeaddrinfo(addrinfoIPv4);
}
if (addrinfoIPv6 && addrinfoIPv6 != addrinfoPointer) {
freeaddrinfo(addrinfoIPv6);
}
});

if (status || addrinfoPointer == NULL) {
freeifaddrs(ifaddrPointer);
Expand Down
2 changes: 1 addition & 1 deletion Sources/TwilioVerifySNAConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
import Foundation

public struct TwilioVerifySNAConfig {
public static let version = "0.0.7"
public static let version = "0.0.8"
}
Original file line number Diff line number Diff line change
Expand Up @@ -398,4 +398,4 @@ extension PhoneNumberViewController {
}

/// Not required for the SDK implementation.
private let sampleAppVersion = "0.0.7"
private let sampleAppVersion = "0.0.8"
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 0.0.7;
MARKETING_VERSION = 0.0.8;
PRODUCT_BUNDLE_IDENTIFIER = com.twilio.TwilioVerifySNADemo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -448,7 +448,7 @@
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 0.0.7;
MARKETING_VERSION = 0.0.8;
PRODUCT_BUNDLE_IDENTIFIER = com.twilio.TwilioVerifySNADemo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down

0 comments on commit a39011d

Please sign in to comment.