RFC 7088
Session Initiation Protocol Service Example -- Music on Hold
RFC 7088: Session Initiation Protocol Service Example -- Music on Hold π
okay bestie, this one is RFC 7088 πβ¨ It's an Informational doc (published for info, not a Standards Track spec) from February 2014 (ISSN 2070-1721), written by D. Worley from Ariadne π. The header has no Obsoletes or Updates line, so it doesn't list anything it replaces or changes.
Abstract πΈ
"Music on hold" is one of the features that business phone buyers want most πΌ When one party has a call "on hold", their phone plays an audio stream (often music) for the other person to hear. SIP's architecture makes it hard to do this in a way that's fully standards-compliant π€ The method in this doc is fully effective, standards-compliant, and has a bunch of perks over the older methods. It's less likely to cause weird UI effects and more likely to work in systems that do authentication, compared to the music-on-hold method in Section 2.3 of RFC 5359 π
Status of This Memo π
This is not an Internet Standards Track spec. It's just published for info π«Ά
This is an IETF product and it reflects 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, so check Section 2 of RFC 5741 for the details π
For the current status, any errata, and how to give feedback, go to http://www.rfc-editor.org/info/rfc7088 π¦
Copyright Notice Β©οΈ
Copyright (c) 2014 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please read these carefully, because they spell out your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they're provided without warranty as described in the Simplified BSD License π
Table of Contents ποΈ
1. Introduction ....................................................4
1.1. Requirements Language ......................................4
2. Technique .......................................................4
2.1. Placing a Call on Hold and Establishing an External
Media Stream ...............................................5
2.2. Taking a Call off Hold and Terminating the External
Media Stream ...............................................6
2.3. Example Message Flow .......................................6
2.4. Receiving Re-INVITE and UPDATE from the Remote UA .........17
2.5. Receiving INVITE with Replaces ............................17
2.6. Receiving REFER from the Remote UA ........................19
2.7. Receiving Re-INVITE and UPDATE from the
Music-on-Hold Source ......................................21
2.8. Handling Payload Type Numbers .............................22
2.8.1. Analysis ...........................................22
2.8.2. Solution to the Problem ............................23
2.8.3. Example of the Solution ............................24
2.9. Dialog/Session Timers .....................................28
2.10. When the Media Stream Directionality is "inactive" .......28
2.11. Multiple Media Streams ...................................28
3. Advantages .....................................................29
4. Caveats ........................................................30
4.1. Offering All Available Media Formats ......................30
4.2. Handling Re-INVITES in a B2BUA ............................31
5. Security Considerations ........................................31
5.1. Network Security ..........................................31
5.2. SIP (Signaling) Security ..................................32
5.3. RTP (Media) Security ......................................32
5.4. Media Filtering ...........................................32
6. Acknowledgments ................................................33
7. References .....................................................34
7.1. Normative References ......................................34
7.2. Informative References ....................................34
1. Introduction π
In systems built on SIP [RFC3261], people really want features like the ones in traditional phone systems π± One of the most requested is "music on hold": when one party has the call "on hold", their phone plays an audio stream (often music) for the other party to hear πΆ
SIP's architecture makes it hard to do music on hold in a way that's fully standards-compliant π This doc describes a method that's reasonably simple and still fully effective and standards-compliant. It has big advantages over other methods already in use, which Section 3 covers π
Every current music-on-hold method works with every other one. The two user agents in a call can use different methods and still get the same functionality as if both used the same method. So you lose nothing if different user agents in a phone system use different methods, or if one user agent switches methods between calls or even partway through a single call π§
1.1. Requirements Language π
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].
2. Technique π
The core idea is this π The executing user agent (UA) (the user's own UA) sends a re-INVITE to the remote UA (the other user's UA) to set the hold state. It leaves out the Session Description Protocol (SDP) [RFC4566] offer [RFC3264] [RFC6337], which forces the remote UA to make an SDP offer. The executing UA then takes that offer from the remote UA's 2xx response and uses it as the offer SDP in a new INVITE to the external media source. That way the media source sends its media straight to the remote UA. The media source's answer SDP goes back to the remote UA in the ACK to the re-INVITE π¦
2.1. Placing a Call on Hold and Establishing an External Media Stream βΈοΈ
- The executing user tells the executing UA to put the dialog on hold π
- The executing UA sends a re-INVITE without SDP to the remote UA. This forces the remote UA to put an SDP offer in its 2xx response. The Contact header of the re-INVITE includes the
'+sip.rendering="no"'field parameter to show that it's putting the call on hold ([RFC4235], Section 5.2) π - The remote UA sends a 2xx to the re-INVITE, and its SDP offer gives its own listening address/port. If the remote UA understands the sip.rendering feature parameter, the offer may say it won't send media by setting the media directionalities to
recvonly(the reverse of "on hold") orinactive. But the remote UA may also offer to send media π€·ββοΈ - The executing UA uses this offer to build the offer SDP of an initial INVITE that it sends to the configured music-on-hold (MOH) source. The SDP in this request is mostly copied from the SDP the remote UA returned in the previous step, especially the listening address/port and the payload type numbers. The media directionalities are restricted to
recvonlyorinactive, whichever fits. The executing UA may want or need to change theo=line. It may also need to add somea=rtpmaplines to control how RTP payload type numbers get assigned (Section 2.8) β¨ - The MOH source sends a 2xx response to the INVITE. Its SDP answer should include its media source address as its listening address/port. This SDP must necessarily set
sendonlyorinactiveas the directionality for all media streams [RFC3264] π΅
Even though this address/port shouldn't receive any RTP, the port it specifies decides the port for receiving RTP Control Protocol (RTCP) packets. By convention it also sends RTCP from that port [RFC4961] π‘
By convention, UAs use their declared RTP listening ports as their RTP source ports too [RFC4961]. The answer SDP reaches the remote UA, which tells it the address/port the MOH media will come from. That presumably stops the remote UA from ignoring the MOH media if it filters media packets by source address. This only works if the SDP answer has the sending address in the c= line, even though the MOH source doesn't receive RTP π‘οΈ
- The executing UA sends this SDP answer as its SDP answer in the ACK for the re-INVITE to the remote UA. The
o=line in the answer must be changed so it fits in the sequence ofo=lines the executing UA already made in the dialog. Any dynamic payload type number assignments made in the answer must be recorded in the state of the original dialog π§Ύ - Because of the sip.rendering feature parameter in the re-INVITE's Contact header and the media directionality in the SDP answer inside the ACK, the on-hold state of the dialog gets set up (at the executing end) π
- From here on, the MOH source makes RTP with the music-on-hold media and sends it straight to the remote UA's listening address/port. The executing UA keeps two dialogs (one with the remote UA, one with the MOH source), but it never sees or handles the MOH RTP π
2.2. Taking a Call off Hold and Terminating the External Media Stream π²
- The executing user tells the executing UA to take the dialog off hold π
- The executing UA sends a re-INVITE to the remote UA with SDP that asks to receive media. The re-INVITE's Contact header doesn't include the
'+sip.rendering="no"'field parameter. (It may have a sip.rendering field parameter set to "yes" or "unknown", or it may leave the field parameter out.) So this re-INVITE clears the on-hold state of the dialog (at the executing end) π« The version in theo=line of the offered SDP has to account for the SDP versions that came through from the MOH source. Any payload type numbers that were assigned in SDP from the MOH source must be respected too π§ - When the remote UA sends a 2xx response to the re-INVITE, the executing UA sends a BYE request in the dialog to the MOH source π
- From here on, the MOH source stops making RTP, and ordinary RTP flow comes back in the original dialog πΈ
2.3. Example Message Flow βοΈ
This section walks through a message flow for the technique. Alice calls Bob, Bob puts her on hold with music from an external source, and then he takes her off hold πΆ Bob's UA is the executing UA, and Alice's UA is the remote UA. This is just one possible flow, though. The standards allow a bunch of variations on these operations β¨
Alice establishes the call:
| | |
| INVITE F1 | |
|--------------->| |
| 180 Ringing F2 | |
|<---------------| |
| 200 OK F3 | |
|<---------------| |
| ACK F4 | |
|--------------->| |
| RTP | |
|<==============>| |
| | |
Bob places Alice on hold, compelling Alice's UA to provide SDP: π
| | |
| INVITE F5 | |
| (no SDP) | |
|<---------------| |
| 200 OK F6 | |
| (SDP offer) | |
|--------------->| |
| | |
Bob's UA initiates music on hold: π΅
| | |
| | INVITE F7 |
| | (SDP offer, |
| | rev. hold) |
| |------------->|
| | 200 OK F8 |
| | (SDP answer, |
| | hold) |
| |<-------------|
| | ACK F9 |
| |------------->|
| | |
Bob's UA provides an SDP answer containing the address/port of Music Source: π¦
| | |
| ACK F10 | |
| (SDP answer, | |
| hold) | |
|<---------------| |
| no RTP | |
|<..............>| |
| Music-on-hold RTP |
|<==============================|
| | |
The music on hold is active π
Bob takes Alice off hold: π
| | |
| INVITE F11 | |
| (SDP offer) | |
|<---------------| |
| 200 OK F12 | |
| (SDP answer) | |
|--------------->| |
| ACK F13 | |
|<---------------| |
| | BYE F14 |
| |------------->|
| | 200 F15 |
| |<-------------|
| RTP | |
|<==============>| |
| | |
And the normal media session between Alice and Bob is back on πβ¨
Here are the actual messages, one at a time π
/* Alice calls Bob. */
F1 INVITE Alice -> Bob
INVITE sips:bob@biloxi.example.com SIP/2.0
Via: SIP/2.0/TLS atlanta.example.com:5061
;branch=z9hG4bK74bf9
Max-Forwards: 70
From: Alice <sips:alice@atlanta.example.com>;tag=1234567
To: Bob <sips:bob@biloxi.example.com>
Call-ID: 12345600@atlanta.example.com
CSeq: 1 INVITE
Contact: <sips:a8342043f@atlanta.example.com;gr>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces, gruu
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=alice 2890844526 2890844526 IN IP4 atlanta.example.com
s=
c=IN IP4 atlanta.example.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
F2 180 Ringing Bob -> Alice
SIP/2.0 180 Ringing
Via: SIP/2.0/TLS atlanta.example.com:5061
;branch=z9hG4bK74bf9
;received=192.0.2.103
From: Alice <sips:alice@atlanta.example.com>;tag=1234567
To: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 1 INVITE
Contact: <sips:bob@biloxi.example.com>
Content-Length: 0
F3 200 OK Bob -> Alice
SIP/2.0 200 OK
Via: SIP/2.0/TLS atlanta.example.com:5061
;branch=z9hG4bK74bf9
;received=192.0.2.103
From: Alice <sips:alice@atlanta.example.com>;tag=1234567
To: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 1 INVITE
Contact: <sips:bob@biloxi.example.com>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=bob 2890844527 2890844527 IN IP4 biloxi.example.com
s=
c=IN IP4 biloxi.example.com
t=0 0
m=audio 3456 RTP/AVP 0
a=rtpmap:0 PCMU/8000
F4 ACK Alice -> Bob
ACK sips:bob@biloxi.example.com SIP/2.0
Via: SIP/2.0/TLS atlanta.example.com:5061
;branch=z9hG4bK74bfd
Max-Forwards: 70
From: Alice <sips:alice@atlanta.example.com>;tag=1234567
To: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 1 ACK
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces
Content-Length: 0
/* Bob places Alice on hold. */
/* The re-INVITE contains no SDP, thus compelling Alice's UA
to provide an offer. */
F5 INVITE Bob -> Alice
INVITE sips:a8342043f@atlanta.example.com;gr SIP/2.0
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bK874bk
To: Alice <sips:alice@atlanta.example.com>;tag=1234567
From: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 712 INVITE
Contact: <sips:bob@biloxi.example.com>;+sip.rendering="no"
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces
Content-Length: 0
/* Alice's UA provides an SDP offer.
Since it does not know that it is being put on hold,
the offer is the same as the original offer and describes
bidirectional media. */
F6 200 OK Alice -> Bob
SIP/2.0 200 OK
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bK874bk
;received=192.0.2.105
To: Alice <sips:alice@atlanta.example.com>;tag=1234567
From: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 712 INVITE
Contact: <sips:a8342043f@atlanta.example.com;gr>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces, gruu
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=alice 2890844526 2890844526 IN IP4 atlanta.example.com
s=
c=IN IP4 atlanta.example.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=active
/* Bob's UA initiates music on hold. */
/* This INVITE contains Alice's offer, but with the media
direction set to "reverse hold", receive-only. */
F7 INVITE Bob -> Music Source
INVITE sips:music@source.example.com SIP/2.0
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bKnashds9
Max-Forwards: 70
From: Bob <sips:bob@biloxi.example.com>;tag=02134
To: Music Source <sips:music@source.example.com>
Call-ID: 4802029847@biloxi.example.com
CSeq: 1 INVITE
Contact: <sips:bob@biloxi.example.com>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces, gruu
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=bob 2890844534 2890844534 IN IP4 atlanta.example.com
s=
c=IN IP4 atlanta.example.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=recvonly
F8 200 OK Music Source -> Bob
SIP/2.0 200 OK
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bKnashds9
;received=192.0.2.105
From: Bob <sips:bob@biloxi.example.com>;tag=02134
To: Music Source <sips:music@source.example.com>;tag=56323
Call-ID: 4802029847@biloxi.example.com
Contact: <sips:music@source.example.com>;automaton
;+sip.byeless;+sip.rendering="no"
CSeq: 1 INVITE
Content-Length: [omitted]
v=0
o=MusicSource 2890844576 2890844576 IN IP4 source.example.com
s=
c=IN IP4 source.example.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=sendonly
F9 ACK Bob -> Music Source
ACK sips:music@source.example.com SIP/2.0
Via: SIP/2.0/TLS source.example.com:5061
;branch=z9hG4bK74bT6
From: Bob <sips:bob@biloxi.example.com>;tag=02134
To: Music Source <sips:music@source.example.com>;tag=56323
Max-Forwards: 70
Call-ID: 4802029847@biloxi.example.com
CSeq: 1 ACK
Content-Length: 0
/* Bob's UA now sends the ACK that completes the re-INVITE
to Alice and completes the SDP offer/answer.
The ACK contains the SDP received from Music Source and thus
contains the address/port from which Music Source will send media,
and implies the address/port that Music
Source will use to send/receive RTCP. */
F10 ACK Bob -> Alice
ACK sips:a8342043f@atlanta.example.com;gr SIP/2.0
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bKq874b
To: Alice <sips:alice@atlanta.example.com>;tag=1234567
From: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 712 ACK
Contact: <sips:bob@biloxi.example.com>;+sip.rendering="no"
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces
Content-Length: [omitted]
v=0
o=bob 2890844527 2890844528 IN IP4 biloxi.example.com
s=
c=IN IP4 source.example.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=sendonly
/* Bob picks up the call by sending a re-INVITE to Alice. */
F11 INVITE Bob -> Alice
INVITE sips:a8342043f@atlanta.example.com;gr SIP/2.0
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bK874bk
To: Alice <sips:alice@atlanta.example.com>;tag=1234567
From: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 713 INVITE
Contact: <sips:bob@biloxi.example.com>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=bob 2890844527 2890844529 IN IP4 biloxi.example.com
s=
c=IN IP4 biloxi.example.com
t=0 0
m=audio 3456 RTP/AVP 0
a=rtpmap:0 PCMU/8000
F12 200 OK Alice -> Bob
SIP/2.0 200 OK
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bK874bk
;received=192.0.2.105
To: Alice <sips:alice@atlanta.example.com>;tag=1234567
From: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 713 INVITE
Contact: <sips:a8342043f@atlanta.example.com;gr>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces, gruu
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=alice 2890844526 2890844527 IN IP4 atlanta.example.com
s=
c=IN IP4 atlanta.example.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
F13 ACK Bob -> Alice
ACK sips:a8342043f@atlanta.example.com;gr SIP/2.0
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bKq874b
To: Alice <sips:alice@atlanta.example.com>;tag=1234567
From: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 713 ACK
Contact: <sips:bob@biloxi.example.com>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces
Content-Length: 0
And now for the last bit of the call flow, F14 BYE Bob -> Music Source π«Ά
BYE sips:music@source.example.com SIP/2.0
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bK74rf
Max-Forwards: 70
From: Bob <sips:bob@biloxi.example.com>;tag=02134
To: Music Source <sips:music@source.example.com>;tag=56323
Call-ID: 4802029847@biloxi.example.com
CSeq: 2 BYE
Contact: <sips:bob@biloxi.example.com>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces, gruu
Content-Length: [omitted]
F15 200 OK Music Source -> Bob
SIP/2.0 200 OK
Via: SIP/2.0/TLS atlanta.example.com:5061
;branch=z9hG4bK74rf
;received=192.0.2.103
From: Bob <sips:bob@biloxi.example.com>;tag=02134
To: Music Source <sips:music@source.example.com>;tag=56323
Call-ID: 4802029847@biloxi.example.com
Contact: <sips:music@source.example.com>;automaton
;+sip.byeless;+sip.rendering="no"
CSeq: 2 BYE
Content-Length: 0
/* Normal media session between Alice and Bob is resumed. */
2.4. Receiving Re-INVITE and UPDATE from the Remote UA π
Okay so, while the call is on hold, the remote UA can totally send a request to change the SDP or the feature parameters in its Contact header π. It can do this with either an INVITE or an UPDATE method, and honestly both of them hit pretty much the same way when it comes to MOH πΆ.
A super common reason for a re-INVITE is when the remote UA wants to put the dialog on hold on its end π. Because this case matters so much, an implementation must process INVITEs and UPDATEs during the on-hold state, as described below. No skipping this one, bestie π .
The executing UA handles these by echoing requests and responses π¦. An incoming request from the remote UA makes the executing UA send a similar request to the MOH source, and an incoming response from the MOH source makes the executing UA send a similar response back to the remote UA β¨. In every case, any SDP offers or answers that come in get added as bodies to the stimulated request or response going to the other UA π.
The passed-through SDP will usually need its "o=" line modified π§. The directionality attributes might need to be restricted too, by changing "active" to "recvonly" and "sendonly" to "inactive", since the executing UA will not render media from the remote UA πΈ. (If all of the passed-through directionality attributes are "inactive", the optimization described in Section 2.10 may be applied.) And when it comes to payload type numbers, the mapping has already been set up within the MOH dialog, so "a=rtpmap" lines don't need to be added π.
2.5. Receiving INVITE with Replaces π
The executing UA must be prepared to receive an INVITE request with a Replaces header that specifies the dialog with the remote UA π₯. If the executing UA wants to create this new dialog in the on-hold state, it creates a new dialog with the MOH source to get MOH π. The executing UA negotiates the SDP within the dialog created by the INVITE with Replaces. It does this by passing the offer through to the new MOH dialog (if the INVITE contains an offer), or by creating the new MOH dialog with an offerless INVITE (if the INVITE does not contain an offer) π«Ά.
Continuing the example of Section 2.3, the executing UA receives an INVITE with Replaces that contains an offer π:
Alice Bob Music Source Carol
(For example, Alice has called Carol and initiates an attended transfer by sending a REFER to Carol, causing Carol to send an INVITE with Replaces to Bob.)
Bob receives INVITE with Replaces from Carol π:
| | | |
| | | INVITE/Replaces |
| | | From: Carol |
| | | To: Bob |
| | | (SDP offer) |
| |<-------------------------------|
| | INVITE | |
| | From: Bob | |
| | To: Music Source |
| | (SDP offer, | |
| | rev. hold) | |
| |------------->| |
| | 200 OK | |
| | From: Bob | |
| | To: Music Source |
| | (SDP answer, | |
| | hold) | |
| |<-------------| |
| | ACK | |
| | From: Bob | |
| | To: Music Source |
| |------------->| |
| | | 200 OK |
| | | From: Carol |
| | | To: Bob |
| | | (SDP answer, |
| | | hold) |
| |------------------------------->|
| | | ACK |
| | | From: Carol |
| | | To: Bob |
| |<-------------------------------|
| | | Music-on-hold RTP
| | |================>|
| | | |
Bob terminates the previous dialog with Alice π:
| | | |
| BYE | | |
| From: Bob | | |
| To: Alice | | |
|<---------------| | |
| 200 OK | | |
| From: Bob | | |
| To: Alice | | |
|--------------->| | |
| | | |
Bob terminates the MOH dialog for the dialog with Alice π₯:
| | | |
| | BYE | |
| | From: Bob | |
| | To: Music Source |
| |------------->| |
| | 200 OK | |
| | From: Music Source |
| | To: Bob | |
| |<-------------| |
| | | |
The new session continues on hold, between Bob and Carol π that's the vibe!
2.6. Receiving REFER from the Remote UA π§
The executing UA must be prepared to receive a REFER request within the dialog with the remote UA π. The SDP within the dialog created by the REFER gets negotiated by sending an offerless INVITE (or offerless re-INVITE) to the MOH source to obtain an offer, and then using that offer in the INVITE to the refer target π«§.
Similar processing is used for an out-of-dialog REFER whose Target-Dialog header refers to the dialog with the remote UA π·.
Continuing the example of Section 2.3, the executing UA receives an INVITE with Replaces that contains an offer π :
Alice Bob Music Source Carol
(For example, Alice initiates an unattended transfer of the call to Carol by sending a REFER to Bob.)
Bob receives REFER from Alice π:
| | | |
| REFER | | |
| From: Bob | | |
| To: Alice | | |
| Refer-To: Carol| | |
|--------------->| | |
| | re-INVITE | |
| | From: Bob | |
| | To: Music Source |
| | (no SDP) | |
| |------------->| |
| | 200 OK | |
| | From: Bob | |
| | To: Music Source |
| | (SDP offer, | |
| | hold) | |
| |<-------------| |
| | | INVITE |
| | | From: Bob |
| | | To: Carol |
| | | (SDP offer, |
| | | hold) |
| |------------------------------->|
| | | 200 OK |
| | | From: Bob |
| | | To: Carol |
| | | (SDP answer, |
| | | rev. hold) |
| |------------------------------->|
| | ACK | |
| | From: Bob | |
| | To: Music Source |
| | (SDP answer, | |
| | rev. hold) | |
| |------------->| |
| | | ACK |
| | | From: Bob |
| | | To: Carol |
| |------------------------------->|
| | | Music-on-hold RTP
| | |================>|
| | | |
Bob terminates the previous dialog with Alice π:
| | | |
| BYE | | |
| From: Bob | | |
| To: Alice | | |
|<---------------| | |
| 200 OK | | |
| From: Bob | | |
| To: Alice | | |
|--------------->| | |
| | | |
2.7. Receiving Re-INVITE and UPDATE from the Music-on-Hold Source π΅
It is possible for the MOH source to send a re-INVITE or UPDATE request, and the executing UA can support doing that in a similar way to requests from the remote UA π€. However, if the MOH source is within the same administrative domain as the executing UA, the executing UA may have knowledge that the MOH source will not (or need not) make such requests. So it can respond to any such request with a failure response, which avoids having to pass the request through π ββοΈ. The 403 (Forbidden) response is suitable for this purpose, because [RFC3261] specifies that this response indicates "the request SHOULD NOT be repeated" π«.
Heads up: in an environment where Interactive Connectivity Establishment (ICE) [RFC5245] is supported, the MOH source may need to send requests as part of ICE negotiation with the remote UA. So in environments that support ICE, the executing UA must be able to pass through requests from the MOH source as well as requests from the remote UA π§ββοΈ.
Again, as SDP is passed through, its "o=" line will need to be modified. In some cases, the directionality attributes will need to be restricted πΈ.
2.8. Handling Payload Type Numbers β¨
2.8.1. Analysis
okay so in this technique the MOH source makes an SDP answer π, and the executing UA hands that answer to the remote UA as an answer inside the original dialog β¨. in basic functionality this is no problem at all, bc [RFC3264], Section 6.1 (right at the very end) says the payload type numbers used in either direction of RTP are the ones from the SDP sent by the recipient of that RTP π . so the MOH source sends RTP to the remote UA using the payload type numbers from the offer SDP it got (ultimately) from the remote UA π¦
but strict compliance with [RFC3264], Section 8.3.2 is a whole different vibe π. it says payload type numbers used in SDP may only duplicate the payload type numbers from any previous SDP sent in the same direction if those numbers still represent the same media format (codec) they did before. the problem is the MOH source has zero knowledge of which payload type numbers were used in the original dialog, so it may accidentally give a different media format to a number that was already used (in its answer, or in a later INVITE or UPDATE it generates) π. this wouldn't break media decoding, bc it can't send any format that wasn't in the remote UA's offer, BUT it would still violate [RFC3264] π
strictly speaking you can't avoid this, bc the generator of a first answer in its dialog can pick payload numbers totally independently of the ones in the offer, and the MOH server thinks its answer is first in the dialog πΈ. so the only absolute fix is for the executing UA to rewrite the SDP passing through it to reassign payload type numbers, which would also mean rewriting the payload type numbers in the RTP packets too. a very undesirable solution π¬
the difficulty of solving this (and similar problems elsewhere) is kinda the argument that strict adherence shouldn't be required for the rule that payload type numbers not be reused for different codecs π§
if an implementation of this technique interacts with a remote UA that requires strict compliance to [RFC3264], that remote UA might reject the SDP the MOH server provided (that SDP is in message F10 in Section 2.3 π). as a result, the MOH session won't get established and the call stays in its initial state π implementors who want to dodge this situation need to implement the solution in Section 2.8.2 π
2.8.2. Solution to the Problem
we can build a technique that strictly follows the payload type rule by exploiting a SHOULD-level requirement in [RFC3264], Section 6.1 π¦: "In the case of RTP, if a particular codec was referenced with a specific payload type number in the offer, that same payload type number SHOULD be used for that codec in the answer". or rather, we exploit the "implied requirement" that if a specific payload number in the offer is used for a particular codec, then the answer should not use that payload number for a different codec π«Ά. if the MOH source obeys this restriction, the executing UA can modify the offer SDP to "reserve" every payload type number the executing UA has ever offered, so the MOH source can't use them for different media formats π
When the executing UA is composing the INVITE to the MOH source, it compiles a list of all the (dynamically assigned) payload type numbers and associated media formats that have been used by it (or by MOH sources on its behalf) in the original dialog. (The executing UA must maintain a list of all previously used payload type numbers anyway, in order to comply with [RFC3264].)
Any payload type number that's in the offer but was previously used by the executing UA in the original dialog for a different media format gets rewritten to describe a dummy media format. (One dummy media format name can be used for many payload type numbers, since multiple payload type numbers can refer to the same media format.) A payload type number is added to describe the deleted media format, and that number is either previously unused or previously used by the executing UA for that media format.
Any further payload type numbers that have been used by the executing UA in the original dialog but aren't mapped to a media format in the current offer then get mapped to a dummy media format.
The result is that the modified offer SDP:
- offers the same set of media formats (ignoring dummies) as the original offer SDP (though possibly with different payload type numbers),
- associates every payload type number either with a dummy media format or with the media format that the executing UA has previously used it for, and
- provides a (real or dummy) media format for every payload type number that the executing UA has previously used.
These properties are sufficient to force an MOH server that obeys the implied requirement to generate an answer that is a correct answer to the original offer and is also compatible with previous SDP from the executing UA β¨
Note that any re-INVITEs from the remote UA that the executing UA passes through to the MOH server need similar modification π. payload type numbers the MOH server received in past offers aren't absolutely reserved against its use (they weren't sent in SDP by the MOH server), and there's no SHOULD-level proscription against using them in the current answer (they don't appear in the current offer).
This should provide an adequate solution to the problems with payload type numbers, as it will fail only if (1) the remote UA is particular that other UAs follow the rule about not redefining payload type numbers, and (2) the MOH server does not follow the implied requirement of [RFC3264], Section 6.1 π₯Ί
2.8.3. Example of the Solution
let's see how this process works by modifying the example of Section 2.3 with this specific assignment of supported codecs π
Alice supports formats X and Y.
Bob supports formats X and Z.
Music Source supports formats Y and Z.
in this case, the SDP exchanges are:
F1 offers X and Y, F3 answers X and Z. (Only X can be used.)
F6 offers X and Y, but F7 offers X, Y, and a place-holder to block
use of type 92.
F8/F10 answers Y.
the messages that are changed from Section 2.3 are:
F1 INVITE Alice -> Bob
INVITE sips:bob@biloxi.example.com SIP/2.0
Via: SIP/2.0/TLS atlanta.example.com:5061
;branch=z9hG4bK74bf9
Max-Forwards: 70
From: Alice <sips:alice@atlanta.example.com>;tag=1234567
To: Bob <sips:bob@biloxi.example.com>
Call-ID: 12345600@atlanta.example.com
CSeq: 1 INVITE
Contact: <sips:a8342043f@atlanta.example.com;gr>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces, gruu
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=alice 2890844526 2890844526 IN IP4 atlanta.example.com
s=
c=IN IP4 atlanta.example.com
t=0 0
m=audio 49170 RTP/AVP 90 91
a=rtpmap:90 X/8000
a=rtpmap:91 Y/8000
F3 200 OK Bob -> Alice
SIP/2.0 200 OK
Via: SIP/2.0/TLS atlanta.example.com:5061
;branch=z9hG4bK74bf9
;received=192.0.2.103
From: Alice <sips:alice@atlanta.example.com>;tag=1234567
To: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 1 INVITE
Contact: <sips:bob@biloxi.example.com>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=bob 2890844527 2890844527 IN IP4 biloxi.example.com
s=
c=IN IP4 biloxi.example.com
t=0 0
m=audio 3456 RTP/AVP 90 92
a=rtpmap:90 X/8000
a=rtpmap:92 Z/8000
F6 200 OK Alice -> Bob
SIP/2.0 200 OK
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bK874bk
;received=192.0.2.105
To: Alice <sips:alice@atlanta.example.com>;tag=1234567
From: Bob <sips:bob@biloxi.example.com>;tag=23431
Call-ID: 12345600@atlanta.example.com
CSeq: 712 INVITE
Contact: <sips:a8342043f@atlanta.example.com;gr>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces, gruu
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=alice 2890844526 2890844526 IN IP4 atlanta.example.com
s=
c=IN IP4 atlanta.example.com
t=0 0
m=audio 49170 RTP/AVP 90 91
a=rtpmap:90 X/8000
a=rtpmap:91 Y/8000
a=active
F7 INVITE Bob -> Music Source
INVITE sips:music@source.example.com SIP/2.0
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bKnashds9
Max-Forwards: 70
From: Bob <sips:bob@biloxi.example.com>;tag=02134
To: Music Source <sips:music@source.example.com>
Call-ID: 4802029847@biloxi.example.com
CSeq: 1 INVITE
Contact: <sips:bob@biloxi.example.com>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY
Supported: replaces, gruu
Content-Type: application/sdp
Content-Length: [omitted]
v=0
o=bob 2890844534 2890844534 IN IP4 atlanta.example.com
s=
c=IN IP4 atlanta.example.com
t=0 0
m=audio 49170 RTP/AVP 90 91 92
a=rtpmap:90 X/8000
a=rtpmap:91 Y/8000
a=rtpmap:92 x-reserved/8000
a=recvonly
F8 200 OK Music Source -> Bob
SIP/2.0 200 OK
Via: SIP/2.0/TLS biloxi.example.com:5061
;branch=z9hG4bKnashds9
;received=192.0.2.105
From: Bob <sips:bob@biloxi.example.com>;tag=02134
To: Music Source <sips:music@source.example.com>;tag=56323
Call-ID: 4802029847@biloxi.example.com
Contact: <sips:music@source.example.com>;automaton
;+sip.byeless;+sip.rendering="no"
CSeq: 1 INVITE
Content-Length: [omitted]
v=0
o=MusicSource 2890844576 2890844576 IN IP4 source.example.com
s=
c=IN IP4 source.example.com
t=0 0
m=audio 49170 RTP/AVP 91
a=rtpmap:91 Y/8000
a=sendonly
2.9. Dialog/Session Timers
the executing UA may discover that either the remote UA or the MOH source wants to use dialog/session liveness timers [RFC4028] β°. since the timers verify the liveness of dialogs, not sessions (despite the terminology of [RFC4028]), the executing UA can support the timers on each dialog (to the remote UA and to the MOH source) independently π¦. (if the executing UA becomes obliged to initiate a refresh transaction, it must send an offerless UPDATE or re-INVITE, bc if it sends an offer, the remote element gets the chance to give an answer that's different from its previous SDP, and that could not easily be conveyed to the other remote element π)
2.10. When the Media Stream Directionality is "inactive"
the directionality of the media stream in the SDP offer in an INVITE or re-INVITE to the music source can be "inactive" if the SDP offer from the remote UA was "sendonly" or "inactive" πΈ. generally this happens when the remote UA also put the call on hold and gave a directionality of "sendonly". in this situation the executing UA can skip establishing the dialog with the music source (or can terminate the existing dialog with the music source) π€
if the executing UA uses this optimization, it creates the SDP answer itself, with directionality "inactive" and using its own RTP/RTCP ports, and sends that answer back to the remote UA π
the executing UA must be prepared for the remote UA to send a re-INVITE with directionality "active" or "recvonly". in that case the executing UA must initiate a dialog with the music source, as described above π«Ά
2.11. Multiple Media Streams π
okay so there can be multiple media streams (multiple "m=" lines) in any of the SDPs involved in the dialogs π§ as the SDPs get manipulated, each media description (each starting with an "m=" line) gets handled the way we just went over for a single media stream, mostly independently of the other media streams. but there are some extra moves the executing UA can make to get specific effects β¨
if the executing UA only wants certain media types to be treated as on-hold media, it can pass the offer SDP through and reject any particular media streams by setting the port number in the "m=" line to zero [RFC3264]. this makes sure the answer SDP has a rejection for that "m=" line too π
if the executing UA wants to provide its own on-hold media for a particular "m=" line, it can do that by providing the answer information for that "m=" line. it might decide to do this when the offer SDP comes in (by changing the "m=" line to rejected state when it sends it to the music source), or after it gets the answer from the music source and sees that the "m=" line was rejected πΆ
the executing UA may not want to pass a rejected "m=" line from the music source along to the remote UA (when the remote UA gave a non-rejected "m=" line). instead, it may give an answer with directionality "inactive" (and specify its own RTP/RTCP ports) π¦
3. Advantages π
this technique for providing music on hold has advantages over other methods now in use, including:
- bestie, the original dialog is not transferred to another UA, so the "remote endpoint URI" shown by the remote endpoint's user interface and dialog event package [RFC4235] does not change during the call. this is unlike the method in [RFC5359], Section 2.3. this URI is usually shown to the user as the name and number of the other party on the call, so it's really desirable for it not to switch over to the MOH server π
- compared to [RFC5359], this method does not require use of an out-of-dialog REFER, which isn't used much in SIP otherwise. out-of-dialog REFERs may not be routed correctly, since neither the From nor Contact URI of the original dialog may route correctly to the remote UA. also, out-of-dialog requests to UA URIs may not be handled correctly by authorization mechanisms π
- the music-on-hold media goes directly from the music-on-hold source to the remote UA, rather than being relayed through the executing UA. this reduces the computational load on the executing UA and can reduce the load on the network (by eliminating "hairpinning" of the media through the link serving the executing UA) π§
- the remote UA sees, in the incoming SDP, the address/port that the MOH source will send MOH media from (assuming the MOH source follows the convention of sending its media from its advertised media-listening address/port). so the remote UA will render the MOH media even if it's filtering incoming media based on originating address as a media security measure π
- the technique requires relatively simple manipulation of SDP. in particular, (1) it does not require a SIP element to modify unrelated SDP to be acceptable to be sent within an already established sequence of SDP (a problem with [SIP-SERV-EX], Section 2.3), and (2) it does not require converting an SDP answer into an SDP offer (which was a problem with the initial draft version of this document, as well as with [SIP-SERV-EX]) β¨
4. Caveats π§
4.1. Offering All Available Media Formats π
unnecessary failures can happen if SDP offerers don't always offer all the media formats they support. doing so is considered best practice ([RFC6337], Sections 5.1 and 5.3), but some SIP elements offer only formats that have already been in use in the dialog.
an example of how omitting media formats in an offer can lead to failure goes like this. suppose the UAs in Section 2.3 each support the following media formats:
Alice supports formats X and Y.
Bob supports formats X and Z.
Music Source supports formats Y and Z.
in this case, the SDP exchanges are:
- Alice calls Bob:
- Alice offers X and Y (message F1).
- Bob answers X (F3).
- Bob puts Alice on hold:
- Alice (via Bob) offers X and Y (F6 and F7).
- Music Source (via Bob) answers Y (F8 and F10).
- Bob takes Alice off hold:
- Bob offers X and Z (F11).
- Alice answers X (F12).
note that in exchange 2, if Alice assumes that because only format X is currently in use she should offer only X, the exchange fails. in exchange 3, Bob offers formats X and Z, even though neither is in use at the time (because Bob is not involved in the media streams).
4.2. Handling Re-INVITES in a B2BUA π
lots of UAs provide MOH in the interval while they're processing a blind transfer, between receiving the REFER and receiving the final response to the stimulated INVITE. this process involves switching the user's interface between three media sources: (1) the session of the original dialog, (2) the session with the MOH server, and (3) the session of the new dialog. it also involves a number of race conditions that must be handled correctly. if the UA is a back-to-back user agent (B2BUA) whose "other side" is maintaining a single dialog with another UA, each switching of media sources potentially causes a re-INVITE transaction within the other-side dialog. since re-INVITEs take time and must be sequenced correctly ([RFC3261], Section 14), such a B2BUA must allow the events on each side to be non-synchronous and must coordinate them correctly. failing to do so will lead to "glare" errors (491 or 500), leaving the other-side UA not rendering the correct session π¬
5. Security Considerations π‘οΈ
this part is seriously important, so read it carefully. these are the security notes for everything above.
5.1. Network Security π
some mechanism outside the scope of this document must inform the executing UA of the MOH server that it should use. care must be exercised in selecting the MOH server, because signaling information that is part of the original dialog will be transmitted along the path from the executing UA to the server. if the path between the executing UA and the server is not entirely contained within every network domain that contains the executing UA, the signaling between the UA and the server may be protected by different network security than is applied to the original dialog.
care must also be exercised because media information that is part of the original dialog will be transmitted along the path between the remote UA and the server. if the path between the remote UA and the server does not pass through the same network domains as the path between the remote UA and the executing UA, the media between the UA and the server may be protected by different network security than is applied to the original dialog.
these requirements may be satisfied by selecting an MOH server that is in the same administrative and network domain as the executing UA and whose path to all external addresses is the same as the UA's path to those addresses.
5.2. SIP (Signaling) Security π
the executing UA and the MOH server will usually be within the same administrative domain, and the SIP signaling path between them will lie entirely within that domain. in this case, the administrator of the domain should configure the UA and server to apply to the dialog between them a level of security that is appropriate for the administrative domain.
if the executing UA and the MOH server are not within the same administrative domain, the SIP signaling between them should be at least as secure as the SIP signaling between the executing UA and the remote UA. thus, the MOH server should support all of the SIP security facilities that are supported by the executing UA, and the executing UA should use in its dialog with the MOH server all SIP security facilities that are used in its dialog with the remote UA.
5.3. RTP (Media) Security π§
the RTP for the MOH media will pass directly between the MOH server and the remote UA, and thus may pass outside the administrative domain of the executing UA. while it is uncommon for the contents of the MOH media to be sensitive (and the remote UA will not usually be generating RTP when it is on hold), the MOH RTP should be at least as secure as the RTP between the executing UA and the remote UA. in order to make this possible, the MOH server should support all of the RTP security facilities that are supported by the executing UA.
it is possible that the remote UA and the MOH server support an RTP security facility that the executing UA does not support, and that it is desirable to use this facility for the MOH RTP. to enable doing so, the executing UA should pass the SDP between the remote UA and the MOH server completely, not omitting elements that it does not understand.
5.4. Media Filtering π΅οΈ
some UAs filter incoming RTP based on the address of origin as a media security measure, refusing to render the contents of RTP packets that originate from an address that is not shown in the remote SDP as an RTP destination address. the remote UA in the original dialog may use this form of media filtering, and if the executing UA does not update the SDP to inform the remote UA of the source address of the MOH media, the remote UA may not render the MOH media. note that the executing UA has no means for detecting that the remote UA uses media filtering, so the executing UA must assume that any remote UA uses media filtering.
the technique described in this document ensures that any UA that should render MOH media will be informed of the source address of the media via the SDP that it receives. this allows such UAs to filter media without interfering with MOH operation π
6. Acknowledgments β¨
okay so this is the thank-you section π«Ά and it's giving "the whole crew showed up." The first version came from Section 2.3 of [SIP-SERV-EX] plus the similar MOH setup in the snom UA π. Venkatesh [VENKATESH] then suggested big upgrades to the sequence of operations, which let the SDP handling get way better π₯.
John Elwell [ELWELL] was the MVP here π. He pointed out that the executing UA has to pass through re-INVITEs/UPDATEs so ICE negotiation can happen, suggested mentioning the role of RTCP listening ports π¦, and floated leaving out the dialog to the music source when the directionality would be "inactive". He also noticed that with multiple media streams, the executing UA may want to pick which streams get MOH π.
Paul Kyzivat [KYZIVAT-1] [KYZIVAT-2] flagged the headaches around reusing payload type numbers and the ideas for dodging them, which is how Section 2.8 came to be π§. Paul also suggested adding Section 4.1 to show why offerers should always include all supported formats π .
M. Ranganathan pointed out the struggles a B2BUA has (Section 4.2) because of all the changes of media source πΈ. Section 4.1 got a big glow-up after Attila Sipos [SIPOS] shared advice π.
Rifaat Shekh-Yusef [SHEKH-YUSEF] is the reason we talk about dialog/session timers in Section 2.9 β.
Robert Sparks clarified what the "Best Current Practice" status is actually for, so this document got switched to "Informational" π.
In his SecDir review, Stephen Kent pointed out that the Security Considerations should cover how the MOH server uses SIP and SDP security features π₯π.
And honestly, tons of the text got better thanks to reviewers, including Rifaat Shekh-Yusef and Richard Barnes π«Άβ¨. Thank you all, periodt π π.
7. References π
7.1. Normative References
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
- [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.
- [RFC4028] Donovan, S. and J. Rosenberg, "Session Timers in the Session Initiation Protocol (SIP)", RFC 4028, April 2005.
- [RFC4566] Handley, M., Jacobson, V., and C. Perkins, "SDP: Session Description Protocol", RFC 4566, July 2006.
7.2. Informative References
- [RFC4235] Rosenberg, J., Schulzrinne, H., and R. Mahy, "An INVITE-Initiated Dialog Event Package for the Session Initiation Protocol (SIP)", RFC 4235, November 2005.
- [RFC4961] Wing, D., "Symmetric RTP / RTP Control Protocol (RTCP)", BCP 131, RFC 4961, July 2007.
- [RFC5245] Rosenberg, J., "Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols", RFC 5245, April 2010.
- [RFC5359] Johnston, A., Sparks, R., Cunningham, C., Donovan, S., and K. Summers, "Session Initiation Protocol Service Examples", BCP 144, RFC 5359, October 2008.
- [RFC6337] Okumura, S., Sawada, T., and P. Kyzivat, "Session Initiation Protocol (SIP) Usage of the Offer/Answer Model", RFC 6337, August 2011.
- [ELWELL] Elwell, J., "Subject: [Sipping] RE: I-D Action:draft-worley-service-example-00.txt", message to the IETF Sipping mailing list, November 2007, <http://www1.ietf.org/mail-archive/web/sipping/current/msg14678.html>.
- [KYZIVAT-1] Kyzivat, P., "Subject: Re: [Sipping] I-D ACTION:draft-ietf-sipping-service-examples-11.txt", message to the IETF Sipping mailing list, October 2006, <http://www1.ietf.org/mail-archive/web/sipping/current/msg12181.html>.
- [KYZIVAT-2] Kyzivat, P., "Subject: [Sip-implementors] draft-worley-service-example-02", message to the sip-implementors mailing list, September 2008, <http://lists.cs.columbia.edu/pipermail/sip-implementors/2008-September/020394.html>.
- [SHEKH-YUSEF] Shekh-Yusef, R., "Subject: [sipcore] draft-worley-service-example-03", message to the IETF Sipcore mailing list, July 2009, <http://www.ietf.org/mail-archive/web/sipcore/current/msg00580.html>.
- [SIPOS] Sipos, A., "Subject: [Sip-implementors] draft-worley-service-example-02", message to the sip-implementors mailing list, March 2009, <http://lists.cs.columbia.edu/pipermail/sip-implementors/2009-March/021970.html>.
- [SIP-SERV-EX] Johnston, A., Sparks, R., Cunningham, C., Donovan, S., and K. Summers, "Session Initiation Protocol Service Examples", Work in Progress, October 2006.
- [VENKATESH] Venkatesh, "Subject: Re: [Sipping] I-D ACTION:draft-ietf-sipping-service-examples-11.txt", message to the IETF Sipping mailing list, October 2006, <http://www1.ietf.org/mail-archive/web/sipping/current/msg12180.html>.
Author's Address π
Dale R. Worley
Ariadne Internet Services, Inc.
738 Main St.
Waltham, MA 02451
US
Phone: +1 781 647 9199
EMail: worley@ariadne.com
That's the whole doc, bestie! ππ¦π Hit me up if you wanna go over any of the MOH stuff, I'm obsessed with it π§β¨
π¦ where this page comes from
- ietf: rfc7088 2014-02
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms