avm1: Implement onData()

This commit is contained in:
sleepycatcoding 2023-08-02 01:09:08 +03:00 committed by Nathan Adams
parent 2b18a5999b
commit 25b1ed7e9c
2 changed files with 34 additions and 3 deletions

View File

@ -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<Option<SocketHandle>>,
/// Connection timeout in milliseconds.
timeout: Cell<u32>,
read_buffer: RefCell<Vec<u8>>,
}
#[derive(Clone, Debug, Collect)]
@ -34,6 +35,10 @@ impl<'gc> XmlSocket<'gc> {
self.0.timeout.get()
}
pub fn read_buffer(&self) -> RefMut<'_, Vec<u8>> {
self.0.read_buffer.borrow_mut()
}
pub fn cast(value: Value<'gc>) -> Option<Self> {
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()),
},
));

View File

@ -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::<Vec<_>>();
// 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,
);
}
}
}
}