forked from xsf/xeps
-
Notifications
You must be signed in to change notification settings - Fork 0
/
xep-0024.xml
1130 lines (1005 loc) · 38.5 KB
/
xep-0024.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>Publish/Subscribe</title>
<abstract>A publish-subscribe protocol for Jabber.</abstract>
&PUBLICDOMAINNOTICE;
<number>0024</number>
<status>Retracted</status>
<type>Standards Track</type>
<sig>Standards</sig>
<dependencies/>
<supersedes/>
<supersededby><spec>XEP-0060</spec></supersededby>
<shortname>None</shortname>
<author>
<firstname>DJ</firstname>
<surname>Adams</surname>
<email>dj.adams@pobox.com</email>
<jid>dj@gnu.mine.nu</jid>
</author>
<author>
<firstname>Piers</firstname>
<surname>Harding</surname>
<email>piers@ompa.net</email>
<jid>piers@gnu.mine.nu</jid>
</author>
<revision>
<version>0.2</version>
<date>2003-04-22</date>
<initials>psa</initials>
<remark>At the request of the authors, the status of this document has been changed to Retracted since it has been superseded by XEP-0060.</remark>
</revision>
<revision>
<version>0.1</version>
<date>2002-03-05</date>
<initials>dja</initials>
<remark>Initial draft.</remark>
</revision>
</header>
<section1 topic='Abstract'>
<p>
Pubsub ("publish/subscribe") is a technique for coordinating the efficient
delivery of information from publisher to consumer. This specification
describes the use of pubsub within a Jabber context and is a result of
two separate but related goals:
</p>
<ul>
<li>to be able to exchange information _within_ a Jabber environment
(for example continuously changing personal information between users)</li>
<li>to be able to exchange information _using_ Jabber as a mechanism for
<ul>
<li>organising that exchange</li>
<li>providing transport for the information</li>
</ul>
</li>
</ul>
<p>
The specification details the use of the Jabber protocol elements and
introduces a new namespace, jabber:iq:pubsub.
It also includes notes on actual implementation of such a
mechanism in Jabber.
</p>
</section1>
<section1 topic='Introduction'>
<p>
It's clear that as Jabber is deployed over a wider spectrum of platforms
and circumstances, more and more information will be exchanged. Whether
that information is specific to Jabber (JSM) users, or components, we need
an mechanism to be able to manage the exchange of this information in an
efficient way.
</p>
<p>
For example, it is currently the trend to embed information about a
particular client's circumstance inside presence packets, either in the
<status/> tag or in an <x/> extension. One example that comes
to mind is "song currently playing on my MP3 player" (to which I have to
admit some responsibility for the meme in the first place). While embedding
information inside presence packets and having that information diffused to
the users who are subscribed to that user's presence has the desired effect,
it has a couple of non-trivial drawbacks:
</p>
<ul>
<li>the diffusion is inefficient, sending potentially huge amounts of data
to recipients who aren't interested</li>
<li>the distribution is tied to closely to presence subscription; any entity
that wants to receive information must be subscribed to the source's presence,
and there is no mechanism for specifying _what_ information they wish to
receive. It is also arguably too closely tied to the JSM to be useful for
_component_-based information exchange.</li>
</ul>
<p>
This is above and beyond the simple fact that this overloading of presence
packets and the presence subscription and diffusion mechanism can only end
in tears.
</p>
<p>
It would be far better to have a separate (sub-)protocol that enabled
entities to take part in publish/subscribe relationships, and have a service
that facilitated the efficient exchange of information. Not only would it
relax the undue pressure on the presence mechanism, but it would also allow
people to use Jabber, which is, after all, about exchanging structured content
between endpoints, as a publish/subscribe _mechanism_ in its own right.
</p>
<p>
This specification describes a publish/subscribe protocol in terms
of IQ packets with payload data in a new namespace, jabber:iq:pubsub. The
choice for this namespace is slightly arbitrary - it was the same namespace
used in temas's original document, seems to fit well, and we need a namespace
to focus on.<note>It may well be that we will move to a URI-based namespace
in the form of a URL pointing to this specification.</note>
</p>
<p>
The aim of the specification is to provide for a facility where Jabber
entities can subscribe to (consume) and publish (emit) information in an
efficient and organised way. These entities could be JSM users or components.
</p>
<p>
Push technology is back with a vengeance. Jabber can play a fundamental
part.
</p>
</section1>
<section1 topic='The Specification'>
<p>
The pubsub services will be typically provided by a component. In what
follows, there are generally three parties involved:
</p>
<ul>
<li>the subscriber</li>
<li>the pubsub service</li>
<li>the publisher</li>
</ul>
<p>
Bear in mind that it is perfectly possible for a subscriber to be a
publisher, and a publisher to be a subscriber, too.
</p>
<p>
The pubsub traffic will be carried in info/query (IQ) packets. All of the
data in these packets will be qualified by the jabber:iq:pubsub namespace.
</p>
<p>
Pubsub scenarios can be seen in a subscribe (or unsubscribe) context or a
publish context. In light of this, we will examine the IQ packets
used in these contexts.
</p>
<section2 topic='Subscribe/Unsubscribe Context'>
<p>
A potential consumer, or recipient, of published information, needs to
request that he be sent that published information. Requesting to receive,
or be pushed, information is known as subscribing.
</p>
<p>
A subscription request generally takes this form:
</p>
<example caption='General form of a subscription'>
SEND: <iq type='set' from='subscriber' to='pubsub' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher'>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
...
<ns>namespace:N</ns>
</subscribe>
</query>
</iq>
RECV: <iq type='result' to='subscriber' from='pubsub' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher'>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
...
<ns>namespace:N</ns>
</subscribe>
</query>
</iq>
</example>
<section3 topic='Publisher-Specific Subscriptions and Unsubscriptions'>
<p>
Subscriptions can be specific to a publisher, in which case a to attribute
is specified in the <subscribe/> tag:
</p>
<example caption='Publisher-specific subscription'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher'>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher'>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
</query>
</iq>
</example>
<p>
In this case, the namespaces specified will be added to any existing list
of namespaces already recorded for that subscriber:publisher relationship.
In other words, it's a relative, not an absolute, subscription request.
</p>
<p>
It is also possible in a publisher-specific subscription to omit specific
namespaces, if you want to be sent everything that particular publisher
might publish:
</p>
<example caption='Publisher-specific subscription without namespace specification'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher'/>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher'/>
</query>
</iq>
</example>
<p>
This type of subscription should have the effect of absolutely replacing any
previous namespace-specific subscription to the publisher specified.
</p>
<p>
If a subscriber wishes to cancel a subscription from a particular publisher,
he can send an unsubscribe like this:
</p>
<example caption='Publisher-specific unsubscription'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<unsubscribe to='publisher'>
<ns>namespace:1</ns>
</unsubscribe>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<unsubscribe to='publisher'>
<ns>namespace:1</ns>
</unsubscribe>
</query>
</iq>
</example>
<p>
This should have the effect of removing the subscription from that publisher
for the namespaces specified.
</p>
<p>
You can also send an unsubscribe without specifying any namespaces:
</p>
<example caption='Publisher-specific general unsubscription'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<unsubscribe to='publisher'/>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<unsubscribe to='publisher'/>
</query>
</iq>
</example>
<p>
This should have the effect of removing any subscription relationship with
the publisher specified. Note, however, that this won't stop the subscriber
being pushed information from that publisher if he's specified a
"publisher-generic" subscription (see next section).
</p>
</section3>
<section3 topic='Non-Publisher-Specific Subscriptions and Unsubscriptions'>
<p>
As well as being able to subscribe to specific publishers, it is also
possible to subscribe to receive data, according to namespace, regardless
of publisher:
</p>
<example caption='General namespace specific subscription'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
</query>
</iq>
</example>
<p>
This means that the subscriber wishes to be pushed information in the
namespaces specified, regardless of who publishes it. Like the
publisher-specific subscribe that specifies namespaces, this request is
relative, in the namespaces are added to any existing namespaces already
recorded for this generic subscription.
</p>
<p>
Subscribing to everything from everyone is probably not a good idea and
we should not allow this. (The format of the request is actually used in
an IQ-get context - see later).
</p>
<example caption='This is not allowed'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe/>
</query>
</iq>
RECV: <iq type='error' from='pubsub.localhost'
to='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe/>
</query>
<error code='405'>Not Allowed</error>
</iq>
</example>
<p>
Likewise, you can unsubscribe from certain namespaces in this non-publisher-specific context like this:
</p>
<example caption='General unsubscription to specific namespaces'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<unsubscribe>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</unsubscribe>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<unsubscribe>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</unsubscribe>
</query>
</iq>
</example>
<p>
If there are any subscriptions to specific publishers for the namespaces
specified here, they should be removed (for those namespaces) in addition
to the removal from the 'all publishers' list.
</p>
<p>
Finally, a subscriber can wipe the slate clean like this:
</p>
<example caption='Wiping the slate'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<unsubscribe/>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<unsubscribe/>
</query>
</iq>
</example>
<p>
which should have the effect of removing all namespace subscriptions
from everywhere.
</p>
</section3>
<section3 topic='Further Notes'>
<p>
All the examples so far have shown actions on the subscriber's part, and
have consisted of IQ-sets. In an IQ-set, within the jabber:iq:pubsub
namespace, multiple children can exist in the query payload, but those
children must be of the same type. In other words, you can send multiple
<subscribe/>s, or multiple <unsubscribe/>s, but not a combination
of the two.
</p>
<p>
This is allowed:
</p>
<example caption='Subscribing to more than one publisher at once'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisherA'>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
<subscribe to='publisherB'>
<ns>namespace:3</ns>
</subscribe>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisherA'>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
<subscribe to='publisherB'>
<ns>namespace:3</ns>
</subscribe>
</query>
</iq>
</example>
<p>
But this is not allowed:
</p>
<example caption='Subscribes and unsubscribes in same IQ-set is not allowed'>
SEND: <iq type='set' to='pubsub.localhost'
from='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisherA'>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
<unsubscribe to='publisherB'>
<ns>namespace:3</ns>
</unsubscribe>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisherA'>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
<unsubscribe to='publisherB'>
<ns>namespace:3</ns>
</unsubscribe>
</query>
<error code='400'>
Bad Request: only subscribes or unsubscribes
</error>
</iq>
</example>
<p>
In the case where multiple <subscribe/>s or <unsubscribe/>s
appear in an action, each element will be processed in turn, as they appear
in the payload.
</p>
<p>
As well as actions, the subscriber can query his subscription using an
IQ-get in the jabber:iq:pubsub namespace. This should return a list of
the subscribers current subscriptions, like this:
</p>
<example caption='Querying current subscription'>
SEND: <iq type='get' to='pubsub.localhost'
from='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe/>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
<subscribe to='publisherA'>
<ns>namespace:2</ns>
<ns>namespace:4</ns>
</subscribe>
<subscribe to='publisherB'>
<ns>namespace:5</ns>
</subscribe>
</query>
</iq>
</example>
<p>
Note the two references to namespace:2 - one inside the non-publisher-specific
subscription list and one inside the subscription list specific to publisherA.
This example implies that the non-publisher-specific and publisher-specific
subscription information should be kept separately. This is designed to make
it easier on the subscriber to manage his specific subscriptions over time.
</p>
</section3>
</section2>
<section2 topic='Publish Context'>
<p>
In contrast to the subscribe and unsubscribe context, the publishing
context is a lot simpler to explain.
</p>
<p>
A publisher can publish information within a certain namespace, like this:
</p>
<example caption='Publishing information'>
SEND: <iq type='set' to='pubsub.localhost'
from='publisher@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<publish ns='foo'>
<foo xmlns='foo'>bar</foo>
</publish>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='publisher@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<publish ns='foo'>
<foo xmlns='foo'>bar</foo>
</publish>
</query>
</iq>
</example>
<p>
It's also possible for a publisher to publish more than one item at once,
like this:
</p>
<example caption='Publishing information in different namespaces'>
SEND: <iq type='set' to='pubsub.localhost'
from='publisher.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<publish ns='foo'>
<foo xmlns='foo'>bar</foo>
</publish>
<publish ns='jabber:x:oob'>
<x xmlns='jabber:x:oob'>
<url>http://www.pipetree.com/jabber/</url>
<desc>Some stuff about Jabber</desc>
</x>
</publish>
</query>
</iq>
RECV: <iq type='result' from='pubsub.localhost'
to='publisher.localhost' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<publish ns='foo'>
<foo xmlns='foo'>bar</foo>
</publish>
<publish ns='jabber:x:oob'>
<x xmlns='jabber:x:oob'>
<url>http://www.pipetree.com/jabber/</url>
<desc>Some stuff about Jabber</desc>
</x>
</publish>
</query>
</iq>
</example>
<!--
<p>
Optionally, a pubsub component may respond with an empty IQ-result, to
reduce traffic:
</p>
<example>
RECV: <iq type='result' from='pubsub.localhost'
to='publisher.localhost' id='s1'>
</iq>
</example>
-->
<p>
Each published item is wrapped in a <publish/> tag. This tag
must contain the namespace of the item being publishes, in an ns
attribute, as shown. This is distinct from the xmlns attribute of
the fragment of XML actually being published. It is theoretically
none of the pubsub component's business to go poking around in the
real published data, nor should it have to. It needs to know what
namespace is qualifying the published information that has been
received, so that the list of appropriate recipients can be
determined.
</p>
</section2>
<section2 topic='Distributing Published Information'>
<p>
While it's the responsibility of the publishing entities to publish
information, it's the responsibility of the pubsub
component to push out that published data to the subscribers. The
list of recipient subscribers must be determined by the information
stored by the pubsub component as a result of receiving subscription
requests (which are described earlier).
</p>
<p>
On receipt of an IQ-set containing published information, the pubsub
entity must determine the list of subscribers to which that information
should be pushed. If the IQ-set contains multiple <publish/>
fragments, this process must be carried out for each one in turn.
<note>Whether a pubsub component implementation should be allowed to
batch up individual published information fragments for one recipient
as a result of a large, multi-part incoming publishing IQ-set, is not
specified here, the choice is down to the implementer. Receiving entities
should be able to cope with being pushed an IQ-set with multiple
fragments of published data.</note>
</p>
<p>
Taking the earlier example of the publishing of data in the 'foo'
namespace, the following example shows what the pubsub component
must send to push this foo data out to a subscriber.
</p>
<example caption='Pushing out published information to a subscriber'>
SEND: <iq type='set' to='subscriber@localhost/foosink'
from='pubsub.localhost' id='push1'>
<query xmlns='jabber:iq:pubsub'>
<publish ns='foo' from='publisher@localhost'>
<foo xmlns='foo'>bar</foo>
</publish>
</query>
</iq>
</example>
<p>
The recipient is _not_ required to send an 'acknowledgement' in the
form of an IQ-result; the idea that this _push_ of information is
akin to how information is pushed in a live browsing context (see
jabber:iq:browse documentation for more details).
</p>
</section2>
<section2 topic='Delivery Sensitivity'>
<p>
When a pubsub service receives a publish packet like the ones above, it
needs to deliver (push) the information out according to the subscriptions
that have been made.
</p>
<p>
However, we can introduce a modicum of sensitivity by using a presence
subscription between the pubsub service and the subscriber(s). If the
subscriber wishes only to receive information when he's online (this is
a JSM-specific issue), then he needs to set up a presence subscription
relationship with the pubsub service. The pubsub service should respond
to presence subscriptions and unsubscriptions by
</p>
<ul>
<li>accepting the (un)subscription request</li>
<li>reciprocating the (un)subscription request</li>
</ul>
<p>
If the pubsub service deems that a published piece of information should
be pushed to a subscriber, and there is a presence subscription relationship
with that subscriber, the service should only push that information to the
subscriber if he is available. If he is not available, the information is not
to be sent.
</p>
<p>
Thus the subscriber can control the sensitivity by initiating (or not) a
presence relationship with the service. If the subscriber wishes to receive
information regardless of availability, he should not initiate a (or cancel
any previous) presence relationship with the service.
</p>
<p>
This loose coupling of presence relationships for sensitivity allows this
specification to be used in the wider context of component-to-component
publish/subscribe where presence is not a given.
</p>
</section2>
<section2 topic='Use of Resources'>
<p>
When in receipt of a pubsub subscription request from an entity
where a resource is specified in the JID, the pubsub component must
honour the resource specified in the from attribute of the request.
For example, here's a typical subscription request from a JSM user:
</p>
<example caption='Incoming subscription request from a JSM user'>
RECV: <iq type='set' to='pubsub.localhost'
from='subscriber@localhost/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher'>
<ns>namespace:1</ns>
<ns>namespace:2</ns>
</subscribe>
</query>
</iq>
</example>
<p>
When storing the subscriber/publisher/namespace relationship matrix for
eventual querying when a publisher publishes some information, the
pubsub component must use the full JID, not just the username@host part.
</p>
<p>
Similarly, in this example:
</p>
<example caption='Incoming subscription request from a component'>
RECV: <iq type='set' to='pubsub.localhost'
from='news.server/politics-listener' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher'>
<ns>news:politics:home</ns>
<ns>news:politics:foreign:usa</ns>
</subscribe>
</query>
</iq>
</example>
<p>
the full JID of the component subscriber - news.server/politics-listener,
should be used to qualify the matrix.
</p>
<p>
This is because it allows the subscribing entities to arrange the
receipt of pushed items by resource. In the case of a JSM user, it
allows him to organise his clients, which may have different capabilities
(some being able to handle the jabber:iq:pubsub data, others not) to
receive the 'right' data. In the case of a component, it allows the
component to associate component-specific data with incoming published
namespace-qualified information.
</p>
</section2>
</section1>
<section1 topic='Implementation Notes'>
<p>
While the specification describes the fundamental building blocks of the
pubsub protocol, there are ideas that are not discussed above but nonetheless
may be incorporated into an implementation. There are other considerations
that have to be made in the wider context of publish and subscribe. Some of
the main ones are discussed briefly here too.
</p>
<section2 topic='Publisher Discovery'>
<p>
There is no part of this pubsub specification that determines how a
potential subscriber might discover publishers. After all, there are
no rules governing which pubsub component a publisher could or should
publish to. And since pubsub subscriptions are specific to a pubsub
component, there is an information gap - "how do I find out what
publishers there are, and through which pubsub components they're publishing
information?"
</p>
<p>
This problem domain should be solved using other methods, not with the
actual jabber:iq:pubsub specific namespace. A combination of jabber:iq:browse
usage (the magic ointment that heals all things) and perhaps a DNS style
(or at least root-node-based) knowledge hierarchy might be the right
direction.
</p>
<p>
In the case where a server administrator wishes to facilitate pubsub
flow between JSM users on a server, a pubsub component can be plugged
into the jabberd backbone, and there is potentially no real issue with
knowing which pubsub component to use, and where it is.
But what about if the JSM users on one server wish to build pubsub
relationships with JSM users on another server? (Note that this general
question is not specific to JSM users, although that example will be used
here). The next two sections look at how these things might pan out.
</p>
</section2>
<section2 topic='Cross-Server Relationships'>
<p>
When JSM users on server1 wish to subscribe to information published
by JSM users on server2 (let's say it's the mp3 player info, or avatars)
then there are some issues that come immediately to mind:
</p>
<ul>
<li>Does a JSM user on server1 (userA@server1) send his IQ-set subscription
to the pubsub component on server2 (pubsub.server2), or server1
(pubsub.server1)?</li>
<li>If he sends it to pubsub.server2, can we expect
pubsub.server2 to always accept that subscription request, i.e. to
be willing to serve userA@server1 (if pubsub.server2 knows that
pubsub.server1 exists)?</li>
<li>Will there be performance (or at least server-to-server traffic)
implications if many subscription relationships exist between subscribers on
server1 and publishers on server2?</li>
</ul>
<section3 topic='Proxy Subscriptions'>
<p>
To reduce the amount of server-to-server traffic, we can employ the
concept of "proxy subscriptions". This is simply getting a pubsub component
to act on behalf of a (server-local) subscriber. Benefit comes when a pubsub
component acts on behalf of multiple (server-local) subscribers.
</p>
<p>
Here's how such proxy subscriptions can work, to reduce the amount of
server-to-server traffic:
</p>
<p>
Step 1: Subscriber sends original subscription
</p>
<p>
JSM users on server1 wish to subscribe to information published by an
entity on server2. Each of them sends a subscription request to the
_local_ pubsub component:
</p>
<example>
SEND: <iq type='set' to='pubsub.server1'
from='subscriber@server1/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher.server2'>
<ns>namespace:1</ns>
</subscribe>
</query>
</iq>
</example>
<p>
Step2: Pubsub component subscribes on subscriber's behalf
</p>
<p>
The pubsub component knows about the publisher, and where (to which
pubsub component) that publisher publishes information. It formulates
a subscription request and sends it to the remote pubsub component:
</p>
<example>
SEND: <iq type='set' to='pubsub.server2'
from='pubsub.server1' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher.server2'>
<ns>namespace:1</ns>
</subscribe>
</query>
</iq>
</example>
<p>
The remote pubsub component receives and acknowledges the subscription
request, and the local pubsub component relays the response back to
the original requester:
</p>
<example>
SEND: <iq type='result' from='pubsub.server1'
to='subscriber@server1/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher.server2'>
<ns>namespace:1</ns>
</subscribe>
</query>
</iq>
</example>
<p>
If the remote pubsub server was unable or unwilling to accept the
subscription request, this should be reflected in the response:
</p>
<example>
SEND: <iq type='error' from='pubsub.server1'
to='subscriber@server1/resource' id='s1'>
<query xmlns='jabber:iq:pubsub'>
<subscribe to='publisher.server2'>
<ns>namespace:1</ns>
</subscribe>
</query>
<error code='406'>Not Acceptable</error>
</iq>
</example>
<p>
Step3: Publisher publishes information
</p>
<p>
The publisher, publisher.server2, publishes information in the
namespace:1 namespace, to the remote pubsub component pubsub.server2:
</p>
<example>
SEND: <iq type='set' from='publisher.server2'
to='pubsub.server2' id='p1'>
<query xmlns='jabber:iq:pubsub'>
<publish ns='namespace;1'>
<stuff xmlns='namespace:1'>nonsense</stuff>
</publish>
</query>
</iq>
</example>
<p>
Step4: Pubsub component receives published information
</p>
<p>
The pubsub component pushes the published information to pubsub.server1,
who has been determined to be a valid recipient:
</p>
<example>
RECV: <iq type='set' from='pubsub.server2'
to='pubsub.server1' id='p1'>
<query xmlns='jabber:iq:pubsub'>
<publish ns='namespace;1' from='publisher.server2'>
<stuff xmlns='namespace:1'>nonsense</stuff>
</publish>
</query>
</iq>
</example>
<p>
Step5: Pubsub component forwards published information to original subscriber
</p>
<p>
The local pubsub component then diffuses the information received to the
original subscriber: