Commit b7ac7a29 authored by Dele Olajide's avatar Dele Olajide Committed by dele

Work in progress

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@13751 b35dd754-fafc-0310-a699-88a17e54d16e
parent 7c613d9c
......@@ -10,12 +10,10 @@
<minServerVersion>3.9.0</minServerVersion>
<adminconsole>
<tab id="tab-server">
<sidebar id="siderbar-rayo" name="${admin.item.rayo}">
<item id="rayo" name="${admin.item.rayo.settings.name}"
description="${admin.item.rayo.settings.description}" url="rayo.jsp"/>
<tab id="tab-rayo" name="Rayo" url="rayo.jsp" description="${admin.item.rayo.description}">
<sidebar id="siderbar-rayo" name="${admin.item.rayo.settings}">
<item id="rayo" name="${admin.item.rayo.settings.name}" description="${admin.item.rayo.settings.description}" url="rayo.jsp"/>
</sidebar>
</tab>
</adminconsole>
......
login.title = Admin Console
admin.item.rayo=Rayo
admin.item.rayo.settings.name=Rayo Status
admin.item.rayo.settings.description=XEP-0327:XMPP protocol extension for the third-party control of telephone calls and other similar media sessions.
admin.item.rayo.description=XEP-0327:XMPP protocol extension for the third-party control of telephone calls and other similar media sessions.
admin.item.rayo.settings=Settings
admin.item.rayo.settings.name=Rayo Settings
admin.item.rayo.settings.description=Configure Rayo
rayo.verified.ip=Verified Public IP
rayo.active.channels=Active Channels
rayo.settings.title=Rayo Status
rayo.verified.ip.warning=Rayo Requires a Public IP. Public IP Found:
rayo.settings.update.settings =Update Settings
rayo.settings.overrideip= Override Public IP
rayo.settings.invalid.publicip =Invalid Public IP Address
\ No newline at end of file
rayo.settings.invalid.publicip =Invalid Public IP Address
rayo.settings.title=Rayo Status
rayo.active.channels=Active Channels
/**
* $Revision $
* $Date $
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rayo.core.verb;
import javax.validation.Valid;
......@@ -24,21 +40,17 @@ public class Handset extends BaseVerb {
@NotNull(message=Handset.MISSING_REMOTE_CRYPTO)
public String remoteCrypto;
@NotNull(message=Handset.MISSING_MIXER)
public String mixer;
@NotNull(message=Handset.MISSING_CODEC)
public String codec;
@NotNull(message=Handset.MISSING_STEREO)
public String stereo;
public Handset(String cryptoSuite, String localCrypto, String remoteCrypto, String mixer, String codec, String stereo)
public Handset(String cryptoSuite, String localCrypto, String remoteCrypto, String codec, String stereo)
{
this.cryptoSuite = cryptoSuite;
this.localCrypto = localCrypto;
this.remoteCrypto = remoteCrypto;
this.mixer = mixer;
this.codec = codec;
this.stereo = stereo;
}
......@@ -52,7 +64,6 @@ public class Handset extends BaseVerb {
.append("cryptoSuite",cryptoSuite)
.append("localCrypto",localCrypto)
.append("remoteCrypto",remoteCrypto)
.append("mixer",mixer)
.append("codec",codec)
.append("stereo",stereo)
.toString();
......
/**
* $Revision $
* $Date $
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rayo.core.xml.providers;
import java.net.URISyntaxException;
......@@ -58,7 +74,6 @@ public class HandsetProvider extends BaseProvider {
Handset handset = new Handset( element.attributeValue("cryptoSuite"),
element.attributeValue("localCrypto"),
element.attributeValue("remoteCrypto"),
element.attributeValue("mixer"),
element.attributeValue("codec"),
element.attributeValue("stereo"));
return handset;
......@@ -98,7 +113,6 @@ public class HandsetProvider extends BaseProvider {
root.addAttribute("cryptoSuite", handset.cryptoSuite);
root.addAttribute("localCrypto", handset.localCrypto);
root.addAttribute("remoteCrypto", handset.cryptoSuite);
root.addAttribute("mixer", handset.mixer);
root.addAttribute("codec", handset.codec);
root.addAttribute("stereo", handset.stereo);
}
......
......@@ -2,8 +2,6 @@
* $Revision $
* $Date $
*
* Copyright (C) 2005-2010 Jive Software. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
......@@ -346,6 +344,81 @@ public class RayoComponent extends AbstractComponent
{
Log.info("RayoComponent handleDialCommand " + iq.getFrom());
Map<String, String> headers = command.getHeaders();
String bridged = headers.get("voicebridge");
if (bridged == null)
return handleHandsetDialCommand(command, iq);
else
return handleBridgedDialCommand(command, iq);
}
private IQ handleHandsetDialCommand(DialCommand command, IQ iq)
{
Log.info("RayoComponent handleHandsetDialCommand " + iq.getFrom());
final IQ reply = IQ.createResultIQ(iq);
Map<String, String> headers = command.getHeaders();
String from = command.getFrom().toString();
String to = command.getTo().toString();
boolean toPhone = to.indexOf("sip:") == 0 || to.indexOf("tel:") == 0;
boolean toXmpp = to.indexOf("xmpp:") == 0;
String codec = headers.get("caller-id");
String mixer = "rayo-mixer-" + System.currentTimeMillis();
String callerId = headers.get("caller-id");
String calledId = headers.get("called-id");
String callerName = headers.get("caller-name");
String calledName = headers.get("called-name");
JoinCommand join = command.getJoin();
if (join != null && join.getTo() != null)
{
if (join.getType() == JoinDestinationType.CALL) {
// TODO join.getTo()
} else {
mixer = join.getTo();
}
}
if (callerId == null) callerId = "rayo-caller-" + System.currentTimeMillis();
if (calledId == null) calledId = "rayo-called-" + System.currentTimeMillis();
CallParticipant cp = new CallParticipant();
cp.setVoiceDetection(true);
cp.setCallOwner(iq.getFrom().toString());
if (toPhone)
{
cp.setMediaPreference("PCMU/8000/1");
cp.setProtocol("SIP");
cp.setCallId(calledId);
cp.setPhoneNumber(to.substring(4));
cp.setName(calledName == null ? cp.getPhoneNumber() : calledName);
mixer = mixer == null ? cp.getPhoneNumber() : mixer;
cp.setConferenceId(mixer);
doPhoneAndPcCall(iq.getFrom(), cp, reply, mixer);
} else if (toXmpp){
} else {
reply.setError(PacketError.Condition.feature_not_implemented);
}
return reply;
}
private IQ handleBridgedDialCommand(DialCommand command, IQ iq)
{
Log.info("RayoComponent handleBridgedDialCommand " + iq.getFrom());
final IQ reply = IQ.createResultIQ(iq);
Map<String, String> headers = command.getHeaders();
......@@ -374,19 +447,18 @@ public class RayoComponent extends AbstractComponent
}
}
if (callerId == null) callerId = "ray-caller-" + System.currentTimeMillis();
if (calledId == null) calledId = "ray-called-" + System.currentTimeMillis();
if (callerId == null) callerId = "rayo-caller-" + System.currentTimeMillis();
if (calledId == null) calledId = "rayo-called-" + System.currentTimeMillis();
CallParticipant cp = new CallParticipant();
cp.setConferenceId(mixer);
cp.setMediaPreference("PCMU/8000/1");
cp.setProtocol("SIP");
cp.setVoiceDetection(true);
cp.setCallOwner(iq.getFrom().toString());
if (fromPhone && toPhone) // Phone to Phone
{
cp.setMediaPreference("PCMU/8000/1");
cp.setProtocol("SIP");
cp.setCallId(calledId);
cp.setPhoneNumber(to.substring(4));
cp.setName(calledName == null ? cp.getPhoneNumber() : calledName);
......@@ -402,6 +474,9 @@ public class RayoComponent extends AbstractComponent
} else { // TwoParty, use a mixer
if (mixer == null) mixer = cp.getPhoneNumber();
cp.setConferenceId(mixer);
TwoPartyCallHandler callHandler = new TwoPartyCallHandler(this, cp);
callHandler.start();
}
......@@ -413,13 +488,18 @@ public class RayoComponent extends AbstractComponent
} else if (fromPhone && !toPhone) { // Phone to PC
cp.setMediaPreference("PCMU/8000/1");
cp.setProtocol("SIP");
cp.setCallId(callerId);
cp.setPhoneNumber(from.substring(4));
cp.setName(callerName == null ? cp.getPhoneNumber() : callerName);
if (mixer == null) mixer = cp.getPhoneNumber();
cp.setConferenceId(mixer);
if (toHandset) // (no offer)
{
doPhonePcCall(new JID(to.substring(8)), cp, reply, mixer);
doPhoneAndPcCall(new JID(to.substring(8)), cp, reply, mixer);
} else { // (offer)
......@@ -428,13 +508,18 @@ public class RayoComponent extends AbstractComponent
} else if (!fromPhone && toPhone) { // PC to Phone
cp.setMediaPreference("PCMU/8000/1");
cp.setProtocol("SIP");
cp.setCallId(calledId);
cp.setPhoneNumber(to.substring(4));
cp.setName(calledName == null ? cp.getPhoneNumber() : calledName);
if (mixer == null) mixer = cp.getPhoneNumber();
cp.setConferenceId(mixer);
if (fromHandset) // (no offer)
{
doPhonePcCall(new JID(from.substring(8)), cp, reply, mixer);
doPhoneAndPcCall(new JID(from.substring(8)), cp, reply, mixer);
} else { // (offer)
......@@ -459,28 +544,20 @@ public class RayoComponent extends AbstractComponent
return reply;
}
private void doPhonePcCall(JID handsetJid, CallParticipant cp, IQ reply, String mixer)
private void doPhoneAndPcCall(JID handsetJid, CallParticipant cp, IQ reply, String mixer)
{
Log.info("RayoComponent doPhonePcCall " + handsetJid + " " + mixer);
Log.info("RayoComponent doPhoneAndPcCall " + handsetJid + " " + mixer);
RelayChannel channel = plugin.getRelayChannel(handsetJid.getNode());
if (channel != null)
{
Handset handset = channel.getHandset();
if (mixer == null) // no join request, use handset mixer
{
cp.setConferenceId(handset.mixer);
} else { // explicit mixer, transfer handset to mixer
try {
IncomingCallHandler.transferCall(channel.getAttachment(), mixer);
try {
setMixer(mixer, channel, reply);
IncomingCallHandler.transferCall(channel.getAttachment(), mixer);
} catch (Exception e) {
reply.setError(PacketError.Condition.internal_server_error);
}
} catch (Exception e) {
reply.setError(PacketError.Condition.internal_server_error);
}
OutgoingCallHandler outgoingCallHandler = new OutgoingCallHandler(this, cp);
......@@ -491,6 +568,22 @@ public class RayoComponent extends AbstractComponent
}
}
private void setMixer(String mixer, RelayChannel channel, IQ reply)
{
ConferenceManager conferenceManager = ConferenceManager.getConference( mixer,
channel.getMediaPreference(),
channel.getFrom().getNode(), false);
try {
if (conferenceManager.getMemberList().size() == 0) {
conferenceManager.recordConference(true, mixer + "-" + System.currentTimeMillis() + ".au", "au");
}
} catch (ParseException e1) {
reply.setError(PacketError.Condition.internal_server_error);
}
}
private IQ handleHandset(Handset handset, IQ iq)
{
Log.info("RayoComponent handleHandset " + iq.getFrom());
......@@ -559,7 +652,7 @@ public class RayoComponent extends AbstractComponent
CallParticipant cp = new CallParticipant();
cp.setCallId(channel.getAttachment());
cp.setProtocol("WebRtc");
cp.setConferenceId(handset.mixer);
cp.setConferenceId(defaultIncomingConferenceId);
cp.setMediaPreference(mediaPreference);
cp.setRelayChannel(channel);
cp.setDisplayName(channel.getAttachment());
......@@ -742,6 +835,18 @@ public class RayoComponent extends AbstractComponent
sendPacket(presence);
}
}
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(conferenceEvent.getConferenceId());
if (conferenceManager.getMemberList().size() == 0) {
conferenceManager.recordConference(false, null, null);
conferenceManager.endConference(conferenceEvent.getConferenceId());
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
......
......@@ -293,7 +293,15 @@ public class RayoPlugin implements Plugin, SessionEventListener {
{
try
{
File recordingFolderPath = new File(JiveGlobals.getHomeDirectory() + File.separator + "recordings");
File rayoFolderPath = new File(JiveGlobals.getHomeDirectory() + File.separator + "rayo");
if(!rayoFolderPath.exists())
{
rayoFolderPath.mkdirs();
}
File recordingFolderPath = new File(JiveGlobals.getHomeDirectory() + File.separator + "rayo" + File.separator + "recordings");
if(!recordingFolderPath.exists())
{
......@@ -301,7 +309,7 @@ public class RayoPlugin implements Plugin, SessionEventListener {
}
File soundsFolderPath = new File(JiveGlobals.getHomeDirectory() + File.separator + "sounds");
File soundsFolderPath = new File(JiveGlobals.getHomeDirectory() + File.separator + "rayo" + File.separator + "sounds");
if(!soundsFolderPath.exists())
{
......
......@@ -44,7 +44,7 @@ public class Application implements CallEventListener {
System.setProperty("com.sun.voip.server.BRIDGE_LOG", "bridge.log");
System.setProperty("com.sun.voip.server.LOGLEVEL", "99");
System.setProperty("com.sun.voip.server.PUBLIC_IP_ADDRESS", config.getPublicHost());
System.setProperty("com.sun.voip.server.Bridge.recordDirectory", pluginDirectory.getAbsolutePath() + File.separator + ".." + File.separator + ".." + File.separator + "recordings");
System.setProperty("com.sun.voip.server.Bridge.recordDirectory", pluginDirectory.getAbsolutePath() + File.separator + ".." + File.separator + ".." + File.separator + "rayo" + File.separator + "recordings");
System.setProperty("freetts.voices", "com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory");
Properties properties = new Properties();
......
/**
* $Revision $
* $Date $
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xmpp.jnodes;
import org.slf4j.Logger;
......@@ -270,7 +286,7 @@ public class RelayChannel {
remoteCryptoKey = BitAssistant.subArray(remoteCryptoByte, Integer.valueOf(0), Integer.valueOf(16));
remoteCryptoSalt = BitAssistant.subArray(remoteCryptoByte, Integer.valueOf(16), Integer.valueOf(14));
Log.info("Crypto Suite " + handset.cryptoSuite + " " + handset.localCrypto + " " + handset.remoteCrypto + " " + handset.mixer + " " + handset.codec + " " + handset.stereo);
Log.info("Crypto Suite " + handset.cryptoSuite + " " + handset.localCrypto + " " + handset.remoteCrypto + " " + " " + handset.codec + " " + handset.stereo);
try {
encryptor = new Encryptor(SDPCryptoSuite.getEncryptionMode(handset.cryptoSuite), localCryptoKey, localCryptoSalt, remoteCryptoKey, remoteCryptoSalt);
......@@ -289,32 +305,28 @@ public class RelayChannel {
if (decoder == 0) Log.error( "Opus decoder creation error ");
if (encoder == 0) Log.error( "Opus encoder creation error ");
String mediaPreference = "PCMU/8000/1";
if (handset.codec == null || "OPUS".equals(handset.codec))
mediaPreference = "PCM/48000/2";
if (decoder == 0 || encoder == 0)
{
mediaPreference = "PCMU/8000/1";
handset.codec = "PCMU";
Log.warn( "Opus encoder/decoder creation failure, PCMU will be used in default");
}
ConferenceManager.createConference(handset.mixer, mediaPreference, getAttachment());
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(handset.mixer);
if (conferenceManager.getMemberList().size() == 0) {
conferenceManager.recordConference(true, handset.mixer + "-" + System.currentTimeMillis() + ".au", "au");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public String getMediaPreference()
{
String mediaPreference = "PCMU/8000/1";
if (handset.codec == null || "OPUS".equals(handset.codec))
mediaPreference = "PCM/48000/2";
return mediaPreference;
}
public void close() {
try {
channelA.close();
......@@ -339,19 +351,6 @@ public class RelayChannel {
if (callHandler != null) callHandler.cancelRequest("Channel closing..");
try {
ConferenceManager conferenceManager = ConferenceManager.findConferenceManager(handset.mixer);
if (conferenceManager.getMemberList().size() == 0) {
conferenceManager.recordConference(false, null, null);
conferenceManager.endConference(handset.mixer);
}
} catch (Exception e) {
e.printStackTrace();
}
if (decoder != 0)
{
Opus.decoder_destroy(decoder);
......@@ -520,7 +519,7 @@ public class RelayChannel {
decoded = true;
//Log.info("Decoded media " + " " + packet2.getPayloadType() + " " + packet2.getSequenceNumber() + " " + packet2.getTimestamp());
if (packet2.getPayloadType() == 0 && handset.mixer != null) // PCMU (uLaw), mix audio
if (packet2.getPayloadType() == 0) // PCMU (uLaw), mix audio
{
packet = encryptor.decryptRTP(data);
......@@ -547,7 +546,7 @@ public class RelayChannel {
}
} else Log.warn("cannot decode packet " + packet2.getPayloadType() + " " + packet2.getSequenceNumber() + " " + packet2.getTimestamp());
} else if (packet2.getPayloadType() == 111 && handset.mixer != null) { // OPUS, decode and mix audio
} else if (packet2.getPayloadType() == 111) { // OPUS, decode and mix audio
packet = encryptor.decryptRTP(data);
......
/**
* $Revision $
* $Date $
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xmpp.jnodes;
import org.xmpp.jnodes.nio.PublicIPResolver;
......
/**
* RAYO XMPP extensions
*
*
*/
Strophe.addConnectionPlugin('rayo', {
_connection: null,
init: function(conn) {
this._connection = conn;
/* extend name space
* NS.RAYO - XMPP -0327
*
*/
Strophe.addNamespace('RAYO_CORE', "urn:xmpp:rayo:1");
Strophe.addNamespace('RAYO_CALL', "urn:xmpp:rayo:call:1");
Strophe.addNamespace('RAYO_MIXER', "urn:xmpp:rayo:mixer:1");
Strophe.addNamespace('RAYO_EXT', "urn:xmpp:rayo:ext:1");
Strophe.addNamespace('RAYO_EXT_COMPLETE', "urn:xmpp:rayo:ext:complete:1");
Strophe.addNamespace('RAYO_INPUT', "urn:xmpp:rayo:input:1");
Strophe.addNamespace('RAYO_INPUT_COMPLETE', "urn:xmpp:rayo:input:complete:1");
Strophe.addNamespace('RAYO_OUTPUT', "urn:xmpp:rayo:output:1");
Strophe.addNamespace('RAYO_OUTPUT_COMPLETE', "urn:xmpp:rayo:output:complete:1");
Strophe.addNamespace('RAYO_PROMPT', "urn:xmpp:rayo:promprt:1");
Strophe.addNamespace('RAYO_RECORD', "urn:xmpp:rayo:record:1");
Strophe.addNamespace('RAYO_RECORD_COMPLETE', "urn:xmpp:rayo:record:complete:1");
Strophe.addNamespace('RAYO_SAY', "urn:xmpp:tropo:say:1");
Strophe.addNamespace('RAYO_SAY_COMPLETE', "urn:xmpp:tropo:say:complete:1");
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);
},
handset: function(config)
{
this.config = config;
var self = this;
var iq = $iq({to: server, from: this._connection.jid, type: "get"})
.c("handset", {xmlns: Strophe.NS.RAYO_HANDSET, cryptoSuite: config.cryptoSuite, localCrypto: config.localCrypto, remoteCrypto: config.remoteCrypto, mixer: config.mixer, codec: config.codec, stereo: config.stereo});
this._connection.sendIQ(iq, function(response)
{
$('ref', response).each(function()
{
var ref = {host: $(this).attr('host'), localport: $(this).attr('localport'), remoteport: $(this).attr('remoteport'), id: $(this).attr('id'), uri: $(this).attr('uri')}
self.config.onStart(ref);
});
});
},
handlePresence: function(presence)
{
}
});
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