Browse Source

Implemented room types.

pull/192/head
Simon Eisenmann 10 years ago
parent
commit
0a44f596bf
  1. 8
      src/app/spreed-webrtc-server/channelling.go
  2. 8
      src/app/spreed-webrtc-server/channelling_api.go
  3. 38
      src/app/spreed-webrtc-server/room_manager.go
  4. 24
      src/app/spreed-webrtc-server/roomworker.go
  5. 5
      src/app/spreed-webrtc-server/session.go

8
src/app/spreed-webrtc-server/channelling.go

@ -42,7 +42,9 @@ type DataRoomCredentials struct {
type DataHello struct { type DataHello struct {
Version string Version string
Ua string Ua string
Id string Id string // Compatibility with old clients.
Name string // Room name.
Type string // Room type.
Credentials *DataRoomCredentials Credentials *DataRoomCredentials
} }
@ -53,8 +55,8 @@ type DataWelcome struct {
} }
type DataRoom struct { type DataRoom struct {
Type string Type string // Room type.
Name string Name string // Room name.
Credentials *DataRoomCredentials Credentials *DataRoomCredentials
} }

8
src/app/spreed-webrtc-server/channelling_api.go

@ -189,7 +189,13 @@ func (api *channellingAPI) HandleHello(session *Session, hello *DataHello, sende
// TODO(longsleep): Filter room id and user agent. // TODO(longsleep): Filter room id and user agent.
session.Update(&SessionUpdate{Types: []string{"Ua"}, Ua: hello.Ua}) session.Update(&SessionUpdate{Types: []string{"Ua"}, Ua: hello.Ua})
room, err := session.JoinRoom(hello.Id, hello.Credentials, sender) // Compatibily for old clients.
roomName := hello.Name
if roomName == "" {
roomName = hello.Id
}
room, err := session.JoinRoom(roomName, hello.Type, hello.Credentials, sender)
if err != nil { if err != nil {
return nil, err return nil, err
} }

38
src/app/spreed-webrtc-server/room_manager.go

@ -22,15 +22,17 @@
package main package main
import ( import (
"fmt"
"log" "log"
"sync" "sync"
) )
type RoomStatusManager interface { type RoomStatusManager interface {
RoomUsers(*Session) []*DataSession RoomUsers(*Session) []*DataSession
JoinRoom(roomID string, credentials *DataRoomCredentials, session *Session, sessionAuthenticated bool, sender Sender) (*DataRoom, error) JoinRoom(roomID, roomName, roomType string, credentials *DataRoomCredentials, session *Session, sessionAuthenticated bool, sender Sender) (*DataRoom, error)
LeaveRoom(roomID, sessionID string) LeaveRoom(roomID, sessionID string)
UpdateRoom(*Session, *DataRoom) (*DataRoom, error) UpdateRoom(*Session, *DataRoom) (*DataRoom, error)
MakeRoomID(roomName, roomType string) string
} }
type Broadcaster interface { type Broadcaster interface {
@ -52,15 +54,24 @@ type roomManager struct {
*Config *Config
OutgoingEncoder OutgoingEncoder
roomTable map[string]RoomWorker roomTable map[string]RoomWorker
globalRoomID string
defaultRoomID string
roomTypeDefault string
} }
func NewRoomManager(config *Config, encoder OutgoingEncoder) RoomManager { func NewRoomManager(config *Config, encoder OutgoingEncoder) RoomManager {
return &roomManager{ rm := &roomManager{
sync.RWMutex{}, sync.RWMutex{},
config, config,
encoder, encoder,
make(map[string]RoomWorker), make(map[string]RoomWorker),
"",
"",
"Room",
} }
rm.globalRoomID = rm.MakeRoomID(config.globalRoomID, "")
rm.defaultRoomID = rm.MakeRoomID("", "")
return rm
} }
func (rooms *roomManager) RoomUsers(session *Session) []*DataSession { func (rooms *roomManager) RoomUsers(session *Session) []*DataSession {
@ -71,12 +82,12 @@ func (rooms *roomManager) RoomUsers(session *Session) []*DataSession {
return []*DataSession{} return []*DataSession{}
} }
func (rooms *roomManager) JoinRoom(roomID string, credentials *DataRoomCredentials, session *Session, sessionAuthenticated bool, sender Sender) (*DataRoom, error) { func (rooms *roomManager) JoinRoom(roomID, roomName, roomType string, credentials *DataRoomCredentials, session *Session, sessionAuthenticated bool, sender Sender) (*DataRoom, error) {
if roomID == "" && !rooms.DefaultRoomEnabled { if roomID == rooms.defaultRoomID && !rooms.DefaultRoomEnabled {
return nil, NewDataError("default_room_disabled", "The default room is not enabled") return nil, NewDataError("default_room_disabled", "The default room is not enabled")
} }
roomWorker, err := rooms.GetOrCreate(roomID, credentials, sessionAuthenticated) roomWorker, err := rooms.GetOrCreate(roomID, roomName, roomType, credentials, sessionAuthenticated)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -91,12 +102,10 @@ func (rooms *roomManager) LeaveRoom(roomID, sessionID string) {
} }
func (rooms *roomManager) UpdateRoom(session *Session, room *DataRoom) (*DataRoom, error) { func (rooms *roomManager) UpdateRoom(session *Session, room *DataRoom) (*DataRoom, error) {
if !session.Hello || session.Roomid != room.Name { roomID := rooms.MakeRoomID(room.Name, room.Type)
if !session.Hello || session.Roomid != roomID {
return nil, NewDataError("not_in_room", "Cannot update other rooms") return nil, NewDataError("not_in_room", "Cannot update other rooms")
} }
// XXX(lcooper): We'll process and send documents without this field
// correctly, however clients cannot not handle it currently.
room.Type = "Room"
if roomWorker, ok := rooms.Get(session.Roomid); ok { if roomWorker, ok := rooms.Get(session.Roomid); ok {
return room, roomWorker.Update(room) return room, roomWorker.Update(room)
} }
@ -145,7 +154,7 @@ func (rooms *roomManager) Get(roomID string) (room RoomWorker, ok bool) {
return return
} }
func (rooms *roomManager) GetOrCreate(roomID string, credentials *DataRoomCredentials, sessionAuthenticated bool) (RoomWorker, error) { func (rooms *roomManager) GetOrCreate(roomID, roomName, roomType string, credentials *DataRoomCredentials, sessionAuthenticated bool) (RoomWorker, error) {
if rooms.AuthorizeRoomJoin && rooms.UsersEnabled && !sessionAuthenticated { if rooms.AuthorizeRoomJoin && rooms.UsersEnabled && !sessionAuthenticated {
return nil, NewDataError("room_join_requires_account", "Room join requires a user account") return nil, NewDataError("room_join_requires_account", "Room join requires a user account")
} }
@ -167,7 +176,7 @@ func (rooms *roomManager) GetOrCreate(roomID string, credentials *DataRoomCreden
return nil, NewDataError("room_join_requires_account", "Room creation requires a user account") return nil, NewDataError("room_join_requires_account", "Room creation requires a user account")
} }
room := NewRoomWorker(rooms, roomID, credentials) room := NewRoomWorker(rooms, roomID, roomName, roomType, credentials)
rooms.roomTable[roomID] = room rooms.roomTable[roomID] = room
rooms.Unlock() rooms.Unlock()
go func() { go func() {
@ -196,3 +205,10 @@ func (rooms *roomManager) GlobalUsers() []*roomUser {
rooms.RUnlock() rooms.RUnlock()
return make([]*roomUser, 0) return make([]*roomUser, 0)
} }
func (rooms *roomManager) MakeRoomID(roomName, roomType string) string {
if roomType == "" {
roomType = rooms.roomTypeDefault
}
return fmt.Sprintf("%s:%s", roomType, roomName)
}

24
src/app/spreed-webrtc-server/roomworker.go

@ -56,7 +56,9 @@ type roomWorker struct {
mutex sync.RWMutex mutex sync.RWMutex
// Metadata. // Metadata.
Id string id string
Name string
Type string
credentials *DataRoomCredentials credentials *DataRoomCredentials
} }
@ -65,13 +67,15 @@ type roomUser struct {
Sender Sender
} }
func NewRoomWorker(manager *roomManager, id string, credentials *DataRoomCredentials) RoomWorker { func NewRoomWorker(manager *roomManager, roomID, roomName, roomType string, credentials *DataRoomCredentials) RoomWorker {
log.Printf("Creating worker for room '%s'\n", id) log.Printf("Creating worker for room '%s'\n", roomID)
r := &roomWorker{ r := &roomWorker{
manager: manager, manager: manager,
Id: id, id: roomID,
Name: roomName,
Type: roomType,
workers: make(chan func(), roomMaxWorkers), workers: make(chan func(), roomMaxWorkers),
expired: make(chan bool), expired: make(chan bool),
users: make(map[string]*roomUser), users: make(map[string]*roomUser),
@ -107,7 +111,7 @@ L:
if len(r.users) == 0 { if len(r.users) == 0 {
// Cleanup room when it is empty. // Cleanup room when it is empty.
r.mutex.RUnlock() r.mutex.RUnlock()
log.Printf("Room worker not in use - cleaning up '%s'\n", r.Id) log.Printf("Room worker not in use - cleaning up '%s'\n", r.id)
break L break L
} else { } else {
r.mutex.RUnlock() r.mutex.RUnlock()
@ -149,7 +153,7 @@ func (r *roomWorker) Run(f func()) bool {
case r.workers <- f: case r.workers <- f:
return true return true
default: default:
log.Printf("Room worker channel full or closed '%s'\n", r.Id) log.Printf("Room worker channel full or closed '%s'\n", r.id)
return false return false
} }
@ -159,6 +163,10 @@ func (r *roomWorker) Update(room *DataRoom) error {
fault := make(chan error, 1) fault := make(chan error, 1)
worker := func() { worker := func() {
r.mutex.Lock() r.mutex.Lock()
// Enforce room type and name.
room.Type = r.Type
room.Name = r.Name
// Update credentials.
if room.Credentials != nil { if room.Credentials != nil {
if len(room.Credentials.PIN) > 0 { if len(room.Credentials.PIN) > 0 {
r.credentials = room.Credentials r.credentials = room.Credentials
@ -184,7 +192,7 @@ func (r *roomWorker) GetUsers() []*DataSession {
session.Type = "Online" session.Type = "Online"
sl = append(sl, session) sl = append(sl, session)
if len(sl) > maxUsersLength { if len(sl) > maxUsersLength {
log.Println("Limiting users response length in channel", r.Id) log.Println("Limiting users response length in channel", r.id)
return false return false
} }
} }
@ -264,7 +272,7 @@ func (r *roomWorker) Join(credentials *DataRoomCredentials, session *Session, se
r.users[session.Id] = &roomUser{session, sender} r.users[session.Id] = &roomUser{session, sender}
// NOTE(lcooper): Needs to be a copy, else we risk races with // NOTE(lcooper): Needs to be a copy, else we risk races with
// a subsequent modification of room properties. // a subsequent modification of room properties.
result := joinResult{&DataRoom{Name: r.Id}, nil} result := joinResult{&DataRoom{Name: r.Name, Type: r.Type}, nil}
r.mutex.Unlock() r.mutex.Unlock()
results <- result results <- result
} }

5
src/app/spreed-webrtc-server/session.go

@ -116,7 +116,8 @@ func (s *Session) RemoveSubscriber(id string) {
s.mutex.Unlock() s.mutex.Unlock()
} }
func (s *Session) JoinRoom(roomID string, credentials *DataRoomCredentials, sender Sender) (*DataRoom, error) { func (s *Session) JoinRoom(roomName, roomType string, credentials *DataRoomCredentials, sender Sender) (*DataRoom, error) {
roomID := s.RoomStatusManager.MakeRoomID(roomName, roomType)
s.mutex.Lock() s.mutex.Lock()
defer s.mutex.Unlock() defer s.mutex.Unlock()
@ -133,7 +134,7 @@ func (s *Session) JoinRoom(roomID string, credentials *DataRoomCredentials, send
}) })
} }
room, err := s.RoomStatusManager.JoinRoom(roomID, credentials, s, s.authenticated(), sender) room, err := s.RoomStatusManager.JoinRoom(roomID, roomName, roomType, credentials, s, s.authenticated(), sender)
if err == nil { if err == nil {
s.Hello = true s.Hello = true
s.Roomid = roomID s.Roomid = roomID

Loading…
Cancel
Save