1 /**
2 * This file is part of TelepathyQt
3 *
4 * @copyright Copyright (C) 2010-2011 Collabora Ltd. <http://www.collabora.co.uk/>
5 * @license LGPL 2.1
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <TelepathyQt/StreamTubeChannel>
23
24 #include "TelepathyQt/_gen/stream-tube-channel.moc.hpp"
25
26 #include "TelepathyQt/debug-internal.h"
27
28 #include <TelepathyQt/Connection>
29 #include <TelepathyQt/ContactManager>
30 #include <TelepathyQt/PendingContacts>
31 #include <TelepathyQt/PendingVariantMap>
32
33 #include <QHostAddress>
34
35 namespace Tp
36 {
37
38 struct TP_QT_NO_EXPORT StreamTubeChannel::Private
39 {
40 Private(StreamTubeChannel *parent);
41
42 static void introspectStreamTube(Private *self);
43 static void introspectConnectionMonitoring(Private *self);
44
45 void extractStreamTubeProperties(const QVariantMap &props);
46
47 // Public object
48 StreamTubeChannel *parent;
49
50 ReadinessHelper *readinessHelper;
51
52 // Introspection
53 SupportedSocketMap socketTypes;
54 QString serviceName;
55
56 QSet<uint> connections;
57 QPair<QHostAddress, quint16> ipAddress;
58 QString unixAddress;
59 SocketAddressType addressType;
60 SocketAccessControl accessControl;
61 bool droppingConnections;
62 };
63
Private(StreamTubeChannel * parent)64 StreamTubeChannel::Private::Private(StreamTubeChannel *parent)
65 : parent(parent),
66 readinessHelper(parent->readinessHelper()),
67 addressType(SocketAddressTypeUnix),
68 accessControl(SocketAccessControlLocalhost),
69 droppingConnections(false)
70 {
71 ReadinessHelper::Introspectables introspectables;
72
73 ReadinessHelper::Introspectable introspectableStreamTube(
74 QSet<uint>() << 0, // makesSenseForStatuses
75 Features() << TubeChannel::FeatureCore, // dependsOnFeatures (core)
76 QStringList(), // dependsOnInterfaces
77 (ReadinessHelper::IntrospectFunc) &StreamTubeChannel::Private::introspectStreamTube,
78 this);
79 introspectables[StreamTubeChannel::FeatureCore] = introspectableStreamTube;
80
81 ReadinessHelper::Introspectable introspectableConnectionMonitoring(
82 QSet<uint>() << 0, // makesSenseForStatuses
83 Features() << StreamTubeChannel::FeatureCore, // dependsOnFeatures (core)
84 QStringList(), // dependsOnInterfaces
85 (ReadinessHelper::IntrospectFunc)
86 &StreamTubeChannel::Private::introspectConnectionMonitoring,
87 this);
88 introspectables[StreamTubeChannel::FeatureConnectionMonitoring] =
89 introspectableConnectionMonitoring;
90
91 parent->connect(
92 parent,
93 SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
94 SLOT(dropConnections()));
95
96 readinessHelper->addIntrospectables(introspectables);
97 }
98
introspectStreamTube(StreamTubeChannel::Private * self)99 void StreamTubeChannel::Private::introspectStreamTube(
100 StreamTubeChannel::Private *self)
101 {
102 StreamTubeChannel *parent = self->parent;
103
104 debug() << "Introspecting stream tube properties";
105 Client::ChannelTypeStreamTubeInterface *streamTubeInterface =
106 parent->interface<Client::ChannelTypeStreamTubeInterface>();
107
108 PendingVariantMap *pvm = streamTubeInterface->requestAllProperties();
109 parent->connect(pvm,
110 SIGNAL(finished(Tp::PendingOperation *)),
111 SLOT(gotStreamTubeProperties(Tp::PendingOperation *)));
112 }
113
introspectConnectionMonitoring(StreamTubeChannel::Private * self)114 void StreamTubeChannel::Private::introspectConnectionMonitoring(
115 StreamTubeChannel::Private *self)
116 {
117 StreamTubeChannel *parent = self->parent;
118
119 Client::ChannelTypeStreamTubeInterface *streamTubeInterface =
120 parent->interface<Client::ChannelTypeStreamTubeInterface>();
121
122 parent->connect(streamTubeInterface,
123 SIGNAL(ConnectionClosed(uint,QString,QString)),
124 SLOT(onConnectionClosed(uint,QString,QString)));
125
126 if (parent->isRequested()) {
127 parent->connect(streamTubeInterface,
128 SIGNAL(NewRemoteConnection(uint,QDBusVariant,uint)),
129 SLOT(onNewRemoteConnection(uint,QDBusVariant,uint)));
130 } else {
131 parent->connect(streamTubeInterface,
132 SIGNAL(NewLocalConnection(uint)),
133 SLOT(onNewLocalConnection(uint)));
134 }
135
136 self->readinessHelper->setIntrospectCompleted(
137 StreamTubeChannel::FeatureConnectionMonitoring, true);
138 }
139
extractStreamTubeProperties(const QVariantMap & props)140 void StreamTubeChannel::Private::extractStreamTubeProperties(const QVariantMap &props)
141 {
142 serviceName = qdbus_cast<QString>(props[QLatin1String("Service")]);
143 socketTypes = qdbus_cast<SupportedSocketMap>(props[QLatin1String("SupportedSocketTypes")]);
144 }
145
146 /**
147 * \class StreamTubeChannel
148 * \ingroup clientchannel
149 * \headerfile TelepathyQt/stream-tube-channel.h <TelepathyQt/StreamTubeChannel>
150 *
151 * \brief The StreamTubeChannel class represents a Telepathy channel of type StreamTube.
152 *
153 * It provides a transport for reliable and ordered data transfer, similar to SOCK_STREAM sockets.
154 *
155 * StreamTubeChannel is an intermediate base class; OutgoingStreamTubeChannel and
156 * IncomingStreamTubeChannel are the specialized classes used for locally and remotely initiated
157 * tubes respectively.
158 *
159 * For more details, please refer to \telepathy_spec.
160 *
161 * See \ref async_model, \ref shared_ptr
162 */
163
164 /**
165 * Feature representing the core that needs to become ready to make the
166 * StreamTubeChannel object usable.
167 *
168 * Note that this feature must be enabled in order to use most
169 * StreamTubeChannel methods.
170 * See specific methods documentation for more details.
171 */
172 const Feature StreamTubeChannel::FeatureCore =
173 Feature(QLatin1String(StreamTubeChannel::staticMetaObject.className()), 0);
174
175 /**
176 * Feature used in order to monitor connections to this stream tube.
177 *
178 * See connection monitoring specific methods' documentation for more details.
179 *
180 * \sa newConnection(), connectionClosed()
181 */
182 const Feature StreamTubeChannel::FeatureConnectionMonitoring =
183 Feature(QLatin1String(StreamTubeChannel::staticMetaObject.className()), 1);
184
185 /**
186 * Create a new StreamTubeChannel channel.
187 *
188 * \param connection Connection owning this channel, and specifying the
189 * service.
190 * \param objectPath The channel object path.
191 * \param immutableProperties The channel immutable properties.
192 * \return A StreamTubeChannelPtr object pointing to the newly created
193 * StreamTubeChannel object.
194 */
create(const ConnectionPtr & connection,const QString & objectPath,const QVariantMap & immutableProperties)195 StreamTubeChannelPtr StreamTubeChannel::create(const ConnectionPtr &connection,
196 const QString &objectPath, const QVariantMap &immutableProperties)
197 {
198 return StreamTubeChannelPtr(new StreamTubeChannel(connection, objectPath,
199 immutableProperties, StreamTubeChannel::FeatureCore));
200 }
201
202 /**
203 * Construct a new StreamTubeChannel object.
204 *
205 * \param connection Connection owning this channel, and specifying the
206 * service.
207 * \param objectPath The channel object path.
208 * \param immutableProperties The channel immutable properties.
209 * \param coreFeature The core feature of the channel type, if any. The corresponding introspectable should
210 * depend on StreamTubeChannel::FeatureCore.
211 */
StreamTubeChannel(const ConnectionPtr & connection,const QString & objectPath,const QVariantMap & immutableProperties,const Feature & coreFeature)212 StreamTubeChannel::StreamTubeChannel(const ConnectionPtr &connection,
213 const QString &objectPath,
214 const QVariantMap &immutableProperties,
215 const Feature &coreFeature)
216 : TubeChannel(connection, objectPath, immutableProperties, coreFeature),
217 mPriv(new Private(this))
218 {
219 }
220
221 /**
222 * Class destructor.
223 */
~StreamTubeChannel()224 StreamTubeChannel::~StreamTubeChannel()
225 {
226 delete mPriv;
227 }
228
229 /**
230 * Return the service name which will be used over this stream tube. This should be a
231 * well-known TCP service name, for instance "rsync" or "daap".
232 *
233 * This method requires StreamTubeChannel::FeatureCore to be ready.
234 *
235 * \return The service name.
236 */
service() const237 QString StreamTubeChannel::service() const
238 {
239 if (!isReady(FeatureCore)) {
240 warning() << "StreamTubeChannel::service() used with "
241 "FeatureCore not ready";
242 return QString();
243 }
244
245 return mPriv->serviceName;
246 }
247
248 /**
249 * Return whether this stream tube is capable to accept or offer an IPv4 socket accepting all
250 * incoming connections coming from localhost.
251 *
252 * Note that the \telepathy_spec implies that any connection manager, if capable of providing
253 * stream tubes, must at least support IPv4 sockets with localhost access control.
254 * For this reason, this method should always return \c true.
255 *
256 * This method requires StreamTubeChannel::FeatureCore to be ready.
257 *
258 * \return \c true if the stream tube is capable to accept or offer an IPv4 socket
259 * accepting all incoming connections coming from localhost, \c false otherwise.
260 * \sa IncomingStreamTubeChannel::acceptTubeAsTcpSocket(),
261 * OutgoingStreamTubeChannel::offerTcpSocket(),
262 * supportsIPv4SocketsWithSpecifiedAddress()
263 */
supportsIPv4SocketsOnLocalhost() const264 bool StreamTubeChannel::supportsIPv4SocketsOnLocalhost() const
265 {
266 if (!isReady(FeatureCore)) {
267 warning() << "StreamTubeChannel::supportsIPv4SocketsOnLocalhost() used with "
268 "FeatureCore not ready";
269 return false;
270 }
271
272 return mPriv->socketTypes.value(SocketAddressTypeIPv4).contains(SocketAccessControlLocalhost);
273 }
274
275 /**
276 * Return whether this stream tube is capable to accept an IPv4 socket accepting all
277 * incoming connections coming from a specific address for incoming tubes or whether
278 * this stream tube is capable of mapping connections to the socket's source address for outgoing
279 * tubes.
280 *
281 * For incoming tubes, when this capability is available, the stream tube can be accepted specifying
282 * an IPv4 address. Every connection coming from any other address than the specified one will be
283 * rejected.
284 *
285 * For outgoing tubes, when this capability is available, one can keep track of incoming connections
286 * by enabling StreamTubeChannel::FeatureConnectionMonitoring (possibly before
287 * opening the stream tube itself), and checking OutgoingStreamTubeChannel::contactsForConnections()
288 * or OutgoingStreamTubeChannel::connectionsForSourceAddresses().
289 *
290 * Note that it is strongly advised to call this method before attempting to call
291 * IncomingStreamTubeChannel::acceptTubeAsTcpSocket() or
292 * OutgoingStreamTubeChannel::offerTcpSocket() with a specified address to prevent failures,
293 * as the spec implies this feature is not compulsory for connection managers.
294 *
295 * This method requires StreamTubeChannel::FeatureCore to be ready.
296 *
297 * \return \c true if the stream tube is capable to accept an IPv4 socket accepting all
298 * incoming connections coming from a specific address for incoming tubes or
299 * the stream tube is capable of mapping connections to the socket's source address for
300 * outgoing tubes, \c false otherwise.
301 * \sa IncomingStreamTubeChannel::acceptTubeAsTcpSocket(),
302 * OutgoingStreamTubeChannel::offerTcpSocket(),
303 * OutgoingStreamTubeChannel::connectionsForSourceAddresses(),
304 * OutgoingStreamTubeChannel::contactsForConnections(),
305 * supportsIPv4SocketsOnLocalhost()
306 */
supportsIPv4SocketsWithSpecifiedAddress() const307 bool StreamTubeChannel::supportsIPv4SocketsWithSpecifiedAddress() const
308 {
309 if (!isReady(FeatureCore)) {
310 warning() << "StreamTubeChannel::supportsIPv4SocketsWithSpecifiedAddress() used with "
311 "FeatureCore not ready";
312 return false;
313 }
314
315 return mPriv->socketTypes.value(SocketAddressTypeIPv4).contains(SocketAccessControlPort);
316 }
317
318 /**
319 * Return whether this stream tube is capable to accept or offer an IPv6 socket accepting all
320 * incoming connections coming from localhost.
321 *
322 * Note that it is strongly advised to call this method before attempting to call
323 * IncomingStreamTubeChannel::acceptTubeAsTcpSocket() or
324 * OutgoingStreamTubeChannel::offerTcpSocket() with a specified address to prevent failures,
325 * as the spec implies this feature is not compulsory for connection managers.
326 *
327 * This method requires StreamTubeChannel::FeatureCore to be ready.
328 *
329 * \return \c true if the stream tube is capable to accept or offer an IPv6 socket
330 * accepting all incoming connections coming from localhost, \c false otherwise.
331 * \sa IncomingStreamTubeChannel::acceptTubeAsTcpSocket(),
332 * OutgoingStreamTubeChannel::offerTcpSocket(),
333 * supportsIPv6SocketsWithSpecifiedAddress()
334 */
supportsIPv6SocketsOnLocalhost() const335 bool StreamTubeChannel::supportsIPv6SocketsOnLocalhost() const
336 {
337 if (!isReady(FeatureCore)) {
338 warning() << "StreamTubeChannel::supportsIPv6SocketsOnLocalhost() used with "
339 "FeatureCore not ready";
340 return false;
341 }
342
343 return mPriv->socketTypes.value(SocketAddressTypeIPv6).contains(SocketAccessControlLocalhost);
344 }
345
346 /**
347 * Return whether this stream tube is capable to accept an IPv6 socket accepting all
348 * incoming connections coming from a specific address for incoming tubes or whether
349 * this stream tube is capable of mapping connections to the socket's source address for outgoing
350 * tubes.
351 *
352 * For incoming tubes, when this capability is available, the stream tube can be accepted specifying
353 * an IPv6 address. Every connection coming from any other address than the specified one will be
354 * rejected.
355 *
356 * For outgoing tubes, when this capability is available, one can keep track of incoming connections
357 * by enabling StreamTubeChannel::FeatureConnectionMonitoring (possibly before
358 * opening the stream tube itself), and checking OutgoingStreamTubeChannel::contactsForConnections()
359 * or OutgoingStreamTubeChannel::connectionsForSourceAddresses().
360 *
361 * Note that it is strongly advised to call this method before attempting to call
362 * IncomingStreamTubeChannel::acceptTubeAsTcpSocket() or
363 * OutgoingStreamTubeChannel::offerTcpSocket() with a specified address to prevent failures,
364 * as the spec implies this feature is not compulsory for connection managers.
365 *
366 * This method requires StreamTubeChannel::FeatureCore to be ready.
367 *
368 * \return \c true if the stream tube is capable to accept an IPv6 socket accepting all
369 * incoming connections coming from a specific address for incoming tubes or
370 * the stream tube is capable of mapping connections to the socket's source address for
371 * outgoing tubes, \c false otherwise.
372 * \sa IncomingStreamTubeChannel::acceptTubeAsTcpSocket(),
373 * OutgoingStreamTubeChannel::offerTcpSocket(),
374 * OutgoingStreamTubeChannel::connectionsForSourceAddresses(),
375 * OutgoingStreamTubeChannel::contactsForConnections(),
376 * supportsIPv6SocketsOnLocalhost()
377 */
supportsIPv6SocketsWithSpecifiedAddress() const378 bool StreamTubeChannel::supportsIPv6SocketsWithSpecifiedAddress() const
379 {
380 if (!isReady(FeatureCore)) {
381 warning() << "StreamTubeChannel::supportsIPv6SocketsWithSpecifiedAddress() used with "
382 "FeatureCore not ready";
383 return false;
384 }
385
386 return mPriv->socketTypes.value(SocketAddressTypeIPv6).contains(SocketAccessControlPort);
387 }
388
389 /**
390 * Return whether this stream tube is capable to accept or offer an Unix socket accepting all
391 * incoming connections coming from localhost.
392 *
393 * Note that it is strongly advised to call this method before attempting to call
394 * IncomingStreamTubeChannel::acceptTubeAsUnixSocket() or
395 * OutgoingStreamTubeChannel::offerUnixSocket() without credentials enabled, as the spec implies
396 * this feature is not compulsory for connection managers.
397 *
398 * This method requires StreamTubeChannel::FeatureCore to be ready.
399 *
400 * \return \c true if the stream tube is capable to accept or offer an Unix socket
401 * accepting all incoming connections coming from localhost, \c false otherwise.
402 * \sa IncomingStreamTubeChannel::acceptTubeAsUnixSocket(),
403 * OutgoingStreamTubeChannel::offerUnixSocket(),
404 * supportsUnixSocketsWithCredentials()
405 * supportsAbstractUnixSocketsOnLocalhost(),
406 * supportsAbstractUnixSocketsWithCredentials(),
407 */
supportsUnixSocketsOnLocalhost() const408 bool StreamTubeChannel::supportsUnixSocketsOnLocalhost() const
409 {
410 if (!isReady(FeatureCore)) {
411 warning() << "StreamTubeChannel::supportsUnixSocketsOnLocalhost() used with "
412 "FeatureCore not ready";
413 return false;
414 }
415
416 return mPriv->socketTypes.value(SocketAddressTypeUnix).contains(SocketAccessControlLocalhost);
417 }
418
419 /**
420 * Return whether this stream tube is capable to accept or offer an Unix socket which will require
421 * credentials upon connection.
422 *
423 * When this capability is available and enabled, the connecting process must send a byte when
424 * it first connects, which is not considered to be part of the data stream.
425 * If the operating system uses sendmsg() with SCM_CREDS or SCM_CREDENTIALS to pass
426 * credentials over sockets, the connecting process must do so if possible;
427 * if not, it must still send the byte.
428 *
429 * The listening process will disconnect the connection unless it can determine
430 * by OS-specific means that the connecting process has the same user ID as the listening process.
431 *
432 * Note that it is strongly advised to call this method before attempting to call
433 * IncomingStreamTubeChannel::acceptTubeAsUnixSocket() or
434 * OutgoingStreamTubeChannel::offerUnixSocket() with credentials enabled, as the spec implies
435 * this feature is not compulsory for connection managers.
436 *
437 * This method requires StreamTubeChannel::FeatureCore to be ready.
438 *
439 * \return \c true if the stream tube is capable to accept or offer an Unix socket
440 * which will require credentials upon connection, \c false otherwise.
441 * \sa IncomingStreamTubeChannel::acceptTubeAsUnixSocket(),
442 * OutgoingStreamTubeChannel::offerUnixSocket(),
443 * supportsUnixSocketsOnLocalhost(),
444 * supportsAbstractUnixSocketsOnLocalhost(),
445 * supportsAbstractUnixSocketsWithCredentials(),
446 */
supportsUnixSocketsWithCredentials() const447 bool StreamTubeChannel::supportsUnixSocketsWithCredentials() const
448 {
449 if (!isReady(FeatureCore)) {
450 warning() << "StreamTubeChannel::supportsUnixSocketsWithCredentials() used with "
451 "FeatureCore not ready";
452 return false;
453 }
454
455 return mPriv->socketTypes[SocketAddressTypeUnix].contains(SocketAccessControlCredentials);
456 }
457
458 /**
459 * Return whether this stream tube is capable to accept or offer an abstract Unix socket accepting
460 * all incoming connections coming from localhost.
461 *
462 * Note that it is strongly advised to call this method before attempting to call
463 * IncomingStreamTubeChannel::acceptTubeAsUnixSocket() or
464 * OutgoingStreamTubeChannel::offerUnixSocket() without credentials enabled, as the spec implies
465 * this feature is not compulsory for connection managers.
466 *
467 * This method requires StreamTubeChannel::FeatureCore to be ready.
468 *
469 * \return \c true if the stream tube is capable to accept or offer an abstract Unix socket
470 * accepting all incoming connections coming from localhost, \c false otherwise.
471 * \sa IncomingStreamTubeChannel::acceptTubeAsUnixSocket(),
472 * OutgoingStreamTubeChannel::offerUnixSocket(),
473 * supportsUnixSocketsOnLocalhost(),
474 * supportsUnixSocketsWithCredentials(),
475 * supportsAbstractUnixSocketsWithCredentials()
476 */
supportsAbstractUnixSocketsOnLocalhost() const477 bool StreamTubeChannel::supportsAbstractUnixSocketsOnLocalhost() const
478 {
479 if (!isReady(FeatureCore)) {
480 warning() << "StreamTubeChannel::supportsAbstractUnixSocketsOnLocalhost() used with "
481 "FeatureCore not ready";
482 return false;
483 }
484
485 return mPriv->socketTypes[SocketAddressTypeAbstractUnix].contains(SocketAccessControlLocalhost);
486 }
487
488 /**
489 * Return whether this stream tube is capable to accept or offer an abstract Unix socket which will
490 * require credentials upon connection.
491 *
492 * When this capability is available and enabled, the connecting process must send a byte when
493 * it first connects, which is not considered to be part of the data stream.
494 * If the operating system uses sendmsg() with SCM_CREDS or SCM_CREDENTIALS to pass
495 * credentials over sockets, the connecting process must do so if possible;
496 * if not, it must still send the byte.
497 *
498 * The listening process will disconnect the connection unless it can determine
499 * by OS-specific means that the connecting process has the same user ID as the listening process.
500 *
501 * Note that it is strongly advised to call this method before attempting to call
502 * IncomingStreamTubeChannel::acceptTubeAsUnixSocket() or
503 * OutgoingStreamTubeChannel::offerUnixSocket() with credentials enabled, as the spec implies
504 * this feature is not compulsory for connection managers.
505 *
506 * This method requires StreamTubeChannel::FeatureCore to be ready.
507 *
508 * \return \c true if the stream tube is capable to accept or offer an abstract Unix socket
509 * which will require credentials upon connection, \c false otherwise.
510 * \sa IncomingStreamTubeChannel::acceptTubeAsUnixSocket(),
511 * OutgoingStreamTubeChannel::offerUnixSocket(),
512 * supportsUnixSocketsOnLocalhost(),
513 * supportsUnixSocketsWithCredentials(),
514 * supportsAbstractUnixSocketsOnLocalhost()
515 */
supportsAbstractUnixSocketsWithCredentials() const516 bool StreamTubeChannel::supportsAbstractUnixSocketsWithCredentials() const
517 {
518 if (!isReady(FeatureCore)) {
519 warning() << "StreamTubeChannel::supportsAbstractUnixSocketsWithCredentials() used with "
520 "FeatureCore not ready";
521 return false;
522 }
523
524 return mPriv->socketTypes[SocketAddressTypeAbstractUnix].contains(SocketAccessControlCredentials);
525 }
526
527 /**
528 * Return all the known active connections since StreamTubeChannel::FeatureConnectionMonitoring has
529 * been enabled.
530 *
531 * For this method to return all known connections, you need to make
532 * StreamTubeChannel::FeatureConnectionMonitoring ready before accepting or offering the stream
533 * tube.
534 *
535 * This method requires StreamTubeChannel::FeatureConnectionMonitoring to be ready.
536 *
537 * \return The list of active connection ids.
538 * \sa newConnection(), connectionClosed()
539 */
connections() const540 QSet<uint> StreamTubeChannel::connections() const
541 {
542 if (!isReady(FeatureConnectionMonitoring)) {
543 warning() << "StreamTubeChannel::connections() used with "
544 "FeatureConnectionMonitoring not ready";
545 return QSet<uint>();
546 }
547
548 return mPriv->connections;
549 }
550
551 /**
552 * Return the type of the tube's local endpoint socket.
553 *
554 * Note that this function will return a valid value only after state() has gone #TubeStateOpen.
555 *
556 * \return The socket type as #SocketAddressType.
557 * \sa localAddress(), ipAddress()
558 */
addressType() const559 SocketAddressType StreamTubeChannel::addressType() const
560 {
561 return mPriv->addressType;
562 }
563
564 /**
565 * Return the access control used by this stream tube.
566 *
567 * Note that this function will only return a valid value after state() has gone #TubeStateOpen.
568 *
569 * \return The access control as #SocketAccessControl.
570 * \sa addressType()
571 */
accessControl() const572 SocketAccessControl StreamTubeChannel::accessControl() const
573 {
574 return mPriv->accessControl;
575 }
576
577 /**
578 * Return the IP address/port combination used by this stream tube.
579 *
580 * This method will return a meaningful value only if the local endpoint socket for the tube is a
581 * TCP socket, i.e. addressType() is #SocketAddressTypeIPv4 or #SocketAddressTypeIPv6.
582 *
583 * Note that this function will return a valid value only after state() has gone #TubeStateOpen.
584 *
585 * \return Pair of IP address as QHostAddress and port if using a TCP socket,
586 * or an undefined value otherwise.
587 * \sa localAddress()
588 */
ipAddress() const589 QPair<QHostAddress, quint16> StreamTubeChannel::ipAddress() const
590 {
591 if (state() != TubeChannelStateOpen) {
592 warning() << "Tube not open, returning invalid IP address";
593 return qMakePair<QHostAddress, quint16>(QHostAddress::Null, 0);
594 }
595
596 return mPriv->ipAddress;
597 }
598
599 /**
600 * Return the local address used by this stream tube.
601 *
602 * This method will return a meaningful value only if the local endpoint socket for the tube is an
603 * UNIX socket, i.e. addressType() is #SocketAddressTypeUnix or #SocketAddressTypeAbstractUnix.
604 *
605 * Note that this function will return a valid value only after state() has gone #TubeStateOpen.
606 *
607 * \return Unix socket address if using an Unix socket,
608 * or an undefined value otherwise.
609 * \sa ipAddress()
610 */
localAddress() const611 QString StreamTubeChannel::localAddress() const
612 {
613 if (state() != TubeChannelStateOpen) {
614 warning() << "Tube not open, returning invalid local socket address";
615 return QString();
616 }
617
618 return mPriv->unixAddress;
619 }
620
addConnection(uint connection)621 void StreamTubeChannel::addConnection(uint connection)
622 {
623 if (!mPriv->connections.contains(connection)) {
624 mPriv->connections.insert(connection);
625 emit newConnection(connection);
626 } else {
627 warning() << "Tried to add connection" << connection << "on StreamTube" << objectPath()
628 << "but it already was there";
629 }
630 }
631
removeConnection(uint connection,const QString & error,const QString & message)632 void StreamTubeChannel::removeConnection(uint connection, const QString &error,
633 const QString &message)
634 {
635 if (mPriv->connections.contains(connection)) {
636 mPriv->connections.remove(connection);
637 emit connectionClosed(connection, error, message);
638 } else {
639 warning() << "Tried to remove connection" << connection << "from StreamTube" << objectPath()
640 << "but it wasn't there";
641 }
642 }
643
setAddressType(SocketAddressType type)644 void StreamTubeChannel::setAddressType(SocketAddressType type)
645 {
646 mPriv->addressType = type;
647 }
648
setAccessControl(SocketAccessControl accessControl)649 void StreamTubeChannel::setAccessControl(SocketAccessControl accessControl)
650 {
651 mPriv->accessControl = accessControl;
652 }
653
setIpAddress(const QPair<QHostAddress,quint16> & address)654 void StreamTubeChannel::setIpAddress(const QPair<QHostAddress, quint16> &address)
655 {
656 mPriv->ipAddress = address;
657 }
658
setLocalAddress(const QString & address)659 void StreamTubeChannel::setLocalAddress(const QString &address)
660 {
661 mPriv->unixAddress = address;
662 }
663
isDroppingConnections() const664 bool StreamTubeChannel::isDroppingConnections() const
665 {
666 return mPriv->droppingConnections;
667 }
668
gotStreamTubeProperties(PendingOperation * op)669 void StreamTubeChannel::gotStreamTubeProperties(PendingOperation *op)
670 {
671 if (!op->isError()) {
672 PendingVariantMap *pvm = qobject_cast<PendingVariantMap *>(op);
673
674 mPriv->extractStreamTubeProperties(pvm->result());
675
676 debug() << "Got reply to Properties::GetAll(StreamTubeChannel)";
677 mPriv->readinessHelper->setIntrospectCompleted(StreamTubeChannel::FeatureCore, true);
678 }
679 else {
680 warning().nospace() << "Properties::GetAll(StreamTubeChannel) failed "
681 "with " << op->errorName() << ": " << op->errorMessage();
682 mPriv->readinessHelper->setIntrospectCompleted(StreamTubeChannel::FeatureCore, false,
683 op->errorName(), op->errorMessage());
684 }
685 }
686
onConnectionClosed(uint connId,const QString & error,const QString & message)687 void StreamTubeChannel::onConnectionClosed(uint connId, const QString &error,
688 const QString &message)
689 {
690 removeConnection(connId, error, message);
691 }
692
dropConnections()693 void StreamTubeChannel::dropConnections()
694 {
695 if (!mPriv->connections.isEmpty()) {
696 debug() << "StreamTubeChannel invalidated with" << mPriv->connections.size()
697 << "connections remaining, synthesizing close events";
698 mPriv->droppingConnections = true;
699 foreach (uint connId, mPriv->connections) {
700 removeConnection(connId, TP_QT_ERROR_ORPHANED,
701 QLatin1String("parent tube invalidated, streams closing"));
702 }
703 mPriv->droppingConnections = false;
704 }
705 }
706
707 /**
708 * \fn void StreamTubeChannel::connectionClosed(uint connectionId,
709 * const QString &errorName, const QString &errorMessage)
710 *
711 * Emitted when a connection on this stream tube has been closed.
712 *
713 * \param connectionId The unique ID associated with the connection that was closed.
714 * \param errorName The name of a D-Bus error describing the error that occurred.
715 * \param errorMessage A debugging message associated with the error.
716 * \sa newConnection(), connections()
717 */
718
719 } // Tp
720