[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