From 9df30b334240de78bd0448bd9bcfb450437855c7 Mon Sep 17 00:00:00 2001 From: 0xboobface <0xboobface@gmail.com> Date: Sun, 22 Dec 2019 12:11:32 +0100 Subject: [PATCH] Attach HMAC only to recordings --- client/src/main/java/ctbrec/ui/Player.java | 52 +++++++++++-------- .../main/java/ctbrec/ui/RecordingsTab.java | 32 +++--------- 2 files changed, 39 insertions(+), 45 deletions(-) diff --git a/client/src/main/java/ctbrec/ui/Player.java b/client/src/main/java/ctbrec/ui/Player.java index 14b0f53b..bc1c5522 100644 --- a/client/src/main/java/ctbrec/ui/Player.java +++ b/client/src/main/java/ctbrec/ui/Player.java @@ -1,7 +1,11 @@ package ctbrec.ui; import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; import java.net.URL; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.Collections; import java.util.List; @@ -24,7 +28,8 @@ public class Player { private static PlayerThread playerThread; public static Scene scene; - private Player() {} + private Player() { + } public static boolean play(String url) { return play(url, true); @@ -38,7 +43,7 @@ public class Player { } playerThread = new PlayerThread(url); - if(!async) { + if (!async) { playerThread.join(); } return true; @@ -69,14 +74,14 @@ public class Player { public static boolean play(Model model, boolean async) { try { - if(model.isOnline(true)) { + if (model.isOnline(true)) { boolean singlePlayer = Config.getInstance().getSettings().singlePlayer; if (singlePlayer && playerThread != null && playerThread.isRunning()) { playerThread.stopThread(); } List sources = model.getStreamSources(); Collections.sort(sources); - StreamSource best = sources.get(sources.size()-1); + StreamSource best = sources.get(sources.size() - 1); LOG.debug("Playing {}", best.getMediaPlaylistUrl()); return Player.play(best.getMediaPlaylistUrl(), async); } else { @@ -90,14 +95,12 @@ public class Player { } } - public static void stop() { if (playerThread != null) { playerThread.stopThread(); } } - private static class PlayerThread extends Thread { private boolean running = false; private Process playerProcess; @@ -124,21 +127,11 @@ public class Player { try { if (cfg.getSettings().localRecording && rec != null) { File file = new File(cfg.getSettings().recordingsDir, rec.getPath()); - String[] args = new String[] { - cfg.getSettings().mediaPlayer, - file.getName() - }; + String[] args = new String[] { cfg.getSettings().mediaPlayer, file.getName() }; playerProcess = rt.exec(args, OS.getEnvironment(), file.getParentFile()); } else { - if(cfg.getSettings().requireAuthentication) { - URL u = new URL(url); - String path = u.getPath(); - if(!cfg.getContextPath().isEmpty()) { - path = path.substring(cfg.getContextPath().length()); - } - byte[] key = cfg.getSettings().key; - String hmac = Hmac.calculate(path, key); - url = url + "?hmac=" + hmac; + if (rec != null) { + url = getRemoteRecordingUrl(rec, cfg); } LOG.debug("Playing {}", url); playerProcess = rt.exec(cfg.getSettings().mediaPlayer + " " + url); @@ -147,12 +140,12 @@ public class Player { // create threads, which read stdout and stderr of the player process. these are needed, // because otherwise the internal buffer for these streams fill up and block the process Thread std = new Thread(new StreamRedirectThread(playerProcess.getInputStream(), new DevNull())); - //Thread std = new Thread(new StreamRedirectThread(playerProcess.getInputStream(), System.out)); + // Thread std = new Thread(new StreamRedirectThread(playerProcess.getInputStream(), System.out)); std.setName("Player stdout pipe"); std.setDaemon(true); std.start(); Thread err = new Thread(new StreamRedirectThread(playerProcess.getErrorStream(), new DevNull())); - //Thread err = new Thread(new StreamRedirectThread(playerProcess.getErrorStream(), System.err)); + // Thread err = new Thread(new StreamRedirectThread(playerProcess.getErrorStream(), System.err)); err.setName("Player stderr pipe"); err.setDaemon(true); err.start(); @@ -166,6 +159,23 @@ public class Player { running = false; } + private String getRemoteRecordingUrl(Recording rec, Config cfg) + throws MalformedURLException, InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException { + String hlsBase = Config.getInstance().getServerUrl() + "/hls"; + String recUrl = hlsBase + rec.getPath() + (rec.isSegmented() ? "/playlist.m3u8" : ""); + if (cfg.getSettings().requireAuthentication) { + URL u = new URL(recUrl); + String path = u.getPath(); + if (!cfg.getContextPath().isEmpty()) { + path = path.substring(cfg.getContextPath().length()); + } + byte[] key = cfg.getSettings().key; + String hmac = Hmac.calculate(path, key); + recUrl = recUrl + "?hmac=" + hmac; + } + return recUrl; + } + public boolean isRunning() { return running; } diff --git a/client/src/main/java/ctbrec/ui/RecordingsTab.java b/client/src/main/java/ctbrec/ui/RecordingsTab.java index 98edb20a..e18fbf5e 100644 --- a/client/src/main/java/ctbrec/ui/RecordingsTab.java +++ b/client/src/main/java/ctbrec/ui/RecordingsTab.java @@ -537,31 +537,15 @@ public class RecordingsTab extends Tab implements TabSelectionListener { } private void play(Recording recording) { - final String url; - if (Config.getInstance().getSettings().localRecording) { - new Thread() { - @Override - public void run() { - boolean started = Player.play(recording); - if(started && Config.getInstance().getSettings().showPlayerStarting) { - Platform.runLater(() -> Toast.makeText(getTabPane().getScene(), "Starting Player", 2000, 500, 500)); - } + new Thread() { + @Override + public void run() { + boolean started = Player.play(recording); + if(started && Config.getInstance().getSettings().showPlayerStarting) { + Platform.runLater(() -> Toast.makeText(getTabPane().getScene(), "Starting Player", 2000, 500, 500)); } - }.start(); - } else { - String hlsBase = Config.getInstance().getServerUrl() + "/hls"; - url = hlsBase + recording.getPath() + (recording.isSegmented() ? "/playlist.m3u8" : ""); - new Thread() { - @Override - public void run() { - boolean started = Player.play(url); - if(started && Config.getInstance().getSettings().showPlayerStarting) { - Platform.runLater(() -> Toast.makeText(getTabPane().getScene(), "Starting Player", 2000, 500, 500)); - } - } - }.start(); - } - + } + }.start(); } private void delete(List recordings) {