C2D: How do you integrate with SIP.js 0.8+
Problem
You want to use WebRTC to integrate into the Teleforge PBX, but since SIP.js 0.8 the API has become a lot harder to use, how do we handle it?
Solution
basic_webrtc.html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script src="sip-0.11.2.js"></script> <script src="basic_webrtc.js"></script> </style></head> <body cz-shortcut-listen="true"> <audio autoplay="autoplay" id="audio"></audio> <div> <button id="makeCall">Make call</button> <button id="endCall">End call</button> </div> </body> </html>
- This config uses Secure WebSockets (wss) by default.
- From v4.0.0 X-Platforma headers have been deprecated in favour of X-Teleforge
Using SIP.Web.Simple will not work because it does not allow custom headers to be sent.
Variables
- teleforgePbxAddress: PBX IP/Domain Address
- agentExtension: Agent extension/number
- agentExtensionPass: Agents Password for the Extension
- <callee>: number to dial
- <outbound_id> number to use as caller ID
- <custom_call_ref> your custom call reference
basic_webrtc.js (SIP.UA)
// site config const remoteAudio = document.getElementById("audio"); let session; // the active session needs to be stored somewhere to be accessible by the handlers. // global config, same for all agents for this client const teleforgePbxAddress = "<????>.forge-cloud.com"; // per agent config, each agent has their own credentials const agentExtension = "9000"; const agentExtensionPass = "supersecret"; const agentDisplayName = "0120001234"; // either a CLID or a name, it's not used but does add some additional info. // Creates the user agent const userAgent = new SIP.UA({ uri: agentExtension + "@" + teleforgePbxAddress, authorizationUser: agentExtension, password: agentExtensionPass, displayName: agentDisplayName, transportOptions: { wsServers: ["wss://" + teleforgePbxAddress + ":8089/ws"] }, //hackIpInContact: true, // may or may not be needed, try without first. register: true, sessionDescriptionHandlerFactoryOptions: { constraints: { audio: true, video: false } }, }); userAgent.on("registrationFailed", function (response, cause) { // Normally either bad user credentials or PBX issues, if the latter then mail support@teleforge.co.za console.error("registrationFailed cause", cause); console.error("registrationFailed response", response); }); userAgent.on("registered", function (response, cause) { // credentials are good console.info("registered"); }); userAgent.on("unregistered", function (response, cause) { // not normally a problem but could indicate one. console.warn("unregistered cause", cause); console.warn("unregistered response", response); }); function onFailedCall(request) { //http://sipjs.com/api/0.11.0/causes/ console.error("Call Failed"); //We send back special error messages for validation errors. const validationErrors = request.getHeaders("X-Teleforge-Error"); // from v4.0.0 (X-Platforma-Error has been deprecated) if (0 < validationErrors.length) { validationErrors.forEach(function(error) { console.error("Validation Error: ", error); }); } } function onIncomingCall(session) { const confirmation = confirm("Incoming call from " + session.remoteIdentity.displayName); if (confirmation) { session.accept(); } else { session.reject(); } } function handleMedia(session) { const pc = session.sessionDescriptionHandler.peerConnection; const remoteStream = new MediaStream(); pc.getReceivers().forEach(function(receiver) { remoteStream.addTrack(receiver.track); }); remoteAudio.srcObject = remoteStream; remoteAudio.play(); } function makeOutboundCall() { // Outbound API Call options const outboundOptions = { extraHeaders : [ "X-Teleforge-Outbound-ID: <outbound_id>", // from v4.0.0 (X-Platforma-Outbound-ID has been deprecated) "X-Teleforge-Contact-Ref: <custom_call_ref>" // from v4.0.0 (X-Platforma-Contact-Ref has been deprecated) ] }; session = userAgent.invite("sip:" + <callee> + "@" + teleforgePbxAddress, outboundOptions); // Error while placing a call session.on("failed", onFailedCall); session.on("trackAdded", function() { handleMedia(session); }); console.info("Call started"); console.debug("session:" + session); } function hangupCall() { session.bye(); session = null; remoteAudio.srcObject = null; console.info("Hangup Call..."); } // Listen for the invite: inbound calls userAgent.on("invite", onIncomingCall); // UI const makeButton = document.getElementById("makeCall"); const endButton = document.getElementById("endCall"); makeButton.addEventListener("click", makeOutboundCall); endButton.addEventListener("click", hangupCall, false);
- use the latest 0.11.x SIP.js (newer should be supported)
- ensure you create the UserAgent with the defined parameters
- ensure you handle the media as shown.
Related articles