case PAUSE:
case PAUSE_RAW:
case RECEIVE_VIDEO:
case RECEIVE_AUDIO:
IStreamService streamService = (IStreamService) ScopeUtils.getScopeService(conn.getScope(), IStreamService.class, StreamService.class);
Status status = null;
try {
log.debug("Invoking {} from {} with service: {}", new Object[] { call, conn, streamService });
if (invokeCall(conn, call, streamService)) {
log.debug("Stream service invoke {} success", action);
} else {
status = getStatus(NS_INVALID_ARGUMENT).asStatus();
status.setDescription(String.format("Failed to %s (stream id: %d)", action, source.getStreamId()));
}
} catch (Throwable err) {
log.error("Error while invoking {} on stream service. {}", action, err);
status = getStatus(NS_FAILED).asStatus();
status.setDescription(String.format("Error while invoking %s (stream id: %d)", action, source.getStreamId()));
status.setDetails(err.getMessage());
}
if (status != null) {
channel.sendStatus(status);
} else {
log.debug("Status for {} was null", action);
}
break;
default:
log.debug("Defaulting to invoke for: {}", action);
invokeCall(conn, call);
}
} else {
// handle service calls
invokeCall(conn, call);
}
} else {
if (StreamAction.CONNECT.equals(action)) {
// Handle connection
log.debug("connect");
// Get parameters passed from client to
// NetConnection#connection
final Map<String, Object> params = command.getConnectionParams();
// Get hostname
String host = getHostname((String) params.get("tcUrl"));
// app name as path, but without query string if there is one
String path = (String) params.get("app");
if (path.indexOf("?") != -1) {
int idx = path.indexOf("?");
params.put("queryString", path.substring(idx));
path = path.substring(0, idx);
}
params.put("path", path);
// connection setup
conn.setup(host, path, params);
try {
// Lookup server scope when connected using host and application name
IGlobalScope global = server.lookupGlobal(host, path);
log.trace("Global lookup result: {}", global);
if (global != null) {
final IContext context = global.getContext();
IScope scope = null;
try {
// TODO optimize this to use Scope instead of Context
scope = context.resolveScope(global, path);
// if global scope connection is not allowed, reject
if (scope.getDepth() < 1 && !globalScopeConnectionAllowed) {
call.setStatus(Call.STATUS_ACCESS_DENIED);
if (call instanceof IPendingServiceCall) {
IPendingServiceCall pc = (IPendingServiceCall) call;
StatusObject status = getStatus(NC_CONNECT_REJECTED);
status.setDescription("Global scope connection disallowed on this server.");
pc.setResult(status);
}
disconnectOnReturn = true;
}
if (scope != null) {
if (log.isTraceEnabled()) {
log.trace("Connecting to: {}", scope);
}
if (log.isDebugEnabled()) {
log.debug("Connecting to: {}", scope.getName());
log.debug("Conn {}, scope {}, call {}", new Object[] { conn, scope, call });
log.debug("Call args {}", call.getArguments());
}
boolean okayToConnect;
try {
if (call.getArguments() != null) {
okayToConnect = conn.connect(scope, call.getArguments());
} else {
okayToConnect = conn.connect(scope);
}
if (okayToConnect) {
log.debug("Connected - {}", conn.getClient());
call.setStatus(Call.STATUS_SUCCESS_RESULT);
if (call instanceof IPendingServiceCall) {
IPendingServiceCall pc = (IPendingServiceCall) call;
//send fmsver and capabilities
StatusObject result = getStatus(NC_CONNECT_SUCCESS);
result.setAdditional("fmsVer", Red5.getFMSVersion());
result.setAdditional("capabilities", Integer.valueOf(31));
result.setAdditional("mode", Integer.valueOf(1));
result.setAdditional("data", Red5.getDataVersion());
pc.setResult(result);
}
// Measure initial roundtrip time after connecting
conn.ping(new Ping(Ping.STREAM_BEGIN, 0, -1));
disconnectOnReturn = false;
} else {
log.debug("Connect failed");
call.setStatus(Call.STATUS_ACCESS_DENIED);
if (call instanceof IPendingServiceCall) {
IPendingServiceCall pc = (IPendingServiceCall) call;
pc.setResult(getStatus(NC_CONNECT_REJECTED));
}
disconnectOnReturn = true;
}
} catch (ClientRejectedException rejected) {
log.debug("Connect rejected");
call.setStatus(Call.STATUS_ACCESS_DENIED);
if (call instanceof IPendingServiceCall) {
IPendingServiceCall pc = (IPendingServiceCall) call;
StatusObject status = getStatus(NC_CONNECT_REJECTED);
Object reason = rejected.getReason();
if (reason != null) {
status.setApplication(reason);
//should we set description?
status.setDescription(reason.toString());
}
pc.setResult(status);
}
disconnectOnReturn = true;
}
}
} catch (ScopeNotFoundException err) {
log.warn("Scope not found", err);
call.setStatus(Call.STATUS_SERVICE_NOT_FOUND);
if (call instanceof IPendingServiceCall) {
StatusObject status = getStatus(NC_CONNECT_REJECTED);
status.setDescription(String.format("No scope '%s' on this server.", path));
((IPendingServiceCall) call).setResult(status);
}
log.info("Scope {} not found on {}", path, host);
disconnectOnReturn = true;
} catch (ScopeShuttingDownException err) {
log.warn("Scope shutting down", err);
call.setStatus(Call.STATUS_APP_SHUTTING_DOWN);
if (call instanceof IPendingServiceCall) {
StatusObject status = getStatus(NC_CONNECT_APPSHUTDOWN);
status.setDescription(String.format("Application at '%s' is currently shutting down.", path));
((IPendingServiceCall) call).setResult(status);
}
log.info("Application at {} currently shutting down on {}", path, host);
disconnectOnReturn = true;
}
} else {
log.warn("Scope {} not found", path);
call.setStatus(Call.STATUS_SERVICE_NOT_FOUND);
if (call instanceof IPendingServiceCall) {
StatusObject status = getStatus(NC_CONNECT_INVALID_APPLICATION);
status.setDescription(String.format("No scope '%s' on this server.", path));
((IPendingServiceCall) call).setResult(status);
}
log.info("No application scope found for {} on host {}", path, host);
disconnectOnReturn = true;
}
} catch (RuntimeException e) {
call.setStatus(Call.STATUS_GENERAL_EXCEPTION);
if (call instanceof IPendingServiceCall) {
IPendingServiceCall pc = (IPendingServiceCall) call;
pc.setResult(getStatus(NC_CONNECT_FAILED));
}
log.error("Error connecting {}", e);
disconnectOnReturn = true;
}
// Evaluate request for AMF3 encoding
if (Integer.valueOf(3).equals(params.get("objectEncoding"))) {
if (call instanceof IPendingServiceCall) {
Object pcResult = ((IPendingServiceCall) call).getResult();
Map<String, Object> result;
if (pcResult instanceof Map) {
result = (Map<String, Object>) pcResult;
result.put("objectEncoding", 3);
} else if (pcResult instanceof StatusObject) {
result = new HashMap<String, Object>();
StatusObject status = (StatusObject) pcResult;
result.put("code", status.getCode());
result.put("description", status.getDescription());
result.put("application", status.getApplication());
result.put("level", status.getLevel());
result.put("objectEncoding", 3);
((IPendingServiceCall) call).setResult(result);
}
}
conn.getState().setEncoding(Encoding.AMF3);