Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the plugins of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qcorewlanengine.h" |
41 | #include "../qnetworksession_impl.h" |
42 | |
43 | #include <QtNetwork/private/qnetworkconfiguration_p.h> |
44 | |
45 | #include <QtCore/qthread.h> |
46 | #include <QtCore/qmutex.h> |
47 | #include <QtCore/qcoreapplication.h> |
48 | #include <QtCore/qstringlist.h> |
49 | |
50 | #include <QtCore/qdebug.h> |
51 | |
52 | #include <QDir> |
53 | #ifndef QT_NO_BEARERMANAGEMENT |
54 | |
55 | extern "C"{ // Otherwise it won't find CWKeychain* symbols at link time |
56 | #import <CoreWLAN/CoreWLAN.h> |
57 | } |
58 | |
59 | #include "private/qcore_mac_p.h" |
60 | |
61 | #include <net/if.h> |
62 | #include <ifaddrs.h> |
63 | |
64 | @interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject <CWEventDelegate> |
65 | |
66 | @property (assign) QCoreWlanEngine* engine; |
67 | |
68 | @end |
69 | |
70 | @implementation QT_MANGLE_NAMESPACE(QNSListener) { |
71 | NSNotificationCenter *notificationCenter; |
72 | CWWiFiClient *client; |
73 | QCoreWlanEngine *engine; |
74 | NSLock *locker; |
75 | } |
76 | |
77 | - (instancetype)init |
78 | { |
79 | if ((self = [super init])) { |
80 | [locker lock]; |
81 | QMacAutoReleasePool pool; |
82 | notificationCenter = [NSNotificationCenter defaultCenter]; |
83 | client = [CWWiFiClient sharedWiFiClient]; |
84 | client.delegate = self; |
85 | [client startMonitoringEventWithType:CWEventTypePowerDidChange error:nil]; |
86 | [locker unlock]; |
87 | } |
88 | return self; |
89 | } |
90 | |
91 | static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0; |
92 | |
93 | -(void)dealloc |
94 | { |
95 | client.delegate = nil; |
96 | listener = nil; |
97 | [super dealloc]; |
98 | } |
99 | |
100 | -(void)setEngine:(QCoreWlanEngine *)coreEngine |
101 | { |
102 | [locker lock]; |
103 | if(!engine) |
104 | engine = coreEngine; |
105 | [locker unlock]; |
106 | } |
107 | |
108 | -(QCoreWlanEngine *)engine |
109 | { |
110 | return engine; |
111 | } |
112 | |
113 | -(void)remove |
114 | { |
115 | [locker lock]; |
116 | [client stopMonitoringAllEventsAndReturnError:nil]; |
117 | [locker unlock]; |
118 | } |
119 | |
120 | - (void)powerStateDidChangeForWiFiInterfaceWithName:(NSString *)interfaceName |
121 | { |
122 | Q_UNUSED(interfaceName); |
123 | engine->requestUpdate(); |
124 | } |
125 | @end |
126 | |
127 | |
128 | QT_BEGIN_NAMESPACE |
129 | |
130 | void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info) |
131 | { |
132 | for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) { |
133 | |
134 | QString changed = QString::fromCFString((CFStringRef)CFArrayGetValueAtIndex(changedKeys, i)); |
135 | if( changed.contains("/Network/Global/IPv4")) { |
136 | QCoreWlanEngine* wlanEngine = static_cast<QCoreWlanEngine*>(info); |
137 | wlanEngine->requestUpdate(); |
138 | } |
139 | } |
140 | return; |
141 | } |
142 | |
143 | |
144 | QScanThread::QScanThread(QObject *parent) |
145 | :QThread(parent) |
146 | { |
147 | } |
148 | |
149 | QScanThread::~QScanThread() |
150 | { |
151 | } |
152 | |
153 | void QScanThread::quit() |
154 | { |
155 | wait(); |
156 | } |
157 | |
158 | void QScanThread::run() |
159 | { |
160 | QMacAutoReleasePool pool; |
161 | QStringList found; |
162 | mutex.lock(); |
163 | CWInterface *currentInterface = [[CWWiFiClient sharedWiFiClient] |
164 | interfaceWithName:interfaceName.toNSString()]; |
165 | mutex.unlock(); |
166 | const bool currentInterfaceServiceActive = currentInterface.serviceActive; |
167 | |
168 | if (currentInterface.powerOn) { |
169 | NSError *err = nil; |
170 | |
171 | NSSet* apSet = [currentInterface scanForNetworksWithName:nil error:&err]; |
172 | |
173 | if (!err) { |
174 | for (CWNetwork *apNetwork in apSet) { |
175 | const QString networkSsid = QString::fromNSString([apNetwork ssid]); |
176 | const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); |
177 | found.append(id); |
178 | |
179 | QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; |
180 | bool known = isKnownSsid(networkSsid); |
181 | if (currentInterfaceServiceActive) { |
182 | if (networkSsid == QString::fromNSString([currentInterface ssid])) { |
183 | state = QNetworkConfiguration::Active; |
184 | } |
185 | } |
186 | if (state == QNetworkConfiguration::Undefined) { |
187 | if(known) { |
188 | state = QNetworkConfiguration::Discovered; |
189 | } else { |
190 | state = QNetworkConfiguration::Undefined; |
191 | } |
192 | } |
193 | QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose; |
194 | if ([apNetwork supportsSecurity:kCWSecurityNone]) { |
195 | purpose = QNetworkConfiguration::PublicPurpose; |
196 | } else { |
197 | purpose = QNetworkConfiguration::PrivatePurpose; |
198 | } |
199 | |
200 | found.append(foundNetwork(id, networkSsid, state, interfaceName, purpose)); |
201 | |
202 | } |
203 | } |
204 | } |
205 | // add known configurations that are not around. |
206 | for (auto i = userProfiles.cbegin(), end = userProfiles.cend(); i != end; ++i) { |
207 | |
208 | QString networkName = i.key(); |
209 | const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName)); |
210 | |
211 | if(!found.contains(id)) { |
212 | QString networkSsid = getSsidFromNetworkName(networkName); |
213 | const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); |
214 | QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; |
215 | QString interfaceName; |
216 | if (!i.value().isEmpty()) |
217 | interfaceName = i.value().last(); |
218 | |
219 | if (currentInterfaceServiceActive) { |
220 | if (networkSsid == QString::fromNSString([currentInterface ssid])) { |
221 | state = QNetworkConfiguration::Active; |
222 | } |
223 | } |
224 | if(state == QNetworkConfiguration::Undefined) { |
225 | if( userProfiles.contains(networkName) |
226 | && found.contains(ssidId)) { |
227 | state = QNetworkConfiguration::Discovered; |
228 | } |
229 | } |
230 | |
231 | if(state == QNetworkConfiguration::Undefined) { |
232 | state = QNetworkConfiguration::Defined; |
233 | } |
234 | |
235 | found.append(foundNetwork(id, networkName, state, interfaceName, QNetworkConfiguration::UnknownPurpose)); |
236 | } |
237 | } |
238 | emit networksChanged(); |
239 | } |
240 | |
241 | QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose) |
242 | { |
243 | QStringList found; |
244 | QMutexLocker locker(&mutex); |
245 | QNetworkConfigurationPrivate *ptr = new QNetworkConfigurationPrivate; |
246 | |
247 | ptr->name = name; |
248 | ptr->isValid = true; |
249 | ptr->id = id; |
250 | ptr->state = state; |
251 | ptr->type = QNetworkConfiguration::InternetAccessPoint; |
252 | ptr->bearerType = QNetworkConfiguration::BearerWLAN; |
253 | ptr->purpose = purpose; |
254 | |
255 | fetchedConfigurations.append( ptr); |
256 | configurationInterface.insert(ptr->id, interfaceName); |
257 | |
258 | locker.unlock(); |
259 | locker.relock(); |
260 | found.append(id); |
261 | return found; |
262 | } |
263 | |
264 | QList<QNetworkConfigurationPrivate *> QScanThread::getConfigurations() |
265 | { |
266 | QMutexLocker locker(&mutex); |
267 | return qExchange(fetchedConfigurations, {}); |
268 | } |
269 | |
270 | void QScanThread::getUserConfigurations() |
271 | { |
272 | QMutexLocker locker(&mutex); |
273 | |
274 | QMacAutoReleasePool pool; |
275 | userProfiles.clear(); |
276 | |
277 | NSArray<NSString *> *wifiInterfaces = [CWWiFiClient interfaceNames]; |
278 | for (NSString *ifName in wifiInterfaces) { |
279 | |
280 | CWInterface *wifiInterface = [[CWWiFiClient sharedWiFiClient] interfaceWithName:ifName]; |
281 | |
282 | NSString *nsInterfaceName = wifiInterface.ssid; |
283 | // add user configured system networks |
284 | SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil); |
285 | NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]); |
286 | CFRelease(dynRef); |
287 | if(airportPlist != nil) { |
288 | NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"]; |
289 | |
290 | NSArray<NSString *> *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"]; |
291 | for (NSString *ssidkey in thisSsidarray) { |
292 | QString thisSsid = QString::fromNSString(ssidkey); |
293 | if(!userProfiles.contains(thisSsid)) { |
294 | QMap <QString,QString> map; |
295 | map.insert(thisSsid, QString::fromNSString(nsInterfaceName)); |
296 | userProfiles.insert(thisSsid, map); |
297 | } |
298 | } |
299 | CFRelease(airportPlist); |
300 | } |
301 | |
302 | // remembered networks |
303 | CWConfiguration *userConfig = [wifiInterface configuration]; |
304 | NSOrderedSet *networkProfiles = [userConfig networkProfiles]; |
305 | NSEnumerator *enumerator = [networkProfiles objectEnumerator]; |
306 | CWNetworkProfile *wProfile; |
307 | while ((wProfile = [enumerator nextObject])) { |
308 | QString networkName = QString::fromNSString([wProfile ssid]); |
309 | |
310 | if (!userProfiles.contains(networkName)) { |
311 | QMap<QString,QString> map; |
312 | map.insert(networkName, QString::fromNSString(nsInterfaceName)); |
313 | userProfiles.insert(networkName, map); |
314 | } |
315 | } |
316 | |
317 | // 802.1X user profiles |
318 | QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist"; |
319 | NSDictionary* eapDict = [[[NSDictionary alloc] initWithContentsOfFile:userProfilePath.toNSString()] autorelease]; |
320 | if(eapDict != nil) { |
321 | NSString *profileStr= @"Profiles"; |
322 | NSString *nameStr = @"UserDefinedName"; |
323 | NSString *networkSsidStr = @"Wireless Network"; |
324 | for (id profileKey in eapDict) { |
325 | if ([profileStr isEqualToString:profileKey]) { |
326 | NSDictionary *itemDict = [eapDict objectForKey:profileKey]; |
327 | for (id itemKey in itemDict) { |
328 | |
329 | NSInteger dictSize = [itemKey count]; |
330 | id objects[dictSize]; |
331 | id keys[dictSize]; |
332 | |
333 | [itemKey getObjects:objects andKeys:keys]; |
334 | QString networkName; |
335 | QString ssid; |
336 | for (int i = 0; i < dictSize; i++) { |
337 | if([nameStr isEqualToString:keys[i]]) { |
338 | networkName = QString::fromNSString(objects[i]); |
339 | } |
340 | if ([networkSsidStr isEqualToString:keys[i]]) { |
341 | ssid = QString::fromNSString(objects[i]); |
342 | } |
343 | if (!userProfiles.contains(networkName) |
344 | && !ssid.isEmpty()) { |
345 | QMap<QString,QString> map; |
346 | map.insert(ssid, QString::fromNSString(nsInterfaceName)); |
347 | userProfiles.insert(networkName, map); |
348 | } |
349 | } |
350 | } |
351 | } |
352 | } |
353 | } |
354 | } |
355 | } |
356 | |
357 | QString QScanThread::getSsidFromNetworkName(const QString &name) const |
358 | { |
359 | QMutexLocker locker(&mutex); |
360 | |
361 | for (auto i = userProfiles.cbegin(), end = userProfiles.cend(); i != end; ++i) { |
362 | for (auto ij = i.value().cbegin(), end = i.value().cend(); ij != end; ++ij) { |
363 | const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key())); |
364 | if(name == i.key() || name == networkNameHash) { |
365 | return ij.key(); |
366 | } |
367 | } |
368 | } |
369 | return QString(); |
370 | } |
371 | |
372 | QString QScanThread::getNetworkNameFromSsid(const QString &ssid) const |
373 | { |
374 | QMutexLocker locker(&mutex); |
375 | |
376 | for (auto i = userProfiles.cbegin(), end = userProfiles.cend(); i != end; ++i) { |
377 | if (i.value().contains(ssid)) |
378 | return i.key(); |
379 | } |
380 | return QString(); |
381 | } |
382 | |
383 | bool QScanThread::isKnownSsid(const QString &ssid) const |
384 | { |
385 | QMutexLocker locker(&mutex); |
386 | |
387 | for (auto i = userProfiles.cbegin(), end = userProfiles.cend(); i != end; ++i) { |
388 | if (i.value().contains(ssid)) |
389 | return true; |
390 | } |
391 | return false; |
392 | } |
393 | |
394 | |
395 | QCoreWlanEngine::QCoreWlanEngine(QObject *parent) |
396 | : QBearerEngineImpl(parent), scanThread(0) |
397 | { |
398 | scanThread = new QScanThread(this); |
399 | connect(scanThread, SIGNAL(networksChanged()), |
400 | this, SLOT(networksChanged())); |
401 | } |
402 | |
403 | QCoreWlanEngine::~QCoreWlanEngine() |
404 | { |
405 | scanThread->wait(); |
406 | |
407 | qDeleteAll(qExchange(foundConfigurations, {})); |
408 | [listener remove]; |
409 | [listener release]; |
410 | } |
411 | |
412 | void QCoreWlanEngine::initialize() |
413 | { |
414 | QMutexLocker locker(&mutex); |
415 | QMacAutoReleasePool pool; |
416 | |
417 | if ([[CWWiFiClient interfaceNames] count] > 0 && !listener) { |
418 | listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init]; |
419 | listener.engine = this; |
420 | hasWifi = true; |
421 | } else { |
422 | hasWifi = false; |
423 | } |
424 | storeSession = NULL; |
425 | |
426 | startNetworkChangeLoop(); |
427 | } |
428 | |
429 | |
430 | QString QCoreWlanEngine::getInterfaceFromId(const QString &id) |
431 | { |
432 | QMutexLocker locker(&mutex); |
433 | |
434 | return scanThread->configurationInterface.value(id); |
435 | } |
436 | |
437 | bool QCoreWlanEngine::hasIdentifier(const QString &id) |
438 | { |
439 | QMutexLocker locker(&mutex); |
440 | |
441 | return scanThread->configurationInterface.contains(id); |
442 | } |
443 | |
444 | void QCoreWlanEngine::connectToId(const QString &id) |
445 | { |
446 | QMutexLocker locker(&mutex); |
447 | QMacAutoReleasePool pool; |
448 | QString interfaceString = getInterfaceFromId(id); |
449 | |
450 | CWInterface *wifiInterface = |
451 | [[CWWiFiClient sharedWiFiClient] interfaceWithName:interfaceString.toNSString()]; |
452 | |
453 | if (wifiInterface.powerOn) { |
454 | NSError *err = nil; |
455 | QString wantedSsid; |
456 | QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); |
457 | |
458 | const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + ptr->name)); |
459 | const QString idHash2 = QString::number(qHash(QLatin1String("corewlan:") + scanThread->getNetworkNameFromSsid(ptr->name))); |
460 | |
461 | QString wantedNetwork; |
462 | for (auto i = scanThread->userProfiles.cbegin(), end = scanThread->userProfiles.cend(); i != end; ++i) { |
463 | wantedNetwork = i.key(); |
464 | const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + wantedNetwork)); |
465 | if (id == networkNameHash) { |
466 | wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork); |
467 | break; |
468 | } |
469 | } |
470 | |
471 | NSSet *scanSet = [wifiInterface scanForNetworksWithName:wantedSsid.toNSString() error:&err]; |
472 | |
473 | if(!err) { |
474 | for (CWNetwork *apNetwork in scanSet) { |
475 | NSData *ssidData = [apNetwork ssidData]; |
476 | bool result = false; |
477 | |
478 | SecIdentityRef identity = 0; |
479 | // Check first whether we require IEEE 802.1X authentication for the wanted SSID |
480 | if (CWKeychainCopyWiFiEAPIdentity(kCWKeychainDomainSystem, ssidData, &identity) == errSecSuccess) { |
481 | NSString *username = nil; |
482 | NSString *password = nil; |
483 | if (CWKeychainFindWiFiEAPUsernameAndPassword(kCWKeychainDomainSystem, ssidData, &username, &password) == errSecSuccess) { |
484 | result = [wifiInterface associateToEnterpriseNetwork:apNetwork |
485 | identity:identity username:(NSString *)username password:(NSString *)password |
486 | error:&err]; |
487 | [username release]; |
488 | [password release]; |
489 | } |
490 | CFRelease(identity); |
491 | } else { |
492 | NSString *password = nil; |
493 | if (CWKeychainFindWiFiPassword(kCWKeychainDomainSystem, ssidData, &password) == errSecSuccess) { |
494 | result = [wifiInterface associateToNetwork:apNetwork password:(NSString *)password error:&err]; |
495 | [password release]; |
496 | } |
497 | } |
498 | |
499 | if (!err) { |
500 | if (!result) { |
501 | emit connectionError(id, ConnectError); |
502 | } else { |
503 | return; |
504 | } |
505 | } else { |
506 | qDebug() <<"associate ERROR"<< QString::fromNSString([err localizedDescription ]); |
507 | } |
508 | } //end scan network |
509 | } else { |
510 | qDebug() <<"scan ERROR"<< QString::fromNSString([err localizedDescription ]); |
511 | } |
512 | emit connectionError(id, InterfaceLookupError); |
513 | } |
514 | |
515 | locker.unlock(); |
516 | emit connectionError(id, InterfaceLookupError); |
517 | } |
518 | |
519 | void QCoreWlanEngine::disconnectFromId(const QString &id) |
520 | { |
521 | QMutexLocker locker(&mutex); |
522 | |
523 | QString interfaceString = getInterfaceFromId(id); |
524 | if (interfaceString.isEmpty()) { |
525 | locker.unlock(); |
526 | emit connectionError(id, DisconnectionError); |
527 | return; |
528 | } |
529 | QMacAutoReleasePool pool; |
530 | |
531 | CWInterface *wifiInterface = |
532 | [[CWWiFiClient sharedWiFiClient] interfaceWithName:interfaceString.toNSString()]; |
533 | disconnectedInterfaceString = interfaceString; |
534 | |
535 | [wifiInterface disassociate]; |
536 | |
537 | QTimer::singleShot(1000, this,SLOT(checkDisconnect())); |
538 | } |
539 | |
540 | void QCoreWlanEngine::checkDisconnect() |
541 | { |
542 | QMutexLocker locker(&mutex); |
543 | if (!disconnectedInterfaceString.isEmpty()) { |
544 | QMacAutoReleasePool pool; |
545 | |
546 | CWInterface *wifiInterface = [[CWWiFiClient sharedWiFiClient] |
547 | interfaceWithName:disconnectedInterfaceString.toNSString()]; |
548 | |
549 | const QString networkSsid = QString::fromNSString([wifiInterface ssid]); |
550 | if (!networkSsid.isEmpty()) { |
551 | const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); |
552 | locker.unlock(); |
553 | emit connectionError(id, DisconnectionError); |
554 | locker.relock(); |
555 | } |
556 | disconnectedInterfaceString.clear(); |
557 | } |
558 | } |
559 | |
560 | void QCoreWlanEngine::requestUpdate() |
561 | { |
562 | scanThread->getUserConfigurations(); |
563 | doRequestUpdate(); |
564 | } |
565 | |
566 | void QCoreWlanEngine::doRequestUpdate() |
567 | { |
568 | QMutexLocker locker(&mutex); |
569 | |
570 | QMacAutoReleasePool pool; |
571 | |
572 | NSArray<NSString *> *wifiInterfaces = [CWWiFiClient interfaceNames]; |
573 | for (NSString *ifName in wifiInterfaces) { |
574 | scanThread->interfaceName = QString::fromNSString(ifName); |
575 | scanThread->start(); |
576 | } |
577 | locker.unlock(); |
578 | if ([wifiInterfaces count] == 0) |
579 | networksChanged(); |
580 | } |
581 | |
582 | bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) |
583 | { |
584 | QMutexLocker locker(&mutex); |
585 | bool haswifi = false; |
586 | if(hasWifi) { |
587 | QMacAutoReleasePool pool; |
588 | CWInterface *defaultInterface = [[CWWiFiClient sharedWiFiClient] |
589 | interfaceWithName:wifiDeviceName.toNSString()]; |
590 | if (defaultInterface.powerOn) { |
591 | haswifi = true; |
592 | } |
593 | } |
594 | return haswifi; |
595 | } |
596 | |
597 | |
598 | QNetworkSession::State QCoreWlanEngine::sessionStateForId(const QString &id) |
599 | { |
600 | QMutexLocker locker(&mutex); |
601 | QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); |
602 | |
603 | if (!ptr) |
604 | return QNetworkSession::Invalid; |
605 | |
606 | if (!ptr->isValid) { |
607 | return QNetworkSession::Invalid; |
608 | } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { |
609 | return QNetworkSession::Connected; |
610 | } else if ((ptr->state & QNetworkConfiguration::Discovered) == |
611 | QNetworkConfiguration::Discovered) { |
612 | return QNetworkSession::Disconnected; |
613 | } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { |
614 | return QNetworkSession::NotAvailable; |
615 | } else if ((ptr->state & QNetworkConfiguration::Undefined) == |
616 | QNetworkConfiguration::Undefined) { |
617 | return QNetworkSession::NotAvailable; |
618 | } |
619 | |
620 | return QNetworkSession::Invalid; |
621 | } |
622 | |
623 | QNetworkConfigurationManager::Capabilities QCoreWlanEngine::capabilities() const |
624 | { |
625 | return QNetworkConfigurationManager::ForcedRoaming; |
626 | } |
627 | |
628 | void QCoreWlanEngine::startNetworkChangeLoop() |
629 | { |
630 | |
631 | SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL }; |
632 | storeSession = SCDynamicStoreCreate(NULL, |
633 | CFSTR("networkChangeCallback"), |
634 | networkChangeCallback, |
635 | &dynStoreContext); |
636 | if (!storeSession ) { |
637 | qWarning() << "could not open dynamic store: error:"<< SCErrorString(SCError()); |
638 | return; |
639 | } |
640 | |
641 | CFMutableArrayRef notificationKeys; |
642 | notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
643 | CFMutableArrayRef patternsArray; |
644 | patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
645 | |
646 | CFStringRef storeKey; |
647 | storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, |
648 | kSCDynamicStoreDomainState, |
649 | kSCEntNetIPv4); |
650 | CFArrayAppendValue(notificationKeys, storeKey); |
651 | CFRelease(storeKey); |
652 | |
653 | storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, |
654 | kSCDynamicStoreDomainState, |
655 | kSCCompAnyRegex, |
656 | kSCEntNetIPv4); |
657 | CFArrayAppendValue(patternsArray, storeKey); |
658 | CFRelease(storeKey); |
659 | |
660 | if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) { |
661 | qWarning() << "register notification error:"<< SCErrorString(SCError()); |
662 | CFRelease(storeSession ); |
663 | CFRelease(notificationKeys); |
664 | CFRelease(patternsArray); |
665 | return; |
666 | } |
667 | CFRelease(notificationKeys); |
668 | CFRelease(patternsArray); |
669 | |
670 | runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0); |
671 | if (!runloopSource) { |
672 | qWarning() << "runloop source error:"<< SCErrorString(SCError()); |
673 | CFRelease(storeSession ); |
674 | return; |
675 | } |
676 | |
677 | CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode); |
678 | return; |
679 | } |
680 | |
681 | QNetworkSessionPrivate *QCoreWlanEngine::createSessionBackend() |
682 | { |
683 | return new QNetworkSessionPrivateImpl; |
684 | } |
685 | |
686 | QNetworkConfigurationPrivatePointer QCoreWlanEngine::defaultConfiguration() |
687 | { |
688 | return QNetworkConfigurationPrivatePointer(); |
689 | } |
690 | |
691 | bool QCoreWlanEngine::requiresPolling() const |
692 | { |
693 | return true; |
694 | } |
695 | |
696 | void QCoreWlanEngine::networksChanged() |
697 | { |
698 | QMutexLocker locker(&mutex); |
699 | |
700 | QStringList previous = accessPointConfigurations.keys(); |
701 | |
702 | QList<QNetworkConfigurationPrivate *> foundConfigurations = scanThread->getConfigurations(); |
703 | while (!foundConfigurations.isEmpty()) { |
704 | QNetworkConfigurationPrivate *cpPriv = foundConfigurations.takeFirst(); |
705 | |
706 | previous.removeAll(cpPriv->id); |
707 | |
708 | if (accessPointConfigurations.contains(cpPriv->id)) { |
709 | QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id); |
710 | |
711 | bool changed = false; |
712 | |
713 | ptr->mutex.lock(); |
714 | |
715 | if (ptr->isValid != cpPriv->isValid) { |
716 | ptr->isValid = cpPriv->isValid; |
717 | changed = true; |
718 | } |
719 | |
720 | if (ptr->name != cpPriv->name) { |
721 | ptr->name = cpPriv->name; |
722 | changed = true; |
723 | } |
724 | |
725 | if (ptr->bearerType != cpPriv->bearerType) { |
726 | ptr->bearerType = cpPriv->bearerType; |
727 | changed = true; |
728 | } |
729 | |
730 | if (ptr->state != cpPriv->state) { |
731 | ptr->state = cpPriv->state; |
732 | changed = true; |
733 | } |
734 | |
735 | ptr->mutex.unlock(); |
736 | |
737 | if (changed) { |
738 | locker.unlock(); |
739 | emit configurationChanged(ptr); |
740 | locker.relock(); |
741 | } |
742 | |
743 | delete cpPriv; |
744 | } else { |
745 | QNetworkConfigurationPrivatePointer ptr(cpPriv); |
746 | |
747 | accessPointConfigurations.insert(ptr->id, ptr); |
748 | |
749 | locker.unlock(); |
750 | emit configurationAdded(ptr); |
751 | locker.relock(); |
752 | } |
753 | } |
754 | |
755 | while (!previous.isEmpty()) { |
756 | QNetworkConfigurationPrivatePointer ptr = |
757 | accessPointConfigurations.take(previous.takeFirst()); |
758 | |
759 | locker.unlock(); |
760 | emit configurationRemoved(ptr); |
761 | locker.relock(); |
762 | } |
763 | |
764 | locker.unlock(); |
765 | emit updateCompleted(); |
766 | |
767 | } |
768 | |
769 | quint64 QCoreWlanEngine::bytesWritten(const QString &id) |
770 | { |
771 | QMutexLocker locker(&mutex); |
772 | const QString interfaceStr = getInterfaceFromId(id); |
773 | return getBytes(interfaceStr,false); |
774 | } |
775 | |
776 | quint64 QCoreWlanEngine::bytesReceived(const QString &id) |
777 | { |
778 | QMutexLocker locker(&mutex); |
779 | const QString interfaceStr = getInterfaceFromId(id); |
780 | return getBytes(interfaceStr,true); |
781 | } |
782 | |
783 | quint64 QCoreWlanEngine::startTime(const QString &identifier) |
784 | { |
785 | QMutexLocker locker(&mutex); |
786 | QMacAutoReleasePool pool; |
787 | quint64 timestamp = 0; |
788 | |
789 | NSString *filePath = @"/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist"; |
790 | NSDictionary* plistDict = [[[NSDictionary alloc] initWithContentsOfFile:filePath] autorelease]; |
791 | if(plistDict == nil) |
792 | return timestamp; |
793 | NSString *input = @"KnownNetworks"; |
794 | NSString *timeStampStr = @"_timeStamp"; |
795 | |
796 | NSString *ssidStr = @"SSID_STR"; |
797 | |
798 | for (id key in plistDict) { |
799 | if ([input isEqualToString:key]) { |
800 | |
801 | NSDictionary *knownNetworksDict = [plistDict objectForKey:key]; |
802 | if(knownNetworksDict == nil) |
803 | return timestamp; |
804 | for (id networkKey in knownNetworksDict) { |
805 | bool isFound = false; |
806 | NSDictionary *itemDict = [knownNetworksDict objectForKey:networkKey]; |
807 | if(itemDict == nil) |
808 | return timestamp; |
809 | NSInteger dictSize = [itemDict count]; |
810 | id objects[dictSize]; |
811 | id keys[dictSize]; |
812 | |
813 | [itemDict getObjects:objects andKeys:keys]; |
814 | bool ok = false; |
815 | for(int i = 0; i < dictSize; i++) { |
816 | if([ssidStr isEqualToString:keys[i]]) { |
817 | const QString ident = QString::number(qHash(QLatin1String("corewlan:") + QString::fromNSString(objects[i]))); |
818 | if(ident == identifier) { |
819 | ok = true; |
820 | } |
821 | } |
822 | if(ok && [timeStampStr isEqualToString:keys[i]]) { |
823 | timestamp = (quint64)[objects[i] timeIntervalSince1970]; |
824 | isFound = true; |
825 | break; |
826 | } |
827 | } |
828 | if(isFound) |
829 | break; |
830 | } |
831 | } |
832 | } |
833 | return timestamp; |
834 | } |
835 | |
836 | quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b) |
837 | { |
838 | struct ifaddrs *ifAddressList, *ifAddress; |
839 | struct if_data *if_data; |
840 | |
841 | quint64 bytes = 0; |
842 | ifAddressList = nil; |
843 | if(getifaddrs(&ifAddressList) == 0) { |
844 | for(ifAddress = ifAddressList; ifAddress; ifAddress = ifAddress->ifa_next) { |
845 | if(interfaceName == ifAddress->ifa_name) { |
846 | if_data = (struct if_data*)ifAddress->ifa_data; |
847 | if(b) { |
848 | bytes = if_data->ifi_ibytes; |
849 | break; |
850 | } else { |
851 | bytes = if_data->ifi_obytes; |
852 | break; |
853 | } |
854 | } |
855 | } |
856 | freeifaddrs(ifAddressList); |
857 | } |
858 | return bytes; |
859 | } |
860 | |
861 | QT_END_NAMESPACE |
862 | |
863 | #endif |
864 |
Warning: That file was not part of the compilation database. It may have many parsing errors.