iOS 10 Reachability reachabilityForLocalWifi - ios

I want to check connection to a local wifi with bonjour using [Reachability reachabilityForLocalWifi] but it is now deprecated in iOS 10. Apple suggested to use [Reachability reachabilityWithAddress:] but it still returns "not reachable" even when i'm connected to a local wifi.
update:
Here is my code using reachabilityWithAddress which always returns "not reachable" for local wifi.
+(BOOL)checkWifiConnectionIfOn{
BOOL isOn;
struct sockaddr_in localWifiAddress;
bzero(&localWifiAddress, sizeof(localWifiAddress));
localWifiAddress.sin_len = sizeof(localWifiAddress);
localWifiAddress.sin_family = AF_INET;
// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0.
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
Reachability* returnValue = [Reachability reachabilityWithAddress:(struct sockaddr_in *) &localWifiAddress];
if (returnValue != NULL && [returnValue currentReachabilityStatus] != NotReachable) //Reachable
{
//
isOn = YES;
}
else{ // Not Reachable
NSString *log = [NSString stringWithFormat:#"WifiController checkWifiConnectionIfOn Wifi OFF"];
[Logger writeDeviceLog:log logType:ERROR_LOG];
isOn = NO;
}
return isOn;
}

Related

XMPP connect issue in ipv4 network

i tried all the code.i used this code to allow connect ipv6 network for connect XMPP.
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:xmppQueue];
[asyncSocket setPreferIPv4OverIPv6:NO];
- (void)setPreferIPv4OverIPv6:(BOOL)flag
{
// Note: YES means kPreferIPv6 is OFF
dispatch_block_t block = ^{
if (flag)
config &= ~kPreferIPv6;
else
config |= kPreferIPv6;
};
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
block();
else
dispatch_async(socketQueue, block);
}
- (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr
{
LogTrace();
NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), #"Must be dispatched on socketQueue");
LogVerbose(#"IPv4: %#:%hu", [[self class] hostFromAddress:address4], [[self class] portFromAddress:address4]);
LogVerbose(#"IPv6: %#:%hu", [[self class] hostFromAddress:address6], [[self class] portFromAddress:address6]);
// Determine socket type
BOOL preferIPv6 = (config & kPreferIPv6) ? YES : NO;
BOOL useIPv6 = ((preferIPv6 && address6) || (address4 == nil));
// Create the socket
__block int socketFD;
__block NSData *address;
__block NSData *connectInterface;
if (useIPv6)
{
LogVerbose(#"Creating IPv6 socket");
socket6FD = socket(AF_INET6, SOCK_STREAM, 0);
socketFD = socket6FD;
address = address6;
connectInterface = connectInterface6;
}
else
{
LogVerbose(#"Creating IPv4 socket");
socket4FD = socket(AF_INET, SOCK_STREAM, 0);
socketFD = socket4FD;
address = address4;
connectInterface = connectInterface4;
}
if (socketFD == SOCKET_NULL)
{
if (errPtr)
*errPtr = [self errnoErrorWithReason:#"Error in socket() function"];
return NO;
}
// Bind the socket to the desired interface (if needed)
if (connectInterface)
{
LogVerbose(#"Binding socket...");
if ([[self class] portFromAddress:connectInterface] > 0)
{
// Since we're going to be binding to a specific port,
// we should turn on reuseaddr to allow us to override sockets in time_wait.
int reuseOn = 1;
setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
}
const struct sockaddr *interfaceAddr = (const struct sockaddr *)[connectInterface bytes];
int result = bind(socketFD, interfaceAddr, (socklen_t)[connectInterface length]);
if (result != 0)
{
if (errPtr)
*errPtr = [self errnoErrorWithReason:#"Error in bind() function"];
return NO;
}
}
// Prevent SIGPIPE signals
int nosigpipe = 1;
setsockopt(socketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
// Start the connection process in a background queue
int aConnectIndex = connectIndex;
// dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// dispatch_async(globalConcurrentQueue, ^{
int result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]);
if (result != 0) {
socket6FD = SOCKET_NULL;
socket4FD = socket(AF_INET, SOCK_STREAM, 0);
socketFD = socket4FD;
address = address4;
connectInterface = connectInterface4;
result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]);
}
//});
LogVerbose(#"Connecting...");
return YES;
}
above this method always connect ipv6 in both network.
if i will commet [asyncSocket setPreferIPv4OverIPv6:NO]; this code than proper work in ipv4 network but does not connect ipv6.if i used this code than does not connect ipv4.please help me.i want to connect both network..
try this method of connectWithAddress4...
- (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr
{
LogTrace();
NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), #"Must be dispatched on socketQueue");
LogVerbose(#"IPv4: %#:%hu", [[self class] hostFromAddress:address4], [[self class] portFromAddress:address4]);
LogVerbose(#"IPv6: %#:%hu", [[self class] hostFromAddress:address6], [[self class] portFromAddress:address6]);
// Determine socket type
BOOL preferIPv6 = (config & kPreferIPv6) ? YES : NO;
BOOL useIPv6 = ((preferIPv6 && address6) || (address4 == nil));
// Create the socket
int socketFD;
NSData *address;
NSData *connectInterface;
if (useIPv6)
{
LogVerbose(#"Creating IPv6 socket");
socket6FD = socket(AF_INET6, SOCK_STREAM, 0);
socketFD = socket6FD;
address = address6;
connectInterface = connectInterface6;
}
else
{
LogVerbose(#"Creating IPv4 socket");
socket4FD = socket(AF_INET, SOCK_STREAM, 0);
socketFD = socket4FD;
address = address4;
connectInterface = connectInterface4;
}
if (socketFD == SOCKET_NULL)
{
if (errPtr)
*errPtr = [self errnoErrorWithReason:#"Error in socket() function"];
return NO;
}
// Bind the socket to the desired interface (if needed)
if (connectInterface)
{
LogVerbose(#"Binding socket...");
if ([[self class] portFromAddress:connectInterface] > 0)
{
// Since we're going to be binding to a specific port,
// we should turn on reuseaddr to allow us to override sockets in time_wait.
int reuseOn = 1;
setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
}
const struct sockaddr *interfaceAddr = (const struct sockaddr *)[connectInterface bytes];
int result = bind(socketFD, interfaceAddr, (socklen_t)[connectInterface length]);
if (result != 0)
{
if (errPtr)
*errPtr = [self errnoErrorWithReason:#"Error in bind() function"];
return NO;
}
}
// Prevent SIGPIPE signals
int nosigpipe = 1;
setsockopt(socketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
// Start the connection process in a background queue
int aStateIndex = stateIndex;
__weak GCDAsyncSocket *weakSelf = self;
dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalConcurrentQueue, ^{
#pragma clang diagnostic push
#pragma clang diagnostic warning "-Wimplicit-retain-self"
int result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]);
__strong GCDAsyncSocket *strongSelf = weakSelf;
if (strongSelf == nil) return_from_block;
if (result == 0)
{
dispatch_async(strongSelf->socketQueue, ^{ #autoreleasepool {
[strongSelf didConnect:aStateIndex];
}});
}
else
{
NSError *error = [strongSelf errnoErrorWithReason:#"Error in connect() function"];
dispatch_async(strongSelf->socketQueue, ^{ #autoreleasepool {
[strongSelf didNotConnect:aStateIndex error:error];
}});
}
#pragma clang diagnostic pop
});
LogVerbose(#"Connecting...");
return YES;
}

iOS Objective-C get VPN IP programmatically

I use a third-party app to connect a VPN, and we can get the detail information in Settings->VPN->information. How can I get the Assigned IP programmatically in our app by Objective-C?
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while (temp_addr != NULL) {
if( temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"utun1"])
{
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
NSLog(#"ifaName: %#, Address: %#",[NSString stringWithUTF8String:temp_addr->ifa_name],address);
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
address will have the assigned IP Address
This is working on iOS 14:
- (NSString *)getVPNIPAddress
{
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0)
{
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL)
{
if(temp_addr->ifa_addr->sa_family == AF_INET)
{
NSLog(#"%#",[NSString stringWithUTF8String:temp_addr->ifa_name]);
// Check if interface is en0 which is the wifi connection on the iPhone
if(
[[NSString stringWithUTF8String:temp_addr->ifa_name] containsString:#"tun"] ||
[[NSString stringWithUTF8String:temp_addr->ifa_name] containsString:#"tap"] ||
[[NSString stringWithUTF8String:temp_addr->ifa_name] containsString:#"ipsec"] ||
[[NSString stringWithUTF8String:temp_addr->ifa_name] containsString:#"ppp"]){
// Get NSString from C String
struct sockaddr_in *in = (struct sockaddr_in*) temp_addr->ifa_addr;
address = [NSString stringWithUTF8String:inet_ntoa((in)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}

How to judge a Network environment is Only-IPV6 in iOS

Since you know after June 1, app in iOS should support only-IPV6. I find a way that can change an ipv4 ip address to an ipv6 ip address. But, I cann't judge a network environment is only-IPV6. I already open a NAT64 WIFI by my MACBOOK, also use flight mode to make sure it's the only-IPV6. I just find there is an ipv6 ip address at first. Then work the code again, i will get both an ipv4 and an ipv6 address. I have no idea about it. Anyone have any idea?
There are my codes for fetch ip address:
- (NSMutableDictionary *)localIPAddressFetcher {
NSMutableDictionary *addressDic = [NSMutableDictionary dictionary];
struct ifaddrs *myaddrs, *temp_addr;
struct sockaddr_in *s4;
struct sockaddr_in6 *s6;
int status = 0;
char buf[64];
status = getifaddrs(&myaddrs);
if (status == 0) {
for (temp_addr = myaddrs; temp_addr != NULL; temp_addr = temp_addr->ifa_next) {
if (temp_addr->ifa_addr == NULL) continue;
if ((temp_addr->ifa_flags & IFF_UP) == 0) continue;
if (temp_addr->ifa_flags & IFF_LOOPBACK) continue;
if (temp_addr->ifa_addr->sa_family == AF_INET) {
s4 = (struct sockaddr_in *)(temp_addr->ifa_addr);
if (inet_ntop(temp_addr->ifa_addr->sa_family, (void *)&(s4->sin_addr), buf, sizeof(buf)) != NULL) {
if (![[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"lo0"]) {
NSString *address = [NSString stringWithUTF8String:buf];
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]) {
[addressDic setObject:address forKey:#"ipv4_wifi"];
} else {
[addressDic setObject:address forKey:[NSString stringWithUTF8String:temp_addr->ifa_name]];
}
}
}
} else if (temp_addr->ifa_addr->sa_family == AF_INET6) {
s6 = (struct sockaddr_in6 *)(temp_addr->ifa_addr);
if (inet_ntop(temp_addr->ifa_addr->sa_family, (void *)&(s6->sin6_addr), buf, sizeof(buf)) != NULL) {
if (![[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"lo0"]) {
NSString *address = [NSString stringWithUTF8String:buf];
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]) {
[addressDic setObject:address forKey:#"ipv6_wifi"];
} else {
[addressDic setObject:address forKey:[NSString stringWithUTF8String:temp_addr->ifa_name]];
}
}
}
}
}
}
freeifaddrs(myaddrs);
return addressDic;}

Get IP address code worked before but failed now in iOS

I use the code below to get IP address of iPhone
#define IOS_CELLULAR #"pdp_ip0"
#define IOS_WIFI #"en0"
#define IOS_VPN #"utun0"
#define IP_ADDR_IPv4 #"ipv4"
#define IP_ADDR_IPv6 #"ipv6"
- (NSString *) getIPAddress1;
{
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0)
{
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL)
{
if(temp_addr->ifa_addr->sa_family == AF_INET)
{
// Check if interface is en0 which is the wifi connection on the iPhone
NSString *s= [NSString stringWithUTF8String:temp_addr->ifa_name];
NSLog(#"%# ---",s);
if([s isEqualToString:IOS_WIFI] || [s isEqualToString:IOS_CELLULAR] || [s isEqualToString:IOS_VPN])
{
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
It worked before, but now it always returns #"error".
I even tried all method mention here
iPhone/iPad/OSX: How to get my IP address programmatically?
but none worked.
Your comments are welcome.
Try this
#import <ifaddrs.h>
#import <arpa/inet.h>
- (NSString *)getIPAddress {
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}

How to Detect wifi or 3G signal strength in iOS?

I am working on video player using MPMediaplayer framework in iOS, I need to play two videos in my app.(i.e. My first video will play when user has strong Network signal).
My second video player will be played when their low network. I need to play my video in wifi or 3G etc... My First thing is how to detect my wifi speed in my iphone mobile and 3G speed also. I need to get mobile wifi speed in MBPS. I am was trying to write some code. But it is not working for me. Thanks in advance.
#import "Reachability.h"
#interface NetworkViewController ()
#end
#implementation NetworkViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self getDataCounters];
networkLabel = [[UILabel alloc]initWithFrame:CGRectMake(20, 100, 300, 40)];
networkLabel.textColor = [UIColor blackColor];
networkLabel.backgroundColor = [UIColor whiteColor];
networkLabel.userInteractionEnabled = NO;
networkLabel.text = myNewString;
[self.view addSubview:networkLabel];
}
- (NSArray *)getDataCounters
{
BOOL success;
struct ifaddrs *addrs;
const struct ifaddrs *cursor;
const struct if_data *networkStatisc;
int WiFiSent = 0;
int WiFiReceived = 0;
int WWANSent = 0;
int WWANReceived = 0;
NSString *name=[[NSString alloc]init];
success = getifaddrs(&addrs) == 0;
if (success)
{
cursor = addrs;
while (cursor != NULL)
{
name=[NSString stringWithFormat:#"%s",cursor->ifa_name];
NSLog(#"ifa_name %s == %#\n", cursor->ifa_name,name);
// names of interfaces: en0 is WiFi ,pdp_ip0 is WWAN
if (cursor->ifa_addr->sa_family == AF_LINK)
{
if ([name hasPrefix:#"en"])
{
networkStatisc = (const struct if_data *) cursor->ifa_data;
WiFiSent+=networkStatisc->ifi_obytes;
WiFiReceived+=networkStatisc->ifi_ibytes;
NSLog(#"WiFiSent %d ==%d",WiFiSent,networkStatisc->ifi_obytes);
NSLog(#"WiFiReceived %d ==%d",WiFiReceived,networkStatisc->ifi_ibytes);
NSLog(#"wifi data is %.2f",(float)WiFiReceived/1048576);
myNewString = [NSString stringWithFormat:#"%2f", (float)WiFiReceived/1048576];
networkLabel.text = myNewString;
}
if ([name hasPrefix:#"pdp_ip"])
{
networkStatisc = (const struct if_data *) cursor->ifa_data;
WWANSent+=networkStatisc->ifi_obytes;
WWANReceived+=networkStatisc->ifi_ibytes;
NSLog(#"WWANSent %d ==%d",WWANSent,networkStatisc->ifi_obytes);
NSLog(#"WWANReceived %d ==%d",WWANReceived,networkStatisc->ifi_ibytes);
}
}
cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
return [NSArray arrayWithObjects:[NSNumber numberWithInt:WiFiSent], [NSNumber numberWithInt:WiFiReceived],[NSNumber numberWithInt:WWANSent],[NSNumber numberWithInt:WWANReceived], nil];
}
You can play high resolution video for wifi and low resolution video on cellular data.
Reachability *reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];
NetworkStatus status = [reachability currentReachabilityStatus];
if(status == NotReachable)
{
//No internet
}
else if (status == ReachableViaWiFi)
{
//WiFi Play high resolution video
}
else if (status == ReachableViaWWAN)
{
//3G Play low resolution video
}
Apple can reject your app if you will stream high resolution video over 3g Network.

Resources