Commit 1a6c79e9 authored by Dele Olajide's avatar Dele Olajide Committed by dele

Rayo plugin work-in-progress

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@13756 b35dd754-fafc-0310-a699-88a17e54d16e
parent dc855d85
......@@ -17,10 +17,8 @@
<script>
var avatar = 'unknown.jpg';
var callerId = "unknown";
var domain = "81.201.82.25";
var prefix = "sip:";
var handsetOffhook = false;
var ringtone;
window.dialer = new Dialpad({
......@@ -65,6 +63,7 @@
if (domain == "81.201.82.25" && prefix == "sip:") prefix = "sip:883510";
if (prefix == "tel:") domain = "";
if (prefix == "xmpp:") domain = window.location.hostname;
var iNum = urlParam("inum");
......@@ -74,7 +73,6 @@
}
window.connection = new Openfire.Connection(window.location.protocol + '//' + window.location.host + '/http-bind/');
window.connection.resource = iNum;
window.connection.addHandler(handlePresence, null,"presence", null, null, null);
window.connection.connect(window.location.hostname, null, function (status)
{
......@@ -84,16 +82,13 @@
if (status === Strophe.Status.CONNECTED)
{
$("#status").html("Ready");
setPresence();
window.connection.send($pres());
$(window).unload( function() {
onhook();
window.connection.disconnect();
});
setPresence();
getContacts();
offhook();
setPhone();
}
});
......@@ -105,184 +100,109 @@
}
})
function setPresence(chat)
{
//console.log("setPresence");
if (window.connection)
{
var presence = $pres();
if (chat) presence.c('show').t(chat).up();
window.connection.send(presence);
}
}
function offhook()
function setPhone()
{
console.log("offhook()");
console.log("setPhone()");
if (window.connection)
{
window.connection.rayo.offhook(
window.connection.rayo.phone(
{
codec: "OPUS",
stereo: "0",
onReady: function() {
console.log('Handset is off hook');
$("#status").html("Off Hook");
handsetOffhook = true;
},
onUnready: function() {
console.log('Handset is on hook');
$("#status").html("On Hook");
handsetOffhook = false;
},
onEnd: function() {
console.log('Handset is disconnected');
$("#status").html("On Hook");
handsetOffhook = false;
},
onError: function(e) {
console.error(e);
}
});
}
}
function toggleHook()
{
console.log("onhook()");
onOffer: function(call, headers) {
console.log('onOffer ' + call.from);
console.log(headers);
if (window.connection)
{
if (handsetOffhook)
window.connection.rayo.onhook();
else
offhook()
}
}
function handlePresence(presence)
{
//console.log("handlePresence");
//console.log(presence);
var from = $(presence).attr('from');
var iNum = Strophe.getResourceFromJid(from);
var xquery = presence.getElementsByTagName("x");
if (xquery.length == 0)
{
var type = $(presence).attr('type');
if (type == "unavailable")
if (window.candybar.call == null) // ignore when user has active call
{
window.candybar.setUser({
name: call.from,
number: call.to,
picUrl: 'unknown.jpg'
});
} else {
//var status = $(presence).find('status').text();
}
window.candybar.call = call;
window.candybar.setState('incoming');
window.dialer.setCallLabel('Answer');
}
},
return true;
};
function getContacts ()
{
//console.log("getContacts ");
};
function makeCall(destination)
{
console.log("makeCall " + destination);
var sipUri = prefix + destination + "@" + domain
if (prefix == "tel:") sipUri = prefix + destination
window.candybar.call = window.connection.rayo.dial(
{
from: 'unknown',
to: sipUri,
onEnd: function(callId, headers) {
console.log('onEnd ' + callId);
console.log(headers);
onEnd: function() {
//console.log('ended...............');
window.candybar.endGently();
window.candybar.call = null;
window.dialer.setCallLabel('Call');
},
onAnswer: function() {
//console.log('answered...............');
onAnswer: function(callId, headers) {
console.log('onAnswer ' + callId);
console.log(headers);
window.candybar.setState('active');
window.dialer.setCallLabel('Hangup');
stopTone();
},
onRing: function() {
//console.log('ringing...............');
onRing: function(callId, headers) {
console.log('onRing ' + callId);
console.log(headers);
window.candybar.setState('calling');
startTone("ringback-uk");
},
onError: function(e) {
//console.log('dial error ' + e);
window.candybar.endGently();
window.candybar.call = null;
console.error(e);
}
});
}
}
function makeCall(destination)
{
console.log("makeCall " + destination);
var sipUri = prefix + destination + "@" + domain
if (prefix == "tel:") sipUri = prefix + destination
window.candybar.call = window.connection.rayo.dial("xmpp:" + window.connection.jid, sipUri);
window.candybar.setUser({
name: callerId,
name: sipUri,
number: destination,
picUrl: 'unknown.jpg'
});
}
function onIncomingCall(event)
function onIncomingCall(call)
{
console.log(' call from ' + event.call.initiator);
console.log(' call from ' + call.from);
if (window.candybar.call == null) // ignore when user has active call
{
var destination = Strophe.getNodeFromJid(event.call.initiator);
window.candybar.setUser({
name: destination,
number: destination,
picUrl: 'http://placekitten.com/100/100'
name: call.from,
number: call.to,
picUrl: 'unknown.jpg'
});
window.candybar.call = event.call;
window.candybar.call = call;
window.candybar.setState('incoming');
window.dialer.setCallLabel('Answer');
/*
window.candybar.call.bind(
{
onHangup: function(event)
{
window.candybar.endGently();
//window.candybar.call = null;
window.dialer.setCallLabel('Call');
},
onAnswer: function(event)
{
window.candybar.setState('active');
window.dialer.setCallLabel('Hangup');
},
onError: function(event)
{
console.log('call error ' + event.reason);
}
});
*/
}
}
......@@ -303,15 +223,18 @@
}
function stopTone()
{
if (ringtone)
{
ringtone.pause();
ringtone = null;
}
}
</script>
</head>
<body>
<div id="dialpadDiv" style="position: absolute; width: 500px: height: 300px;"/>
<span id="status" onClick="toggleHook()">Loading...</span>
<span id="status">Loading...</span>
</body>
</html>
\ No newline at end of file
......@@ -21,7 +21,6 @@ Strophe.addConnectionPlugin('rayo',
init: function(conn)
{
this._connection = conn;
this.calls = {};
Strophe.addNamespace('RAYO_CORE', "urn:xmpp:rayo:1");
Strophe.addNamespace('RAYO_CALL', "urn:xmpp:rayo:call:1");
......@@ -40,39 +39,171 @@ Strophe.addConnectionPlugin('rayo',
Strophe.addNamespace('RAYO_HANDSET', "urn:xmpp:rayo:handset:1");
Strophe.addNamespace('RAYO_HANDSET_COMPLETE', "urn:xmpp:rayo:handset:complete:1");
this._connection.addHandler(this.handlePresence.bind(this), null,"presence", null, null, null);
this._connection.addHandler(this._handlePresence.bind(this), null,"presence", null, null, null);
console.log('Rayo plugin initialised');
},
offhook: function(handset)
phone: function(callbacks)
{
//console.log('Rayo plugin offhook');
this.callbacks = callbacks;
},
if (this.handset && this.handset.mixer) // reuse mixer
hangup: function(callId)
{
handset.mixer = this.handset.mixer;
console.log("hangup " + callId);
var that = this;
var iq = $iq({to: callId + "@rayo." + this._connection.domain, from: this._connection.jid, type: "get"}).c("hangup", {xmlns: Strophe.NS.RAYO_CORE});
console.log(iq.toString());
that._connection.sendIQ(iq, function(response)
{
console.log(response);
if ($(response).attr('type') != "result")
{
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("hangup failure");
}
});
if (!handset.mixer) handset.mixer = "rayo-mixer-" + Math.random().toString(36).substr(2,9);
this._onhook();
},
digit: function(callId, key)
{
//console.log("digit " + callId + " " + key);
var that = this;
var iq = $iq({to: callId + "@rayo." + this._connection.domain, from: this._connection.jid, type: "get"}).c("dtmf", {xmlns: Strophe.NS.RAYO_CORE, tones: key});
that._connection.sendIQ(iq, function(response)
{
if ($(response).attr('type') != "result")
{
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("dtmf failure");
}
});
},
answer: function(callId, headers)
{
//console.log('Rayo plugin accept ' + callId);
//console.log(headers)
var that = this;
if (this._isOffhook()) this._onhook();
this._offhook(callId, headers, function()
{
var iq = $iq({to: "rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("answer", {xmlns: Strophe.NS.RAYO_CORE});
if (headers)
{
var hdrs = Object.getOwnPropertyNames(headers)
for (var i=0; i< hdrs.length; i++)
{
var name = hdrs[i];
var value = headers[name];
iq.c("header", {name: name, value: value}).up();
}
}
console.log(iq.toString());
that._connection.sendIQ(iq, function(response)
{
if ($(response).attr('type') != "result")
{
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("answer failure");
}
});
});
},
dial: function(from, to, headers)
{
//console.log('Rayo plugin dial ' + from + " " + to);
//console.log(headers)
var that = this;
var callId = "rayo-call-" + Math.random().toString(36).substr(2,9);
if (this._isOffhook()) this._onhook();
this._offhook(callId, headers, function()
{
var iq = $iq({to: "rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("dial", {xmlns: Strophe.NS.RAYO_CORE, to: to, from: from});
iq.c("header", {name: "call-id", value: callId}).up();
if (headers)
{
var hdrs = Object.getOwnPropertyNames(headers)
for (var i=0; i< hdrs.length; i++)
{
var name = hdrs[i];
var value = headers[name];
iq.c("header", {name: name, value: value}).up();
}
}
console.log(iq.toString());
that._connection.sendIQ(iq, function(response)
{
if ($(response).attr('type') != "result")
{
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("dial failure");
}
});
});
return {
digit: function(tone) {that.digit(callId, tone);},
hangup: function() {that.hangup(callId);},
from: from,
to: to,
id: callId
}
},
_isOffhook: function()
{
return this.localStream != null;
},
_offhook: function(mixer, headers, action)
{
//console.log('Rayo plugin offhook ' + mixer);
//console.log(headers);
this.handset = handset;
var that = this;
navigator.webkitGetUserMedia({audio:true, video:false}, function(stream)
{
that.localStream = stream;
that._offhook1();
that._offhook1(mixer, headers, action);
}, function(error) {
if (that.handset && that.handset.onError) that.handset.onError(error);
if (that.callbacks && that.callbacks.onError) that.callbacks.onError(error);
});
},
_offhook1: function()
_offhook1: function(mixer, headers, action)
{
//console.log('Rayo plugin _offhook1 ');
//console.log('Rayo plugin _offhook1 ' + mixer);
var that = this;
that.pc1 = new webkitRTCPeerConnection(null);
......@@ -100,7 +231,7 @@ Strophe.addConnectionPlugin('rayo',
var sdp = WebrtcSDP.buildSDP(sdpObj2);
//console.log(sdp);
that.pc1.setRemoteDescription(new RTCSessionDescription({type: "answer", sdp : sdp}));
that._offhook2();
that._offhook2(mixer, headers, action);
});
});
......@@ -115,12 +246,15 @@ Strophe.addConnectionPlugin('rayo',
};
},
_offhook2: function()
_offhook2: function(mixer, headers, action)
{
//console.log('Rayo plugin _offhook2 ' + this.cryptoSuite + " " + this.localCrypto + " " + this.remoteCrypto);
//console.log('Rayo plugin _offhook2 ' + this.cryptoSuite + " " + this.localCrypto + " " + this.remoteCrypto + " " + mixer);
var that = this;
var iq = $iq({to: "rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("offhook", {xmlns: Strophe.NS.RAYO_HANDSET, cryptoSuite: that.cryptoSuite, localCrypto: that.localCrypto, remoteCrypto: that.remoteCrypto, codec: that.handset.codec, stereo: that.handset.stereo, mixer: that.handset.mixer});
var stereo = (headers && headers.stereo) ? headers.stereo : "0";
var codec = (headers && headers.codec) ? headers.codec : "OPUS";
var iq = $iq({to: "rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("offhook", {xmlns: Strophe.NS.RAYO_HANDSET, cryptoSuite: that.cryptoSuite, localCrypto: that.localCrypto, remoteCrypto: that.remoteCrypto, codec: codec, stereo: stereo, mixer: mixer});
//console.log(iq.toString())
......@@ -139,15 +273,16 @@ Strophe.addConnectionPlugin('rayo',
that.pc2.addIceCandidate(new RTCIceCandidate({sdpMLineIndex: "0", candidate: "a=candidate:3707591233 1 udp 2113937151 " + that.relayHost + " " + that.relayRemotePort + " typ host generation 0"}));
that.pc1.addIceCandidate(new RTCIceCandidate({sdpMLineIndex: "0", candidate: "a=candidate:3707591233 1 udp 2113937151 " + that.relayHost + " " + that.relayLocalPort + " typ host generation 0"}));
action();
});
} else {
if (handset.onError) handset.onError("offhook failure");
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("offhook failure");
}
});
},
onhook: function()
_onhook: function()
{
//console.log('Rayo plugin onhook ' + this.handsetId);
......@@ -167,76 +302,66 @@ Strophe.addConnectionPlugin('rayo',
},
dial: function(config)
{
//console.log('Rayo plugin dial');
//console.log(config)
var callId = "rayo-call-" + Math.random().toString(36).substr(2,9);
_handlePresence: function(presence)
{
//console.log('Rayo plugin handlePresence');
//console.log(presence);
var that = this;
var from = $(presence).attr('from');
var headers = {}
var iq = $iq({to: "rayo." + this._connection.domain, from: this._connection.jid, type: "get"}).c("dial", {xmlns: Strophe.NS.RAYO_CORE, to: config.to, from: config.from});
iq.c("join", {xmlns: Strophe.NS.RAYO_CORE, 'mixer-name': this.handset.mixer}).up();
iq.c("header", {name: "call-id", value: callId}).up();
iq.c("header", {name: "handset", value: that.handsetId}).up();
if (config.headers)
{
for (var i=0; i<headers.length; i++)
$(presence).find('header').each(function()
{
iq.c("header", {name: config.headers[i].name, value: config.headers[i].value}).up();
}
}
var name = $(this).attr('name');
var value = $(this).attr('value');
//console.log(iq.toString());
headers[name] = value;
});
this._connection.sendIQ(iq, function(response)
$(presence).find('complete').each(function()
{
if ($(response).attr('type') != "result")
$(this).find('success').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_HANDSET_COMPLETE)
{
if (config.onError) config.onError("dial failure");
that._onhook();
}
});
});
this.calls[callId] =
$(presence).find('offer').each(function()
{
callId: callId,
onRing: config.onRing,
onAnswer: config.onAnswer,
onError: config.onError,
onEnd: config.onEnd,
from: config.from,
to: config.to,
hangup: function()
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
//console.log("hangup " + this.callId);
var callFrom = $(this).attr('from');
var callTo = $(this).attr('value');
var callId = Strophe.getNodeFromJid(from);
var iq = $iq({to: this.callId + "@rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("hangup", {xmlns: Strophe.NS.RAYO_CORE});
var call = {
digit: function(tone) {that.digit(callId, tone);},
hangup: function() {that.hangup(callId);},
answer: function(callId, headers) {that.answer(callId, headers);},
that._connection.sendIQ(iq, function(response)
{
if ($(response).attr('type') != "result")
{
if (config.onError) config.onError("hangup failure");
from: callFrom,
to: callTo,
id: callId
}
});
},
answer: function()
{
if (that.callbacks && that.callbacks.onOffer) that.callbacks.onOffer(call, headers);
},
var iq = $iq({to: from, from: that._connection.jid, type: "get"}).c("accept", {xmlns: Strophe.NS.RAYO_CORE});
digit: function(key)
var hdrs = Object.getOwnPropertyNames(headers)
for (var i=0; i< hdrs.length; i++)
{
//console.log("digit " + this.callId + " " + key);
var name = hdrs[i];
var value = headers[name];
var iq = $iq({to: this.callId + "@rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("dtmf", {xmlns: Strophe.NS.RAYO_CORE, tones: key});
iq.c("header", {name: name, value: value}).up();
}
//console.log(iq.toString());
......@@ -244,44 +369,17 @@ Strophe.addConnectionPlugin('rayo',
{
if ($(response).attr('type') != "result")
{
if (config.onError) config.onError("dtmf failure");
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("accept failure");
}
});
}
};
return this.calls[callId];
},
handlePresence: function(presence)
{
//console.log('Rayo plugin handlePresence');
//console.log(presence);
var that = this;
var from = $(presence).attr('from');
$(presence).find('complete').each(function()
{
$(this).find('success').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_HANDSET_COMPLETE)
{
that.onhook();
if (that.handset && that.handset.onEnd) that.handset.onEnd();
}
});
});
})
$(presence).find('joined').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId == Strophe.getNodeFromJid(from))
{
if (that.handset && that.handset.onReady) that.handset.onReady();
}
}
});
......@@ -289,41 +387,50 @@ Strophe.addConnectionPlugin('rayo',
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId == Strophe.getNodeFromJid(from))
{
if (that.handset && that.handset.onUnready) that.handset.onUnready();
}
}
});
$(presence).find('ringing').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId != Strophe.getNodeFromJid(from))
{
var callId = Strophe.getNodeFromJid(from);
var call = that.calls[callId];
if (call && call.onRing) call.onRing(call);
if (that.callbacks && that.callbacks.onRing) that.callbacks.onRing(callId, headers);
}
}
});
$(presence).find('answered').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId != Strophe.getNodeFromJid(from))
{
var callId = Strophe.getNodeFromJid(from);
var call = that.calls[callId];
if (call && call.onAnswer) call.onAnswer(call);
if (that.callbacks && that.callbacks.onAnswer) that.callbacks.onAnswer(callId, headers);
} else {
if (that.callbacks && that.callbacks.onReady) that.callbacks.onReady();
}
}
});
$(presence).find('end').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId != Strophe.getNodeFromJid(from))
{
var callId = Strophe.getNodeFromJid(from);
var call = that.calls[callId];
if (call && call.onEnd) call.onEnd(call);
that.calls[callId] = null;
if (that.callbacks && that.callbacks.onEnd) that.callbacks.onEnd(callId, headers);
} else {
if (that.callbacks && that.callbacks.onUnready) that.callbacks.onUnready();
}
}
});
......
......@@ -27,6 +27,7 @@ import java.net.InetSocketAddress;
import org.voicebridge.*;
import org.xmpp.jnodes.RelayChannel;
import java.util.*;
/**
* A Class to represent a call participant - a party in a call.
......@@ -90,6 +91,9 @@ public class CallParticipant {
private ProxyCredentials proxyCredentials = null;
private RelayChannel relayChannel = null;
private boolean autoAnswer = true;
private long startTimestamp = 0;
private long endTimestamp = 0;
private Map<String, String> headers = new HashMap<String, String>();
/*
* Second party in a two party call or target of migration
......@@ -123,9 +127,7 @@ public class CallParticipant {
this.proxyCredentials = proxyCredentials;
}
/**
* Get/Set proxy credentials
*/
public RelayChannel getRelayChannel()
{
return relayChannel;
......@@ -136,6 +138,35 @@ public class CallParticipant {
this.relayChannel = relayChannel;
}
public long getStartTimestamp()
{
return startTimestamp;
}
public void setStartTimestamp(long startTimestamp)
{
this.startTimestamp = startTimestamp;
}
public long getEndTimestamp()
{
return endTimestamp;
}
public void setEndTimestamp(long endTimestamp)
{
this.endTimestamp = endTimestamp;
}
public Map<String, String> getHeaders()
{
return headers;
}
public void setHeaders(Map<String, String> headers)
{
this.headers = headers;
}
/**
* Get call answer timeout
......
......@@ -30,6 +30,8 @@ import org.xmpp.packet.*;
import java.util.*;
import java.text.ParseException;
import java.net.URI;
import java.net.URISyntaxException;
import com.rayo.core.*;
import com.rayo.core.verb.*;
......@@ -39,6 +41,11 @@ import com.rayo.core.xml.providers.*;
import com.sun.voip.server.*;
import com.sun.voip.*;
import org.voicebridge.*;
public class RayoComponent extends AbstractComponent
implements TreatmentDoneListener,
CallEventListener,
......@@ -139,8 +146,6 @@ public class RayoComponent extends AbstractComponent
if (object instanceof ConnectCommand) {
} else if (object instanceof AcceptCommand) {
} else if (object instanceof HoldCommand) {
} else if (object instanceof UnholdCommand) {
......@@ -155,8 +160,11 @@ public class RayoComponent extends AbstractComponent
} else if (object instanceof UnjoinCommand) {
reply = handleUnjoinCommand((UnjoinCommand) object, iq);
} else if (object instanceof AcceptCommand) {
reply = handleAcceptCommand((AcceptCommand) object, iq);
} else if (object instanceof AnswerCommand) {
reply = handleAnswerCommand((AnswerCommand) object, iq);
} else if (object instanceof HangupCommand) {
reply = handleHangupCommand(iq);
......@@ -199,11 +207,7 @@ public class RayoComponent extends AbstractComponent
if (object instanceof OnHookCommand)
{
String key = iq.getTo().getNode();
if (key != null)
{
RelayChannel channel = plugin.getRelayChannel(iq.getTo().getNode());
RelayChannel channel = plugin.getRelayChannel(JID.escapeNode(iq.getFrom().toString()));
if (channel != null)
{
......@@ -213,11 +217,6 @@ public class RayoComponent extends AbstractComponent
reply.setError(PacketError.Condition.item_not_found);
}
} else {
reply.setError(PacketError.Condition.item_not_found);
}
} else {
final Handset handset = ((OffHookCommand) object).getHandset();
......@@ -371,6 +370,88 @@ public class RayoComponent extends AbstractComponent
}
private IQ handleAcceptCommand(AcceptCommand command, IQ iq)
{
Log.info("RayoComponent handleAcceptCommand " + iq.getFrom() + " " + iq.getTo().getNode());
IQ reply = IQ.createResultIQ(iq);
Map<String, String> headers = command.getHeaders();
try {
Presence presence = new Presence();
presence.setFrom(iq.getTo());
presence.setTo(JID.unescapeNode(iq.getTo().getNode()));
presence.getElement().add(rayoProvider.toXML(new RingingEvent(null, headers)));
sendPacket(presence);
} catch (Exception e) {
reply.setError(PacketError.Condition.item_not_found);
}
return reply;
}
private IQ handleAnswerCommand(AnswerCommand command, IQ iq)
{
Log.info("RayoComponent AnswerCommand " + iq.getFrom() + " " + iq.getTo().getNode());
IQ reply = IQ.createResultIQ(iq);
Map<String, String> headers = command.getHeaders();
try {
String handsetId = JID.escapeNode(iq.getFrom().toString());
Presence presence = new Presence();
presence.setFrom(iq.getTo());
presence.setTo(JID.unescapeNode(iq.getTo().getNode()));
presence.getElement().add(rayoProvider.toXML(new AnsweredEvent(null, headers)));
sendPacket(presence);
RelayChannel channel = plugin.getRelayChannel(handsetId);
if (channel != null)
{
Handset handset = channel.getHandset();
CallHandler callHandler = channel.getCallHandler();
if (callHandler != null)
{
Log.info("RayoComponent handleAnswerCommand found call handler " + callHandler);
CallParticipant cp = callHandler.getCallParticipant();
if (cp != null)
{
String username = iq.getFrom().getNode();
ConferenceManager conferenceManager = ConferenceManager.getConference( handset.mixer,
channel.getMediaPreference(),
username, false);
try {
cp.setStartTimestamp(System.currentTimeMillis());
cp.setHeaders(headers);
String recording = handset.mixer + "-" + cp.getStartTimestamp() + ".au";
conferenceManager.recordConference(true, recording, "au");
Config.createCallRecord(username, recording, "xmpp:" + iq.getFrom().toString(), cp.getStartTimestamp(), 0, "dialed") ;
} catch (ParseException e1) {
reply.setError(PacketError.Condition.internal_server_error);
}
}
}
}
} catch (Exception e) {
reply.setError(PacketError.Condition.item_not_found);
e.printStackTrace();
}
return reply;
}
private IQ handleHangupCommand(IQ iq)
{
Log.info("RayoComponent handleHangupCommand " + iq.getFrom());
......@@ -478,55 +559,90 @@ public class RayoComponent extends AbstractComponent
boolean toPhone = to.indexOf("sip:") == 0 || to.indexOf("tel:") == 0;
boolean toXmpp = to.indexOf("xmpp:") == 0;
String codec = headers.get("caller-id");
String handsetId = headers.get("handset");
String mixer = null;
String callId = headers.get("call-id");
String callerName = headers.get("caller-name");
String calledName = headers.get("called-name");
String handsetId = iq.getFrom().toString();
JoinCommand join = command.getJoin();
if (join != null && join.getTo() != null)
if (join != null)
{
if (join.getType() == JoinDestinationType.CALL) {
// TODO join.getTo()
} else {
mixer = join.getTo();
}
reply.setError(PacketError.Condition.feature_not_implemented);
} else {
if (callId == null)
{
callId = "rayo-call-" + System.currentTimeMillis();
headers.put("call-id", callId);
}
if (mixer != null)
if (callerName == null)
{
if (callId == null) callId = "rayo-call-" + System.currentTimeMillis();
if (callerName == null) callerName = iq.getFrom().toString();
callerName = iq.getFrom().getNode();
headers.put("caller-name", callerName);
}
CallParticipant cp = new CallParticipant();
cp.setVoiceDetection(true);
cp.setCallOwner(iq.getFrom().toString());
if (calledName == null)
{
calledName = to;
headers.put("called-name", calledName);
}
if (toPhone)
{
CallParticipant cp = new CallParticipant();
cp.setVoiceDetection(true);
cp.setCallOwner(handsetId);
cp.setMediaPreference("PCMU/8000/1");
cp.setProtocol("SIP");
cp.setCallId(callId);
cp.setDisplayName(callerName);
cp.setPhoneNumber(to);
cp.setName(calledName == null ? cp.getPhoneNumber() : calledName);
cp.setConferenceId(mixer);
cp.setName(calledName);
cp.setHeaders(headers);
reply = doPhoneAndPcCall(handsetId, cp, reply);
reply = doPhoneAndPcCall(JID.escapeNode(handsetId), cp, reply);
} else if (toXmpp){
} else {
String destination = to.substring(5);
String mixer = JID.escapeNode(destination);
Presence presence = new Presence();
presence.setFrom(mixer + "@rayo." + getDomain());
presence.setTo(new JID(destination));
headers.put("mixer-name", mixer);
OfferEvent offer = new OfferEvent(callId);
try {
offer.setFrom(new URI("xmpp:" + iq.getFrom().toString()));
offer.setTo(new URI(to));
} catch (URISyntaxException e) {
reply.setError(PacketError.Condition.feature_not_implemented);
return reply;
}
offer.setHeaders(headers);
presence.getElement().add(rayoProvider.toXML(offer));
sendPacket(presence);
} else {
reply.setError(PacketError.Condition.feature_not_implemented);
}
}
return reply;
}
......@@ -662,16 +778,14 @@ public class RayoComponent extends AbstractComponent
private IQ doPhoneAndPcCall(String handsetId, CallParticipant cp, IQ reply)
{
String mixer = cp.getConferenceId();
Log.info("RayoComponent doPhoneAndPcCall " + handsetId + " " + mixer);
Log.info("RayoComponent doPhoneAndPcCall " + handsetId);
RelayChannel channel = plugin.getRelayChannel(handsetId);
if (channel != null)
{
try {
setMixer(mixer, channel, reply);
setMixer(channel, reply, cp);
OutgoingCallHandler outgoingCallHandler = new OutgoingCallHandler(this, cp);
......@@ -696,15 +810,20 @@ public class RayoComponent extends AbstractComponent
return reply;
}
private void setMixer(String mixer, RelayChannel channel, IQ reply)
private void setMixer(RelayChannel channel, IQ reply, CallParticipant cp)
{
String username = channel.getFrom().getNode();
String mixer = channel.getHandset().mixer;
ConferenceManager conferenceManager = ConferenceManager.getConference( mixer,
channel.getMediaPreference(),
channel.getFrom().getNode(), false);
username, false);
try {
if (conferenceManager.getMemberList().size() == 0) {
conferenceManager.recordConference(true, mixer + "-" + System.currentTimeMillis() + ".au", "au");
}
cp.setConferenceId(mixer);
cp.setStartTimestamp(System.currentTimeMillis());
String recording = mixer + "-" + cp.getStartTimestamp() + ".au";
conferenceManager.recordConference(true, recording, "au");
Config.createCallRecord(cp.getDisplayName(), recording, cp.getPhoneNumber(), cp.getStartTimestamp(), 0, "dialed") ;
} catch (ParseException e1) {
reply.setError(PacketError.Condition.internal_server_error);
......@@ -737,18 +856,30 @@ public class RayoComponent extends AbstractComponent
String myEvent = com.sun.voip.CallEvent.getEventString(callEvent.getEvent());
String callState = callEvent.getCallState().toString();
Map<String, String> headers = new HashMap<String, String>();
headers.put("callId", callEvent.getCallId());
headers.put("info", callEvent.getCallInfo() == null ? "" : callEvent.getCallInfo());
headers.put("mixer", callEvent.getConferenceId() == null ? "" : callEvent.getConferenceId());
headers.put("callInfo", callEvent.getCallInfo() == null ? "" : callEvent.getCallInfo());
try {
CallHandler callHandler = CallHandler.findCall(callEvent.getCallId());
if (callHandler != null)
{
Log.info("RayoComponent callEventNotification found call handler " + callHandler);
CallParticipant cp = callHandler.getCallParticipant();
if (cp != null)
{
Log.info("RayoComponent callEventNotification found call paticipant " + cp);
Map<String, String> headers = cp.getHeaders();
headers.put("call-id", callEvent.getCallId());
headers.put("mixer-name", callEvent.getConferenceId());
Presence presence = new Presence();
presence.setFrom(callEvent.getCallId() + "@rayo." + getDomain());
presence.setTo(from);
if ("001 STATE CHANGED".equals(myEvent)) {
if ("001 STATE CHANGED".equals(myEvent))
{
if ("110 ANSWERED".equals(callState)) {
presence.getElement().add(rayoProvider.toXML(new RingingEvent(null, headers)));
sendPacket(presence);
......@@ -760,16 +891,28 @@ public class RayoComponent extends AbstractComponent
} else if ("299 ENDED".equals(callState)) {
presence.getElement().add(rayoProvider.toXML(new EndEvent(null, EndEvent.Reason.valueOf("HANGUP"), headers)));
sendPacket(presence);
if (cp.getStartTimestamp() > 0)
{
cp.setEndTimestamp(System.currentTimeMillis());
Config.updateCallRecord(cp.getStartTimestamp(), (int)((cp.getEndTimestamp() - cp.getStartTimestamp()) / 1000));
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(callEvent.getConferenceId());
conferenceManager.recordConference(false, null, null);
cp.setStartTimestamp(0);
}
}
} else if ("250 STARTED SPEAKING".equals(myEvent)) {
StartedSpeakingEvent speaker = new StartedSpeakingEvent();
speaker.setSpeakerId(headers.get("callId"));
speaker.setSpeakerId(callEvent.getCallId());
presence.getElement().add(rayoProvider.toXML(speaker));
sendPacket(presence);
} else if ("259 STOPPED SPEAKING".equals(myEvent)) {
StoppedSpeakingEvent speaker = new StoppedSpeakingEvent();
speaker.setSpeakerId(headers.get("callId"));
speaker.setSpeakerId(callEvent.getCallId());
presence.getElement().add(rayoProvider.toXML(speaker));
sendPacket(presence);
......@@ -785,6 +928,12 @@ public class RayoComponent extends AbstractComponent
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void initiated(String name, String callId)
{
Log.info( "RayoComponent initiated " + name + " " + callId);
......
......@@ -159,7 +159,7 @@ public class RayoPlugin implements Plugin, SessionEventListener {
try {
rc = RelayChannel.createLocalRelayChannel(bindAllInterfaces ? "0.0.0.0" : LocalIPResolver.getLocalIP(), 30000, 50000);
final int id = ids.incrementAndGet();
final String sId = "rayo-handset-" + String.valueOf(id);
final String sId = JID.escapeNode(jid.toString());
rc.setAttachment(sId);
rc.setFrom(jid, component);
rc.setCrypto(handset);
......
......@@ -4,6 +4,9 @@ import java.util.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
......@@ -20,6 +23,8 @@ import org.xmpp.packet.*;
public class Config implements MUCEventListener {
private static final Logger Log = LoggerFactory.getLogger(Config.class);
private MultiUserChatManager mucManager;
private HashMap<String, Conference> conferences;
private HashMap<String, Conference> confExtensions;
......@@ -59,7 +64,7 @@ public class Config implements MUCEventListener {
MUCEventDispatcher.addListener(this);
try {
System.out.println(String.format("VoiceBridge read site configuration"));
Log.info(String.format("VoiceBridge read site configuration"));
mucManager = XMPPServer.getInstance().getMultiUserChatManager();
......@@ -87,14 +92,15 @@ public class Config implements MUCEventListener {
processDefaultRegistration(username);
}
Log.info(String.format("VoiceBridge sip plugin assumed available"));
sipPlugin = true;
} else {
registerWithDefaultProxy();
}
}
} catch (Throwable t) {
t.printStackTrace();
}
......@@ -147,10 +153,10 @@ public class Config implements MUCEventListener {
registrars.add(sipAccount.getHost());
registrations.add(sipAccount);
System.out.println(String.format("VoiceBridge adding SIP registration: %s with user %s host %s", sipAccount.getXmppUserName(), sipAccount.getUserName(), sipAccount.getHost()));
Log.info(String.format("VoiceBridge adding SIP registration: %s with user %s host %s", sipAccount.getXmppUserName(), sipAccount.getUserName(), sipAccount.getHost()));
} catch (Exception e) {
System.out.println("registerWithDefaultProxy " + e);
Log.info("registerWithDefaultProxy " + e);
}
}
......@@ -176,20 +182,18 @@ public class Config implements MUCEventListener {
registrars.add(credentials.getHost());
registrations.add(credentials);
System.out.println(String.format("VoiceBridge adding SIP registration: %s with user %s host %s", credentials.getXmppUserName(), credentials.getUserName(), credentials.getHost()));
Log.info(String.format("VoiceBridge adding SIP registration: %s with user %s host %s", credentials.getXmppUserName(), credentials.getUserName(), credentials.getHost()));
} catch (Exception e) {
System.out.println(String.format("processDefaultRegistration Bad Address %s ", credentials.getHost()));
Log.info(String.format("processDefaultRegistration Bad Address %s ", credentials.getHost()));
}
}
rs.close();
pstmt.close();
con.close();
sipPlugin = true;
} catch (SQLException e) {
System.out.println("processDefaultRegistration " + e);
Log.info("processDefaultRegistration " + e);
}
}
......@@ -214,21 +218,19 @@ public class Config implements MUCEventListener {
registrars.add(credentials.getHost());
registrations.add(credentials);
System.out.println(String.format("VoiceBridge adding SIP registration: %s with user %s host %s", credentials.getXmppUserName(), credentials.getUserName(), credentials.getHost()));
Log.info(String.format("VoiceBridge adding SIP registration: %s with user %s host %s", credentials.getXmppUserName(), credentials.getUserName(), credentials.getHost()));
} catch (Exception e) {
System.out.println(String.format("processRegistrations Bad Address %s ", credentials.getHost()));
Log.info(String.format("processRegistrations Bad Address %s ", credentials.getHost()));
}
}
rs.close();
pstmt.close();
con.close();
sipPlugin = true;
} catch (SQLException e) {
System.out.println("processRegistrations " + e);
Log.info("processRegistrations " + e);
}
}
......@@ -261,7 +263,7 @@ public class Config implements MUCEventListener {
sipExtensions.put(username, sipAccount);
} catch (SQLException e) {
System.out.println("ProxyCredentials " + e);
Log.info("ProxyCredentials " + e);
}
return sipAccount;
......@@ -289,7 +291,7 @@ public class Config implements MUCEventListener {
} catch (SQLException e) {
System.out.println("updateStatus " + e);
Log.info("updateStatus " + e);
} finally {
DbConnectionManager.closeConnection(psmt, con);
......@@ -297,7 +299,11 @@ public class Config implements MUCEventListener {
}
}
public static void recordCall(String username, String addressFrom, String addressTo, long datetime, int duration, String calltype) {
public static void createCallRecord(String username, String addressFrom, String addressTo, long datetime, int duration, String calltype) {
if (sipPlugin)
{
Log.info("createCallRecord " + username + " " + addressFrom + " " + addressTo + " " + datetime);
String sql = "INSERT INTO ofSipPhoneLog (username, addressFrom, addressTo, datetime, duration, calltype) values (?, ?, ?, ?, ?, ?)";
......@@ -318,11 +324,41 @@ public class Config implements MUCEventListener {
psmt.executeUpdate();
} catch (SQLException e) {
Log.debug(e.getMessage(), e);
Log.error(e.getMessage(), e);
} finally {
DbConnectionManager.closeConnection(rs, psmt, con);
}
}
}
public static void updateCallRecord(long datetime, int duration) {
if (sipPlugin)
{
Log.info("updateCallRecord " + datetime + " " + duration);
String sql = "UPDATE ofSipPhoneLog SET duration = ? WHERE datetime = ?";
Connection con = null;
PreparedStatement psmt = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setInt(1, duration);
psmt.setLong(2, datetime);
psmt.executeUpdate();
} catch (SQLException e) {
Log.error(e.getMessage(), e);
} finally {
DbConnectionManager.closeConnection(psmt, con);
}
}
}
public ProxyCredentials getProxyCredentialsByUser(String username)
......@@ -370,7 +406,7 @@ public class Config implements MUCEventListener {
conferences.put(conference.id, conference);
System.out.println(String.format("VoiceBridge create conference: %s with pin %s extension %s", conference.id, conference.pin, conference.exten));
Log.info(String.format("VoiceBridge create conference: %s with pin %s extension %s", conference.id, conference.pin, conference.exten));
}
private void destroyConference(MUCRoom room)
......@@ -383,7 +419,7 @@ public class Config implements MUCEventListener {
Conference conference2 = confExtensions.remove(room.getName());
conference2 = null;
System.out.println(String.format("VoiceBridge destroy conference: %s", room.getName()));
Log.info(String.format("VoiceBridge destroy conference: %s", room.getName()));
}
}
......
......@@ -21,7 +21,6 @@ Strophe.addConnectionPlugin('rayo',
init: function(conn)
{
this._connection = conn;
this.calls = {};
Strophe.addNamespace('RAYO_CORE', "urn:xmpp:rayo:1");
Strophe.addNamespace('RAYO_CALL', "urn:xmpp:rayo:call:1");
......@@ -40,39 +39,171 @@ Strophe.addConnectionPlugin('rayo',
Strophe.addNamespace('RAYO_HANDSET', "urn:xmpp:rayo:handset:1");
Strophe.addNamespace('RAYO_HANDSET_COMPLETE', "urn:xmpp:rayo:handset:complete:1");
this._connection.addHandler(this.handlePresence.bind(this), null,"presence", null, null, null);
this._connection.addHandler(this._handlePresence.bind(this), null,"presence", null, null, null);
console.log('Rayo plugin initialised');
},
offhook: function(handset)
phone: function(callbacks)
{
//console.log('Rayo plugin offhook');
this.callbacks = callbacks;
},
if (this.handset && this.handset.mixer) // reuse mixer
hangup: function(callId)
{
handset.mixer = this.handset.mixer;
console.log("hangup " + callId);
var that = this;
var iq = $iq({to: callId + "@rayo." + this._connection.domain, from: this._connection.jid, type: "get"}).c("hangup", {xmlns: Strophe.NS.RAYO_CORE});
console.log(iq.toString());
that._connection.sendIQ(iq, function(response)
{
console.log(response);
if ($(response).attr('type') != "result")
{
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("hangup failure");
}
});
if (!handset.mixer) handset.mixer = "rayo-mixer-" + Math.random().toString(36).substr(2,9);
this._onhook();
},
digit: function(callId, key)
{
//console.log("digit " + callId + " " + key);
var that = this;
var iq = $iq({to: callId + "@rayo." + this._connection.domain, from: this._connection.jid, type: "get"}).c("dtmf", {xmlns: Strophe.NS.RAYO_CORE, tones: key});
that._connection.sendIQ(iq, function(response)
{
if ($(response).attr('type') != "result")
{
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("dtmf failure");
}
});
},
answer: function(callId, headers)
{
//console.log('Rayo plugin accept ' + callId);
//console.log(headers)
var that = this;
if (this._isOffhook()) this._onhook();
this._offhook(callId, headers, function()
{
var iq = $iq({to: "rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("answer", {xmlns: Strophe.NS.RAYO_CORE});
if (headers)
{
var hdrs = Object.getOwnPropertyNames(headers)
for (var i=0; i< hdrs.length; i++)
{
var name = hdrs[i];
var value = headers[name];
iq.c("header", {name: name, value: value}).up();
}
}
console.log(iq.toString());
that._connection.sendIQ(iq, function(response)
{
if ($(response).attr('type') != "result")
{
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("answer failure");
}
});
});
},
dial: function(from, to, headers)
{
//console.log('Rayo plugin dial ' + from + " " + to);
//console.log(headers)
var that = this;
var callId = "rayo-call-" + Math.random().toString(36).substr(2,9);
if (this._isOffhook()) this._onhook();
this._offhook(callId, headers, function()
{
var iq = $iq({to: "rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("dial", {xmlns: Strophe.NS.RAYO_CORE, to: to, from: from});
iq.c("header", {name: "call-id", value: callId}).up();
if (headers)
{
var hdrs = Object.getOwnPropertyNames(headers)
for (var i=0; i< hdrs.length; i++)
{
var name = hdrs[i];
var value = headers[name];
iq.c("header", {name: name, value: value}).up();
}
}
console.log(iq.toString());
that._connection.sendIQ(iq, function(response)
{
if ($(response).attr('type') != "result")
{
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("dial failure");
}
});
});
return {
digit: function(tone) {that.digit(callId, tone);},
hangup: function() {that.hangup(callId);},
from: from,
to: to,
id: callId
}
},
_isOffhook: function()
{
return this.localStream != null;
},
_offhook: function(mixer, headers, action)
{
//console.log('Rayo plugin offhook ' + mixer);
//console.log(headers);
this.handset = handset;
var that = this;
navigator.webkitGetUserMedia({audio:true, video:false}, function(stream)
{
that.localStream = stream;
that._offhook1();
that._offhook1(mixer, headers, action);
}, function(error) {
if (that.handset && that.handset.onError) that.handset.onError(error);
if (that.callbacks && that.callbacks.onError) that.callbacks.onError(error);
});
},
_offhook1: function()
_offhook1: function(mixer, headers, action)
{
//console.log('Rayo plugin _offhook1 ');
//console.log('Rayo plugin _offhook1 ' + mixer);
var that = this;
that.pc1 = new webkitRTCPeerConnection(null);
......@@ -100,7 +231,7 @@ Strophe.addConnectionPlugin('rayo',
var sdp = WebrtcSDP.buildSDP(sdpObj2);
//console.log(sdp);
that.pc1.setRemoteDescription(new RTCSessionDescription({type: "answer", sdp : sdp}));
that._offhook2();
that._offhook2(mixer, headers, action);
});
});
......@@ -115,12 +246,15 @@ Strophe.addConnectionPlugin('rayo',
};
},
_offhook2: function()
_offhook2: function(mixer, headers, action)
{
//console.log('Rayo plugin _offhook2 ' + this.cryptoSuite + " " + this.localCrypto + " " + this.remoteCrypto);
//console.log('Rayo plugin _offhook2 ' + this.cryptoSuite + " " + this.localCrypto + " " + this.remoteCrypto + " " + mixer);
var that = this;
var iq = $iq({to: "rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("offhook", {xmlns: Strophe.NS.RAYO_HANDSET, cryptoSuite: that.cryptoSuite, localCrypto: that.localCrypto, remoteCrypto: that.remoteCrypto, codec: that.handset.codec, stereo: that.handset.stereo, mixer: that.handset.mixer});
var stereo = (headers && headers.stereo) ? headers.stereo : "0";
var codec = (headers && headers.codec) ? headers.codec : "OPUS";
var iq = $iq({to: "rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("offhook", {xmlns: Strophe.NS.RAYO_HANDSET, cryptoSuite: that.cryptoSuite, localCrypto: that.localCrypto, remoteCrypto: that.remoteCrypto, codec: codec, stereo: stereo, mixer: mixer});
//console.log(iq.toString())
......@@ -139,15 +273,16 @@ Strophe.addConnectionPlugin('rayo',
that.pc2.addIceCandidate(new RTCIceCandidate({sdpMLineIndex: "0", candidate: "a=candidate:3707591233 1 udp 2113937151 " + that.relayHost + " " + that.relayRemotePort + " typ host generation 0"}));
that.pc1.addIceCandidate(new RTCIceCandidate({sdpMLineIndex: "0", candidate: "a=candidate:3707591233 1 udp 2113937151 " + that.relayHost + " " + that.relayLocalPort + " typ host generation 0"}));
action();
});
} else {
if (handset.onError) handset.onError("offhook failure");
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("offhook failure");
}
});
},
onhook: function()
_onhook: function()
{
//console.log('Rayo plugin onhook ' + this.handsetId);
......@@ -167,76 +302,66 @@ Strophe.addConnectionPlugin('rayo',
},
dial: function(config)
{
//console.log('Rayo plugin dial');
//console.log(config)
var callId = "rayo-call-" + Math.random().toString(36).substr(2,9);
_handlePresence: function(presence)
{
//console.log('Rayo plugin handlePresence');
//console.log(presence);
var that = this;
var from = $(presence).attr('from');
var headers = {}
var iq = $iq({to: "rayo." + this._connection.domain, from: this._connection.jid, type: "get"}).c("dial", {xmlns: Strophe.NS.RAYO_CORE, to: config.to, from: config.from});
iq.c("join", {xmlns: Strophe.NS.RAYO_CORE, 'mixer-name': this.handset.mixer}).up();
iq.c("header", {name: "call-id", value: callId}).up();
iq.c("header", {name: "handset", value: that.handsetId}).up();
if (config.headers)
{
for (var i=0; i<headers.length; i++)
$(presence).find('header').each(function()
{
iq.c("header", {name: config.headers[i].name, value: config.headers[i].value}).up();
}
}
var name = $(this).attr('name');
var value = $(this).attr('value');
//console.log(iq.toString());
headers[name] = value;
});
this._connection.sendIQ(iq, function(response)
$(presence).find('complete').each(function()
{
if ($(response).attr('type') != "result")
$(this).find('success').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_HANDSET_COMPLETE)
{
if (config.onError) config.onError("dial failure");
that._onhook();
}
});
});
this.calls[callId] =
$(presence).find('offer').each(function()
{
callId: callId,
onRing: config.onRing,
onAnswer: config.onAnswer,
onError: config.onError,
onEnd: config.onEnd,
from: config.from,
to: config.to,
hangup: function()
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
//console.log("hangup " + this.callId);
var callFrom = $(this).attr('from');
var callTo = $(this).attr('value');
var callId = Strophe.getNodeFromJid(from);
var iq = $iq({to: this.callId + "@rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("hangup", {xmlns: Strophe.NS.RAYO_CORE});
var call = {
digit: function(tone) {that.digit(callId, tone);},
hangup: function() {that.hangup(callId);},
answer: function(callId, headers) {that.answer(callId, headers);},
that._connection.sendIQ(iq, function(response)
{
if ($(response).attr('type') != "result")
{
if (config.onError) config.onError("hangup failure");
from: callFrom,
to: callTo,
id: callId
}
});
},
answer: function()
{
if (that.callbacks && that.callbacks.onOffer) that.callbacks.onOffer(call, headers);
},
var iq = $iq({to: from, from: that._connection.jid, type: "get"}).c("accept", {xmlns: Strophe.NS.RAYO_CORE});
digit: function(key)
var hdrs = Object.getOwnPropertyNames(headers)
for (var i=0; i< hdrs.length; i++)
{
//console.log("digit " + this.callId + " " + key);
var name = hdrs[i];
var value = headers[name];
var iq = $iq({to: this.callId + "@rayo." + that._connection.domain, from: that._connection.jid, type: "get"}).c("dtmf", {xmlns: Strophe.NS.RAYO_CORE, tones: key});
iq.c("header", {name: name, value: value}).up();
}
//console.log(iq.toString());
......@@ -244,44 +369,17 @@ Strophe.addConnectionPlugin('rayo',
{
if ($(response).attr('type') != "result")
{
if (config.onError) config.onError("dtmf failure");
if (that.callbacks && that.callbacks.onError) that.callbacks.onError("accept failure");
}
});
}
};
return this.calls[callId];
},
handlePresence: function(presence)
{
//console.log('Rayo plugin handlePresence');
//console.log(presence);
var that = this;
var from = $(presence).attr('from');
$(presence).find('complete').each(function()
{
$(this).find('success').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_HANDSET_COMPLETE)
{
that.onhook();
if (that.handset && that.handset.onEnd) that.handset.onEnd();
}
});
});
})
$(presence).find('joined').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId == Strophe.getNodeFromJid(from))
{
if (that.handset && that.handset.onReady) that.handset.onReady();
}
}
});
......@@ -289,41 +387,50 @@ Strophe.addConnectionPlugin('rayo',
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId == Strophe.getNodeFromJid(from))
{
if (that.handset && that.handset.onUnready) that.handset.onUnready();
}
}
});
$(presence).find('ringing').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId != Strophe.getNodeFromJid(from))
{
var callId = Strophe.getNodeFromJid(from);
var call = that.calls[callId];
if (call && call.onRing) call.onRing(call);
if (that.callbacks && that.callbacks.onRing) that.callbacks.onRing(callId, headers);
}
}
});
$(presence).find('answered').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId != Strophe.getNodeFromJid(from))
{
var callId = Strophe.getNodeFromJid(from);
var call = that.calls[callId];
if (call && call.onAnswer) call.onAnswer(call);
if (that.callbacks && that.callbacks.onAnswer) that.callbacks.onAnswer(callId, headers);
} else {
if (that.callbacks && that.callbacks.onReady) that.callbacks.onReady();
}
}
});
$(presence).find('end').each(function()
{
if ($(this).attr('xmlns') == Strophe.NS.RAYO_CORE)
{
if (that.handsetId != Strophe.getNodeFromJid(from))
{
var callId = Strophe.getNodeFromJid(from);
var call = that.calls[callId];
if (call && call.onEnd) call.onEnd(call);
that.calls[callId] = null;
if (that.callbacks && that.callbacks.onEnd) that.callbacks.onEnd(callId, headers);
} else {
if (that.callbacks && that.callbacks.onUnready) that.callbacks.onUnready();
}
}
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment