not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / libs / solid / control / networking.cpp
bloba630ef8c25aafdf01b4d72dca14c9a75e5f44826
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>
24 #include <kglobal.h>
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",
34 "/status",
35 QDBusConnection::sessionBus(),
36 this ) )
40 Solid::Control::NetworkingPrivate::~NetworkingPrivate()
42 }uint Solid::Control::NetworkingPrivate::requestConnection( QObject * receiver, const char * member )
44 connect( this, SIGNAL( connectionResult( bool ) ), receiver, member );
45 return iface->requestConnection();
48 void Solid::Control::NetworkingPrivate::releaseConnection()
50 iface->releaseConnection();
53 Solid::Control::Networking::Result Solid::Control::NetworkingPrivate::beginManagingSocket( QAbstractSocket * socket, int autoDisconnectTimeout )
55 mManagedSockets.insert( socket, new ManagedSocketContainer( socket, autoDisconnectTimeout ) );
56 return Solid::Control::Networking::Accepted;
59 void Solid::Control::NetworkingPrivate::stopManagingSocket( QAbstractSocket * socket )
61 ManagedSocketContainer * removed = mManagedSockets.take( socket );
62 delete removed;
65 Solid::Control::Networking::Result Solid::Control::Networking::requestConnection( QObject * receiver, const char * member )
67 return static_cast<Solid::Control::Networking::Result>( globalNetworkControl->requestConnection( receiver, member ) );
70 void Solid::Control::Networking::releaseConnection()
72 globalNetworkControl->releaseConnection();
75 /*=========================================================================*/
78 Solid::Control::ManagedSocketContainer::ManagedSocketContainer( QAbstractSocket * socket, int autoDisconnectTimeout ) : mSocket( socket ), mAutoDisconnectTimer( 0 )
80 if ( autoDisconnectTimeout >= 0 )
82 mAutoDisconnectTimer = new QTimer( this );
83 mAutoDisconnectTimer->setSingleShot( true );
84 mAutoDisconnectTimer->setInterval( autoDisconnectTimeout );
85 connect( mAutoDisconnectTimer, SIGNAL( timeout() ), SLOT( autoDisconnect() ) );
87 // react to network management events
88 connect( Solid::Networking::notifier(), SIGNAL( statusChanged( uint ) ), this, SLOT( networkStatusChanged( Networking::Status ) ) );
90 if ( socket )
92 // react to socket events
93 connect( socket, SIGNAL( destroyed() ), SLOT( socketDestroyed() ) );
94 connect( socket, SIGNAL( error( QAbstractSocket::SocketError ) ), SLOT( socketError( QAbstractSocket::SocketError ) ) );
95 connect( socket, SIGNAL( stateChanged( QAbstractSocket::SocketState ) ), SLOT( socketStateChanged( QAbstractSocket::SocketState ) ) );
96 // initialise our state from that of the socket
97 switch ( socket->state() )
99 case QAbstractSocket::UnconnectedState:
100 mState = SocketUnconnected;
101 break;
102 case QAbstractSocket::HostLookupState:
103 case QAbstractSocket::ConnectingState:
104 mState = SocketConnecting;
105 break;
106 case QAbstractSocket::ConnectedState:
107 case QAbstractSocket::ClosingState:
108 mState = SocketConnected;
109 break;
110 default:
111 mState = SocketUnconnected;
116 void Solid::Control::ManagedSocketContainer::networkStatusChanged( Solid::Networking::Status netStatus )
118 switch ( mState )
120 case SocketUnconnected:
121 break;
122 case SocketConnecting:
123 break;
124 case AwaitingNetworkConnection:
125 switch ( netStatus )
127 case Solid::Networking::Connected:
128 performConnectToHost();
129 break;
130 default:
131 //do nothing
134 break;
135 case SocketConnected:
136 switch ( netStatus )
138 case Solid::Networking::Unconnected:
139 case Solid::Networking::Disconnecting:
140 mState = DisconnectWait;
141 if ( mAutoDisconnectTimer )
143 mAutoDisconnectTimer->start();
145 break;
146 default:
147 // do nothing
150 break;
151 case DisconnectWait:
152 switch ( netStatus )
154 case Solid::Networking::Connected:
155 // RECOVERED
156 mState = SocketConnected;
157 if ( mAutoDisconnectTimer )
159 mAutoDisconnectTimer->stop();
161 break;
162 default:
163 // do nothing
166 break;
170 void Solid::Control::ManagedSocketContainer::socketError( QAbstractSocket::SocketError socketError )
172 switch ( mState )
174 case SocketUnconnected:
175 break;
176 case SocketConnecting:
177 switch ( socketError )
179 case QAbstractSocket::HostNotFoundError:
180 case QAbstractSocket::NetworkError:
181 // socket tried to resolve and failed
182 // Either the host doesn't exist at all
183 // or the resolve failed because we're offline, so request that we go online
184 if ( Solid::Networking::status() != Solid::Networking::Connected )
186 mState = AwaitingNetworkConnection;
187 globalNetworkControl->requestConnection();
189 else
191 mState = SocketUnconnected;
193 break;
194 default:
195 mState = SocketUnconnected;
197 break;
198 case AwaitingNetworkConnection:
199 case SocketConnected:
200 // setup automatic reconnect now when/if we impl this
201 case DisconnectWait:
202 // maybe check the socket state that it thinks it is now unconnected too
203 mState = SocketUnconnected;
204 break;
208 void Solid::Control::ManagedSocketContainer::socketStateChanged( QAbstractSocket::SocketState socketState )
210 switch ( mState )
212 case SocketUnconnected:
213 switch ( socketState )
215 case QAbstractSocket::HostLookupState:
216 case QAbstractSocket::ConnectingState:
217 // the socket is trying to connect, cache its connection parameter in case it
218 // fails and we want to reconnect it when the network is available.
219 mState = SocketConnecting;
220 if ( mSocket )
222 mPeerName = mSocket->peerName();
223 mPeerPort = mSocket->peerPort();
224 mSocketOpenMode = mSocket->openMode();
226 break;
227 default:
230 break;
231 case SocketConnecting:
232 switch ( socketState )
234 case QAbstractSocket::HostLookupState:
235 case QAbstractSocket::ConnectingState:
236 // still connecting, do nothing
237 break;
238 case QAbstractSocket::BoundState:
239 case QAbstractSocket::ConnectedState:
240 case QAbstractSocket::ListeningState:
241 // socket connected unaided
242 mState = SocketConnected;
243 break;
244 case QAbstractSocket::UnconnectedState:
245 // this state is preceded by ClosingState, so no action needed
246 break;
247 case QAbstractSocket::ClosingState:
248 // it's unlikely that an unconnected socket can go to this state, but...
249 mState = SocketUnconnected;
250 break;
252 break;
253 case AwaitingNetworkConnection:
254 switch ( socketState )
256 case QAbstractSocket::ConnectedState:
257 // somehow the socket connected itself when it shouldn't have been able to.
258 mState = SocketConnected;
260 break;
261 default:
262 //do nothing
265 break;
266 case SocketConnected:
267 switch ( socketState )
269 case QAbstractSocket::UnconnectedState:
270 case QAbstractSocket::ClosingState:
271 // socket disconnected
272 mState = SocketUnconnected;
273 break;
274 case QAbstractSocket::ConnectingState:
275 mState = SocketConnected;
276 break;
277 default:
280 break;
281 case DisconnectWait:
282 switch ( socketState )
284 case QAbstractSocket::UnconnectedState:
285 case QAbstractSocket::ClosingState:
286 // socket disconnected anyway
287 mState = SocketUnconnected;
288 if ( mAutoDisconnectTimer )
290 mAutoDisconnectTimer->stop();
292 break;
293 default:
294 break;
296 break;
300 void Solid::Control::ManagedSocketContainer::autoDisconnect()
302 if ( mAutoDisconnectTimer && mSocket )
303 mSocket->disconnectFromHost();
306 void Solid::Control::ManagedSocketContainer::socketDestroyed()
308 mSocket = 0;
309 delete mAutoDisconnectTimer;
310 mAutoDisconnectTimer = 0;
311 disconnect( globalNetworkControl );
314 void Solid::Control::ManagedSocketContainer::performConnectToHost()
316 if ( mSocket )
318 mSocket->connectToHost( mPeerName, mPeerPort, mSocketOpenMode );
322 #include "networking_p.moc"
323 #include "networking.moc"