source: trunk/src/plugins/bearer/generic/qgenericengine.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 10.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the plugins of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qgenericengine.h"
43#include "../qnetworksession_impl.h"
44
45#include <QtNetwork/private/qnetworkconfiguration_p.h>
46
47#include <QtCore/qthread.h>
48#include <QtCore/qmutex.h>
49#include <QtCore/qcoreapplication.h>
50#include <QtCore/qstringlist.h>
51
52#include <QtCore/qdebug.h>
53#include <QtCore/private/qcoreapplication_p.h>
54
55#ifdef Q_OS_WIN
56#include "../platformdefs_win.h"
57#endif
58
59#ifdef Q_OS_LINUX
60#include <sys/socket.h>
61#include <sys/ioctl.h>
62#include <net/if.h>
63#include <net/if_arp.h>
64#include <unistd.h>
65#endif
66
67#ifndef QT_NO_BEARERMANAGEMENT
68
69QT_BEGIN_NAMESPACE
70
71#ifndef QT_NO_NETWORKINTERFACE
72static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interface)
73{
74#ifdef Q_OS_WIN32
75 unsigned long oid;
76 DWORD bytesWritten;
77
78 NDIS_MEDIUM medium;
79 NDIS_PHYSICAL_MEDIUM physicalMedium;
80
81 HANDLE handle = CreateFile((TCHAR *)QString::fromLatin1("\\\\.\\%1").arg(interface).utf16(), 0,
82 FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
83 if (handle == INVALID_HANDLE_VALUE)
84 return QNetworkConfiguration::BearerUnknown;
85
86 oid = OID_GEN_MEDIA_SUPPORTED;
87 bytesWritten = 0;
88 bool result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid),
89 &medium, sizeof(medium), &bytesWritten, 0);
90 if (!result) {
91 CloseHandle(handle);
92 return QNetworkConfiguration::BearerUnknown;
93 }
94
95 oid = OID_GEN_PHYSICAL_MEDIUM;
96 bytesWritten = 0;
97 result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid),
98 &physicalMedium, sizeof(physicalMedium), &bytesWritten, 0);
99 if (!result) {
100 CloseHandle(handle);
101
102 if (medium == NdisMedium802_3)
103 return QNetworkConfiguration::BearerEthernet;
104 else
105 return QNetworkConfiguration::BearerUnknown;
106 }
107
108 CloseHandle(handle);
109
110 if (medium == NdisMedium802_3) {
111 switch (physicalMedium) {
112 case NdisPhysicalMediumWirelessLan:
113 return QNetworkConfiguration::BearerWLAN;
114 case NdisPhysicalMediumBluetooth:
115 return QNetworkConfiguration::BearerBluetooth;
116 case NdisPhysicalMediumWiMax:
117 return QNetworkConfiguration::BearerWiMAX;
118 default:
119#ifdef BEARER_MANAGEMENT_DEBUG
120 qDebug() << "Physical Medium" << physicalMedium;
121#endif
122 return QNetworkConfiguration::BearerEthernet;
123 }
124 }
125
126#ifdef BEARER_MANAGEMENT_DEBUG
127 qDebug() << medium << physicalMedium;
128#endif
129#elif defined(Q_OS_LINUX)
130 int sock = socket(AF_INET, SOCK_DGRAM, 0);
131
132 ifreq request;
133 strncpy(request.ifr_name, interface.toLocal8Bit().data(), sizeof(request.ifr_name));
134 int result = ioctl(sock, SIOCGIFHWADDR, &request);
135 close(sock);
136
137 if (result >= 0 && request.ifr_hwaddr.sa_family == ARPHRD_ETHER)
138 return QNetworkConfiguration::BearerEthernet;
139#else
140 Q_UNUSED(interface);
141#endif
142
143 return QNetworkConfiguration::BearerUnknown;
144}
145#endif
146
147QGenericEngine::QGenericEngine(QObject *parent)
148: QBearerEngineImpl(parent)
149{
150}
151
152QGenericEngine::~QGenericEngine()
153{
154}
155
156QString QGenericEngine::getInterfaceFromId(const QString &id)
157{
158 QMutexLocker locker(&mutex);
159
160 return configurationInterface.value(id);
161}
162
163bool QGenericEngine::hasIdentifier(const QString &id)
164{
165 QMutexLocker locker(&mutex);
166
167 return configurationInterface.contains(id);
168}
169
170void QGenericEngine::connectToId(const QString &id)
171{
172 emit connectionError(id, OperationNotSupported);
173}
174
175void QGenericEngine::disconnectFromId(const QString &id)
176{
177 emit connectionError(id, OperationNotSupported);
178}
179
180void QGenericEngine::initialize()
181{
182 doRequestUpdate();
183}
184
185void QGenericEngine::requestUpdate()
186{
187 doRequestUpdate();
188}
189
190void QGenericEngine::doRequestUpdate()
191{
192#ifndef QT_NO_NETWORKINTERFACE
193 QMutexLocker locker(&mutex);
194
195 // Immediately after connecting with a wireless access point
196 // QNetworkInterface::allInterfaces() will sometimes return an empty list. Calling it again a
197 // second time results in a non-empty list. If we loose interfaces we will end up removing
198 // network configurations which will break current sessions.
199 QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
200 if (interfaces.isEmpty())
201 interfaces = QNetworkInterface::allInterfaces();
202
203 QStringList previous = accessPointConfigurations.keys();
204
205 // create configuration for each interface
206 while (!interfaces.isEmpty()) {
207 QNetworkInterface interface = interfaces.takeFirst();
208
209 if (!interface.isValid())
210 continue;
211
212 // ignore loopback interface
213 if (interface.flags() & QNetworkInterface::IsLoopBack)
214 continue;
215
216 // ignore WLAN interface handled in separate engine
217 if (qGetInterfaceType(interface.name()) == QNetworkConfiguration::BearerWLAN)
218 continue;
219
220 uint identifier;
221 if (interface.index())
222 identifier = qHash(QLatin1String("generic:") + QString::number(interface.index()));
223 else
224 identifier = qHash(QLatin1String("generic:") + interface.hardwareAddress());
225
226 const QString id = QString::number(identifier);
227
228 previous.removeAll(id);
229
230 QString name = interface.humanReadableName();
231 if (name.isEmpty())
232 name = interface.name();
233
234 QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Defined;
235 if((interface.flags() & QNetworkInterface::IsUp) && !interface.addressEntries().isEmpty())
236 state |= QNetworkConfiguration::Active;
237
238 if (accessPointConfigurations.contains(id)) {
239 QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
240
241 bool changed = false;
242
243 ptr->mutex.lock();
244
245 if (!ptr->isValid) {
246 ptr->isValid = true;
247 changed = true;
248 }
249
250 if (ptr->name != name) {
251 ptr->name = name;
252 changed = true;
253 }
254
255 if (ptr->id != id) {
256 ptr->id = id;
257 changed = true;
258 }
259
260 if (ptr->state != state) {
261 ptr->state = state;
262 changed = true;
263 }
264
265 ptr->mutex.unlock();
266
267 if (changed) {
268 locker.unlock();
269 emit configurationChanged(ptr);
270 locker.relock();
271 }
272 } else {
273 QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate);
274
275 ptr->name = name;
276 ptr->isValid = true;
277 ptr->id = id;
278 ptr->state = state;
279 ptr->type = QNetworkConfiguration::InternetAccessPoint;
280 ptr->bearerType = qGetInterfaceType(interface.name());
281
282 accessPointConfigurations.insert(id, ptr);
283 configurationInterface.insert(id, interface.name());
284
285 locker.unlock();
286 emit configurationAdded(ptr);
287 locker.relock();
288 }
289 }
290
291 while (!previous.isEmpty()) {
292 QNetworkConfigurationPrivatePointer ptr =
293 accessPointConfigurations.take(previous.takeFirst());
294
295 configurationInterface.remove(ptr->id);
296
297 locker.unlock();
298 emit configurationRemoved(ptr);
299 locker.relock();
300 }
301
302 locker.unlock();
303#endif
304
305 emit updateCompleted();
306}
307
308QNetworkSession::State QGenericEngine::sessionStateForId(const QString &id)
309{
310 QMutexLocker locker(&mutex);
311
312 QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
313
314 if (!ptr)
315 return QNetworkSession::Invalid;
316
317 QMutexLocker configLocker(&ptr->mutex);
318
319 if (!ptr->isValid) {
320 return QNetworkSession::Invalid;
321 } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
322 return QNetworkSession::Connected;
323 } else if ((ptr->state & QNetworkConfiguration::Discovered) ==
324 QNetworkConfiguration::Discovered) {
325 return QNetworkSession::Disconnected;
326 } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
327 return QNetworkSession::NotAvailable;
328 } else if ((ptr->state & QNetworkConfiguration::Undefined) ==
329 QNetworkConfiguration::Undefined) {
330 return QNetworkSession::NotAvailable;
331 }
332
333 return QNetworkSession::Invalid;
334}
335
336QNetworkConfigurationManager::Capabilities QGenericEngine::capabilities() const
337{
338 return QNetworkConfigurationManager::ForcedRoaming;
339}
340
341QNetworkSessionPrivate *QGenericEngine::createSessionBackend()
342{
343 return new QNetworkSessionPrivateImpl;
344}
345
346QNetworkConfigurationPrivatePointer QGenericEngine::defaultConfiguration()
347{
348 return QNetworkConfigurationPrivatePointer();
349}
350
351
352bool QGenericEngine::requiresPolling() const
353{
354 return true;
355}
356
357QT_END_NAMESPACE
358
359#endif // QT_NO_BEARERMANAGEMENT
Note: See TracBrowser for help on using the repository browser.