Improve file handling in HLS servlet

This commit is contained in:
0xb00bface 2020-10-03 18:29:09 +02:00
parent 073546b9d3
commit 986744dfe7
5 changed files with 37 additions and 56 deletions

View File

@ -162,8 +162,7 @@ public class JavaFxRecording extends Recording {
setProgress(updated.getProgress()); setProgress(updated.getProgress());
setSizeInByte(updated.getSizeInByte()); setSizeInByte(updated.getSizeInByte());
setSingleFile(updated.isSingleFile()); setSingleFile(updated.isSingleFile());
getAssociatedFiles().clear(); setAssociatedFiles(updated.getAssociatedFiles());
getAssociatedFiles().addAll(updated.getAssociatedFiles());
} }
@Override @Override
@ -297,11 +296,6 @@ public class JavaFxRecording extends Recording {
return delegate.getAssociatedFiles(); return delegate.getAssociatedFiles();
} }
@Override
public boolean hasContactSheet() {
return delegate.hasContactSheet();
}
@Override @Override
public Optional<File> getContactSheet() { public Optional<File> getContactSheet() {
return delegate.getContactSheet(); return delegate.getContactSheet();

View File

@ -394,7 +394,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
MenuItem openContactSheet = new MenuItem("Open contact sheet"); MenuItem openContactSheet = new MenuItem("Open contact sheet");
openContactSheet.setOnAction(e -> openContactSheet(first)); openContactSheet.setOnAction(e -> openContactSheet(first));
openContactSheet.setDisable(!first.hasContactSheet()); openContactSheet.setDisable(first.getContactSheet().isEmpty());
contextMenu.getItems().add(openContactSheet); contextMenu.getItems().add(openContactSheet);
// TODO find a way to reenable this // TODO find a way to reenable this
@ -471,7 +471,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
DesktopIntegration.open(target); DesktopIntegration.open(target);
} }
}); });
String url = config.getServerUrl() + "/hls/" + recording.getId() + "/contactsheet.jpg"; String url = config.getServerUrl() + "/hls/" + recording.getId() + f.getCanonicalPath();
if (config.getSettings().requireAuthentication) { if (config.getSettings().requireAuthentication) {
url = UrlUtil.addHmac(url, config); url = UrlUtil.addHmac(url, config);
} }

View File

@ -310,12 +310,12 @@ public class Recording implements Serializable {
return getStatus() == FAILED || getStatus() == WAITING || getStatus() == FINISHED; return getStatus() == FAILED || getStatus() == WAITING || getStatus() == FINISHED;
} }
public Set<String> getAssociatedFiles() { protected void setAssociatedFiles(Set<String> associatedFiles) {
return associatedFiles; this.associatedFiles = associatedFiles;
} }
public boolean hasContactSheet() { public Set<String> getAssociatedFiles() {
return getAssociatedFiles().stream().anyMatch(path -> path.endsWith("contactsheet.jpg")); return associatedFiles;
} }
public Optional<File> getContactSheet() { public Optional<File> getContactSheet() {

View File

@ -4,11 +4,8 @@ import static javax.servlet.http.HttpServletResponse.*;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -22,7 +19,6 @@ import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Config;
import ctbrec.Recording; import ctbrec.Recording;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
@ -30,12 +26,9 @@ public class HlsServlet extends AbstractCtbrecServlet {
private static final transient Logger LOG = LoggerFactory.getLogger(HlsServlet.class); private static final transient Logger LOG = LoggerFactory.getLogger(HlsServlet.class);
private final Config config;
private Recorder recorder; private Recorder recorder;
public HlsServlet(Config config, Recorder recorder) { public HlsServlet(Recorder recorder) {
this.config = config;
this.recorder = recorder; this.recorder = recorder;
} }
@ -43,45 +36,39 @@ public class HlsServlet extends AbstractCtbrecServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String contextPath = getServletContext().getContextPath(); String contextPath = getServletContext().getContextPath();
String request = req.getRequestURI().substring(contextPath.length() + 5); String request = req.getRequestURI().substring(contextPath.length() + 5);
Path recordingsDirPath = Paths.get(config.getSettings().recordingsDir).toAbsolutePath().normalize();
Path requestedFilePath = recordingsDirPath.resolve(request).toAbsolutePath().normalize();
File requestedFile = requestedFilePath.toFile();
try { try {
if (requestedFile.getName().equals("playlist.m3u8")) { String id = request.split("/")[0];
boolean isRequestAuthenticated = checkAuthentication(req, req.getRequestURI()); Optional<Recording> rec = getRecordingById(id);
if (!isRequestAuthenticated) { if (!rec.isPresent()) {
writeResponse(resp, SC_UNAUTHORIZED, "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}"); error404(req, resp);
return; return;
} }
String id = request.substring(0, request.indexOf('/')); String requestedFilePath;
Optional<Recording> rec = getRecordingById(id); File requestFile;
if (rec.isPresent()) { boolean idOnly = request.indexOf('/') < 0;
if (idOnly) {
requestFile = rec.get().getPostProcessedFile();
requestedFilePath = requestFile.getCanonicalPath();
} else {
requestedFilePath = request.substring(request.indexOf('/'));
requestFile = new File(requestedFilePath);
}
if (rec.get().getAssociatedFiles().contains(requestedFilePath)) {
serveSegment(req, resp, requestFile);
} else {
if (requestFile.getName().equals("playlist.m3u8")) {
boolean isRequestAuthenticated = checkAuthentication(req, req.getRequestURI());
if (!isRequestAuthenticated) {
writeResponse(resp, SC_UNAUTHORIZED, "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}");
return;
}
servePlaylist(req, resp, rec.get().getAbsoluteFile()); servePlaylist(req, resp, rec.get().getAbsoluteFile());
} else { } else {
error404(req, resp); requestFile = new File(rec.get().getAbsoluteFile(), requestedFilePath);
return; serveSegment(req, resp, requestFile);
}
} else {
String id = request.split("/")[0];
Optional<Recording> rec = getRecordingById(id);
if (rec.isPresent()) {
File path = rec.get().getAbsoluteFile();
if (!path.isFile()) {
path = new File(path, requestedFile.getName());
}
if (LOG.isTraceEnabled()) {
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String header = headerNames.nextElement();
LOG.trace("{}: {}", header, req.getHeader(header));
}
}
serveSegment(req, resp, path);
} else {
error404(req, resp);
return;
} }
} }
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e1) { } catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e1) {

View File

@ -213,7 +213,7 @@ public class HttpServer {
holder = new ServletHolder(configServlet); holder = new ServletHolder(configServlet);
defaultContext.addServlet(holder, "/config"); defaultContext.addServlet(holder, "/config");
HlsServlet hlsServlet = new HlsServlet(this.config, recorder); HlsServlet hlsServlet = new HlsServlet(recorder);
holder = new ServletHolder(hlsServlet); holder = new ServletHolder(hlsServlet);
defaultContext.addServlet(holder, "/hls/*"); defaultContext.addServlet(holder, "/hls/*");