package srtp
import (
"errors"
"io"
"net"
"sync"
"time"
"github.com/pion/logging"
"github.com/pion/transport/v3/packetio"
)
type streamSession interface {
Close() error
write([]byte ) (int , error )
decrypt([]byte ) error
}
type session struct {
localContextMutex sync .Mutex
localContext, remoteContext *Context
localOptions, remoteOptions []ContextOption
newStream chan readStream
acceptStreamTimeout time .Time
started chan interface {}
closed chan interface {}
readStreamsClosed bool
readStreams map [uint32 ]readStream
readStreamsLock sync .Mutex
log logging .LeveledLogger
bufferFactory func (packetType packetio .BufferPacketType , ssrc uint32 ) io .ReadWriteCloser
nextConn net .Conn
}
type Config struct {
Keys SessionKeys
Profile ProtectionProfile
BufferFactory func (packetType packetio .BufferPacketType , ssrc uint32 ) io .ReadWriteCloser
LoggerFactory logging .LoggerFactory
AcceptStreamTimeout time .Time
LocalOptions, RemoteOptions []ContextOption
}
type SessionKeys struct {
LocalMasterKey []byte
LocalMasterSalt []byte
RemoteMasterKey []byte
RemoteMasterSalt []byte
}
func (s *session ) getOrCreateReadStream (ssrc uint32 , child streamSession , proto func () readStream ) (readStream , bool ) {
s .readStreamsLock .Lock ()
defer s .readStreamsLock .Unlock ()
if s .readStreamsClosed {
return nil , false
}
rStream , ok := s .readStreams [ssrc ]
if ok {
return rStream , false
}
rStream = proto ()
if err := rStream .init (child , ssrc ); err != nil {
return nil , false
}
s .readStreams [ssrc ] = rStream
return rStream , true
}
func (s *session ) removeReadStream (ssrc uint32 ) {
s .readStreamsLock .Lock ()
defer s .readStreamsLock .Unlock ()
if s .readStreamsClosed {
return
}
delete (s .readStreams , ssrc )
}
func (s *session ) close () error {
if s .nextConn == nil {
return nil
} else if err := s .nextConn .Close (); err != nil {
return err
}
<-s .closed
return nil
}
func (s *session ) start (
localMasterKey , localMasterSalt , remoteMasterKey , remoteMasterSalt []byte ,
profile ProtectionProfile ,
child streamSession ,
) error {
var err error
s .localContext , err = CreateContext (localMasterKey , localMasterSalt , profile , s .localOptions ...)
if err != nil {
return err
}
s .remoteContext , err = CreateContext (remoteMasterKey , remoteMasterSalt , profile , s .remoteOptions ...)
if err != nil {
return err
}
if err = s .nextConn .SetReadDeadline (s .acceptStreamTimeout ); err != nil {
return err
}
go func () {
defer func () {
close (s .newStream )
s .readStreamsLock .Lock ()
s .readStreamsClosed = true
s .readStreamsLock .Unlock ()
close (s .closed )
}()
b := make ([]byte , 8192 )
for {
var i int
i , err = s .nextConn .Read (b )
if err != nil {
if !errors .Is (err , io .EOF ) {
s .log .Error (err .Error())
}
return
}
if err = child .decrypt (b [:i ]); err != nil {
s .log .Info (err .Error())
}
}
}()
close (s .started )
return nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .