Browse Source

Defined and implemented contact request/response protocol and data structure.

pull/48/head
Simon Eisenmann 12 years ago committed by Simon Eisenmann
parent
commit
ea91cbd8ca
  1. 79
      doc/CHANNELING-API.txt
  2. 30
      src/app/spreed-webrtc-server/channeling.go
  3. 30
      src/app/spreed-webrtc-server/contact.go
  4. 79
      src/app/spreed-webrtc-server/hub.go
  5. 15
      src/app/spreed-webrtc-server/server.go

79
doc/CHANNELING-API.txt

@ -303,11 +303,7 @@ Additional types for session listing and notifications
Users (Request uses empty data) Users (Request uses empty data)
{ {
"Type": "Users", "Type": "Users"
"Users": {
"Type": "Users",
"Users": {}
}
} }
Users (Response with data) Users (Response with data)
@ -385,6 +381,37 @@ User authorization and session authentication
the session (disconnect) and forget the token. the session (disconnect) and forget the token.
Information retrieval
Sessions (Request uses Id, Token and Type)
{
"Type": "Sessions",
"Sessions": {
"Id": "Client generated request ID",
"Token": "Request token",
"TokenType": "Token type"
}
}
Valid known token types are: "contact", "token".
Sesions (Response with Id, Token and Type from request and
populated Session list).
{
"Type": "Sessions",
"Sessions": {
"Id": "ID as from request",
"Token": "Token as from request",
"TokenType": "Type as from request",
"Sessions": [
"1", "2", "3", ...
]
}
}
Chat messages and status information Chat messages and status information
The chat is used to transfer simple messages ore more complex structures The chat is used to transfer simple messages ore more complex structures
@ -457,6 +484,48 @@ Chat messages and status information
message is shown or not. For file transfer information the message is message is shown or not. For file transfer information the message is
always "File". always "File".
Chat with contact request/confirm information
Request to create a contact token with Id.
{
"Message": "Some message",
"Time": "2013-11-20T16:28:42+01:00",
"Status": {
"ContactRequest": {
"Id": "client-generated-id"
}
}
}
Reply with success (Sever generates and inserts token).
{
"Message": "Some response message",
"Time": "2013-11-20T16:28:59+01:00",
"Status": {
"ContactRequest": {
"Id": "request-id",
"Success": true,
"Token": "server-generated-token-on-success"
}
}
}
Or reject (no reply is also possible).
{
"Message": "Some response message",
"Time": "2013-11-20T16:28:59+01:00",
"Status": {
"ContactRequest": {
"Id": "request-id",
"Success": false
}
}
}
Chat message deliver status extensions Chat message deliver status extensions
Send chat messages as normal, but add the "Mid" field which is a Send chat messages as normal, but add the "Mid" field which is a

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

