Browse Source

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

pull/48/head
Simon Eisenmann 11 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 @@ -303,11 +303,7 @@ Additional types for session listing and notifications
Users (Request uses empty data)
{
"Type": "Users",
"Users": {
"Type": "Users",
"Users": {}
}
"Type": "Users"
}
Users (Response with data)
@ -385,6 +381,37 @@ User authorization and session authentication @@ -385,6 +381,37 @@ User authorization and session authentication
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
The chat is used to transfer simple messages ore more complex structures
@ -457,6 +484,48 @@ Chat messages and status information @@ -457,6 +484,48 @@ Chat messages and status information
message is shown or not. For file transfer information the message is
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
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 { @@ -92,16 +92,34 @@ type DataChat struct {
}
type DataChatMessage struct {
Mid string
Message string
Time string
NoEcho bool `json:"NoEcho,omitempty"`
Status interface{}
NoEcho bool `json:",omitempty"`
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 {
State string
Mid string
type DataFileInfo struct {
Id string `json:"id"`
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 {

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

@ -0,0 +1,30 @@ @@ -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 { @@ -83,6 +83,7 @@ type Hub struct {
realm string
tokenName string
useridRetriever func(*http.Request) (string, error)
contacts *securecookie.SecureCookie
}
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 @@ -106,6 +107,8 @@ func NewHub(version string, config *Config, sessionSecret, turnSecret, realm str
h.buffers = NewBufferCache(1024, bytes.MinRead)
h.buddyImages = NewImageCache()
h.tokenName = fmt.Sprintf("token@%s", h.realm)
h.contacts = securecookie.New(h.sessionSecret, nil)
h.contacts.MaxAge(0)
return h
}
@ -423,3 +426,79 @@ func (h *Hub) sessiontokenHandler(st *SessionToken) (string, error) { @@ -423,3 +426,79 @@ func (h *Hub) sessiontokenHandler(st *SessionToken) (string, error) {
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) { @@ -137,11 +137,18 @@ func (s *Server) OnText(c *Connection, b Buffer) {
s.Broadcast(c, msg.Chat)
}
} 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)
s.Unicast(c, msg.Chat.To, msg.Chat)
if msg.Chat.Chat.Mid != "" {
// 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":
@ -194,6 +201,12 @@ func (s *Server) UpdateSession(c *Connection, su *SessionUpdate) uint64 { @@ -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{}) {
b := c.h.buffers.New()

Loading…
Cancel
Save