1/** 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 */ 7 8#import "RNCConnectionState.h" 9#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST 10#import <CoreTelephony/CTTelephonyNetworkInfo.h> 11#endif 12 13#if TARGET_OS_TV || TARGET_OS_OSX || TARGET_OS_MACCATALYST 14#include <ifaddrs.h> 15#endif 16 17@implementation RNCConnectionState 18 19// Creates a new "blank" state 20- (instancetype)init 21{ 22 self = [super init]; 23 if (self) { 24 _type = RNCConnectionTypeUnknown; 25 _cellularGeneration = nil; 26 _expensive = false; 27 } 28 return self; 29} 30 31// Creates the state from the given reachability references 32- (instancetype)initWithReachabilityFlags:(SCNetworkReachabilityFlags)flags 33{ 34 self = [self init]; 35 if (self) { 36 _type = RNCConnectionTypeUnknown; 37 _cellularGeneration = nil; 38 _expensive = false; 39 40 if ((flags & kSCNetworkReachabilityFlagsReachable) == 0 || 41 (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0) { 42 _type = RNCConnectionTypeNone; 43 } 44#if !TARGET_OS_TV && !TARGET_OS_OSX && !TARGET_OS_MACCATALYST 45 else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) { 46 _type = RNCConnectionTypeCellular; 47 _expensive = true; 48 49 CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init]; 50 if (netinfo) { 51 if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS] || 52 [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge] || 53 [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x]) { 54 _cellularGeneration = RNCCellularGeneration2g; 55 } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA] || 56 [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA] || 57 [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA] || 58 [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0] || 59 [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA] || 60 [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB] || 61 [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD]) { 62 _cellularGeneration = RNCCellularGeneration3g; 63 } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) { 64 _cellularGeneration = RNCCellularGeneration4g; 65 } else if (@available(iOS 14.1, *)) { 66 if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyNRNSA] || 67 [netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyNR]) { 68 _cellularGeneration = RNCCellularGeneration5g; 69 } 70 } 71 } 72 } 73#endif 74 else { 75 _type = RNCConnectionTypeWifi; 76#if TARGET_OS_TV || TARGET_OS_OSX || TARGET_OS_MACCATALYST 77 struct ifaddrs *interfaces = NULL; 78 struct ifaddrs *temp_addr = NULL; 79 int success = 0; 80 // retrieve the current interfaces - returns 0 on success 81 success = getifaddrs(&interfaces); 82 if (success == 0) { 83 // Loop through linked list of interfaces 84 temp_addr = interfaces; 85 while (temp_addr != NULL) { 86 if (temp_addr->ifa_addr->sa_family == AF_INET) { 87 // Check if interface is en0 which is the ethernet connection on the Apple TV 88 NSString* ifname = [NSString stringWithUTF8String:temp_addr->ifa_name]; 89 if ([ifname isEqualToString:@"en0"]) { 90 _type = RNCConnectionTypeEthernet; 91 } 92 } 93 temp_addr = temp_addr->ifa_next; 94 } 95 } 96 // Free memory 97 freeifaddrs(interfaces); 98#endif 99 } 100 } 101 return self; 102} 103 104// Checks if two states are equal 105- (BOOL)isEqualToConnectionState:(RNCConnectionState *)otherState 106{ 107 return [self.type isEqualToString:otherState.type] 108 && [self.cellularGeneration isEqualToString:otherState.cellularGeneration] 109 && self.expensive == otherState.expensive; 110} 111 112- (BOOL)connected 113{ 114 return ![self.type isEqualToString:RNCConnectionTypeNone] && ![self.type isEqualToString:RNCConnectionTypeUnknown]; 115} 116 117@end 118