@ -92,16 +92,34 @@ type DataChat struct {
} }
type DataChatMessage struct { type DataChatMessage struct {
Mid string
Message string Message string
Time string Time string
NoEcho bool `json:"NoEcho,omitempty"` NoEcho bool `json:",omitempty"`
Status interface{} Mid string `json:",omitempty"`
Status *DataChatStatus
}
type DataChatStatus struct {
Typing string `json:",omitempty"`
State string `json:",omitempty"`
Mid string `json:",omitempty"`
SeenMids []string `json:",omitempty"`
FileInfo *DataFileInfo `json:",omitempty"`
ContactRequest *DataContactRequest `json:",omitempty"`
} }
type DataChatMessageStatus struct { type DataFileInfo struct {
State string Id string `json:"id"`
Mid string Chunks uint64 `json:"chunks"`
Name string `json:"name"`
Size uint64 `json:"size"`
Type string `json:"type"`
}
type DataContactRequest struct {
Id string
Success bool
Token string `json:",omitempty"`
} }
type DataIncoming struct { type DataIncoming struct {

30
src/app/spreed-webrtc-server/contact.go

@ -0,0 +1,30 @@
/*
* Spreed WebRTC.
* Copyright (C) 2013-2014 struktur AG
*
* This file is part of Spreed WebRTC.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package main
import ()
type Contact struct {
a string
b string
ok bool
}

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

@ -83,6 +83,7 @@ type Hub struct {
realm string realm string
tokenName string tokenName string
useridRetriever func(*http.Request) (string, error) useridRetriever func(*http.Request) (string, error)
contacts *securecookie.SecureCookie
} }
func NewHub(version string, config *Config, sessionSecret, turnSecret, realm string) *Hub { func NewHub(version string, config *Config, sessionSecret, turnSecret, realm string) *Hub {
@ -106,6 +107,8 @@ func NewHub(version string, config *Config, sessionSecret, turnSecret, realm str
h.buffers = NewBufferCache(1024, bytes.MinRead) h.buffers = NewBufferCache(1024, bytes.MinRead)
h.buddyImages = NewImageCache() h.buddyImages = NewImageCache()
h.tokenName = fmt.Sprintf("token@%s", h.realm) h.tokenName = fmt.Sprintf("token@%s", h.realm)
h.contacts = securecookie.New(h.sessionSecret, nil)
h.contacts.MaxAge(0)
return h return h
} }
@ -423,3 +426,79 @@ func (h *Hub) sessiontokenHandler(st *SessionToken) (string, error) {
return nonce, nil return nonce, nil
} }
func (h *Hub) contactrequestHandler(c *Connection, to string, cr *DataContactRequest) error {
var err error
if cr.Success {
// Client replied with success.
// Decode Token and make sure c.Session.Userid and the to Session.UserId are a match.
contact := &Contact{}
err = h.contacts.Decode("contactRequest", cr.Token, contact)
if err != nil {
return err
}
if contact.ok {
return errors.New("received success with ok state set")
}
bSessionData := c.Session.Data()
if bSessionData.Userid == "" {
return errors.New("no userid")
}
h.mutex.RLock()
aSession, ok := h.sessionTable[to]
h.mutex.RUnlock()
if !ok {
return errors.New("unknown to session for confirm")
}
aSessionData := aSession.Data()
if aSessionData.Userid == "" {
return errors.New("to has no userid for confirm")
}
if aSessionData.Userid != contact.a {
return errors.New("contact mismatch in a")
}
if bSessionData.Userid != contact.b {
return errors.New("contact mismatch in b")
}
contact.ok = true
cr.Token, err = h.contacts.Encode("contactConfirmed", contact)
} else {
if cr.Token != "" {
// Client replied with no success.
// Decode Token.
contact := &Contact{}
err = h.contacts.Decode("contactRequest", cr.Token, contact)
if err != nil {
return err
}
// Remove token.
cr.Token = ""
} else {
// New request.
// Create Token with flag and c.Session.Userid and the to Session.Userid.
aSessionData := c.Session.Data()
if aSessionData.Userid == "" {
return errors.New("no userid")
}
h.mutex.RLock()
bSession, ok := h.sessionTable[to]
h.mutex.RUnlock()
if !ok {
return errors.New("unknown to session")
}
bSessionData := bSession.Data()
if bSessionData.Userid == "" {
return errors.New("to has no userid")
}
// Create object.
contact := &Contact{aSessionData.Userid, bSessionData.Userid, false}
// Serialize.
cr.Token, err = h.contacts.Encode("contactRequest", contact)
}
}
return err
}

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

@ -137,11 +137,18 @@ func (s *Server) OnText(c *Connection, b Buffer) {
s.Broadcast(c, msg.Chat) s.Broadcast(c, msg.Chat)
} }
} else { } else {
if msg.Chat.Chat.Status.ContactRequest != nil {
err = s.ContactRequest(c, msg.Chat.To, msg.Chat.Chat.Status.ContactRequest)
if err != nil {
log.Println("Ignoring invalid contact request.", err)
return
}
}
atomic.AddUint64(&c.h.unicastChatMessages, 1) atomic.AddUint64(&c.h.unicastChatMessages, 1)
s.Unicast(c, msg.Chat.To, msg.Chat) s.Unicast(c, msg.Chat.To, msg.Chat)
if msg.Chat.Chat.Mid != "" { if msg.Chat.Chat.Mid != "" {
// Send out delivery confirmation status chat message. // Send out delivery confirmation status chat message.
s.Unicast(c, c.Id, &DataChat{To: msg.Chat.To, Type: "Chat", Chat: &DataChatMessage{Mid: msg.Chat.Chat.Mid, Status: &DataChatMessageStatus{State: "sent"}}}) s.Unicast(c, c.Id, &DataChat{To: msg.Chat.To, Type: "Chat", Chat: &DataChatMessage{Mid: msg.Chat.Chat.Mid, Status: &DataChatStatus{State: "sent"}}})
} }
} }
case "Conference": case "Conference":
@ -194,6 +201,12 @@ func (s *Server) UpdateSession(c *Connection, su *SessionUpdate) uint64 {
} }
func (s *Server) ContactRequest(c *Connection, to string, cr *DataContactRequest) (err error) {
return c.h.contactrequestHandler(c, to, cr)
}
func (s *Server) Broadcast(c *Connection, m interface{}) { func (s *Server) Broadcast(c *Connection, m interface{}) {
b := c.h.buffers.New() b := c.h.buffers.New()

Loading…
Cancel
Save