~threeve/ubuntuone-ios-files/logout-cleanup

« back to all changes in this revision

Viewing changes to Dependencies/Reachability/Reachability.m

  • Committer: Zachery Bir
  • Date: 2011-11-01 14:28:05 UTC
  • mfrom: (6.2.116 auto-uploads-view)
  • Revision ID: zachery.bir@canonical.com-20111101142805-uyjwtzm552h638r2
Merged urbanape's auto-uploads-view branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
 File: Reachability.m
 
4
 Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
 
5
 
 
6
 Version: 2.0
 
7
 
 
8
 Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Inc.
 
9
 ("Apple") in consideration of your agreement to the following terms, and your
 
10
 use, installation, modification or redistribution of this Apple software
 
11
 constitutes acceptance of these terms.  If you do not agree with these terms,
 
12
 please do not use, install, modify or redistribute this Apple software.
 
13
 
 
14
 In consideration of your agreement to abide by the following terms, and subject
 
15
 to these terms, Apple grants you a personal, non-exclusive license, under
 
16
 Apple's copyrights in this original Apple software (the "Apple Software"), to
 
17
 use, reproduce, modify and redistribute the Apple Software, with or without
 
18
 modifications, in source and/or binary forms; provided that if you redistribute
 
19
 the Apple Software in its entirety and without modifications, you must retain
 
20
 this notice and the following text and disclaimers in all such redistributions
 
21
 of the Apple Software.
 
22
 Neither the name, trademarks, service marks or logos of Apple Inc. may be used
 
23
 to endorse or promote products derived from the Apple Software without specific
 
24
 prior written permission from Apple.  Except as expressly stated in this notice,
 
25
 no other rights or licenses, express or implied, are granted by Apple herein,
 
26
 including but not limited to any patent rights that may be infringed by your
 
27
 derivative works or by other works in which the Apple Software may be
 
28
 incorporated.
 
29
 
 
30
 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
 
31
 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 
32
 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
33
 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 
34
 COMBINATION WITH YOUR PRODUCTS.
 
35
 
 
36
 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 
37
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 
38
 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
39
 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
 
40
 DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
 
41
 CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
 
42
 APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
43
 
 
44
 Copyright (C) 2009 Apple Inc. All Rights Reserved.
 
45
 
 
46
*/
 
47
 
 
48
#import <sys/socket.h>
 
49
#import <netinet/in.h>
 
50
#import <netinet6/in6.h>
 
51
#import <arpa/inet.h>
 
52
#import <ifaddrs.h>
 
53
#import <netdb.h>
 
54
 
 
55
#import <CoreFoundation/CoreFoundation.h>
 
56
 
 
57
#import "Reachability.h"
 
58
 
 
59
#define kShouldPrintReachabilityFlags 0
 
60
 
 
61
static void PrintReachabilityFlags(SCNetworkReachabilityFlags    flags, const char* comment)
 
