Skip to content

Commit b10f131

Browse files
authored
Add local ip address to returned device info (AIS-341). (#724)
* Implemented. * Fixed build errors for < Xcode 9.
1 parent 4f4d337 commit b10f131

File tree

8 files changed

+158
-29
lines changed

8 files changed

+158
-29
lines changed

Branch-SDK/Branch-SDK/BNCDeviceInfo.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
@property (atomic, copy, readonly) NSString *hardwareId;
1515
@property (atomic, copy, readonly) NSString *hardwareIdType;
1616
@property (atomic, readonly) BOOL isRealHardwareId;
17-
// vendorId can be nil initially and non-nil later.
18-
@property (atomic, copy, readonly) NSString *vendorId;
17+
@property (atomic, copy, readonly) NSString *vendorId; //!< VendorId can be nil initially and non-nil later.
1918
@property (atomic, copy, readonly) NSString *brandName;
2019
@property (atomic, copy, readonly) NSString *modelName;
2120
@property (atomic, copy, readonly) NSString *osName;
@@ -24,10 +23,10 @@
2423
@property (atomic, copy, readonly) NSNumber *screenHeight;
2524
@property (atomic, readonly) BOOL isAdTrackingEnabled;
2625

27-
@property (atomic, copy, readonly) NSString* country; // iso2 Country name (us, in,etc).
28-
@property (atomic, copy, readonly) NSString* language; // iso2 language code (en, ml).
29-
@property (atomic, copy, readonly) NSString* browserUserAgent; // Simple user agent string.
30-
26+
@property (atomic, copy, readonly) NSString* country; //!< The iso2 Country name (us, in,etc).
27+
@property (atomic, copy, readonly) NSString* language; //!< The iso2 language code (en, ml).
28+
@property (atomic, copy, readonly) NSString* browserUserAgent; //!< Simple user agent string.
29+
@property (atomic, copy, readonly) NSString* localIPAddress; //!< The current local IP address.
3130

3231
//----------Methods----------------//
3332
+ (BNCDeviceInfo *)getInstance;

Branch-SDK/Branch-SDK/BNCDeviceInfo.m

Lines changed: 110 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,117 @@
66
// Copyright © 2016 Branch Metrics. All rights reserved.
77
//
88

9-
10-
@import Foundation;
11-
@import UIKit;
12-
@import Darwin.sys.sysctl;
139
#import "BNCDeviceInfo.h"
1410
#import "BNCPreferenceHelper.h"
1511
#import "BNCSystemObserver.h"
1612
#import "BNCXcode7Support.h"
1713
#import "BNCLog.h"
1814

15+
@import UIKit;
16+
#import <sys/sysctl.h> // @import not available in Xcode 7
17+
#import <net/if.h>
18+
#import <ifaddrs.h>
19+
#import <arpa/inet.h>
20+
#import <netinet/in.h>
21+
22+
#pragma mark - BRNNetworkInfo
23+
24+
typedef NS_ENUM(NSInteger, BNCNetworkAddressType) {
25+
BNCNetworkAddressTypeUnknown = 0,
26+
BNCNetworkAddressTypeIPv4,
27+
BNCNetworkAddressTypeIPv6
28+
};
29+
30+
@interface BNCNetworkInterface : NSObject
31+
32+
+ (NSArray<BNCNetworkInterface*>*) currentInterfaces;
33+
34+
@property (nonatomic, strong) NSString *interfaceName;
35+
@property (nonatomic, assign) BNCNetworkAddressType addressType;
36+
@property (nonatomic, strong) NSString *address;
37+
@end
38+
39+
@implementation BNCNetworkInterface
40+
41+
+ (NSArray<BNCNetworkInterface*>*) currentInterfaces {
42+
43+
struct ifaddrs *interfaces = NULL;
44+
NSMutableArray *currentInterfaces = [NSMutableArray arrayWithCapacity:8];
45+
46+
// Retrieve the current interfaces - returns 0 on success
47+
48+
if (getifaddrs(&interfaces) != 0) {
49+
int e = errno;
50+
BNCLogError(@"Can't read ip address: (%d): %s.", e, strerror(e));
51+
goto exit;
52+
}
53+
54+
// Loop through linked list of interfaces --
55+
56+
struct ifaddrs *interface = NULL;
57+
for(interface=interfaces; interface; interface=interface->ifa_next) {
58+
// BNCLogDebugSDK(@"Found %s: %x.", interface->ifa_name, interface->ifa_flags);
59+
60+
// Check the state: IFF_RUNNING, IFF_UP, IFF_LOOPBACK, etc.
61+
if (!(interface->ifa_flags & IFF_RUNNING) ||
62+
(interface->ifa_flags & IFF_LOOPBACK))
63+
continue;
64+
65+
const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
66+
if (!addr) continue;
67+
68+
BNCNetworkAddressType type = BNCNetworkAddressTypeUnknown;
69+
char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
70+
71+
if (addr->sin_family == AF_INET) {
72+
if (inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN))
73+
type = BNCNetworkAddressTypeIPv4;
74+
}
75+
else
76+
if (addr->sin_family == AF_INET6) {
77+
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
78+
if (inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN))
79+
type = BNCNetworkAddressTypeIPv6;
80+
}
81+
else {
82+
continue;
83+
}
84+
85+
NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
86+
if (name && type != BNCNetworkAddressTypeUnknown) {
87+
BNCNetworkInterface *interface = [BNCNetworkInterface new];
88+
interface.interfaceName = name;
89+
interface.addressType = type;
90+
interface.address = [NSString stringWithUTF8String:addrBuf];
91+
[currentInterfaces addObject:interface];
92+
}
93+
}
94+
95+
exit:
96+
if (interfaces) freeifaddrs(interfaces);
97+
return currentInterfaces;
98+
}
99+
100+
- (NSString*) description {
101+
return [NSString stringWithFormat:@"<%@ %p %@ %@>",
102+
NSStringFromClass(self.class),
103+
self,
104+
self.interfaceName,
105+
self.address
106+
];
107+
}
108+
109+
@end
110+
111+
#pragma mark - BNCDeviceInfo
19112

