Contents
Romeo has a chat or IM UI open already, and wants to use it to chat to Juliet. He selects Juliet from a contact list or types in her username on some IM service.
Current implementation:
if a channel with GetHandle() -> (CONTACT, juliet) exists: foreground its window or tab else: RequestChannel (Text, CONTACT, juliet, suppress_handler=TRUE)
Proposed implementation:
if a channel with TargetHandleType == CONTACT and TargetHandle == juliet is being handled by the chat UI: foreground its window or tab (no interaction with the ChannelDispatcher) stop here (note: this check is optional, the process below can cope with the case where the chat UI is already handling the desired channel) chat UI calls ChannelDispatcher.EnsureChannel( account, { '...ChannelType': '...Text', '...TargetHandleType': CONTACT, '...TargetHandle': juliet }, timestamp, its_own_bus_name ) chat UI connects to signals and calls ChannelRequest.Proceed() ChannelDispatcher calls AddRequest on chat UI, chat UI ignores it as the request is already known to it try: ChannelDispatcher tells AccountManager to put account online ChannelDispatcher calls EnsureChannel ({...same arguments...}) on success, with Yours = TRUE: channel observers run (if and only if NewChannels emitted) ChannelRequest emits Succeeded, chat UI ignores its arguments channel approvers do not run CD calls HandleChannels on chat UI chat UI handles channel on success, with Yours = FALSE: if we're already handling this channel: foreground it else: chat UI isn't allowed to handle the channel (someone else is) CR emits Failed and CD calls RemoveFailedRequest with error o.fd.T.E.NotYours FIXME: could perhaps try calling CreateChannel to get a new thread? on failure: ChannelDispatcher calls RemoveFailedRequest on chat UI, and ChannelRequest emits Failed chat UI displays failure
Juliet wants to talk to Romeo. She chooses his entry in an address book or other list of people (not necessarily Telepathy-centric) and is presented with a list of possible ways to talk to him. She decides to use text chat.
New vs. existing: | |
---|---|
Existing channel preferred, new channel acceptable | |
Definition of channel identity: | |
ChannelType is Text, TargetHandleType is CONTACT, TargetHandle is romeo |
Current implementation:
address book asks Mission Control for a channel with (Text, CONTACT, romeo) Mission Control calls RequestChannel (Text, CONTACT, romeo, suppress_handler=FALSE) on CM Mission Control dispatches the channel to the default/only handler if the channel is new: the channel handler creates a new window or tab else: the channel handler puts the existing window or tab in the foreground
Things smcv considered to be problems:
Proposed implementation:
address book calls ChannelDispatcher.EnsureChannel( account, { '...ChannelType': '...Text', '...TargetHandleType': CONTACT, '...TargetHandle': romeo, }, timestamp, '' ) address book connects to signals and calls ChannelRequest.Proceed ChannelDispatcher calls AddRequest on chat UI, which makes a new tab (if it is not already handling such a channel) [+] try: ChannelDispatcher tells AccountManager to put account online ChannelDispatcher calls EnsureChannel ({...same arguments...}) on creation of new channel: channel observers run ChannelRequest emits Succeeded, address book ignores its arguments channel approvers do not run CD calls HandleChannels on chat UI chat UI handles channel on return of existing channel: (this is req2a) on failure: ChannelDispatcher calls RemoveFailedRequest on chat UI (1) ChannelRequest emits Failed (2) chat UI displays failure in response to (1) address book displays failure in response to (2)
After use-case req2 has happened, Juliet loses the chat window somewhere on her desktop (but it is still open). She wants to continue to talk to Romeo, and chooses his entry in her address book again.
Proposed implementation:
initially the same as for req2 (until [+]) ChannelDispatcher tells AccountManager to put account online ChannelDispatcher calls EnsureChannel ({...same arguments...}) CM returns existing channel ChannelRequest emits Succeeded, address book ignores its arguments channel observers and approvers do not run CD calls HandleChannels on handler of existing channel handler of existing channel brings channel to foreground
Juliet is about to open a text conversation with Romeo as per req2, when Romeo sends her a message as in dis1. Instead of responding to the "new message" notification, she continues to select "Chat with Romeo" in her address book.
The intended result is that there is exactly one Text channel talking to Romeo.
Proposed implementation:
New channel comes in: 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 [cdo1] CD calls AddDispatchOperation on all matching Approvers, including org.freedesktop.Telepathy.Client.EmpathyTrayIcon Empathy tray icon flashes Juliet tells address book to open a channel to Romeo: address book calls ChannelDispatcher.EnsureChannel( account, { '...ChannelType': '...Text', '...TargetHandleType': CONTACT, '...TargetHandle': romeo, }, timestamp, '' ) (this returns cr1, say) address book calls ChannelRequest.Proceed() on cr1 ChannelDispatcher calls AddRequest on chat UI, which makes a new tab ChannelDispatcher tells AccountManager to put account online (no-op) ChannelDispatcher calls EnsureChannel ({...same arguments...}) CM returns existing channel ChannelRequest cr1 emits Succeeded, address book ignores its arguments CD considers the request for an existing channel to have constituted approval of the CDO, so ChannelDispatchOperation cdo1 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 SHOULD give the request's preferred handler precedence over the CDO's in choosing the chat UI CD calls HandleChannels on chat UI (service-activating it if needed)
Romeo is collaborating on a document with Mercutio, and wants to have a chat embedded in his AbiWord instance, separate from any other chat with Mercutio that may be ongoing.
New vs. existing: | |
---|---|
New channel required [1] | |
Definition of channel identity: | |
ChannelType is Text, TargetHandleType is CONTACT, TargetHandle is mercutio, Bundle is the same as the AbiWord Tube channel |
[1] | If the collaborative app already has a suitable channel, it is expected to work this out without the channel dispatcher's help. Stealing a channel from another UI is likely to fail (e.g. in the Text interface, they'll both try to acknowledge messages) so we should forbid this for sanity's sake |
Current implementation: impossible, even in protocols supporting conversation threads, because the spec can't represent them
Proposed implementation:
let bundle_id = ...Bundle property of AbiWord Tube channel if a channel with TargetHandleType == CONTACT, TargetHandle == mercutio and Bundle == bundle_id is being handled by AbiWord: nothing to do, we already have a Text channel: stop AbiWord calls ChannelDispatcher.CreateChannel( account, { '...ChannelType': '...Text', '...TargetHandleType': CONTACT, '...TargetHandle': mercutio, '...Bundle': bundle_id, }, timestamp, abiword_client_bus_name ) AbiWord calls ChannelRequest.Proceed() ChannelDispatcher calls AddRequest on AbiWord, AbiWord ignores it as the request is already known to it try: ChannelDispatcher calls CreateChannel ({same dictionary as above}) on success: channel observers run ChannelRequest emits Succeeded channel approvers do not run CD calls HandleChannels on AbiWord AbiWord handles channel on failure: ChannelDispatcher calls RemoveFailedRequest on AbiWord, and ChannelRequest emits Failed AbiWord displays failure if the error is the EEXIST equivalent, the message might be "Already talking to Mercutio in another app, and multiple threads are not possible in this protocol"
(Fallback behaviour if the CM is pre-Requests: the request is made with suppress_handler = TRUE.)
Romeo is talking to Juliet using text chat, but is disconnected due to network instability. After reconnecting, he wants to keep using the same window to talk to Juliet.
A solution for this use case should work correctly (and result in a single channel) if there is a "mid-air collision" with Juliet doing the same thing, with Juliet sending messages to Romeo while he is still offline (on store-and-forward protocols like XMPP), or with Juliet recovering from Romeo's disconnection as per req28 (on protocols that do not allow offline messages).
(Recovering from a connection manager crash is equivalent to this.)
New vs. existing: | |
---|---|
??? | |
Definition of channel identity: | |
ChannelType is Text, TargetHandleType is CONTACT, TargetHandle is juliet, ThreadID is the same as before |
Current implementation: same as req1
Problems addressed by proposed implementation:
Proposed implementation (with a new Chan.I.Thread):
Romeo's chat UI (or incoming message database) automatically saves the ...Channel.Interface.Thread.ThreadID property of the old channel Disconnect/reconnect occurs Same as req1, except that ThreadID is included in the request
Problems remaining:
Resolution: defer the threads spec til later, https://bugs.freedesktop.org/show_bug.cgi?id=16544
The same as req26, but before Romeo's client can open the replacement channel, Juliet sends him a message, thus opening a new channel. (This is really a dispatching problem, but is closely related...)
The desired behaviour is that the same handler receives the channel.
Imagine that Romeo has both Kopete and Empathy installed, and Empathy is the default, but Romeo is using Kopete to talk to Juliet.
Naive implementation: either the race is won by the request for a replacement channel (and Kopete gets it) or it's won by Juliet's message creating a new channel (and Empathy gets it).
Too-clever implementation: in principle, there's nothing to stop the channel dispatcher remembering that a channel handler has lost a channel, and using that as input to its handler-choosing heuristic
Romeo chooses a past conversation with Juliet in a log browser and wants to resume it. (The definition of threading in XMPP expects that this is possible.)
New vs. existing: | |
---|---|
Existing channel preferred, new channel acceptable | |
Definition of channel identity: | |
ChannelType is Text, TargetHandleType is CONTACT, TargetHandle is juliet, ThreadID is the same as before |
Current implementation: same as req2
Problems addressed by proposed implementation: Juliet cannot distinguish between this case and req2
Proposed implementation: same as req26, except that it resembles req2 instead of req1 (i.e. no SUPPRESS_HANDLER flag)
Problems remaining: same as req26 (including a potential race, like req26b)
Resolution: defer the threads spec til later, https://bugs.freedesktop.org/show_bug.cgi?id=16544
Juliet is talking to Romeo using text chat when Romeo is disconnected due to network instability. The protocol is one that does not allow offline messages to be sent, like IRC. After Romeo reconnects, Juliet wants to keep using the same window to talk to him.
A solution for this use case should work correctly (and result in a single channel) if there is a "mid-air collision" with Romeo doing the same thing, or with Romeo recovering from disconnection as per req26.
(Recovering from Romeo's connection manager crash is equivalent to this.)
Current implementation: Juliet's text channel does not close, but she cannot send messages. When Romeo reconnects, because of 1-1 chat uniqueness, Juliet's client continues to use the same channel and there is no disconnection.
Proposed implementation: Juliet's client continues to use the same channel
Problems remaining: how do we ensure that?
Romeo has a VoIP UI open already, and wants to use it to chat to Juliet. He selects Juliet from a contact list or types in her username on some IM service.
New vs. existing: | |
---|---|
New channel required (same reasoning as req1) | |
Definition of channel identity: | |
??? |
Theoretical implementation:
if a channel containing handle juliet exists: foreground its window or tab else: RequestChannel (StreamedMedia, NONE, 0, suppress_handler=TRUE) RequestStreams (juliet, [AUDIO, VIDEO])
Problems:
Resolved problems:
Unless the VoIP UI keeps a table of (handle => channel) (which can't necessarily be done - some protocols allow "parallel" calls), the following race condition:
choose to call Juliet RequestChannel (StreamedMedia, NONE, 0, suppress_handler=TRUE) (request A) choose to call Juliet RequestChannel (StreamedMedia, NONE, 0, suppress_handler=TRUE) (request B) Request A returns /.../ChannelA Request B returns /.../ChannelB
can result in unnecessarily opening two parallel calls to the same contact.
(For instance: Empathy users sometimes incorrectly double-click on the Call button, resulting in two calls.)
Resolution: UIs are responsible for not doing this. For instance, Empathy should disable (make insensitive) the Call button just before requesting a streamed media channel, and re-enable it when the request has either failed or succeeded.
Practical implementation:
if a channel containing handle juliet exists: foreground its window or tab else: RequestChannel (StreamedMedia, NONE, 0, suppress_handler=TRUE) AddMembers ([juliet]) RequestStreams (juliet, [AUDIO, VIDEO])
Problems:
Deprecated implementation:
if a channel containing handle juliet exists: foreground its window or tab else: RequestChannel (StreamedMedia, CONTACT, juliet, suppress_handler=TRUE) RequestStreams (juliet, [AUDIO, VIDEO])
Problems:
Proposed implementation: (FIXME: requires InitialAudio, InitialVideo in spec)
if a streamed media call with Juliet is being handled by the call UI: foreground its window or tab (no interaction with the ChannelDispatcher) else: call UI calls ChannelDispatcher.CreateChannel( account, { '...ChannelType': '...StreamedMedia', '...TargetHandleType': CONTACT, '...TargetHandle': juliet, '...InitialAudioStream': TRUE, '...InitialVideoStream': TRUE, }, timestamp, its_own_bus_name ) call UI calls ChannelRequest.Proceed() ChannelDispatcher calls AddRequest on call UI, call UI ignores it as the request is already known to it try: ChannelDispatcher tells AccountManager to put account online ChannelDispatcher calls CreateChannel ({...same arguments...}) on success: channel observers run ChannelRequest emits Succeeded, call UI ignores its arguments channel approvers do not run CD calls HandleChannels on call UI call UI handles channel on failure: ChannelDispatcher calls RemoveFailedRequest on call UI, and ChannelRequest emits Failed call UI displays failure
Juliet wants to talk to Romeo. She chooses his entry in an address book or other list of people (not necessarily Telepathy-centric) and is presented with a list of possible ways to talk to him. She decides to use a VoIP call.
New vs. existing: | |
---|---|
Existing channel preferred? New channel acceptable | |
Definition of channel identity: | |
??? |
Current implementation:
RequestChannel (StreamedMedia, NONE, 0, suppress_handler=FALSE) perhaps AddMembers ([romeo]) RequestStreams (romeo, [AUDIO, VIDEO]) The channel handler creates a new window or tab for the new channel
Problems:
Deprecated (?) implementation:
ask Mission Control for a channel (StreamedMedia, CONTACT, romeo) Mission Control does... something?
Problems:
Proposed implementation: (FIXME: needs same extra API as req4 and req2 combined)
address book calls ChannelDispatcher.StartRequest address book calls ChannelRequest.EnsureChannelByAccount( account, { '...ChannelType': '...StreamedMedia', '...TargetHandleType': CONTACT, '...TargetHandle': juliet '...InitialAudioStream': TRUE, '...InitialVideoStream': FALSE, }, timestamp, '' ) ChannelDispatcher calls AddRequest on call UI, call UI makes a new tab try: ChannelDispatcher tells AccountManager to put account online ChannelDispatcher calls EnsureChannel ({...same arguments...}) on creation of new channel: channel observers run ChannelRequest emits Succeeded, address book ignores its arguments channel approvers do not run CD calls HandleChannels on call UI call UI handles channel on return of existing channel: ChannelRequest emits Succeeded, address book ignores its arguments channel observers and approvers do not run CD calls HandleChannels on handler of existing channel handler of existing channel brings channel to foreground on failure: ChannelDispatcher calls RemoveFailedRequest on call UI (1) ChannelRequest emits Failed (2) call UI displays failure in response to (1) address book displays failure in response to (2)
Romeo is collaborating on a document with Mercutio, and wants to have a call embedded in his AbiWord instance, separate from any other call with Mercutio that may be ongoing.
Current implementation: same as req5
Problems: same as req5
Proposed implementation: same as req5, but ask for a new channel in a bundle (like in req3)
Romeo is talking to Juliet using VoIP, but is disconnected due to network instability. After reconnecting, he wants to keep using the same window to talk to Juliet.
A solution for this use case should ideally work correctly (and result in a single channel) if there is a "mid-air collision" with Juliet doing the same thing, or with Juliet recovering from Romeo's disconnection as per req30.
(Recovering from a connection manager crash is equivalent to this.)
Current implementation: same as req4
Problems:
Proposed implementation: same as req4, revisit later if the problems are felt to be serious
Juliet is talking to Romeo using VoIP when Romeo is disconnected due to network instability. After reconnecting, Juliet wants to keep using the same window to talk to Romeo.
A solution for this use case should ideally work correctly (and result in a single channel) if there is a "mid-air collision" with Romeo doing the same thing, or with Romeo recovering from disconnection as per req29.
(Recovering from a connection manager crash is equivalent to this.)
Current implementation: same as req4
Problems:
Proposed implementation: same as req4, revisit later if the problems are felt to be serious
Tybalt starts an IRC-style chatroom client and wants to join a chatroom, either by explicit request or because his client auto-joins his favourite rooms.
New vs. existing: | |
---|---|
??? | |
Definition of channel identity: | |
ChannelType is Text, TargetHandleType is ROOM, TargetHandle is #capulet |
Current implementation:
if a channel with GetHandle() -> (ROOM, chatroom_handle) exists: foreground its window or tab else: RequestChannel (Text, ROOM, chatroom_handle, suppress_handler=TRUE)
Problems addressed by proposed implementation:
Proposed implementation: some new interface for this functionality is created, like Chan.I.Chatroom.
if a channel with TargetHandleType == ROOM and TargetID == '#capulet' is being handled by the chatroom UI: foreground its window or tab (no interaction with the ChannelDispatcher) else: chatroom UI calls ChannelDispatcher.StartRequest chatroom UI calls ChannelRequest.CreateChannelByAccount( account, { '...ChannelType': '...Text', '...TargetHandleType': ROOM, '...TargetID': '#capulet' '...Channel.Interface.Chatroom.Nickname': 'The Prince of Cats' }, timestamp, my_own_bus_name ) ChannelDispatcher calls AddRequest on chatroom UI, which ignores it as the request is already known to it try: ChannelDispatcher tells AccountManager to put account online ChannelDispatcher calls CreateChannel ({...same arguments...}) on success: channel observers run ChannelRequest emits Succeeded, chatroom UI ignores its arguments channel approvers do not run CD calls HandleChannels on chatroom UI chatroom UI handles channel on failure: ChannelDispatcher calls RemoveFailedRequest on chatroom UI, and ChannelRequest emits Failed chatroom UI displays failure
Proplems remaining:
How do threads work? By analogy with 1-1 messaging, they should be separate channels - is this really what we want?
Resolution: solve later, https://bugs.freedesktop.org/show_bug.cgi?id=16544
Benvolio chooses to rejoin a recently-used chatroom from (hypothetical functionality of) the GNOME Places menu.
New vs. existing: | |
---|---|
??? | |
Definition of channel identity: | |
ChannelType is Text, TargetHandleType is ROOM, TargetHandle is #capulet |
Proposed implementation:
Places menu calls ChannelDispatcher.StartRequest Places menu calls ChannelRequest.EnsureChannelByAccount( account, { '...ChannelType': '...Text', '...TargetHandleType': ROOM, '...TargetHandle': '#capulet' }, timestamp, '' ) ChannelDispatcher calls AddRequest on chatroom UI, which makes a new tab (if it is not already handling such a channel) try: ChannelDispatcher tells AccountManager to put account online ChannelDispatcher calls EnsureChannel ({...same arguments...}) on creation of new channel: channel observers run ChannelRequest emits Succeeded, Places menu ignores its arguments channel approvers do not run CD calls HandleChannels on chatroom UI chatroom UI handles channel on return of existing channel: ChannelRequest emits Succeeded, Places menu ignores its arguments channel observers and approvers do not run CD calls HandleChannels on handler of existing channel handler of existing channel brings channel to foreground on failure: ChannelDispatcher calls RemoveFailedRequest on chatroom UI (1) ChannelRequest emits Failed (2) chatroom UI displays failure in response to (1) Places menu displays failure in response to (2)
Romeo wants to list all the chatrooms on the server or service that hosts his account.
New vs. existing: | |
---|---|
New (parallel) channel preferred, but might not be possible | |
Definition of channel identity: | |
None - the returned channel probably looks like one from req10 |
Current implementation:
RequestChannel (RoomList, NONE, 0, suppress_handler=TRUE)
Notes:
Implementation problems not affecting design:
Proposed implementation: a straightforward port of the current API. In the returned channel, the Channel.Type.RoomList.Server property will be the actual server name, rather than empty
Romeo wants to list all the chatrooms on the server capulet.example.com that hosts Juliet's account.
New vs. existing: | |
---|---|
New (parallel) channel preferred, but might not be possible | |
Definition of channel identity: | |
ChannelType is RoomList, RoomList.Server is capulet.example.com |
Current implementation: impossible
Proposed implementation: in the request, set the Channel.Type.RoomList.Server property to the desired DNS name
Current best-practice to get contact lists (should not use ListChannels and NewChannel, cf my conversation with Zdra in #telepathy on 2008-04-25):
RequestChannel (ContactList, CONTACT_LIST, handle("subscribe")) RequestChannel (ContactList, CONTACT_LIST, handle("publish")) RequestChannel (ContactList, CONTACT_LIST, handle("hide")) RequestChannel (ContactList, CONTACT_LIST, handle("allow")) RequestChannel (ContactList, CONTACT_LIST, handle("deny"))
Current best-practice to get initial user-defined groups:
ListChannels ()
(finding new groups will be part of the "incoming" use cases list)
Problems:
Proposed implementation req11impl1:
Problems with req11impl1:
Current implementation:
RequestChannel (ContactList, GROUP, handle("Colleagues"), suppress_handler=FALSE)
Proposed implementation: a straightforward port to EnsureChannel
This section refers to protocols like MSN, where what appears to be a 1-1 conversation is actually just an unnamed chatroom into which other users can be invited.
(The same as req1, but Romeo and Juliet are using a "fully correct" MSN implementation like telepathy-butterfly, or some similar protocol.)
Romeo has a chat or IM UI open already, and wants to use it to chat to Juliet. He selects Juliet from a contact list or types in her username on some IM service.
Proposed implementation: a channel with TargetHandleType == CONTACT and TargetHandle == juliet will definitely not already exist. Otherwise, exactly the same as req1
Romeo is talking to Juliet using text chat, but is disconnected due to network instability. After reconnecting, he wants to keep using the same window to talk to Juliet.
A solution for this use case should work correctly (and result in a single channel) if there is a "mid-air collision" with Juliet doing the same thing, with Juliet sending messages to Romeo while he is still offline (on store-and-forward protocols like XMPP), or with Juliet recovering from Romeo's disconnection as per req33 (on protocols that do not allow offline messages).
(Recovering from a connection manager crash is equivalent to this.)
Current implementation: same as req13
Problems:
Proposed implementation:
Romeo chooses a past conversation with Juliet in a log browser and wants to resume it. (The definition of threading in XMPP expects that this is possible.)
This is basically req31 but for a different reason; I expect that the solution can be similar.
Current implementation: same as req13
Problems: Juliet cannot distinguish between this case and req13
Resolution: not a serious problem
Juliet is talking to Romeo using text chat when Romeo is disconnected due to network instability. The protocol is one that does not allow offline messages to be sent, like IRC. After reconnecting, Juliet wants to keep using the same window to talk to Romeo.
A solution for this use case should work correctly (and result in a single channel) if there is a "mid-air collision" with Romeo doing the same thing, or with Romeo recovering from disconnection as per req31.
(Recovering from a connection manager crash is equivalent to this.)
Proposed implementation: basically the same as req31
Romeo wants to talk to both Mercutio and Benvolio in an ad-hoc chatroom. He selects them both from a contact list, or types in both their usernames.
Problems:
Proposed implementation: ignore this and only support req15
Romeo wants to talk to both Mercutio and Benvolio in an ad-hoc chatroom. He selects Mercutio from a contact list, or types in Mercutio's username, then invites Benvolio to the chatroom too.
Proposed implementation:
(Rationale for not faking true 1-1 channels: once Benvolio has been added, we must have an ad-hoc chatroom with TargetHandleType = NONE. Since UIs will need to be able to cope with such channels anyway, we might as well start off with one.)
(The same as req2, but Romeo and Juliet are using a "fully correct" MSN implementation like telepathy-butterfly, or some similar protocol.)
Juliet wants to talk to Romeo. She chooses his entry in an address book or other list of people (not necessarily Telepathy-centric) and is presented with a list of possible ways to talk to him. She decides to use text chat.
Proposed implementation: the same as req2
The same as req14 but from an address book.
Proposed implementation: ignore this and only support the equivalent of req15
Romeo is collaborating on a document with Mercutio, and wants to have a chat embedded in his AbiWord instance, separate from any other chat with Mercutio that may be ongoing.
Possible implementation: the same as req3
Same as http://www.xmpp.org/extensions/xep-0045.html ยง7.6. XMPP does this by using thread IDs.
Current implementation: can't be done
Proposed implementation: request a chatroom channel with the same (thread ID and) bundle ID as the 1-1 chat, or something (use of two channels is unavoidable here, because they have a distinct identity)
Resolution: defer the threads spec til later, https://bugs.freedesktop.org/show_bug.cgi?id=16544
Romeo is talking to Juliet using a text or VoIP UI, and wishes to send Juliet a file in the context of that conversation.
Proposed implementation:
Let bundle_id be the value of the Bundle property of the existing Text or StreamedMedia channel. Romeo's UI calls ChannelDispatcher.StartRequest Romeo's UI calls ChannelRequest.CreateChannelByAccount( account, { '...ChannelType': '...FileTransfer', '...TargetHandleType': CONTACT, '...TargetID': 'juliet@capulet.example.com' '...Bundle': bundle_id, '...Channel.Type.FileTransfer.ContentType': 'image/png', ... }, timestamp, my_own_bus_name ) ChannelDispatcher calls AddRequest on Romeo's UI, which ignores it as the request is already known to it try: ChannelDispatcher calls CreateChannel ({same dictionary as above}) on success: channel observers run ChannelRequest emits Succeeded channel approvers do not run CD calls HandleChannels on Romeo's UI which handles the transfer on failure: ChannelDispatcher calls RemoveFailedRequest on Romeo's UI, and ChannelRequest emits Failed Romeo's UI displays failure
Proposed implementation:
Let bundle_id be the value of the Bundle property of the existing Text or StreamedMedia channel. Romeo's UI calls ChannelDispatcher.StartRequest Romeo's UI calls ChannelRequest.CreateChannelByAccount( account, { '...ChannelType': '...FileTransfer', '...TargetHandleType': CONTACT, '...TargetID': 'juliet@capulet.example.com' '...Bundle': bundle_id, '...Channel.Type.FileTransfer.ContentType': 'image/png', ... }, timestamp, '' ) ChannelDispatcher calls AddRequest on file transfer UI try: ChannelDispatcher calls CreateChannel ({same dictionary as above}) on success: channel observers run ChannelRequest emits Succeeded channel approvers do not run CD calls HandleChannels on file transfer UI, which handles the transfer on failure: ChannelDispatcher calls RemoveFailedRequest on file transfer UI ChannelRequest emits Failed => Romeo's UI displays failure
Romeo right-clicks on a file in his file manager, chooses a "Send to User" option and chooses to send it to Juliet.
Proposed implementation: if the file manager is the channel handler, this is the same as req20a, but with no bundle ID; otherwise it's the same as req20b but with no bundle ID
While collaborating on a document with Mercutio, Romeo inserts an embedded image into the document. The collaborative application could usefully choose to represent this by a file transfer.
Proposed implementation: don't do this, use Tubes instead
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 addressed by proposed implementation:
Proposed implementation:
Tybalt asks Juliet to help him fix a problem with his computer. He offers her a VNC connection to his computer so she can interact with his desktop.
Proposed implementation:
Romeo offers Mercutio and Benvolio access to an OpenArena server running on his local computer.
Proposed implementation:
Romeo opens a text channel to Juliet to send a message, but Juliet's server is down and Romeo's server signals failure. (This is mostly applicable to decentralized protocols like XMPP and SIP.)
Current implementation:
the message is sent SendError (and soon DeliveryReporting) report the failure the channel remains open
Proposed implementation: keep the current implementation
Romeo makes a VoIP call to Juliet, but Juliet's server crashes and failure is signalled.
Current implementation:
Juliet is removed from the Group interface, with an error for the reason the StreamedMedia channel closes
Proposed implementation: keep the current implementation?
Juliet starts a VoIP call to Tybalt, but then thinks better of it and cancels the call.
Current implementation (NMC 4.x):
UI calls mission_control_cancel_channel_request() if dispatching of the channel has already begun: cancellation succeeds else: cancellation fails the UI is asked to handle the channel
Problems:
Proposed implementation: the cancelling client calls Cancel on the channel request. There are in fact several cases.
CD should refrain from calling it
CD should remember the cancellation, and when the channel creation method returns, immediately close the channel with Close()
CD should close the channel with Close()
FIXME: is it still safe for the CD to close the channel? This raises a race condition - the handler will look for details of the channel and find that it's gone - but that can happen anyway (because the remote peer could close the channel). Perhaps the CD should follow up with a method call to say "it's OK that you just failed to handle that channel - it went away", but probably that's crack.
It's too late, and Cancel should fail (indeed, the channel-request object should no longer exist)
Romeo makes a VoIP call to Juliet from a Maemo device at a time when he has no connectivity. Mission Control (the ChannelDispatcher implementation) on Maemo is able to request that the device obtains some sort of connection when needed, so it does so. However, Romeo is not near a wireless LAN access point, and it takes a couple of minutes for him to walk towards one.
Naive implementation: the request is a method call, the request being satisfied is a response
Problems addressed by proposed implementation: the D-Bus method call will time out after around 25 seconds unless special action is taken
Proposed implementation: req4
A new channel is needed in one of the following cases:
Proposed implementation:
A UI (perhaps an address book) allows sending one-off messages to contacts, without entering into a dialogue. If the contact replies, this should be dispatched as usual.
The UI can't close the channel in a race-free way, and if a message comes in on the same channel, at that point (only) it needs dispatching to a handler.
Similarly, imagine a text channel where sending messages is very slow: we want to be able to close the channel handler (UI) without closing the channel, and have the channel be re-dispatched only when a message comes in.
Possible solution: for Text channels, somehow arrange for the channel to be re-dispatched to a "silent" handler; when an incoming message arrives, the "silent" handler exits (or somehow submits the channel for re-dispatching) and the CD will re-dispatch to a UI.
Possible solution: closing a Text channel that has pending messages causes another one to open with the same pending messages
We can solve this later. For now, it's implementation-dependent which handler is used if several are possible - the channel dispatcher can use any reasonable algorithm to choose one.
We assume that creating a channel has visible side-effects, and that this is undesirable in some cases.
When requesting a single channel, there are four possibilities:
When requesting a bundle of channels, everything gets more complicated - if we're failing a request because the client wanted all new channels but got one existing channel, we don't want the CM to create any new channels.
Proposed implementation: