Home · Modules · All Classes · All Namespaces
Classes | Signals | Public Member Functions | Static Public Member Functions | List of all members
Tp::StreamTubeClient Class Reference

The StreamTubeClient class is a Handler implementation for incoming Stream Tube channels, allowing an application to easily get notified about services they can connect to offered to them over Telepathy Tubes without worrying about the channel dispatching details. More...

#include <TelepathyQt/StreamTubeClient>

Inherits QObject, and Tp::RefCounted.

Classes

class  TcpSourceAddressGenerator
 The StreamTubeClient::TcpSourceAddressGenerator abstract interface allows using socket source address/port based access control for connecting to tubes accepted as TCP sockets. More...
 
class  Tube
 The StreamTubeClient::Tube class represents a tube being handled by the client. More...
 

Signals

void tubeOffered (const Tp::AccountPtr &account, const Tp::IncomingStreamTubeChannelPtr &tube)
 
void tubeClosed (const Tp::AccountPtr &account, const Tp::IncomingStreamTubeChannelPtr &tube, const QString &error, const QString &message)
 
void tubeAcceptedAsTcp (const QHostAddress &listenAddress, quint16 listenPort, const QHostAddress &sourceAddress, quint16 sourcePort, const Tp::AccountPtr &account, const Tp::IncomingStreamTubeChannelPtr &tube)
 
void tubeAcceptedAsUnix (const QString &listenAddress, bool requiresCredentials, uchar credentialByte, const Tp::AccountPtr &account, const Tp::IncomingStreamTubeChannelPtr &tube)
 
void newConnection (const Tp::AccountPtr &account, const Tp::IncomingStreamTubeChannelPtr &tube, uint connectionId)
 
void connectionClosed (const Tp::AccountPtr &account, const Tp::IncomingStreamTubeChannelPtr &tube, uint connectionId, const QString &error, const QString &message)
 

Public Member Functions

virtual ~StreamTubeClient ()
 
ClientRegistrarPtr registrar () const
 
QString clientName () const
 
bool isRegistered () const
 
bool monitorsConnections () const
 
bool acceptsAsTcp () const
 
TcpSourceAddressGeneratortcpGenerator () const
 
bool acceptsAsUnix () const
 
void setToAcceptAsTcp (TcpSourceAddressGenerator *generator=0)
 
void setToAcceptAsUnix (bool requireCredentials=false)
 
QList< Tubetubes () const
 
QHash< Tube, QSet< uint > > connections () const
 
- Public Member Functions inherited from Tp::RefCounted
 RefCounted ()
 
virtual ~RefCounted ()
 

Static Public Member Functions

static StreamTubeClientPtr create (const QStringList &p2pServices, const QStringList &roomServices=QStringList(), const QString &clientName=QString(), bool monitorConnections=false, bool bypassApproval=false, const AccountFactoryConstPtr &accountFactory=AccountFactory::create(QDBusConnection::sessionBus()), const ConnectionFactoryConstPtr &connectionFactory=ConnectionFactory::create(QDBusConnection::sessionBus()), const ChannelFactoryConstPtr &channelFactory=ChannelFactory::create(QDBusConnection::sessionBus()), const ContactFactoryConstPtr &contactFactory=ContactFactory::create())
 
static StreamTubeClientPtr create (const QDBusConnection &bus, const AccountFactoryConstPtr &accountFactory, const ConnectionFactoryConstPtr &connectionFactory, const ChannelFactoryConstPtr &channelFactory, const ContactFactoryConstPtr &contactFactory, const QStringList &p2pServices, const QStringList &roomServices=QStringList(), const QString &clientName=QString(), bool monitorConnections=false, bool bypassApproval=false)
 
static StreamTubeClientPtr create (const AccountManagerPtr &accountManager, const QStringList &p2pServices, const QStringList &roomServices=QStringList(), const QString &clientName=QString(), bool monitorConnections=false, bool bypassApproval=false)
 
