[Red5commits] [1596] added experimental AMF3 support

jbauch luke at codegent.com
Wed Jan 24 11:02:25 EST 2007


added experimental AMF3 support


Timestamp: 12/20/06 20:35:22 EST (1 month ago) 
Change: 1596 
Author: jbauch

Files (see diff or trac for details): 
java/server/trunk/src/org/red5/io/amf/AMF.java
java/server/trunk/src/org/red5/io/amf/Input.java
java/server/trunk/src/org/red5/io/amf/Output.java
java/server/trunk/src/org/red5/io/amf3/Input.java
java/server/trunk/src/org/red5/io/amf3/Output.java
java/server/trunk/src/org/red5/io/mock/Input.java
java/server/trunk/src/org/red5/io/mock/Output.java
java/server/trunk/src/org/red5/io/object/BaseInput.java
java/server/trunk/src/org/red5/io/object/Input.java
java/server/trunk/src/org/red5/io/object/Output.java
java/server/trunk/src/org/red5/io/object/Serializer.java
java/server/trunk/src/org/red5/server/BaseConnection.java
java/server/trunk/src/org/red5/server/api/IConnection.java
java/server/trunk/src/org/red5/server/net/rtmp/BaseRTMPHandler.java
java/server/trunk/src/org/red5/server/net/rtmp/Channel.java
java/server/trunk/src/org/red5/server/net/rtmp/RTMPConnection.java
java/server/trunk/src/org/red5/server/net/rtmp/RTMPHandler.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventDecoder.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPMinaProtocolDecoder.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolEncoder.java
java/server/trunk/src/org/red5/server/net/rtmp/event/FlexMessage.java
java/server/trunk/src/org/red5/server/net/rtmp/message/Constants.java
java/server/trunk/src/org/red5/server/net/servlet/ServletConnection.java
java/server/trunk/test/org/red5/server/api/test/TestConnection.java


Trac: http://mirror1.cvsdude.com/trac/osflash/red5/changeset/1596

Index: /java/server/trunk/test/org/red5/server/api/test/TestConnection.java
===================================================================
--- /java/server/trunk/test/org/red5/server/api/test/TestConnection.java (revision 1406)
+++ /java/server/trunk/test/org/red5/server/api/test/TestConnection.java (revision 1596)
@@ -9,4 +9,8 @@
 	}
 
+	public Encoding getEncoding() {
+		return Encoding.AMF0;
+	}
+	
 	@Override
 	public long getReadBytes() {
Index: /java/server/trunk/src/org/red5/server/net/rtmp/RTMPHandler.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/RTMPHandler.java (revision 1582)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/RTMPHandler.java (revision 1596)
@@ -221,6 +221,15 @@
 										call.setStatus(Call.STATUS_SUCCESS_RESULT);
 										if (call instanceof IPendingServiceCall) {
-											((IPendingServiceCall) call)
-													.setResult(getStatus(NC_CONNECT_SUCCESS));
+											IPendingServiceCall pc = (IPendingServiceCall) call;
+											Map<String, Object> result = new HashMap<String, Object>();
+											StatusObject status = getStatus(NC_CONNECT_SUCCESS);
+											result.put("code", status.getCode());
+											result.put("description", status.getDescription());
+											result.put("application", status.getApplication());
+											result.put("level", status.getLevel());
+											if (params.get("objectEncoding") == Integer.valueOf(3))
+												// Client wants to use AMF3 encoding
+												result.put("objectEncoding", 3);
+											pc.setResult(result);
 										}
 										// Measure initial roundtrip time after connecting
@@ -325,5 +334,5 @@
 	}
 
