if (!(conn instanceof IStreamCapableConnection)) {
return;
}
IScope scope = conn.getScope();
IStreamCapableConnection streamConn = (IStreamCapableConnection) conn;
int streamId = getCurrentStreamId();
if (name == null || "".equals(name)) {
sendNSFailed((RTMPConnection) streamConn, "The stream name may not be empty.", name, streamId);
return;
}
IStreamSecurityService security = (IStreamSecurityService) ScopeUtils.getScopeService(scope, IStreamSecurityService.class);
if (security != null) {
Set<IStreamPublishSecurity> handlers = security.getStreamPublishSecurity();
for (IStreamPublishSecurity handler: handlers) {
if (!handler.isPublishAllowed(scope, name, mode)) {
sendNSFailed((RTMPConnection) streamConn, "You are not allowed to publish the stream.", name, streamId);
return;
}
}
}
IBroadcastScope bsScope = getBroadcastScope(scope, name);
if (bsScope != null && !bsScope.getProviders().isEmpty()) {
// Another stream with that name is already published.
Status badName = new Status(StatusCodes.NS_PUBLISH_BADNAME);
badName.setClientid(streamId);
badName.setDetails(name);
badName.setLevel("error");
// FIXME: there should be a direct way to send the status
Channel channel = ((RTMPConnection) streamConn).getChannel((byte) (4 + ((streamId-1) * 5)));
channel.sendStatus(badName);
return;
}
IClientStream stream = streamConn.getStreamById(streamId);
if (stream != null && !(stream instanceof IClientBroadcastStream)) {
return;
}
boolean created = false;
if (stream == null) {
stream = streamConn.newBroadcastStream(streamId);
created = true;
}
IClientBroadcastStream bs = (IClientBroadcastStream) stream;
try {
bs.setPublishedName(name);
IContext context = conn.getScope().getContext();
IProviderService providerService = (IProviderService) context
.getBean(IProviderService.BEAN_NAME);
// TODO handle registration failure
if (providerService.registerBroadcastStream(conn.getScope(),
name, bs)) {
bsScope = getBroadcastScope(conn.getScope(), name);
bsScope.setAttribute(IBroadcastScope.STREAM_ATTRIBUTE, bs);
if (conn instanceof BaseConnection) {
((BaseConnection) conn).registerBasicScope(bsScope);
}
}
if (IClientStream.MODE_RECORD.equals(mode)) {
bs.start();
bs.saveAs(name, false);
} else if (IClientStream.MODE_APPEND.equals(mode)) {
bs.start();
bs.saveAs(name, true);
} else if (IClientStream.MODE_LIVE.equals(mode)) {
bs.start();
}
bs.startPublishing();
} catch (IOException e) {
Status accessDenied = new Status(StatusCodes.NS_RECORD_NOACCESS);
accessDenied.setClientid(streamId);
accessDenied.setDesciption("The file could not be created/written to.");
accessDenied.setDetails(name);
accessDenied.setLevel("error");
// FIXME: there should be a direct way to send the status
Channel channel = ((RTMPConnection) streamConn).getChannel((byte) (4 + ((streamId-1) * 5)));
channel.sendStatus(accessDenied);
bs.close();
if (created)
streamConn.deleteStreamById(streamId);
return;
} catch (Exception e) {
logger.warn("publish caught Exception");
}
}