Last active
September 11, 2018 05:40
-
-
Save zyxar/9827049 to your computer and use it in GitHub Desktop.
WebRTC <-> SIP <-> WebRTC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var express = require('express'); | |
var app = express(); | |
app.configure(function () { | |
"use strict"; | |
app.use(express.logger('dev')); | |
app.use(express.static(__dirname + '/public')); | |
}); | |
app.use(function (req, res, next) { | |
"use strict"; | |
res.header('Access-Control-Allow-Origin', '*'); | |
res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, DELETE'); | |
res.header('Access-Control-Allow-Headers', 'origin, content-type'); | |
if (req.method == 'OPTIONS') { | |
res.send(200); | |
} | |
else { | |
next(); | |
} | |
}); | |
var port = process.env.PORT || 4321; | |
app.listen(port); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html><html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title>WebRTC over SIP POC</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<script src="js/jquery-latest.js"></script> | |
<link rel="stylesheet" href="css/bootstrap.min.css"> | |
<script src="js/bootstrap.min.js"></script> | |
<script src="js/jssip.js"></script> | |
<script type="text/javascript" src="poc.js"></script> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="row clearfix"> | |
<div class="col-md-12 column"> | |
<div class="jumbotron"> | |
<span>WebRTC over SIP</span> | |
</div> | |
</div> | |
</div> | |
<div class="row clearfix"> | |
<div class="col-md-8 column"> | |
<div class="row"> | |
<h2>Call</h2> | |
<div style="white-space:nowrap;"> | |
<input type="text" style="width: 100%; height:100%" id="sipURI" value="" placeholder="Enter sip uri" /> | |
</div><br /> | |
<div style="white-space:nowrap;"> | |
<input type="text" style="width: 100%; height:100%" id="sipText" value="" placeholder="Enter text message to send" /> | |
</div><br /> | |
<div class="btn-toolbar" > | |
<div class="btn-group pull-left"> | |
<button id="btnConnect" class="btn btn-success" data-toggle="dropdown">Connect</button> | |
</div> | |
<div class="btn-group pull-right"> | |
<button id="btnCall" class="btn btn-primary" data-toggle="dropdown" disabled="disabled">Call</button> | |
</div> | |
<div class="btn-group pull-right"> | |
<button id="btnHangup" class="btn btn-warning" data-toggle="dropdown" disabled="disabled">Hangup</button> | |
</div> | |
<div class="btn-group pull-right"> | |
<button id="btnSend" class="btn btn-info" data-toggle="dropdown" disabled="disabled">Send</button> | |
</div> | |
</div> | |
</div> | |
<div class="row"><br /></div> | |
<div class="row"> | |
<div class="col-md-4 column"> | |
<video id="my-video"></video> | |
</div> | |
<div class="col-md-4 column"> | |
<video id="peer-video"></video> | |
</div> | |
</div> | |
</div> | |
<div class="col-md-4 column"> | |
<div id="mysipuri"> | |
</div> | |
<div id="messageBoard"> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
$(document).ready(function(){ | |
var self = {}; | |
var dismiss_button_str = '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>'; | |
function enableButtons () { | |
for (var i = arguments.length - 1; i >= 0; i--) { | |
$(arguments[i]).removeAttr('disabled'); | |
}; | |
} | |
function disableButtons () { | |
for (var i = arguments.length - 1; i >= 0; i--) { | |
$(arguments[i]).attr('disabled', 'disabled'); | |
}; | |
} | |
var sip_handlers = { | |
newRTCSession: function (e) { | |
var domElement = $('#messageBoard'); | |
domElement.append('<div class="alert alert-info alert-dismissable">'+ dismiss_button_str+'newRTCSession!' +'</div>'); | |
$('#messageBoard .alert-info:last').delay(2000).addClass("in").fadeOut(4000); | |
}, | |
connected: function (e) { | |
var domElement = $('#messageBoard'); | |
domElement.append('<div class="alert alert-info alert-dismissable">'+ dismiss_button_str+'connected!' +'</div>'); | |
$('#messageBoard .alert-info:last').delay(2000).addClass("in").fadeOut(4000); | |
}, | |
disconnected: function (e) { | |
var domElement = $('#messageBoard'); | |
domElement.append('<div class="alert alert-info alert-dismissable">'+ dismiss_button_str+'disconnected!' +'</div>'); | |
$('#messageBoard .alert-info:last').delay(2000).addClass("in").fadeOut(4000); | |
$('#mysipuri').children().remove(); | |
}, | |
newMessage: function (e) { | |
if (e.data.originator !== 'local' && e.data.message) { | |
var message = { | |
from: e.data.message.request.from.uri.user, | |
body: e.data.message.request.body, | |
data: e.data.message.request.data | |
}; | |
$('input#sipURI').val(e.data.message.request.from.uri); | |
var domElement = $('#messageBoard'); | |
domElement.append('<div class="alert alert-info alert-dismissable">'+ dismiss_button_str+'<strong>'+message.from+'</strong>: '+message.body +'</div>'); | |
$('#messageBoard .alert-info:last').delay(2000).addClass("in").fadeOut(4000); | |
} else { | |
console.log(e.data); | |
} | |
}, | |
registered: function (e) { | |
$('#mysipuri').append('<h4>My SIP URI:<br /><span></span></h4>'); | |
var domElement = $('#mysipuri span') | |
domElement.removeClass(); | |
domElement.addClass("label label-info"); | |
domElement.text(self.siprtc.uri()); | |
console.log(e.data.response); | |
$('#messageBoard').append('<div class="alert alert-success alert-dismissable">'+ dismiss_button_str+e.data.response.data +'</div>'); | |
$('#messageBoard .alert-success:last').delay(5000).addClass("in").fadeOut(1000); | |
enableButtons('button#btnSend', 'button#btnCall'); | |
}, | |
unregistered: function (e) { | |
var domElement = $('#messageBoard'); | |
domElement.append('<div class="alert alert-info alert-dismissable">'+ dismiss_button_str+'unregistered!' +'</div>'); | |
$('#messageBoard .alert-info:last').delay(2000).addClass("in").fadeOut(4000); | |
$('#mysipuri').children().remove(); | |
}, | |
registrationFailed: function (e) { | |
var domElement = $('#messageBoard'); | |
domElement.append('<div class="alert alert-info alert-dismissable">'+ dismiss_button_str+'registrationFailed!' +'</div>'); | |
$('#messageBoard .alert-info:last').delay(2000).addClass("in").fadeOut(4000); | |
} | |
}; | |
$('button#btnConnect').click(function (event) { | |
event.preventDefault(); | |
var siprtc = self.siprtc = new SipRTC({ | |
eventHandlers: sip_handlers | |
}); | |
$(event.currentTarget).attr('disabled','disabled'); | |
}); | |
$('button#btnCall').click(function (event) { | |
event.preventDefault(); | |
if (self.siprtc) { | |
var target = $('input#sipURI').val(); | |
var options = { | |
'mediaConstraints': {'audio': true, 'video': true} | |
}; | |
self.siprtc.call(target, options); | |
} | |
}) | |
$('button#btnSend').click(function (event) { | |
event.preventDefault(); | |
if (self.siprtc) { | |
var target = $('input#sipURI').val(); | |
var message = $('input#sipText').val(); | |
self.siprtc.sendMessage(target, message, { | |
eventHandlers: { | |
succeeded: function(e){ | |
var domElement = $('#messageBoard'); | |
domElement.append('<div class="alert alert-success alert-dismissable">'+ dismiss_button_str+'message sent!' +'</div>'); | |
$('#messageBoard .alert-success:last').delay(2000).addClass("in").fadeOut(4000); | |
}, | |
failed: function(e){ | |
var domElement = $('#messageBoard'); | |
domElement.append('<div class="alert alert-danger alert-dismissable">'+ dismiss_button_str+'message not sent!' +'</div>'); | |
$('#messageBoard .alert-danger:last').delay(2000).addClass("in").fadeOut(4000); | |
} | |
} | |
}); | |
} | |
}) | |
}); | |
</script> | |
</body></html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SipRTC = function (config) { | |
config = config || {}; | |
var sip_config = config.sip_config || {}; | |
this.sip_config = { | |
ws_servers: [ "ws://WS_SIP_SERVER:10080" ], | |
// register: true, | |
// register_expires: 300, | |
trace_sip: true, | |
stun_servers: [ "stun:74.125.132.127:19302" ], | |
use_preloaded_route: false, | |
log: 'warn' // works only on 'jssip-devel.js'i | |
}; | |
if (typeof sip_config.uri === 'string' && sip_config.uri !== '') { | |
this.sip_config.uri = sip_config.uri; | |
this.sip_config.display_name = sip_config.display_name || "SipRTC_User"; | |
this.sip_config.password = sip_config.password || ''; | |
} else { | |
var uid = sip_config.uid || 'woogeen00'+(Math.floor(Math.random() * 10) % 9 + 1); | |
this.sip_config.uri = 'sip:'+uid+"@SIP_SERVER"; | |
this.sip_config.display_name = sip_config.display_name || 'SipRTC_'+uid; | |
this.sip_config.password = sip_config.password || uid; | |
} | |
try { | |
this.sip = new JsSIP.UA(this.sip_config); | |
} catch (e) { | |
console.log(e); | |
throw(e); | |
return this; | |
} | |
var eventHandlers = config.eventHandlers || {}; | |
eventHandlers.newRTCSession = eventHandlers.newRTCSession || function(e){console.log(e.data);}; | |
eventHandlers.connected = eventHandlers.connected || function(e){console.log(e.data);}; | |
eventHandlers.disconnected = eventHandlers.disconnected || function(e){console.log(e.data);}; | |
eventHandlers.newMessage = eventHandlers.newMessage || function(e){console.log(e.data);}; | |
eventHandlers.registered = eventHandlers.registered || function(e){console.log(e.data);}; | |
eventHandlers.unregistered = eventHandlers.unregistered || function(e){console.log(e.data);}; | |
eventHandlers.registrationFailed = eventHandlers.registrationFailed || function(e){console.log(e.data);}; | |
this.sip.on('newRTCSession', (function(e) { | |
eventHandlers.newRTCSession(e); | |
this.onCall(e); | |
}).bind(this)); | |
this.sip.on('connected', eventHandlers.connected); | |
this.sip.on('disconnected', eventHandlers.disconnected); | |
this.sip.on('newMessage', eventHandlers.newMessage); | |
this.sip.on('registered', eventHandlers.registered); | |
this.sip.on('unregistered', eventHandlers.unregistered); | |
this.sip.on('registrationFailed', eventHandlers.registrationFailed); | |
this.sip.start(); | |
function VideoView (eid) { | |
var self = this; | |
this.view = document.getElementById(eid); | |
this.on = false; | |
this.start = function (session) { | |
if (!self.on && session.getLocalStreams().length > 0) { | |
self.view.src = window.URL.createObjectURL(session.getLocalStreams()[0]); | |
self.view.play(); | |
self.on = true; | |
} | |
}; | |
this.stop = function () { | |
if (self.on) { | |
self.view.src = ""; | |
self.view.pause(); | |
self.on = false; | |
} | |
}; | |
} | |
this.localVideo = new VideoView('my-video'); | |
this.remoteVideo = new VideoView('peer-video'); | |
}; | |
SipRTC.prototype.uri = function() { | |
return this.sip_config.uri; | |
}; | |
SipRTC.prototype.onCall = function(evt) { // TODO; | |
// var request = evt.data.request; | |
var session = evt.data.session; | |
this.currentSession = session; | |
if (session.direction === 'incoming') { | |
console.log("incoming call from " + session.remote_identity.uri.user); | |
session.answer({ | |
mediaConstraints: { audio: true, video: true } | |
}); | |
this.localVideo.start(session); | |
} | |
session.on('progress', (function (e) { | |
console.log("call " + e.type + ":"); | |
console.log(e.data); | |
this.localVideo.start(session); | |
}).bind(this)); | |
session.on('started', (function (e) { | |
console.log("call " + e.type + ":"); | |
console.log(e.data); | |
this.localVideo.start(session); | |
this.remoteVideo.start(session); | |
}).bind(this)); | |
session.on('failed', function (e) { | |
console.log("call " + e.type + ":"); | |
console.log(e.data); | |
}); | |
session.on('ended', (function (e) { | |
console.log("call " + e.type + ":"); | |
console.log(e.data); | |
this.remoteVideo.stop(); | |
}).bind(this)); | |
}; | |
SipRTC.prototype.sendMessage = function() { | |
this.sip.sendMessage.apply(this.sip, arguments); | |
}; | |
SipRTC.prototype.call = function() { | |
this.sip.call.apply(this.sip, arguments); | |
}; | |
// SipRTC.onXXX% |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment