WebRTC audio/video call and conferencing server.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

190 lines
4.1 KiB

/*
* Spreed WebRTC.
* Copyright (C) 2013-2015 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 channelling
import (
"bytes"
"encoding/json"
"errors"
"log"
"sync"
"time"
"github.com/strukturag/spreed-webrtc/go/buffercache"
)
type PipelineFeedLine struct {
Seq int
Msg *DataOutgoing
}
type Pipeline struct {
PipelineManager PipelineManager
mutex sync.RWMutex
namespace string
id string
from *Session
expires *time.Time
data []*DataOutgoing
sink Sink
}
func NewPipeline(manager PipelineManager,
namespace string,
id string,
from *Session,
duration time.Duration) *Pipeline {
pipeline := &Pipeline{
PipelineManager: manager,
namespace: namespace,
id: id,
from: from,
}
pipeline.Refresh(duration)
return pipeline
}
func (pipeline *Pipeline) GetID() string {
return pipeline.id
}
func (pipeline *Pipeline) Refresh(duration time.Duration) {
pipeline.mutex.Lock()
expiration := time.Now().Add(duration)
pipeline.expires = &expiration
pipeline.mutex.Unlock()
}
func (pipeline *Pipeline) Add(msg *DataOutgoing) *Pipeline {
pipeline.mutex.Lock()
pipeline.data = append(pipeline.data, msg)
pipeline.mutex.Unlock()
return pipeline
}
func (pipeline *Pipeline) Send(b buffercache.Buffer) {
// noop for now
}
func (pipeline *Pipeline) Index() uint64 {
return 0
}
func (pipeline *Pipeline) Close() {
pipeline.mutex.Lock()
pipeline.expires = nil
if pipeline.sink != nil {
pipeline.sink.Close()
pipeline.sink = nil
}
pipeline.mutex.Unlock()
}
func (pipeline *Pipeline) Expired() bool {
var expired bool
pipeline.mutex.RLock()
if pipeline.expires == nil {
expired = true
} else {
expired = pipeline.expires.Before(time.Now())
}
pipeline.mutex.RUnlock()
return expired
}
func (pipeline *Pipeline) Session() *Session {
return pipeline.from
}
func (pipeline *Pipeline) JSONFeed(since, limit int) ([]byte, error) {
pipeline.mutex.RLock()
var lineRaw []byte
var line *PipelineFeedLine
var buffer bytes.Buffer
var err error
data := pipeline.data[since:]
count := 0
for seq, msg := range data {
line = &PipelineFeedLine{
Seq: seq + since,
Msg: msg,
}
lineRaw, err = json.Marshal(line)
if err != nil {
return nil, err
}
buffer.Write(lineRaw)
buffer.WriteString("\n")
count++
if limit > 0 && count >= limit {
break
}
}
pipeline.mutex.RUnlock()
return buffer.Bytes(), nil
}
func (pipeline *Pipeline) FlushOutgoing(hub Hub, client *Client, to string, outgoing *DataOutgoing) bool {
pipeline.mutex.RLock()
log.Println("Flush outgoing via pipeline", to, client == nil)
if client == nil {
sink := pipeline.sink
pipeline.mutex.RUnlock()
pipeline.Add(outgoing)
// It is possible to retrieve the userid for fake sessions here.
if session, found := pipeline.PipelineManager.GetSession(to); found {
log.Println("Pipeline found userid via manager", session.Userid())
}
if sink == nil {
return true
}
// Sink it.
pipeline.sink.Write(outgoing)
return true
}
pipeline.mutex.RUnlock()
return false
}
func (pipeline *Pipeline) Attach(sink Sink) error {
pipeline.mutex.Lock()
defer pipeline.mutex.Unlock()
if pipeline.sink != nil {
return errors.New("pipeline already attached to sink")
}
pipeline.sink = sink
// Sink existing data first.
log.Println("Attach sink to pipeline", pipeline.id)
for _, msg := range pipeline.data {
sink.Write(msg)
}
return nil
}