[Telepathy] Just what is stream directionality?

Simon McVittie simon.mcvittie at collabora.co.uk
Fri Mar 13 10:51:54 PDT 2009


I've recently been working on an example StreamedMedia connection manager,
in which simulated contacts can be called (having a simulated contact who
calls you whenever you go from Away to Available isn't far down the list
of things to do).

In the process, I've run into a problem with stream directionality: we
don't always know the direction of streams! When StreamAdded is emitted, it
doesn't tell the client about the stream direction (although when
RequestStreams returns, it does).

Introduction
============

Incoming calls have one or more streams. Each stream has a (current)
direction, which can be None, Receive, Send or Bidirectional. These are an
enum for historical reasons, but should be treated as a set of flags: neither,
either or both of Receive and Send.

Each stream also has a set of pending send flags, which can be neither, either
or both of Pending_Local_Send and Pending_Remote_Send.

For streaming from us to the remote contact, the possible states are
nothing (we are not sending and the remote contact is content with this),
Pending_Local_Send (we are not sending but the remote contact would like us
to), and Send (we are sending media). Send and Pending_Local_Send do not make
sense together.

Similarly, for streaming from the remote contact to us, the possible states
are nothing (the remote contact is not sending and we are content with this),
Pending_Remote_Send (they are not sending but we would like them to do so),
and Receive (we are receiving media). Receive and Pending_Remote_Send do not
make sense together.

How Gabble implements it
========================

Streams created by the remote contact are created with a direction set by
the Jingle content, except that if they asked for us to send, we transform that
into Pending_Local_Send so the user can approve it.

If a call to RequestStreamDirection enables sending, we'll accept a
pending local send if there is one; otherwise, we'll alter the "senders"
attribute on the Jingle content to inform the peer that we would like to send
them media.

When we move our own handle from local-pending to member state
(= accept the call), all currently pending local sends are automatically
accepted (i.e. we start sending if we were asked to).

Streams created by us are set to Bidirectional immediately; the remote contact
might refuse this by changing the direction at their end.

If a call to RequestStreamDirection enables receiving, we tell the remote
contact to send us media, and blindly assume that they will do so (the
StreamDirectionChanged signal immediately indicates that we expect to receive).
If they refuse our request, they'll do so by removing the Receive direction
later.

This appears to be because the protocol has no concept of an
intermediate/requested state. Conceptually, the stream is bidirectional
as soon as we say it is, and the contact's only recourse is to change it
back to (from their point of view) receive-only if they don't actually want
to send us media. This doesn't really seem right, though - surely they send
back *some* sort of affirmative response if they'll be sending us media?

How telepathy-sofiasip implements it
====================================

Streams created by the remote contact are receiving and pending local send,
which seems right.

If the call is on hold locally, streams created by the remote contact are
directionless and pending local send, which also seems right.

Streams created by the local contact are receiving and pending remote send,
which seems to me to be clearly wrong. Surely they should be sending and
pending remote send?

If the call is on hold locally, streams created by the local contact are
directionless and pending remote send, which seems OK (but why
would we want to request a stream if we've placed the call on hold,
and why aren't they directionless and not pending anything?)

When we request a stream direction, the code is a twisty maze of bitfields
that doesn't make sense to me right now - perhaps some vodka would help.
It doesn't look right to me at the moment, though...

What StreamAdded should imply
=============================

Possible solutions seem to be:

* Arbitrarily pick one of the possible directions (which one?) and declare it
  to be the default. In all other cases, emit StreamDirectionChanged
  immediately after StreamAdded.
* Require clients to call ListStreams after every StreamAdded to find out
  what's *really* going on.


More information about the telepathy mailing list