Skip to content

Commit

Permalink
Add IPv6 support and logging of flag status
Browse files Browse the repository at this point in the history
  • Loading branch information
GlennChiu committed Oct 3, 2012
1 parent 622d22a commit 24f5e96
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 15 deletions.
7 changes: 6 additions & 1 deletion GCNetworkReachability.h
Expand Up @@ -46,12 +46,16 @@ extern NSString * const kGCNetworkReachabilityStatusKey;

+ (GCNetworkReachability *)reachabilityWithHostName:(NSString *)hostName;

+ (GCNetworkReachability *)reachabilityWithHostAddress:(const struct sockaddr_in *)hostAddress;
+ (GCNetworkReachability *)reachabilityWithHostAddress:(const struct sockaddr *)hostAddress;

+ (GCNetworkReachability *)reachabilityWithInternetAddress:(in_addr_t)internetAddress;

+ (GCNetworkReachability *)reachabilityWithInternetAddressString:(NSString *)internetAddress;

+ (GCNetworkReachability *)reachabilityWithIPv6Address:(const struct in6_addr)internetAddress;

+ (GCNetworkReachability *)reachabilityWithIPv6AddressString:(NSString *)internetAddress;

+ (GCNetworkReachability *)reachabilityForInternetConnection;

+ (GCNetworkReachability *)reachabilityForLocalWiFi;
Expand All @@ -75,6 +79,7 @@ extern NSString * const kGCNetworkReachabilityStatusKey;
- (BOOL)isReachableViaWWAN;
#endif


- (void)startMonitoringNetworkReachabilityWithHandler:(void(^)(GCNetworkReachabilityStatus status))block;

- (void)startMonitoringNetworkReachabilityWithNotification;
Expand Down
94 changes: 80 additions & 14 deletions GCNetworkReachability.m
Expand Up @@ -59,12 +59,15 @@
# endif
#endif

static GCNetworkReachabilityStatus GCReachabilityStatusForFlags(SCNetworkConnectionFlags flags);
static GCNetworkReachabilityStatus GCReachabilityStatusForFlags(SCNetworkReachabilityFlags flags);
static const void * GCNetworkReachabilityRetainCallback(const void *info);
static void GCNetworkReachabilityReleaseCallback(const void *info);
static void GCNetworkReachabilityCallbackWithBlock(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info);
static void GCNetworkReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info);
static void GCNetworkReachabilityPostNotification(void *info, GCNetworkReachabilityStatus status);
static void GCNetworkReachabilityPrintFlags(SCNetworkReachabilityFlags flags);
static struct sockaddr_in GCNetworkReachabilityCreateSocketAddress(void);
static struct sockaddr_in6 GCNetworkReachabilityCreateIPv6SocketAddress(void);

static BOOL _localWiFi;

Expand All @@ -82,49 +85,108 @@ @implementation GCNetworkReachability
void(^_handler_blk)(GCNetworkReachabilityStatus status);
}

static void GCNetworkReachabilityPrintFlags(SCNetworkReachabilityFlags flags)
{
#if 1
GCNRLog(@"GCNetworkReachability Flag Status: %c%c %c%c%c%c%c%c%c",
#if TARGET_OS_IPHONE
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
#else
'-',
#endif
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-'
);
#endif
}

+ (GCNetworkReachability *)reachabilityWithHostName:(NSString *)hostName
{
return hostName ? [[self alloc] initWithReachability:SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [hostName UTF8String])] : nil;
}

+ (GCNetworkReachability *)reachabilityWithHostAddress:(const struct sockaddr_in *)hostAddress
+ (GCNetworkReachability *)reachabilityWithHostAddress:(const struct sockaddr *)hostAddress
{
return hostAddress ? [[self alloc] initWithReachability:SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress)] : nil;
}

static struct sockaddr_in GCNetworkReachabilityCreateSocketAddress(void)
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
return addr;
}

