• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
  • network
kstreamsocket.cpp
1 /*
2  * Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net>
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 <config.h>
26 
27 #include <tqsocketnotifier.h>
28 #include <tqdatetime.h>
29 #include <tqtimer.h>
30 #include <tqguardedptr.h>
31 
32 #include "tdesocketaddress.h"
33 #include "kresolver.h"
34 #include "tdesocketdevice.h"
35 #include "kstreamsocket.h"
36 
37 using namespace KNetwork;
38 
39 class KNetwork::KStreamSocketPrivate
40 {
41 public:
42  KResolverResults::ConstIterator local, peer;
43  TQTime startTime;
44  TQTimer timer;
45 
46  int timeout;
47 
48  inline KStreamSocketPrivate()
49  : timeout(0)
50  { }
51 };
52 
53 KStreamSocket::KStreamSocket(const TQString& node, const TQString& service,
54  TQObject* parent, const char *name)
55  : KClientSocketBase(parent, name), d(new KStreamSocketPrivate)
56 {
57  peerResolver().setNodeName(node);
58  peerResolver().setServiceName(service);
59  peerResolver().setFamily(KResolver::KnownFamily);
60  localResolver().setFamily(KResolver::KnownFamily);
61 
62  setSocketOptions(socketOptions() & ~Blocking);
63 
64  TQObject::connect(&d->timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(timeoutSlot()));
65 }
66 
67 KStreamSocket::~KStreamSocket()
68 {
69  delete d;
70  // KClientSocketBase's destructor closes the socket
71 }
72 
73 int KStreamSocket::timeout() const
74 {
75  return d->timeout;
76 }
77 
78 int KStreamSocket::remainingTimeout() const
79 {
80  if (state() != Connecting)
81  return timeout();
82  if (timeout() <= 0)
83  return 0;
84 
85  return timeout() - d->startTime.elapsed();
86 }
87 
88 void KStreamSocket::setTimeout(int msecs)
89 {
90  d->timeout = msecs;
91 
92  if (state() == Connecting)
93  d->timer.changeInterval(msecs);
94 }
95 
96 bool KStreamSocket::bind(const TQString& node, const TQString& service)
97 {
98  if (state() != Idle)
99  return false;
100 
101  if (!node.isNull())
102  localResolver().setNodeName(node);
103  if (!service.isNull())
104  localResolver().setServiceName(service);
105  return true;
106 }
107 
108 bool KStreamSocket::connect(const TQString& node, const TQString& service)
109 {
110  if (state() == Connected)
111  return true; // already connected
112 
113  if (state() > Connected)
114  return false; // can't do much here
115 
116  if (!node.isNull())
117  peerResolver().setNodeName(node);
118  if (!service.isNull())
119  peerResolver().setServiceName(service);
120 
121  if (state() == Connecting && !blocking())
122  {
123  setError(IO_ConnectError, InProgress);
124  emit gotError(InProgress);
125  return true; // we're already connecting
126  }
127 
128  if (state() < HostFound)
129  {
130  // connection hasn't started yet
131  if (!blocking())
132  {
133  TQObject::connect(this, TQ_SIGNAL(hostFound()), TQ_SLOT(hostFoundSlot()));
134  return lookup();
135  }
136 
137  // blocking mode
138  if (!lookup())
139  return false; // lookup failure
140  }
141 
142  /*
143  * lookup results are available here
144  */
145 
146  if (timeout() > 0)
147  {
148  if (!blocking() && !d->timer.isActive())
149  d->timer.start(timeout(), true);
150  else
151  {
152  // blocking connection with timeout
153  // this must be handled as a special case because it requires a
154  // non-blocking socket
155 
156  d->timer.stop(); // no need for a timer here
157 
158  socketDevice()->setBlocking(false);
159  while (true)
160  {
161  connectionEvent();
162  if (state() < Connecting)
163  return false; // error connecting
164  if (state() == Connected)
165  return true; // connected!
166 
167  if (remainingTimeout() <= 0)
168  {
169  // we've timed out
170  timeoutSlot();
171  return false;
172  }
173 
174  if (socketDevice()->error() == InProgress)
175  {
176  bool timedout;
177  socketDevice()->poll(remainingTimeout(), &timedout);
178  if (timedout)
179  {
180  timeoutSlot();
181  return false;
182  }
183  }
184  }
185  }
186  }
187 
188  connectionEvent();
189  return error() == NoError;
190 }
191 
192 bool KStreamSocket::connect(const KResolverEntry& entry)
193 {
194  return KClientSocketBase::connect(entry);
195 }
196 
197 void KStreamSocket::hostFoundSlot()
198 {
199  TQObject::disconnect(this, TQ_SLOT(hostFoundSlot()));
200  if (timeout() > 0)
201  d->timer.start(timeout(), true);
202  TQTimer::singleShot(0, this, TQ_SLOT(connectionEvent()));
203 }
204 
205 void KStreamSocket::connectionEvent()
206 {
207  if (state() != HostFound && state() != Connecting)
208  return; // nothing to do
209 
210  const KResolverResults& peer = peerResults();
211  if (state() == HostFound)
212  {
213  d->startTime.start();
214 
215  setState(Connecting);
216  emit stateChanged(Connecting);
217  d->peer = peer.begin();
218  d->local = localResults().begin(); // just to be on the safe side
219  }
220 
221  while (d->peer != peer.end())
222  {
223  const KResolverEntry &r = *d->peer;
224 
225  if (socketDevice()->socket() != -1)
226  {
227  // we have an existing file descriptor
228  // this means that we've got activity in it (connection result)
229  if (socketDevice()->connect(r) && socketDevice()->error() == NoError)
230  {
231  // yes, it did connect!
232  connectionSucceeded(r);
233  return;
234  }
235  else if (socketDevice()->error() == InProgress)
236  // nope, still in progress
237  return;
238 
239  // no, the socket failed to connect
240  copyError();
241  socketDevice()->close();
242  ++d->peer;
243  continue;
244  }
245 
246  // try to bind
247  if (!bindLocallyFor(r))
248  {
249  // could not find a matching family
250  ++d->peer;
251  continue;
252  }
253 
254  {
255  bool skip = false;
256  emit aboutToConnect(r, skip);
257  if (skip)
258  {
259  ++d->peer;
260  continue;
261  }
262  }
263 
264  if (socketDevice()->connect(r) || socketDevice()->error() == InProgress)
265  {
266  // socket is attempting to connect
267  if (socketDevice()->error() == InProgress)
268  {
269  TQSocketNotifier *n = socketDevice()->readNotifier();
270  TQObject::connect(n, TQ_SIGNAL(activated(int)),
271  this, TQ_SLOT(connectionEvent()));
272  n->setEnabled(true);
273 
274  n = socketDevice()->writeNotifier();
275  TQObject::connect(n, TQ_SIGNAL(activated(int)),
276  this, TQ_SLOT(connectionEvent()));
277  n->setEnabled(true);
278 
279  return; // wait for activity
280  }
281 
282  // socket has connected
283  connectionSucceeded(r);
284  return;
285  }
286 
287  // connection failed
288  // try next
289  copyError();
290  socketDevice()->close();
291  ++d->peer;
292  }
293 
294  // that was the last item
295  socketDevice()->setSocketOptions(socketOptions());
296  setState(Idle);
297  emit stateChanged(Idle);
298  emit gotError(error());
299  return;
300 }
301 
302 void KStreamSocket::timeoutSlot()
303 {
304  if (state() != Connecting)
305  return;
306 
307  // halt the connections
308  socketDevice()->close(); // this also kills the notifiers
309 
310  setError(IO_TimeOutError, Timeout);
311  setState(HostFound);
312  emit stateChanged(HostFound);
313 
314  TQGuardedPtr<KStreamSocket> that = this;
315  emit gotError(Timeout);
316  if (!that.isNull())
317  emit timedOut();
318 }
319 
320 bool KStreamSocket::bindLocallyFor(const KResolverEntry& peer)
321 {
322  const KResolverResults& local = localResults();
323 
324  if (local.isEmpty())
325  // user doesn't want to bind to any specific local address
326  return true;
327 
328  bool foundone = false;
329  // scan the local resolution for a matching family
330  for (d->local = local.begin(); d->local != local.end(); ++d->local)
331  if ((*d->local).family() == peer.family())
332  {
333  // found a suitable address!
334  foundone = true;
335 
336  if (socketDevice()->bind(*d->local))
337  return true;
338  }
339 
340  if (!foundone)
341  {
342  // found nothing
343  setError(IO_BindError, NotSupported);
344  emit gotError(NotSupported);
345  }
346  else
347  copyError();
348  return false;
349 }
350 
351 void KStreamSocket::connectionSucceeded(const KResolverEntry& peer)
352 {
353  TQObject::disconnect(socketDevice()->readNotifier(), 0, this, TQ_SLOT(connectionEvent()));
354  TQObject::disconnect(socketDevice()->writeNotifier(), 0, this, TQ_SLOT(connectionEvent()));
355 
356  resetError();
357  setFlags(IO_Sequential | IO_Raw | IO_ReadWrite | IO_Open | IO_Async);
358  setState(Connected);
359  socketDevice()->setSocketOptions(socketOptions());
360  d->timer.stop();
361  emit stateChanged(Connected);
362 
363  if (!localResults().isEmpty())
364  emit bound(*d->local);
365  emit connected(peer);
366 }
367 
368 #include "kstreamsocket.moc"
KNetwork::KActiveSocketBase::setError
void setError(int status, SocketError error)
Sets the socket's error code and the I/O Device's status.
Definition: tdesocketbase.cpp:309
KNetwork::KActiveSocketBase::resetError
void resetError()
Resets the socket error code and the I/O Device's status.
Definition: tdesocketbase.cpp:315
KNetwork::KClientSocketBase
Abstract client socket class.
Definition: kclientsocketbase.h:50
KNetwork::KClientSocketBase::connected
void connected(const KResolverEntry &remote)
This socket is emitted when the socket successfully connects to a remote address.
KNetwork::KClientSocketBase::localResults
const KResolverResults & localResults() const
Returns the internal list of resolved results for the local address.
Definition: kclientsocketbase.cpp:106
KNetwork::KClientSocketBase::setState
void setState(SocketState state)
Sets the socket state to state.
Definition: kclientsocketbase.cpp:69
KNetwork::KClientSocketBase::state
SocketState state() const
Returns the current state for this socket.
Definition: kclientsocketbase.cpp:64
KNetwork::KClientSocketBase::bound
void bound(const KResolverEntry &local)
This signal is emitted when the socket successfully binds to an address.
KNetwork::KClientSocketBase::connect
virtual bool connect(const TQString &node=TQString::null, const TQString &service=TQString::null)=0
Attempts to connect to the these hostname and service, or use the default ones if none are given.
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: kclientsocketbase.cpp:131
KNetwork::KClientSocketBase::aboutToConnect
void aboutToConnect(const KResolverEntry &remote, bool &skip)
This signal is emitted when the socket is about to connect to an address (but before doing so).
KNetwork::KClientSocketBase::peerResolver
KResolver & peerResolver() const
Returns the internal KResolver object used for looking up the peer host name and service.
Definition: kclientsocketbase.cpp:91
KNetwork::KClientSocketBase::copyError
void copyError()
Convenience function to set this object's error code to match that of the socket device.
Definition: kclientsocketbase.cpp:472
KNetwork::KClientSocketBase::hostFound
void hostFound()
This signal is emitted when the lookup is successfully completed.
KNetwork::KClientSocketBase::setSocketOptions
virtual bool setSocketOptions(int opts)
Sets the socket options.
Definition: kclientsocketbase.cpp:75
KNetwork::KClientSocketBase::peerResults
const KResolverResults & peerResults() const
Returns the internal list of resolved results for the peer address.
Definition: kclientsocketbase.cpp:96
KNetwork::KClientSocketBase::stateChanged
void stateChanged(int newstate)
This signal is emitted whenever the socket state changes.
KNetwork::KClientSocketBase::localResolver
KResolver & localResolver() const
Returns the internal KResolver object used for looking up the local host name and service.
Definition: kclientsocketbase.cpp:101
KNetwork::KResolverEntry
One resolution entry.
Definition: kresolver.h:67
KNetwork::KResolverEntry::family
int family() const
Retrieves the family associated with this socket address.
Definition: kresolver.cpp:154
KNetwork::KResolverResults
Name and service resolution results.
Definition: kresolver.h:198
KNetwork::KResolver::setFamily
void setFamily(int families)
Sets the allowed socket families.
Definition: kresolver.cpp:401
KNetwork::KResolver::setServiceName
void setServiceName(const TQString &service)
Sets the service name to be resolved.
Definition: kresolver.cpp:364
KNetwork::KResolver::setNodeName
void setNodeName(const TQString &nodename)
Sets the nodename for the resolution.
Definition: kresolver.cpp:352
KNetwork::KStreamSocket::connect
virtual bool connect(const TQString &node=TQString::null, const TQString &service=TQString::null)
Reimplemented from KClientSocketBase.
Definition: kstreamsocket.cpp:108
KNetwork::KStreamSocket::bind
virtual bool bind(const TQString &node=TQString::null, const TQString &service=TQString::null)
Binds this socket to the given nodename and service, or use the default ones if none are given.
Definition: kstreamsocket.cpp:96
KNetwork::KStreamSocket::timeout
int timeout() const
Retrieves the timeout value (in milliseconds).
Definition: kstreamsocket.cpp:73
KNetwork::KStreamSocket::setTimeout
void setTimeout(int msecs)
Sets the timeout value.
Definition: kstreamsocket.cpp:88
KNetwork::KStreamSocket::KStreamSocket
KStreamSocket(const TQString &node=TQString::null, const TQString &service=TQString::null, TQObject *parent=0L, const char *name=0L)
Default constructor.
Definition: kstreamsocket.cpp:53
KNetwork::KStreamSocket::~KStreamSocket
virtual ~KStreamSocket()
Destructor.
Definition: kstreamsocket.cpp:67
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: kstreamsocket.cpp:78
KNetwork::TDESocketBase::setBlocking
virtual bool setBlocking(bool enable)
Sets this socket's blocking mode.
Definition: tdesocketbase.cpp:76
KNetwork::TDESocketBase::error
SocketError error() const
Retrieves the socket error code.
Definition: tdesocketbase.cpp:160
KNetwork::TDESocketBase::blocking
bool blocking() const
Retrieves this socket's blocking mode.
Definition: tdesocketbase.cpp:81
KNetwork::TDESocketBase::socketDevice
TDESocketDevice * socketDevice() const
Retrieves the socket implementation used on this socket.
Definition: tdesocketbase.cpp:116
KNetwork::TDESocketBase::socketOptions
virtual int socketOptions() const
Retrieves the socket options that have been set.
Definition: tdesocketbase.cpp:71
KNetwork::TDESocketDevice::setSocketOptions
virtual bool setSocketOptions(int opts)
This implementation sets the options on the socket.
Definition: tdesocketdevice.cpp:110
KNetwork::TDESocketDevice::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: tdesocketdevice.cpp:663
KNetwork::TDESocketDevice::close
virtual void close()
Closes the socket.
Definition: tdesocketdevice.cpp:180
KNetwork::TDESocketDevice::writeNotifier
TQSocketNotifier * writeNotifier() const
Returns a socket notifier for output on this socket.
Definition: tdesocketdevice.cpp:627
KNetwork::TDESocketDevice::readNotifier
TQSocketNotifier * readNotifier() const
Returns a socket notifier for input on this socket.
Definition: tdesocketdevice.cpp:609
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: kbufferedsocket.h:36

tdecore

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

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.1
This website is maintained by Timothy Pearson.