summaryrefslogtreecommitdiff
path: root/src/net.moon
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.moon')
-rw-r--r--src/net.moon114
1 files changed, 93 insertions, 21 deletions
diff --git a/src/net.moon b/src/net.moon
index b22d6f2..acd75c7 100644
--- a/src/net.moon
+++ b/src/net.moon
@@ -1,54 +1,103 @@
-- Handles the bridge to javascript to do peer-to-peer connections
-
log = require("log")
+rng = require("rng")
+util = require("util")
+
net = {}
-net.initalize = () ->
+initalized = false
+initalize = () ->
am.eval_js(require("js_bridge"))
+ initalized = true
net.call = (method, args) ->
- print("About to eval")
+ if not initalized
+ initalize!
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 = []")
+net.pull_peers = () ->
+ if not initalized
+ initalize!
+ messages = am.eval_js("window.PEER.peer_message_queue")
+ am.eval_js("window.PEER.peer_message_queue = []")
+ messages
+
+net.pull_connections = () ->
+ if not initalized
+ initalize!
+ messages = am.eval_js("window.PEER.connection_message_queue")
+ am.eval_js("window.PEER.connection_message_queue = []")
messages
callbacks = {}
peers = {}
connections = {}
+--Connections are always create js side, this is just it's lua representation
class Connection
+ @connections = {}
+ @methods = util.reverse({"data","open","close","error"})
new: (source, dest) =>
@source = source
@dest = dest
+ @get: (source, dest) =>
+ key = table.concat({source,dest},",")
+ if @connections[key]
+ return @connections[key]
+ @@connections[key] = Connection(source,dest)
+ @@connections[key]
on: (event, callback) =>
+ if not @@methods[event]
+ error("Tried to set an unknown event (" .. event .. ") on a connection")
newid = #callbacks + 1
callbacks[newid] = callback
- net.call("conn_on", {name: @source, id: @dest, e: event, message: newid})
+ while am.eval_js('window.PEER.connections[["' .. @source .. '","' .. @dest .. '"].sort()] == null')
+ print("Waiting for peer")
+ coroutine.yield("Waiting for peer")
+ --not backwards, "on" is always called on the incomming connection
+ net.call("conn_on", {source: @dest, dest: @source, e: event, message: newid})
send: (msgname, msg) =>
net.validate(msgname, msg)
- net.call("send",{name: @source, id: @dest, data: msg})
+ net.call("send",{source: @source, dest: @dest, data: {msgname, msg}})
class Peer
+ @methods = util.reverse({"open","connection","call","close","disconnected","error"})
new: (id) =>
- net.call("create",{name: id})
- if id
- @id = id
- peers[id] = @
+ -- We can't create peers with peerjs-generated random ids,
+ -- their names are too hard to type.
+ -- Instead use (Year, Month), and append 4 random digits
+ -- to make a unique id (people can't join past midnight at the
+ -- end of the month, oh well)
+ -- Also needs to handle id-already-taken errors.
+ id = id or @generate_id!
+ while peers[id]
+ id = @generate_id!
+ @id = id
+ peers[@id] = @
+ net.call("create",{name: @id})
+ log.info("Creating peer: " .. @id, {"net"})
+ generate_id: () =>
+ os.date("%Y%e") .. rng.randomstring("ab",1) --.. rng.numstring(4)
+ replace_id: () =>
+ log.info("Regenerating id for peer: " .. @id, {"net"})
+ -- peers[@id] = nil TODO: uncomment, this breaks when running multiple peers from the same tab.
+ net.call("delete_peer",{name: @id})
+ @id = @generate_id!
+ peers[@id] = @
+ net.call("create", {name: @id})
on: (event, callback) =>
+ if not @@methods[event]
+ error("Tried to set an unknown event (" .. event .. ") on a peer.")
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})
+ conn = net.call("connect", {source: @id, dest: id})
log.info("Got connection: " .. tostring(conn), {"net"})
- Connection(conn[1],conn[2])
+ Connection\get(conn[1],conn[2])
net.Peer = Peer
@@ -84,9 +133,10 @@ 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")
+ if not (next(format.required) or next(format.optional))
+ log.warn("Message " .. name .. " registered with no fields.")
for set in *({format.required, format.optional})
- for field, type_ in pairs(format.required)
+ for field, type_ in pairs(set)
if type(type_) == "string"
key = string.format("%s\0%s\0%s",name,field,type_)
if not formatcache[key]
@@ -97,6 +147,7 @@ net.register_message = (name, format) ->
message_callbacks[name] = {}
net.validate = (name, message) ->
+ log.info("Validating message:" .. tostring(message), {"net"})
assert(type(message) == "table", "Message must be a table")
format = messages[name]
required = {}
@@ -122,27 +173,48 @@ net.listen = (name, callback, id) ->
net.defen = (name, id) ->
message_callbacks[name][id] = nil
+-- net.route = (conn, name, data) ->
+-- if message_callbacks[name]
+-- for id, callback in pairs(message_callbacks[name])
+-- ret = message_callbacks[name](conn,
+
rewrite_events = {
connection: (message) ->
- message.data.data = Connection(message.data.data[1], message.data.data[2])
+ conn = Connection\get(message.data.data[2], message.data.data[1])
+ assert(conn, "Failed to build conn?")
+ assert(conn.source and conn.dest)
+ message.data.data = conn
}
net.pump = () ->
- msg_ = net.pull!
- log.info("Processing " .. tostring(#msg_) .. " messages", {"net"})
+ msg_ = net.pull_peers!
+ log.info("Processing " .. tostring(#msg_) .. " peer 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})
+ if not message.data.peer and message.data.e == "open"
+ log.info("Setting peerid for a peer that didn't have one " ..tostring(message), {"net"})
peer = peers[message.data.peer]
- assert(peer, "Failed to find peer:" .. message.data.peer)
+ assert(peer, "Failed to find peer:" .. message.data.peer .. " peers:" .. tostring(net.peers!))
callback = callbacks[message.message]
assert(callback, "Failed to find callback " .. message.message .. " on peer " .. message.data.peer)
callback(peer,message.data)
+ msg_ = net.pull_connections!
+ log.info("Processing " .. tostring(#msg_) .. " connection messages", {"net"})
+ for message in *msg_
+ log.info(tostring(message), {"net", message.data.peer})
+ connection = Connection\get(message.dest, message.peer)
+ callback = callbacks[message.message]
+ assert(callback, "Fakled to find callback " .. message.message .. " for message" .. tostring(message))
+ callback(connection, message.data)
+
net.peers = () ->
peers
+initalize!
+
net