diff --git a/core/src/avm2/globals/flash/net/Socket.as b/core/src/avm2/globals/flash/net/Socket.as index 13fc53431..4f2b32d84 100644 --- a/core/src/avm2/globals/flash/net/Socket.as +++ b/core/src/avm2/globals/flash/net/Socket.as @@ -5,7 +5,6 @@ package flash.net { import flash.utils.IDataInput; import flash.utils.IDataOutput; - import __ruffle__.stub_method; import __ruffle__.stub_getter; [Ruffle(InstanceAllocator)] @@ -60,12 +59,7 @@ package flash.net { public native function readFloat():Number; public native function readInt():int; public native function readMultiByte(length:uint, charSet:String):String; - - public function readObject():* { - stub_method("flash.net.Socket", "readObject"); - return null; - } - + public native function readObject():*; public native function readShort():int; public native function readUnsignedByte():uint; public native function readUnsignedInt():uint; @@ -80,11 +74,7 @@ package flash.net { public native function writeFloat(value:Number):void; public native function writeInt(value:int):void; public native function writeMultiByte(value:String, charSet:String):void; - - public function writeObject(value:*):void { - stub_method("flash.net.Socket", "writeObject"); - } - + public native function writeObject(value:*):void; public native function writeShort(value:int):void; public native function writeUnsignedInt(value:uint):void; public native function writeUTF(value:String):void; diff --git a/core/src/avm2/globals/flash/net/socket.rs b/core/src/avm2/globals/flash/net/socket.rs index ad9c4b112..c0547eed6 100644 --- a/core/src/avm2/globals/flash/net/socket.rs +++ b/core/src/avm2/globals/flash/net/socket.rs @@ -7,6 +7,9 @@ use crate::avm2::{Activation, Error, Object, TObject, Value}; use crate::context::UpdateContext; use encoding_rs::Encoding; use encoding_rs::UTF_8; +use flash_lso::amf0::read::AMF0Decoder; +use flash_lso::amf3::read::AMF3Decoder; +use flash_lso::types::{AMFVersion, Element}; pub fn connect<'gc>( activation: &mut Activation<'_, 'gc>, @@ -292,6 +295,45 @@ pub fn read_multi_byte<'gc>( Ok(Value::Undefined) } +pub fn read_object<'gc>( + activation: &mut Activation<'_, 'gc>, + this: Object<'gc>, + _args: &[Value<'gc>], +) -> Result, Error<'gc>> { + if let Some(socket) = this.as_socket() { + let mut bytes = socket.read_buffer(); + + let (bytes_left, value) = match socket.object_encoding() { + ObjectEncoding::Amf0 => { + let mut decoder = AMF0Decoder::default(); + let (extra, amf) = decoder + .parse_single_element(&bytes) + .map_err(|_| "Error: Invalid object")?; + ( + extra.len(), + crate::avm2::amf::deserialize_value(activation, &amf)?, + ) + } + ObjectEncoding::Amf3 => { + let mut decoder = AMF3Decoder::default(); + let (extra, amf) = decoder + .parse_single_element(&bytes) + .map_err(|_| "Error: Invalid object")?; + ( + extra.len(), + crate::avm2::amf::deserialize_value(activation, &amf)?, + ) + } + }; + + let len = bytes.len(); + let _ = bytes.drain(..(len - bytes_left)); + return Ok(value); + } + + Ok(Value::Undefined) +} + pub fn read_short<'gc>( activation: &mut Activation<'_, 'gc>, this: Object<'gc>, @@ -504,6 +546,38 @@ pub fn write_multi_byte<'gc>( Ok(Value::Undefined) } +pub fn write_object<'gc>( + activation: &mut Activation<'_, 'gc>, + this: Object<'gc>, + args: &[Value<'gc>], +) -> Result, Error<'gc>> { + if let Some(socket) = this.as_socket() { + let obj = args.get_value(0); + let amf_version = match socket.object_encoding() { + ObjectEncoding::Amf0 => AMFVersion::AMF0, + ObjectEncoding::Amf3 => AMFVersion::AMF3, + }; + if let Some(amf) = crate::avm2::amf::serialize_value(activation, obj, amf_version) { + let element = Element::new("", amf); + let mut lso = flash_lso::types::Lso::new(vec![element], "", amf_version); + let bytes = flash_lso::write::write_to_bytes(&mut lso) + .map_err(|_| "Failed to serialize object")?; + // This is kind of hacky: We need to strip out the header and any padding so that we only write + // the value. In the future, there should be a method to do this in the flash_lso crate. + let element_padding = match amf_version { + AMFVersion::AMF0 => 8, + AMFVersion::AMF3 => 7, + }; + socket.write_bytes( + &bytes[flash_lso::write::header_length(&lso.header) + element_padding + ..bytes.len() - 1], + ); + } + } + + Ok(Value::Undefined) +} + pub fn write_short<'gc>( activation: &mut Activation<'_, 'gc>, this: Object<'gc>,