diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java index 6e9faba7..1c21a7ca 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java +++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java @@ -44,6 +44,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; +import io.openvidu.client.OpenViduException; import io.openvidu.server.cdr.CDRLoggerFile; import io.openvidu.server.cdr.CallDetailRecord; import io.openvidu.server.config.OpenviduConfig; @@ -233,7 +234,14 @@ public class OpenViduServer implements JsonRpcConfigurer { } if (this.openviduConfig().isRecordingModuleEnabled()) { - this.recordingManager().initializeRecordingManager(); + try { + this.recordingManager().initializeRecordingManager(); + } catch (OpenViduException e) { + log.error( + "Error initializing recording path \"{}\" set with system property \"openvidu.recording.path\". Shutting down OpenVidu Server", + this.openviduConfig().getOpenViduRecordingPath()); + System.exit(1); + } } httpUrl = openviduConf.getFinalUrl(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java index 0801d153..283b9a87 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java @@ -39,7 +39,11 @@ import java.util.stream.Collectors; import javax.ws.rs.ProcessingException; import org.apache.commons.io.FileUtils; +import org.kurento.client.ErrorEvent; +import org.kurento.client.EventListener; +import org.kurento.client.MediaPipeline; import org.kurento.client.MediaProfileSpecType; +import org.kurento.client.RecorderEndpoint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -62,7 +66,11 @@ import io.openvidu.server.core.Participant; import io.openvidu.server.core.Session; import io.openvidu.server.core.SessionEventsHandler; import io.openvidu.server.core.SessionManager; +import io.openvidu.server.kurento.KurentoClientProvider; +import io.openvidu.server.kurento.KurentoClientSessionInfo; +import io.openvidu.server.kurento.OpenViduKurentoClientSessionInfo; import io.openvidu.server.recording.Recording; +import io.openvidu.server.utils.CustomFileManager; public class RecordingManager { @@ -81,6 +89,9 @@ public class RecordingManager { @Autowired protected OpenviduConfig openviduConfig; + @Autowired + private KurentoClientProvider kcProvider; + protected Map startingRecordings = new ConcurrentHashMap<>(); protected Map startedRecordings = new ConcurrentHashMap<>(); protected Map sessionsRecordings = new ConcurrentHashMap<>(); @@ -100,7 +111,7 @@ public class RecordingManager { return this.sessionHandler; } - public void initializeRecordingManager() { + public void initializeRecordingManager() throws OpenViduException { RecordingManager.IMAGE_TAG = openviduConfig.getOpenViduRecordingVersion(); @@ -513,18 +524,77 @@ public class RecordingManager { return fileNamesNoExtension; } - private File initRecordingPath() throws OpenViduException { + private void initRecordingPath() throws OpenViduException { + log.info("Initializing recording path"); try { - Path path = Files.createDirectories(Paths.get(this.openviduConfig.getOpenViduRecordingPath())); + final String recPath = this.openviduConfig.getOpenViduRecordingPath(); + final String testFolderPath = recPath + "/TEST_RECORDING_PATH_" + System.currentTimeMillis(); + final String testFilePath = testFolderPath + "/TEST_RECORDING_PATH.webm"; + Path path = Files.createDirectories(Paths.get(recPath)); + // Check OpenVidu Server write permissions in recording path if (!Files.isWritable(path)) { - throw new OpenViduException(Code.RECORDING_PATH_NOT_VALID, - "The recording path '" + this.openviduConfig.getOpenViduRecordingPath() - + "' is not valid. Reason: OpenVidu Server process needs write permissions"); + String errorMessage = "The recording path \"" + recPath + + "\" is not valid. Reason: OpenVidu Server needs write permissions. Try running command \"sudo chmod 777 " + + recPath + "\""; + log.error(errorMessage); + throw new OpenViduException(Code.RECORDING_PATH_NOT_VALID, errorMessage); + } else { + log.info("OpenVidu Server has write permissions on recording path: {}", recPath); } - log.info("Recording path: {}", this.openviduConfig.getOpenViduRecordingPath()); - return path.toFile(); + // Check Kurento Media Server write permissions in recording path + KurentoClientSessionInfo kcSessionInfo = new OpenViduKurentoClientSessionInfo("TEST_RECORDING_PATH", + "TEST_RECORDING_PATH"); + MediaPipeline pipeline = this.kcProvider.getKurentoClient(kcSessionInfo).createMediaPipeline(); + RecorderEndpoint recorder = new RecorderEndpoint.Builder(pipeline, "file://" + testFilePath).build(); + + recorder.addErrorListener(new EventListener() { + @Override + public void onEvent(ErrorEvent event) { + if (event.getErrorCode() == 6) { + // KMS write permissions error + log.error("The recording path \"" + recPath + + "\" is not valid. Reason: Kurento Media Server needs write permissions. Try running command \"sudo chmod 777 " + + recPath + "\""); + log.error( + "Error initializing recording path \"{}\" set with system property \"openvidu.recording.path\". Shutting down OpenVidu Server", + recPath); + System.exit(1); + } + } + }); + + recorder.record(); + + try { + Thread.sleep(250); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + + recorder.release(); + pipeline.release(); + + log.info("Kurento Media Server has write permissions on recording path: {}", recPath); + + try { + new CustomFileManager().deleteFolder(testFolderPath); + log.info("OpenVidu Server has write permissions over files created by Kurento Media Server"); + } catch (IOException e) { + String errorMessage = "The recording path \"" + recPath + + "\" is not valid. Reason: OpenVidu Server does not have write permissions over files created by Kurento Media Server. " + + "Try running Kurento Media Server as user \"" + System.getProperty("user.name") + + "\" or run OpenVidu Server as superuser"; + log.error(errorMessage); + log.error( + "Be aware that a folder \"{}\" was created and should be manually deleted (\"sudo rm -rf {}\")", + testFolderPath, testFolderPath); + throw new OpenViduException(Code.RECORDING_PATH_NOT_VALID, errorMessage); + } + + log.info("Recording path successfully initialized at {}", this.openviduConfig.getOpenViduRecordingPath()); + } catch (IOException e) { throw new OpenViduException(Code.RECORDING_PATH_NOT_VALID, "The recording path '" + this.openviduConfig.getOpenViduRecordingPath() + "' is not valid. Reason: " diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java index 69455614..45d79ac2 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java @@ -30,7 +30,7 @@ import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.core.Session; import io.openvidu.server.recording.Recording; import io.openvidu.server.utils.CommandExecutor; -import io.openvidu.server.utils.CustomFileWriter; +import io.openvidu.server.utils.CustomFileManager; public abstract class RecordingService { @@ -38,7 +38,7 @@ public abstract class RecordingService { protected OpenviduConfig openviduConfig; protected RecordingManager recordingManager; - protected CustomFileWriter fileWriter = new CustomFileWriter(); + protected CustomFileManager fileWriter = new CustomFileManager(); RecordingService(RecordingManager recordingManager, OpenviduConfig openviduConfig) { this.recordingManager = recordingManager; diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/CustomFileWriter.java b/openvidu-server/src/main/java/io/openvidu/server/utils/CustomFileManager.java similarity index 90% rename from openvidu-server/src/main/java/io/openvidu/server/utils/CustomFileWriter.java rename to openvidu-server/src/main/java/io/openvidu/server/utils/CustomFileManager.java index 607f4123..1517db51 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/utils/CustomFileWriter.java +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/CustomFileManager.java @@ -22,12 +22,13 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; +import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class CustomFileWriter { +public class CustomFileManager { - private static final Logger log = LoggerFactory.getLogger(CustomFileWriter.class); + private static final Logger log = LoggerFactory.getLogger(CustomFileManager.class); public void createAndWriteFile(String filePath, String text) { try { @@ -52,7 +53,10 @@ public class CustomFileWriter { } else { return false; } + } + public void deleteFolder(String path) throws IOException { + FileUtils.deleteDirectory(new File(path)); } private void writeAndCloseOnOutputStreamWriter(FileOutputStream fos, String text) throws IOException {