Commit 81a9161d authored by Dele Olajide's avatar Dele Olajide

ofmeet plugin version 0.2.1

Updated Jitsi Videobridge to latest code
Fixed issues with Jigasi voip gateway
Added Multicast RTP to Jigasi voip gateway
parent 8877da14
......@@ -49,6 +49,14 @@
Openfire Meetings Plugin Changelog
</h1>
<p><b>0.2.1</b> -- Oct 8th, 2015</p>
<ul>
<li>Updated Jitsi Videobridge to latest code</li>
<li>Fixed issues with Jigasi voip gateway</li>
<li>Added Multicast RTP to Jigasi voip gateway</li>
</ul>
<p><b>0.2.0</b> -- Aug 29th, 2015</p>
<ul>
......
handlers= java.util.logging.ConsoleHandler
#handlers= java.util.logging.ConsoleHandler, com.agafua.syslog.SyslogHandler
java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.formatter = net.java.sip.communicator.util.ScLogFormatter
......@@ -7,4 +8,10 @@ java.util.logging.ConsoleHandler.formatter = net.java.sip.communicator.util.ScLo
.level=INFO
# FIXME: remove once RTT issue is fixed
org.jitsi.impl.neomedia.MediaStreamStatsImpl.level=WARNING
\ No newline at end of file
org.jitsi.impl.neomedia.MediaStreamStatsImpl.level=WARNING
# Syslog(uncomment handler to use)
com.agafua.syslog.SyslogHandler.transport = udp
com.agafua.syslog.SyslogHandler.facility = local0
com.agafua.syslog.SyslogHandler.port = 514
com.agafua.syslog.SyslogHandler.hostname = localhost
......@@ -5,8 +5,8 @@
<name>Openfire Meetings</name>
<description>Provides high quality, scalable video conferences using Jitsi Meet and Jitsi Videobridge</description>
<author>Ignite Realtime</author>
<version>0.2.0</version>
<date>08/29/2015</date>
<version>0.2.1</version>
<date>10/08/2015</date>
<minServerVersion>3.9.9</minServerVersion>
<adminconsole>
......@@ -14,9 +14,8 @@
<sidebar id="siderbar-ofmeet" name="${plugin.title}">
<item id="ofmeet-summary" name="${config.page.summary.title}" description="${config.page.summary.description}" url="ofmeet-summary.jsp"/>
<item id="ofmeet-settings" name="${config.page.settings.title}" description="${config.page.settings.description}" url="ofmeet-settings.jsp"/>
<item id="ofmeet-planner" name="${config.page.planner.title}" description="${config.page.planner.description}" url="ofmeet-planner.jsp"/>
</sidebar>
<item id="ofmeet-planner" name="${config.page.planner.title}" description="${config.page.planner.description}" url="ofmeet-planner.jsp"/>
</sidebar>
</tab>
</adminconsole>
</plugin>
......@@ -57,7 +57,7 @@
<div>
<p>Ignite Realtime is pleased to announce "Openfire Meetings", a new plugin for Openfire that continues the development of the ofmeet web application which was part of the now deprecated <a href="https://community.igniterealtime.org/community/support/jitsi_videobridge_plugin">Jitsi-videobridge plugin</a>.</p>
<p style="min-height: 8pt; padding: 0px;">&nbsp;</p><p><strong>PLEASE NOTE</strong> - You will need latest Openfire 3.10.0 to use this plugin. Use a nightly build or wait for the imminent official release.</p>
<p style="min-height: 8pt; padding: 0px;">&nbsp;</p><p><strong>PLEASE NOTE</strong> - You will need at least Openfire 3.10.0 to use this plugin. You will also need the <a href="https://chrome.google.com/webstore/detail/openfire-meetings-chrome/fohfnhgabmicpkjcpjpjongpijcffaba?hl=en-GB">Openfire Meetings Chrome extension</a> for screen sharing, co-browsing and application sharing.</p>
<p><a href="https://community.igniterealtime.org/servlet/JiveServlet/showImage/38-1730-22181/ofmeet1.png"><img alt="ofmeet1.png" height="272" src="https://community.igniterealtime.org/servlet/JiveServlet/downloadImage/38-1730-22181/432-272/ofmeet1.png" style="width:432px; height: 272.438709677419px;" width="432"/></a></p>
<p style="min-height: 8pt; padding: 0px;">&nbsp;</p><p>Openfire Meetings is a complete standalone plugin powered by Jitsi Videobridge. It does not depend on any other plugins. It can be enhanced by adding the optional client control and fastpath plugins. The client control plugin will enable the management and user provisioning of PDF presentation urls and conference bookmarks. Users can select presentations and conferences from a pull down list.</p><p style="min-height: 8pt; padding: 0px;">&nbsp;</p>
<p><a href="https://community.igniterealtime.org/servlet/JiveServlet/showImage/38-1730-22275/ofmeet3.png"><img alt="ofmeet3.png" height="160" src="https://community.igniterealtime.org/servlet/JiveServlet/downloadImage/38-1730-22275/428-160/ofmeet3.png" style="width:428px; height: 160.325732899023px;" width="428"/></a></p>
......
......@@ -1729,27 +1729,44 @@ $(document).bind("pinnedendpointchanged", function(event, userJid) {
function callSipButtonClicked()
{
if ($("#sipCallButton > a").hasClass("glow"))
var button = $("#sipCallButton > a");
if (button.hasClass("glow"))
{
connection.rayo.hang_up(); // BAO
$("#sipCallButton > a").removeClass("glow")
button.removeClass("glow")
} else {
var defaultNumber
= config.defaultSipNumber ? config.defaultSipNumber : '';
var phoneList = '<datalist id="phoneLabel">'
messageHandler.openTwoButtonDialog(null,
'<h2>Enter SIP number</h2>' +
'<input id="sipNumber" type="text"' +
for (var i=0; i<connection.ofmuc.urls.length; i++)
{
if (connection.ofmuc.urls[i].url.indexOf("mrtp:") == 0 || connection.ofmuc.urls[i].url.indexOf("sip:") == 0 || connection.ofmuc.urls[i].url.indexOf("tel:") == 0)
{
phoneList = phoneList + '<option value="' + connection.ofmuc.urls[i].url + '">' + connection.ofmuc.urls[i].name + '</option>'
}
}
phoneList = phoneList + '</datalist>'
var defaultNumber = config.defaultSipNumber ? config.defaultSipNumber : '';
messageHandler.openTwoButtonDialog
(
null,
'<h2>Add Telephone Participant</h2>Enter a sip: uri or tel: uri or mrtp: uri or telephone number' + phoneList +
'<input id="sipNumber" list="phoneLabel" type="text"' +
' value="' + defaultNumber + '" autofocus>',
false,
"Dial",
function (e, v, m, f) {
if (v) {
var numberInput = document.getElementById('sipNumber');
if (numberInput.value) {
connection.rayo.dial(
numberInput.value, roomName, roomName); // BAO
if (numberInput.value)
{
connection.rayo.dial(numberInput.value, roomName, roomName); // BAO
button.addClass("glow");
}
}
},
......@@ -1757,7 +1774,7 @@ function callSipButtonClicked()
function (event) {
document.getElementById('sipNumber').focus();
}
);
);
}
}
......
......@@ -327,11 +327,11 @@ var ChromeUi = (function(self) {
{
console.log('background-ui.js load event');
chrome.systemIndicator.enable();
//chrome.systemIndicator.enable();
chrome.browserAction.onClicked.addListener(function()
{
ChromeUi.doOptions();
ChromeUi.doOptions();
});
chrome.windows.onRemoved.addListener(function(win)
......@@ -377,20 +377,7 @@ var ChromeUi = (function(self) {
delete callbacks[notificationId];
});
}
})
chrome.systemIndicator.onClicked.addListener(function()
{
console.log("background-ui.js systemIndicator.onClicked");
if (windowClosed)
{
ChromeUi.createRootWindow();
} else {
ChromeUi.destroyRootWindow();
}
});
})
chrome.runtime.onMessageExternal.addListener(function(request, sender, sendResponse)
{
......@@ -417,6 +404,8 @@ var ChromeUi = (function(self) {
});
ChromeUi.createRootWindow();
});
window.addEventListener("beforeunload", function ()
......
......@@ -25,13 +25,7 @@
"minimum_chrome_version": "34",
"name": "Openfire Meetings Chrome Extension",
"permissions": [ "desktopCapture", "background", "management", "idle", "notifications", "tabs", "http://*/*", "https://*/*" ],
"short_name": "ofmeet chrome extension",
"system_indicator": {
"default_icon": {
"19": "icon16.png",
"38": "icon48.png"
}
},
"short_name": "ofmeet chrome extension",
"options_page": "options/index.html",
"version": "0.0.6"
}
\ No newline at end of file
<script>
document.title = "Openfire Meetings"
</script>
\ No newline at end of file
plugin.title=Meetings
plugin.description=Openfire Meetings
config.page.configuration.enabled=Enabled
config.page.configuration.disabled=Disabled
config.page.summary.title=Meetings Summary
......@@ -82,6 +83,7 @@ config.page.configuration.record.secret=Recording Password/Secret
config.page.configuration.advanced.features.title=Advanced Features
config.page.configuration.focus.jid=Focus JID
config.page.configuration.focus.password=Focus Password
ofmeet.conference.summary=Below is an overview of meetings.
ofmeet.conference.expired=Conference has been expired.
ofmeet.summary.conferences=Total Conferences
......
......@@ -17,10 +17,8 @@
package org.ifsoft.sip;
import java.io.IOException;
import java.util.Date;
import java.util.LinkedList;
import java.util.Vector;
import java.io.*;
import java.util.*;
import java.net.*;
import javax.sdp.Attribute;
......@@ -47,6 +45,13 @@ import org.jitsi.service.libjitsi.*;
import org.xmpp.packet.*;
import org.jitsi.jigasi.openfire.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
import net.sf.fmj.media.rtp.*;
import org.jivesoftware.util.JiveGlobals;
/**
*
* Represents a call, contains the information for the Jingle as well as the sip side of the call
......@@ -55,9 +60,11 @@ import org.jitsi.jigasi.openfire.*;
public class CallSession
{
private static final Logger Log = LoggerFactory.getLogger(CallSession.class);
private static LinkedList<Payload> supported = new LinkedList<Payload>();
public SSRCFactoryImpl ssrcFactory = new SSRCFactoryImpl();
private long initialLocalSSRC = ssrcFactory.doGenerateSSRC() & 0xFFFFFFFFL;
public static Payload PAYLOAD_SPEEX = new Payload(99, "speex", 16000, 22000);
public static Payload PAYLOAD_SPEEX2 = new Payload(98, "speex", 8000, 11000);
public static Payload PAYLOAD_PCMU = new Payload(0, "PCMU", 8000, 64000);
......@@ -67,6 +74,10 @@ public class CallSession
public static VPayload PAYLOAD_H264 = new VPayload(97, "H264", 90000, 512000, 640, 480, 15);
public static VPayload PAYLOAD_H264SVC = new VPayload(96, "H264-SVC", 90000, 512000, 640, 480, 15);
private int remotePort;
private String remoteParty;
private boolean started = false;
static
{
......@@ -147,14 +158,13 @@ public class CallSession
public long startTimestamp = 0;
private CallControlComponent callControl;
private RtpChannel channel;
public CallSession(MediaStream mediaStream, String host, CallControlComponent callControl, String callId, String focusJID, String roomJID)
public CallSession(Conference conference, String host, CallControlComponent callControl, String callId, String focusJID, String roomJID)
{
Log.info("CallSession creation " + host);
this.mediaStream = mediaStream;
this.callControl = callControl;
this.callId = callId;
this.focusJID = focusJID;
......@@ -166,18 +176,45 @@ public class CallSession
answerPayloads.add(PAYLOAD_PCMU);
try {
MediaService mediaService = LibJitsi.getMediaService();
Content content = conference.getOrCreateContent("audio");
mediaStream = mediaService.createMediaStream(null, org.jitsi.service.neomedia.MediaType.AUDIO, null);
mediaStream.setName("ofmeet-" + System.currentTimeMillis());
boolean useAudioMixer = false;
String useAudioString = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.audio.mixer"); // BAO
if (useAudioString != null) useAudioMixer = useAudioString.equals("true");
if (useAudioMixer)
{
mediaStream.setSSRCFactory(ssrcFactory);
mediaStream.setDevice(content.getMixer());
} else {
mediaStream.setRTPTranslator(content.getRTPTranslator());
}
InetAddress bindAddr = InetAddress.getByName(host);
connector = new DefaultStreamConnector(bindAddr);
connector.getDataSocket();
connector.getControlSocket();
mediaStream.setDirection(MediaDirection.RECVONLY);
mediaStream.setConnector(connector);
mediaStream.start();
mediaStream.setConnector(connector);
mediaStream.addDynamicRTPPayloadType((byte)0, mediaService.getFormatFactory().createMediaFormat("PCMU", 8000, 1));
mediaStream.setFormat(mediaService.getFormatFactory().createMediaFormat("PCMU", 8000, 1));
//channel = content.createRtpChannel(null, RawUdpTransportPacketExtension.NAMESPACE, false);
//mediaStream = channel.getStream();
//channel.setRTPLevelRelayType(RTPLevelRelayType.MIXER);
//connector = channel.getTransportManager().getStreamConnector(channel);
//mediaStream.addDynamicRTPPayloadType((byte)111, mediaService.getFormatFactory().createMediaFormat("opus", 48000, 2));
//channel.getTransportManager().payloadTypesChanged(channel);
} catch (Exception e) {
Log.error("CallSession failure", e);
}
}
public void sendBye()
......@@ -638,7 +675,6 @@ public class CallSession
}
sd.setMediaDescriptions(mds);
Log.info("buildSDP " + sd);
return sd;
}
catch (SdpException e)
......@@ -686,8 +722,8 @@ public class CallSession
}
}
int remotePort = media.getMediaPort();
String remoteParty = null;
remotePort = media.getMediaPort();
if (md.getConnection() != null)
{
remoteParty = md.getConnection().getAddress();
......@@ -710,7 +746,8 @@ public class CallSession
int codec = Integer.parseInt(fields[0]);
String name = fields[1].split("/")[0];
int clockRate = Integer.parseInt(fields[1].split("/")[1]);
Log.debug("[[" + internalCallId + "]] Payload " + codec + " rate " + clockRate + " is mapped to " + name);
Log.info("[[" + internalCallId + "]] Payload " + codec + " rate " + clockRate + " is mapped to " + name);
if (codec >= 96)
{
......@@ -735,8 +772,8 @@ public class CallSession
}
else
{
int remotePort = media.getMediaPort();
String remoteParty = null;
remotePort = media.getMediaPort();
if (md.getConnection() != null)
{
remoteParty = md.getConnection().getAddress();
......@@ -746,19 +783,7 @@ public class CallSession
remoteParty = sd.getConnection().getAddress();
}
InetAddress remoteAddr = InetAddress.getByName(remoteParty);
Log.info("CallSession parseSDP " + remoteAddr + " " + remoteParty + " " + remotePort);
MediaService mediaService = LibJitsi.getMediaService();
mediaStream.setTarget(new MediaStreamTarget(new InetSocketAddress(remoteAddr, remotePort),new InetSocketAddress(remoteAddr, remotePort + 1)));
mediaStream.addDynamicRTPPayloadType((byte)111, mediaService.getFormatFactory().createMediaFormat("opus", 48000, 2));
mediaStream.addDynamicRTPPayloadType((byte)0, mediaService.getFormatFactory().createMediaFormat("PCMU", 8000, 1));
mediaStream.setFormat(mediaService.getFormatFactory().createMediaFormat("PCMU", 8000, 1));
mediaStream.setDirection(MediaDirection.SENDRECV);
Log.info("CallSession parseSDP " + remoteParty + " " + remotePort);
@SuppressWarnings("unchecked")
Vector<String> codecs = (Vector<String>) media.getMediaFormats(false);
......@@ -794,7 +819,8 @@ public class CallSession
int codec = Integer.parseInt(fields[0]);
String name = fields[1].split("/")[0];
int clockRate = Integer.parseInt(fields[1].split("/")[1]);
Log.debug("[[" + internalCallId + "]] Payload " + codec + " rate " + clockRate + " is mapped to " + name);
Log.info("[[" + internalCallId + "]] Payload " + codec + " rate " + clockRate + " is mapped to " + name);
if (codec >= 96)
{
......@@ -818,6 +844,18 @@ public class CallSession
}
}
try {
InetAddress remoteAddr = InetAddress.getByName(remoteParty);
Log.info("CallSession buildSDP " + remoteAddr + " " + remoteParty + " " + remotePort + "\n" + sd);
mediaStream.setTarget(new MediaStreamTarget(new InetSocketAddress(remoteAddr, remotePort),new InetSocketAddress(remoteAddr, remotePort + 1)));
mediaStream.setDirection(MediaDirection.SENDRECV);
mediaStream.start();
} catch (Exception e) {
Log.error("Error building SDP", e);
}
callControl.inviteEvent(true, callId);
}
catch (Exception e)
......@@ -833,4 +871,40 @@ public class CallSession
parseSDP(new String(message.getRawContent()), true);
}
private long ssrcFactoryGenerateSSRC(String cause, int i)
{
if (initialLocalSSRC != -1)
{
if (i == 0)
return (int) initialLocalSSRC;
else if (cause.equals(GenerateSSRCCause.REMOVE_SEND_STREAM.name()))
return Long.MAX_VALUE;
}
return ssrcFactory.doGenerateSSRC();
}
private class SSRCFactoryImpl implements SSRCFactory
{
private int i = 0;
/**
* The <tt>Random</tt> instance used by this <tt>SSRCFactory</tt> to
* generate new synchronization source (SSRC) identifiers.
*/
private final Random random = new Random();
public int doGenerateSSRC()
{
return random.nextInt();
}
/**
* {@inheritDoc}
*/
@Override
public long generateSSRC(String cause)
{
return ssrcFactoryGenerateSSRC(cause, i++);
}
}
}
......@@ -243,10 +243,13 @@ public class SipService
}
else
{
req = cs.sipDialog.createRequest(Request.BYE);
ClientTransaction t = sipProvider.getNewClientTransaction(req);
cs.sipDialog.sendRequest(t);
cs.sendBye();
if (cs.sipDialog != null)
{
req = cs.sipDialog.createRequest(Request.BYE);
ClientTransaction t = sipProvider.getNewClientTransaction(req);
cs.sipDialog.sendRequest(t);
cs.sendBye();
}
}
}
catch (SipException e)
......
......@@ -1157,7 +1157,7 @@ public class VideoBridgeSipListener implements SipListener
*/
public boolean doAuthenticate(Request request, AuthorizationHeader authHeader, String user, String password)
{
Log.info("doAuthenticate " + user + " " + password);
Log.info("doAuthenticate " + user + " " + password + " " + authHeader.getRealm() + " " + defaultRealm + " " + authHeader.getURI());
String username = authHeader.getUsername();
if (username == null || !username.equals(user))
......
......@@ -21,6 +21,7 @@ import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.provider.*;
import java.util.*;
import org.jivesoftware.util.JiveGlobals;
/**
* Default implementation of {@link OperationSetColibriConference} that uses
......@@ -141,13 +142,12 @@ public class OperationSetColibriConferenceImpl
ColibriConferenceIQ allocateRequest
= colibriBuilder.getRequest(jitsiVideobridge);
boolean useAudioMixer = false;
ColibriConferenceIQ.Content colibriContent = allocateRequest.getContent("audio");
String useAudioString = System.getProperty("org.jitsi.videobridge.ofmeet.audio.mixer"); // BAO
boolean useAudioMixer = false;
String useAudioString = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.audio.mixer"); // BAO
if (useAudioString != null) useAudioMixer = useAudioString.equals("true");
ColibriConferenceIQ.Content colibriContent = allocateRequest.getContent("audio");
if (useAudioMixer && colibriContent != null)
{
logger.info("audio mixer set " + colibriContent);
......
......@@ -57,7 +57,8 @@ public class JicofoPlugin
{
Log.info("JicofoPlugin - using focus " + focusUserJid + ":" + hostName);
//System.setProperty("org.jitsi.videobridge.ofmeet.audio.mixer", JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.audio.mixer", "false"));
System.setProperty("org.jitsi.videobridge.ofmeet.audio.mixer", JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.audio.mixer", "false"));
System.setProperty("org.jitsi.videobridge.ofmeet.sip.enabled", JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.sip.enabled", "false"));
System.setProperty("net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED", "true");
System.setProperty(FocusManager.HOSTNAME_PNAME, hostName);
......
......@@ -35,6 +35,7 @@ public class JingleOfferFactory
public static ContentPacketExtension createContentForMedia(
MediaType mediaType, boolean enableFirefoxHacks)
{
ContentPacketExtension content
= new ContentPacketExtension(
ContentPacketExtension.CreatorEnum.initiator,
......@@ -58,34 +59,42 @@ public class JingleOfferFactory
URI.create("urn:ietf:params:rtp-hdrext:ssrc-audio-level"));
rtpDesc.addExtmap(ssrcAudioLevel);
// a=rtpmap:111 opus/48000/2
PayloadTypePacketExtension opus
= new PayloadTypePacketExtension();
opus.setId(111);
opus.setName("opus");
opus.setClockrate(48000);
opus.setChannels(2);
rtpDesc.addPayloadType(opus);
// fmtp:111 minptime=10
ParameterPacketExtension opusMinptime
= new ParameterPacketExtension();
opusMinptime.setName("minptime");
opusMinptime.setValue("10");
opus.addParameter(opusMinptime);
// a=rtpmap:103 ISAC/16000
PayloadTypePacketExtension isac16
= new PayloadTypePacketExtension();
isac16.setId(103);
isac16.setName("ISAC");
isac16.setClockrate(16000);
rtpDesc.addPayloadType(isac16);
// a=rtpmap:104 ISAC/32000
PayloadTypePacketExtension isac32
= new PayloadTypePacketExtension();
isac32.setId(104);
isac32.setName("ISAC");
isac32.setClockrate(32000);
rtpDesc.addPayloadType(isac32);
boolean sipEnabled = false;
String sipEnabledString = System.getProperty("org.jitsi.videobridge.ofmeet.sip.enabled"); // BAO
if (sipEnabledString != null) sipEnabled = sipEnabledString.equals("true");
if (sipEnabled == false)
{
// a=rtpmap:111 opus/48000/2
PayloadTypePacketExtension opus
= new PayloadTypePacketExtension();
opus.setId(111);
opus.setName("opus");
opus.setClockrate(48000);
opus.setChannels(2);
rtpDesc.addPayloadType(opus);
// fmtp:111 minptime=10
ParameterPacketExtension opusMinptime
= new ParameterPacketExtension();
opusMinptime.setName("minptime");
opusMinptime.setValue("10");
opus.addParameter(opusMinptime);
// a=rtpmap:103 ISAC/16000
PayloadTypePacketExtension isac16
= new PayloadTypePacketExtension();
isac16.setId(103);
isac16.setName("ISAC");
isac16.setClockrate(16000);
rtpDesc.addPayloadType(isac16);
// a=rtpmap:104 ISAC/32000
PayloadTypePacketExtension isac32
= new PayloadTypePacketExtension();
isac32.setId(104);
isac32.setName("ISAC");
isac32.setClockrate(32000);
rtpDesc.addPayloadType(isac32);
}
// a=rtpmap:0 PCMU/8000
PayloadTypePacketExtension pcmu
= new PayloadTypePacketExtension();
......
......@@ -32,7 +32,12 @@ import org.slf4j.*;
import org.slf4j.Logger;
import net.java.sip.communicator.impl.protocol.jabber.extensions.rayo.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
import net.java.sip.communicator.util.*;
import net.sf.fmj.media.rtp.*;
import org.dom4j.*;
import org.jitsi.jigasi.*;
import org.osgi.framework.*;
......@@ -62,17 +67,18 @@ import net.sf.fmj.media.rtp.*;
import org.ifsoft.rtp.*;
import uk.nominet.DDDS.*;
public class CallControlComponent extends AbstractComponent
{
private static final Logger Log = LoggerFactory.getLogger(JigasiPlugin.class);
public SSRCFactoryImpl ssrcFactory = new SSRCFactoryImpl();
private long initialLocalSSRC = ssrcFactory.doGenerateSSRC() & 0xFFFFFFFFL;
public ConcurrentHashMap<String, CallSession> callSessions = new ConcurrentHashMap<String, CallSession>();
public ConcurrentHashMap<String, String> conferences = new ConcurrentHashMap<String, String>();
public ConcurrentHashMap<String, String> registrations = new ConcurrentHashMap<String, String>();
public static CallControlComponent self;
private SipService sipService = null;
private MultiUserChatManager mucManager = XMPPServer.getInstance().getMultiUserChatManager();
private String hostName;
private Videobridge getVideobridge()
{
......@@ -85,7 +91,14 @@ public class CallControlComponent extends AbstractComponent
self = this;
Properties properties = new Properties();
String hostName = JiveGlobals.getProperty("org.jitsi.videobridge.nat.harvester.public.address", XMPPServer.getInstance().getServerInfo().getXMPPDomain());
hostName = JiveGlobals.getProperty("org.jitsi.videobridge.nat.harvester.public.address", XMPPServer.getInstance().getServerInfo().getHostname());
try {
hostName = InetAddress.getByName(hostName).getHostAddress();
} catch (Exception e) {
}
String logDir = pluginDirectory.getAbsolutePath() + File.separator + ".." + File.separator + ".." + File.separator + "logs" + File.separator;
String port = JiveGlobals.getProperty("org.jitsi.videobridge.sip.port.number", "5060");
......@@ -106,7 +119,7 @@ public class CallControlComponent extends AbstractComponent
sipService = new SipService(properties);
} else {
Log.info("CallControlComponent -enabling SIP gateway");
Log.info("CallControlComponent - disabling SIP gateway");
}
}
......@@ -166,35 +179,19 @@ public class CallControlComponent extends AbstractComponent
Log.info("CallControlComponent - makeCall " + confJid + " " + to + " " + callId);
try {
String hostname = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
String callerId = (new JID(confJid)).getNode();
String focusJid = conference.getFocus();
MediaService mediaService = LibJitsi.getMediaService();
MediaStream mediaStream = mediaService.createMediaStream(null, org.jitsi.service.neomedia.MediaType.AUDIO, mediaService.createSrtpControl(SrtpControlType.MIKEY));
mediaStream.setName("rayo-" + System.currentTimeMillis());
Content content = conference.getOrCreateContent("audio");
boolean audioMixer = "true".equals(JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.audio.mixer", "false"));
if (audioMixer)
{
mediaStream.setSSRCFactory(ssrcFactory);
mediaStream.setDevice(content.getMixer());
} else {
mediaStream.setRTPTranslator(content.getRTPTranslator());
}
content.createRtpChannel(null, null, null);
CallSession cs = new CallSession(mediaStream, hostname, this, callId, focusJid, confJid);
CallSession cs = new CallSession(conference, hostName, this, callId, focusJid, confJid);
callSessions.put(callId, cs);
boolean toSip = to.indexOf("sip:") == 0 ;
boolean toPhone = to.indexOf("tel:") == 0;
String from = null;
boolean toMulticast = to.indexOf("mrtp:") == 0;
if (!toSip && !toPhone)
String from = "sip:" + callerId + "@" + hostName;
if (!toSip && !toPhone && !toMulticast)
{
String sipUri = null;
......@@ -233,18 +230,18 @@ public class CallControlComponent extends AbstractComponent
if (toSip)
{
from = "sip:" + callerId + "@" + hostname;
from = "sip:" + callerId + "@" + hostName;
Log.info("CallControlComponent - makeCall with direct sip " + to + " " + from);
} else {
} else if (toPhone) {
to = to.substring(4);
if (registrations.containsKey(to))
{
to = registrations.get(to);
from = "sip:" + callerId + "@" + hostname;
from = "sip:" + callerId + "@" + hostName;
Log.info("CallControlComponent - makeCall with registration " + to + " " + from);
......@@ -265,14 +262,29 @@ public class CallControlComponent extends AbstractComponent
return;
}
}
} else if (toMulticast) {
String params[] = to.split(":");
InetAddress remoteAddr = InetAddress.getByName(params[1]);
cs.mediaStream.setTarget(new MediaStreamTarget(new InetSocketAddress(remoteAddr, Integer.parseInt(params[2])), null));
cs.mediaStream.setDirection(MediaDirection.SENDONLY);
cs.mediaStream.start();
}
cs.jabberRemote = to;
cs.jabberLocal = from;
cs.username = username;
cs.startTimestamp = startTimestamp;
SipService.sendInvite(cs);
if (!toMulticast)
{
cs.jabberRemote = to;
SipService.sendInvite(cs);
} else {
cs.jabberRemote = "multicast";
inviteEvent(true, callId);
}
} catch (Exception e) {
......@@ -284,11 +296,18 @@ public class CallControlComponent extends AbstractComponent
{
Log.info("hangupCall " + callId);
CallSession cs = callSessions.remove(callId);
CallSession cs = callSessions.get(callId);
if (cs != null)
{
SipService.sendBye(cs);
if (cs.jabberRemote != null && cs.jabberRemote.startsWith("multicast"))
{
cs.sendBye();
} else {
SipService.sendBye(cs);
}
updateCallRecord(cs.startTimestamp, (int)(System.currentTimeMillis() - cs.startTimestamp));
} else {
......@@ -301,14 +320,13 @@ public class CallControlComponent extends AbstractComponent
Log.info("CallControlComponent - findCreateSession " + from + " " + to + " " + destination);
CallSession session = null;
String hostname = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
String callerId = to;
String confJID = null;
Conference conference = null;
boolean allowDirectSIP = "true".equals(JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.allow.direct.sip", "false"));
if (!allowDirectSIP || !registrations.containsKey(from))
if (!allowDirectSIP && !registrations.containsKey(from))
{
Log.warn("CallControlComponent - call rejected from " + from + " " + to);
return null; // only accept calls from registered SIP user endpoint
......@@ -330,6 +348,8 @@ public class CallControlComponent extends AbstractComponent
if (confJID != null) break;
}
Log.info("CallControlComponent - findCreateSession conference looking for id " + confJID);
if (confJID != null && conferences.containsKey(confJID))
{
String confId = conferences.get(confJID);
......@@ -352,25 +372,8 @@ public class CallControlComponent extends AbstractComponent
try
{
MediaService mediaService = LibJitsi.getMediaService();
MediaStream mediaStream = mediaService.createMediaStream(null, org.jitsi.service.neomedia.MediaType.AUDIO, mediaService.createSrtpControl(SrtpControlType.MIKEY));
mediaStream.setName("rayo-" + System.currentTimeMillis());
Content content = conference.getOrCreateContent("audio");
boolean audioMixer = "true".equals(JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.audio.mixer", "false"));
if (audioMixer)
{
mediaStream.setSSRCFactory(ssrcFactory);
mediaStream.setDevice(content.getMixer());
} else {
mediaStream.setRTPTranslator(content.getRTPTranslator());
}
content.createRtpChannel(null, null, null);
String callId = Long.toHexString(System.currentTimeMillis());
session = new CallSession(mediaStream, hostname, this, callId, conference.getFocus(), confJID);
session = new CallSession(conference, hostName, this, callId, conference.getFocus(), confJID);
session.jabberRemote = from;
session.jabberLocal = to;
......@@ -382,6 +385,8 @@ public class CallControlComponent extends AbstractComponent
{
Log.error("CallControlComponent findCreateSession", e);
}
} else {
Log.warn("conferennce not found " + confJID);
}
if (session != null)
......@@ -481,6 +486,8 @@ public class CallControlComponent extends AbstractComponent
Log.error("CallControlComponent inviteEvent. error" + session.roomJID, e);
}
if (!accepted) callSessions.remove(callId);
} else {
Log.error("CallControlComponent inviteEvent. cannot find callid " + callId);
}
......@@ -685,43 +692,6 @@ public class CallControlComponent extends AbstractComponent
return reply;
}
private long ssrcFactoryGenerateSSRC(String cause, int i)
{
if (initialLocalSSRC != -1)
{
if (i == 0)
return (int) initialLocalSSRC;
else if (cause.equals(GenerateSSRCCause.REMOVE_SEND_STREAM.name()))
return Long.MAX_VALUE;
}
return ssrcFactory.doGenerateSSRC();
}
private class SSRCFactoryImpl implements SSRCFactory
{
private int i = 0;
/**
* The <tt>Random</tt> instance used by this <tt>SSRCFactory</tt> to
* generate new synchronization source (SSRC) identifiers.
*/
private final Random random = new Random();
public int doGenerateSSRC()
{
return random.nextInt();
}
/**
* {@inheritDoc}
*/
@Override
public long generateSSRC(String cause)
{
return ssrcFactoryGenerateSSRC(cause, i++);
}
}
private void sendPacket(Packet packet)
{
try {
......
......@@ -71,6 +71,8 @@ public class OpenfireEventService implements LoggingService
// }
// ]
if ("focus_created".equals(e.getName())) return;
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", e.getName());
......
......@@ -237,7 +237,6 @@ Strophe.addConnectionPlugin('ofmuc', {
var jid = null;
var videoSpanId = null;
var node = null;
var button = $("#sipCallButton > a");
$(packet).find('header').each(function()
{
......@@ -280,8 +279,6 @@ Strophe.addConnectionPlugin('ofmuc', {
$(container).attr("title", Strophe.getBareJidFromJid(jid));
}
}
button.addClass("glow");
});
$(packet).find('hangup').each(function()
......@@ -301,8 +298,7 @@ Strophe.addConnectionPlugin('ofmuc', {
$(container).hide();
VideoLayout.resizeThumbnails();
}
}
button.removeClass("glow");
}
});
return true;
......@@ -600,7 +596,10 @@ Strophe.addConnectionPlugin('ofmuc', {
for (var i=0; i<that.urls.length; i++)
{
if (that.urls[i].url.indexOf(".pdf") == -1 ) appsList = appsList + '<option value="' + that.urls[i].url + '">' + that.urls[i].name + '</option>'
if (that.urls[i].url.indexOf(".pdf") == -1 && that.urls[i].url.indexOf("mrtp:") == -1 )
{
appsList = appsList + '<option value="' + that.urls[i].url + '">' + that.urls[i].name + '</option>'
}
}
appsList = appsList + '</select>'
......
#Sample config with one XMPP and one SIP account configured
# Replace {sip-pass-hash} with SIP user password hash
# as well as other account properties
# Name of default JVB room that will be joined if no special header is included
# in SIP invite
org.jitsi.jigasi.DEFAULT_JVB_ROOM_NAME=dele123
net.java.sip.communicator.impl.protocol.SingleCallInProgressPolicy.enabled=false
# Adjust opus encoder complexity
net.java.sip.communicator.impl.neomedia.codec.audio.opus.encoder.COMPLEXITY=10
net.java.sip.communicator.impl.neomedia.codec.audio.opus.encoder.FEC=false
# Disables packet logging
net.java.sip.communicator.packetlogging.PACKET_LOGGING_ENABLED=true
net.java.sip.communicator.impl.protocol.sip.acc1403273890647=acc1403273890647
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.ACCOUNT_UID=SIP\:bbbuser@192.168.1.253
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.PASSWORD=c2VjcmV0
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.PROTOCOL_NAME=SIP
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.SERVER_ADDRESS=192.168.1.253
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.USER_ID=bbbuser@192.168.1.253
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.KEEP_ALIVE_INTERVAL=25
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.KEEP_ALIVE_METHOD=OPTIONS
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.Encodings.PCMU/8000=650
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.Encodings.telephone-event/8000=1
net.java.sip.communicator.impl.protocol.sip.acc1403273890647.OVERRIDE_ENCODINGS=false
net.java.sip.communicator.SIP_PREFERRED_CLEAR_PORT=5080
net.java.sip.communicator.SIP_PREFERRED_SECURE_PORT=5081
# We can use the prefix org.jitsi.jigasi.xmpp.acc to override any of the
# properties that will be used for creating xmpp account for communication.
# The following two props assume we are using jigasi on the same machine as
# the xmpp server.
org.jitsi.jigasi.xmpp.acc.IS_SERVER_OVERRIDDEN=true
org.jitsi.jigasi.xmpp.acc.SERVER_ADDRESS=192.168.1.253
# If you want jigasi to perform authenticated login instead of anonymous login
# to the XMPP server, you can set the following properties.
org.jitsi.jigasi.xmpp.acc.USER_ID=deleolajide@btg199251
org.jitsi.jigasi.xmpp.acc.PASS=969131
org.jitsi.jigasi.xmpp.acc.ANONYMOUS_AUTH=false
# If you want to use the SIP user part of the incoming/outgoing call SIP URI
# you can set the following property to true.
# org.jitsi.jigasi.USE_SIP_USER_AS_XMPP_RESOURCE=true
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