Browse Source

Implementd client side lookup support.

pull/48/head
Simon Eisenmann 11 years ago
parent
commit
3204c329bc
  1. 31
      doc/CHANNELING-API.txt
  2. 19
      src/app/spreed-webrtc-server/channeling.go
  3. 28
      src/app/spreed-webrtc-server/hub.go
  4. 14
      src/app/spreed-webrtc-server/server.go
  5. 2
      static/js/directives/audiolevel.js
  6. 36
      static/js/mediastream/api.js
  7. 54
      static/js/services/buddylist.js

31
doc/CHANNELING-API.txt

@ -52,11 +52,14 @@ Sending vs receiving document data encapsulation @@ -52,11 +52,14 @@ Sending vs receiving document data encapsulation
{
"Type": "Whatever",
"Whatever": { /* your document */ }
"Whatever": { /* your document */ },
"Iid": "request-identifier-unique-to-client"
}
So any document you sent, you have to specify a Type key pointing
to the key where the real document is to be found.
to the key where the real document is to be found. The Iid field is
optional and is returned back with the response wrapper document to
match requests with response data when supported by the type.
Received documents are wrapped by a special Document which provides
additional information.
@ -64,7 +67,8 @@ Sending vs receiving document data encapsulation @@ -64,7 +67,8 @@ Sending vs receiving document data encapsulation
{
"From": "4",
"To": "5",
"Data": {}
"Data": {},
"Iid": "request-identifier-unique-to-client"
}
The Data key contains the real Document.
@ -76,6 +80,9 @@ Sending vs receiving document data encapsulation @@ -76,6 +80,9 @@ Sending vs receiving document data encapsulation
To : The Id, the server send this Document to. Should be the same as
your current Self Id.
Data : Contains the payload.
Iid : Optional request identifier to match this response to the calling
request. Only available when sent by the client and the requested
type implementation does support it.
Special purpose documents for channling
@ -333,9 +340,7 @@ Additional types for session listing and notifications @@ -333,9 +340,7 @@ Additional types for session listing and notifications
"Ua": "Chrome 28",
"Status": {...}
}
],
"Index": 0,
"Batch": 0
]
}
Note: The Userid field is only present, if that session belongs to a known user.
@ -389,9 +394,10 @@ Information retrieval @@ -389,9 +394,10 @@ Information retrieval
{
"Type": "Sessions",
"Id": "Client generated request ID",
"Token": "Request token",
"TokenType": "Token type"
"Sessions": {
"Type": "Token type",
"Token": "Request token"
}
}
Valid known token types are: "contact".
@ -401,9 +407,10 @@ Information retrieval @@ -401,9 +407,10 @@ Information retrieval
{
"Type": "Sessions",
"Id": "ID as from request",
"Token": "Token as in request",
"TokenType": "Type as in request",
"Sessions": {
"Type": "Type as in request",
"Token": "Token as in request"
},
"Users": [
{
"Type": "Online",

19
src/app/spreed-webrtc-server/channeling.go

@ -65,8 +65,8 @@ type DataTurn struct { @@ -65,8 +65,8 @@ type DataTurn struct {
}
type DataSession struct {
Type string
Id string
Type string `json:",omitempty"`
Userid string `json:",omitempty"`
Ua string `json:",omitempty"`
Token string `json:",omitempty"`
@ -148,22 +148,25 @@ type DataIncoming struct { @@ -148,22 +148,25 @@ type DataIncoming struct {
Alive *DataAlive
Authentication *DataAuthentication
Sessions *DataSessions
Iid string `json:",omitempty"`
}
type DataOutgoing struct {
Data interface{}
From string
To string
Iid string `json:",omitempty"`
}
type DataSessions struct {
Type string
Users []*DataSession
Id string `json:",omitempty"`
Token string `json:",omitempty"`
TokenType string `json:",omitempty"`
Index uint64 `json:",omitempty"`
Batch uint64 `json:",omitempty"`
Type string
Sessions *DataSessionsRequest `json:",omitempty"`
Users []*DataSession
}
type DataSessionsRequest struct {
Token string
Type string
}
type DataConference struct {

28
src/app/spreed-webrtc-server/hub.go

@ -405,11 +405,11 @@ func (h *Hub) unicastHandler(m *MessageRequest) { @@ -405,11 +405,11 @@ func (h *Hub) unicastHandler(m *MessageRequest) {
}
func (h *Hub) aliveHandler(c *Connection, alive *DataAlive) {
func (h *Hub) aliveHandler(c *Connection, alive *DataAlive, iid string) {
aliveJson := h.buffers.New()
encoder := json.NewEncoder(aliveJson)
err := encoder.Encode(&DataOutgoing{From: c.Id, Data: alive})
err := encoder.Encode(&DataOutgoing{From: c.Id, Data: alive, Iid: iid})
if err != nil {
log.Println("Alive error while encoding JSON", err)
aliveJson.Decref()
@ -420,16 +420,20 @@ func (h *Hub) aliveHandler(c *Connection, alive *DataAlive) { @@ -420,16 +420,20 @@ func (h *Hub) aliveHandler(c *Connection, alive *DataAlive) {
}
func (h *Hub) sessionsHandler(c *Connection, sessions *DataSessions) {
func (h *Hub) sessionsHandler(c *Connection, srq *DataSessionsRequest, iid string) {
reply := false
var users []*DataSession
switch sessions.TokenType {
switch srq.Type {
case "contact":
contact := &Contact{}
err := h.contacts.Decode("contactRequest", sessions.Token, contact)
err := h.contacts.Decode("contactConfirmed", srq.Token, contact)
if err != nil {
log.Println("Failed to decode incoming contact token", err, sessions.Token)
log.Println("Failed to decode incoming contact token", err, srq.Token)
return
}
if !contact.Ok {
log.Println("Ignoring contact token without Ok", contact)
return
}
// Use the userid which is not ours from the contact data.
@ -451,16 +455,16 @@ func (h *Hub) sessionsHandler(c *Connection, sessions *DataSessions) { @@ -451,16 +455,16 @@ func (h *Hub) sessionsHandler(c *Connection, sessions *DataSessions) {
return
}
// Add sessions for forein user.
sessions.Users = user.SessionsData()
reply = true
users = user.SessionsData()
default:
log.Println("Unkown incoming sessions request type", sessions.TokenType)
log.Println("Unkown incoming sessions request type", srq.Type)
}
if reply {
if users != nil {
sessions := &DataSessions{Type: "Sessions", Users: users, Sessions: srq}
sessionsJson := h.buffers.New()
encoder := json.NewEncoder(sessionsJson)
err := encoder.Encode(&DataOutgoing{From: c.Id, Data: sessions})
err := encoder.Encode(&DataOutgoing{From: c.Id, Data: sessions, Iid: iid})
if err != nil {
log.Println("Sessions error while encoding JSON", err)
sessionsJson.Decref()

14
src/app/spreed-webrtc-server/server.go

@ -68,7 +68,7 @@ func (s *Server) OnUnregister(c *Connection) { @@ -68,7 +68,7 @@ func (s *Server) OnUnregister(c *Connection) {
func (s *Server) OnText(c *Connection, b Buffer) {
//log.Printf("OnText from %d: %s\n", c.id, b)
//log.Printf("OnText from %d: %s\n", c.Id, b)
var msg DataIncoming
err := json.Unmarshal(b.Bytes(), &msg)
if err != nil {
@ -167,9 +167,9 @@ func (s *Server) OnText(c *Connection, b Buffer) { @@ -167,9 +167,9 @@ func (s *Server) OnText(c *Connection, b Buffer) {
}
}
case "Alive":
s.Alive(c, msg.Alive)
s.Alive(c, msg.Alive, msg.Iid)
case "Sessions":
s.Sessions(c, msg.Sessions)
s.Sessions(c, msg.Sessions.Sessions, msg.Iid)
default:
log.Println("OnText unhandled message type", msg.Type)
}
@ -192,15 +192,15 @@ func (s *Server) Unicast(c *Connection, to string, m interface{}) { @@ -192,15 +192,15 @@ func (s *Server) Unicast(c *Connection, to string, m interface{}) {
b.Decref()
}
func (s *Server) Alive(c *Connection, alive *DataAlive) {
func (s *Server) Alive(c *Connection, alive *DataAlive, iid string) {
c.h.aliveHandler(c, alive)
c.h.aliveHandler(c, alive, iid)
}
func (s *Server) Sessions(c *Connection, sessions *DataSessions) {
func (s *Server) Sessions(c *Connection, srq *DataSessionsRequest, iid string) {
c.h.sessionsHandler(c, sessions)
c.h.sessionsHandler(c, srq, iid)
}

2
static/js/directives/audiolevel.js

@ -44,7 +44,7 @@ define(['jquery', 'underscore'], function($, _) { @@ -44,7 +44,7 @@ define(['jquery', 'underscore'], function($, _) {
var element = $element[0];
var width = 0;
this.update = _.bind(function() {
if (this.active || width > 0) {
if (this.active || width > 0) {
if (webrtc.usermedia.audioLevel) {
width = Math.round(100 * webrtc.usermedia.audioLevel);
// Hide low volumes.

36
static/js/mediastream/api.js

@ -29,6 +29,7 @@ define(['jquery', 'underscore'], function($, _) { @@ -29,6 +29,7 @@ define(['jquery', 'underscore'], function($, _) {
this.sid = null;
this.session = {};
this.connector = connector;
this.iids= 0;
this.e = $({});
@ -74,7 +75,7 @@ define(['jquery', 'underscore'], function($, _) { @@ -74,7 +75,7 @@ define(['jquery', 'underscore'], function($, _) {
Type: type
};
payload[type] = data;
//console.log("<<<<<<<<<<<<", JSON.stringify(payload));
//console.log("<<<<<<<<<<<<", JSON.stringify(payload, null, 2));
this.connector.send(payload, noqueue);
};
@ -91,6 +92,21 @@ define(['jquery', 'underscore'], function($, _) { @@ -91,6 +92,21 @@ define(['jquery', 'underscore'], function($, _) {
return this.apply(name, obj);
};
Api.prototype.request = function(type, data, cb) {
var payload = {
Type: type
}
payload[type] = data;
if (cb) {
var iid = ""+(this.iids++);
payload.Iid = iid;
this.e.one(iid+".request", cb);
}
this.connector.send(payload);
}
// Helper hack function to send API requests to other destinations.
// Simply provide an alternative send function on the obj Object.
Api.prototype.apply = function(name, obj) {
@ -105,9 +121,16 @@ define(['jquery', 'underscore'], function($, _) { @@ -105,9 +121,16 @@ define(['jquery', 'underscore'], function($, _) {
this.last_receive = now;
this.last_receive_overdue = false;
var iid = d.Iid;
var data = d.Data;
var dataType = data.Type;
if (iid) {
// Shortcut for iid registered responses.
this.e.triggerHandler(iid+".request", [dataType, data]);
return;
}
switch (dataType) {
case "Self":
console.log("Self received", data);
@ -321,16 +344,17 @@ define(['jquery', 'underscore'], function($, _) { @@ -321,16 +344,17 @@ define(['jquery', 'underscore'], function($, _) {
return this.send("Alive", data);
};
Api.prototype.sendSessions = function(token, type) {
Api.prototype.sendSessions = function(token, type, cb) {
var data = {
Type: "Sessions",
Id: "some-random-whatever",
Token: token,
TokenType: type
Sessions: {
Type: type,
Token: token
}
}
return this.send("Sessions", data);
return this.request("Sessions", data, cb);
};

54
static/js/services/buddylist.js

@ -129,7 +129,7 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text! @@ -129,7 +129,7 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
};
// buddyList
return ["$window", "$compile", "playSound", "buddyData", "buddySession", "fastScroll", "mediaStream", "animationFrame", function($window, $compile, playSound, buddyData, buddySession, fastScroll, mediaStream, animationFrame) {
return ["$window", "$compile", "playSound", "buddyData", "buddySession", "fastScroll", "mediaStream", "animationFrame", "$q", function($window, $compile, playSound, buddyData, buddySession, fastScroll, mediaStream, animationFrame, $q) {
var buddyTemplate = $compile(templateBuddy);
var buddyActions = $compile(templateBuddyActions);
@ -158,16 +158,9 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text! @@ -158,16 +158,9 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
this.hover(buddyElement, event.type === "mouseenter" ? true : false);
}, this));
$element.on("click", ".buddy", _.bind(function(event) {
console.log("click event", event);
var buddyElement = $(event.currentTarget);
//buddyElement.scope().doDefault();
this.click(buddyElement, event.target);
}, this));
/*$element.on("click", ".fa.contact", _.bind(function(event) {
event.stopPropagation();
var buddyElement = $(event.currentTarget);
buddyElement.scope().doDefaultContact();
}, this));*/
$element.attr("data-xthreshold", "10");
$element.on("swipeleft", ".buddy", _.bind(function(event) {
event.preventDefault();
@ -658,32 +651,47 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text! @@ -658,32 +651,47 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
var scope = buddyElement.scope();
var session = scope.session;
var sessionData = session.get()
var contact = scope.contact;
var id;
if (!sessionData) {
// TODO(longsleep): Find session with help of contact.
console.log("No sessions for this buddy.", session, contact);
if (contact && contact.Token) {
mediaStream.api.sendSessions(contact.Token, "contact");
var promise = (function() {
var deferred = $q.defer();
var sessionData = session.get()
if (!sessionData) {
// Find session with help of contact.
if (contact && contact.Token) {
mediaStream.api.sendSessions(contact.Token, "contact", function(event, type, data) {
//console.log("oooooooooooooooo", type, data);
if (data.Users && data.Users.length > 0) {
var s = data.Users[0];
buddyData.set(s.Id, scope);
deferred.resolve(s.Id);
}
});
}
} else {
deferred.resolve(sessionData.Id);
}
return;
} else {
id = sessionData.Id;
}
//console.log("id", id);
return deferred.promise;
})();
switch (action) {
case "call":
scope.doCall(id);
promise.then(function(id) {
scope.doCall(id);
});
break;
case "chat":
scope.doChat(id);
promise.then(function(id) {
scope.doChat(id);
});
break;
case "contact":
if (contact) {
scope.doContactRemove(contact.Userid);
} else {
scope.doContactRequest(id);
promise.then(function(id) {
scope.doContactRequest(id);
});
}
break;
}

Loading…
Cancel
Save