v86
v86 copied to clipboard
Stream comunication between JavaScript and guest OS
Hi, thank you so much for the fantastic project!
I'd like to comunicate or stream data between JavaScript and guest OS. I know emulator.serial0_send()
and "serial0-output-line" event, using in the Lua intepreter, but the output might have noises.
For example, when we have device files such as /dev/jsread
and /dev/jswrite
, we can compress in a guest OS and use in JavaScript by using cat /dev/jsread | gzip | /dev/jswrite
. You can also do cat /dev/jsread | lua | /dev/jswrite
.
Another my idea is to use named pipes (FIFO). I tried to use them, but unfortunelly they don't use FS.prototype.Read
orFS.prototype.Write
, so I could not give or obtain data to the named pipe from JavaScript.
Could you tell me how to comunicate between JavaScript and guest OS streamingly?
poor workaround
The script as follows create a large file/root/myjsread
and emulator.fs9p.Read
is modified to give arbitrary data to guest OS from JavaScript.
var emulator = new V86Starter({...});
const rootId = emulator.fs9p.SearchPath("/root").id;
const filename = "myjsread";
const parentid = rootId;
const x = emulator.fs9p.CreateInode();
x.uid = emulator.fs9p.inodes[parentid].uid;
x.gid = emulator.fs9p.inodes[parentid].gid;
x.qid.type = S_IFREG >> 8;
x.mode = (emulator.fs9p.inodes[parentid].mode & 0x1B6) | S_IFREG;
emulator.fs9p.PushInode(x, parentid, filename);
emulator.fs9p.NotifyListeners(emulator.fs9p.inodes.length-1, 'newfile');
var id = emulator.fs9p.inodes.length-1;
x.size = Number.MAX_SAFE_INTEGER;
const originalRead = emulator.fs9p.Read.bind(emulator.fs9p);
console.log("ID", id);
emulator.fs9p.Read = async function (nodeid, offset, count) {
if (id === nodeid) {
console.log("!! READ HOOK !! reading ", arguments);
// You can return bytes what you want, but I just streams infinite "A"
return new Uint8Array(Array(count).fill(65));
}
return originalRead(nodeid, offset, count);
};
An example usage in a guest OS is as follows.
$ cat myjsread
AAAAAAAAAAAA...
AAAAAAAAAAAA...
...
In my experiment, reading the /root/myjsread
stopped arround 2^32 bytes.
I finally made it, ~~but it has a problem~~ ! I specified uartN: true
bellow, then we can read/write /dev/ttyS1
and/dev/ttyS2
in guest OS.
var emulator = new V86Starter({
...
uart1: true,
uart2: true,
uart3: true,
...
});
JavaScript → guest OS
// JavaScript → guest OS
setInterval(() => {
console.log("send now!");
emulator.bus.send("serial1-input", 65);
}, 1000);
stty raw < /dev/ttyS1
cat /dev/ttyS1
guest OS → JavaScript
stty raw < /dev/ttyS2
echo hello > /dev/ttyS2
emulator.add_listener("serial2-output-char", function(char)
{
console.log("outchar2", char);
});
~~The problem is the line buffer.~~
I found this very, very useful. Thanks!
I'm glad to hear that!
This is very helpful, thank you for sharing!