react-native-os/ios/RNOS.m

161 lines
5.2 KiB
Objective-C

//
// RNOS.m
// RNOS
//
// Created by Andy Prock on 11/3/16.
// Copyright © 2016 Peel. All rights reserved.
//
#import "RNOS.h"
#import "RCTAssert.h"
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_dl.h>
@implementation RNOS {
SCNetworkReachabilityRef _reachability;
}
RCT_EXPORT_MODULE()
@synthesize bridge = _bridge;
static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
{
RNOS *self = (__bridge id)info;
// update the info on network changes
[self.bridge.eventDispatcher sendDeviceEventWithName:@"rn-os-info"
body:@{ @"networkInterfaces": [self networkInterfaces] }];
}
- (instancetype)init
{
if ((self = [super init])) {
[self startObserving];
}
return self;
}
- (void)startObserving
{
_reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, "apple.com");
SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL };
SCNetworkReachabilitySetCallback(_reachability, RCTReachabilityCallback, &context);
SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}
- (void)stopObserving
{
if (_reachability) {
SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFRelease(_reachability);
}
}
- (void)invalidate
{
[self stopObserving];
}
- (NSDictionary *)constantsToExport
{
// initialize os info dict
return @{@"networkInterfaces": [self networkInterfaces]};
}
- (NSDictionary*)networkInterfaces {
NSMutableDictionary* ifaces = [NSMutableDictionary new];
struct ifaddrs *addrs, *ent;
if (getifaddrs(&addrs)) {
return @{};
}
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
continue;
if (ent->ifa_addr == NULL)
continue;
/*
* On Mac OS X getifaddrs returns information related to Mac Addresses for
* various devices, such as firewire, etc. These are not relevant here.
*/
if (ent->ifa_addr->sa_family == AF_LINK)
continue;
NSMutableDictionary* address = [NSMutableDictionary new];
NSString *name = [NSString stringWithUTF8String:ent->ifa_name];
const struct sockaddr_in *addr = (const struct sockaddr_in*)ent->ifa_addr;
char addrBuf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
if(addr->sin_family == AF_INET) {
inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN);
[address setObject: [NSString stringWithUTF8String: addrBuf] forKey: @"address"];
[address setObject: @"IPv4" forKey: @"family"];
} else {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)ent->ifa_addr;
inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN);
[address setObject: [NSString stringWithUTF8String: addrBuf] forKey: @"address"];
[address setObject: @"IPv6" forKey: @"family"];
}
}
char netmaskBuf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
const struct sockaddr_in *mask = (const struct sockaddr_in*)ent->ifa_netmask;
if(mask && (mask->sin_family==AF_INET || mask->sin_family==AF_INET6)) {
if(mask->sin_family == AF_INET) {
inet_ntop(AF_INET, &mask->sin_addr, netmaskBuf, INET_ADDRSTRLEN);
[address setObject: [NSString stringWithUTF8String: netmaskBuf] forKey: @"netmask"];
} else {
const struct sockaddr_in6 *mask6 = (const struct sockaddr_in6*)ent->ifa_netmask;
inet_ntop(AF_INET6, &mask6->sin6_addr, netmaskBuf, INET6_ADDRSTRLEN);
[address setObject: [NSString stringWithUTF8String: netmaskBuf] forKey: @"netmask"];
}
}
[address setValue: [NSNumber numberWithBool:!!(ent->ifa_flags & IFF_LOOPBACK)] forKey: @"internal"];
if (((ent->ifa_flags & IFF_UP) || (ent->ifa_flags & IFF_RUNNING)) &&
!(ent->ifa_addr == NULL) &&
!(ent->ifa_addr->sa_family != AF_LINK)) {
NSMutableString *macString = [NSMutableString string];
struct sockaddr_dl* dlAddr = (struct sockaddr_dl*)(ent->ifa_addr);
const unsigned char* base = (const unsigned char *) &dlAddr->sdl_data[dlAddr->sdl_nlen];
for(NSInteger i = 0; i < dlAddr->sdl_alen; i++) {
[macString appendFormat:@"%02x", base[i]];
}
if ([macString length] > 0) {
[address setObject: macString forKey: @"mac"];
}
}
// update array
NSMutableArray* ifacesArray = [ifaces objectForKey: name];
if (ifacesArray) {
[ifacesArray addObject: address];
} else {
ifacesArray = [NSMutableArray arrayWithObject:address];
}
[ifaces setObject: ifacesArray forKey: name];
}
freeifaddrs(addrs);
return ifaces;
}
@end