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()
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
);
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
) ) );
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
;
102 case QAbstractSocket::HostLookupState
:
103 case QAbstractSocket::ConnectingState
:
104 mState
= SocketConnecting
;
106 case QAbstractSocket::ConnectedState
:
107 case QAbstractSocket::ClosingState
:
108 mState
= SocketConnected
;
111 mState
= SocketUnconnected
;
116 void Solid::Control::ManagedSocketContainer::networkStatusChanged( Solid::Networking::Status netStatus
)
120 case SocketUnconnected
:
122 case SocketConnecting
:
124 case AwaitingNetworkConnection
:
127 case Solid::Networking::Connected
:
128 performConnectToHost();
135 case SocketConnected
:
138 case Solid::Networking::Unconnected
:
139 case Solid::Networking::Disconnecting
:
140 mState
= DisconnectWait
;
141 if ( mAutoDisconnectTimer
)
143 mAutoDisconnectTimer
->start();
154 case Solid::Networking::Connected
:
156 mState
= SocketConnected
;
157 if ( mAutoDisconnectTimer
)
159 mAutoDisconnectTimer
->stop();
170 void Solid::Control::ManagedSocketContainer::socketError( QAbstractSocket::SocketError socketError
)
174 case SocketUnconnected
:
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();
191 mState
= SocketUnconnected
;
195 mState
= SocketUnconnected
;
198 case AwaitingNetworkConnection
:
199 case SocketConnected
:
200 // setup automatic reconnect now when/if we impl this
202 // maybe check the socket state that it thinks it is now unconnected too
203 mState
= SocketUnconnected
;
208 void Solid::Control::ManagedSocketContainer::socketStateChanged( QAbstractSocket::SocketState socketState
)
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
;
222 mPeerName
= mSocket
->peerName();
223 mPeerPort
= mSocket
->peerPort();
224 mSocketOpenMode
= mSocket
->openMode();
231 case SocketConnecting
:
232 switch ( socketState
)
234 case QAbstractSocket::HostLookupState
:
235 case QAbstractSocket::ConnectingState
:
236 // still connecting, do nothing
238 case QAbstractSocket::BoundState
:
239 case QAbstractSocket::ConnectedState
:
240 case QAbstractSocket::ListeningState
:
241 // socket connected unaided
242 mState
= SocketConnected
;
244 case QAbstractSocket::UnconnectedState
:
245 // this state is preceded by ClosingState, so no action needed
247 case QAbstractSocket::ClosingState
:
248 // it's unlikely that an unconnected socket can go to this state, but...
249 mState
= SocketUnconnected
;
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
;
266 case SocketConnected
:
267 switch ( socketState
)
269 case QAbstractSocket::UnconnectedState
:
270 case QAbstractSocket::ClosingState
:
271 // socket disconnected
272 mState
= SocketUnconnected
;
274 case QAbstractSocket::ConnectingState
:
275 mState
= SocketConnected
;
282 switch ( socketState
)
284 case QAbstractSocket::UnconnectedState
:
285 case QAbstractSocket::ClosingState
:
286 // socket disconnected anyway
287 mState
= SocketUnconnected
;
288 if ( mAutoDisconnectTimer
)
290 mAutoDisconnectTimer
->stop();
300 void Solid::Control::ManagedSocketContainer::autoDisconnect()
302 if ( mAutoDisconnectTimer
&& mSocket
)
303 mSocket
->disconnectFromHost();
306 void Solid::Control::ManagedSocketContainer::socketDestroyed()
309 delete mAutoDisconnectTimer
;
310 mAutoDisconnectTimer
= 0;
311 disconnect( globalNetworkControl
);
314 void Solid::Control::ManagedSocketContainer::performConnectToHost()
318 mSocket
->connectToHost( mPeerName
, mPeerPort
, mSocketOpenMode
);
322 #include "networking_p.moc"
323 #include "networking.moc"