RFC 7058

Media Control Channel Framework (CFW) Call Flow Examples

📅 published November 2013, from ietf

Part 1 of 34. More to come! 🎀

RFC 7058: Media Control Channel Framework (CFW) Call Flow Examples 💅

Okay bestie, the title block is giving important info, so here it is. This is RFC 7058, published by the Internet Engineering Task Force (IETF) in November 2013 with ISSN 2070-1721. Its category is Informational 📚. The authors are A. Amirante (University of Napoli), T. Castaldi, L. Miniero (Meetecho), and S P. Romano (University of Napoli) 🫶. The title block doesn't list anything it obsoletes or updates.

Here's the full header, untouched:

Internet Engineering Task Force (IETF)                       A. Amirante
Request for Comments: 7058                          University of Napoli
Category: Informational                                      T. Castaldi
ISSN: 2070-1721                                               L. Miniero
                                                                Meetecho
                                                             S P. Romano
                                                    University of Napoli
                                                           November 2013

Abstract ✨

Okay so this doc is a list of typical Media Control Channel Framework call flows 🦋. It's meant to be a simple guide to the interface between Application Servers and MEDIACTRL-based Media Servers, and a base reference for both implementors and protocol researchers. Lowkey the perfect cheat sheet 🌸.

Status of This Memo 🌈

Quick vibe check: this is not an Internet Standards Track specification. It's published just for informational purposes 📚.

That said, it is a product of the IETF and represents the consensus of the IETF community 🫶. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). Not every IESG-approved doc is a candidate for any level of Internet Standard, though. See Section 2 of RFC 5741 for the details 💜.

For the latest status, errata, and how to send feedback, check http://www.rfc-editor.org/info/rfc7058 🔗.

Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved ✨.

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stand on the publication date. Please actually read these, because they spell out your rights and restrictions for this document 🙈. Any Code Components pulled out of this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as the Simplified BSD License describes 💅.

Table of Contents 🧚

1. Introduction ....................................................4
2. Conventions .....................................................5
3. Terminology .....................................................5
4. A Practical Approach ............................................6
   4.1. State Diagrams .............................................6
5. Control Channel Establishment ..................................10
   5.1. COMEDIA Negotiation .......................................11
   5.2. SYNC ......................................................14
   5.3. K-ALIVE ...................................................15
   5.4. Wrong Behavior ............................................17
6. Use-Case Scenarios and Examples ................................20
   6.1. Echo Test .................................................27
        6.1.1. Direct Echo Test ...................................28
        6.1.2. Echo Test Based on Recording .......................30
   6.2. Phone Call ................................................39
        6.2.1. Direct Connection ..................................42
        6.2.2. Conference-Based Approach ..........................44
        6.2.3. Recording a Conversation ...........................51
   6.3. Conferencing ..............................................57
        6.3.1. Simple Bridging ....................................62
        6.3.2. Rich Conference Scenario ...........................66
        6.3.3. Coaching Scenario ..................................75
        6.3.4. Sidebars ...........................................83
        6.3.5. Floor Control ......................................93
   6.4. Additional Scenarios ......................................99
        6.4.1. Voice Mail ........................................100
        6.4.2. Current Time ......................................107
        6.4.3. DTMF-Driven Conference Manipulation ...............112
7. Media Resource Brokering ......................................126
   7.1. Publishing Interface .....................................127
   7.2. Consumer Interface .......................................136
        7.2.1. Query Mode ........................................137
        7.2.2. Inline-Aware Mode .................................140
        7.2.3. Inline-Unaware Mode ...............................155
   7.3. Handling Media Dialogs ...................................157
        7.3.1. Query and Inline-Aware Mode .......................157
        7.3.2. Inline-Unaware Mode ...............................160
        7.3.3. CFW Protocol Behavior .............................167
8. Security Considerations .......................................170
9. Acknowledgments ...............................................180
10. References ...................................................180
   10.1. Normative References ....................................180
   10.2. Informative References ..................................181

1. Introduction 🎀

Okay, this doc is a list of typical MEDIACTRL Media Control Channel Framework [RFC6230] call flows 📞. It exists because of the team's hands-on implementation experience with the framework and its protocol. That experience pushed them to write a simple guide to the several interfaces between Application Servers and MEDIACTRL-based Media Servers, and a base reference for other implementors and protocol researchers 💜.

Following that spirit, the doc covers several parts of how Application Servers and Media Servers talk to each other 🦋. But here's the thing: the call flows almost always show one single Application Server (called the AS from here on, for conciseness) talking to one single Media Server (MS) 👑. In Section 7, some flows involve more entities through a Media Resource Broker compliant with [RFC6917] ✨. To help you follow every flow, whether it's about SIP dialogs or Media Control Channel Framework (CFW) transactions, the domains hosting the AS and the MS in all the scenarios are as.example.com and ms.example.net, per [RFC2606] 🌸. The flows focus more on the CFW [RFC6230] interaction than on the other protocols involved, like SIP [RFC3261], the Session Description Protocol (SDP) [RFC3264], or RTP [RFC3550] 🫶.

Next up, there's a quick overview of the implementation approach, focusing on protocol stuff. It uses state diagrams showing both the client side (the AS) and the server side (the MS) 🧚. And to be clear, this section is not a mandatory approach to implementing the framework. It's just there to help you understand how the framework works in practice 🙈.

After those preliminaries, the later sections get into real-life scenarios. First up is establishing the Control Channel. After that, there are use-case scenarios covering the most typical multimedia applications 💅.

Heads up: this doc is not a self-contained guide to implementing a MEDIACTRL-compliant framework 😭. The specifications are a mandatory read for all implementors. This doc follows their guidelines but doesn't dig into every detail of the protocol 🍓.

2. Conventions 🌷

Quick formatting note: because of RFC formatting conventions, SIP/SDP and CFW lines longer than 72 characters get split across lines. The split is marked by a backslash at the end of the first line. That backslash, the whitespace before it, the following CRLF, and the whitespace starting the next line would NOT show up in the actual protocol contents 🙃.

Same deal with XML: the indentation is only there for readability. Real messages follow strict XML syntax, which allows indentation but doesn't require it. Because of the same 72-character limit, the doc sometimes splits XML element content across lines too. When that happens, no whitespace is actually meant to be at the start or end of the element content 💖.

Also, a few diagrams have arrows that go from a network entity back to itself. Those arrows are NOT transaction messages. They just show that the entity made a decision in its application logic based on input it got earlier 🧠✨.

3. Terminology 📖

This doc uses the same terminology as [RFC6230], [RFC6231], [RFC6505], and [RFC6917]. The terms below are a summary of the most common ones in this context, mostly taken from the related documents 🎀:

COMEDIA: connection-oriented media (so TCP and Transport Layer Security (TLS)). It also signals SDP support for connection-oriented media and the RFCs defining that support, which are [RFC4145] and [RFC4572] 🦋.

Application Server: an entity that asks a Media Server for media processing and manipulation. Typical examples are Back-to-Back User Agents (B2BUAs) and endpoints that request changes to a third party's media stream 👑.

Media Server: an entity that performs a service, like media processing, on behalf of an Application Server. Typical functions are mixing, announcement, tone detection and generation, and play and record services 🎶.

Control Channel: a reliable connection between an Application Server and a Media Server, used to exchange framework messages 🔗.

VCR controls: runtime control of aspects of audio playback, like speed and volume, using dual-tone multi-frequency (DTMF) signals sent by the user. It works like a VCR (video cassette recorder) controller 📼💜.

4. A Practical Approach 🚀

In this doc, we take an engineering approach to describing a bunch of interesting scenarios. These scenarios come from carefully orchestrating the Media Control Channel Framework entities, namely the Application Server and the Media Server 🧩. Through detailed call flows, we show how a variegated bouquet of services 💐, from super simple to much more complicated, can be built with the functionality currently offered inside the main MEDIACTRL framework, by the Control Packages available so far 🌈.

The doc is meant to be a useful guide for anyone investigating how MEDIACTRL components inter-operate. It's also a base reference for application developers who want to build advanced services on top of the base infrastructure the framework provides 🫶✨.

4.1. State Diagrams 🧚

okay so this is the part where we doodle little state diagrams 🎀 and it's giving "informal" vibes (that's literally what the original calls them, so we're keeping the quotes 💅). Each diagram is a classic Mealy automaton ✨. The boxes are protocol states, and the edges are labelled with a slash-separated pair: the input, then the output. A dash in the output spot means that input gets no output from the automaton 🙈

Some inputs are real MEDIACTRL protocol messages landing on a component while it's in a certain state. That's the case for 'CONTROL', 'REPORT' (in all its flavors, like pending, terminate, etc.), '200', '202', and 'Error' (and errors map to specific numeric codes 💀). Other inputs are triggers coming from the upper layer, the Application Programming Interface programmers use when they build MEDIACTRL-enabled services. Those get the word 'API' in front of the message they trigger. So 'API terminate' is basically a request to send a 'REPORT' message with a status of 'terminate' to the peer 🫶

There are four diagrams total 🌈. Figures 1 and 2 show normal operation of the framework. Figure 3 has two diagrams for asynchronous event notifications. Figure 1 is the MS perspective and Figure 2 is the AS side. Over in Figure 3, the top part shows how events get generated on the MS side by sending a CONTROL message to the AS, and the AS acks each one with a standard 200 response. The bottom part is the AS, which just mirrors the MS 🔥

Now back to Figure 1. The MS wakes up when it gets a CONTROL message from the AS, and that CONTROL tells it to run a specific command from one of the available Control Packages. The command can be quick or it can take some time ⏳. If it's quick, the MS sends a 200 right after it finishes, which basically just says "yep, that task finished correctly" 👑. If it takes a while, the MS first sends back an interlocutory 202 with a 'Timeout' value, and that moves it into a new state called '202' sent. It keeps doing the work in that state 💅. If the task isn't done by the timeout, the server updates the AS on the other side of the Control Channel by periodically sending 'REPORT update' messages, and every single one has to be acknowledged by the AS with a '200' response 🦋. When the MS is finished with the service, it sends a 'REPORT terminate' message, and the whole transaction is concluded once the AS acks that message ✨

Lowkey important: the MS may send a 202 response only after it figures out the request doesn't contain any errors that couldn't be reported later in a REPORT terminate request instead. After the MS sends that 202, any error it (or the API) finds in the request gets reported in the final REPORT terminate request 😭

The AS, as shown in Figure 2, mirrors everything the MS does 🪞. The figures also show what happens when a transaction can't be completed because something went wrong 🙈 In those cases, a specific 'Error' message always gets created and sent, and as we said earlier, it carries a numeric error code 💀

+------------------+  CONTROL/-  +------------------+ API 202/202
| Idle/'terminate' |------------>| CONTROL received |---------+
+------------------+             +------------------+         |
  ^          ^   ^   API 200/200    |     |                   |
  |          |   |                  |     |                   |
  |          |   +------------------+     |                   |
  | 200/-    |      API Error/Error       |                   |
  |          +----------------------------+                   |
  |                                                           |
+-------------+                                               |
| Waiting for |                                               v
|  last 200   |<------------------------+             +------------+
+-------------+                         |             | '202' sent |
     ^                                  |             +------------+
     |                                  |               |     |
     |                                  +---------------+     |
     | API terminate/                     API terminate/      |
     | REPORT terminate                   REPORT terminate    |
     |                                                        |
   +--------------------+                                     |
   | 'update' confirmed |------+                  API update/ |
   +--------------------+      |                REPORT update |
             ^                 | API update/                  |
             |                 | REPORT update                |
             |                 v                              |
             |   200/-      +---------------+                 |
             +--------------| 'update' sent |<----------------+
                            +---------------+

              Figure 1: Media Server CFW State Diagram
              +--------------+   202/-   +--------------+
          +-->| CONTROL sent |---------->| 202 received |
          |   +--------------+           +--------------+
          |        |       |                 |     |
          |        |       |                 |     |
API CONTROL/ |        | 200/- |                 |     |
send CONTROL |        |       |                 |     |
          |        |       | Error/          |     |
+------------------+  |       | Error           |     |
| Idle/'terminate' |<-+       |                 |     |
+------------------+<---------+                 |     |
    ^          ^                                |     |
    |          |            REPORT 'terminate'/ |     |
    |          |                       send 200 |     |
    |          +--------------------------------+     | REPORT 'update'/
    |                                                 | send 200
    | REPORT 'terminate'/                             |
    | send 200                                        |
    |                     +-----------+               |
    +---------------------| 'update ' |<--------------+
                          +-----------+
                            ^      |
                            |      | REPORT 'update'/
                            +------+ send 200

             Figure 2: Application Server CFW State Diagram
                                 +--------------+
                             +-->| CONTROL sent |
                             |   +--------------+
                             |           |
                             |           |
                API CONTROL/ |           | 200/-
                send CONTROL |           |
                             |           |
                +------------------+     |
                | Idle/'terminate' |<----+
                +------------------+

                       (Media Server perspective)



        +------------------+  CONTROL/-  +------------------+
        | Idle/'terminate' |------------>| CONTROL received |
        +------------------+             +------------------+
                     ^       API 200/200          |
                     |                            |
                     +----------------------------+

                    (Application Server perspective)

                    Figure 3: Event Notifications

5. Control Channel Establishment 🎀

okay bestie, before an AS and an MS can talk about anything, they need a Control Channel between them 🦋 That's the very first step, and [RFC6230] says so. You get it set up with a connection-oriented media (COMEDIA) [RFC4145] [RFC4572] negotiation, which we'll unpack in the next subsection 🌸 That negotiation gives you a reliable connection between the AS and the MS. This is also where the two of them agree on the transport-level protocol (TCP / Stream Control Transmission Protocol (SCTP)) and whether any application-level security is needed (like TLS 🔐). To keep things simple, we're assuming an unencrypted TCP connection gets negotiated 💖 Once they've connected, a SYNC message from the AS to the MS officially consolidates the Control Channel ✨ There's also a keep-alive example coming up in the next paragraphs, and for completeness we include a couple of common mistakes people make during Control Channel establishment 🙈

           AS                              MS
           |                               |
           | INVITE (COMEDIA)              |
           |------------------------------>|
           |                  100 (Trying) |
           |<------------------------------|
           |              200 OK (COMEDIA) |
           |<------------------------------|
           | ACK                           |
           |------------------------------>|
           |                               |
           |==============================>|
           | TCP CONNECT (CTRL CHANNEL)    |
           |==============================>|
           |                               |
           | SYNC (Dialog-ID, etc.)        |
           |+++++++++++++++++++++++++++++>>|
           |                               |--+
           |                               |  | Check SYNC
           |                               |<-+
           |                        200 OK |
           |<<+++++++++++++++++++++++++++++|
           |                               |
           .                               .
           .                               .

              Figure 4: Control Channel Establishment

5.1. COMEDIA Negotiation 💖

okay so first things first, the AS and the MS set up a Control SIP dialog 🎀, and the AS is usually the one who starts it. The AS sends a SIP INVITE with an SDP body that describes the TCP connection it wants to make with the MS 📞. In the example (check Figure 5 and the call flow), the AS wants to actively open a new TCP connection, bound to port 5757 on its side 🦋. If the request is good, the MS replies with the transport address the AS should connect to, and here the MS listens on port 7575 🌸. Once that's all sorted, the AS can finally connect to the MS ✨.

The negotiation has extra attributes too. The 'cfw-id' one is the MVP 👑 because it carries the Dialog-ID, which both the AS and the MS refer to later on, as described in [RFC6230] 💅.

                  AS                              MS
                  |                               |
                  | 1. INVITE (COMEDIA)           |
                  |------------------------------>|
                  |               2. 100 (Trying) |
                  |<------------------------------|
                  |           3. 200 OK (COMEDIA) |
                  |<------------------------------|
                  | 4. ACK                        |
                  |------------------------------>|
                  |                               |
                  |==============================>|
                  | TCP CONNECT (CTRL CHANNEL)    |
                  |==============================>|
                  |                               |
                  .                               .
                  .                               .

Figure 5: COMEDIA Negotiation: Sequence Diagram

1. AS -> MS (SIP INVITE)

INVITE sip:MediaServer@ms.example.net:5060 SIP/2.0
Via: SIP/2.0/UDP 203.0.113.1:5060;\
        branch=z9hG4bK-d8754z-9b07c8201c3aa510-1---d8754z-;rport=5060
Max-Forwards: 70
Contact: <sip:ApplicationServer@203.0.113.1:5060>
To: <sip:MediaServer@ms.example.net:5060>
From: <sip:ApplicationServer@as.example.com:5060>;tag=4354ec63
Call-ID: MDk2YTk1MDU3YmVkZjgzYTQwYmJlNjE5NTA4ZDQ1OGY.
CSeq: 1 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, UPDATE, REGISTER
Content-Type: application/sdp
Content-Length: 203

v=0
o=lminiero 2890844526 2890842807 IN IP4 as.example.com
s=MediaCtrl
c=IN IP4 as.example.com
t=0 0
m=application 5757 TCP cfw
a=connection:new
a=setup:active
a=cfw-id:5feb6486792a

2. AS <- MS (SIP 100 Trying)

SIP/2.0 100 Trying
Via: SIP/2.0/UDP 203.0.113.1:5060; \
        branch=z9hG4bK-d8754z-9b07c8201c3aa510-1---d8754z-;rport=5060
To: <sip:MediaServer@ms.example.net:5060>;tag=499a5b74
From: <sip:ApplicationServer@as.example.com:5060>;tag=4354ec63
Call-ID: MDk2YTk1MDU3YmVkZjgzYTQwYmJlNjE5NTA4ZDQ1OGY.
CSeq: 1 INVITE
Content-Length: 0

3. AS <- MS (SIP 200 OK)

SIP/2.0 200 OK
Via: SIP/2.0/UDP 203.0.113.1:5060; \
        branch=z9hG4bK-d8754z-9b07c8201c3aa510-1---d8754z-;rport=5060
Contact: <sip:MediaServer@ms.example.net:5060>
To: <sip:MediaServer@ms.example.net:5060>;tag=499a5b74
From: <sip:ApplicationServer@as.example.com:5060>;tag=4354ec63
Call-ID: MDk2YTk1MDU3YmVkZjgzYTQwYmJlNjE5NTA4ZDQ1OGY.
CSeq: 1 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, UPDATE, REGISTER
Content-Type: application/sdp
Content-Length: 199

v=0
o=lminiero 2890844526 2890842808 IN IP4 ms.example.net
s=MediaCtrl
c=IN IP4 ms.example.net
t=0 0
m=application 7575 TCP cfw
a=connection:new
a=setup:passive
a=cfw-id:5feb6486792a

4. AS -> MS (SIP ACK)

ACK sip:MediaServer@ms.example.net:5060 SIP/2.0
Via: SIP/2.0/UDP 203.0.113.1:5060; \
             branch=z9hG4bK-d8754z-22940f5f4589701b-1---d8754z-;rport
Max-Forwards: 70
Contact: <sip:ApplicationServer@203.0.113.1:5060>
To: <sip:MediaServer@ms.example.net:5060>;tag=499a5b74
From: <sip:ApplicationServer@as.example.com:5060>;tag=4354ec63
Call-ID: MDk2YTk1MDU3YmVkZjgzYTQwYmJlNjE5NTA4ZDQ1OGY.
CSeq: 1 ACK
Content-Length: 0

5.2. SYNC ✨

okay so once the AS and the MS have a TCP connection, there's one more step before the Control Channel is usable 🧚. Like we just saw, the very first thing they do is a SIP dialog, and that dialog is what makes the TCP connection happen 🔗. That means the two things, the SIP dialog and the TCP connection, need a proper correlation, so the MS can be sure the connection came from the AS that asked for it 🕵️. This is handled by a dedicated framework message called a SYNC message 💜. The SYNC uses a unique identifier called the Dialog-ID to validate the Control Channel. The Dialog-ID is meant to be globally unique, so the caller (the AS in the call flow) generates it and adds it as an SDP media attribute (cfw-id) to the COMEDIA negotiation, so both sides know its value:

                   a=cfw-id:5feb6486792a
                            ^^^^^^^^^^^^

SYNC does even more than correlating ✨. The AS uses it to negotiate which Control Packages it's interested in, and to agree on a 'Keep-Alive' timer that both the AS and the MS need, so they'll know if something goes wrong on the connection 🫶. In the example (see Figure 6 and the related call flow), the AS sends a SYNC with a Dialog-ID built as needed (using the 'cfw-id' attribute from the SIP dialog) and asks for two Control Packages: the Interactive Voice Response (IVR) package and the Mixer package 🎤. The AS also tells the MS that a 100-second timeout should be used for keep-alive messages ⏱️. The MS checks the received Dialog-ID against the SIP dialog values. Assuming it supports the Control Packages the AS asked for (and for the sake of this document, we assume it does 🙈), it answers with a 200 message. The MS also hands the AS a list of other unrequested packages it supports, which here is just a dummy package for testing 🧪.

          AS                              MS
          .                               .
          .                               .
          |                               |
          | 1. SYNC (Dialog-ID, etc.)     |
          |+++++++++++++++++++++++++++++>>|
          |                               |--+
          |                               |  | Check SYNC
          |                               |<-+
          |                     2. 200 OK |
          |<<+++++++++++++++++++++++++++++|
          |                               |
          .                               .
          .                               .

Figure 6: SYNC: Sequence Diagram

1. AS -> MS (CFW SYNC)

CFW 6e5e86f95609 SYNC
Dialog-ID: 5feb6486792a
Keep-Alive: 100
Packages: msc-ivr/1.0,msc-mixer/1.0

2. AS <- MS (CFW 200)

CFW 6e5e86f95609 200
Keep-Alive: 100
Packages: msc-ivr/1.0,msc-mixer/1.0
Supported: msc-example-pkg/1.0

The framework-level transaction identifier is obviously the same in both the request and the response (6e5e86f95609), since the AS needs to be able to match the response to the original request 💖. At this point the Control Channel is finally established 🎉, and the AS can use it to request services from the MS 💅.

5.3. K-ALIVE 💖

Okay so, [RFC6230] gives us a keep-alive mechanism, and it's honestly so needed 😭 Any NAT or firewall sitting between an AS and an MS can be a problem. These boxes have timeout values for the TCP connections they handle, so if no traffic shows up on a connection for a while, they can shut it down. That can happen to a Control Channel between an AS and an MS that just sits there unused for some time. So [RFC6230] defines a dedicated framework message (K-ALIVE) that the AS and MS can use to generate traffic on the TCP connection and keep it alive. ✨

As we covered in Section 5.2, the SYNC request is what sets the timeout value for the keep-alive mechanism. In our example, the AS asked for 100 seconds. The timeout value isn't actually negotiated between the AS and MS, though. Whichever endpoint takes the active role just specifies it. The 100-second value fits how NATs and firewalls are usually set up, since their timeout before closing TCP connections is most often around 2 minutes. That number matters a lot here. The active role (the AS, in this case) has to send a K-ALIVE message before those 100 seconds pass. If it doesn't, the passive role (the MS) will tear down the connection and treat it like a timeout. 🙈 [RFC6230] takes a more cautious approach to this timeout value and suggests triggering the K-ALIVE message before 80% of the negotiated time has passed (80 seconds, in this case). That's exactly what Figure 7 shows. 🎀

                   AS                              MS
                   .                               .
                   .                               .
                   |                               |
     ~80 s have +--|                               |
   passed since |  |                               |
   last K-ALIVE +->|                               |
                   | 1. K-ALIVE                    |
                   |+++++++++++++++++++++++++++++>>|
                   |                               |--+ Reset the local
                   |                               |  | 'Keep-Alive'
                   |                               |<-+ timer
                   |                     2. 200 OK |
                   |<<+++++++++++++++++++++++++++++|
      Reset the +--|                               |
          local |  |                               |
   'Keep-Alive' +->|                               |
          timer    |                               |
                   .                               .
                   .                               .

                    Figure 7: K-ALIVE: Sequence Diagram

