• 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
k3serversocket.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 "k3serversocket.h"
26 
27 #include <config.h>
28 #include <config-network.h>
29 
30 #include <QSocketNotifier>
31 #include <QMutex>
32 
33 #include "k3socketaddress.h"
34 #include "k3resolver.h"
35 #include "k3socketbase.h"
36 #include "k3socketdevice.h"
37 #include "k3bufferedsocket.h"
38 
39 using namespace KNetwork;
40 
41 class KNetwork::KServerSocketPrivate
42 {
43 public:
44  KResolver resolver;
45  KResolverResults resolverResults;
46 
47  enum { None, LookupDone, Bound, Listening } state;
48  int backlog;
49  int timeout;
50 
51  bool bindWhenFound : 1, listenWhenBound : 1, useKBufferedSocket : 1;
52 
53  KServerSocketPrivate()
54  : state(None), timeout(0), bindWhenFound(false), listenWhenBound(false),
55  useKBufferedSocket(true)
56  {
57  resolver.setFlags(KResolver::Passive);
58  resolver.setFamily(KResolver::KnownFamily);
59  }
60 };
61 
62 KServerSocket::KServerSocket(QObject* parent)
63  : QObject(parent), d(new KServerSocketPrivate)
64 {
65  QObject::connect(&d->resolver, SIGNAL(finished(KNetwork::KResolverResults)),
66  this, SLOT(lookupFinishedSlot()));
67 }
68 
69 KServerSocket::KServerSocket(const QString& service, QObject* parent)
70  : QObject(parent), d(new KServerSocketPrivate)
71 {
72  QObject::connect(&d->resolver, SIGNAL(finished(KNetwork::KResolverResults)),
73  this, SLOT(lookupFinishedSlot()));
74  d->resolver.setServiceName(service);
75 }
76 
77 KServerSocket::KServerSocket(const QString& node, const QString& service,
78  QObject* parent)
79  : QObject(parent), d(new KServerSocketPrivate)
80 {
81  QObject::connect(&d->resolver, SIGNAL(finished(KNetwork::KResolverResults)),
82  this, SLOT(lookupFinishedSlot()));
83  setAddress(node, service);
84 }
85 
86 KServerSocket::~KServerSocket()
87 {
88  close();
89  delete d;
90 }
91 
92 bool KServerSocket::setSocketOptions(int opts)
93 {
94  QMutexLocker locker(mutex());
95  KSocketBase::setSocketOptions(opts); // call parent
96  bool result = socketDevice()->setSocketOptions(opts); // and set the implementation
97  copyError();
98  return result;
99 }
100 
101 KResolver& KServerSocket::resolver() const
102 {
103  return d->resolver;
104 }
105 
106 const KResolverResults& KServerSocket::resolverResults() const
107 {
108  return d->resolverResults;
109 }
110 
111 void KServerSocket::setResolutionEnabled(bool enable)
112 {
113  if (enable)
114  d->resolver.setFlags(d->resolver.flags() & ~KResolver::NoResolve);
115  else
116  d->resolver.setFlags(d->resolver.flags() | KResolver::NoResolve);
117 }
118 
119 void KServerSocket::setFamily(int families)
120 {
121  d->resolver.setFamily(families);
122 }
123 
124 void KServerSocket::setAddress(const QString& service)
125 {
126  d->resolver.setNodeName(QString());
127  d->resolver.setServiceName(service);
128  d->resolverResults.empty();
129  if (d->state <= KServerSocketPrivate::LookupDone)
130  d->state = KServerSocketPrivate::None;
131 }
132 
133 void KServerSocket::setAddress(const QString& node, const QString& service)
134 {
135  d->resolver.setNodeName(node);
136  d->resolver.setServiceName(service);
137  d->resolverResults.empty();
138  if (d->state <= KServerSocketPrivate::LookupDone)
139  d->state = KServerSocketPrivate::None;
140 }
141 
142 void KServerSocket::setTimeout(int msec)
143 {
144  d->timeout = msec;
145 }
146 
147 bool KServerSocket::lookup()
148 {
149  setError(NoError);
150  if (d->resolver.isRunning() && !blocking())
151  return true; // already doing lookup
152 
153  if (d->state >= KServerSocketPrivate::LookupDone)
154  return true; // results are already available
155 
156  // make sure we have at least one parameter for lookup
157  if (d->resolver.serviceName().isNull() &&
158  !d->resolver.nodeName().isNull())
159  d->resolver.setServiceName(QLatin1String(""));
160 
161  // don't restart the lookups if they had succeeded and
162  // the input values weren't changed
163 
164  // reset results
165  d->resolverResults = KResolverResults();
166 
167  if (d->resolver.status() <= 0)
168  // if it's already running, there's no harm in calling again
169  d->resolver.start(); // signal may emit
170 
171  if (blocking())
172  {
173  // we're in blocking mode operation
174  // wait for the results
175 
176  d->resolver.wait(); // signal may be emitted again
177  // lookupFinishedSlot has been called
178  }
179 
180  return true;
181 }
182 
183 bool KServerSocket::bind(const KResolverEntry& address)
184 {
185  if (socketDevice()->bind(address))
186  {
187  setError(NoError);
188 
189  d->state = KServerSocketPrivate::Bound;
190  emit bound(address);
191  return true;
192  }
193  copyError();
194  return false;
195 }
196 
197 bool KServerSocket::bind(const QString& node, const QString& service)
198 {
199  setAddress(node, service);
200  return bind();
201 }
202 
203 bool KServerSocket::bind(const QString& service)
204 {
205  setAddress(service);
206  return bind();
207 }
208 
209 bool KServerSocket::bind()
210 {
211  if (d->state >= KServerSocketPrivate::Bound)
212  return true;
213 
214  if (d->state < KServerSocketPrivate::LookupDone)
215  {
216  if (!blocking())
217  {
218  d->bindWhenFound = true;
219  bool ok = lookup(); // will call doBind
220  if (d->state >= KServerSocketPrivate::Bound)
221  d->bindWhenFound = false;
222  return ok;
223  }
224 
225  // not blocking
226  if (!lookup())
227  return false;
228  }
229 
230  return doBind();
231 }
232 
233 bool KServerSocket::listen(int backlog)
234 {
235  // WARNING
236  // this function has to be reentrant
237  // due to the mechanisms used for binding, this function might
238  // end up calling itself
239 
240  if (d->state == KServerSocketPrivate::Listening)
241  return true; // already listening
242 
243  d->backlog = backlog;
244 
245  if (d->state < KServerSocketPrivate::Bound)
246  {
247  // we must bind
248  // note that we can end up calling ourselves here
249  d->listenWhenBound = true;
250  if (!bind())
251  {
252  d->listenWhenBound = false;
253  return false;
254  }
255 
256  if (d->state < KServerSocketPrivate::Bound)
257  // asynchronous lookup in progress...
258  // we can't be blocking here anyways
259  return true;
260 
261  d->listenWhenBound = false;
262  }
263 
264  if (d->state < KServerSocketPrivate::Listening)
265  return doListen();
266 
267  return true;
268 }
269 
270 void KServerSocket::close()
271 {
272  socketDevice()->close();
273  if (d->resolver.isRunning())
274  d->resolver.cancel(false);
275  d->state = KServerSocketPrivate::None;
276  emit closed();
277 }
278 
279 void KServerSocket::setAcceptBuffered(bool enable)
280 {
281  d->useKBufferedSocket = enable;
282 }
283 
284 KStreamSocket* KServerSocket::accept()
285 {
286  if (d->state < KServerSocketPrivate::Listening)
287  {
288  if (!blocking())
289  {
290  listen();
291  setError(WouldBlock);
292  return NULL;
293  }
294  else if (!listen())
295  // error happened during listen
296  return NULL;
297  }
298 
299  // check to see if we're doing a timeout
300  if (blocking() && d->timeout > 0)
301  {
302  bool timedout;
303  if (!socketDevice()->poll(d->timeout, &timedout))
304  {
305  copyError();
306  return NULL;
307  }
308 
309  if (timedout)
310  return 0L;
311  }
312 
313  // we're listening here
314  KSocketDevice* accepted = socketDevice()->accept();
315  if (!accepted)
316  {
317  // error happened during accept
318  copyError();
319  return NULL;
320  }
321 
322  KStreamSocket* streamsocket;
323  if (d->useKBufferedSocket)
324  {
325  streamsocket = new KBufferedSocket();
326  streamsocket->setOpenMode(KStreamSocket::ReadWrite);
327  }
328  else
329  {
330  streamsocket = new KStreamSocket();
331  streamsocket->setOpenMode(KStreamSocket::ReadWrite |
332  KStreamSocket::Unbuffered);
333  }
334  streamsocket->setSocketDevice(accepted);
335 
336  // FIXME!
337  // when KStreamSocket can find out the state of the socket passed through
338  // setSocketDevice, this will probably be unnecessary:
339  streamsocket->setState(KStreamSocket::Connected);
340 
341  return streamsocket;
342 }
343 
344 KSocketAddress KServerSocket::localAddress() const
345 {
346  return socketDevice()->localAddress();
347 }
348 
349 KSocketAddress KServerSocket::externalAddress() const
350 {
351  return socketDevice()->externalAddress();
352 }
353 
354 void KServerSocket::lookupFinishedSlot()
355 {
356  if (d->resolver.isRunning() || d->state > KServerSocketPrivate::LookupDone)
357  return;
358 
359  if (d->resolver.status() < 0)
360  {
361  setError(LookupFailure);
362  emit gotError(LookupFailure);
363  d->bindWhenFound = d->listenWhenBound = false;
364  d->state = KServerSocketPrivate::None;
365  return;
366  }
367 
368  // lookup succeeded
369  d->resolverResults = d->resolver.results();
370  d->state = KServerSocketPrivate::LookupDone;
371  emit hostFound();
372 
373  if (d->bindWhenFound)
374  doBind();
375 }
376 
377 void KServerSocket::copyError()
378 {
379  setError(socketDevice()->error());
380 }
381 
382 bool KServerSocket::doBind()
383 {
384  d->bindWhenFound = false;
385  // loop through the results and bind to the first that works
386 
387  KResolverResults::ConstIterator it = d->resolverResults.constBegin();
388  for ( ; it != d->resolverResults.constEnd(); ++it)
389  if (bind(*it))
390  {
391  if (d->listenWhenBound)
392  return doListen();
393  return true;
394  }
395  else
396  socketDevice()->close(); // didn't work, try again
397 
398  // failed to bind
399  emit gotError(error());
400  return false;
401 }
402 
403 bool KServerSocket::doListen()
404 {
405  if (!socketDevice()->listen(d->backlog))
406  {
407  copyError();
408  emit gotError(error());
409  return false; // failed to listen
410  }
411 
412  // set up ready accept signal
413  QObject::connect(socketDevice()->readNotifier(), SIGNAL(activated(int)),
414  this, SIGNAL(readyAccept()));
415  d->state = KServerSocketPrivate::Listening;
416  return true;
417 }
418 
419 
420 #include "k3serversocket.moc"
k3socketaddress.h
KNetwork::KServerSocket::externalAddress
virtual KSocketAddress externalAddress() const
Returns this socket's externally-visible address if know.
Definition: k3serversocket.cpp:349
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::KStreamSocket
Simple stream socket.
Definition: k3streamsocket.h:98
k3socketdevice.h
KNetwork::KServerSocket::localAddress
virtual KSocketAddress localAddress() const
Returns this socket's local address.
Definition: k3serversocket.cpp:344
KNetwork::KServerSocket::resolverResults
const KResolverResults & resolverResults() const
Returns the internal list of resolved results for the binding address.
Definition: k3serversocket.cpp:106
KNetwork::KSocketDevice::accept
virtual KSocketDevice * accept()
Accepts a new incoming connection.
Definition: k3socketdevice.cpp:382
timeout
int timeout
Definition: kkernel_mac.cpp:46
KNetwork::KResolverEntry
One resolution entry.
Definition: k3resolver.h:68
k3serversocket.h
KNetwork::KResolver
Name and service resolution class.
Definition: k3resolver.h:312
KNetwork::KServerSocket::bound
void bound(const KNetwork::KResolverEntry &local)
This signal is emitted when the socket successfully binds to an address.
KNetwork::KSocketBase::error
SocketError error() const
Retrieves the socket error code.
Definition: k3socketbase.cpp:197
KNetwork::KSocketAddress
A generic socket address.
Definition: k3socketaddress.h:414
KNetwork::KSocketBase::LookupFailure
Definition: k3socketbase.h:146
KNetwork::KServerSocket::listen
virtual bool listen(int backlog=5)
Puts this socket into listening mode.
Definition: k3serversocket.cpp:233
KNetwork::KServerSocket::setAddress
void setAddress(const QString &service)
Sets the address on which we will listen.
Definition: k3serversocket.cpp:124
KNetwork::KResolverResults
Name and service resolution results.
Definition: k3resolver.h:212
KNetwork::KSocketDevice::setSocketOptions
virtual bool setSocketOptions(int opts)
This implementation sets the options on the socket.
Definition: k3socketdevice.cpp:137
k3bufferedsocket.h
KNetwork::KServerSocket::~KServerSocket
~KServerSocket()
Destructor.
Definition: k3serversocket.cpp:86
Kuit::Tag::None
Definition: kuitsemantics.cpp:82
KNetwork::KSocketBase::WouldBlock
Definition: k3socketbase.h:154
KNetwork::KServerSocket::gotError
void gotError(int code)
This signal is emitted when this object finds an error.
QObject
KNetwork::KSocketBase::mutex
QMutex * mutex() const
Returns the internal mutex for this class.
Definition: k3socketbase.cpp:320
KNetwork::KSocketBase::setError
void setError(SocketError error)
Sets the socket's error code.
Definition: k3socketbase.cpp:187
KNetwork::KSocketBase::NoError
Definition: k3socketbase.h:145
KNetwork::KServerSocket::KServerSocket
KServerSocket(QObject *parent=0L)
Default constructor.
Definition: k3serversocket.cpp:62
KNetwork::KBufferedSocket
Buffered stream sockets.
Definition: k3bufferedsocket.h:58
KNetwork::KServerSocket::setResolutionEnabled
void setResolutionEnabled(bool enable)
Enables or disables name resolution.
Definition: k3serversocket.cpp:111
QString
KNetwork::KServerSocket::setTimeout
void setTimeout(int msecs)
Sets the timeout for accepting.
Definition: k3serversocket.cpp:142
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::KSocketBase::setSocketOptions
virtual bool setSocketOptions(int opts)
Set the given socket options.
Definition: k3socketbase.cpp:86
k3resolver.h
KNetwork::KServerSocket::closed
void closed()
This signal is emitted when the socket completes the closing/shut down process.
KNetwork::KActiveSocketBase::setSocketDevice
virtual void setSocketDevice(KSocketDevice *device)
Definition: k3socketbase.cpp:347
KNetwork::KServerSocket::hostFound
void hostFound()
This signal is emitted when the lookup is successfully completed.
k3socketbase.h
KNetwork::KServerSocket::bind
virtual bool bind()
Binds the socket to the addresses previously set with setAddress().
Definition: k3serversocket.cpp:209
KNetwork::KSocketDevice::close
virtual void close()
Closes the socket.
Definition: k3socketdevice.cpp:232
QLatin1String
QMutexLocker
KNetwork::KServerSocket::accept
virtual KStreamSocket * accept()
Accepts one incoming connection and return the associated, open socket.
Definition: k3serversocket.cpp:284
KNetwork::KSocketDevice::localAddress
virtual KSocketAddress localAddress() const
Returns this socket's local address.
Definition: k3socketdevice.cpp:568
KNetwork::KResolver::Passive
Definition: k3resolver.h:369
QList< KResolverEntry >::ConstIterator
typedef ConstIterator
KNetwork::KServerSocket::close
virtual void close()
Closes this socket.
Definition: k3serversocket.cpp:270
KNetwork::KServerSocket::readyAccept
void readyAccept()
This signal is emitted whenever the socket is ready for accepting – i.e., there is at least one conn...
KNetwork::KServerSocket::copyError
void copyError()
Convenience function to set this object's error code to match that of the socket device.
Definition: k3serversocket.cpp:377
KNetwork::KSocketDevice
Low-level socket functionality.
Definition: k3socketdevice.h:51
KNetwork::KServerSocket::setAcceptBuffered
void setAcceptBuffered(bool enable)
Toggles whether the accepted socket will be buffered or not.
Definition: k3serversocket.cpp:279
KNetwork::KServerSocket::setFamily
void setFamily(int families)
Sets the allowed families for the resolutions.
Definition: k3serversocket.cpp:119
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QIODevice::setOpenMode
void setOpenMode(QFlags< QIODevice::OpenModeFlag > openMode)
KNetwork::KServerSocket::resolver
KResolver & resolver() const
Returns the internal KResolver object used for looking up the host name and service.
Definition: k3serversocket.cpp:101
KNetwork::KServerSocket::setSocketOptions
virtual bool setSocketOptions(int opts)
Sets the socket options.
Definition: k3serversocket.cpp:92
KNetwork::KSocketDevice::externalAddress
virtual KSocketAddress externalAddress() const
Returns this socket's externally visible local address.
Definition: k3socketdevice.cpp:640
KNetwork::KServerSocket::lookup
virtual bool lookup()
Starts the lookup for peer and local hostnames as well as their services.
Definition: k3serversocket.cpp:147
KNetwork::KResolver::NoResolve
Definition: k3resolver.h:371
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