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

KDECore

  • kdecore
  • network
k3clientsocketbase.cpp
Go to the documentation of this file.
1 /* -*- C++ -*-
2  * Copyright (C) 2003,2005 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 "k3clientsocketbase.h"
26 
27 #include <config.h>
28 #include <config-network.h>
29 
30 #include <QSocketNotifier>
31 #include <QTimer>
32 #include <QMutex>
33 
34 #include "k3socketaddress.h"
35 #include "k3resolver.h"
36 #include "k3socketbase.h"
37 #include "k3socketdevice.h"
38 
39 using namespace KNetwork;
40 
41 class KNetwork::KClientSocketBasePrivate
42 {
43 public:
44  int state;
45 
46  KResolver localResolver, peerResolver;
47  KResolverResults localResults, peerResults;
48 
49  bool enableRead : 1, enableWrite : 1;
50 };
51 
52 KClientSocketBase::KClientSocketBase(QObject *parent)
53  : KActiveSocketBase(parent), d(new KClientSocketBasePrivate)
54 {
55  d->state = Idle;
56  d->enableRead = true;
57  d->enableWrite = false;
58 }
59 
60 KClientSocketBase::~KClientSocketBase()
61 {
62  close();
63  delete d;
64 }
65 
66 KClientSocketBase::SocketState KClientSocketBase::state() const
67 {
68  return static_cast<SocketState>(d->state);
69 }
70 
71 void KClientSocketBase::setState(SocketState state)
72 {
73  d->state = state;
74  stateChanging(state);
75 }
76 
77 bool KClientSocketBase::setSocketOptions(int opts)
78 {
79  QMutexLocker locker(mutex());
80  KSocketBase::setSocketOptions(opts); // call parent
81 
82  // don't create the device unnecessarily
83  if (hasDevice())
84  {
85  bool result = socketDevice()->setSocketOptions(opts); // and set the implementation
86  copyError();
87  return result;
88  }
89 
90  return true;
91 }
92 
93 KResolver& KClientSocketBase::peerResolver() const
94 {
95  return d->peerResolver;
96 }
97 
98 const KResolverResults& KClientSocketBase::peerResults() const
99 {
100  return d->peerResults;
101 }
102 
103 KResolver& KClientSocketBase::localResolver() const
104 {
105  return d->localResolver;
106 }
107 
108 const KResolverResults& KClientSocketBase::localResults() const
109 {
110  return d->localResults;
111 }
112 
113 void KClientSocketBase::setResolutionEnabled(bool enable)
114 {
115  if (enable)
116  {
117  d->localResolver.setFlags(d->localResolver.flags() & ~KResolver::NoResolve);
118  d->peerResolver.setFlags(d->peerResolver.flags() & ~KResolver::NoResolve);
119  }
120  else
121  {
122  d->localResolver.setFlags(d->localResolver.flags() | KResolver::NoResolve);
123  d->peerResolver.setFlags(d->peerResolver.flags() | KResolver::NoResolve);
124  }
125 }
126 
127 void KClientSocketBase::setFamily(int families)
128 {
129  d->localResolver.setFamily(families);
130  d->peerResolver.setFamily(families);
131 }
132 
133 bool KClientSocketBase::lookup()
134 {
135  if (state() == HostLookup && !blocking())
136  return true; // already doing lookup
137 
138  if (state() > HostLookup)
139  return true; // results are already available
140 
141  if (state() < HostLookup)
142  {
143  if (d->localResolver.serviceName().isNull() &&
144  !d->localResolver.nodeName().isNull())
145  d->localResolver.setServiceName(QLatin1String(""));
146 
147  // don't restart the lookups if they had succeeded and
148  // the input values weren't changed
149  QObject::connect(&d->peerResolver,
150  SIGNAL(finished(KNetwork::KResolverResults)),
151  this, SLOT(lookupFinishedSlot()));
152  QObject::connect(&d->localResolver,
153  SIGNAL(finished(KNetwork::KResolverResults)),
154  this, SLOT(lookupFinishedSlot()));
155 
156  if (d->localResolver.status() <= 0)
157  d->localResolver.start();
158  if (d->peerResolver.status() <= 0)
159  d->peerResolver.start();
160 
161  setState(HostLookup);
162  emit stateChanged(HostLookup);
163 
164  if (!d->localResolver.isRunning() && !d->peerResolver.isRunning())
165  {
166  // if nothing is running, then the lookup results are still valid
167  // pretend we had done lookup
168  if (blocking())
169  lookupFinishedSlot();
170  else
171  QTimer::singleShot(0, this, SLOT(lookupFinishedSlot()));
172  }
173  else
174  {
175  d->localResults = d->peerResults = KResolverResults();
176  }
177  }
178 
179  if (blocking())
180  {
181  // we're in blocking mode operation
182  // wait for the results
183 
184  localResolver().wait();
185  peerResolver().wait();
186 
187  // lookupFinishedSlot has been called
188  }
189 
190  return true;
191 }
192 
193 bool KClientSocketBase::bind(const KResolverEntry& address)
194 {
195  if (state() == HostLookup || state() > Connecting)
196  return false;
197 
198  if (socketDevice()->bind(address))
199  {
200  resetError();
201 
202  // don't set the state or emit signals if we are in a higher state
203  if (state() < Bound)
204  {
205  setState(Bound);
206  emit stateChanged(Bound);
207  emit bound(address);
208  }
209  return true;
210  }
211  return false;
212 }
213 
214 bool KClientSocketBase::connect(const KResolverEntry& address, OpenMode mode)
215 {
216  if (state() == Connected)
217  return true; // to be compliant with the other classes
218  if (state() == HostLookup || state() > Connecting)
219  return false;
220 
221  bool ok = socketDevice()->connect(address);
222  copyError();
223 
224  if (ok)
225  {
226  SocketState newstate;
227  if (error() == InProgress)
228  newstate = Connecting;
229  else
230  newstate = Connected;
231 
232  if (state() < newstate)
233  {
234  setState(newstate);
235  emit stateChanged(newstate);
236  if (error() == NoError)
237  {
238  KActiveSocketBase::open(mode | Unbuffered);
239  emit connected(address);
240  }
241  }
242 
243  return true;
244  }
245  return false;
246 }
247 
248 bool KClientSocketBase::disconnect()
249 {
250  if (state() != Connected)
251  return false;
252 
253  bool ok = socketDevice()->disconnect();
254  copyError();
255 
256  if (ok)
257  {
258  setState(Unconnected);
259  emit stateChanged(Unconnected);
260  return true;
261  }
262  return false;
263 }
264 
265 bool KClientSocketBase::open(OpenMode mode)
266 {
267  return connect(QString(), QString(), mode);
268 }
269 
270 void KClientSocketBase::close()
271 {
272  if (state() == Idle)
273  return; // nothing to do
274 
275  if (state() == HostLookup)
276  {
277  d->peerResolver.cancel(false);
278  d->localResolver.cancel(false);
279  }
280 
281  d->localResults = d->peerResults = KResolverResults();
282 
283  socketDevice()->close();
284  KActiveSocketBase::close();
285  setState(Idle);
286  emit stateChanged(Idle);
287  emit closed();
288 }
289 
290 bool KClientSocketBase::flush()
291 {
292  return false;
293 }
294 
295 // This function is unlike all the others because it is const
296 qint64 KClientSocketBase::bytesAvailable() const
297 {
298  return socketDevice()->bytesAvailable();
299 }
300 
301 // All the functions below look really alike
302 // Should I use a macro to define them?
303 
304 qint64 KClientSocketBase::waitForMore(int msecs, bool *timeout)
305 {
306  resetError();
307  qint64 retval = socketDevice()->waitForMore(msecs, timeout);
308  if (retval == -1)
309  {
310  copyError();
311  emit gotError(error());
312  }
313  return retval;
314 }
315 
316 qint64 KClientSocketBase::readData(char *data, qint64 maxlen, KSocketAddress* from)
317 {
318  resetError();
319  qint64 retval = socketDevice()->readData(data, maxlen, from);
320  if (retval == -1)
321  {
322  copyError();
323  emit gotError(error());
324  }
325  return retval;
326 }
327 
328 qint64 KClientSocketBase::peekData(char *data, qint64 maxlen, KSocketAddress* from)
329 {
330  resetError();
331  qint64 retval = socketDevice()->peekData(data, maxlen, from);
332  if (retval == -1)
333  {
334  copyError();
335  emit gotError(error());
336  }
337  return retval;
338 }
339 
340 qint64 KClientSocketBase::writeData(const char *data, qint64 len, const KSocketAddress* to)
341 {
342  resetError();
343  qint64 retval = socketDevice()->writeData(data, len, to);
344  if (retval == -1)
345  {
346  copyError();
347  emit gotError(error());
348  }
349  else
350  emit bytesWritten(retval);
351  return retval;
352 }
353 
354 KSocketAddress KClientSocketBase::localAddress() const
355 {
356  return socketDevice()->localAddress();
357 }
358 
359 KSocketAddress KClientSocketBase::peerAddress() const
360 {
361  return socketDevice()->peerAddress();
362 }
363 
364 bool KClientSocketBase::emitsReadyRead() const
365 {
366  return d->enableRead;
367 }
368 
369 void KClientSocketBase::enableRead(bool enable)
370 {
371  QMutexLocker locker(mutex());
372 
373  d->enableRead = enable;
374  QSocketNotifier *n = socketDevice()->readNotifier();
375  if (n)
376  n->setEnabled(enable);
377 }
378 
379 bool KClientSocketBase::emitsReadyWrite() const
380 {
381  return d->enableWrite;
382 }
383 
384 void KClientSocketBase::enableWrite(bool enable)
385 {
386  QMutexLocker locker(mutex());
387 
388  d->enableWrite = enable;
389  QSocketNotifier *n = socketDevice()->writeNotifier();
390  if (n)
391  n->setEnabled(enable);
392 }
393 
394 void KClientSocketBase::slotReadActivity()
395 {
396  if (d->enableRead)
397  emit readyRead();
398 }
399 
400 void KClientSocketBase::slotWriteActivity()
401 {
402  if (d->enableWrite)
403  emit readyWrite();
404 }
405 
406 void KClientSocketBase::lookupFinishedSlot()
407 {
408  if (d->peerResolver.isRunning() || d->localResolver.isRunning() || state() != HostLookup)
409  return;
410 
411  QObject::disconnect(&d->peerResolver, 0L, this, SLOT(lookupFinishedSlot()));
412  QObject::disconnect(&d->localResolver, 0L, this, SLOT(lookupFinishedSlot()));
413  if (d->peerResolver.status() < 0 || d->localResolver.status() < 0)
414  {
415  setState(Idle); // backtrack
416  setError(LookupFailure);
417  emit stateChanged(Idle);
418  emit gotError(LookupFailure);
419  return;
420  }
421 
422  d->localResults = d->localResolver.results();
423  d->peerResults = d->peerResolver.results();
424  setState(HostFound);
425  emit stateChanged(HostFound);
426  emit hostFound();
427 }
428 
429 void KClientSocketBase::stateChanging(SocketState newState)
430 {
431  if (newState == Connected && socketDevice())
432  {
433  QSocketNotifier *n = socketDevice()->readNotifier();
434  if (n)
435  {
436  n->setEnabled(d->enableRead);
437  QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotReadActivity()));
438  }
439  else
440  return;
441 
442  n = socketDevice()->writeNotifier();
443  if (n)
444  {
445  n->setEnabled(d->enableWrite);
446  QObject::connect(n, SIGNAL(activated(int)), this, SLOT(slotWriteActivity()));
447  }
448  else
449  return;
450  }
451 }
452 
453 void KClientSocketBase::copyError()
454 {
455  setError(socketDevice()->error());
456 }
457 
458 #include "k3clientsocketbase.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jun 1 2013 21:52:33 by doxygen 1.8.3.1 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.10.4 API Reference

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