core: Introduce a NetConnection struct, backing AVM1/AVM2 NetConnection objects
This commit is contained in:
parent
514611451f
commit
c691b32886
|
@ -3,6 +3,7 @@ package flash.net {
|
|||
import flash.errors.IOError;
|
||||
import __ruffle__.stub_method;
|
||||
|
||||
[Ruffle(InstanceAllocator)]
|
||||
public class NetConnection extends EventDispatcher {
|
||||
|
||||
public static var defaultObjectEncoding:uint = 3;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
pub use crate::avm2::object::net_connection_allocator;
|
||||
use crate::avm2::object::TObject;
|
||||
use crate::net_connection::NetConnections;
|
||||
use crate::{
|
||||
avm2::{Activation, Avm2, Error, EventObject, Object, Value},
|
||||
avm2::{Activation, Error, Object, Value},
|
||||
avm2_stub_method,
|
||||
};
|
||||
|
||||
|
@ -8,16 +11,12 @@ pub fn connect<'gc>(
|
|||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let connection = this
|
||||
.as_net_connection()
|
||||
.expect("Must be NetConnection object");
|
||||
|
||||
if let Value::Null = args[0] {
|
||||
let event = EventObject::net_status_event(
|
||||
activation,
|
||||
"netStatus",
|
||||
vec![
|
||||
("code", "NetConnection.Connect.Success"),
|
||||
("level", "status"),
|
||||
],
|
||||
);
|
||||
Avm2::dispatch_event(&mut activation.context, event, this);
|
||||
NetConnections::connect_to_local(&mut activation.context, connection);
|
||||
return Ok(Value::Undefined);
|
||||
}
|
||||
avm2_stub_method!(
|
||||
|
|
|
@ -45,6 +45,7 @@ mod function_object;
|
|||
mod index_buffer_3d_object;
|
||||
mod loaderinfo_object;
|
||||
mod namespace_object;
|
||||
mod net_connection_object;
|
||||
mod netstream_object;
|
||||
mod primitive_object;
|
||||
mod program_3d_object;
|
||||
|
@ -97,6 +98,9 @@ pub use crate::avm2::object::loaderinfo_object::{
|
|||
pub use crate::avm2::object::namespace_object::{
|
||||
namespace_allocator, NamespaceObject, NamespaceObjectWeak,
|
||||
};
|
||||
pub use crate::avm2::object::net_connection_object::{
|
||||
net_connection_allocator, NetConnectionObject, NetConnectionObjectWeak,
|
||||
};
|
||||
pub use crate::avm2::object::netstream_object::{
|
||||
netstream_allocator, NetStreamObject, NetStreamObjectWeak,
|
||||
};
|
||||
|
@ -175,6 +179,7 @@ use crate::font::Font;
|
|||
TextureObject(TextureObject<'gc>),
|
||||
Program3DObject(Program3DObject<'gc>),
|
||||
NetStreamObject(NetStreamObject<'gc>),
|
||||
NetConnectionObject(NetConnectionObject<'gc>),
|
||||
ShaderDataObject(ShaderDataObject<'gc>),
|
||||
SocketObject(SocketObject<'gc>),
|
||||
FontObject(FontObject<'gc>)
|
||||
|
@ -1385,6 +1390,10 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
None
|
||||
}
|
||||
|
||||
fn as_net_connection(self) -> Option<NetConnectionObject<'gc>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_socket(&self) -> Option<SocketObject<'gc>> {
|
||||
None
|
||||
}
|
||||
|
@ -1432,6 +1441,7 @@ impl<'gc> Object<'gc> {
|
|||
Self::TextureObject(o) => WeakObject::TextureObject(TextureObjectWeak(Gc::downgrade(o.0))),
|
||||
Self::Program3DObject(o) => WeakObject::Program3DObject(Program3DObjectWeak(Gc::downgrade(o.0))),
|
||||
Self::NetStreamObject(o) => WeakObject::NetStreamObject(NetStreamObjectWeak(GcCell::downgrade(o.0))),
|
||||
Self::NetConnectionObject(o) => WeakObject::NetConnectionObject(NetConnectionObjectWeak(Gc::downgrade(o.0))),
|
||||
Self::ShaderDataObject(o) => WeakObject::ShaderDataObject(ShaderDataObjectWeak(Gc::downgrade(o.0))),
|
||||
Self::SocketObject(o) => WeakObject::SocketObject(SocketObjectWeak(Gc::downgrade(o.0))),
|
||||
Self::FontObject(o) => WeakObject::FontObject(FontObjectWeak(GcCell::downgrade(o.0))),
|
||||
|
@ -1489,6 +1499,7 @@ pub enum WeakObject<'gc> {
|
|||
TextureObject(TextureObjectWeak<'gc>),
|
||||
Program3DObject(Program3DObjectWeak<'gc>),
|
||||
NetStreamObject(NetStreamObjectWeak<'gc>),
|
||||
NetConnectionObject(NetConnectionObjectWeak<'gc>),
|
||||
ShaderDataObject(ShaderDataObjectWeak<'gc>),
|
||||
SocketObject(SocketObjectWeak<'gc>),
|
||||
FontObject(FontObjectWeak<'gc>),
|
||||
|
@ -1529,6 +1540,7 @@ impl<'gc> WeakObject<'gc> {
|
|||
Self::TextureObject(o) => TextureObject(o.0.upgrade(mc)?).into(),
|
||||
Self::Program3DObject(o) => Program3DObject(o.0.upgrade(mc)?).into(),
|
||||
Self::NetStreamObject(o) => NetStreamObject(o.0.upgrade(mc)?).into(),
|
||||
Self::NetConnectionObject(o) => NetConnectionObject(o.0.upgrade(mc)?).into(),
|
||||
Self::ShaderDataObject(o) => ShaderDataObject(o.0.upgrade(mc)?).into(),
|
||||
Self::SocketObject(o) => SocketObject(o.0.upgrade(mc)?).into(),
|
||||
Self::FontObject(o) => FontObject(o.0.upgrade(mc)?).into(),
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
//! Object representation for NetConnection
|
||||
|
||||
use crate::avm2::activation::Activation;
|
||||
use crate::avm2::object::script_object::ScriptObjectData;
|
||||
use crate::avm2::object::{ClassObject, Object, ObjectPtr, TObject};
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use crate::net_connection::NetConnectionHandle;
|
||||
use gc_arena::barrier::unlock;
|
||||
use gc_arena::lock::RefLock;
|
||||
use gc_arena::{Collect, Gc, GcWeak, Mutation};
|
||||
use std::cell::{Cell, Ref, RefMut};
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub fn net_connection_allocator<'gc>(
|
||||
class: ClassObject<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
) -> Result<Object<'gc>, Error<'gc>> {
|
||||
let base = ScriptObjectData::new(class).into();
|
||||
let this: Object<'gc> = NetConnectionObject(Gc::new(
|
||||
activation.context.gc_context,
|
||||
NetConnectionObjectData {
|
||||
base,
|
||||
handle: Cell::new(None),
|
||||
},
|
||||
))
|
||||
.into();
|
||||
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
#[derive(Clone, Collect, Copy)]
|
||||
#[collect(no_drop)]
|
||||
pub struct NetConnectionObject<'gc>(pub Gc<'gc, NetConnectionObjectData<'gc>>);
|
||||
|
||||
#[derive(Collect, Clone, Copy, Debug)]
|
||||
#[collect(no_drop)]
|
||||
pub struct NetConnectionObjectWeak<'gc>(pub GcWeak<'gc, NetConnectionObjectData<'gc>>);
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct NetConnectionObjectData<'gc> {
|
||||
base: RefLock<ScriptObjectData<'gc>>,
|
||||
#[collect(require_static)]
|
||||
handle: Cell<Option<NetConnectionHandle>>,
|
||||
}
|
||||
|
||||
impl<'gc> TObject<'gc> for NetConnectionObject<'gc> {
|
||||
fn base(&self) -> Ref<ScriptObjectData<'gc>> {
|
||||
self.0.base.borrow()
|
||||
}
|
||||
|
||||
fn base_mut(&self, mc: &Mutation<'gc>) -> RefMut<ScriptObjectData<'gc>> {
|
||||
unlock!(Gc::write(mc, self.0), NetConnectionObjectData, base).borrow_mut()
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const ObjectPtr {
|
||||
Gc::as_ptr(self.0) as *const ObjectPtr
|
||||
}
|
||||
|
||||
fn value_of(&self, _mc: &Mutation<'gc>) -> Result<Value<'gc>, Error<'gc>> {
|
||||
Ok(Value::Object(Object::from(*self)))
|
||||
}
|
||||
|
||||
fn as_net_connection(self) -> Option<NetConnectionObject<'gc>> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> NetConnectionObject<'gc> {
|
||||
pub fn handle(&self) -> Option<NetConnectionHandle> {
|
||||
self.0.handle.get()
|
||||
}
|
||||
|
||||
pub fn set_handle(&self, handle: Option<NetConnectionHandle>) -> Option<NetConnectionHandle> {
|
||||
self.0.handle.replace(handle)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Debug for NetConnectionObject<'gc> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "NetConnectionObject")
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ use crate::focus_tracker::FocusTracker;
|
|||
use crate::frame_lifecycle::FramePhase;
|
||||
use crate::library::Library;
|
||||
use crate::loader::LoadManager;
|
||||
use crate::net_connection::NetConnections;
|
||||
use crate::player::Player;
|
||||
use crate::prelude::*;
|
||||
use crate::socket::Sockets;
|
||||
|
@ -227,6 +228,9 @@ pub struct UpdateContext<'a, 'gc> {
|
|||
|
||||
pub sockets: &'a mut Sockets<'gc>,
|
||||
|
||||
/// List of active NetConnection instances.
|
||||
pub net_connections: &'a mut NetConnections<'gc>,
|
||||
|
||||
/// Dynamic root for allowing handles to GC objects to exist outside of the GC.
|
||||
pub dynamic_root: gc_arena::DynamicRootSet<'gc>,
|
||||
}
|
||||
|
@ -394,6 +398,7 @@ impl<'a, 'gc> UpdateContext<'a, 'gc> {
|
|||
frame_phase: self.frame_phase,
|
||||
stream_manager: self.stream_manager,
|
||||
sockets: self.sockets,
|
||||
net_connections: self.net_connections,
|
||||
dynamic_root: self.dynamic_root,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ mod library;
|
|||
pub mod limits;
|
||||
pub mod loader;
|
||||
mod locale;
|
||||
mod net_connection;
|
||||
pub mod pixel_bender;
|
||||
mod player;
|
||||
mod prelude;
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
use crate::avm2::object::NetConnectionObject as Avm2NetConnectionObject;
|
||||
use crate::avm2::{Activation as Avm2Activation, Avm2, EventObject as Avm2EventObject};
|
||||
use crate::context::UpdateContext;
|
||||
use gc_arena::Collect;
|
||||
use generational_arena::{Arena, Index};
|
||||
|
||||
pub type NetConnectionHandle = Index;
|
||||
|
||||
#[derive(Copy, Clone, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub enum NetConnectionObject<'gc> {
|
||||
Avm2(Avm2NetConnectionObject<'gc>),
|
||||
}
|
||||
|
||||
impl<'gc> NetConnectionObject<'gc> {
|
||||
pub fn set_handle(&self, handle: Option<NetConnectionHandle>) -> Option<NetConnectionHandle> {
|
||||
match self {
|
||||
NetConnectionObject::Avm2(object) => object.set_handle(handle),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> From<Avm2NetConnectionObject<'gc>> for NetConnectionObject<'gc> {
|
||||
fn from(value: Avm2NetConnectionObject<'gc>) -> Self {
|
||||
NetConnectionObject::Avm2(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Manages the collection of NetConnections.
|
||||
pub struct NetConnections<'gc> {
|
||||
connections: Arena<NetConnection<'gc>>,
|
||||
}
|
||||
|
||||
unsafe impl<'gc> Collect for NetConnections<'gc> {
|
||||
fn trace(&self, cc: &gc_arena::Collection) {
|
||||
for (_, connection) in self.connections.iter() {
|
||||
connection.trace(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Default for NetConnections<'gc> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
connections: Arena::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> NetConnections<'gc> {
|
||||
pub fn connect_to_local<O: Into<NetConnectionObject<'gc>>>(
|
||||
context: &mut UpdateContext<'_, 'gc>,
|
||||
target: O,
|
||||
) {
|
||||
let target = target.into();
|
||||
let connection = NetConnection { object: target };
|
||||
let handle = context.net_connections.connections.insert(connection);
|
||||
|
||||
if let Some(existing_handle) = target.set_handle(Some(handle)) {
|
||||
NetConnections::close(context, existing_handle)
|
||||
}
|
||||
|
||||
match target {
|
||||
NetConnectionObject::Avm2(object) => {
|
||||
let mut activation = Avm2Activation::from_nothing(context.reborrow());
|
||||
let event = Avm2EventObject::net_status_event(
|
||||
&mut activation,
|
||||
"netStatus",
|
||||
vec![
|
||||
("code", "NetConnection.Connect.Success"),
|
||||
("level", "status"),
|
||||
],
|
||||
);
|
||||
Avm2::dispatch_event(&mut activation.context, event, object.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(context: &mut UpdateContext<'_, 'gc>, handle: NetConnectionHandle) {
|
||||
let Some(connection) = context.net_connections.connections.remove(handle) else {
|
||||
return;
|
||||
};
|
||||
|
||||
match connection.object {
|
||||
NetConnectionObject::Avm2(object) => {
|
||||
let mut activation = Avm2Activation::from_nothing(context.reborrow());
|
||||
let event = Avm2EventObject::net_status_event(
|
||||
&mut activation,
|
||||
"netStatus",
|
||||
vec![
|
||||
("code", "NetConnection.Connect.Closed"),
|
||||
("level", "status"),
|
||||
],
|
||||
);
|
||||
Avm2::dispatch_event(&mut activation.context, event, object.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct NetConnection<'gc> {
|
||||
object: NetConnectionObject<'gc>,
|
||||
}
|
|
@ -39,6 +39,7 @@ use crate::library::Library;
|
|||
use crate::limits::ExecutionLimit;
|
||||
use crate::loader::{LoadBehavior, LoadManager};
|
||||
use crate::locale::get_current_date_time;
|
||||
use crate::net_connection::NetConnections;
|
||||
use crate::prelude::*;
|
||||
use crate::socket::Sockets;
|
||||
use crate::streams::StreamManager;
|
||||
|
@ -167,6 +168,9 @@ struct GcRootData<'gc> {
|
|||
|
||||
sockets: Sockets<'gc>,
|
||||
|
||||
/// List of active NetConnection objects.
|
||||
net_connections: NetConnections<'gc>,
|
||||
|
||||
/// Dynamic root for allowing handles to GC objects to exist outside of the GC.
|
||||
dynamic_root: DynamicRootSet<'gc>,
|
||||
}
|
||||
|
@ -195,6 +199,7 @@ impl<'gc> GcRootData<'gc> {
|
|||
&mut AudioManager<'gc>,
|
||||
&mut StreamManager<'gc>,
|
||||
&mut Sockets<'gc>,
|
||||
&mut NetConnections<'gc>,
|
||||
DynamicRootSet<'gc>,
|
||||
) {
|
||||
(
|
||||
|
@ -215,6 +220,7 @@ impl<'gc> GcRootData<'gc> {
|
|||
&mut self.audio_manager,
|
||||
&mut self.stream_manager,
|
||||
&mut self.sockets,
|
||||
&mut self.net_connections,
|
||||
self.dynamic_root,
|
||||
)
|
||||
}
|
||||
|
@ -1889,6 +1895,7 @@ impl Player {
|
|||
audio_manager,
|
||||
stream_manager,
|
||||
sockets,
|
||||
net_connections,
|
||||
dynamic_root,
|
||||
) = root_data.update_context_params();
|
||||
|
||||
|
@ -1940,6 +1947,7 @@ impl Player {
|
|||
stub_tracker: &mut self.stub_tracker,
|
||||
stream_manager,
|
||||
sockets,
|
||||
net_connections,
|
||||
dynamic_root,
|
||||
};
|
||||
|
||||
|
@ -2423,6 +2431,7 @@ impl PlayerBuilder {
|
|||
unbound_text_fields: Vec::new(),
|
||||
stream_manager: StreamManager::new(),
|
||||
sockets: Sockets::empty(),
|
||||
net_connections: NetConnections::default(),
|
||||
dynamic_root,
|
||||
},
|
||||
),
|
||||
|
|
Loading…
Reference in New Issue