diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index 5f1f39df..339a4ed7 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -295,7 +295,7 @@ public abstract class SessionManager { } public String newToken(Session session, OpenViduRole role, String serverMetadata, - KurentoTokenOptions kurentoTokenOptions) throws OpenViduException { + KurentoTokenOptions kurentoTokenOptions) throws Exception { if (!formatChecker.isServerMetadataFormatCorrect(serverMetadata)) { log.error("Data invalid format"); throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format"); @@ -307,7 +307,7 @@ public abstract class SessionManager { return tokenObj.getToken(); } - public Token newTokenForInsecureUser(Session session, String token, String serverMetadata) { + public Token newTokenForInsecureUser(Session session, String token, String serverMetadata) throws Exception { Token tokenObj = new Token(token, OpenViduRole.PUBLISHER, serverMetadata != null ? serverMetadata : "", this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null, null); session.storeToken(tokenObj); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index 3bbece90..472f4ee8 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -23,6 +23,6 @@ import io.openvidu.server.kurento.core.KurentoTokenOptions; public interface TokenGenerator { public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata, - KurentoTokenOptions kurentoTokenOptions); + KurentoTokenOptions kurentoTokenOptions) throws Exception; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGeneratorDefault.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGeneratorDefault.java index 1d0d83a0..eeb46563 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGeneratorDefault.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGeneratorDefault.java @@ -35,13 +35,13 @@ public class TokenGeneratorDefault implements TokenGenerator { @Autowired protected OpenviduConfig openviduConfig; - + @Autowired protected OpenviduBuildInfo openviduBuildConfig; @Override public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata, - KurentoTokenOptions kurentoTokenOptions) { + KurentoTokenOptions kurentoTokenOptions) throws Exception { String token = OpenViduServer.wsUrl; token += "?sessionId=" + sessionId; token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() diff --git a/openvidu-server/src/main/java/io/openvidu/server/coturn/BashCoturnCredentialsService.java b/openvidu-server/src/main/java/io/openvidu/server/coturn/BashCoturnCredentialsService.java index bd293173..95327cb4 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/coturn/BashCoturnCredentialsService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/coturn/BashCoturnCredentialsService.java @@ -74,23 +74,19 @@ public class BashCoturnCredentialsService extends CoturnCredentialsService { } @Override - public TurnCredentials createUser() { + public TurnCredentials createUser() throws IOException, InterruptedException { TurnCredentials credentials = null; log.info("Creating COTURN user"); String user = RandomStringUtils.randomAlphanumeric(6).toUpperCase(); String pass = RandomStringUtils.randomAlphanumeric(6).toLowerCase(); String command = "turnadmin -a -u " + user + " -r openvidu -p " + pass + " -N " + this.coturnDatabaseString; - try { - String response = CommandExecutor.execCommand("/bin/sh", "-c", command); - if (response.contains("connection success: " + this.trimmedCoturnDatabaseString)) { - credentials = new TurnCredentials(user, pass); - this.cleanTurnLogFiles(); - log.info("COTURN user created: true"); - } else { - log.info("COTURN user created: false"); - } - } catch (IOException | InterruptedException e) { - e.printStackTrace(); + String response = CommandExecutor.execCommand("/bin/sh", "-c", command); + if (response.contains("connection success: " + this.trimmedCoturnDatabaseString)) { + credentials = new TurnCredentials(user, pass); + this.cleanTurnLogFiles(); + log.info("COTURN user created: true"); + } else { + log.info("COTURN user created: false"); } return credentials; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/coturn/CoturnCredentialsService.java b/openvidu-server/src/main/java/io/openvidu/server/coturn/CoturnCredentialsService.java index 048ce0f4..98f7de05 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/coturn/CoturnCredentialsService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/coturn/CoturnCredentialsService.java @@ -35,7 +35,7 @@ public abstract class CoturnCredentialsService { protected String coturnDatabaseString; protected String trimmedCoturnDatabaseString; - public abstract TurnCredentials createUser(); + public abstract TurnCredentials createUser() throws Exception; public abstract boolean deleteUser(String user); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index bf5d18cf..98ecaad8 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -207,7 +207,7 @@ public class SessionRestController { public ResponseEntity listSessions( @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { - log.info("REST API: GET /api/sessions"); + log.info("REST API: GET /api/sessions?webRtcStats={}", webRtcStats); Collection sessions = this.sessionManager.getSessionsWithNotActive(); JsonObject json = new JsonObject(); @@ -423,6 +423,10 @@ public class SessionRestController { responseJson.add("kurentoOptions", kurentoOptsResponse); } return new ResponseEntity<>(responseJson.toString(), getResponseHeaders(), HttpStatus.OK); + } catch (Exception e) { + return this.generateErrorResponse( + "Error generating token for session " + sessionId + ": " + e.getMessage(), "/api/tokens", + HttpStatus.INTERNAL_SERVER_ERROR); } finally { session.closingLock.readLock().unlock(); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java index ff6a9ce7..bece2d68 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java @@ -244,7 +244,12 @@ public class RpcHandler extends DefaultJsonRpcHandler { sessionManager.newInsecureParticipant(participantPrivatetId); token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); - sessionManager.newTokenForInsecureUser(session, token, null); + try { + sessionManager.newTokenForInsecureUser(session, token, null); + } catch (Exception e) { + throw new OpenViduException(Code.TOKEN_CANNOT_BE_CREATED_ERROR_CODE, + "Unable to create token for session " + sessionId + ": " + e.getMessage()); + } if (recorder) { generateRecorderParticipant = true; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/CommandExecutor.java b/openvidu-server/src/main/java/io/openvidu/server/utils/CommandExecutor.java index 28f4eb71..4e7a1165 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/utils/CommandExecutor.java +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/CommandExecutor.java @@ -21,12 +21,21 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Pablo Fuente (pablofuenteperez@gmail.com) */ public class CommandExecutor { + private static final Logger log = LoggerFactory.getLogger(CommandExecutor.class); + + private static final long MILLIS_TIMEOUT = 10000; + public static String execCommand(String... command) throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder(command); processBuilder.redirectErrorStream(true); @@ -44,7 +53,12 @@ public class CommandExecutor { ProcessBuilder processBuilder = new ProcessBuilder(command).redirectOutput(standardOutputFile) .redirectError(errorOutputFile); Process process = processBuilder.start(); - process.waitFor(); + if (!process.waitFor(MILLIS_TIMEOUT, TimeUnit.MILLISECONDS)) { + log.error("Command {} did not receive a response in {} ms", Arrays.toString(command), MILLIS_TIMEOUT); + String errorMsg = "Current process status of host:\n" + gatherLinuxHostInformation(); + log.error(errorMsg); + throw new IOException(errorMsg); + } } private static String commonExecCommand(ProcessBuilder processBuilder) throws IOException, InterruptedException { @@ -60,7 +74,14 @@ public class CommandExecutor { while ((readLine = processOutputReader.readLine()) != null) { processOutput.append(readLine + System.lineSeparator()); } - process.waitFor(); + + if (!process.waitFor(MILLIS_TIMEOUT, TimeUnit.MILLISECONDS)) { + log.error("Command {} did not receive a response in {} ms", + Arrays.toString(processBuilder.command().toArray()), MILLIS_TIMEOUT); + String errorMsg = "Current process status of host:\n" + gatherLinuxHostInformation(); + log.error(errorMsg); + throw new IOException(errorMsg); + } output = processOutput.toString().trim(); } finally { if (inputStreamReader != null) { @@ -73,4 +94,9 @@ public class CommandExecutor { return output; } + public static String gatherLinuxHostInformation() throws IOException, InterruptedException { + final String psCommand = "ps -eo pid,ppid,user,%mem,%cpu,cmd --sort=-%cpu"; + return execCommand("/bin/sh", "-c", psCommand); + } + }