avm1: Implement some event handlers

This commit is contained in:
sleepycatcoding 2023-08-02 00:33:34 +03:00 committed by Nathan Adams
parent 78a68f95ea
commit dccf254281
2 changed files with 59 additions and 21 deletions

View File

@ -118,7 +118,7 @@ pub fn connect<'gc>(
.. ..
} = &mut activation.context; } = &mut activation.context;
sockets.connect_avm1(*navigator, xml_socket, host.to_utf8_lossy().into_owned(), port); sockets.connect_avm1(*navigator, this, host.to_utf8_lossy().into_owned(), port);
// NOTE: At this point we do not know if the connection will succeed // NOTE: At this point we do not know if the connection will succeed
// because connecting is an asynchronous process, so we just return true. // because connecting is an asynchronous process, so we just return true.

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
avm1::globals::xml_socket::XmlSocket, avm1::{globals::xml_socket::XmlSocket, Activation, ActivationIdentifier, ExecutionReason, TObject, Object},
avm2::{object::SocketObject, Activation, Avm2, EventObject, TObject}, avm2::{object::SocketObject, Activation as Avm2Activation, Avm2, EventObject, TObject as Avm2TObject},
backend::navigator::NavigatorBackend, backend::navigator::NavigatorBackend,
context::UpdateContext, context::UpdateContext,
}; };
@ -15,11 +15,11 @@ use std::{
pub type SocketHandle = Index; pub type SocketHandle = Index;
#[derive(Collect)] #[derive(Copy, Clone, Collect)]
#[collect(no_drop)] #[collect(no_drop)]
enum SocketKind<'gc> { enum SocketKind<'gc> {
Avm2(SocketObject<'gc>), Avm2(SocketObject<'gc>),
Avm1(XmlSocket<'gc>), Avm1(Object<'gc>),
} }
#[derive(Collect)] #[derive(Collect)]
@ -111,11 +111,16 @@ impl<'gc> Sockets<'gc> {
pub fn connect_avm1( pub fn connect_avm1(
&mut self, &mut self,
backend: &mut dyn NavigatorBackend, backend: &mut dyn NavigatorBackend,
target: XmlSocket<'gc>, target: Object<'gc>,
host: String, host: String,
port: u16, port: u16,
) { ) {
let (sender, receiver) = unbounded(); let (sender, receiver) = unbounded();
let xml_socket = match XmlSocket::cast(target.into()) {
Some(xml_socket) => xml_socket,
None => return,
};
let socket = Socket::new(SocketKind::Avm1(target), sender); let socket = Socket::new(SocketKind::Avm1(target), sender);
let handle = self.sockets.insert(socket); let handle = self.sockets.insert(socket);
@ -124,13 +129,13 @@ impl<'gc> Sockets<'gc> {
backend.connect_socket( backend.connect_socket(
host, host,
port, port,
Duration::from_millis(target.timeout().into()), Duration::from_millis(xml_socket.timeout().into()),
handle, handle,
receiver, receiver,
self.sender.clone(), self.sender.clone(),
); );
if let Some(existing_handle) = target.set_handle(handle) { if let Some(existing_handle) = xml_socket.set_handle(handle) {
// NOTE: AS2 docs don't specify what happens when connect is called with open connection, // NOTE: AS2 docs don't specify what happens when connect is called with open connection,
// but we will close the existing connection anyway. // but we will close the existing connection anyway.
self.close(existing_handle) self.close(existing_handle)
@ -154,18 +159,16 @@ impl<'gc> Sockets<'gc> {
} }
pub fn update_sockets(context: &mut UpdateContext<'_, 'gc>) { pub fn update_sockets(context: &mut UpdateContext<'_, 'gc>) {
let mut activation = Activation::from_nothing(context.reborrow());
let mut actions = vec![]; let mut actions = vec![];
while let Ok(action) = activation.context.sockets.receiver.try_recv() { while let Ok(action) = context.sockets.receiver.try_recv() {
actions.push(action) actions.push(action)
} }
for action in actions { for action in actions {
match action { match action {
SocketAction::Connect(handle, ConnectionState::Connected) => { SocketAction::Connect(handle, ConnectionState::Connected) => {
let target = match activation.context.sockets.sockets.get(handle) { let target = match context.sockets.sockets.get(handle) {
Some(socket) => socket.target, Some(socket) => socket.target,
// Socket must have been closed before we could send event. // Socket must have been closed before we could send event.
None => continue, None => continue,
@ -173,6 +176,8 @@ impl<'gc> Sockets<'gc> {
match target { match target {
SocketKind::Avm2(target) => { SocketKind::Avm2(target) => {
let mut activation = Avm2Activation::from_nothing(context.reborrow());
let connect_evt = let connect_evt =
EventObject::bare_default_event(&mut activation.context, "connect"); EventObject::bare_default_event(&mut activation.context, "connect");
Avm2::dispatch_event( Avm2::dispatch_event(
@ -181,15 +186,23 @@ impl<'gc> Sockets<'gc> {
target.into(), target.into(),
); );
} }
// TODO: Implement this. SocketKind::Avm1(target) => {
SocketKind::Avm1(_) => {} let mut activation = Activation::from_stub(context.reborrow(), ActivationIdentifier::root("[XMLSocket]"));
let _ = target.call_method(
"onConnect".into(),
&[true.into()],
&mut activation,
ExecutionReason::Special,
);
}
} }
} }
SocketAction::Connect( SocketAction::Connect(
handle, handle,
ConnectionState::Failed | ConnectionState::TimedOut, ConnectionState::Failed | ConnectionState::TimedOut,
) => { ) => {
let target = match activation.context.sockets.sockets.get(handle) { let target = match context.sockets.sockets.get(handle) {
Some(socket) => socket.target, Some(socket) => socket.target,
// Socket must have been closed before we could send event. // Socket must have been closed before we could send event.
None => continue, None => continue,
@ -197,6 +210,8 @@ impl<'gc> Sockets<'gc> {
match target { match target {
SocketKind::Avm2(target) => { SocketKind::Avm2(target) => {
let mut activation = Avm2Activation::from_nothing(context.reborrow());
let io_error_evt = activation let io_error_evt = activation
.avm2() .avm2()
.classes() .classes()
@ -220,11 +235,20 @@ impl<'gc> Sockets<'gc> {
); );
} }
// TODO: Not sure if avm1 xmlsocket has a way to notify a error. (Probably should just fire connect event with success as false). // TODO: Not sure if avm1 xmlsocket has a way to notify a error. (Probably should just fire connect event with success as false).
SocketKind::Avm1(_) => {} SocketKind::Avm1(target) => {
let mut activation = Activation::from_stub(context.reborrow(), ActivationIdentifier::root("[XMLSocket]"));
let _ = target.call_method(
"onConnect".into(),
&[false.into()],
&mut activation,
ExecutionReason::Special,
);
}
} }
} }
SocketAction::Data(handle, data) => { SocketAction::Data(handle, data) => {
let target = match activation.context.sockets.sockets.get(handle) { let target = match context.sockets.sockets.get(handle) {
Some(socket) => socket.target, Some(socket) => socket.target,
// Socket must have been closed before we could send event. // Socket must have been closed before we could send event.
None => continue, None => continue,
@ -232,6 +256,8 @@ impl<'gc> Sockets<'gc> {
match target { match target {
SocketKind::Avm2(target) => { SocketKind::Avm2(target) => {
let mut activation = Avm2Activation::from_nothing(context.reborrow());
let bytes_loaded = data.len(); let bytes_loaded = data.len();
target.read_buffer().extend(data); target.read_buffer().extend(data);
@ -259,11 +285,13 @@ impl<'gc> Sockets<'gc> {
); );
} }
// TODO: Implement this. // TODO: Implement this.
SocketKind::Avm1(_) => {} SocketKind::Avm1(_) => {
let mut activation = Activation::from_stub(context.reborrow(), ActivationIdentifier::root("[XMLSocket]"));
}
} }
} }
SocketAction::Close(handle) => { SocketAction::Close(handle) => {
let target = match activation.context.sockets.sockets.get(handle) { let target = match context.sockets.sockets.get(handle) {
Some(socket) => socket.target, Some(socket) => socket.target,
// Socket must have been closed before we could send event. // Socket must have been closed before we could send event.
None => continue, None => continue,
@ -271,12 +299,22 @@ impl<'gc> Sockets<'gc> {
match target { match target {
SocketKind::Avm2(target) => { SocketKind::Avm2(target) => {
let mut activation = Avm2Activation::from_nothing(context.reborrow());
let close_evt = let close_evt =
EventObject::bare_default_event(&mut activation.context, "close"); EventObject::bare_default_event(&mut activation.context, "close");
Avm2::dispatch_event(&mut activation.context, close_evt, target.into()); Avm2::dispatch_event(&mut activation.context, close_evt, target.into());
} }
// TODO: Implement this. SocketKind::Avm1(target) => {
SocketKind::Avm1(_) => {} let mut activation = Activation::from_stub(context.reborrow(), ActivationIdentifier::root("[XMLSocket]"));
let _ = target.call_method(
"onClose".into(),
&[],
&mut activation,
ExecutionReason::Special,
);
}
} }
} }
} }