1// Copyright (C) 2021 Ilya Fedin <fedin-ilja2010@ya.ru>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <QtNetwork/private/qnetworkinformation_p.h>
6
7#include <QtCore/qglobal.h>
8#include <QtCore/private/qobject_p.h>
9
10#include <gio/gio.h>
11
12QT_BEGIN_NAMESPACE
13
14using namespace Qt::StringLiterals;
15
16Q_DECLARE_LOGGING_CATEGORY(lcNetInfoGlib)
17Q_LOGGING_CATEGORY(lcNetInfoGlib, "qt.network.info.glib");
18
19namespace {
20QNetworkInformation::Reachability reachabilityFromGNetworkConnectivity(GNetworkConnectivity connectivity)
21{
22 switch (connectivity) {
23 case G_NETWORK_CONNECTIVITY_LOCAL:
24 return QNetworkInformation::Reachability::Disconnected;
25 case G_NETWORK_CONNECTIVITY_LIMITED:
26 case G_NETWORK_CONNECTIVITY_PORTAL:
27 return QNetworkInformation::Reachability::Site;
28 case G_NETWORK_CONNECTIVITY_FULL:
29 return QNetworkInformation::Reachability::Online;
30 }
31 return QNetworkInformation::Reachability::Unknown;
32}
33}
34
35static const QString &backendName()
36{
37 static auto name = u"glib"_s;
38 return name;
39}
40
41class QGlibNetworkInformationBackend : public QNetworkInformationBackend
42{
43 Q_OBJECT
44public:
45 QGlibNetworkInformationBackend();
46 ~QGlibNetworkInformationBackend();
47
48 QString name() const override { return backendName(); }
49 QNetworkInformation::Features featuresSupported() const override
50 {
51 if (!isValid())
52 return {};
53 return featuresSupportedStatic();
54 }
55
56 static QNetworkInformation::Features featuresSupportedStatic()
57 {
58 using Feature = QNetworkInformation::Feature;
59 return QNetworkInformation::Features(Feature::Reachability | Feature::CaptivePortal
60 | Feature::Metered);
61 }
62
63 bool isValid() const;
64
65private:
66 Q_DISABLE_COPY_MOVE(QGlibNetworkInformationBackend)
67
68 static void updateConnectivity(QGlibNetworkInformationBackend *backend);
69 static void updateMetered(QGlibNetworkInformationBackend *backend);
70
71 GNetworkMonitor *networkMonitor = nullptr;
72 gulong connectivityHandlerId = 0;
73 gulong meteredHandlerId = 0;
74};
75
76class QGlibNetworkInformationBackendFactory : public QNetworkInformationBackendFactory
77{
78 Q_OBJECT
79 Q_PLUGIN_METADATA(IID QNetworkInformationBackendFactory_iid)
80 Q_INTERFACES(QNetworkInformationBackendFactory)
81public:
82 QGlibNetworkInformationBackendFactory() = default;
83 ~QGlibNetworkInformationBackendFactory() = default;
84 QString name() const override { return backendName(); }
85 QNetworkInformation::Features featuresSupported() const override
86 {
87 return QGlibNetworkInformationBackend::featuresSupportedStatic();
88 }
89
90 QNetworkInformationBackend *create(QNetworkInformation::Features requiredFeatures) const override
91 {
92 if ((requiredFeatures & featuresSupported()) != requiredFeatures)
93 return nullptr;
94 auto backend = new QGlibNetworkInformationBackend();
95 if (!backend->isValid())
96 delete std::exchange(obj&: backend, new_val: nullptr);
97 return backend;
98 }
99private:
100 Q_DISABLE_COPY_MOVE(QGlibNetworkInformationBackendFactory)
101};
102
103QGlibNetworkInformationBackend::QGlibNetworkInformationBackend()
104: networkMonitor(g_network_monitor_get_default())
105{
106 updateConnectivity(backend: this);
107 updateMetered(backend: this);
108
109 connectivityHandlerId = g_signal_connect_swapped(networkMonitor, "notify::connectivity",
110 G_CALLBACK(updateConnectivity), this);
111
112 meteredHandlerId = g_signal_connect_swapped(networkMonitor, "notify::network-metered",
113 G_CALLBACK(updateMetered), this);
114}
115
116QGlibNetworkInformationBackend::~QGlibNetworkInformationBackend()
117{
118 g_signal_handler_disconnect(instance: networkMonitor, handler_id: meteredHandlerId);
119 g_signal_handler_disconnect(instance: networkMonitor, handler_id: connectivityHandlerId);
120}
121
122bool QGlibNetworkInformationBackend::isValid() const
123{
124 return QLatin1StringView(G_OBJECT_TYPE_NAME(networkMonitor)) != "GNetworkMonitorBase"_L1;
125}
126
127void QGlibNetworkInformationBackend::updateConnectivity(QGlibNetworkInformationBackend *backend)
128{
129 const auto connectivityState = g_network_monitor_get_connectivity(monitor: backend->networkMonitor);
130 const bool behindPortal = (connectivityState == G_NETWORK_CONNECTIVITY_PORTAL);
131 backend->setReachability(reachabilityFromGNetworkConnectivity(connectivity: connectivityState));
132 backend->setBehindCaptivePortal(behindPortal);
133}
134
135void QGlibNetworkInformationBackend::updateMetered(QGlibNetworkInformationBackend *backend)
136{
137 backend->setMetered(g_network_monitor_get_network_metered(monitor: backend->networkMonitor));
138}
139
140QT_END_NAMESPACE
141
142#include "qglibnetworkinformationbackend.moc"
143

source code of qtbase/src/plugins/networkinformation/glib/qglibnetworkinformationbackend.cpp