forked from j62/ctbrec
Attach HMAC only to recordings
This commit is contained in:
parent
5d2d5145b9
commit
9df30b3342
|
@ -1,7 +1,11 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -24,7 +28,8 @@ public class Player {
|
||||||
private static PlayerThread playerThread;
|
private static PlayerThread playerThread;
|
||||||
public static Scene scene;
|
public static Scene scene;
|
||||||
|
|
||||||
private Player() {}
|
private Player() {
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean play(String url) {
|
public static boolean play(String url) {
|
||||||
return play(url, true);
|
return play(url, true);
|
||||||
|
@ -38,7 +43,7 @@ public class Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
playerThread = new PlayerThread(url);
|
playerThread = new PlayerThread(url);
|
||||||
if(!async) {
|
if (!async) {
|
||||||
playerThread.join();
|
playerThread.join();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -69,14 +74,14 @@ public class Player {
|
||||||
|
|
||||||
public static boolean play(Model model, boolean async) {
|
public static boolean play(Model model, boolean async) {
|
||||||
try {
|
try {
|
||||||
if(model.isOnline(true)) {
|
if (model.isOnline(true)) {
|
||||||
boolean singlePlayer = Config.getInstance().getSettings().singlePlayer;
|
boolean singlePlayer = Config.getInstance().getSettings().singlePlayer;
|
||||||
if (singlePlayer && playerThread != null && playerThread.isRunning()) {
|
if (singlePlayer && playerThread != null && playerThread.isRunning()) {
|
||||||
playerThread.stopThread();
|
playerThread.stopThread();
|
||||||
}
|
}
|
||||||
List<StreamSource> sources = model.getStreamSources();
|
List<StreamSource> sources = model.getStreamSources();
|
||||||
Collections.sort(sources);
|
Collections.sort(sources);
|
||||||
StreamSource best = sources.get(sources.size()-1);
|
StreamSource best = sources.get(sources.size() - 1);
|
||||||
LOG.debug("Playing {}", best.getMediaPlaylistUrl());
|
LOG.debug("Playing {}", best.getMediaPlaylistUrl());
|
||||||
return Player.play(best.getMediaPlaylistUrl(), async);
|
return Player.play(best.getMediaPlaylistUrl(), async);
|
||||||
} else {
|
} else {
|
||||||
|
@ -90,14 +95,12 @@ public class Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void stop() {
|
public static void stop() {
|
||||||
if (playerThread != null) {
|
if (playerThread != null) {
|
||||||
playerThread.stopThread();
|
playerThread.stopThread();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class PlayerThread extends Thread {
|
private static class PlayerThread extends Thread {
|
||||||
private boolean running = false;
|
private boolean running = false;
|
||||||
private Process playerProcess;
|
private Process playerProcess;
|
||||||
|
@ -124,21 +127,11 @@ public class Player {
|
||||||
try {
|
try {
|
||||||
if (cfg.getSettings().localRecording && rec != null) {
|
if (cfg.getSettings().localRecording && rec != null) {
|
||||||
File file = new File(cfg.getSettings().recordingsDir, rec.getPath());
|
File file = new File(cfg.getSettings().recordingsDir, rec.getPath());
|
||||||
String[] args = new String[] {
|
String[] args = new String[] { cfg.getSettings().mediaPlayer, file.getName() };
|
||||||
cfg.getSettings().mediaPlayer,
|
|
||||||
file.getName()
|
|
||||||
};
|
|
||||||
playerProcess = rt.exec(args, OS.getEnvironment(), file.getParentFile());
|
playerProcess = rt.exec(args, OS.getEnvironment(), file.getParentFile());
|
||||||
} else {
|
} else {
|
||||||
if(cfg.getSettings().requireAuthentication) {
|
if (rec != null) {
|
||||||
URL u = new URL(url);
|
url = getRemoteRecordingUrl(rec, cfg);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
LOG.debug("Playing {}", url);
|
LOG.debug("Playing {}", url);
|
||||||
playerProcess = rt.exec(cfg.getSettings().mediaPlayer + " " + 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,
|
// 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
|
// 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(), 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.setName("Player stdout pipe");
|
||||||
std.setDaemon(true);
|
std.setDaemon(true);
|
||||||
std.start();
|
std.start();
|
||||||
Thread err = new Thread(new StreamRedirectThread(playerProcess.getErrorStream(), new DevNull()));
|
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.setName("Player stderr pipe");
|
||||||
err.setDaemon(true);
|
err.setDaemon(true);
|
||||||
err.start();
|
err.start();
|
||||||
|
@ -166,6 +159,23 @@ public class Player {
|
||||||
running = false;
|
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() {
|
public boolean isRunning() {
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
|
|
@ -537,8 +537,6 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void play(Recording recording) {
|
private void play(Recording recording) {
|
||||||
final String url;
|
|
||||||
if (Config.getInstance().getSettings().localRecording) {
|
|
||||||
new Thread() {
|
new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -548,20 +546,6 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.start();
|
}.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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void delete(List<JavaFxRecording> recordings) {
|
private void delete(List<JavaFxRecording> recordings) {
|
||||||
|
|
Loading…
Reference in New Issue