This repository has been archived by the owner on May 6, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
xep-0327.xml
4420 lines (4055 loc) · 197 KB
/
xep-0327.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Rayo</title>
<abstract>This specification defines an XMPP protocol extension for the third-party control of telephone calls and other similar media sessions. The protocol includes support for session management/signaling, as well as advanced media resources such as speech recognizers, speech synthesizers and audio/video recorders. The protocol serves a different purpose from that of first-party protocols such as Jingle or SIP, and is compatible with those protocols.</abstract>
&LEGALNOTICE;
<number>0327</number>
<status>Experimental</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
<author>
<firstname>Ben</firstname>
<surname>Langfeld</surname>
<email>ben@langfeld.me</email>
<jid>ben@langfeld.me</jid>
<uri>http://langfeld.me</uri>
</author>
<author>
<firstname>Jose</firstname>
<surname>de Castro</surname>
<email>jdecastro@tropo.com</email>
<jid>jdecastro@tropo.com</jid>
<uri>http://tropo.com</uri>
</author>
<revision>
<version>0.4</version>
<date>2014-03-13</date>
<initials>bl</initials>
<remark><p>Suggest timestamping Rayo events; allow specifying a call URI when dialing.</p></remark>
</revision>
<revision>
<version>0.3</version>
<date>2014-01-30</date>
<initials>bl</initials>
<remark><p>Further updates.</p></remark>
</revision>
<revision>
<version>0.2</version>
<date>2013-06-10</date>
<initials>bl</initials>
<remark><p>Updates to address open issues.</p></remark>
</revision>
<revision>
<version>0.1</version>
<date>2013-05-06</date>
<initials>psa</initials>
<remark><p>Initial published version approved by the XMPP Council.</p></remark>
</revision>
<revision>
<version>0.0.1</version>
<date>2013-04-05</date>
<initials>bl</initials>
<remark><p>First draft.</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>Rayo is a protocol to allow third-party remote control over media sessions, audio/video mixers and a variety of advanced media resources such as speech recognizers, speech synthesizers and audio/video recorders. These capabilities can be combined to create a wide variety of applications such as menu-based phone systems, in-game conferencing and anonymous dating services. Unlike <a href='xep-0166.html'>Jingle</a> or even <a href='http://en.wikipedia.org/wiki/Session_Initiation_Protocol'>SIP</a>, a Rayo client is not concerned with being a party to either the session negotiation or the media stream itself.</p>
<ul>
<li>A Rayo server takes on the role of negotiating a media session between itself and some other endpoint, or between two external endpoints, by way of an implementation-specific means, be that Jingle, SIP, the public-switched telephone network, or anything else. The server may even bridge multiple networks.</li>
<li>The server then presents the Rayo protocol as an interface to a Rayo client, allowing it to monitor and/or exercise third-party control over the established media sessions.</li>
<li>The client has the option to accept/reject/answer inbound session requests, request the creation of outbound sessions and monitor their progress, execute media operations such as speech synthesis, speech recognition & recording, and to end sessions.</li>
</ul>
<p>The relationship between the calling parties, the Rayo server and the Rayo client looks something like this:</p>
<code>
[caller] ----e.g. SIP---- [rayo server] ( -----e.g. Jingle---- [callee] ) optional
|
|
rayo client
</code>
<p>This document defines the core Rayo protocol, and contains provisions for its extension by further specifications.</p>
</section1>
<section1 topic='How it works' anchor='howitworks'>
<p>In order to understand the nature of a Rayo interaction, here we show a simple example of a control session.</p>
<example caption="New call announces itself to a potential controlling party"><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:call:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
<offer xmlns='urn:xmpp:rayo:1'
to='tel:+18003211212'
from='tel:+13058881212'/>
</presence>
]]></example>
<p>In this example, a call from 'tel:+13058881212' has reached the Rayo server 'shakespeare.lit' by calling 'tel:+18003211212', and been assigned an ID '9f00061'. The server has determined that 'juliet@capulet.lit' is a valid candidate to be the client to whom the server delegates control of the call, and so has directed an <a href='def-offer'>offer event</a> to her 'balcony' resource.</p>
<p>The client, 'juliet@capulet.lit', then decides that it is able to handle the incoming call, and so accepts it from the server, thus gaining exclusive control and indicating to the calling party that the call will be processed and that it should ring.</p>
<example caption="Potential controlling party attempts to become definitive controlling party by sending the call an accept command"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='hd721'>
<accept xmlns='urn:xmpp:rayo:1'/>
</iq>
]]></example>
<example caption="Call acknowledges accept command to the (now) definitive controlling party"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='hd721'/>
]]></example>
<p>Following confirmation from the server that the attempt to gain control of the call was successful, the client proceeds to answer the call, opening up the media stream between the caller and the server.</p>
<example caption="Controlling party answers the call"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='43jo3'>
<answer xmlns='urn:xmpp:rayo:1'/>
</iq>
]]></example>
<example caption="Call acknowledges answer command to controlling party"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='43jo3'/>
]]></example>
<p>Once the client has confirmation that the call has been answered, it triggers the start of a media output component in order to play a message to the caller using a Text-to-speech (TTS) engine.</p>
<example caption="Controlling party requests a new output component"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='j9d3j'>
<output xmlns='urn:xmpp:rayo:output:1'
voice='allison'>
<document content-type="text/plain">
<![CDATA[
You have no new messages. Goodbye!
]]]]><![CDATA[>
</document>
</output>
</iq>
]]></example>
<example caption="Call acknowledges request for new output component and provides its ID"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='j9d3j'>
<ref xmlns='urn:xmpp:rayo:1' uri='xmpp:9f00061@call.shakespeare.lit/fgh4590'/>
</iq>
]]></example>
<p>After confirmation that the output component was successfully created, the client then awaits notification of its completion.</p>
<example caption="Output component announces its completion, giving the reason"><![CDATA[
<presence from='9f00061@call.shakespeare.lit/fgh4590'
to='juliet@capulet.lit/balcony'
type='unavailable'>
<complete xmlns='urn:xmpp:rayo:ext:1'>
<finish xmlns='urn:xmpp:rayo:output:complete:1' />
</complete>
</presence>
]]></example>
<p>The client then decides it has no further operations to perform on the call, and that the call should end. It instructs the server to hang up the call gracefully.</p>
<example caption="Controlling party hangs up the call"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='f3wh8'>
<hangup xmlns='urn:xmpp:rayo:1'/>
</iq>
]]></example>
<example caption="Call acknowledges hangup command to controlling party"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='f3wh8'/>
]]></example>
<example caption="Controlling party receives notification of the call being terminated"><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='unavailable'>
<end xmlns='urn:xmpp:rayo:1'>
<hangup-command/>
</end>
</presence>
]]></example>
</section1>
<section1 topic='Requirements' anchor='reqs'>
<p>The protocol defined herein is designed to provide the following features:</p>
<ol>
<li><strong>Call Control:</strong> Incoming calls are "offered" to clients at which point they can be answered, rejected, redirected to another destination, etc. Outbound calls may also be made and monitored. Every attempt is made to be shield the Rayo client from the low level telephony protocol (e.g. SIP, Jingle, PSTN, etc).</li>
<li><strong>Audio File Playback:</strong> A compatible Rayo server will fetch a file from a a specified URL and play the containing audio to the caller.</li>
<li><strong>Speech Synthesis / TTS:</strong> In cases where dynamic data must be spoken, a Speech Synthesis engine may be used to play computer generated speech to the caller.</li>
<li><strong>Touch-tone Events / DTMF:</strong> Rayo surfaces real-time event when the caller presses keys on their touch-tone keypad.</li>
<li><strong>Speech Recognition:</strong> Enables the phone application to take spoken queues allowing for sophisticated voice-driven menus and directory services.</li>
<li><strong>Call Recording:</strong> Can be used to capture the caller's voice (e.g. Voicemail) or both sides of the call for auditing and compliance purposes.</li>
<li><strong>Mixing:</strong> Typically referred to as an audio "conference"; calls can be joined together so that the participants can hear each other in real-time.</li>
</ol>
<p>Many third-party call control protocols have preceeded Rayo (see Asterisk's AGI/AMI, FreeSWITCH's eventsocket, Microsoft's TAPI, Java's JTAPI, Novell/AT&T's TSAPI, CSTA, etc). None of these protocols is ideal, and all have one or more of the following drawbacks:</p>
<ul>
<li><strong>Totally ground-up wire protocol</strong> requiring implementation all the way down to the socket.</li>
<li><strong>Platform/vendor/hardware specific</strong> - each system implements its own proprietary protocol (in many cases, without a formal published specification) which does not allow easily porting an application from one back-end to another.</li>
<li><strong>Synchronous interface</strong> - Operations on calls or other entities are often blocking, and one must serialise all control messages.</li>
<li><strong>Inconsistent</strong> - evolved, rather than designed.</li>
<li><strong>Lacking in scalability</strong> - client/server sometimes tied one-to-one, servers rarely clustered, advanced message routing not possible.</li>
<li><strong>Poor security</strong> - lack of wire-level encryption, lack of or sub-standard authentication mechanisms, lack of or limited authorization mechanisms, lack of or poor sandboxing between multiple tenants on one system.</li>
<li><strong>Inextensible</strong> - The specification of extensions to the core protocol is either impossible or very difficult.</li>
</ul>
<p>Rayo has been designed with these failings in mind, and intends to address many concerns not addressed by these earlier attempts. The following considerations were made:</p>
<ul>
<li><strong>Simple client library implementation</strong> - XMPP client libraries exist in all modern languages, and many are of a high standard of quality and maturity.</li>
<li><strong>Cross-platform standard</strong> - The protocol must not expose any platform specifics and all elements should be candidates for implementation on any suitable platform. Addiditionally, the protocol must be ratified as a standard following a community discussion.</li>
<li><strong>Asynchronous interface</strong> - The protocol should present an asynchronous interface for the purposes of performance and flexibility in performing parallel operations.</li>
<li><strong>Consistent</strong> - The protocol must provide a considered, unobtrusive, logically and philisophically consistent interface.</li>
<li><strong>Federated</strong> - The protocol must support communication between client and server entities on separately owned, operated and addressed networks.</li>
<li><strong>Flexible routing</strong> - The protocol must lend itself to routing across wide networks such as the internet, and to potential complex routing such as proxying or redirection. Additionally, the client and server should each be aware of the presence of the other and be able to use such information to make routing decisions.</li>
<li><strong>Extensible</strong> - The protocol must provide for the possibility of extra functionality being added by future specifications or an individual implementation.</li>
<li><strong>Secure</strong> - The protocol should include appropriate measures for authentication and authorization of participants, as well as preventing third-parties from intercepting control messages.</li>
</ul>
<p>Many of the features in the above list are available to Rayo at no specification or implementation cost, since they are core to XMPP itself and thus Rayo inherits these 'for free'.</p>
<p>Additionally, the protocol is required to abstract away the complexity of the back-end negotiation, especially the details of the transport protocols such as SIP or Jingle, but to map conceptually to such protocols.</p>
</section1>
<section1 topic='Terminology' anchor='terms'>
<section2 topic='Glossary' anchor='terms-glossary'>
<dl>
<di>
<dt>Third-party call control (3PCC)</dt>
<dd>The observation and/or control of a live media session by an entity which is not a direct party to the session.</dd>
</di>
<di>
<dt>Command</dt>
<dd>Commands instruct the receiving entity to perform some atomic action. Commands may be executed against a given call, component or mixer and can be considered completed as soon as they receive a response. Some commands create components, and return a reference to the component in their response.</dd>
</di>
<di>
<dt>Component</dt>
<dd>Components extend the Rayo protocol by providing additional media and call control functionality. Components are created by an appropriate command, which returns a reference to the component. Components are executed asynchronously, and have a lifecycle attached to them, with the ability to trigger events or have commands issued to it. Once a component is stopped or comes to an end naturally, it will issue a special <complete/> event, indicating that it has ceased executing and deliver any required data.</dd>
</di>
<di>
<dt>Potential controlling party (PCP)</dt>
<dd>An XMPP entity to which an offer to control an incoming call may be sent.</dd>
</di>
<di>
<dt>Definitive controlling party (DCP)</dt>
<dd>The XMPP entity which gains a lock on control of a session, either by requesting the session's creation, or being the first respondent to an offer.</dd>
</di>
<di>
<dt>Security Zone</dt>
<dd>A security zone is the conceptual border around a call which defines which parties may interact with the call's media or signaling. A security zone MUST contain the rayo server's internal implementation, the media server to which the call is joined, the DCP, and any JID whose bare form is the same as the DCP. A server MAY relax this definition further, for example to consider all JIDs at the same domain to be in the same security zone.</dd>
</di>
</dl>
</section2>
<section2 topic='Conventions' anchor='terms-conventions'>
In examples, the following JIDs are used:
<ul>
<li><strong>juliet@capulet.lit/balcony, romeo@montague.lit/orchard</strong> - Potential controlling parties</li>
<li><strong>shakespeare.lit</strong> - The root domain of the Rayo service</li>
</ul>
</section2>
</section1>
<section1 topic='Concepts and Approach' anchor='concepts'>
<p>A complete Rayo deployment has several elements and interacting entities which must be understood.</p>
<section2 topic='Actors' anchor='concepts-actors'>
<section3 topic='Server' anchor='concepts-actors-server'>
<p>A Rayo server is an entity which is capable of receiving and initiating calls and being party to their media stream, while exposing a Rayo interface to a client in order to permit control over its calls. The Rayo server may handle calls in any way supported by the implementation, such as SIP, Jingle, etc, and should expose a full XMPP domain at the root level of the service deployment (eg shakespeare.lit).</p>
<p>The Rayo server is responsible for keeping track of valid clients, routing calls to the correct potential controlling parties, performing authorization measures on received stanzas, etc.</p>
<p>For the purposes of this specification, complex server-side deployments such as clusters, proxies, gateways, protocol translators, etc are not considered. Further details of such concepts may be found in their (present or future) relevant specifications.</p>
</section3>
<section3 topic='Client(s)' anchor='concepts-actors-client'>
<p>A Rayo client is an entity which implements the Rayo protocol for the purpose of asserting control over calls made available by a Rayo server. The method by which such control measures are determined is outside the scope of this document, but may be the result of human interaction or some automated decision-making process.</p>
<p>A Rayo client is responsible for indicating its availability to a Rayo server and responding to offer messages appropriately.</p>
</section3>
<section3 topic='Calls' anchor='concepts-actors-calls'>
<p>A Rayo call is a short-lived XMPP entity within the scope of the deployment's root domain, perhaps at a sub-domain, with the purpose of representing a single session. It is usually a simple alias for the main server process.</p>
<p>A Rayo call is the entity with which most client interactions are made, and is responsible for sending its events to and receiving commands from a client. Calls may host components.</p>
<p>Calls have separate presence from the root domain of the service and thus appear to be separate entities.</p>
</section3>
<section3 topic='Mixers' anchor='concepts-actors-mixers'>
<p>A Rayo mixer is an XMPP entity within the scope of the deployment's root domain, perhaps at a sub-domain, with the purpose of representing a service for the linking of media streams from several calls. It is usually a simple alias for the main server process.</p>
<p>A Rayo mixer is responsible for sending its events to and receiving commands from one or more clients, and can host components.</p>
<p>Mixers have separate presence from the root domain of the service and its calls and thus appear to be separate entities.</p>
</section3>
<section3 topic='Commands' anchor='concepts-actors-commands'>
<p>A Rayo command is a simple combination of request and response and may be issued directly to the service domain, a call, a mixer or a component attached to any of the former. Commands are executed serially and are generally very short-lived.</p>
</section3>
<section3 topic='Components' anchor='concepts-actors-components'>
<p>Components extend the Rayo protocol by providing additional media and call control functionality.</p>
<p>Components have a lifecycle and are started by sending a specialized command to a call or mixer. Thus, a request for creation of a component will return a reference to the component's ID, and the component will continue to execute until it completes, potentially sending events and processing commands along the way (such as an instruction to pause or terminate), before finally issuing an event indicating its completion and thus unavailability. Multiple components may be active on a call or mixer at any one time, and commands may be executed on any entity during the execution of a component.</p>
</section3>
<section3 topic='Remote Party' anchor='concepts-actors-remote-party'>
<p>A call's Remote Party is the software or device with which the Call's signalling (and optionally media) connection is established. This might be a software or hardware phone, a PBX, a gateway or some other such system.</p>
</section3>
</section2>
<section2 topic="Addressing Scheme" anchor='addressing'>
<p>All of the actors described in the previous section (with the exception of commands) are represented by XMPP entities with a JID of their own. Thus, a scheme for determining the JIDs of each of these entities is required. The following is the required naming scheme for Rayo deployments, where elements in square brackets are optional.</p>
<table>
<tr>
<th>Actor</th>
<th>JID format</th>
<th>Example JID</th>
</tr>
<tr>
<td>Server</td>
<td>[service domain]</td>
<td>shakespeare.lit</td>
</tr>
<tr>
<td>Client</td>
<td>any JID</td>
<td>juliet@capulet.lit/balcony</td>
</tr>
<tr>
<td>Call</td>
<td><call ID>@[<call sub-domain>.]<service domain></td>
<td>f88eh2@call.shakespeare.lit</td>
</tr>
<tr>
<td>Mixer</td>
<td><mixer name>@[<mixer sub-domain>.]<service domain></td>
<td>conf1@mixer.shakespeare.lit</td>
</tr>
<tr>
<td>Call Component</td>
<td><call ID>@[<call sub-domain>.]<service domain>/<component ID></td>
<td>f88eh2@call.shakespeare.lit/8f83jf</td>
</tr>
<tr>
<td>Mixer Component</td>
<td><mixer name>@[<mixer sub-domain>.]<service domain>/<component ID></td>
<td>conf1@mixer.shakespeare.lit/932eu</td>
</tr>
<tr>
<td>Server Component</td>
<td><service domain>/<component ID></td>
<td>shakespeare.lit/f3fg4</td>
</tr>
</table>
<p>Commands should be addressed to the entity on which they should be enacted. Individual commands only apply to certain object (for example instructing a component to hangup will return an error). In general, commands may be sent from a client to the service, a call, a mixer or a component. Events may be sent from a call, a mixer or a component to a client.</p>
</section2>
<section2 topic='Delivery Mechanism' anchor='concepts-delivery'>
<p>Rayo defines several events and commands which may be executed on one of the above actors. These payloads must be sent within an XMPP primitive element, and the rules are as such:</p>
<ul>
<li><strong>Events:</strong> Sent as directed presence from the entity producing the event to a client. Rayo servers SHOULD timestamp all events using &xep0203; in order to allow clients to reliably use Rayo events for billing purposes.</li>
<li><strong>Commands:</strong> Sent as an <iq/> with the 'type' attribute 'set' from the client to the entity to be acted on. Responses returned as an <iq/> with the 'type' attribute either 'result' or 'error'.</li>
</ul>
</section2>
</section1>
<section1 topic='Session Flow' anchor='session'>
<p>This section describes the form, function and order of Rayo stanzas sent across the wire, and the circumstances in which they apply and/or may arise.</p>
<section2 topic='Client Registration' anchor='session-registration'>
<p>In order for a Rayo client to be considered a potential controlling party for incoming sessions, it MUST first notify the Rayo server that it is available for the receipt of calls. This is done by sending directed presence to the Rayo server with a <show/> element containing 'chat' as in the example:</p>
<example caption="Client presents itself as available to the Rayo server"><![CDATA[
<presence from='juliet@capulet.lit/balcony'
to='shakespeare.lit'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:client:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
<show>chat</show>
</presence>
]]></example>
<p>Conversely, when a Rayo client wishes not to be considered a potential controlling party, it SHOULD send directed presence to the Rayo server with a <show/> element containing 'dnd' as in the example:</p>
<example caption="Client presents itself as unavailable to the Rayo server"><![CDATA[
<presence from='juliet@capulet.lit/balcony'
to='shakespeare.lit'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:client:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
<show>dnd</show>
</presence>
]]></example>
</section2>
<section2 topic='Session Establishment' anchor='session-establishment'>
<p>Sessions may be established either at the request of the Rayo client (an outbound call) or as a result of a 3rd party request (an inbound call). Each scenario differs in the Rayo protocol only up to the point at which the session is established and media begins to flow. First we shall examine the sequence of stanzas passed between server and client in each of these scenarios.</p>
<section3 topic='Outbound Call' anchor='session-establishment-outbound'>
<p>In order for a client to establish a new outbound call, it MUST first send a <link url="#def-dial">dial command</link> to the server, indicating the proposed target for the call, its apparent source, and any meta-data to send to the target as headers.</p>
<example caption="Client requests establishment of a new outbound session"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='shakespeare.lit'
type='set'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
</iq>
]]></example>
<p>On successfully receiving and parsing the dial command, the server SHOULD perform its own proprietary authorization measures to ensure that only desirable outbound sessions are created. If it is established that the command should not be allowed, the server MUST return an error giving an authorization reason.</p>
<p>If a 'uri' attribute is set on the dial command, the server MUST attempt to create the call at the requested URI. This allows clients to know the URI of the call prior to it coming into existence, for clients where this distinction might be important. Such a URI MUST be a valid Rayo call address.</p>
<p>The specified metadata in the form of the 'from' attribute and any <header/> elements SHOULD be mapped to the underlying signalling protocol for communication to the remote party.</p>
<section4 topic='Errors' anchor='session-establishment-outbound-errors'>
<p>There are several reasons why the server might immediately return an error instead of acknowledging the creation of a new call:</p>
<ul>
<li>The client is unknown to the server and the server does not permit session creation by unknown clients.</li>
<li>The client is not authorized to create this new session.</li>
<li>The server does not support outbound calls.</li>
<li>The server does not have sufficient resources to create a new session.</li>
<li>The dial command was malformed.</li>
<li>The requested URI conflicts with an existing call.</li>
</ul>
<p>If the client is unknown to the server and the server does not permit session creation by unknown clients, the server MUST return a <registration-required/> error with a type of 'auth'.</p>
<example caption="Server indicates client is unknown and the server does not permit session creation by unknown clients"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='auth'>
<registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the client is not authorized (as determined by an implementation/deployment-specific algorithm) to create a new outbound session given the parameters provided, the server MUST return a <not-authorized/> error with a type of 'auth'.</p>
<example caption="Server indicates client is not authorized to create a new outbound session given the parameters provided"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server does not support outbound calls, the server MUST return a <feature-not-implemented/> error with a type of 'cancel'.</p>
<example caption="Server indicates that it does not support outbound calls"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server does not have sufficient resources to create a new session, the server MUST return a <resource-constraint/> error with a type of 'wait'.</p>
<example caption="Server indicates that it does not have sufficient resources to create a new session"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='wait'>
<resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the dial command was malformed, the server MUST return a <bad-request/> error with a type of 'modify'.</p>
<example caption="Server indicates the dial command was malformed"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='foo:bar'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the requested URI conflicts with an existing call, the server MUST return a <conflict/> error with a type of 'modify'.</p>
<example caption="Server indicates the requested URI conflicts with an existing call"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='foo:bar'
from='tel:+14152226789'
uri='xmpp:somecall@capulet.lit'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='modify'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<p>If the command is successful and the call is queued, however, confirmation of such should be sent to the client, including a reference to the unique ID of the call. This call ID may be used to execute commands and filter events for the duration of the session.</p>
<example caption="Confirmation of successful dial request and call ID"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'>
<ref xmlns='urn:xmpp:rayo:1' uri='xmpp:9f00061@call.shakespeare.lit'/>
</iq>
]]></example>
<p>Once the server receives notification that the session has been accepted by the remote party, it should send a ringing event to the client to indicate such:</p>
<example caption="Call announces its ringing state (accepted by 3rd party but not yet answered)."><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<ringing xmlns='urn:xmpp:rayo:1'/>
</presence>
]]></example>
<p>Similarly, once the server receives notification that the session has been answered, it should negotiate media between the remote party and its local media server. Once media negotiation is complete, it should send an answered event to the client to indicate such:</p>
<example caption="Call announces its answered state (media connected)."><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<answered xmlns='urn:xmpp:rayo:1'/>
</presence>
]]></example>
<section4 topic='Nested join' anchor='session-establishment-outbound-nested-join'>
<p>When sending a dial request, a client MAY specify a join target within the dial element:</p>
<example caption="Client requests establishment of a new outbound session, with a nested join"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='shakespeare.lit'
type='set'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<join call-uri='xmpp:e8u398d902i90@call.shakespeare.lit' />
</dial>
</iq>
]]></example>
<p>In this case, the server MUST negotiate media as specified by the join element, in accordance with the rules defined in <link url='#session-joining'>joining calls</link>. Media MUST NOT be negotiated with the local media server, unless the join specifies so. The join operation MUST behave as described in <link url='#session-joining'>joining calls</link>.</p>
</section4>
</section3>
<section3 topic='Inbound Call' anchor='session-establishment-inbound'>
<p>When the Server receives a call from one of its connected networks, it MUST then expose that requested session to Rayo clients. It SHOULD use an implementation-specific routing mechanism to map incoming calls to some set of registered JIDs which are considered appropriate controlling parties. From this set, it SHOULD then remove any parties whom it can identify as being temporarily inappropriate for control (either unavailable based on presence, under too much load, or any other metric which the server has available). If, as a result, the set of Potentially Controlling Parties is empty, the server MUST reject the call indicating that the requested service was unavailable.</p>
<p>If the server can identify active Potential Controlling Parties, it MUST offer them control of the call according to its particular distribution method, which MAY be simultaneous or staged. The server must broadcast an offer on behalf of the call to all Potential Controlling Parties, using applicable to/from/header data from the incoming session. The server MUST also include entity capabilities information in the presence stanza containing the offer, in order to advertise the fact that the entity is a call, qualified by the node name "urn:xmpp:rayo:call:1".</p>
<example caption="New call announces itself to a potential controlling party"><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:call:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
<offer xmlns='urn:xmpp:rayo:1'
to='tel:+18003211212'
from='tel:+13058881212'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</offer>
</presence>
]]></example>
<p>Once the server has offered control, it MUST wait for a response from a PCP or for the remote party to end the call. The server SHOULD monitor the availability of PCPs to whom offers have been sent. If they all cease to be PCPs (eg by going offline) then the call should be rejected in the same way as if there had not been any available PCPs to begin with.</p>
<p>If an offered PCP executes a command against the call, by sending a command node to the call's JID inside an IQ 'set', the server should execute the following routine:</p>
<ol>
<li>If the call does not have a DCP, set it to the PCP from which the command originated.</li>
<li>If the call has a DCP, and the command did not originate from the DCP, return a conflict (cancel) error in response to the command of the following format:
<example caption="Server indicates that the call already has another DCP and that control of the call is no longer available."><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<accept xmlns='urn:xmpp:rayo:1'/>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
otherwise;
</li>
<li>If the command is an accept command, notify the remote calling party that the call has been accepted. Return an empty IQ result to the command issuing party to confirm successful execution.</li>
<li>If the command is an answer command, notify the remote calling party that the call has been answered and negotiate media between the calling party and the server's local media server. Return an empty IQ result to the command issuing party to confirm successful execution.</li>
<li>If the command is any other, handle it in the manner detailed in the following sections.</li>
</ol>
</section3>
</section2>
<section2 topic='Joining Calls' anchor='session-joining'>
<p>Calls on a Rayo Server are capable of having their media streams moved/manipulated. Once such manipulation is to join the media streams of two calls. In a scenario where callA and callB should be joined, the client MUST send a join command to either call (not both) specifying the call ID of the other call, and optionally media attributes (direction and media) specified in the schema, like so:</p>
<example caption="Client instructs callA to join to callB and the server acknowledges the join was completed"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<p>If the calls to be joined to each other are in the same security zone, the server MUST join the media streams of the two calls and return an empty IQ result to confirm that the operation has been successful. If the parties to be joined are not within the same security zone, an error should be returned as detailed below.</p>
<p>When calls are joined to each other by any mechanism, each call MUST dispatch a joined event specifying who they have been joined to:</p>
<example caption="Call A and B were joined, both calls emit joined events"><![CDATA[
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='callB@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
]]></example>
<p>By default, the server MUST join the calls by bridging their audio through its local media server, with bidirectional media. In order to specify alternative behaviour, the client MAY specify a media option (either 'bridge' or 'direct') and/or a direction option (either 'duplex', 'send' or 'recv'), and the server MUST bridge accordingly.</p>
<section3 topic='Errors' anchor='session-joining-errors'>
<p>There are several reasons why the call might return an error instead of acknowledging a join:</p>
<ul>
<li>The specified join party does not exist or cannot be found.</li>
<li>The specified join party is inaccessible for the purposes of being joined due to security restrictions.</li>
<li>The server does not have sufficient resources to complete the join.</li>
<li>The join command was malformed.</li>
<li>The specified media/direction options or their combination are not possible/supported.</li>
</ul>
<p>If the specified join party does not exist or cannot be found, the server MUST return a <service-unavailable/> error with a type of 'cancel'.</p>
<example caption="Call indicates that the specified join party does not exist or cannot be found"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the specified join party is inaccessible for the purposes of being joined due to security restrictions, the server MUST return a <not-allowed/> error with a type of 'cancel'.</p>
<example caption="Call indicates that the specified join party is inaccessible for the purposes of being joined due to security restrictionss"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server does not have sufficient resources to complete the join, the server MUST return a <resource-constraint/> error with a type of 'wait'.</p>
<example caption="Call indicates that there are not sufficient resources to complete the join"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
<error type='wait'>
<resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the join command was malformed (eg no call URI specified), the server MUST return a <bad-request/> error with a type of 'modify'.</p>
<example caption="Call indicates that the join command was malformed"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:'/>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the specified media/direction options or their combination are not possible/supported, the server MUST return a <feature-not-implemented/> error with a type of 'modify'.</p>
<example caption="Call indicates that the specified media/direction options or their combination are not possible/supported."><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit' media='direct' direction='recv'/>
<error type='modify'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section3>
<section3 topic='Unjoin Command' anchor='session-joining-unjoin-command'>
<p>When the client wishes to terminate an existing join, it MUST send an unjoin command specifying the join to break (call-id).</p>
<example caption="Client instructs callA to unjoin from callB"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<unjoin xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</iq>
]]></example>
<p>The server MUST unjoin the media streams of the two calls, rejoin both to the media server and return an empty IQ result to confirm that the operation has been successful:</p>
<example caption="CallA acknowledges unjoin from callB"><![CDATA[
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<p>Optionally, if no join is specified on the unjoin command, all existing joins must be broken:</p>
<example caption="Client instructs callA to unjoin from every existing join"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<unjoin xmlns='urn:xmpp:rayo:1'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<section4 topic='Errors' anchor='session-joining-unjoin-command-errors'>
<p>There are several reasons why the call might return an error instead of acknowledging an unjoin command:</p>
<ul>
<li>The specified join does not exist.</li>
<li>The unjoin command was malformed.</li>
</ul>
<p>If the specified join does not exist, the server MUST return a <service-unavailable/> error with a type of 'cancel'.</p>
<example caption="Call indicates that the specified join does not exist"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the unjoin command was malformed (eg an empty call URI specified), the server MUST return a <bad-request/> error with a type of 'modify'.</p>
<example caption="Call indicates that the join command was malformed"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<unjoin xmlns='urn:xmpp:rayo:1' call-uri='xmpp:'/>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
</section3>
<section3 topic='Unjoined Event' anchor='session-joining-unjoined-event'>
<p>Calls may be unjoined from other calls either in response to an unjoin command, as the result of one of the calls disconnecting, or as the result of an error. The server MUST monitor calls for being unjoined from another call, and emit an unjoined event when this is detected.</p>
<example caption="CallA announces that it has been unjoined from callB, and vice versa"><![CDATA[
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<unjoined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='callB@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<unjoined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
]]></example>
</section3>
<section3 topic='Multiple Joins' anchor='session-joining-multiple'>
<p>If a client wishes to modify the parameters of a join, it MUST send a new join command to the target call with the new parameters. The server MUST renegotiate media using the new parameters, and acknowledge the command's completion. The server MUST NOT re-send joined events.</p>
<example caption="Client joins callA to callB in receive-only mode, and then 'upgrades' the join to full-duplex"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit' direction='recv'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='callB@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed3'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit' direction='duplex'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed3'/>
]]></example>
<p>Rayo calls SHOULD support being joined to more than one other call at a time, each join having different parameters. Creating a new join MUST NOT destroy existing joins. If a join is requested but cannot be created without destroying existing joins, the call MUST return a conflict (cancel) error.</p>
<example caption="Call indicates that the requested joins cannot be created in parallel"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='callB@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed3'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
</iq>
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed3'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section3>
</section2>
<section2 topic='Mixers' anchor='session-mixers'>
<p>While calls may generally be joined peer-to-peer in any desirable combination, such an implementation is not necessarily scalable or practical to manage. Rayo, therefore, includes the concept of mixers, which are entities like calls, to which calls or other mixers may be joined in the same way as joining multiple calls directly. A mixer MUST be implicitly created the first time a call attempts to join it, MUST immediately broadcast presence to all controlling parties who have calls joined to it, and must respond to the join command with a reference to the mixer. If a mixer cannot be created, an error similar to those specified for <dial/> should be returned in response to the <join/> command. The server MUST include entity capabilities information in the first presence stanza it sends, in order to advertise the fact that the entity is a mixer, qualified by the node name "urn:xmpp:rayo:mixer:1". A mixer MUST emit events (joined, unjoined) to all controlling parties who have calls joined to it, using the same semantics as joining calls.</p>
<p>In order to support friendly-named mixers without causing naming collisions between security zones, a server SHOULD represent a mixer internally using some alternative name scoped to the client's security zone and mapped to the friendly name/URI presented to the client for the emission of events and processing of commands. A server MUST NOT allow clients to interact with mixers allocated within other security zones either by observing their status or media.</p>
<example caption="Client instructs call to join a mixer"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' mixer-name='myMixer'/>
</iq>
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:mixer:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
</presence>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'>
<ref xmlns='urn:xmpp:rayo:1' uri='xmpp:myMixer@mixer.shakespeare.lit'/>
</iq>
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' mixer-name='myMixer'/>
</presence>
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
]]></example>
<p>Mixers MUST respect the normal rules of XMPP presence subscriptions, and presence subscriptions from clients within the same security zone as the mixer must be implicitly permitted.</p>
<p>The error conditions on joining a mixer are the same as for calls, as are the unjoin and join modification semantics. Additionally, mixers SHOULD be able to host components just like calls, following the rules defined for each component.</p>
<example caption="Client renders output to a mixer"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='myMixer@mixer.shakespeare.lit'
type='set'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='text/plain'>
Thanks for calling, goodbye!
</document>
</output>
</iq>
<iq from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'>
<ref xmlns='urn:xmpp:rayo:1' uri='xmpp:myMixer@mixer.shakespeare.lit/d38d3'/>
</iq>
]]></example>
<p>If the media server providing the mixer supports active speaker detection, it MUST emit active speaker events to all clients with a presence subscription. Such events MUST indicate the start and end of speaking for a particular call ID joined to the mixer.</p>
<example caption="Mixer indicates overlapping speaking status of two joined calls"><![CDATA[
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<started-speaking xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<started-speaking xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<stopped-speaking xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='myMixer@mixer.shakespeare.lit'