openvidu-server: CommandExecutor timeout

pull/494/head
pabloFuente 2020-06-04 12:28:40 +02:00
parent c150b87a2a
commit c4a6ca5543
8 changed files with 53 additions and 22 deletions

View File

@ -295,7 +295,7 @@ public abstract class SessionManager {
} }
public String newToken(Session session, OpenViduRole role, String serverMetadata, public String newToken(Session session, OpenViduRole role, String serverMetadata,
KurentoTokenOptions kurentoTokenOptions) throws OpenViduException { KurentoTokenOptions kurentoTokenOptions) throws Exception {
if (!formatChecker.isServerMetadataFormatCorrect(serverMetadata)) { if (!formatChecker.isServerMetadataFormatCorrect(serverMetadata)) {
log.error("Data invalid format"); log.error("Data invalid format");
throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format"); throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format");
@ -307,7 +307,7 @@ public abstract class SessionManager {
return tokenObj.getToken(); 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 : "", Token tokenObj = new Token(token, OpenViduRole.PUBLISHER, serverMetadata != null ? serverMetadata : "",
this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null, null); this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null, null);
session.storeToken(tokenObj); session.storeToken(tokenObj);

View File

@ -23,6 +23,6 @@ import io.openvidu.server.kurento.core.KurentoTokenOptions;
public interface TokenGenerator { public interface TokenGenerator {
public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata, public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata,
KurentoTokenOptions kurentoTokenOptions); KurentoTokenOptions kurentoTokenOptions) throws Exception;
} }

View File

@ -41,7 +41,7 @@ public class TokenGeneratorDefault implements TokenGenerator {
@Override @Override
public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata, public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata,
KurentoTokenOptions kurentoTokenOptions) { KurentoTokenOptions kurentoTokenOptions) throws Exception {
String token = OpenViduServer.wsUrl; String token = OpenViduServer.wsUrl;
token += "?sessionId=" + sessionId; token += "?sessionId=" + sessionId;
token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()

View File

@ -74,23 +74,19 @@ public class BashCoturnCredentialsService extends CoturnCredentialsService {
} }
@Override @Override
public TurnCredentials createUser() { public TurnCredentials createUser() throws IOException, InterruptedException {
TurnCredentials credentials = null; TurnCredentials credentials = null;
log.info("Creating COTURN user"); log.info("Creating COTURN user");
String user = RandomStringUtils.randomAlphanumeric(6).toUpperCase(); String user = RandomStringUtils.randomAlphanumeric(6).toUpperCase();
String pass = RandomStringUtils.randomAlphanumeric(6).toLowerCase(); String pass = RandomStringUtils.randomAlphanumeric(6).toLowerCase();
String command = "turnadmin -a -u " + user + " -r openvidu -p " + pass + " -N " + this.coturnDatabaseString; String command = "turnadmin -a -u " + user + " -r openvidu -p " + pass + " -N " + this.coturnDatabaseString;
try { String response = CommandExecutor.execCommand("/bin/sh", "-c", command);
String response = CommandExecutor.execCommand("/bin/sh", "-c", command); if (response.contains("connection success: " + this.trimmedCoturnDatabaseString)) {
if (response.contains("connection success: " + this.trimmedCoturnDatabaseString)) { credentials = new TurnCredentials(user, pass);
credentials = new TurnCredentials(user, pass); this.cleanTurnLogFiles();
this.cleanTurnLogFiles(); log.info("COTURN user created: true");
log.info("COTURN user created: true"); } else {
} else { log.info("COTURN user created: false");
log.info("COTURN user created: false");
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} }
return credentials; return credentials;
} }

View File

@ -35,7 +35,7 @@ public abstract class CoturnCredentialsService {
protected String coturnDatabaseString; protected String coturnDatabaseString;
protected String trimmedCoturnDatabaseString; protected String trimmedCoturnDatabaseString;
public abstract TurnCredentials createUser(); public abstract TurnCredentials createUser() throws Exception;
public abstract boolean deleteUser(String user); public abstract boolean deleteUser(String user);

View File

@ -207,7 +207,7 @@ public class SessionRestController {
public ResponseEntity<?> listSessions( public ResponseEntity<?> listSessions(
@RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { @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<Session> sessions = this.sessionManager.getSessionsWithNotActive(); Collection<Session> sessions = this.sessionManager.getSessionsWithNotActive();
JsonObject json = new JsonObject(); JsonObject json = new JsonObject();
@ -423,6 +423,10 @@ public class SessionRestController {
responseJson.add("kurentoOptions", kurentoOptsResponse); responseJson.add("kurentoOptions", kurentoOptsResponse);
} }
return new ResponseEntity<>(responseJson.toString(), getResponseHeaders(), HttpStatus.OK); 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 { } finally {
session.closingLock.readLock().unlock(); session.closingLock.readLock().unlock();
} }

View File

@ -244,7 +244,12 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
sessionManager.newInsecureParticipant(participantPrivatetId); sessionManager.newInsecureParticipant(participantPrivatetId);
token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()
+ RandomStringUtils.randomAlphanumeric(15); + 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) { if (recorder) {
generateRecorderParticipant = true; generateRecorderParticipant = true;
} }

View File

@ -21,12 +21,21 @@ import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; 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) * @author Pablo Fuente (pablofuenteperez@gmail.com)
*/ */
public class CommandExecutor { 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 { public static String execCommand(String... command) throws IOException, InterruptedException {
ProcessBuilder processBuilder = new ProcessBuilder(command); ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true); processBuilder.redirectErrorStream(true);
@ -44,7 +53,12 @@ public class CommandExecutor {
ProcessBuilder processBuilder = new ProcessBuilder(command).redirectOutput(standardOutputFile) ProcessBuilder processBuilder = new ProcessBuilder(command).redirectOutput(standardOutputFile)
.redirectError(errorOutputFile); .redirectError(errorOutputFile);
Process process = processBuilder.start(); 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 { private static String commonExecCommand(ProcessBuilder processBuilder) throws IOException, InterruptedException {
@ -60,7 +74,14 @@ public class CommandExecutor {
while ((readLine = processOutputReader.readLine()) != null) { while ((readLine = processOutputReader.readLine()) != null) {
processOutput.append(readLine + System.lineSeparator()); 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(); output = processOutput.toString().trim();
} finally { } finally {
if (inputStreamReader != null) { if (inputStreamReader != null) {
@ -73,4 +94,9 @@ public class CommandExecutor {
return output; 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);
}
} }