This is likely a matter of semantics, but I think the RFC might favour the
current behaviour since the Contact endpoint is expected to be global (i.e. function outside of the current dialog).
Not sure how it can be expected behavior to use a SIP UDP 5060 contact over a WSS interface that has no way of talking to SIP UDP 5060.
Hence the global scope of the Contact endpoint, I guess especially so in a historical context ... for devices limited to a handful of connectivity options, such as WSS, it _might_ be expected to follow a rport approach. As with some SIP concepts, there's a big gap between original spec/RFC intent and the field implementations. Not really sure where this one stands!
How did you modify SIP.js?
I've only modified the linked demo (https://sipjs.com/guides/full-demo-app/) to see how it behaves with a stock FS install, here's the resulting fiddle: http://jsfiddle.net/o890yfs7/ -- line #3 is the host on which the Sofia profile is listening to requests. I've tested against a Docker instance (using host network mode) as follows: FROM debian:buster RUN apt-get update && apt-get install -y gnupg2 wget lsb-release RUN wget -O - https://files.freeswitch.org/repo/deb/debian-release/fsstretch-archive-keyri... | apt-key add - RUN echo "deb http://files.freeswitch.org/repo/deb/debian-release/ `lsb_release -sc` main" > /etc/apt/sources.list.d/freeswitch.list RUN echo "deb-src http://files.freeswitch.org/repo/deb/debian-release/ `lsb_release -sc` main" >> /etc/apt/sources.list.d/freeswitch.list RUN apt-get update && apt-get install -y freeswitch-meta-all RUN rm -rf /etc/freeswitch/sip_profiles/*ipv6* COPY files / CMD ["freeswitch", "-nonat"] There's an intentional 10 seconds delay in the default dialplan you can use to test the CANCEL behaviour while the other extension is ringing.