• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • network
k3streamsocket.cpp
Go to the documentation of this file.
1/* -*- C++ -*-
2 * Copyright (C) 2003 Thiago Macieira <thiago@kde.org>
3 *
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include "k3streamsocket.h"
26
27#include <config.h>
28#include <config-network.h>
29
30#include <QSocketNotifier>
31#include <QDateTime>
32#include <QTimer>
33#include <QPointer>
34
35#include "k3socketaddress.h"
36#include "k3resolver.h"
37#include "k3socketdevice.h"
38
39using namespace KNetwork;
40
41class KNetwork::KStreamSocketPrivate
42{
43public:
44 KResolverResults::ConstIterator local, peer;
45 QTime startTime;
46 QTimer timer;
47
48 int timeout;
49
50 inline KStreamSocketPrivate()
51 : timeout(0)
52 { }
53};
54
55KStreamSocket::KStreamSocket(const QString& node, const QString& service,
56 QObject* parent)
57 : KClientSocketBase(parent), d(new KStreamSocketPrivate)
58{
59 peerResolver().setNodeName(node);
60 peerResolver().setServiceName(service);
61 peerResolver().setFamily(KResolver::KnownFamily);
62 localResolver().setFamily(KResolver::KnownFamily);
63
64 setSocketOptions(socketOptions() & ~Blocking);
65
66 QObject::connect(&d->timer, SIGNAL(timeout()), this, SLOT(timeoutSlot()));
67}
68
69KStreamSocket::~KStreamSocket()
70{
71 delete d;
72 // KClientSocketBase's destructor closes the socket
73}
74
75int KStreamSocket::timeout() const
76{
77 return d->timeout;
78}
79
80int KStreamSocket::remainingTimeout() const
81{
82 if (state() != Connecting)
83 return timeout();
84 if (timeout() <= 0)
85 return 0;
86
87 return timeout() - d->startTime.elapsed();
88}
89
90void KStreamSocket::setTimeout(int msecs)
91{
92 d->timeout = msecs;
93
94 if (state() == Connecting)
95 d->timer.start(msecs);
96}
97
98bool KStreamSocket::bind(const QString& node, const QString& service)
99{
100 if (state() != Idle)
101 return false;
102
103 if (!node.isNull())
104 localResolver().setNodeName(node);
105 if (!service.isNull())
106 localResolver().setServiceName(service);
107 return true;
108}
109
110bool KStreamSocket::bind(const KResolverEntry& entry)
111{
112 return KClientSocketBase::bind(entry);
113}
114
115bool KStreamSocket::connect(const QString& node, const QString& service,
116 OpenMode mode)
117{
118 Q_UNUSED(mode);
119 if (state() == Connected)
120 return true; // already connected
121
122 if (state() > Connected)
123 return false; // can't do much here
124
125 if (!node.isNull())
126 peerResolver().setNodeName(node);
127 if (!service.isNull())
128 peerResolver().setServiceName(service);
129
130 if (state() == Connecting && !blocking())
131 {
132 setError(InProgress);
133 emit gotError(InProgress);
134 return true; // we're already connecting
135 }
136
137 if (state() < HostFound)
138 {
139 // connection hasn't started yet
140 if (!blocking())
141 {
142 QObject::connect(this, SIGNAL(hostFound()), SLOT(hostFoundSlot()));
143 return lookup();
144 }
145
146 // blocking mode
147 if (!lookup())
148 return false; // lookup failure
149 }
150
151 /*
152 * lookup results are available here
153 */
154
155 if (timeout() > 0)
156 {
157 if (!blocking() && !d->timer.isActive())
158 {
159 d->timer.setSingleShot(true);
160 d->timer.start(timeout());
161 }
162 else
163 {
164 // blocking connection with timeout
165 // this must be handled as a special case because it requires a
166 // non-blocking socket
167
168 d->timer.stop(); // no need for a timer here
169
170 socketDevice()->setBlocking(false);
171 while (true)
172 {
173 connectionEvent();
174 if (state() < Connecting)
175 return false; // error connecting
176 if (state() == Connected)
177 return true; // connected!
178
179 if (remainingTimeout() <= 0)
180 {
181 // we've timed out
182 timeoutSlot();
183 return false;
184 }
185
186 if (socketDevice()->error() == InProgress)
187 {
188 bool timedout;
189 socketDevice()->poll(remainingTimeout(), &timedout);
190 if (timedout)
191 {
192 timeoutSlot();
193 return false;
194 }
195 }
196 }
197 }
198 }
199
200 connectionEvent();
201 return error() == NoError;
202}
203
204bool KStreamSocket::connect(const KResolverEntry& entry, OpenMode mode)
205{
206 return KClientSocketBase::connect(entry, mode);
207}
208
209void KStreamSocket::hostFoundSlot()
210{
211 QObject::disconnect(this, SLOT(hostFoundSlot()));
212 if (timeout() > 0)
213 {
214 d->timer.setSingleShot(true);
215 d->timer.start(timeout());
216 }
217 QTimer::singleShot(0, this, SLOT(connectionEvent()));
218}
219
220void KStreamSocket::connectionEvent()
221{
222 if (state() != HostFound && state() != Connecting)
223 return; // nothing to do
224
225 const KResolverResults& peer = peerResults();
226 if (state() == HostFound)
227 {
228 d->startTime.start();
229
230 setState(Connecting);
231 emit stateChanged(Connecting);
232 d->peer = peer.begin();
233 d->local = localResults().begin(); // just to be on the safe side
234 }
235
236 while (d->peer != peer.end())
237 {
238 const KResolverEntry &r = *d->peer;
239
240 if (socketDevice()->socket() != -1)
241 {
242 // we have an existing file descriptor
243 // this means that we've got activity in it (connection result)
244 if (socketDevice()->connect(r) && socketDevice()->error() == NoError)
245 {
246 // yes, it did connect!
247 connectionSucceeded(r);
248 return;
249 }
250 else if (socketDevice()->error() == InProgress)
251 // nope, still in progress
252 return;
253
254 // no, the socket failed to connect
255 copyError();
256 socketDevice()->close();
257 ++d->peer;
258 continue;
259 }
260
261 // try to bind
262 if (!bindLocallyFor(r))
263 {
264 // could not find a matching family
265 ++d->peer;
266 continue;
267 }
268
269 {
270 bool skip = false;
271 emit aboutToConnect(r, skip);
272 if (skip)
273 {
274 ++d->peer;
275 continue;
276 }
277 }
278
279 if (socketDevice()->connect(r) || socketDevice()->error() == InProgress)
280 {
281 // socket is attempting to connect
282 if (socketDevice()->error() == InProgress)
283 {
284 QSocketNotifier *n = socketDevice()->readNotifier();
285 QObject::connect(n, SIGNAL(activated(int)),
286 this, SLOT(connectionEvent()));
287 n->setEnabled(true);
288
289 n = socketDevice()->writeNotifier();
290 QObject::connect(n, SIGNAL(activated(int)),
291 this, SLOT(connectionEvent()));
292 n->setEnabled(true);
293
294 return; // wait for activity
295 }
296
297 // socket has connected
298 connectionSucceeded(r);
299 return;
300 }
301
302 // connection failed
303 // try next
304 copyError();
305 socketDevice()->close();
306 ++d->peer;
307 }
308
309 // that was the last item
310 socketDevice()->setSocketOptions(socketOptions());
311 setState(Idle);
312 emit stateChanged(Idle);
313 emit gotError(error());
314 return;
315}
316
317void KStreamSocket::timeoutSlot()
318{
319 if (state() != Connecting)
320 return;
321
322 // halt the connections
323 socketDevice()->close(); // this also kills the notifiers
324
325 setError(Timeout);
326 setState(HostFound);
327 emit stateChanged(HostFound);
328
329 QPointer<KStreamSocket> that = this;
330 emit gotError(Timeout);
331
332 if (!that.isNull())
333 emit timedOut();
334}
335
336bool KStreamSocket::bindLocallyFor(const KResolverEntry& peer)
337{
338 const KResolverResults& local = localResults();
339
340 if (local.isEmpty())
341 // user doesn't want to bind to any specific local address
342 return true;
343
344 bool foundone = false;
345 // scan the local resolution for a matching family
346 for (d->local = local.begin(); d->local != local.end(); ++d->local)
347 if ((*d->local).family() == peer.family())
348 {
349 // found a suitable address!
350 foundone = true;
351
352 if (socketDevice()->bind(*d->local))
353 return true;
354 }
355
356 if (!foundone)
357 {
358 // found nothing
359 setError(NotSupported);
360 emit gotError(NotSupported);
361 }
362 else
363 copyError();
364 return false;
365}
366
367void KStreamSocket::connectionSucceeded(const KResolverEntry& peer)
368{
369 QObject::disconnect(socketDevice()->readNotifier(), 0, this, SLOT(connectionEvent()));
370 QObject::disconnect(socketDevice()->writeNotifier(), 0, this, SLOT(connectionEvent()));
371
372 resetError();
373 KActiveSocketBase::open(ReadWrite | Unbuffered);
374 setState(Connected);
375 socketDevice()->setSocketOptions(socketOptions());
376 d->timer.stop();
377 emit stateChanged(Connected);
378
379 if (!localResults().isEmpty())
380 emit bound(*d->local);
381 emit connected(peer);
382}
383
384#include "k3streamsocket.moc"
KNetwork::KActiveSocketBase::resetError
void resetError()
Resets the socket error code and the I/O Device's status.
Definition: k3socketbase.cpp:441
KNetwork::KActiveSocketBase::open
virtual bool open(OpenMode mode)
Reimplemented from QIODevice.
Definition: k3socketbase.cpp:339
KNetwork::KActiveSocketBase::setError
void setError(SocketError error)
Sets the socket's error code.
Definition: k3socketbase.cpp:435
KNetwork::KClientSocketBase
Abstract client socket class.
Definition: k3clientsocketbase.h:51
KNetwork::KClientSocketBase::Connected
@ Connected
Definition: k3clientsocketbase.h:83
KNetwork::KClientSocketBase::Connecting
@ Connecting
Definition: k3clientsocketbase.h:78
KNetwork::KClientSocketBase::Idle
@ Idle
Definition: k3clientsocketbase.h:74
KNetwork::KClientSocketBase::HostFound
@ HostFound
Definition: k3clientsocketbase.h:76
KNetwork::KClientSocketBase::bind
virtual bool bind(const QString &node=QString(), const QString &service=QString())=0
Binds this socket to the given nodename and service, or use the default ones if none are given.
KNetwork::KClientSocketBase::aboutToConnect
void aboutToConnect(const KNetwork::KResolverEntry &remote, bool &skip)
This signal is emitted when the socket is about to connect to an address (but before doing so).
KNetwork::KClientSocketBase::localResults
const KResolverResults & localResults() const
Returns the internal list of resolved results for the local address.
Definition: k3clientsocketbase.cpp:108
KNetwork::KClientSocketBase::connected
void connected(const KNetwork::KResolverEntry &remote)
This socket is emitted when the socket successfully connects to a remote address.
KNetwork::KClientSocketBase::setState
void setState(SocketState state)
Sets the socket state to state.
Definition: k3clientsocketbase.cpp:71
KNetwork::KClientSocketBase::state
SocketState state() const
Returns the current state for this socket.
Definition: k3clientsocketbase.cpp:66
KNetwork::KClientSocketBase::gotError
void gotError(int code)
This signal is emitted when this object finds an error.
KNetwork::KClientSocketBase::lookup
virtual bool lookup()
Starts the lookup for peer and local hostnames as well as their services.
Definition: k3clientsocketbase.cpp:133
KNetwork::KClientSocketBase::peerResolver
KResolver & peerResolver() const
Returns the internal KResolver object used for looking up the peer host name and service.
Definition: k3clientsocketbase.cpp:93
KNetwork::KClientSocketBase::copyError
void copyError()
Convenience function to set this object's error code to match that of the socket device.
Definition: k3clientsocketbase.cpp:453
KNetwork::KClientSocketBase::hostFound
void hostFound()
This signal is emitted when the lookup is successfully completed.
KNetwork::KClientSocketBase::bound
void bound(const KNetwork::KResolverEntry &local)
This signal is emitted when the socket successfully binds to an address.
KNetwork::KClientSocketBase::setSocketOptions
virtual bool setSocketOptions(int opts)
Sets the socket options.
Definition: k3clientsocketbase.cpp:77
KNetwork::KClientSocketBase::peerResults
const KResolverResults & peerResults() const
Returns the internal list of resolved results for the peer address.
Definition: k3clientsocketbase.cpp:98
KNetwork::KClientSocketBase::stateChanged
void stateChanged(int newstate)
This signal is emitted whenever the socket state changes.
KNetwork::KClientSocketBase::connect
virtual bool connect(const QString &node=QString(), const QString &service=QString(), OpenMode mode=ReadWrite)=0
Attempts to connect to a given hostname and service, or use the default ones if none are given.
KNetwork::KClientSocketBase::localResolver
KResolver & localResolver() const
Returns the internal KResolver object used for looking up the local host name and service.
Definition: k3clientsocketbase.cpp:103
KNetwork::KResolverEntry
One resolution entry.
Definition: k3resolver.h:69
KNetwork::KResolverEntry::family
int family() const
Retrieves the family associated with this socket address.
Definition: k3resolver.cpp:147
KNetwork::KResolverResults
Name and service resolution results.
Definition: k3resolver.h:213
KNetwork::KResolver::KnownFamily
@ KnownFamily
Definition: k3resolver.h:346
KNetwork::KResolver::setFamily
void setFamily(int families)
Sets the allowed socket families.
Definition: k3resolver.cpp:385
KNetwork::KResolver::setServiceName
void setServiceName(const QString &service)
Sets the service name to be resolved.
Definition: k3resolver.cpp:348
KNetwork::KResolver::setNodeName
void setNodeName(const QString &nodename)
Sets the nodename for the resolution.
Definition: k3resolver.cpp:336
KNetwork::KSocketBase::socketOptions
virtual int socketOptions() const
Retrieves the socket options that have been set.
Definition: k3socketbase.cpp:92
KNetwork::KSocketBase::Blocking
@ Blocking
Definition: k3socketbase.h:110
KNetwork::KSocketBase::NotSupported
@ NotSupported
Definition: k3socketbase.h:159
KNetwork::KSocketBase::InProgress
@ InProgress
Definition: k3socketbase.h:157
KNetwork::KSocketBase::NoError
@ NoError
Definition: k3socketbase.h:145
KNetwork::KSocketBase::Timeout
@ Timeout
Definition: k3socketbase.h:160
KNetwork::KSocketBase::blocking
bool blocking() const
Retrieves this socket's blocking mode.
Definition: k3socketbase.cpp:102
KNetwork::KSocketBase::error
SocketError error() const
Retrieves the socket error code.
Definition: k3socketbase.cpp:197
KNetwork::KSocketBase::setBlocking
virtual bool setBlocking(bool enable)
Sets this socket's blocking mode.
Definition: k3socketbase.cpp:97
KNetwork::KSocketBase::socketDevice
KSocketDevice * socketDevice() const
Retrieves the socket implementation used on this socket.
Definition: k3socketbase.cpp:148
KNetwork::KSocketDevice::setSocketOptions
virtual bool setSocketOptions(int opts)
This implementation sets the options on the socket.
Definition: k3socketdevice.cpp:137
KNetwork::KSocketDevice::readNotifier
QSocketNotifier * readNotifier() const
Returns a socket notifier for input on this socket.
Definition: k3socketdevice.cpp:647
KNetwork::KSocketDevice::close
virtual void close()
Closes the socket.
Definition: k3socketdevice.cpp:232
KNetwork::KSocketDevice::writeNotifier
QSocketNotifier * writeNotifier() const
Returns a socket notifier for output on this socket.
Definition: k3socketdevice.cpp:665
KNetwork::KSocketDevice::poll
virtual bool poll(bool *input, bool *output, bool *exception=0L, int timeout=-1, bool *timedout=0L)
Executes a poll in the socket, via select(2) or poll(2).
Definition: k3socketdevice.cpp:701
KNetwork::KStreamSocket::connect
virtual bool connect(const QString &node=QString(), const QString &service=QString(), OpenMode mode=ReadWrite)
Reimplemented from KClientSocketBase.
Definition: k3streamsocket.cpp:115
KNetwork::KStreamSocket::bind
virtual bool bind(const QString &node=QString(), const QString &service=QString())
Binds this socket to the given nodename and service, or use the default ones if none are given.
Definition: k3streamsocket.cpp:98
KNetwork::KStreamSocket::timeout
int timeout() const
Retrieves the timeout value (in milliseconds).
Definition: k3streamsocket.cpp:75
KNetwork::KStreamSocket::setTimeout
void setTimeout(int msecs)
Sets the timeout value.
Definition: k3streamsocket.cpp:90
KNetwork::KStreamSocket::~KStreamSocket
virtual ~KStreamSocket()
Destructor.
Definition: k3streamsocket.cpp:69
KNetwork::KStreamSocket::KStreamSocket
KStreamSocket(const QString &node=QString(), const QString &service=QString(), QObject *parent=0L)
Default constructor.
Definition: k3streamsocket.cpp:55
KNetwork::KStreamSocket::timedOut
void timedOut()
This signal is emitted when a connection timeout occurs.
KNetwork::KStreamSocket::remainingTimeout
int remainingTimeout() const
Retrieves the remaining timeout time (in milliseconds).
Definition: k3streamsocket.cpp:80
QObject
QString
k3resolver.h
k3socketaddress.h
k3socketdevice.h
k3streamsocket.h
timeout
int timeout
Definition: kkernel_mac.cpp:46
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: k3bufferedsocket.h:35
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal