1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qnetworksession.h"
43 #include "qbearerengine_p.h"
44 
45 #include <QEventLoop>
46 #include <QTimer>
47 #include <QThread>
48 
49 #include "qnetworkconfigmanager_p.h"
50 #include "qnetworksession_p.h"
51 
52 #ifdef Q_OS_SYMBIAN
53 #include <es_sock.h>
54 #include <private/qcore_symbian_p.h>
55 #endif
56 
57 #ifndef QT_NO_BEARERMANAGEMENT
58 
59 QT_BEGIN_NAMESPACE
60 
61 /*!
62     \class QNetworkSession
63 
64     \brief The QNetworkSession class provides control over the system's access points
65     and enables session management for cases when multiple clients access the same access point.
66 
67     \since 4.7
68 
69     \inmodule QtNetwork
70     \ingroup network
71 
72     A QNetworkSession enables control over the system's network interfaces. The session's configuration
73     parameter are determined via the QNetworkConfiguration object to which it is bound. Depending on the
74     type of the session (single access point or service network) a session may be linked to one or more
75     network interfaces. By means of \l{open()}{opening} and \l{close()}{closing} of network sessions
76     a developer can start and stop the systems network interfaces. If the configuration represents
77     multiple access points (see \l QNetworkConfiguration::ServiceNetwork) more advanced features such as roaming may be supported.
78 
79     QNetworkSession supports session management within the same process and depending on the platform's
80     capabilities may support out-of-process sessions. If the same
81     network configuration is used by multiple open sessions the underlying network interface is only terminated once
82     the last session has been closed.
83 
84     \section1 Roaming
85 
86     Applications may connect to the preferredConfigurationChanged() signal in order to
87     receive notifications when a more suitable access point becomes available.
88     In response to this signal the application must either initiate the roaming via migrate()
89     or ignore() the new access point. Once the session has roamed the
90     newConfigurationActivated() signal is emitted. The application may now test the
91     carrier and must either accept() or reject() it. The session will return to the previous
92     access point if the roaming was rejected. The subsequent state diagram depicts the required
93     state transitions.
94 
95     \image roaming-states.png
96 
97     Some platforms may distinguish forced roaming and application level roaming (ALR).
98     ALR implies that the application controls (via migrate(), ignore(), accept() and reject())
99     whether a network session can roam from one access point to the next. Such control is useful
100     if the application maintains stateful socket connections and wants to control the transition from
101     one interface to the next. Forced roaming implies that the system automatically roams to the next network without
102     consulting the application. This has the advantage that the application can make use of roaming features
103     without actually being aware of it. It is expected that the application detects that the underlying
104     socket is broken and automatically reconnects via the new network link.
105 
106     If the platform supports both modes of roaming, an application indicates its preference
107     by connecting to the preferredConfigurationChanged() signal. Connecting to this signal means that
108     the application wants to take control over the roaming behavior and therefore implies application
109     level roaming. If the client does not connect to the preferredConfigurationChanged(), forced roaming
110     is used. If forced roaming is not supported the network session will not roam by default.
111 
112     Some applications may want to suppress any form of roaming altogether. Possible use cases may be
113     high priority downloads or remote services which cannot handle a roaming enabled client. Clients
114     can suppress roaming by connecting to the preferredConfigurationChanged() signal and answer each
115     signal emission with ignore().
116 
117     \sa QNetworkConfiguration, QNetworkConfigurationManager
118 */
119 
120 /*!
121     \enum QNetworkSession::State
122 
123     This enum describes the connectivity state of the session. If the session is based on a
124     single access point configuration the state of the session is the same as the state of the
125     associated network interface.
126 
127     \value Invalid          The session is invalid due to an invalid configuration. This may
128                             happen due to a removed access point or a configuration that was
129                             invalid to begin with.
130     \value NotAvailable     The session is based on a defined but not yet discovered QNetworkConfiguration
131                             (see \l QNetworkConfiguration::StateFlag).
132     \value Connecting       The network session is being established.
133     \value Connected        The network session is connected. If the current process wishes to use this session
134                             it has to register its interest by calling open(). A network session
135                             is considered to be ready for socket operations if it isOpen() and connected.
136     \value Closing          The network session is in the process of being shut down.
137     \value Disconnected     The network session is not connected. The associated QNetworkConfiguration
138                             has the state QNetworkConfiguration::Discovered.
139     \value Roaming          The network session is roaming from one access point to another
140                             access point.
141 */
142 
143 /*!
144     \enum QNetworkSession::SessionError
145 
146     This enum describes the session errors that can occur.
147 
148     \value UnknownSessionError          An unidentified error occurred.
149     \value SessionAbortedError          The session was aborted by the user or system.
150     \value RoamingError                 The session cannot roam to a new configuration.
151     \value OperationNotSupportedError   The operation is not supported for current configuration.
152     \value InvalidConfigurationError    The operation cannot currently be performed for the
153                                         current configuration.
154 */
155 
156 /*!
157     \fn void QNetworkSession::stateChanged(QNetworkSession::State state)
158 
159     This signal is emitted whenever the state of the network session changes.
160     The \a state parameter is the new state.
161 
162     \sa state()
163 */
164 
165 /*!
166     \fn void QNetworkSession::error(QNetworkSession::SessionError error)
167 
168     This signal is emitted after an error occurred. The \a error parameter
169     describes the error that occurred.
170 
171     \sa error(), errorString()
172 */
173 
174 /*!
175     \fn void QNetworkSession::preferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless)
176 
177     This signal is emitted when the preferred configuration/access point for the
178     session changes. Only sessions which are based on service network configurations
179     may emit this signal. \a config can be used to determine access point specific
180     details such as proxy settings and \a isSeamless indicates whether roaming will
181     break the sessions IP address.
182 
183     As a consequence to this signal the application must either start the roaming process
184     by calling migrate() or choose to ignore() the new access point.
185 
186     If the roaming process is non-seamless the IP address will change which means that
187     a socket becomes invalid. However seamless mobility can ensure that the local IP address
188     does not change. This is achieved by using a virtual IP address which is bound to the actual
189     link address. During the roaming process the virtual address is attached to the new link
190     address.
191 
192     Some platforms may support the concept of Forced Roaming and Application Level Roaming (ALR).
193     Forced roaming implies that the platform may simply roam to a new configuration without
194     consulting applications. It is up to the application to detect the link layer loss and reestablish
195     its sockets. In contrast ALR provides the opportunity to prevent the system from roaming.
196     If this session is based on a configuration that supports roaming the application can choose
197     whether it wants to be consulted (ALR use case) by connecting to this signal. For as long as this signal
198     connection remains the session remains registered as a roaming stakeholder; otherwise roaming will
199     be enforced by the platform.
200 
201     \sa migrate(), ignore(), QNetworkConfiguration::isRoamingAvailable()
202 */
203 
204 /*!
205     \fn void QNetworkSession::newConfigurationActivated()
206 
207     This signal is emitted once the session has roamed to the new access point.
208     The application may reopen its socket and test the suitability of the new network link.
209     Subsequently it must either accept() or reject() the new access point.
210 
211     \sa accept(), reject()
212 */
213 
214 /*!
215     \fn void QNetworkSession::opened()
216 
217     This signal is emitted when the network session has been opened.
218 
219     The underlying network interface will not be shut down as long as the session remains open.
220     Note that this feature is dependent on \l{QNetworkConfigurationManager::SystemSessionSupport}{system wide session support}.
221 */
222 
223 /*!
224     \fn void QNetworkSession::closed()
225 
226     This signal is emitted when the network session has been closed.
227 */
228 
229 /*!
230     Constructs a session based on \a connectionConfig with the given \a parent.
231 
232     \sa QNetworkConfiguration
233 */
QNetworkSession(const QNetworkConfiguration & connectionConfig,QObject * parent)234 QNetworkSession::QNetworkSession(const QNetworkConfiguration &connectionConfig, QObject *parent)
235     : QObject(parent), d(0)
236 {
237     // invalid configuration
238     if (!connectionConfig.identifier().isEmpty()) {
239         foreach (QBearerEngine *engine, qNetworkConfigurationManagerPrivate()->engines()) {
240             if (engine->hasIdentifier(connectionConfig.identifier())) {
241                 d = engine->createSessionBackend();
242                 d->q = this;
243                 d->publicConfig = connectionConfig;
244                 d->syncStateWithInterface();
245                 connect(d, SIGNAL(quitPendingWaitsForOpened()), this, SIGNAL(opened()));
246                 connect(d, SIGNAL(error(QNetworkSession::SessionError)),
247                         this, SIGNAL(error(QNetworkSession::SessionError)));
248                 connect(d, SIGNAL(stateChanged(QNetworkSession::State)),
249                         this, SIGNAL(stateChanged(QNetworkSession::State)));
250                 connect(d, SIGNAL(closed()), this, SIGNAL(closed()));
251                 connect(d, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool)),
252                         this, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool)));
253                 connect(d, SIGNAL(newConfigurationActivated()),
254                         this, SIGNAL(newConfigurationActivated()));
255                 break;
256             }
257         }
258     }
259 
260     qRegisterMetaType<QNetworkSession::State>();
261     qRegisterMetaType<QNetworkSession::SessionError>();
262 }
263 
264 /*!
265     Frees the resources associated with the QNetworkSession object.
266 */
~QNetworkSession()267 QNetworkSession::~QNetworkSession()
268 {
269     delete d;
270 }
271 
272 /*!
273     Creates an open session which increases the session counter on the underlying network interface.
274     The system will not terminate a network interface until the session reference counter reaches zero.
275     Therefore an open session allows an application to register its use of the interface.
276 
277     As a result of calling open() the interface will be started if it is not connected/up yet.
278     Some platforms may not provide support for out-of-process sessions. On such platforms the session
279     counter ignores any sessions held by another process. The platform capabilities can be
280     detected via QNetworkConfigurationManager::capabilities().
281 
282     Note that this call is asynchronous. Depending on the outcome of this call the results can be enquired
283     by connecting to the stateChanged(), opened() or error() signals.
284 
285     It is not a requirement to open a session in order to monitor the underlying network interface.
286 
287     \sa close(), stop(), isOpen()
288 */
open()289 void QNetworkSession::open()
290 {
291     if (d)
292         d->open();
293     else
294         emit error(InvalidConfigurationError);
295 }
296 
297 /*!
298     Waits until the session has been opened, up to \a msecs milliseconds. If the session has been opened, this
299     function returns true; otherwise it returns false. In the case where it returns false, you can call error()
300     to determine the cause of the error.
301 
302     The following example waits up to one second for the session to be opened:
303 
304     \code
305         session->open();
306         if (session->waitForOpened(1000))
307             qDebug("Open!");
308     \endcode
309 
310     If \a msecs is -1, this function will not time out.
311 
312     \sa open(), error()
313 */
waitForOpened(int msecs)314 bool QNetworkSession::waitForOpened(int msecs)
315 {
316     if (!d)
317         return false;
318 
319     if (d->isOpen)
320         return true;
321 
322     if (!(d->state == Connecting || d->state == Connected)) {
323         return false;
324     }
325 
326     QEventLoop loop;
327     QObject::connect(d, SIGNAL(quitPendingWaitsForOpened()), &loop, SLOT(quit()));
328     QObject::connect(this, SIGNAL(error(QNetworkSession::SessionError)), &loop, SLOT(quit()));
329 
330     //final call
331     if (msecs >= 0)
332         QTimer::singleShot(msecs, &loop, SLOT(quit()));
333 
334     // enter the event loop and wait for opened/error/timeout
335     loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);
336 
337     return d->isOpen;
338 }
339 
340 /*!
341     Decreases the session counter on the associated network configuration. If the session counter reaches zero
342     the active network interface is shut down. This also means that state() will only change from \l Connected to
343     \l Disconnected if the current session was the last open session.
344 
345     If the platform does not support out-of-process sessions calling this function does not stop the
346     interface. In this case \l{stop()} has to be used to force a shut down.
347     The platform capabilities can be detected via QNetworkConfigurationManager::capabilities().
348 
349     Note that this call is asynchronous. Depending on the outcome of this call the results can be enquired
350     by connecting to the stateChanged(), opened() or error() signals.
351 
352     \sa open(), stop(), isOpen()
353 */
close()354 void QNetworkSession::close()
355 {
356     if (d)
357         d->close();
358 }
359 
360 /*!
361     Invalidates all open sessions against the network interface and therefore stops the
362     underlying network interface. This function always changes the session's state() flag to
363     \l Disconnected.
364 
365     On Symbian platform, a 'NetworkControl' capability is required for
366     full interface-level stop (without the capability, only the current session is stopped).
367 
368     \sa open(), close()
369 */
stop()370 void QNetworkSession::stop()
371 {
372     if (d)
373         d->stop();
374 }
375 
376 /*!
377     Returns the QNetworkConfiguration that this network session object is based on.
378 
379     \sa QNetworkConfiguration
380 */
configuration() const381 QNetworkConfiguration QNetworkSession::configuration() const
382 {
383     return d ? d->publicConfig : QNetworkConfiguration();
384 }
385 
386 #ifndef QT_NO_NETWORKINTERFACE
387 /*!
388     Returns the network interface that is used by this session.
389 
390     This function only returns a valid QNetworkInterface when this session is \l Connected.
391 
392     The returned interface may change as a result of a roaming process.
393 
394     Note: this function does not work in Symbian emulator due to the way the
395     connectivity is emulated on Windows.
396 
397     \sa state()
398 */
interface() const399 QNetworkInterface QNetworkSession::interface() const
400 {
401     return d ? d->currentInterface() : QNetworkInterface();
402 }
403 #endif
404 
405 /*!
406     Returns true if this session is open. If the number of all open sessions is greater than
407     zero the underlying network interface will remain connected/up.
408 
409     The session can be controlled via open() and close().
410 */
isOpen() const411 bool QNetworkSession::isOpen() const
412 {
413     return d ? d->isOpen : false;
414 }
415 
416 /*!
417     Returns the state of the session.
418 
419     If the session is based on a single access point configuration the state of the
420     session is the same as the state of the associated network interface. Therefore
421     a network session object can be used to monitor network interfaces.
422 
423     A \l QNetworkConfiguration::ServiceNetwork based session summarizes the state of all its children
424     and therefore returns the \l Connected state if at least one of the service network's
425     \l {QNetworkConfiguration::children()}{children()} configurations is active.
426 
427     Note that it is not required to hold an open session in order to obtain the network interface state.
428     A connected but closed session may be used to monitor network interfaces whereas an open and connected
429     session object may prevent the network interface from being shut down.
430 
431     \sa error(), stateChanged()
432 */
state() const433 QNetworkSession::State QNetworkSession::state() const
434 {
435     return d ? d->state : QNetworkSession::Invalid;
436 }
437 
438 /*!
439     Returns the type of error that last occurred.
440 
441     \sa state(), errorString()
442 */
error() const443 QNetworkSession::SessionError QNetworkSession::error() const
444 {
445     return d ? d->error() : InvalidConfigurationError;
446 }
447 
448 /*!
449     Returns a human-readable description of the last device error that
450     occurred.
451 
452     \sa error()
453 */
errorString() const454 QString QNetworkSession::errorString() const
455 {
456     return d ? d->errorString() : tr("Invalid configuration.");
457 }
458 
459 /*!
460     Returns the value for property \a key.
461 
462     A network session can have properties attached which may describe the session in more details.
463     This function can be used to gain access to those properties.
464 
465     The following property keys are guaranteed to be specified on all platforms:
466 
467     \table
468         \header
469             \o Key \o Description
470         \row
471             \o ActiveConfiguration
472             \o If the session \l isOpen() this property returns the identifier of the
473             QNetworkConfiguration that is used by this session; otherwise an empty string.
474 
475             The main purpose of this key is to determine which Internet access point is used
476             if the session is based on a \l{QNetworkConfiguration::ServiceNetwork}{ServiceNetwork}.
477             The following code snippet highlights the difference:
478             \code
479                     QNetworkConfigurationManager mgr;
480                     QNetworkConfiguration ap = mgr.defaultConfiguration();
481                     QNetworkSession *session = new QNetworkSession(ap);
482                     ... //code activates session
483 
484                     QString ident = session->sessionProperty("ActiveConfiguration").toString();
485                     if ( ap.type() == QNetworkConfiguration::ServiceNetwork ) {
486                         Q_ASSERT( ap.identifier() != ident );
487                         Q_ASSERT( ap.children().contains( mgr.configurationFromIdentifier(ident) ) );
488                     } else if ( ap.type() == QNetworkConfiguration::InternetAccessPoint ) {
489                         Q_ASSERT( ap.identifier() == ident );
490                     }
491                 \endcode
492         \row
493             \o UserChoiceConfiguration
494             \o If the session \l isOpen() and is bound to a QNetworkConfiguration of type
495             UserChoice, this property returns the identifier of the QNetworkConfiguration that the
496             configuration resolved to when \l open() was called; otherwise an empty string.
497 
498             The purpose of this key is to determine the real QNetworkConfiguration that the
499             session is using. This key is different from \e ActiveConfiguration in that
500             this key may return an identifier for either a
501             \l {QNetworkConfiguration::ServiceNetwork}{service network} or a
502             \l {QNetworkConfiguration::InternetAccessPoint}{Internet access points} configurations,
503             whereas \e ActiveConfiguration always returns identifiers to
504             \l {QNetworkConfiguration::InternetAccessPoint}{Internet access points} configurations.
505         \row
506             \o ConnectInBackground
507             \o Setting this property to \e true before calling \l open() implies that the connection attempt
508             is made but if no connection can be established, the user is not connsulted and asked to select
509             a suitable connection. This property is not set by default and support for it depends on the platform.
510 
511         \row
512             \o AutoCloseSessionTimeout
513             \o If the session requires polling to keep its state up to date, this property holds
514                the timeout in milliseconds before the session will automatically close. If the
515                value of this property is -1 the session will not automatically close. This property
516                is set to -1 by default.
517 
518                The purpose of this property is to minimize resource use on platforms that use
519                polling to update the state of the session. Applications can set the value of this
520                property to the desired timeout before the session is closed. In response to the
521                closed() signal the network session should be deleted to ensure that all polling is
522                stopped. The session can then be recreated once it is required again. This property
523                has no effect for sessions that do not require polling.
524     \endtable
525 */
sessionProperty(const QString & key) const526 QVariant QNetworkSession::sessionProperty(const QString &key) const
527 {
528     if (!d || !d->publicConfig.isValid())
529         return QVariant();
530 
531     if (key == QLatin1String("ActiveConfiguration"))
532         return d->isOpen ? d->activeConfig.identifier() : QString();
533 
534     if (key == QLatin1String("UserChoiceConfiguration")) {
535         if (!d->isOpen || d->publicConfig.type() != QNetworkConfiguration::UserChoice)
536             return QString();
537 
538         if (d->serviceConfig.isValid())
539             return d->serviceConfig.identifier();
540         else
541             return d->activeConfig.identifier();
542     }
543 
544     return d->sessionProperty(key);
545 }
546 
547 /*!
548     Sets the property \a value on the session. The property is identified using
549     \a key. Removing an already set  property can be achieved by passing an
550     invalid QVariant.
551 
552     Note that the \e UserChoiceConfiguration and \e ActiveConfiguration
553     properties are read only and cannot be changed using this method.
554 */
setSessionProperty(const QString & key,const QVariant & value)555 void QNetworkSession::setSessionProperty(const QString &key, const QVariant &value)
556 {
557     if (!d)
558         return;
559 
560     if (key == QLatin1String("ActiveConfiguration") ||
561         key == QLatin1String("UserChoiceConfiguration")) {
562         return;
563     }
564 
565     d->setSessionProperty(key, value);
566 }
567 
568 /*!
569     Instructs the session to roam to the new access point. The old access point remains active
570     until the application calls accept().
571 
572    The newConfigurationActivated() signal is emitted once roaming has been completed.
573 
574     \sa accept()
575 */
migrate()576 void QNetworkSession::migrate()
577 {
578     if (d)
579         d->migrate();
580 }
581 
582 /*!
583     This function indicates that the application does not wish to roam the session.
584 
585     \sa migrate()
586 */
ignore()587 void QNetworkSession::ignore()
588 {
589     // Needed on at least Symbian platform: the roaming must be explicitly
590     // ignore()'d or migrate()'d
591     if (d)
592         d->ignore();
593 }
594 
595 /*!
596     Instructs the session to permanently accept the new access point. Once this function
597     has been called the session may not return to the old access point.
598 
599     The old access point may be closed in the process if there are no other network sessions for it.
600     Therefore any open socket that still uses the old access point
601     may become unusable and should be closed before completing the migration.
602 */
accept()603 void QNetworkSession::accept()
604 {
605     if (d)
606         d->accept();
607 }
608 
609 /*!
610     The new access point is not suitable for the application. By calling this function the
611     session returns to the previous access point/configuration. This action may invalidate
612     any socket that has been created via the not desired access point.
613 
614     \sa accept()
615 */
reject()616 void QNetworkSession::reject()
617 {
618     if (d)
619         d->reject();
620 }
621 
622 
623 /*!
624     Returns the amount of data sent in bytes; otherwise 0.
625 
626     This field value includes the usage across all open network
627     sessions which use the same network interface.
628 
629     If the session is based on a service network configuration the number of
630     sent bytes across all active member configurations are returned.
631 
632     This function may not always be supported on all platforms and returns 0.
633     The platform capability can be detected via QNetworkConfigurationManager::DataStatistics.
634 
635     \note On some platforms this function may run the main event loop.
636 */
bytesWritten() const637 quint64 QNetworkSession::bytesWritten() const
638 {
639     return d ? d->bytesWritten() : Q_UINT64_C(0);
640 }
641 
642 /*!
643     Returns the amount of data received in bytes; otherwise 0.
644 
645     This field value includes the usage across all open network
646     sessions which use the same network interface.
647 
648     If the session is based on a service network configuration the number of
649     sent bytes across all active member configurations are returned.
650 
651     This function may not always be supported on all platforms and returns 0.
652     The platform capability can be detected via QNetworkConfigurationManager::DataStatistics.
653 
654     \note On some platforms this function may run the main event loop.
655 */
bytesReceived() const656 quint64 QNetworkSession::bytesReceived() const
657 {
658     return d ? d->bytesReceived() : Q_UINT64_C(0);
659 }
660 
661 /*!
662     Returns the number of seconds that the session has been active.
663 */
activeTime() const664 quint64 QNetworkSession::activeTime() const
665 {
666     return d ? d->activeTime() : Q_UINT64_C(0);
667 }
668 
669 /*!
670     \internal
671 
672     This function is required to detect whether the client wants to control
673     the roaming process. If he connects to preferredConfigurationChanged() signal
674     he intends to influence it. Otherwise QNetworkSession always roams
675     without registering this session as a stakeholder in the roaming process.
676 
677     For more details check the Forced vs ALR roaming section in the QNetworkSession
678     class description.
679 */
connectNotify(const char * signal)680 void QNetworkSession::connectNotify(const char *signal)
681 {
682     QObject::connectNotify(signal);
683 
684     if (!d)
685         return;
686 
687     //check for preferredConfigurationChanged() signal connect notification
688     //This is not required on all platforms
689     if (qstrcmp(signal, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) == 0)
690         d->setALREnabled(true);
691 }
692 
693 /*!
694     \internal
695 
696     This function is called when the client disconnects from the
697     preferredConfigurationChanged() signal.
698 
699     \sa connectNotify()
700 */
disconnectNotify(const char * signal)701 void QNetworkSession::disconnectNotify(const char *signal)
702 {
703     QObject::disconnectNotify(signal);
704 
705     if (!d)
706         return;
707 
708     //check for preferredConfigurationChanged() signal disconnect notification
709     //This is not required on all platforms
710     if (qstrcmp(signal, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) == 0)
711         d->setALREnabled(false);
712 }
713 
714 #ifdef Q_OS_SYMBIAN
nativeSession(QNetworkSession & s)715 RConnection* QNetworkSessionPrivate::nativeSession(QNetworkSession &s)
716 {
717     if (!s.d)
718         return 0;
719     if (s.thread() != QThread::currentThread())
720         qWarning("QNetworkSessionPrivate::nativeSession called in wrong thread");
721     return s.d->nativeSession();
722 }
723 
nativeOpenSocket(QNetworkSession & s,RSocket & sock,TUint family,TUint type,TUint protocol)724 TInt QNetworkSessionPrivate::nativeOpenSocket(QNetworkSession& s, RSocket& sock, TUint family, TUint type, TUint protocol)
725 {
726     if (!s.d)
727         return 0;
728     QMutexLocker lock(&(s.d->mutex));
729     RConnection *con = s.d->nativeSession();
730     if (!con || !con->SubSessionHandle())
731         return KErrNotReady;
732     return sock.Open(qt_symbianGetSocketServer(), family, type, protocol, *con);
733 }
734 
nativeOpenHostResolver(QNetworkSession & s,RHostResolver & resolver,TUint family,TUint protocol)735 TInt QNetworkSessionPrivate::nativeOpenHostResolver(QNetworkSession& s, RHostResolver& resolver, TUint family, TUint protocol)
736 {
737     if (!s.d)
738         return 0;
739     QMutexLocker lock(&(s.d->mutex));
740     RConnection *con = s.d->nativeSession();
741     if (!con || !con->SubSessionHandle())
742         return KErrNotReady;
743     return resolver.Open(qt_symbianGetSocketServer(), family, protocol, *con);
744 }
745 
746 #endif
747 
748 #include "moc_qnetworksession.cpp"
749 
750 QT_END_NAMESPACE
751 
752 #endif // QT_NO_BEARERMANAGEMENT
753