-	public Object getStatus(String code) {
+	public StatusObject getStatus(String code) {
 		return statusObjectService.getStatusObject(code);
 	}
Index: /java/server/trunk/src/org/red5/server/net/rtmp/event/FlexMessage.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/event/FlexMessage.java (revision 1596)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/event/FlexMessage.java (revision 1596)
@@ -0,0 +1,15 @@
+package org.red5.server.net.rtmp.event;
+
+public class FlexMessage extends Invoke {
+
+	public FlexMessage() {
+		super();
+	}
+	
+	@Override
+	public byte getDataType() {
+		// TODO Auto-generated method stub
+		return TYPE_FLEX_MESSAGE;
+	}
+
+}
Index: /java/server/trunk/src/org/red5/server/net/rtmp/RTMPConnection.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/RTMPConnection.java (revision 1582)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/RTMPConnection.java (revision 1596)
@@ -101,4 +101,5 @@
 
 	private int usedStreams;
+	protected Encoding encoding = Encoding.AMF0;
 
 	public RTMPConnection(String type) {
@@ -110,11 +111,17 @@
 
 	public void setup(String host, String path, String sessionId,
-			Map<String, String> params) {
+			Map<String, Object> params) {
 		this.host = host;
 		this.path = path;
 		this.sessionId = sessionId;
 		this.params = params;
-	}
-
+		if (params.get("objectEncoding") == Integer.valueOf(3))
+			encoding = Encoding.AMF3;
+	}
+
+	public Encoding getEncoding() {
+		return encoding;
+	}
+	
 	public int getNextAvailableChannelId() {
 		int result = -1;
Index: /java/server/trunk/src/org/red5/server/net/rtmp/message/Constants.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/message/Constants.java (revision 1406)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/message/Constants.java (revision 1596)
@@ -40,5 +40,7 @@
 	public static final byte TYPE_VIDEO_DATA = 0x09;
 
-	// Unknown: 0x0A ...  0x11
+	// Unknown: 0x0A ...  0x10
+	public static final byte TYPE_FLEX_MESSAGE = 0x11;
+
 	public static final byte TYPE_NOTIFY = 0x12;
 
Index: /java/server/trunk/src/org/red5/server/net/rtmp/Channel.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/Channel.java (revision 1572)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/Channel.java (revision 1596)
@@ -22,5 +22,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.red5.server.api.IConnection.Encoding;
 import org.red5.server.api.stream.IClientStream;
+import org.red5.server.net.rtmp.event.FlexMessage;
 import org.red5.server.net.rtmp.event.IRTMPEvent;
 import org.red5.server.net.rtmp.event.Invoke;
@@ -97,5 +99,8 @@
 			final PendingCall call = new PendingCall(null, "onStatus",
 					new Object[] { status });
-			invoke = new Invoke();
+			if (connection.getEncoding() == Encoding.AMF3)
+				invoke = new FlexMessage();
+			else
+				invoke = new Invoke();
 			invoke.setInvokeId(1);
 			invoke.setCall(call);
Index: /java/server/trunk/src/org/red5/server/net/rtmp/BaseRTMPHandler.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/BaseRTMPHandler.java (revision 1574)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/BaseRTMPHandler.java (revision 1596)
@@ -112,4 +112,5 @@
 
 				case TYPE_INVOKE:
+				case TYPE_FLEX_MESSAGE:
 					onInvoke(conn, channel, header, (Invoke) message);
 					if(message.getHeader().getStreamId()!=0  
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPMinaProtocolDecoder.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPMinaProtocolDecoder.java (revision 1406)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPMinaProtocolDecoder.java (revision 1596)
@@ -28,4 +28,6 @@
 import org.apache.mina.filter.codec.ProtocolDecoder;
 import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+import org.red5.server.api.IConnection;
+import org.red5.server.api.Red5;
 import org.red5.server.net.protocol.ProtocolState;
 
@@ -38,4 +40,9 @@
 		final ProtocolState state = (ProtocolState) session
 				.getAttribute(ProtocolState.SESSION_KEY);
+
+		IConnection conn = (IConnection) session.getAttachment();
+		
+		// Set thread local here so we have the connection during decoding of packets
+		Red5.setConnectionLocal(conn);
 
 		ByteBuffer buf = (ByteBuffer) session.getAttribute("buffer");
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventDecoder.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventDecoder.java (revision 1400)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/IEventDecoder.java (revision 1596)
@@ -24,4 +24,5 @@
 import org.red5.server.net.rtmp.event.BytesRead;
 import org.red5.server.net.rtmp.event.ChunkSize;
+import org.red5.server.net.rtmp.event.FlexMessage;
 import org.red5.server.net.rtmp.event.Invoke;
 import org.red5.server.net.rtmp.event.Notify;
@@ -51,3 +52,4 @@
 	public abstract VideoData decodeVideoData(ByteBuffer in);
 
+	public abstract FlexMessage decodeFlexMessage(ByteBuffer in);
 }
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolEncoder.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolEncoder.java (revision 1574)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolEncoder.java (revision 1596)
@@ -27,7 +27,10 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.mina.common.ByteBuffer;
-import org.red5.io.amf.Output;
+import org.red5.io.object.Output;
 import org.red5.io.object.Serializer;
 import org.red5.io.utils.BufferUtils;
+import org.red5.server.api.IConnection;
+import org.red5.server.api.Red5;
+import org.red5.server.api.IConnection.Encoding;
 import org.red5.server.api.service.IPendingServiceCall;
 import org.red5.server.api.service.IServiceCall;
@@ -39,4 +42,5 @@
 import org.red5.server.net.rtmp.event.ChunkSize;
 import org.red5.server.net.rtmp.event.ClientBW;
+import org.red5.server.net.rtmp.event.FlexMessage;
 import org.red5.server.net.rtmp.event.IRTMPEvent;
 import org.red5.server.net.rtmp.event.Invoke;
@@ -65,4 +69,13 @@
 
 	private Serializer serializer;
+	
+	private Output getOutput(ByteBuffer buffer) {
+		IConnection conn = Red5.getConnectionLocal();
+		if (conn.getEncoding() == Encoding.AMF3) {
+			return new org.red5.io.amf3.Output(buffer);
+		} else {
+			return new org.red5.io.amf.Output(buffer);
+		}
+	}
 
 	public ByteBuffer encode(ProtocolState state, Object message)
@@ -216,4 +229,6 @@
 			case TYPE_CLIENT_BANDWIDTH:
 				return encodeClientBW((ClientBW) message);
+			case TYPE_FLEX_MESSAGE:
+				return encodeFlexMessage((FlexMessage) message);
 			default:
 				return null;
@@ -244,6 +259,7 @@
 		final ByteBuffer out = ByteBuffer.allocate(128);
 		out.setAutoExpand(true);
-
-		Output.putString(out, so.getName());
+		final Output output = getOutput(out);
+
+		output.putString(so.getName());
 		// SO version
 		out.putInt(so.getVersion());
@@ -275,5 +291,5 @@
 					mark = out.position();
 					out.skip(4); // we will be back
-					Output.putString(out, event.getKey());
+					output.putString(event.getKey());
 					len = out.position() - mark - 4;
 					out.putInt(mark, len);
@@ -294,6 +310,5 @@
 
 							String key = (String) keys.next();
-							Output.putString(out, key);
-							final Output output = new Output(out);
+							output.putString(key);
 							serializer.serialize(output, initialData.get(key));
 
@@ -306,6 +321,5 @@
 						out.skip(4); // we will be back
 
-						Output.putString(out, event.getKey());
-						final Output output = new Output(out);
+						output.putString(event.getKey());
 						serializer.serialize(output, event.getValue());
 
@@ -322,5 +336,4 @@
 					out.skip(4);
 					// Serialize name of the handler to call...
-					final Output output = new Output(out);
 					serializer.serialize(output, event.getKey());
 					// ...and the arguments
@@ -338,6 +351,6 @@
 					mark = out.position();
 					out.skip(4); // we will be back
-					Output.putString(out, event.getKey());
-					Output.putString(out, (String) event.getValue());
+					output.putString(event.getKey());
+					output.putString((String) event.getValue());
 					len = out.position() - mark - 4;
 					out.putInt(mark, len);
@@ -353,7 +366,6 @@
 					//out.putInt(0);
 					out.skip(4); // we will be back
-					Output.putString(out, event.getKey());
-					final Output output2 = new Output(out);
-					serializer.serialize(output2, event.getValue());
+					output.putString(event.getKey());
+					serializer.serialize(output, event.getValue());
 					len = out.position() - mark - 4;
 					out.putInt(mark, len);
@@ -384,11 +396,14 @@
 
 	protected ByteBuffer encodeNotifyOrInvoke(Notify invoke) {
+		ByteBuffer out = ByteBuffer.allocate(1024);
+		out.setAutoExpand(true);
+		encodeNotifyOrInvoke(out, invoke);
+		return out;
+	}
+	
+	protected void encodeNotifyOrInvoke(ByteBuffer out, Notify invoke) {
 		// TODO: tidy up here
 		// log.debug("Encode invoke");
-
-		ByteBuffer out = ByteBuffer.allocate(1024);
-		out.setAutoExpand(true);
-		Output output = new Output(out);
-
+		Output output = new org.red5.io.amf.Output(out);
 		final IServiceCall call = invoke.getCall();
 		final boolean isPending = (call.getStatus() == Call.STATUS_PENDING);
@@ -412,4 +427,12 @@
 			serializer.serialize(output, invoke.getConnectionParams());
 		}
+
+		if (call.getServiceName() == null && "connect".equals(call.getServiceMethodName())) {
+			// Response to initial connect, always use AMF0
+			output = new org.red5.io.amf.Output(out);
+		} else {
+			output = getOutput(out);
+		}
+		
 		if (!isPending && (invoke instanceof Invoke)) {
 			IPendingServiceCall pendingCall = (IPendingServiceCall) call;
@@ -429,5 +452,4 @@
 			}
 		}
-		return out;
 	}
 