static StreamTubeClientPtr create (const ClientRegistrarPtr &registrar, const QStringList &p2pServices, const QStringList &roomServices=QStringList(), const QString &clientName=QString(), bool monitorConnections=false, bool bypassApproval=false)
 

Detailed Description

The StreamTubeClient class is a Handler implementation for incoming Stream Tube channels, allowing an application to easily get notified about services they can connect to offered to them over Telepathy Tubes without worrying about the channel dispatching details.

Telepathy Tubes is a technology for connecting arbitrary applications together through the IM network (and sometimes with direct peer-to-peer connections), such that issues like firewall/NAT traversal are automatically handled. Stream Tubes in particular offer properties similar to SOCK_STREAM sockets. The StreamTubeClient class negotiates tubes offered to us so that an application can connect such bytestream sockets of theirs to them. The StreamTubeServer class is the counterpart, offering services from a bytestream socket server to tubes requested to be initiated.

Both peer-to-peer (TargetHandleType == HandleTypeContact) and group (TargetHandleType == HandleTypeRoom) channels are supported, and it's possible to specify the tube services to handle for each separately. There must be at least one service in total declared, as it never makes sense to handle stream tubes without considering the protocol of the service offered through them.

Connection monitoring allows fine-grained error reporting for connections made through tubes, and observing connections being made and broken even if the application code running StreamTubeClient can't easily get this information from the code actually connecting through it. Such a setting might occur e.g. when a wrapper application is developed to connect some existing "black box" networked application through TCP tubes by launching it with the appropriate command line arguments or alike for accepted tubes.

Enabling connection monitoring adds a small overhead and latency to handling each incoming tube and signaling each new incoming connection over them, though, so use it only when needed.

A service activated Handler can be implemented using StreamTubeClient by passing a predefined clientName manually to the chosen create() method, and installing Telepathy .client and D-Bus .service files declaring the implemented tube services as channel classes and a path to the executable. If this is not needed, the clientName can be omitted, in which case a random unique client name is generated and used instead. However, then the tube client application must already be running for remote contacts to be able to offer services to us over tubes.

Whether the Handler application implemented using StreamTubeClient is service activatable or not, incoming channels will typically first be given to an Approver, if there is one for tube services corresponding to the tube in question. Only if the Approver decides that the tube communication should be allowed (usually by asking the user), or if there is no matching Approver at all, is the channel given to the actual Handler tube client. This can be overridden by setting bypassApproval to true, which skips approval for the given services completely and directs them straight to the Handler.

StreamTubeClient shares Account, Connection and Channel proxies and Contact objects with the rest of the application as long as a reference to the AccountManager, ClientRegistrar, or the factories used elsewhere is passed to the create() method. A stand-alone tube client Handler can get away without passing these however, or just passing select factories to make the desired features prepared and subclasses employed for these objects for their own convenience.

Whichever method is used, the ChannelFactory (perhaps indirectly) given must construct IncomingStreamTubeChannel instances or subclasses thereof for all channel classes corresponding to the tube services the client should be able to connect to. This is the default; overriding it without obeying these constraints using ChannelFactory::setSubclassForIncomingStreamTubes() or the related methods for room tubes prevents StreamTubeClient from operating correctly.

