diff --git a/core/src/avm1/globals/xml_socket.rs b/core/src/avm1/globals/xml_socket.rs index e447a0d56..7f258d000 100644 --- a/core/src/avm1/globals/xml_socket.rs +++ b/core/src/avm1/globals/xml_socket.rs @@ -7,7 +7,7 @@ use crate::avm_warn; use crate::context::{GcContext, UpdateContext}; use crate::socket::SocketHandle; use gc_arena::{Collect, Gc}; -use std::cell::Cell; +use std::cell::{Cell, RefCell, RefMut}; #[derive(Clone, Debug, Collect)] #[collect(require_static)] @@ -15,6 +15,7 @@ struct XmlSocketData { handle: Cell>, /// Connection timeout in milliseconds. timeout: Cell, + read_buffer: RefCell>, } #[derive(Clone, Debug, Collect)] @@ -34,6 +35,10 @@ impl<'gc> XmlSocket<'gc> { self.0.timeout.get() } + pub fn read_buffer(&self) -> RefMut<'_, Vec> { + self.0.read_buffer.borrow_mut() + } + pub fn cast(value: Value<'gc>) -> Option { if let Value::Object(object) = value { if let NativeObject::XmlSocket(xml_socket) = object.native() { @@ -212,6 +217,7 @@ pub fn constructor<'gc>( handle: Cell::new(None), /// Default timeout is 20_000 milliseconds (20 seconds) timeout: Cell::new(20000), + read_buffer: RefCell::new(Vec::new()), }, )); diff --git a/core/src/socket.rs b/core/src/socket.rs index 081d7ef4f..be227a5aa 100644 --- a/core/src/socket.rs +++ b/core/src/socket.rs @@ -9,6 +9,7 @@ use crate::{ }, backend::navigator::NavigatorBackend, context::UpdateContext, + string::AvmString, }; use async_channel::{unbounded, Sender as AsyncSender}; use gc_arena::Collect; @@ -296,12 +297,36 @@ impl<'gc> Sockets<'gc> { target.into(), ); } - // TODO: Implement this. - SocketKind::Avm1(_) => { + SocketKind::Avm1(target) => { let mut activation = Activation::from_stub( context.reborrow(), ActivationIdentifier::root("[XMLSocket]"), ); + + // NOTE: This is enforced in connect_avm1() function. + let xml_socket = + XmlSocket::cast(target.into()).expect("target should be XmlSocket"); + + let mut buffer = xml_socket.read_buffer(); + buffer.extend(data); + + // Check for a message. + if let Some((index, _)) = + buffer.iter().enumerate().find(|(_, &b)| b == 0) + { + let message = buffer.drain(..index).collect::>(); + // Remove null byte. + let _ = buffer.drain(..1); + + let message = AvmString::new_utf8_bytes(activation.gc(), &message); + + let _ = target.call_method( + "onData".into(), + &[message.into()], + &mut activation, + ExecutionReason::Special, + ); + } } } }