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

KDECore

  • 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
39using namespace KNetwork;
40
41class KNetwork::KServerSocketPrivate
42{
43public:
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
62KServerSocket::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
69KServerSocket::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
77KServerSocket::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
86KServerSocket::~KServerSocket()
87{
88 close();
89 delete d;
90}
91
92bool 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
101KResolver& KServerSocket::resolver() const
102{
103 return d->resolver;
104}
105
106const KResolverResults& KServerSocket::resolverResults() const
107{
108 return d->resolverResults;
109}
110
111void 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
119void KServerSocket::setFamily(int families)
120{
121 d->resolver.setFamily(families);
122}
123
124void 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
133void 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
142void KServerSocket::setTimeout(int msec)
143{
144 d->timeout = msec;
145}
146
147bool 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
183bool 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
197bool KServerSocket::bind(const QString& node, const QString& service)
198{
199 setAddress(node, service);
200 return bind();
201}
202
203bool KServerSocket::bind(const QString& service)
204{
205 setAddress(service);
206 return bind();
207}
208
209bool 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
233bool 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
270void 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
279void KServerSocket::setAcceptBuffered(bool enable)
280{
281 d->useKBufferedSocket = enable;
282}
283
284KStreamSocket* 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
344KSocketAddress KServerSocket::localAddress() const
345{
346 return socketDevice()->localAddress();
347}
348
349KSocketAddress KServerSocket::externalAddress() const
350{
351 return socketDevice()->externalAddress();
352}
353
354void 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
377void KServerSocket::copyError()
378{
379 setError(socketDevice()->error());
380}
381
382bool 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
403bool 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"
KNetwork::KActiveSocketBase::setSocketDevice
virtual void setSocketDevice(KSocketDevice *device)
Definition: k3socketbase.cpp:347
KNetwork::KBufferedSocket
Buffered stream sockets.
Definition: k3bufferedsocket.h:59
KNetwork::KClientSocketBase::Connected
@ Connected
Definition: k3clientsocketbase.h:83
KNetwork::KClientSocketBase::setState
void setState(SocketState state)
Sets the socket state to state.
Definition: k3clientsocketbase.cpp:71
KNetwork::KResolverEntry
One resolution entry.
Definition: k3resolver.h:69
KNetwork::KResolverResults
Name and service resolution results.
Definition: k3resolver.h:213
KNetwork::KResolver
Name and service resolution class.
Definition: k3resolver.h:313
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::Passive
@ Passive
Definition: k3resolver.h:369
KNetwork::KResolver::NoResolve
@ NoResolve
Definition: k3resolver.h:371
KNetwork::KResolver::setFlags
int setFlags(int flags)
Sets the flags.
Definition: k3resolver.cpp:373
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::setAcceptBuffered
void setAcceptBuffered(bool enable)
Toggles whether the accepted socket will be buffered or not.
Definition: k3serversocket.cpp:279
KNetwork::KServerSocket::KServerSocket
KServerSocket(QObject *parent=0L)
Default constructor.
Definition: k3serversocket.cpp:62
KNetwork::KServerSocket::~KServerSocket
~KServerSocket()
Destructor.
Definition: k3serversocket.cpp:86
KNetwork::KServerSocket::closed
void closed()
This signal is emitted when the socket completes the closing/shut down process.
KNetwork::KServerSocket::lookup
virtual bool lookup()
Starts the lookup for peer and local hostnames as well as their services.
Definition: k3serversocket.cpp:147
KNetwork::KServerSocket::readyAccept
void readyAccept()
This signal is emitted whenever the socket is ready for accepting – i.e., there is at least one conne...
KNetwork::KServerSocket::externalAddress
virtual KSocketAddress externalAddress() const
Returns this socket's externally-visible address if know.
Definition: k3serversocket.cpp:349
KNetwork::KServerSocket::close
virtual void close()
Closes this socket.
Definition: k3serversocket.cpp:270
KNetwork::KServerSocket::setAddress
void setAddress(const QString &service)
Sets the address on which we will listen.
Definition: k3serversocket.cpp:124
KNetwork::KServerSocket::resolverResults
const KResolverResults & resolverResults() const
Returns the internal list of resolved results for the binding address.
Definition: k3serversocket.cpp:106
KNetwork::KServerSocket::setTimeout
void setTimeout(int msecs)
Sets the timeout for accepting.
Definition: k3serversocket.cpp:142
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::KServerSocket::bind
virtual bool bind()
Binds the socket to the addresses previously set with setAddress().
Definition: k3serversocket.cpp:209
KNetwork::KServerSocket::localAddress
virtual KSocketAddress localAddress() const
Returns this socket's local address.
Definition: k3serversocket.cpp:344
KNetwork::KServerSocket::listen
virtual bool listen(int backlog=5)
Puts this socket into listening mode.
Definition: k3serversocket.cpp:233
KNetwork::KServerSocket::setResolutionEnabled
void setResolutionEnabled(bool enable)
Enables or disables name resolution.
Definition: k3serversocket.cpp:111
KNetwork::KServerSocket::accept
virtual KStreamSocket * accept()
Accepts one incoming connection and return the associated, open socket.
Definition: k3serversocket.cpp:284
KNetwork::KServerSocket::hostFound
void hostFound()
This signal is emitted when the lookup is successfully completed.
KNetwork::KServerSocket::bound
void bound(const KNetwork::KResolverEntry &local)
This signal is emitted when the socket successfully binds to an address.
KNetwork::KServerSocket::setSocketOptions
virtual bool setSocketOptions(int opts)
Sets the socket options.
Definition: k3serversocket.cpp:92
KNetwork::KServerSocket::gotError
void gotError(int code)
This signal is emitted when this object finds an error.
KNetwork::KServerSocket::setFamily
void setFamily(int families)
Sets the allowed families for the resolutions.
Definition: k3serversocket.cpp:119
KNetwork::KSocketAddress
A generic socket address.
Definition: k3socketaddress.h:415
KNetwork::KSocketBase::setSocketOptions
virtual bool setSocketOptions(int opts)
Set the given socket options.
Definition: k3socketbase.cpp:86
KNetwork::KSocketBase::NoError
@ NoError
Definition: k3socketbase.h:145
KNetwork::KSocketBase::LookupFailure
@ LookupFailure
Definition: k3socketbase.h:146
KNetwork::KSocketBase::WouldBlock
@ WouldBlock
Definition: k3socketbase.h:154
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::socketDevice
KSocketDevice * socketDevice() const
Retrieves the socket implementation used on this socket.
Definition: k3socketbase.cpp:148
KNetwork::KSocketBase::setError
void setError(SocketError error)
Sets the socket's error code.
Definition: k3socketbase.cpp:187
KNetwork::KSocketBase::mutex
QMutex * mutex() const
Returns the internal mutex for this class.
Definition: k3socketbase.cpp:320
KNetwork::KSocketDevice
Low-level socket functionality.
Definition: k3socketdevice.h:52
KNetwork::KSocketDevice::setSocketOptions
virtual bool setSocketOptions(int opts)
This implementation sets the options on the socket.
Definition: k3socketdevice.cpp:137
KNetwork::KSocketDevice::accept
virtual KSocketDevice * accept()
Accepts a new incoming connection.
Definition: k3socketdevice.cpp:382
KNetwork::KSocketDevice::close
virtual void close()
Closes the socket.
Definition: k3socketdevice.cpp:232
KNetwork::KSocketDevice::externalAddress
virtual KSocketAddress externalAddress() const
Returns this socket's externally visible local address.
Definition: k3socketdevice.cpp:640
KNetwork::KSocketDevice::localAddress
virtual KSocketAddress localAddress() const
Returns this socket's local address.
Definition: k3socketdevice.cpp:568
KNetwork::KStreamSocket
Simple stream socket.
Definition: k3streamsocket.h:99
QObject
QString
k3bufferedsocket.h
k3resolver.h
k3serversocket.h
k3socketaddress.h
k3socketbase.h
k3socketdevice.h
timeout
int timeout
Definition: kkernel_mac.cpp:46
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: k3bufferedsocket.h:35
Kuit::Tag::None
@ None
Definition: kuitsemantics.cpp:82
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