Finished support for new connector type
This commit is contained in:
77
bower_components/connector/lib/connector.coffee
vendored
Normal file
77
bower_components/connector/lib/connector.coffee
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
class Connector
|
||||
|
||||
constructor: ()->
|
||||
# is set to true when this is synced with all other connections
|
||||
@is_synced = false
|
||||
# compute all of these functions when all connections are synced.
|
||||
@compute_when_synced = []
|
||||
# Peerjs Connections: key: conn-id, value: conn
|
||||
@connections = {}
|
||||
# Connections, that have been initialized, but have not been (fully) synced yet.
|
||||
@unsynced_connections = {}
|
||||
# List of functions that shall process incoming data
|
||||
@receive_handlers = []
|
||||
# A list of functions that are executed (left to right) when syncing with a peer.
|
||||
@sync_process_order = []
|
||||
|
||||
#
|
||||
# Execute a function _when_ we are connected. If not connected, wait until connected.
|
||||
# @param f {Function} Will be executed on the PeerJs-Connector context.
|
||||
#
|
||||
whenSynced: (args)->
|
||||
if @is_synced
|
||||
args[0].apply this, args[1..]
|
||||
else
|
||||
@compute_when_synced.push args
|
||||
|
||||
#
|
||||
# Execute an function _when_ a message is received.
|
||||
# @param f {Function} Will be executed on the PeerJs-Connector context. f will be called with (sender_id, broadcast {true|false}, message).
|
||||
#
|
||||
whenReceiving: (f)->
|
||||
@receive_handlers.push f
|
||||
|
||||
#
|
||||
# Send a message to a (sub)-set of all connected peers.
|
||||
# @param peers {Array<connection_ids>} A set of ids.
|
||||
# @param message {Object} The message to send.
|
||||
#
|
||||
multicast: (peers, message)->
|
||||
@whenSynced [_send, peers, message]
|
||||
|
||||
#
|
||||
# Send a message to one of the connected peers.
|
||||
# @param peers {connection_id} A connection id.
|
||||
# @param message {Object} The message to send.
|
||||
#
|
||||
unicast: (peer, message)->
|
||||
@whenSynced [_send, peer, message]
|
||||
|
||||
#
|
||||
# Broadcast a message to all connected peers.
|
||||
# @param message {Object} The message to broadcast.
|
||||
#
|
||||
broadcast: (message)->
|
||||
@whenSynced [()=>
|
||||
for peerid,peer of @connections
|
||||
@_send peerid, message]
|
||||
|
||||
#
|
||||
# Define how you want to handle the sync process of two users.
|
||||
# This is a synchronous handshake. Every user will perform exactly the same actions at the same time. E.g.
|
||||
# @example
|
||||
# whenSyncing(function(){ // first call must not have parameters!
|
||||
# return this.id; // Send the id of this connector.
|
||||
# },function(peerid){ // you receive the peerid of the other connections.
|
||||
# // you can do something with the peerid
|
||||
# // return "you are my friend"; // you could send another massage.
|
||||
# }); // this is the end of the sync process.
|
||||
#
|
||||
whenSyncing: ()->
|
||||
for i in [(arguments.length-1)..0]
|
||||
@sync_process_order.unshift arguments[i]
|
||||
|
||||
|
||||
|
||||
module.exports = Connector
|
||||
29
bower_components/connector/lib/peerjs-connector/peerjs-connector-polymer.coffee
vendored
Normal file
29
bower_components/connector/lib/peerjs-connector/peerjs-connector-polymer.coffee
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
new Polymer 'peerjs-connector',
|
||||
join: (id)->
|
||||
idChanged: (old_val,new_val)->
|
||||
if this.is_initialized
|
||||
throw new Error "You must not set the user_id twice!"
|
||||
else
|
||||
this.initializeConnection()
|
||||
|
||||
initializeConnection: ()->
|
||||
if this.conn_id?
|
||||
console.log("now initializing")
|
||||
options = {}
|
||||
writeIfAvailable = (name, value)->
|
||||
if value?
|
||||
options[name] = value
|
||||
writeIfAvailable 'key', this.key
|
||||
writeIfAvailable 'host', this.host
|
||||
writeIfAvailable 'port', this.port
|
||||
writeIfAvailable 'path', this.path
|
||||
writeIfAvailable 'secure', this.secure
|
||||
writeIfAvailable 'debug', this.debug
|
||||
this.is_initialized = true;
|
||||
this.connector = new PeerJsConnector this.conn_id, options
|
||||
|
||||
ready: ()->
|
||||
if this.conn_id != null
|
||||
this.initializeConnection()
|
||||
|
||||
108
bower_components/connector/lib/peerjs-connector/peerjs-connector.coffee
vendored
Normal file
108
bower_components/connector/lib/peerjs-connector/peerjs-connector.coffee
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
Connector = require '../connector'
|
||||
|
||||
window.PeerJsConnector = class PeerJsConnector extends Connector
|
||||
|
||||
constructor: (@id, options)->
|
||||
super()
|
||||
that = this
|
||||
# The following two functions should be performed at the end of the syncing process.
|
||||
# In peerjs all connection ids must be send.
|
||||
@sync_process_order.push ()->
|
||||
peers = for peerid,conn of that.connections
|
||||
peerid
|
||||
peers
|
||||
# Then connect to the connection ids.
|
||||
@sync_process_order.push (peers)->
|
||||
for peerid in peers
|
||||
that.join peerid
|
||||
true
|
||||
# Create the Peerjs instance
|
||||
@conn = new Peer @id, options
|
||||
# TODO: improve error handling, what happens if disconnected? provide feedback
|
||||
@conn.on 'error', (err)->
|
||||
throw new Error "Peerjs connector: #{err}"
|
||||
@conn.on 'disconnected', ()->
|
||||
throw new Error "Peerjs connector disconnected from signalling server. Cannot accept new connections. Not fatal, but not so good either.."
|
||||
@conn.on 'disconnect', ()->
|
||||
that.conn.reconnect()
|
||||
@conn.on 'connection', @_addConnection
|
||||
|
||||
#
|
||||
# Join a communication room. In case of peerjs, you just have to join to one other client. This connector will join to the other peers automatically.
|
||||
# @param id {String} The connection id of another client.
|
||||
#
|
||||
join: (peerid)->
|
||||
if not @unsynced_connections[peerid]? and not @connections[peerid]? and peerid isnt @id
|
||||
peer = @conn.connect peerid, {reliable: true}
|
||||
@unsynced_connections[peerid] = peer
|
||||
@_addConnection peer
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
#
|
||||
# Send a message to a peer or set of peers. This is peerjs specific.
|
||||
# @overload _send(peerid, message)
|
||||
# @param peerid {String} PeerJs connection id of _another_ peer
|
||||
# @param message {Object} Some object that shall be send
|
||||
# @overload _send(peerids, message)
|
||||
# @param peerids {Array<String>} PeerJs connection ids of _other_ peers
|
||||
# @param message {Object} Some object that shall be send
|
||||
#
|
||||
_send: (peer_s, message)->
|
||||
if peer_s.constructor is [].constructor
|
||||
# Throw errors _after_ the message has been send to all other peers.
|
||||
# Just in case a connection is invalid.
|
||||
errors = []
|
||||
for peer in peer_s
|
||||
try
|
||||
@connection[peer].send message
|
||||
catch error
|
||||
errors.push(error+"")
|
||||
if errors.length > 0
|
||||
throw new Error errors
|
||||
else
|
||||
@connections[peer_s].send message
|
||||
|
||||
#
|
||||
# @private
|
||||
# This is a helper function that is only related to the peerjs connector.
|
||||
# Connect to another peer.
|
||||
_addConnection: (peer)=>
|
||||
peer.on 'open', ()=>
|
||||
that = @
|
||||
peer.send that.sync_process_order[0]()
|
||||
current_sync_i = 1
|
||||
peer.on 'data', (data)->
|
||||
console.log("receive data: #{JSON.stringify data}")
|
||||
if current_sync_i < that.sync_process_order.length
|
||||
peer.send that.sync_process_order[current_sync_i++].call that, data
|
||||
else if current_sync_i is that.sync_process_order.length
|
||||
# All sync functions have been called. Increment current_sync_i one last time
|
||||
current_sync_i++
|
||||
# add it to the connections object
|
||||
delete that.unsynced_connections[peer.peer]
|
||||
that.connections[peer.peer] = peer
|
||||
# when the conn closes, delete it from the connections object
|
||||
peer.on 'close', ()->
|
||||
delete that.connections[peer.peer]
|
||||
# helper fkt. true iff os is an object that does not hold enumerable properties
|
||||
isEmpty = (os)->
|
||||
for o of os
|
||||
return false
|
||||
return true
|
||||
if isEmpty(that.unsynced_connections)
|
||||
# there are no unsynced connections. we are now synced.
|
||||
# therefore execute all fkts in this.compute_when_synced
|
||||
that.is_synced = true
|
||||
for comp in that.compute_when_synced
|
||||
comp[0].apply that, comp[1..]
|
||||
that.compute_when_synced = []
|
||||
else
|
||||
# you received a new message, that is not a sync message.
|
||||
# notify the receive_handlers
|
||||
for f in that.receive_handlers
|
||||
f peer.peer, data
|
||||
|
||||
|
||||
|
||||
98
bower_components/connector/lib/test-connector/test-connector.coffee
vendored
Normal file
98
bower_components/connector/lib/test-connector/test-connector.coffee
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
_ = require "underscore"
|
||||
Connector = require '../connector'
|
||||
|
||||
#
|
||||
# A trivial Connector that simulates network delay.
|
||||
#
|
||||
class TestConnector extends Connector
|
||||
|
||||
#
|
||||
# @param id {String} Some unique id
|
||||
# @param user_connectors {Array<TestConnector>} List of TestConnectors instances
|
||||
#
|
||||
constructor: (@id)->
|
||||
super()
|
||||
# If you think of operations, this will mirror the
|
||||
# execiton order of operations (when a message is send, or received it is put into this)
|
||||
@execution_order = []
|
||||
# The messages are buffered under the name of teh sending user.
|
||||
@receive_buffer = {}
|
||||
@connections = {}
|
||||
|
||||
@whenReceiving (user, message)=>
|
||||
@execution_order.push message
|
||||
@is_synced = true
|
||||
|
||||
# join another user connector
|
||||
join: (conn)->
|
||||
@_addConnection conn.id, conn
|
||||
for cid,c of conn.connections
|
||||
@_addConnection cid, c
|
||||
for comp in @compute_when_synced
|
||||
comp[0].apply @, comp[1..]
|
||||
|
||||
|
||||
#
|
||||
# @private
|
||||
# This is a helper function that is only related to the peerjs connector.
|
||||
# Connect to another peer.
|
||||
_addConnection: (id, user_connector)->
|
||||
if not @connections[id]? and id isnt @id
|
||||
data = null
|
||||
user_data = null
|
||||
for i in [0...@sync_process_order.length]
|
||||
data_ = @sync_process_order[i].call @, user_data
|
||||
user_data = user_connector.sync_process_order[i].call user_connector, data
|
||||
data = data_
|
||||
@connections[id]=user_connector
|
||||
user_connector.connections[@id] = @
|
||||
|
||||
#
|
||||
# Get the ops in the execution order.
|
||||
#
|
||||
getOpsInExecutionOrder: ()->
|
||||
@execution_order
|
||||
|
||||
#
|
||||
# Send a message to another peer
|
||||
# @param {Operation} o The operation that was executed.
|
||||
#
|
||||
_send: (uid, message)->
|
||||
rb = @connections[uid].receive_buffer
|
||||
rb[@id] ?= []
|
||||
rb[@id].push message
|
||||
|
||||
#
|
||||
# Flush one operation from the line of a specific user.
|
||||
#
|
||||
flushOne: (uid)->
|
||||
if @receive_buffer[uid]?.length > 0
|
||||
message = @receive_buffer[uid].shift()
|
||||
for f in @receive_handlers
|
||||
f uid, message
|
||||
|
||||
#
|
||||
# Flush one operation on a random line.
|
||||
#
|
||||
flushOneRandom: ()->
|
||||
connlist = for cid,c of @receive_buffer
|
||||
cid
|
||||
@flushOne connlist[(_.random 0, (connlist.length-1))]
|
||||
|
||||
#
|
||||
# Flush all operations on every line.
|
||||
#
|
||||
flushAll: ()->
|
||||
for n,messages of @receive_buffer
|
||||
for message in messages
|
||||
for f in @receive_handlers
|
||||
f n, message
|
||||
@receive_buffer = {}
|
||||
|
||||
|
||||
if window?
|
||||
window.TestConnector = TestConnector
|
||||
|
||||
if module?
|
||||
module.exports = TestConnector
|
||||
Reference in New Issue
Block a user