Use cases for dispatching channels

Contents

Incoming 1-1 text chats

dis1: Incoming 1-1 text chat

Juliet receives a message from Romeo that starts a new channel. Her desired UI resembles that of Empathy and of the Nokia internet tablets:

  • an icon flashes in the system tray, altering her to the incoming message in an unobtrusive way
  • when she clicks on the icon, a chat window opens
  • all incoming and outgoing messages are logged for later searching

Current implementation, dis1impl1:

NewChannel (Text, CONTACT, handle("romeo@montague.verona.fict"),
    suppress_handler=FALSE)

Mission Control runs filters, which include the blinking "new message"
icon in the system tray

When the tray icon is clicked, Mission Control continues processing
filters and eventually dispatches to the channel handler

Problems addressed by proposed implementation:

  • We want a logger (which might be in a separate process) to be told to handle incoming text channels. This may require that:

    • the logger is a filter; or
    • multiple channel handlers are supported (we launch the UI and the logger simultaneously); or
    • the UI starts the logger (good if the UI uses the logger, e.g. is just a view onto the logging database); or
    • the logger starts the UI (we won't do this, it's a layering violation)

    If there is a logger, only it should be acknowledging messages (there will be problems if both the logger and the UI try to ack messages). This is conceptually rather odd if the logger is a filter.

  • The logger should be started immediately, without waiting for the new conversation to be accepted

  • As currently implemented, if MC crashes, filters are forgotten and the "new message" notification is skipped in future - the chat window pops up straight away, possibly stealing focus (bad!)

  • As currently implemented, if Empathy crashes and is restarted, its filter will end up registered twice, so the user has to click the incoming message icon twice

Alternative implementation, dis1impl2:

  • The UI and the logger are both channel handlers, or the UI is a channel handler and the logger is a filter
  • There is no filter, except possibly the logger
  • The blinking notification icon is provided by the UI, guaranteeing that it always appears and that focus is never stolen

Problems with this alternative implementation:

  • The chat UI may take a while to start, particularly on slow embedded devices; we don't really want to pay this "cost" for conversations that the user is going to reject anyway. This could be solved by making the primary UI a very small launcher which just blinks the notification icon, then executes the real handler as a subprocess, via exec(2) or via dlopen(3) if needed

Proposed implementation:

  • The logger is an Client and a Client.Observer. It must be service-activatable to avoid missing any messages.
  • The tray icon is a Client and a Client.Approver
  • The chat UI is a Client and a Client.Handler (selected in an implementation-specific way)
  • Clients should not wait for the first message in an incoming channel - if a connection manager creates channels before a message arrives, clients should assume it has a valid reason to do so? ("psychic mode")

Dispatch process:

CM emits Requests.NewChannels([(channel_path,
    {
        '...ChannelType': '...Text',
        '...TargetHandleType': CONTACT,
        '...TargetHandle': 1234,
        '...TargetID': 'romeo@montague.example.com',
        '...Requested': FALSE,
        ...
    },
    )])

In response, CD calls ObserveChannels on all matching Observers, including
org.freedesktop.Telepathy.Client.EmpathyLogger

CD creates a ChannelDispatchOperation

CD calls AddDispatchOperation on all matching Approvers, including
org.freedesktop.Telepathy.Client.EmpathyTrayIcon

Empathy tray icon flashes

Juliet clicks on tray icon and chooses Accept

Empathy tray icon calls
HandleWith('org.freedesktop.Telepathy.Client.EmpathyChat')

ChannelDispatchOperation emits Closed

(At or before this point, the CD must wait for all the Observers to return
from ObserveChannels if they have not already done so)

CD calls HandleChannels on Empathy chat process (service-activating it
if needed)

dis2a: Incoming 1-1 text message with lost window

Juliet receives a message from Romeo after a pause in their conversation.

Current implementation, dis2impl1: it arrives in the Text channel

Potential problem: if the chat UI is not currently visible, as currently implemented it cannot necessarily use the same mechanism to notify the user that would be used for a new channel, because it doesn't "own" the notification mechanism for the new-channel case

