blob: 2ca9a404d410accab56a2fb68198d9768f79752e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License") + you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openmeetings.servlet.outputhandler;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.apache.openmeetings.OpenmeetingsVariables;
import org.apache.openmeetings.data.basic.FieldManager;
import org.apache.openmeetings.data.basic.SessiondataDao;
import org.apache.openmeetings.data.basic.dao.ConfigurationDao;
import org.apache.openmeetings.persistence.beans.room.Client;
import org.apache.openmeetings.session.ISessionManager;
import org.apache.openmeetings.utils.OmFileHelper;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ScreenController {
private static final Logger log = Red5LoggerFactory.getLogger(
ScreenController.class, OpenmeetingsVariables.webAppRootKey);
@Autowired
private ISessionManager sessionManager;
@Autowired
public SessiondataDao sessiondataDao;
@Autowired
public ConfigurationDao configurationDao;
@Autowired
public FieldManager fieldManager;
private enum ConnectionType {
rtmp
, rtmps
, rtmpt
}
private String getLabels(Long language_id, int ... ids) {
StringBuilder result = new StringBuilder();
boolean delim = false;
for (int id : ids) {
if (delim) {
result.append(';');
}
result.append(fieldManager.getFieldByIdAndLanguage((long)id, language_id).getValue());
delim = true;
}
return result.toString();
}
@RequestMapping(value = "/screen.upload")
public void handleRequest(HttpServletRequest request,
HttpServletResponse response) {
try {
String sid = request.getParameter("sid");
Long users_id = sessiondataDao.checkSession(sid);
String publicSID = request.getParameter("publicSID");
if (publicSID == null) {
throw new Exception("publicSID is empty: " + publicSID);
}
if (users_id == 0) {
//checkSession will return 0 in case of invalid session
throw new Exception("Request from invalid user " + users_id);
}
String domain = request.getParameter("domain");
if (domain == null) {
throw new Exception("domain is empty: " + domain);
}
String languageAsString = request.getParameter("languageAsString");
if (languageAsString == null) {
throw new Exception("languageAsString is empty: " + languageAsString);
}
Long language_id = Long.parseLong(languageAsString);
String rtmphostlocal = request.getParameter("rtmphostlocal");
if (rtmphostlocal == null) {
throw new Exception("rtmphostlocal is empty: " + rtmphostlocal);
}
String baseURL = request.getParameter("baseurl");
if (baseURL == null) {
throw new Exception("baseurl is empty: " + baseURL);
}
log.debug("language_id :: " + language_id);
String label_sharer = "Sharer";
try {
label_sharer = getLabels(language_id
, 730, 731, 732, 733, 734
, 735, 737, 738, 739, 740
, 741, 742, 844, 869, 870
, 871, 872, 878, 1089, 1090
, 1091, 1092, 1093, 1465, 1466
, 1467, 1468, 1469, 1470, 1471
, 1472, 1473, 1474, 1475, 1476
, 1477);
} catch (Exception e) {
log.error("Error resolving Language labels : ", e);
}
log.debug("Creating JNLP Template for TCP solution");
//libs
StringBuilder libs = new StringBuilder();
File screenShareDir = OmFileHelper.getScreenSharingDir();
for (File jar : screenShareDir.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().endsWith(".jar");
}
})) {
libs.append("\t\t<jar href=\"").append(jar.getName()).append("\"/>\n");
}
log.debug("RTMP Sharer labels :: " + label_sharer);
ConnectionType conType
= ConnectionType.valueOf(request.getParameter("connectionType"));
String startUpClass;
switch (conType) {
case rtmp:
startUpClass = "org.apache.openmeetings.screen.webstart.RTMPScreenShare";
break;
case rtmps:
startUpClass = "org.apache.openmeetings.screen.webstart.RTMPSScreenShare";
break;
case rtmpt:
startUpClass = "org.apache.openmeetings.screen.webstart.RTMPTScreenShare";
break;
default:
throw new Exception("Unknown connection type");
}
String orgIdAsString = request.getParameter("organization_id");
if (orgIdAsString == null) {
throw new Exception("orgIdAsString is empty could not start sharer");
}
String port = request.getParameter("port");
if (port == null) {
throw new Exception("port is empty: ");
}
Client rc = sessionManager.getClientByPublicSID(publicSID, false, null);
if (rc == null) {
throw new Exception("port is empty: ");
}
Long roomId = rc.getRoom_id();
boolean allowRecording = rc.getAllowRecording()
&& (0 == sessionManager.getRecordingCount(roomId));
boolean allowPublishing = (0 == sessionManager
.getPublishingCount(roomId));
Context ctx = new VelocityContext();
ctx.put("APP_NAME", configurationDao.getAppName());
ctx.put("PUBLIC_SID", publicSID);
ctx.put("LABELSHARER", label_sharer);
addKeystore(ctx);
ctx.put("LIBRARIES", libs);
ctx.put("organization_id", orgIdAsString);
ctx.put("startUpClass", startUpClass);
ctx.put("codebase", baseURL + OmFileHelper.SCREENSHARING_DIR);
ctx.put("red5-host", rtmphostlocal);
ctx.put("red5-app", OpenmeetingsVariables.webAppRootKey + "/" + roomId);
ctx.put("default_quality_screensharing",
configurationDao
.getConfValue("default.quality.screensharing", String.class, "1"));
//invited guest does not have valid user_id (have user_id == -1)
ctx.put("user_id", users_id);
ctx.put("port", port);
ctx.put("allowRecording", allowRecording);
ctx.put("allowPublishing", allowPublishing);
String requestedFile = StringUtils.deleteWhitespace(domain + "_" + roomId) + ".jnlp";
response.setContentType("application/x-java-jnlp-file");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition",
"Inline; filename=\"" + requestedFile + "\"");
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
ve.mergeTemplate(
"screenshare.vm"
, "UTF-8"
, ctx
, response.getWriter());
} catch (Exception er) {
log.error("[ScreenController]", er);
}
}
private StringBuilder addArgument(StringBuilder sb, Object arg) {
return sb.append("\t\t<argument>").append(arg).append("</argument>\n");
}
private void addKeystore(Context ctx) {
log.debug("RTMP Sharer Keystore :: start");
StringBuilder sb = new StringBuilder();
FileInputStream fis = null;
try {
File conf = new File(OmFileHelper.getRootDir(), "conf");
File keyStore = new File(conf, "keystore.screen");
if (keyStore.exists()) {
Properties red5Props = new Properties();
red5Props.load(new FileInputStream(new File(conf, "red5.properties")));
byte keyBytes[] = new byte[(int)keyStore.length()];
fis = new FileInputStream(keyStore);
fis.read(keyBytes);
sb = addArgument(addArgument(sb, Hex.encodeHexString(keyBytes)), red5Props.getProperty("rtmps.keystorepass"));
/*
KeyStore ksIn = KeyStore.getInstance(KeyStore.getDefaultType());
ksIn.load(new FileInputStream(keyStore), red5Props.getProperty("rtmps.keystorepass").toCharArray());
ByteArrayInputStream bin = new ByteArrayInputStream()
byte fileContent[] = new byte[(int)file.length()];
sb = addArgument(sb, Object arg)
ctx.put("$KEYSTORE", users_id);
/*
KeyStore ksOut = KeyStore.getInstance(KeyStore.getDefaultType());
for (Certificate cert : ksIn.getCertificateChain("red5")) {
PublicKey pub = cert.getPublicKey();
TrustedCertificateEntry tce = new TrustedCertificateEntry(cert);
tce.
}
*/
}
} catch (Exception e) {
//no op
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// no op
}
}
}
ctx.put("KEYSTORE", sb);
}
}