From ffae6e2f20d3bc7236ff39a0bf0268b5e43b3923 Mon Sep 17 00:00:00 2001 From: Chad Pilkey Date: Tue, 11 Nov 2014 03:52:11 -0800 Subject: [PATCH 1/4] added a SDP hack for Firefox to replace the 0.0.0.0 in the c line --- bigbluebutton-client/resources/prod/lib/sip.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bigbluebutton-client/resources/prod/lib/sip.js b/bigbluebutton-client/resources/prod/lib/sip.js index 05d8698a39..8ff731e808 100755 --- a/bigbluebutton-client/resources/prod/lib/sip.js +++ b/bigbluebutton-client/resources/prod/lib/sip.js @@ -2526,6 +2526,15 @@ var Hacks = module.exports = { } } return sdp; + }, + + hackCLinInIP: function (sdp) { + /* Starting in Firefox 34 they have set the c line to 0.0.0.0 which + * means "hold" according to legacy SIP standards and Freeswitch + * interprets it according to the SIP standards. We replace the + * 0.0.0.0 with any other IP so that the call continues. + */ + return sdp.replace("c=IN IP4 0.0.0.0", "c=IN IP4 127.0.0.1"); } }, @@ -6036,6 +6045,9 @@ InviteClientContext.prototype = { if (self.isCanceled || self.status === C.STATUS_TERMINATED) { return; } + + offer = SIP.Hacks.Firefox.hackCLinInIP(offer); + self.hasOffer = true; self.request.body = offer; self.status = C.STATUS_INVITE_SENT; From b467572fdbfdb7a75e0d0bc9561eddc1c5619045 Mon Sep 17 00:00:00 2001 From: Richard Alam Date: Tue, 11 Nov 2014 08:11:32 -0800 Subject: [PATCH 2/4] - put sending of rtp packet to fs in another thread --- .../SpeexFlashToSipTranscoderImp.java | 53 ++++++++++++++++--- .../media/transcoder/SpeexRtpAudioData.java | 12 +++++ 2 files changed, 57 insertions(+), 8 deletions(-) create mode 100755 bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexRtpAudioData.java diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexFlashToSipTranscoderImp.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexFlashToSipTranscoderImp.java index 7a7371ec68..3c52546801 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexFlashToSipTranscoderImp.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexFlashToSipTranscoderImp.java @@ -19,6 +19,11 @@ package org.bigbluebutton.voiceconf.red5.media.transcoder; import java.util.Random; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; import org.bigbluebutton.voiceconf.red5.media.FlashToSipAudioStream.TranscodedAudioListener; import org.red5.app.sip.codecs.Codec; @@ -36,9 +41,16 @@ public class SpeexFlashToSipTranscoderImp implements FlashToSipTranscoder { private Codec audioCodec; private long timestamp = 0; private final static int TS_INCREMENT = 320; // Determined from PCAP traces. + + private final Executor exec = Executors.newSingleThreadExecutor(); + private Runnable audioDataProcessor; + private volatile boolean processAudioData = false; + private BlockingQueue audioDataQ; + private TranscodedAudioListener transcodedAudioListener; public SpeexFlashToSipTranscoderImp(Codec audioCodec) { + audioDataQ = new LinkedBlockingQueue(); this.audioCodec = audioCodec; Random rgen = new Random(); timestamp = rgen.nextInt(1000); @@ -49,7 +61,13 @@ public class SpeexFlashToSipTranscoderImp implements FlashToSipTranscoder { // Just copy the audio data removing the codec id which is the first-byte // represented by the startOffset var. System.arraycopy(audioData, startOffset, transcodedAudio, 0, length); - transcodedAudioListener.handleTranscodedAudioData(transcodedAudio, timestamp += TS_INCREMENT); + + SpeexRtpAudioData srad = new SpeexRtpAudioData(transcodedAudio, timestamp += TS_INCREMENT); + try { + audioDataQ.offer(srad, 100, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + log.warn("Failed to add speex audio data into queue."); + } } public int getCodecId() { @@ -73,14 +91,33 @@ public class SpeexFlashToSipTranscoderImp implements FlashToSipTranscoder { public void setTranscodedAudioListener(TranscodedAudioListener transcodedAudioListener) { this.transcodedAudioListener = transcodedAudioListener; } - - @Override - public void start() { - // do nothing. just implement the interface. + + private void processAudioData() { + while (processAudioData) { + SpeexRtpAudioData srad; + try { + srad = audioDataQ.take(); + transcodedAudioListener.handleTranscodedAudioData(srad.audioData, srad.timestamp); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } + + @Override + public void start() { + processAudioData = true; + audioDataProcessor = new Runnable() { + public void run() { + processAudioData(); + } + }; + exec.execute(audioDataProcessor); + } @Override - public void stop() { - // do nothing. just implement the interface. - } + public void stop() { + processAudioData = false; + } } diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexRtpAudioData.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexRtpAudioData.java new file mode 100755 index 0000000000..474bb37cb4 --- /dev/null +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexRtpAudioData.java @@ -0,0 +1,12 @@ +package org.bigbluebutton.voiceconf.red5.media.transcoder; + +public class SpeexRtpAudioData { + + public final byte[] audioData; + public final long timestamp; + + public SpeexRtpAudioData(byte[] audioData, long timestamp) { + this.audioData = audioData; + this.timestamp = timestamp; + } +} From a7c4e6fd4341f72020cb1bc1ac3fd589272f0e80 Mon Sep 17 00:00:00 2001 From: Chad Pilkey Date: Tue, 11 Nov 2014 11:32:19 -0800 Subject: [PATCH 3/4] updated the mobile demo to work with the upcoming BBB AIR Mobile app --- bbb-api-demo/src/main/webapp/demo_header.jsp | 2 + bbb-api-demo/src/main/webapp/mobile.jsp | 150 ++++++++++----- bbb-api-demo/src/main/webapp/mobile_api.jsp | 182 ------------------- bbb-api-demo/src/main/webapp/mobile_conf.jsp | 6 - 4 files changed, 111 insertions(+), 229 deletions(-) mode change 100644 => 100755 bbb-api-demo/src/main/webapp/mobile.jsp delete mode 100644 bbb-api-demo/src/main/webapp/mobile_api.jsp delete mode 100644 bbb-api-demo/src/main/webapp/mobile_conf.jsp diff --git a/bbb-api-demo/src/main/webapp/demo_header.jsp b/bbb-api-demo/src/main/webapp/demo_header.jsp index c53b5688e3..c85f730600 100755 --- a/bbb-api-demo/src/main/webapp/demo_header.jsp +++ b/bbb-api-demo/src/main/webapp/demo_header.jsp @@ -20,4 +20,6 @@ Login with Openid    Javascript API    + +Mobile Demo    diff --git a/bbb-api-demo/src/main/webapp/mobile.jsp b/bbb-api-demo/src/main/webapp/mobile.jsp old mode 100644 new mode 100755 index 036abebe4b..9c45ba2e3d --- a/bbb-api-demo/src/main/webapp/mobile.jsp +++ b/bbb-api-demo/src/main/webapp/mobile.jsp @@ -1,51 +1,119 @@ -<% -/* - BigBlueButton - http://www.bigbluebutton.org - - Copyright (c) 2011 by respective authors (see below). All rights reserved. - - BigBlueButton is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software - Foundation; either version 3 of the License, or (at your option) any later - version. - - BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License along - with BigBlueButton; if not, If not, see . - - Author: Felipe Cecagno -*/ -%> -<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> <% request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); %> + + + + + Join Demo Meeting From Mobile + -<%@page import="org.apache.commons.httpclient.HttpClient"%> -<%@page import="org.apache.commons.httpclient.HttpMethod"%> -<%@page import="org.apache.commons.httpclient.methods.GetMethod"%> + + +<%@ include file="bbb_api.jsp"%> + +<% +if (request.getParameterMap().isEmpty()) { + // + // Assume we want to create a meeting + // + %> +<%@ include file="demo_header.jsp"%> + +

Join Demo Meeting From Mobile

+ +You must have the BigBlueButton mobile client installed on your device for this demo to work. +

+
+ + + + + + + + + + + + + + + +
+   + Full Name: +   +
+   +   +   +
+ +
-<%@ include file="mobile_api.jsp"%> <% - String result = error(E_INVALID_URL); - if (request.getParameterMap().isEmpty()) { - result = success("mobileSupported", "This server supports mobile devices."); - } else if (request.getParameter("action") == null) { - // return the default result - } else if (request.getParameter("action").equals("getTimestamp")) { - result = getTimestamp(request); - } else if (request.getParameter("action").equals("getMeetings")) { - result = mobileGetMeetings(request); - } else if (request.getParameter("action").equals("join")) { - result = mobileJoinMeeting(request); - } else if (request.getParameter("action").equals("create")) { - result = mobileCreate(request); - } +} else if (request.getParameter("action").equals("create")) { + + // + // Got an action=create + // + + String username = request.getParameter("username"); + String url = BigBlueButtonURL.replace("bigbluebutton/","demo/"); + // String preUploadPDF = ""; + + String joinURL = getJoinURL(request.getParameter("username"), "Demo Meeting", "false", null, null, null); + + if (joinURL.startsWith("http://")) { + joinURL = joinURL.replace("http", "bigbluebutton"); %> -<%=result%> + + + +<% + } else { +%> + +Error: getJoinURL() failed +

+<%=joinURL %> + +<% + } +} +%> + + +<%@ include file="demo_footer.jsp"%> + + + diff --git a/bbb-api-demo/src/main/webapp/mobile_api.jsp b/bbb-api-demo/src/main/webapp/mobile_api.jsp deleted file mode 100644 index 9dfabc8192..0000000000 --- a/bbb-api-demo/src/main/webapp/mobile_api.jsp +++ /dev/null @@ -1,182 +0,0 @@ -<% -/* - BigBlueButton - http://www.bigbluebutton.org - - Copyright (c) 2011 by respective authors (see below). All rights reserved. - - BigBlueButton is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software - Foundation; either version 3 of the License, or (at your option) any later - version. - - BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License along - with BigBlueButton; if not, If not, see . - - Author: Felipe Cecagno -*/ -%> -<%@ include file="bbb_api.jsp"%> -<%@ include file="mobile_conf.jsp"%> - -<%@page import="org.apache.commons.httpclient.HttpClient"%> -<%@page import="org.apache.commons.httpclient.HttpMethod"%> -<%@page import="org.apache.commons.httpclient.methods.GetMethod"%> - -<%! - public final int E_OK = 0; - public final int E_CHECKSUM_NOT_INFORMED = 1; - public final int E_INVALID_CHECKSUM = 2; - public final int E_INVALID_TIMESTAMP = 3; - public final int E_EMPTY_SECURITY_KEY = 4; - public final int E_MISSING_PARAM_MEETINGID = 5; - public final int E_MISSING_PARAM_FULLNAME = 6; - public final int E_MISSING_PARAM_PASSWORD = 7; - public final int E_MISSING_PARAM_TIMESTAMP = 8; - public final int E_INVALID_URL = 9; - - public String error(int code) { - switch(code) { - case E_CHECKSUM_NOT_INFORMED: - case E_INVALID_CHECKSUM: - return error("checksumError", "You did not pass the checksum security check."); - case E_INVALID_TIMESTAMP: - return error("invalidTimestamp", "You did not pass the timestamp check."); - case E_EMPTY_SECURITY_KEY: - return error("emptySecurityKey", "The mobile security key is empty. Please contact the administrator."); - case E_MISSING_PARAM_MEETINGID: - return error("missingParamMeetingID", "You must specify a meeting ID for the meeting."); - case E_MISSING_PARAM_FULLNAME: - return error("missingParamFullName", "You must specify a name for the attendee who will be joining the meeting."); - case E_MISSING_PARAM_PASSWORD: - return error("invalidPassword", "You either did not supply a password or the password supplied is neither the attendee or moderator password for this conference."); - case E_MISSING_PARAM_TIMESTAMP: - return error("missingParamTimestamp", "You must specify the timestamp provided by the server when you called the method getTimestamp."); - case E_INVALID_URL: - return error("invalidAction", "The requested URL is unavailable."); - default: - return error("unknownError", "An unexpected error occurred"); - } - } - - private String getRequestURL(HttpServletRequest request) { - return request.getQueryString(); - } - - private String removeChecksum(String requestURL) { - return requestURL.substring(0, requestURL.lastIndexOf("&checksum=")); - } - - private String addValidChecksum(String requestURL) { - return requestURL + "&checksum=" + checksum(requestURL + mobileSalt); - } - - private int isRequestValid(HttpServletRequest request) { - // if there's no checksum parameter, the request isn't valid - if (request.getParameter("checksum") == null) - return E_CHECKSUM_NOT_INFORMED; - - // check the timestamp for all the requests except getTimestamp - if (!request.getParameter("action").equals("getTimestamp")) { - String requestTimestamp = request.getParameter("timestamp"); - if (requestTimestamp == null) - return E_MISSING_PARAM_TIMESTAMP; - - Long requestTimestampL = Long.valueOf(requestTimestamp); - // the timestamp is valid for 60 seconds - if (Math.abs(getTimestamp() - requestTimestampL) > 60) - return E_INVALID_TIMESTAMP; - } - - if (mobileSalt.isEmpty()) - return E_EMPTY_SECURITY_KEY; - - String requestURL = getRequestURL(request); - String urlWithoutChecksum = removeChecksum(requestURL); - String urlWithChecksum = addValidChecksum(urlWithoutChecksum); - return (requestURL.equals(urlWithChecksum)? E_OK: E_INVALID_CHECKSUM); - } - - private String mountResponse(String returncode, String messageKey, String message) { - return "" + returncode + "" + messageKey + "" + message + ""; - } - - public String success(String messageKey, String message) { - return mountResponse("SUCCESS", messageKey, message); - } - - public String error(String messageKey, String message) { - return mountResponse("FAILED", messageKey, message); - } - - private long getTimestamp() { - return (System.currentTimeMillis() / 1000L); - } - - public String getTimestamp(HttpServletRequest request) { - int code = isRequestValid(request); - if (code != E_OK) - return error(code); - - return "SUCCESS" + getTimestamp() + ""; - } - - public String mobileGetMeetings(HttpServletRequest request) { - int code = isRequestValid(request); - if (code != E_OK) - return error(code); - - return getMeetings(); - } - - public String mobileJoinMeeting(HttpServletRequest request) { - int code = isRequestValid(request); - if (code != E_OK) - return error(code); - - String meetingID = request.getParameter("meetingID"); - if (meetingID == null) return error(E_MISSING_PARAM_MEETINGID); - - String fullName = request.getParameter("fullName"); - if (fullName == null) return error(E_MISSING_PARAM_FULLNAME); - - String password = request.getParameter("password"); - if (password == null) return error(E_MISSING_PARAM_PASSWORD); - - String result = error("failedJoin", "Couldn't join the meeting."); - String joinUrl = getJoinMeetingURL(fullName, meetingID, password, null); - String enterUrl = BigBlueButtonURL + "api/enter"; - try { - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(joinUrl); - client.executeMethod(method); - method.releaseConnection(); - - method = new GetMethod(enterUrl); - client.executeMethod(method); - result = method.getResponseBodyAsString(); - method.releaseConnection(); - } catch (Exception e) { - } - return result; - } - - public String mobileCreate(HttpServletRequest request) { - int code = isRequestValid(request); - if (code != E_OK) - return error(code); - - String meetingID = request.getParameter("meetingID"); - if (meetingID == null) return error(E_MISSING_PARAM_MEETINGID); - - return createMeeting(meetingID, "", "", "", "", 0, BigBlueButtonURL); - } - - // it's just for testing purposes - private String fixURL(HttpServletRequest request) { - return addValidChecksum(removeChecksum(getRequestURL(request))); - } -%> diff --git a/bbb-api-demo/src/main/webapp/mobile_conf.jsp b/bbb-api-demo/src/main/webapp/mobile_conf.jsp deleted file mode 100644 index 7ee04df0ee..0000000000 --- a/bbb-api-demo/src/main/webapp/mobile_conf.jsp +++ /dev/null @@ -1,6 +0,0 @@ - -<%! -// This is the mobile security salt that must be used to check the requests on mobile.jsp -String mobileSalt = ""; -%> - From 1ef484ba9551575bf0a318e1ecb19eea171db65c Mon Sep 17 00:00:00 2001 From: Fred Dixon Date: Tue, 11 Nov 2014 17:00:05 -0500 Subject: [PATCH 4/4] Aligned URL path for config.xml with install directory --- .../clientcheck/command/GetConfigXMLDataCommand.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/labs/bbb-client-check/src/org/bigbluebutton/clientcheck/command/GetConfigXMLDataCommand.as b/labs/bbb-client-check/src/org/bigbluebutton/clientcheck/command/GetConfigXMLDataCommand.as index 89726cbc75..b162586c8c 100755 --- a/labs/bbb-client-check/src/org/bigbluebutton/clientcheck/command/GetConfigXMLDataCommand.as +++ b/labs/bbb-client-check/src/org/bigbluebutton/clientcheck/command/GetConfigXMLDataCommand.as @@ -23,7 +23,7 @@ package org.bigbluebutton.clientcheck.command [Inject] public var config:IXMLConfig; - private var CONFIG_XML:String="client/client-check/conf/config.xml"; + private var CONFIG_XML:String="check/conf/config.xml"; private var _urlRequest:URLRequest; public override function execute():void