11### Module Description
22
3- This module enabled Jingle to SIP and SIP to Jingle translator.
4- When this module is enalbed, MongooseIM will intercept any iq set jingle stanza with action:
3+ This module enables Jingle to SIP and SIP to Jingle translation.
4+ When this module is enabled, MongooseIM will intercept any Jingle IQ set stanza with action:
5+
56* session-initiate
67* session-terminate
78* session-accept
89* transport-info
910
10- and translate it to SIP messages with approprite SDP content based on the details in the Jingle stanza.
11+ and translate it to SIP messages with appropriate SDP content based on the details in the Jingle stanza.
1112
12- The translation back from SIP to Jingle is done for following SIP messages :
13+ The translation back from SIP to Jingle is done for the following SIP requests :
1314
14- * ` INVITE ` - with additionall callback for following response codes:
15- * ` 200 `
16- * ` 180 ` and ` 183 `
17- * ` 486 ` when the call's recipient rejects it
18- * from ` 400 ` to ` 600 ` - other error codes indicating session terminate
19- * ` re-INVITE ` - ` INVITE ` message sent for established session
15+ * ` INVITE `
16+ * ` re-INVITE ` - ` INVITE ` message sent for an accepted session
2017* ` CANCEL `
2118* ` BYE `
2219* ` INFO `
2320
21+ and following responses to the INVITE request:
22+
23+ * ` 200 ` when the call invite was accepted
24+ * ` 180 ` and ` 183 ` to indicate that the invitation was sent to the device
25+ * ` 486 ` when the call's recipient rejects it
26+ * from ` 400 ` to ` 600 ` - other error codes indicating session termination
27+
28+ #### Jingle to SIP translation
29+
30+ The table below summarises the bilateral translation for standard Jingle and SIP messages:
31+
32+ | Jingle action | SIP message | comment |
33+ | ------------- | ----------- | ------- |
34+ | ` session-initiate ` | ` INVITE ` request | |
35+ | ` session-accept ` | ` 200 OK ` response | |
36+ | ` session-terminate ` with reason ` success ` | ` BYE ` request | Only for accepted session |
37+ | ` session-terminate ` with reason ` decline ` | ` CANCEL ` request | When sent by call's initiator |
38+ | ` session-terminate ` with reason ` decline ` | ` 486 Busy Here ` response | When sent by the invite user |
39+ | ` transport-info ` | ` INFO ` request | |
40+
41+ ##### Ringing notification
42+
43+ Both Jingle and SIP have the ` ringing ` notification.
44+ It's generated as a response code ` 180 Ringing ` by a SIP entity when the INVITE is sent to the device.
45+ In SIP world a ` 183 Session Progress ` response code is also generated in some cases.
46+ Both ` 180 ` and ` 183 ` codes are translated as ` session-info ` Jingle stanza with ` ringing ` sub element.
47+ MongooseIM generates only ` 180 Ringing ` response code the ` INVITE ` request, if the recipient's online.
48+ If the recipient is online, MongooseIM generates the ` 180 Ringing ` response code to the ` INVITE ` request.
49+
50+ ##### Recipient unavailable
51+
52+ When MongooseIM receives a SIP ` INVITE ` request addressed to an offline user,
53+ it replies with a ` 480 Temporarily Unavailable ` code.
54+ The same code is expected from the SIP Proxy when MongooseIM sends the ` INVITE ` request.
55+
56+ ##### Other error codes
57+
58+ When an error response to the ` INVITE ` request is from the range ` 400 ` to ` 699 ` but not ` 486 ` ,
59+ MongooseIM will send a Jingle ` session-terminate ` stanza to the call's initiator.
60+ The stanza has reason ` general-error ` with the SIP error code in the ` sip-error ` sub element.
61+
62+ ##### Non-standard Jingle stanzas used by jingle.js
63+
64+ The following non-standard Jingle stanzas were integrated with https://github.com/softwarehutpl/jingle.js
65+
66+ * ` source-remove `
67+ * ` source-add `
68+ * ` source-update `
69+
70+ When MongooseIM observes the above Jingle stanzas, it will translate them to a SIP in-dialog ` INVITE ` request.
71+ In the SDP content of the request, there will be a custom attribute ` a=jingle-action ` .
72+ The value of the custom attribute is one of the three presented above.
73+
74+ Similarly when MongooseIM gets a SIP in-dialog ` INVITE ` request,
75+ it will check if there is a custom attribute and use it as the ` action ` attribute of the Jingle stanza sent to the user.
76+ If there is no such attribute, the action will be set to regular Jingle ` transport-info ` .
77+
78+ ##### Non-stadard Jingle existing-session-initiate stanza
79+
80+ MongooseIM allows a user to ask for an unanswered ` session-initiate ` request.
81+ This may be useful in web applications when there is a need to handle the call in a new browser window.
82+
83+ In order to get the ` session-initiate ` , which was not answered yet, the user can send a ` get ` Jingle stanza to self with action set to ` existing-session-initiate ` .
84+ As a result, MongooseIM will resend the original ` session-initiate ` request to the device which sent the query.
85+
86+
2487### Prerequisites
2588
2689By default, MongooseIM is built without SIP support.
@@ -42,3 +105,168 @@ MongooseIM 2.2.x packages are built with OTP 19.3, so they include Jingle/SIP su
42105* ` listen_port ` (default: 5600) the port on which MongooseIM will listen for incomming SIP messages
43106* ` local_host ` (default: "localhost") value used to create SIP URIs (including VIA headers)
44107* ` sdp_origin ` (default: "127.0.0.1") value of the ` c= ` SDP attribute
108+
109+ The simplest configuration is the following:
110+
111+ ``` erlang
112+ {mod_jingle_sip , []}
113+ ```
114+
115+ With this configuration MongooseIM will try sending SIP messages to a SIP proxy listening on localhost and port 5060.
116+
117+ ### Use cases covered by tests
118+
119+ Currently to test the functionality we use a SIP Proxy mock written in Erlang.
120+ The following scenarios are covered by our tests in ` big_tests/tests/jingle_SUITE.erl `
121+
122+
123+ All the sequence diagrams where generated with [ textart.io/sequence] ( https://textart.io/sequence ) .
124+ The source code is embedded in the markdown file below every diagram inside a comment ` <!--- ---> `
125+
126+
127+ #### 1. Establishing a session with another XMPP user
128+
129+ With the mod_jingle_sip enabled, all Jingle IQ set stanzas listed above are intercepted, translated to SIP packets and sent to a SIP Proxy.
130+ This means that the current implementation will also translate stanzas addressed to a user in the same domain.
131+ This allows the SIP entity to control how the call between XMPP users is established.
132+ Below there are sequence diagrams showing the communication between XMPP users, MongooseIM and SIP Proxy as in our tests.
133+ It's possible that the SIP Proxy or other SIP entity decides that the call needs to be forked
134+ and delivered to the user's phone number instead of generating a corresponding call back to MongooseIM.
135+
136+
137+ ##### 1.1 Signaling session-initiate to other XMPP user via SIP Proxy
138+
139+ ```
140+ +-------+ +-------------+ +-----------+ +-------+
141+ | UserA | | MongooseIM | | SIPProxy | | UserB |
142+ +-------+ +-------------+ +-----------+ +-------+
143+ | | | |
144+ | session-initiate to UserB | | |
145+ |--------------------------------->| | |
146+ | -------------------------\ | | |
147+ |-| Jingle stanza | | | |
148+ | | action:session-initate | | | |
149+ | | sid: 123 | | | |
150+ | |------------------------| | SIP INVITE | |
151+ | |------------------->| |
152+ | | -------------\ | |
153+ | |-| from:UserA | | |
154+ | | | to:UserB | | |
155+ | | | sid: 123 | | |
156+ | | |------------| | create new call |
157+ | | |---------------- |
158+ | | | | |
159+ | | |<--------------- |
160+ | | | ------------------------\ |
161+ | | |-| SDP content can be | |
162+ | | | | changed for instance | |
163+ | | | | to inject a transport | |
164+ | | SIP INVITE | | canidate | |
165+ | |<-------------------| |-----------------------| |
166+ | | -------------\ | |
167+ | | | from:UserA |-| |
168+ | | | to:UserB | | |
169+ | --------------------\ | | sid:456 | | |
170+ | | yes, new SID: 456 |-| |------------| | |
171+ | |-------------------| | | |
172+ | | | |
173+ | | session-initiate to UserB |
174+ | |------------------------------------------------->|
175+ | | | |
176+ ```
177+
178+ <!-- -
179+ object UserA MongooseIM SIPProxy UserB
180+ UserA->MongooseIM: session-initiate to UserB
181+ note right of UserA: Jingle stanza \n action:session-initate\nsid: 123
182+ MongooseIM->SIPProxy: SIP INVITE
183+ note right of MongooseIM: from:UserA\nto:UserB\nsid: 123
184+ SIPProxy->SIPProxy: create new call
185+ note right of SIPProxy: SDP content can be\nchanged for instance\n to inject a transport\n canidate
186+ SIPProxy->MongooseIM: SIP INVITE
187+ note left of SIPProxy: from:UserA\nto:UserB\nsid:456
188+ note left of MongooseIM: yes, new SID: 456
189+ MongooseIM->UserB: session-initiate to UserB
190+ -->
191+
192+ ##### 1.2 Signaling session-accept to other XMPP user via SIP Proxy
193+
194+ When the other user accepts the call invite sent by the first, the following sequence is executed.
195+ This is a continuation of the [ previous example] ( #11-signaling-session-initiate-to-other-xmpp-user-via-sip-proxy )
196+
197+ ```
198+ +-------+ +-------------+ +-----------+ +-------+
199+ | UserA | | MongooseIM | | SIPProxy | | UserB |
200+ +-------+ +-------------+ +-----------+ +-------+
201+ | | | |
202+ | | | session-accpet to UserA |
203+ | |<--------------------------------------------------|
204+ | | | ------------------------\ |
205+ | | | | Jingle stanza |-|
206+ | | | | action:session-accept | |
207+ | | | | sid: 456 | |
208+ | | 200 OK | |-----------------------| |
209+ | |-------------------->| |
210+ | | --------------\ | |
211+ | |-| from: UserA | | |
212+ | | | to: UserB | | |
213+ | | | sid: 456 | | |
214+ | | |-------------| | find corresponding call |
215+ | | |------------------------ |
216+ | | | | |
217+ | | |<----------------------- |
218+ | | | |
219+ | | 200 OK | |
220+ | |<--------------------| |
221+ | | --------------\ | |
222+ | | | from: UserA |-| |
223+ | | | to: UserB | | |
224+ | | | sid: 123 | | |
225+ | session-accept from UserB | |-------------| | |
226+ |<---------------------------------| | |
227+ | | | |
228+ ```
229+
230+ <!-- -
231+ object UserA MongooseIM SIPProxy UserB
232+ UserB->MongooseIM: session-accpet to UserA
233+ note left of UserB: Jingle stanza \n action:session-accept\nsid: 456
234+ MongooseIM->SIPProxy: 200 OK
235+ note right of MongooseIM:from: UserA\nto: UserB\nsid: 456
236+ SIPProxy->SIPProxy: find corresponding call
237+ SIPProxy->MongooseIM: 200 OK
238+ note left of SIPProxy: from: UserA\nto: UserB\nsid: 123
239+ MongooseIM->UserA: session-accept from UserB
240+ -->
241+
242+ ##### 1.3 Terminating a call
243+
244+ Any Jingle session (accepted or not) can be terminated by sending a Jingle stanza with action ` session-terminate ` and a reason.
245+ In the SIP world it's more complex.
246+ See the following examples for more information.
247+
248+ ###### 1.3.1 Terminating an accepted call
249+
250+ The easiest scenario is when the call was accepted as in [ 1.2] ( #12-signaling-session-accept-to-other-xmpp-user-via-sip-proxy ) .
251+ In this case one of the users sends a ` session-terminate ` Jingle action with a reason ` success ` .
252+ This is translated to a SIP ` BYE ` request with ` to ` and ` from ` headers set appropriately -
253+ ` from ` is the user who wants to terminate the call and ` to ` is the user on the other end of the session.
254+ The ` BYE ` request is sent to the SIP Proxy and then to the other user in a similar way to session acceptance.
255+
256+ ###### 1.3.2 Terminating an unanswered call by initiator
257+
258+ To terminate the call before it's accepted, the initiator sends a Jingle ` session-terminate ` stanza with a reason ` decline ` .
259+ Then MongooseIM translates this to a SIP ` CANCEL ` request which is sent to the SIP Proxy.
260+
261+ ###### 1.3.3 Rejecting the call
262+
263+ When the invitee wants to terminate the call, on the XMPP level this is also a Jingle ` session-terminate ` stanza with a reason ` decline ` .
264+ MongooseIM translates this to SIP ` 486 Busy Here ` ** Response** (because this is a response to the invite request).
265+
266+ #### 2. Establishing a session with a SIP user
267+
268+ Establishing a session with a SIP user (or a SIP entity) works the same as in the previous section.
269+ The only difference is that the SIP Proxy will not call MongooseIM back (as it may happen for call to other XMPP user).
270+ Instead the SIP message sent by MongooseIM to SIP Proxy will be delivered directly to the SIP user's device.
271+
272+
0 commit comments