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());
......
/*
* Jitsi Videobridge, OpenSource video conferencing.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jitsi.videobridge.xmpp;
import java.util.*;
import net.java.sip.communicator.impl.protocol.jabber.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*;
import org.jitsi.videobridge.*;
import org.jitsi.videobridge.osgi.*;
import org.osgi.framework.*;
import org.xmpp.component.*;
import org.xmpp.packet.*;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
/**
* Implements <tt>org.xmpp.component.Component</tt> to provide Jitsi Videobridge
* as an internal Jabber component.
*
* @author Lyubomir Marinov
*/
public class ComponentImpl
extends AbstractComponent
implements BundleActivator
{
private static final org.jitsi.util.Logger logger
= org.jitsi.util.Logger.getLogger(ComponentImpl.class);
/**
* The (default) description of <tt>ComponentImpl</tt> instances.
*/
private static final String DESCRIPTION
= "Jitsi Videobridge Jabber Component";
/**
* The (default) name of <tt>ComponentImpl</tt> instances.
*/
private static final String NAME = "JitsiVideobridge";
/**
* The (default) sub-domain of the address with which <tt>ComponentImpl</tt>
* instances are to be added to their respective <tt>ComponentManager</tt>s.
*/
public static final String SUBDOMAIN = "jitsi-videobridge";
/**
* Gets the <tt>ComponentImpl</tt> instances registered as OSGi services in
* a specific <tt>BundleContext</tt>.
*
* @param bundleContext the <tt>BundleContext</tt> from which the registered
* <tt>ComponentImpl</tt> instances registered as OSGi services are to be
* returned
* @return the <tt>ComponentImpl</tt> instances registered as OSGi services
* in the specified <tt>bundleContext</tt>
*/
public static Collection<ComponentImpl> getComponents(
BundleContext bundleContext)
{
return ServiceUtils2.getServices(bundleContext, ComponentImpl.class);
}
/**
* Logs a specific <tt>String</tt> at debug level.
*
* @param s the <tt>String</tt> to log at debug level
*/
private static void logd(String s)
{
logger.info(s);
}
/**
* Logs a specific <tt>Throwable</tt> at error level.
*
* @param t the <tt>Throwable</tt> to log at error level
*/
private static void loge(Throwable t)
{
t.printStackTrace(System.err);
}
/**
* The <tt>BundleContext</tt> in which this instance has been started as an
* OSGi bundle.
*/
private BundleContext bundleContext;
/**
* Initializes a new <tt>ComponentImpl</tt> instance.
*/
public ComponentImpl()
{
}
/**
* {@inheritDoc}
*
* Gets the namespaces of features that this <tt>Component</tt>
* offers/supports i.e. {@link ColibriConferenceIQ#NAMESPACE}.
*/
@Override
protected String[] discoInfoFeatureNamespaces()
{
return
new String[]
{
ColibriConferenceIQ.NAMESPACE,
ProtocolProviderServiceJabberImpl
.URN_XMPP_JINGLE_DTLS_SRTP,
ProtocolProviderServiceJabberImpl
.URN_XMPP_JINGLE_ICE_UDP_1,
ProtocolProviderServiceJabberImpl
.URN_XMPP_JINGLE_RAW_UDP_0
};
}
/**
* {@inheritDoc}
*
* Gets the type of the Service Discovery Identity of this
* <tt>Component</tt> i.e. &quot;conference&quot;.
*/
@Override
protected String discoInfoIdentityCategoryType()
{
return "conference";
}
/**
* Gets the OSGi <tt>BundleContext</tt> in which this Jabber component is
* executing.
*
* @return the OSGi <tt>BundleContext</tt> in which this Jabber component is
* executing
*/
public BundleContext getBundleContext()
{
return bundleContext;
}
/**
* Gets the description of this <tt>Component</tt>.
*
* @return the description of this <tt>Component</tt>
* @see Component#getDescription()
*/
@Override
public String getDescription()
{
return DESCRIPTION;
}
/**
* Gets the name of this <tt>Component</tt>.
*
* @return the name of this <tt>Component</tt>
* @see Component#getName()
*/
@Override
public String getName()
{
return NAME;
}
public Videobridge getVideobridge()
{
BundleContext bundleContext = getBundleContext();
Videobridge videobridge;
if (bundleContext == null)
{
videobridge = null;
}
else
{
videobridge
= ServiceUtils2.getService(bundleContext, Videobridge.class);
}
return videobridge;
}
/**
* Handles a <tt>ColibriConferenceIQ</tt> stanza which represents a request.
*
* @param conferenceIQ the <tt>ColibriConferenceIQ</tt> stanza represents
* the request to handle
* @return an <tt>org.jivesoftware.smack.packet.IQ</tt> stanza which
* represents the response to the specified request or <tt>null</tt> to
* reply with <tt>feature-not-implemented</tt>
* @throws Exception to reply with <tt>internal-server-error</tt> to the
* specified request
*/
private org.jivesoftware.smack.packet.IQ handleColibriConferenceIQ(
ColibriConferenceIQ conferenceIQ)
throws Exception
{
Videobridge videobridge = getVideobridge();
org.jivesoftware.smack.packet.IQ iq;
if (videobridge == null)
iq = null;
else
iq = videobridge.handleColibriConferenceIQ(conferenceIQ);
return iq;
}
/**
* Handles a <tt>GracefulShutdownIQ</tt> stanza which represents a request.
*
* @param shutdownIQ the <tt>GracefulShutdownIQ</tt> stanza represents
* the request to handle
* @return an <tt>org.jivesoftware.smack.packet.IQ</tt> stanza which
* represents the response to the specified request or <tt>null</tt> to
* reply with <tt>feature-not-implemented</tt>
* @throws Exception to reply with <tt>internal-server-error</tt> to the
* specified request
*/
private org.jivesoftware.smack.packet.IQ handleGracefulShutdownIQ(
GracefulShutdownIQ shutdownIQ)
throws Exception
{
Videobridge videobridge = getVideobridge();
org.jivesoftware.smack.packet.IQ iq;
if (videobridge == null)
iq = null;
else
iq = videobridge.handleGracefulShutdownIQ(shutdownIQ);
return iq;
}
/**
* Handles an <tt>org.xmpp.packet.IQ</tt> stanza of type <tt>get</tt> or
* <tt>set</tt> which represents a request. Converts the specified
* <tt>org.xmpp.packet.IQ</tt> to an
* <tt>org.jivesoftware.smack.packet.IQ</tt> stanza, handles the Smack
* stanza via a call to {@link #handleIQ(org.jivesoftware.smack.packet.IQ)},
* converts the result Smack stanza to an <tt>org.xmpp.packet.iQ</tt> which
* is returned as the response to the request.
*
* @param iq the <tt>org.xmpp.packet.IQ</tt> stanza of type <tt>get</tt> or
* <tt>set</tt> which represents the request to handle
* @return an <tt>org.xmpp.packet.IQ</tt> stanza which represents the
* response to the specified request or <tt>null</tt> to reply with
* <tt>feature-not-implemented</tt>
* @throws Exception to reply with <tt>internal-server-error</tt> to the
* specified request
*/
private IQ handleIQ(IQ iq)
throws Exception
{
try
{
logd("RECV: " + iq.toXML());
org.jivesoftware.smack.packet.IQ smackIQ = IQUtils.convert(iq);
org.jivesoftware.smack.packet.IQ resultSmackIQ = handleIQ(smackIQ);
IQ resultIQ;
if (resultSmackIQ == null)
{
resultIQ = null;
}
else
{
resultIQ = IQUtils.convert(resultSmackIQ);
logd("SENT: " + resultIQ.toXML());
}
return resultIQ;
}
catch (Exception e)
{
loge(e);
throw e;
}
}
/**
* Handles an <tt>org.jivesoftware.smack.packet.IQ</tt> stanza of type
* <tt>get</tt> or <tt>set</tt> which represents a request.
*
* @param iq the <tt>org.jivesoftware.smack.packet.IQ</tt> stanza of type
* <tt>get</tt> or <tt>set</tt> which represents the request to handle
* @return an <tt>org.jivesoftware.smack.packet.IQ</tt> stanza which
* represents the response to the specified request or <tt>null</tt> to
* reply with <tt>feature-not-implemented</tt>
* @throws Exception to reply with <tt>internal-server-error</tt> to the
* specified request
*/
private org.jivesoftware.smack.packet.IQ handleIQ(
org.jivesoftware.smack.packet.IQ iq)
throws Exception
{
org.jivesoftware.smack.packet.IQ responseIQ = null;
if (iq != null)
{
org.jivesoftware.smack.packet.IQ.Type type = iq.getType();
if (org.jivesoftware.smack.packet.IQ.Type.GET.equals(type)
|| org.jivesoftware.smack.packet.IQ.Type.SET.equals(type))
{
responseIQ = handleIQRequest(iq);
if (responseIQ != null)
{
responseIQ.setFrom(iq.getTo());
responseIQ.setPacketID(iq.getPacketID());
responseIQ.setTo(iq.getFrom());
}
}
else if (org.jivesoftware.smack.packet.IQ.Type.ERROR.equals(type)
|| org.jivesoftware.smack.packet.IQ.Type.RESULT.equals(
type))
{
handleIQResponse(iq);
}
}
return responseIQ;
}
@Override
protected void handleIQError(IQ iq)
{
super.handleIQError(iq);
try
{
handleIQ(iq);
}
catch (Exception e)
{
logd("An error occurred while trying to handle error IQ.");
loge(e);
}
}
/**
* Handles an <tt>org.xmpp.packet.IQ</tt> stanza of type <tt>get</tt> which
* represents a request.
*
* @param iq the <tt>org.xmpp.packet.IQ</tt> stanza of type <tt>get</tt>
* which represents the request to handle
* @return an <tt>org.xmpp.packet.IQ</tt> stanza which represents the
* response to the specified request or <tt>null</tt> to reply with
* <tt>feature-not-implemented</tt>
* @throws Exception to reply with <tt>internal-server-error</tt> to the
* specified request
* @see AbstractComponent#handleIQGet(IQ)
*/
@Override
protected IQ handleIQGet(IQ iq)
throws Exception
{
IQ resultIQ = handleIQ(iq);
return (resultIQ == null) ? super.handleIQGet(iq) : resultIQ;
}
private org.jivesoftware.smack.packet.IQ handleIQRequest(
org.jivesoftware.smack.packet.IQ request)
throws Exception
{
/*
* Requests can be categorized in pieces of Videobridge functionality
* based on the org.jivesoftware.smack.packet.IQ runtime type (of their
* child element) and forwarded to specialized Videobridge methods for
* convenience.
*/
org.jivesoftware.smack.packet.IQ response;
if (request instanceof ColibriConferenceIQ)
response = handleColibriConferenceIQ((ColibriConferenceIQ) request);
else if (request instanceof GracefulShutdownIQ)
response = handleGracefulShutdownIQ((GracefulShutdownIQ)request);
else
response = null;
return response;
}
private void handleIQResponse(org.jivesoftware.smack.packet.IQ response)
throws Exception
{
/*
* Requests can be categorized in pieces of Videobridge functionality
* based on the org.jivesoftware.smack.packet.IQ runtime type (of their
* child element) and forwarded to specialized Videobridge methods for
* convenience. However, responses cannot be categorized because they
* care the id of their respective requests only.
*/
Videobridge videobridge = getVideobridge();
if (videobridge != null)
videobridge.handleIQResponse(response);
}
@Override
protected void handleIQResult(IQ iq)
{
super.handleIQResult(iq);
try
{
handleIQ(iq);
}
catch (Exception e)
{
logd("An error occurred while trying to handle result IQ.");
loge(e);
}
}
/**
* Handles an <tt>org.xmpp.packet.IQ</tt> stanza of type <tt>set</tt> which
* represents a request.
*
* @param iq the <tt>org.xmpp.packet.IQ</tt> stanza of type <tt>set</tt>
* which represents the request to handle
* @return an <tt>org.xmpp.packet.IQ</tt> stanza which represents the
* response to the specified request or <tt>null</tt> to reply with
* <tt>feature-not-implemented</tt>
* @throws Exception to reply with <tt>internal-server-error</tt> to the
* specified request
* @see AbstractComponent#handleIQSet(IQ)
*/
@Override
protected IQ handleIQSet(IQ iq)
throws Exception
{
IQ resultIQ = handleIQ(iq);
return (resultIQ == null) ? super.handleIQSet(iq) : resultIQ;
}
/**
* Called as part of the execution of {@link AbstractComponent#shutdown()}
* to enable this <tt>Component</tt> to finish cleaning resources up after
* it gets completely shutdown.
*
* @see AbstractComponent#postComponentShutdown()
*/
@Override
public void postComponentShutdown()
{
super.postComponentShutdown();
OSGi.stop(this);
}
/**
* Called as part of the execution of {@link AbstractComponent#start()} to
* enable this <tt>Component</tt> to finish initializing resources after it
* gets completely started.
*
* @see AbstractComponent#postComponentStart()
*/
@Override
public void postComponentStart()
{
super.postComponentStart();
OSGi.start(this);
}
/**
* Implements a helper to send <tt>org.jivesoftware.smack.packet.IQ</tt>s.
*
* @param iq the <tt>org.jivesoftware.smack.packet.IQ</tt> to send
* @throws Exception if an error occurs during the conversion of the
* specified <tt>iq</tt> to an <tt>org.xmpp.packet.IQ</tt> instance or while
* sending the specified <tt>iq</tt>
*/
public void send(org.jivesoftware.smack.packet.IQ iq)
throws Exception
{
try
{
/*
* The javadoc on ComponentManager.sendPacket(Component,Packet)
* which is invoked by AbstractComponent.send(Packet) says that the
* value of the from property of the Packet must not be null;
* otherwise, an IllegalArgumentException will be thrown.
*/
String from = iq.getFrom();
if ((from == null) || (from.length() == 0))
{
JID fromJID = getJID();
if (fromJID != null)
iq.setFrom(fromJID.toString());
}
Packet packet = IQUtils.convert(iq);
send(packet);
logd("SENT: " + packet.toXML());
}
catch (Exception e)
{
loge(e);
throw e;
}
}
/**
* Starts this Jabber component implementation and the Jitsi Videobridge it
* provides in a specific OSGi <tt>BundleContext</tt>.
*
* @param bundleContext the OSGi <tt>BundleContext</tt> in which this Jabber
* component implementation and the Jitsi Videobridge it provides are to be
* started
* @throws Exception if anything irreversible goes wrong while starting this
* Jabber component implementation and the Jitsi Videobridge it provides in
* the specified <tt>bundleContext</tt>
*/
@Override
public void start(BundleContext bundleContext)
throws Exception
{
this.bundleContext = bundleContext;
// Register this instance as an OSGi service.
Collection<ComponentImpl> components = getComponents(bundleContext);
if (!components.contains(this))
bundleContext.registerService(ComponentImpl.class, this, null);
}
/**
* Stops this Jabber component implementation and the Jitsi Videobridge it
* provides in a specific OSGi <tt>BundleContext</tt>.
*
* @param bundleContext the OSGi <tt>BundleContext</tt> in which this Jabber
* component implementation and the Jitsi Videobridge it provides are to be
* stopped
* @throws Exception if anything irreversible goes wrong while stopping this
* Jabber component implementation and the Jitsi Videobridge it provides in
* the specified <tt>bundleContext</tt>
*/
@Override
public void stop(BundleContext bundleContext)
throws Exception
{
try
{
// Unregister this instance as an OSGi service.
Collection<ServiceReference<ComponentImpl>> serviceReferences
= bundleContext.getServiceReferences(ComponentImpl.class, null);
if (serviceReferences != null)
{
for (ServiceReference<ComponentImpl> serviceReference
: serviceReferences)
{
Object service = bundleContext.getService(serviceReference);
if (service == this)
bundleContext.ungetService(serviceReference);
}
}
}
finally
{
this.bundleContext = null;
}
}
}
......@@ -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