Todo:
Coin up a small Python script or alike to easily generate the .client and .service files. (fd.o #41614)

Constructor & Destructor Documentation

◆ ~StreamTubeClient()

Tp::StreamTubeClient::~StreamTubeClient ( )
virtual

Class destructor.

Member Function Documentation

◆ create() [1/4]

StreamTubeClientPtr Tp::StreamTubeClient::create ( const QStringList &  p2pServices,
const QStringList &  roomServices = QStringList(),
const QString &  clientName = QString(),
bool  monitorConnections = false,
bool  bypassApproval = false,
const AccountFactoryConstPtr &  accountFactory = AccountFactory::create(QDBusConnection::sessionBus()),
const ConnectionFactoryConstPtr &  connectionFactory = ConnectionFactory::create(QDBusConnection::sessionBus()),
const ChannelFactoryConstPtr &  channelFactory = ChannelFactory::create(QDBusConnection::sessionBus()),
const ContactFactoryConstPtr &  contactFactory = ContactFactory::create() 
)
static

Create a new StreamTubeClient, which will register itself on the session bus using an internal ClientRegistrar and use the given factories.

Parameters
p2pServicesNames of the tube services to accept on peer-to-peer tube channels.
roomServicesNames of the tube services to accept on room/group tube channels.
clientNameThe client name (without the org.freedesktop.Telepathy.Client. prefix).
monitorConnectionsWhether to enable connection monitoring or not.
bypassApprovaltrue to skip approval, false to invoke an Approver for incoming channels if there is one.
accountFactoryThe account factory to use.
connectionFactoryThe connection factory to use.
channelFactoryThe channel factory to use.
contactFactoryThe contact factory to use.

◆ create() [2/4]

StreamTubeClientPtr Tp::StreamTubeClient::create ( const QDBusConnection &  bus,
const AccountFactoryConstPtr &  accountFactory,
const ConnectionFactoryConstPtr &  connectionFactory,
const ChannelFactoryConstPtr &  channelFactory,
const ContactFactoryConstPtr &  contactFactory,
const QStringList &  p2pServices,
const QStringList &  roomServices = QStringList(),
const QString &  clientName = QString(),
bool  monitorConnections = false,
bool  bypassApproval = false 
)
static

Create a new StreamTubeClient, which will register itself on the given bus using an internal ClientRegistrar and use the given factories.

The factories must all be created for the given bus.

Parameters
busConnection to the bus to register on.
accountFactoryThe account factory to use.
connectionFactoryThe connection factory to use.
channelFactoryThe channel factory to use.
contactFactoryThe contact factory to use.
p2pServicesNames of the tube services to handle on peer-to-peer tube channels.
roomServicesNames of the tube services to handle on room/group tube channels.
clientNameThe client name (without the org.freedesktop.Telepathy.Client. prefix).
monitorConnectionsWhether to enable connection monitoring or not.
bypassApprovaltrue to skip approval, false to invoke an Approver for incoming channels if there is one.

◆ create() [3/4]

StreamTubeClientPtr Tp::StreamTubeClient::create ( const AccountManagerPtr &  accountManager,
const QStringList &  p2pServices,
const QStringList &  roomServices = QStringList(),
const QString &  clientName = QString(),
bool  monitorConnections = false,
bool  bypassApproval = false 
)
static

Create a new StreamTubeClient, which will register itself on the bus of and share objects with the given accountManager, creating an internal ClientRegistrar.

Parameters
accountManagerA pointer to the account manager to link up with.
p2pServicesNames of the tube services to handle on peer-to-peer tube channels.
roomServicesNames of the tube services to handle on room/group tube channels.
clientNameThe client name (without the org.freedesktop.Telepathy.Client. prefix).
monitorConnectionsWhether to enable connection monitoring or not.
bypassApprovaltrue to skip approval, false to invoke an Approver for incoming channels if there is one.

◆ create() [4/4]

StreamTubeClientPtr Tp::StreamTubeClient::create ( const ClientRegistrarPtr &  registrar,
const QStringList &  p2pServices,
const QStringList &  roomServices = QStringList(),
const QString &  clientName = QString(),
bool  monitorConnections = false,
bool  bypassApproval = false 
)
static

Create a new StreamTubeClient, which will register itself on the bus of and using the given client registrar, and share objects with it.

Parameters
registrarThe client registrar to use.
p2pServicesNames of the tube services to handle on peer-to-peer tube channels.
roomServicesNames of the tube services to handle on room/group tube channels.
clientNameThe client name (without the org.freedesktop.Telepathy.Client. prefix).
monitorConnectionsWhether to enable connection monitoring or not.
bypassApprovaltrue to skip approval, false to invoke an Approver for incoming channels if there is one.

◆ registrar()

ClientRegistrarPtr Tp::StreamTubeClient::registrar ( ) const

Return the client registrar used by the client to register itself as a Telepathy channel Handler Client.

This is the registrar originally passed to create(const ClientRegistrarPtr &, const QStringList &, const QStringList &, const QString &, bool, bool) if that was used, and an internally constructed one otherwise. In any case, it can be used to e.g. register further clients, just like any other ClientRegistrar.

Returns
A pointer to the registrar.

◆ clientName()

QString Tp::StreamTubeClient::clientName ( ) const

Return the Telepathy Client name of the client.

Returns
The name, without the org.freedesktop.Telepathy.Client. prefix of the full D-Bus service name.

◆ isRegistered()

bool Tp::StreamTubeClient::isRegistered ( ) const

Return whether the client has been successfully registered or not.

Registration is attempted, at the latest, when the client is first set to accept incoming tubes, either as TCP sockets (setToAcceptAsTcp()) or Unix ones (setToAcceptAsUnix()). It can fail e.g. because the connection to the bus has failed, or a predefined clientName has been passed to create(), and a Client with the same name is already registered. Typically, failure registering would be a fatal error for a stand-alone tube handler, but only a warning event for an application serving other purposes. In any case, a high-quality user of the API will check the return value of this accessor after choosing the desired address family.

Returns
true if the client has been successfully registered, false if not.

◆ monitorsConnections()

bool Tp::StreamTubeClient::monitorsConnections ( ) const

Return whether connection monitoring is enabled on this client.

For technical reasons, connection monitoring can't be enabled when the client is already running, so there is no corresponding setter method. It has to be enabled by passing true as the monitorConnections parameter to the create() method.

If connection monitoring isn't enabled, newConnection() and connectionClosed() won't be emitted and connections() won't be populated.

Returns
true if monitoring is enabled, false if not.

◆ acceptsAsTcp()

bool Tp::StreamTubeClient::acceptsAsTcp ( ) const

Return whether the client is currently set to accept incoming tubes as TCP sockets.

Returns
true if the client will accept tubes as TCP sockets, false if it will accept them as Unix ones or hasn't been set to accept at all yet.

◆ tcpGenerator()

StreamTubeClient::TcpSourceAddressGenerator * Tp::StreamTubeClient::tcpGenerator ( ) const

Return the TCP source address generator, if any, set by setToAcceptAsTcp() previously.

Returns
A pointer to the generator instance.

◆ acceptsAsUnix()

bool Tp::StreamTubeClient::acceptsAsUnix ( ) const

Return whether the client is currently set to accept incoming tubes as Unix sockets.

Returns
true if the client will accept tubes as Unix sockets, false if it will accept them as TCP ones or hasn't been set to accept at all yet.

◆ setToAcceptAsTcp()

void Tp::StreamTubeClient::setToAcceptAsTcp ( TcpSourceAddressGenerator generator = 0)

Set the client to accept tubes received to handle in the future in a fashion which will yield a TCP socket as the local endpoint to connect to.

A source address generator can optionally be set. If non-null, it will be invoked for each new tube received to handle and an attempt is made to restrict connections to the tube's local socket endpoint to those from that source address.

However, if the protocol backend doesn't actually support source address based access control, tubeAcceptedAsTcp() will be emitted with QHostAddress::Any as the allowed source address to signal that it doesn't matter where we connect from, but more importantly, that anybody else on the same host could have, and can, connect to the tube. The tube can be closed at this point if this would be unacceptable security-wise. To totally prevent the tube from being accepted in the first place, one can close it already when tubeOffered() is emitted for it - support for the needed security mechanism can be queried using its supportsIPv4SocketsWithSpecifiedAddress() accessor.

The handler is registered on the bus at the latest when this method or setToAcceptAsUnix() is called for the first time, so one should check the return value of isRegistered() at that point to verify that was successful.

Parameters
generatorA pointer to the source address generator to use, or 0 to allow all connections from the local host.
Todo:
Make it possible to set the tube client to auto-close tubes if the desired access control level is not achieved, as an alternative to the current best-effort behavior.

◆ setToAcceptAsUnix()

void Tp::StreamTubeClient::setToAcceptAsUnix ( bool  requireCredentials = false)

Set the client to accept tubes received to handle in the future in a fashion which will yield a Unix socket as the local endpoint to connect to.

If that doesn't cause problems for the payload protocol, it's possible to increase security by restricting the processes allowed to connect to the local endpoint socket to those from the same user ID as the protocol backend is running as by setting requireCredentials to true. This requires transmitting a single byte, signaled as the credentialByte parameter to the tubeAcceptedAsUnix() signal, in a SCM_CREDS or SCM_CREDENTIALS message, whichever is supported by the platform, as the first thing after having connected to the socket. Even if the platform doesn't implement either concept, the byte must still be sent.

However, not all protocol backends support the credential passing based access control on all the platforms they can run on. If a tube is offered through such a backend, tubeAcceptedAsUnix() will be emitted with requiresCredentials set to false, to signal that a credential byte should NOT be sent for that tube, and that any local process can or could have connected to the tube already. The tube can be closed at this point if this would be unacceptable security-wise. To totally prevent the tube from being accepted in the first place, one can close it already when tubeOffered() is emitted for it - support for the needed security mechanism can be queried using its supportsIPv4SocketsWithSpecifiedAddress() accessor.

The handler is registered on the bus at the latest when this method or setToAcceptAsTcp() is called for the first time, so one should check the return value of isRegistered() at that point to verify that was successful.

Parameters
requireCredentialstrue to try and restrict connecting by UID, false to allow all connections.
Todo:
Make it possible to set the tube client to auto-close tubes if the desired access control level is not achieved, as an alternative to the current best-effort behavior.

◆ tubes()

QList< StreamTubeClient::Tube > Tp::StreamTubeClient::tubes ( ) const

Return the tubes currently handled by the client.

Returns
A list of Tube structures containing pointers to the account and tube channel for each tube.

◆ connections()

QHash< StreamTubeClient::Tube, QSet< uint > > Tp::StreamTubeClient::connections ( ) const

Return the ongoing connections established through tubes signaled by this client.

The returned mapping has for each Tube a structure containing pointers to the account and tube channel objects as keys, with the integer identifiers for the current connections on them as the values. The IDs are unique amongst the connections active on a single tube at any given time, but not globally.

This is effectively a state recovery accessor corresponding to the change notification signals newConnection() and connectionClosed().

The mapping is only populated if connection monitoring was requested when creating the client (so monitorsConnections() returns true).

Returns
The connections in a mapping with Tube structures containing pointers to the account and channel objects for each tube as keys, and the sets of numerical IDs as values.

◆ tubeOffered

void Tp::StreamTubeClient::tubeOffered ( const Tp::AccountPtr &  account,
const Tp::IncomingStreamTubeChannelPtr &  tube 
)
signal

Emitted when one of the services we're interested in connecting to has been offered by us as a tube, which we've began handling.

This is emitted before invoking the TcpSourceAddressGenerator, if any, for the tube.

Parameters
accountA pointer to the account through which the tube was offered.
tubeA pointer to the actual tube channel.

◆ tubeClosed

void Tp::StreamTubeClient::tubeClosed ( const Tp::AccountPtr &  account,
const Tp::IncomingStreamTubeChannelPtr &  tube,
const QString &  error,
const QString &  message 
)
signal

Emitted when a tube we've been handling (previously announced with tubeOffered()) has encountered an error or has otherwise been closed from further communication.

Parameters
accountA pointer to the account through which the tube was offered.
tubeA pointer to the actual tube channel.
errorThe D-Bus error name corresponding to the reason for the closure.
messageA freeform debug message associated with the error.

◆ tubeAcceptedAsTcp

void Tp::StreamTubeClient::tubeAcceptedAsTcp ( const QHostAddress &  listenAddress,
quint16  listenPort,
const QHostAddress &  sourceAddress,
quint16  sourcePort,
const Tp::AccountPtr &  account,
const Tp::IncomingStreamTubeChannelPtr &  tube 
)
signal

Emitted when a tube offered to us (previously announced with tubeOffered()) has been successfully accepted and a TCP socket established as the local endpoint, as specified by setToAcceptAsTcp().

The allowed source address and port are signaled here if there was a TcpSourceAddressGenerator set at the time of accepting this tube, it yielded a non-zero address, and the protocol backend supports source address based access control. This enables the application to use the correct one of the sockets it currently has bound to the generated addresses.

Parameters
listenAddressThe listen address of the local endpoint socket.
listenPortThe listen port of the local endpoint socket.
sourceAddressThe host address allowed to connect to the tube, or QHostAddress::Any if source address based access control is not in use.
sourcePortThe port from which connections are allowed to the tube, or 0 if source address based access control is not in use.
accountA pointer to the account object through which the tube was offered.
tubeA pointer to the actual tube channel object.

◆ tubeAcceptedAsUnix

void Tp::StreamTubeClient::tubeAcceptedAsUnix ( const QString &  listenAddress,
bool  requiresCredentials,
uchar  credentialByte,
const Tp::AccountPtr &  account,
const Tp::IncomingStreamTubeChannelPtr &  tube 
)
signal

Emitted when a tube offered to us (previously announced with tubeOffered()) has been successfully accepted and a Unix socket established as the local endpoint, as specified by setToAcceptAsUnix().

The credential byte which should be sent after connecting to the tube (in a SCM_CREDENTIALS or SCM_CREDS message if supported by the platform) will be signaled here if the client was set to attempt requiring credentials at the time of accepting this tube, and the protocol backend supports credential passing based access control. Otherwise, requiresCredentials will be false and no byte or associated out-of-band credentials metadata should be sent.

Parameters
listenAddressThe listen address of the local endpoint socket.
requiresCredentialstrue if credentialByte should be sent after connecting to the socket, false if not.
credentialByteThe byte to send if requiresCredentials is true.
accountA pointer to the account object through which the tube was offered.
tubeA pointer to the actual tube channel object.

◆ newConnection

void Tp::StreamTubeClient::newConnection ( const Tp::AccountPtr &  account,
const Tp::IncomingStreamTubeChannelPtr &  tube,
uint  connectionId 
)
signal

Emitted when a new connection has been made to the local endpoint socket for tube.

This can be used to later associate connection errors reported by connectionClosed() with the corresponding application sockets. However, establishing the association generally requires connecting only one socket at a time, waiting for newConnection() to be emitted, and only then proceeding, as there is no identification for the connections unlike the incoming connections in StreamTubeServer.

Note that the connection IDs are only unique within a given tube, so identification of the tube channel must also be recorded together with the ID to establish global uniqueness. Even then, the a connection ID can be reused after the previous connection identified by it having been signaled as closed with connectionClosed().

This is only emitted if connection monitoring was enabled when creating the StreamTubeClient.

Parameters
accountA pointer to the account through which the tube was offered.
tubeA pointer to the tube channel through which the connection has been made.
connectionIdThe integer ID of the new connection.

◆ connectionClosed

void Tp::StreamTubeClient::connectionClosed ( const Tp::AccountPtr &  account,
const Tp::IncomingStreamTubeChannelPtr &  tube,
uint  connectionId,
const QString &  error,
const QString &  message 
)
signal

Emitted when a connection (previously announced with newConnection()) through one of our handled tubes has been closed due to an error or by a graceful disconnect (in which case the error is TP_QT_ERROR_CANCELLED).

This is only emitted if connection monitoring was enabled when creating the StreamTubeClient.

Parameters
accountA pointer to the account through which the tube was offered.
tubeA pointer to the tube channel through which the connection had been made.
connectionIdThe integer ID of the connection closed.
errorThe D-Bus error name corresponding to the reason for the closure.
messageA freeform debug message associated with the error.