Once the Control Channel is established (COMEDIA+SYNC), both the AS and the MS start local 'Keep-Alive' timers that are mapped to the negotiated keep-alive timeout value (100 seconds). When about 80 seconds have passed since the timer started (that's 80% of 100 seconds), the AS sends a framework-level K-ALIVE message to the MS. This message is super lightweight in the protocol message dump: it's just a single line with no additional header. When the MS gets the K-ALIVE message, it resets its local 'Keep-Alive' timer and sends back a 200 message as confirmation. As soon as the AS receives that 200 message, it resets its own local 'Keep-Alive' timer too, and then the whole thing starts over again. 🔁

Here are the actual transaction steps:

1. AS -> MS (K-ALIVE)
---------------------
   CFW 518ba6047880 K-ALIVE


2. AS <- MS (CFW 200)
---------------------
   CFW 518ba6047880 200

If a timer expired in either the AS or the MS (meaning the K-ALIVE or the 200 arrived after the 100 seconds), the entity that noticed the timeout would tear down the connection and the associated SIP control dialog. That ends the interaction between the AS and the MS. 💀


5.4. Wrong Behavior 🙅‍♀️

This section is a quick look at some of the most common mistakes people make when setting up a Control Channel between an AS and an MS. These are a big deal, because they leave the AS and the MS unable to talk to each other at all. Specifically, we'll go through these two simple scenarios:

  1. an AS providing the MS with a wrong Dialog-ID in the initial SYNC.
  2. an AS sending a generic CONTROL message instead of SYNC as a first transaction.

The first scenario is shown in Figure 8. 👀

         AS                              MS
         .                               .
         .                               .
         |                               |
         | 1. SYNC (Dialog-ID, etc.)     |
         |+++++++++++++++++++++++++++++>>|
         |                               |--+
         |                               |  | Check SYNC (wrong!)
         |                               |<-+
         |                        2. 481 |
         |<<+++++++++++++++++++++++++++++|
         |                               |
         |<-XX- CLOSE TCP CONNECTION -XX-|
         |                               |
         | SIP BYE                       |
         |------------------------------>|
         |                               |
         .                               .
         .                               .

       Figure 8: SYNC with Wrong Dialog-ID: Sequence Diagram

This is similar to the scenario in Section 5.2, with one twist: instead of the correct, expected Dialog-ID in the SYNC message (5feb6486792a, the one negotiated via COMEDIA), the AS uses a wrong value (4hrn7490012c). That makes the SYNC transaction fail. First, the MS sends a framework-level 481 message. When it's sent in reply to a SYNC message, a 481 means that the SIP dialog tied to the Dialog-ID you provided (the wrong one) doesn't exist. The Control Channel has to be torn down as a result, so the MS also closes the TCP connection the SYNC message came in on. At this point the AS is supposed to tear down its SIP control dialog too, so it sends a SIP BYE to the MS. 😤

The actual transaction looks like this:

1. AS -> MS (CFW SYNC with wrong Dialog-ID)
-------------------------------------------
   CFW 2b4dd8724f27 SYNC
   Dialog-ID: 4hrn7490012c
   Keep-Alive: 100
   Packages: msc-ivr/1.0,msc-mixer/1.0


2. AS <- MS (CFW 481)
---------------------
   CFW 2b4dd8724f27 481

The second scenario is shown in Figure 9. 🧐

         AS                              MS
         .                               .
         .                               .
         |                               |
         | 1. CONTROL                    |
         |+++++++++++++++++++++++++++++>>|
         |                               |--+ First transaction
         |                               |  | is not a SYNC
         |                               |<-+
         |                        2. 403 |
         |<<+++++++++++++++++++++++++++++|
         |                               |
         |<-XX- CLOSE TCP CONNECTION -XX-|
         |                               |
         | SIP BYE                       |
         |------------------------------>|
         |                               |
         .                               .
         .                               .

      Figure 9: Incorrect First Transaction: Sequence Diagram

This one is another common slip-up when you're trying to set up a Control Channel. [RFC6230] requires the first transaction after the COMEDIA negotiation to be a SYNC, which is what concludes the setup. If the AS sends something else instead of the SYNC message, like the <audit> message aimed at the IVR Control Package in the example below, the MS treats it as an error. So the MS replies with a framework-level 403 message (Forbidden) and, just like before, closes the TCP connection and waits for the related SIP control dialog to be torn down. 🚫

The actual transaction is shown below:

1. AS -> MS (CFW CONTROL instead of SYNC)
-----------------------------------------
   CFW 101fbbd62c35 CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 78

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
      <audit/>
   </mscivr>


2. AS <- MS (CFW 403 Forbidden)
-------------------------------
   CFW 101fbbd62c35 403

6. Use-Case Scenarios and Examples ✨

okay so these scenarios were picked bc they pop up in basically every rich real-time multimedia app 🎀 each one is shown as a set of call flows covering both the SIP/SDP signaling (UACs<->AS<->MS) and the Control Channel chat (AS<->MS) 💅

all the examples assume a Control Channel is already set up and SYNCed between the reference AS and MS 🫶 unless we say otherwise, every example uses the same UAC session too. that session is set up like Figure 10 shows 🦋

   UAC                  AS                          MS
    |                   |                           |
    | INVITE (X)        |                           |
    |------------------>|                           |
    |     180 (Ringing) |                           |
    |<------------------|                           |
    |                   |--+                        |
    |                   |  | Handle app(X)          |
    |                   |<-+                        |
    |                   | INVITE (Y) as 3PCC        |
    |                   |-------------------------->|
    |                   |              100 (Trying) |
    |                   |<--------------------------|
    |                   |                           |--+ Negotiate media
    |                   |                           |  | with UAC; map
    |                   |                           |<-+ tags and labels
    |                   |                    200 OK |
    |                   |<--------------------------|
    |            200 OK |                           |
    |<------------------|                           |
    | ACK               |                           |
    |------------------>|                           |
    |                   | ACK                       |
    |                   |-------------------------->|
    |                   |                           |
    |<<###########################################>>|
    |         RTP Media Stream(s) flowing           |
    |<<###########################################>>|
    |                   |                           |
    .                   .                           .
    .                   .                           .

                     Figure 10: 3PCC Sequence Diagram
Note well: this is just ONE example of a possible way to do Third-Party Call Control (3PCC) negotiation between the UAC, the AS, and the MS. it is not the mandatory way, and it's not best common practice for this scenario either 🙈 [RFC3725] has several different solutions and loads of details on how 3PCC can be realized, with pros and cons. also, the two INVITEs in the figure are different SIP dialogs, so keep that in mind 🧚

the UAC starts by placing a call to a SIP URI that the AS is responsible for 📞 the specific URI doesn't matter here, bc the logic that maps a URI to the service it gives you is only something the AS cares about. so we use a generic sip:mediactrlDemo@as.example.com in every example, and the service behind it gets mapped to each scenario's case as we go 💖 the UAC INVITE is handled as envisaged in [RFC5567]. the AS forwards the INVITE to the MS via a third party (e.g., the 3PCC approach) and it does NOT touch the SDP the UAC sent, so the MS can fully negotiate the session based on its own description 🌸 the MS matches the UAC's offer against its own capabilities and gives its answer in a 200 OK. the AS then forwards that answer to the target UAC, again without changing the SDP contents 👑 so while the SIP signaling from the UAC ends at the AS, all the media starts flowing directly between the UAC and the MS. main character energy for the media, honestly 🦋

as a result of this negotiation, one or more media connections get created between the MS and the UAC 🌈 when needed, the AS and the MS address them using the concatenation of tags, as specified in [RFC6230]. the sample signaling below shows how the identifiers get created and addressed 🍓

1. UAC -> AS (SIP INVITE)

   INVITE sip:mediactrlDemo@as.example.com SIP/2.0
   Via: SIP/2.0/UDP 203.0.113.2:5063;rport;branch=z9hG4bK1396873708
   From: <sip:lminiero@users.example.com>;tag=1153573888
   To: <sip:mediactrlDemo@as.example.com>
   Call-ID: 1355333098
   CSeq: 20 INVITE
   Contact: <sip:lminiero@203.0.113.2:5063>
   Content-Type: application/sdp
   Max-Forwards: 70
   User-Agent: Linphone/2.1.1 (eXosip2/3.0.3)
   Subject: Phone call
   Expires: 120
   Content-Length: 330
   v=0
   o=lminiero 123456 654321 IN IP4 203.0.113.2
   s=A conversation
   c=IN IP4 203.0.113.2
   t=0 0
   m=audio 7078 RTP/AVP 0 3 8 101
   a=rtpmap:0 PCMU/8000/1
   a=rtpmap:3 GSM/8000/1
   a=rtpmap:8 PCMA/8000/1
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-11
   m=video 9078 RTP/AVP 98
   a=rtpmap:98 H263-1998/90000
   a=fmtp:98 CIF=1;QCIF=1

2. UAC <- AS (SIP 180 Ringing)

   SIP/2.0 180 Ringing
   Via: SIP/2.0/UDP 203.0.113.2:5063;rport=5063; \
                                                branch=z9hG4bK1396873708
   Contact: <sip:mediactrlDemo@as.example.com>
   To: <sip:mediactrlDemo@as.example.com>;tag=bcd47c32
   From: <sip:lminiero@users.example.com>;tag=1153573888
   Call-ID: 1355333098
   CSeq: 20 INVITE
   Content-Length: 0

3. AS -> MS (SIP INVITE)

   INVITE sip:MediaServer@ms.example.net:5060;transport=UDP SIP/2.0
   Via: SIP/2.0/UDP 203.0.113.1:5060; \
                branch=z9hG4bK-d8754z-8723e421ebc45f6b-1---d8754z-;rport
   Max-Forwards: 70
   Contact: <sip:ApplicationServer@203.0.113.1:5060>
   To: <sip:MediaServer@ms.example.net:5060>
   From: <sip:ApplicationServer@as.example.com:5060>;tag=10514b7f
   Call-ID: NzI0ZjQ0ZTBlMTEzMGU1ZjVhMjk5NTliMmJmZjE0NDQ.
   CSeq: 1 INVITE
   Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, UPDATE, REGISTER
   Content-Type: application/sdp
   Content-Length: 330
   v=0
   o=lminiero 123456 654321 IN IP4 203.0.113.2
   s=A conversation
   c=IN IP4 203.0.113.2
   t=0 0
   m=audio 7078 RTP/AVP 0 3 8 101
   a=rtpmap:0 PCMU/8000/1
   a=rtpmap:3 GSM/8000/1
   a=rtpmap:8 PCMA/8000/1
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-11
   m=video 9078 RTP/AVP 98
   a=rtpmap:98 H263-1998/90000
   a=fmtp:98 CIF=1;QCIF=1

4. AS <- MS (SIP 100 Trying)

   SIP/2.0 100 Trying
   Via: SIP/2.0/UDP 203.0.113.1:5060; \
           branch=z9hG4bK-d8754z-8723e421ebc45f6b-1---d8754z-;rport=5060
   To: <sip:MediaServer@ms.example.net:5060>;tag=6a900179
   From: <sip:ApplicationServer@as.example.com:5060>;tag=10514b7f
   Call-ID: NzI0ZjQ0ZTBlMTEzMGU1ZjVhMjk5NTliMmJmZjE0NDQ.
   CSeq: 1 INVITE
   Content-Length: 0

5. AS <- MS (SIP 200 OK)

   SIP/2.0 200 OK
   Via: SIP/2.0/UDP 203.0.113.1:5060; \
           branch=z9hG4bK-d8754z-8723e421ebc45f6b-1---d8754z-;rport=5060
   Contact: <sip:MediaServer@ms.example.net:5060>
   To: <sip:MediaServer@ms.example.net:5060>;tag=6a900179
   From: <sip:ApplicationServer@as.example.com:5060>;tag=10514b7f
   Call-ID: NzI0ZjQ0ZTBlMTEzMGU1ZjVhMjk5NTliMmJmZjE0NDQ.
   CSeq: 1 INVITE
   Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, UPDATE, REGISTER
   Content-Type: application/sdp
   Content-Length: 374

   v=0
   o=lminiero 123456 654322 IN IP4 ms.example.net
   s=MediaCtrl
   c=IN IP4 ms.example.net
   t=0 0
   m=audio 63442 RTP/AVP 0 3 8 101
   a=rtpmap:0 PCMU/8000
   a=rtpmap:3 GSM/8000
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-15
   a=ptime:20
   a=label:7eda834
   m=video 33468 RTP/AVP 98
   a=rtpmap:98 H263-1998/90000
   a=fmtp:98 CIF=2
   a=label:0132ca2

6. UAC <- AS (SIP 200 OK)

   SIP/2.0 200 OK
   Via: SIP/2.0/UDP 203.0.113.2:5063;rport=5063; \
                                                branch=z9hG4bK1396873708
   Contact: <sip:mediactrlDemo@as.example.com>
   To: <sip:mediactrlDemo@as.example.com>;tag=bcd47c32
   From: <sip:lminiero@users.example.com>;tag=1153573888
   Call-ID: 1355333098
   CSeq: 20 INVITE
   Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, UPDATE, REGISTER
   Content-Type: application/sdp
   Content-Length: 374

   v=0
   o=lminiero 123456 654322 IN IP4 ms.example.net
   s=MediaCtrl
   c=IN IP4 ms.example.net
   t=0 0
   m=audio 63442 RTP/AVP 0 3 8 101
   a=rtpmap:0 PCMU/8000
   a=rtpmap:3 GSM/8000
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-15
   a=ptime:20
   a=label:7eda834
   m=video 33468 RTP/AVP 98
   a=rtpmap:98 H263-1998/90000
   a=fmtp:98 CIF=2
   a=label:0132ca2

7. UAC -> AS (SIP ACK)

   ACK sip:mediactrlDemo@as.example.com SIP/2.0
   Via: SIP/2.0/UDP 203.0.113.2:5063;rport;branch=z9hG4bK1113338059
   From: <sip:lminiero@users.example.com>;tag=1153573888
   To: <sip:mediactrlDemo@as.example.com>;tag=bcd47c32
   Call-ID: 1355333098
   CSeq: 20 ACK
   Contact: <sip:lminiero@203.0.113.2:5063>
   Max-Forwards: 70
   User-Agent: Linphone/2.1.1 (eXosip2/3.0.3)
   Content-Length: 0

8. AS -> MS (SIP ACK)

   ACK sip:MediaServer@ms.example.net:5060;transport=UDP SIP/2.0
   Via: SIP/2.0/UDP 203.0.113.1:5060; \
                branch=z9hG4bK-d8754z-5246003419ccd662-1---d8754z-;rport
   Max-Forwards: 70
   Contact: <sip:ApplicationServer@203.0.113.1:5060>
   To: <sip:MediaServer@ms.example.net:5060;tag=6a900179
   From: <sip:ApplicationServer@as.example.com:5060>;tag=10514b7f
   Call-ID: NzI0ZjQ0ZTBlMTEzMGU1ZjVhMjk5NTliMmJmZjE0NDQ.
   CSeq: 1 ACK
   Content-Length: 0

Okay so after that 3PCC negotiation 🤝✨ we can pull out some really important info. Lowkey the whole thing is built around this. 💅

  1. The 'From' and 'To' tags (10514b7f and 6a900179, respectively) of the AS<->MS session. Here they are, with the tag values marked:
   From: <sip:ApplicationServer@as.example.com:5060>;tag=10514b7f
                                                         ^^^^^^^^
   To: <sip:MediaServer@ms.example.net:5060>;tag=6a900179
                                                 ^^^^^^^^
  1. The labels [RFC4574] attached to the negotiated media connections. In this case that's an audio stream (7eda834) and a video stream (0132ca2) 🎀:
   m=audio 63442 RTP/AVP 0 3 8 101
   [..]
   a=label:7eda834
           ^^^^^^^

   m=video 33468 RTP/AVP 98
   [..]
   a=label:0132ca2
           ^^^^^^^

These four identifiers are what let the AS and MS point at each other's connections for the related UAC, and there's zero confusion about it. They're univocal and unambiguous, bestie 🫶. Here's how each one works:

  1. 10514b7f:6a900179, the 'From' and 'To' tags stuck together with a colon (':'), targets all the media connections between the MS and the UAC 🌈.
  2. 10514b7f:6a900179 <-> 7eda834 is that same value linked to the label attribute. This one only targets one of the UAC's media connections, which here is the audio stream 🎧. The example scenarios will make this clearer, but the explicit identifiers in requests can only target 'from:tag' connections. So you'd need an extra mechanism for finer control over individual media streams, like the <stream> element in package-level requests 🧚.
The mapping the AS makes between the UAC<->AS and AS<->MS SIP dialogs is out of scope for this document. We just assume the AS knows how to address the right connection for its session with a UAC, like playing an announcement to one specific UAC. And honestly this is super important, because the AS is responsible for all the business logic of the multimedia app it provides 👑.

6.1. Echo Test ✨

The echo test is the simplest example scenario you can build with an MS 🪞. Basically, a UAC directly or indirectly "talks" to itself. Here's the media perspective, in Figure 11 💖:

           +-------+  A (RTP)                 +--------+
           |  UAC  |=========================>| Media  |
           |   A   |<=========================| Server |
           +-------+                 A (RTP)  +--------+

               Figure 11: Echo Test: Media Perspective

From the framework's point of view, when the UAC's leg isn't attached to anything yet, you get what's in Figure 12. Since there's no connection involving the UAC yet, any frames it sends get thrown away, and nothing gets sent back to it, except silence if its transmission was requested 🙈.

                                        MS
                                     +------+
                        UAC          |      |
                         o----->>-------x   |
                         o.....<<.......x   |
                                     |      |
                                     +------+

          Figure 12: Echo Test: UAC Media Leg Not Attached

Based on all that, this document explores two different approaches to the Echo Test scenario 🦋:

  1. A Direct Echo Test approach, where the UAC directly talks to itself.
  2. A Recording-based Echo Test approach, where the UAC indirectly talks to itself.

6.1.1. Direct Echo Test 💜

In the Direct Echo Test approach, the UAC is directly connected to itself 🔁. As Figure 13 shows, each frame the MS receives from the UAC gets sent right back to it in real time ⚡.

                                        MS
                                     +------+
                        UAC          |      |
                         o----->>-------@   |
                         o-----<<-------@   |
                                     |      |
                                     +------+

         Figure 13: Echo Test: Direct Echo (Self-Connection)

In the framework, you can make this happen with the Mixer Control Package [RFC6505], which handles joining connections and conferences 🎀.

Here's a sequence diagram of a potential transaction, in Figure 14 🌸:

UAC                      AS                                 MS
 |                       |                                  |
 |                       | 1. CONTROL (join UAC to itself)  |
 |                       |++++++++++++++++++++++++++++++++>>|
 |                       |                                  |--+ self-
 |                       |                                  |  | join
 |                       |                        2. 200 OK |<-+ UAC
 |                       |<<++++++++++++++++++++++++++++++++|
 |                       |                                  |
 |<<######################################################>>|
 |         Everything is now echoed back to the UAC         |
 |<<######################################################>>|
 |                       |                                  |
 .                       .                                  .
 .                       .                                  .

          Figure 14: Self-Connection: Framework Transaction

Here's the step-by-step, bestie 📝:

  • The AS asks the MS to join the connection to itself by sending a CONTROL request (1). It's specifically meant for the conferencing Control Package (msc-mixer/1.0). It uses a <join> request, and since the connection has to attach to itself, both id1 and id2 are set to the same value, which is the connectionid 💅.
  • The MS checks the request is valid and enforces the join of the connection to itself 🔥. That means every frame the UAC sends gets sent back to it. To report the result, the MS replies to the AS with a 200 OK (2), which wraps up the transaction 🎉. The transaction succeeded, as shown by the body of the message (the 200 status code in the <response> tag) ✨.

The full transaction, meaning the complete bodies of the messages, is right here 👀:

  1. AS -> MS (CFW CONTROL)
   CFW 4fed9bf147e2 CONTROL
   Control-Package: msc-mixer/1.0
   Content-Type: application/msc-mixer+xml
   Content-Length: 130

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <join id1="10514b7f:6a900179" id2="10514b7f:6a900179"/>
   </mscmixer>
  1. AS <- MS (CFW 200 OK)
   CFW 4fed9bf147e2 200
   Timeout: 10
   Content-Type: application/msc-mixer+xml
   Content-Length: 125

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <response status="200" reason="Join successful"/>
   </mscmixer>

6.1.2. Echo Test Based on Recording 🎙️

In the Recording-based Echo Test approach, the UAC is not directly connected to itself. It's connected indirectly 🌀. Figure 15 shows the flow: each frame the MS receives from the UAC gets recorded first, and then once recording ends, all those recorded frames are played back to the UAC as an announcement 📼.

                             MS
                          +------+
             UAC          |      |
              o----->>-------+~~~~~> (recording.wav) ~~+
              o-----<<-------+   |                     |
                          |  ^   |                     v
                          +--|---+                     |
                             +~~~~~~~~~~~<<~~~~~~~~~~~~+

              Figure 15: Echo Test: Recording Involved

In the framework, you can do this with the IVR Control Package [RFC6231], which handles both the recording and the playout phases 🎬. Here's the catch though: the whole scenario can't happen in a single transaction. You need at least two steps 🫣:

  1. First, a recording has to take place, preceded by an announcement if one was requested.
  2. Then, a playout of the previously recorded media has to happen.

So you need to invoke two separate transactions 💖. Here's the sequence diagram of that potential multiple transaction, in Figure 16:

Echo Test Based on Recording, the picture 🎬

 UAC                      AS                                 MS
  |                       |                                  |
  |                       | A1. CONTROL (record for 10s)     |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                          A2. 202 |
  |                       |<<++++++++++++++++++++++++++++++++| prepare &
  |                       |                                  |--+ start
  |                       |                                  |  | the
  |                       |           A3. REPORT (terminate) |<-+ dialog
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | A4. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  |<<########################################################|
  |           "This is an echo test: say something"          |
  |<<########################################################|
  |                       |                                  |
  |########################################################>>|
  |          10 s of audio from the UAC are recorded         |--+ save
  |########################################################>>|  | in a
  |                       |                                  |<-+ file
  |                       |       B1. CONTROL (<recordinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |       Use recorded +--| B2. 200 OK                       |
  |       file to play |  |++++++++++++++++++++++++++++++++>>|
  |       announcement +->|                                  |
  |                       | C1. CONTROL (play recorded)      |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                          C2. 202 |
  |                       |<<++++++++++++++++++++++++++++++++| prepare &
  |                       |                                  |--+ start
  |                       |                                  |  | the
  |                       |           C3. REPORT (terminate) |<-+ dialog
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | C4. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  |<<########################################################|
  |         "Can you hear me? It's me, UAC, talking"         |
  |<<########################################################|
  |                       |                                  |
  |                       |       D1. CONTROL (<promptinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | D2. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  .                       .                                  .
  .                       .                                  .

Figure 16: Recording-Based Echo: Two Framework Transactions ✨

Okay so look at the diagram, the very first thing that jumps out 👀 is that, unlike the Direct Echo vibe, the MS does not reply with a 200 to the CONTROL the AS sent. Instead it sends a 202 provisional first, and then a REPORT. The 202+REPORT(s) combo is what the MS uses whenever it wants to tell the AS that the requested operation might take longer than the limit in the Control Package definition. So the <join> in Direct Echo was expected to be done super fast, but the IVR request was assumed to take a bit longer 🐢. The 202 gives a timeout value and basically says "hold on, the dialog might not be ready right away." Here the prep finishes before the timeout, so the transaction wraps up with a REPORT terminate, which does the same job the 200 did in the last example 💅. If the prep had taken longer than the timeout, an extra REPORT update would've shown up with a new timeout value, and so on, until the REPORT terminate finally lands 🫶.

Also, the REPORT thing in this diagram is only there to show how it works. In real life, the 202+REPORT mechanism is only needed when the transaction is expected to take a long time (for example, grabbing a big media file for a prompt from an external server) 📦. Here the prep would be way quicker, so it would most likely finish inside one simple CONTROL+200 request/response. The next scenarios only bring in 202+REPORTs when they're strictly necessary, so don't panic if they look different 🌸.

Now, the dialog itself. Notice how the AS-originated CONTROL transactions get terminated as soon as the requested dialogs start 🧚. As specified in [RFC6231], the MS uses a framework CONTROL message to report the result of the dialog and how it went. The two transactions (the AS-generated CONTROL request and the MS-generated CONTROL event) are correlated using the associated dialog identifier, which we'll get into below. Same as before, the steps are numbered, and the letter in front tells you which transaction you're looking at: A and B are the recording, C and D are the playout 🎀.

  • The AS kicks off the first transaction by invoking a recording on the UAC connection with a CONTROL request (A1). The body is for the IVR package (msc-ivr/1.0) and asks for the start (<dialogstart>) of a new recording context (<record>). The recording must be preceded by an announcement (<prompt>), must not last longer than 10 s (maxtime), and cannot be interrupted by a DTMF tone (dtmfterm=false). This is only done once (the missing repeatCount attribute is 1 by default for a <dialog>), which means that if the recording does not succeed the first time, the transaction must fail 😬. A video recording is requested (since the associated connection includes both audio and video and nothing restricts the streams to record), and it's going to be fed by both of the negotiated media streams 🎥. A beep has to be played (beep=true) right before the recording starts, so the UAC knows it's go time 🔔.
  • As we saw before, the MS sends a provisional 202 response to let the AS know the operation might need some time ⏳.
  • Meanwhile, the MS gets the dialog ready (for example by fetching the announcement file, which comes with an HTTP URL, and checking that the request is well formed 🔍). If everything looks good, it starts the dialog and tells the AS with a new REPORT (A3) with a terminated status 🚀. Like we covered, interlocutory REPORT messages with an update status would have shown up if the prep ran past the timeout given in the 202 message (say, if fetching the resource over HTTP took longer than expected). Once the dialog is prepared and started, the UAC connection gets handed over to the IVR package, which plays the announcement first, then a beep, and then records all the incoming frames into a buffer 🎙️. The MS also gives the AS a unique dialog identifier (dialogid) that shows up in every later event notification about that dialog 🪪.
  • The AS acks the latest REPORT (A4), which wraps up this transaction, and then just waits for the results 🥱.
  • Once the recording is done, the MS prepares a notification CONTROL (B1). The <event> body explicitly references the dialog identifier from before, so the AS knows the notification belongs to that specific dialog 🔗. The event body is then filled in with the recording info (<recordinfo>), which in this case is the path to the recorded file (an HTTP URL) that the AS can use for whatever it needs 📁. The payload also has info about the prompt (<promptinfo>), but that doesn't matter for this scenario 🤷‍♀️.
  • The AS closes out this first recording transaction by acking the CONTROL event (B2) ✅.

Okay, the first transaction is done! The AS now has the 10-s recording of the UAC talking, so it can let the UAC hear it back by having the MS play it as an announcement 🔁.

  • In the second transaction, the AS invokes a playout on the UAC connection with a brand new CONTROL request (C1). The body is once again for the IVR package (msc-ivr/1.0), but this time it asks for the start (<dialogstart>) of a new announcement context (<prompt>). The file to play is the one that was recorded before (<media>) 🎶.
  • Again, the usual provisional 202 (C2) shows up 🙃.
  • In the meantime, the MS prepares and starts the new dialog, and tells the AS with a new REPORT (C3) with a terminated status. The connection then goes to the IVR package, which plays the file on it 📢.
  • The AS acks the terminating REPORT (C4), and now it's just waiting for the announcement to finish ⏳.
  • Once the playout is over, the MS sends a CONTROL event (D1) whose body (<promptinfo>) has info about the announcement that just wrapped up. Same as before, the right dialogid is used as the reference to the correct dialog 🎯.
  • The AS closes out this second and last transaction by acking the CONTROL event (D2) 💖.

Just like in the previous paragraph, the full CFW interaction is shown below so you can really dig into how the protocol behaves 🔍✨.

A1. AS -> MS (CFW CONTROL, record)

   CFW 796d83aa1ce4 CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 265

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <dialogstart connectionid="10514b7f:6a900179">
       <dialog>
         <prompt>
           <media
             loc="http://www.example.com/demo/echorecord.mpg"/>
         </prompt>
         <record beep="true" maxtime="10s"/>
       </dialog>
     </dialogstart>
   </mscivr>

A2. AS <- MS (CFW 202)

   CFW 796d83aa1ce4 202
   Timeout: 5

A3. AS <- MS (CFW REPORT terminate)

   CFW 796d83aa1ce4 REPORT
   Seq: 1
   Status: terminate
   Timeout: 25
   Content-Type: application/msc-ivr+xml
   Content-Length: 137

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
      <response status="200" reason="Dialog started"
                dialogid="68d6569"/>
   </mscivr>

A4. AS -> MS (CFW 200, ACK to 'REPORT terminate')

   CFW 796d83aa1ce4 200
   Seq: 1

B1. AS <- MS (CFW CONTROL event)

   CFW 0eb1678c0bfc CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 403
      <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
        <event dialogid="68d6569">
          <dialogexit status="1" reason="Dialog successfully completed">
            <promptinfo duration="9987" termmode="completed"/>
            <recordinfo duration="10017" termmode="maxtime">
              <mediainfo
     loc="http://www.example.net/recordings/recording-68d6569.mpg"
     type="video/mpeg" size="591872"/>
            </recordinfo>
          </dialogexit>
        </event>
      </mscivr>

B2. AS -> MS (CFW 200, ACK to 'CONTROL event') ✨

      CFW 0eb1678c0bfc 200

C1. AS -> MS (CFW CONTROL, play) 🎬

      CFW 1632eead7e3b CONTROL
      Control-Package: msc-ivr/1.0
      Content-Type: application/msc-ivr+xml
      Content-Length: 241

      <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
        <dialogstart connectionid="10514b7f:6a900179">
          <dialog>
            <prompt>
              <media
     loc="http://www.example.net/recordings/recording-68d6569.mpg"/>
            </prompt>
          </dialog>
        </dialogstart>
      </mscivr>

C2. AS <- MS (CFW 202) 🙌

      CFW 1632eead7e3b 202
      Timeout: 5

C3. AS <- MS (CFW REPORT terminate) 🛑

      CFW 1632eead7e3b REPORT
      Seq: 1
      Status: terminate
      Timeout: 25
      Content-Type: application/msc-ivr+xml
      Content-Length: 137

      <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
         <response status="200" reason="Dialog started"
                   dialogid="5f5cb45"/>
      </mscivr>

C4. AS -> MS (CFW 200, ACK to 'REPORT terminate') 💅

      CFW 1632eead7e3b 200
      Seq: 1

D1. AS <- MS (CFW CONTROL event) 🎉

      CFW 502a5fd83db8 CONTROL
      Control-Package: msc-ivr/1.0
      Content-Type: application/msc-ivr+xml
      Content-Length: 230

      <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
        <event dialogid="5f5cb45">
          <dialogexit status="1" reason="Dialog successfully completed">
            <promptinfo duration="10366" termmode="completed"/>
          </dialogexit>
        </event>
      </mscivr>

D2. AS -> MS (CFW 200, ACK to 'CONTROL event') 🌈

      CFW 502a5fd83db8 200

6.2. Phone Call

Okay bestie, now we're getting into the classic phone call 📞✨ between two UACs. Like, the most straightforward move is letting the UACs negotiate the session and the media between themselves 💅, but ngl there are times when the services of an MS are actually super useful for calls too 🎀.

One of those times is when the two UACs have no common supported codecs 🙈. If they negotiate directly, they'd end up with a session that has no available media at all 💀. Bringing in the MS as a transcoder still lets them talk to each other 🫶. Another lowkey iconic case is when the AS (or any other entity the AS is working on behalf of) wants to manipulate or monitor the media session between the UACs, like recording the convo 🎙️. A similar scenario gets covered in Section 6.2.2 👑.

Before we look at how the Media Control Channel Framework pulls this off, it's worth peeking at what the SIP signaling with all the interested parties might look like 👀. In this kind of scenario, a 3PCC approach is absolutely needed 😭. Figure 17 has an example. Again, this is not at all best common practice when 3PCC is needed in a MEDIACTRL-based framework 🙅, it's just there to help you understand what the requirements are on the MS side and what info might be needed as a result 🧠. [RFC3725] gives a way more detailed overview of 3PCC patterns across several use cases 📚. Here we only get an explanatory sequence diagram, no deep dive into the exchanged SIP messages 🦋.

   UAC(1)        UAC(2)                  AS                          MS
     |             |                     |                           |
     | INVITE (offer A)                  |                           |
     | Call-Id: A  |                     |                           |
     |---------------------------------->|                           |
     |             |          100 Trying |                           |
     |             |          Call-Id: A |                           |
     |<----------------------------------|                           |
     |             |   INVITE (no offer) |                           |
     |             |   Call-Id: B        |                           |
     |             |<--------------------|                           |
     |             | 180 Ringing         |                           |
     |             | Call-Id: B          |                           |
     |             |-------------------->|                           |
     |             |         180 Ringing |                           |
     |             |          Call-Id: A |                           |
     |<----------------------------------|                           |
     |             |                     | INVITE (offer A)          |
     |             |                     | Call-Id: C                |
     |             |                     |-------------------------->|
     |             |                     |         200 OK (offer A') |
     |             |                     |         Call-Id: C        |
     |             |                     |<--------------------------|
     |             |                     | ACK                       |
     |             |                     | Call-Id: C                |
     |             |                     |-------------------------->|
     |             | 200 OK (offer B)    |                           |
     |             | Call-Id: B          |                           |
     |             |-------------------->|                           |
     |             |                     | INVITE (offer B)          |
     |             |                     | Call-Id: D                |
     |             |                     |-------------------------->|
     |             |                     |         200 OK (offer B') |
     |             |                     |         Call-Id: D        |
     |             |                     |<--------------------------|
     |             |                     | ACK                       |
     |             |                     | Call-Id: D                |
     |             |                     |-------------------------->|
     |             |      ACK (offer B') |                           |
     |             |      Call-Id: B     |                           |
     |             |<--------------------|                           |
     |             |   200 OK (offer A') |                           |
     |             |   Call-Id: A        |                           |
     |<----------------------------------|                           |
     | ACK         |                     |                           |
     | Call-Id: A  |                     |                           |
     |---------------------------------->|                           |
     |             |                     |                           |
     .             .                     .                           .
     .             .                     .                           .

                  Figure 17: Phone Call: Example of 3PCC

So in this example, UAC1 wants to place a phone call to UAC2 📱. To make that happen, it sends an INVITE to the AS with its offer A 💌. The AS then sends an offerless INVITE to UAC2 📤. When UAC2 responds with a 180, the AS forwards that same message to UAC1 so it knows the callee is ringing 🔔. Meanwhile, the AS also adds a leg to the MS for UAC1, as explained at the beginning of Section 6 🧩. To do that, it of course uses the offer A that UAC1 made 💖. Once UAC2 accepts the call by providing its own offer B in the 200, the AS also adds a leg for offer B to the MS 🥳. At this point, the negotiation can be wrapped up by giving the two UACs the SDP answer that the MS negotiated with each of them (A' and B', respectively) 🎀.

Obviously this is just one way to handle the signaling, so it's definitely not meant to be treated as an absolutely mandatory approach 🙃.

Once the negotiation is over, the two UACs are still not in communication yet 🙉. It's up to the AS to actively trigger the MS to attach their media streams to each other, by referring to the connection identifiers associated with the UACs as explained previously 🔗. This document presents two different approaches you can take, depending on what you need to accomplish 🌸. A generic media perspective of the phone call scenario is shown in Figure 18. The MS is basically sitting right in the media path between the two UACs 🧚.

   +-------+  UAC1 (RTP)        +--------+  UAC1 (RTP)        +-------+
   |  UAC  |===================>| Media  |===================>|  UAC  |
   |   1   |<===================| Server |<===================|   2   |
   +-------+        UAC2 (RTP)  +--------+        UAC2 (RTP)  +-------+

                 Figure 18: Phone Call: Media Perspective

From the framework point of view, when the UACs' legs aren't attached to anything yet, things look like Figure 19 🍓. Since there are no connections involving the UACs yet, any frames they might be sending get discarded, and nothing gets sent back to them (except for silence, if its transmission has been requested) 🤫.

                                     MS
                              +--------------+
                UAC 1         |              |         UAC 2
                  o----->>-------x        x.......>>.....o
                  o.....<<.......x        x-------<<-----o
                              |              |
                              +--------------+

             Figure 19: Phone Call: UAC Media Leg Not Attached

6.2.1. Direct Connection

Okay so the Direct Connection approach is the easiest one, and honestly the most straightforward way to get a phone call between two UACs working 💅 It's basically the same vibe as the Direct Echo approach. A <join> directive plugs one UAC straight into the other, and the MS only steps in to handle transcoding or adaptation of the flowing frames, if that's needed 🦋

Here's what it looks like in Figure 20 ✨

                                 MS
                          +--------------+
            UAC 1         |              |         UAC 2
              o----->>-------+~~~>>~~~+------->>-----o
              o-----<<-------+~~~<<~~~+-------<<-----o
                          |              |
                          +--------------+

             Figure 20: Phone Call: Direct Connection
UAC1       UAC2         AS                                   MS
 |           |          |                                    |
 |           |          | 1. CONTROL (join UAC1 to UAC2)     |
 |           |          |++++++++++++++++++++++++++++++++++>>|
 |           |          |                                    |--+ join
 |           |          |                                    |  | UAC1
 |           |          |                          2. 200 OK |<-+ UAC2
 |           |          |<<++++++++++++++++++++++++++++++++++|
 |           |          |                                    |
 |<<#######################################################>>|
 |                UAC1 can hear UAC2 talking                 |
 |<<#######################################################>>|
 |           |          |                                    |
 |           |<<###########################################>>|
 |           |          UAC2 can hear UAC1 talking           |
 |           |<<###########################################>>|
 |           |          |                                    |
 |<*talking*>|          |                                    |
 .           .          .                                    .
 .           .          .                                    .

         Figure 21: Direct Connection: Framework Transactions

The framework transactions for this one are super trivial and easy to follow 🌸 They're basically the same as the Direct Echo Test scenario, the only difference being the identifiers you pass in. This time the MS isn't supposed to attach the UACs' media connections to itself. Instead it joins the media connections of two different UACs, UAC1 and UAC2, so id1 and i2 have to point at the media connections of UAC1 and UAC2 🧚 If the transaction goes through, the MS forwards all media from UAC1 to UAC2 and the other way around, quietly handling any transcoding needed along the way ✨

1. AS -> MS (CFW CONTROL)

CFW 0600855d24c8 CONTROL
Control-Package: msc-mixer/1.0
Content-Type: application/msc-mixer+xml
Content-Length: 130

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <join id1="10514b7f:6a900179" id2="e1e1427c:1c998d22"/>
</mscmixer>

2. AS <- MS (CFW 200 OK)

CFW 0600855d24c8 200
Timeout: 10
Content-Type: application/msc-mixer+xml
Content-Length: 125

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <response status="200" reason="Join successful"/>
</mscmixer>

Now, this simple approach does have drawbacks 🙈 For example, recording a conversation between two users can get tricky. Since nothing is mixed, only the single connections (UAC1<->MS and UAC2<->MS) could be recorded. If the AS still wants a conversation-recording service, it needs extra business logic on its side. Section 6.2.3 has an example of that use case 💜


6.2.2. Conference-Based Approach

The Direct Connection approach totally works for a basic phone call, but like we said before, it can fall short once you want fancier features 💅 For instance, you can't record the whole conversation, only the individual connections, because nothing gets mixed. Even something as simple as playing an announcement over the conversation could get messy, especially if the MS doesn't support implicit mixing over media connections 😭 So for the more advanced stuff, you might go with the conference-based approach covered in this section 👑

The idea is to use a mixing entity inside the MS that acts as a bridge between the two UACs 🌈 Having that entity in the middle gives you way more control over what happens to the conversation, like recording it (which is the example we mentioned earlier). It's shown in Figure 22. The mixing functionality in the MS gets a deeper dive in the next section, which covers a bunch of conference-related scenarios, so here we're only dropping some hints so you can get the basic idea 🦋

                                   MS
                           +---------------+
             UAC A         |               |         UAC B
               o----->>-------+~~>{#}::>+:::::::>>:::::o
               o:::::<<:::::::+<::{#}<~~+-------<<-----o
                           |       :       |
                           |       :       |
                           +-------:-------+
                                   :
                                   +::::> (conversation.wav)

          Figure 22: Phone Call: Conference-Based Approach

To make this concrete, let's look at a sample scenario where the AS wants to record a phone call 🎀

Figure 23 shows how this can be done in the Media Control Channel Framework 🧚 As usual, this example skips the earlier chatter between the UACs and the AS and zooms in on the Control Channel operations and what comes after 💖

UAC1        UAC2       AS                                 MS
 |           |         |                                  |
 |           |         | A1. CONTROL (create conference)  |
 |           |         |++++++++++++++++++++++++++++++++>>|
 |           |         |                                  |--+ create
 |           |         |                                  |  | conf and
 |           |         |      A2. 200 OK (conferenceid=Y) |<-+ its ID
 |           |         |<<++++++++++++++++++++++++++++++++|
 |           |         |                                  |
 |           |         | B1. CONTROL (record for 10800 s) |
 |           |         |++++++++++++++++++++++++++++++++>>|
 |           |         |                                  |--+ start
 |           |         |                                  |  | the
 |           |         |                       B2. 200 OK |<-+ dialog
 |           |         |<<++++++++++++++++++++++++++++++++|
 |        Recording +--|                                  |
 |       of the mix |  |                                  |
 |      has started +->|                                  |
 |           |         | C1. CONTROL (join UAC1<->confY)  |
 |           |         |++++++++++++++++++++++++++++++++>>|
 |           |         |                                  |--+  join
 |           |         |                                  |  | UAC1 &
 |           |         |                       C2. 200 OK |<-+ confY
 |           |         |<<++++++++++++++++++++++++++++++++|
 |           |         |                                  |
 |<<####################################################>>|
 |           Now UAC1 is mixed in the conference          |
 |<<####################################################>>|
 |           |         |                                  |
 |           |         | D1. CONTROL (join UAC2<->confY)  |
 |           |         |++++++++++++++++++++++++++++++++>>|
 |           |         |                                  |--+  join
 |           |         |                                  |  | UAC2 &
 |           |         |                       D2. 200 OK |<-+ confY
 |           |         |<<++++++++++++++++++++++++++++++++|
 |           |         |                                  |
 |           |<<########################################>>|
 |           |            Now UAC2 is mixed too           |
 |           |<#########################################>>|
 |           |         |                                  |
 |<*talking*>|         |                                  |
 |           |         |                                  |
 .           .         .                                  .
 .           .         .                                  .

      Figure 23: Conference-Based Approach: Framework Transactions

The AS uses two different packages for this one 🔥 There's the Mixer package, which creates the mixing entity and joins the UACs, and the IVR package, which records whatever happens in the conference. Here are the framework transaction steps:

  • First up, the AS creates a brand new hidden conference with a <createconference> request (A1) 🌸 The conference is set up to match its purpose. Since only two participants will ever join, both 'reserved-talkers' and 'reserved-listeners' are set to 2, same as the 'n' value for the N-best audio mixing algorithm 💜 The video layout is set to match too (<single-view>/<dual-view>).
  • The MS tells the AS the conference was created successfully in a 200 framework message (A2) ✨ The identifier for the conference, which the AS will use in later requests aimed at it, is 6013f1e.
  • Next, the AS asks for a new recording of that conference 🎀 It sends a proper request to the IVR package (B1). The AS wants a video recording (type=video/mpeg) that can't run longer than 3 hours (maxtime=10800s), and then it has to end. No beep should play in the conference (beep=false), and the recording starts right away, whether or not any audio activity has been reported (vadinitial=false is the default value for <record>) 🦋
  • The MS handles that request, and once the dialog has started successfully, a 200 OK goes back to the AS (B2) 💖 The message includes the dialogid for that dialog (00b29fb), which the AS needs to reference for later notifications.
  • Finally, the AS attaches both UACs to the conference with two separate <join> directives (C1/D1) 🫶 When the MS confirms both operations (C2/D2), the two UACs are actually in contact with each other. It's indirect, though, since a hidden conference they don't know about sits on their path. Their media gets recorded along the way 🌈

A1. AS -> MS (CFW CONTROL, createconference)

   CFW 238e1f2946e8 CONTROL
   Control-Package: msc-mixer
   Content-Type: application/msc-mixer+xml
   Content-Length: 395

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <createconference reserved-talkers="2" reserved-listeners="2">
         <audio-mixing type="nbest" n="2"/>
         <video-layouts>
            <video-layout min-participants='1'>
               <single-view/>
            </video-layout>
            <video-layout min-participants='2'>
               <dual-view/>
            </video-layout>
         </video-layouts>
         <video-switch>
            <controller/>
         </video-switch>
      </createconference>
   </mscmixer>

A2. AS <- MS (CFW 200 OK) 🎀

   CFW 238e1f2946e8 200
   Timeout: 10
   Content-Type: application/msc-mixer+xml
   Content-Length: 151

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <response status="200" reason="Conference created"
                conferenceid="6013f1e"/>
   </mscmixer>

B1. AS -> MS (CFW CONTROL, record) 🦋

   CFW 515f007c5bd0 CONTROL
   Control-Package: msc-ivr
   Content-Type: application/msc-ivr+xml
   Content-Length: 226

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
      <dialogstart conferenceid="6013f1e">
         <dialog>
            <record beep="false" type="video/mpeg" maxtime="10800s"/>
         </dialog>
      </dialogstart>
   </mscivr>

B2. AS <- MS (CFW 200 OK) 🌸

   CFW 515f007c5bd0 200
   Timeout: 10
   Content-Type: application/msc-ivr+xml
   Content-Length: 137

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <response status="200" reason="Dialog started" dialogid="00b29fb"/>
   </mscivr>

C1. AS -> MS (CFW CONTROL, join) 💖

   CFW 0216231b1f16 CONTROL
   Control-Package: msc-mixer
   Content-Type: application/msc-mixer+xml
   Content-Length: 123

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <join id1="10514b7f:6a900179" id2="6013f1e"/>
   </mscmixer>

C2. AS <- MS (CFW 200 OK) ✨

   CFW 0216231b1f16 200
   Timeout: 10
   Content-Type: application/msc-mixer+xml
   Content-Length: 125

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <response status="200" reason="Join successful"/>
   </mscmixer>

D1. AS -> MS (CFW CONTROL, join) 🧚

   CFW 140e0f763352 CONTROL
   Control-Package: msc-mixer
   Content-Type: application/msc-mixer+xml
   Content-Length: 124

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <join id1="219782951:0b9d3347" id2="6013f1e"/>
   </mscmixer>

D2. AS <- MS (CFW 200 OK) 🍓

   CFW 140e0f763352 200
   Timeout: 10
   Content-Type: application/msc-mixer+xml
   Content-Length: 125

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <response status="200" reason="Join successful"/>
   </mscmixer>

okay so the AS can totally go grab the recording later 🎧 by waiting for an event notification from the MS. that event is tied to the recording dialog you already started, and it carries the URI of the recorded file. ngl this is the part where you get your file 🥹

the event can get triggered in two ways. either the dialog finishes naturally (e.g., it hit its programmed 3 hours ⏰) or the dialog gets interrupted (e.g., the AS actively asks for the recording to stop because the call between the UACs ended 📞). iconic behavior, honestly 💅

6.2.3. Recording a Conversation 🎀

okay so the last section showed how the conferencing bit of the Mixer package makes recording phone calls super simple 🫶. BUT using a whole dedicated mixer just for one phone call might be kinda overkill 💀. so this section is about recording a conversation and playing it back without a mixing entity in the call at all. we're talking the Direct Connection approach from Section 6.2.1 🦋

like we said before, if the AS wants to record a phone call between two UACs, using just the <join> directive with no mixer means the AS has to rely on separate recording commands 🙈. the MS records the media from each leg on its own: one recording for everything coming from UAC1, and a different one for everything coming from UAC2. if someone later wants the whole convo, the AS has at least two ways to handle it:

  1. It may mix the two recordings itself (e.g., by delegating it to an offline mixing entity) in order to obtain a single file containing the combination of the two recordings. This way, a simple playout as described in Section 6.1.2 would suffice.
  2. Alternatively, it may take advantage of the mixing functionality provided by the MS itself. One way to do this is to create a hidden conference on the MS, attach the UAC as a passive participant to it, and play the separate recordings on the conference as announcements. This way, the UAC accessing the recording would experience both of the recordings at the same time.

this section is all about option 2 ✨. the framework transaction in Figure 24 assumes a recording has already been requested for both UAC1 and UAC2, the phone call has ended, and the AS has successfully received the URIs to both recordings from the MS. we're not going over those steps again since they'd be basically the same as Section 6.1.2 🙃. the big idea is to use a properly built hidden conference to mix the two separate recordings on the fly and present them to the UAC. and of course it's totally up to the AS to unjoin the user from the conference and destroy the conference once the playout ends for any reason 🫡

 UAC3                     AS                                 MS
  |                       |                                  |
  | (UAC1 and UAC2 have previously been recorded; the AS has |
  |  the two different recordings available for playout.)    |
  |                       |                                  |
  |                       | A1. CONTROL (create conference)  |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |--+ create
  |                       |                                  |  | conf &
  |                       |      A2. 200 OK (conferenceid=Y) |<-+ its ID
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       |                                  |
  |                       | B1. CONTROL (join UAC3 & confY)  |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |--+ join
  |                       |                                  |  | UAC &
  |                       |                       B2. 200 OK |<-+ confY
  |                       |<+++++++++++++++++++++++++++++++++|
  |                       |                                  |
  |<<######################################################>>|
  |   UAC3 is now a passive participant in the conference    |
  |<<######################################################>>|
  |                       |                                  |
  |                       | C1. CONTROL (play REC1 on confY) |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       | D1. CONTROL (play REC2 on confY) |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |--+ Start
  |                       |                                  |  | both
  |                       |                                  |  | of the
  |                       |                                  |  |dialogs
  |                       |                       C2. 200 OK |<-+
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       |                       D2. 200 OK |
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       |                                  |
  |<<########################################################|
  |  The two recordings are mixed and played together to UAC |
  |<<########################################################|
  |                       |                                  |
  |                       |       E1. CONTROL (<promptinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | E2. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |       F1. CONTROL (<promptinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | F2. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  .                       .                                  .
  .                       .                                  .

         Figure 24: Phone Call: Playout of a Recorded Conversation

the diagram assumes both channels (UAC1 and UAC2) were already recorded. later, when we want to play the whole conversation to a brand new user, UAC3, the AS can handle all the transactions 🎬. honestly the steps look more complicated than they are. the only real difference is that transactions C and D run concurrently, since the recordings have to play together 👯

  • First of all, the AS creates a new conference to act as a mixing entity (A1). The settings for the conference are chosen according to the use case, e.g., the video layout, which is fixed to <dual-view>, and the switching type to <controller>. When the conference has been successfully created (A2), the AS takes note of the conference identifier. 🫶
  • At this point, UAC3 is attached to the conference as a passive user (B1). There would be no point in letting the user contribute to the conference mix, since he will only need to watch a recording. In order to specify his passive status, both the audio and video streams for the user are set to 'recvonly'. If the transaction succeeds, the MS notifies the AS (B2). main character energy for UAC3 👑
  • Once the conference has been created and UAC3 has been attached to it, the AS can request the playout of the recordings; in order to do so, it requests two concurrent <prompt> directives (C1 and D1), addressing the recording of UAC1 (REC1) and UAC2 (REC2), respectively. Both of the prompts must be played on the previously created conference and not to UAC3 directly, as can be deduced from the 'conferenceid' attribute of the <dialog> element. 🔥
  • The transactions "live their lives" exactly as explained for previous <prompt> examples. The originating transactions are first prepared and started (C2, D2), and then, as soon as the playout ends, a related CONTROL message is triggered by the MS (E1, F1). This notification may contain a <promptinfo> element with information about how the playout proceeded (e.g., whether the playout completed normally or was interrupted by a DTMF tone, etc.). the MS literally tells you how it went, bestie 🥹✨

A1. AS -> MS (CFW CONTROL, createconference) ✨

Okay bestie, first up is the AS asking the MS to create a conference 🎀

CFW 506e039f65bd CONTROL
Control-Package: msc-mixer/1.0
Content-Type: application/msc-mixer+xml
Content-Length: 312

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <createconference reserved-talkers="0" reserved-listeners="1">
      <audio-mixing type="controller"/>
      <video-layouts>
         <video-layout min-participants='1'>
            <dual-view/>
         </video-layout>
      </video-layouts>
      <video-switch>
         <controller/>
      </video-switch>
   </createconference>
</mscmixer>

A2. AS <- MS (CFW 200 OK) 💖

And the MS says yes, the conference exists now 🥹

CFW 506e039f65bd 200
Timeout: 10
Content-Type: application/msc-mixer+xml
Content-Length: 151

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <response status="200" reason="Conference created"
             conferenceid="2625069"/>
</mscmixer>

B1. AS -> MS (CFW CONTROL, join) 🦋

Now the AS asks for a join, so the conference can be linked up 🫶

CFW 09202baf0c81 CONTROL
Control-Package: msc-mixer/1.0
Content-Type: application/msc-mixer+xml
Content-Length: 214

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <join id1="aafaf62d:0eac5236" id2="2625069">
      <stream media="audio" direction="recvonly"/>
      <stream media="video" direction="recvonly"/>
   </join>
</mscmixer>

B2. AS <- MS (CFW 200 OK) 🌸

CFW 09202baf0c81 200
Timeout: 10
Content-Type: application/msc-mixer+xml
Content-Length: 125

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <response status="200" reason="Join successful"/>
</mscmixer>

C1. AS -> MS (CFW CONTROL, play recording from UAC1) 🎧

Next, the AS tells the MS to play UAC1's recording into the conference. Iconic 💅

CFW 3c2a08be4562 CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 229

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
   <dialogstart conferenceid="2625069">
      <dialog>
         <prompt>
            <media
loc="http://www.example.net/recordings/recording-4ca9fc2.mpg"/>
         </prompt>
      </dialog>
   </dialogstart>
</mscivr>

D1. AS -> MS (CFW CONTROL, play recording from UAC2) 🍓

Same energy, but for UAC2 this time 👑

CFW 1c268d810baa CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 229

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
   <dialogstart conferenceid="2625069">
      <dialog>
         <prompt>
            <media
loc="http://www.example.net/recordings/recording-39dfef4.mpg"/>
         </prompt>
      </dialog>
   </dialogstart>
</mscivr>

C2. AS <- MS (CFW 200 OK) 🧚

CFW 1c268d810baa 200
Timeout: 10
Content-Type: application/msc-ivr+xml
Content-Length: 137

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
   <response status="200" reason="Dialog started"
             dialogid="7a457cc"/>
</mscivr>

D2. AS <- MS (CFW 200 OK) 💜

CFW 3c2a08be4562 200
Timeout: 10
Content-Type: application/msc-ivr+xml
Content-Length: 137

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
   <response status="200" reason="Dialog started"
             dialogid="1a0c7cf"/>
</mscivr>

E1. AS <- MS (CFW CONTROL event, playout of recorded UAC1 ended) 😭

The MS reports that UAC1's playout has finished. Sad but iconic 🥲

CFW 77aec0735922 CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 230

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
   <event dialogid="7a457cc">
      <dialogexit status="1" reason="Dialog successfully completed">
         <promptinfo duration="10339" termmode="completed"/>
      </dialogexit>
   </event>
</mscivr>

E2. AS -> MS (CFW 200, ACK to 'CONTROL event') 🫶

CFW 77aec0735922 200

F1. AS <- MS (CFW CONTROL event, playout of recorded UAC2 ended) 🔥

And the same thing for UAC2, with its own duration 🌈

CFW 62726ace1660 CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 230

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
   <event dialogid="1a0c7cf">
      <dialogexit status="1" reason="Dialog successfully completed">
         <promptinfo duration="10342" termmode="completed"/>
      </dialogexit>
   </event>
</mscivr>

F2. AS -> MS (CFW 200, ACK to 'CONTROL event') ⭐

CFW 62726ace1660 200

6.3. Conferencing 🎀

Okay bestie, the MS has to be able to do mixing, and it's one of its most important jobs ✨ Mixing means taking media streams from different sources, combining them, and delivering the resulting mix(es) to each interested party, often based on per-user policies, settings, and encoding 💅 The classic example is media conferencing. Each participant's media gets mixed, and each participant usually gets the overall mix without their own contribution, encoded in the format they negotiated 🫶 This example really shows how mixing must take care of the profile of each involved entity 👑

Here's the media perspective (Figure 25) 🦋

                                +-------+
                                |  UAC  |
                                |   C   |
                                +-------+
                                   " ^
                           C (RTP) " "
                                   " "
                                   " " A+B (RTP)
                                   v "
   +-------+  A (RTP)           +--------+  A+C (RTP)         +-------+
   |  UAC  |===================>| Media  |===================>|  UAC  |
   |   A   |<===================| Server |<===================|   B   |
   +-------+         B+C (RTP)  +--------+           B (RTP)  +-------+

                 Figure 25: Conference: Media Perspective

From the framework point of view, when the UACs' legs aren't attached to anything yet, things look like Figure 26 🌸 There are no connections involving the UACs yet, so any frames they send get discarded, and nothing gets sent back to them (except silence, if its transmission is requested) 🙈

                                     MS
                             +----------------+
               UAC A         |                |         UAC B
                 o----->>-------x          x.......>>.....o
                 o.....<<.......x          x-------<<-----o
                             |                |
                             |                |
                             |       xx       |
                             |       |.       |
                             +-------|.-------+
                                     |.
                                     ^v
                                     ^v
                                     |.
                                     oo
                                   UAC C

               Figure 26: Conference: UAC Legs Not Attached

The next subsections cover several typical scenarios involving mixing and conferencing as a whole, specifically:

  1. Simple Bridging scenario, a very basic one (no "special effects", just mixing) with one or more participants.
  2. Rich Conference scenario, which levels up the Simple Bridging scenario with features you'd expect from conferencing systems (e.g., DTMF collection for PIN-based conference access, private and global announcements, recordings, and so on) 🎙️
  3. Coaching scenario, a more complex one with per-user mixing, since customers, agents, and coaches don't all get the same mixes 🧑‍🏫
  4. Sidebars scenario, which adds even more complexity by involving sidebars (separate conference instances that only exist within the context of a parent conference instance) and the custom media delivery that follows 🪞
  5. Floor Control scenario, which gives some guidance on how floor control could be involved in a MEDIACTRL-based media conference 🚦

All of these scenarios depend on a mixing entity being available ✨ The Media Control Channel Framework provides one through the conferencing package. Besides letting you interconnect media sources (like in the Direct Echo Test section), this package lets you create abstract connections that can be joined to multiple connections. These abstract connections, called conferences, mix the contribution of each attached connection and feed the mix back accordingly. For example, a connection with a 'sendrecv' property can contribute to the mix and listen to it, while a connection with a 'recvonly' property can only listen to the overall mix and can't actively contribute to it 🎧

That said, each of these scenarios starts more or less the same way: by creating a conference connection (or more than one, as needed in some cases) that gets referred to later when it's time to mix 💜 A typical framework transaction to create a new conference instance in the Media Control Channel Framework looks like Figure 27:

                    AS                                 MS
                    |                                  |
                    | 1. CONTROL (create conference)   |
                    |++++++++++++++++++++++++++++++++>>|
                    |                                  |--+ create
                    |                                  |  | conf and
                    |       2. 200 OK (conferenceid=Y) |<-+ its ID
                    |<<++++++++++++++++++++++++++++++++|
         map URI +--|                                  |
          X with |  |                                  |
           confY +->|                                  |
                    |                                  |
                    .                                  .
                    .                                  .

               Figure 27: Conference: Framework Transactions

The call flow is pretty straightforward and can usually be summed up in these steps:

  • The AS kicks off the creation of a new conference instance with a CONTROL request (1) 🚀 This request is addressed to the conferencing package (msc-mixer/1.0) and carries a <createconference> directive in the body, with all the settings you want for the new conference instance. In the example below, the mixing policy is to mix the five (reserved-talkers) loudest speakers (nbest), and up to ten listeners are allowed. Video settings are configured too, including the mechanism used to pick active video sources (<controller>, which means the AS will explicitly tell the MS about it), plus the video layouts to make available. Here the AS tells the MS to use a <single-view> layout when only one video source is active, switch to a <quad-view> layout when at least two video sources are active, and use a <multiple-5x1> layout whenever there are at least five sources. Finally, the AS subscribes to the "active-talkers" event, meaning it wants to be told (every 4 seconds) whenever an active participant is speaking 🗣️
  • The MS creates the conference instance, gives it a unique identifier (6146dd5), and wraps up the transaction with a 200 response (2) ✅
  • Now the requested conference instance is active and ready to go, and the AS can start using this identifier in its application logic. That part's on the AS 💅

1. AS -> MS (CFW CONTROL)

   CFW 3032e5fb79a1 CONTROL
   Control-Package: msc-mixer/1.0
   Content-Type: application/msc-mixer+xml
   Content-Length: 489

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
     <createconference reserved-talkers="5" reserved-listeners="10">
        <audio-mixing type="nbest"/>
        <video-layouts>
          <video-layout min-participants='1'>
             <single-view/>
          </video-layout>
          <video-layout min-participants='2'>
             <quad-view/>
          </video-layout>
          <video-layout min-participants='5'>
             <multiple-5x1/>
          </video-layout>
        </video-layouts>
        <video-switch>
           <controller/>
        </video-switch>
        <subscribe>
           <active-talkers-sub interval="4"/>
        </subscribe>
     </createconference>
   </mscmixer>

2. AS <- MS (CFW 200)

   CFW 3032e5fb79a1 200
   Timeout: 10
   Content-Type: application/msc-mixer+xml
   Content-Length: 151

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <response status="200" reason="Conference created"
                conferenceid="6146dd5"/>
   </mscmixer>

6.3.1. Simple Bridging ✨

okay so, like I mentioned before, the simplest way an AS can use a conference instance is simple bridging 🌸 The conference instance just acts as a bridge for everyone attached to it. The bridge handles transcoding if needed (lowkey essential, since different participants may use different codecs for their streams 🎀), echo cancellation (each participant gets the overall mix minus its own contribution, so nobody hears themselves 🙈), and per-participant mixing (each participant may get different mixed streams depending on what it needs and is allowed to send and receive 💅). This assumes every interested participant has to be joined to the bridge somehow, so they can talk indirectly to everyone else 🫶 From the media side it looks like Figure 28 🦋

                                  MS
                         +-----------------+
           UAC A         |                 |         UAC B
             o----->>-------+~~~>{##}:::>+:::::::>>:::::o
             o:::::<<:::::::+<:::{##}<~~~+-------<<-----o
                         |        ^:       |
                         |        |v       |
                         |        ++       |
                         |        |:       |
                         +--------|:-------+
                                  |:
                                  ^v
                                  ^v
                                  |:
                                  oo
                                UAC C

              Figure 28: Conference: Simple Bridging

Okay, first step is obviously creating a new conference instance, like we saw in the intro (Figure 27) 👑 Once a conference instance exists, bridging participants to it is super straightforward and works just like the Direct Echo Test scenario 💖 The only difference is that each participant isn't directly connected to itself (Direct Echo) or to another UAC (Direct Connection). Instead, it's connected to the bridge 🧚 Figure 29 shows two different UACs joining the same conference. As usual, the example skips the earlier chat between each UAC and the AS and just zooms in on what the AS does to get the participants into the bridge so they can interact in a conference ✨ Also, to keep the diagram readable, I'm using two identifiers (UAC1 and UAC2) instead of the ones we used to introduce the scenario (UAC A, B, C) 🌈

 UAC1      UAC2         AS                                   MS
  |          |          |                                    |
  |          |          | A1. CONTROL (join UAC1 and confY)  |
  |          |          |++++++++++++++++++++++++++++++++++>>|
  |          |          |                                    |--+  join
  |          |          |                                    |  | UAC1 &
  |          |          |                         A2. 200 OK |<-+ confY
  |          |          |<<++++++++++++++++++++++++++++++++++|
  |          |          |                                    |
  |<<######################################################>>|
  |            Now UAC1 is mixed in the conference           |
  |<<######################################################>>|
  |          |          |                                    |
  |          |          | B1. CONTROL (join UAC2 and confY)  |
  |          |          |++++++++++++++++++++++++++++++++++>>|
  |          |          |                                    |--+  join
  |          |          |                                    |  | UAC2 &
  |          |          |                         B2. 200 OK |<-+ confY
  |          |          |<<++++++++++++++++++++++++++++++++++|
  |          |          |                                    |
  |          |<<###########################################>>|
  |          |    Now UAC2 too is mixed in the conference    |
  |          |<<###########################################>>|
  |          |          |                                    |
  .          .          .                                    .
  .          .          .                                    .

          Figure 29: Simple Bridging: Framework Transactions (1)

The framework steps are honestly trivial, because they're very similar to scenarios we've already covered 💅 The AS joins UAC1 (id1 in A1) and UAC2 (id1 in B1) to the conference (id2 in both transactions). As a result, both UACs are mixed in the conference 🎉 No <stream> is given explicitly in either transaction, so all the media from the UACs (audio and video) gets attached to the conference, as long as the conference is configured to support both 🦋

A1. AS -> MS (CFW CONTROL)
--------------------------
   CFW 434a95786df8 CONTROL
   Control-Package: msc-mixer/1.0
   Content-Type: application/msc-mixer+xml
   Content-Length: 120

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <join id1="e1e1427c:1c998d22" id2="6146dd5"/>
   </mscmixer>


A2. AS <- MS (CFW 200 OK)
-------------------------
   CFW 434a95786df8 200
   Timeout: 10
   Content-Type: application/msc-mixer+xml
   Content-Length: 125

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <response status="200" reason="Join successful"/>
   </mscmixer>


B1. AS -> MS (CFW CONTROL)
--------------------------
   CFW 5c0cbd372046 CONTROL
   Control-Package: msc-mixer/1.0
   Content-Type: application/msc-mixer+xml
   Content-Length: 120

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <join id1="10514b7f:6a900179" id2="6146dd5"/>
   </mscmixer>

B2. AS <- MS (CFW 200 OK)
-------------------------
   CFW 5c0cbd372046 200
   Timeout: 10
   Content-Type: application/msc-mixer+xml
   Content-Length: 125

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <response status="200" reason="Join successful"/>
   </mscmixer>

Once one or more participants are attached to the bridge, their connections and how the bridge handles their media can be changed on the fly with another directive called <modifyjoin> 🎀 A classic use case is flipping the direction of an existing media stream. Say a participant who was speaking gets muted, so its media direction changes from 'sendrecv' to 'recvonly' 🙊 Figure 30 shows what a framework transaction asking for that might look like 💜

 UAC1      UAC2         AS                                 MS
  |          |          |                                  |
  |          |          | 1. CONTROL (modifyjoin UAC1)     |
  |          |          |++++++++++++++++++++++++++++++++>>|
  |          |          |                                  |--+ modify
  |          |          |                                  |  | join
  |          |          |                        2. 200 OK |<-+ settings
  |          |          |<<++++++++++++++++++++++++++++++++|
  |          |          |                                  |
  |<<######################################################|
  |      Now UAC1 can receive but not send (recvonly)      |
  |<<######################################################|
  |          |          |                                  |
  .          .          .                                  .
  .          .          .                                  .

          Figure 30: Simple Bridging: Framework Transactions (2)

The directive for changing an existing join is <modifyjoin>, and its syntax is exactly the same as the <join> instructions 🧁 The same identifiers (id1/id2) are used too. Whenever a <modifyjoin> arrives and id1 and id2 point at one or more joined connections, the AS is asking to change that join configuration 🔥 In this case, the AS tells the MS to mute UAC1 (id1=UAC1) in the conference it was previously attached to (id2), using <stream> media=audio, direction=recvonly. Any other connection between them is left alone 🌷

Here's the important bit: <stream> settings are enforced based on BOTH the direction provided AND the id1 and id2 identifiers 👑 In this example, id1 is UAC1 and id2 is the conference in the MS. So the change has to be applied to the stream named in the <stream> element, along the direction going from id1 to id2 (as set in the <modifyjoin> element). The AS wants to mute UAC1 relative to the conference, so the direction is 'recvonly'. That means that, as far as id1 is concerned, the media stream is only to be received 🫶 If id1 were the conference and id2 were UAC1, getting the same result would need the direction to be 'sendonly', meaning "id1 (the conference) can only send to id2 (UAC1), and no media stream must be received" 🙈 Other <stream> settings (like audio volume, region assignments, and so on) work the same way, as we'll see in later sections ✨

1. AS -> MS (CFW CONTROL)
-------------------------
   CFW 57f2195875c9 CONTROL
   Control-Package: msc-mixer/1.0
   Content-Type: application/msc-mixer+xml
   Content-Length: 182

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <modifyjoin id1="e1e1427c:1c998d22" id2="6146dd5">
         <stream media="audio" direction="recvonly"/>
      </modifyjoin>
   </mscmixer>


2. AS <- MS (CFW 200 OK)
------------------------
   CFW 57f2195875c9 200
   Timeout: 10
   Content-Type: application/msc-mixer+xml
   Content-Length: 123

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
      <response status="200" reason="Join modified"/>
   </mscmixer>

6.3.2. Rich Conference Scenario ✨

okay so the previous scenario can get a glow-up with extra features that existing conferencing systems totally have 💅 like IVR menus (think DTMF collection for PIN-based conference access 🔐), partial and complete recordings in the conference (for the "state your name" thing and recording the whole conference 🎙️), private and global announcements, and more. ALL of this is doable with what the MS offers 🦋. Even though the conferencing and IVR features come from different packages, the AS can talk to both and get complex results by correlating the effects of different transactions in its application logic 🧠. iconic, honestly.

From the media and framework perspective, a typical Rich Conference scenario looks like this, as shown in Figure 31 🌈:

                                   MS
                                    +-------- (announcement.wav)
  (conference_recording.wav) <:::::+|
                                   :|
                          +--------:|--------+
            UAC A         |        :v        |         UAC B
              o----->>-------+~~~>{##}:::>+:::::::>>:::::o
              o:::::<<:::::::+<:::{##}<~~~+-------<<-----o
                          |        ^:     |  |
                          |        |v     v  |
                          |        ++     * (collect DTMF, get name)
                          |        |:        |
                          +--------|:--------+
                                   |:
                                   ^v
                                   ^v
                                   |:
                                   oo
                                 UAC C

Figure 31: Conference: Rich Conference Scenario

To check out one sample scenario, let's look at a participant joining a conference (which, again, we assume has already been created) 🎀. It goes like this:

  1. The UAC as usual INVITEs a URI associated with a conference, and the AS follows the previously explained procedure to have the UAC negotiate a new media session with the MS.
  2. The UAC is presented with an IVR menu, in which it is requested to input a PIN code to access the conference.
  3. If the PIN is correct, the UAC is asked to state its name so that it can be recorded.
  4. The UAC is attached to the conference, and the previously recorded name is announced globally to the conference to advertise its arrival.

Figure 32 shows a single UAC joining a conference 🍓. As usual, the example skips the earlier chit-chat between the UAC and the AS and zooms in on what the AS does to actually interact with the participant and join them to the conference bridge.

 UAC                      AS                                 MS
  |                       |                                  |
  |                       | A1. CONTROL (request DTMF PIN)   |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |--+ start
  |                       |                                  |  | the
  |                       |                       A2. 200 OK |<-+ dialog
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       |                                  |
  |<<########################################################|
  |   "Please input the PIN number to join the conference"   |
  |<<########################################################|
  |                       |                                  |
  |########################################################>>|
  |                   DTMF digits are collected              |--+ get
  |########################################################>>|  | DTMF
  |                       |                                  |<-+ digits
  |                       |      B1. CONTROL (<collectinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |       Compare DTMF +--| B2. 200 OK                       |
  |        digits with |  |++++++++++++++++++++++++++++++++>>|
  |     the PIN number +->|                                  |
  |                       | C1. CONTROL (record name)        |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |--+ start
  |                       |                                  |  | the
  |                       |                       C2. 200 OK |<-+ dialog
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       |                                  |
  |<<########################################################|
  |          "Please state your name after the beep"         |
  |<<########################################################|
  |                       |                                  |
  |########################################################>>|
  |  Audio from the UAC is recorded (until timeout or DTMF)  |--+ save
  |########################################################>>|  | in a
  |                       |                                  |<-+ file
  |                       |       D1. CONTROL (<recordinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |     Store recorded +--| D2. 200 OK                       |
  |       file to play |  |++++++++++++++++++++++++++++++++>>|
  |    announcement in +->|                                  |
  |   conference later    |                                  |
  |                       | E1. CONTROL (join UAC & confY)   |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |--+ join
  |                       |                                  |  | UAC &
  |                       |                       E2. 200 OK |<-+ confY
  |                       |<+++++++++++++++++++++++++++++++++|
  |                       |                                  |
  |<<######################################################>>|
  |     UAC is now included in the mix of the conference     |
  |<<######################################################>>|
  |                       |                                  |
  |                       | F1. CONTROL (play name on confY) |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |--+ start
  |                       |                                  |  | the
  |                       |                       F2. 200 OK |<-+ dialog
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       |                                  |
  |<<########################################################|
  |  Global announcement: "Simon has joined the conference"  |
  |<<########################################################|
  |                       |                                  |
  |                       |       G1. CONTROL (<promptinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | G2. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  .                       .                                  .
  .                       .                                  .

Figure 32: Rich Conference Scenario: Framework Transactions

As you can deduce from the sequence diagram above, the AS, in its business logic, correlates the results of different transactions, addressed to different packages, to pull off a conferencing scenario that's way more complex than the Simple Bridging scenario we did before 👑. The framework transaction steps go like this:

  • Since this is a private conference, the UAC gets asked for a password, here a PIN number 🔐. So the AS tells the MS (A1) to collect a series of DTMF digits from the specified UAC (connectionid=UAC). The request includes both a voice message (<prompt>) and the digit collection context (<collect>). The PIN is assumed to be a 4-digit number, so the MS has to collect 4 digits maximum (maxdigits=4). The DTMF digit buffer must be cleared before collecting (cleardigitbuffer=true), and the UAC can use the star key to restart the collection (escapekey=*), e.g., if the UAC realizes they mistyped a digit and wants to start over 💀.
  • The transaction carries on as usual (A2), with the transaction getting handled and the dialog start notified in a 200 OK. After that, the UAC actually hears the voice message and gets asked to input the required PIN number.
  • We assume the UAC typed the correct PIN (1234) 🥹, which the MS reports to the AS with the usual MS-generated CONTROL event (B1). The AS links this event to the earlier started dialog by checking the referenced dialogid (06d1bac) and acks the event (B2). Then it pulls out what it needs from the event (here, the digits the MS provided) from the <controlinfo> container (dtmf=1234) and checks that they're correct.
  • Since the PIN is correct, the AS moves on to asking the UAC to state their name, so the recording can be played in the conference to announce the new participant 🎤. Again this is a request to the IVR package (C1). The AS tells the MS to play a voice message ("state your name after the beep"), followed by a recording of only the audio from the UAC (in stream, media=audio/sendonly, while media=video/inactive). A beep must be played right before the recording starts (beep=true), and the recording must only last 3 seconds (maxtime=3s), since it's just a brief announcement ⏱️.
  • Without going deep into the details of a recording-related transaction (C2), the AS finally gets the URI of the requested recording (D1, acked in D2).
  • Now the AS attaches the UAC (id1) to the conference (id2), just like in the Simple Bridging scenario (E1/E2) 🔗.
  • Finally, to tell the other participants a new person has arrived, the AS requests a global announcement on the conference 📣. This is a simple <prompt> request to the IVR package (F1), like we explained in earlier sections (e.g., Section 6.1.2, among others), but with a twist: the target of the prompt isn't a connectionid (a media connection) but the conference itself (conferenceid=6146dd5). As a result, the announcement would be played on all the media connections attached to the conference that are allowed to receive media from it. The AS specifically asks for two media files to be played:
    1. the media file with the recorded name of the new user as retrieved in D1 ("Simon...").
    2. a pre-recorded media file explaining what happened ("... has joined the conference").

The transaction then follows its usual flow (F2), and the event that notifies about the end of the announcement (G1, acked in G2) wraps up the scenario 🎉.

A1. AS -> MS (CFW CONTROL, collect)

CFW 50e56b8d65f9 CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 311

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
  <dialogstart connectionid="10514b7f:6a900179">
     <dialog>
       <prompt>
           <media
        loc="http://www.example.net/prompts/conf-getpin.wav"
        type="audio/x-wav"/>
       </prompt>
       <collect maxdigits="4" escapekey="*" cleardigitbuffer="true"/>
     </dialog>
  </dialogstart>
</mscivr>

Okay so that's the collect request 🎀 The AS asks the MS to play a PIN prompt and then gather up to 4 digits, with * as the escape key and the digit buffer cleared first. Iconic, honestly 💅

A2. AS <- MS (CFW 200 OK)

Here's the MS saying "yep, dialog started" ✨

CFW 50e56b8d65f9 200
Timeout: 10
Content-Type: application/msc-ivr+xml
Content-Length: 137

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
  <response status="200" reason="Dialog started" dialogid="06d1bac"/>
</mscivr>

B1. AS <- MS (CFW CONTROL event)

Later the MS comes back with the result 🦋 The dialog finished successfully, the prompt ran for 2312 and the digits 1234 matched. Main character energy, no cap 👑

CFW 166d68a76659 CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 272

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
   <event dialogid="06d1bac">
      <dialogexit status="1" reason="Dialog successfully completed">
         <promptinfo duration="2312" termmode="completed"/>
         <collectinfo dtmf="1234" termmode="match"/>
      </dialogexit>
   </event>
</mscivr>

B2. AS -> MS (CFW 200, ACK to 'CONTROL event')

And the AS just says "got it" back to the MS 🫶

CFW 166d68a76659 200

C1. AS -> MS (CFW CONTROL, record)

Now the AS wants a name recording 🎙️ It plays a prompt, then records for up to 3 seconds with a beep. It also sets the audio stream to sendonly and the video stream to inactive. Very specific, very iconic 🌸

CFW 61fd484f196e CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 373

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
   <dialogstart connectionid="10514b7f:6a900179">
      <dialog>
         <prompt>
            <media
      loc="http://www.example.net/prompts/conf-rec-name.wav"
      type="audio/x-wav"/>
         </prompt>
         <record beep="true" maxtime="3s"/>
      </dialog>
      <stream media="audio" direction="sendonly"/>
      <stream media="video" direction="inactive"/>
   </dialogstart>
</mscivr>

C2. AS <- MS (CFW 200 OK)

The MS confirms the record dialog started 🧚

CFW 61fd484f196e 200
Timeout: 10
Content-Type: application/msc-ivr+xml
Content-Length: 137

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
  <response status="200" reason="Dialog started" dialogid="1cf0549"/>
</mscivr>

D1. AS <- MS (CFW CONTROL event)

Recording's done 🥹 It ran for 3000 ms and stopped at maxtime, and the MS tells us where the file lives and how big it is (48044). The file is at http://www.example.net/recordings/recording-1cf0549.wav. Bestie, we did it 🎉

CFW 3ec13ab96224 CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 402

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
  <event dialogid="1cf0549">
    <dialogexit status="1" reason="Dialog successfully completed">
      <promptinfo duration="4988" termmode="completed"/>
      <recordinfo duration="3000" termmode="maxtime">
        <mediainfo
loc="http://www.example.net/recordings/recording-1cf0549.wav"
type="audio/x-wav" size="48044"/>
      </recordinfo>
    </dialogexit>
  </event>
</mscivr>

D2. AS -> MS (CFW 200, ACK to 'CONTROL event')

Ack sent, bestie 💌

CFW 3ec13ab96224 200

E1. AS -> MS (CFW CONTROL, join)

Time to join the caller to the conference 🌈 This uses the Mixer Control Package, msc-mixer/1.0, and joins connection 10514b7f:6a900179 with conference 6146dd5. Mixing era 🔥

CFW 261d188b63b7 CONTROL
Control-Package: msc-mixer/1.0
Content-Type: application/msc-mixer+xml
Content-Length: 120

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <join id1="10514b7f:6a900179" id2="6146dd5"/>
</mscmixer>

E2. AS <- MS (CFW 200 OK)

And the MS says "join successful" 💖

CFW 261d188b63b7 200
Timeout: 10
Content-Type: application/msc-mixer+xml
Content-Length: 125

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <response status="200" reason="Join successful"/>
</mscmixer>

F1. AS -> MS (CFW CONTROL, play)

Now the AS tells the MS to play two prompts into the conference 🎶 First the recording we just made, then a "someone has joined" prompt. Playing it back for the whole room, iconic 👑

CFW 718c30836f38 CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 334

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
  <dialogstart conferenceid="6146dd5">
    <dialog>
      <prompt>
        <media
loc="http://www.example.net/recordings/recording-1cf0549.wav"
type="audio/x-wav"/>
            <media
loc="http://www.example.net/prompts/conf-hasjoin.wav"
type="audio/x-wav"/>
      </prompt>
    </dialog>
  </dialogstart>
</mscivr>

F2. AS <- MS (CFW 200 OK)

The MS says the play dialog started 🦋

CFW 718c30836f38 200
Timeout: 10
Content-Type: application/msc-ivr+xml
Content-Length: 137

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
  <response status="200" reason="Dialog started" dialogid="5f4bc7e"/>
</mscivr>

G1. AS <- MS (CFW CONTROL event)

The playback finished completed, and it ran for 1838 ms 🎀

CFW 6485194f622f CONTROL
Control-Package: msc-ivr/1.0
Content-Type: application/msc-ivr+xml
Content-Length: 229

<mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
   <event dialogid="5f4bc7e">
      <dialogexit status="1" reason="Dialog successfully completed">
         <promptinfo duration="1838" termmode="completed"/>
      </dialogexit>
   </event>
</mscivr>

G2. AS -> MS (CFW 200, ACK to 'CONTROL event')

Final ack 🫶

CFW 6485194f622f 200

6.3.3. Coaching Scenario

Okay so this one is giving secret-agent energy 🕵️‍♀️ The Coaching scenario is another typical conference use case. A customer, "A", calls a business call center. An agent, "B", is assigned to them. A coach, "C", whom the customer cannot hear, whispers suggestions to the agent about what to say. This scenario is also described in [RFC4597].

Bestie, per-user policies for media mixing and delivery, meaning who can hear what, are everything here 🔥 The MS must make sure that only the agent can hear the coach's suggestions. Even though the customer might think it's just a two-person call, it's really a multiparty call 😭 So a mixing entity is needed to pull this off. The quick version:

  • The customer (A) must only hear what the agent (B) says.
  • The agent (B) must be able to hear both A and the coach (C).
  • C must be able to hear both A and B in order to give B the right suggestions and also be aware of the whole conversation.

From the media and framework point of view, the setup looks like Figure 33 💖

 **************              +-------+
 * A=Customer *              |  UAC  |
 * B=Agent    *              |   C   |
 * C=Coach    *              +-------+
 **************                 " ^
                        C (RTP) " "
                                " "
                                " " A+B (RTP)
                                v "
+-------+  A (RTP)           +--------+  A+C (RTP)         +-------+
|  UAC  |===================>| Media  |===================>|  UAC  |
|   A   |<===================| Server |<===================|   B   |
+-------+           B (RTP)  +--------+           B (RTP)  +-------+

           Figure 33: Coaching Scenario: Media Perspective

From the framework point of view, when the legs aren't attached to anything yet, it looks like Figure 34 🧚

                                 MS
                   +---------------------------+
                   |                           |
     UAC A         |                           |         UAC B
       o.....<<.......x                     x-------<<-----o
       o----->>-------x                     x.......>>.....o
                   |                           |
                   |                           |
                   |                           |
                   |                           |
                   |            xx             |
                   |            .|             +
                   +------------v^-------------+
                                v^
                                .|
                                .|
                                oo
                               UAC C

         Figure 34: Coaching Scenario: UAC Legs Not Attached

Now the vibe we actually want is Figure 35 🌸 The customer gets media straight from the agent (recvonly), while all three participants contribute to a hidden conference. The customer isn't allowed to receive the mixed flows from the conference (sendonly) 🙈 The agent and the coach, though, must both be aware of the whole conversation (sendrecv).

                                 MS
                   +---------------------------+
                   |                           |
     UAC A         |                           |         UAC B
       o-----<<-------+----<<----+----<<----+-------<<-----o
       o----->>-------+          |          +------->>-----o
                   |  |          v          ^  |
                   |  +~~~~~~~>[##]::::>::::+  |
                   |            v^             |
                   |            ||             |
                   |            ++             |
                   |            :|             +
                   +------------v^-------------+
                                v^
                                :|
                                :|
                                oo
                               UAC C

      Figure 35: Coaching Scenario: UAC Legs Mixed and Attached

In the framework, this is done with the Mixer Control Package, which we already saw in the earlier conferencing examples. It can be used whenever mixing and joining entities are needed 💅 The steps go like this:

  1. First of all, a hidden conference is created.
  2. Then, the three participants are all attached to it, each with a custom mixing policy, specifically:
    • the customer (A) as sendonly.
    • the agent (B) as sendrecv.
    • the coach (C) as sendrecv and with a gain of -3 dB to halve the volume of its own contribution (so that the agent actually hears the customer at a louder volume and hears the coach whispering).
  3. Finally, the customer is joined to the agent as a passive receiver (recvonly).

A diagram of this sequence of transactions is shown in Figure 36 👀

6.3.4. Sidebars 🎀

Okay bestie, so in conferencing there can be a need for sidebars (aka side conferences) 🫶 Picture this: a couple of people on a call want to whisper among themselves, but they still wanna hear a bit of the main call in the background 👂✨ Motivations for this are found in [RFC4597] and [RFC5239], so go check those if you're curious 💜

Here's the tea 🍵 The side conference is actually its own separate conference, but it still has to be somehow related to the original one. The application-level relationship is out of scope for this doc (that's giving XCON energy, "belongs" to Centralized Conferencing (XCON) 💅). The media stream relationship is the part that matters here, because it's a much stronger connection from the MEDIACTRL point of view 🦋 So we're gonna look at how sidebars could be used to build the conference mixes according to the MEDIACTRL specification 🌈

The scenario in this section has a conference hosting four participants: A, B, C, and D 🌸 All of them are attached as active senders and receivers of the existing media streams. Then at some point, B and D decide they want a sidebar just for the two of them 🧚 This sidebar is audio only. The audio mix of the sidebar must not be made available to the main conference, so A and C can't hear them 🙈 Meanwhile, the mix of the conference must be attached to the sidebar, but at a lower volume (30%), because it's just background to the actual convo 🍓

So the vibe is: B and D can talk to each other without A and C listening in, and they can still keep an overview of what's happening in the main conference 👑 Literally the best of both worlds, no cap 💖

From the media and framework perspective, this whole thing can be seen as depicted in Figure 37 ✨

From the framework point of view, when all the participants are attached to the main conference, what appears is shown in Figure 38.

                                 +-------+
                                 |  UAC  |
                                 |   C   |
                                 +-------+
                                    " ^
                            C (RTP) " "
                                    " "
                                    " " A (RTP)
                                    v "
    +-------+  A (RTP)           +--------+  D+[a+c] (RTP)     +-------+
    |  UAC  |===================>| Media  |===================>|  UAC  |
    |   A   |<===================| Server |<===================|   B   |
    +-------+           C (RTP)  +--------+           B (RTP)  +-------+
                                    ^ "
                                    " " B+[a+c] (RTP)
                                    " "
                            D (RTP) " "
                                    " v
                                 +-------+
                                 |  UAC  |
                                 |   D   |
                                 +-------+

Figure 37: Sidebars: Media Perspective

Okay, this is the picture from the media side, and it's giving busy 💅. Now let's zoom out to the framework view, where everyone is hanging out in the main conference together. 🌸

                                    UAC C
                                      oo
                                      :|
                                      ^v
                                      ^v
                                      :|
                             +--------:|-------+
                             |        :|       |
                             |        ++       |
               UAC A         |        ^|       |         UAC B
                 o----->>-------+~~~>{##}:::>+:::::::>>:::::o
                 o:::::<<:::::::+<:::{##}<~~~+-------<<-----o
                             |        ^:       |
                             |        |v       |
                             |        ++       |
                             |        |:       |
                             +--------|:-------+
                                      |:
                                      ^v
                                      ^v
                                      |:
                                      oo
                                    UAC D

Figure 38: Sidebars: UAC Legs in Main Conference

Now here's the glow-up we actually want 🦋✨. A new mixer gets created to host the sidebar. Then the main mix gets attached as sendonly to the sidebar mix at a lower volume, so the sidebar folks still get a little background of the main conference. Next, the two interested participants (B and D) get their audio leg detached from the main conference and attached to the sidebar. The detaching can happen by actually detaching the leg, or just by flipping the status of the leg to inactive, both are fine 🙌. Heads up, this only touches the audio stream. The video of those two is still attached to the main conference, and whatever happens at the application level may or may not have been changed to match (e.g., XCON protocol interactions) 👀.

Quick reminder that the main conference is assumed to already be in place, with A, B, C, and D all attached (sendrecv) to it.

                                 UAC C
                                   oo
                                   :|
                                   ^v
                                   ^v
                                   :|
                          +--------:|----------------+
                          |        :|                |
                          |        ++                |
            UAC A         |        ^|                |          UAC B
              o----->>-------+~~~>{##}:::>{##}:::>+:::::::>>:::::o
              o:::::<<:::::::+<:::{##}    {##}<~~~+-------<<-----o
                          |                ^:        |
                          |                ++        |
                          |                |v        |
                          +----------------|:--------+
                                           |:
                                           ^v
                                           ^v
                                           |:
                                           oo
                                          UAC D

Figure 39: Sidebars: UAC Legs Mixed and Attached

Sometimes you want to undo the whole sidebar drama 🙄. That can be done in the same way (for example, destroying the sidebar conference and reattaching B and D to the main conference mix). The AS would just need to unjoin B and D from the hidden conference and change their connection with the main conference back to sendrecv. After unjoining the main mix and the sidebar mix, the sidebar conference could then be destroyed. For brevity, and because similar transactions have already been presented, these steps are not described here 🫶.

Okay, so in the framework, just like in the previous section, this whole scenario can be pulled off with the Mixer Control Package 🎀. The steps look like this:

  1. First of all, a hidden conference is created (the sidebar mix).
  2. Then, the main conference mix is attached to it as sendonly and with a gain of -5 dB to limit the volume of its own contribution to 30% (so that B and D can hear each other at a louder volume while still listening to what's happening in the main conference in the background).
  3. B and D are detached from the main mix for audio (<modifyjoin> with inactive status).
  4. B and D are attached to the hidden sidebar mix for audio.

Now, the tea ☕: for detaching B and D from the main mix, they use a <modifyjoin> with an inactive status, NOT an <unjoin>. The reason is all about how rejoining later could work. With <modifyjoin>, the resources created when B and D first joined the main mix stay in place, even though they're marked as unused for now. An <unjoin> would actually free those resources, and they could get handed to other people who join the conference in the meantime 😬. So if B and D need to rejoin the main mix later, the MS may not have the resources to do it, and that's an undesired failure we don't want.

Here's the sequence of transactions (where confX is the identifier of the pre-existing main conference mix) in Figure 40 🧚:

  B         D         AS                                 MS
  |         |         |                                  |
  |         |         | A1. CONTROL (create conference)  |
  |         |         |++++++++++++++++++++++++++++++++>>|
  |         |         |                                  |--+ create
  |         |         |                                  |  | conf and
  |         |         |      A2. 200 OK (conferenceid=Y) |<-+ its ID
  |         |         |<<++++++++++++++++++++++++++++++++|
  |         |         |                                  |
  |         |         | B1. CONTROL (join confX-->confY) |
  |         |         |++++++++++++++++++++++++++++++++>>|
  |         |         |                                  |--+ join confX
  |         |         |                                  |  | & confY
  |         |         |                       B2. 200 OK |<-+ sendonly
  |         |         |<<++++++++++++++++++++++++++++++++|    (30% vol)
  |         |         |                                  |
  |         |         | C1. CONTROL (modjoin B---confX)  |
  |         |         |++++++++++++++++++++++++++++++++>>|
  |         |         |                                  |--+ modjoin B
  |         |         |                                  |  | & confX
  |         |         |                       C2. 200 OK |<-+ (inactive)
  |         |         |<<++++++++++++++++++++++++++++++++|
  |         |         |                                  |
  |         |         | D1. CONTROL (join B<-->confY)    |
  |         |         |++++++++++++++++++++++++++++++++>>|
  |         |         |                                  |--+ join B
  |         |         |                                  |  | & confY
  |         |         |                       D2. 200 OK |<-+ sendrecv
  |         |         |<<++++++++++++++++++++++++++++++++|    (audio)
  |         |         |                                  |
  |<<##################################################>>|
  |   Participant B is mixed (sendrecv) in the sidebar   |
  |     (A, C, and D can't listen to her/him anymore)    |
  |<<##################################################>>|
  |         |         |                                  |
  |         |         | E1. CONTROL (modjoin D---confX)  |
  |         |         |++++++++++++++++++++++++++++++++>>|
  |         |         |                                  |--+ modjoin D
  |         |         |                                  |  | & confX
  |         |         |                       E2. 200 OK |<-+ (inactive)
  |         |         |<<++++++++++++++++++++++++++++++++|
  |         |         |                                  |
  |         |         | F1. CONTROL (join D<-->confY)    |
  |         |         |++++++++++++++++++++++++++++++++>>|
  |         |         |                                  |--+ join D
  |         |         |                                  |  | & confY
  |         |         |                       F2. 200 OK |<-+ sendrecv
  |         |         |<<++++++++++++++++++++++++++++++++|    (audio)
  |         |         |                                  |
  |         |<<########################################>>|
  |         |  D is mixed (sendrecv) in the sidebar too  |
  |         |  (A and C can't listen to her/him anymore) |
  |         |<<########################################>>|
  |         |                                            |
  .         .                                            .
  .         .                                            .

Figure 40: Sidebars: Framework Transactions

  • First of all, the hidden conference mix is created (A1). The request is basically the same as the ones presented in previous sections, i.e., a <createconference> request addressed to the Mixer package. The request is very lightweight and asks the MS to only reserve two listener seats (reserved-listeners, since only B and D have to hear something) and three talker seats (reserved-listeners, because in addition to B and D the main mix is also an active contributor to the sidebar). The mixing will be driven by directives from the AS (mix-type=controller). When the mix is successfully created, the MS provides the AS with its identifier (519c1b9).
  • As a first transaction after that, the AS joins the audio from the main conference and the newly created sidebar conference mix (B1). Only audio needs to be joined (media=audio), with a sendonly direction (i.e., only flowing from the main conference to the sidebar and not vice versa) and at 30% volume with respect to the original stream (setgain=-5 dB). A successful completion of the transaction is reported to the AS (B2).
  • At this point, the AS makes the connection of B (2133178233: 18294826) and the main conference (2f5ad43) inactive by means of a <modifyjoin> directive (C1). The request is taken care of by the MS (C2), and B is actually excluded from the mix for sending as well as receiving 🙈.

6.3.5. Floor Control 🎀

okay so bestie, floor control is basically the "who gets to talk right now" system 🎤 As described in [RFC4597], it's a feature that's typically needed and used in most conference scenarios. Is it mandatory to implement when you're building a conferencing app? Nope, not mandatory 🙅‍♀️ But it gives you extra control over the media streams that participants send in, so you can moderate the resources, and honestly that's giving main character moderator energy ✨

The Centralized Conferencing (XCON) framework [RFC5239] suggests using the Binary Floor Control Protocol (BFCP) [RFC4582] to get this functionality 💜 That said, combining floor control with the tools that the MEDIACTRL specification gives you for conferencing would be absolutely fascinating to look into 🦋 [RFC5567] covers two different ways to bring floor control into the MEDIACTRL architecture 👀 Option (i) puts the floor control server in the same place as the AS, and option (ii) puts it in the same place as the MS. These two are really different in how much info the AS and the MS have to juggle, especially when you think about floor queues and automated decisions 🧠

Now, considering how the Media Control Channel Framework is designed, option (ii) would need a dedicated package (either an extension or a brand new one) so that the MS knows about floor control and can talk to the interested UAC about it 🫶 At the time of writing, that package doesn't exist yet, so only option (i) gets covered in this scenario 🙈

So here's the setup. The scenario assumes the Floor Control Server (FCS) is co-located with the AS 🏠 That means all the BFCP requests go from the Floor Control Participants (FCPs) straight to the FCS, which makes the AS directly aware of the floor statuses 👑 To keep things simple, the scenario assumes the participants already know all the identifiers they need to make BFCP requests for a specific conference. That info may have been carried using the COMEDIA negotiation specified in [RFC4583] 💅

⚠️ Bestie, this next part is really important: that BFCP information must not reach the MS! ⚠️ So if a UAC was attached to the MS through 3PCC, all the BFCP-related info that the AS and the UAC negotiated has to be stripped out before the negotiation is handed over to the MS, because the MS may not be able to understand that specification 😭

A simplified example of how this could work is in Figure 41 🌸 Quick heads-up: in this example, different identifiers might be used to refer to the same entity 🙃 Specifically, the UAC (the endpoint sending and receiving media) is also an FCP here, since it negotiates a BFCP channel too 🧚

  UAC                               AS
 (FCP)                             (FCS)                              MS
  |                                 |                                 |
  | INVITE (SDP: RTP+BFCP)          |                                 |
  |-------------------------------->|                                 |
  |                                 | INVITE (SDP: RTP)               |
  |                                 |-------------------------------->|
  |                                 |          200 (SDP: RTP'+labels) |
  |                                 |<--------------------------------|
  |                        match +--|                                 |
  |                       floors |  |                                 |
  |                     & labels +->|                                 |
  |                                 |                                 |
  |    200 (SDP: RTP'+BFCP'+labels) |                                 |
  |<--------------------------------|                                 |
  | ACK                             |                                 |
  |-------------------------------->|                                 |
  |                                 | ACK                             |
  |                                 |-------------------------------->|
  |                                 |                                 |
  |<<###################### RTP MEDIA STREAMS ######################>>|
  |                                 |                                 |
  |<<******** BFCP CHANNEL *******>>|                                 |
  |                                 |                                 |
  .                                 .                                 .
  .                                 .                                 .
             Figure 41: Floor Control: Example of Negotiation

From the media and framework angle, this scenario isn't that different from the conferencing scenarios we already looked at 🌈 The more interesting part is the topology, so check out Figure 42 👀

+-------+                    +--------+
|  UAC  |                    |   AS   |                     +-------+
| (FCP) |<****** BFCP ******>|  (FCS) |<****** BFCP *******>| (FCC) |
+-------+                    +--------+                     +-------+
    ^                             ^
    |                             |
    |                         CFW |
    |                             |
    |                             v
    |                        +--------+
    +----------RTP---------->|   MS   |
                             +--------+
               Figure 42: Floor Control: Overall Perspective

So the AS does double duty 💖 Besides keeping up the SIP signaling that's already going on between everyone involved, it also acts as the FCS for the participants in the conferences it's responsible for 🫶 In this scenario there are two Floor Control Participants: a basic Participant (FCP) and a Chair (FCC) 👑✨

okay so, the framework does this the same way as every other conferencing example 💅 Using the Mixer Control Package, and assuming the conference already exists, the participant is attached (recvonly) to it, and they know the BFCP identifiers involved 🎀, here's the whole flow, bestie:

  1. The assigned chair, FCC, sends a subscription for events related to the floor it's responsible for (FloorQuery). 💌
  2. The FCP sends a BFCP request (FloorRequest) to access the audio resource ("I want to speak") 🎤
  3. The FCS (AS) sends a provisional response to the FCP (FloorRequestStatus PENDING) and handles the request in its queue. Since a chair is assigned to this floor, the request gets forwarded to the FCC for a decision (FloorStatus). 👀
  4. The FCC makes a decision and sends it to the FCS (ChairAction ACCEPTED). ⚖️
  5. The FCS takes note of the decision and updates the queue accordingly. The decision is sent to the FCP (FloorRequestStatus ACCEPTED). The floor has not been granted yet 🫠
  6. As soon as the queue allows it, the floor is actually granted to the FCP. The AS, which is co-located with the FCS, understands in its business logic that this event is tied to the audio resource being granted to the FCP. So a <modifyjoin> (sendrecv) gets sent through the Control Channel to the MS to unmute the FCP UAC in the conference 🔊
  7. The FCP is notified of this event (FloorRequestStatus GRANTED), and that's the end of the scenario 🏁

A diagram of this sequence of transactions (which also shows the BFCP message flow at a higher level) is shown in Figure 43 🦋

 UAC1      UAC2       AS
 (FCP)     (FCC)     (FCS)                               MS
  |         |         |                                  |
  |<<####################################################|
  |   UAC1 is muted (recvonly stream) in the conference  |
  |<<####################################################|
  |         |         |                                  |
  |         | FloorQuery                                 |
  |         |*******>>|                                  |
  |         |         |--+ handle                        |
  |         |         |  | subscription                  |
  |         |         |<-+                               |
  |         | FloorStatus                                |
  |         |<<*******|                                  |
  |         |         |                                  |
  | FloorRequest      |                                  |
  |*****************>>|                                  |
  |         |         |--+ handle                        |
  |         |         |  | request                       |
  |           Pending |<-+ (queue)                       |
  |<<*****************|                                  |
  |         |         |                                  |
  |         | FloorStatus                                |
  |         |<<*******|                                  |
  |         |         |                                  |
  |         | ChairAction (ACCEPT)                       |
  |         |*******>>|                                  |
  |         | ChairActionAck                             |
  |         |<<*******|                                  |
  |         |         |--+ handle                        |
  |         |         |  | decision                      |
  |         |         |<-+ (queue)                       |
  |          Accepted |                                  |
  |<<*****************|                                  |
  |         | FloorStatus                                |
  |         |<<*******|                                  |
  |         |         |                                  |
  |         |         |--+ queue                         |
  |         |         |  | grants                        |
  |         |         |<-+ floor                         |
  |         |         |                                  |
  |         |         | 1. CONTROL (modjoin UAC<->conf)  |
  |         |         |++++++++++++++++++++++++++++++++>>|
  |         |         |                                  |--+ modjoin
  |         |         |                                  |  | UAC & conf
  |         |         |                        2. 200 OK |<-+ (sendrecv)
  |         |         |<<++++++++++++++++++++++++++++++++|
  |         |         |                                  |
  |<<##################################################>>|
  |   UAC1 is now unmuted (sendrecv) in the conference   |
  |        and can speak, contributing to the mix        |
  |<<##################################################>>|
  |         |         |                                  |
  |           Granted |                                  |
  |<<*****************|                                  |
  |         | FloorStatus                                |
  |         |<<*******|                                  |
  |         |         |                                  |
  .         .                                            .
  .         .                                            .

Figure 43: Floor Control: Framework Transactions ✨

As you can easily see from the diagram above, all that complex BFCP back-and-forth only results in a single transaction at the MEDIACTRL level 🧚 The whole point of the BFCP transactions is to moderate access to the audio resource, which means they provide the event trigger for MEDIACTRL-based conference manipulation transactions. Before the floor is granted, the FCP UAC is excluded from the conference mix at the MEDIACTRL level (recvonly). As soon as the floor has been granted, the FCP UAC gets included in the mix. In MEDIACTRL words:

  • Since the FCP UAC must be included in the audio mix, a <modifyjoin> is sent to the MS in a CONTROL directive. The <modifyjoin> has as identifiers the connectionid associated with the FCP UAC (e1e1427c:1c998d22) and the conferenceid of the mix (cf45ee2). The <stream> element tells the MS that the audio media stream between the two must become bidirectional (sendrecv), changing the previous status (recvonly). Please note that in this case only audio was involved in the conference. If video were involved as well, and video had to be unchanged, a <stream> directive for video had to be placed in the request as well, in order to maintain its current status 🎬

1. AS -> MS (CFW CONTROL) 💌

CFW gh67ffg56w21 CONTROL
Control-Package: msc-mixer/1.0
Content-Type: application/msc-mixer+xml
Content-Length: 182

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <modifyjoin id1="e1e1427c:1c998d22" id2="cf45ee2">
      <stream media="audio" direction="sendrecv"/>
   </modifyjoin>
</mscmixer>

2. AS <- MS (CFW 200 OK) 🥰

CFW gh67ffg56w21 200
Timeout: 10
Content-Type: application/msc-mixer+xml
Content-Length: 123

<mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
   <response status="200" reason="Join modified"/>
</mscmixer>

6.4. Additional Scenarios 🌈

This section includes additional scenarios that can be of interest when you're dealing with AS<->MS flows 🧁 The subsections that follow show off features that are peculiar to the IVR package: variable announcements, VCR (video cassette recorder) prompts, parallel playback, recurring dialogs, and custom grammars. To see how call flows involving these features might happen, three sample scenarios have been chosen:

  1. Voice Mail (variable announcements for digits, VCR controls) 📼
  2. Current Time (variable announcements for date and time, parallel playback) ⏰
  3. DTMF-driven Conference Manipulation (recurring dialogs, custom grammars) 🎹

6.4.1. Voice Mail 🎀

okay so Voice Mail is the app that lives off the MS's services, bestie 📞. A lot of it is just app logic, like mapping a URI to someone's mailbox or keeping track of the message list and each message's properties, but the actual media work is done by the MS 💅. Voice Mail needs to record a stream and play it back later, give verbose announcements about the status of the app, control playout of recorded messages with VCR controls, and more. The MS handles all of that through the IVR package 🎧✨

We're not going to dive into a full Voice Mail app and every single use case 🙈. Instead, this section walks through one specific scenario and tries to cover as many AS-to-MS interactions as possible in that context 🧚. The scenario is shown as a sequence diagram in Figure 44 and goes like this:

  1. The UAC INVITEs a URI tied to his mailbox, and the AS follows the procedure we went over earlier to get the UAC to negotiate a new media session with the MS 💌.
  2. The UAC first hears an announcement telling him how many new messages are in the mailbox. After that, he can pick which message to access by sending a DTMF tone 🔢.
  3. The UAC then gets a VCR-controlled announcement where the chosen message gets played back to him. VCR controls let him move around inside the prompt 🎬.

ngl this is pretty oversimplified 😭. It doesn't even let the UAC delete old messages or organize them. It only lets him choose which received message to play. Still, it's a great way to deal with variable announcements and VCR controls, which are two features a Voice Mail app almost always uses 💜. Other features a Voice Mail app would rely on, like recording streams or event-driven IVR menus, were already covered in earlier sections, so repeating them would be redundant 🙄. The call flows here assume some messages are already recorded and sitting at reachable locations. The example also assumes the AS put those recordings in its own storage, because it isn't safe to rely on the internal MS storage, which is likely to be temporary 🥺🫶

 UAC                      AS                                 MS
  |                       |                                  |
  |                       | A1. CONTROL (play variables and  |
  |                       |      collect the user's choice)  |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  | prepare &
  |                       |                                  |--+ start
  |                       |                                  |  | the
  |                       |                       A2. 200 OK |<-+ dialog
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       |                                  |
  |<<########################################################|
  |                "You have five messages ..."              |
  |<<########################################################|
  |                       |                                  |
  |                       |      B1. CONTROL (<collectinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | B2. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  |                       | C1. CONTROL (VCR for chosen msg) |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  | prepare &
  |                       |                                  |--+ start
  |                       |                                  |  | the
  |                       |                       C2. 200 OK |<-+ dialog
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       |                                  |
  |<<########################################################|
  |          "Hi there, I tried to call you but..."          |--+
  |<<########################################################|  | handle
  |                       |                                  |  | VCR-
  |########################################################>>|  | driven
  |        The UAC controls the playout using DTMF           |  | (DTMF)
  |########################################################>>|  |playout
  |                       |                                  |<-+
  |                       |       D1. CONTROL (<dtmfnotify>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | D2. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  .                       .                                  .
  .       (other events are received in the meantime)        |
  .                       .                                  .
  |                       |      E1. CONTROL (<controlinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | E2. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  .                       .                                  .
  .                       .                                  .

               Figure 44: Voice Mail: Framework Transactions

Here's how the framework transactions go 👀✨

  • The first transaction (A1) is addressed to the IVR package (msc-ivr). It's basically an [RFC6231] promptandcollect dialog, with one twist: some prompts are real audio files with a URI provided (media loc="xxx"), while others are so-called <variable> prompts. Those <variable> prompts get built by the MS itself based on what the AS tells it to do 🛠️. In this example, the AS asks for the following prompts, in order:
    1. play a wav file ("you have...").
    2. play a digit ("five...") by building it (variable: digit=5).
    3. play a wav file ("messages...").

A DTMF collection (<collect>) is requested too, to be taken after the prompts finish. The AS only cares about a single digit (maxdigits=1) 🔥.

  • The MS handles the transaction. If everything goes well (the MS grabbed all the audio files and built the variable announcements), the dialog starts. The MS reports that start, along with its identifier (5db01f4), to the AS in a terminating 200 OK message (A2) 🎉.
  • The AS then waits for the dialog to end so it can get the results it cares about. Here that's the DTMF tone the UAC picks, because it decides which message gets played next 👑.
  • The UAC hears the prompts and picks a message. In this example he wants the first one, so he inputs "1". The MS catches that tone and tells the AS in a newly created CONTROL event message (B1). This CONTROL includes info about how each requested operation ended (<promptinfo> and <collectinfo>). Specifically, the event says the prompt ended normally (termmode=completed) and the collected tone is 1 (dtmf=1). The AS acks the event (B2), since the dialogid in the message matches the dialog that was started earlier 🫶.
  • Now the AS uses the value from the event to keep its business logic going. It decides to give the UAC a VCR-controllable playout of the requested message. That's a new request to the IVR package (C1) with two operations: <prompt> to point at the media file to play (an old recording), and <control> to tell the MS how playout of that file gets controlled through DTMF tones from the UAC. In this example, different DTMF digits map to different actions, like pause/resume, fast forward, rewind, and so on 🎬. The AS also subscribes to DTMF events for this control operation (matchmode=control), which means the MS triggers an event any time a DTMF tied to a control operation (e.g., 7=pause) gets intercepted 🔔.
  • The MS prepares the dialog and, once playout starts, sends a notification in a terminating 200 OK message (C2). At this point the UAC hears the prompt and can use DTMF digits to control playback 🎧💖.
  • Like we explained before, any DTMF tied to a VCR operation gets reported to the AS, together with a timestamp for when it happened. The example (D1) shows the UAC pressing the fast-forward key (6) at a specific time ⏩. As with any other MS-generated event, the AS acks it (D2) 💅.
  • When playback ends (either because the media reached its end or because some other interruption happened), the MS triggers a concluding event with info about the whole dialog (E1). This event includes info about the prompt itself (<promptinfo>), and also info about the VCR operations (<controlinfo>). That's every VCR control the UAC used (fast forward, rewind, pause, and resume in this example) and when each one happened 📼. The final ack by the AS (E2) wraps up the scenario 🌈

A1. AS -> MS (CFW CONTROL, play and collect) ✨

   CFW 2f931de22820 CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 429

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
      <dialogstart connectionid="10514b7f:6a900179">
         <dialog>
            <prompt>
               <media
            loc="http://www.example.net/prompts/vm-youhave.wav"
            type="audio/x-wav"/>
               <variable value="5" type="digits"/>
               <media
           loc="http://www.example.net/prompts/vm-messages.wav"
           type="audio/x-wav"/>
            </prompt>
            <collect maxdigits="1" escapekey="*"
                     cleardigitbuffer="true"/>
         </dialog>
      </dialogstart>
   </mscivr>

A2. AS <- MS (CFW 200 OK) 🎀

   CFW 2f931de22820 200
   Timeout: 10
   Content-Type: application/msc-ivr+xml
   Content-Length: 137

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <response status="200" reason="Dialog started" dialogid="5db01f4"/>
   </mscivr>

B1. AS <- MS (CFW CONTROL event) 💜

   CFW 7c97adc41b3e CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 270

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
      <event dialogid="5db01f4">
         <dialogexit status="1" reason="Dialog successfully completed">
            <promptinfo duration="11713" termmode="completed"/>
            <collectinfo dtmf="1" termmode="match"/>
         </dialogexit>
      </event>
   </mscivr>

B2. AS -> MS (CFW 200, ACK to 'CONTROL event') 💌

   CFW 7c97adc41b3e 200

C1. AS -> MS (CFW CONTROL, VCR) 🎬

   CFW 3140c24614bb CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 423

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
      <dialogstart connectionid="10514b7f:6a900179">
         <dialog>
            <prompt bargein="false">
               <media
  loc="http://www.example.com/messages/recording-4ca9fc2.mpg"/>
            </prompt>
            <control gotostartkey="1" gotoendkey="3"
                     ffkey="6" rwkey="4" pausekey="7" resumekey="9"
                     volupkey="#" voldnkey="*"/>
            </dialog>
         <subscribe>
            <dtmfsub matchmode="control"/>
         </subscribe>
      </dialogstart>
   </mscivr>

C2. AS <- MS (CFW 200 OK) 🙌

   CFW 3140c24614bb 200
   Timeout: 10
   Content-Type: application/msc-ivr+xml
   Content-Length: 137

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <response status="200" reason="Dialog started" dialogid="3e936e0"/>
   </mscivr>

D1. AS <- MS (CFW CONTROL event, dtmfnotify) 🔔

   CFW 361840da0581 CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 179

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
      <event dialogid="3e936e0">
         <dtmfnotify matchmode="control" dtmf="6"
                     timestamp="2008-12-16T12:58:36Z"/>
      </event>
   </mscivr>

D2. AS -> MS (CFW 200, ACK to 'CONTROL event') ✅

   CFW 361840da0581 200
[..] The other VCR DTMF notifications are skipped for brevity [..] 🙈

E1. AS <- MS (CFW CONTROL event, dialogexit) 🏁

   CFW 3ffab81c21e9 CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 485

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
      <event dialogid="3e936e0">
         <dialogexit status="1" reason="Dialog successfully completed">
            <promptinfo duration="10270" termmode="completed"/>
            <controlinfo>
               <controlmatch dtmf="6" timestamp="2008-12-16T12:58:36Z"/>
               <controlmatch dtmf="4" timestamp="2008-12-16T12:58:37Z"/>
               <controlmatch dtmf="7" timestamp="2008-12-16T12:58:38Z"/>
               <controlmatch dtmf="9" timestamp="2008-12-16T12:58:40Z"/>
            </controlinfo>
         </dialogexit>
      </event>
   </mscivr>

E2. AS -> MS (CFW 200, ACK to 'CONTROL event') 💅

   CFW 3ffab81c21e9 200

6.4.2. Current Time 🕰️✨

Okay, so an interesting scenario to build with the MS's features is what everyone calls 'Current Time'! 💖 A UAC calls a URI, and it tells the caller the current date and time. Since that's literally the whole point of the app, variable announcements are the star here 🌟. Instead of making the AS build an announcement by hand from a pile of different framework messages (so much work, ew 😩), it's way easier to lean on the "variable announcements" mechanism from the IVR package, because variable announcements handle dates and times in several different ways 🧠.

To make it more fun and cover more functionality, the app also plays background music during the announcement 🎶. Since most of the announcements are variable, we need a way to have more streams playing in parallel on the same connection. There are two different ways to do that:

  1. two separate and different dialogs, playing the variable announcements and the background track, respectively.
  2. a single dialog implementing a parallel playback.

The first approach assumes the available MS implements implicit mixing, which may or may not be supported since it's a recommended feature but not mandatory 🤷‍♀️. The second approach assumes the MS supports more streams of the same media type (in this case audio) in the same dialog, and, exactly like implicit mixing, that is not to be taken for granted 🙃. Because the first approach is quite straightforward and easy to understand, the following scenario uses the second approach and assumes the available MS supports parallel playback of more audio tracks within the context of the same dialog ✨.

That said, the covered scenario, depicted as a sequence diagram in Figure 45, goes like this 👇:

  1. The UAC INVITEs a URI associated with the Current Time application, and the AS follows the previously explained procedure to have the UAC negotiate a new media session with the MS.
  2. The UAC is presented with an announcement including (i) a voice stating the current date and time; (ii) a background music track; and (iii) a mute background video track.
 UAC                      AS                                 MS
  |                       |                                  |
  |                       | A1. CONTROL (play variables)     |
  |                       |++++++++++++++++++++++++++++++++>>| prepare
  |                       |                                  |--+ and
  |                       |                          A2. 202 |  | start
  |                       |<<++++++++++++++++++++++++++++++++|  | the
  |                       |                                  |  | dialog
  |                       |                                  |  | (takes
  |                       |           A3. REPORT (terminate) |<-+ time)
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | A4. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  |<<########################################################|
  |            "16th of december 2008, 5:31 PM..."           |
  |<<########################################################|
  |                       |                                  |
  |                       |       B1. CONTROL (<promptinfo>) |
  |                       |<<++++++++++++++++++++++++++++++++|
  |                       | B2. 200 OK                       |
  |                       |++++++++++++++++++++++++++++++++>>|
  |                       |                                  |
  .                       .                                  .
  .                       .                                  .
  .                       .                                  .

Figure 45: Current Time: Framework Transactions 📊

The framework transaction steps go like this 🧩:

  • The first transaction (A1) is addressed to the IVR package (msc-ivr); it's basically an [RFC6231] 'playannouncements' dialog, but, unlike all the scenarios presented so far, it includes directives for a parallel playback, as indicated by the <par> element. There are three flows to play in parallel:
    • a sequence (<seq>) of variable and static announcements (the actual time and date).
    • a music track ('media=music.wav') to be played in the background at a lower volume (soundLevel=50%).
    • a mute background video track (media=clock.mpg).

The global announcement ends when the longest of the three parallel steps ends (endsync=last). This means that if one of the steps ends before the others, that step is muted for the rest of the playback. In this example, the series of static and <variable> announcements is requested by the AS:

  • play a wav file ("Tuesday...").
  • play a date ("16th of december 2008...") by building it (variable: date with a ymd=year/month/day format).
  • play a time ("5:31 PM...") by building it (variable: time with a t12=12 hour day format, am/pm).
  • The transaction is extended by the MS (A2) with a new timeout, because the MS needs some more time to retrieve all the needed media files ⏳. Should the new timeout expire as well, the MS would send a further message to extend it again (a REPORT update), but for the sake of simplicity we assume that in this scenario it is not needed. If everything went fine (i.e., the MS retrieved all the audio files, successfully built the variable announcements, and supports parallel playback as requested), the dialog is started 🚀. Its start is reported, together with the associated identifier (415719e), to the AS in a terminating REPORT message (A3).
  • The AS acks the REPORT (A4) and waits for the dialog to end, so it can either wrap up the application or move on to further steps if the application itself requires them 🙋‍♀️.
  • When the last of the three parallel announcements ends, the dialog terminates, and an event (B1) is triggered to the AS with the relevant information (promptinfo). The AS acks (B2) and terminates the scenario 🎀.

A1. AS -> MS (CFW CONTROL, play) 🎵

   CFW 0c7680191bd2 CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 506

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <dialogstart connectionid="21c8e07b:055a893f">
       <dialog>
         <prompt bargein="true">
           <par endsync="last">
             <seq>
               <media loc="http://www.example.com/day-2.wav"/>
               <variable value="2008-12-16" type="date" format="ymd"/>
               <variable value="17:31" type="time" format="t12"/>
             </seq>
             <media loc="http://www.example.com/music.wav"
                    soundLevel="50%"/>
             <media loc="http://www.example.com/clock.mpg"/>
           </par>
         </prompt>
       </dialog>
     </dialogstart>
   </mscivr>

A2. AS <- MS (CFW 202) ⏱️

   CFW 0c7680191bd2 202
   Timeout: 5

A3. AS <- MS (CFW REPORT terminate) 📣

   CFW 0c7680191bd2 REPORT
   Seq: 1
   Status: terminate
   Timeout: 10
   Content-Type: application/msc-ivr+xml
   Content-Length: 137

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <response status="200" reason="Dialog started" dialogid="415719e"/>
   </mscivr>

A4. AS -> MS (CFW 200, ACK to 'REPORT terminate') 🫶

   CFW 0c7680191bd2 200
   Seq: 1

B1. AS <- MS (CFW CONTROL event) 🏁

   CFW 4481ca0c4fca CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 229

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
      <event dialogid="415719e">
         <dialogexit status="1" reason="Dialog successfully completed">
            <promptinfo duration="8046" termmode="completed"/>
         </dialogexit>
      </event>
   </mscivr>

B2. AS -> MS (CFW 200, ACK to 'CONTROL event') 💖

   CFW 4481ca0c4fca 200

6.4.3. DTMF-Driven Conference Manipulation 🎙️👑

To wrap up the scenarios from Section 6.3, this section is all about how the AS can use the MS to detect DTMF tones from conference participants and then take actions on the conference accordingly 🔥. A typical example is when participants in a conference are given specific codes to:

  • mute/unmute themselves in the conference;
  • change their volume in the conference, or the volume of the conference itself;
  • change the video layout in the conference, if allowed 📺;
  • kick abusive users out of the conference 🙅‍♀️;

and so on 💅 To pull all this off, the simplest thing an AS can do is set up a recurring DTMF collection for each participant, with specific grammars to match. If the collected tones match the grammar, the MS notifies the AS of the tones and starts the collection again ✨ When <collectinfo> events come in, the AS then originates the proper related request, e.g., a <modifyjoin> on the participant's stream with the conference. Three features of the IVR package make this possible 🎀

  1. the repeatCount attribute.
  2. the subscription mechanism.
  3. the Speech Recognition Grammar Specification (SRGS) [SRGS].

The first feature lets the same dialog run again and again without needing extra requests every time it finishes 🔁 The repeatCount attribute says how many times the dialog has to be repeated. When it's set to 0, the dialog repeats indefinitely, which means the AS is the one in charge of destroying it with a <dialogterminate> request once it's no longer needed 🧹 The second feature lets the AS subscribe to events related to the IVR package without waiting for the dialog to end, e.g., matching DTMF collections in this case 👀 Last but not least, the third feature lets custom matching grammars be specified. That way, only a subset of the possible DTMF strings can be set up, so only the matches the AS actually cares about get reported 🎯 Grammars other than SRGS may be supported by the MS and will achieve the same result. This document will only describe the use of an SRGS grammar, since support for SRGS is mandated in [RFC6231] 💖

To nail down one sample scenario, we assume a participant has successfully joined a conference, e.g., as detailed in Figure 32 🦋 We also assume these codes are available inside the conference so participants can use the advanced features:

  1. *6 to mute/unmute themselves (on/off trigger).
  2. *1 to lower their own volume in the conference and *3 to raise it.
  3. *7 to lower the volume of the conference stream they are receiving and *9 to raise it.
  4. *0 to leave the conference.

That means six different codes are supported, and they need to be matched in the requested DTMF collection 🍓 All other codes are collected by the MS but discarded, and no event is triggered to the AS 🙈 Since all the codes have the * (star) DTMF code in common, here's an example SRGS grammar that the AS may use in the request:

  <grammar mode="dtmf" version="1.0"
           xmlns="http://www.w3.org/2001/06/grammar">
    <rule id="digit">
      <one-of>
        <item>0</item>
        <item>1</item>
        <item>3</item>
        <item>6</item>
        <item>7</item>
        <item>9</item>
      </one-of>
    </rule>
    <rule id="action" scope="public">
      <item>
        *
        <item><ruleref uri="#digit"/></item>
      </item>
    </rule>
  </grammar>

Looking at the grammar, the SRGS XML basically spells out exactly what the collections have to match 🧠 The rule is to match any string that has a star (*) followed by a single supported digit (0, 1, 3, 6, 7, or 9). That grammar, as stated in [RFC6231], may be either provided inline in the request itself or referenced externally by means of the src attribute. In our example we'll put it inline, but an external reference to the same document would achieve exactly the same result 🫶

Figure 46 shows how the AS might request the recurring collection for a UAC 🌈 As before, the example assumes that the UAC is already a participant in the conference.

 UAC                  AS                                     MS
  |                   |                                      |
  |                   | A1. CONTROL (recurring collection)   |
  |                   |++++++++++++++++++++++++++++++++++++>>|
  |                   |                                      |--+ start
  |                   |                                      |  | the
  |                   |                           A2. 200 OK |<-+ dialog
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   |                                      |
  |########################################################>>|
  |          Recurring DTMF digit collection starts          |--+ get
  |########################################################>>|  | DTMF
  |                   |                                      |<-+ digits
  |                   |            B1. CONTROL (dtmfinfo=*1) |
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   | B2. 200 OK                           |--+ get
  |                   |++++++++++++++++++++++++++++++++++++>>|  | DTMF
  |                   |                                      |<-+ digits
  |                   | C1. CONTROL (modifyjoin UAC1-->conf) |
  |                   |++++++++++++++++++++++++++++++++++++>>|
  |                   |                                      |--+ modify
  |                   |                                      |  | UAC
  |                   |                           C2. 200 OK |<-+ volume
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   |                                      |
  |########################################################>>|
  |          Volume of UAC in conference is lowered          |
  |########################################################>>|
  |                   |                                      |
  |                   |            D1. CONTROL (dtmfinfo=*9) |
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   | D2. 200 OK                           |--+ get
  |                   |++++++++++++++++++++++++++++++++++++>>|  | DTMF
  |                   |                                      |<-+ digits
  |                   | E1. CONTROL (modifyjoin UAC1<--conf) |
  |                   |++++++++++++++++++++++++++++++++++++>>|
  |                   |                                      |--+ modify
  |                   |                                      |  | conf
  |                   |                           E2. 200 OK |<-+ volume
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   |                                      |
  |<<########################################################|
  |  Now UAC can hear the conference mix at a higher volume  |
  |<<########################################################|
  |                   |                                      |
  |                   |            F1. CONTROL (dtmfinfo=*6) |
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   | F2. 200 OK                           |--+ get
  |                   |++++++++++++++++++++++++++++++++++++>>|  | DTMF
  |                   |                                      |<-+ digits
  |                   | G1. CONTROL (modifyjoin UAC1-->conf) |
  |                   |++++++++++++++++++++++++++++++++++++>>|
  |                   |                                      |--+ mute
  |                   |                                      |  | UAC in
  |                   |                           G2. 200 OK |<-+ conf
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   |                                      |
  |########################################################>>|
  |             UAC is now muted in the conference           |
  |########################################################>>|
  |                   |                                      |
  |                   |            H1. CONTROL (dtmfinfo=*0) |
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   | H2. 200 OK                           |--+ get
  |                   |++++++++++++++++++++++++++++++++++++>>|  | DTMF
  |                   |                                      |<-+ digits
  |                   | I1. CONTROL (destroy DTMF dialog)    |
  |                   |++++++++++++++++++++++++++++++++++++>>|
  |                   |                                      |--+ delete
  |                   |                                      |  | the
  |                   |                           I2. 200 OK |<-+ dialog
  |                   |<<++++++++++++++++++++++++++++++++++++|    (DTMF
  |                   |                                      |collection
  |                   |                                      |    stops)
  |                   |             J1. CONTROL (dialogexit) |
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   | J2. 200 OK                           |
  |                   |++++++++++++++++++++++++++++++++++++>>|
  |                   |                                      |
  |########################################################>>|
  |           No more tones from UAC are collected           |
  |########################################################>>|
  |                   |                                      |
  |                   | K1. CONTROL (unjoin UAC1<-X->conf)   |
  |                   |++++++++++++++++++++++++++++++++++++>>|
  |                   |                                      |--+ unjoin
  |                   |                                      |  | UAC &
  |                   |                           K2. 200 OK |<-+ conf
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   |                                      |
  |                   |          L1. CONTROL (unjoin-notify) |
  |                   |<<++++++++++++++++++++++++++++++++++++|
  |                   | L2. 200 OK                           |
  |                   |++++++++++++++++++++++++++++++++++++>>|
  |                   |                                      |
  .                   .                                      .
  .                   .                                      .

              Figure 46: DTMF-Driven Conference Manipulation:
                          Framework Transactions

As can be deduced from the sequence diagram above, the AS, in its business logic, correlates the results of different transactions, addressed to different packages, to implement a more complex conferencing scenario 🧩 In fact, <dtmfnotify> events are used to take actions according to the functions of the DTMF codes. The framework transaction steps are as follows:

  • The UAC is already in the conference, so the AS starts a recurring collect with a grammar to match 🎀 This is done by placing a CONTROL request addressed to the IVR package (A1). The operation to implement is a <collect>, and we are only interested in two-digit DTMF strings (maxdigits). The AS is not interested in a DTMF terminator (termchar is set to a non-conventional DTMF character), and the DTMF escape key is set to # (the default is *, which would conflict with the code syntax for the conference and so needs to be changed) 🙌 A custom SRGS grammar is provided inline (<grammar> with mode=dtmf). The whole dialog is to be repeated indefinitely (dialog has repeatCount=0), and the AS wants to be notified when matching collections occur (dtmfsub with matchmode=collect) 💜

I2. AS <- MS (CFW 200 OK) 💅

   CFW 515f007c5bd0 200
   Timeout: 10
   Content-Type: application/msc-ivr+xml
   Content-Length: 140

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <response status="200" reason="Dialog terminated"
               dialogid="01d1b38"/>
   </mscivr>

J1. AS <- MS (CFW CONTROL dialogexit event) 📞

   CFW 76adc41122c1 CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 155

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <event dialogid="01d1b38">
       <dialogexit status="0" reason="Dialog terminated"/>
     </event>
   </mscivr>

J2. AS -> MS (CFW 200, ACK to 'CONTROL event') 🫶

   CFW 76adc41122c1 200

K1. AS -> MS (CFW CONTROL, unjoin) ✂️

   CFW 4e6afb6625e4 CONTROL
   Control-Package: msc-mixer/1.0
   Content-Type: application/msc-mixer+xml
   Content-Length: 127

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
     <unjoin id1="873975758:a5105056" id2="54b4ab3"/>
   </mscmixer>

K2. AS <- MS (CFW 200 OK) ✨

   CFW 4e6afb6625e4 200
   Timeout: 10
   Content-Type: application/msc-mixer+xml
   Content-Length: 122

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
     <response status="200" reason="Join removed"/>
   </mscmixer>

L1. AS <- MS (CFW CONTROL unjoin-notify event) 🔔

   CFW 577696293504 CONTROL
   Control-Package: msc-mixer/1.0
   Content-Type: application/msc-mixer+xml
   Content-Length: 157

   <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
     <event>
       <unjoin-notify status="0"
                      id1="873975758:a5105056" id2="54b4ab3"/>
     </event>
   </mscmixer>

L2. AS -> MS (CFW 200, ACK to 'CONTROL event') 💖

   CFW 577696293504 200

7. Media Resource Brokering ✨

Okay so, every flow we've looked at so far is just one AS talking to one MS. bestie, that's the simplest setup you can picture in a MEDIACTRL-compliant architecture 🧚, but it is NOT the only setup allowed! 💅 [RFC5567] lays out a bunch of possible topologies with several AS and several MS floating around, and to make those work, the architecture got an extra element called the Media Resource Broker (MRB) 🦋. The MRB and the protocols for talking to it are standardized in [RFC6917], so go check that one out if you want the full tea.

An MRB is basically a locator 📍 that knows about a whole pool of MS and hands them out to whichever AS needs one, based on what that AS is asking for. ngl, it's giving matchmaker energy 💘. Because of that, there are two different interfaces:

  • the Publishing interface (Section 7.1), which lets an MRB subscribe for notifications at the MS it's handling (e.g., available and occupied resources, current state, etc.) 📣
  • the Consumer interface (Section 7.2), which lets an interested AS ask an MRB for an MS that can actually fulfil its requirements 🎀

The flows in the next sections show some typical use-case scenarios with an MRB, plus the different topologies it was designed to work in 🌈. And if you're wondering about media dialogs when an MRB is involved, Section 7.3 has a few considerations on that 👑.

7.1. Publishing Interface

The MRB uses the MS's Publishing interface to grab the info it needs 🍓. This Publishing interface, as specified in [RFC6917], is made available as a Control Package for the Media Control Channel Framework. So if an MRB wants info from an MS, it has to negotiate a Control Channel first, as explained in Section 5 🔥. This package lets the MRB either make a direct request and get an answer, or subscribe for events. Iconic options, honestly 🙌.

Of course, since the MRB is the one interested in the Publishing interface, the negotiation I just mentioned has to change to account for the MRB Control Package 💜. The name of this package is 'mrb-publish/1.0', so the SYNC could look something like this:

1. MRB -> MS (CFW SYNC) 🌸

   CFW 6b8b4567327b SYNC
   Dialog-ID: z9hG4bK-4542-1-0
   Keep-Alive: 100
   Packages: msc-ivr/1.0,msc-mixer/1.0,mrb-publish/1.0

2. MRB <- MS (CFW 200) 🥰

   CFW 6b8b4567327b 200
   Keep-Alive: 100
   Packages: msc-ivr/1.0,msc-mixer/1.0,mrb-publish/1.0
   Supported: msc-example-pkg/1.0

We already covered what this negotiation means, so just a quick reminder 🫠. Here the MRB adds a new item to the 'Packages' it needs support for (mrb-publish/1.0). The MS supports it, so it gets added to the negotiated packages in the reply:

           Packages: msc-ivr/1.0,msc-mixer/1.0,mrb-publish/1.0
                                               ^^^^^^^^^^^^^^^

Meanwhile the MS from Section 5 did NOT have support for that package, since the only thing in its 'Supported' list was 'msc-example-pkg/1.0' 🙈. Not everyone gets invited to the party!

Figure 47 is a ladder diagram of a typical interaction based on the MRB Control Package 🪜:

         MRB                                            MS
          |                                              |
          | A1. CONTROL (MRB subscription)               |
          |--------------------------------------------->|
          |                                   A2. 200 OK |
          |<---------------------------------------------|
          |                                              |--+ collect
          |                                              |  | requested
          |                                              |<-+ info
          |               B1. CONTROL (MRB notification) |
          |<---------------------------------------------|
          | B2. 200 OK                                   |
          |--------------------------------------------->|
          |                                              |
          .                                              .
          .                                              .
          |                                              |
          |                                              |--+ collect
          |                                              |  | up-to-date
          |                                              |<-+ info
          |               C1. CONTROL (MRB notification) |
          |<---------------------------------------------|
          | C2. 200 OK                                   |
          |--------------------------------------------->|
          |                                              |
          .                                              .
          .                                              .
          |                                              |
          | D1. CONTROL (Update MRB subscription)        |
          |--------------------------------------------->|
          |                                   D2. 200 OK |
          |<---------------------------------------------|
          |                                              |
          .                                              .
          .                                              .

Figure 47: Media Resource Brokering: Subscription and Notification

In this example the MRB subscribes for info at the specified MS, and events fire on a regular, negotiated schedule ⏰. All of these messages go through the Control Channel, same as every other message in this doc 💌. Here are the framework transaction steps, bestie:

  • The MRB sends a new CONTROL message (A1) addressed to the MRB package (mrb-publish/1.0). It's a subscription for info (<subscription>), and the MRB wants to be notified at least every 10 minutes (<minfrequency>) or, if needed, every 30 seconds at max 🏃‍♀️. The subscription must last 30 minutes (<expires>), and after that no more notifications must be sent 🛑.
  • The MS acks the request (A2) and tells the MRB whether it worked, in a 200 OK message (<mrbresponse>) ✅.
  • The MS gets the first notification ready and sends it to the MRB (B1). Like with other packages, it's sent as an MS-generated CONTROL message, and it's tied to the first request because the 'id' (p0T65U) matches. All the info the MRB subscribed for is in the payload 📦.
  • The MRB acks the notification (B2) and uses the info to update its own stuff as part of its business logic 🧠.
  • The previous step (acking notifications and using the info) keeps repeating at the required frequency, so the MRB always has up-to-date info 🔁.
  • After a while, the MRB updates its subscription (D1) to get more frequent updates (minfrequency=1, an update every second at least) 🏎️. The MS accepts the update (D2), but it might tweak the frequency in the reply based on its policies (e.g., a lower rate, such as minfrequency=30) 🙃. The notifications keep coming, just at the new rate, and the expiration gets updated too (600 seconds again, since the update refreshes it) ⏳.

A1. MRB -> MS (CONTROL, publish request) 📝

   CFW lidc30BZObiC CONTROL
   Control-Package: mrb-publish/1.0
   Content-Type: application/mrb-publish+xml
   Content-Length: 337

   <mrbpublish version="1.0" xmlns="urn:ietf:params:xml:ns:mrb-publish">
      <mrbrequest>
         <subscription action="create" seqnumber="1" id="p0T65U">
            <expires>60</expires>
            <minfrequency>600</minfrequency>
            <maxfrequency>30</maxfrequency>
         </subscription>
      </mrbrequest>
   </mrbpublish>

A2. MRB <- MS (200 to CONTROL, request accepted) 🎉

   CFW lidc30BZObiC 200
   Timeout: 10
   Content-Type: application/mrb-publish+xml
   Content-Length: 139

   <mrbpublish version="1.0" xmlns="urn:ietf:params:xml:ns:mrb-publish">
           <mrbresponse status="200" reason="OK: Request accepted"/>
   </mrbpublish>

B1. MRB <- MS (CONTROL, event notification from MS) 🔔

B2. MRB -> MS (200 to CONTROL)

Bestie, this one is tiny 🥹 The MRB just sends back a quick 200 to say it got the CONTROL message:

CFW 03fff52e7b7a 200

(C1 and C2 are omitted for brevity 🙈)

D1. MRB -> MS (CONTROL, publish request)

Now the MRB sends its own CONTROL message, a publish request 📬 It's an update on the subscription with seqnumber 2, and it asks for an expires of 600 and a minfrequency of 1. The request is sent with mrb-publish/1.0 as the Control-Package:

CFW pyu788fc32wa CONTROL
Control-Package: mrb-publish/1.0
Content-Type: application/mrb-publish+xml
Content-Length: 342

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<mrbpublish version="1.0" xmlns="urn:ietf:params:xml:ns:mrb-publish">
    <mrbrequest>
        <subscription action="update" seqnumber="2" id="p0T65U">
            <expires>600</expires>
            <minfrequency>1</minfrequency>
        </subscription>
    </mrbrequest>
</mrbpublish>

D2. MRB <- MS (200 to CONTROL, request accepted)

The MS answers with a 200 and the reason "OK: Request accepted" ✨ Look closely though, because the MS comes back with a minfrequency of 30 instead of the 1 the MRB asked for 👀 The expires value stays at 600, and the subscription action is now create 💖

CFW pyu788fc32wa 200
Timeout: 10
Content-Type: application/mrb-publish+xml
Content-Length: 332

<mrbpublish version="1.0" xmlns="urn:ietf:params:xml:ns:mrb-publish">
    <mrbresponse status="200" reason="OK: Request accepted">
        <subscription action="create" seqnumber="2" id="p0T65U">
            <expires>600</expires>
            <minfrequency>30</minfrequency>
        </subscription>
    </mrbresponse>
</mrbpublish>

7.2. Consumer Interface ✨

Okay so, the Publishing interface is how an MS tells an MRB what it can do and keeps it up to date 📡 The Consumer interface is the other side of the deal 🤝 It's how an interested AS gets to a resource. The AS uses it to reach out to an MRB and describe the resources it needs, and then the MRB writes back with the info it needs, specifically the address of an MS that can actually meet those requirements 🎀

Now, the twist: unlike the Publishing interface, the Consumer interface is not specified as a Control Package 🙅‍♀️ It's its own XML-based protocol instead, and it can ride on either HTTP or SIP. We'll see both in the next sections 🦋

As specified in [RFC6917], the Consumer interface can show up in two topologies: Query mode and Inline mode 💅 In Query mode (Section 7.2.1), the Consumer requests and responses travel over HTTP. Once the AS has its answer, the usual MEDIACTRL interactions happen between the AS and whichever MS the MRB picked 🌸

Inline mode is different. Here the MRB sits right in the path between the AS and the pool of MS it's handling 👑 The AS can send its Consumer requests over SIP, using a multipart payload (Section 7.2.2). That payload holds the Consumer request itself plus an SDP, and the SDP is about either setting up a Control Channel or a UAC media dialog. This is called Inline-aware mode, since the AS already knows an MRB is there and knows how to talk to it 🧚

The MRB also works with ASes that have no idea it exists, meaning ASes that don't know about the Consumer interface at all 😭 For those, Inline mode still gets used, but the AS thinks the MRB it's talking to is actually an MS 🙈 This is called Inline-unaware mode (Section 7.2.3). Iconic, honestly 💜

7.2.1. Query Mode ✨

Okay so, as we just covered, in Query mode the AS sends Consumer requests over HTTP 💌. It's an HTTP POST that carries the request, and the MRB replies with an HTTP 200 OK. The reply includes info on the one MS the MRB thinks is best for the AS's needs, so the AS can go straight to that MS (see Section 5) 🎯. Basically the MRB is just a locator here, and after that the AS and the MS talk 1:1 💅.

Here's a ladder diagram of a typical Consumer request in the Query topology (Figure 48) 👇

  AS                                             MRB
   |                                              |
   | 1. HTTP POST (Consumer request)              |
   |--------------------------------------------->|
   |                                              |
   |                                              |
   |                                              |--+ Parse request
   |                                              |  | and see if any
   |                                              |<-+ MS applies
   |                                              |
   |                2. 200 OK (Consumer response) |
   |<---------------------------------------------|
   |                                              |
   |--+ Parse response and                        |
   |  | start session (SIP/COMEDIA/CFW)           |
   |<-+ with MS reported by MRB                   |
   |                                              |
   .                                              .
   .                                              .

           Figure 48: Media Resource Brokering: Query Mode

In this example the AS wants an MS that meets a specific set of requirements 🧐. The MS must:

  1. support both the IVR and Mixer packages.
  2. provide at least 10 G.711 encoding/decoding RTP sessions for IVR purposes.
  3. support HTTP-based streaming and support for the audio/x-wav file format in the IVR package.

These requirements are formatted properly for the MRB Consumer syntax 🫶. Here's how the steps go:

  • The AS sends an HTTP POST message to the MRB (1) 📮. The payload is, obviously, the Consumer request, and the Content-Type header tells you so (application/mrb-consumer+xml). The Consumer request is a <mediaResourceRequest> with its id attribute set to the random value 'n3un93wd'. It has some general requirements in <generalInfo> and some IVR-specific ones in <ivrInfo>. The general part lists the required packages in <packages>. The IVR part covers how many IVR sessions are needed (<ivr-sessions>), which file formats must be supported (<file-formats>), and which file transfer capabilities are required (<file-transfer-modes>).
  • The MRB gets the request and parses it 🧠. Following its business logic, it realizes it can't find a single MS that can handle the whole request, so it picks two MS instances that can handle 60 and 40 of the requested sessions, respectively. Then it prepares a Consumer response (2) to give the AS what it asked for 🎁. The response is a <mediaResourceResponse> with the same id attribute as the request, and it says success (status=200) with the relevant info in <response-session-info>. That info includes the transaction details (the same session-id and seq the AS sent, so the request and response can be matched up correctly), how long the reservation lasts (expires=3600, i.e., after an hour the request will expire), and the SIP addresses of the chosen MSs.
Notice that the sequence number the MRB returned is not 1 👀. According to the MRB specification, that's the starting value the AS increments for the sequence number in later requests. So if the AS wants to update or remove the session, it should use 10 as the sequence number in that request. According to Section 12 of [RFC6917], this random starting sequence number is also a way to stop a malicious entity from messing with or disrupting another AS session with the MRB 🛡️. Sequence numbers in requests and responses have to match, and if the AS doesn't send the correct one, the session fails and you get a 405 error message 💀.

Here are the actual messages 💌

1. AS -> MRB (HTTP POST, Consumer request)
------------------------------------------
 POST /Mrb/Consumer HTTP/1.1
 Content-Length: 893
 Content-Type: application/mrb-consumer+xml
 Host: mrb.example.com:8080
 Connection: Keep-Alive
 User-Agent: Apache-HttpClient/4.0.1 (java 1.5)

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <mrbconsumer version="1.0" xmlns="urn:ietf:params:xml:ns:mrb-consumer">
    <mediaResourceRequest id="n3un93wd">
        <generalInfo>
            <packages>
                <package>msc-ivr/1.0</package>
                <package>msc-mixer/1.0</package>
            </packages>
        </generalInfo>
        <ivrInfo>
            <ivr-sessions>
                <rtp-codec name="audio/basic">
                    <decoding>100</decoding>
                    <encoding>100</encoding>
                </rtp-codec>
            </ivr-sessions>
            <file-formats>
                <required-format name="audio/x-wav"/>
            </file-formats>
            <file-transfer-modes>
                <file-transfer-mode package="msc-ivr/1.0" name="HTTP"/>
            </file-transfer-modes>
        </ivrInfo>
    </mediaResourceRequest>
 </mrbconsumer>


2. AS <- MRB (200 to POST, Consumer response)
---------------------------------------------
 HTTP/1.1 200 OK
 X-Powered-By: Servlet/2.5
 Server: Sun GlassFish Communications Server 1.5
 Content-Type: application/mrb-consumer+xml;charset=ISO-8859-1
 Content-Length: 1146
 Date: Thu, 28 Jul 2011 10:34:45 GMT
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <mrbconsumer version="1.0" xmlns="urn:ietf:params:xml:ns:mrb-consumer">
    <mediaResourceResponse reason="Resource found" status="200"
                           id="n3un93wd">
        <response-session-info>
            <session-id>z603G3yaUzM8</session-id>
            <seq>9</seq>
            <expires>3600</expires>
            <media-server-address
                              uri="sip:MediaServer@ms.example.com:5080">
                <ivr-sessions>
                    <rtp-codec name="audio/basic">
                        <decoding>60</decoding>
                        <encoding>60</encoding>
                    </rtp-codec>
                </ivr-sessions>
            </media-server-address>
            <media-server-address
                       uri="sip:OtherMediaServer@pool.example.net:5080">
                <ivr-sessions>
                    <rtp-codec name="audio/basic">
                        <decoding>40</decoding>
                        <encoding>40</encoding>
                    </rtp-codec>
                </ivr-sessions>
            </media-server-address>
        </response-session-info>
    </mediaResourceResponse>
 </mrbconsumer>

For the sake of brevity, I'm skipping the remaining steps 🙈. They're super simple: the AS just starts a COMEDIA negotiation with either of the MSs it got, same as in Section 5. The same goes for attaching UAC media dialogs. Since the AS<->MS interaction is 1:1 after the Query, UAC media dialogs can be redirected straight to the right MS using the 3PCC approach, like in Figure 10 🦋.

7.2.2. Inline-Aware Mode 🌸

Unlike Query mode, in the Inline-Aware MRB Mode (IAMM) the AS sends Consumer requests over SIP 📞. And saying the transport switches from HTTP to SIP is not as easy as it sounds 😤. HTTP and SIP work very differently, and that's reflected in how Inline-aware mode is designed.

An AS that wants to send a Consumer request over SIP has to use an INVITE 💜. As specified in [RFC6917], the INVITE payload can't contain only the Consumer request itself. The Consumer request is supposed to be carried within a SIP transaction. A Consumer session isn't strictly tied to the lifetime of any one SIP transaction, so Consumer requests from the same session can travel in different SIP messages. That means hanging up on any of those SIP dialogs would not affect the Consumer session 🙌.

That said, as documented in [RFC6230], [RFC6917] has two kinds of SIP dialogs a Consumer request can go over: a SIP control dialog (a SIP dialog the AS sends to set up a Control Channel) and a UAC media dialog (a SIP dialog the AS sends to attach a UAC to an MS) 🔥. In both cases, the AS prepares a multipart/mixed payload so it can both receive a reply to its Consumer request and carry on the negotiation described in the SDP payload.

The behaviors in the two cases are called the CFW-based approach and the media dialog-based approach 🧚. They're only slightly different, but we'll go through both so you can see how they could be used. To keep things clear, the same Consumer request as in the Query mode will be sent, so you can see how the two sides might behave differently 👀💖.

7.2.2.1. Inline-Aware Mode: CFW-Based Approach ✨

Okay bestie, Figure 49 is the ladder diagram for a typical Consumer request in the CFW-based Inline-aware topology 🦋 so let's look at it:

   AS                      MRB                          MS
    |                       |                           |
    | 1. INVITE             |                           |
    | (multipart/mixed:     |                           |
    |  application/cfw,     |                           |
    |  application/mrb-consumer+xml)                    |
    |---------------------->|                           |
    |       2. 100 (Trying) |                           |
    |<----------------------|                           |
    |                       |--+ Extract SDP and        |
    |                       |  | MRB payloads; handle   |
    |                       |<-+ Consumer request to    |
    |                       |    pick MS                |
    |                       |                           |
    |                       | 3. INVITE                 |
    |                       | (application/cfw from 1.) |
    |                       |-------------------------->|
    |                       |           4. 100 (Trying) |
    |                       |<--------------------------|
    |                       |                           |--+ Negotiate
    |                       |                           |  | CFW Control
    |                       |                           |<-+ Channel
    |                       |                 5. 200 OK |
    |                       | (application/cfw from MS) |
    |                       |<--------------------------|
    |                       | 6. ACK                    |
    |                       |-------------------------->|
    |        Prepare new +--|                           |
    |       payload with |  |                           |
    |    SDP from MS and +->|                           |
    |     Consumer reply    |                           |
    |                       |                           |
    |             7. 200 OK |                           |
    |     (multipart/mixed: |                           |
    |      application/cfw from MS,                     |
    |      application/mrb-consumer+xml)                |
    |<----------------------|                           |
    | 8. ACK                |                           |
    |---------------------->|                           |
    |                       |                           |
    |--+ Read Consumer      |                           |
    |  | reply and use SDP  |                           |
    |<-+ to create CFW Chn. |                           |
    |                       |                           |
    |                                                   |
    |<<############## TCP CONNECTION #################>>|
    |                                                   |
    | CFW SYNC                                          |
    |++++++++++++++++++++++++++++++++++++++++++++++++++>|
    |                                                   |
    .                       .                           .
    .                       .                           .

Figure 49: Media Resource Brokering: CFW-Based Inline-Aware Mode

To make things easier to follow, we're gonna assume the AS is into exactly the same set of requirements as in Section 7.2.1 🎀. So the Consumer request the AS sends is the same as before, and only the transport/topology is changing 💅.

Quick heads up 🙈: to keep the protocol contents readable, we use a simple 'Part' whenever a boundary for a multipart/mixed payload is given, instead of the real boundary that would show up in the SIP messages.

The framework transaction steps are below (for simplicity's sake, we only show the payloads, not the full SIP transactions) 🧚:

1. AS -> MRB (INVITE multipart/mixed)
-------------------------------------
   [..]
   Content-Type: multipart/mixed;boundary="Part"

   --Part
   Content-Type: application/sdp

   v=0
   o=- 2890844526 2890842807 IN IP4 as.example.com
   s=MediaCtrl
   c=IN IP4 as.example.com
   t=0 0
   m=application 48035 TCP cfw
   a=connection:new
   a=setup:active
   a=cfw-id:vF0zD4xzUAW9

   --Part
   Content-Type: application/mrb-consumer+xml

   <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
   <mrbconsumer version="1.0"
                xmlns="urn:ietf:params:xml:ns:mrb-consumer">
     <mediaResourceRequest id="fr34asx1">
        <generalInfo>
            <packages>
                <package>msc-ivr/1.0</package>
                <package>msc-mixer/1.0</package>
            </packages>
        </generalInfo>
        <ivrInfo>
            <ivr-sessions>
                <rtp-codec name="audio/basic">
                    <decoding>100</decoding>
                    <encoding>100</encoding>
                </rtp-codec>
            </ivr-sessions>
            <file-formats>
                <required-format name="audio/x-wav"/>
            </file-formats>
            <file-transfer-modes>
                <file-transfer-mode package="msc-ivr/1.0" name="HTTP"/>
            </file-transfer-modes>
        </ivrInfo>
     </mediaResourceRequest>
   </mrbconsumer>

   --Part
3. MRB -> MS (INVITE SDP only)
------------------------------
   [..]
   Content-Type: application/sdp

   v=0
   o=- 2890844526 2890842807 IN IP4 as.example.com
   s=MediaCtrl
   c=IN IP4 as.example.com
   t=0 0
   m=application 48035 TCP cfw
   a=connection:new
   a=setup:active
   a=cfw-id:vF0zD4xzUAW9
5. MRB <- MS (200 OK SDP)
-------------------------
   [..]
   Content-Type: application/sdp

   v=0
   o=lminiero 2890844526 2890842808 IN IP4 ms.example.net
   s=MediaCtrl
   c=IN IP4 ms.example.net
   t=0 0
   m=application 7575 TCP cfw
   a=connection:new
   a=setup:passive
   a=cfw-id:vF0zD4xzUAW9
7. AS <- MRB (200 OK multipart/mixed)
-------------------------------------
   [..]
   Content-Type: multipart/mixed;boundary="Part"

   --Part
   Content-Type: application/sdp

   v=0
   o=lminiero 2890844526 2890842808 IN IP4 ms.example.net
   s=MediaCtrl
   c=IN IP4 ms.example.net
   t=0 0
   m=application 7575 TCP cfw
   a=connection:new
   a=setup:passive
   a=cfw-id:vF0zD4xzUAW9

   --Part
   Content-Type: application/mrb-consumer+xml

   <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
   <mrbconsumer version="1.0"
                xmlns="urn:ietf:params:xml:ns:mrb-consumer">
     <mediaResourceResponse reason="Resource found" status="200"
                            id="fr34asx1">
        <response-session-info>
            <session-id>z603G3yaUzM8</session-id>
            <seq>9</seq>
            <expires>3600</expires>
            <media-server-address
                              uri="sip:MediaServer@ms.example.com:5080">
                <connection-id>32pbdxZ8:KQw677BF</connection-id>
                <ivr-sessions>
                    <rtp-codec name="audio/basic">
                        <decoding>60</decoding>
                        <encoding>60</encoding>
                    </rtp-codec>
                </ivr-sessions>
            </media-server-address>
            <media-server-address
                       uri="sip:OtherMediaServer@pool.example.net:5080">
                <ivr-sessions>
                    <rtp-codec name="audio/basic">
                        <decoding>40</decoding>
                        <encoding>40</encoding>
                    </rtp-codec>
                </ivr-sessions>
            </media-server-address>
        </response-session-info>
     </mediaResourceResponse>
   </mrbconsumer>

   --Part

The sequence diagram and dumps show a totally different vibe compared to Query mode 🌈. The SIP INVITE the AS sends (1.) includes both a Consumer request (same as before) and an SDP to negotiate a CFW channel with an MS. The MRB handles the request exactly as before (provisioning two MS instances), but with one big difference: it picks one of the two MS instances on the AS's behalf (negotiating the Control Channel in steps 3 to 6) and only then replies to the AS with both the MS side of the SDP negotiation (with info on how to set up the Control Channel) and the Consumer response itself 👑.

The Consumer response is also a little different. As you can see in 7., the MRB added an extra element (<connection-id>) to the message 🫶. This element holds the 'connection-id' that the AS and MS would have built out of the 'From' and 'To' tags as explained in Section 6, had the AS contacted the MS directly. Since the MRB did the negotiation on behalf of the AS, without this info the AS and MS would refer to different connectionid attributes when targeting the same dialog, and the CFW protocol wouldn't behave as expected 😭. This aspect gets a closer look in the next section (for the media dialog-based approach), since the 'connection-id' attribute is strictly related to media sessions.

As before, for conciseness, the subsequent steps of the previous transaction are pretty trivial, so they're not shown 💅. As the flow shows, the SIP negotiation left both the AS and the chosen MS negotiating a Control Channel. So the AS just has to instantiate the Control Channel and send CFW requests according to its application logic ✨.

It's worth highlighting that, as in the Query example, the AS gets the addresses of both chosen MS here too, since a Consumer transaction took place 🌸. So just like in the Query case, any UAC media dialog can be redirected directly to the proper MS using the 3PCC approach (e.g., as shown in Figure 10), rather than going through the MRB as a Proxy/B2BUA 🦋. Of course, a separate SIP control dialog would be needed before attempting to use the second MS instance. iykyk 💜

7.2.2.2. Inline-Aware Mode: Media Dialog-Based Approach ✨

okay so there's a second way to slay IAMM mode 💅, and that's by using the SIP dialogs related to the UAC media dialogs as 'vessels' for Consumer messages 🦋. The ladder diagram and protocol dumps below will make it clearer, but ngl this one is giving very similar vibes to Section 7.2.2.1 when it comes to the Consumer request/response. It's still worth comparing the two, though, because they're different in how the media dialog itself gets managed and what happens with any CFW Control Channel that may be involved 🌸.

Figure 50 shows a ladder diagram of a typical Consumer request in the media dialog-based Inline-aware topology 🧚:

   UAC              AS                     MRB                        MS
    |               |                       |                          |
    | 1. INVITE     |                       |                          |
    | (audio/video) |                       |                          |
    |-------------->|                       |                          |
    | 2. 100 Trying |                       |                          |
    |<--------------|                       |                          |
    |               | 3. INVITE             |                          |
    |               | (multipart/mixed:     |                          |
    |               |  audio/video from 1., |                          |
    |               |  application/mrb-consumer+xml)                   |
    |               |---------------------->|                          |
    |               |       4. 100 (Trying) |                          |
    |               |<----------------------|                          |
    |               |                       |--+ Extract SDP and       |
    |               |                       |  | MRB payloads; handle  |
    |               |                       |<-+ Consumer request to   |
    |               |                       |    pick Media Servers    |
    |               |                       |                          |
    |               |                       | 5. INVITE                |
    |               |                       | (audio/video from 3.)    |
    |               |                       |------------------------->|
    |               |                       |          6. 100 (Trying) |
    |               |                       |<-------------------------|
    |               |                       |                       +--|
    |               |                       |   Handle media dialog |  |
    |               |                       |       (connection-id) +->|
    |               |                       |                          |
    |               |                       |                7. 200 OK |
    |               |                       |    (audio/video from MS) |
    |               |                       |<-------------------------|
    |               |                       | 8. ACK                   |
    |               |                       |------------------------->|
    |               |        Prepare new +--|                          |
    |               |       payload with |  |                          |
    |               |    SDP from MS and +->|                          |
    |               |     Consumer reply    |                          |
    |               |                       |                          |
    |               |             9. 200 OK |                          |
    |               |     (multipart/mixed: |                          |
    |               |      audio/video from MS,                        |
    |               |      application/mrb-consumer+xml)               |
    |               |<----------------------|                          |
    |               | 10. ACK               |                          |
    |               |---------------------->|                          |
    |               |                       |                          |
    |               |--+ Read Consumer      |                          |
    |               |  | reply and send     |                          |
    |               |<-+ SDP back to UAC    |                          |
    |    11. 200 OK |                       |                          |
    |(audio/video from MS)                  |                          |
    |<--------------|                       |                          |
    | 12. ACK       |                       |                          |
    |-------------->|                       |                          |
    |               |                       |                          |
    |<<*************************** RTP ******************************>>|
    |               |                       |                          |
    |               |--+ Negotiate          |                          |
    |               |  | CFW channel        |                          |
    |               |<-+ towards MS         |                          |
    |               |    (if needed)        |                          |
    .               .                       .                          .
    .               .                       .                          .
    |               |                       |                          |
    |               |<<############## TCP CONNECTION ################>>|
    |               |                                                  |
    |               | CFW SYNC                                         |
    |               |+++++++++++++++++++++++++++++++++++++++++++++++++>|
    |               |                                                  |
    .               .                       .                          .
    .               .                       .                          .

          Figure 50: Media Resource Brokering: Media Dialog-Based
                             Inline-Aware Mode

To make the scenario easier to understand, we're assuming that the AS is interested in exactly the same set of requirements as those in Section 7.2.1. So the Consumer request the AS sends will be the same as before, with only the transport/topology changing 🎀.

Again, to make the protocol contents easier to read, a simple 'Part' is used whenever a boundary for a multipart/mixed payload is provided, instead of the actual boundary that would be inserted in the SIP messages 🫶.

The framework transaction steps are below (for simplicity's sake, only the relevant headers and payloads are reported, not the complete SIP transactions) 💖:

1. UAC -> AS (INVITE with media SDP)

   [..]
   From: <sip:lminiero@users.example.com>;tag=1153573888
   To: <sip:mediactrlDemo@as.example.com>
   [..]
   Content-Type: application/sdp

   v=0
   o=lminiero 123456 654321 IN IP4 203.0.113.2
   s=A conversation
   c=IN IP4 203.0.113.2
   t=0 0
   m=audio 7078 RTP/AVP 0 3 8 101
   a=rtpmap:0 PCMU/8000/1
   a=rtpmap:3 GSM/8000/1
   a=rtpmap:8 PCMA/8000/1
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-11
   m=video 9078 RTP/AVP 98

3. AS -> MRB (INVITE multipart/mixed)

   [..]
   From: <sip:ApplicationServer@as.example.com>;tag=fd4fush5
   To: <sip:Mrb@mrb.example.org>
   [..]
   Content-Type: multipart/mixed;boundary="Part"

   --Part
   Content-Type: application/sdp

   v=0
   o=lminiero 123456 654321 IN IP4 203.0.113.2
   s=A conversation
   c=IN IP4 203.0.113.2
   t=0 0
   m=audio 7078 RTP/AVP 0 3 8 101
   a=rtpmap:0 PCMU/8000/1
   a=rtpmap:3 GSM/8000/1
   a=rtpmap:8 PCMA/8000/1
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-11
   m=video 9078 RTP/AVP 98

   --Part
   Content-Type: application/mrb-consumer+xml

   <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
   <mrbconsumer version="1.0"
                xmlns="urn:ietf:params:xml:ns:mrb-consumer">
    <mediaResourceRequest id="bnv3xc45">
        <generalInfo>
            <packages>
                <package>msc-ivr/1.0</package>
                <package>msc-mixer/1.0</package>
            </packages>
        </generalInfo>
        <ivrInfo>
            <ivr-sessions>
                <rtp-codec name="audio/basic">
                    <decoding>100</decoding>
                    <encoding>100</encoding>
                </rtp-codec>
            </ivr-sessions>
            <file-formats>
                <required-format name="audio/x-wav"/>
            </file-formats>
            <file-transfer-modes>
                <file-transfer-mode package="msc-ivr/1.0" name="HTTP"/>
            </file-transfer-modes>
        </ivrInfo>
    </mediaResourceRequest>
   </mrbconsumer>

   --Part

5. MRB -> MS (INVITE SDP only)

   [..]
   From: <sip:Mrb@mrb.example.org:5060>;tag=32pbdxZ8
   To: <sip:MediaServer@ms.example.com:5080>
   [..]
   Content-Type: application/sdp

   v=0
   o=lminiero 123456 654321 IN IP4 203.0.113.2
   s=A conversation
   c=IN IP4 203.0.113.2
   t=0 0
   m=audio 7078 RTP/AVP 0 3 8 101
   a=rtpmap:0 PCMU/8000/1
   a=rtpmap:3 GSM/8000/1
   a=rtpmap:8 PCMA/8000/1
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-11
   m=video 9078 RTP/AVP 98

7. MRB <- MS (200 OK SDP)

   [..]
   From: <sip:Mrb@mrb.example.org:5060>;tag=32pbdxZ8
   To: <sip:MediaServer@ms.example.com:5080>;tag=KQw677BF
   [..]
   Content-Type: application/sdp

   v=0
   o=lminiero 123456 654322 IN IP4 203.0.113.1
   s=MediaCtrl
   c=IN IP4 203.0.113.1
   t=0 0
   m=audio 63442 RTP/AVP 0 3 8 101
   a=rtpmap:0 PCMU/8000
   a=rtpmap:3 GSM/8000
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-15
   a=ptime:20
   a=label:7eda834
   m=video 33468 RTP/AVP 98
   a=rtpmap:98 H263-1998/90000
   a=fmtp:98 CIF=2
   a=label:0132ca2

9. AS <- MRB (200 OK multipart/mixed)

11. UAC <- AS (200 OK SDP)

   [..]
   From: <sip:lminiero@users.example.com>;tag=1153573888
   To: <sip:mediactrlDemo@as.example.com>;tag=bcd47c32
   [..]
   Content-Type: application/sdp

   v=0
   o=lminiero 123456 654322 IN IP4 203.0.113.1
   s=MediaCtrl
   c=IN IP4 203.0.113.1
   t=0 0
   m=audio 63442 RTP/AVP 0 3 8 101
   a=rtpmap:0 PCMU/8000
   a=rtpmap:3 GSM/8000
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-15
   a=ptime:20
   a=label:7eda834
   m=video 33468 RTP/AVP 98
   a=rtpmap:98 H263-1998/90000
   a=fmtp:98 CIF=2
   a=label:0132ca2

okay so the first big difference 💅 is that the first INVITE (1.) isn't coming from the AS itself (the AS was happy to set up a Control Channel in the previous example). Instead, an authorized UAC sends it, probably because it wants to use a media service the AS offers 🎀. So that first INVITE only carries an SDP offering an audio and a video channel ✨. The AS's business logic then has to attach this UAC to an MS that meets certain requirements (for example, the called URI is tied to a specific service) 🧚. So the AS builds a Consumer request for the MRB to get a valid MS for the job. Same as before, the Consumer request goes to the MRB together with the SDP (3.) 💜. The MRB opens up the Consumer payload and handles it like usual. It picks two MS instances and attaches the UAC to the first one (5.) 🦋. Once the MS has successfully negotiated the audio and video streams (7.) 🔥, the MRB writes down the 'connection-id' for this call (we'll need it later to manipulate this user's audio and video streams) and sends the SDP from the MS back to the AS, along with the Consumer response (9.) 🫶. The AS unpacks the Consumer response and notes both of the MS instances it was given, plus the connection-id info 📝. Then it wraps things up by passing the SDP from the MS back to the UAC (11.) 👑.

At this point the UAC is attached to an MS, and that's already a win 🌈. The AS only needs to set up a Control Channel to that MS if it actually needs one 🌸. This step might not even be necessary, especially if the Consumer request is just an update to an existing session and not a brand new one 🙈. Assuming there's no Control Channel toward that MS yet, the AS creates one the normal way, by sending an INVITE straight to the MS it has an address for ✨. Once that's done, it can start manipulating the UAC's audio and video streams 💖. To do that, it uses the <connection-id> element the MRB reported, not the one it already had in its own records 🎯. The AS knows a connection-id value of fd4fush5: 117652221 (built from the messages it swapped with the MRB), but the MS knows a different one, 32pbdxZ8:KQw677BF (built from the MRB-MS interaction) 🧩. The correct one is the value the MS knows, so the AS uses that, and the MRB put it in the Consumer response for exactly this reason 💅😭.

7.2.3. Inline-Unaware Mode

Okay so in Inline-Aware mode the AS knows it's sending an INVITE to an MRB and not an MS, and it acts accordingly 🎀. It uses the multipart/mixed payload to look for an MS that can do what it needs ✨. In the Inline-Unaware MRB Mode (IUMM) though, the AS doesn't tell an MRB apart from an MS at all 🙈. So an MRB-unaware AS that can reach an MRB treats it like any generic MEDIACTRL MS 💜. It negotiates a Control Channel straight with the MRB and attaches its media dialogs there too 🦋. Here's the twist: the MRB doesn't offer any MS functionality on its own, so it has to act as a Proxy/B2BUA between the AS and an MS for both the Control Channel dialog and the media dialogs 🔥. Depending on implementation or deployment choices, simple redirects could also be used for this 🌈.

The catch is that with no Consumer request coming from the MRB-unaware AS, the MRB can't lean on AS directives to choose one MS over another 😭. The MRB can't really know what the AS is looking for 🙈. So it picks an MS using its own logic, which is implementation specific 🧚.

Figure 51 shows a ladder diagram of a typical Consumer request in the Inline-Unaware topology 📸:

   AS                      MRB                          MS
    |                       |                           |
    | 1. INVITE             |                           |
    | (application/cfw)     |                           |
    |---------------------->|                           |
    |       2. 100 (Trying) |                           |
    |<----------------------|                           |
    |                       |--+ Pick an MS             |
    |                       |  | and redirect           |
    |                       |<-+ INVITE there           |
    |                       |                           |
    |                       | 3. INVITE                 |
    |                       | (application/cfw from 1.) |
    |                       |-------------------------->|
    |                       |           4. 100 (Trying) |
    |                       |<--------------------------|
    |                       |                           |--+ Negotiate
    |                       |                           |  | CFW Control
    |                       |                           |<-+ Channel
    |                       |                 5. 200 OK |
    |                       | (application/cfw from MS) |
    |                       |<--------------------------|
    |                       | 6. ACK                    |
    |                       |-------------------------->|
    |                       |                           |
    |             7. 200 OK |                           |
    |(application/cfw from MS)                          |
    |<----------------------|                           |
    | 8. ACK                |                           |
    |---------------------->|                           |
    |                       |                           |
    |                                                   |
    |<<############## TCP CONNECTION #################>>|
    |                                                   |
    | CFW SYNC                                          |
    |++++++++++++++++++++++++++++++++++++++++++++++++++>|
    |                                                   |
    .                       .                           .
    .                       .                           .

         Figure 51: Media Resource Brokering: Inline-Unaware Mode

Look at that diagram 👀. In this setup the MRB is basically acting as a 3PCC between the AS and whichever MS it chose 💖.

The same goes for attaching UAC media dialogs 🎀. The MRB remembers which MS it picked for the AS. For every UAC media dialog the AS tries to attach to the MRB, the MRB makes sure it's somehow actually redirected to that MS 🦋.

Nothing is shown in the messages in this section, since IUMM doesn't involve any Consumer transaction 🙈. In this example, a simple [RFC6230] Control Channel negotiation happens, with the MRB acting as an intermediary and picking an MS for the AS based on some logic 🧚. That's because the AS doesn't support the MRB specification here, so it just tries to set up a Control Channel using its own logic 💅.

Quick heads up 🚨: the "redirect the INVITE" wording in Figure 51 doesn't automatically mean a SIP 302 message has to be used 👀. One simple approach is to give the unaware AS different URIs that the MRB handles transparently, so the MRB can just map each URI to a different MS instance 🌸. The MRB can also use the SIP 'Contact' header in a reply to an INVITE from an AS, to give the actual URI where the chosen MS can be reached 🫶. The reasons behind this discussion, plus more details, are covered in Section 7.3.2 ✨.

7.3. Handling Media Dialogs

Okay so it's worth briefly going over how media dialogs get managed when an MRB is involved 🧁. Honestly, the MRB can add some extra complexity compared to the pretty straightforward 1:1 AS-MS topology 😭💜.

7.3.1. Query and Inline-Aware Mode ✨

okay so bestie, in the Query and IAMM case the MRB usually only handles the Consumer request from an AS 💅. After that, the AS and the MS that the MRB picked talk directly over SIP. That works because the AS gets the MS SIP URI back in its reply. So the AS can just pass the media dialogs for that session to the right MS and let it handle them 🦋. For this to work, the AS has to set up a Control Channel to its chosen MS before it has any requests to service. Plan ahead, babe 🧚

Here's the vibe in Figure 52. Heads up: this diagram and the ones after it are simplified. The full SIP transactions aren't shown, and only the originating messages are included so the story is easy to follow 🎀

UAC              AS                           MRB                     MS
 |                |                            |                      |
 |                | 1. Consumer request        |                      |
 |                |--------------------------->|                      |
 |                |                            |                      |
 |                |       2. Consumer response |                      |
 |                |<---------------------------|                      |
 |                |                            |                      |
 |                | 3. COMEDIA negotiation to create CFW channel      |
 |                |-------------------------------------------------->|
 |                |                            |                      |
 |                |<<############## CFW CONNECTION #################>>|
 | 4. INVITE xyz  |                            |                      |
 |--------------->|                            |                      |
 |                | 5. Attach UAC to MS (3PCC)                        |
 |                |-------------------------------------------------->|
 |                |                            |                      |
 |<<++++++++++++++++++++++ RTP channels ++++++++++++++++++++++++++++>>|
 |                |                            |                      |
 .                .                            .                      .
 .                .                            .                      .

              Figure 52: Handling Media Dialogs in Query/IAMM

So the interactions are pretty straightforward, honestly iconic 🌸 The AS knows which MS it got assigned to, because that came back from the MRB Consumer request (whether that happened over HTTP or SIP). So it can attach any UAC that wants its features straight to the MS and mess with the media connections through the CFW Control Channel like normal 💖

In this setup the MRB is basically just a locator 📍 Once it gives the AS the URI of the resource, it stays out of the way. The only exception is if it wants to monitor things, like by using the Publishing information the MS reports. So the whole thing goes back to being 1:1 between the AS and the MS. Clean ✨

Now, sometimes you do want the MRB sitting in the SIP signaling path too, for example to have more control over how resources get used 👑 The Consumer interface was designed so this is easy, and it doesn't need any protocol changes at all 🙈 Here's how: the MRB can answer a Consumer request with a URI it's responsible for (instead of the MS SIP URI), then map that URI to the real MS URI in its own logic. The AS has no idea, and it just treats the MRB like it's the MS itself 😭

Figure 53 shows how the scenario changes in this case.

 UAC              AS                           MRB                    MS
  |                |                            |                      |
  |                | 1. Consumer request        |                      |
  |                |--------------------------->|                      |
  |                |                            |                      |
  |                |       2. Consumer response |                      |
  |                |<---------------------------|                      |
  |                |                            |                      |
  |                | 3. COMEDIA negotiation     |                      |
  |                |--------------------------->|                      |
  |                |                            | 4. COMEDIA neg.      |
  |                |                            |--------------------->|
  |                |                            |                      |
  |                |<<############## CFW CONNECTION #################>>|
  | 5. INVITE xyz  |                            |                      |
  |--------------->|                            |                      |
  |                | 6. Attach UAC to MS (3PCC) |                      |
  |                |--------------------------->|                      |
  |                |                            | 7. Attach UAC (3PCC) |
  |                |                            |--------------------->|
  |                |                            |                      |
  |<<++++++++++++++++++++++ RTP channels ++++++++++++++++++++++++++++>>|
  |                |                            |                      |
  .                .                            .                      .
  .                .                            .                      .

             Figure 53: Handling Media Dialogs in Query/IAMM:
                         MRB in the Signaling Path

This time, even though the MRB picked a specific MS after the AS asked for one, it replies with a different SIP URI, one the MRB itself answers to 🦋 The AS negotiates the Control Channel with that URI, and the MRB passes the request along to the actual MS without the AS noticing. Eventually the Control Channel ends up between the AS and the MS. Same deal for UACs handled by the AS: it sends the calls to the URI it was given (the one the MRB handles), and the MRB relays each call to the MS so the RTP channels get created between the UAC and the MS 🎀

Honestly this is pretty similar to the last scenario, except now the MRB is on the signaling path for both the SIP control dialog and the SIP media dialogs. That gives it extra control over resources, like sending a BYE when a resource has expired 💀 There are a few ways an MRB could hand out URIs to map to a requested MS. For example, it could use SIP URI parameters to make several unique SIP URIs that all route to the same host and port, like sip:MrbToMs@mrb.example.com:5080;p=1234567890 🌈 Or it could just keep a pool of URIs it's responsible for and manage which ones map to which requested MS services 💜


7.3.2. Inline-Unaware Mode 🫶

Like I said earlier, in the IUMM case the AS interacts with the MRB as if it were the MS itself. Someone might say this makes the AS act the same way it does in the IAMM case. Nope! 🙅‍♀️ The AS actually gave the MRB info about the resources it needed, and that's how the MRB picked a proper MS. In the IUMM case, the MRB has to pick an MS with zero help from the AS 😤

Still, IUMM is super interesting for media dialog management 🔥 In the MRB-unaware mode there's no Consumer request, so the AS just sees the MRB as an MS. Since there's no AS<->MRB interaction and no MS selection process, the MRB will probably be in the signaling path anyway, at least when the AS first shows up. The MRB has two options: it can redirect the AS straight to an MS, or it can act as a Proxy/B2BUA and contact an MS on the AS's behalf, following whatever implementation-specific policies it has 💅

Not a big deal on its own, BUT it gets messy when the same unaware AS has several sessions with different MSs 😭 The AS only sees one "virtual" MS (the MRB), so it sends all its calls there. That makes it hard for the MRB to figure out which media dialogs belong where. Like, is this UAC calling for the AS application logic that leads to MS1, or MS2, or something else entirely? Iykyk 🙈

One simple way to fix this is to always relay the SIP dialogs from the same unaware AS to the same MS, as shown in Figure 54 👑

UAC1  UAC2       AS                           MRB                     MS
 |     |          |                            |                      |
 |     |          | 1. COMEDIA negotiation (A) |                      |
 |     |          |--------------------------->|                      |
 |     |          |                            | 2. COMEDIA neg. (A)  |
 |     |          |                            |--------------------->|
 |     |          |                            |                      |
 |     |          |<<############## CFW CONNECTION #################>>|
 |     |          |                            |                      |
 |     |          | 3. COMEDIA negotiation (B) |                      |
 |     |          |--------------------------->|                      |
 |     |          |                            | 4. COMEDIA neg. (B)  |
 |     |          |                            |--------------------->|
 |     |          |                            |                      |
 |     |          |<<############## CFW CONNECTION #################>>|
 | 5. INVITE xyz  |                            |                      |
 |--------------->|                            |                      |
 |     |          | 6. Attach UAC1 to MS (3PCC)|                      |
 |     |          |--------------------------->|                      |
 |     |          |                            | 7. Attach UAC (3PCC) |
 |     |          |                            |--------------------->|
 |     |          |                            |                      |
 |<<++++++++++++++++++++++ RTP channels ++++++++++++++++++++++++++++>>|
 |     |          |                            |                      |
 |     | 8. INVITE|                            |                      |
 |     |    jkl   |                            |                      |
 |     |--------->|                            |                      |
 |     |          | 9. Attach UAC2 to MS (3PCC)|                      |
 |     |          |--------------------------->|                      |
 |     |          |                            | 10. Attach UAC (3PCC)|
 |     |          |                            |--------------------->|
 |     |          |                            |                      |
 |     |<<++++++++++++++++ RTP channels ++++++++++++++++++++++++++++>>|
 |     |          |                            |                      |
 .     .          .                            .                      .
 .     .          .                            .                      .

       Figure 54: Handling Media Dialogs in IUMM: Always the Same MS

Okay so the AS makes two separate Control Channel sessions (A and B) to handle two different business logic implementations 💅. Like, the AS SIP URI xyz (tied to CFW session A) could be an IVR pizza-ordering app 🍕, while the AS SIP URI jkl (tied to CFW session B) could be a conference room 🎀. It's giving pretty obvious problem though. If the MRB sent those two CFW sessions to two different MS, it'd be a total mess trying to figure out whether UAC1 should attach to the MS running CFW session A or the one running CFW session B 😭. In this setup, if every CFW session and UAC media dialog from the same MRB-unaware AS goes to the same MS, everything just works ✨. The MRB basically leaves the mapping between media dialogs and CFW sessions up to the AS, which is very relaxed of it honestly 🦋.

This approach is super simple, but also not very scalable 💀. Still, it does fix the problem. No matter how many separate Control Channels the AS has with the MRB/MS (here, Control Channel A maps to application xyz and Control Channel B maps to application jkl), the termination point is still the same MS, so that MS ends up being the destination for all the media dialogs too.

Now, the scalability issue. If the MRB is in the SIP signaling path for every call, this gets rough 😩. So a different approach is needed. Especially when different applications are being handled by the same unaware AS, it makes sense to use different MS for each one and to track the media dialogs being forwarded to them correctly 🧚. That means the MRB needs a way to redirect the unaware AS to a different MS whenever it predicts or realizes that a different application logic is involved 👑.

There are a few ways the MRB can do this. One is redirection, for example with a SIP 302 message sent in reply to a Control Channel negotiation started by an unaware AS 🔥. Here's how that looks in Figure 55 🌸:

UAC1             AS                           MRB                     MS
 |                |                            |                      |
 |                | 1. COMEDIA negotiation     |                      |
 |                |--------------------------->|                      |
 |                |                            |                      |
 |                |          2. 302 Moved (MS) |                      |
 |                |<---------------------------|                      |
 |                |                            |                      |
 |                | 3. COMEDIA negotiation     |                      |
 |                |-------------------------------------------------->|
 |                |                            |                      |
 |                |<<############## CFW CONNECTION #################>>|
 |                |                            |                      |
 | 4. INVITE xyz  |                            |                      |
 |--------------->|                            |                      |
 |                | 5. Attach UAC1 to MS (3PCC)|                      |
 |                |-------------------------------------------------->|
 |                |                            |                      |
 |<<++++++++++++++++++++++ RTP channels ++++++++++++++++++++++++++++>>|
 |                |                            |                      |
 .                .                            .                      .
 .                .                            .                      .

Figure 55: Handling Media Dialogs in IUMM: Redirection

With this approach, the MRB can redirect the AS to a specific MS every time a new Control Channel is created, and the AS then sends the related calls over there 🦋. It's kind of like the first approach in the Query/IAMM case, except there's no Consumer request involved this time 🙈. The result is still a 1:1 topology between the AS and the MS, which keeps things really simple ✨.

Also, just like before, the MRB might want to be in the signaling path for the SIP dialogs instead of just acting as a locator 👀. A third option is to use the "virtual" URIs that the MRB handles, as described in the previous section 💜. So instead of explicit redirection or always using the same MS, the MRB may redirect new SIP control dialogs to one of its own URIs, using the same approach shown in Figure 53 🌈. Here's how that looks for the IUMM case in Figure 56:

UAC1             AS                              MRB                  MS
 |                |                               |                   |
 |                | 1. COMEDIA negotiation (MRB)  |                   |
 |                |------------------------------>|                   |
 |                |                               |                   |
 |                |           2. 302 Moved (MRB') |                   |
 |                |<------------------------------|                   |
 |                |                               |                   |
 |                | 3. COMEDIA negotiation (MRB') |                   |
 |                |------------------------------>|                   |
 |                |                               | 4. COMEDIA neg.   |
 |                |                               |------------------>
 |                |                               |                   |
 |                |<<############## CFW CONNECTION #################>>|
 |                |                               |                   |
 | 5. INVITE xyz  |                               |                   |
 |--------------->|                               |                   |
 |                | 6. Attach UAC1 to MRB' (3PCC) |                   |
 |                |------------------------------>|                   |
 |                |                               | 7 Attach UAC (3PCC)
 |                |                               |------------------>
 |                |                               |                   |
 |<<++++++++++++++++++++++ RTP channels ++++++++++++++++++++++++++++>>|
 |                |                               |                   |
 .                .                               .                   .
 .                .                               .                   .

Figure 56: Handling Media Dialogs in IUMM: MRB in the Signaling Path

Heads up, though 🚨: in both cases, there's no guarantee that the AS will actually see the 302 the MRB sends. If there's a proxy between the AS and the MRB, that proxy could act on the 302 itself 😱. To deal with that, the MRB might also use the Contact header in its SIP responses to the INVITE to point at the right MS 🎯. The AS isn't required to use the info in that header to reach the MS, but it could be a good idea to use it anyway, since it covers the proxy scenario we just talked about 🫶.

Last one, and then I'm done 💅. The IUMM issues mostly come down to the fact that the AS sees the MRB as a single MS instance. So a simple fix is to make the MRB look like a bunch of different MS right away 🍓. You do this by provisioning the unaware AS with a series of different URIs, all handled by the MRB, which acts as a pool of "virtual" MS 🌸. That way, the AS can be designed to use a different MS for each class of calls, like different applications it manages (two in the example in this section). It would contact two different provisioned URIs to create two separate Control Channels to two different MS ✨. Since the MRB handles both URIs, it can use them to decide which MS each call should go to 🧠. Basically, this takes Figure 54 and removes the constraint of always using the same MS, so the new scenario looks like Figure 57 below 🦋:

 UAC1  UAC2       AS                           MRB              MS1  MS2
  |     |          |                            |                 |    |
  |     |          | 1. COMEDIA negotiation (A) |                 |    |
  |     |          |    INVITE fake-ms1         |                 |    |
  |     |          |--------------------------->|                 |    |
  |     |          |                            | 2. COMEDIA (A)  |    |
  |     |          |                            |---------------->|    |
  |     |          |                            |                 |    |
  |     |          |<<############## CFW CONNECTION 1 ##########>>|    |
  |     |          |                            |                 |    |
  |     |          | 3. COMEDIA negotiation (B) |                 |    |
  |     |          |    INVITE fake-ms2         |                 |    |
  |     |          |--------------------------->|                 |    |
  |     |          |                            | 4. COMEDIA neg. (B)  |
  |     |          |                            |--------------------->|
  |     |          |                            |                 |    |
  |     |          |<<############## CFW CONNECTION 2 ###############>>|
  |     |          |                            |                 |    |
  | 5. INVITE xyz  |                            |                 |    |
  |--------------->|                            |                 |    |
  |     |          | 6. Attach UAC1 to fake-ms1 (3PCC)            |    |
  |     |          |--------------------------->|                 |    |
  |     |          |                            | 7. Attach UAC   |    |
  |     |          |                            |---------------->|    |
  |     |          |                            |                 |    |
  |<<++++++++++++++++++++++ RTP channels +++++++++++++++++++++++>>|    |
  |     |          |                            |                 |    |
  | 8. INVITE jkl  |                            |                 |    |
  |--------------->|                            |                 |    |
  |     |          | 9. Attach UAC2 to fake-ms2 (3PCC)            |    |
  |     |          |--------------------------->|                 |    |
  |     |          |                            | 10. Attach UAC  |    |
  |     |          |                            |--------------------->|
  |     |          |                            |                 |    |
  |<<+++++++++++++++++++++++++ RTP channels +++++++++++++++++++++++++>>|
  |     |          |                            |                 |    |
  .     .          .                            .                 .    .
  .     .          .                            .                 .    .

Figure 57: Handling Media Dialogs in IUMM: Provisioned URIs

In this new example, the same unaware AS is still handling two different applications, still tied to the same URIs as before. This time, though, the AS has been designed to use different MS instances for those two very different applications 🎀. It's been configured to use two MS instances, reachable at SIP URI 'fake-ms1' and 'fake-ms2', and the MRB handles both of them transparently ✨. Just like before, this creates two Control Channels (A and B), but this time they go to two different MS. The MRB makes sure that for this AS, Control Channel negotiation towards 'fake-ms1' is actually redirected to MS1. At the same time, 'fake-ms2' is associated with MS2 💖. Once the AS has set up Control Channels with both MS, it's ready to handle media dialogs. UAC1 calls the SIP URI 'xyz' on the AS to order a pizza 🍕. The AS attaches that media dialog to 'fake-ms1', the MS it knows is responsible for that branch of application logic. The MRB then makes sure it reaches the right MS instance, which is MS1 🦋. Later on, a different user, UAC2, calls SIP URI 'jkl' to join a conference room 🌈. This time the AS attaches the new media dialog to 'fake-ms2', the MS instance handling the conference application. Once again, the MRB makes sure that MS2 is the one that actually receives the dialog 👑.

Again, this diagram is only meant to show how the MRB might enforce its decisions 🧚. As in the previous examples, the MRB may either act as a Proxy/B2BUA between the AS and the MS instances, or it may redirect the AS to the right MS instances when they're first contacted (for example, by means of the Contact header and/or a SIP redirect, as explained before) and then let the AS attach the media dialogs by itself 💅.


7.3.3. CFW Protocol Behavior

As shown in the previous diagrams, no matter what the topology is, the AS and MS usually end up with a direct connection with respect to the CFW Control Channel 🫶. So it can be expected that the CFW protocol keeps working as it should, and as a result, all the call flows presented in this document can easily be reproduced in those circumstances too ✨.

That said, one aspect needs to be considered very carefully 👀. It's worth reminding readers that both the AS and the MS use some SIP-related information to address the entities they manipulate. This is the case, for instance, for the <connectionid> element that both the AS and the MS refer to when addressing a specific UAC. As explained in Section 6, this 'connectionid' identifier is constructed by concatenating the 'From' and 'To' tags taken from a SIP header: specifically, from the headers of the AS<->MS leg that allows a UAC to be attached to the MS. The presence of an additional component in the path between the AS and the MS, the MRB, might alter these tags. That could cause the AS to use tags (AS<->MRB) that are different from those used by the MS (MRB<->MS) 😭. The result would be that the AS and MS use different 'connectionid' identifiers to address the same UAC, and the protocol wouldn't work as expected. So it's super important that any MRB implementation takes very good care to preserve the integrity of the involved SIP headers when proxying or forwarding SIP dialogs between the AS and MS, so it doesn't "break" the behavior of the protocol 🚫.

Let's take, for instance, the scenario depicted in Figure 53, especially steps 6 and 7, which specifically address a UAC being attached by an AS to an MS via the MRB 💜. Let's assume that Figure 58 shows what happens to the 'From' and 'To' headers in that scenario, when dealing with the 3PCC approach to attach a specific UAC to the MS 🎀.

UAC              AS                         MRB                       MS
 |                |                          |                        |
 | INVITE xyz     |                          |                        |
 |--------------->|                          |                        |
 |                | SIP [..]                 |                        |
 |                | From: <..>;tag=a1b2c3    |                        |
 |                | To: <..>;tag=d4e5f6      |                        |
 |                |<------------------------>|                        |
 |                |                          | SIP [..]               |
 |                |                          | From: <..>;tag=aaabbb  |
 |                |                          | To: <..>;tag=cccddd    |
 |                |                          |<---------------------->|
 |                |                          |                        |
 |                | 1. CONTROL (play announcement to UAC)             |
 |                |-------------------------------------------------->|
 |                |                               2. 200 (IVR Error!) |
 |                |<--------------------------------------------------|
 |                |                          |                        |
 .                .                          .                        .
 .                .                          .                        .

     Figure 58: CFW Protocol Behavior in the Case of Manipulated Tags

In this example, once the 3PCC is done and the UAC is attached to the MS, the AS and the MS end up with different ideas of what the 'connectionid' for the UAC should be 😵. The AS builds a 'connectionid' from the tags it knows about (a1b2c3:d4e5f6), while the MS builds a different identifier after receiving different information from the MRB (aaabbb:cccddd) 🙈.

So when the AS tries to play an announcement to the UAC using the connectionid it correctly built, the MS just as correctly replies with an error, since it doesn't recognise that identifier 💀. This is correct protocol behavior, because the failure was caused by misuse of the information needed for it to work as expected 🌸.

1. AS -> MS (CFW CONTROL, play)

   CFW ffhg45dzf123 CONTROL
   Control-Package: msc-ivr/1.0
   Content-Type: application/msc-ivr+xml
   Content-Length: 284

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <dialogstart connectionid="a1b2c3:d4e5f6">
       <dialog>
         <prompt>
           <media loc="http://www.example.net/hello.wav"/>
         </prompt>
       </dialog>
     </dialogstart>
   </mscivr>

2. AS <- MS (CFW 200 OK)

   CFW ffhg45dzf123 200
   Timeout: 10
   Content-Type: application/msc-ivr+xml
   Content-Length: 148

   <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <response status="407" reason="connectionid does not exist"
               dialogid=""/>
   </mscivr>

In an even worse scenario, the connectionid might actually exist but be mapped to a different UAC 😱. In that case the transaction would succeed, but a completely different UAC would be involved. That's a silent failure that neither the AS nor the MS would ever notice 🥺.

That said, proper management of these sensitive pieces of information by the MRB would stop those failure scenarios from happening 🫧. How this issue is handled in the IAMM case (both CFW-based and media dialog-based) has already been described 💜. Handling this issue for the IUMM case is not documented in [RFC6917], which explicitly puts it out of scope, so it may be implementation specific 🤷‍♀️.

The same goes for SDP fields 🎀. The AS and MS use ad hoc SDP attributes to instantiate a Control Channel, and they use SDP labels to address specific media connections of a UAC media dialog when a fine-grained approach is needed. So any MRB implementation should limit any SDP manipulation as much as possible, or at least take very good care not to cause changes that could "break" the expected behavior of the CFW protocol 🌈.


8. Security Considerations 🔐

All the MEDIACTRL documents make strong statements about security considerations for the interactions happening at every level between the parties involved 🛡️. Given how sensitive the interaction between AS and MS is, a lot of effort has gone into guidance on how to secure what flows through a Control Channel 💅. Transactions about dialogs, connections, and mixes are strongly tied to resources that are actually deployed and used in the MS 😤. So it's in the interest of both the AS and the MS that resources created and handled by an entity are not manipulated by a potentially malicious third party when permission hasn't been granted 🚨.

Because the aforementioned documents make strong statements and give implementers good guidance on these issues, this section will only show the reader some MEDIACTRL call flows. Those flows show how a single secured MS is assumed to reply to different AS when it receives requests that may cross the bounds each AS is constrained by 👑. This would be the case, for instance, for generic auditing requests, or explicit conference manipulation requests where the identifiers involved are not part of the context of the originating AS 🧐.

To address one very specific scenario, let's assume that two different AS, AS1 and AS2, have established a Control Channel with the same MS 🎭. Considering the SYNC transaction that an AS and an MS use to set up a Control Channel, the MS is able to tell requests coming from AS1 apart from requests coming from AS2 🔍. In fact, as explained in Sections 5.1 and 5.2, an AS and an MS negotiate a cfw-id attribute in the SDP. The same value is then used in the SYNC message on the Control Channel created after the negotiation, which reassures both the AS and the MS that the Control Channel they share is actually the channel they negotiated in the first place 🫶.

Let's also assume that AS1 has created a conference mix (confid=74b6d62) to which it has attached some participants as part of its business logic 🎉. Meanwhile, AS2 has created a currently active IVR dialog (dialogid=dfg3252) with a user agent it is handling (237430727:a338e95f) 📞. AS2 has also joined two connections to each other (1:75d4dd0d and 1:b9e6a659) 🦋. Clearly, it's highly desirable that AS1 not be aware of what AS2 is doing with the MS, and vice versa, and that neither is allowed to manipulate the other's resources 🙅‍♀️. The following transactions will occur:

  1. AS1 places a generic audit request to both the Mixer and IVR packages.
  2. AS2 places a generic audit request to both the Mixer and IVR packages.
  3. AS1 tries to terminate the dialog created by AS2 (6791fee).
  4. AS2 tries to join a user agent it handles (1:272e9c05) to the conference mix created by AS1 (74b6d62).

A sequence diagram of the above-mentioned transactions is depicted in Figure 59, which shows how the MS is assumed to reply in all cases, in order to avoid security issues 🌷

Okay bestie, the big picture here is a security check-up 🔍✨ This figure is a little story with four characters: AS1, AS2, and the MS in the middle, plus a bunch of sneaky requests that the ASes shouldn't be making. Let's see how the MS handles them 💅

      AS1                     AS2                                 MS
       |                       |                                  |
       | A1. CONTROL (IVR audit)                                  |
       |++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>|
       |                       |                       A2. 200 OK |
       |<<++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
       |                       |                                  |
       | B1. CONTROL (Mixer audit)                                |
       |++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>|
       |                       |                       B2. 200 OK |
       |<<++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
       |                       |                                  |
       |                       | C1. CONTROL (IVR audit)          |
       |                       |++++++++++++++++++++++++++++++++>>|
       |                       |                       C2. 200 OK |
       |                       |<<++++++++++++++++++++++++++++++++|
       |                       |                                  |
       |                       | D1. CONTROL (Mixer audit)        |
       |                       |++++++++++++++++++++++++++++++++>>|
       |                       |                       D2. 200 OK |
       |                       |<<++++++++++++++++++++++++++++++++|
       |                       |                                  |
       | E1. CONTROL (dialogterminate)                            |
       |++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>|
       |                       |                E2. 403 Forbidden |
       |<<++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
       |                       |                                  |
       |                       | F1. CONTROL (join UAC&conf[AS1]) |
       |                       |++++++++++++++++++++++++++++++++>>|
       |                       |                F2. 403 Forbidden |
       |                       |<<++++++++++++++++++++++++++++++++|
       |                       |                                  |
       .                       .                                  .
       .                       .                                  .

Figure 59: Security Considerations: Framework Transaction

The expected outcome is that the MS kinda fibs to both AS1 and AS2 when they ask for audits 🙈 It doesn't report every identifier, only the ones each AS is directly involved with. And when someone asks for something they aren't allowed to do, the MS says no with a 403 (Forbidden) 🚫 Let's go through each transaction, one by one:

  • First transaction (A1): AS1 sends a generic <audit> request to the IVR package. It's generic because no attributes are passed with it, which means AS1 wants to know the MS capabilities AND every dialog the MS is currently handling. In the reply (A2), the MS reports the package capabilities in the <auditresponse>, but the <dialogs> element comes back empty 👀 That's because the only dialog the MS is handling was created by AS2, so the MS doesn't report its identifier (6791fee) to AS1. Honestly, this matters: AS1 could use that identifier to mess with the dialog, like tearing it down, and that would interrupt the service without AS2 being involved at all 😱
  • Second transaction (B1): AS1 sends the same kind of <audit> request, but this time to the Mixer package. It's generic again, so AS1 wants the package capabilities AND all the mixers and connections the package is handling right now. This time the MS reports the capabilities (B2) AND info about mixers and connections. But the info is incomplete ✨ Only the mixers and connections that AS1 started are shown (mixer 74b6d62 and its participants), and the stuff AS2 started gets left out of the report. Same reason as before 💅
  • Third and fourth transactions (C1 and D1): Now it's AS2 sending <audit> requests to both the IVR and Mixer packages. Same deal, they're generic. Looking at the replies (C2 and D2), the capabilities section is exactly the same as what AS1 got, because the MS has no reason to fib about what it can do 💁 The <dialogs> and <mixers> sections are totally different though. AS2 gets info about its own IVR dialog (6791fee), which was left out of AS1's reply. It also only gets info about the one connection it made (1:75d4dd0d and 1:b9e6a659), with no details about the mixers and connections AS1 started.
  • Fifth transaction (E1): This is where AS1 gets greedy 😤 Instead of just auditing the packages, it tries to <dialogterminate> the dialog AS2 created (6791fee). The MS never reported that identifier in the earlier audit reply, so we assume AS1 got it some other way, out-of-band. That's an unauthorized move, since the dialog is outside AS1's lane. So the MS doesn't handle the request even though it's perfectly well-formed. It replies (E2) with a framework-level 403 (Forbidden) and leaves the dialog totally alone 🛑
  • Sixth and last transaction (F1): AS2 tries to <join> one of the UACs it's handling to the conference mix that AS1 created (74b6d62). Same story as the last one: the MS never reported that identifier, so we assume AS2 got it out-of-band. One of the two identifiers (the UAC) really is handled by AS2, but the other (the conference mix) isn't. So, just like the fifth transaction, the MS treats this as outside AS2's bounds. For the same reason, the MS replies (F2) with a framework-level 403 (Forbidden), and neither the mix nor the UAC gets joined 🙅‍♀️

Now let's look at the actual messages, starting with AS1 asking the MS to audit IVR 📞

  A1. AS1 -> MS (CFW CONTROL, audit IVR)
  --------------------------------------
     CFW 140e0f763352 CONTROL
     Control-Package: msc-ivr/1.0
     Content-Type: application/msc-ivr+xml
     Content-Length: 81

     <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
        <audit/>
     </mscivr>

And here's the MS's reply to that, with the capabilities list and the empty dialogs 🎀

  A2. AS1 <- MS (CFW 200, auditresponse)
  --------------------------------------
     CFW 140e0f763352 200
     Timeout: 10
     Content-Type: application/msc-ivr+xml
     Content-Length: 1419

     <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <auditresponse status="200">
        <capabilities>
           <dialoglanguages/>
           <grammartypes/>
           <recordtypes>
              <mimetype>audio/x-wav</mimetype>
              <mimetype>video/mpeg</mimetype>
           </recordtypes>
           <prompttypes>
              <mimetype>audio/x-wav</mimetype>
              <mimetype>video/mpeg</mimetype>
           </prompttypes>
           <variables>
              <variabletype type="date"
                            desc="value formatted as YYYY-MM-DD">
                 <format desc="month day year">mdy</format>
                 <format desc="year month day">ymd</format>
                 <format desc="day month year">dmy</format>
                 <format desc="day month">dm</format>
              </variabletype>
              <variabletype type="time" desc="value formatted as HH:MM">
                 <format desc="24 hour format">t24</format>
                 <format desc="12 hour format with am/pm">t12</format>
              </variabletype>
              <variabletype type="digits" desc="value formatted as D+">
                 <format desc="general digit string">gen</format>
                 <format desc="cardinal">crn</format>
                 <format desc="ordinal">ord</format>
              </variabletype>
           </variables>
           <maxpreparedduration>60s</maxpreparedduration>
           <maxrecordduration>1800s</maxrecordduration>
           <codecs>
              <codec name="audio"><subtype>basic</subtype></codec>
              <codec name="audio"><subtype>gsm</subtype></codec>
              <codec name="video"><subtype>h261</subtype></codec>
              <codec name="video"><subtype>h263</subtype></codec>
              <codec name="video"><subtype>h263-1998</subtype></codec>
              <codec name="video"><subtype>h264</subtype></codec>
           </codecs>

        </capabilities>
        <dialogs>
        </dialogs>
     </auditresponse>
     </mscivr>

Next up, AS1 auditing the Mixer package 🎶

  B1. AS1 -> MS (CFW CONTROL, audit mixer)
  ----------------------------------------
     CFW 0216231b1f16 CONTROL
     Control-Package: msc-mixer/1.0
     Content-Type: application/msc-mixer+xml
     Content-Length: 87

     <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
        <audit/>
     </mscmixer>
  B2. AS1 <- MS (CFW 200, auditresponse)
  --------------------------------------
     CFW 0216231b1f16 200
     Timeout: 10
     Content-Type: application/msc-mixer+xml
     Content-Length: 903

     <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
     <auditresponse status="200">
       <capabilities>
          <codecs>
             <codec name="audio"><subtype>basic</subtype></codec>
             <codec name="audio"><subtype>gsm</subtype></codec>
             <codec name="video"><subtype>h261</subtype></codec>
             <codec name="video"><subtype>h263</subtype></codec>
             <codec name="video"><subtype>h263-1998</subtype></codec>
             <codec name="video"><subtype>h264</subtype></codec>
          </codecs>
       </capabilities>
       <mixers>
         <conferenceaudit conferenceid="74b6d62">
           <participants>
             <participant id="1864574426:e2192766"/>
             <participant id="1:5a97fd79"/>
           </participants>
           <video-layout min-participants="1">
             <quad-view/>
           </video-layout>
         </conferenceaudit>
         <joinaudit id1="1864574426:e2192766" id2="74b6d62"/>
         <joinaudit id1="1:5a97fd79" id2="74b6d62"/>
       </mixers>
     </auditresponse>
     </mscmixer>

Now it's AS2's turn to audit the IVR package 🌸

  C1. AS2 -> MS (CFW CONTROL, audit IVR)
  --------------------------------------
     CFW 0216231b1f16 CONTROL
     Control-Package: msc-ivr/1.0
     Content-Type: application/msc-ivr+xml
     Content-Length: 81

     <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
        <audit/>
     </mscivr>
  C2. AS2 <- MS (CFW 200, auditresponse)
  --------------------------------------
     CFW 0216231b1f16 200
     Timeout: 10
     Content-Type: application/msc-ivr+xml
     Content-Length: 1502
     <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
     <auditresponse status="200">
        <capabilities>
           <dialoglanguages/>
           <grammartypes/>
           <recordtypes>
              <mimetype>audio/wav</mimetype>
              <mimetype>video/mpeg</mimetype>
           </recordtypes>
           <prompttypes>
              <mimetype>audio/wav</mimetype>
              <mimetype>video/mpeg</mimetype>
           </prompttypes>
           <variables>
              <variabletype type="date"
                            desc="value formatted as YYYY-MM-DD">
                 <format desc="month day year">mdy</format>
                 <format desc="year month day">ymd</format>
                 <format desc="day month year">dmy</format>
                 <format desc="day month">dm</format>
              </variabletype>
              <variabletype type="time" desc="value formatted as HH:MM">
                 <format desc="24 hour format">t24</format>
                 <format desc="12 hour format with am/pm">t12</format>
              </variabletype>
              <variabletype type="digits" desc="value formatted as D+">
                 <format desc="general digit string">gen</format>
                 <format desc="cardinal">crn</format>
                 <format desc="ordinal">ord</format>
              </variabletype>
           </variables>
           <maxpreparedduration>60s</maxpreparedduration>
           <maxrecordduration>1800s</maxrecordduration>
           <codecs>
              <codec name="audio"><subtype>basic</subtype></codec>
              <codec name="audio"><subtype>gsm</subtype></codec>
              <codec name="video"><subtype>h261</subtype></codec>
              <codec name="video"><subtype>h263</subtype></codec>
              <codec name="video"><subtype>h263-1998</subtype></codec>
              <codec name="video"><subtype>h264</subtype></codec>
           </codecs>
        </capabilities>
        <dialogs>
           <dialogaudit dialogid="6791fee" state="started"
                        connectionid="237430727:a338e95f"/>
        </dialogs>
     </auditresponse>
     </mscivr>

D1. AS2 -> MS (CFW CONTROL, audit mixer) 🎀

Okay so this one is the audit request, bestie! 💖 AS2 asks the MS to check its mixer, and it's giving very "what do you have for me" energy ✨

     CFW 515f007c5bd0 CONTROL
     Control-Package: msc-mixer/1.0
     Content-Type: application/msc-mixer+xml
     Content-Length: 87

     <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
        <audit/>
     </mscmixer>

D2. AS2 <- MS (CFW 200, auditresponse) 🦋

And here's the MS slaying the reply 💅 with a 200 and the auditresponse, listing its codecs and the joinaudit it's got going on 🔥

     CFW 515f007c5bd0 200
     Timeout: 10
     Content-Type: application/msc-mixer+xml
     Content-Length: 548

     <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
     <auditresponse status="200">
        <capabilities>
           <codecs>
              <codec name="audio"><subtype>basic</subtype></codec>
              <codec name="audio"><subtype>gsm</subtype></codec>
              <codec name="video"><subtype>h261</subtype></codec>
              <codec name="video"><subtype>h263</subtype></codec>
              <codec name="video"><subtype>h263-1998</subtype></codec>
              <codec name="video"><subtype>h264</subtype></codec>
           </codecs>
        </capabilities>
        <mixers>
           <joinaudit id1="1:75d4dd0d" id2="1:b9e6a659"/>
        </mixers>
     </auditresponse>
     </mscmixer>

E1. AS1 -> MS (CFW CONTROL, dialogterminate) 💀

Now AS1 is ending a dialog, bestie. 😭 It sends dialogterminate with immediate="true", no cap, the vibe is "we're done here" 🌸

     CFW 7fdcc2331bef CONTROL
     Control-Package: msc-ivr/1.0
     Content-Type: application/msc-ivr+xml
     Content-Length: 127

     <mscivr version="1.0" xmlns="urn:ietf:params:xml:ns:msc-ivr">
        <dialogterminate dialogid="6791fee" immediate="true"/>
     </mscivr>

E2. AS1 <- MS (CFW 403 Forbidden) 🙈

And the MS replies with a 403 Forbidden. Not me getting rejected in the group chat 💀 but the MS said no 🙅‍♀️

     CFW 7fdcc2331bef 403

F1. AS2 -> MS (CFW CONTROL, join to conference) 🧚

AS2 wants in on the conference, so it sends a join with id1 and id2 🫶 main character energy ✨

     CFW 140e0f763352 CONTROL
     Control-Package: msc-mixer/1.0
     Content-Type: application/msc-mixer+xml
     Content-Length: 117

     <mscmixer version="1.0" xmlns="urn:ietf:params:xml:ns:msc-mixer">
        <join id1="1:272e9c05" id2="74b6d62"/>
     </mscmixer>

F2. AS2 <- MS (CFW 403 Forbidden) 🌈

And the join gets a 403 Forbidden back. Iykyk, the MS just wasn't letting AS2 into the party this time 🥲

     CFW 140e0f763352 403

9. Acknowledgments 🫶

Okay bestie, huge shout-out to Dale Worley 💜 who gave the whole document a thorough review and even wrote some of the text so it's way easier to read. Iconic behaviour, literally the MVP ✨

10. References 📚

10.1. Normative References 💖

  • [RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP: Session Initiation Protocol", RFC 3261, June 2002.
  • [RFC3264] Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model with Session Description Protocol (SDP)", RFC 3264, June 2002.
  • [RFC3550] Schulzrinne, H., Casner, S., Frederick, R., and V. Jacobson, "RTP: A Transport Protocol for Real-Time Applications", STD 64, RFC 3550, July 2003.
  • [RFC4574] Levin, O. and G. Camarillo, "The Session Description Protocol (SDP) Label Attribute", RFC 4574, August 2006.
  • [RFC4145] Yon, D. and G. Camarillo, "TCP-Based Media Transport in the Session Description Protocol (SDP)", RFC 4145, September 2005.
  • [RFC4572] Lennox, J., "Connection-Oriented Media Transport over the Transport Layer Security (TLS) Protocol in the Session Description Protocol (SDP)", RFC 4572, July 2006.
  • [RFC6230] Boulton, C., Melanchuk, T., and S. McGlashan, "Media Control Channel Framework", RFC 6230, May 2011.
  • [RFC6231] McGlashan, S., Melanchuk, T., and C. Boulton, "An Interactive Voice Response (IVR) Control Package for the Media Control Channel Framework", RFC 6231, May 2011.
  • [RFC6505] McGlashan, S., Melanchuk, T., and C. Boulton, "A Mixer Control Package for the Media Control Channel Framework", RFC 6505, March 2012.
  • [RFC6917] Boulton, C., Miniero, L., and G. Munson, "Media Resource Brokering", RFC 6917, April 2013.
  • [RFC5239] Barnes, M., Boulton, C., and O. Levin, "A Framework for Centralized Conferencing", RFC 5239, June 2008.
  • [RFC4582] Camarillo, G., Ott, J., and K. Drage, "The Binary Floor Control Protocol (BFCP)", RFC 4582, November 2006.
  • [RFC4583] Camarillo, G., "Session Description Protocol (SDP) Format for Binary Floor Control Protocol (BFCP) Streams", RFC 4583, November 2006.

10.2. Informative References 🔍

  • [RFC2606] Eastlake, D. and A. Panitz, "Reserved Top Level DNS Names", BCP 32, RFC 2606, June 1999.
  • [RFC3725] Rosenberg, J., Peterson, J., Schulzrinne, H., and G. Camarillo, "Best Current Practices for Third Party Call Control (3pcc) in the Session Initiation Protocol (SIP)", BCP 85, RFC 3725, April 2004.
  • [SRGS] Hunt, A. and S. McGlashan, "Speech Recognition Grammar Specification Version 1.0", W3C Recommendation, March 2004.
  • [RFC4597] Even, R. and N. Ismail, "Conferencing Scenarios", RFC 4597, August 2006.
  • [RFC5567] Melanchuk, T., "An Architectural Framework for Media Server Control", RFC 5567, June 2009.

Authors' Addresses 💌

Okay, here are the people who made this happen, with their contact details, slay 👑

   Alessandro Amirante
   University of Napoli
   Via Claudio 21
   Napoli  80125
   Italy

   EMail: alessandro.amirante@unina.it


   Tobia Castaldi
   Meetecho
   Via Carlo Poerio 89
   Napoli  80100
   Italy

   EMail: tcastaldi@meetecho.com


   Lorenzo Miniero
   Meetecho
   Via Carlo Poerio 89
   Napoli  80100
   Italy

   EMail: lorenzo@meetecho.com


   Simon Pietro Romano
   University of Napoli
   Via Claudio 21
   Napoli  80125
   Italy

   EMail: spromano@unina.it
📦 where this page comes from