• 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
37using namespace KNetwork;
38
39class KNetwork::KStreamSocketPrivate
40{
41public:
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
53KStreamSocket::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
67KStreamSocket::~KStreamSocket()
68{
69 delete d;
70 // KClientSocketBase's destructor closes the socket
71}
72
73int KStreamSocket::timeout() const
74{
75 return d->timeout;
76}
77
78int 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
88void KStreamSocket::setTimeout(int msecs)
89{
90 d->timeout = msecs;
91
92 if (state() == Connecting)
93 d->timer.changeInterval(msecs);
94}
95
96bool 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
108bool 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
192bool KStreamSocket::connect(const KResolverEntry& entry)
193{
194 return KClientSocketBase::connect(entry);
195}
196
197void 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
205void 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
302void 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
320bool 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
351void 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
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.4
This website is maintained by Timothy Pearson.