20113
@interface BNCDeviceInfo()
21114
@end
22115

23116

24117
@implementation BNCDeviceInfo {
25-
NSString * volatile _vendorId;
118+
NSString *_vendorId;
119+
NSString *_localIPAddress;
26120
}
27121

28122
+ (BNCDeviceInfo *)getInstance {
@@ -84,6 +178,17 @@ - (NSString *)vendorId {
84178
}
85179
}
86180

181+
- (NSString*) localIPAddress { // For 'local_ip' server field.
182+
@synchronized (self) {
183+
NSArray<BNCNetworkInterface*>*interfaces = [BNCNetworkInterface currentInterfaces];
184+
for (BNCNetworkInterface *interface in interfaces) {
185+
if (interface.addressType == BNCNetworkAddressTypeIPv4)
186+
return interface.address;
187+
}
188+
return nil;
189+
}
190+
}
191+
87192
+ (NSString*) bnc_country {
88193

89194
NSString *country = nil;

Branch-SDK/Branch-SDK/BNCLog.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
//--------------------------------------------------------------------------------------------------
1414

1515

16-
#import "BNCLog.h"
17-
@import Darwin.C.stdatomic;
16+
#import "BNCLog.h"
17+
#import <stdatomic.h> // @import not available in Xcode 7
1818

1919

2020
#define _countof(array) (sizeof(array)/sizeof(array[0]))

Branch-SDK/Branch-SDK/Networking/BNCServerInterface.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@ - (void)updateDeviceInfoToMutableDictionary:(NSMutableDictionary *)dict {
779779
[self safeSetValue:deviceInfo.browserUserAgent forKey:@"user_agent" onDict:dict];
780780
[self safeSetValue:deviceInfo.country forKey:@"country" onDict:dict];
781781
[self safeSetValue:deviceInfo.language forKey:@"language" onDict:dict];
782+
dict[@"local_ip"] = deviceInfo.localIPAddress;
782783

783784
dict[BRANCH_REQUEST_KEY_AD_TRACKING_ENABLED] = @(deviceInfo.isAdTrackingEnabled);
784785
}

Branch-TestBed/Branch-SDK-Tests/BNCDeviceInfo.Test.m

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,31 @@
1414

1515

1616
#import "BNCTestCase.h"
17+
#import "BNCLog.h"
1718
#import "BNCDeviceInfo.h"
1819
#import "NSString+Branch.h"
19-
#import "BNCLog.h"
2020

2121
@interface BNCDeviceInfoTest : BNCTestCase
2222
@end
2323

2424
@implementation BNCDeviceInfoTest
2525

2626
- (void)testGetDeviceInfo {
27-
/*
28-
@property (nonatomic, strong) NSString *hardwareId;
29-
@property (nonatomic, strong) NSString *hardwareIdType;
30-
@property (nonatomic) BOOL isRealHardwareId;
31-
@property (nonatomic, strong) NSString *vendorId;
32-
@property (nonatomic, strong) NSString *brandName;
33-
@property (nonatomic, strong) NSString *modelName;
34-
@property (nonatomic, strong) NSString *osName;
35-
@property (nonatomic, strong) NSString *osVersion;
36-
@property (nonatomic, strong) NSNumber *screenWidth;
37-
@property (nonatomic, strong) NSNumber *screenHeight;
38-
@property (nonatomic) BOOL isAdTrackingEnabled;
39-
*/
27+
/*
28+
These are the device info properties:
29+
30+
@property (nonatomic, strong) NSString *hardwareId;
31+
@property (nonatomic, strong) NSString *hardwareIdType;
32+
@property (nonatomic) BOOL isRealHardwareId;
33+
@property (nonatomic, strong) NSString *vendorId;
34+
@property (nonatomic, strong) NSString *brandName;
35+
@property (nonatomic, strong) NSString *modelName;
36+
@property (nonatomic, strong) NSString *osName;
37+
@property (nonatomic, strong) NSString *osVersion;
38+
@property (nonatomic, strong) NSNumber *screenWidth;
39+
@property (nonatomic, strong) NSNumber *screenHeight;
40+
@property (nonatomic) BOOL isAdTrackingEnabled;
41+
*/
4042
BNCDeviceInfo *device = [BNCDeviceInfo getInstance];
4143

4244
#define maskedStringAssert(field, maskedString) { \
@@ -125,4 +127,10 @@ - (void)testStress {
125127
BNCSStringForCurrentMethod(), - startTime.timeIntervalSinceNow);
126128
}
127129

130+
- (void) testLocalIPAddress {
131+
NSString *address = [BNCDeviceInfo getInstance].localIPAddress;
132+
XCTAssertNotNil(address);
133+
XCTAssertStringMatchesRegex(address, @"[0-9]*\\.[0-9]*\\.[0-9]*\\.[0-9]*");
134+
}
135+
128136
@end

Branch-TestBed/Branch-SDK-Tests/BNCTestCase.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ static inline void BNCSleepForTimeInterval(NSTimeInterval seconds) {
2626
nanosleep(&sleepTime, NULL);
2727
}
2828

29+
extern BOOL BNCTestStringMatchesRegex(NSString *string, NSString *regex);
30+
31+
#define XCTAssertStringMatchesRegex(string, regex) \
32+
XCTAssertTrue(BNCTestStringMatchesRegex(string, regex))
2933

3034
@interface BNCTestCase : XCTestCase
3135

Branch-TestBed/Branch-SDK-Tests/BNCTestCase.m

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@
99
#import "BNCTestCase.h"
1010
#import "BNCPreferenceHelper.h"
1111

12+
BOOL BNCTestStringMatchesRegex(NSString *string, NSString *regex) {
13+
NSError *error = nil;
14+
NSRegularExpression* nsregex = [NSRegularExpression regularExpressionWithPattern:regex options:0 error:&error];
15+
if (error) {
16+
NSLog(@"Error in regex pattern: %@.", error);
17+
return NO;
18+
}
19+
NSRange stringRange = NSMakeRange(0, string.length);
20+
NSTextCheckingResult *match = [nsregex firstMatchInString:string options:0 range:stringRange];
21+
return NSEqualRanges(match.range, stringRange);
22+
}
23+
24+
#pragma mark - BNCTestCase
25+
1226
@interface BNCTestCase ()
1327
@property (assign, nonatomic) BOOL hasExceededExpectations;
1428
@end

Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,6 @@
11631163
PRODUCT_NAME = "$(TARGET_NAME)";
11641164
PUBLIC_HEADERS_FOLDER_PATH = /headers;
11651165
SKIP_INSTALL = YES;
1166-
WARNING_CFLAGS = "";
11671166
};
11681167
name = Debug;
11691168
};
@@ -1183,7 +1182,6 @@
11831182
PRODUCT_NAME = "$(TARGET_NAME)";
11841183
PUBLIC_HEADERS_FOLDER_PATH = /headers;
11851184
SKIP_INSTALL = YES;
1186-
WARNING_CFLAGS = "";
11871185
};
11881186
name = Release;
11891187
};

0 commit comments

Comments
 (0)