1
/* This file is part of the KDE project
2
Copyright (C) 2006-2007 Will Stephenson <wstephenson@kde.org>
3
Copyright (C) 2006-2007 Kevin Ottens <ervin@kde.org>
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License version 2 as published by the Free Software Foundation.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Library General Public License for more details.
14
You should have received a copy of the GNU Library General Public License
15
along with this library; see the file COPYING.LIB. If not, write to
16
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
Boston, MA 02110-1301, USA.
21
#include <QtNetwork/QAbstractSocket>
22
#include <QtCore/QTimer>
26
#include "networking_p.h"
27
#include "networking.h"
28
#include "org_kde_solid_networking.h"
30
K_GLOBAL_STATIC(Solid::Control::NetworkingPrivate, globalNetworkControl)
32
Solid::Control::NetworkingPrivate::NetworkingPrivate() : iface(
33
new OrgKdeSolidNetworkingInterface( "org.kde.Solid.Networking",
35
QDBusConnection::sessionBus(),
40
Solid::Control::NetworkingPrivate::~NetworkingPrivate()
44
uint Solid::Control::NetworkingPrivate::requestConnection( QObject * receiver, const char * member )
46
connect( this, SIGNAL( connectionResult( bool ) ), receiver, member );
47
return iface->requestConnection();
50
void Solid::Control::NetworkingPrivate::releaseConnection()
52
iface->releaseConnection();
55
Solid::Control::Networking::Result Solid::Control::NetworkingPrivate::beginManagingSocket( QAbstractSocket * socket, int autoDisconnectTimeout )
57
mManagedSockets.insert( socket, new ManagedSocketContainer( socket, autoDisconnectTimeout ) );
58
return Solid::Control::Networking::Accepted;
61
void Solid::Control::NetworkingPrivate::stopManagingSocket( QAbstractSocket * socket )
63
ManagedSocketContainer * removed = mManagedSockets.take( socket );
67
Solid::Control::Networking::Result Solid::Control::Networking::requestConnection( QObject * receiver, const char * member )
69
return static_cast<Solid::Control::Networking::Result>( globalNetworkControl->requestConnection( receiver, member ) );
72
void Solid::Control::Networking::releaseConnection()
74
globalNetworkControl->releaseConnection();
77
/*=========================================================================*/
80
Solid::Control::ManagedSocketContainer::ManagedSocketContainer( QAbstractSocket * socket, int autoDisconnectTimeout ) : mSocket( socket ), mAutoDisconnectTimer( 0 )
82
if ( autoDisconnectTimeout >= 0 )
84
mAutoDisconnectTimer = new QTimer( this );
85
mAutoDisconnectTimer->setSingleShot( true );
86
mAutoDisconnectTimer->setInterval( autoDisconnectTimeout );
87
connect( mAutoDisconnectTimer, SIGNAL( timeout() ), SLOT( autoDisconnect() ) );
89
// react to network management events
90
connect( Solid::Networking::notifier(), SIGNAL( statusChanged( uint ) ), this, SLOT( networkStatusChanged( Networking::Status ) ) );
94
// react to socket events
95
connect( socket, SIGNAL( destroyed() ), SLOT( socketDestroyed() ) );
96
connect( socket, SIGNAL( error( QAbstractSocket::SocketError ) ), SLOT( socketError( QAbstractSocket::SocketError ) ) );
97
connect( socket, SIGNAL( stateChanged( QAbstractSocket::SocketState ) ), SLOT( socketStateChanged( QAbstractSocket::SocketState ) ) );
98
// initialise our state from that of the socket
99
switch ( socket->state() )
101
case QAbstractSocket::UnconnectedState:
102
mState = SocketUnconnected;
104
case QAbstractSocket::HostLookupState:
105
case QAbstractSocket::ConnectingState:
106
mState = SocketConnecting;
108
case QAbstractSocket::ConnectedState:
109
case QAbstractSocket::ClosingState:
110
mState = SocketConnected;
113
mState = SocketUnconnected;
118
void Solid::Control::ManagedSocketContainer::networkStatusChanged( Solid::Networking::Status netStatus )
122
case SocketUnconnected:
124
case SocketConnecting:
126
case AwaitingNetworkConnection:
129
case Solid::Networking::Connected:
130
performConnectToHost();
137
case SocketConnected:
140
case Solid::Networking::Unconnected:
141
case Solid::Networking::Disconnecting:
142
mState = DisconnectWait;
143
if ( mAutoDisconnectTimer )
145
mAutoDisconnectTimer->start();
156
case Solid::Networking::Connected:
158
mState = SocketConnected;
159
if ( mAutoDisconnectTimer )
161
mAutoDisconnectTimer->stop();
172
void Solid::Control::ManagedSocketContainer::socketError( QAbstractSocket::SocketError socketError )
176
case SocketUnconnected:
178
case SocketConnecting:
179
switch ( socketError )
181
case QAbstractSocket::HostNotFoundError:
182
case QAbstractSocket::NetworkError:
183
// socket tried to resolve and failed
184
// Either the host doesn't exist at all
185
// or the resolve failed because we're offline, so request that we go online
186
if ( Solid::Networking::status() != Solid::Networking::Connected )
188
mState = AwaitingNetworkConnection;
189
globalNetworkControl->requestConnection();
193
mState = SocketUnconnected;
197
mState = SocketUnconnected;
200
case AwaitingNetworkConnection:
201
case SocketConnected:
202
// setup automatic reconnect now when/if we impl this
204
// maybe check the socket state that it thinks it is now unconnected too
205
mState = SocketUnconnected;
210
void Solid::Control::ManagedSocketContainer::socketStateChanged( QAbstractSocket::SocketState socketState )
214
case SocketUnconnected:
215
switch ( socketState )
217
case QAbstractSocket::HostLookupState:
218
case QAbstractSocket::ConnectingState:
219
// the socket is trying to connect, cache its connection parameter in case it
220
// fails and we want to reconnect it when the network is available.
221
mState = SocketConnecting;
224
mPeerName = mSocket->peerName();
225
mPeerPort = mSocket->peerPort();
226
mSocketOpenMode = mSocket->openMode();
233
case SocketConnecting:
234
switch ( socketState )
236
case QAbstractSocket::HostLookupState:
237
case QAbstractSocket::ConnectingState:
238
// still connecting, do nothing
240
case QAbstractSocket::BoundState:
241
case QAbstractSocket::ConnectedState:
242
case QAbstractSocket::ListeningState:
243
// socket connected unaided
244
mState = SocketConnected;
246
case QAbstractSocket::UnconnectedState:
247
// this state is preceded by ClosingState, so no action needed
249
case QAbstractSocket::ClosingState:
250
// it's unlikely that an unconnected socket can go to this state, but...
251
mState = SocketUnconnected;
255
case AwaitingNetworkConnection:
256
switch ( socketState )
258
case QAbstractSocket::ConnectedState:
259
// somehow the socket connected itself when it shouldn't have been able to.
260
mState = SocketConnected;
268
case SocketConnected:
269
switch ( socketState )
271
case QAbstractSocket::UnconnectedState:
272
case QAbstractSocket::ClosingState:
273
// socket disconnected
274
mState = SocketUnconnected;
276
case QAbstractSocket::ConnectingState:
277
mState = SocketConnected;
284
switch ( socketState )
286
case QAbstractSocket::UnconnectedState:
287
case QAbstractSocket::ClosingState:
288
// socket disconnected anyway
289
mState = SocketUnconnected;
290
if ( mAutoDisconnectTimer )
292
mAutoDisconnectTimer->stop();
302
void Solid::Control::ManagedSocketContainer::autoDisconnect()
304
if ( mAutoDisconnectTimer && mSocket )
305
mSocket->disconnectFromHost();
308
void Solid::Control::ManagedSocketContainer::socketDestroyed()
311
delete mAutoDisconnectTimer;
312
mAutoDisconnectTimer = 0;
313
disconnect( globalNetworkControl );
316
void Solid::Control::ManagedSocketContainer::performConnectToHost()
320
mSocket->connectToHost( mPeerName, mPeerPort, mSocketOpenMode );
324
#include "networking_p.moc"