Open mtryfoss opened 8 months ago
Please print the initial INVITE, 100, 180/183, 200, ACK messages and then the received BYE.
Here you go!
2024-01-17 16:28:14 +0100 : 192.168.75.141:60278 -> 192.168.23.184:443
INVITE sip:+47494949@sip.domain.com SIP/2.0
Via: SIP/2.0/WSS e2ecvh8aqqb7.invalid;branch=z9hG4bK3017171
Max-Forwards: 69
To: <sip:+47494949@sip.domain.com>
From: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=bhkk93kg21
Call-ID: 5hpl8bbtoq2hhhfgcn2k
CSeq: 3488 INVITE
Authorization: Digest algorithm=MD5, username="1705508839:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com", realm="domain.com", nonce="...", uri="sip:+47494949@sip.domain.com", response="..."
P-Preferred-Identity: sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com
Contact: <sip:1jjiz6hyxjgzotleyhbeejocnyv@domain.com;gr=urn:uuid:9147fcf9-4eda-4259-8997-55f65ef7c97b>
Content-Type: application/sdp
Session-Expires: 3600;refresher=uac
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO,NOTIFY
Supported: timer,gruu,ice,replaces,outbound
User-Agent: JsSIP 3.10.1
Content-Length: 1956
<removed SDP>
2024-01-17 16:28:14 +0100 : 192.168.23.184:443 -> 192.168.75.141:60278
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/WSS e2ecvh8aqqb7.invalid;branch=z9hG4bK3017171;rport=60278;received=192.168.75.141
To: <sip:+47494949@sip.domain.com>
From: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=bhkk93kg21
Call-ID: 5hpl8bbtoq2hhhfgcn2k
CSeq: 3488 INVITE
Content-Length: 0
2024-01-17 16:28:16 +0100 : 192.168.23.184:443 -> 192.168.75.141:60278
SIP/2.0 180 Ringing
Via: SIP/2.0/WSS e2ecvh8aqqb7.invalid;rport=60278;received=192.168.75.141;branch=z9hG4bK3017171
Record-Route: <sip:192.168.23.179;lr>
Record-Route: <sip:192.168.23.184;r2=on;lr;ftag=bhkk93kg21>
Record-Route: <sip:192.168.23.184:443;transport=ws;r2=on;lr;ftag=bhkk93kg21>
From: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=bhkk93kg21
To: <sip:+47494949@sip.domain.com>;tag=as09dc2c45
Call-ID: 5hpl8bbtoq2hhhfgcn2k
CSeq: 3488 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE, PRACK, UPDATE
Supported: timer, 100rel
Session-Expires: 3600;refresher=uac
Contact: <sip:+47494949@192.168.23.188:5060>
Require: timer
Content-Length: 0
2024-01-17 16:28:17 +0100 : 192.168.23.184:443 -> 192.168.75.141:60278
SIP/2.0 200 OK
Via: SIP/2.0/WSS e2ecvh8aqqb7.invalid;rport=60278;received=192.168.75.141;branch=z9hG4bK3017171
Record-Route: <sip:192.168.23.179;lr>
Record-Route: <sip:192.168.23.184;r2=on;lr;ftag=bhkk93kg21>
Record-Route: <sip:192.168.23.184:443;transport=ws;r2=on;lr;ftag=bhkk93kg21>
From: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=bhkk93kg21
To: <sip:+47494949@sip.domain.com>;tag=as09dc2c45
Call-ID: 5hpl8bbtoq2hhhfgcn2k
CSeq: 3488 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE, PRACK, UPDATE
Supported: timer, 100rel
Session-Expires: 3600;refresher=uac
Contact: <sip:+47494949@192.168.23.188:5060>
Require: timer
Content-Type: application/sdp
Content-Length: 647
<removed SDP>
2024-01-17 16:28:17 +0100 : 192.168.75.141:60278 -> 192.168.23.184:443
ACK sip:+47494949@192.168.23.188:5060 SIP/2.0
Route: <sip:192.168.23.184:443;transport=ws;r2=on;lr;ftag=bhkk93kg21>
Route: <sip:192.168.23.184;r2=on;lr;ftag=bhkk93kg21>
Route: <sip:192.168.23.179;lr>
Via: SIP/2.0/WSS e2ecvh8aqqb7.invalid;branch=z9hG4bK7058213
Max-Forwards: 69
To: <sip:+47494949@sip.domain.com>;tag=as09dc2c45
From: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=bhkk93kg21
Call-ID: 5hpl8bbtoq2hhhfgcn2k
CSeq: 3488 ACK
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO,NOTIFY
Supported: outbound
User-Agent: JsSIP 3.10.1
Content-Length: 0
2024-01-17 16:28:21 +0100 : 192.168.23.184:443 -> 192.168.75.141:60278
BYE sip:1jjiz6hyxjgzotleyhbeejocnyv@domain.com;gr=urn:uuid:9147fcf9-4eda-4259-8997-55f65ef7c97b SIP/2.0
Via: SIP/2.0/WSS 192.168.23.184:443;branch=z9hG4bK819d.79edfb897b40652e26f39143ec35b1ce.0
Via: SIP/2.0/UDP 192.168.23.179;rport=5060;branch=z9hG4bK819d.363edda7249aa41e91730a76c91ceb7f.0
Via: SIP/2.0/UDP 192.168.23.188:5060;rport=5060;branch=z9hG4bK1652c731
Max-Forwards: 68
From: <sip:+47494949@sip.domain.com>;tag=as09dc2c45
To: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=bhkk93kg21
Call-ID: 5hpl8bbtoq2hhhfgcn2k
CSeq: 102 BYE
Content-Length: 0
2024-01-17 16:28:21 +0100 : 192.168.75.141:60278 -> 192.168.23.184:443
SIP/2.0 404 Not Found
Via: SIP/2.0/WSS 192.168.23.184:443;branch=z9hG4bK819d.79edfb897b40652e26f39143ec35b1ce.0
Via: SIP/2.0/UDP 192.168.23.179;rport=5060;branch=z9hG4bK819d.363edda7249aa41e91730a76c91ceb7f.0
Via: SIP/2.0/UDP 192.168.23.188:5060;rport=5060;branch=z9hG4bK1652c731
To: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=bhkk93kg21
From: <sip:+47494949@sip.domain.com>;tag=as09dc2c45
Call-ID: 5hpl8bbtoq2hhhfgcn2k
CSeq: 102 BYE
Content-Length: 0
You are not explicitly passing any "contact" to new UA, right? So it looks like if JsSIP takes the identity uri, converts it to low case and use it as Contact header. That's perfectly fine since it can use whatever it wants. Problem is that the incoming BYE is rejected with 404 despite its RURI matches the Contact URI of the initial INVITE. My guess is that JsSIP stores internally the contact header without converting it to low case, then it converts it to low case when sending the INVITE, and later when the BYE arrives JsSIP tries to match the RURI (which is all low case to match the INVITE'/s Contact) using its internally stored identity URI which is not in low case.
@jmillan thoughts?
You're correct. I'm not specifying the contact directly. Afaik, I wasn't aware that that was an option.
It seems like some other people also had the same struggle, so would be nice with a fix and/or at least - a clarification :)
I tested using contact_uri too with the original non-lowercased value, and it seems to end with the same result.
@mtryfoss, can you please share the REGISTER request and response? I'm wondering if the registrar server is the one lowercasing the URI in the pub gruu.
The user-part of To and From is in lower case, while username in Authorization header is like it should be.
REGISTER sip:domain.com SIP/2.0
Via: SIP/2.0/WSS tkb9vrejfuua.invalid;branch=z9hG4bK9724461
Max-Forwards: 69
To: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>
From: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=4l3k4ii8o1
Call-ID: rdpm76h7q47lujq80n9dup
CSeq: 2 REGISTER
Authorization: Digest algorithm=MD5, username="1705577130:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com", realm="domain.com", nonce="...", uri="sip:domain.com", response="..."
Contact: <sip:s64qtlfe@tkb9vrejfuua.invalid;transport=ws>;+sip.ice;reg-id=1;+sip.instance="<urn:uuid:44e0581c-0d2a-4a7f-aca5-bfdcddd9f742>";expires=300
Expires: 300
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO,NOTIFY
Supported: path,gruu,outbound
User-Agent: JsSIP 3.10.1
Content-Length: 0
SIP/2.0 200 OK
Via: SIP/2.0/WSS tkb9vrejfuua.invalid;rport=49556;received=192.168.75.141;branch=z9hG4bK1484306
To: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=78322ec717f7a5b13edafae546c3bb10.49460000
From: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com>;tag=kp3a0fcvvq
Call-ID: rdpm76h7q47lujq80n9dup
CSeq: 2 REGISTER
Contact: <sip:s64qtlfe@tkb9vrejfuua.invalid;transport=ws>;expires=300;pub-gruu="sip:1jjiz6hyxjgzotleyhbeejocnyv@domain.com;gr=urn:uuid:44e0581c-0d2a-4a7f-aca5-bfdcddd9f742";temp-gruu="sip:uloc-65a69615-354ff-915-b804a376@domain.com;gr";+sip.instance="<urn:uuid:44e0581c-0d2a-4a7f-aca5-bfdcddd9f742>";reg-id=1
Supported: outbound
Require: outbound
Content-Length: 0
I'm using save() in the Kamailio registrar module with an explicit URI based on the Authorization header, which is the correct string (non-lower case). However, I see the user-part of the Kamailio-registration appears to be saved in all lower.
Checking the docs, I see this one:
3.10. case_sensitive (integer)
If set to 1 then AOR comparison and also storing will be case sensitive, if set to 0 then AOR comparison and storing will be case insensitive. This is recommended. This parameter can be modified via Kamailio config framework.
Default value is 0.
Changing that to 1, stores the AOR correct.
Now the INVITE is sent with the correct user in the Contact (and From) too:
Contact: <sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@....
And the BYE is accepted, even after I removed the toLowerCase() in the settings for the client.
I'm part of the Kamailio team too, but was not aware of this setting. I'll bring it up to maybe change the default.
All in all, a quite confusing case. The question is then, would it cause any trouble for JsSIP to handle this situation for others which may not be able to fix it server side?
Despite what kamailio registrar does, the fact here is that:
Contact: <sip:1jjiz6hyxjgzotleyhbeejocnyv@domain.com;gr=urn:uuid:9147fcf9-4eda-4259-8997-55f65ef7c97b>
sip:1jjiz6hyxjgzotleyhbeejocnyv@domain.com;gr=urn:uuid:9147fcf9-4eda-4259-8997-55f65ef7c97b
which perfectly matches the Contact URI that JsSIP used in the INVITE.BTW I fail to see how the Authorization header can affect this problem, it's supposed to be the credentials for the client to get registered and make calls. It should not directly affect the generated Contact URIs. Also I don't understand the problem you said in the REGISTER flow. JsSIP sets a low case uri in the REGISTER and Kamailio honors it (in low case) in the 200 to the REGISTER.
I originally included the signalling with my client-side workaround in place, so it registers with all-lower. Edited the post to what I can see after altering behaviour in both ends.
To conclude I think we can say:
Can you please show the changes in the edited REGISTER flow with that kamailio setting set to default value? I cannot see the difference (note: I'm in mobile with super low availability for some days).
This should be before the client workaround, and with default setting in Kamailio.
REGISTER sip:domain.com SIP/2.0
Via: SIP/2.0/WSS q5q96qlrkps3.invalid;branch=z9hG4bK1767564
Max-Forwards: 69
To: <sip:1nbDtTItg1DaVroTrzmBRjLTB7q@domain.com>
From: <sip:1nbDtTItg1DaVroTrzmBRjLTB7q@domain.com>;tag=de0133hugt
Call-ID: igh7bgvafcobtbp26jsgs9
CSeq: 2 REGISTER
Authorization: Digest algorithm=MD5, username="1705508948:1nbDtTItg1DaVroTrzmBRjLTB7q@domain.com", realm="domain.com", nonce="...", uri="sip:domain.com", response="..."
Contact: <sip:7crp59qm@q5q96qlrkps3.invalid;transport=ws>;+sip.ice;reg-id=1;+sip.instance="<urn:uuid:d1996bf3-326c-4d2d-9f7b-f91a017f123f>";expires=300
Expires: 300
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO,NOTIFY
Supported: path,gruu,outbound
User-Agent: JsSIP 3.10.1
Content-Length: 0
SIP/2.0 200 OK
Via: SIP/2.0/WSS q5q96qlrkps3.invalid;rport=61044;received=192.168.54.193;branch=z9hG4bK1767564
To: <sip:1nbDtTItg1DaVroTrzmBRjLTB7q@domain.com>;tag=78322ec717f7a5b13edafae546c3bb10.b2010000
From: <sip:1nbDtTItg1DaVroTrzmBRjLTB7q@domain.com>;tag=de0133hugt
Call-ID: igh7bgvafcobtbp26jsgs9
CSeq: 2 REGISTER
Contact: <sip:7crp59qm@q5q96qlrkps3.invalid;transport=ws>;expires=300;pub-gruu="sip:1nbdttitg1davrotrzmbrjltb7q@domain.com;gr=urn:uuid:d1996bf3-326c-4d2d-9f7b-f91a017f123f";temp-gruu="sip:uloc-65a69615-35501-6c2-a0423bf8@domain.com;gr";+sip.instance="<urn:uuid:d1996bf3-326c-4d2d-9f7b-f91a017f123f>";reg-id=1
Supported: outbound
Require: outbound
Content-Length: 0
Returned contact: pub-gruu="sip:1nbdttitg1davrotrzmbrjltb7q@domain.com
Returned contact: pub-gruu="sip:1nbdttitg1davrotrzmbrjltb7q@domain.com
Sorry, and what's the problem or unexpected thing with this returned contact? Why should it be different? I insi that the fact that it doesn't match the username in the Authorization header is irrelevant. Do I miss something? (Sorry I'm on vacation)
JsSIP is not handling this INVITE/BYE scenario isolated (it should accept the URI in a BYE that has been used as Contact in the INVITE).
I don't think JsSIP should store all temp
and and pub
GRUU's that have been used during a session. The spec clear says that the GRUU generation must adhere to the following:
https://www.rfc-editor.org/rfc/rfc5627#section-5.4
Every GRUU is associated with a single AOR
and a single instance ID.
sip:1nbdttitg1davrotrzmbrjltb7q@domain.com;gr=urn:uuid:d1996bf3-326c-4d2d-9f7b-f91a017f123f
is different from
sip:1NBdttitg1davrotrzmbrjltb7q@domain.com;gr=urn:uuid:d1996bf3-326c-4d2d-9f7b-f91a017f123f
, meaning that the GRUU cannot convert the case of the AOR it contains.
@jmillan, despite the kamailio gruu low case stuff, do you see the problem in the REGISTER + INVITE + incoming BYE flow? Because I don't so I don't really understand why JsSIP fails to match the incoming BYE. The RURI of the BYE matches the Contact in the 200 of the REGUSTER. So what's the problem?
Seems like JsSIP is somehow falling back to matching this against the configured value (settings), and not what it use for the INVITE?
And what is the configured value in settings?
Sorry, my bad. It's been so much back and forth here :) That was my previous presumption since I didn't notice it was actually the REGISTER-response causing it to use in lower case.
It will not match against the settings, since they could be in both upper and lower while the contact is in lower.
But I insist something must be wrong in JsSIP side. Can you show the settings you pass to new JsSIP.UA()?
At first we only used:
uri: '1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com',
authorization_user: '1705588985:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com',
but then we also tried specifying contact_uri explicitely:
contact_uri: 'sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com',
Same effect.
At first we only used:
uri: '1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com'
So here the bug because the uri is given with low and upper chars but the JsSIP generated Contact URI is in low case so later it doesn't match the RURI of the incoming BYE (which is correct) because it's in low case. Yes, here the bug. Somewhere in JsSIP we are converting the given settings uri to low case when we generate the REGISTER and the INVITE, but we keep it in upper+low case in memory and use it to match incoming requests. That's the bug.
Nop,
JsSIP sends a REGISTER with TO URI: sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com
REGISTER response comes with pub_gruu: sip:1jjiz6hyxjgzotleyhbeejocnyv@domain.com;gr=urn:uuid:44e0581c-0d2a-4a7f-aca5-bfdcddd9f742
NOTE lowercase, this is against the spec, it does not represent the AoR
JsSIP uses the pub_gruu as the Contact in outgoing requests.
JsSIP receives a request (BYE) with the pub_gruu in the RURI, which does not point to user AoR.
In summary, the issue is in the server lowercasing the AoR in the pub_gruu, which makes it identify a different AoR.
JsSIP sends a REGISTER with TO URI: sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com
Where do you see that in messages above? I see this instead in the REGISTER sent by JsSIP:
Contact: sip:7crp59qm@q5q96qlrkps3.invalid;transport=ws;+sip.ice;reg-id=1;+sip.instance="
All in low case. So it should match and accept a BYE with same RURI in low case. But it doesn't.
Where do you see that in messages above?
here: https://github.com/versatica/JsSIP/issues/844#issuecomment-1898326471
Where do you see that in messages above?
here: https://github.com/versatica/JsSIP/issues/844#issuecomment-1898326471
The contact in that REGISTER is:
Contact: sip:s64qtlfe@tkb9vrejfuua.invalid;transport=ws;+sip.ice;reg-id=1;+sip.instance="
Where do you see upper chars there?
Where do you see upper chars there?
That is the Contact generated by us in the REGISTER. I did not mention that in my comment here https://github.com/versatica/JsSIP/issues/844#issuecomment-1898841830
JsSIP sends a REGISTER with TO URI: sip:1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com
REGISTER response comes with pub_gruu: sip:1jjiz6hyxjgzotleyhbeejocnyv@domain.com;gr=urn:uuid:44e0581c-0d2a-4a7f-aca5-bfdcddd9f742 NOTE lowercase, this is against the spec, it does not represent the AoR
This is your comment but still I don't see any evidence that JsSIP sends REGISTER with upper case chars in the Contact header. I just see it in your comment, nowhere else. I may be wrong.
This is your comment but still I don't see any evidence that JsSIP sends REGISTER with upper case chars in the Contact header. I just see it in your comment, nowhere else. I may be wrong.
Not the in the Contact header, but in the To header. The registrar extracts the AoR from the To header field and creates the GRUU out of it, which adds to the Contact header in the response. As part of the GRUU creation, the registrar lower cases the AoR, which I claim to be the bug.
I would absolutely say it's a non-optimal behaviour/bug in the way Kamailio works without modified settings.
Regardless of that, wouldn't it be a good idea to handle this in JsSIP so it at least accepts a BYE to a URI matching a contact in an INVITE sent by the same client? Maybe log a notice about it in the REGISTER process, if the returned contact no longer match the expected value?
It was more or less pure luck I found the cause relatively quick. Looking at the call isolated, there's literally no reason at all it shouldn't work.
Not the in the Contact header, but in the To header. The registrar extracts the AoR from the To header field and creates the GRUU out of it, which adds to the Contact header in the response. As part of the GRUU creation, the registrar lower cases the AoR, which I claim to be the bug.
The pub-gruu in the REGISTER 200 is clearly in low case, and JsSIP uses that pub-gruu in low case in the Contact of the INVITE so it honors it. So it should match the BYE since its RURI perfectly matches the Contact URI that JsSIP told to the callee. But is doesn't so hence the bug in JsSIP.
The pub-gruu is chosen/decided by the registrar server. JsSIP should not expect any specific URI. That's why the pub-gruu is indicated in the REGISTER 200.
Section 5.4 of RGC 5627 clearly says:
This specification does not mandate a particular mechanism for
construction of the GRUU. Example algorithms for public and
temporary GRUUs that work well are given in Appendix A. However, in
addition to the properties described in Section 3.1, a GRUU
constructed by a registrar MUST exhibit the following properties:
o The domain part of the URI is an IP address present on the public
Internet, or, if it is a hostname, the resolution procedures of
RFC 3263 [2], once applied, result in an IP address on the public
Internet.
o When a request is sent to the GRUU, it routes to a proxy that can
access the registration data generated by the registrar. Such a
proxy is called an authoritative proxy, defined in RFC 5626 [14].
Appendix A says:
pendix A. Example GRUU Construction Algorithms
The mechanism for constructing a GRUU is not subject to
specification. This appendix provides an example that can be used by
a registrar to construct a public and a temporary GRUU. Of course,
others are permitted, as long as they meet the constraints defined
for a GRUU.
A.1. Public GRUU
The most basic approach for constructing a public GRUU is to take the
AOR and place the actual value of the instance ID into the contents
of the "gr" URI parameter.
In other words: the registrar can decide how the entire pub gruu looks. So this is only a bug in JsSIP despite the low case stuff of kamailio.
I missread the spec and interpreted that the AoR should be included too.
I don't have an ETA myself for this fix as for now, as I have my hands at this momemt.
No hurry for me - we're covered by the server side fix. Just wanted to create a ticket regarding this, so no more people would need to scratch their heads about the same thing.
Route header missing when SIP BYE reached, and loose_route() return -1
Hello!
I've seen a couple of posts/tickets regarding this message.
Although a workaround would do for me by doing
.toLowerCase()
on this in the settings:uri: '1jjIz6hYXjgzOTLEyhBEeJoCnYV@domain.com'
.. I think it would be smart to adjust the cause of this problem - or at least make a note regarding it.I have this scenario with an outgoing JsSIP call which is terminated with a BYE from the callee. Results in a 404 towards the callee.
According to the rules, the URI or BYE matches the Contact of the initial INVITE - which it does. That's why I used some time debugging this. Everything seems ok by looking at the SIP.
While digging a bit deeper, it seems like the username of the uri is lower cased when starting the call.
According to https://datatracker.ietf.org/doc/html/rfc3261#section-19.1.4:
Because of that, JsSIP will not be able to use a username that is in not pure lower case in settings. I suggest leaving the settings.user as it is configured when starting calls.