Basic TERMTYPE implementation.
This commit is contained in:
parent
86c5e01b53
commit
43a4a4f4d2
@ -311,7 +311,8 @@ pub fn install_lua_globals(
|
|||||||
register_class_function!(mud_class_table, mudoutput_wont);
|
register_class_function!(mud_class_table, mudoutput_wont);
|
||||||
register_class_function!(mud_class_table, mudoutput_do);
|
register_class_function!(mud_class_table, mudoutput_do);
|
||||||
register_class_function!(mud_class_table, mudoutput_dont);
|
register_class_function!(mud_class_table, mudoutput_dont);
|
||||||
register_class_function!(mud_class_table, mudoutput_subnegotiation);
|
register_stateless_class_function!(mud_class_table, mudoutput_subnegotiation);
|
||||||
|
register_class_function!(mud_class_table, mudoutput_subnegotiation_termtype);
|
||||||
register_class_function!(mud_class_table, mudinput_line);
|
register_class_function!(mud_class_table, mudinput_line);
|
||||||
register_class_function!(mud_class_table, "closed", mudclass_closed);
|
register_class_function!(mud_class_table, "closed", mudclass_closed);
|
||||||
register_stateless_class_function!(mud_class_table, "new", new_mud);
|
register_stateless_class_function!(mud_class_table, "new", new_mud);
|
||||||
|
@ -4,6 +4,7 @@ use piccolo::{
|
|||||||
self, async_sequence, Callback, CallbackReturn, Context, FromValue, Function, IntoValue,
|
self, async_sequence, Callback, CallbackReturn, Context, FromValue, Function, IntoValue,
|
||||||
SequenceReturn, StashedTable, StashedUserData, StashedValue, Table, UserData, Value,
|
SequenceReturn, StashedTable, StashedUserData, StashedValue, Table, UserData, Value,
|
||||||
};
|
};
|
||||||
|
use telopt::TERMTYPE_TELOPT;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
use web_sys::{console, window};
|
use web_sys::{console, window};
|
||||||
use yew::UseStateSetter;
|
use yew::UseStateSetter;
|
||||||
@ -239,6 +240,7 @@ pub(super) fn connect_mud<'gc>(
|
|||||||
if naws {
|
if naws {
|
||||||
set_option_supported(ctx, &conntab, &NAWS_TELOPT, &Side::Us);
|
set_option_supported(ctx, &conntab, &NAWS_TELOPT, &Side::Us);
|
||||||
}
|
}
|
||||||
|
set_option_supported(ctx, &conntab, &TERMTYPE_TELOPT, &Side::Us);
|
||||||
|
|
||||||
// Call conntab:new...
|
// Call conntab:new...
|
||||||
let seq = async_sequence(&ctx, |locals, mut seq| {
|
let seq = async_sequence(&ctx, |locals, mut seq| {
|
||||||
@ -596,11 +598,72 @@ pub(super) fn mudoutput_dont<'gc>(
|
|||||||
Ok(CallbackReturn::Return)
|
Ok(CallbackReturn::Return)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub(super) fn mudoutput_subnegotiation<'gc>(
|
pub(super) fn mudoutput_subnegotiation<'gc>(ctx: Context<'gc>) -> Callback<'gc> {
|
||||||
|
Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
|
||||||
|
let (mud, mut msg): (Table, Vec<u8>) = stack.consume(ctx)?;
|
||||||
|
if msg.is_empty() {
|
||||||
|
console::log_1(&JsValue::from_str(
|
||||||
|
"Received invalid subnegotiation with no type",
|
||||||
|
));
|
||||||
|
return Ok(CallbackReturn::Return);
|
||||||
|
}
|
||||||
|
let msg_type = msg.remove(0);
|
||||||
|
let msg_typename = name_telopt(ctx, msg_type)?;
|
||||||
|
|
||||||
|
let seq = async_sequence(&ctx, |locals, mut seq| {
|
||||||
|
let mud = locals.stash(&ctx, mud);
|
||||||
|
let msg = locals.stash(&ctx, msg.into_value(ctx));
|
||||||
|
async move {
|
||||||
|
call_checking_metatable(
|
||||||
|
&mut seq,
|
||||||
|
mud,
|
||||||
|
format!("mudoutput_subnegotiation_{}", &msg_typename),
|
||||||
|
&[msg],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(SequenceReturn::Return)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(CallbackReturn::Sequence(seq))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn mudoutput_subnegotiation_termtype<'gc>(
|
||||||
ctx: Context<'gc>,
|
ctx: Context<'gc>,
|
||||||
_global_memo: &GlobalMemoCell,
|
global_memo: &GlobalMemoCell,
|
||||||
) -> Callback<'gc> {
|
) -> Callback<'gc> {
|
||||||
Callback::from_fn(&ctx, move |_ctx, _ex, _stack| Ok(CallbackReturn::Return))
|
let global_memo = global_memo.clone();
|
||||||
|
Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
|
||||||
|
let (mud, mut msg): (Table, Vec<u8>) = stack.consume(ctx)?;
|
||||||
|
if msg.is_empty() {
|
||||||
|
return Ok(CallbackReturn::Return);
|
||||||
|
}
|
||||||
|
let cmd = msg.remove(0);
|
||||||
|
|
||||||
|
let socket: Value = mud.get(ctx, "socket")?;
|
||||||
|
let socket: &WebSocketId =
|
||||||
|
UserData::from_value(ctx, socket)?.downcast::<Rootable![Gc<'_, WebSocketId>]>()?;
|
||||||
|
|
||||||
|
const SEND_CMD: u8 = 1;
|
||||||
|
match cmd {
|
||||||
|
SEND_CMD => {
|
||||||
|
send_subnegotiation_if_allowed(
|
||||||
|
ctx,
|
||||||
|
&mud,
|
||||||
|
&TERMTYPE_TELOPT,
|
||||||
|
&Side::Us,
|
||||||
|
&mut MudWithMemo {
|
||||||
|
memo: global_memo.clone(),
|
||||||
|
mud: socket.clone(),
|
||||||
|
},
|
||||||
|
format!("\x00{}", "xterm").as_bytes(),
|
||||||
|
);
|
||||||
|
Ok(CallbackReturn::Return)
|
||||||
|
}
|
||||||
|
_ => Ok(CallbackReturn::Return),
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn mudinput_line<'gc>(
|
pub(super) fn mudinput_line<'gc>(
|
||||||
|
@ -193,6 +193,7 @@ pub fn send_subnegotiation_if_allowed<'gc, T: SendRaw>(
|
|||||||
if get_option_state(ctx, mud_table, opt, side) == OptionState::Yes {
|
if get_option_state(ctx, mud_table, opt, side) == OptionState::Yes {
|
||||||
let mut buf: Vec<u8> = Vec::with_capacity(msg.len() + 4);
|
let mut buf: Vec<u8> = Vec::with_capacity(msg.len() + 4);
|
||||||
buf.extend_from_slice(&[IAC, STARTSUB]);
|
buf.extend_from_slice(&[IAC, STARTSUB]);
|
||||||
|
buf.push(opt.0);
|
||||||
for c in msg {
|
for c in msg {
|
||||||
if *c == IAC {
|
if *c == IAC {
|
||||||
buf.extend_from_slice(b"\xff\xff");
|
buf.extend_from_slice(b"\xff\xff");
|
||||||
@ -426,8 +427,9 @@ pub fn handle_incoming_dont<'gc, T: SendOptNeg>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const GMCP_TELOPT: Telopt = Telopt(201);
|
pub const TERMTYPE_TELOPT: Telopt = Telopt(24);
|
||||||
pub const NAWS_TELOPT: Telopt = Telopt(31);
|
pub const NAWS_TELOPT: Telopt = Telopt(31);
|
||||||
|
pub const GMCP_TELOPT: Telopt = Telopt(201);
|
||||||
|
|
||||||
fn negotiate_option_on<'gc, T: SendOptNeg>(
|
fn negotiate_option_on<'gc, T: SendOptNeg>(
|
||||||
ctx: Context<'gc>,
|
ctx: Context<'gc>,
|
||||||
@ -522,7 +524,10 @@ pub fn configure_telopt_table<'gc>(ctx: Context<'gc>, table: &Table<'gc>) {
|
|||||||
.set(ctx, "naws", NAWS_TELOPT.0)
|
.set(ctx, "naws", NAWS_TELOPT.0)
|
||||||
.expect("Can't set NAWS in telopt table");
|
.expect("Can't set NAWS in telopt table");
|
||||||
table
|
table
|
||||||
.set(ctx, "gmcp", GMCP_TELOPT.0)
|
.set(ctx, "naws", NAWS_TELOPT.0)
|
||||||
|
.expect("Can't set NAWS in telopt table");
|
||||||
|
table
|
||||||
|
.set(ctx, "termtype", TERMTYPE_TELOPT.0)
|
||||||
.expect("Can't set GMCP in telopt table");
|
.expect("Can't set GMCP in telopt table");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user