Proposed solution: if the the chat UI is in the same process as the notification mechanism, all is good - it can prod the notifier directly. If it's not, then it can use a D-Bus API outside the scope of this spec to do the same. (Avoiding premature generalization and assuming clients to be competent)

dis2b: Incoming 1-1 text message with crashed handler

Juliet receives a message from Romeo after her chat UI has crashed.

Current implementation: it arrives in the Text channel, which nothing is handling, and is lost

Proposed implementation: when a ChannelHandler that was handling a channel falls off the bus, the channel dispatcher closes the channel. If the channel is of type Text, it restarts when the new message arrives.

dis3: Incoming 1-1 text message with window closed

After a pause in a conversation with Romeo, Juliet closes the IM window or tab. She then receives another message from Romeo, resuming the conversation.

Incorrect implementation, dis3impl1:

  • The Text channel is not closed
  • The new message causes the chat window to pop up, possibly stealing focus

Problems with dis3impl1:

  • Focus stealing is likely

Current implementation in Empathy, dis3impl2:

  • The Text channel is closed (depending on protocol, this may be visible to the remote user, e.g. MSN's "Juliet has closed the window")
  • As a result, the new message is indistinguishable from a new channel (dis1)

Problems with dis3impl2:

  • Not associated with the previous chat session, although this could be fixed with "conversation thread IDs" as in req27
  • Zdra doesn't think the Chat UI should Close() text channels, although in Message-ID: <1209127037.6294.41.camel@zdra-laptop> he doesn't provide any rationale or use cases. (Zdra, could you explain please?)

Alternative implementation, dis3impl3:

  • the same as dis3impl1, but use the same notification icon as for a new channel (dis1), and only pop up the main chat UI window if accepted
  • in practice this would give basically the same UI as for dis3impl2, but without actually closing the channel

Problems with dis3impl3:

  • if it is desirable to tell the remote user that the window has been closed, the CM can't know

Proposed implementation: keep dis3impl2, and later use conversation thread IDs as per req27 to solve the problem above

dis4: Incoming 1-1 text chat thread

While talking to Romeo in one IM window or tab, Juliet receives a message from him in a separate "thread" of conversation.

Current implementation: impossible on protocols where 1-1 chats are not just a special case of ad-hoc chatrooms, since we guarantee uniqueness per (handle type, handle, channel type) for all handle types except NONE

Proposed implementation:

  • The new thread is announced as a separate ChannelBundle (channels in each bundle have a ThreadID property)
  • The new thread is dispatched to observers, approvers and the handler separately

Invitations to named chatrooms

dis7: Incoming named-chatroom invitation

Romeo is invited to a named chatroom by Mercutio.

Current implementation:

NewChannel (Text, ROOM, handle("The Capulets' ball"),
    suppress_handler=FALSE)

Mission Control runs filters, which include a notification
icon in the system tray

When the tray icon is clicked, Mission Control continues processing
filters and eventually dispatches to the channel handler

The channel handler moves Romeo from local-pending to members.

Problems and variations: same as dis1

Proposed implementation:

CM emits Requests.NewChannels([(channel_path,
    {
        '...ChannelType': '...Text',
        '...TargetHandleType': ROOM,
        '...TargetHandle': 123,
        '...TargetID': 'ball@conference.capulet.example.com',
        '...Requested': FALSE,
        '...InitiatorHandle': 6543,
        '...InitiatorID': 'mercutio@example.com',
        ...
    },
    )])

In response, CD calls ObserveChannels on all matching Observers, including
org.freedesktop.Telepathy.Client.EmpathyLogger

CD creates a ChannelDispatchOperation

CD calls AddDispatchOperation on all matching Approvers, including
org.freedesktop.Telepathy.Client.EmpathyTrayIcon

Empathy tray icon flashes

Romeo clicks on tray icon and chooses "Join room"

Empathy tray icon calls
HandleWith('org.freedesktop.Telepathy.Client.EmpathyChatroom')

ChannelDispatchOperation emits Closed

(At or before this point, the CD must wait for all the Observers to return
from ObserveChannels if they have not already done so)

CD calls HandleChannels on Empathy chat process (service-activating it
if needed)

dis14, dis28: Forcibly joining a chatroom

Benvolio connects to an irssi-proxy, bip or other IRC bouncer running on some colo box somewhere. The proxy informs his client that he is already in #telepathy and #farsight.

Current implementation: same as dis7, but Benvolio is already in the members set for those channels.

Problems:

  • Empathy's filter (notification icon) considers these channels to be incoming and waits for the first received message before blinking the status icon, which means Benvolio thinks his proxy instance has lost its connection to those channels

Issues to bear in mind:

  • These Text channels are neither incoming nor outgoing - they are in a third state, "automatically created". I don't think it's very useful to distinguish between this and incoming, though.

Proposed implementation:

  • The channels have Requested=FALSE, just like incoming channels
  • Clients should not wait for the first message in an incoming channel - this would break chatroom invitations in any case
  • If a connection manager creates channels before a message arrives, clients should assume it has a valid reason to do so? ("psychic mode")

Incoming VoIP calls

dis8: Incoming VoIP call

Romeo receives a VoIP call from Juliet. He answers.

Current implementation: similar to dis1, but the channel has type StreamedMedia, handle type NONE and handle 0; all the UI components must investigate the channel's Group interface to find out who's calling.

Problems:

  • The Group interface is unnecessarily complex just to find out who's calling

Proposed implementation:

CM emits Requests.NewChannels([(channel_path,
    {
        '...ChannelType': '...Text',
        '...TargetHandleType': CONTACT,
        '...TargetHandle': 6,
        '...TargetID': 'juliet@capulet.example.com',
        '...Requested': FALSE,
        # and perhaps...
        '...InitiatorHandle': 6,
        '...InitiatorID': 'juliet@capulet.example.com',
        ...
    },
    )])

In response, CD calls ObserveChannels on all matching Observers, including
org.freedesktop.Telepathy.Client.EmpathyLogger

CD creates a ChannelDispatchOperation

CD calls AddDispatchOperation on all matching Approvers, including
org.freedesktop.Telepathy.Client.EmpathyTrayIcon

Empathy tray icon flashes

Romeo clicks on tray icon and chooses Answer

Empathy tray icon calls
HandleWith('org.freedesktop.Telepathy.Client.EmpathyVoIP')

ChannelDispatchOperation emits Closed

(At or before this point, the CD must wait for all the Observers to return
from ObserveChannels if they have not already done so)

CD calls HandleChannels on Empathy VoIP process (service-activating it
if needed)

dis9: Missed incoming VoIP call

Romeo receives a VoIP call from Juliet. He does not answer, and Juliet eventually gives up and cancels the call.

Current implementation: as for dis8

Problems:

Proposed implementation:

  • As for dis8. The properties ...Channel.InitiatorHandle, ...Channel.InitiatorID indicate Juliet's handle and ID (JID, SIP URI, etc.) immediately. TargetHandle and TargetID also indicate the same information, although there are backwards-compatibility issues.
CM emits Requests.NewChannels([(channel_path,
    {
        '...ChannelType': '...Text',
        '...TargetHandleType': CONTACT,
        '...TargetHandle': 6,
        '...TargetID': 'juliet@capulet.example.com',
        '...Requested': FALSE,
        # and perhaps...
        '...InitiatorHandle': 6,
        '...InitiatorID': 'juliet@capulet.example.com',
        ...
    },
    )])

In response, CD calls ObserveChannels on all matching Observers, including
org.freedesktop.Telepathy.Client.EmpathyLogger

CD creates a ChannelDispatchOperation

CD calls AddDispatchOperation on all matching Approvers, including
org.freedesktop.Telepathy.Client.EmpathyTrayIcon

Empathy tray icon flashes

Time passes, Juliet gives up and hangs up the call

CM emits ChannelClosed(channel_path)

ChannelDispatchOperation emits Closed

Problems remaining:

  • Perhaps the ChannelDispatchOperation should emit a different signal, which indicates that the channel was closed by Juliet rather than by Romeo? This would require the CD to watch the Channel's Group interface etc., not just Connection.Interface.Requests; or perhaps the ChannelClosed signal should contain a D-Bus error code?

Contact lists

dis11: A contact list is found during login

Romeo logs on to an IM service. As part of the connection process, contact list channels for the various predefined CONTACT_LIST handles, e.g. subscribe, are created automatically by the connection manager, as specified by the Telepathy API.

Current implementation:

NewChannel (ContactList, LIST, handle("subscribe"),
    suppress_handler=FALSE)

Mission Control dispatches to the channel handler

Problems:

  • Can we register more than one channel handler for contact lists? Every process with a contact-list UI might be interested in them - or not, since best practice is to request the contact lists that you want to use
  • On Maemo devices, the address-book synchronization process is currently a handler for contact lists - this excludes the possibility of a third-party process that does the same thing
  • Client authors would prefer to wait for all contact lists to arrive (or definitely not arrive), then query for all those contacts' aliases, avatars etc. in one big transaction, and only then display them - but that's impossible if the client is being passive, because it can't know whether the 'publish' channel hasn't arrived yet, or will never arrive because the CM doesn't support it

Proposed implementation:

  • Clients SHOULD NOT rely on being channel handlers for contact lists; clients SHOULD explicitly request any contact list channels that they want to use
  • Clients interested in contact lists should be Observers and observe them, instead of relying on being a channel handler
  • In the long term, we should switch to a Connection.Interface.Roster

dis12: A user-defined contact group is found during login

Romeo logs on to an IM service. As part of the connection process, contact list channels are created automatically by the connection manager for all the GROUP handles he has previously defined, as specified by the Telepathy API.

Current implementation:

NewChannel (ContactList, GROUP, handle("Montagues"),
    suppress_handler=FALSE)

Mission Control dispatches to the channel handler

Problems addressed by proposed implementation:

  • Can we register more than one channel handler for groups? Every process with a contact-list UI might be interested in them

Proposed implementation dis12impl1:

  • Each contact list UI is an Observer for groups
  • There is no channel handler for groups

Problems remaining:

  • Clients can't know when we've finished creating groups (see dis11), but it is desirable for clients not to display anything until all groups and all contact lists have arrived
  • We'd have to avoid making the channel dispatcher panic and close the "unhandled" group
  • In the long term, we should switch to a Connection.Interface.Roster

dis13: A user-defined contact group is created

Romeo is connected to the same XMPP account using his PC and his N800. He uses the PC to create a contact group, "My true love", and adds Juliet to it. On the N800 he expects the new group to appear automatically.

Current implementation:

NewChannel (ContactList, GROUP, handle("My true love"),
    suppress_handler=FALSE)

Mission Control dispatches to the channel handler

Problems: same as dis12

Possible solution: same as dis12

Invitations to ad-hoc chatrooms

dis15: Invitation to an ad-hoc chatroom with one user

Juliet receives a message from Romeo using MSN, in which "1-1" conversations are actually ad-hoc chatrooms with exactly two members. She would like this to be indistinguishable from Romeo sending her a message over XMPP, in which 1-1 conversations are really 1-1.

Current implementation:

NewChannel (Text, NONE, 0, suppress_handler=FALSE)

The channel is passed through filters, etc.

Problems:

  • Same as dis8 and dis1 combined
  • It's unclear whether Juliet should be in member or local-pending state in the new channel

dis16: Invitation to an ad-hoc chatroom with multiple users

Romeo receives an invitation to join an ad-hoc chatroom currently containing Mercutio and Benvolio.

Current implementation:

NewChannel (Text, NONE, 0, suppress_handler=FALSE)

The channel is passed through filters, etc.

Problems:

  • Same as dis15, but the desired state (member vs local pending) might be different

dis17: Upgrading a 1-1 chat to a named or ad-hoc chatroom

Mercutio is talking to Benvolio in a 1-1 chat. Benvolio upgrades the chat to a chatroom in order to invite Romeo to join in.

Current implementation: none

File transfers

dis18: Receiving a file in the context of a conversation

Juliet is talking to Romeo using a text or VoIP UI when he sends her a file in the context of that conversation. If it implements file transfer functionality, the text or VoIP UI should handle the file transfer; otherwise, the channel dispatcher should fall back to launching a standalone file transfer handler.

Proposed implementation and problems: same as dis5

dis19: Receiving a file unexpectedly

Juliet is not interacting with Romeo when he sends her a file. Some appropriate UI needs to be launched to indicate that the file has been offered.

Proposed implementation: same as dis1

dis20: Receiving a file in a collaborative application

File transfers might be a useful model for collaborative applications to use to transfer snapshots of state, or to transfer related files (e.g. in a word processor, you could receive an inline image that is embedded in the document). This is much like dis6.

Additional problems: if the file transfer is part of the word processor's IPC mechanism, then it really wants to get the file transfer, rather than having another process get it as a result of a situation like dis5c.

Proposed implementation: Don't do this.

dis31: unified download manager

An applet displays all file transfers made using Telepathy, Firefox, etc.

Proposed implementation: it's an Observer for all file transfers

Tubes

dis21: Invited to One Laptop per Child Activities, as of early 2008

An OLPC Activity instance encapsulates an instance of an application, zero or more D-Bus tubes and zero or more stream tubes to transfer messages or state between participants, and a text chatroom to discuss the activity.

In the "1.0" protocol used in early 2008, each Activity instance is backed by an XMPP or Clique MUC (chatroom).

Current implementation: we assume that the channels (Tubes, ROOM, foo) and (Text, ROOM, foo) correspond 1:1. Activity discovery is done out-of-band using OLPC-specific extensions, although we'd like to make some of it more standard (mainly invitations).

Problems:

  • we don't want Tubes channels in their current form, since dispatching them is likely to be a bit of a nightmare if we can't rely on OLPC assumptions; we want one channel per Tube instead
  • in a less constrained environment, two different collaborative applications could conceivably share a MUC (the OLPC UI can't cause this to happen, but would likely get incredibly confused if it did)

Proposed implementation:

  • Each Tube is its own channel
  • OLPC Activities map 1:1 to conversation threads
  • For compatibility with older OLPC code, we place each activity thread in a new chatroom
  • For compatibility with older OLPC code, the Tubes channel type still exists in a deprecated state

dis22: Invited to be a client in an existing UDP/TCP client/server protocol

(Use-cases req24, req25)

Tybalt asks Juliet to help him fix a problem with his computer, and offers her a VNC connection to his computer so she can interact with his desktop.

  • or -

Romeo offers Mercutio and Benvolio access to an OpenArena server running on his local computer.

Proposed implementation:

  • Each TCP/UDP Tube is its own channel, with a thread ID associated with it

Failures and other exceptional cases

dis23: Client-side blocking

Rosalind has blocked messages and calls from Romeo. However, her IM service does not support server-side blocking, so her client must implement blocking on the client side.

(A similar approach can be used to implement other privacy models, such as "only allow messages from contacts on my publish list".)

Current implementation: a filter in Mission Control 4.x

Proposed implementation: a filter (dlopen()ed or hard-coded) in Mission Control 5.x - we do not propose to allow this sort of thing over D-Bus

Miscellaneous

dis24: multiple notification mechanisms

(From Frederic Peters on the mailing list)

Frederic wants to see IM messages appear as some sort of overlay when Totem is running full-screen.

Problems:

  • Having Totem, mplayer, OpenArena and every other full-screen app know about Telepathy messages, gnome-power-manager low-battery warnings and every other source of notifications doesn't really scale. Can't we solve this at the level of the fd.o Desktop Notification spec instead?

Proposed implementation:

  • any application that really wants to know about Telepathy channels can be an Approver

dis29: multiple notification mechanisms (2)

A Telepathy gnome-panel applet needs to be able to indicate incoming calls or channels. The Empathy contact list window should also be able to indicate incoming calls or channels, e.g. by highlighting the contact.

Proposed implementation: they're both Approvers

dis25: brightness on portable devices

(From the Nokia Internet Tablets, but also generally applicable)

Naba's Internet tablet dims the screen when not in use. When a message or call comes in, the screen backlight should come up to normal brightness.

Current implementation: a filter in Mission Control 4.x?

Problems: is this really just a special case of dis24?

Proposed implementation: either a filter in Mission Control 5.x, or the device-state service (which handles the backlight) can be made an Observer

dis26: multiple channel handlers available - 1

Romeo has both Kopette and Empathy installed on his system and both clients are able to handle text channels. Romeo wants to be able to choose between kopette and empathy just like he can choose between epiphany and firefox to handle http urls (see gnome-default-applications-properties).

Problems:

  • There is no way currently to choose between channel handlers, Mission Control 4.x only accepts one chandler.

Proposed implementation:

  • The channel dispatcher prioritizes channel handlers in an implementation-dependent way
  • Approvers can select which one to use from among several possible channel handlers, for incoming channels only

Problems remaining:

  • Should outgoing channels go through approvers, just to have a way to influence the choice of handler?
  • What about automatic or unknown-directionality channels?

dis27: multiple channel handlers available - 2

Romeo has both Empathy and Elisa installed. When elisa is running fullscreen he wants it to handle outgoing and incoming calls, otherwise he wants empathy to handle them.

Problems:

  • There is no way currently to choose between channel handlers, Mission Control 4.x only accepts one chandler.
  • Empathy's filter will get the media channel before elisa's chandler, so the status icon will blink and Romeo won't see it because elisa is running fullscreen.

Proposed implementation:

  • elisa is an Approver which claims incoming channels using Claim(). The Empathy status icon blinks momentarily, but this is not visible, and because there is no user action, Empathy never approves anything

dis30: monolithic client

A monolithic Telepathy client on a resource-constrained platform responds to new channels without the help of a channel dispatcher implementation.

Current implementation: the client sets suppress_handler=TRUE on all its channel requests, and ignores NewChannel signals that have suppress_handler=TRUE

Proposed implementation: a straightforward port of the current implementation

dis32: Channel Dispatcher crash recovery

The channel dispatcher crashes. Some other component (probably a UI) notices and restarts it. The channel dispatcher must reconcile its internal state with what's actually going on.

It is likely that the channel dispatcher and the account manager are in fact the same process (Mission Control and Decibel are both implemented like this), so we must be able to cope with a simultaneous CD and AM crash.

Current implementation: Nokia's Mission Control 4 calls Disconnect on all connections, causing reality to reflect its internal state. Obviously, this isn't ideal (and can cause messages to be lost).

Proposed implementation: The channel dispatcher discovers existing connections and channels, causing its internal state to reflect reality.

More specifically:

  • before it calls Connect on each new connection, the account manager saves the association between connections and accounts to a cache
  • during startup, the account manager discovers existing connections, and reads that cache to find out which ones correspond to an account that it manages
  • the channel dispatcher discovers from the account manager which connections it should manage
  • the CD lists the channels on each connection (call this set E)
  • the CD also discovers all clients (by looking for o.fd.T.Client.* bus names) and lists the channels that each client is handling (call this set H)
  • the CD now knows what everyone is handling
  • now the CD can dispatch every unhandled channel (the set E H) as if newly created

dis33: One channel (of many) is closed while in Dispatcher

The NewChannels signal carries 2 or more channels. One or more of these channels, but not all of them, emit Closed before the CD has a chance to invoke some or all of the Clients.

Current implementation: Nokia's Mission Control 4 supports dispatching of only one channel at a time, and if that channel is closed, the operation is aborted (i.e., clients don't even see the channel).

Proposed implementation: the CD behaves as if nothing happened, and happily dispatches the channels (including the dead ones) to the clients.

Problems addressed:

  • in case the channels are the result of a ChannelRequest, the request can still be listed among the "Satisfied_Request" argument of the HandleChannels. This means that the client can map the channels to the request it made, it can see the properties of all the channels that were created (they are passed in HandleChannels' arguments) and in any case it will have to cope with the fact that a channel is no longer there.
  • ChannelDispatcher code is simpler.