Friday, June 10, 2011

Conflict settings of flash player

This is just a note. If anyone know a setting which satisfy both, let me know.

1. Jquery + Flash
I'm using jquery's sliding menu and flash object in the same page. The problem is the same as this. As suggested in the page, I use wmode=transparent.

2. Linux + Firefox + Flash
When I tried this configuration, "Settings..." menu is disabled. Adobe says it is a specification (see this), since it works on Windows.

How can I solve two issues with one configuration?

Compile Red5 on Eclipse

When I tried to compile red5 at Eclipse from the source checked out from the svn, I got the compile error.

BUILD FAILED
C:\opt\workspace\red5_server\build.xml:225: The following error occurred while executing this line:
C:\opt\workspace\red5_server\build.xml:246: Error running javac.exe compiler

To fix this issue, I changed following two. First, change the JRE System Library to jdk. And Second change the ant's JRE to jdk.

To do first, right click the "JRE System Library", and select "Properties". Then you can see the image shown below. Select "Alternate JRE" and select the jdk.


Next, select build.xml, right click it, select "Run As" -> "Ant Build...". Then you can see the following image shown below. Select "JRE" tab, and select "Separate JRE" and chose jdk.

Wednesday, June 1, 2011

RTMP sampler for JMeter to test flash with http

I want to have an integrated performance test environment for both HTTP and RTMP. For HTTP, JMeter is a well known tool, and has a lot of good features. But the problem is that it does not have RTMP sampler.

So I create the RTMP sampler for JMeter. I create the proxy methods using Java Sampler, and from those methods RTMPclient methods are invoked.

I use Red5 to create RTMPclient. There is a good tutorial for customizing the RTMPclient.

public class RTMPJavaSampler extends AbstractJavaSamplerClient {
 
    private static HashMap<String, MyRTMPClient> clientMap = new HashMap<String, MyRTMPClient>();

    public SampleResult runTest(JavaSamplerContext ctx) {
        JMeterVariables vars = JMeterContextService.getContext().getVariables();
        SampleResult sampleResult = new SampleResult();
        boolean ret = false;
        if (ctx.getParameter("MethodName").equals("connect")){
            ret = connect(ctx.getParameter("SessionId"), ctx.getParameter("HostIp"), ctx.getParameter("AppName"), ctx.getParameter("Arg1"), ctx.getParameter("Arg2"));
        } else if (ctx.getParameter("MethodName").equals("disconnect")){
            ret = disconnect(ctx.getParameter("SessionId"));
        }
        if (ret) {
            getLogger().info("Invoke " + ctx.getParameter("MethodName") + " done." );
            sampleResult.setResponseData("test success".getBytes());
            sampleResult.setDataType(SampleResult.TEXT);
            sampleResult.setSuccessful(true);
        } else {
            getLogger().error("Failed to invoke " + ctx.getParameter("MethodName") + ".");
            sampleResult.setResponseData("test failed".getBytes());
            sampleResult.setDataType(SampleResult.TEXT);
            sampleResult.setSuccessful(false);
        }

        sampleResult.setResponseCodeOK();
        sampleResult.setResponseMessageOK();
        return sampleResult;
    }

    @Override
    public Arguments getDefaultParameters() {
        Arguments params = new Arguments();
        params.addArgument("MethodName", "");
        params.addArgument("SessionId", "");
        params.addArgument("HostIp", "");
        params.addArgument("AppName", "");
        params.addArgument("Arg1","");
        params.addArgument("Arg2","");
        return params;
    }

    public boolean connect(String sessionId, String hostIp, String appName, String arg1, String arg2){
        MyRTMPClient client = new MyRTMPClient();  
        client.connect(hostIp, appName, arg1, arg2);
        clientMap.put(sessionId, client);

        while(client.getConnected()==null);
  
        return (client.getConnected());
    }
 
    public boolean disconnect(String sessionId){
        MyRTMPClient client = clientMap.remove(sessionId);
        client.disconnect();
        return true;
    }
}

public class MyRTMPClient extends RTMPClient implements IPendingServiceCallback, INetStreamEventHandler, IEventDispatcher, ClientExceptionHandler {
    private static final Logger logger = LoggingManager.getLoggerForClass();
    private Boolean connected;
    
    public MyRTMPClient(){
        setServiceProvider(this);
        setExceptionHandler(this);
        setStreamEventDispatcher(this);
    }
    
    public void resultReceived(IPendingServiceCall call) {
        Object result = call.getResult();
        if ("connect".equals(call.getServiceMethodName())) {
            if (result instanceof ObjectMap){
                @SuppressWarnings("unchecked")
                String code = ((ObjectMap<String, String>) result).get("code");
                if (StatusCodes.NC_CONNECT_SUCCESS.equals(code)){
                    logger.debug("Connection Success.");
                    connected=true;
                } else {
                    logger.error("resultsReceived: " + code);
                    connected=false;
                }
            }
        } else if ("createStream".equals(call.getServiceMethodName())){
            if (result instanceof Integer) {
                Integer streamIdInt = (Integer) result;
                // onStreamCreated(streamIdInt);
            } else {
                logger.error("Unexpected response for createStream " + result.toString());
            }
        } else {
            logger.info(call.getServiceMethodName());
        }
    }
 
    public void connect(String host, String app, String arg1, String arg2){
        Map<String, Object> defParams = makeDefaultConnectionParams(host, 1935, app);
        HashMap<String, Object>authParams = new HashMap<String, Object>();
        authParams.put("arg1", arg1);
        authParams.put("arg2", arg2);
        Object[] params = new Object[] {authParams};
        connect(host, 1935, defParams, this, params);
        logger.info("Connect done: " + app);
    }
 
    public void onStatus(Object obj){
        @SuppressWarnings("unchecked")
        ObjectMap<String, String> map = (ObjectMap<String, String>) obj;
        if ("status".equals(map.get("level"))){
            logger.debug("onStatus: " + obj.toString());
        } else {
            logger.info("onStatus: " + obj.toString());
        }
    }

    public void onMetaData(Object obj){
        logger.info("onMetaData: " + obj.toString());
    }
 
    public void onStreamEvent(Notify notify) {
        logger.info("onStreamEvent");
    }

    public void dispatchEvent(IEvent event) {
        if (!(event instanceof IRTMPEvent)) {  
            logger.debug("skipping non rtmp event: " + event);  
            return;  
        }  
        IRTMPEvent rtmpEvent = (IRTMPEvent) event;  

        if (rtmpEvent instanceof VideoData) {  
        } else if (rtmpEvent instanceof AudioData) {  
        } else if (rtmpEvent instanceof Notify){
        }        
    }

    public Boolean getConnected() {
        return connected;
    }
}