@@ -498,3 +520,12 @@
 	}
 
+	public ByteBuffer encodeFlexMessage(FlexMessage msg) {
+		ByteBuffer out = ByteBuffer.allocate(1024);
+		out.setAutoExpand(true);
+		// Unknown byte, always 0?
+		out.put((byte) 0);
+		encodeNotifyOrInvoke(out, msg);
+		return out;
+	}
+	
 }
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java (revision 1574)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java (revision 1596)
@@ -29,7 +29,11 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.mina.common.ByteBuffer;
-import org.red5.io.amf.Input;
+import org.red5.io.amf.AMF;
 import org.red5.io.object.Deserializer;
+import org.red5.io.object.Input;
 import org.red5.io.utils.BufferUtils;
+import org.red5.server.api.IConnection;
+import org.red5.server.api.Red5;
+import org.red5.server.api.IConnection.Encoding;
 import org.red5.server.net.protocol.ProtocolException;
 import org.red5.server.net.protocol.ProtocolState;
@@ -40,4 +44,5 @@
 import org.red5.server.net.rtmp.event.ChunkSize;
 import org.red5.server.net.rtmp.event.ClientBW;
+import org.red5.server.net.rtmp.event.FlexMessage;
 import org.red5.server.net.rtmp.event.IRTMPEvent;
 import org.red5.server.net.rtmp.event.Invoke;
