Commit cad52ff9 authored by daryl herzmann's avatar daryl herzmann

Merge pull request #216 from deleolajide/ofmeet-ver-0.1.7

ofmeet plugin version 0.1.7
parents dedb78d1 0b70bf1f
......@@ -49,6 +49,15 @@
Openfire Meetings Plugin Changelog
</h1>
<p><b>0.1.7</b> -- May 13th, 2015</p>
<ul>
<li>Logs openfire meeting audit events with Openfire security auditor</li>
<li>Logs meeting SIP calls via SIP plugin</li>
<li>Added support for audio conferencing meetings (no video)</li>
<li>Updated Jitsi Videobridge</li>
</ul>
<p><b>0.1.6</b> -- May 9th, 2015</p>
<ul>
......
......@@ -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.1.6</version>
<date>05/09/2015</date>
<version>0.1.7</version>
<date>05/13/2015</date>
<minServerVersion>3.9.9</minServerVersion>
<adminconsole>
......
......@@ -17,6 +17,13 @@
var visible = false;
var joined = false;
function urlParam(name)
{
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (!results) { return undefined; }
return unescape(results[1] || undefined);
};
$(document).bind('ofmeet.connected', function (event, connection)
{
console.log("ofmeet connected", connection);
......@@ -55,7 +62,7 @@
$(document).bind('ofmeet.ready', function ()
{
console.log("ofmeet.ready");
ofmeet.connect();
ofmeet.connect(urlParam("novideo"));
});
$(document).ready(function ()
......
......@@ -211,8 +211,20 @@ function obtainAudioAndVideoPermissions(callback) {
video: stream.getVideoTracks().length
});
}
var media = ['audio', 'video'];
var resolution = config.resolution || '360';
if (urlParam("novideo"))
{
media = ['audio'];
resolution = null;
}
console.log("using media", media);
getUserMediaWithConstraints(
['audio', 'video'],
media,
cb,
function (error) {
console.error('failed to obtain audio/video stream - trying audio only', error);
......@@ -231,7 +243,7 @@ function obtainAudioAndVideoPermissions(callback) {
}
);
},
config.resolution || '360');
resolution);
}
function maybeDoJoin() {
......@@ -285,6 +297,13 @@ function doJoin() {
roomName, doJoinAfterFocus);
}
function urlParam(name)
{
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (!results) { return undefined; }
return unescape(results[1] || undefined);
};
function doJoinAfterFocus() {
var roomjid;
......
......@@ -24046,6 +24046,11 @@ var ofmeet = (function(of)
}
VideoLayout.updateLargeVideo(localVideoSrc, 0,
myResourceJid);
if (stream.getVideoTracks().length == 0)
{
localVideoSelector.css("display", "none");
}
};
......@@ -31184,7 +31189,7 @@ var ofmeet = (function(of)
var sessionTerminated = false;
function connectOpenfire(jid, password)
function connectOpenfire(jid, password, novideo)
{
//console.log("connect", jid, password);
......@@ -31269,7 +31274,7 @@ var ofmeet = (function(of)
}
$(document).trigger('ofmeet.connected', [connection]);
});
}, novideo);
} else if (status === Strophe.Status.CONNFAIL) {
......@@ -31293,18 +31298,30 @@ var ofmeet = (function(of)
* We ask for audio and video combined stream in order to get permissions and
* not to ask twice.
*/
function obtainAudioAndVideoPermissions(callback) {
function obtainAudioAndVideoPermissions(callback, novideo) {
// Get AV
var cb = function (stream) {
//console.log('got', stream, stream.getAudioTracks().length, stream.getVideoTracks().length);
console.log('got', stream, stream.getAudioTracks().length, stream.getVideoTracks().length);
callback(stream);
trackUsage('localMedia', {
audio: stream.getAudioTracks().length,
video: stream.getVideoTracks().length
});
}
var media = ['audio', 'video'];
var resolution = config.resolution || '360';
if (novideo)
{
media = ['audio'];
resolution = null;
}
console.log("using media", media);
getUserMediaWithConstraints(
['audio', 'video'],
media,
cb,
function (error) {
console.error('failed to obtain audio/video stream - trying audio only', error);
......@@ -31323,7 +31340,7 @@ var ofmeet = (function(of)
}
);
},
config.resolution || '360');
resolution);
}
function generateRoomName() {
......@@ -32534,7 +32551,9 @@ var ofmeet = (function(of)
if (username && password)
{
headers = {"Authorization": "Basic " + btoa(username + ":" + password)}
headers = {"Authorization": "Basic " + btoa(username + ":" + password)};
of.username = username;
of.password = password;
}
$.ajax({type: "GET", url: "/ofmeet/config", dataType: "script", headers: headers}).done(function()
......@@ -32631,7 +32650,7 @@ var ofmeet = (function(of)
setAudioMuted(!isAudioMuted());
}
of.connect = function connect(username, password)
of.connect = function connect(novideo)
{
RTC = setupRTC();
......@@ -32642,7 +32661,7 @@ var ofmeet = (function(of)
}
var jid = config.hosts.domain;
if (username) jid = username + "@" + config.hosts.domain;
if (of.username) jid = of.username + "@" + config.hosts.domain;
if (config.userName)
{
......@@ -32650,7 +32669,7 @@ var ofmeet = (function(of)
authenticatedUser = true;
}
connectOpenfire(jid, password);
connectOpenfire(jid, of.password, novideo);
}
of.leaveRoom = function leaveRoom()
......@@ -88,7 +88,11 @@ window.addEventListener("load", function()
$(document).bind('inum.cleared', function(event, callId)
{
console.log("inum.cleared", callId);
console.log("inum.cleared", callId);
dialer.setLabel("Call");
dialer.setState("inactive");
dialer.call = null
stopTone();
});
$(document).bind('inum.dialled', function (event, confId, to, callId)
......
......@@ -143,6 +143,8 @@ public class CallSession
public String callId;
public String focusJID;
public String roomJID;
public String username;
public long startTimestamp = 0;
private CallControlComponent callControl;
......
......@@ -57,7 +57,7 @@ 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("net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED", "true");
System.setProperty(FocusManager.HOSTNAME_PNAME, hostName);
......
......@@ -25,6 +25,8 @@ import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.muc.*;
import org.jivesoftware.openfire.session.*;
import org.jivesoftware.database.DbConnectionManager;
import java.sql.*;
import org.slf4j.*;
import org.slf4j.Logger;
......@@ -159,7 +161,7 @@ public class CallControlComponent extends AbstractComponent
sendPacket(iq);
}
private void makeCall(Conference conference, String confJid, String to, String callId)
private void makeCall(Conference conference, String confJid, String to, String callId, String username, long startTimestamp)
{
Log.info("CallControlComponent - makeCall " + confJid + " " + to + " " + callId);
......@@ -267,6 +269,8 @@ public class CallControlComponent extends AbstractComponent
cs.jabberRemote = to;
cs.jabberLocal = from;
cs.username = username;
cs.startTimestamp = startTimestamp;
SipService.sendInvite(cs);
......@@ -280,11 +284,12 @@ public class CallControlComponent extends AbstractComponent
{
Log.info("hangupCall " + callId);
CallSession cs = callSessions.get(callId);
CallSession cs = callSessions.remove(callId);
if (cs != null)
{
SipService.sendBye(cs);
updateCallRecord(cs.startTimestamp, (int)(System.currentTimeMillis() - cs.startTimestamp));
} else {
Log.error("CallControlComponent hangup. cannot fine callid " + callId);
......@@ -379,6 +384,12 @@ public class CallControlComponent extends AbstractComponent
}
}
if (session != null)
{
long startTimestamp = System.currentTimeMillis();
session.startTimestamp = startTimestamp;
createCallRecord("admin", from, confJID, startTimestamp, 0, "received");
}
return session;
}
......@@ -455,7 +466,12 @@ public class CallControlComponent extends AbstractComponent
hangup.addElement("header").addAttribute("name", "caller_id").addAttribute("value", session.jabberRemote);
hangup.addElement("header").addAttribute("name", "called_id").addAttribute("value", session.jabberLocal);
callSessions.remove(callId);
CallSession cs = callSessions.remove(callId);
if (cs != null)
{
updateCallRecord(cs.startTimestamp, (int)(System.currentTimeMillis() - cs.startTimestamp));
}
}
sendPacket(presence);
......@@ -548,7 +564,11 @@ public class CallControlComponent extends AbstractComponent
if (conference != null)
{
makeCall(conference, confJid, to, callId);
String username = iq.getFrom().getNode();
long startTimestamp = System.currentTimeMillis();
makeCall(conference, confJid, to, callId, username, startTimestamp);
createCallRecord(username, confJid, to, startTimestamp, 0, "dialed");
} else {
Log.error("CallControlComponent - can't find conference " + confId);
......@@ -711,4 +731,70 @@ public class CallControlComponent extends AbstractComponent
Log.error("CallControlComponent sendPacket ", e);
}
}
private void createCallRecord(String username, String addressFrom, String addressTo, long datetime, int duration, String calltype)
{
boolean sipPlugin = XMPPServer.getInstance().getPluginManager().getPlugin("sip") != null;
if (sipPlugin)
{
Log.info("createCallRecord " + username + " " + addressFrom + " " + addressTo + " " + datetime);
String sql = "INSERT INTO ofSipPhoneLog (username, addressFrom, addressTo, datetime, duration, calltype) values (?, ?, ?, ?, ?, ?)";
Connection con = null;
PreparedStatement psmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setString(1, username);
psmt.setString(2, addressFrom);
psmt.setString(3, addressTo);
psmt.setLong(4, datetime);
psmt.setInt(5, duration);
psmt.setString(6, calltype);
psmt.executeUpdate();
} catch (SQLException e) {
Log.error(e.getMessage(), e);
} finally {
DbConnectionManager.closeConnection(rs, psmt, con);
}
}
}
private void updateCallRecord(long datetime, int duration)
{
boolean sipPlugin = XMPPServer.getInstance().getPluginManager().getPlugin("sip") != null;
if (sipPlugin)
{
Log.info("updateCallRecord " + datetime + " " + duration);
String sql = "UPDATE ofSipPhoneLog SET duration = ? WHERE datetime = ?";
Connection con = null;
PreparedStatement psmt = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setInt(1, duration);
psmt.setLong(2, (datetime / 1000));
psmt.executeUpdate();
} catch (SQLException e) {
Log.error(e.getMessage(), e);
} finally {
DbConnectionManager.closeConnection(psmt, con);
}
}
}
}
......@@ -18,6 +18,11 @@ import java.util.concurrent.*;
import org.slf4j.*;
import org.slf4j.Logger;
import org.jivesoftware.openfire.security.SecurityAuditManager;
import org.jivesoftware.util.*;
import org.xmpp.packet.*;
/**
* Allows logging of {@link org.jitsi.videobridge.log.Event}s using an
* <tt>Openfire</tt> instance.
......@@ -55,7 +60,7 @@ public class OpenfireEventService implements LoggingService
*/
@SuppressWarnings("unchecked")
@Override
public void logEvent(Event e)
public void logEvent(final Event e)
{
// The following is a sample JSON message in the format used by InfluxDB
// [
......@@ -101,7 +106,7 @@ public class OpenfireEventService implements LoggingService
@Override
public void run()
{
sendPost(jsonString);
sendPost(e.getName(), jsonString);
}
});
}
......@@ -111,11 +116,19 @@ public class OpenfireEventService implements LoggingService
* {@link #url}.
* @param s the content of the POST request.
*/
private void sendPost(final String s)
private void sendPost(final String summary, final String detail)
{
try
{
Log.info("OpenfireEventService sendPost " + s);
String focusUsername = "focus";
String focusUserJid = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.focus.user.jid");
if (focusUserJid != null)
{
focusUsername = (new JID(focusUserJid)).getNode();
}
Log.info("OpenfireEventService sendPost " + focusUsername + " " + detail);
SecurityAuditManager.getInstance().logEvent(focusUsername, summary, detail);
}
catch (Exception e)
{
......
......@@ -573,4 +573,4 @@ public class ComponentImpl
this.bundleContext = null;
}
}
}
\ No newline at end of file
}
......@@ -43,6 +43,7 @@ import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.openfire.muc.*;
import org.jivesoftware.openfire.group.*;
import org.jivesoftware.openfire.security.SecurityAuditManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -295,7 +296,7 @@ public class OfMeetPlugin implements Plugin, ClusterEventListener {
public void processMeetingPlanner()
{
Log.info("OfMeet Plugin - processMeetingPlanner");
Log.debug("OfMeet Plugin - processMeetingPlanner");
final Collection<Bookmark> bookmarks = BookmarkManager.getBookmarks();
......@@ -392,6 +393,7 @@ public class OfMeetPlugin implements Plugin, ClusterEventListener {
variables.put("domain", XMPPServer.getInstance().getServerInfo().getXMPPDomain());
sendEmail(name, email, title, replaceTokens(template, variables), null);
SecurityAuditManager.getInstance().logEvent(user.getUsername(), "sent email - " + title, description);
}
}
catch (Exception e) {
......
......@@ -675,55 +675,58 @@ function getUserMediaWithConstraints(um, success_callback, failure_callback, res
}
}
// Check if we are running on Android device
var isAndroid = navigator.userAgent.indexOf('Android') != -1;
if (resolution && !constraints.video || isAndroid) {
constraints.video = { mandatory: {}, optional: [] };// same behaviour as true
}
// see https://code.google.com/p/chromium/issues/detail?id=143631#c9 for list of supported resolutions
switch (resolution) {
// 16:9 first
case '1080':
case 'fullhd':
constraints.video.mandatory.minWidth = 1920;
constraints.video.mandatory.minHeight = 1080;
break;
case '720':
case 'hd':
constraints.video.mandatory.minWidth = 1280;
constraints.video.mandatory.minHeight = 720;
break;
case '360':
constraints.video.mandatory.minWidth = 640;
constraints.video.mandatory.minHeight = 360;
break;
case '180':
constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.minHeight = 180;
break;
// 4:3
case '960':
constraints.video.mandatory.minWidth = 960;
constraints.video.mandatory.minHeight = 720;
break;
case '640':
case 'vga':
constraints.video.mandatory.minWidth = 640;
constraints.video.mandatory.minHeight = 480;
break;
case '320':
constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.minHeight = 240;
break;
default:
if (isAndroid) {
constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.minHeight = 240;
constraints.video.mandatory.maxFrameRate = 15;
}
break;
if (constraints.video) {
// Check if we are running on Android device
var isAndroid = navigator.userAgent.indexOf('Android') != -1;
if (resolution && !constraints.video || isAndroid) {
constraints.video = { mandatory: {}, optional: [] };// same behaviour as true
}
// see https://code.google.com/p/chromium/issues/detail?id=143631#c9 for list of supported resolutions
switch (resolution) {
// 16:9 first
case '1080':
case 'fullhd':
constraints.video.mandatory.minWidth = 1920;
constraints.video.mandatory.minHeight = 1080;
break;
case '720':
case 'hd':
constraints.video.mandatory.minWidth = 1280;
constraints.video.mandatory.minHeight = 720;
break;
case '360':
constraints.video.mandatory.minWidth = 640;
constraints.video.mandatory.minHeight = 360;
break;
case '180':
constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.minHeight = 180;
break;
// 4:3
case '960':
constraints.video.mandatory.minWidth = 960;
constraints.video.mandatory.minHeight = 720;
break;
case '640':
case 'vga':
constraints.video.mandatory.minWidth = 640;
constraints.video.mandatory.minHeight = 480;
break;
case '320':
constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.minHeight = 240;
break;
default:
if (isAndroid) {
constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.minHeight = 240;
constraints.video.mandatory.maxFrameRate = 15;
}
break;
}
}
if (constraints.video)
{
if (constraints.video.mandatory.minWidth)
......
......@@ -108,8 +108,12 @@ var VideoLayout = (function (my) {
{
myResourceJid = Strophe.getResourceFromJid(connection.emuc.myroomjid);
}
VideoLayout.updateLargeVideo(localVideoSrc, 0,
myResourceJid);
VideoLayout.updateLargeVideo(localVideoSrc, 0, myResourceJid);
if (stream.getVideoTracks().length == 0)
{
localVideoSelector.css("display", "none");
}
};
......
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