Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added Go server
The code is from http://code.google.com/p/webrtc-datachannel-polyfill
developed by Alfred Knallfred Godoy (alfred.knallfred.godoy@gmail.com),
but I bet that his polyfill implementation was stoled from mine... It's
not normal that has the same structure and also almost the same vars
names...
  • Loading branch information
piranna committed Mar 6, 2013
1 parent a9dd1df commit 4305801
Show file tree
Hide file tree
Showing 2 changed files with 253 additions and 0 deletions.
153 changes: 153 additions & 0 deletions datachannel-alfred.js
@@ -0,0 +1,153 @@
(function() {

var
// Configuration:
hostname = window.CHANNEL_HOST || window.location.host || 'localhost:8000',
websocketServer = "ws://"+hostname+"/",

// For browser compatibility:
PeerConnection = window.PeerConnection
|| window.RTCPeerConnection
|| window.mozPeerConnection
|| window.webkitRTCPeerConnection
|| window.webkitPeerConnection00;

if (typeof(PeerConnection) === 'undefined') {
console.error('Your browser does not support PeerConnection.');
return;
}

var pc = new PeerConnection(null);

if (typeof(pc.createDataChannel) !== 'undefined') {
try {
// This will throw when data channels is not implemented properly yet
pc.createDataChannel('polyfill')

// If we get this far you already have DataChannel support.
return console.log('REAL DATACHANNELS!');
} catch(e){
// TODO verify the Error
}
}

function DataChannel(peerConnection,label,dataChannelDict) {
this.readyState = "connecting";
this.label = label;
this.reliable = (!dataChannelDict || !dataChannelDict.reliable);
this._peerConnection = peerConnection;
this._queue = [];
this._webSocket = new WebSocket(websocketServer);

this._webSocket.onclose = function() {
this.readyState = "closed";
if (typeof this.onclose == 'function'){
this.onclose()
}
}.bind(this);

this._webSocket.onopen = function() {
this.readyState = "open";
this._identify();

if (typeof this.onopen == 'function'){
this.onopen()
}

if (typeof this._peerConnection.ondatachannel == 'function') {
var evt = document.createEvent('Event')
evt.initEvent('datachannel', true, true)
evt.channel = this;
this._peerConnection.ondatachannel(evt)
}

// empty the queue
while(this._queue.length) {
data = this._queue.shift();
this.send(data);
}
}.bind(this);

this._webSocket.onmessage = function(msg) {
if (typeof this.onmessage == 'function') {
this.onmessage(msg);
}
}.bind(this);

this._webSocket.onerror = function(msg) {
console.error(msg)
if (typeof this.onerror == 'function') {
this.onerror(msg);
}
}.bind(this);
};

DataChannel.prototype._identify = function() {
if (this._peerConnection === null) return false;

if (this._peerConnection._localDescription && this._peerConnection._remoteDescription) {
this._localId = description2id(this._peerConnection._localDescription) + '_' + this.label
this._remoteId = description2id(this._peerConnection._remoteDescription) + '_' + this.label
this.send('connect:' + this._localId + ':' + this._remoteId );
}
};

DataChannel.prototype.close = function() {
this.readyState = "closing";
this._webSocket.close();
};

DataChannel.prototype.send = function(data) {
if( this.readyState == 'open' ) {
this._webSocket.send(data);
} else if( this.reliable ) { // queue messages when "reliable"
this._queue.push(data);
}
};

PeerConnection.prototype.createDataChannel = function(label, dataChannelDict) {
console.log('createDataChannel',label,dataChannelDict)
var channel = new DataChannel(this,label,dataChannelDict);

if (typeof(this._allDataChannels) == 'undefined') {
this._allDataChannels = [];
}
this._allDataChannels.push(channel);

return channel;
}

function description2id(description) {
var result = description.sdp.replace(/(\r\n|\n|\r)/gm, '\n')
var re = new RegExp("o=.+");
result = re.exec(result)
return result[0]
}

// Overwrite PeerConnection's description setters, to get ID:s for the websocket connections.

var
setLocalDescription = PeerConnection.prototype.setLocalDescription,
setRemoteDescription = PeerConnection.prototype.setRemoteDescription;

PeerConnection.prototype.setLocalDescription = function(description, successCallback, errorCallback) {
this._localDescription = description;
if (typeof(this._allDataChannels) != 'undefined') {
for (var i in this._allDataChannels) {
this._allDataChannels[i]._identify();
}
}
setLocalDescription.apply(this, arguments);
};

PeerConnection.prototype.setRemoteDescription = function(description) {
this._remoteDescription = description;
if (typeof(this._allDataChannels) != 'undefined') {
for (var i in this._allDataChannels) {
this._allDataChannels[i]._identify();
}
};
setRemoteDescription.apply(this, arguments);
};

}());
100 changes: 100 additions & 0 deletions websockserver.go
@@ -0,0 +1,100 @@
package main

import (
"fmt"
"net/http"
"code.google.com/p/go.net/websocket"
"strings"
)

// ===================
// C O N N E C T I O N
// ===================

type connection struct {
// The websocket connection.
ws *websocket.Conn

id string

peer *connection

// Buffered channel of outbound messages.
send chan string
}

var connections map[string]*connection = make(map[string]*connection)

func (c *connection) reader() {
for {

fmt.Println(len(connections))

var message string
err := websocket.Message.Receive(c.ws, &message)
if err != nil {
fmt.Println(err)
break
}

fmt.Println("R: " + c.id + " : " + message)

if len(message) > 7 && message[0:8] == "connect:" {
{
connectParts := strings.Split(message, ":")
if len(connectParts) == 3 {
c.id = connectParts[1]
connections[c.id] = c

if _,ok := connections[connectParts[2]]; ok {
c.peer = connections[connectParts[2]]
connections[connectParts[2]].peer = c
}
}
}
} else if (c.peer != nil) {

c.peer.send <- message

}

}
c.send <- "disconnect" // Send disconnect to my own writer.
delete(connections, c.id) // Remove myself from connection map.
fmt.Println("R: Connection lost:" + c.id)
c.ws.Close()
}

func (c *connection) writer() {
for {
message := <- c.send
if message == "disconnect" {
break;
}
fmt.Println("W: " + c.id + " : " + message)
err := websocket.Message.Send(c.ws, message)
if err != nil {
break
}
}
fmt.Println("W: Connection lost:" + c.id)
c.ws.Close()
}

// =======
// M A I N
// =======

func wsHandler(ws *websocket.Conn) {
fmt.Println("NEW WEBSOCKET!");
fmt.Println(ws.Config())
fmt.Println(ws.RemoteAddr())
c := &connection{send: make(chan string, 256), ws: ws}
go c.writer()
c.reader()
}

func main() {
http.Handle("/", websocket.Handler(wsHandler));
http.ListenAndServe(":8000", nil)
}

0 comments on commit 4305801

Please sign in to comment.