[Free] RTMP / AMF Packet breakdown

Luke Hubbard (luke at codegent.com) king.selassie at gmail.com
Sun Sep 18 00:06:42 PDT 2005


Skipped content of type multipart/alternative-------------- next part --------------
package org.red5.server;

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.SessionConfig;
import org.apache.mina.common.TransportType;
import org.apache.mina.io.IoHandlerAdapter;
import org.apache.mina.io.IoSession;
import org.apache.mina.io.socket.SocketSessionConfig;
import org.apache.mina.registry.Service;
import org.apache.mina.registry.ServiceRegistry;
import org.apache.mina.registry.SimpleServiceRegistry;

public class SimpleRTMPProtocolHandler extends IoHandlerAdapter
{
	
	private static final int PORT = 1935;

    public static void main( String[] args ) throws Exception
    {
        ServiceRegistry registry = new SimpleServiceRegistry();
        
        // Bind
        Service service = new Service( "rtmp", TransportType.SOCKET, PORT );
        registry.bind( service, new SimpleRTMPProtocolHandler() );

        System.out.println( "RED5 Listening on port " + PORT );
    }
	
    public void sessionCreated( IoSession session )
    {
        SessionConfig cfg = session.getConfig();
        if( cfg instanceof SocketSessionConfig )
        {
            ( ( SocketSessionConfig ) cfg ).setSessionReceiveBufferSize( 2048 );
        }
    }

    public void exceptionCaught( IoSession session, Throwable cause )
    {
        session.close();
    }
    
    public void dataRead( IoSession session, ByteBuffer in )
    {
    	
    	    final byte STATE_HANDSHAKE = 1;
        final byte STATE_FIRST_PACKET = 2;
        final byte STATE_CONNECTED = 3;
    		
    		Object attachment = session.getAttachment();
    		byte state = STATE_HANDSHAKE; 
    		if(attachment != null) state = ( (Byte) attachment ).byteValue();
    		
    		ByteBuffer out;
    		
    		switch(state){
    		
	    		case STATE_HANDSHAKE:
	    			System.out.println("STATE: Handshake");
	    			logBuffer(">> Client handshake", in);
	    			
	    			// read the header byte
	    			byte header = in.get();
	    			
	    			if(header != 0x03) {
	    				System.err.println("Something fishy going on");
	    			}
	    			
	    			// create an out buffer the right size
	    			out = ByteBuffer.allocate( (1536 * 2) + 1 );
	    			// write the server response
	    			
	    			// header byte
	    			out.put( (byte) 0x03 );
	    			
	    			// initially I used the actual bytes from micks dump
	    			// but I soon discovered it doesnt matter what these bytes are
	    			// so lets create the response filling it with 0x00
	    			byte[] serverHandshake = new byte[1536];
	    			for(int i=0; i<serverHandshake.length; i++) 
	    				serverHandshake[i] = 0x00;
	  
	    			// write server handshake to the buffer
	    			out.put( serverHandshake );
	    			
	    			// write the client handshake back
	    			out.put( in );
	    			
	    			// flip the buffer, log it, and send to client
	    			out.flip();
	    			logBuffer("<< Server handshake", out);
	    	         session.write( out, null );
	    	        
	    	         // switch state
	    			state = STATE_FIRST_PACKET;
	    			break;
	    			
	    		case STATE_FIRST_PACKET:
	    			System.out.println("STATE: First Packet"); 
	    			
	    			logBuffer(">> Client first packet", in);
	    			
	    			// skip the first 1536 as these are the as server handshake 
	    			in.skip(1536);
	    			
	    			// create an out buffer to hold the rest
	    			ByteBuffer amf = ByteBuffer.allocate(in.remaining());
	    			
	    			// copy the bytes to out
	    			amf.put(in);
	    			
	    			// flip and print out
	    			amf.flip();
	    			
	    			logBuffer("First AMF", amf);
	    			
	    			// decode amf object next
	    			// handleAMF(amf);

	    			state = STATE_CONNECTED;
	    			break;
	    			
	    		case STATE_CONNECTED:
	    			System.out.println("STATE: Connected"); 
	    			break;
	    			
    		}
    		
      	session.setAttachment(new Byte(state));

    }
    
    public void logBuffer(String msg, ByteBuffer buff){
    		System.out.println(msg);	
    		System.out.println("Size: "+buff.remaining());
		System.out.println(formatHexDump(buff.getHexDump()));
    }
    
    public static String formatHexDump(String in){
 	   int chunk = 60;
 	   StringBuffer out = new StringBuffer();
 	   int from = 0;
 	   int to = 0;
 	   int size = in.length();
 	   while(from < size){
 		   if(size < from + chunk)
 			   to = size;
 		   else to = from + chunk;
 		   out.append(in.substring(from,to));
 		   out.append("\n");
 		   from = to;
 	   }
 	   return out.toString();
    }
    
    
}


More information about the Free mailing list