@@ -73,4 +78,13 @@
 	}
 
+	private Input getInput(ByteBuffer buffer) {
+		IConnection conn = Red5.getConnectionLocal();
+		if (conn != null && conn.getEncoding() == Encoding.AMF3) {
+			return new org.red5.io.amf3.Input(buffer);
+		} else {
+			return new org.red5.io.amf.Input(buffer);
+		}
+	}
+
 	public void setDeserializer(Deserializer deserializer) {
 		this.deserializer = deserializer;
@@ -379,4 +393,7 @@
 				message = decodeClientBW(in);
 				break;
+			case TYPE_FLEX_MESSAGE:
+				message = decodeFlexMessage(in);
+				break;
 			default:
 				message = decodeUnknown(header.getDataType(), in);
@@ -421,6 +438,6 @@
 	public ISharedObjectMessage decodeSharedObject(ByteBuffer in) {
 
-		final Input input = new Input(in);
-		String name = Input.getString(in);
+		final Input input = getInput(in);
+		String name = input.getString();
 		// Read version of SO to modify
 		int version = in.getInt();
@@ -448,7 +465,7 @@
 			if (type == ISharedObjectEvent.Type.CLIENT_STATUS) {
 				// Status code
-				key = Input.getString(in);
+				key = input.getString();
 				// Status level
-				value = Input.getString(in);
+				value = input.getString();
 			} else if (type == ISharedObjectEvent.Type.CLIENT_UPDATE_DATA) {
 				key = null;
@@ -457,5 +474,5 @@
 				final int start = in.position();
 				while (in.position() - start < length) {
-					String tmp = Input.getString(in);
+					String tmp = input.getString();
 					map.put(tmp, deserializer.deserialize(input));
 				}
@@ -464,5 +481,5 @@
 					&& type != ISharedObjectEvent.Type.CLIENT_SEND_MESSAGE) {
 				if (length > 0) {
-					key = Input.getString(in);
+					key = input.getString();
 					if (length > key.length() + 2) {
 						value = deserializer.deserialize(input);
@@ -530,5 +547,5 @@
 		// TODO: we should use different code depending on server or client mode
 		int start = in.position();
-		Input input = new Input(in);
+		Input input = getInput(in);
 
 		String action = (String) deserializer.deserialize(input);
@@ -647,3 +664,53 @@
 	}
 
+	public FlexMessage decodeFlexMessage(ByteBuffer in) {
+		// Unknown byte, always 0?
+		in.skip(1);
+		Input input = new org.red5.io.amf.Input(in);
+		String action = (String) deserializer.deserialize(input);
+		int invokeId = ((Number) deserializer.deserialize(input)).intValue();
+		FlexMessage msg = new FlexMessage();
+		msg.setInvokeId(invokeId);
+		Object[] params = new Object[] {};
+
+		if (in.hasRemaining()) {
+			ArrayList paramList = new ArrayList();
+
+			final Object obj = deserializer.deserialize(input);
+			if (obj != null) {
+				paramList.add(obj);
+			}
+			
+			if (in.hasRemaining()) {
+				// Check for AMF3 encoding of parameters
+				byte tmp = in.get();
+				in.position(in.position()-1);
+				if (tmp == AMF.TYPE_AMF3_OBJECT) {
+					// All further parameters are encoded using AMF3
+					input = new org.red5.io.amf3.Input(in);
+				}
+				while (in.hasRemaining()) {
+					paramList.add(deserializer.deserialize(input));
+				}
+			}
+			params = paramList.toArray();
+			if (log.isDebugEnabled()) {
+				log.debug("Num params: " + paramList.size());
+				for (int i = 0; i < params.length; i++) {
+					log.debug(" > " + i + ": " + params[i]);
+				}
+			}
+		}
+
+		final int dotIndex = action.lastIndexOf('.');
+		String serviceName = (dotIndex == -1) ? null : action.substring(0,
+				dotIndex);
+		String serviceMethod = (dotIndex == -1) ? action : action.substring(
+				dotIndex + 1, action.length());
+
+		PendingCall call = new PendingCall(serviceName, serviceMethod, params);
+		msg.setCall(call);
+		return msg;
+	}
+	
 }
Index: /java/server/trunk/src/org/red5/server/net/servlet/ServletConnection.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/servlet/ServletConnection.java (revision 1519)
+++ /java/server/trunk/src/org/red5/server/net/servlet/ServletConnection.java (revision 1596)
@@ -55,4 +55,8 @@
 	}
 
+	public Encoding getEncoding() {
+		return Encoding.AMF0;
+	}
+	
 	public String getType() {
 		return IConnection.TRANSIENT;
@@ -81,6 +85,6 @@
 	}
 
-	public Map<String, String> getConnectParams() {
-		return new HashMap<String, String>();
+	public Map<String, Object> getConnectParams() {
+		return new HashMap<String, Object>();
 	}
 
Index: /java/server/trunk/src/org/red5/server/api/IConnection.java
===================================================================
--- /java/server/trunk/src/org/red5/server/api/IConnection.java (revision 1590)
+++ /java/server/trunk/src/org/red5/server/api/IConnection.java (revision 1596)
@@ -39,4 +39,12 @@
 
 	/**
+	 * Encoding types.
+	 */
+	public static enum Encoding {
+		AMF0,
+		AMF3
+	};
+	
+	/**
 	 * Persistent connection type, eg RTMP.
 	 */
@@ -60,4 +68,11 @@
 	public String getType(); // PERSISTENT | POLLING | TRANSIENT
 
+	/**
+	 * Get the object encoding for this connection.
+	 * 
+	 * @return the used encoding.
+	 */
+	public Encoding getEncoding();
+	
 	/**
 	 * Initialize the connection.
@@ -100,5 +115,5 @@
 	 * @return
 	 */
-	public Map<String, String> getConnectParams();
+	public Map<String, Object> getConnectParams();
 
 	/**
Index: /java/server/trunk/src/org/red5/server/BaseConnection.java
===================================================================
--- /java/server/trunk/src/org/red5/server/BaseConnection.java (revision 1590)
+++ /java/server/trunk/src/org/red5/server/BaseConnection.java (revision 1596)
@@ -87,5 +87,5 @@
      */
 	@SuppressWarnings({"JavadocReference"})
-    protected Map<String, String> params = null;
+    protected Map<String, Object> params = null;
     /**
      *  Client bound to connection
@@ -113,5 +113,5 @@
 	public BaseConnection(String type, String host, String remoteAddress,
 			int remotePort, String path, String sessionId,
-			Map<String, String> params) {
+			Map<String, Object> params) {
 		this.type = type;
 		this.host = host;
@@ -192,5 +192,5 @@
      * @return
      */
-	public Map<String, String> getConnectParams() {
+	public Map<String, Object> getConnectParams() {
 		return Collections.unmodifiableMap(params);
 	}
Index: /java/server/trunk/src/org/red5/io/amf3/Input.java
===================================================================
--- /java/server/trunk/src/org/red5/io/amf3/Input.java (revision 1406)
+++ /java/server/trunk/src/org/red5/io/amf3/Input.java (revision 1596)
@@ -29,4 +29,5 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.mina.common.ByteBuffer;
+import org.red5.io.amf.AMF;
 import org.red5.io.object.BaseInput;
 import org.red5.io.object.DataTypes;
@@ -37,13 +38,10 @@
  * @author The Red5 Project (red5 at osflash.org)
  * @author Luke Hubbard, Codegent Ltd (luke at codegent.com)
+ * @author Joachim Bauch (jojo at struktur.de)
  */
-public class Input extends BaseInput implements org.red5.io.object.Input {
+public class Input extends org.red5.io.amf.Input implements org.red5.io.object.Input {
 
 	protected static Log log = LogFactory.getLog(Input.class.getName());
 
-	protected ByteBuffer buf;
-
-	protected byte currentDataType;
-
 	/**
 	 * Input Constructor
@@ -52,6 +50,5 @@
 	 */
 	public Input(ByteBuffer buf) {
-		super();
-		this.buf = buf;
+		super(buf);
 	}
 
@@ -70,6 +67,12 @@
 		byte coreType;
 
+		if (currentDataType == AMF.TYPE_AMF3_OBJECT) {
+			currentDataType = buf.get();
+		} else {
+			// AMF0 object
+			return readDataType(currentDataType);
+		}
+
 		switch (currentDataType) {
-
 			case AMF3.TYPE_NULL:
 				coreType = DataTypes.CORE_NULL;
@@ -158,7 +161,13 @@
 	 */
 	public String readString() {
-		int len = buf.getInt();
-		// shift by one bit ?
-		// is it a reference ? if not continue
+		int len = readAMF3Integer();
+		if (len == 0)
+			return "";
+		
+		if ((len & 1) == 0) {
+			// Reference
+			return (String) getReference(len >> 1);
+		}
+		len >>= 1;
 		int limit = buf.limit();
 		final java.nio.ByteBuffer strBuf = buf.buf();
@@ -166,5 +175,5 @@
 		final String string = AMF3.CHARSET.decode(strBuf).toString();
 		buf.limit(limit); // Reset the limit
-		// save a reference
+		storeReference(string);
 		return string;
 	}
@@ -203,4 +212,5 @@
 	 */
 	public int readStartArray() {
+		System.err.println("MISSING: readStartArray");
 		return buf.getInt();
 	}
@@ -228,4 +238,5 @@
 	 */
 	public int readStartMap() {
+		System.err.println("MISSING: readStartMap");
 		return buf.getInt();
 	}
@@ -246,5 +257,5 @@
 	 */
 	public String readItemKey() {
-		return "";
+		return readString();
 	}
 
@@ -271,4 +282,5 @@
 	 */
 	public String readStartObject() {
+		System.err.println("MISSING: readStartObject");
 		return null;
 	}
@@ -280,5 +292,7 @@
 	 */
 	public boolean hasMoreProperties() {
-		return false;
+		boolean isEnd = (buf.get() == 0);
+		buf.position(buf.position()-1);
+		return isEnd;
 	}
 
@@ -289,5 +303,5 @@
 	 */
 	public String readPropertyName() {
-		return null;
+		return readString();
 	}
 
@@ -303,8 +317,5 @@
 	 */
 	public void skipEndObject() {
-		// skip two marker bytes
-		// then end of object byte
-		buf.skip(3);
-		// byte nextType = buf.get();
+		buf.skip(1);
 	}
 
@@ -328,13 +339,4 @@
 		// Return null for now
 		return null;
-	}
-
-	/**
-	 * Reads Reference
-	 * 
-	 * @return Object
-	 */
-	public Object readReference() {
-		return getReference(buf.getShort());
 	}
 
Index: /java/server/trunk/src/org/red5/io/amf3/Output.java
===================================================================
--- /java/server/trunk/src/org/red5/io/amf3/Output.java (revision 1400)
+++ /java/server/trunk/src/org/red5/io/amf3/Output.java (revision 1596)
@@ -25,4 +25,6 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.mina.common.ByteBuffer;
+import org.red5.io.amf.AMF;
+import org.red5.io.amf3.AMF3;
 
 /**
@@ -32,10 +34,9 @@
  * @see  org.red5.io.amf3.Input
  * @author The Red5 Project (red5 at osflash.org)
+ * @author Joachim Bauch (jojo at struktur.de)
  */
-public class Output implements org.red5.io.object.Output {
+public class Output extends org.red5.io.amf.Output implements org.red5.io.object.Output {
 
 	protected static Log log = LogFactory.getLog(Output.class.getName());
-
-	protected ByteBuffer buffer;
 
 	/**
@@ -46,102 +47,148 @@
 	 * @see ByteBuffer
 	 */
-	public Output(ByteBuffer buffer) {
-		this.buffer = buffer;
+	public Output(ByteBuffer buf) {
+		super(buf);
 	}
 
 	public boolean supportsDataType(byte type) {
-		return false;
+		return true;
 	}// Basic Data Types
 
-	public void writeNumber(Number num) {
-
+	public void writeBoolean(Boolean bol) {
+		buf.put(AMF.TYPE_AMF3_OBJECT);
+		buf.put(bol.booleanValue() ? AMF3.TYPE_BOOLEAN_TRUE : AMF3.TYPE_BOOLEAN_FALSE);
 	}
 
-	public void writeBoolean(Boolean bol) {
+	public void writeNull() {
+		buf.put(AMF.TYPE_AMF3_OBJECT);
+		buf.put(AMF3.TYPE_NULL);
+	}
 
+	protected void putInteger(long value) {
+		if (value < 0) {
+			System.err.println("MISSING: negative integer");
+			return;
+		}
+		
+	

Note:
Diffs are chopped if more than 25k.
This is to get past the limit on the mailing list.



More information about the Red5commits mailing list