Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to network v86 instances together inside the browser? #1094

Closed
Darin755 opened this issue Jul 27, 2024 · 12 comments
Closed

Is it possible to network v86 instances together inside the browser? #1094

Darin755 opened this issue Jul 27, 2024 · 12 comments

Comments

@Darin755
Copy link
Contributor

I am looking for a way to network multiple instances together without having to do anything server side. This will be a part of a virtual networking lab for educational purposes. It might be possible to use serial to setup an connection but it would be tricky and not ideal. Ideally it would be nice to have a local network interface that can be used to make a virtual switch in the browser. You could have some sort of hook that runs a handler program when a frame is received. From there I could write a proper switch that could do routing based on mac.

@copy
Copy link
Owner

copy commented Jul 28, 2024

Yes, see https://github.com/copy/v86/blob/master/examples/two_instances.html (haven't tested it in a while, but it should still be working)

@ProgrammerIn-wonderland
Copy link
Contributor

I am looking for a way to network multiple instances together without having to do anything server side. This will be a part of a virtual networking lab for educational purposes. It might be possible to use serial to setup an connection but it would be tricky and not ideal. Ideally it would be nice to have a local network interface that can be used to make a virtual switch in the browser. You could have some sort of hook that runs a handler program when a frame is received. From there I could write a proper switch that could do routing based on mac.

I've been playing around with the new fetch based network driver and have to say, its really friendly to begin work on (I even made my own handler for TCP in a day that uses https://github.com/MercuryWorkshop/wsproxy and is much faster than the relay based networking available), you could probably play around with that + webrtc if you're looking for cross computer communication.

alternatively you could hook virtio console and serial and send messages that way, it would be a form of networking, just not through the NIC

@Darin755
Copy link
Contributor Author

Yes, see https://github.com/copy/v86/blob/master/examples/two_instances.html (haven't tested it in a while, but it should still be working)

Is it possible to have multiple interfaces? I am looking to have a mini web based network. For now I am looking into possibly writing a switch program that matches Mac addresses.

@ProgrammerIn-wonderland
Copy link
Contributor

Is it possible to have multiple interfaces? I am looking to have a mini web based network. For now I am looking into possibly writing a switch program that matches Mac addresses.

I think the switch is the best idea here, there doesn't seem to be a way to create multiple NICs in v86 in starter.js, you'd probably need to do substantial modifications

@Darin755
Copy link
Contributor Author

Darin755 commented Jul 31, 2024

I might just use premade simulators. This is starting to seem way more ambitious than I realized.

Thanks

@copy
Copy link
Owner

copy commented Aug 3, 2024

I'd accept a PR to support multiple adapters in the constructor. We'll soon have three network backends (wsproxy, fetch and wisp) and two adapters (ne2k and virtio-net), and it would be nice to support arbitrary combinations too.

@SuperMaxusa
Copy link
Contributor

I am looking for a way to network multiple instances together without having to do anything server side.

If you need to connect instances within in a browser frame without server side, you can try to use Broadcast Channel API to receive/send Ethernet frames. Here I'm tried to make simple example:

v86-mesh

<!doctype html>
<script src="libv86.js"></script>
<script>
"use strict";

// from src/browser/fetch_network.js
function a2ethaddr(bytes) {
    return [0,1,2,3,4,5].map((i) => bytes[i].toString(16)).map(x => x.length === 1 ? "0" + x : x).join(":");
};

window.onload = function()
{
    var emulator = window.emulator = new V86({
        ...
    });

    emulator.add_listener("net0-mac", function(mac) {
        emulator.mac = mac; 
        document.title = "mesh: " + emulator.mac;
    });

    // [connecting to a channel (or creating a new one)]
    var broadcast = new BroadcastChannel("v86-mesh");

    // [receiving]
    broadcast.addEventListener("message", function(e) {
        const packet = e.data;
        const eth = {
            dest: a2ethaddr(packet.subarray(0, 6)),
            src: a2ethaddr(packet.subarray(6, 12))
        };
        
        // don't accept packets not addressed to us
        // ff:ff:ff:ff:ff:ff - broadcast
        if((eth.dest === emulator.mac) || (eth.dest === "ff:ff:ff:ff:ff:ff")) {
            console.log("packet from %s to %s", eth.src, eth.dest);
            emulator.bus.send("net0-receive", packet);
        };
    });

    // [sending]
    emulator.add_listener("net0-send", function(packet) {
        broadcast.postMessage(packet);
    });
}
</script>

<div id="screen_container">
    <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
    <canvas style="display: none"></canvas>
</div>

Partly based on examples/two_instances.html and you also need to set a static IP for each VM, Currently it uses one network adapter, but could probably be redesigned for multiple network adapters.

@Darin755
Copy link
Contributor Author

Darin755 commented Aug 6, 2024

Well that is not an approach that I had considered. It would be closer to a hub instead of switch and I would need to come up with some sort of lock to prevent two instances broadcasting at the same time but it might be feasible.

Thanks

@Darin755
Copy link
Contributor Author

I have a working proof of concept. Thanks @SuperMaxusa

@Darin755
Copy link
Contributor Author

Darin755 commented Aug 15, 2024

https://darin755.codeberg.page/netemu/src/

to run commands on the web worker you can run window.worker1.postMessage({cmd: "ip neigh"}) in the browser debug console. (there is a connection between the web worker and browser instance. Eventually it will be just web workers with the browser main just running switch/hub code)

@copy
Copy link
Owner

copy commented Dec 10, 2024

@SuperMaxusa That is pretty cool, could you send a PR to add as an example?

Just a comment, I believe the following check is not necessary (it's already done in the network card)

        // don't accept packets not addressed to us
        // ff:ff:ff:ff:ff:ff - broadcast
        if((eth.dest === emulator.mac) || (eth.dest === "ff:ff:ff:ff:ff:ff")) {

@SuperMaxusa
Copy link
Contributor

Just a comment, I believe the following check is not necessary (it's already done in the network card)

Indeed, thanks for your comment! Seems that I left this for clear logging on each VM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants