From decb72f936060a65bff18e9cbf33642ea3a71cd0 Mon Sep 17 00:00:00 2001 From: Alexander M Pickering Date: Thu, 9 Jan 2025 18:11:46 -0600 Subject: Work --- src/net.moon | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/net.moon (limited to 'src/net.moon') diff --git a/src/net.moon b/src/net.moon new file mode 100644 index 0000000..b22d6f2 --- /dev/null +++ b/src/net.moon @@ -0,0 +1,148 @@ +-- Handles the bridge to javascript to do peer-to-peer connections + + +log = require("log") +net = {} + +net.initalize = () -> + am.eval_js(require("js_bridge")) + +net.call = (method, args) -> + print("About to eval") + result = am.eval_js("window.PEER." .. method .. "(" .. am.to_json(args) .. ")") + print("Done evaling") + result + +net.pull = () -> + messages = am.eval_js("window.PEER.message_queue") + am.eval_js("window.PEER.message_queue = []") + messages + +callbacks = {} +peers = {} +connections = {} + +class Connection + new: (source, dest) => + @source = source + @dest = dest + on: (event, callback) => + newid = #callbacks + 1 + callbacks[newid] = callback + net.call("conn_on", {name: @source, id: @dest, e: event, message: newid}) + send: (msgname, msg) => + net.validate(msgname, msg) + net.call("send",{name: @source, id: @dest, data: msg}) + +class Peer + new: (id) => + net.call("create",{name: id}) + if id + @id = id + peers[id] = @ + on: (event, callback) => + newid = #callbacks + 1 + callbacks[newid] = callback + net.call("on",{name: @id, message:newid, e: event}) + + connect: (id, options) => + conn = net.call("connect", {name: @id, id: id}) + log.info("Got connection: " .. tostring(conn), {"net"}) + Connection(conn[1],conn[2]) + + +net.Peer = Peer + +-- A fake peer for testing +fakepeers = {} +fakeconnections = {} +fakecallbacks = {} +channel = require("channel") + +class FakePeer + new: (id) => + if id + @id = id + fakepeers[id] = @ + on: (event, callback) => + newid = #fakecallbacks + 1 + fakecallbacks[newid] = callback + + connect: (id, options) => + conn = channel.FaultyChannel({ + avg_latency: 200 + latency_std: 100 + loss: 0.1 + }) + conn + + +messages = {} +formatcache = {} +message_callbacks = {} +net.register_message = (name, format) -> + assert(type(format) == "table", "Format must be a table") + format.required = format.required or {} + format.optional = format.optional or {} + assert(next(format.required) or next(format.optional), "No fields found") + for set in *({format.required, format.optional}) + for field, type_ in pairs(format.required) + if type(type_) == "string" + key = string.format("%s\0%s\0%s",name,field,type_) + if not formatcache[key] + formatcache[key] = (any) -> + assert(type(any) == type_, string.format("In message %q %q must be a %q, but was a %q", name, field, type_, type(any))) + set[field] = formatcache[key] + messages[name] = format + message_callbacks[name] = {} + +net.validate = (name, message) -> + assert(type(message) == "table", "Message must be a table") + format = messages[name] + required = {} + for field, validate in pairs(format.required) + required[field] = validate + for field, value in pairs(message) + if format.required[field] + required[field](value) + required[field] = nil + if format.optional[field] + format.optional[field](value) + missing = next(required) + if missing + error("Missing required field: " .. missing) + true + +net.listen = (name, callback, id) -> + id = id or {} + message_callbacks[name] = message_callbacks[name] or {} + message_callbacks[name][id] = callback + id + +net.defen = (name, id) -> + message_callbacks[name][id] = nil + +rewrite_events = { + connection: (message) -> + message.data.data = Connection(message.data.data[1], message.data.data[2]) +} + +net.pump = () -> + msg_ = net.pull! + log.info("Processing " .. tostring(#msg_) .. " messages", {"net"}) + for message in *msg_ + log.info(tostring(message), {"net", message.data.peer}) + if rewrite_events[message.data.e] + log.info("Rewriting data due to " .. message.data.e .. " event", {"net", message.data.peer}) + rewrite_events[message.data.e](message) + log.info(tostring(message), {"net", message.data.peer}) + peer = peers[message.data.peer] + assert(peer, "Failed to find peer:" .. message.data.peer) + callback = callbacks[message.message] + assert(callback, "Failed to find callback " .. message.message .. " on peer " .. message.data.peer) + callback(peer,message.data) + +net.peers = () -> + peers + +net -- cgit v1.2.3-70-g09d2