Bug 24939 - Interface for upgrading chats/calls to multi-user
Interface for upgrading chats/calls to multi-user
Status: RESOLVED FIXED
Product: Telepathy
Classification: Unclassified
Component: tp-spec
unspecified
Other All
: high enhancement
Assigned To: Telepathy bugs list
Telepathy bugs list
http://git.collabora.co.uk/?p=user/sm...
see 24906 for patch
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2009-11-05 07:06 UTC by Simon McVittie
Modified: 2010-11-10 06:41 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Simon McVittie 2009-11-05 07:06:34 UTC
In XMPP you can have a 1-1 chat, then invite the other guy to a MUC that is conceptually a continuation of that 1-1 chat. We also want to be able to do this for Muji.

In MSN (and Skype), all Text channels are backed by a potentially-multi-user thing on the server. We've traditionally said that these should be "anonymous rooms" (handle type 0, target handle 0, Group), and that's what telepathy-butterfly does, but that turns out to be really awkward.

As a result, we propose to change MSN/Skype CMs to emulate XMPP-like semantics: have a defined way to upgrade the 1-1 chat to multi-user, and when that's done, quietly migrate the server-side construct (switchboard in MSN) to the new multi-user Channel.

If the user sends another message in the 1-1 chat, quietly establish a new switchboard for it, and if the user is sent a private message by the peer from the 1-1 chat (in a new switchboard), nail that switchboard onto the existing 1-1 channel.
Comment 1 Simon McVittie 2009-11-13 10:27:37 UTC
This API should also be used to upgrade 1-1 XMPP Jingle calls to Muji
calls, although there are extra subtleties there: What happens to the
streams/contents in the original call channel? Should they implicitly be
put on hold, or something, by the act of upgrading?

It would be ideal if we could use the same mechanism for GSM conference
calls (Bug #24906).

An anti-use-case which should be considered:

* Alice is talking to Bob (1-1 chat)
* Bob invites Chris to join in, but Alice's UI hasn't been told yet
* Alice sends a message "to Bob" that Chris wasn't meant to see
* Alice is now told that the 1-1 chat has become (or has been replaced
  by) a multi-user chat containing Alice, Bob and Chris
* The message gets sent to the replacement channel and Chris sees it
Comment 2 Simon McVittie 2009-11-13 10:36:59 UTC
The XMPP mechanism referred to in the initial bug report is
XEP-0045 §7.6, "Converting a One-to-One Chat Into a Multi-User
Conference" <http://xmpp.org/extensions/xep-0045.html#continue>.
This works as follows:

* Two users, Alice and Bob, are chatting via 1-1 messages (Telepathy
  models this with a Channel, but in the underlying protocol, each message
  stands alone).
* Bob joins a new chatroom, automatically triggering its creation.
* Bob sends chatroom invitations to Alice and Chris, each containing a
  reference to the previous conversation with Alice. This reference can
  either be the thread ID of that conversation, or just "<continue/>" as
  an implicit indicator of "whatever conversation we were having".

I think it's fairly clear that the only reasonable representation for this
from Alice's point of view is something like:

* there is a 1-1 Channel (call it C1), with TargetHandleType = CONTACT,
  TargetHandle = Bob
* a new Channel, C2, appears, with TargetHandleType = ROOM
* C2 has some property that identifies it as a continuation of C1
* if Alice ignores C2 and sends a message to C1, that message is sent
  1-1 to Bob
* C1 probably shouldn't close? (tbd)

and from Bob's point of view:

* there is a 1-1 Channel C3 with TargetHandleType = CONTACT,
  TargetHandle = Alice
* Bob uses some yet-to-be-defined API to make a new Channel, C4, with
  himself in it, and invite Alice and Chris to that Channel
* C4 has TargetHandleType = ROOM, and the same property as C2 to
  identify it as a continuation of C3
* C3 might automatically close? (tbd)
* if Alice ignores the room and sends a 1-1 message to Bob, that message
  turns up in C3 (if it still exists) or in a new 1-1 channel C5 (otherwise)

Rob points out that for atomicity, the new channel (C2/C4) has to
have a property saying "I am a continuation of (C1/C3)", as opposed to
having the old channel (C1/C3) emit a signal "I've been replaced by (C2/C4)".
Comment 3 Simon McVittie 2009-11-13 10:51:31 UTC
Here's the protocol-level situation in MSN. I'm told it's basically
equivalent in Skype, except that the constructs on the server aren't
called switchboards; I'll use the MSN terminology here.

* Two users, Alice and Bob, are chatting. To contain their messages, the
  MSN servers provide a construct called a "switchboard". Telepathy
  models this as a Channel. Suppose they're in a switchboard S1, which
  telepathy-butterfly represents by a channel C1.

* If Alice and Bob are idle for a while, the switchboard will
  automatically be closed by the server. A new switchboard, S2, needs
  to be created in order for either of them to send a message to the
  other. To be nice to UIs, telepathy-butterfly does this automatically,
  so the channel C1 is now associated with a switchboard S2.

* Bob invites Chris to join the conversation. The switchboard S2 now
  connects Alice, Bob and Chris. (As a side-effect of having more than
  two people in it, the switchboard is now no longer susceptible to
  being closed automatically by the server.)

* telepathy-butterfly needs to do something with the channel C1 to
  indicate that Chris is a member.

The proposal is that since UIs need to cope with the XMPP way of doing
things *anyway*, we should simplify by pretending that all protocols act
like XMPP. From Alice's point of view:

* there is a 1-1 Channel (call it C1), with TargetHandleType = CONTACT,
  TargetHandle = Bob; it represents the switchboard S2 (and previously, it
  represented S1)
* a new Channel, C2, appears, with TargetHandleType = NONE (an
  "anonymous chatroom"); now *it* represents the switchboard S2
* C2 has some property that identifies it as a continuation of C1
* if Alice ignores C2 and sends a message to C1, either:
  - a new switchboard S3 is created to communicate with Bob and the
    message is sent to S3; or
  - sending that message fails with a user-visible error
* it's unclear whether C1 should close automatically (tbd)

and from Bob's point of view:

* there is a 1-1 Channel C3 with TargetHandleType = CONTACT,
  TargetHandle = Alice; it represents the switchboard S2 (and previously,
  it represented S1)
* Bob uses some yet-to-be-defined API to make a new Channel, C4, with
  himself in it, and invite Alice and Chris to that Channel
* C4 has TargetHandleType = NONE, and the same property as C2 to
  identify it as a continuation of C3
* C3 might automatically close? (tbd)
* if Alice ignores the room and sends a 1-1 message to Bob via a new
  switchboard S3, then that message turns up in C3 (if it still exists) or
  in a new 1-1 channel C5 (otherwise)
Comment 4 Simon McVittie 2009-11-13 10:55:46 UTC
One subtlety of having a "replace this channel" API is that we should
avoid the appearance of altering the immutable properties of a channel:
the replacement channel should appear at a different object path. Here's a  solution that I think should be rejected, because it does not have that property:

Having the replacement appear at the same object path is *technically*
allowed by telepathy-spec, and it's tempting to use this as a solution.
It could even be the same C object inside the connection manager, by
using the same trick that our CMs do to "respawn" closed Text channels
with unacknowledged messages:

* [begin critical section in which the main loop must not be re-entered]
* emit Closed (conceptually, this removes the old Channel)
* adjust the properties that would normally be immutable
* emit NewChannel and NewChannels (conceptually, this replaces the old
  Channel with a new one that "coincidentally" has the same object path)
* [end critical section; you may re-enter the main loop now]

This would look a lot like the proposed solution, except that C1/C3 is closed a moment before C2/C4 is created at the same object path. Conceptually,
C2/C4 is still a new channel, and the ChannelDispatcher will behave as such, so the only possible simplification is within the connection manager's code.

We'd discourage doing this. It's easy to get wrong, and if you
get the subtle details slightly wrong in either the client or the CM,
it looks as though you're violating some quite fundamental Telepathy
API guarantees (that the immutable properties are immutable).

If we recycle object paths, there's also an unavoidable possibility that
you'll try to call a method on the old channel, and instead have the
method-call message delivered to the new one. This is bad if the method
call is Close(), and very bad if the method call is Send() (you might
accidentally send the message to people you didn't think would see it -
the anti-use-case from Comment #1).
Comment 5 Simon McVittie 2009-11-13 11:04:43 UTC
For comparison, here's what telepathy-butterfly *currently* does, which we now think was a mistake. From Alice's point of view:

* there is a Channel (call it C1), with TargetHandleType = NONE,
  containing Alice and Bob; it represents the switchboard S2 (and previously,
  it represented S1)
* Chris appears in C1
* The anti-use-case from Comment #1 can easily happen

and from Bob's point of view:

* there is a Channel C3 with TargetHandleType = NONE, containing Alice and
  Bob; it represents the switchboard S2 (and previously,
  it represented S1)
* Bob uses the Group interface to invite Chris to that Channel

As well as provoking the anti-use-case mentioned, this makes the following things hard:

* UIs want to have the same code for XMPP and MSN
* UIs may want to log 1-1 chats but not multi-user chats
* UIs want to be able to choose a sane title for the window!
Comment 6 Simon McVittie 2009-11-13 11:22:09 UTC
Interaction with approvers and MC is tricky. Because C2/C4 are new channels, they go through the normal dispatch process.

For Bob, we'll usually want the UI that requested the channel C4 to be the one handling it. This suggests that the yet-to-be-defined upgrade API should be to call CreateChannel or EnsureChannel, and get normal MC behaviour; approvers will be bypassed because Requested=True, which is appropriate.

For Alice things get more complicated, because depending on protocol behaviour, she might be in either Members or LocalPending in C2 (in XMPP she'll be in LocalPending, but in MSN/Skype she'll be forced into Members immediately, because in the underlying protocol, she is in the switchboard or equivalent already).

There are three interesting UI policies that I can see:

* Treat the channels like any other new channel, complete with Approvers. Easy to implement.

* Automatically pick up and accept the channels. This can be done by having an Observer in the chat UI, which Claim()s any channel that is a continuation of a channel that it is already handling, then accepts the invitation if necessary; or even by having an Observer per channel being handled, which claims continuations of exactly that channel. However, there's a race condition here which needs to be solved: Bob might start talking to Alice, then immediately invite Chris, before Alice's chat UI has set up its Observer (or perhaps even before Alice's chat UI has *started*).

* Apply the first policy to channels where Alice is in LocalPending (XMPP) and the second to channels where Alice is in Members (Skype?).
Comment 7 Naveen 2009-11-14 06:49:12 UTC
(In reply to comment #4)
> One subtlety of having a "replace this channel" API is that we should
> avoid the appearance of altering the immutable properties of a channel:
> the replacement channel should appear at a different object path. Here's a 
> solution that I think should be rejected, because it does not have that
> property:
> 
> Having the replacement appear at the same object path is *technically*
> allowed by telepathy-spec, and it's tempting to use this as a solution.
> It could even be the same C object inside the connection manager, by
> using the same trick that our CMs do to "respawn" closed Text channels
> with unacknowledged messages:
> 
> * [begin critical section in which the main loop must not be re-entered]
> * emit Closed (conceptually, this removes the old Channel)
> * adjust the properties that would normally be immutable
> * emit NewChannel and NewChannels (conceptually, this replaces the old
>   Channel with a new one that "coincidentally" has the same object path)
> * [end critical section; you may re-enter the main loop now]
> 
> This would look a lot like the proposed solution, except that C1/C3 is closed a
> moment before C2/C4 is created at the same object path. Conceptually,
> C2/C4 is still a new channel, and the ChannelDispatcher will behave as such, so
> the only possible simplification is within the connection manager's code.
> 
> We'd discourage doing this. It's easy to get wrong, and if you
> get the subtle details slightly wrong in either the client or the CM,
> it looks as though you're violating some quite fundamental Telepathy
> API guarantees (that the immutable properties are immutable).
> 
> If we recycle object paths, there's also an unavoidable possibility that
> you'll try to call a method on the old channel, and instead have the
> method-call message delivered to the new one. This is bad if the method
> call is Close(), and very bad if the method call is Send() (you might
> accidentally send the message to people you didn't think would see it -
> the anti-use-case from Comment #1).
> 

This is pretty much same what is happening in skype connection manager at the moment which client interface doesn't like.
Comment 8 Naveen 2009-11-14 07:06:31 UTC
(In reply to comment #2)
> The XMPP mechanism referred to in the initial bug report is
> XEP-0045 §7.6, "Converting a One-to-One Chat Into a Multi-User
> Conference" <http://xmpp.org/extensions/xep-0045.html#continue>.
> This works as follows:
> 
> * Two users, Alice and Bob, are chatting via 1-1 messages (Telepathy
>   models this with a Channel, but in the underlying protocol, each message
>   stands alone).
> * Bob joins a new chatroom, automatically triggering its creation.
> * Bob sends chatroom invitations to Alice and Chris, each containing a
>   reference to the previous conversation with Alice. This reference can
>   either be the thread ID of that conversation, or just "<continue/>" as
>   an implicit indicator of "whatever conversation we were having".
> 
> I think it's fairly clear that the only reasonable representation for this
> from Alice's point of view is something like:
> 
> * there is a 1-1 Channel (call it C1), with TargetHandleType = CONTACT,
>   TargetHandle = Bob
> * a new Channel, C2, appears, with TargetHandleType = ROOM
> * C2 has some property that identifies it as a continuation of C1
> * if Alice ignores C2 and sends a message to C1, that message is sent
>   1-1 to Bob
> * C1 probably shouldn't close? (tbd)

-- Above description looks clear to me, accept not closing the channel while underlaying protocol object which was mapped with the channel C1 has been moved to C2.
What if we close the channel C1, and if UI still wants to continue p2p chat then request a new channel C5 between Alice & Bod?


> 
> and from Bob's point of view:
> 
> * there is a 1-1 Channel C3 with TargetHandleType = CONTACT,
>   TargetHandle = Alice
> * Bob uses some yet-to-be-defined API to make a new Channel, C4, with
>   himself in it, and invite Alice and Chris to that Channel
> * C4 has TargetHandleType = ROOM, and the same property as C2 to
>   identify it as a continuation of C3
> * C3 might automatically close? (tbd)
> * if Alice ignores the room and sends a 1-1 message to Bob, that message
>   turns up in C3 (if it still exists) or in a new 1-1 channel C5 (otherwise)
> 
> Rob points out that for atomicity, the new channel (C2/C4) has to
> have a property saying "I am a continuation of (C1/C3)", as opposed to
> having the old channel (C1/C3) emit a signal "I've been replaced by (C2/C4)".
> 

Comment 9 Simon McVittie 2009-11-16 04:10:44 UTC
(In reply to comment #8)
> What if we close the channel C1, and if UI still wants to continue p2p chat
> then request a new channel C5 between Alice & Bod?

If C1 automatically closes, then yes, Alice's UI would have to request a new 1-1 channel to Bob in order to send additional private messages. This new channel would have a newly-created switchboard (or the Skype equivalent).

Open questions that we'll need to think about some more:

* Should C1 close automatically? Why/why not?
* Should C3 close automatically? Why/why not?
* How do we solve the race condition mentioned in Comment #6?
Comment 10 Simon McVittie 2009-11-17 09:47:04 UTC
(In reply to comment #9)
> * Should C1 close automatically? Why/why not?
> * Should C3 close automatically? Why/why not?

Sjoerd and I concluded that it's least astonishing if neither of them closes.

> * How do we solve the race condition mentioned in Comment #6?

Sjoerd and I concluded that UIs wanting this auto-accept behaviour should implement it via cooperation between the approver and the handler:

* Approver knows about this upgrading API, sees that the channel is an upgrade of a channel that's being handled, and lets it go past silently

* no race is involved, because the Approver is (presumably) single-threaded

* an Approver that's actively co-operating with a Handler can always learn what channels that Handler is handling, by asking it (via the normal Handler API or otherwise)

An API is proposed in comment 6 of Bug #24906:
http://bugs.freedesktop.org/show_bug.cgi?id=24906#c6

Possible concrete implementations of that API:

XMPP
====

Channels do not implement Splittable.

This description only covers Text: Muji will have analogous APIs for Call.

Capability discovery
--------------------

RequestableChannelClasses includes two channel classes, as follows:

For upgrading 1-1 chats to an unspecified (generated) chatroom:

    Fixed:
        ...Channel.ChannelType: ...Channel.Type.Text
    Allowed:
        ...Channel.Interface.Conference.InitialChannels
        ...Channel.Interface.Conference.SupportsNonMerge

and for upgrading 1-1 chats to a specific chatroom:

    Fixed:
        ...Channel.ChannelType: ...Channel.Type.Text
        ...Channel.TargetHandleType: ROOM
    Allowed:
        ...Channel.TargetHandle
        ...Channel.TargetID
        ...Channel.Interface.Conference.InitialChannels
        ...Channel.Interface.Conference.SupportsNonMerge

Use cases
---------

X1. Joining or creating a chatroom (as implemented in Gabble 0.8.x):

    EnsureChannel({
        ...Channel.ChannelType: Channel.Type.Text,
        ...Channel.TargetHandleType: ROOM,
        ...Channel.TargetID: 'lolz@conf.example.com',      # or TargetHandle
        })
    returns a channel with type Text, TargetHandleType = ROOM, and a room
    handle representing lolz@conf.example.com.

X2. Creating a chatroom with an unspecified name and not inviting anyone:

    CreateChannel({
        ...Channel.ChannelType: Channel.Type.Text,
        ...Channel.Interface.Conference.InitialChannels: [],    # or omitted
        })
    returns a channel with type Text, TargetHandleType = ROOM, and a room
    handle representing <some UUID>@conf.example.com.

    (Behind the scenes, this either uses XEP-0045 §10.1.4, or just generates
    a UUID; XEP-0045 §10.1.4 would require us to disco the server, which
    never yields a reply in Google Talk PMUC, so we might as well just
    generate a UUID.)

X3. Continuing one or more chats in a chatroom:

    Let C1, C2, ... be arbitrarily many Text channels with
    TargetHandleType = CONTACT, whose TargetIDs are the JIDs J1, J2, ...

    CreateChannel({
        ...Channel.ChannelType: Channel.Type.Text,
        ...Channel.Interface.Conference.InitialChannels: [C1, C2, ...],
        })
    returns a channel with type Text, TargetHandleType = ROOM,
    and a room handle representing <some UUID>@conf.example.com,
    to which the contacts J1, J2, ... have been invited.

    (Behind the scenes, this does the same as X2, then sends invitations to
    each of J1, J2, ..., with each invitation containing the appropriate
    <continue/> element from among C1, C2, ...)

X4. Continuing one or more chats in a specific chatroom:

    Let C1, C2, ... be arbitrarily many Text channels with
    TargetHandleType = CONTACT, whose TargetIDs are the JIDs J1, J2, ...

    EnsureChannel({
        ...Channel.ChannelType: Channel.Type.Text,
        ...Channel.Interface.Conference.InitialChannels: [C1, C2, ...],
        ...Channel.TargetHandleType: ROOM,
        ...Channel.TargetID: 'lolz@conf.example.com',      # or TargetHandle
        })
    returns a channel with type Text, TargetHandleType = ROOM,
    and a room handle representing lolz@conf.example.com,
    to which the contacts J1, J2, ... have been invited.

    (Behind the scenes, this does a normal MUC join if necessary, then sends
    invitations to each of J1, J2, ..., with each invitation containing the
    appropriate <continue/> element from among C1, C2, ...)

X5. Merging a chat C1 into a specified Conference channel Cn

    Either do X4 with the appropriate handle, or call
    Conference.Merge(C1) on Cn. (Behind the scenes, this invites the peer
    from C1, as for X4.)

    (In practice, using Conference.Merge is preferred if you already have
    a Conference channel, because this will also work for MSN/Skype.)

MSN/Skype
=========

Channels do not implement Splittable.

Capability discovery
--------------------

RequestableChannelClasses includes one channel class
for upgrading 1-1 chats to an unspecified (generated) chatroom:

    Fixed:
        ...Channel.ChannelType: ...Channel.Type.Text
    Allowed:
        ...Channel.Interface.Conference.InitialChannels
        ...Channel.Interface.Conference.SupportsNonMerge

Use cases
---------

M1. Continuing one or more chats in a chatroom:

    Let C1, C2, ... be arbitrarily many Text channels with
    TargetHandleType = CONTACT, whose TargetIDs are the JIDs J1, J2, ...

    CreateChannel({     # this is the same method call as for X3
        ...Channel.ChannelType: Channel.Type.Text,
        ...Channel.Interface.Conference.InitialChannels: [C1, C2, ...],
        })
    returns a channel with type Text, TargetHandleType = NONE,
    into which the contacts J1, J2, ... have been forcibly added.

    Behind the scenes, the channel has "stolen" the switchboard
    from C1; the peers in C2, ... will see it as a new chat, the peer in
    C1 will see it as a distinct chat.

M2. Creating a new switchboard and not initially inviting anyone (not very
    useful, but allowed for symmetry):

    CreateChannel({     # this is the same method call as for X2
        ...Channel.ChannelType: Channel.Type.Text,
        ...Channel.Interface.Conference.InitialChannels: [],    # or omitted
        })
    returns a channel with type Text, TargetHandleType = NONE, with no
    associated switchboard; a new switchboard will be allocated as soon
    as someone is invited

M3. Merging a chat C1 into a specified Conference channel Cn

    Call Conference.Merge(C1) on Cn. (Behind the scenes, this just invites
    the peer from C1 - they don't see any indication that you consider it to
    be a continuation of C1.)
Comment 11 Mikhail Zabaluev 2009-11-18 08:00:00 UTC
(In reply to comment #10)
> MSN/Skype
> =========
> 
> Use cases
> ---------
> 
> M1. Continuing one or more chats in a chatroom:

Consider a slightly semantically different use case: adding a user (with or without previous history of communication and the respective channel) to an existing chat, thus turning it into a conference. This matches Skype semantics better.
Comment 12 Simon McVittie 2009-11-18 08:20:33 UTC
(In reply to comment #11)
> Consider a slightly semantically different use case: adding a user (with or
> without previous history of communication and the respective channel) to an
> existing chat, thus turning it into a conference. This matches Skype semantics
> better.

I think the way to do that in a UI that only has one channel right now would be to treat it like M1 with a single channel, then invite the other people.

(This would fail on connection managers that don't have SupportsNonMerges (bad name, needs improvement) in the requestable channel class for conferences, but I'm not aware of any Text protocol where this would actually matter. If you wanted to support this for some reason, then you'd have to switch between M1 and M4 behaviour based on that capability.)

M4: inviting users without channels to an existing chat

    Let C1 be a Text channel with
    TargetHandleType = CONTACT, whose TargetID is J1. Let J2, J3, ... be
    some other MSN identifiers (Passports).

    First:

    CreateChannel({     # this is the same method call as for X3
        ...Channel.ChannelType: Channel.Type.Text,
        ...Channel.Interface.Conference.InitialChannels: [C1],
        })
    returns a channel with type Text, TargetHandleType = NONE,
    into which the contact J1 has been forcibly

    Behind the scenes, the channel has "stolen" the switchboard
    from C1.

    Second:

    Group.AddMembers([J2, J3, ...], "") on the new channel

    J2, J3, ... are forcibly added [citation needed]

X6: inviting users without channels to an existing chat
    
    Same situation as M4, for XMPP (so J1, ... are JIDs).

    First:

    CreateChannel({     # this is the same method call as for X3
        ...Channel.ChannelType: Channel.Type.Text,
        ...Channel.Interface.Conference.InitialChannels: [C1],
        })
    returns a channel with type Text, TargetHandleType = NONE,
    into which the contact J1 has been invited with a <continue/>
    element referencing C1

    Second:

    Group.AddMembers([J2, J3, ...], "") on the new channel

    J2, J3, ... are invited in the usual way.
Comment 13 Simon McVittie 2009-11-18 08:21:36 UTC
(In reply to comment #12)
>     returns a channel with type Text, TargetHandleType = NONE,
>     into which the contact J1 has been forcibly

please read as "... has been forcibly added", obviously
Comment 15 Jonny Lamb 2010-03-08 13:21:31 UTC
I'm looking to implement Conference in butterfly to see how well it fits. All the examples here and on the draft interface provide more than enough information for how to deal with moving from a 1-1 chat to a multi-user chat, but nothing for the other way round.

Let's take this example:

1. You're chatting to contact J1 on channel C1.
2. Either you or J1 "invites" J2 to the conversation, which ends
   up with a new channel, C2, which is a group channel with you,
   C1 and C2 in. C1 remains open where you can bitch about J2
   behind his or her back.

Up to this point, this is great, and well documented. Now,

3. J2 realises that you and J1 are ganging up on him or her and
   decides to take it to court, so disconnects to free his or her
   line to call his or her lawyer.
4. C1 is still a 1-1 chat with J1. C2 is still a MUC but with just
   you and J1 in.

The situation in 4 sounds a little odd, but I guess I would accept the answer "yes, suck it up". Thinking about it now, I'm not sure what else we could possibly do?

Looking back in my memory of the times when I used the Windows MSN Messenger client, they have this exact same issue, except because of their UI, C2 is less obviously a MUC (or, given how the MSN switchboards work, C2 has downgraded, internally). If I remember correctly, you could continue talking to J1 in both C1 and C2, although obviously most people just closed one of the two open channels.

When I started writing this comment, I was a little unclear on how downgrading should work, but at this point, I think it's just how I described, right?
Comment 16 Simon McVittie 2010-03-08 13:27:21 UTC
(In reply to comment #15)

Your understanding of how this should work matches mine.

> 1. You're chatting to contact J1 on channel C1.
> 2. Either you or J1 "invites" J2 to the conversation, which ends
>    up with a new channel, C2, which is a group channel with you,
>    C1 and C2 in. C1 remains open where you can bitch about J2
>    behind his or her back.

Yes. Ideally, the underlying MSN switchboard from C1 is "stolen" by C2, and if you say something to J1 in C1, a new switchboard opens for C1.

> 4. C1 is still a 1-1 chat with J1. C2 is still a MUC but with just
>    you and J1 in.
> [...] I guess I would accept the answer "yes, suck it up".

Yes, that's my answer.

> Thinking about it now, I'm not sure what else we could
> possibly do?

I can't think of any other decent handling for this either.
Comment 17 Jonny Lamb 2010-03-11 05:09:05 UTC
I just implemented the conference interface in butterfly, and in general, I have no changes to propose or problems to point out.

However, I would say that it's actually rather a complicated interface to understand. It took a while to work out, but maybe that was me? Without a doubt, SupportsNonMerges was the most complicated to understand. I spoke to Simon about it yesterday, and am still not exactly clear on its use:

18:04 < smcv> jonnylamb: also put SupportsNonMerges in the allowed, if 
              that's what you support
18:04 < smcv> jonnylamb: (as documented)
18:04 < smcv> "An XMPP 1-1 conversation C1 can be continued in a newly 
              created multi-user chatroom Cn by calling 
              CreateChannel({...ChannelType: ...Text, ...InitialChannels: 
              [C1]})  which returns Cn"
18:04 < smcv> says the spec
18:05 < smcv> so our CMs should support that usage, really
18:05 < jonnylamb> Hm, I'm a little confused about that property. Why would 
                   it be requestable? I don't see a case where it wouldn't 
                   be True in butterfly.
18:05 < smcv> jonnylamb: it's sort of fake-requestable... it exists only to 
              indicate static CM capabilities
18:06 < smcv> jonnylamb: you should allow it to appear in requests but 
              ignore its value, probably
18:06 < smcv> jonnylamb: it's a way to tell "oh shit, this is GSM" :-)
18:07 < jonnylamb> So something in allowed properties doesn't mean the CM 
                   will take any notice of its value?
18:07 < smcv> yes. I know it's a bit mad
18:07 < jonnylamb> (At the moment, butterfly hardcodes its value to True.)
18:08 < smcv> as long as we preserve the invariant that there exists at 
              least one value you could genuinely put in your request, I 
              think it's OK
18:08 < smcv> in general there's no guarantee that the returned channel will 
              match what you asked for
18:08 < smcv> as long as it's "close enough" (as defined by the actual 
              interface being implemented)

Yeah, in fact, I'd say SupportsNonMerges would be the only thing I'm not so happy about at all in conference. As butterfly sets it to True in all cases, I guess it's not such a big deal for butterfly.

So, yeah, butterfly is a happy user of the conference interface now. Hopefully it can be merged soon. :-)
Comment 18 Jonny Lamb 2010-03-11 05:18:48 UTC
Simon wanted me to state what parts of the conference interface Empathy actually uses. There are two:

First of all, when it has a 1-1 chat, it looks at RequestableChannelClasses for the connection and if there is a channel class with ChannelType=TEXT and InitialChannels is in allowed properties, then it marks it as can be upgradable to a MUC. If this is possible, then the "invite new person" option is sensitive, otherwise it's insensitive.

Secondly, when you invite a new contact to a 1-1 conversation and Empathy has already seen that this is possible with the InitialChannels property, it calls CreateChannel with properties:

{ ChannelType: TEXT,
  TargetHandleType: NONE,
  InitialChannels: ['/old/object/path/'],
  InitialInviteeIDs: ['smcv@example.com']
}

where smcv@example.com is obviously the contact we want to invite to the chat, and /old/object/path/ is the object path of the old 1-1 chat.

This is the only thing Empathy does with the conference interface. As a result, a new window pops up when this new channel is created.
Comment 19 Simon McVittie 2010-03-11 05:23:02 UTC
(In reply to comment #18)
> if there is a channel class with ChannelType=TEXT and
> InitialChannels is in allowed properties, then it marks it as can be upgradable
> to a MUC.

This previously only worked for TargetHandleType=ROOM, but that can/should be fixed in Empathy.

> Secondly, when you invite a new contact to a 1-1 conversation and Empathy has
> already seen that this is possible with the InitialChannels property, it calls
> CreateChannel with properties:
> 
> { ChannelType: TEXT,
>   TargetHandleType: NONE,
>   InitialChannels: ['/old/object/path/'],
>   InitialInviteeIDs: ['smcv@example.com']
> }

THT=NONE doesn't seem right; I think it should be left unspecified?
Comment 20 Simon McVittie 2010-11-10 06:41:42 UTC
Conference was merged.