I have 1 server running Red5 and about 5-6 other server running icecast2 as channel
Now i want to using Red5 to re-streaming from icecast2
When user request a content, Red5 will know that content belong to which icecast2 server, and it will connect to corrected server to get media and re-stream to user
My question is, normally, Red5 streaming a static content, but in my situation, i must re-streaming a dynamic content from icecast2 with specify speed and bandwidth? Is that possible?
Is there any example i could look at to get the idea?
For restreaming one server to another server use StreamingProxy
import java.util.HashMap;
import java.util.Map;
import org.red5.server.adapter.MultiThreadedApplicationAdapter;
import org.red5.server.api.IBasicScope;
import org.red5.server.api.IConnection;
import org.red5.server.api.IScope;
import org.red5.server.api.stream.IBroadcastStream;
import org.red5.server.stream.IBroadcastScope;
import org.red5.server.stream.StreamingProxy;
public class Application extends MultiThreadedApplicationAdapter implements IStreamListener {
private Map<String, StreamingProxy> streamingProxyMap = new HashMap<String, StreamingProxy>();
public IBroadcastScope getBroadcastScope(IScope scope, String name) {
IBasicScope basicScope = scope.getBasicScope(IBroadcastScope.TYPE,
name);
if (!(basicScope instanceof IBroadcastScope)) {
return null;
} else {
return (IBroadcastScope) basicScope;
}
}
/** {#inheritDoc} */
#Override
public boolean connect(IConnection conn, IScope scope, Object[] params) {
return true;
}
public void streamBroadcastStart(IBroadcastStream stream)
{
IScope scope = stream.getScope();
IBroadcastScope bsScope = getBroadcastScope(scope, stream.getPublishedName());
StreamingProxy proxy = new StreamingProxy();
proxy.setHost("live.justin.tv");
proxy.setApp("app");
proxy.setPort(1935);
proxy.init();
bsScope.subscribe(proxy, null);
proxy.start("MY_STRING", StreamingProxy.LIVE, null);
streamingProxyMap.put(stream.getPublishedName(), proxy);
stream.addStreamListener(this);
}
public void packetReceived(IBroadcastStream stream, IStreamPacket packet)
{
RTMPMessage m = RTMPMessage.build((IRTMPEvent) packet,packet.getTimestamp());
streamer.pushMessage(null, m);
}
synchronized public void streamBroadcastClose(IBroadcastStream stream) {
StreamingProxy proxy =
streamingProxyMap.get(stream.getPublishedName());
if (proxy != null) {
proxy.stop();
IScope scope = stream.getScope();
IBroadcastScope bsScope = getBroadcastScope(scope, stream.getPublishedName());
if (bsScope != null) {
bsScope.unsubscribe(proxy);
}
}
}
/** {#inheritDoc} */
#Override
public void disconnect(IConnection conn, IScope scope) {
super.disconnect(conn, scope);
}
}
Related
Flink can read a socket stream, can it read http requests? how?
// socket example
DataStream<XXX> socketStream = env
.socketTextStream("localhost", 9999)
.map(...);
There's an open JIRA ticket for creating an HTTP sink connector for Flink, but I've seen no discussion about creating a source connector.
Moreover, it's not clear this is a good idea. Flink's approach to fault tolerance requires sources that can be rewound and replayed, so it works best with input sources that behave like message queues. I would suggest buffering the incoming http requests in a distributed log.
For an example, look at how DriveTribe uses Flink to power their website on the data Artisans blog and on YouTube.
I write one custom http source. please ref OneHourHttpTextStreamFunction. you need create a fat jar to include apache httpserver classes if you want run my code.
package org.apache.flink.streaming.examples.http;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.java.utils.ParameterTool;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.examples.socket.SocketWindowWordCount.WordWithCount;
import org.apache.flink.util.Collector;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.bootstrap.HttpServer;
import org.apache.http.impl.bootstrap.ServerBootstrap;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import static org.apache.flink.util.Preconditions.checkArgument;
import static org.apache.flink.util.Preconditions.checkNotNull;
public class HttpRequestCount {
public static void main(String[] args) throws Exception {
// the host and the port to connect to
final String path;
final int port;
try {
final ParameterTool params = ParameterTool.fromArgs(args);
path = params.has("path") ? params.get("path") : "*";
port = params.getInt("port");
} catch (Exception e) {
System.err.println("No port specified. Please run 'SocketWindowWordCount "
+ "--path <hostname> --port <port>', where path (* by default) "
+ "and port is the address of the text server");
System.err.println("To start a simple text server, run 'netcat -l <port>' and "
+ "type the input text into the command line");
return;
}
// get the execution environment
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// get input data by connecting to the socket
DataStream<String> text = env.addSource(new OneHourHttpTextStreamFunction(path, port));
// parse the data, group it, window it, and aggregate the counts
DataStream<WordWithCount> windowCounts = text
.flatMap(new FlatMapFunction<String, WordWithCount>() {
#Override
public void flatMap(String value, Collector<WordWithCount> out) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (String word : value.split("\\s")) {
out.collect(new WordWithCount(word, 1L));
}
}
})
.keyBy("word").timeWindow(Time.seconds(5))
.reduce(new ReduceFunction<WordWithCount>() {
#Override
public WordWithCount reduce(WordWithCount a, WordWithCount b) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new WordWithCount(a.word, a.count + b.count);
}
});
// print the results with a single thread, rather than in parallel
windowCounts.print().setParallelism(1);
env.execute("Http Request Count");
}
}
class OneHourHttpTextStreamFunction implements SourceFunction<String> {
private static final long serialVersionUID = 1L;
private final String path;
private final int port;
private transient HttpServer server;
public OneHourHttpTextStreamFunction(String path, int port) {
checkArgument(port > 0 && port < 65536, "port is out of range");
this.path = checkNotNull(path, "path must not be null");
this.port = port;
}
#Override
public void run(SourceContext<String> ctx) throws Exception {
server = ServerBootstrap.bootstrap().setListenerPort(port).registerHandler(path, new HttpRequestHandler(){
#Override
public void handle(HttpRequest req, HttpResponse rep, HttpContext context) throws HttpException, IOException {
ctx.collect(req.getRequestLine().getUri());
rep.setStatusCode(200);
rep.setEntity(new StringEntity("OK"));
}
}).create();
server.start();
server.awaitTermination(1, TimeUnit.HOURS);
}
#Override
public void cancel() {
server.stop();
}
}
Leave you comment, if you want the demo jar.
I've just started looking at netty for some projects and have been able to get some simple client and server examples running that use INET and unix domain sockets to send messages back and forth. I've also been able to send datagram packets over INET sockets. But I have a need to send datagram packets over UNIX domain sockets. Is this supported in netty? If so, could someone point me at documentation or an example? I suspect this is not supported given that the DatagramPacket explicitly takes InetSocketAddress. If not supported, would it be feasible to add this to netty?
Is this supported in netty?
Yes. Below is a simple example I wrote.
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollDomainSocketChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerDomainSocketChannel;
import io.netty.channel.unix.DomainSocketAddress;
/**
* #author louyl
*/
public class App {
public static void main(String[] args) throws Exception {
String sockPath = "/tmp/echo.sock";
final ServerBootstrap bootstrap = new ServerBootstrap();
EventLoopGroup serverBossEventLoopGroup = new EpollEventLoopGroup();
EventLoopGroup serverWorkerEventLoopGroup = new EpollEventLoopGroup();
bootstrap.group(serverBossEventLoopGroup, serverWorkerEventLoopGroup)
.localAddress(new DomainSocketAddress(sockPath))
.channel(EpollServerDomainSocketChannel.class)
.childHandler(
new ChannelInitializer<Channel>() {
#Override
protected void initChannel(final Channel channel) throws Exception {
channel.pipeline().addLast(
new ChannelInboundHandlerAdapter() {
#Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
final ByteBuf buff = ctx.alloc().buffer();
buff.writeBytes("This is a test".getBytes());
ctx.writeAndFlush(buff).addListeners(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture future) {
future.channel().close();
future.channel().parent().close();
}
});
}
}
);
}
}
);
final ChannelFuture serverFuture = bootstrap.bind().sync();
final Bootstrap bootstrapClient = new Bootstrap();
EventLoopGroup clientEventLoop = new EpollEventLoopGroup();
bootstrapClient.group(clientEventLoop)
.channel(EpollDomainSocketChannel.class)
.handler(new ChannelInitializer<Channel>() {
#Override
protected void initChannel(final Channel channel) throws Exception {
channel.pipeline().addLast(
new ChannelInboundHandlerAdapter() {
#Override
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
final ByteBuf buff = (ByteBuf) msg;
try {
byte[] bytes = new byte[buff.readableBytes()];
buff.getBytes(0, bytes);
System.out.println(new String(bytes));
} finally {
buff.release();
}
ctx.close();
}
#Override
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
System.out.println("Error occur when reading from Unix domain socket: " + cause.getMessage());
ctx.close();
}
}
);
}
}
);
final ChannelFuture clientFuture = bootstrapClient.connect(new DomainSocketAddress(sockPath)).sync();
clientFuture.channel().closeFuture().sync();
serverFuture.channel().closeFuture().sync();
serverBossEventLoopGroup.shutdownGracefully();
serverWorkerEventLoopGroup.shutdownGracefully();
clientEventLoop.shutdownGracefully();
}
}
I am trying to autowire an object of a service class in mule flow. The code is:
public class SignatureValidator implements Callable
{
#Autowired
private TriggerHostServiceImpl triggerHostServiceImpl;
#Override
public Object onCall(MuleEventContext eventContext) throws Exception
{
MuleMessage message = eventContext.getMessage();
message = fetchPropertiesAndValidateMessageSignature(message);
return message.getPayload();
}
private MuleMessage fetchPropertiesAndValidateMessageSignature(MuleMessage message) throws GeneralSecurityException, IOException
{
String muleWSTriggerLabel = message.getInboundProperty("triggerLabel");
String muleWSSignature = message.getInboundProperty("signature");
String muleWSExpiresOn = message.getInboundProperty("expiresOn");
String xmlData = message.getInboundProperty("xmlData");
String appHostName = InitConfigurationLoader.getConfigSetting("applicationHostingName");
Trigger triggerJaxbObject = (Trigger) message.getPayload();
String applicationIdentifier = triggerJaxbObject.getApplicationIdentifier();
TriggerMapper triggerMapper = FetchConfigurationEntities.getTriggerMapper(applicationIdentifier, muleWSTriggerLabel);
String reportEmail = FetchConfigurationEntities.getReportEmail(triggerMapper);
ImportDetails importInstance = FetchConfigurationEntities.getImport(triggerMapper);
String importInstanceURL = importInstance.getWebserviceURL();
message.setInvocationProperty("triggerJaxbObject", triggerJaxbObject);
message.setInvocationProperty("importInstance", importInstance);
message.setInvocationProperty("reportEmail", reportEmail);
message.setInvocationProperty("appIdentifier", applicationIdentifier);
message.setInvocationProperty("importHost", importInstanceURL.substring(importInstanceURL.lastIndexOf('/')+1, importInstanceURL.length()));
setPayloadAfterValidation(message, muleWSTriggerLabel, xmlData, muleWSSignature, appHostName, muleWSExpiresOn);
return message;
}
My service class is:
package com.catalystone.csi.service;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.catalystone.csi.core.cache.UpdateCacheable;
import com.catalystone.csi.dao.TriggerHostDao;
import com.catalystone.csi.model.TriggerHost;
#Service
public class TriggerHostServiceImpl implements TriggerHostService
{
#Autowired
private TriggerHostDao triggerHostDao;
#Autowired
private UpdateCacheable updateCacheable;
/**
* Method to save mule configurations i.e. TriggerHosts
*/
#Override
#Transactional
public boolean saveTriggerHost(TriggerHost triggerHost)
{
if(triggerHostDao.saveTriggerHost(triggerHost))
{
Map<String, TriggerHost> allTriggerHosts = getAllTriggerHosts();
allTriggerHosts.put(triggerHost.getTriggerIdentifier(), triggerHost);
updateCacheable.updateAllTriggerHostCache(allTriggerHosts);
return true;
}
else
return false;
}
/**
* Method to fetch all the configurations
*/
#Override
#Transactional//this annotation is used to maintain transaction
public Map<String, TriggerHost> getAllTriggerHosts()
{
return triggerHostDao.getAllTriggerHosts();
}
/**
* Method to delete mule configuration for triggerHost
* #return - true if delete configuration is successfully done
*/
#Override
#Transactional//this annotation is used to maintain transaction
public Boolean deleteConfiguration(TriggerHost triggerHost, boolean isMultipleImportOccurrence)
{
Boolean isDeleteSuccessful = triggerHostDao.deleteConfiguration(triggerHost, isMultipleImportOccurrence);
//Getting all the configurations from cache
Map<String, TriggerHost> allTriggerHosts = getAllTriggerHosts();
//check if delete configuration successful then remove that configuration from cache
if(isDeleteSuccessful)
{
for(Entry<String, TriggerHost> triggerHostEntry : allTriggerHosts.entrySet())
{
if(triggerHostEntry.getValue().getTriggerIdentifier().equals(triggerHost.getTriggerIdentifier()))
{
allTriggerHosts.remove(triggerHostEntry.getKey());
break;
}
}
//update cache
updateCacheable.updateAllTriggerHostCache(allTriggerHosts);
return true;
}
return false;
}
#Override
#Transactional
public Boolean updateConfiguration(TriggerHost triggerHost)
{
if(triggerHostDao.updateConfiguration(triggerHost))
{
Map<String, TriggerHost> allTriggerHosts = getAllTriggerHosts();
allTriggerHosts.put(triggerHost.getTriggerIdentifier(), triggerHost);
updateCacheable.updateAllTriggerHostCache(allTriggerHosts);
return true;
}
return false;
}
#Override
#Transactional
public Boolean deleteConfiguration(String existingImportIdentifier)
{
return triggerHostDao.deleteConfiguration(existingImportIdentifier);
}
}
when I run this code then value of triggerHostServiceImpl is always null. How to autowire? I have also tried a link Dependency Injection is working at Mule application startup. Objects are getting null, when a request received and Failing by throwing NullEx
and
Spring3 Dependency Injection not working with mule
but then it is giving me so many exception that I couldn't get.
you have to Autowire the Interface not the Implementation
#Autowired
private TriggerHostService triggerHostService;
and add the setter and getter of triggerHostService
I'm new to socket programming and Netty framework. I was trying to modify the Echo Server example so that the message is not sent from client as soon as a message is received, but a call from another thread would trigger the client send a message to the server.
The problem is, the server does not get the message unless the client sends it from readChannel or MessageReceived or channelActive which are where the server is specified with a parameter (ChannelHandlerContext). I couldn't manage to find a way to save the server channel and send a message later and repeatedly.
Here's my Client Handler code;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
public class EchoClientHandler extends ChannelHandlerAdapter {
ChannelHandlerContext server;
#Override
public void channelActive(ChannelHandlerContext ctx) {
this.server = ctx;
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// ctx.write(msg); //not
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//ctx.flush();
}
public void externalcall(String msg) throws Exception {
if(server!=null){
server.writeAndFlush("[" + "] " + msg + '\n');
}
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
ctx.close();
}
}
When Client creates the handler, it also creates a thread with a "SourceGenerator" object which gets the handler as parameter so as to call the externalcall() method.
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
* Sends one message when a connection is open and echoes back any received
* data to the server. Simply put, the echo client initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server.
*/
public class EchoClient {
private final String host;
private final int port;
public EchoClient(String host, int port, int firstMessageSize) {
this.host = host;
this.port = port;
}
public void run() throws Exception {
// Configure the client.
EventLoopGroup group = new NioEventLoopGroup();
final EchoClientHandler x = new EchoClientHandler();
SourceGenerator sg = new SourceGenerator(x);
new Thread(sg).start();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(x);
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync();
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down the event loop to terminate all threads.
group.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length < 2 || args.length > 3) {
System.err.println(
"Usage: " + EchoClient.class.getSimpleName() +
" <host> <port> [<first message size>]");
return;
}
// Parse options.
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int firstMessageSize;
if (args.length == 3) {
firstMessageSize = Integer.parseInt(args[2]);
} else {
firstMessageSize = 256;
}
new EchoClient(host, port, firstMessageSize).run();
}
}
and the SourceGenerator class;
public class SourceGenerator implements Runnable {
public String dat;
public EchoClientHandler asd;
public SourceGenerator(EchoClientHandler x) {
asd = x;
System.out.println("initialized source generator");
dat = "";
}
#Override
public void run() {
try{
while(true){
Thread.sleep(2000);
dat += "a";
asd.externalcall(dat);
System.out.print("ha!");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
Thanks in advance!
If you want to write a String you need to have the StringEncoder in the ChannelPipeline.
Otherwise you can only send ByteBuf instances.
I'm having a web-application that is secured with HTTP-Basic auth.
I also implemented a filter using the ServletRequestListener interface. Now when the filter calls the requestInitialized method, the getUserPrincipal-Method of the request returns null. But when I check the request headers, the authorization-header is set with the encrypted value. Here's the code:
#Override
public void requestInitialized(ServletRequestEvent e) {
HttpServletRequest request = (HttpServletRequest) e.getServletRequest();
//p is null
Principal p = request.getUserPrincipal();
Enumeration<String> enH = request.getHeaders("Authorization");
while (enH.hasMoreElements()) {
String s = enH.nextElement();
System.out.println(s);
//prints.
//Basic c3RhY2tvdmVyZmxvdzpteXBhc3N3b3Jk
}
}
Why is the userprincipal not initialized?
You are likely not setting up the needed security layers for embedded-jetty.
Here's an example found in the Jetty embedded examples source tree.
package org.eclipse.jetty.embedded;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.security.Constraint;
public class SecuredHelloHandler
{
public static void main(String[] args) throws Exception
{
Server server = new Server(8080);
LoginService loginService = new HashLoginService("MyRealm","src/test/resources/realm.properties");
server.addBean(loginService);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
server.setHandler(security);
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate( true );
constraint.setRoles(new String[]{"user", "admin"});
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec( "/*" );
mapping.setConstraint( constraint );
Set<String> knownRoles = new HashSet<String>();
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);
// Your Handler (or Servlet) that should be secured
HelloHandler hh = new HelloHandler();
security.setHandler(hh);
server.start();
server.join();
}
}
I solved it by using a Filter instead of a Listener..
#WebFilter(urlPatterns = { "/*" })
public class RequestFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain fChain) throws IOException, ServletException {
HttpServletRequest hReq = (HttpServletRequest) req;
//p is not null anymore
Principal p = hReq.getUserPrincipal();
fChain.doFilter(hReq, res);
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig config) throws ServletException {
}
}