Reputation: 715
I am developing a JavaScript-based web SIP client communicating with Asterisk SIP server.
The SIP client is using JSSIP 3.4.2, I'm testing on Chrome version 80.
Both SIP client and SIP server are behind firewalls. I'm using STUN server stun.l.google.com:19302.
The call is established well, but there's a 40 sec delay between calling the "call" method and establishing a call (starting an RTP session).
Here's the code of SIP UA registration:
// SIP UA registration
var currentUserSipAccount = {
uri: '211',
pwd: 'secret'
};
var sipDomain = 'sip.my-domain.com';
var sipServerUrl = 'wss://' + sipDomain + ':8089/ws';
var socket = new JsSIP.WebSocketInterface(sipServerUrl);
var connectionParams = {};
connectionParams.sockets = [socket];
connectionParams.register = true;
connectionParams.uri = 'sip:' + currentUserSipAccount.uri + '@' + sipDomain;
connectionParams.password = currentUserSipAccount.pwd;
var bwPhone = new JsSIP.UA(connectionParams);
Here's the code of call initiation:
// SIP call
var callNumber = 'sip:233@' + sipDomain;
var callOptions = {
mediaConstraints: {
audio: true, // only audio calls
video: false
},
pcConfig: {
iceServers: [
{'urls': ['stun:stun.l.google.com:19302']}
]
}
};
bwPhone.call(callNumber, callOptions);
I have setup logging of each SIP event and found that the delay is related to the onicegatheringstatechange and onicecandidate events.
Here's the Wireshark log:
Each 10 sec, a STUN request is being sent, followed by an instant response. This happens 4 times.
Here is the browser console log I am getting:
The computer on which I'm doing a call has multiple network interfaces. I see icecandidate events containing two IP addresses, one of them (169.254.128.100) is related to Ethernet and not used, another one (192.168.1.33) is related to WiFi and is used for connecting to Internet.
I also see in the browser console log, that the STUN response is being received within several milliseconds after initiating the call. But after that, JSSIP waits for 40 seconds!
How to avoid this 40 sec delay?
Upvotes: 5
Views: 6261
Reputation: 108
In my case
session.on('icecandidate', (e) => {
console.log(e.candidate.relatedAddress,e.candidate.relatedPort,e.candidate.type);
// always return undefined undefined undefined undefined
})
the working version is
const extractValues = (inputString: string) => {
const match = inputString.match(
/typ (\w+) raddr (\d+\.\d+\.\d+\.\d+) rport (\d+)/
);
if (match) {
const [, type, raddr, rport] = match;
return { type, raddr, rport: parseInt(rport, 10) };
}
return null;
};
session.on('icecandidate', (e) => {
const values = extractValues(e.candidate.candidate);
if (values && values.type === 'srflx' && values.raddr !== 'null' && !isNaN(values.rport)){
e.ready();
}
});
Upvotes: 0
Reputation: 141
If you do not plan to create a conference call, then you can do this. (works for me)
session.on("icecandidate", function (event) {
event.ready();
});
Upvotes: 0
Reputation: 715
Got some hints in the JSSIP group. To stop gathering for ICE candidates and continue SIP flow, I need to call event.ready() inside the icecandidate event handler.
This code resolved the issue (not sure what is srflx, maybe that's not necessary):
session.on("icecandidate", function (event) {
if (event.candidate.type === "srflx" &&
event.candidate.relatedAddress !== null &&
event.candidate.relatedPort !== null) {
event.ready();
}
});
Upvotes: 2
Reputation: 1745
Gathering candidates can be very long, and usually, when the delay is large, the last ice candidate will failed to be found.
To solve your delay, your can control the timeout and abort when you decide. This is an example for a timeout of 5 seconds with jssip:
var myCandidateTimeout = null;
_session.on('icecandidate', function(candidate, ready) {
console.log('getting a candidate' + candidate.candidate.candidate);
if (myCandidateTimeout!=null)
clearTimeout(myCandidateTimeout);
// 5 seconds timeout after the last icecandidate received!
myCandidateTimeout = setTimeout(candidate.ready, 5000);
}
Upvotes: 7