Stream Tubes allow you to proxy an existing network socket via Telepathy. Stream Tubes should be used when you wish to share an existing network protocol, for instance a HTTP stream, between two contacts.
Unlike D-Bus Tubes, multi-user Stream Tubes are point-to-point between the offerer and the accepter (see Figure 11-2). Stream Tubes cannot be used to multicast between members of the MUC room.
When creating a Stream Tube, you must specify the property org.freedesktop.Telepathy.Channel.Type.StreamTube.Service, which is the canonical name of the service your Tube is offering (e.g. ssh).
The StreamTube.Offer method takes four parameters:
Stream Tubes differ from D-Bus Tubes in that it is assumed that a Stream Tube will frequently be used to proxy an existing protocol or service. Thus unlike for D-Bus Tubes or file transfer, the socket you wish to offer must already be set up and listening as if you were writing a regular network service. This address is then passed to the Offer method. The socket can either be a UNIX socket, an IPv4 socket or an IPv6 socket.
The appropriate access control should be chosen based on the socket type and the service. Typically it will be either Socket_Access_Control_Localhost or Socket_Access_Control_Port.
Not all connection managers that support Stream Tubes support all combinations of address type and access control. Connection managers must at least offer IPv4 sockets with Socket_Access_Control_Localhost, other supported methods are listed in the SupportedSocketTypes property.
The parameter map is the same as for D-Bus Tubes.
For Stream Tubes, network addresses are passed as a variant type that varies based on the provided Socket_Address_Type. More information is provided in Section 9.1 ― Sending Files.
In general, Stream Tubes will be used to proxy an existing network protocol or application between contacts. However, if you wish to open your own socket, or your protocol library doesn't handle sockets for you, the you can serve your own network socket using GNIO.
/* create the network service */ GSocketService *socket_service = g_socket_service_new (); GInetAddress *inet_address = g_inet_address_new_loopback ( G_SOCKET_FAMILY_IPV4); GSocketAddress *socket_address = g_inet_socket_address_new ( inet_address, 0); g_object_unref (inet_address); g_socket_listener_add_address (G_SOCKET_LISTENER (socket_service), socket_address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, NULL, &server_sockaddr, &error); g_object_unref (socket_address); if (error) g_error ("%s", error->message); char *address_str = g_inet_address_to_string ( g_inet_socket_address_get_address ( G_INET_SOCKET_ADDRESS (server_sockaddr))); guint16 port = g_inet_socket_address_get_port ( G_INET_SOCKET_ADDRESS (server_sockaddr)); g_print ("address = %s\nport = %u\n", address_str, port); g_free (address_str); g_signal_connect (socket_service, "incoming", G_CALLBACK (socket_incoming), NULL); g_socket_service_start (socket_service);
telepathy-glib provides API to convert between Telepathy address variants and GSocketAddress objects: tp_address_variant_from_g_socket_address and tp_g_socket_address_from_variant.
An incoming Stream Tube appears as an incoming channel (see Section 6.2 ― Incoming Channels). The Tube will have two immutable properties that you can inspect; Service, which is a TCP service name (this should be a well-known IANA or DNS-SD service name, e.g. "ssh" or "_raap._tcp") and Parameters, the map of parameters passed to Offer.
The channel will be in the initial State Tube_Channel_State_Local_Pending, incidating that you have to Accept the Tube.
The StreamTube.Accept method takes three properties: a Socket_Address_Type, the type of address for this socket (e.g. TCP), a Socket_Access_Control, and a variant access control parameter.
D-Bus provides no NULL type, so even in cases where an optional variant is not required, a variant value must be provided (e.g. integer 0).
Example 11-3 provides an example for telepathy-glib.
GValue noop = { 0, }; g_value_init (&noop, G_TYPE_INT); tp_cli_channel_type_stream_tube_call_accept (channel, -1, TP_SOCKET_ADDRESS_TYPE_IPV4, TP_SOCKET_ACCESS_CONTROL_LOCALHOST, &noop, tube_accept_cb, NULL, NULL, NULL); g_value_unset (&noop);
The Accept method will return an address variant of the appropriate for the requeseted Socket_Address_Type (see above).