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

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • 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 
39 using namespace KNetwork;
40 
41 class KNetwork::KStreamSocketPrivate
42 {
43 public:
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 
55 KStreamSocket::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 
69 KStreamSocket::~KStreamSocket()
70 {
71  delete d;
72  // KClientSocketBase's destructor closes the socket
73 }
74 
75 int KStreamSocket::timeout() const
76 {
77  return d->timeout;
78 }
79 
80 int 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 
90 void KStreamSocket::setTimeout(int msecs)
91 {
92  d->timeout = msecs;
93 
94  if (state() == Connecting)
95  d->timer.start(msecs);
96 }
97 
98 bool 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 
110 bool KStreamSocket::bind(const KResolverEntry& entry)
111 {
112  return KClientSocketBase::bind(entry);
113 }
114 
115 bool 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 
204 bool KStreamSocket::connect(const KResolverEntry& entry, OpenMode mode)
205 {
206  return KClientSocketBase::connect(entry, mode);
207 }
208 
209 void 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 
220 void 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 
317 void 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 
336 bool 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 
367 void 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"
k3socketaddress.h
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::KSocketBase::blocking
bool blocking() const
Retrieves this socket's blocking mode.
Definition: k3socketbase.cpp:102
KNetwork::KSocketBase::socketDevice
KSocketDevice * socketDevice() const
Retrieves the socket implementation used on this socket.
Definition: k3socketbase.cpp:148
KNetwork::KClientSocketBase::Idle
Definition: k3clientsocketbase.h:74
k3socketdevice.h
KNetwork::KClientSocketBase::state
SocketState state() const
Returns the current state for this socket.
Definition: k3clientsocketbase.cpp:66
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::KStreamSocket
KStreamSocket(const QString &node=QString(), const QString &service=QString(), QObject *parent=0L)
Default constructor.
Definition: k3streamsocket.cpp:55
QSocketNotifier
KNetwork::KStreamSocket::remainingTimeout
int remainingTimeout() const
Retrieves the remaining timeout time (in milliseconds).
Definition: k3streamsocket.cpp:80
KNetwork::KStreamSocket::timeout
int timeout() const
Retrieves the timeout value (in milliseconds).
Definition: k3streamsocket.cpp:75
timeout
int timeout
Definition: kkernel_mac.cpp:46
KNetwork::KResolverEntry
One resolution entry.
Definition: k3resolver.h:68
KNetwork::KActiveSocketBase::resetError
void resetError()
Resets the socket error code and the I/O Device's status.
Definition: k3socketbase.cpp:441
KNetwork::KSocketDevice::writeNotifier
QSocketNotifier * writeNotifier() const
Returns a socket notifier for output on this socket.
Definition: k3socketdevice.cpp:665
KNetwork::KSocketDevice::connect
virtual bool connect(const KResolverEntry &address, OpenMode mode=ReadWrite)
Connect to a remote host.
Definition: k3socketdevice.cpp:345
KNetwork::KResolver::setFamily
void setFamily(int families)
Sets the allowed socket families.
Definition: k3resolver.cpp:385
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...
QPointer
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::localResolver
KResolver & localResolver() const
Returns the internal KResolver object used for looking up the local host name and service...
Definition: k3clientsocketbase.cpp:103
KNetwork::KSocketBase::InProgress
Definition: k3socketbase.h:157
KNetwork::KSocketBase::error
SocketError error() const
Retrieves the socket error code.
Definition: k3socketbase.cpp:197
KNetwork::KSocketDevice::socket
int socket() const
Returns the file descriptor for this socket.
Definition: k3socketdevice.cpp:127
k3streamsocket.h
KNetwork::KClientSocketBase::gotError
void gotError(int code)
This signal is emitted when this object finds an error.
KNetwork::KClientSocketBase::hostFound
void hostFound()
This signal is emitted when the lookup is successfully completed.
QObject::disconnect
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
KNetwork::KResolverResults
Name and service resolution results.
Definition: k3resolver.h:212
QTime
KNetwork::KSocketDevice::setSocketOptions
virtual bool setSocketOptions(int opts)
This implementation sets the options on the socket.
Definition: k3socketdevice.cpp:137
KNetwork::KClientSocketBase::setSocketOptions
virtual bool setSocketOptions(int opts)
Sets the socket options.
Definition: k3clientsocketbase.cpp:77
KNetwork::KResolver::setServiceName
void setServiceName(const QString &service)
Sets the service name to be resolved.
Definition: k3resolver.cpp:348
QString::isNull
bool isNull() const
KNetwork::KActiveSocketBase::open
virtual bool open(OpenMode mode)
Reimplemented from QIODevice.
Definition: k3socketbase.cpp:339
KNetwork::KSocketDevice::readNotifier
QSocketNotifier * readNotifier() const
Returns a socket notifier for input on this socket.
Definition: k3socketdevice.cpp:647
KNetwork::KStreamSocket::timedOut
void timedOut()
This signal is emitted when a connection timeout occurs.
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
QTimer
KNetwork::KSocketDevice::bind
virtual bool bind(const KResolverEntry &address)
Binds this socket to the given address.
Definition: k3socketdevice.cpp:293
QObject
QPointer::isNull
bool isNull() const
QList::isEmpty
bool isEmpty() const
KNetwork::KSocketBase::NoError
Definition: k3socketbase.h:145
KNetwork::KClientSocketBase::peerResults
const KResolverResults & peerResults() const
Returns the internal list of resolved results for the peer address.
Definition: k3clientsocketbase.cpp:98
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::KStreamSocket::~KStreamSocket
virtual ~KStreamSocket()
Destructor.
Definition: k3streamsocket.cpp:69
QString
KNetwork::KClientSocketBase::HostFound
Definition: k3clientsocketbase.h:76
KNetwork::KClientSocketBase::setState
void setState(SocketState state)
Sets the socket state to state.
Definition: k3clientsocketbase.cpp:71
KNetwork::KClientSocketBase::Connected
Definition: k3clientsocketbase.h:83
KNetwork::KResolver::KnownFamily
Definition: k3resolver.h:346
KNetwork::KClientSocketBase::stateChanged
void stateChanged(int newstate)
This signal is emitted whenever the socket state changes.
KNetwork::KStreamSocket::setTimeout
void setTimeout(int msecs)
Sets the timeout value.
Definition: k3streamsocket.cpp:90
KNetwork::KActiveSocketBase::setError
void setError(SocketError error)
Sets the socket's error code.
Definition: k3socketbase.cpp:435
KNetwork::KSocketBase::NotSupported
Definition: k3socketbase.h:159
QList::end
iterator end()
k3resolver.h
KNetwork::KClientSocketBase::bound
void bound(const KNetwork::KResolverEntry &local)
This signal is emitted when the socket successfully binds to an address.
KNetwork::KResolver::setNodeName
void setNodeName(const QString &nodename)
Sets the nodename for the resolution.
Definition: k3resolver.cpp:336
QSocketNotifier::setEnabled
void setEnabled(bool enable)
KNetwork::KSocketDevice::close
virtual void close()
Closes the socket.
Definition: k3socketdevice.cpp:232
KNetwork::KClientSocketBase::Connecting
Definition: k3clientsocketbase.h:78
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
QList< KResolverEntry >::ConstIterator
typedef ConstIterator
KNetwork::KResolverEntry::family
int family() const
Retrieves the family associated with this socket address.
Definition: k3resolver.cpp:147
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::KSocketBase::Timeout
Definition: k3socketbase.h:160
KNetwork::KClientSocketBase
Abstract client socket class.
Definition: k3clientsocketbase.h:50
KNetwork::KSocketBase::setBlocking
virtual bool setBlocking(bool enable)
Sets this socket's blocking mode.
Definition: k3socketbase.cpp:97
KNetwork::KClientSocketBase::localResults
const KResolverResults & localResults() const
Returns the internal list of resolved results for the local address.
Definition: k3clientsocketbase.cpp:108
KNetwork::KSocketBase::Blocking
Definition: k3socketbase.h:110
KNetwork::KSocketBase::socketOptions
virtual int socketOptions() const
Retrieves the socket options that have been set.
Definition: k3socketbase.cpp:92
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
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::connected
void connected(const KNetwork::KResolverEntry &remote)
This socket is emitted when the socket successfully connects to a remote address. ...
QList::begin
iterator begin()
QTimer::singleShot
singleShot
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:10 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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