+ (GCNetworkReachability *)reachabilityWithInternetAddress:(in_addr_t)internetAddress
{
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_len = sizeof(address);
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(internetAddress);
return [self reachabilityWithHostAddress:&address];
struct sockaddr_in addr = GCNetworkReachabilityCreateSocketAddress();
addr.sin_addr.s_addr = htonl(internetAddress);
return [self reachabilityWithHostAddress:(const struct sockaddr *)&addr];
}

+ (GCNetworkReachability *)reachabilityWithInternetAddressString:(NSString *)internetAddress
{
if (!internetAddress) return nil;

const char *addr = [internetAddress UTF8String];
const in_addr_t inetAddr = inet_addr(addr);
return [self reachabilityWithInternetAddress:inetAddr];
struct sockaddr_in addr = GCNetworkReachabilityCreateSocketAddress();
inet_pton(AF_INET, [internetAddress UTF8String], &addr.sin_addr);

return [self reachabilityWithHostAddress:(const struct sockaddr *)&addr];
}

+ (GCNetworkReachability *)reachabilityForInternetConnection
{
const in_addr_t zeroAddr = 0x00000000;
static const in_addr_t zeroAddr = INADDR_ANY;
return [self reachabilityWithInternetAddress:zeroAddr];
}

+ (GCNetworkReachability *)reachabilityForLocalWiFi
{
_localWiFi = YES;

const in_addr_t localAddr = 0xA9FE0000;
static const in_addr_t localAddr = IN_LINKLOCALNETNUM;
return [self reachabilityWithInternetAddress:localAddr];
}

static struct sockaddr_in6 GCNetworkReachabilityCreateIPv6SocketAddress(void)
{
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_len = sizeof(addr);
addr.sin6_family = AF_INET6;
return addr;
}

+ (GCNetworkReachability *)reachabilityWithIPv6Address:(const struct in6_addr)internetAddress
{
char strAddr[INET6_ADDRSTRLEN];

struct sockaddr_in6 addr = GCNetworkReachabilityCreateIPv6SocketAddress();
addr.sin6_addr = internetAddress;
inet_ntop(AF_INET6, &addr.sin6_addr, strAddr, INET6_ADDRSTRLEN);
inet_pton(AF_INET6, strAddr, &addr.sin6_addr);

return [self reachabilityWithHostAddress:(const struct sockaddr *)&addr];
}

+ (GCNetworkReachability *)reachabilityWithIPv6AddressString:(NSString *)internetAddress
{
if (!internetAddress) return nil;

struct sockaddr_in6 addr = GCNetworkReachabilityCreateIPv6SocketAddress();
inet_pton(AF_INET6, [internetAddress UTF8String], &addr.sin6_addr);

return [self reachabilityWithHostAddress:(const struct sockaddr *)&addr];
}

- (id)initWithHostAddress:(const struct sockaddr_in *)hostAddress
{
assert(hostAddress);
Expand Down Expand Up @@ -191,7 +253,7 @@ - (void)dealloc
}
}

static GCNetworkReachabilityStatus GCReachabilityStatusForFlags(SCNetworkConnectionFlags flags)
static GCNetworkReachabilityStatus GCReachabilityStatusForFlags(SCNetworkReachabilityFlags flags)
{
GCNetworkReachabilityStatus status = GCNetworkReachabilityStatusNotReachable;

Expand Down Expand Up @@ -277,12 +339,16 @@ static void GCNetworkReachabilityCallbackWithBlock(SCNetworkReachabilityRef __un
GCNetworkReachabilityStatus status = GCReachabilityStatusForFlags(flags);
void(^cb_blk)(GCNetworkReachabilityStatus status) = (__bridge void(^)(GCNetworkReachabilityStatus status))info;
if (cb_blk) cb_blk(status);

GCNetworkReachabilityPrintFlags(flags);
}

static void GCNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info)
{
GCNetworkReachabilityStatus status = GCReachabilityStatusForFlags(flags);
GCNetworkReachabilityPostNotification(info, status);

GCNetworkReachabilityPrintFlags(flags);
}

- (void)startMonitoringNetworkReachabilityWithHandler:(void(^)(GCNetworkReachabilityStatus status))block
Expand Down

0 comments on commit 24f5e96

Please sign in to comment.