Skip to content
Snippets Groups Projects
Commit 7cbbe585 authored by Serene Han's avatar Serene Han
Browse files

implement Snowflake coffee class (issue #5)

parent c0397bc3
No related branches found
No related tags found
No related merge requests found
###
A Coffeescript WebRTC snowflake proxy
Using Copy-paste signaling for now.
Uses WebRTC from the client, and websocket to the server.
Assume that the webrtc client plugin is always the offerer, in which case
this must always act as the answerer.
###
Query =
###
Parse a URL query string or application/x-www-form-urlencoded body. The
return type is an object mapping string keys to string values. By design,
this function doesn't support multiple values for the same named parameter,
for example "a=1&a=2&a=3"; the first definition always wins. Returns null on
error.
Always decodes from UTF-8, not any other encoding.
http://dev.w3.org/html5/spec/Overview.html#url-encoded-form-data
###
parse: (qs) ->
result = {}
strings = []
strings = qs.split '&' if qs
return result if 0 == strings.length
for i in [1..strings.length]
string = strings[i]
j = string.indexOf '='
if j == -1
name = string
value = ''
else
name = string.substr(0, j)
value = string.substr(j + 1)
name = decodeURIComponent(name.replace(/\+/g, ' '))
value = decodeURIComponent(value.replace(/\+/g, ' '))
result[name] = value if !(name in result)
result
Params =
getBool: (query, param, defaultValue) ->
val = query[param]
return defaultValue if undefined == val
return true if "true" == val || "1" == val || "" == val
return false if "false" == val || "0" == val
return null
# HEADLESS is true if we are running not in a browser with a DOM.
query = Query.parse(window.location.search.substr(1))
HEADLESS = "undefined" == typeof(document)
DEBUG = Params.getBool(query, "debug", false)
# Janky state machine
MODE =
INIT: 0
......@@ -10,6 +58,8 @@ MODE =
CHAT: 2
currentMode = MODE.INIT
# TODO: Different ICE servers.
config = {
iceServers: [
{ urls: ["stun:stun.l.google.com:19302"] }
......@@ -21,22 +71,96 @@ $chatlog = null
$send = null
$input = null
window.PeerConnection = window.RTCPeerConnection ||
window.mozRTCPeerConnection || window.webkitRTCPeerConnection
window.mozRTCPeerConnection ||
window.webkitRTCPeerConnection
window.RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate;
window.RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription
window.RTCSessionDescription = window.RTCSessionDescription ||
window.mozRTCSessionDescription
# TODO: Implement
class Badge
# Minimum viable snowflake for now - just 1 client.
class Snowflake
rateLimit: 0
proxyPairs: null
badge: null
$badge: null
MAX_NUM_CLIENTS = 1
constructor: ->
if HEADLESS
# No badge
else if DEBUG
@$badge = debug_div
else
@badge = new Badge()
@$badgem = @badge.elem
if (@$badge)
@$badge.setAttribute("id", "snowflake-badge")
start: ->
log "Starting up Snowflake..."
# Poll facilitator when this snowflake can support more clients.
proxyMain = ->
if @proxyPairs.length >= @MAX_NUM_CLIENTS * CONNECTIONS_PER_CLIENT
setTimeout(@proxyMain, @facilitator_poll_interval * 1000)
return
params = [["r", "1"]]
params.push ["transport", "websocket"]
params.push ["transport", "webrtc"]
beginProxy = (client, relay) ->
for i in [0..CONNECTIONS_PER_CLIENT]
makeProxyPair(client, relay)
makeProxyPair = (client, relay) ->
pair = new ProxyPair(client, relay, @rate_limit);
@proxyPairs.push pair
pair.onCleanup = (event) =>
# Delete from the list of active proxy pairs.
@proxyPairs.splice(@proxy_pairs.indexOf(pair), 1)
@badge.endProxy() if @badge
try
proxy_pair.connect()
catch err
log "ProxyPair: exception while connecting: " + safe_repr(err.message) + "."
return
@badge.beginProxy if @badge
cease = ->
# @start = null
# @proxyMain = null
# @make_proxy_pair = function(client_addr, relay_addr) { };
while @proxyPairs.length > 0
@proxyPairs.pop().close()
disable = ->
log "Disabling Snowflake."
@cease()
@badge.disable() if @badge
die = ->
log "Snowflake died."
@cease()
@badge.die() if @badge
# TODO: Implement
class ProxyPair
#
## -- DOM & Input Functionality -- ##
#
snowflake = new Snowflake()
welcome = ->
log "== snowflake JS proxy =="
log "== snowflake browser proxy =="
log "Input offer from the snowflake client:"
# Log to the message window.
......@@ -82,7 +206,7 @@ Signalling =
log "Invalid JSON."
return
# Begin as answerer if peerconnection doesn't exist yet.
start false if !pc
snowflake.start false if !pc
desc = recv['sdp']
ice = recv['candidate']
if !desc && ! ice
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment