summaryrefslogtreecommitdiff
path: root/src/net.moon
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.moon')
-rw-r--r--src/net.moon148
1 files changed, 148 insertions, 0 deletions
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