159 } |
157 } |
160 } |
158 } |
161 return; |
159 return; |
162 } |
160 } |
163 |
161 |
164 QCoreWlanEngine::QCoreWlanEngine(QObject *parent) |
162 QScanThread::QScanThread(QObject *parent) |
165 : QNetworkSessionEngine(parent) |
163 :QThread(parent), interfaceName(nil) |
166 { |
164 { |
|
165 } |
|
166 |
|
167 QScanThread::~QScanThread() |
|
168 { |
|
169 } |
|
170 |
|
171 void QScanThread::quit() |
|
172 { |
|
173 wait(); |
|
174 } |
|
175 |
|
176 void QScanThread::run() |
|
177 { |
|
178 #if defined(MAC_SDK_10_6) |
|
179 getUserProfiles(); |
167 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
180 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
168 getAllScInterfaces(); |
181 QStringList found; |
169 startNetworkChangeLoop(); |
182 mutex.lock(); |
170 #ifdef MAC_SDK_10_6 |
183 CWInterface *currentInterface; |
171 if([[CWInterface supportedInterfaces] count] > 0 ) { |
184 if(interfaceName.isEmpty()) { |
172 QNSListener *listener; |
185 currentInterface = [CWInterface interfaceWithName:nil]; |
173 listener = [[QNSListener alloc] init]; |
186 interfaceName = nsstringToQString([currentInterface name]); |
174 hasWifi = true; |
|
175 } else { |
187 } else { |
176 hasWifi = false; |
188 currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)]; |
177 } |
189 } |
178 #endif |
190 mutex.unlock(); |
179 getUserConfigurations(); |
191 |
180 requestUpdate(); |
192 if([currentInterface power]) { |
181 [pool release]; |
193 NSError *err = nil; |
182 } |
194 NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys: |
183 |
195 [NSNumber numberWithBool:YES], kCWScanKeyMerge, |
184 QCoreWlanEngine::~QCoreWlanEngine() |
196 [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil]; |
185 { |
197 |
186 QNetworkConfigurationPrivate* cpPriv = 0; |
198 NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; |
187 foundConfigurations.clear(); |
199 CWNetwork *apNetwork; |
188 while(!foundConfigurations.isEmpty()) { |
200 |
189 cpPriv = foundConfigurations.takeFirst(); |
201 if (!err) { |
190 delete cpPriv; |
202 for(uint row=0; row < [apArray count]; row++ ) { |
191 } |
203 apNetwork = [apArray objectAtIndex:row]; |
192 } |
204 |
193 |
205 const QString networkSsid = nsstringToQString([apNetwork ssid]); |
194 QList<QNetworkConfigurationPrivate *> QCoreWlanEngine::getConfigurations(bool *ok) |
206 found.append(networkSsid); |
195 { |
207 |
196 if (ok) |
208 QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; |
197 *ok = true; |
209 |
198 foundConfigurations.clear(); |
210 bool known = isKnownSsid(networkSsid); |
199 |
211 if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { |
200 uint identifier; |
212 if( networkSsid == nsstringToQString( [currentInterface ssid])) { |
201 QMapIterator<QString, QString> i(networkInterfaces); |
213 state = QNetworkConfiguration::Active; |
202 QNetworkConfigurationPrivate* cpPriv = 0; |
|
203 while (i.hasNext()) { |
|
204 i.next(); |
|
205 if (i.value() == "WLAN") { |
|
206 QList<QNetworkConfigurationPrivate *> fetchedConfigurations = scanForSsids(i.key()); |
|
207 for (int i = 0; i < fetchedConfigurations.count(); ++i) { |
|
208 |
|
209 QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate(); |
|
210 cpPriv = fetchedConfigurations.at(i); |
|
211 config->name = cpPriv->name; |
|
212 config->isValid = cpPriv->isValid; |
|
213 config->id = cpPriv->id; |
|
214 |
|
215 config->state = cpPriv->state; |
|
216 config->type = cpPriv->type; |
|
217 config->roamingSupported = cpPriv->roamingSupported; |
|
218 config->purpose = cpPriv->purpose; |
|
219 config->internet = cpPriv->internet; |
|
220 config->serviceInterface = cpPriv->serviceInterface; |
|
221 config->bearer = cpPriv->bearer; |
|
222 |
|
223 identifier = config->name.toUInt(); |
|
224 configurationInterface[identifier] = config->serviceInterface.name(); |
|
225 foundConfigurations.append(config); |
|
226 delete cpPriv; |
|
227 } |
|
228 } |
|
229 |
|
230 QNetworkInterface interface = QNetworkInterface::interfaceFromName(i.key()); |
|
231 QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate(); |
|
232 const QString humanReadableName = interface.humanReadableName(); |
|
233 cpPriv->name = humanReadableName.isEmpty() ? interface.name() : humanReadableName; |
|
234 cpPriv->isValid = true; |
|
235 |
|
236 if (interface.index()) |
|
237 identifier = interface.index(); |
|
238 else |
|
239 identifier = qHash(interface.hardwareAddress()); |
|
240 |
|
241 cpPriv->id = QString::number(identifier); |
|
242 cpPriv->type = QNetworkConfiguration::InternetAccessPoint; |
|
243 cpPriv->state = QNetworkConfiguration::Undefined; |
|
244 |
|
245 if (interface.flags() & QNetworkInterface::IsRunning) { |
|
246 cpPriv->state = QNetworkConfiguration::Defined; |
|
247 cpPriv->internet = true; |
|
248 } |
|
249 if ( !interface.addressEntries().isEmpty()) { |
|
250 cpPriv->state |= QNetworkConfiguration::Active; |
|
251 cpPriv->internet = true; |
|
252 } |
|
253 configurationInterface[identifier] = interface.name(); |
|
254 cpPriv->bearer = interface.name().isEmpty()? QLatin1String("Unknown") : qGetInterfaceType(interface.name()); |
|
255 foundConfigurations.append(cpPriv); |
|
256 } |
|
257 |
|
258 pollTimer.start(); |
|
259 return foundConfigurations; |
|
260 } |
|
261 |
|
262 QString QCoreWlanEngine::getInterfaceFromId(const QString &id) |
|
263 { |
|
264 return configurationInterface.value(id.toUInt()); |
|
265 } |
|
266 |
|
267 bool QCoreWlanEngine::hasIdentifier(const QString &id) |
|
268 { |
|
269 return configurationInterface.contains(id.toUInt()); |
|
270 } |
|
271 |
|
272 void QCoreWlanEngine::connectToId(const QString &id) |
|
273 { |
|
274 QString interfaceString = getInterfaceFromId(id); |
|
275 |
|
276 if(networkInterfaces.value(interfaceString) == "WLAN") { |
|
277 #if defined(MAC_SDK_10_6) |
|
278 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
279 CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; |
|
280 |
|
281 if([wifiInterface power]) { |
|
282 NSError *err = nil; |
|
283 NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; |
|
284 |
|
285 QString wantedSsid = 0; |
|
286 bool using8021X = false; |
|
287 |
|
288 if(getNetworkNameFromSsid(id) != id) { |
|
289 NSArray *array = [CW8021XProfile allUser8021XProfiles]; |
|
290 for (NSUInteger i=0; i<[array count]; ++i) { |
|
291 |
|
292 if(id == nsstringToQString([[array objectAtIndex:i] userDefinedName]) |
|
293 || id == nsstringToQString([[array objectAtIndex:i] ssid]) ) { |
|
294 QString thisName = getSsidFromNetworkName(id); |
|
295 if(thisName.isEmpty()) { |
|
296 wantedSsid = id; |
|
297 } else { |
|
298 wantedSsid = thisName; |
|
299 } |
|
300 [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile]; |
|
301 using8021X = true; |
|
302 break; |
|
303 } |
214 } |
304 } |
215 } |
305 } |
216 if(state == QNetworkConfiguration::Undefined) { |
306 |
217 if(known) { |
307 if(!using8021X) { |
218 state = QNetworkConfiguration::Discovered; |
308 QString wantedNetwork; |
219 } else { |
309 QMapIterator<QString, QMap<QString,QString> > i(userProfiles); |
220 state = QNetworkConfiguration::Undefined; |
310 while (i.hasNext()) { |
|
311 i.next(); |
|
312 wantedNetwork = i.key(); |
|
313 if(id == wantedNetwork) { |
|
314 wantedSsid = getSsidFromNetworkName(wantedNetwork); |
|
315 break; |
|
316 } |
221 } |
317 } |
222 } |
318 } |
223 |
319 |
224 QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose; |
320 NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys: |
225 if([[apNetwork securityMode] intValue] == kCWSecurityModeOpen) { |
321 [NSNumber numberWithBool:YES], kCWScanKeyMerge, |
226 purpose = QNetworkConfiguration::PublicPurpose; |
322 [NSNumber numberWithInteger:100], kCWScanKeyRestTime, |
227 } else { |
323 qstringToNSString(wantedSsid), kCWScanKeySSID, |
228 purpose = QNetworkConfiguration::PrivatePurpose; |
324 nil]; |
|
325 |
|
326 |
|
327 NSArray *scanArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; |
|
328 if(!err) { |
|
329 for(uint row=0; row < [scanArray count]; row++ ) { |
|
330 CWNetwork *apNetwork = [scanArray objectAtIndex:row]; |
|
331 if(wantedSsid == nsstringToQString([apNetwork ssid])) { |
|
332 |
|
333 if(!using8021X) { |
|
334 SecKeychainAttribute attributes[3]; |
|
335 |
|
336 NSString *account = [apNetwork ssid]; |
|
337 NSString *keyKind = @"AirPort network password"; |
|
338 NSString *keyName = account; |
|
339 |
|
340 attributes[0].tag = kSecAccountItemAttr; |
|
341 attributes[0].data = (void *)[account UTF8String]; |
|
342 attributes[0].length = [account length]; |
|
343 |
|
344 attributes[1].tag = kSecDescriptionItemAttr; |
|
345 attributes[1].data = (void *)[keyKind UTF8String]; |
|
346 attributes[1].length = [keyKind length]; |
|
347 |
|
348 attributes[2].tag = kSecLabelItemAttr; |
|
349 attributes[2].data = (void *)[keyName UTF8String]; |
|
350 attributes[2].length = [keyName length]; |
|
351 |
|
352 SecKeychainAttributeList attributeList = {3,attributes}; |
|
353 |
|
354 SecKeychainSearchRef searchRef; |
|
355 OSErr result = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef); |
|
356 |
|
357 NSString *password = @""; |
|
358 SecKeychainItemRef searchItem; |
|
359 |
|
360 if (SecKeychainSearchCopyNext(searchRef, &searchItem) == noErr) { |
|
361 UInt32 realPasswordLength; |
|
362 SecKeychainAttribute attributesW[8]; |
|
363 attributesW[0].tag = kSecAccountItemAttr; |
|
364 SecKeychainAttributeList listW = {1,attributesW}; |
|
365 char *realPassword; |
|
366 OSStatus status = SecKeychainItemCopyContent(searchItem, NULL, &listW, &realPasswordLength,(void **)&realPassword); |
|
367 |
|
368 if (status == noErr) { |
|
369 if (realPassword != NULL) { |
|
370 |
|
371 QByteArray pBuf; |
|
372 pBuf.resize(realPasswordLength); |
|
373 pBuf.prepend(realPassword); |
|
374 pBuf.insert(realPasswordLength,'\0'); |
|
375 |
|
376 password = [NSString stringWithUTF8String:pBuf]; |
|
377 } |
|
378 } |
|
379 |
|
380 CFRelease(searchItem); |
|
381 SecKeychainItemFreeContent(&listW, realPassword); |
|
382 } else { |
|
383 qDebug() << "SecKeychainSearchCopyNext error"; |
|
384 } |
|
385 [params setValue: password forKey: kCWAssocKeyPassphrase]; |
|
386 } // end using8021X |
|
387 |
|
388 bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; |
|
389 |
|
390 if(!result) { |
|
391 emit connectionError(id, ConnectError); |
|
392 } else { |
|
393 [autoreleasepool release]; |
|
394 return; |
|
395 } |
|
396 } |
|
397 } |
229 } |
398 } else { |
230 |
399 qDebug() <<"ERROR"<< nsstringToQString([err localizedDescription ]); |
231 found.append(foundNetwork(networkSsid, networkSsid, state, interfaceName, purpose)); |
400 } |
232 |
401 |
233 } //end row |
402 emit connectionError(id, InterfaceLookupError); |
234 }//end error |
403 [autoreleasepool release]; |
235 }// endwifi power |
404 |
236 |
405 } else { |
237 // add known configurations that are not around. |
406 // not wifi |
|
407 } |
|
408 #endif |
|
409 } |
|
410 emit connectionError(id, OperationNotSupported); |
|
411 } |
|
412 |
|
413 void QCoreWlanEngine::disconnectFromId(const QString &id) |
|
414 { |
|
415 QString interfaceString = getInterfaceFromId(id); |
|
416 if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now |
|
417 #if defined(MAC_SDK_10_6) |
|
418 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
419 CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; |
|
420 [wifiInterface disassociate]; |
|
421 if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { |
|
422 emit connectionError(id, DisconnectionError); |
|
423 } |
|
424 [autoreleasepool release]; |
|
425 return; |
|
426 #endif |
|
427 } else { |
|
428 |
|
429 } |
|
430 emit connectionError(id, OperationNotSupported); |
|
431 } |
|
432 |
|
433 void QCoreWlanEngine::requestUpdate() |
|
434 { |
|
435 getAllScInterfaces(); |
|
436 getUserConfigurations(); |
|
437 emit configurationsChanged(); |
|
438 } |
|
439 |
|
440 QCoreWlanEngine *QCoreWlanEngine::instance() |
|
441 { |
|
442 return coreWlanEngine(); |
|
443 } |
|
444 |
|
445 QString QCoreWlanEngine::getSsidFromNetworkName(const QString &name) |
|
446 { |
|
447 QMapIterator<QString, QMap<QString,QString> > i(userProfiles); |
238 QMapIterator<QString, QMap<QString,QString> > i(userProfiles); |
448 while (i.hasNext()) { |
239 while (i.hasNext()) { |
449 i.next(); |
240 i.next(); |
450 QMap<QString,QString> map = i.value(); |
241 |
451 QMapIterator<QString, QString> ij(i.value()); |
|
452 while (ij.hasNext()) { |
|
453 ij.next(); |
|
454 if(name == i.key()) { |
|
455 return ij.key(); |
|
456 } |
|
457 } |
|
458 } |
|
459 return QString(); |
|
460 } |
|
461 |
|
462 QString QCoreWlanEngine::getNetworkNameFromSsid(const QString &ssid) |
|
463 { |
|
464 QMapIterator<QString, QMap<QString,QString> > i(userProfiles); |
|
465 while (i.hasNext()) { |
|
466 i.next(); |
|
467 QMap<QString,QString> map = i.value(); |
|
468 QMapIterator<QString, QString> ij(i.value()); |
|
469 while (ij.hasNext()) { |
|
470 ij.next(); |
|
471 if(ij.key() == ssid) { |
|
472 return i.key(); |
|
473 } |
|
474 } |
|
475 } |
|
476 return QString(); |
|
477 } |
|
478 |
|
479 QList<QNetworkConfigurationPrivate *> QCoreWlanEngine::scanForSsids(const QString &interfaceName) |
|
480 { |
|
481 QList<QNetworkConfigurationPrivate *> foundConfigs; |
|
482 if(!hasWifi) { |
|
483 return foundConfigs; |
|
484 } |
|
485 #if defined(MAC_SDK_10_6) |
|
486 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
487 CWInterface *currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)]; |
|
488 QStringList addedConfigs; |
|
489 |
|
490 if([currentInterface power]) { |
|
491 NSError *err = nil; |
|
492 NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys: |
|
493 [NSNumber numberWithBool:YES], kCWScanKeyMerge, |
|
494 [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, // get the networks in the scan cache |
|
495 [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil]; |
|
496 NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; |
|
497 CWNetwork *apNetwork; |
|
498 if(!err) { |
|
499 for(uint row=0; row < [apArray count]; row++ ) { |
|
500 apNetwork = [apArray objectAtIndex:row]; |
|
501 |
|
502 QString networkSsid = nsstringToQString([apNetwork ssid]); |
|
503 |
|
504 QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); |
|
505 cpPriv->name = networkSsid; |
|
506 cpPriv->isValid = true; |
|
507 cpPriv->id = networkSsid; |
|
508 cpPriv->internet = true; |
|
509 cpPriv->bearer = QLatin1String("WLAN"); |
|
510 cpPriv->type = QNetworkConfiguration::InternetAccessPoint; |
|
511 cpPriv->serviceInterface = QNetworkInterface::interfaceFromName(interfaceName); |
|
512 bool known = isKnownSsid(networkSsid); |
|
513 if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { |
|
514 if( cpPriv->name == nsstringToQString( [currentInterface ssid])) { |
|
515 cpPriv->state |= QNetworkConfiguration::Active; |
|
516 } |
|
517 } |
|
518 |
|
519 if(!cpPriv->state) { |
|
520 if(known) { |
|
521 cpPriv->state = QNetworkConfiguration::Discovered; |
|
522 } else { |
|
523 cpPriv->state = QNetworkConfiguration::Undefined; |
|
524 } |
|
525 } |
|
526 if([[apNetwork securityMode ] intValue]== kCWSecurityModeOpen) |
|
527 cpPriv->purpose = QNetworkConfiguration::PublicPurpose; |
|
528 else |
|
529 cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; |
|
530 |
|
531 foundConfigs.append(cpPriv); |
|
532 addedConfigs << networkSsid; |
|
533 |
|
534 } //end scanned row |
|
535 } |
|
536 } //end power |
|
537 |
|
538 |
|
539 // add known configurations that are not around. |
|
540 QMapIterator<QString, QMap<QString,QString> > i(userProfiles); |
|
541 while (i.hasNext()) { |
|
542 i.next(); |
|
543 QString networkName = i.key(); |
242 QString networkName = i.key(); |
544 |
243 const QString id = networkName; |
545 if(!addedConfigs.contains(networkName)) { |
244 |
|
245 if(!found.contains(id)) { |
|
246 QString networkSsid = getSsidFromNetworkName(networkName); |
|
247 const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); |
|
248 QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; |
546 QString interfaceName; |
249 QString interfaceName; |
547 QMapIterator<QString, QString> ij(i.value()); |
250 QMapIterator<QString, QString> ij(i.value()); |
548 while (ij.hasNext()) { |
251 while (ij.hasNext()) { |
549 ij.next(); |
252 ij.next(); |
550 interfaceName = ij.value(); |
253 interfaceName = ij.value(); |
551 } |
254 } |
552 |
255 |
553 QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); |
|
554 cpPriv->name = networkName; |
|
555 cpPriv->isValid = true; |
|
556 cpPriv->id = networkName; |
|
557 cpPriv->internet = true; |
|
558 cpPriv->bearer = QLatin1String("WLAN"); |
|
559 cpPriv->type = QNetworkConfiguration::InternetAccessPoint; |
|
560 cpPriv->serviceInterface = QNetworkInterface::interfaceFromName(interfaceName); |
|
561 QString ssid = getSsidFromNetworkName(networkName); |
|
562 if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { |
256 if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { |
563 if( ssid == nsstringToQString( [currentInterface ssid])) { |
257 if( networkSsid == nsstringToQString([currentInterface ssid])) { |
564 cpPriv->state |= QNetworkConfiguration::Active; |
258 state = QNetworkConfiguration::Active; |
565 } |
259 } |
566 } |
260 } |
567 |
261 if(state == QNetworkConfiguration::Undefined) { |
568 if( addedConfigs.contains(ssid)) { |
262 if( userProfiles.contains(networkName) |
569 cpPriv->state |= QNetworkConfiguration::Discovered; |
263 && found.contains(ssidId)) { |
570 } |
264 state = QNetworkConfiguration::Discovered; |
571 |
265 } |
572 if(!cpPriv->state) { |
266 } |
573 cpPriv->state = QNetworkConfiguration::Defined; |
267 |
574 } |
268 if(state == QNetworkConfiguration::Undefined) { |
575 |
269 state = QNetworkConfiguration::Defined; |
576 foundConfigs.append(cpPriv); |
270 } |
|
271 |
|
272 found.append(foundNetwork(id, networkName, state, interfaceName, QNetworkConfiguration::UnknownPurpose)); |
577 } |
273 } |
578 } |
274 } |
579 |
275 emit networksChanged(); |
580 [autoreleasepool drain]; |
276 [pool release]; |
581 #else |
|
582 Q_UNUSED(interfaceName); |
|
583 #endif |
277 #endif |
584 return foundConfigs; |
278 } |
585 } |
279 |
586 |
280 QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose) |
587 bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) |
281 { |
|
282 QStringList found; |
|
283 QMutexLocker locker(&mutex); |
|
284 QNetworkConfigurationPrivate *ptr = new QNetworkConfigurationPrivate; |
|
285 |
|
286 ptr->name = name; |
|
287 ptr->isValid = true; |
|
288 ptr->id = id; |
|
289 ptr->state = state; |
|
290 ptr->type = QNetworkConfiguration::InternetAccessPoint; |
|
291 ptr->bearer = QLatin1String("WLAN"); |
|
292 ptr->purpose = purpose; |
|
293 ptr->internet = true; |
|
294 ptr->serviceInterface = QNetworkInterface::interfaceFromName(interfaceName); |
|
295 |
|
296 fetchedConfigurations.append( ptr); |
|
297 configurationInterface[name] = interfaceName; |
|
298 |
|
299 locker.unlock(); |
|
300 locker.relock(); |
|
301 found.append(id); |
|
302 return found; |
|
303 } |
|
304 |
|
305 QList<QNetworkConfigurationPrivate *> QScanThread::getConfigurations() |
|
306 { |
|
307 QMutexLocker locker(&mutex); |
|
308 |
|
309 QList<QNetworkConfigurationPrivate *> foundConfigurations; |
|
310 |
|
311 for (int i = 0; i < fetchedConfigurations.count(); ++i) { |
|
312 QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate; |
|
313 config->name = fetchedConfigurations.at(i)->name; |
|
314 config->isValid = fetchedConfigurations.at(i)->isValid; |
|
315 config->id = fetchedConfigurations.at(i)->id; |
|
316 config->state = fetchedConfigurations.at(i)->state; |
|
317 |
|
318 config->type = fetchedConfigurations.at(i)->type; |
|
319 config->roamingSupported = fetchedConfigurations.at(i)->roamingSupported; |
|
320 config->purpose = fetchedConfigurations.at(i)->purpose; |
|
321 config->internet = fetchedConfigurations.at(i)->internet; |
|
322 foundConfigurations.append(config); |
|
323 } |
|
324 |
|
325 return foundConfigurations; |
|
326 } |
|
327 |
|
328 void QScanThread::getUserProfiles() |
588 { |
329 { |
589 #if defined(MAC_SDK_10_6) |
330 #if defined(MAC_SDK_10_6) |
590 if([[CWInterface supportedInterfaces] count] > 0 ) { |
331 QMutexLocker locker(&mutex); |
591 CWInterface *defaultInterface = [CWInterface interfaceWithName: qstringToNSString(wifiDeviceName)]; |
332 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
592 if([defaultInterface power]) |
|
593 return true; |
|
594 } |
|
595 #else |
|
596 Q_UNUSED(wifiDeviceName); |
|
597 #endif |
|
598 return false; |
|
599 } |
|
600 |
|
601 bool QCoreWlanEngine::isKnownSsid( const QString &ssid) |
|
602 { |
|
603 #if defined(MAC_SDK_10_6) |
|
604 QMapIterator<QString, QMap<QString,QString> > i(userProfiles); |
|
605 while (i.hasNext()) { |
|
606 i.next(); |
|
607 QMap<QString,QString> map = i.value(); |
|
608 if(map.keys().contains(ssid)) { |
|
609 return true; |
|
610 } |
|
611 } |
|
612 #else |
|
613 Q_UNUSED(ssid); |
|
614 #endif |
|
615 return false; |
|
616 } |
|
617 |
|
618 bool QCoreWlanEngine::getAllScInterfaces() |
|
619 { |
|
620 networkInterfaces.clear(); |
|
621 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
622 |
|
623 CFArrayRef interfaces = SCNetworkInterfaceCopyAll(); |
|
624 if (interfaces != NULL) { |
|
625 CFIndex interfaceCount; |
|
626 CFIndex interfaceIndex; |
|
627 interfaceCount = CFArrayGetCount(interfaces); |
|
628 for (interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) { |
|
629 NSAutoreleasePool *looppool = [[NSAutoreleasePool alloc] init]; |
|
630 |
|
631 CFStringRef bsdName; |
|
632 CFTypeRef thisInterface = CFArrayGetValueAtIndex(interfaces, interfaceIndex); |
|
633 bsdName = SCNetworkInterfaceGetBSDName((SCNetworkInterfaceRef)thisInterface); |
|
634 QString interfaceName = cfstringRefToQstring(bsdName); |
|
635 QString typeStr; |
|
636 CFStringRef type = SCNetworkInterfaceGetInterfaceType((SCNetworkInterfaceRef)thisInterface); |
|
637 if ( CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) { |
|
638 typeStr = "WLAN"; |
|
639 // } else if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth)) { |
|
640 // typeStr = "Bluetooth"; |
|
641 } else if(CFEqual(type, kSCNetworkInterfaceTypeEthernet)) { |
|
642 typeStr = "Ethernet"; |
|
643 } else if(CFEqual(type, kSCNetworkInterfaceTypeFireWire)) { |
|
644 typeStr = "Ethernet"; //ok a bit fudged |
|
645 } |
|
646 if(!networkInterfaces.contains(interfaceName) && !typeStr.isEmpty()) { |
|
647 networkInterfaces.insert(interfaceName,typeStr); |
|
648 } |
|
649 [looppool release]; |
|
650 } |
|
651 } |
|
652 CFRelease(interfaces); |
|
653 |
|
654 [autoreleasepool drain]; |
|
655 return true; |
|
656 } |
|
657 |
|
658 void QCoreWlanEngine::startNetworkChangeLoop() |
|
659 { |
|
660 storeSession = NULL; |
|
661 |
|
662 SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL }; |
|
663 storeSession = SCDynamicStoreCreate(NULL, |
|
664 CFSTR("networkChangeCallback"), |
|
665 networkChangeCallback, |
|
666 &dynStoreContext); |
|
667 if (!storeSession ) { |
|
668 qWarning() << "could not open dynamic store: error:" << SCErrorString(SCError()); |
|
669 return; |
|
670 } |
|
671 |
|
672 CFMutableArrayRef notificationKeys; |
|
673 notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
|
674 CFMutableArrayRef patternsArray; |
|
675 patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
|
676 |
|
677 CFStringRef storeKey; |
|
678 storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, |
|
679 kSCDynamicStoreDomainState, |
|
680 kSCEntNetIPv4); |
|
681 CFArrayAppendValue(notificationKeys, storeKey); |
|
682 CFRelease(storeKey); |
|
683 |
|
684 storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, |
|
685 kSCDynamicStoreDomainState, |
|
686 kSCCompAnyRegex, |
|
687 kSCEntNetIPv4); |
|
688 CFArrayAppendValue(patternsArray, storeKey); |
|
689 CFRelease(storeKey); |
|
690 |
|
691 if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) { |
|
692 qWarning() << "register notification error:"<< SCErrorString(SCError()); |
|
693 CFRelease(storeSession ); |
|
694 CFRelease(notificationKeys); |
|
695 CFRelease(patternsArray); |
|
696 return; |
|
697 } |
|
698 CFRelease(notificationKeys); |
|
699 CFRelease(patternsArray); |
|
700 |
|
701 runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0); |
|
702 if (!runloopSource) { |
|
703 qWarning() << "runloop source error:"<< SCErrorString(SCError()); |
|
704 CFRelease(storeSession ); |
|
705 return; |
|
706 } |
|
707 |
|
708 CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode); |
|
709 return; |
|
710 } |
|
711 |
|
712 void QCoreWlanEngine::getUserConfigurations() |
|
713 { |
|
714 #ifdef MAC_SDK_10_6 |
|
715 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
716 userProfiles.clear(); |
333 userProfiles.clear(); |
717 |
334 |
718 NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; |
335 NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; |
719 for(uint row=0; row < [wifiInterfaces count]; row++ ) { |
336 for(uint row=0; row < [wifiInterfaces count]; row++ ) { |
720 |
337 |
721 CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]]; |
338 CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]]; |
722 NSString *nsInterfaceName = [wifiInterface name]; |
339 NSString *nsInterfaceName = [wifiInterface name]; |
723 // add user configured system networks |
340 // add user configured system networks |
724 SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil); |
341 SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil); |
725 NSDictionary *airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName] autorelease]); |
342 NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]); |
726 CFRelease(dynRef); |
343 CFRelease(dynRef); |
727 |
344 |
728 NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"]; |
345 NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"]; |
729 |
346 |
730 NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"]; |
347 NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"]; |
731 for(NSString *ssidkey in thisSsidarray) { |
348 NSEnumerator *ssidEnumerator = [thisSsidarray objectEnumerator]; |
|
349 NSString *ssidkey; |
|
350 while ((ssidkey = [ssidEnumerator nextObject])) { |
732 QString thisSsid = nsstringToQString(ssidkey); |
351 QString thisSsid = nsstringToQString(ssidkey); |
733 if(!userProfiles.contains(thisSsid)) { |
352 if(!userProfiles.contains(thisSsid)) { |
734 QMap <QString,QString> map; |
353 QMap <QString,QString> map; |
735 map.insert(thisSsid, nsstringToQString(nsInterfaceName)); |
354 map.insert(thisSsid, nsstringToQString(nsInterfaceName)); |
736 userProfiles.insert(thisSsid, map); |
355 userProfiles.insert(thisSsid, map); |
769 map.insert(ssid, nsstringToQString(nsInterfaceName)); |
394 map.insert(ssid, nsstringToQString(nsInterfaceName)); |
770 userProfiles.insert(networkName, map); |
395 userProfiles.insert(networkName, map); |
771 } |
396 } |
772 } |
397 } |
773 } |
398 } |
774 [itemDict release]; |
|
775 } |
399 } |
776 } |
400 } |
777 [eapDict release]; |
401 } |
778 } |
402 |
779 [autoreleasepool release]; |
403 [pool release]; |
|
404 #endif |
|
405 } |
|
406 |
|
407 QString QScanThread::getSsidFromNetworkName(const QString &name) |
|
408 { |
|
409 QMutexLocker locker(&mutex); |
|
410 QMapIterator<QString, QMap<QString,QString> > i(userProfiles); |
|
411 while (i.hasNext()) { |
|
412 i.next(); |
|
413 QMap<QString,QString> map = i.value(); |
|
414 QMapIterator<QString, QString> ij(i.value()); |
|
415 while (ij.hasNext()) { |
|
416 ij.next(); |
|
417 const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key())); |
|
418 if(name == i.key() || name == networkNameHash) { |
|
419 return ij.key(); |
|
420 } |
|
421 } |
|
422 } |
|
423 return QString(); |
|
424 } |
|
425 |
|
426 QString QScanThread::getNetworkNameFromSsid(const QString &ssid) |
|
427 { |
|
428 QMutexLocker locker(&mutex); |
|
429 QMapIterator<QString, QMap<QString,QString> > i(userProfiles); |
|
430 while (i.hasNext()) { |
|
431 i.next(); |
|
432 QMap<QString,QString> map = i.value(); |
|
433 QMapIterator<QString, QString> ij(i.value()); |
|
434 while (ij.hasNext()) { |
|
435 ij.next(); |
|
436 if(ij.key() == ssid) { |
|
437 return i.key(); |
|
438 } |
|
439 } |
|
440 } |
|
441 return QString(); |
|
442 } |
|
443 |
|
444 bool QScanThread::isKnownSsid(const QString &ssid) |
|
445 { |
|
446 QMutexLocker locker(&mutex); |
|
447 |
|
448 QMapIterator<QString, QMap<QString,QString> > i(userProfiles); |
|
449 while (i.hasNext()) { |
|
450 i.next(); |
|
451 QMap<QString,QString> map = i.value(); |
|
452 if(map.keys().contains(ssid)) { |
|
453 return true; |
|
454 } |
|
455 } |
|
456 return false; |
|
457 } |
|
458 |
|
459 |
|
460 QCoreWlanEngine::QCoreWlanEngine(QObject *parent) |
|
461 : QNetworkSessionEngine(parent) |
|
462 { |
|
463 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
|
464 getAllScInterfaces(); |
|
465 scanThread = new QScanThread(this); |
|
466 connect(scanThread, SIGNAL(networksChanged()), |
|
467 this, SIGNAL(configurationsChanged())); |
|
468 |
|
469 QTimer::singleShot(0,this,SLOT(init())); |
|
470 [pool release]; |
|
471 } |
|
472 |
|
473 QCoreWlanEngine::~QCoreWlanEngine() |
|
474 { |
|
475 QNetworkConfigurationPrivate* cpPriv = 0; |
|
476 foundConfigurations.clear(); |
|
477 while(!foundConfigurations.isEmpty()) { |
|
478 cpPriv = foundConfigurations.takeFirst(); |
|
479 delete cpPriv; |
|
480 } |
|
481 } |
|
482 |
|
483 void QCoreWlanEngine::init() |
|
484 { |
|
485 #ifdef MAC_SDK_10_6 |
|
486 if([[CWInterface supportedInterfaces] count] > 0 && !listener) { |
|
487 listener = [[QNSListener alloc] init]; |
|
488 hasWifi = true; |
|
489 } else { |
|
490 hasWifi = false; |
|
491 } |
780 #endif |
492 #endif |
781 |
493 storeSession = NULL; |
782 } |
494 scanThread->start(); |
783 |
495 |
|
496 startNetworkChangeLoop(); |
|
497 } |
|
498 |
|
499 |
|
500 QList<QNetworkConfigurationPrivate *> QCoreWlanEngine::getConfigurations(bool *ok) |
|
501 { |
|
502 if (ok) |
|
503 *ok = true; |
|
504 foundConfigurations.clear(); |
|
505 |
|
506 QNetworkConfigurationPrivate* cpPriv = 0; |
|
507 QMutexLocker locker(&mutex); |
|
508 QList<QNetworkConfigurationPrivate *> fetchedConfigurations = scanThread->getConfigurations(); |
|
509 locker.unlock(); |
|
510 |
|
511 for (int i = 0; i < fetchedConfigurations.count(); ++i) { |
|
512 |
|
513 QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate(); |
|
514 cpPriv = fetchedConfigurations.at(i); |
|
515 config->name = cpPriv->name; |
|
516 config->isValid = cpPriv->isValid; |
|
517 config->id = cpPriv->id; |
|
518 config->state = cpPriv->state; |
|
519 config->type = cpPriv->type; |
|
520 config->roamingSupported = cpPriv->roamingSupported; |
|
521 config->purpose = cpPriv->purpose; |
|
522 config->internet = cpPriv->internet; |
|
523 config->serviceInterface = cpPriv->serviceInterface; |
|
524 config->bearer = cpPriv->bearer; |
|
525 |
|
526 foundConfigurations.append(config); |
|
527 delete cpPriv; |
|
528 } |
|
529 |
|
530 |
|
531 return foundConfigurations; |
|
532 } |
|
533 |
|
534 QString QCoreWlanEngine::getInterfaceFromId(const QString &id) |
|
535 { |
|
536 return scanThread->configurationInterface.value(id); |
|
537 } |
|
538 |
|
539 bool QCoreWlanEngine::hasIdentifier(const QString &id) |
|
540 { |
|
541 return scanThread->configurationInterface.contains(id); |
|
542 } |
|
543 |
|
544 void QCoreWlanEngine::connectToId(const QString &id) |
|
545 { |
|
546 QString interfaceString = getInterfaceFromId(id); |
|
547 |
|
548 if(networkInterfaces.value(interfaceString) == "WLAN") { |
|
549 #if defined(MAC_SDK_10_6) |
|
550 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
551 CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; |
|
552 |
|
553 if([wifiInterface power]) { |
|
554 NSError *err = nil; |
|
555 NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; |
|
556 |
|
557 QString wantedSsid = 0; |
|
558 bool using8021X = false; |
|
559 |
|
560 if(scanThread->getNetworkNameFromSsid(id) != id) { |
|
561 NSArray *array = [CW8021XProfile allUser8021XProfiles]; |
|
562 for (NSUInteger i=0; i<[array count]; ++i) { |
|
563 |
|
564 if(id == nsstringToQString([[array objectAtIndex:i] userDefinedName]) |
|
565 || id == nsstringToQString([[array objectAtIndex:i] ssid]) ) { |
|
566 QString thisName = scanThread->getSsidFromNetworkName(id); |
|
567 if(thisName.isEmpty()) { |
|
568 wantedSsid = id; |
|
569 } else { |
|
570 wantedSsid = thisName; |
|
571 } |
|
572 [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile]; |
|
573 using8021X = true; |
|
574 break; |
|
575 } |
|
576 } |
|
577 } |
|
578 |
|
579 if(!using8021X) { |
|
580 QString wantedNetwork; |
|
581 QMapIterator<QString, QMap<QString,QString> > i(scanThread->userProfiles); |
|
582 while (i.hasNext()) { |
|
583 i.next(); |
|
584 wantedNetwork = i.key(); |
|
585 if(id == wantedNetwork) { |
|
586 wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork); |
|
587 break; |
|
588 } |
|
589 } |
|
590 } |
|
591 |
|
592 NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys: |
|
593 [NSNumber numberWithBool:YES], kCWScanKeyMerge, |
|
594 [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, |
|
595 [NSNumber numberWithInteger:100], kCWScanKeyRestTime, |
|
596 qstringToNSString(wantedSsid), kCWScanKeySSID, |
|
597 nil]; |
|
598 |
|
599 NSArray *scanArray = [wifiInterface scanForNetworksWithParameters:parametersDict error:&err]; |
|
600 if(!err) { |
|
601 for(uint row=0; row < [scanArray count]; row++ ) { |
|
602 CWNetwork *apNetwork = [scanArray objectAtIndex:row]; |
|
603 if(wantedSsid == nsstringToQString([apNetwork ssid])) { |
|
604 |
|
605 if(!using8021X) { |
|
606 SecKeychainAttribute attributes[3]; |
|
607 |
|
608 NSString *account = [apNetwork ssid]; |
|
609 NSString *keyKind = @"AirPort network password"; |
|
610 NSString *keyName = account; |
|
611 |
|
612 attributes[0].tag = kSecAccountItemAttr; |
|
613 attributes[0].data = (void *)[account UTF8String]; |
|
614 attributes[0].length = [account length]; |
|
615 |
|
616 attributes[1].tag = kSecDescriptionItemAttr; |
|
617 attributes[1].data = (void *)[keyKind UTF8String]; |
|
618 attributes[1].length = [keyKind length]; |
|
619 |
|
620 attributes[2].tag = kSecLabelItemAttr; |
|
621 attributes[2].data = (void *)[keyName UTF8String]; |
|
622 attributes[2].length = [keyName length]; |
|
623 |
|
624 SecKeychainAttributeList attributeList = {3,attributes}; |
|
625 |
|
626 SecKeychainSearchRef searchRef; |
|
627 OSErr result = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef); |
|
628 Q_UNUSED(result); |
|
629 NSString *password = @""; |
|
630 SecKeychainItemRef searchItem; |
|
631 OSStatus resultStatus; |
|
632 resultStatus = SecKeychainSearchCopyNext(searchRef, &searchItem); |
|
633 |
|
634 if (resultStatus == errSecSuccess) { |
|
635 UInt32 realPasswordLength; |
|
636 SecKeychainAttribute attributesW[8]; |
|
637 attributesW[0].tag = kSecAccountItemAttr; |
|
638 SecKeychainAttributeList listW = {1,attributesW}; |
|
639 char *realPassword; |
|
640 OSStatus status = SecKeychainItemCopyContent(searchItem, NULL, &listW, &realPasswordLength,(void **)&realPassword); |
|
641 |
|
642 if (status == noErr) { |
|
643 if (realPassword != NULL) { |
|
644 |
|
645 QByteArray pBuf; |
|
646 pBuf.resize(realPasswordLength); |
|
647 pBuf.prepend(realPassword); |
|
648 pBuf.insert(realPasswordLength,'\0'); |
|
649 |
|
650 password = [NSString stringWithUTF8String:pBuf]; |
|
651 } |
|
652 } |
|
653 |
|
654 CFRelease(searchItem); |
|
655 SecKeychainItemFreeContent(&listW, realPassword); |
|
656 } else { |
|
657 qDebug() << "SecKeychainSearchCopyNext error" << cfstringRefToQstring(SecCopyErrorMessageString(resultStatus, NULL)); |
|
658 } |
|
659 [params setValue: password forKey: kCWAssocKeyPassphrase]; |
|
660 } // end using8021X |
|
661 |
|
662 bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; |
|
663 |
|
664 if(!result) { |
|
665 emit connectionError(id, ConnectError); |
|
666 } else { |
|
667 [autoreleasepool release]; |
|
668 return; |
|
669 } |
|
670 } |
|
671 } |
|
672 } else { |
|
673 qDebug() <<"ERROR"<< nsstringToQString([err localizedDescription ]); |
|
674 } |
|
675 |
|
676 emit connectionError(id, InterfaceLookupError); |
|
677 [autoreleasepool release]; |
|
678 |
|
679 } else { |
|
680 qDebug() << "wifi power off"; |
|
681 // not wifi |
|
682 } |
|
683 #endif |
|
684 } |
|
685 emit connectionError(id, OperationNotSupported); |
|
686 } |
|
687 |
|
688 void QCoreWlanEngine::disconnectFromId(const QString &id) |
|
689 { |
|
690 QString interfaceString = getInterfaceFromId(id); |
|
691 if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now |
|
692 #if defined(MAC_SDK_10_6) |
|
693 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
694 CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; |
|
695 [wifiInterface disassociate]; |
|
696 if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { |
|
697 emit connectionError(id, DisconnectionError); |
|
698 } |
|
699 [autoreleasepool release]; |
|
700 return; |
|
701 #endif |
|
702 } else { |
|
703 |
|
704 } |
|
705 emit connectionError(id, OperationNotSupported); |
|
706 } |
|
707 |
|
708 void QCoreWlanEngine::requestUpdate() |
|
709 { |
|
710 getAllScInterfaces(); |
|
711 scanThread->getUserProfiles(); |
|
712 scanThread->start(); |
|
713 } |
|
714 |
|
715 QCoreWlanEngine *QCoreWlanEngine::instance() |
|
716 { |
|
717 return coreWlanEngine(); |
|
718 } |
|
719 |
|
720 bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) |
|
721 { |
|
722 #if defined(MAC_SDK_10_6) |
|
723 if([[CWInterface supportedInterfaces] count] > 0 ) { |
|
724 CWInterface *defaultInterface = [CWInterface interfaceWithName: qstringToNSString(wifiDeviceName)]; |
|
725 if([defaultInterface power]) |
|
726 return true; |
|
727 } |
|
728 #else |
|
729 Q_UNUSED(wifiDeviceName); |
|
730 #endif |
|
731 return false; |
|
732 } |
|
733 |
|
734 bool QCoreWlanEngine::getAllScInterfaces() |
|
735 { |
|
736 networkInterfaces.clear(); |
|
737 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
738 |
|
739 CFArrayRef interfaces = SCNetworkInterfaceCopyAll(); |
|
740 if (interfaces != NULL) { |
|
741 CFIndex interfaceCount; |
|
742 CFIndex interfaceIndex; |
|
743 interfaceCount = CFArrayGetCount(interfaces); |
|
744 for (interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) { |
|
745 NSAutoreleasePool *looppool = [[NSAutoreleasePool alloc] init]; |
|
746 |
|
747 CFStringRef bsdName; |
|
748 CFTypeRef thisInterface = CFArrayGetValueAtIndex(interfaces, interfaceIndex); |
|
749 bsdName = SCNetworkInterfaceGetBSDName((SCNetworkInterfaceRef)thisInterface); |
|
750 QString interfaceName = cfstringRefToQstring(bsdName); |
|
751 QString typeStr; |
|
752 CFStringRef type = SCNetworkInterfaceGetInterfaceType((SCNetworkInterfaceRef)thisInterface); |
|
753 if ( CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) { |
|
754 typeStr = "WLAN"; |
|
755 // } else if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth)) { |
|
756 // typeStr = "Bluetooth"; |
|
757 } else if(CFEqual(type, kSCNetworkInterfaceTypeEthernet)) { |
|
758 typeStr = "Ethernet"; |
|
759 } else if(CFEqual(type, kSCNetworkInterfaceTypeFireWire)) { |
|
760 typeStr = "Ethernet"; //ok a bit fudged |
|
761 } |
|
762 if(!networkInterfaces.contains(interfaceName) && !typeStr.isEmpty()) { |
|
763 networkInterfaces.insert(interfaceName,typeStr); |
|
764 } |
|
765 [looppool release]; |
|
766 } |
|
767 } |
|
768 CFRelease(interfaces); |
|
769 |
|
770 [autoreleasepool drain]; |
|
771 return true; |
|
772 } |
|
773 |
|
774 void QCoreWlanEngine::startNetworkChangeLoop() |
|
775 { |
|
776 storeSession = NULL; |
|
777 |
|
778 SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL }; |
|
779 storeSession = SCDynamicStoreCreate(NULL, |
|
780 CFSTR("networkChangeCallback"), |
|
781 networkChangeCallback, |
|
782 &dynStoreContext); |
|
783 if (!storeSession ) { |
|
784 qDebug() << "could not open dynamic store: error:" << SCErrorString(SCError()); |
|
785 return; |
|
786 } |
|
787 |
|
788 CFMutableArrayRef notificationKeys; |
|
789 notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
|
790 CFMutableArrayRef patternsArray; |
|
791 patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
|
792 |
|
793 CFStringRef storeKey; |
|
794 storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, |
|
795 kSCDynamicStoreDomainState, |
|
796 kSCEntNetIPv4); |
|
797 CFArrayAppendValue(notificationKeys, storeKey); |
|
798 CFRelease(storeKey); |
|
799 |
|
800 storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, |
|
801 kSCDynamicStoreDomainState, |
|
802 kSCCompAnyRegex, |
|
803 kSCEntNetIPv4); |
|
804 CFArrayAppendValue(patternsArray, storeKey); |
|
805 CFRelease(storeKey); |
|
806 |
|
807 if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) { |
|
808 qDebug() << "register notification error:"<< SCErrorString(SCError()); |
|
809 CFRelease(storeSession ); |
|
810 CFRelease(notificationKeys); |
|
811 CFRelease(patternsArray); |
|
812 return; |
|
813 } |
|
814 CFRelease(notificationKeys); |
|
815 CFRelease(patternsArray); |
|
816 |
|
817 runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0); |
|
818 if (!runloopSource) { |
|
819 qDebug() << "runloop source error:"<< SCErrorString(SCError()); |
|
820 CFRelease(storeSession ); |
|
821 return; |
|
822 } |
|
823 |
|
824 CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode); |
|
825 return; |
|
826 } |
784 #include "moc_qcorewlanengine_mac_p.cpp" |
827 #include "moc_qcorewlanengine_mac_p.cpp" |
785 |
828 |
786 QTM_END_NAMESPACE |
829 QTM_END_NAMESPACE |