mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
1. Add live benchmark support in srs-bench, which only connects and disconnects without any media transport, to test source creation and disposal and verify source memory leaks. 2. SmartPtr: Support cleanup of HTTP-FLV stream. Unregister the HTTP-FLV handler for the pattern and clean up the objects and resources. 3. Support benchmarking RTMP/SRT with srs-bench by integrating the gosrt and oryx RTMP libraries. 4. Refine SRT and RTC sources by using a timer to clean up the sources, following the same strategy as the Live source. --------- Co-authored-by: Haibo Chen <495810242@qq.com> Co-authored-by: Jacob Su <suzp1984@gmail.com>
191 lines
6.5 KiB
Go
191 lines
6.5 KiB
Go
package srtgo
|
|
|
|
// #cgo LDFLAGS: -lsrt
|
|
// #include <srt/srt.h>
|
|
import "C"
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
const (
|
|
transTypeLive = 0
|
|
transTypeFile = 1
|
|
)
|
|
|
|
const (
|
|
tInteger32 = 0
|
|
tInteger64 = 1
|
|
tString = 2
|
|
tBoolean = 3
|
|
tTransType = 4
|
|
|
|
SRTO_TRANSTYPE = C.SRTO_TRANSTYPE
|
|
SRTO_MAXBW = C.SRTO_MAXBW
|
|
SRTO_PBKEYLEN = C.SRTO_PBKEYLEN
|
|
SRTO_PASSPHRASE = C.SRTO_PASSPHRASE
|
|
SRTO_MSS = C.SRTO_MSS
|
|
SRTO_FC = C.SRTO_FC
|
|
SRTO_SNDBUF = C.SRTO_SNDBUF
|
|
SRTO_RCVBUF = C.SRTO_RCVBUF
|
|
SRTO_IPTTL = C.SRTO_IPTTL
|
|
SRTO_IPTOS = C.SRTO_IPTOS
|
|
SRTO_INPUTBW = C.SRTO_INPUTBW
|
|
SRTO_OHEADBW = C.SRTO_OHEADBW
|
|
SRTO_LATENCY = C.SRTO_LATENCY
|
|
SRTO_TSBPDMODE = C.SRTO_TSBPDMODE
|
|
SRTO_TLPKTDROP = C.SRTO_TLPKTDROP
|
|
SRTO_SNDDROPDELAY = C.SRTO_SNDDROPDELAY
|
|
SRTO_NAKREPORT = C.SRTO_NAKREPORT
|
|
SRTO_CONNTIMEO = C.SRTO_CONNTIMEO
|
|
SRTO_LOSSMAXTTL = C.SRTO_LOSSMAXTTL
|
|
SRTO_RCVLATENCY = C.SRTO_RCVLATENCY
|
|
SRTO_PEERLATENCY = C.SRTO_PEERLATENCY
|
|
SRTO_MINVERSION = C.SRTO_MINVERSION
|
|
SRTO_STREAMID = C.SRTO_STREAMID
|
|
SRTO_CONGESTION = C.SRTO_CONGESTION
|
|
SRTO_MESSAGEAPI = C.SRTO_MESSAGEAPI
|
|
SRTO_PAYLOADSIZE = C.SRTO_PAYLOADSIZE
|
|
SRTO_KMREFRESHRATE = C.SRTO_KMREFRESHRATE
|
|
SRTO_KMPREANNOUNCE = C.SRTO_KMPREANNOUNCE
|
|
SRTO_ENFORCEDENCRYPTION = C.SRTO_ENFORCEDENCRYPTION
|
|
SRTO_PEERIDLETIMEO = C.SRTO_PEERIDLETIMEO
|
|
SRTO_PACKETFILTER = C.SRTO_PACKETFILTER
|
|
SRTO_STATE = C.SRTO_STATE
|
|
)
|
|
|
|
type socketOption struct {
|
|
name string
|
|
level int
|
|
option int
|
|
binding int
|
|
dataType int
|
|
}
|
|
|
|
// List of possible srt socket options
|
|
var SocketOptions = []socketOption{
|
|
{"transtype", 0, SRTO_TRANSTYPE, bindingPre, tTransType},
|
|
{"maxbw", 0, SRTO_MAXBW, bindingPre, tInteger64},
|
|
{"pbkeylen", 0, SRTO_PBKEYLEN, bindingPre, tInteger32},
|
|
{"passphrase", 0, SRTO_PASSPHRASE, bindingPre, tString},
|
|
{"mss", 0, SRTO_MSS, bindingPre, tInteger32},
|
|
{"fc", 0, SRTO_FC, bindingPre, tInteger32},
|
|
{"sndbuf", 0, SRTO_SNDBUF, bindingPre, tInteger32},
|
|
{"rcvbuf", 0, SRTO_RCVBUF, bindingPre, tInteger32},
|
|
{"ipttl", 0, SRTO_IPTTL, bindingPre, tInteger32},
|
|
{"iptos", 0, SRTO_IPTOS, bindingPre, tInteger32},
|
|
{"inputbw", 0, SRTO_INPUTBW, bindingPost, tInteger64},
|
|
{"oheadbw", 0, SRTO_OHEADBW, bindingPost, tInteger32},
|
|
{"latency", 0, SRTO_LATENCY, bindingPre, tInteger32},
|
|
{"tsbpdmode", 0, SRTO_TSBPDMODE, bindingPre, tBoolean},
|
|
{"tlpktdrop", 0, SRTO_TLPKTDROP, bindingPre, tBoolean},
|
|
{"snddropdelay", 0, SRTO_SNDDROPDELAY, bindingPost, tInteger32},
|
|
{"nakreport", 0, SRTO_NAKREPORT, bindingPre, tBoolean},
|
|
{"conntimeo", 0, SRTO_CONNTIMEO, bindingPre, tInteger32},
|
|
{"lossmaxttl", 0, SRTO_LOSSMAXTTL, bindingPre, tInteger32},
|
|
{"rcvlatency", 0, SRTO_RCVLATENCY, bindingPre, tInteger32},
|
|
{"peerlatency", 0, SRTO_PEERLATENCY, bindingPre, tInteger32},
|
|
{"minversion", 0, SRTO_MINVERSION, bindingPre, tInteger32},
|
|
{"streamid", 0, SRTO_STREAMID, bindingPre, tString},
|
|
{"congestion", 0, SRTO_CONGESTION, bindingPre, tString},
|
|
{"messageapi", 0, SRTO_MESSAGEAPI, bindingPre, tBoolean},
|
|
{"payloadsize", 0, SRTO_PAYLOADSIZE, bindingPre, tInteger32},
|
|
{"kmrefreshrate", 0, SRTO_KMREFRESHRATE, bindingPre, tInteger32},
|
|
{"kmpreannounce", 0, SRTO_KMPREANNOUNCE, bindingPre, tInteger32},
|
|
{"enforcedencryption", 0, SRTO_ENFORCEDENCRYPTION, bindingPre, tBoolean},
|
|
{"peeridletimeo", 0, SRTO_PEERIDLETIMEO, bindingPre, tInteger32},
|
|
{"packetfilter", 0, SRTO_PACKETFILTER, bindingPre, tString},
|
|
}
|
|
|
|
func setSocketLingerOption(s C.int, li int32) error {
|
|
var lin syscall.Linger
|
|
lin.Linger = li
|
|
if lin.Linger > 0 {
|
|
lin.Onoff = 1
|
|
} else {
|
|
lin.Onoff = 0
|
|
}
|
|
res := C.srt_setsockopt(s, bindingPre, C.SRTO_LINGER, unsafe.Pointer(&lin), C.int(unsafe.Sizeof(lin)))
|
|
if res == SRT_ERROR {
|
|
return errors.New("failed to set linger")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getSocketLingerOption(s *SrtSocket) (int32, error) {
|
|
var lin syscall.Linger
|
|
size := int(unsafe.Sizeof(lin))
|
|
err := s.getSockOpt(C.SRTO_LINGER, unsafe.Pointer(&lin), &size)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if lin.Onoff == 0 {
|
|
return 0, nil
|
|
}
|
|
return lin.Linger, nil
|
|
}
|
|
|
|
// Set socket options for SRT
|
|
func setSocketOptions(s C.int, binding int, options map[string]string) error {
|
|
for _, so := range SocketOptions {
|
|
if val, ok := options[so.name]; ok {
|
|
if so.binding == binding {
|
|
if so.dataType == tInteger32 {
|
|
v, err := strconv.Atoi(val)
|
|
v32 := int32(v)
|
|
if err == nil {
|
|
result := C.srt_setsockflag(s, C.SRT_SOCKOPT(so.option), unsafe.Pointer(&v32), C.int32_t(unsafe.Sizeof(v32)))
|
|
if result == -1 {
|
|
return fmt.Errorf("warning - error setting option %s to %s, %w", so.name, val, srtGetAndClearError())
|
|
}
|
|
}
|
|
} else if so.dataType == tInteger64 {
|
|
v, err := strconv.ParseInt(val, 10, 64)
|
|
if err == nil {
|
|
result := C.srt_setsockflag(s, C.SRT_SOCKOPT(so.option), unsafe.Pointer(&v), C.int32_t(unsafe.Sizeof(v)))
|
|
if result == -1 {
|
|
return fmt.Errorf("warning - error setting option %s to %s, %w", so.name, val, srtGetAndClearError())
|
|
}
|
|
}
|
|
} else if so.dataType == tString {
|
|
sval := C.CString(val)
|
|
defer C.free(unsafe.Pointer(sval))
|
|
result := C.srt_setsockflag(s, C.SRT_SOCKOPT(so.option), unsafe.Pointer(sval), C.int32_t(len(val)))
|
|
if result == -1 {
|
|
return fmt.Errorf("warning - error setting option %s to %s, %w", so.name, val, srtGetAndClearError())
|
|
}
|
|
|
|
} else if so.dataType == tBoolean {
|
|
var result C.int
|
|
if val == "1" {
|
|
v := C.char(1)
|
|
result = C.srt_setsockflag(s, C.SRT_SOCKOPT(so.option), unsafe.Pointer(&v), C.int32_t(unsafe.Sizeof(v)))
|
|
} else if val == "0" {
|
|
v := C.char(0)
|
|
result = C.srt_setsockflag(s, C.SRT_SOCKOPT(so.option), unsafe.Pointer(&v), C.int32_t(unsafe.Sizeof(v)))
|
|
}
|
|
if result == -1 {
|
|
return fmt.Errorf("warning - error setting option %s to %s, %w", so.name, val, srtGetAndClearError())
|
|
}
|
|
} else if so.dataType == tTransType {
|
|
var result C.int
|
|
if val == "live" {
|
|
var v int32 = C.SRTT_LIVE
|
|
result = C.srt_setsockflag(s, C.SRT_SOCKOPT(so.option), unsafe.Pointer(&v), C.int32_t(unsafe.Sizeof(v)))
|
|
} else if val == "file" {
|
|
var v int32 = C.SRTT_FILE
|
|
result = C.srt_setsockflag(s, C.SRT_SOCKOPT(so.option), unsafe.Pointer(&v), C.int32_t(unsafe.Sizeof(v)))
|
|
}
|
|
if result == -1 {
|
|
return fmt.Errorf("warning - error setting option %s to %s: %w", so.name, val, srtGetAndClearError())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|