diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-04-14 16:02:08 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-04-14 16:02:08 (GMT) |
commit | 0f4505dd18a1342b62a049d4c37414179d6ec065 (patch) | |
tree | 3be71264d34e2ec7534a404634ae39f3cf47d497 /src | |
parent | b371999d3e9c207047be6afda89d008b6cf04763 (diff) | |
parent | 8876c7c44744b0813f98ebbb0f748331f9d8a22c (diff) | |
download | Qt-0f4505dd18a1342b62a049d4c37414179d6ec065.zip Qt-0f4505dd18a1342b62a049d4c37414179d6ec065.tar.gz Qt-0f4505dd18a1342b62a049d4c37414179d6ec065.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1: (21 commits)
Added missing newline after warning message when using -L with qml
Doc: updating scripts
Fixed a crash on embedded due to uninitialized pointer.
Fix a race where QThread::exit() is "lost" when called after start()
qdoc: Removed all <table> attributes in favor of using css.
Autotest failure: dialogModality test fails on cocoa (macgui)
Force the bic test to compile in 32-bit mode on Mac
Revert "Doc: Updating design files."
Remove statically allocated pixmaps through the post routine
qdoc: Checked for empty title.
qdoc: Added TOC to class ref pages.
Cocoa: qwidget autotest fails on setToolTip
Compile on Mac OS 10.4
Bearer management changes from Qt Mobility (7a5ff985)
Partially revert "Sunstudio12.1(5.10): Fix compile errors GTK style and other minor compile errors"
Fix margins for placeholdertext in QLineEdit
qdoc: Added TOC to module pages.
Doc: Updating design files.
Doc: Fixing design bugs. Updating the index page and script/style files. Adding some image files.
qdoc: Changed <ul> elements in TOC.
...
Diffstat (limited to 'src')
25 files changed, 1310 insertions, 978 deletions
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index c35eb28..cdcb65c 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -174,7 +174,7 @@ void QAdoptedThread::run() QThreadPrivate::QThreadPrivate(QThreadData *d) : QObjectPrivate(), running(false), finished(false), terminated(false), - stackSize(0), priority(QThread::InheritPriority), data(d), object(0) + stackSize(0), priority(QThread::InheritPriority), data(d) { #if defined (Q_OS_UNIX) thread_id = 0; @@ -377,9 +377,6 @@ QThread::QThread(QObject *parent) Q_D(QThread); // fprintf(stderr, "QThreadData %p created for thread %p\n", d->data, this); d->data->thread = this; - - d->object = new QThreadPrivateInternalObject; - d->object->moveToThread(this); } /*! \internal @@ -390,8 +387,6 @@ QThread::QThread(QThreadPrivate &dd, QObject *parent) Q_D(QThread); // fprintf(stderr, "QThreadData %p taken from private data for thread %p\n", d->data, this); d->data->thread = this; - - // do not create the internal object for adopted threads } /*! @@ -413,9 +408,6 @@ QThread::~QThread() d->data->thread = 0; } - - delete d->object; - d->object = 0; } /*! @@ -488,11 +480,11 @@ uint QThread::stackSize() const int QThread::exec() { Q_D(QThread); - QMutexLocker locker(&d->mutex); - d->data->quitNow = false; QEventLoop eventLoop; - locker.unlock(); int returnCode = eventLoop.exec(); + + QMutexLocker locker(&d->mutex); + d->data->quitNow = false; return returnCode; } @@ -518,21 +510,6 @@ int QThread::exec() void QThread::exit(int returnCode) { Q_D(QThread); - if (d->object) { - QMetaObject::invokeMethod(d->object, "exit", Q_ARG(int, returnCode)); - } else { - QMutexLocker locker(&d->mutex); - d->data->quitNow = true; - for (int i = 0; i < d->data->eventLoops.size(); ++i) { - QEventLoop *eventLoop = d->data->eventLoops.at(i); - eventLoop->exit(returnCode); - } - } -} - -void QThreadPrivateInternalObject::exit(int returnCode) -{ - QThreadPrivate *d = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread())); QMutexLocker locker(&d->mutex); d->data->quitNow = true; for (int i = 0; i < d->data->eventLoops.size(); ++i) { diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 54ffd80..44eb8f8 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -113,14 +113,6 @@ public: #ifndef QT_NO_THREAD -class QThreadPrivateInternalObject : public QObject -{ - Q_OBJECT - -public slots: - void exit(int); -}; - class QThreadPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QThread) @@ -165,7 +157,6 @@ public: bool terminationEnabled, terminatePending; # endif QThreadData *data; - QThreadPrivateInternalObject *object; static void createEventDispatcher(QThreadData *data); }; diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 6b34b5f..bd31d9c 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -253,7 +253,6 @@ void *QThreadPrivate::start(void *arg) pthread_setspecific(current_thread_data_key, data); data->ref(); - data->quitNow = false; // ### TODO: allow the user to create a custom event dispatcher createEventDispatcher(data); @@ -495,6 +494,7 @@ void QThread::start(Priority priority) d->running = true; d->finished = false; d->terminated = false; + d->data->quitNow = false; pthread_attr_t attr; pthread_attr_init(&attr); diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 37d5b87..9826dcb 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -298,7 +298,6 @@ unsigned int __stdcall QThreadPrivate::start(void *arg) QThread::setTerminationEnabled(false); - data->quitNow = false; // ### TODO: allow the user to create a custom event dispatcher createEventDispatcher(data); @@ -405,6 +404,7 @@ void QThread::start(Priority priority) d->running = true; d->finished = false; d->terminated = false; + d->data->quitNow = false; /* NOTE: we create the thread in the suspended state, set the diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index b0a23d4..5f5e29f 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -186,11 +186,9 @@ QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::T gestureManager = 0; gestureWidget = 0; -#if defined(Q_WS_X11) || defined(Q_WS_WIN) move_cursor = 0; copy_cursor = 0; link_cursor = 0; -#endif #if defined(Q_WS_WIN) ignore_cursor = 0; #endif @@ -1045,11 +1043,9 @@ QApplication::~QApplication() qt_clipboard = 0; #endif -#if defined(Q_WS_X11) || defined(Q_WS_WIN) delete d->move_cursor; d->move_cursor = 0; delete d->copy_cursor; d->copy_cursor = 0; delete d->link_cursor; d->link_cursor = 0; -#endif #if defined(Q_WS_WIN) delete d->ignore_cursor; d->ignore_cursor = 0; #endif diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 9c5380b..dd12f65 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -673,13 +673,14 @@ static int qCocoaViewCount = 0; // Send mouse move and hover events as well: if (!qAppInstance()->activePopupWidget() || qAppInstance()->activePopupWidget() == qwidget->window()) { - if (qwidget->testAttribute(Qt::WA_MouseTracking)) { - NSEvent *mouseEvent = [NSEvent mouseEventWithType:NSMouseMoved - location:windowPoint modifierFlags:[event modifierFlags] timestamp:[event timestamp] - windowNumber:[event windowNumber] context:[event context] eventNumber:[event eventNumber] - clickCount:0 pressure:0]; - qt_mac_handleMouseEvent(self, mouseEvent, QEvent::MouseMove, Qt::NoButton); - } + // This mouse move event should be sendt, even when mouse + // tracking is switched off (to trigger tooltips): + NSEvent *mouseEvent = [NSEvent mouseEventWithType:NSMouseMoved + location:windowPoint modifierFlags:[event modifierFlags] timestamp:[event timestamp] + windowNumber:[event windowNumber] context:[event context] eventNumber:[event eventNumber] + clickCount:0 pressure:0]; + qt_mac_handleMouseEvent(self, mouseEvent, QEvent::MouseMove, Qt::NoButton); + if (qwidget->testAttribute(Qt::WA_Hover)) { QHoverEvent he(QEvent::HoverEnter, QPoint(viewPoint.x, viewPoint.y), QPoint(-1, -1)); QApplicationPrivate::instance()->notify_helper(qwidget, &he); diff --git a/src/gui/kernel/qcursor_mac.mm b/src/gui/kernel/qcursor_mac.mm index 03e38b0..c3d6c54 100644 --- a/src/gui/kernel/qcursor_mac.mm +++ b/src/gui/kernel/qcursor_mac.mm @@ -224,6 +224,15 @@ QPoint QCursor::pos() void QCursor::setPos(int x, int y) { +#ifdef QT_MAC_USE_COCOA + CGPoint pos; + pos.x = x; + pos.y = y; + + CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0); + CGEventPost(kCGHIDEventTap, e); + CFRelease(e); +#else CGWarpMouseCursorPosition(CGPointMake(x, y)); /* I'm not too keen on doing this, but this makes it a lot easier, so I just @@ -240,6 +249,7 @@ void QCursor::setPos(int x, int y) QApplication::mouseButtons(), QApplication::keyboardModifiers()); qt_sendSpontaneousEvent(widget, &me); } +#endif } void QCursorData::initCursorFromBitmap() diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 0b8dca9..655fc61 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1869,13 +1869,18 @@ void QLineEdit::paintEvent(QPaintEvent *) } QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height()); + int minLB = qMax(0, -fm.minLeftBearing()); + int minRB = qMax(0, -fm.minRightBearing()); + if (d->control->text().isEmpty()) { if (!hasFocus() && !d->placeholderText.isEmpty()) { QColor col = pal.text().color(); col.setAlpha(128); QPen oldpen = p.pen(); p.setPen(col); - p.drawText(lineRect, va, d->placeholderText); + lineRect.adjust(minLB, 0, 0, 0); + QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, lineRect.width()); + p.drawText(lineRect, va, elidedText); p.setPen(oldpen); return; } @@ -1889,8 +1894,6 @@ void QLineEdit::paintEvent(QPaintEvent *) // the below code handles all scrolling based on the textline (widthUsed, // minLB, minRB), the line edit rect (lineRect) and the cursor position // (cix). - int minLB = qMax(0, -fm.minLeftBearing()); - int minRB = qMax(0, -fm.minRightBearing()); int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; if ((minLB + widthUsed) <= lineRect.width()) { // text fits in lineRect; use hscroll for alignment diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index 1bba56f..638bee7 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -225,6 +225,10 @@ QT_BEGIN_NAMESPACE QNetworkSession::QNetworkSession(const QNetworkConfiguration& connectionConfig, QObject* parent) : QObject(parent), d(0) { + // invalid configuration + if (connectionConfig.identifier().isNull()) + return; + foreach (QBearerEngine *engine, qNetworkConfigurationManagerPrivate()->engines()) { if (engine->hasIdentifier(connectionConfig.identifier())) { d = engine->createSessionBackend(); diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index b59ccee..e418432 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -91,7 +91,7 @@ [locker lock]; QMacCocoaAutoReleasePool pool; center = [NSNotificationCenter defaultCenter]; - currentInterface = [CWInterface interface]; + currentInterface = [CWInterface interfaceWithName:nil]; // [center addObserver:self selector:@selector(notificationHandler:) name:kCWLinkDidChangeNotification object:nil]; [center addObserver:self selector:@selector(notificationHandler:) name:kCWPowerDidChangeNotification object:nil]; [locker unlock]; @@ -154,7 +154,7 @@ QCoreWlanEngine::QCoreWlanEngine(QObject *parent) } else { hasWifi = false; } - requestUpdate(); + QMetaObject::invokeMethod(this, "requestUpdate", Qt::QueuedConnection); } QCoreWlanEngine::~QCoreWlanEngine() @@ -193,14 +193,13 @@ void QCoreWlanEngine::connectToId(const QString &id) NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; QString wantedSsid; + bool using8021X = false; QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); - const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + ptr->name)); - const QString idHash2 = QString::number(qHash(QLatin1String("corewlan:") + getNetworkNameFromSsid(ptr->name))); + const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + getNetworkNameFromSsid(ptr->name))); - bool using8021X = false; - if (idHash2 != id) { + if (idHash != id) { NSArray *array = [CW8021XProfile allUser8021XProfiles]; for (NSUInteger i = 0; i < [array count]; ++i) { @@ -382,6 +381,41 @@ void QCoreWlanEngine::doRequestUpdate() emit updateCompleted(); } +QString QCoreWlanEngine::getSsidFromNetworkName(const QString &name) +{ + QMapIterator<QString, QMap<QString,QString> > i(userProfiles); + while (i.hasNext()) { + i.next(); + QMap<QString,QString> map = i.value(); + QMapIterator<QString, QString> ij(i.value()); + while (ij.hasNext()) { + ij.next(); + const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + i.key())); + if (name == i.key() || name == networkNameHash) { + return ij.key(); + } + } + } + return QString(); +} + +QString QCoreWlanEngine::getNetworkNameFromSsid(const QString &ssid) +{ + QMapIterator<QString, QMap<QString,QString> > i(userProfiles); + while (i.hasNext()) { + i.next(); + QMap<QString,QString> map = i.value(); + QMapIterator<QString, QString> ij(i.value()); + while (ij.hasNext()) { + ij.next(); + if(ij.key() == ssid) { + return i.key(); + } + } + } + return QString(); +} + QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) { QMutexLocker locker(&mutex); @@ -404,7 +438,6 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil]; NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; CWNetwork *apNetwork; - if (!err) { for(uint row=0; row < [apArray count]; row++ ) { @@ -676,42 +709,6 @@ bool QCoreWlanEngine::requiresPolling() const return true; } -QString QCoreWlanEngine::getSsidFromNetworkName(const QString &name) -{ - QMapIterator<QString, QMap<QString,QString> > i(userProfiles); - while (i.hasNext()) { - i.next(); - QMap<QString,QString> map = i.value(); - QMapIterator<QString, QString> ij(i.value()); - while (ij.hasNext()) { - ij.next(); - const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key())); - if(name == i.key() || name == networkNameHash) { - return ij.key(); - } - } - } - return QString(); -} - -QString QCoreWlanEngine::getNetworkNameFromSsid(const QString &ssid) -{ - QMapIterator<QString, QMap<QString,QString> > i(userProfiles); - while (i.hasNext()) { - i.next(); - QMap<QString,QString> map = i.value(); - QMapIterator<QString, QString> ij(i.value()); - while (ij.hasNext()) { - ij.next(); - if(ij.key() == ssid) { - return i.key(); - } - } - } - return QString(); -} - - void QCoreWlanEngine::getUserConfigurations() { QMacCocoaAutoReleasePool pool; @@ -724,7 +721,7 @@ void QCoreWlanEngine::getUserConfigurations() NSString *nsInterfaceName = [wifiInterface name]; // add user configured system networks SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil); - NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]); + NSDictionary *airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName] autorelease]); CFRelease(dynRef); NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"]; @@ -742,7 +739,7 @@ void QCoreWlanEngine::getUserConfigurations() // 802.1X user profiles QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist"; - NSDictionary* eapDict = [[NSMutableDictionary alloc] initWithContentsOfFile:qt_mac_QStringToNSString(userProfilePath)]; + NSDictionary* eapDict = [[NSDictionary alloc] initWithContentsOfFile:qt_mac_QStringToNSString(userProfilePath)]; NSString *profileStr= @"Profiles"; NSString *nameStr = @"UserDefinedName"; NSString *networkSsidStr = @"Wireless Network"; @@ -773,8 +770,10 @@ void QCoreWlanEngine::getUserConfigurations() } } } + [itemDict release]; } } + [eapDict release]; } } diff --git a/src/plugins/bearer/icd/icd.pro b/src/plugins/bearer/icd/icd.pro index f411de2..c7337f5 100644 --- a/src/plugins/bearer/icd/icd.pro +++ b/src/plugins/bearer/icd/icd.pro @@ -7,12 +7,10 @@ QMAKE_CXXFLAGS += $$QT_CFLAGS_ICD LIBS += $$QT_LIBS_ICD HEADERS += qicdengine.h \ - monitor.h \ qnetworksession_impl.h SOURCES += main.cpp \ qicdengine.cpp \ - monitor.cpp \ qnetworksession_impl.cpp #DEFINES += BEARER_MANAGEMENT_DEBUG diff --git a/src/plugins/bearer/icd/monitor.cpp b/src/plugins/bearer/icd/monitor.cpp deleted file mode 100644 index 5b0af7e..0000000 --- a/src/plugins/bearer/icd/monitor.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "monitor.h" -#include "qicdengine.h" - -#include <wlancond.h> -#include <libicd-network-wlan-dev.h> -#include <maemo_icd.h> -#include <iapconf.h> - - -void IapMonitor::setup(QIcdEngine *d_ptr) -{ - if (first_call) { - d = d_ptr; - first_call = false; - } -} - - -void IapMonitor::cleanup() -{ - if (!first_call) { - timers.removeAll(); - first_call = true; - } -} - - -void IapMonitor::iapAdded(const QString &iap_id) -{ - /* We cannot know when the IAP is fully added to db, so a timer is - * installed instead. When the timer expires we hope that IAP is added ok. - */ - QString id = iap_id; - timers.add(id, d); -} - - -void IapMonitor::iapRemoved(const QString &iap_id) -{ - QString id = iap_id; - d->deleteConfiguration(id); -} - diff --git a/src/plugins/bearer/icd/monitor.h b/src/plugins/bearer/icd/monitor.h deleted file mode 100644 index 10ffb30..0000000 --- a/src/plugins/bearer/icd/monitor.h +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MONITOR_H -#define MONITOR_H - -#include <QtCore/qhash.h> -#include <QtCore/qtimer.h> - -#include <gconf/gconf.h> -#include <gconf/gconf-client.h> - -#include <iapmonitor.h> - -class QIcdEngine; - -/* The IapAddTimer is a helper class that makes sure we update - * the configuration only after all db additions to certain - * iap are finished (after a certain timeout) - */ -class _IapAddTimer : public QObject -{ - Q_OBJECT - -public: - _IapAddTimer() {} - ~_IapAddTimer() - { - if (timer.isActive()) { - QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); - timer.stop(); - } - } - - void add(QString& iap_id, QIcdEngine *d); - - QString iap_id; - QTimer timer; - QIcdEngine *d; - -public Q_SLOTS: - void timeout(); -}; - -class IapAddTimer { - QHash<QString, _IapAddTimer* > timers; - -public: - IapAddTimer() {} - ~IapAddTimer() {} - - void add(QString& iap_id, QIcdEngine *d); - void del(QString& iap_id); - void removeAll(); -}; - -class IapMonitor : public Maemo::IAPMonitor -{ -public: - IapMonitor() : first_call(true) { } - - void setup(QIcdEngine *d); - void cleanup(); - -protected: - void iapAdded(const QString &iapId); - void iapRemoved(const QString &iapId); - -private: - bool first_call; - - QIcdEngine *d; - IapAddTimer timers; -}; - -#endif // MONITOR_H diff --git a/src/plugins/bearer/icd/qicdengine.cpp b/src/plugins/bearer/icd/qicdengine.cpp index 7a4cb9d..a6cf0c2 100644 --- a/src/plugins/bearer/icd/qicdengine.cpp +++ b/src/plugins/bearer/icd/qicdengine.cpp @@ -40,12 +40,12 @@ ****************************************************************************/ #include "qicdengine.h" -#include "monitor.h" #include "qnetworksession_impl.h" +#include <wlancond.h> #include <libicd-network-wlan-dev.h> -#include <maemo_icd.h> #include <iapconf.h> +#include <iapmonitor.h> QT_BEGIN_NAMESPACE @@ -70,6 +70,208 @@ QString IcdNetworkConfigurationPrivate::bearerName() const } } +/* The IapAddTimer is a helper class that makes sure we update + * the configuration only after all db additions to certain + * iap are finished (after a certain timeout) + */ +class _IapAddTimer : public QObject +{ + Q_OBJECT + +public: + _IapAddTimer() {} + ~_IapAddTimer() + { + if (timer.isActive()) { + QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); + timer.stop(); + } + } + + void add(QString& iap_id, QIcdEngine *d); + + QString iap_id; + QTimer timer; + QIcdEngine *d; + +public Q_SLOTS: + void timeout(); +}; + + +void _IapAddTimer::add(QString& id, QIcdEngine *d_ptr) +{ + iap_id = id; + d = d_ptr; + + if (timer.isActive()) { + QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); + timer.stop(); + } + timer.setSingleShot(true); + QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); + timer.start(1500); +} + + +void _IapAddTimer::timeout() +{ + d->addConfiguration(iap_id); +} + + +class IapAddTimer { + QHash<QString, _IapAddTimer* > timers; + +public: + IapAddTimer() {} + ~IapAddTimer() {} + + void add(QString& iap_id, QIcdEngine *d); + void del(QString& iap_id); + void removeAll(); +}; + + +void IapAddTimer::removeAll() +{ + QHashIterator<QString, _IapAddTimer* > i(timers); + while (i.hasNext()) { + i.next(); + _IapAddTimer *t = i.value(); + delete t; + } + timers.clear(); +} + + +void IapAddTimer::add(QString& iap_id, QIcdEngine *d) +{ + if (timers.contains(iap_id)) { + _IapAddTimer *iap = timers.value(iap_id); + iap->add(iap_id, d); + } else { + _IapAddTimer *iap = new _IapAddTimer; + iap->add(iap_id, d); + timers.insert(iap_id, iap); + } +} + +void IapAddTimer::del(QString& iap_id) +{ + if (timers.contains(iap_id)) { + _IapAddTimer *iap = timers.take(iap_id); + delete iap; + } +} + + +class IapMonitor : public Maemo::IAPMonitor +{ +public: + IapMonitor() : first_call(true) { } + + void setup(QIcdEngine *d); + void cleanup(); + +protected: + void iapAdded(const QString &iapId); + void iapRemoved(const QString &iapId); + +private: + bool first_call; + + QIcdEngine *d; + IapAddTimer timers; +}; + +void IapMonitor::setup(QIcdEngine *d_ptr) +{ + if (first_call) { + d = d_ptr; + first_call = false; + } +} + + +void IapMonitor::cleanup() +{ + if (!first_call) { + timers.removeAll(); + first_call = true; + } +} + + +void IapMonitor::iapAdded(const QString &iap_id) +{ + /* We cannot know when the IAP is fully added to db, so a timer is + * installed instead. When the timer expires we hope that IAP is added ok. + */ + QString id = iap_id; + timers.add(id, d); +} + + +void IapMonitor::iapRemoved(const QString &iap_id) +{ + QString id = iap_id; + d->deleteConfiguration(id); +} + +QIcdEngine::QIcdEngine(QObject *parent) +: QBearerEngine(parent), iapMonitor(new IapMonitor), m_dbusInterface(0), + firstUpdate(true), m_scanGoingOn(false) +{ + QMetaObject::invokeMethod(this, "doRequestUpdate", Qt::QueuedConnection); + init(); +} + +QIcdEngine::~QIcdEngine() +{ + cleanup(); + delete iapMonitor; +} + +QNetworkConfigurationManager::Capabilities QIcdEngine::capabilities() const +{ + return QNetworkConfigurationManager::CanStartAndStopInterfaces | + QNetworkConfigurationManager::DataStatistics | + QNetworkConfigurationManager::ForcedRoaming | + QNetworkConfigurationManager::NetworkSessionRequired; +} + +void QIcdEngine::init() +{ + // Setup DBus Interface for ICD + m_dbusInterface = new QDBusInterface(ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_PATH, + ICD_DBUS_API_INTERFACE, + QDBusConnection::systemBus(), + this); + connect(&m_scanTimer, SIGNAL(timeout()), this, SLOT(finishAsyncConfigurationUpdate())); + m_scanTimer.setSingleShot(true); + + /* Turn on IAP state monitoring */ + startListeningStateSignalsForAllConnections(); + + /* Turn on IAP add/remove monitoring */ + iapMonitor->setup(this); + + /* We create a default configuration which is a pseudo config */ + QNetworkConfigurationPrivate *cpPriv = new IcdNetworkConfigurationPrivate; + cpPriv->name = "UserChoice"; + cpPriv->state = QNetworkConfiguration::Discovered; + cpPriv->isValid = true; + cpPriv->id = OSSO_IAP_ANY; + cpPriv->type = QNetworkConfiguration::UserChoice; + cpPriv->purpose = QNetworkConfiguration::UnknownPurpose; + cpPriv->roamingSupported = false; + + QNetworkConfigurationPrivatePointer ptr(cpPriv); + userChoiceConfigurations.insert(cpPriv->id, ptr); +} + static inline QString network_attrs_to_security(uint network_attrs) { uint cap = 0; @@ -85,38 +287,40 @@ static inline QString network_attrs_to_security(uint network_attrs) return ""; } -QIcdEngine::QIcdEngine(QObject *parent) -: QBearerEngine(parent), iapMonitor(new IapMonitor) -{ - /* Turn on IAP monitoring */ - iapMonitor->setup(this); - doRequestUpdate(); -} +struct SSIDInfo { + QString iap_id; + QString wlan_security; +}; -QIcdEngine::~QIcdEngine() -{ -} -bool QIcdEngine::hasIdentifier(const QString &id) +void QIcdEngine::deleteConfiguration(const QString &iap_id) { QMutexLocker locker(&mutex); - return accessPointConfigurations.contains(id) || - snapConfigurations.contains(id) || - userChoiceConfigurations.contains(id); -} - -void QIcdEngine::requestUpdate() -{ - QMutexLocker locker(&mutex); + /* Called when IAPs are deleted in db, in this case we do not scan + * or read all the IAPs from db because it might take too much power + * (multiple applications would need to scan and read all IAPs from db) + */ + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(iap_id); + if (ptr) { +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "IAP" << iap_id << "was removed from storage."; +#endif - QTimer::singleShot(0, this, SLOT(doRequestUpdate())); + locker.unlock(); + emit configurationRemoved(ptr); + } else { +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug("IAP: %s, already missing from the known list", iap_id.toAscii().data()); +#endif + } } + static uint32_t getNetworkAttrs(bool is_iap_id, - QString& iap_id, - QString& iap_type, + const QString &iap_id, + const QString &iap_type, QString security_method) { guint network_attr = 0; @@ -158,45 +362,171 @@ static uint32_t getNetworkAttrs(bool is_iap_id, return (uint32_t)network_attr; } -void QIcdEngine::doRequestUpdate() + +void QIcdEngine::addConfiguration(QString& iap_id) { + // Note: When new IAP is created, this function gets called multiple times + // in a row. + // For example: Empty type & name for WLAN was stored into newly + // created IAP data in gconf when this function gets + // called for the first time. + // WLAN type & name are updated into IAP data in gconf + // as soon as WLAN connection is up and running. + // => And this function gets called again. + QMutexLocker locker(&mutex); - QStringList previous = accessPointConfigurations.keys(); + if (!accessPointConfigurations.contains(iap_id)) { + Maemo::IAPConf saved_iap(iap_id); + QString iap_type = saved_iap.value("type").toString(); + QString iap_name = saved_iap.value("name").toString(); + QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray(); + if (!iap_type.isEmpty() && !iap_name.isEmpty()) { + // Check if new IAP is actually Undefined WLAN configuration + // Note: SSID is used as an iap id for Undefined WLAN configurations + // => configuration must be searched using SSID + if (!ssid.isEmpty() && accessPointConfigurations.contains(ssid)) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(ssid); + if (ptr) { + ptr->mutex.lock(); + ptr->id = iap_id; + toIcdConfig(ptr)->iap_type = iap_type; + toIcdConfig(ptr)->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString()); + toIcdConfig(ptr)->network_id = ssid; + toIcdConfig(ptr)->service_id = saved_iap.value("service_id").toString(); + toIcdConfig(ptr)->service_type = saved_iap.value("service_type").toString(); + if (m_onlineIapId == iap_id) { + ptr->state = QNetworkConfiguration::Active; + } else { + ptr->state = QNetworkConfiguration::Defined; + } + ptr->mutex.unlock(); + accessPointConfigurations.insert(iap_id, ptr); - /* All the scanned access points */ - QList<Maemo::IcdScanResult> scanned; + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); + } + } else { + IcdNetworkConfigurationPrivate *cpPriv = new IcdNetworkConfigurationPrivate; + cpPriv->name = saved_iap.value("name").toString(); + if (cpPriv->name.isEmpty()) + cpPriv->name = iap_id; + cpPriv->isValid = true; + cpPriv->id = iap_id; + cpPriv->iap_type = iap_type; + cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString()); + cpPriv->service_id = saved_iap.value("service_id").toString(); + cpPriv->service_type = saved_iap.value("service_type").toString(); + if (iap_type.startsWith(QLatin1String("WLAN"))) { + QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray(); + if (ssid.isEmpty()) { + qWarning() << "Cannot get ssid for" << iap_id; + } + cpPriv->network_id = ssid; + } + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + if (m_onlineIapId == iap_id) { + cpPriv->state = QNetworkConfiguration::Active; + } else { + cpPriv->state = QNetworkConfiguration::Defined; + } - /* We create a default configuration which is a pseudo config */ - if (!userChoiceConfigurations.contains(OSSO_IAP_ANY)) { - QNetworkConfigurationPrivatePointer ptr(new IcdNetworkConfigurationPrivate); + QNetworkConfigurationPrivatePointer ptr(cpPriv); + accessPointConfigurations.insert(iap_id, ptr); - ptr->name = QLatin1String("UserChoice"); - ptr->state = QNetworkConfiguration::Discovered; - ptr->isValid = true; - ptr->id = OSSO_IAP_ANY; - ptr->type = QNetworkConfiguration::UserChoice; - ptr->purpose = QNetworkConfiguration::UnknownPurpose; - ptr->roamingSupported = false; +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug("IAP: %s, name: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data()); +#endif + locker.unlock(); + emit configurationAdded(ptr); + locker.relock(); + } + } else { + qWarning("IAP %s does not have \"type\" or \"name\" fields defined, skipping this IAP.", iap_id.toAscii().data()); + } + } else { +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "IAP" << iap_id << "already in db."; +#endif - userChoiceConfigurations.insert(ptr->id, ptr); + /* Check if the data in db changed and update configuration accordingly + */ + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iap_id); + if (ptr) { + Maemo::IAPConf changed_iap(iap_id); + QString iap_type = changed_iap.value("type").toString(); + bool update_needed = false; /* if IAP type or ssid changed, we need to change the state */ + + QMutexLocker configLocker(&ptr->mutex); + + toIcdConfig(ptr)->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString()); + toIcdConfig(ptr)->service_id = changed_iap.value("service_id").toString(); + toIcdConfig(ptr)->service_type = changed_iap.value("service_type").toString(); + + if (!iap_type.isEmpty()) { + ptr->name = changed_iap.value("name").toString(); + if (ptr->name.isEmpty()) + ptr->name = iap_id; + ptr->isValid = true; + if (toIcdConfig(ptr)->iap_type != iap_type) { + toIcdConfig(ptr)->iap_type = iap_type; + update_needed = true; + } + if (iap_type.startsWith(QLatin1String("WLAN"))) { + QByteArray ssid = changed_iap.value("wlan_ssid").toByteArray(); + if (ssid.isEmpty()) { + qWarning() << "Cannot get ssid for" << iap_id; + } + if (toIcdConfig(ptr)->network_id != ssid) { + toIcdConfig(ptr)->network_id = ssid; + update_needed = true; + } + } + } + + if (update_needed) { + ptr->type = QNetworkConfiguration::InternetAccessPoint; + if (m_onlineIapId == iap_id) { + if (ptr->state < QNetworkConfiguration::Active) { + ptr->state = QNetworkConfiguration::Active; + + configLocker.unlock(); + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); + } + } else if (ptr->state < QNetworkConfiguration::Defined) { + ptr->state = QNetworkConfiguration::Defined; - locker.unlock(); - emit configurationAdded(ptr); - locker.relock(); + configLocker.unlock(); + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); + } + } + } else { + qWarning("Cannot find IAP %s from current configuration although it should be there.", iap_id.toAscii().data()); + } } +} + +void QIcdEngine::doRequestUpdate(QList<Maemo::IcdScanResult> scanned) +{ + QMutexLocker locker(&mutex); + + /* Contains all known iap_ids from storage */ + QList<QString> knownConfigs = accessPointConfigurations.keys(); + + /* Contains all known WLAN network ids (like ssid) from storage */ + QMultiHash<QByteArray, SSIDInfo* > notDiscoveredWLANConfigs; - /* We return currently configured IAPs in the first run and do the WLAN - * scan in subsequent runs. - */ QList<QString> all_iaps; Maemo::IAPConf::getAll(all_iaps); - foreach (QString iap_id, all_iaps) { + foreach (const QString &iap_id, all_iaps) { QByteArray ssid; - previous.removeAll(iap_id); - Maemo::IAPConf saved_ap(iap_id); bool is_temporary = saved_ap.value("temporary").toBool(); if (is_temporary) { @@ -207,12 +537,16 @@ void QIcdEngine::doRequestUpdate() } QString iap_type = saved_ap.value("type").toString(); - if (iap_type.startsWith("WLAN")) { + if (iap_type.startsWith(QLatin1String("WLAN"))) { ssid = saved_ap.value("wlan_ssid").toByteArray(); if (ssid.isEmpty()) continue; QString security_method = saved_ap.value("wlan_security").toString(); + SSIDInfo *info = new SSIDInfo; + info->iap_id = iap_id; + info->wlan_security = security_method; + notDiscoveredWLANConfigs.insert(ssid, info); } else if (iap_type.isEmpty()) { continue; } else { @@ -227,10 +561,10 @@ void QIcdEngine::doRequestUpdate() cpPriv->name = saved_ap.value("name").toString(); if (cpPriv->name.isEmpty()) { - if (!ssid.isEmpty() && ssid.size() > 0) - cpPriv->name = ssid.data(); - else - cpPriv->name = iap_id; + if (!ssid.isEmpty() && ssid.size() > 0) + cpPriv->name = ssid.data(); + else + cpPriv->name = iap_id; } cpPriv->isValid = true; cpPriv->id = iap_id; @@ -255,6 +589,7 @@ void QIcdEngine::doRequestUpdate() !ssid.isEmpty() ? ssid.data() : "-"); #endif } else { + knownConfigs.removeOne(iap_id); #ifdef BEARER_MANAGEMENT_DEBUG qDebug("IAP: %s, ssid: %s, already exists in the known list", iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-"); @@ -262,47 +597,16 @@ void QIcdEngine::doRequestUpdate() } } - if (sender()) { - QStringList scannedNetworkTypes; - QStringList networkTypesToScan; - QString error; - Maemo::Icd icd(ICD_SHORT_SCAN_TIMEOUT); - - scannedNetworkTypes = icd.scan(ICD_SCAN_REQUEST_ACTIVE, - networkTypesToScan, - scanned, - error); - if (!error.isEmpty()) { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "Network scanning failed" << error; -#endif - } else { -#ifdef BEARER_MANAGEMENT_DEBUG - if (!scanned.isEmpty()) - qDebug() << "Scan returned" << scanned.size() << "networks"; - else - qDebug() << "Scan returned nothing."; -#endif - } - } - /* This is skipped in the first update as scanned size is zero */ if (!scanned.isEmpty()) { for (int i=0; i<scanned.size(); ++i) { const Maemo::IcdScanResult ap = scanned.at(i); - QByteArray scanned_ssid = ap.scan.network_id; - if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) { /* The network_id is IAP id, so the IAP is a known one */ QString iapid = ap.scan.network_id.data(); - - previous.removeAll(iapid); - - if (accessPointConfigurations.contains(iapid)) { - QNetworkConfigurationPrivatePointer ptr = - accessPointConfigurations.value(iapid); - + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iapid); + if (ptr) { bool changed = false; ptr->mutex.lock(); @@ -324,7 +628,7 @@ void QIcdEngine::doRequestUpdate() #ifdef BEARER_MANAGEMENT_DEBUG qDebug("IAP: %s, ssid: %s, discovered", - iapid.toAscii().data(), scanned_ssid.data()); + iapid.toAscii().data(), toIcdConfig(ptr)->network_id.data()); #endif ptr->mutex.unlock(); @@ -337,101 +641,350 @@ void QIcdEngine::doRequestUpdate() if (!ap.scan.network_type.startsWith(QLatin1String("WLAN"))) continue; // not a wlan AP + + /* Remove scanned AP from discovered WLAN configurations so that we can + * emit configurationRemoved signal later + */ + ptr->mutex.lock(); + QList<SSIDInfo* > known_iaps = notDiscoveredWLANConfigs.values(toIcdConfig(ptr)->network_id); +rescan_list: + if (!known_iaps.isEmpty()) { + for (int k=0; k<known_iaps.size(); ++k) { + SSIDInfo *iap = known_iaps.at(k); + + if (iap->wlan_security == + network_attrs_to_security(ap.scan.network_attrs)) { + /* Remove IAP from the list */ + notDiscoveredWLANConfigs.remove(toIcdConfig(ptr)->network_id, iap); +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "Removed IAP" << iap->iap_id << "from unknown config"; +#endif + known_iaps.removeAt(k); + delete iap; + goto rescan_list; + } + } + } + ptr->mutex.unlock(); } } else { - IcdNetworkConfigurationPrivate *cpPriv = new IcdNetworkConfigurationPrivate; - - QString hrs = scanned_ssid.data(); - - cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name; - cpPriv->isValid = true; - // Note: id is now ssid, it should be set to IAP id if the IAP is saved - cpPriv->id = scanned_ssid.data(); - cpPriv->network_id = scanned_ssid; - cpPriv->iap_type = ap.scan.network_type; - if (cpPriv->iap_type.isEmpty()) - cpPriv->iap_type = QLatin1String("WLAN"); - cpPriv->network_attrs = ap.scan.network_attrs; - cpPriv->service_id = ap.scan.service_id; - cpPriv->service_type = ap.scan.service_type; - cpPriv->service_attrs = ap.scan.service_attrs; - - cpPriv->type = QNetworkConfiguration::InternetAccessPoint; - cpPriv->state = QNetworkConfiguration::Undefined; + /* Non saved access point data */ + QByteArray scanned_ssid = ap.scan.network_id; + if (!accessPointConfigurations.contains(scanned_ssid)) { + IcdNetworkConfigurationPrivate *cpPriv = new IcdNetworkConfigurationPrivate; + QString hrs = scanned_ssid.data(); + + cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name; + cpPriv->isValid = true; + cpPriv->id = scanned_ssid.data(); // Note: id is now ssid, it should be set to IAP id if the IAP is saved + cpPriv->network_id = scanned_ssid; + cpPriv->iap_type = ap.scan.network_type; + cpPriv->network_attrs = ap.scan.network_attrs; + cpPriv->service_id = ap.scan.service_id; + cpPriv->service_type = ap.scan.service_type; + cpPriv->service_attrs = ap.scan.service_attrs; + + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + cpPriv->state = QNetworkConfiguration::Undefined; #ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan."; + qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan."; #endif - previous.removeAll(cpPriv->id); + QNetworkConfigurationPrivatePointer ptr(cpPriv); + accessPointConfigurations.insert(ptr->id, ptr); - QNetworkConfigurationPrivatePointer ptr(cpPriv); - accessPointConfigurations.insert(ptr->id, ptr); + locker.unlock(); + emit configurationAdded(ptr); + locker.relock(); + } else { + knownConfigs.removeOne(scanned_ssid); + } + } + } + } + + if (!firstUpdate) { + // Update Defined status to all defined WLAN IAPs which + // could not be found when access points were scanned + QHashIterator<QByteArray, SSIDInfo* > i(notDiscoveredWLANConfigs); + while (i.hasNext()) { + i.next(); + SSIDInfo *iap = i.value(); + QString iap_id = iap->iap_id; + //qDebug() << i.key() << ": " << iap_id; + + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iap_id); + if (ptr) { + QMutexLocker configLocker(&ptr->mutex); + + // WLAN AccessPoint configuration could not be Discovered + // => Make sure that configuration state is Defined + if (ptr->state > QNetworkConfiguration::Defined) { + ptr->state = QNetworkConfiguration::Defined; + + configLocker.unlock(); + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); + } + } + } + /* Remove non existing iaps since last update */ + foreach (const QString &oldIface, knownConfigs) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldIface); + if (ptr) { locker.unlock(); - emit configurationAdded(ptr); + emit configurationRemoved(ptr); locker.relock(); + //if we would have SNAP support we would have to remove the references + //from existing ServiceNetworks to the removed access point configuration } } } - while (!previous.isEmpty()) { - QNetworkConfigurationPrivatePointer ptr = - accessPointConfigurations.take(previous.takeFirst()); + QMutableHashIterator<QByteArray, SSIDInfo* > i(notDiscoveredWLANConfigs); + while (i.hasNext()) { + i.next(); + SSIDInfo *iap = i.value(); + delete iap; + i.remove(); + } + if (!firstUpdate) { locker.unlock(); - emit configurationRemoved(ptr); + emit updateCompleted(); locker.relock(); } - if (sender()) { - locker.unlock(); - emit updateCompleted(); + if (firstUpdate) + firstUpdate = false; +} + +QNetworkConfigurationPrivatePointer QIcdEngine::defaultConfiguration() +{ + QMutexLocker locker(&mutex); + + // Here we just return [ANY] request to icd and let the icd decide which IAP to connect. + return userChoiceConfigurations.value(OSSO_IAP_ANY); +} + +void QIcdEngine::startListeningStateSignalsForAllConnections() +{ + QMutexLocker locker(&mutex); + + // Start listening ICD_DBUS_API_STATE_SIG signals + m_dbusInterface->connection().connect(ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_PATH, + ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_STATE_SIG, + this, SLOT(connectionStateSignalsSlot(QDBusMessage))); + + // Calling ICD_DBUS_API_STATE_REQ makes sure that initial state will be updated immediately + m_gettingInitialConnectionState = true; + m_dbusInterface->call(ICD_DBUS_API_STATE_REQ); +} + +void QIcdEngine::connectionStateSignalsSlot(QDBusMessage msg) +{ + QMutexLocker locker(&mutex); + + QList<QVariant> arguments = msg.arguments(); + if (arguments[1].toUInt() != 0 || arguments.count() < 8) { + return; } + + QString iapid = arguments[5].toByteArray().data(); + uint icd_connection_state = arguments[7].toUInt(); + + switch (icd_connection_state) { + case ICD_STATE_CONNECTED: + { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iapid); + if (ptr) { + QMutexLocker configLocker(&ptr->mutex); + + ptr->type = QNetworkConfiguration::InternetAccessPoint; + if (ptr->state != QNetworkConfiguration::Active) { + ptr->state = QNetworkConfiguration::Active; + if (!m_gettingInitialConnectionState) { + configLocker.unlock(); + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); + } + m_onlineIapId = iapid; + } + } else { + // This gets called when new WLAN IAP is created using Connection dialog + // At this point Undefined WLAN configuration has SSID as iap id + // => Because of that configuration can not be found from + // accessPointConfigurations using correct iap id + m_onlineIapId = iapid; + } + break; + } + case ICD_STATE_DISCONNECTED: + { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iapid); + if (ptr) { + QMutexLocker configLocker(&ptr->mutex); + + ptr->type = QNetworkConfiguration::InternetAccessPoint; + if (ptr->state == QNetworkConfiguration::Active) { + ptr->state = QNetworkConfiguration::Discovered; + if (!m_gettingInitialConnectionState) { + configLocker.unlock(); + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); + + // Note: If ICD switches used IAP from one to another: + // 1) new IAP is reported to be online first + // 2) old IAP is reported to be offline then + // => Device can be reported to be offline only + // if last known online IAP is reported to be disconnected + if (iapid == m_onlineIapId) { + // It's known that there is only one global ICD connection + // => Because ICD state was reported to be DISCONNECTED, Device is offline + m_onlineIapId.clear(); + } + } + } + } else { + // Disconnected IAP was not found from accessPointConfigurations + // => Reason: Online IAP was removed which resulted ICD to disconnect + if (iapid == m_onlineIapId) { + // It's known that there is only one global ICD connection + // => Because ICD state was reported to be DISCONNECTED, Device is offline + m_onlineIapId.clear(); + } + } + break; + } + default: + break; + } + + locker.unlock(); + emit iapStateChanged(iapid, icd_connection_state); + locker.relock(); + + m_gettingInitialConnectionState = false; } -void QIcdEngine::deleteConfiguration(const QString &iap_id) +void QIcdEngine::requestUpdate() { QMutexLocker locker(&mutex); - /* Called when IAPs are deleted in db, in this case we do not scan - * or read all the IAPs from db because it might take too much power - * (multiple applications would need to scan and read all IAPs from db) - */ - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(iap_id); - if (ptr) { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "IAP" << iap_id << "was removed from storage."; -#endif + if (m_scanGoingOn) { + return; + } + m_scanGoingOn = true; + + m_dbusInterface->connection().connect(ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_PATH, + ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_SCAN_SIG, + this, SLOT(asyncUpdateConfigurationsSlot(QDBusMessage))); + + QDBusMessage msg = m_dbusInterface->call(ICD_DBUS_API_SCAN_REQ, + (uint)ICD_SCAN_REQUEST_ACTIVE); + m_typesToBeScanned = msg.arguments()[0].value<QStringList>(); + m_scanTimer.start(ICD_SHORT_SCAN_TIMEOUT); +} - locker.unlock(); - emit configurationRemoved(ptr); - } else { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug("IAP: %s, already missing from the known list", iap_id.toAscii().data()); -#endif +void QIcdEngine::cancelAsyncConfigurationUpdate() +{ + QMutexLocker locker(&mutex); + + if (!m_scanGoingOn) { + return; + } + m_scanGoingOn = false; + + if (m_scanTimer.isActive()) { + m_scanTimer.stop(); } + + m_dbusInterface->connection().disconnect(ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_PATH, + ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_SCAN_SIG, + this, SLOT(asyncUpdateConfigurationsSlot(QDBusMessage))); + + // Stop scanning rounds by calling ICD_DBUS_API_SCAN_CANCEL + // <=> If ICD_DBUS_API_SCAN_CANCEL is not called, new scanning round will + // be started after the module scan timeout. + m_dbusInterface->call(ICD_DBUS_API_SCAN_CANCEL); } -QNetworkConfigurationManager::Capabilities QIcdEngine::capabilities() const +void QIcdEngine::finishAsyncConfigurationUpdate() { - return QNetworkConfigurationManager::CanStartAndStopInterfaces | - QNetworkConfigurationManager::DataStatistics | - QNetworkConfigurationManager::ForcedRoaming | - QNetworkConfigurationManager::NetworkSessionRequired; + QMutexLocker locker(&mutex); + + cancelAsyncConfigurationUpdate(); + doRequestUpdate(m_scanResult); + m_scanResult.clear(); } -QNetworkSessionPrivate *QIcdEngine::createSessionBackend() +void QIcdEngine::asyncUpdateConfigurationsSlot(QDBusMessage msg) { - return new QNetworkSessionPrivateImpl(this); + QMutexLocker locker(&mutex); + + QList<QVariant> arguments = msg.arguments(); + uint icd_scan_status = arguments.takeFirst().toUInt(); + if (icd_scan_status == ICD_SCAN_COMPLETE) { + m_typesToBeScanned.removeOne(arguments[6].toString()); + if (!m_typesToBeScanned.count()) { + finishAsyncConfigurationUpdate(); + } + } else { + Maemo::IcdScanResult scanResult; + scanResult.status = icd_scan_status; + scanResult.timestamp = arguments.takeFirst().toUInt(); + scanResult.scan.service_type = arguments.takeFirst().toString(); + scanResult.service_name = arguments.takeFirst().toString(); + scanResult.scan.service_attrs = arguments.takeFirst().toUInt(); + scanResult.scan.service_id = arguments.takeFirst().toString(); + scanResult.service_priority = arguments.takeFirst().toInt(); + scanResult.scan.network_type = arguments.takeFirst().toString(); + scanResult.network_name = arguments.takeFirst().toString(); + scanResult.scan.network_attrs = arguments.takeFirst().toUInt(); + scanResult.scan.network_id = arguments.takeFirst().toByteArray(); + scanResult.network_priority = arguments.takeFirst().toInt(); + scanResult.signal_strength = arguments.takeFirst().toInt(); + scanResult.station_id = arguments.takeFirst().toString(); + scanResult.signal_dB = arguments.takeFirst().toInt(); + + m_scanResult.append(scanResult); + } } -QNetworkConfigurationPrivatePointer QIcdEngine::defaultConfiguration() +void QIcdEngine::cleanup() +{ + if (m_scanGoingOn) { + m_scanTimer.stop(); + m_dbusInterface->call(ICD_DBUS_API_SCAN_CANCEL); + } + iapMonitor->cleanup(); +} + +bool QIcdEngine::hasIdentifier(const QString &id) { QMutexLocker locker(&mutex); - // Here we just return [ANY] request to icd and let the icd decide which IAP to connect. - return userChoiceConfigurations.value(OSSO_IAP_ANY); + return accessPointConfigurations.contains(id) || + snapConfigurations.contains(id) || + userChoiceConfigurations.contains(id); } +QNetworkSessionPrivate *QIcdEngine::createSessionBackend() +{ + return new QNetworkSessionPrivateImpl(this); +} + +#include "qicdengine.moc" + QT_END_NAMESPACE diff --git a/src/plugins/bearer/icd/qicdengine.h b/src/plugins/bearer/icd/qicdengine.h index 50cda62..a2e9a2f 100644 --- a/src/plugins/bearer/icd/qicdengine.h +++ b/src/plugins/bearer/icd/qicdengine.h @@ -44,10 +44,15 @@ #include <QtNetwork/private/qbearerengine_p.h> +#include <QtCore/qtimer.h> + +#include <maemo_icd.h> + QT_BEGIN_NAMESPACE class QNetworkConfigurationPrivate; class IapMonitor; +class QDBusInterface; class IcdNetworkConfigurationPrivate : public QNetworkConfigurationPrivate { @@ -118,11 +123,35 @@ public: emit configurationChanged(ptr); } + void init(); + void cleanup(); + + void addConfiguration(QString &iap_id); + +Q_SIGNALS: + void iapStateChanged(const QString& iapid, uint icd_connection_state); + private Q_SLOTS: - void doRequestUpdate(); + void doRequestUpdate(QList<Maemo::IcdScanResult> scanned = QList<Maemo::IcdScanResult>()); + void cancelAsyncConfigurationUpdate(); + void finishAsyncConfigurationUpdate(); + void asyncUpdateConfigurationsSlot(QDBusMessage msg); + void connectionStateSignalsSlot(QDBusMessage msg); + +private: + void startListeningStateSignalsForAllConnections(); private: IapMonitor *iapMonitor; + QDBusInterface *m_dbusInterface; + QTimer m_scanTimer; + QString m_onlineIapId; + QStringList m_typesToBeScanned; + QList<Maemo::IcdScanResult> m_scanResult; + + bool firstUpdate; + bool m_gettingInitialConnectionState; + bool m_scanGoingOn; }; QT_END_NAMESPACE diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp index 5bf95dc..2928a31 100644 --- a/src/plugins/bearer/icd/qnetworksession_impl.cpp +++ b/src/plugins/bearer/icd/qnetworksession_impl.cpp @@ -44,294 +44,146 @@ #include <QHash> -#include <dbus/dbus.h> -#include <dbus/dbus-glib-lowlevel.h> - #include <maemo_icd.h> #include <iapconf.h> #include <proxyconf.h> -#include <sys/types.h> #include <ifaddrs.h> -#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> QT_BEGIN_NAMESPACE -static QHash<QString, QVariant> properties; - -static QString get_network_interface(); -static DBusConnection *dbus_connection; -static DBusHandlerResult signal_handler(DBusConnection *connection, - DBusMessage *message, - void *user_data); - -#define ICD_DBUS_MATCH "type='signal'," \ - "interface='" ICD_DBUS_INTERFACE "'," \ - "path='" ICD_DBUS_PATH "'" - - -static inline DBusConnection *get_dbus_conn(DBusError *error) +QDBusArgument &operator<<(QDBusArgument &argument, + const ICd2DetailsDBusStruct &icd2) { - DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, error); -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "Listening to bus" << dbus_bus_get_unique_name(conn); -#endif - - return conn; + argument.beginStructure(); + argument << icd2.serviceType; + argument << icd2.serviceAttributes; + argument << icd2.setviceId; + argument << icd2.networkType; + argument << icd2.networkAttributes; + argument << icd2.networkId; + argument.endStructure(); + return argument; } - -/* Helper class that monitors the Icd status messages and - * can change the IAP status accordingly. This is a singleton. - */ -class IcdListener : public QObject -{ - Q_OBJECT - -public: - IcdListener() : first_call(true) { } - friend DBusHandlerResult signal_handler(DBusConnection *connection, - DBusMessage *message, - void *user_data); - void setup(QNetworkSessionPrivateImpl *d); - void cleanup(); - void cleanupSession(QNetworkSessionPrivateImpl *ptr); - - enum IapConnectionStatus { - /* The IAP was connected */ - CONNECTED = 0, - /* The IAP was disconnected */ - DISCONNECTED, - /* The IAP is disconnecting */ - DISCONNECTING, - /* The IAP has a network address, but is not yet fully connected */ - NETWORK_UP - }; - -private: - void icdSignalReceived(QString&, QString&, QString&); - bool first_call; - QHash<QString, QNetworkSessionPrivateImpl *> sessions; -}; - -Q_GLOBAL_STATIC(IcdListener, icdListener); - - -static DBusHandlerResult signal_handler(DBusConnection *, - DBusMessage *message, - void *user_data) +const QDBusArgument &operator>>(const QDBusArgument &argument, + ICd2DetailsDBusStruct &icd2) { - if (dbus_message_is_signal(message, - ICD_DBUS_INTERFACE, - ICD_STATUS_CHANGED_SIG)) { - - IcdListener *icd = (IcdListener *)user_data; - DBusError error; - dbus_error_init(&error); - - char *iap_id = 0; - char *network_type = 0; - char *state = 0; - - if (dbus_message_get_args(message, &error, - DBUS_TYPE_STRING, &iap_id, - DBUS_TYPE_STRING, &network_type, - DBUS_TYPE_STRING, &state, - DBUS_TYPE_INVALID) == FALSE) { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << QString("Failed to parse icd status signal: %1").arg(error.message); -#endif - } else { - QString _iap_id(iap_id); - QString _network_type(network_type); - QString _state(state); - - icd->icdSignalReceived(_iap_id, _network_type, _state); - } - - dbus_error_free(&error); - return DBUS_HANDLER_RESULT_HANDLED; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + argument.beginStructure(); + argument >> icd2.serviceType; + argument >> icd2.serviceAttributes; + argument >> icd2.setviceId; + argument >> icd2.networkType; + argument >> icd2.networkAttributes; + argument >> icd2.networkId; + argument.endStructure(); + return argument; } - -void IcdListener::setup(QNetworkSessionPrivateImpl *d) +const QDBusArgument &operator>>(const QDBusArgument &argument, + ICd2DetailsList &detailsList) { - if (first_call) { - // We use the old Icd dbus interface like in ConIC - DBusError error; - dbus_error_init(&error); - - dbus_connection = get_dbus_conn(&error); - if (dbus_error_is_set(&error)) { - dbus_error_free(&error); - return; - } - - static struct DBusObjectPathVTable icd_vtable; - icd_vtable.message_function = signal_handler; - - dbus_bus_add_match(dbus_connection, ICD_DBUS_MATCH, &error); - if (dbus_error_is_set(&error)) { - dbus_error_free(&error); - return; - } - - if (dbus_connection_register_object_path(dbus_connection, - ICD_DBUS_PATH, - &icd_vtable, - (void*)this) == FALSE) { - dbus_error_free(&error); - return; - } + argument.beginArray(); + detailsList.clear(); -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "Listening" << ICD_STATUS_CHANGED_SIG << "signal from" << ICD_DBUS_SERVICE; -#endif - first_call = false; - dbus_error_free(&error); - } + while (!argument.atEnd()) { + ICd2DetailsDBusStruct element; + argument >> element; + detailsList.append(element); + } - QString id = d->activeConfig.identifier(); - if (!sessions.contains(id)) { - QNetworkSessionPrivateImpl *ptr = d; - sessions.insert(id, ptr); - } + argument.endArray(); + return argument; } - -void IcdListener::icdSignalReceived(QString& iap_id, -#ifdef BEARER_MANAGEMENT_DEBUG - QString& network_type, -#else - QString&, -#endif - QString& state) +QDBusArgument &operator<<(QDBusArgument &argument, + const ICd2DetailsList &detailsList) { - if (iap_id == OSSO_IAP_SCAN) // icd sends scan status signals which we will ignore - return; - -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "Status received:" << iap_id << "type" << network_type << "state" << state; -#endif - - if (!sessions.contains(iap_id)) { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "No session for IAP" << iap_id; -#endif - return; - } - - QNetworkSessionPrivateImpl *session = sessions.value(iap_id); - QNetworkConfiguration ap_conf = - QNetworkConfigurationManager().configurationFromIdentifier(iap_id); - if (!ap_conf.isValid()) { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "Unknown IAP" << iap_id; -#endif - return; - } - - IapConnectionStatus status; - - if (state == "IDLE") { - status = DISCONNECTED; - } else if (state == "CONNECTED") { - status = CONNECTED; - } else if (state == "NETWORKUP") { - status = NETWORK_UP; - } else { - //qDebug() << "Unknown state" << state; - return; - } - - if (status == DISCONNECTED) { - if (ap_conf.state() == QNetworkConfiguration::Active) { - /* The IAP was just disconnected by Icd */ - session->updateState(QNetworkSession::Disconnected); - } else { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "Got a network disconnect when in state" << ap_conf.state(); -#endif - } - } else if (status == CONNECTED) { - /* The IAP was just connected by Icd */ - session->updateState(QNetworkSession::Connected); - session->updateIdentifier(iap_id); - - if (session->publicConfig.identifier() == OSSO_IAP_ANY) { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "IAP" << iap_id << "connected when connecting to" << OSSO_IAP_ANY; -#endif - } else { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "IAP" << iap_id << "connected"; -#endif - } - } - - return; + argument.beginArray(qMetaTypeId<ICd2DetailsDBusStruct>()); + for (int i = 0; i < detailsList.count(); ++i) + argument << detailsList[i]; + argument.endArray(); + return argument; } +static QHash<QString, QVariant> properties; -void IcdListener::cleanup() +static QString get_network_interface(); + +void QNetworkSessionPrivateImpl::iapStateChanged(const QString& iapid, uint icd_connection_state) { - if (!first_call) { - dbus_bus_remove_match(dbus_connection, ICD_DBUS_MATCH, NULL); - dbus_connection_unref(dbus_connection); + if ((publicConfig.type() == QNetworkConfiguration::UserChoice) && opened) { + updateIdentifier(iapid); } -} - -void IcdListener::cleanupSession(QNetworkSessionPrivateImpl *ptr) -{ - if (ptr->publicConfig.type() == QNetworkConfiguration::UserChoice) - (void)sessions.take(ptr->activeConfig.identifier()); - else - (void)sessions.take(ptr->publicConfig.identifier()); + if (((publicConfig.type() == QNetworkConfiguration::UserChoice) && + (activeConfig.identifier() == iapid)) || + (publicConfig.identifier() == iapid)) { + switch (icd_connection_state) { + case ICD_STATE_CONNECTING: + updateState(QNetworkSession::Connecting); + break; + case ICD_STATE_CONNECTED: + updateState(QNetworkSession::Connected); + break; + case ICD_STATE_DISCONNECTING: + updateState(QNetworkSession::Closing); + break; + case ICD_STATE_DISCONNECTED: + updateState(QNetworkSession::Disconnected); + break; + default: + break; + } + } } - void QNetworkSessionPrivateImpl::cleanupSession(void) { - icdListener()->cleanupSession(this); - QObject::disconnect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State))); } void QNetworkSessionPrivateImpl::updateState(QNetworkSession::State newState) { - if (newState == state) - return; - - state = newState; - - if (state == QNetworkSession::Disconnected) { - isOpen = false; - currentNetworkInterface.clear(); - if (publicConfig.type() == QNetworkConfiguration::UserChoice) { - IcdNetworkConfigurationPrivate *icdConfig = - toIcdConfig(privateConfiguration(activeConfig)); - - icdConfig->mutex.lock(); - icdConfig->state = QNetworkConfiguration::Defined; - icdConfig->mutex.unlock(); - } - - IcdNetworkConfigurationPrivate *icdConfig = - toIcdConfig(privateConfiguration(publicConfig)); - - icdConfig->mutex.lock(); - icdConfig->state = QNetworkConfiguration::Defined; - icdConfig->mutex.unlock(); - - } else if (state == QNetworkSession::Connected) { - isOpen = true; + if (newState != state) { + if (newState == QNetworkSession::Disconnected) { + if (isOpen) { + // The Session was aborted by the user or system + lastError = QNetworkSession::SessionAbortedError; + emit QNetworkSessionPrivate::error(lastError); + emit closed(); + } + if (m_stopTimer.isActive()) { + // Session was closed by calling stop() + m_stopTimer.stop(); + } + isOpen = false; + opened = false; + currentNetworkInterface.clear(); + if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + copyConfig(publicConfig, activeConfig); + IcdNetworkConfigurationPrivate *icdConfig = + toIcdConfig(privateConfiguration(activeConfig)); + + icdConfig->mutex.lock(); + icdConfig->state = QNetworkConfiguration::Defined; + icdConfig->mutex.unlock(); + } else { + if (!activeConfig.isValid()) { + // Active configuration (IAP) was removed from system + // => Connection was disconnected and configuration became + // invalid + // => Also Session state must be changed to invalid + newState = QNetworkSession::Invalid; + } + } + } else if (newState == QNetworkSession::Connected) { + if (opened) { + isOpen = true; + } if (publicConfig.type() == QNetworkConfiguration::UserChoice) { IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(activeConfig)); @@ -350,11 +202,15 @@ void QNetworkSessionPrivateImpl::updateState(QNetworkSession::State newState) icdConfig->mutex.unlock(); } - emit stateChanged(newState); + if (newState != state) { + state = newState; + emit stateChanged(newState); + } + } } -void QNetworkSessionPrivateImpl::updateIdentifier(QString &newId) +void QNetworkSessionPrivateImpl::updateIdentifier(const QString &newId) { if (publicConfig.type() == QNetworkConfiguration::UserChoice) { IcdNetworkConfigurationPrivate *icdConfig = @@ -479,9 +335,6 @@ QNetworkConfiguration& QNetworkSessionPrivateImpl::copyConfig(QNetworkConfigurat */ void QNetworkSessionPrivateImpl::syncStateWithInterface() { - /* Start to listen Icd status messages. */ - icdListener()->setup(this); - /* Initially we are not active although the configuration might be in * connected state. */ @@ -490,8 +343,8 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged())); - connect(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)), - this, SLOT(configurationChanged(QNetworkConfiguration))); + connect(engine, SIGNAL(iapStateChanged(const QString&, uint)), + this, SLOT(iapStateChanged(const QString&, uint))); QObject::connect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State))); @@ -500,14 +353,14 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() switch (publicConfig.type()) { case QNetworkConfiguration::InternetAccessPoint: - activeConfig = publicConfig; + activeConfig = publicConfig; break; case QNetworkConfiguration::ServiceNetwork: - serviceConfig = publicConfig; + serviceConfig = publicConfig; break; case QNetworkConfiguration::UserChoice: // active config will contain correct data after open() has succeeded - copyConfig(publicConfig, activeConfig); + copyConfig(publicConfig, activeConfig); /* We create new configuration that holds the actual configuration * returned by icd. This way publicConfig still contains the @@ -541,7 +394,6 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() * supports only one connection anyway. */ if (icd.state(state_results) && !state_results.isEmpty()) { - /* If we did not get full state back, then we are not * connected and can skip the next part. */ @@ -554,35 +406,28 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() */ if (publicConfig.type() == QNetworkConfiguration::UserChoice || publicConfig.identifier() == state_results.first().params.network_id) { - switch (state_results.first().state) { case ICD_STATE_DISCONNECTED: - state = QNetworkSession::Disconnected; - { - QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig); - if (ptr) { - ptr->mutex.lock(); - ptr->isValid = true; - ptr->mutex.unlock(); - } + state = QNetworkSession::Disconnected; + if (QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig)) { + ptr->mutex.lock(); + ptr->isValid = true; + ptr->mutex.unlock(); } - break; + break; case ICD_STATE_CONNECTING: - state = QNetworkSession::Connecting; - { - QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig); - if (ptr) { - ptr->mutex.lock(); - ptr->isValid = true; - ptr->mutex.unlock(); - } + state = QNetworkSession::Connecting; + if (QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig)) { + ptr->mutex.lock(); + ptr->isValid = true; + ptr->mutex.unlock(); } - break; + break; case ICD_STATE_CONNECTED: - { - if (!state_results.first().error.isEmpty()) - break; - + { + if (!state_results.first().error.isEmpty()) + break; + const QString id = state_results.first().params.network_id; QNetworkConfiguration config = manager.configurationFromIdentifier(id); @@ -607,7 +452,7 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() ptr->type = QNetworkConfiguration::InternetAccessPoint; ptr->state = QNetworkConfiguration::Active; ptr->isValid = true; - currentNetworkInterface = get_network_interface(); + currentNetworkInterface = get_network_interface(); Maemo::IAPConf iap_name(ptr->id); QString name_value = iap_name.value("name").toString(); @@ -616,8 +461,7 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() else ptr->name = ptr->id; - - // Add the new active configuration to manager or update the old config + // Add the new active configuration to manager or update the old config if (!engine->hasIdentifier(ptr->id)) { configLocker.unlock(); engine->addSessionConfiguration(ptr); @@ -625,24 +469,21 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() configLocker.unlock(); engine->changedSessionConfiguration(ptr); } - } - break; + } + break; case ICD_STATE_DISCONNECTING: - state = QNetworkSession::Closing; - { - QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig); - if (ptr) { - ptr->mutex.lock(); - ptr->isValid = true; - ptr->mutex.unlock(); - } + state = QNetworkSession::Closing; + if (QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig)) { + ptr->mutex.lock(); + ptr->isValid = true; + ptr->mutex.unlock(); } - break; + break; default: - break; + break; } - } + } } else { #ifdef BEARER_MANAGEMENT_DEBUG qDebug() << "status_req tells icd is not connected"; @@ -733,7 +574,6 @@ void QNetworkSessionPrivateImpl::updateStateFromActiveConfig() state = QNetworkSession::NotAvailable; } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) { state = QNetworkSession::NotAvailable; - //clearConfiguration(activeConfig); } bool oldActive = isOpen; @@ -748,7 +588,7 @@ void QNetworkSessionPrivateImpl::updateStateFromActiveConfig() if (oldState != state) { emit stateChanged(state); - if (state == QNetworkSession::Disconnected) { + if (state == QNetworkSession::Disconnected && oldActive) { #ifdef BEARER_MANAGEMENT_DEBUG //qDebug()<<"session aborted error emitted for"<<activeConfig.identifier(); #endif @@ -762,16 +602,6 @@ void QNetworkSessionPrivateImpl::updateStateFromActiveConfig() #endif } - -void QNetworkSessionPrivateImpl::configurationChanged(const QNetworkConfiguration &config) -{ - if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig)) - updateStateFromServiceNetwork(); - else if (config == activeConfig) - updateStateFromActiveConfig(); -} - - static QString get_network_interface() { Maemo::Icd icd; @@ -808,14 +638,16 @@ static QString get_network_interface() } for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - family = ifa->ifa_addr->sa_family; - if (family != AF_INET) { - continue; /* Currently only IPv4 is supported by icd dbus interface */ - } - if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == addr.s_addr) { - iface = QString(ifa->ifa_name); - break; - } + if (ifa->ifa_addr) { + family = ifa->ifa_addr->sa_family; + if (family != AF_INET) { + continue; /* Currently only IPv4 is supported by icd dbus interface */ + } + if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == addr.s_addr) { + iface = QString(ifa->ifa_name); + break; + } + } } freeifaddrs(ifaddr); @@ -825,11 +657,18 @@ static QString get_network_interface() void QNetworkSessionPrivateImpl::open() { + if (m_stopTimer.isActive()) { + m_stopTimer.stop(); + } + if (!publicConfig.isValid()) { + lastError = QNetworkSession::InvalidConfigurationError; + emit QNetworkSessionPrivate::error(lastError); + return; + } if (serviceConfig.isValid()) { lastError = QNetworkSession::OperationNotSupportedError; emit QNetworkSessionPrivate::error(lastError); } else if (!isOpen) { - if (publicConfig.type() == QNetworkConfiguration::UserChoice) { /* Caller is trying to connect to default IAP. * At this time we will not know the IAP details so we just @@ -857,189 +696,183 @@ void QNetworkSessionPrivateImpl::open() if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) { state = QNetworkSession::Connecting; emit stateChanged(state); - - QTimer::singleShot(0, this, SLOT(do_open())); - return; + QTimer::singleShot(0, this, SLOT(do_open())); + return; } - isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active; if (isOpen) emit quitPendingWaitsForOpened(); } else { - /* We seem to be active so inform caller */ - emit quitPendingWaitsForOpened(); + /* We seem to be active so inform caller */ + emit quitPendingWaitsForOpened(); } } - void QNetworkSessionPrivateImpl::do_open() { icd_connection_flags flags = connectFlags; - bool st; - QString result; QString iap = publicConfig.identifier(); if (state == QNetworkSession::Connected) { #ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "Already connected to" << activeConfig.identifier(); + qDebug() << "Already connected to" << activeConfig.identifier(); #endif emit stateChanged(QNetworkSession::Connected); - emit quitPendingWaitsForOpened(); + emit quitPendingWaitsForOpened(); return; } - Maemo::IcdConnectResult connect_result; - Maemo::Icd icd(ICD_LONG_CONNECT_TIMEOUT); - QNetworkConfiguration config; if (publicConfig.type() == QNetworkConfiguration::UserChoice) - config = activeConfig; + config = activeConfig; else - config = publicConfig; + config = publicConfig; if (iap == OSSO_IAP_ANY) { #ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "connecting to default IAP" << iap; + qDebug() << "connecting to default IAP" << iap; #endif - st = icd.connect(flags, connect_result); - + m_connectRequestTimer.start(ICD_LONG_CONNECT_TIMEOUT); + m_dbusInterface->asyncCall(ICD_DBUS_API_CONNECT_REQ, (uint)flags); // Return value ignored + m_asynchCallActive = true; } else { + IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config)); - QList<Maemo::ConnectParams> params; - Maemo::ConnectParams param; - - IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config)); - - icdConfig->mutex.lock(); - param.connect.service_type = icdConfig->service_type; - param.connect.service_attrs = icdConfig->service_attrs; - param.connect.service_id = icdConfig->service_id; - param.connect.network_type = icdConfig->iap_type; - param.connect.network_attrs = icdConfig->network_attrs; - if (icdConfig->network_attrs & ICD_NW_ATTR_IAPNAME) - param.connect.network_id = QByteArray(iap.toLatin1()); - else - param.connect.network_id = icdConfig->network_id; - params.append(param); - icdConfig->mutex.unlock(); + icdConfig->mutex.lock(); + ICd2DetailsDBusStruct icd2; + icd2.serviceType = icdConfig->service_type; + icd2.serviceAttributes = icdConfig->service_attrs; + icd2.setviceId = icdConfig->service_id; + icd2.networkType = icdConfig->iap_type; + icd2.networkAttributes = icdConfig->network_attrs; + if (icdConfig->network_attrs & ICD_NW_ATTR_IAPNAME) { + icd2.networkId = QByteArray(iap.toLatin1()); + } else { + icd2.networkId = icdConfig->network_id; + } + icdConfig->mutex.unlock(); #ifdef BEARER_MANAGEMENT_DEBUG - qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s", - param.connect.network_id.data(), - param.connect.network_type.toAscii().constData(), - param.connect.network_attrs, - param.connect.service_type.toAscii().constData(), - param.connect.service_attrs, - param.connect.service_id.toAscii().constData()); + qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s", + icd2.networkId.data(), + icd2.networkType.toAscii().constData(), + icd2.networkAttributes, + icd2.serviceType.toAscii().constData(), + icd2.serviceAttributes, + icd2.setviceId.toAscii().constData()); #endif - st = icd.connect(flags, params, connect_result); - } - if (st) { - result = connect_result.connect.network_id.data(); - QString connected_iap = result; + ICd2DetailsList paramArray; + paramArray.append(icd2); + m_connectRequestTimer.start(ICD_LONG_CONNECT_TIMEOUT); + m_dbusInterface->asyncCall(ICD_DBUS_API_CONNECT_REQ, (uint)flags, QVariant::fromValue(paramArray)); // Return value ignored + m_asynchCallActive = true; + } +} - if (connected_iap.isEmpty()) { +void QNetworkSessionPrivateImpl::stateChange(const QDBusMessage& rep) +{ + if (m_asynchCallActive == true) { + if (m_connectRequestTimer.isActive()) + m_connectRequestTimer.stop(); + m_asynchCallActive = false; + + QString result = rep.arguments().at(5).toString(); // network id or empty string + QString connected_iap = result; + if (connected_iap.isEmpty()) { #ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "connect to"<< iap << "failed, result is empty"; + qDebug() << "connect to"<< publicConfig.identifier() << "failed, result is empty"; #endif - updateState(QNetworkSession::Disconnected); - emit QNetworkSessionPrivate::error(QNetworkSession::InvalidConfigurationError); - if (publicConfig.type() == QNetworkConfiguration::UserChoice) - cleanupAnyConfiguration(); - return; - } - - /* If the user tried to connect to some specific connection (foo) - * and we were already connected to some other connection (bar), - * then we cannot activate this session although icd has a valid - * connection to somewhere. - */ - if ((publicConfig.type() != QNetworkConfiguration::UserChoice) && - (connected_iap != config.identifier())) { - updateState(QNetworkSession::Disconnected); - emit QNetworkSessionPrivate::error(QNetworkSession::InvalidConfigurationError); - return; - } - - IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config)); - - /* Did we connect to non saved IAP? */ - icdConfig->mutex.lock(); - if (!(icdConfig->network_attrs & ICD_NW_ATTR_IAPNAME)) { - /* Because the connection succeeded, the IAP is now known. - */ - icdConfig->network_attrs |= ICD_NW_ATTR_IAPNAME; - icdConfig->id = connected_iap; - } + updateState(QNetworkSession::Disconnected); + emit QNetworkSessionPrivate::error(QNetworkSession::InvalidConfigurationError); + if (publicConfig.type() == QNetworkConfiguration::UserChoice) + copyConfig(publicConfig, activeConfig); + return; + } - /* User might have changed the IAP name when a new IAP was saved */ - Maemo::IAPConf iap_name(icdConfig->id); - QString name = iap_name.value("name").toString(); - if (!name.isEmpty()) - icdConfig->name = name; + /* If the user tried to connect to some specific connection (foo) + * and we were already connected to some other connection (bar), + * then we cannot activate this session although icd has a valid + * connection to somewhere. + */ + if ((publicConfig.type() != QNetworkConfiguration::UserChoice) && + (connected_iap != config.identifier())) { + updateState(QNetworkSession::Disconnected); + emit QNetworkSessionPrivate::error(QNetworkSession::InvalidConfigurationError); + return; + } - icdConfig->iap_type = connect_result.connect.network_type; + IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config)); - icdConfig->isValid = true; - icdConfig->state = QNetworkConfiguration::Active; - icdConfig->type = QNetworkConfiguration::InternetAccessPoint; + /* Did we connect to non saved IAP? */ + icdConfig->mutex.lock(); + if (!(icdConfig->network_attrs & ICD_NW_ATTR_IAPNAME)) { + /* Because the connection succeeded, the IAP is now known. + */ + icdConfig->network_attrs |= ICD_NW_ATTR_IAPNAME; + icdConfig->id = connected_iap; + } - icdConfig->mutex.unlock(); + /* User might have changed the IAP name when a new IAP was saved */ + Maemo::IAPConf iap_name(icdConfig->id); + QString name = iap_name.value("name").toString(); + if (!name.isEmpty()) + icdConfig->name = name; - startTime = QDateTime::currentDateTime(); - updateState(QNetworkSession::Connected); + icdConfig->iap_type = rep.arguments().at(3).toString(); // connect_result.connect.network_type; + icdConfig->isValid = true; + icdConfig->state = QNetworkConfiguration::Active; + icdConfig->type = QNetworkConfiguration::InternetAccessPoint; - currentNetworkInterface = get_network_interface(); + icdConfig->mutex.unlock(); + startTime = QDateTime::currentDateTime(); + updateState(QNetworkSession::Connected); + //currentNetworkInterface = get_network_interface(); #ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "connected to" << result << config.name() << "at" << currentNetworkInterface; + //qDebug() << "connected to" << result << config.name() << "at" << currentNetworkInterface; #endif - /* We first check if the configuration already exists in the manager - * and if it is not found there, we then insert it. Note that this - * is only done for user choice config only because it can be missing - * from config manager list. - */ - - if (publicConfig.type() == QNetworkConfiguration::UserChoice) { - if (!engine->hasIdentifier(result)) { - engine->addSessionConfiguration(privateConfiguration(config)); - } else { - QNetworkConfigurationPrivatePointer priv = engine->configuration(result); - QNetworkConfiguration reference; - setPrivateConfiguration(reference, priv); - copyConfig(config, reference, false); - config = reference; - activeConfig = reference; - engine->changedSessionConfiguration(privateConfiguration(config)); - } - } - - emit quitPendingWaitsForOpened(); + /* We first check if the configuration already exists in the manager + * and if it is not found there, we then insert it. Note that this + * is only done for user choice config only because it can be missing + * from config manager list. + */ + if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + if (!engine->hasIdentifier(result)) { + engine->addSessionConfiguration(privateConfiguration(config)); + } else { + QNetworkConfigurationPrivatePointer priv = engine->configuration(result); + QNetworkConfiguration reference; + setPrivateConfiguration(reference, priv); + copyConfig(config, reference, false); + privateConfiguration(reference)->id = result; // Note: Id was not copied in copyConfig() function + config = reference; + activeConfig = reference; + engine->changedSessionConfiguration(privateConfiguration(config)); - } else { #ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "connect to"<< iap << "failed, status:" << connect_result.status; + qDebug()<<"Existing configuration"<<result<<"updated in manager in open"; #endif - updateState(QNetworkSession::Disconnected); - if (publicConfig.type() == QNetworkConfiguration::UserChoice) - cleanupAnyConfiguration(); - emit QNetworkSessionPrivate::error(QNetworkSession::UnknownSessionError); + } + } + + emit quitPendingWaitsForOpened(); } } - -void QNetworkSessionPrivateImpl::cleanupAnyConfiguration() +void QNetworkSessionPrivateImpl::connectTimeout() { -#ifdef BEARER_MANAGEMENT_DEBUG - qDebug()<<"Removing configuration created for" << activeConfig.identifier(); -#endif - activeConfig = publicConfig; + updateState(QNetworkSession::Disconnected); + if (publicConfig.type() == QNetworkConfiguration::UserChoice) + copyConfig(publicConfig, activeConfig); + emit QNetworkSessionPrivate::error(QNetworkSession::UnknownSessionError); } - void QNetworkSessionPrivateImpl::close() { + if (m_connectRequestTimer.isActive()) + m_connectRequestTimer.stop(); + if (serviceConfig.isValid()) { lastError = QNetworkSession::OperationNotSupportedError; emit QNetworkSessionPrivate::error(lastError); @@ -1053,35 +886,37 @@ void QNetworkSessionPrivateImpl::close() void QNetworkSessionPrivateImpl::stop() { + if (m_connectRequestTimer.isActive()) + m_connectRequestTimer.stop(); + if (serviceConfig.isValid()) { lastError = QNetworkSession::OperationNotSupportedError; emit QNetworkSessionPrivate::error(lastError); } else { if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { - state = QNetworkSession::Closing; - emit stateChanged(state); - - Maemo::Icd icd; + if (!m_stopTimer.isActive()) { + Maemo::Icd icd; #ifdef BEARER_MANAGEMENT_DEBUG - qDebug() << "stopping session" << publicConfig.identifier(); + qDebug() << "stopping session" << publicConfig.identifier(); #endif - icd.disconnect(ICD_CONNECTION_FLAG_APPLICATION_EVENT); - startTime = QDateTime(); + state = QNetworkSession::Closing; + emit stateChanged(state); - /* Note that the state will go disconnected in - * updateStateFromActiveConfig() which gets called after - * configurationChanged is emitted (below). - */ + opened = false; + isOpen = false; - QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig); - ptr->mutex.lock(); - ptr->state = QNetworkConfiguration::Discovered; - ptr->mutex.unlock(); - engine->changedSessionConfiguration(ptr); + icd.disconnect(ICD_CONNECTION_FLAG_APPLICATION_EVENT); + startTime = QDateTime(); - opened = false; - isOpen = false; + /* Note: Session state will change to disconnected + * as soon as QNetworkConfigurationManager sends + * corresponding iapStateChanged signal. + */ + // Make sure that this Session will send closed signal + // even though ICD connection will not ever get closed + m_stopTimer.start(ICD_SHORT_CONNECT_TIMEOUT); // 10 seconds wait + } } else { opened = false; isOpen = false; @@ -1090,6 +925,15 @@ void QNetworkSessionPrivateImpl::stop() } } +void QNetworkSessionPrivateImpl::finishStopBySendingClosedSignal() +{ + if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + state = QNetworkSession::Connected; + emit stateChanged(state); + } + + emit closed(); +} void QNetworkSessionPrivateImpl::migrate() { @@ -1199,6 +1043,4 @@ void QNetworkSessionPrivateImpl::clearProxyInformation() Maemo::ProxyConf::clear(); } -#include "qnetworksession_impl.moc" - QT_END_NAMESPACE diff --git a/src/plugins/bearer/icd/qnetworksession_impl.h b/src/plugins/bearer/icd/qnetworksession_impl.h index c02faac..d15f401 100644 --- a/src/plugins/bearer/icd/qnetworksession_impl.h +++ b/src/plugins/bearer/icd/qnetworksession_impl.h @@ -57,6 +57,12 @@ #include <QtNetwork/qnetworkconfigmanager.h> #include <QtCore/qdatetime.h> +#include <QtCore/qtimer.h> + +#include <QtDBus/qdbusconnection.h> +#include <QtDBus/qdbusinterface.h> +#include <QtDBus/qdbusmessage.h> +#include <QtDBus/qdbusmetatype.h> #include <icd/dbus_api.h> @@ -64,14 +70,52 @@ QT_BEGIN_NAMESPACE class QIcdEngine; +struct ICd2DetailsDBusStruct +{ + QString serviceType; + uint serviceAttributes; + QString setviceId; + QString networkType; + uint networkAttributes; + QByteArray networkId; +}; + +typedef QList<ICd2DetailsDBusStruct> ICd2DetailsList; + class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate { Q_OBJECT public: QNetworkSessionPrivateImpl(QIcdEngine *engine) - : engine(engine), connectFlags(ICD_CONNECTION_FLAG_USER_EVENT), currentState(QNetworkSession::Invalid) + : engine(engine), + connectFlags(ICD_CONNECTION_FLAG_USER_EVENT), + currentState(QNetworkSession::Invalid), + m_asynchCallActive(false) { + m_stopTimer.setSingleShot(true); + connect(&m_stopTimer, SIGNAL(timeout()), this, SLOT(finishStopBySendingClosedSignal())); + + QDBusConnection systemBus = QDBusConnection::systemBus(); + + m_dbusInterface = new QDBusInterface(ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_PATH, + ICD_DBUS_API_INTERFACE, + systemBus, + this); + + systemBus.connect(ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_PATH, + ICD_DBUS_API_INTERFACE, + ICD_DBUS_API_CONNECT_SIG, + this, + SLOT(stateChange(const QDBusMessage&))); + + qDBusRegisterMetaType<ICd2DetailsDBusStruct>(); + qDBusRegisterMetaType<ICd2DetailsList>(); + + m_connectRequestTimer.setSingleShot(true); + connect(&m_connectRequestTimer, SIGNAL(timeout()), this, SLOT(connectTimeout())); } ~QNetworkSessionPrivateImpl() @@ -114,16 +158,21 @@ private: private Q_SLOTS: void do_open(); void networkConfigurationsChanged(); - void configurationChanged(const QNetworkConfiguration &config); + void iapStateChanged(const QString& iapid, uint icd_connection_state); void updateProxies(QNetworkSession::State newState); + void finishStopBySendingClosedSignal(); + void stateChange(const QDBusMessage& rep); + void connectTimeout(); private: QNetworkConfigurationManager manager; QIcdEngine *engine; + // The config set on QNetworkSession. + QNetworkConfiguration config; + QNetworkConfiguration& copyConfig(QNetworkConfiguration &fromConfig, QNetworkConfiguration &toConfig, bool deepCopy = true); void clearConfiguration(QNetworkConfiguration &config); - void cleanupAnyConfiguration(); bool opened; icd_connection_flags connectFlags; @@ -134,15 +183,31 @@ private: QString currentNetworkInterface; friend class IcdListener; void updateState(QNetworkSession::State); - void updateIdentifier(QString &newId); + void updateIdentifier(const QString &newId); quint64 getStatistics(bool sent) const; void cleanupSession(void); void updateProxyInformation(); void clearProxyInformation(); QNetworkSession::State currentState; + + QDBusInterface *m_dbusInterface; + + QTimer m_stopTimer; + + bool m_asynchCallActive; + QTimer m_connectRequestTimer; }; +// Marshall the ICd2DetailsDBusStruct data into a D-Bus argument +QDBusArgument &operator<<(QDBusArgument &argument, const ICd2DetailsDBusStruct &icd2); + +// Retrieve the ICd2DetailsDBusStruct data from the D-Bus argument +const QDBusArgument &operator>>(const QDBusArgument &argument, ICd2DetailsDBusStruct &icd2); + +Q_DECLARE_METATYPE(ICd2DetailsDBusStruct); +Q_DECLARE_METATYPE(ICd2DetailsList); + QT_END_NAMESPACE #endif //QNETWORKSESSIONPRIVATE_H diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 512ea51..36fbc51 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -53,16 +53,13 @@ QT_BEGIN_NAMESPACE QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) : CActive(CActive::EPriorityStandard), engine(engine), ipConnectionNotifier(0), iError(QNetworkSession::UnknownSessionError), - iALREnabled(0) + iALREnabled(0), iConnectInBackground(false) { CActiveScheduler::Add(this); - - // Try to load "Open C" dll dynamically and - // try to attach to setdefaultif function dynamically. - if (iOpenCLibrary.Load(_L("libc")) == KErrNone) { - iDynamicSetdefaultif = (TOpenCSetdefaultifFunction)iOpenCLibrary.Lookup(564); - } +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + iMobility = NULL; +#endif TRAP_IGNORE(iConnectionMonitor.ConnectL()); } @@ -88,14 +85,12 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() iConnection.Close(); iSocketServ.Close(); - if (iDynamicSetdefaultif) { - iDynamicSetdefaultif(0); - } + + // Close global 'Open C' RConnection + setdefaultif(0); iConnectionMonitor.CancelNotifications(); iConnectionMonitor.Close(); - - iOpenCLibrary.Close(); } void QNetworkSessionPrivateImpl::syncStateWithInterface() @@ -203,13 +198,24 @@ QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const } #endif -QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& /*key*/) const +QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& key) const { + if (key == "ConnectInBackground") { + return QVariant(iConnectInBackground); + } return QVariant(); } -void QNetworkSessionPrivateImpl::setSessionProperty(const QString& /*key*/, const QVariant& /*value*/) +void QNetworkSessionPrivateImpl::setSessionProperty(const QString& key, const QVariant& value) { + // Valid value means adding property, invalid means removing it. + if (key == "ConnectInBackground") { + if (value.isValid()) { + iConnectInBackground = value.toBool(); + } else { + iConnectInBackground = EFalse; + } + } } QString QNetworkSessionPrivateImpl::errorString() const @@ -318,14 +324,12 @@ void QNetworkSessionPrivateImpl::open() #endif connected = ETrue; startTime = QDateTime::currentDateTime(); - if (iDynamicSetdefaultif) { - // Use name of the IAP to set default IAP - QByteArray nameAsByteArray = publicConfig.name().toUtf8(); - ifreq ifr; - strcpy(ifr.ifr_name, nameAsByteArray.constData()); - - error = iDynamicSetdefaultif(&ifr); - } + // Use name of the IAP to open global 'Open C' RConnection + QByteArray nameAsByteArray = publicConfig.name().toUtf8(); + ifreq ifr; + memset(&ifr, 0, sizeof(struct ifreq)); + strcpy(ifr.ifr_name, nameAsByteArray.constData()); + error = setdefaultif(&ifr); isOpen = true; // Make sure that state will be Connected newState(QNetworkSession::Connected); @@ -337,14 +341,30 @@ void QNetworkSessionPrivateImpl::open() } } if (!connected) { - TCommDbConnPref pref; - pref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); SymbianNetworkConfigurationPrivate *symbianConfig = toSymbianConfig(privateConfiguration(publicConfig)); +#ifdef OCC_FUNCTIONALITY_AVAILABLE + // With One Click Connectivity (Symbian^3 onwards) it is possible + // to connect silently, without any popups. + TConnPrefList pref; + TExtendedConnPref prefs; + + symbianConfig->mutex.lock(); + prefs.SetIapId(symbianConfig->numericId); + symbianConfig->mutex.unlock(); + if (iConnectInBackground) { + prefs.SetNoteBehaviour( TExtendedConnPref::ENoteBehaviourConnSilent ); + } + pref.AppendL(&prefs); +#else + TCommDbConnPref pref; + pref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); + symbianConfig->mutex.lock(); pref.SetIapId(symbianConfig->numericId); symbianConfig->mutex.unlock(); +#endif iConnection.Start(pref, iStatus); if (!IsActive()) { SetActive(); @@ -355,9 +375,21 @@ void QNetworkSessionPrivateImpl::open() SymbianNetworkConfigurationPrivate *symbianConfig = toSymbianConfig(privateConfiguration(publicConfig)); +#ifdef OCC_FUNCTIONALITY_AVAILABLE + TConnPrefList snapPref; + TExtendedConnPref prefs; + symbianConfig->mutex.lock(); + prefs.SetSnapId(symbianConfig->numericId); + symbianConfig->mutex.unlock(); + if (iConnectInBackground) { + prefs.SetNoteBehaviour( TExtendedConnPref::ENoteBehaviourConnSilent ); + } + snapPref.AppendL(&prefs); +#else symbianConfig->mutex.lock(); TConnSnapPref snapPref(symbianConfig->numericId); symbianConfig->mutex.unlock(); +#endif iConnection.Start(snapPref, iStatus); if (!IsActive()) { SetActive(); @@ -441,9 +473,9 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) iConnection.Close(); iSocketServ.Close(); - if (iDynamicSetdefaultif) { - iDynamicSetdefaultif(0); - } + + // Close global 'Open C' RConnection + setdefaultif(0); #ifdef Q_CC_NOKIAX86 if ((allowSignals && iapClientCount(activeIap) <= 0) || @@ -513,18 +545,26 @@ void QNetworkSessionPrivateImpl::stop() void QNetworkSessionPrivateImpl::migrate() { #ifdef SNAP_FUNCTIONALITY_AVAILABLE - iMobility->MigrateToPreferredCarrier(); + if (iMobility) { + // Close global 'Open C' RConnection + setdefaultif(0); + // Start migrating to new IAP + iMobility->MigrateToPreferredCarrier(); + } #endif } void QNetworkSessionPrivateImpl::ignore() { #ifdef SNAP_FUNCTIONALITY_AVAILABLE - iMobility->IgnorePreferredCarrier(); - if (!iALRUpgradingConnection) { - newState(QNetworkSession::Disconnected); - } else { - newState(QNetworkSession::Connected,iOldRoamingIap); + if (iMobility) { + iMobility->IgnorePreferredCarrier(); + + if (!iALRUpgradingConnection) { + newState(QNetworkSession::Disconnected); + } else { + newState(QNetworkSession::Connected,iOldRoamingIap); + } } #endif } @@ -532,27 +572,43 @@ void QNetworkSessionPrivateImpl::ignore() void QNetworkSessionPrivateImpl::accept() { #ifdef SNAP_FUNCTIONALITY_AVAILABLE - iMobility->NewCarrierAccepted(); - if (iDynamicSetdefaultif) { - // Use name of the IAP to set default IAP - QByteArray nameAsByteArray = activeConfig.name().toUtf8(); + if (iMobility) { + iMobility->NewCarrierAccepted(); + + QNetworkConfiguration newActiveConfig = activeConfiguration(iNewRoamingIap); + + // Use name of the new IAP to open global 'Open C' RConnection + QByteArray nameAsByteArray = newActiveConfig.name().toUtf8(); ifreq ifr; + memset(&ifr, 0, sizeof(struct ifreq)); strcpy(ifr.ifr_name, nameAsByteArray.constData()); + setdefaultif(&ifr); - iDynamicSetdefaultif(&ifr); + newState(QNetworkSession::Connected, iNewRoamingIap); } - newState(QNetworkSession::Connected, iNewRoamingIap); #endif } void QNetworkSessionPrivateImpl::reject() { #ifdef SNAP_FUNCTIONALITY_AVAILABLE - iMobility->NewCarrierRejected(); - if (!iALRUpgradingConnection) { - newState(QNetworkSession::Disconnected); - } else { - newState(QNetworkSession::Connected, iOldRoamingIap); + if (iMobility) { + iMobility->NewCarrierRejected(); + + if (!iALRUpgradingConnection) { + newState(QNetworkSession::Disconnected); + } else { + QNetworkConfiguration newActiveConfig = activeConfiguration(iOldRoamingIap); + + // Use name of the old IAP to open global 'Open C' RConnection + QByteArray nameAsByteArray = newActiveConfig.name().toUtf8(); + ifreq ifr; + memset(&ifr, 0, sizeof(struct ifreq)); + strcpy(ifr.ifr_name, nameAsByteArray.constData()); + setdefaultif(&ifr); + + newState(QNetworkSession::Connected, iOldRoamingIap); + } } #endif } @@ -849,13 +905,13 @@ void QNetworkSessionPrivateImpl::RunL() QNetworkConfiguration newActiveConfig = activeConfiguration(); if (!newActiveConfig.isValid()) { error = KErrGeneral; - } else if (iDynamicSetdefaultif) { - // Use name of the IAP to set default IAP - QByteArray nameAsByteArray = newActiveConfig.name().toUtf8(); + } else { + // Use name of the IAP to open global 'Open C' RConnection ifreq ifr; + memset(&ifr, 0, sizeof(struct ifreq)); + QByteArray nameAsByteArray = newActiveConfig.name().toUtf8(); strcpy(ifr.ifr_name, nameAsByteArray.constData()); - - error = iDynamicSetdefaultif(&ifr); + error = setdefaultif(&ifr); } if (error != KErrNone) { @@ -951,14 +1007,12 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint #endif #ifdef SNAP_FUNCTIONALITY_AVAILABLE - if (iDynamicSetdefaultif) { - // Use name of the IAP to set default IAP - QByteArray nameAsByteArray = activeConfig.name().toUtf8(); - ifreq ifr; - strcpy(ifr.ifr_name, nameAsByteArray.constData()); + // Use name of the IAP to set default IAP + QByteArray nameAsByteArray = activeConfig.name().toUtf8(); + ifreq ifr; + strcpy(ifr.ifr_name, nameAsByteArray.constData()); - iDynamicSetdefaultif(&ifr); - } + setdefaultif(&ifr); #endif } diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 9a57eae..7116519 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -64,8 +64,9 @@ #ifdef SNAP_FUNCTIONALITY_AVAILABLE #include <comms-infras/cs_mobility_apiext.h> #endif - -typedef int(*TOpenCSetdefaultifFunction)(const struct ifreq*); +#ifdef OCC_FUNCTIONALITY_AVAILABLE + #include <extendedconnpref.h> +#endif QT_BEGIN_NAMESPACE @@ -152,9 +153,6 @@ private: // data QDateTime startTime; - RLibrary iOpenCLibrary; - TOpenCSetdefaultifFunction iDynamicSetdefaultif; - mutable RSocketServ iSocketServ; mutable RConnection iConnection; mutable RConnectionMonitor iConnectionMonitor; @@ -166,6 +164,7 @@ private: // data QNetworkSession::SessionError iError; TInt iALREnabled; TBool iALRUpgradingConnection; + TBool iConnectInBackground; QList<QString> iKnownConfigsBeforeConnectionStart; diff --git a/src/plugins/mediaservices/qt7/qcvdisplaylink.h b/src/plugins/mediaservices/qt7/qcvdisplaylink.h index 5cd8f73..5a1180d 100644 --- a/src/plugins/mediaservices/qt7/qcvdisplaylink.h +++ b/src/plugins/mediaservices/qt7/qcvdisplaylink.h @@ -45,7 +45,7 @@ #include <QtCore/qobject.h> #include <QtCore/qmutex.h> -#include <CoreVideo/CVDisplayLink.h> +#include <QuartzCore/CVDisplayLink.h> QT_BEGIN_HEADER diff --git a/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.mm b/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.mm index 3778b58..7c02f9f 100644 --- a/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.mm +++ b/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.mm @@ -41,6 +41,9 @@ #include "qt7ciimagevideobuffer.h" +#include <QuartzCore/CIFilter.h> +#include <QuartzCore/CIVector.h> + QT7CIImageVideoBuffer::QT7CIImageVideoBuffer(CIImage *image) : QAbstractVideoBuffer(CoreImageHandle) , m_image(image) diff --git a/src/plugins/mediaservices/qt7/qt7movierenderer.h b/src/plugins/mediaservices/qt7/qt7movierenderer.h index c2dd177..5953b54 100644 --- a/src/plugins/mediaservices/qt7/qt7movierenderer.h +++ b/src/plugins/mediaservices/qt7/qt7movierenderer.h @@ -53,7 +53,7 @@ #include <QtGui/qmacdefines_mac.h> #include "qt7videooutputcontrol.h" -#include <CoreVideo/CVOpenGLTexture.h> +#include <QuartzCore/CVOpenGLTexture.h> #include <QuickTime/QuickTime.h> diff --git a/src/plugins/mediaservices/qt7/qt7movievideowidget.h b/src/plugins/mediaservices/qt7/qt7movievideowidget.h index 831a18d..3ff14f5 100644 --- a/src/plugins/mediaservices/qt7/qt7movievideowidget.h +++ b/src/plugins/mediaservices/qt7/qt7movievideowidget.h @@ -51,7 +51,7 @@ #include <QtGui/qmacdefines_mac.h> #include "qt7videooutputcontrol.h" -#include <CoreVideo/CVOpenGLTexture.h> +#include <QuartzCore/CVOpenGLTexture.h> #include <QuickTime/QuickTime.h> diff --git a/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm b/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm index 20f1a02..06299a3 100644 --- a/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm +++ b/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm @@ -48,6 +48,9 @@ #include "qt7playersession.h" #include <QtCore/qdebug.h> +#include <QuartzCore/CIFilter.h> +#include <QuartzCore/CIVector.h> + #define VIDEO_TRANSPARENT(m) -(void)m:(NSEvent *)e{[[self superview] m:e];} diff --git a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm index 33a6970..5af9809 100644 --- a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm +++ b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm @@ -55,6 +55,9 @@ #include <QtMultimedia/qabstractvideosurface.h> #include <QtMultimedia/qvideosurfaceformat.h> +#include <QuartzCore/CIFilter.h> +#include <QuartzCore/CIVector.h> + QT_BEGIN_NAMESPACE |