62
{
 
63
#if kShouldPrintReachabilityFlags
 
64
        
 
65
    NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
 
66
                        (flags & kSCNetworkReachabilityFlagsIsWWAN)                               ? 'W' : '-',
 
67
                        (flags & kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',
 
68
                        
 
69
                        (flags & kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',
 
70
                        (flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',
 
71
                        (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? 'C' : '-',
 
72
                        (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
 
73
                        (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-',
 
74
                        (flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',
 
75
                        (flags & kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-',
 
76
                        comment
 
77
                        );
 
78
#endif
 
79
}
 
80
 
 
81
 
 
82
@implementation Reachability
 
83
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
 
84
{
 
85
        #pragma unused (target, flags)
 
86
        NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
 
87
        NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
 
88
 
 
89
        //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
 
90
        // in case someon uses the Reachablity object in a different thread.
 
91
        NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
 
92
        
 
93
        Reachability* noteObject = (Reachability*) info;
 
94
        // Post a notification to notify the client that the network reachability changed.
 
95
        [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
 
96
        
 
97
        [myPool release];
 
98
}
 
99
 
 
100
- (BOOL) startNotifer
 
101
{
 
102
        BOOL retVal = NO;
 
103
        SCNetworkReachabilityContext    context = {0, self, NULL, NULL, NULL};
 
104
        if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
 
105
        {
 
106
                if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
 
107
                {
 
108
                        retVal = YES;
 
109
                }
 
110
        }
 
111
        return retVal;
 
112
}
 
113
 
 
114
- (void) stopNotifer
 
115
{
 
116
        if(reachabilityRef!= NULL)
 
117
        {
 
118
                SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
 
119
        }
 
120
}
 
121
 
 
122
- (void) dealloc
 
123
{
 
124
        [self stopNotifer];
 
125
        if(reachabilityRef!= NULL)
 
126
        {
 
127
                CFRelease(reachabilityRef);
 
128
        }
 
129
        [super dealloc];
 
130
}
 
131
 
 
132
+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
 
133
{
 
134
        Reachability* retVal = NULL;
 
135
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
 
136
        if(reachability!= NULL)
 
137
        {
 
138
                retVal= [[[self alloc] init] autorelease];
 
139
                if(retVal!= NULL)
 
140
                {
 
141
                        retVal->reachabilityRef = reachability;
 
142
                        retVal->localWiFiRef = NO;
 
143
                }
 
144
        }
 
145
        return retVal;
 
146
}
 
147
 
 
148
+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
 
149
{
 
150
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
 
151
        Reachability* retVal = NULL;
 
152
        if(reachability!= NULL)
 
153
        {
 
154
                retVal= [[[self alloc] init] autorelease];
 
155
                if(retVal!= NULL)
 
156
                {
 
157
                        retVal->reachabilityRef = reachability;
 
158
                        retVal->localWiFiRef = NO;
 
159
                }
 
160
        }
 
161
        return retVal;
 
162
}
 
163
 
 
164
+ (Reachability*) reachabilityForInternetConnection;
 
165
{
 
166
        struct sockaddr_in zeroAddress;
 
167
        bzero(&zeroAddress, sizeof(zeroAddress));
 
168
        zeroAddress.sin_len = sizeof(zeroAddress);
 
169
        zeroAddress.sin_family = AF_INET;
 
170
        return [self reachabilityWithAddress: &zeroAddress];
 
171
}
 
172
 
 
173
+ (Reachability*) reachabilityForLocalWiFi;
 
174
{
 
175
        //[super init];
 
176
        struct sockaddr_in localWifiAddress;
 
177
        bzero(&localWifiAddress, sizeof(localWifiAddress));
 
178
        localWifiAddress.sin_len = sizeof(localWifiAddress);
 
179
        localWifiAddress.sin_family = AF_INET;
 
180
        // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
 
181
        localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
 
182
        Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress];
 
183
        if(retVal!= NULL)
 
184
        {
 
185
                retVal->localWiFiRef = YES;
 
186
        }
 
187
        return retVal;
 
188
}
 
189
 
 
190
#pragma mark Network Flag Handling
 
191
 
 
192
- (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags
 
193
{
 
194
        PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
 
195
 
 
196
        BOOL retVal = NotReachable;
 
197
        if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
 
198
        {
 
199
                retVal = ReachableViaWiFi;      
 
200
        }
 
201
        return retVal;
 
202
}
 
203
 
 
204
- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags
 
205
{
 
206
        PrintReachabilityFlags(flags, "networkStatusForFlags");
 
207
        if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
 
208
        {
 
209
                // if target host is not reachable
 
210
                return NotReachable;
 
211
        }
 
212
 
 
213
        BOOL retVal = NotReachable;
 
214
        
 
215
        if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
 
216
        {
 
217
                // if target host is reachable and no connection is required
 
218
                //  then we'll assume (for now) that your on Wi-Fi
 
219
                retVal = ReachableViaWiFi;
 
220
        }
 
221
        
 
222
        
 
223
        if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
 
224
                (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
 
225
        {
 
226
                        // ... and the connection is on-demand (or on-traffic) if the
 
227
                        //     calling application is using the CFSocketStream or higher APIs
 
228
 
 
229
                        if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
 
230
                        {
 
231
                                // ... and no [user] intervention is needed
 
232
                                retVal = ReachableViaWiFi;
 
233
                        }
 
234
                }
 
235
        
 
236
        if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
 
237
        {
 
238
                // ... but WWAN connections are OK if the calling application
 
239
                //     is using the CFNetwork (CFSocketStream?) APIs.
 
240
                retVal = ReachableViaWWAN;
 
241
        }
 
242
        return retVal;
 
243
}
 
244
 
 
245
- (BOOL) connectionRequired;
 
246
{
 
247
        NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
 
248
        SCNetworkReachabilityFlags flags;
 
249
        if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
 
250
        {
 
251
                return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
 
252
        }
 
253
        return NO;
 
254
}
 
255
 
 
256
- (NetworkStatus) currentReachabilityStatus
 
257
{
 
258
        NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
 
259
        NetworkStatus retVal = NotReachable;
 
260
        SCNetworkReachabilityFlags flags;
 
261
        if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
 
262
        {
 
263
                if(localWiFiRef)
 
264
                {
 
265
                        retVal = [self localWiFiStatusForFlags: flags];
 
266
                }
 
267
                else
 
268
                {
 
269
                        retVal = [self networkStatusForFlags: flags];
 
270
                }
 
271
        }
 
272
        return retVal;
 
273
}
 
274
@end