mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 03:41:55 +00:00
SmartPtr: Support load test for source by srs-bench. v6.0.130 (#4097)
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>
This commit is contained in:
parent
e3d74fb045
commit
1f9309ae25
508 changed files with 6805 additions and 3299 deletions
25
trunk/3rdparty/srs-bench/Makefile
vendored
25
trunk/3rdparty/srs-bench/Makefile
vendored
|
@ -1,20 +1,32 @@
|
|||
.PHONY: help default clean bench test
|
||||
.PHONY: help default clean bench pcap test all
|
||||
|
||||
default: bench test
|
||||
|
||||
clean:
|
||||
rm -rf ./objs
|
||||
|
||||
all: bench test pcap test
|
||||
|
||||
#########################################################################################################
|
||||
# SRS benchmark tool for SRS, janus, GB28181.
|
||||
./objs/.format.bench.txt: *.go janus/*.go ./objs/.format.srs.txt ./objs/.format.gb28181.txt
|
||||
gofmt -w *.go janus
|
||||
mkdir -p objs && echo "done" > ./objs/.format.bench.txt
|
||||
|
||||
bench: ./objs/srs_bench ./objs/pcap_simulator
|
||||
bench: ./objs/srs_bench
|
||||
|
||||
./objs/srs_bench: ./objs/.format.bench.txt *.go janus/*.go srs/*.go vnet/*.go gb28181/*.go Makefile
|
||||
go build -mod=vendor -o objs/srs_bench .
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
SRT_PREFIX := $(shell brew --prefix srt)
|
||||
CGO_CFLAGS := -I$(SRT_PREFIX)/include
|
||||
CGO_LDFLAGS := -L$(SRT_PREFIX)/lib -lsrt
|
||||
else ifeq ($(UNAME_S),Linux)
|
||||
CGO_CFLAGS := -I/usr/local/include
|
||||
CGO_LDFLAGS := -L/usr/local/lib -lsrt -L/usr/local/ssl/lib -lcrypto -lstdc++ -lm -ldl
|
||||
endif
|
||||
|
||||
./objs/srs_bench: ./objs/.format.bench.txt *.go janus/*.go srs/*.go vnet/*.go gb28181/*.go live/*.go Makefile
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" go build -mod=vendor -o objs/srs_bench .
|
||||
|
||||
#########################################################################################################
|
||||
# For all regression tests.
|
||||
|
@ -35,6 +47,8 @@ test: ./objs/srs_test ./objs/srs_gb28181_test ./objs/srs_blackbox_test
|
|||
gofmt -w pcap
|
||||
mkdir -p objs && echo "done" > ./objs/.format.pcap.txt
|
||||
|
||||
pcap: ./objs/pcap_simulator
|
||||
|
||||
./objs/pcap_simulator: ./objs/.format.pcap.txt pcap/*.go Makefile
|
||||
go build -mod=vendor -o ./objs/pcap_simulator ./pcap
|
||||
|
||||
|
@ -59,9 +73,10 @@ test: ./objs/srs_test ./objs/srs_gb28181_test ./objs/srs_blackbox_test
|
|||
#########################################################################################################
|
||||
# Help menu.
|
||||
help:
|
||||
@echo "Usage: make [default|bench|test|clean]"
|
||||
@echo "Usage: make [default|bench|pcap|test|clean]"
|
||||
@echo " default The default entry for make is bench+test"
|
||||
@echo " bench Make the bench to ./objs/srs_bench"
|
||||
@echo " pcap Make the pcap simulator to ./objs/pcap_simulator"
|
||||
@echo " test Make the test tool to ./objs/srs_test and ./objs/srs_gb28181_test ./objs/srs_blackbox_test"
|
||||
@echo " clean Remove all tools at ./objs"
|
||||
|
||||
|
|
87
trunk/3rdparty/srs-bench/README.md
vendored
87
trunk/3rdparty/srs-bench/README.md
vendored
|
@ -14,6 +14,8 @@ git clone -b feature/rtc https://github.com/ossrs/srs-bench.git &&
|
|||
cd srs-bench && make
|
||||
```
|
||||
|
||||
> Note: 依赖Go编译工具,建议使用 Go 1.17 及以上的版本。
|
||||
|
||||
编译会生成下面的工具:
|
||||
|
||||
* `./objs/srs_bench` 压测,模拟大量客户端的负载测试,支持SRS、GB28181和Janus三种场景。
|
||||
|
@ -33,7 +35,7 @@ cd srs/trunk && ./configure --h265=on --gb28181=on && make &&
|
|||
|
||||
具体场景,请按下面的操作启动测试。
|
||||
|
||||
## Player for Live
|
||||
## Player for WHEP
|
||||
|
||||
直播播放压测,一个流,很多个播放。
|
||||
|
||||
|
@ -49,7 +51,7 @@ ffmpeg -re -i doc/source.200kbps.768x320.flv -c copy -f flv -y rtmp://localhost/
|
|||
./objs/srs_bench -sr webrtc://localhost/live/livestream -nn 100
|
||||
```
|
||||
|
||||
## Publisher for Live or RTC
|
||||
## Publisher for WHIP
|
||||
|
||||
直播或会议场景推流压测,一般会推多个流。
|
||||
|
||||
|
@ -63,7 +65,7 @@ ffmpeg -re -i doc/source.200kbps.768x320.flv -c copy -f flv -y rtmp://localhost/
|
|||
|
||||
> 注意:帧率是原始视频的帧率,由于264中没有这个信息所以需要传递。
|
||||
|
||||
## Multipel Player or Publisher for RTC
|
||||
## Multiple WHIP or WHEP for RTC
|
||||
|
||||
会议场景的播放压测,会多个客户端播放多个流,比如3人会议,那么就有3个推流,每个流有2个播放。
|
||||
|
||||
|
@ -84,7 +86,7 @@ ffmpeg -re -i doc/source.200kbps.768x320.flv -c copy -f flv -y rtmp://localhost/
|
|||
> 备注:URL的变量格式参考Go的`fmt.Sprintf`,比如可以用`webrtc://localhost/live/livestream_%03d`。
|
||||
|
||||
<a name="dvr"></a>
|
||||
## DVR for Benchmark
|
||||
## DVR for RTC Benchmark
|
||||
|
||||
录制场景,主要是把内容录制下来后,可分析,也可以用于推流。
|
||||
|
||||
|
@ -120,6 +122,37 @@ ffmpeg -re -i doc/source.200kbps.768x320.flv -c copy -f flv -y rtmp://localhost/
|
|||
|
||||
> Note: 可以传递更多参数,详细参考SRS支持的参数。
|
||||
|
||||
## Reconnecting Load Test
|
||||
|
||||
建立连接和断开重连的压测,可以测试SRS在多个Source时是否有内存泄露问题,参考 [#3667](https://github.com/ossrs/srs/discussions/3667#discussioncomment-8969107)
|
||||
|
||||
RTMP重连测试:
|
||||
|
||||
```bash
|
||||
for ((i=0;;i++)); do
|
||||
./objs/srs_bench -sfu=live -pr=rtmp://localhost/live${i}/stream -sn=1000 -cap=true;
|
||||
sleep 10;
|
||||
done
|
||||
```
|
||||
|
||||
SRT重连测试:
|
||||
|
||||
```bash
|
||||
for ((i=0;;i++)); do
|
||||
./objs/srs_bench -sfu=live -pr='srt://127.0.0.1:10080?streamid=#!::'m=publish,r=live${i}/stream -sn=1000 -cap=true;
|
||||
sleep 10;
|
||||
done
|
||||
```
|
||||
|
||||
WebRTC重连测试:
|
||||
|
||||
```bash
|
||||
for ((i=0;;i++)); do
|
||||
./objs/srs_bench -sfu=rtc -pr=webrtc://localhost/live${i}/livestream -sn=1000 -cap=true;
|
||||
sleep 10;
|
||||
done
|
||||
```
|
||||
|
||||
## Regression Test
|
||||
|
||||
回归测试需要先启动[SRS](https://github.com/ossrs/srs/issues/307),支持WebRTC推拉流:
|
||||
|
@ -329,4 +362,50 @@ make -j10 && ./objs/srs_bench -sfu janus \
|
|||
-nn 5
|
||||
```
|
||||
|
||||
## Install LIBSRT
|
||||
|
||||
我们使用 [srtgo](https://github.com/Haivision/srtgo) 库测试SRT协议,需要安装libsrt库,
|
||||
参考[macOS](https://github.com/Haivision/srt/blob/master/docs/build/build-macOS.md):
|
||||
|
||||
```bash
|
||||
brew install srt
|
||||
```
|
||||
|
||||
如果是Ubuntu,可以参考[Ubuntu](https://github.com/Haivision/srt/blob/master/docs/build/package-managers.md):
|
||||
|
||||
```bash
|
||||
apt-get install -y libsrt
|
||||
```
|
||||
|
||||
安装完libsrt后,直接编译srs-bench即可:
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
## Ubuntu Docker
|
||||
|
||||
如果使用Ubuntu编译,推荐使用 `ossrs/srs:ubuntu20` 作为镜像编译,已经编译了openssl和libsrt,启动容器:
|
||||
|
||||
```bash
|
||||
docker run --rm -it -v $(pwd):/g -w /g ossrs/srs:ubuntu20 make
|
||||
```
|
||||
|
||||
## GoLand
|
||||
|
||||
使用GoLand编译和调试时,需要设置libsrt的环境变量,首先可以使用brew获取路径:
|
||||
|
||||
```bash
|
||||
brew --prefix srt
|
||||
#/opt/homebrew/opt/srt
|
||||
```
|
||||
|
||||
然后在GoLand中,编辑配置 `Edit Configurations`,添加环境变量:
|
||||
|
||||
```bash
|
||||
CGO_CFLAGS=-I/opt/homebrew/opt/srt/include;CGO_LDFLAGS=-L/opt/homebrew/opt/srt/lib -lsrt
|
||||
```
|
||||
|
||||
> Note: 特别注意的是,CGO_LDFLAGS是可以有空格的,不能使用字符串,否则找不到库。
|
||||
|
||||
2021.01, Winlin
|
||||
|
|
8
trunk/3rdparty/srs-bench/gb28181/gb28181.go
vendored
8
trunk/3rdparty/srs-bench/gb28181/gb28181.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2022 Winlin
|
||||
// # Copyright (c) 2022-2024 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
|
@ -57,7 +57,11 @@ func Parse(ctx context.Context) interface{} {
|
|||
fl.Usage = func() {
|
||||
fmt.Println(fmt.Sprintf("Usage: %v [Options]", os.Args[0]))
|
||||
fmt.Println(fmt.Sprintf("Options:"))
|
||||
fmt.Println(fmt.Sprintf(" -sfu The target SFU, srs or gb28181 or janus. Default: srs"))
|
||||
fmt.Println(fmt.Sprintf(" -sfu The target server that can be rtc, live, janus, or gb28181. Default: rtc"))
|
||||
fmt.Println(fmt.Sprintf(" rtc/srs: SRS WebRTC SFU server, for WebRTC/WHIP/WHEP."))
|
||||
fmt.Println(fmt.Sprintf(" live: SRS live streaming server, for RTMP/HTTP-FLV/HLS."))
|
||||
fmt.Println(fmt.Sprintf(" janus: Janus WebRTC SFU server, for janus private protocol."))
|
||||
fmt.Println(fmt.Sprintf(" gb28181: GB media server, for GB protocol."))
|
||||
fmt.Println(fmt.Sprintf("SIP:"))
|
||||
fmt.Println(fmt.Sprintf(" -user The SIP username, ID of device."))
|
||||
fmt.Println(fmt.Sprintf(" -random Append N number to user as random device ID, like 1320000001."))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2022 Winlin
|
||||
// # Copyright (c) 2022-2024 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
2
trunk/3rdparty/srs-bench/gb28181/gb_test.go
vendored
2
trunk/3rdparty/srs-bench/gb28181/gb_test.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2022 Winlin
|
||||
// # Copyright (c) 2022-2024 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
2
trunk/3rdparty/srs-bench/gb28181/ingester.go
vendored
2
trunk/3rdparty/srs-bench/gb28181/ingester.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2022 Winlin
|
||||
// # Copyright (c) 2022-2024 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
2
trunk/3rdparty/srs-bench/gb28181/ps.go
vendored
2
trunk/3rdparty/srs-bench/gb28181/ps.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2022 Winlin
|
||||
// # Copyright (c) 2022-2024 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
2
trunk/3rdparty/srs-bench/gb28181/sip.go
vendored
2
trunk/3rdparty/srs-bench/gb28181/sip.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2022 Winlin
|
||||
// # Copyright (c) 2022-2024 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
2
trunk/3rdparty/srs-bench/gb28181/util.go
vendored
2
trunk/3rdparty/srs-bench/gb28181/util.go
vendored
|
@ -1,6 +1,6 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2022 Winlin
|
||||
// # Copyright (c) 2022-2024 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
12
trunk/3rdparty/srs-bench/go.mod
vendored
12
trunk/3rdparty/srs-bench/go.mod
vendored
|
@ -5,6 +5,7 @@ go 1.17
|
|||
require (
|
||||
github.com/ghettovoice/gosip v0.0.0-20220929080231-de8ba881be83
|
||||
github.com/google/gopacket v1.1.19
|
||||
github.com/haivision/srtgo v0.0.0-20230627061225-a70d53fcd618
|
||||
github.com/ossrs/go-oryx-lib v0.0.9
|
||||
github.com/pion/ice/v2 v2.3.6
|
||||
github.com/pion/interceptor v0.1.17
|
||||
|
@ -28,6 +29,7 @@ require (
|
|||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/mattn/go-colorable v0.1.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.8 // indirect
|
||||
github.com/mattn/go-pointer v0.0.1 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/pion/datachannel v1.5.5 // indirect
|
||||
github.com/pion/dtls/v2 v2.2.7 // indirect
|
||||
|
@ -40,12 +42,12 @@ require (
|
|||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b // indirect
|
||||
github.com/sirupsen/logrus v1.4.2 // indirect
|
||||
github.com/stretchr/testify v1.8.4 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5 // indirect
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
|
||||
golang.org/x/crypto v0.9.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/term v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
27
trunk/3rdparty/srs-bench/go.sum
vendored
27
trunk/3rdparty/srs-bench/go.sum
vendored
|
@ -31,6 +31,8 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF
|
|||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/haivision/srtgo v0.0.0-20230627061225-a70d53fcd618 h1:oGPTZa7I5wqmQs/UhWHj3ln6/CjQX2yQt784xx6H0wI=
|
||||
github.com/haivision/srtgo v0.0.0-20230627061225-a70d53fcd618/go.mod h1:aTd4vOr9wtzkCbbocUFh6atlJy7H/iV5jhqEWlTdCdA=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
|
@ -44,6 +46,8 @@ github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaa
|
|||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
|
||||
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
|
@ -115,6 +119,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
|
@ -122,8 +127,9 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
|||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5 h1:hNna6Fi0eP1f2sMBe/rJicDmaHmoXGe1Ta84FPYHLuE=
|
||||
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5/go.mod h1:f1SCnEOt6sc3fOJfPQDRDzHOtSXuTtnz0ImG9kPRDV0=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
|
||||
|
@ -140,8 +146,10 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
|
@ -161,8 +169,9 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
|||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -178,6 +187,7 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -193,8 +203,10 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -202,8 +214,10 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
|||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
@ -213,8 +227,9 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
|
|
6
trunk/3rdparty/srs-bench/janus/janus.go
vendored
6
trunk/3rdparty/srs-bench/janus/janus.go
vendored
|
@ -66,7 +66,11 @@ func Parse(ctx context.Context) {
|
|||
fl.Usage = func() {
|
||||
fmt.Println(fmt.Sprintf("Usage: %v [Options]", os.Args[0]))
|
||||
fmt.Println(fmt.Sprintf("Options:"))
|
||||
fmt.Println(fmt.Sprintf(" -sfu The target SFU, srs or gb28181 or janus. Default: srs"))
|
||||
fmt.Println(fmt.Sprintf(" -sfu The target server that can be rtc, live, janus, or gb28181. Default: rtc"))
|
||||
fmt.Println(fmt.Sprintf(" rtc/srs: SRS WebRTC SFU server, for WebRTC/WHIP/WHEP."))
|
||||
fmt.Println(fmt.Sprintf(" live: SRS live streaming server, for RTMP/HTTP-FLV/HLS."))
|
||||
fmt.Println(fmt.Sprintf(" janus: Janus WebRTC SFU server, for janus private protocol."))
|
||||
fmt.Println(fmt.Sprintf(" gb28181: GB media server, for GB protocol."))
|
||||
fmt.Println(fmt.Sprintf(" -nn The number of clients to simulate. Default: 1"))
|
||||
fmt.Println(fmt.Sprintf(" -sn The number of streams to simulate. Variable: %%d. Default: 1"))
|
||||
fmt.Println(fmt.Sprintf(" -delay The start delay in ms for each client or stream to simulate. Default: 50"))
|
||||
|
|
195
trunk/3rdparty/srs-bench/live/live.go
vendored
Normal file
195
trunk/3rdparty/srs-bench/live/live.go
vendored
Normal file
|
@ -0,0 +1,195 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// # Copyright (c) 2021 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
package live
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
)
|
||||
|
||||
var closeAfterPublished bool
|
||||
|
||||
var pr string
|
||||
|
||||
var streams, delay int
|
||||
|
||||
var statListen string
|
||||
|
||||
func Parse(ctx context.Context) {
|
||||
fl := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||
|
||||
var sfu string
|
||||
fl.StringVar(&sfu, "sfu", "srs", "The SFU server, srs or gb28181 or janus")
|
||||
|
||||
fl.BoolVar(&closeAfterPublished, "cap", false, "")
|
||||
|
||||
fl.StringVar(&pr, "pr", "", "")
|
||||
|
||||
fl.IntVar(&streams, "sn", 1, "")
|
||||
fl.IntVar(&delay, "delay", 10, "")
|
||||
|
||||
fl.StringVar(&statListen, "stat", "", "")
|
||||
|
||||
fl.Usage = func() {
|
||||
fmt.Println(fmt.Sprintf("Usage: %v [Options]", os.Args[0]))
|
||||
fmt.Println(fmt.Sprintf("Options:"))
|
||||
fmt.Println(fmt.Sprintf(" -sfu The target server that can be rtc, live, janus, or gb28181. Default: rtc"))
|
||||
fmt.Println(fmt.Sprintf(" rtc/srs: SRS WebRTC SFU server, for WebRTC/WHIP/WHEP."))
|
||||
fmt.Println(fmt.Sprintf(" live: SRS live streaming server, for RTMP/HTTP-FLV/HLS."))
|
||||
fmt.Println(fmt.Sprintf(" janus: Janus WebRTC SFU server, for janus private protocol."))
|
||||
fmt.Println(fmt.Sprintf(" -sn The number of streams to simulate. Variable: %%d. Default: 1"))
|
||||
fmt.Println(fmt.Sprintf(" -delay The start delay in ms for each client or stream to simulate. Default: 50"))
|
||||
fmt.Println(fmt.Sprintf(" -stat [Optional] The stat server API listen port."))
|
||||
fmt.Println(fmt.Sprintf("Publisher:"))
|
||||
fmt.Println(fmt.Sprintf(" -pr The url to publish. If sn exceed 1, auto append variable %%d."))
|
||||
fmt.Println(fmt.Sprintf(" -cap Whether to close connection after publish. Default: false"))
|
||||
fmt.Println(fmt.Sprintf("\n例如,1个推流,无媒体传输:"))
|
||||
fmt.Println(fmt.Sprintf(" %v -pr=rtmp://localhost/live/livestream -cap=true", os.Args[0]))
|
||||
fmt.Println(fmt.Sprintf("\n例如,2个推流,无媒体传输:"))
|
||||
fmt.Println(fmt.Sprintf(" %v -pr=rtmp://localhost/live/livestream_%%d -sn=2 -cap=true", os.Args[0]))
|
||||
fmt.Println()
|
||||
}
|
||||
_ = fl.Parse(os.Args[1:])
|
||||
|
||||
showHelp := streams <= 0
|
||||
if pr == "" {
|
||||
showHelp = true
|
||||
}
|
||||
if showHelp {
|
||||
fl.Usage()
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
if statListen != "" && !strings.Contains(statListen, ":") {
|
||||
statListen = ":" + statListen
|
||||
}
|
||||
|
||||
summaryDesc := fmt.Sprintf("streams=%v", streams)
|
||||
if pr != "" {
|
||||
summaryDesc = fmt.Sprintf("%v, publish=(url=%v,cap=%v)",
|
||||
summaryDesc, pr, closeAfterPublished)
|
||||
}
|
||||
logger.Tf(ctx, "Run benchmark with %v", summaryDesc)
|
||||
}
|
||||
|
||||
func Run(ctx context.Context) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
// Run tasks.
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
// Run STAT API server.
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if statListen == "" {
|
||||
return
|
||||
}
|
||||
|
||||
var lc net.ListenConfig
|
||||
ln, err := lc.Listen(ctx, "tcp", statListen)
|
||||
if err != nil {
|
||||
logger.Ef(ctx, "stat listen err+%v", err)
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
handleStat(ctx, mux, statListen)
|
||||
|
||||
srv := &http.Server{
|
||||
Handler: mux,
|
||||
BaseContext: func(listener net.Listener) context.Context {
|
||||
return ctx
|
||||
},
|
||||
}
|
||||
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
srv.Shutdown(ctx)
|
||||
}()
|
||||
|
||||
logger.Tf(ctx, "Stat listen at %v", statListen)
|
||||
if err := srv.Serve(ln); err != nil {
|
||||
if ctx.Err() == nil {
|
||||
logger.Ef(ctx, "stat serve err+%v", err)
|
||||
cancel()
|
||||
}
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
// Run all publishers.
|
||||
publisherStartedCtx, publisherStartedCancel := context.WithCancel(ctx)
|
||||
defer publisherStartedCancel()
|
||||
for i := 0; pr != "" && i < streams && ctx.Err() == nil; i++ {
|
||||
r_auto := pr
|
||||
if streams > 1 && !strings.Contains(r_auto, "%") {
|
||||
r_auto += "%d"
|
||||
}
|
||||
|
||||
r2 := r_auto
|
||||
if strings.Contains(r2, "%") {
|
||||
r2 = fmt.Sprintf(r2, i)
|
||||
}
|
||||
|
||||
gStatLive.Publishers.Expect++
|
||||
gStatLive.Publishers.Alive++
|
||||
|
||||
wg.Add(1)
|
||||
go func(pr string) {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
gStatLive.Publishers.Alive--
|
||||
logger.Tf(ctx, "Publisher %v done, alive=%v", pr, gStatLive.Publishers.Alive)
|
||||
|
||||
<- publisherStartedCtx.Done()
|
||||
if gStatLive.Publishers.Alive == 0 {
|
||||
cancel()
|
||||
}
|
||||
}()
|
||||
|
||||
if err := startPublish(ctx, pr, closeAfterPublished); err != nil {
|
||||
if errors.Cause(err) != context.Canceled {
|
||||
logger.Wf(ctx, "Run err %+v", err)
|
||||
}
|
||||
}
|
||||
}(r2)
|
||||
|
||||
if delay > 0 {
|
||||
time.Sleep(time.Duration(delay) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
210
trunk/3rdparty/srs-bench/live/publisher.go
vendored
Normal file
210
trunk/3rdparty/srs-bench/live/publisher.go
vendored
Normal file
|
@ -0,0 +1,210 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// # Copyright (c) 2021 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
package live
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/haivision/srtgo"
|
||||
"github.com/ossrs/go-oryx-lib/amf0"
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/ossrs/go-oryx-lib/rtmp"
|
||||
)
|
||||
|
||||
func startPublish(ctx context.Context, r string, closeAfterPublished bool) error {
|
||||
ctx = logger.WithContext(ctx)
|
||||
logger.Tf(ctx, "Run publish url=%v, cap=%v", r, closeAfterPublished)
|
||||
|
||||
u, err := url.Parse(r)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "parse %v", r)
|
||||
}
|
||||
|
||||
if u.Scheme == "rtmp" {
|
||||
return startPublishRTMP(ctx, u, closeAfterPublished)
|
||||
} else if u.Scheme == "srt" {
|
||||
return startPublishSRT(ctx, u, closeAfterPublished)
|
||||
}
|
||||
|
||||
return fmt.Errorf("invalid schema %v of %v", u.Scheme, r)
|
||||
}
|
||||
|
||||
func startPublishSRT(ctx context.Context, u *url.URL, closeAfterPublished bool) (err error) {
|
||||
// Parse host and port.
|
||||
port := 1935
|
||||
if u.Port() != "" {
|
||||
if port, err = strconv.Atoi(u.Port()); err != nil {
|
||||
return errors.Wrapf(err, "parse port %v", u.Port())
|
||||
}
|
||||
}
|
||||
|
||||
ips, err := net.LookupIP(u.Hostname())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "lookup %v", u.Hostname())
|
||||
}
|
||||
if len(ips) == 0 {
|
||||
return errors.Errorf("no ips for %v", u.Hostname())
|
||||
}
|
||||
logger.Tf(ctx, "Parse url %v to host=%v, ip=%v, port=%v",
|
||||
u.String(), u.Hostname(), ips[0], port)
|
||||
|
||||
// Setup libsrt.
|
||||
client := srtgo.NewSrtSocket(ips[0].To4().String(), uint16(port),
|
||||
map[string]string{
|
||||
"transtype": "live",
|
||||
"tsbpdmode": "false",
|
||||
"tlpktdrop": "false",
|
||||
"latency": "0",
|
||||
"streamid": fmt.Sprintf("#%v", u.Fragment),
|
||||
},
|
||||
)
|
||||
defer client.Close()
|
||||
|
||||
if err := client.Connect(); err != nil {
|
||||
return errors.Wrapf(err, "SRT connect to %v:%v", u.Hostname(), port)
|
||||
}
|
||||
logger.Tf(ctx, "Connect to SRT server %v:%v success", u.Hostname(), port)
|
||||
|
||||
// We should wait for a while after connected to SRT server before quit. Because SRT server use timeout
|
||||
// to detect UDP connection status, so we should never reconnect very fast.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-time.After(3 * time.Second):
|
||||
logger.Tf(ctx, "SRT publish stream success, stream=%v", u.Fragment)
|
||||
}
|
||||
|
||||
if closeAfterPublished {
|
||||
logger.Tf(ctx, "Close connection after published")
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func startPublishRTMP(ctx context.Context, u *url.URL, closeAfterPublished bool) (err error) {
|
||||
parts := strings.Split(u.Path, "/")
|
||||
if len(parts) == 0 {
|
||||
return errors.Errorf("invalid path %v", u.Path)
|
||||
}
|
||||
app, stream := strings.Join(parts[:len(parts)-1], "/"), parts[len(parts)-1]
|
||||
|
||||
// Parse host and port.
|
||||
port := 1935
|
||||
if u.Port() != "" {
|
||||
if port, err = strconv.Atoi(u.Port()); err != nil {
|
||||
return errors.Wrapf(err, "parse port %v", u.Port())
|
||||
}
|
||||
}
|
||||
|
||||
ips, err := net.LookupIP(u.Hostname())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "lookup %v", u.Hostname())
|
||||
}
|
||||
if len(ips) == 0 {
|
||||
return errors.Errorf("no ips for %v", u.Hostname())
|
||||
}
|
||||
logger.Tf(ctx, "Parse url %v to host=%v, ip=%v, port=%v, app=%v, stream=%v",
|
||||
u.String(), u.Hostname(), ips[0], port, app, stream)
|
||||
|
||||
// Connect via TCP client.
|
||||
c, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ips[0], Port: port})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "dial %v %v", u.Hostname(), u.Port())
|
||||
}
|
||||
defer c.Close()
|
||||
logger.Tf(ctx, "Connect to RTMP server %v:%v success", u.Hostname(), port)
|
||||
|
||||
// RTMP Handshake.
|
||||
rd := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
hs := rtmp.NewHandshake(rd)
|
||||
|
||||
if err := hs.WriteC0S0(c); err != nil {
|
||||
return errors.Wrap(err, "write c0")
|
||||
}
|
||||
if err := hs.WriteC1S1(c); err != nil {
|
||||
return errors.Wrap(err, "write c1")
|
||||
}
|
||||
|
||||
if _, err = hs.ReadC0S0(c); err != nil {
|
||||
return errors.Wrap(err, "read s1")
|
||||
}
|
||||
s1, err := hs.ReadC1S1(c)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "read s1")
|
||||
}
|
||||
if _, err = hs.ReadC2S2(c); err != nil {
|
||||
return errors.Wrap(err, "read s2")
|
||||
}
|
||||
|
||||
if err := hs.WriteC2S2(c, s1); err != nil {
|
||||
return errors.Wrap(err, "write c2")
|
||||
}
|
||||
logger.Tf(ctx, "RTMP handshake with %v:%v success", ips[0], port)
|
||||
|
||||
// Do connect and publish.
|
||||
client := rtmp.NewProtocol(c)
|
||||
|
||||
connectApp := rtmp.NewConnectAppPacket()
|
||||
tcURL := fmt.Sprintf("rtmp://%v%v", u.Hostname(), app)
|
||||
connectApp.CommandObject.Set("tcUrl", amf0.NewString(tcURL))
|
||||
if err = client.WritePacket(connectApp, 1); err != nil {
|
||||
return errors.Wrap(err, "write connect app")
|
||||
}
|
||||
|
||||
var connectAppRes *rtmp.ConnectAppResPacket
|
||||
if _, err = client.ExpectPacket(&connectAppRes); err != nil {
|
||||
return errors.Wrap(err, "expect connect app res")
|
||||
}
|
||||
logger.Tf(ctx, "RTMP connect app success, tcUrl=%v", tcURL)
|
||||
|
||||
createStream := rtmp.NewCreateStreamPacket()
|
||||
if err = client.WritePacket(createStream, 1); err != nil {
|
||||
return errors.Wrap(err, "write create stream")
|
||||
}
|
||||
|
||||
var createStreamRes *rtmp.CreateStreamResPacket
|
||||
if _, err = client.ExpectPacket(&createStreamRes); err != nil {
|
||||
return errors.Wrap(err, "expect create stream res")
|
||||
}
|
||||
logger.Tf(ctx, "RTMP create stream success")
|
||||
|
||||
publish := rtmp.NewPublishPacket()
|
||||
publish.StreamName = *amf0.NewString(stream)
|
||||
if err = client.WritePacket(publish, 1); err != nil {
|
||||
return errors.Wrap(err, "write publish")
|
||||
}
|
||||
logger.Tf(ctx, "RTMP publish stream success, stream=%v", stream)
|
||||
|
||||
if closeAfterPublished {
|
||||
logger.Tf(ctx, "Close connection after published")
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
68
trunk/3rdparty/srs-bench/live/stat.go
vendored
Normal file
68
trunk/3rdparty/srs-bench/live/stat.go
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
// The MIT License (MIT)
|
||||
//
|
||||
// # Copyright (c) 2021 Winlin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
package live
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
)
|
||||
|
||||
type statLive struct {
|
||||
Publishers struct {
|
||||
Expect int `json:"expect"`
|
||||
Alive int `json:"alive"`
|
||||
} `json:"publishers"`
|
||||
Subscribers struct {
|
||||
Expect int `json:"expect"`
|
||||
Alive int `json:"alive"`
|
||||
} `json:"subscribers"`
|
||||
PeerConnection interface{} `json:"random-pc"`
|
||||
}
|
||||
|
||||
var gStatLive statLive
|
||||
|
||||
func handleStat(ctx context.Context, mux *http.ServeMux, l string) {
|
||||
if strings.HasPrefix(l, ":") {
|
||||
l = "127.0.0.1" + l
|
||||
}
|
||||
|
||||
logger.Tf(ctx, "Handle http://%v/api/v1/sb/live", l)
|
||||
mux.HandleFunc("/api/v1/sb/live", func(w http.ResponseWriter, r *http.Request) {
|
||||
res := &struct {
|
||||
Code int `json:"code"`
|
||||
Data interface{} `json:"data"`
|
||||
}{
|
||||
0, &gStatLive,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
logger.Wf(ctx, "marshal %v err %+v", res, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(b)
|
||||
})
|
||||
}
|
26
trunk/3rdparty/srs-bench/main.go
vendored
26
trunk/3rdparty/srs-bench/main.go
vendored
|
@ -24,27 +24,31 @@ import (
|
|||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/ossrs/srs-bench/gb28181"
|
||||
"github.com/ossrs/srs-bench/janus"
|
||||
"github.com/ossrs/srs-bench/srs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/ossrs/srs-bench/gb28181"
|
||||
"github.com/ossrs/srs-bench/janus"
|
||||
"github.com/ossrs/srs-bench/live"
|
||||
"github.com/ossrs/srs-bench/srs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var sfu string
|
||||
fl := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||
fl.SetOutput(ioutil.Discard)
|
||||
fl.StringVar(&sfu, "sfu", "srs", "The SFU server, srs or gb28181 or janus")
|
||||
fl.StringVar(&sfu, "sfu", "rtc", "")
|
||||
_ = fl.Parse(os.Args[1:])
|
||||
|
||||
ctx := context.Background()
|
||||
var conf interface{}
|
||||
if sfu == "srs" {
|
||||
if sfu == "rtc" || sfu == "srs" {
|
||||
srs.Parse(ctx)
|
||||
} else if sfu == "live" {
|
||||
live.Parse(ctx)
|
||||
} else if sfu == "gb28181" {
|
||||
conf = gb28181.Parse(ctx)
|
||||
} else if sfu == "janus" {
|
||||
|
@ -52,7 +56,11 @@ func main() {
|
|||
} else {
|
||||
fmt.Println(fmt.Sprintf("Usage: %v [Options]", os.Args[0]))
|
||||
fmt.Println(fmt.Sprintf("Options:"))
|
||||
fmt.Println(fmt.Sprintf(" -sfu The target SFU, srs or gb28181 or janus. Default: srs"))
|
||||
fmt.Println(fmt.Sprintf(" -sfu The target server that can be rtc, live, janus, or gb28181. Default: rtc"))
|
||||
fmt.Println(fmt.Sprintf(" rtc/srs: SRS WebRTC SFU server, for WebRTC/WHIP/WHEP."))
|
||||
fmt.Println(fmt.Sprintf(" live: SRS live streaming server, for RTMP/HTTP-FLV/HLS."))
|
||||
fmt.Println(fmt.Sprintf(" janus: Janus WebRTC SFU server, for janus private protocol."))
|
||||
fmt.Println(fmt.Sprintf(" gb28181: GB media server, for GB protocol."))
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
|
@ -67,8 +75,10 @@ func main() {
|
|||
}()
|
||||
|
||||
var err error
|
||||
if sfu == "srs" {
|
||||
if sfu == "rtc" || sfu == "srs" {
|
||||
err = srs.Run(ctx)
|
||||
} else if sfu == "live" {
|
||||
err = live.Run(ctx)
|
||||
} else if sfu == "gb28181" {
|
||||
err = gb28181.Run(ctx, conf)
|
||||
} else if sfu == "janus" {
|
||||
|
|
21
trunk/3rdparty/srs-bench/srs/publisher.go
vendored
21
trunk/3rdparty/srs-bench/srs/publisher.go
vendored
|
@ -34,7 +34,7 @@ import (
|
|||
)
|
||||
|
||||
// @see https://github.com/pion/webrtc/blob/master/examples/play-from-disk/main.go
|
||||
func startPublish(ctx context.Context, r, sourceAudio, sourceVideo string, fps int, enableAudioLevel, enableTWCC bool) error {
|
||||
func startPublish(ctx context.Context, r, sourceAudio, sourceVideo string, fps int, enableAudioLevel, enableTWCC, closeAfterPublished bool) error {
|
||||
ctx = logger.WithContext(ctx)
|
||||
|
||||
logger.Tf(ctx, "Run publish url=%v, audio=%v, video=%v, fps=%v, audio-level=%v, twcc=%v",
|
||||
|
@ -77,10 +77,13 @@ func startPublish(ctx context.Context, r, sourceAudio, sourceVideo string, fps i
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if sourceAudio != "" {
|
||||
// For CAP, we always add audio track, because both audio and video are disabled for CAP, which will
|
||||
// cause failed when exchange SDP.
|
||||
if sourceAudio != "" || closeAfterPublished {
|
||||
aIngester = newAudioIngester(sourceAudio)
|
||||
registry.Add(&rtpInteceptorFactory{aIngester.audioLevelInterceptor})
|
||||
}
|
||||
|
||||
if sourceVideo != "" {
|
||||
vIngester = newVideoIngester(sourceVideo)
|
||||
registry.Add(&rtpInteceptorFactory{vIngester.markerInterceptor})
|
||||
|
@ -178,6 +181,7 @@ func startPublish(ctx context.Context, r, sourceAudio, sourceVideo string, fps i
|
|||
|
||||
// Wait for event from context or tracks.
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
|
@ -186,6 +190,18 @@ func startPublish(ctx context.Context, r, sourceAudio, sourceVideo string, fps i
|
|||
doClose() // Interrupt the RTCP read.
|
||||
}()
|
||||
|
||||
// If CAP, directly close the connection after published.
|
||||
if closeAfterPublished {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-pcDoneCtx.Done():
|
||||
}
|
||||
|
||||
logger.Tf(ctx, "Close connection after published")
|
||||
cancel()
|
||||
return nil
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
@ -295,6 +311,5 @@ func startPublish(ctx context.Context, r, sourceAudio, sourceVideo string, fps i
|
|||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
|
1
trunk/3rdparty/srs-bench/srs/rtc_test.go
vendored
1
trunk/3rdparty/srs-bench/srs/rtc_test.go
vendored
|
@ -2213,6 +2213,7 @@ func TestRtcDTLS_ClientActive_Corrupt_ClientHello(t *testing.T) {
|
|||
// No.2 srs-server: ServerHello, Certificate, ServerKeyExchange, CertificateRequest, ServerHelloDone
|
||||
// [Corrupt] No.3 srs-bench: Certificate, ClientKeyExchange, CertificateVerify, ChangeCipherSpec, Finished
|
||||
// No.4 srs-server: Alert (Level: Fatal, Description: Illegal Parameter)
|
||||
//
|
||||
// [Corrupt] No.1 srs-bench: ClientHello(Epoch=0, Sequence=0), change length from 129 to 0xf.
|
||||
// No.2 srs-server: Alert (Level: Fatal, Description: Illegal Parameter)
|
||||
func TestRtcDTLS_ClientActive_Corrupt_Certificate(t *testing.T) {
|
||||
|
|
22
trunk/3rdparty/srs-bench/srs/srs.go
vendored
22
trunk/3rdparty/srs-bench/srs/srs.go
vendored
|
@ -46,6 +46,8 @@ var clients, streams, delay int
|
|||
|
||||
var statListen string
|
||||
|
||||
var closeAfterPublished bool
|
||||
|
||||
func Parse(ctx context.Context) {
|
||||
fl := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||
|
||||
|
@ -71,10 +73,16 @@ func Parse(ctx context.Context) {
|
|||
|
||||
fl.StringVar(&statListen, "stat", "", "")
|
||||
|
||||
fl.BoolVar(&closeAfterPublished, "cap", false, "")
|
||||
|
||||
fl.Usage = func() {
|
||||
fmt.Println(fmt.Sprintf("Usage: %v [Options]", os.Args[0]))
|
||||
fmt.Println(fmt.Sprintf("Options:"))
|
||||
fmt.Println(fmt.Sprintf(" -sfu The target SFU, srs or gb28181 or janus. Default: srs"))
|
||||
fmt.Println(fmt.Sprintf(" -sfu The target server that can be rtc, live, janus, or gb28181. Default: rtc"))
|
||||
fmt.Println(fmt.Sprintf(" rtc/srs: SRS WebRTC SFU server, for WebRTC/WHIP/WHEP."))
|
||||
fmt.Println(fmt.Sprintf(" live: SRS live streaming server, for RTMP/HTTP-FLV/HLS."))
|
||||
fmt.Println(fmt.Sprintf(" janus: Janus WebRTC SFU server, for janus private protocol."))
|
||||
fmt.Println(fmt.Sprintf(" gb28181: GB media server, for GB protocol."))
|
||||
fmt.Println(fmt.Sprintf(" -nn The number of clients to simulate. Default: 1"))
|
||||
fmt.Println(fmt.Sprintf(" -sn The number of streams to simulate. Variable: %%d. Default: 1"))
|
||||
fmt.Println(fmt.Sprintf(" -delay The start delay in ms for each client or stream to simulate. Default: 50"))
|
||||
|
@ -91,6 +99,7 @@ func Parse(ctx context.Context) {
|
|||
fmt.Println(fmt.Sprintf(" -fps [Optional] The fps of .h264 source file."))
|
||||
fmt.Println(fmt.Sprintf(" -sa [Optional] The file path to read audio, ignore if empty."))
|
||||
fmt.Println(fmt.Sprintf(" -sv [Optional] The file path to read video, ignore if empty."))
|
||||
fmt.Println(fmt.Sprintf(" -cap Whether to close connection after publish. Default: false"))
|
||||
fmt.Println(fmt.Sprintf("\n例如,1个播放,1个推流:"))
|
||||
fmt.Println(fmt.Sprintf(" %v -sr webrtc://localhost/live/livestream", os.Args[0]))
|
||||
fmt.Println(fmt.Sprintf(" %v -pr webrtc://localhost/live/livestream -sa avatar.ogg -sv avatar.h264 -fps 25", os.Args[0]))
|
||||
|
@ -114,7 +123,7 @@ func Parse(ctx context.Context) {
|
|||
if sr == "" && pr == "" {
|
||||
showHelp = true
|
||||
}
|
||||
if pr != "" && (sourceAudio == "" && sourceVideo == "") {
|
||||
if pr != "" && !closeAfterPublished && (sourceAudio == "" && sourceVideo == "") {
|
||||
showHelp = true
|
||||
}
|
||||
if showHelp {
|
||||
|
@ -131,8 +140,8 @@ func Parse(ctx context.Context) {
|
|||
summaryDesc = fmt.Sprintf("%v, play(url=%v, da=%v, dv=%v, pli=%v)", summaryDesc, sr, dumpAudio, dumpVideo, pli)
|
||||
}
|
||||
if pr != "" {
|
||||
summaryDesc = fmt.Sprintf("%v, publish(url=%v, sa=%v, sv=%v, fps=%v)",
|
||||
summaryDesc, pr, sourceAudio, sourceVideo, fps)
|
||||
summaryDesc = fmt.Sprintf("%v, publish(url=%v, sa=%v, sv=%v, fps=%v, cap=%v)",
|
||||
summaryDesc, pr, sourceAudio, sourceVideo, fps, closeAfterPublished)
|
||||
}
|
||||
logger.Tf(ctx, "Run benchmark with %v", summaryDesc)
|
||||
|
||||
|
@ -161,6 +170,7 @@ func Run(ctx context.Context) error {
|
|||
|
||||
// Run tasks.
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
// Run STAT API server.
|
||||
wg.Add(1)
|
||||
|
@ -266,7 +276,7 @@ func Run(ctx context.Context) error {
|
|||
gStatRTC.Publishers.Alive--
|
||||
}()
|
||||
|
||||
if err := startPublish(ctx, pr, sourceAudio, sourceVideo, fps, audioLevel, videoTWCC); err != nil {
|
||||
if err := startPublish(ctx, pr, sourceAudio, sourceVideo, fps, audioLevel, videoTWCC, closeAfterPublished); err != nil {
|
||||
if errors.Cause(err) != context.Canceled {
|
||||
logger.Wf(ctx, "Run err %+v", err)
|
||||
}
|
||||
|
@ -276,7 +286,5 @@ func Run(ctx context.Context) error {
|
|||
time.Sleep(time.Duration(delay) * time.Millisecond)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
373
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/LICENSE
generated
vendored
Normal file
373
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,373 @@
|
|||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
63
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/README.md
generated
vendored
Normal file
63
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/README.md
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
[![PkgGoDev](https://pkg.go.dev/badge/github.com/haivision/srtgo)](https://pkg.go.dev/github.com/haivision/srtgo)
|
||||
|
||||
# srtgo
|
||||
|
||||
Go bindings for [SRT](https://github.com/Haivision/srt) (Secure Reliable Transport), the open source transport technology that optimizes streaming performance across unpredictable networks.
|
||||
|
||||
## Why srtgo?
|
||||
The purpose of srtgo is easing the adoption of SRT transport technology. Using Go, with just a few lines of code you can implement an application that sends/receives data with all the benefits of SRT technology: security and reliability, while keeping latency low.
|
||||
|
||||
## Is this a new implementation of SRT?
|
||||
No! We are just exposing the great work done by the community in the [SRT project](https://github.com/Haivision/srt) as a golang library. All the functionality and implementation still resides in the official SRT project.
|
||||
|
||||
|
||||
# Features supported
|
||||
* Basic API exposed to easy develop SRT sender/receiver apps
|
||||
* Caller and Listener mode
|
||||
* Live transport type
|
||||
* File transport type
|
||||
* Message/Buffer API
|
||||
* SRT transport options up to SRT 1.4.1
|
||||
* SRT Stats retrieval
|
||||
|
||||
# Usage
|
||||
Example of a SRT receiver application:
|
||||
``` go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/haivision/srtgo"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := make(map[string]string)
|
||||
options["transtype"] = "file"
|
||||
|
||||
sck := srtgo.NewSrtSocket("0.0.0.0", 8090, options)
|
||||
defer sck.Close()
|
||||
sck.Listen(1)
|
||||
s, _ := sck.Accept()
|
||||
defer s.Close()
|
||||
|
||||
buf := make([]byte, 2048)
|
||||
for {
|
||||
n, _ := s.Read(buf)
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
fmt.Println("Received %d bytes", n)
|
||||
}
|
||||
//....
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
* srtlib
|
||||
|
||||
You can find detailed instructions about how to install srtlib in its [README file](https://github.com/Haivision/srt#requirements)
|
||||
|
||||
gosrt has been developed with srt 1.4.1 as its main target and has been successfully tested in srt 1.3.4 and above.
|
69
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/accept.go
generated
vendored
Normal file
69
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/accept.go
generated
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include <srt/srt.h>
|
||||
|
||||
SRTSOCKET srt_accept_wrapped(SRTSOCKET lsn, struct sockaddr* addr, int* addrlen, int *srterror, int *syserror)
|
||||
{
|
||||
int ret = srt_accept(lsn, addr, addrlen);
|
||||
if (ret < 0) {
|
||||
*srterror = srt_getlasterror(syserror);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func srtAcceptImpl(lsn C.SRTSOCKET, addr *C.struct_sockaddr, addrlen *C.int) (C.SRTSOCKET, error) {
|
||||
srterr := C.int(0)
|
||||
syserr := C.int(0)
|
||||
socket := C.srt_accept_wrapped(lsn, addr, addrlen, &srterr, &syserr)
|
||||
if srterr != 0 {
|
||||
srterror := SRTErrno(srterr)
|
||||
if syserr < 0 {
|
||||
srterror.wrapSysErr(syscall.Errno(syserr))
|
||||
}
|
||||
return socket, srterror
|
||||
}
|
||||
return socket, nil
|
||||
}
|
||||
|
||||
// Accept an incoming connection
|
||||
func (s SrtSocket) Accept() (*SrtSocket, *net.UDPAddr, error) {
|
||||
var err error
|
||||
if !s.blocking {
|
||||
err = s.pd.wait(ModeRead)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
var addr syscall.RawSockaddrAny
|
||||
sclen := C.int(syscall.SizeofSockaddrAny)
|
||||
socket, err := srtAcceptImpl(s.socket, (*C.struct_sockaddr)(unsafe.Pointer(&addr)), &sclen)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if socket == SRT_INVALID_SOCK {
|
||||
return nil, nil, fmt.Errorf("srt accept, error accepting the connection: %w", srtGetAndClearError())
|
||||
}
|
||||
|
||||
newSocket, err := newFromSocket(&s, socket)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("new socket could not be created: %w", err)
|
||||
}
|
||||
|
||||
udpAddr, err := udpAddrFromSockaddr(&addr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return newSocket, udpAddr, nil
|
||||
}
|
7
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/callback.h
generated
vendored
Normal file
7
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/callback.h
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include <srt/srt.h>
|
||||
|
||||
int srtListenCBWrapper(void* opaque, SRTSOCKET ns, int hs_version, struct sockaddr* peeraddr, char* streamid);
|
||||
void srtConnectCBWrapper(void* opaque, SRTSOCKET ns, int errorcode, struct sockaddr* peeraddr, int token);
|
||||
|
||||
int srtListenCB(void* opaque, SRTSOCKET ns, int hs_version, const struct sockaddr* peeraddr, const char* streamid);
|
||||
void srtConnectCB(void* opaque, SRTSOCKET ns, int errorcode, const struct sockaddr* peeraddr, int token);
|
17
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/callback_c.go
generated
vendored
Normal file
17
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/callback_c.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include "callback.h"
|
||||
|
||||
int srtListenCB(void* opaque, SRTSOCKET ns, int hs_version, const struct sockaddr* peeraddr, const char* streamid)
|
||||
{
|
||||
return srtListenCBWrapper(opaque, ns, hs_version, (struct sockaddr*)peeraddr, (char*)streamid);
|
||||
}
|
||||
|
||||
void srtConnectCB(void* opaque, SRTSOCKET ns, int errorcode, const struct sockaddr* peeraddr, int token)
|
||||
{
|
||||
srtConnectCBWrapper(opaque, ns, errorcode, (struct sockaddr*)peeraddr, token);
|
||||
}
|
||||
*/
|
||||
import "C"
|
242
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/errors.go
generated
vendored
Normal file
242
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,242 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include <srt/srt.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type SrtInvalidSock struct{}
|
||||
type SrtRendezvousUnbound struct{}
|
||||
type SrtSockConnected struct{}
|
||||
type SrtConnectionRejected struct{}
|
||||
type SrtConnectTimeout struct{}
|
||||
type SrtSocketClosed struct{}
|
||||
type SrtEpollTimeout struct{}
|
||||
|
||||
func (m *SrtInvalidSock) Error() string {
|
||||
return "Socket u indicates no valid socket ID"
|
||||
}
|
||||
|
||||
func (m *SrtRendezvousUnbound) Error() string {
|
||||
return "Socket u is in rendezvous mode, but it wasn't bound"
|
||||
}
|
||||
|
||||
func (m *SrtSockConnected) Error() string {
|
||||
return "Socket u is already connected"
|
||||
}
|
||||
|
||||
func (m *SrtConnectionRejected) Error() string {
|
||||
return "Connection has been rejected"
|
||||
}
|
||||
|
||||
func (m *SrtConnectTimeout) Error() string {
|
||||
return "Connection has been timed out"
|
||||
}
|
||||
|
||||
func (m *SrtSocketClosed) Error() string {
|
||||
return "The socket has been closed"
|
||||
}
|
||||
|
||||
func (m *SrtEpollTimeout) Error() string {
|
||||
return "Operation has timed out"
|
||||
}
|
||||
|
||||
func (m *SrtEpollTimeout) Timeout() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *SrtEpollTimeout) Temporary() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
//MUST be called from same OS thread that generated the error (i.e.: use runtime.LockOSThread())
|
||||
func srtGetAndClearError() error {
|
||||
defer C.srt_clearlasterror()
|
||||
eSysErrno := C.int(0)
|
||||
errno := C.srt_getlasterror(&eSysErrno)
|
||||
srterr := SRTErrno(errno)
|
||||
if eSysErrno != 0 {
|
||||
return srterr.wrapSysErr(syscall.Errno(eSysErrno))
|
||||
}
|
||||
return srterr
|
||||
}
|
||||
|
||||
//Based of off golang errno handling: https://cs.opensource.google/go/go/+/refs/tags/go1.16.6:src/syscall/syscall_unix.go;l=114
|
||||
type SRTErrno int
|
||||
|
||||
func (e SRTErrno) Error() string {
|
||||
//Workaround for unknown being -1
|
||||
if e == Unknown {
|
||||
return "Internal error when setting the right error code"
|
||||
}
|
||||
if 0 <= int(e) && int(e) < len(srterrors) {
|
||||
s := srterrors[e]
|
||||
if s != "" {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return "srterrno: " + strconv.Itoa(int(e))
|
||||
}
|
||||
|
||||
func (e SRTErrno) Is(target error) bool {
|
||||
//for backwards compat
|
||||
switch target.(type) {
|
||||
case *SrtInvalidSock:
|
||||
return e == EInvSock
|
||||
case *SrtRendezvousUnbound:
|
||||
return e == ERdvUnbound
|
||||
case *SrtSockConnected:
|
||||
return e == EConnSock
|
||||
case *SrtConnectionRejected:
|
||||
return e == EConnRej
|
||||
case *SrtConnectTimeout:
|
||||
return e == ETimeout
|
||||
case *SrtSocketClosed:
|
||||
return e == ESClosed
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e SRTErrno) Temporary() bool {
|
||||
return e == EAsyncFAIL || e == EAsyncRCV || e == EAsyncSND || e == ECongest || e == ETimeout
|
||||
}
|
||||
|
||||
func (e SRTErrno) Timeout() bool {
|
||||
return e == ETimeout
|
||||
}
|
||||
|
||||
func (e SRTErrno) wrapSysErr(errno syscall.Errno) error {
|
||||
return &srtErrnoSysErrnoWrapped{
|
||||
e: e,
|
||||
eSys: errno,
|
||||
}
|
||||
}
|
||||
|
||||
type srtErrnoSysErrnoWrapped struct {
|
||||
e SRTErrno
|
||||
eSys syscall.Errno
|
||||
}
|
||||
|
||||
func (e *srtErrnoSysErrnoWrapped) Error() string {
|
||||
return e.e.Error()
|
||||
}
|
||||
|
||||
func (e *srtErrnoSysErrnoWrapped) Is(target error) bool {
|
||||
return e.e.Is(target)
|
||||
}
|
||||
|
||||
func (e *srtErrnoSysErrnoWrapped) Temporary() bool {
|
||||
return e.e.Temporary()
|
||||
}
|
||||
|
||||
func (e *srtErrnoSysErrnoWrapped) Timeout() bool {
|
||||
return e.e.Timeout()
|
||||
}
|
||||
|
||||
func (e *srtErrnoSysErrnoWrapped) Unwrap() error {
|
||||
return error(e.eSys)
|
||||
}
|
||||
|
||||
//Shadows SRT_ERRNO srtcore/srt.h line 490+
|
||||
const (
|
||||
Unknown = SRTErrno(C.SRT_EUNKNOWN)
|
||||
Success = SRTErrno(C.SRT_SUCCESS)
|
||||
//Major: SETUP
|
||||
EConnSetup = SRTErrno(C.SRT_ECONNSETUP)
|
||||
ENoServer = SRTErrno(C.SRT_ENOSERVER)
|
||||
EConnRej = SRTErrno(C.SRT_ECONNREJ)
|
||||
ESockFail = SRTErrno(C.SRT_ESOCKFAIL)
|
||||
ESecFail = SRTErrno(C.SRT_ESECFAIL)
|
||||
ESClosed = SRTErrno(C.SRT_ESCLOSED)
|
||||
//Major: CONNECTION
|
||||
EConnFail = SRTErrno(C.SRT_ECONNFAIL)
|
||||
EConnLost = SRTErrno(C.SRT_ECONNLOST)
|
||||
ENoConn = SRTErrno(C.SRT_ENOCONN)
|
||||
//Major: SYSTEMRES
|
||||
EResource = SRTErrno(C.SRT_ERESOURCE)
|
||||
EThread = SRTErrno(C.SRT_ETHREAD)
|
||||
EnoBuf = SRTErrno(C.SRT_ENOBUF)
|
||||
ESysObj = SRTErrno(C.SRT_ESYSOBJ)
|
||||
//Major: FILESYSTEM
|
||||
EFile = SRTErrno(C.SRT_EFILE)
|
||||
EInvRdOff = SRTErrno(C.SRT_EINVRDOFF)
|
||||
ERdPerm = SRTErrno(C.SRT_ERDPERM)
|
||||
EInvWrOff = SRTErrno(C.SRT_EINVWROFF)
|
||||
EWrPerm = SRTErrno(C.SRT_EWRPERM)
|
||||
//Major: NOTSUP
|
||||
EInvOp = SRTErrno(C.SRT_EINVOP)
|
||||
EBoundSock = SRTErrno(C.SRT_EBOUNDSOCK)
|
||||
EConnSock = SRTErrno(C.SRT_ECONNSOCK)
|
||||
EInvParam = SRTErrno(C.SRT_EINVPARAM)
|
||||
EInvSock = SRTErrno(C.SRT_EINVSOCK)
|
||||
EUnboundSock = SRTErrno(C.SRT_EUNBOUNDSOCK)
|
||||
ENoListen = SRTErrno(C.SRT_ENOLISTEN)
|
||||
ERdvNoServ = SRTErrno(C.SRT_ERDVNOSERV)
|
||||
ERdvUnbound = SRTErrno(C.SRT_ERDVUNBOUND)
|
||||
EInvalMsgAPI = SRTErrno(C.SRT_EINVALMSGAPI)
|
||||
EInvalBufferAPI = SRTErrno(C.SRT_EINVALBUFFERAPI)
|
||||
EDupListen = SRTErrno(C.SRT_EDUPLISTEN)
|
||||
ELargeMsg = SRTErrno(C.SRT_ELARGEMSG)
|
||||
EInvPollID = SRTErrno(C.SRT_EINVPOLLID)
|
||||
EPollEmpty = SRTErrno(C.SRT_EPOLLEMPTY)
|
||||
//EBindConflict = SRTErrno(C.SRT_EBINDCONFLICT)
|
||||
//Major: AGAIN
|
||||
EAsyncFAIL = SRTErrno(C.SRT_EASYNCFAIL)
|
||||
EAsyncSND = SRTErrno(C.SRT_EASYNCSND)
|
||||
EAsyncRCV = SRTErrno(C.SRT_EASYNCRCV)
|
||||
ETimeout = SRTErrno(C.SRT_ETIMEOUT)
|
||||
ECongest = SRTErrno(C.SRT_ECONGEST)
|
||||
//Major: PEERERROR
|
||||
EPeer = SRTErrno(C.SRT_EPEERERR)
|
||||
)
|
||||
|
||||
//Unknown cannot be here since it would have a negative index!
|
||||
//Error strings taken from: https://github.com/Haivision/srt/blob/master/docs/API/API-functions.md
|
||||
var srterrors = [...]string{
|
||||
Success: "The value set when the last error was cleared and no error has occurred since then",
|
||||
EConnSetup: "General setup error resulting from internal system state",
|
||||
ENoServer: "Connection timed out while attempting to connect to the remote address",
|
||||
EConnRej: "Connection has been rejected",
|
||||
ESockFail: "An error occurred when trying to call a system function on an internally used UDP socket",
|
||||
ESecFail: "A possible tampering with the handshake packets was detected, or encryption request wasn't properly fulfilled.",
|
||||
ESClosed: "A socket that was vital for an operation called in blocking mode has been closed during the operation",
|
||||
EConnFail: "General connection failure of unknown details",
|
||||
EConnLost: "The socket was properly connected, but the connection has been broken",
|
||||
ENoConn: "The socket is not connected",
|
||||
EResource: "System or standard library error reported unexpectedly for unknown purpose",
|
||||
EThread: "System was unable to spawn a new thread when requried",
|
||||
EnoBuf: "System was unable to allocate memory for buffers",
|
||||
ESysObj: "System was unable to allocate system specific objects",
|
||||
EFile: "General filesystem error (for functions operating with file transmission)",
|
||||
EInvRdOff: "Failure when trying to read from a given position in the file",
|
||||
ERdPerm: "Read permission was denied when trying to read from file",
|
||||
EInvWrOff: "Failed to set position in the written file",
|
||||
EWrPerm: "Write permission was denied when trying to write to a file",
|
||||
EInvOp: "Invalid operation performed for the current state of a socket",
|
||||
EBoundSock: "The socket is currently bound and the required operation cannot be performed in this state",
|
||||
EConnSock: "The socket is currently connected and therefore performing the required operation is not possible",
|
||||
EInvParam: "Call parameters for API functions have some requirements that were not satisfied",
|
||||
EInvSock: "The API function required an ID of an entity (socket or group) and it was invalid",
|
||||
EUnboundSock: "The operation to be performed on a socket requires that it first be explicitly bound",
|
||||
ENoListen: "The socket passed for the operation is required to be in the listen state",
|
||||
ERdvNoServ: "The required operation cannot be performed when the socket is set to rendezvous mode",
|
||||
ERdvUnbound: "An attempt was made to connect to a socket set to rendezvous mode that was not first bound",
|
||||
EInvalMsgAPI: "The function was used incorrectly in the message API",
|
||||
EInvalBufferAPI: "The function was used incorrectly in the stream (buffer) API",
|
||||
EDupListen: "The port tried to be bound for listening is already busy",
|
||||
ELargeMsg: "Size exceeded",
|
||||
EInvPollID: "The epoll ID passed to an epoll function is invalid",
|
||||
EPollEmpty: "The epoll container currently has no subscribed sockets",
|
||||
//EBindConflict: "SRT_EBINDCONFLICT",
|
||||
EAsyncFAIL: "General asynchronous failure (not in use currently)",
|
||||
EAsyncSND: "Sending operation is not ready to perform",
|
||||
EAsyncRCV: "Receiving operation is not ready to perform",
|
||||
ETimeout: "The operation timed out",
|
||||
ECongest: "With SRTO_TSBPDMODE and SRTO_TLPKTDROP set to true, some packets were dropped by sender",
|
||||
EPeer: "Receiver peer is writing to a file that the agent is sending",
|
||||
}
|
66
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/logging.go
generated
vendored
Normal file
66
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/logging.go
generated
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include <srt/srt.h>
|
||||
extern void srtLogCB(void* opaque, int level, const char* file, int line, const char* area, const char* message);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
gopointer "github.com/mattn/go-pointer"
|
||||
)
|
||||
|
||||
type LogCallBackFunc func(level SrtLogLevel, file string, line int, area, message string)
|
||||
|
||||
type SrtLogLevel int
|
||||
|
||||
const (
|
||||
// SrtLogLevelEmerg = int(C.LOG_EMERG)
|
||||
// SrtLogLevelAlert = int(C.LOG_ALERT)
|
||||
SrtLogLevelCrit SrtLogLevel = SrtLogLevel(C.LOG_CRIT)
|
||||
SrtLogLevelErr SrtLogLevel = SrtLogLevel(C.LOG_ERR)
|
||||
SrtLogLevelWarning SrtLogLevel = SrtLogLevel(C.LOG_WARNING)
|
||||
SrtLogLevelNotice SrtLogLevel = SrtLogLevel(C.LOG_NOTICE)
|
||||
SrtLogLevelInfo SrtLogLevel = SrtLogLevel(C.LOG_INFO)
|
||||
SrtLogLevelDebug SrtLogLevel = SrtLogLevel(C.LOG_DEBUG)
|
||||
SrtLogLevelTrace SrtLogLevel = SrtLogLevel(8)
|
||||
)
|
||||
|
||||
var (
|
||||
logCBPtr unsafe.Pointer = nil
|
||||
logCBPtrLock sync.Mutex
|
||||
)
|
||||
|
||||
//export srtLogCBWrapper
|
||||
func srtLogCBWrapper(arg unsafe.Pointer, level C.int, file *C.char, line C.int, area, message *C.char) {
|
||||
userCB := gopointer.Restore(arg).(LogCallBackFunc)
|
||||
go userCB(SrtLogLevel(level), C.GoString(file), int(line), C.GoString(area), C.GoString(message))
|
||||
}
|
||||
|
||||
func SrtSetLogLevel(level SrtLogLevel) {
|
||||
C.srt_setloglevel(C.int(level))
|
||||
}
|
||||
|
||||
func SrtSetLogHandler(cb LogCallBackFunc) {
|
||||
ptr := gopointer.Save(cb)
|
||||
C.srt_setloghandler(ptr, (*C.SRT_LOG_HANDLER_FN)(C.srtLogCB))
|
||||
storeLogCBPtr(ptr)
|
||||
}
|
||||
|
||||
func SrtUnsetLogHandler() {
|
||||
C.srt_setloghandler(nil, nil)
|
||||
storeLogCBPtr(nil)
|
||||
}
|
||||
|
||||
func storeLogCBPtr(ptr unsafe.Pointer) {
|
||||
logCBPtrLock.Lock()
|
||||
defer logCBPtrLock.Unlock()
|
||||
if logCBPtr != nil {
|
||||
gopointer.Unref(logCBPtr)
|
||||
}
|
||||
logCBPtr = ptr
|
||||
}
|
14
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/logging_c.go
generated
vendored
Normal file
14
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/logging_c.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include <srt/srt.h>
|
||||
|
||||
extern void srtLogCBWrapper (void* opaque, int level, char* file, int line, char* area, char* message);
|
||||
|
||||
void srtLogCB(void* opaque, int level, const char* file, int line, const char* area, const char* message)
|
||||
{
|
||||
srtLogCBWrapper(opaque, level, (char*)file, line, (char*)area,(char*) message);
|
||||
}
|
||||
*/
|
||||
import "C"
|
87
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/netutils.go
generated
vendored
Normal file
87
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/netutils.go
generated
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
package srtgo
|
||||
|
||||
//#include <srt/srt.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func ntohs(val uint16) uint16 {
|
||||
tmp := ((*[unsafe.Sizeof(val)]byte)(unsafe.Pointer(&val)))
|
||||
return binary.BigEndian.Uint16((*tmp)[:])
|
||||
}
|
||||
|
||||
func udpAddrFromSockaddr(addr *syscall.RawSockaddrAny) (*net.UDPAddr, error) {
|
||||
var udpAddr net.UDPAddr
|
||||
|
||||
switch addr.Addr.Family {
|
||||
case afINET6:
|
||||
ptr := (*syscall.RawSockaddrInet6)(unsafe.Pointer(addr))
|
||||
udpAddr.Port = int(ntohs(ptr.Port))
|
||||
udpAddr.IP = ptr.Addr[:]
|
||||
|
||||
case afINET4:
|
||||
ptr := (*syscall.RawSockaddrInet4)(unsafe.Pointer(addr))
|
||||
udpAddr.Port = int(ntohs(ptr.Port))
|
||||
udpAddr.IP = net.IPv4(
|
||||
ptr.Addr[0],
|
||||
ptr.Addr[1],
|
||||
ptr.Addr[2],
|
||||
ptr.Addr[3],
|
||||
)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown address family: %v", addr.Addr.Family)
|
||||
}
|
||||
|
||||
return &udpAddr, nil
|
||||
}
|
||||
|
||||
func sockAddrFromIp4(ip net.IP, port uint16) (*C.struct_sockaddr, int, error) {
|
||||
var raw syscall.RawSockaddrInet4
|
||||
raw.Family = afINET4
|
||||
|
||||
p := (*[2]byte)(unsafe.Pointer(&raw.Port))
|
||||
p[0] = byte(port >> 8)
|
||||
p[1] = byte(port)
|
||||
|
||||
copy(raw.Addr[:], ip.To4())
|
||||
|
||||
return (*C.struct_sockaddr)(unsafe.Pointer(&raw)), int(sizeofSockAddrInet4), nil
|
||||
}
|
||||
|
||||
func sockAddrFromIp6(ip net.IP, port uint16) (*C.struct_sockaddr, int, error) {
|
||||
var raw syscall.RawSockaddrInet6
|
||||
raw.Family = afINET6
|
||||
|
||||
p := (*[2]byte)(unsafe.Pointer(&raw.Port))
|
||||
p[0] = byte(port >> 8)
|
||||
p[1] = byte(port)
|
||||
|
||||
copy(raw.Addr[:], ip.To16())
|
||||
|
||||
return (*C.struct_sockaddr)(unsafe.Pointer(&raw)), int(sizeofSockAddrInet6), nil
|
||||
}
|
||||
|
||||
func CreateAddrInet(name string, port uint16) (*C.struct_sockaddr, int, error) {
|
||||
ip := net.ParseIP(name)
|
||||
if ip == nil {
|
||||
ips, err := net.LookupIP(name)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("Error in CreateAddrInet, LookupIP")
|
||||
}
|
||||
ip = ips[0]
|
||||
}
|
||||
|
||||
if ip.To4() != nil {
|
||||
return sockAddrFromIp4(ip, port)
|
||||
} else if ip.To16() != nil {
|
||||
return sockAddrFromIp6(ip, port)
|
||||
}
|
||||
|
||||
return nil, 0, fmt.Errorf("Error in CreateAddrInet, LookupIP")
|
||||
}
|
17
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/netutils_unix.go
generated
vendored
Normal file
17
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/netutils_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
//go:build !windows
|
||||
|
||||
package srtgo
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
sizeofSockAddrInet4 = syscall.SizeofSockaddrInet4
|
||||
sizeofSockAddrInet6 = syscall.SizeofSockaddrInet6
|
||||
sizeofSockaddrAny = syscall.SizeofSockaddrAny
|
||||
afINET4 = unix.AF_INET
|
||||
afINET6 = unix.AF_INET6
|
||||
)
|
29
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/netutils_windows.go
generated
vendored
Normal file
29
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/netutils_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
//go:build windows
|
||||
|
||||
package srtgo
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
afINET4 = windows.AF_INET
|
||||
afINET6 = windows.AF_INET6
|
||||
)
|
||||
|
||||
var (
|
||||
sizeofSockAddrInet4 uint64 = 0
|
||||
sizeofSockAddrInet6 uint64 = 0
|
||||
sizeofSockaddrAny uint64 = 0
|
||||
)
|
||||
|
||||
func init() {
|
||||
inet4 := windows.RawSockaddrInet4{}
|
||||
inet6 := windows.RawSockaddrInet6{}
|
||||
any := windows.RawSockaddrAny{}
|
||||
sizeofSockAddrInet4 = uint64(unsafe.Sizeof(inet4))
|
||||
sizeofSockAddrInet6 = uint64(unsafe.Sizeof(inet6))
|
||||
sizeofSockaddrAny = uint64(unsafe.Sizeof(any))
|
||||
}
|
269
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/poll.go
generated
vendored
Normal file
269
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/poll.go
generated
vendored
Normal file
|
@ -0,0 +1,269 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include <srt/srt.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
pollDefault = int32(iota)
|
||||
pollReady = int32(iota)
|
||||
pollWait = int32(iota)
|
||||
)
|
||||
|
||||
type PollMode int
|
||||
|
||||
const (
|
||||
ModeRead = PollMode(iota)
|
||||
ModeWrite
|
||||
)
|
||||
|
||||
/*
|
||||
pollDesc contains the polling state for the associated SrtSocket
|
||||
closing: socket is closing, reject all poll operations
|
||||
pollErr: an error occured on the socket, indicates it's not useable anymore.
|
||||
unblockRd: is used to unblock the poller when the socket becomes ready for io
|
||||
rdState: polling state for read operations
|
||||
rdDeadline: deadline in NS before poll operation times out, -1 means timedout (needs to be cleared), 0 is without timeout
|
||||
rdSeq: sequence number protects against spurious signalling of timeouts when timer is reset.
|
||||
rdTimer: timer used to enforce deadline.
|
||||
*/
|
||||
type pollDesc struct {
|
||||
lock sync.Mutex
|
||||
closing bool
|
||||
fd C.SRTSOCKET
|
||||
pollErr bool
|
||||
unblockRd chan interface{}
|
||||
rdState int32
|
||||
rdLock sync.Mutex
|
||||
rdDeadline int64
|
||||
rdSeq int64
|
||||
rdTimer *time.Timer
|
||||
rtSeq int64
|
||||
unblockWr chan interface{}
|
||||
wrState int32
|
||||
wrLock sync.Mutex
|
||||
wdDeadline int64
|
||||
wdSeq int64
|
||||
wdTimer *time.Timer
|
||||
wtSeq int64
|
||||
pollS *pollServer
|
||||
}
|
||||
|
||||
var pdPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &pollDesc{
|
||||
unblockRd: make(chan interface{}, 1),
|
||||
unblockWr: make(chan interface{}, 1),
|
||||
rdTimer: time.NewTimer(0),
|
||||
wdTimer: time.NewTimer(0),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func pollDescInit(s C.SRTSOCKET) *pollDesc {
|
||||
pd := pdPool.Get().(*pollDesc)
|
||||
pd.lock.Lock()
|
||||
defer pd.lock.Unlock()
|
||||
pd.fd = s
|
||||
pd.rdState = pollDefault
|
||||
pd.wrState = pollDefault
|
||||
pd.pollS = pollServerCtx()
|
||||
pd.closing = false
|
||||
pd.pollErr = false
|
||||
pd.rdSeq++
|
||||
pd.wdSeq++
|
||||
pd.pollS.pollOpen(pd)
|
||||
return pd
|
||||
}
|
||||
|
||||
func (pd *pollDesc) release() {
|
||||
pd.lock.Lock()
|
||||
defer pd.lock.Unlock()
|
||||
if !pd.closing || pd.rdState == pollWait || pd.wrState == pollWait {
|
||||
panic("returning open or blocked upon pollDesc")
|
||||
}
|
||||
pd.fd = 0
|
||||
pdPool.Put(pd)
|
||||
}
|
||||
|
||||
func (pd *pollDesc) wait(mode PollMode) error {
|
||||
defer pd.reset(mode)
|
||||
if err := pd.checkPollErr(mode); err != nil {
|
||||
return err
|
||||
}
|
||||
state := &pd.rdState
|
||||
unblockChan := pd.unblockRd
|
||||
expiryChan := pd.rdTimer.C
|
||||
timerSeq := int64(0)
|
||||
pd.lock.Lock()
|
||||
if mode == ModeRead {
|
||||
timerSeq = pd.rtSeq
|
||||
pd.rdLock.Lock()
|
||||
defer pd.rdLock.Unlock()
|
||||
} else if mode == ModeWrite {
|
||||
timerSeq = pd.wtSeq
|
||||
state = &pd.wrState
|
||||
unblockChan = pd.unblockWr
|
||||
expiryChan = pd.wdTimer.C
|
||||
pd.wrLock.Lock()
|
||||
defer pd.wrLock.Unlock()
|
||||
}
|
||||
|
||||
for {
|
||||
old := *state
|
||||
if old == pollReady {
|
||||
*state = pollDefault
|
||||
pd.lock.Unlock()
|
||||
return nil
|
||||
}
|
||||
if atomic.CompareAndSwapInt32(state, pollDefault, pollWait) {
|
||||
break
|
||||
}
|
||||
}
|
||||
pd.lock.Unlock()
|
||||
|
||||
wait:
|
||||
for {
|
||||
select {
|
||||
case <-unblockChan:
|
||||
break wait
|
||||
case <-expiryChan:
|
||||
pd.lock.Lock()
|
||||
if mode == ModeRead {
|
||||
if timerSeq == pd.rdSeq {
|
||||
pd.rdDeadline = -1
|
||||
pd.lock.Unlock()
|
||||
break wait
|
||||
}
|
||||
timerSeq = pd.rtSeq
|
||||
}
|
||||
if mode == ModeWrite {
|
||||
if timerSeq == pd.wdSeq {
|
||||
pd.wdDeadline = -1
|
||||
pd.lock.Unlock()
|
||||
break wait
|
||||
}
|
||||
timerSeq = pd.wtSeq
|
||||
}
|
||||
pd.lock.Unlock()
|
||||
}
|
||||
}
|
||||
err := pd.checkPollErr(mode)
|
||||
return err
|
||||
}
|
||||
|
||||
func (pd *pollDesc) close() {
|
||||
pd.lock.Lock()
|
||||
defer pd.lock.Unlock()
|
||||
if pd.closing {
|
||||
return
|
||||
}
|
||||
pd.closing = true
|
||||
pd.pollS.pollClose(pd)
|
||||
}
|
||||
|
||||
func (pd *pollDesc) checkPollErr(mode PollMode) error {
|
||||
pd.lock.Lock()
|
||||
defer pd.lock.Unlock()
|
||||
if pd.closing {
|
||||
return &SrtSocketClosed{}
|
||||
}
|
||||
|
||||
if mode == ModeRead && pd.rdDeadline < 0 || mode == ModeWrite && pd.wdDeadline < 0 {
|
||||
return &SrtEpollTimeout{}
|
||||
}
|
||||
|
||||
if pd.pollErr {
|
||||
return &SrtSocketClosed{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pd *pollDesc) setDeadline(t time.Time, mode PollMode) {
|
||||
pd.lock.Lock()
|
||||
defer pd.lock.Unlock()
|
||||
var d int64
|
||||
if !t.IsZero() {
|
||||
d = int64(time.Until(t))
|
||||
if d == 0 {
|
||||
d = -1
|
||||
}
|
||||
}
|
||||
if mode == ModeRead || mode == ModeRead+ModeWrite {
|
||||
pd.rdSeq++
|
||||
pd.rtSeq = pd.rdSeq
|
||||
if pd.rdDeadline > 0 {
|
||||
pd.rdTimer.Stop()
|
||||
}
|
||||
pd.rdDeadline = d
|
||||
if d > 0 {
|
||||
pd.rdTimer.Reset(time.Duration(d))
|
||||
}
|
||||
if d < 0 {
|
||||
pd.unblock(ModeRead, false, false)
|
||||
}
|
||||
}
|
||||
if mode == ModeWrite || mode == ModeRead+ModeWrite {
|
||||
pd.wdSeq++
|
||||
pd.wtSeq = pd.wdSeq
|
||||
if pd.wdDeadline > 0 {
|
||||
pd.wdTimer.Stop()
|
||||
}
|
||||
pd.wdDeadline = d
|
||||
if d > 0 {
|
||||
pd.wdTimer.Reset(time.Duration(d))
|
||||
}
|
||||
if d < 0 {
|
||||
pd.unblock(ModeWrite, false, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *pollDesc) unblock(mode PollMode, pollerr, ioready bool) {
|
||||
if pollerr {
|
||||
pd.lock.Lock()
|
||||
pd.pollErr = pollerr
|
||||
pd.lock.Unlock()
|
||||
}
|
||||
state := &pd.rdState
|
||||
unblockChan := pd.unblockRd
|
||||
if mode == ModeWrite {
|
||||
state = &pd.wrState
|
||||
unblockChan = pd.unblockWr
|
||||
}
|
||||
pd.lock.Lock()
|
||||
old := atomic.LoadInt32(state)
|
||||
if ioready {
|
||||
atomic.StoreInt32(state, pollReady)
|
||||
}
|
||||
pd.lock.Unlock()
|
||||
if old == pollWait {
|
||||
//make sure we never block here
|
||||
select {
|
||||
case unblockChan <- struct{}{}:
|
||||
//
|
||||
default:
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *pollDesc) reset(mode PollMode) {
|
||||
if mode == ModeRead {
|
||||
pd.rdLock.Lock()
|
||||
pd.rdState = pollDefault
|
||||
pd.rdLock.Unlock()
|
||||
} else if mode == ModeWrite {
|
||||
pd.wrLock.Lock()
|
||||
pd.wrState = pollDefault
|
||||
pd.wrLock.Unlock()
|
||||
}
|
||||
}
|
109
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/pollserver.go
generated
vendored
Normal file
109
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/pollserver.go
generated
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include <srt/srt.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
phctx *pollServer
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
func pollServerCtx() *pollServer {
|
||||
once.Do(pollServerCtxInit)
|
||||
return phctx
|
||||
}
|
||||
|
||||
func pollServerCtxInit() {
|
||||
eid := C.srt_epoll_create()
|
||||
C.srt_epoll_set(eid, C.SRT_EPOLL_ENABLE_EMPTY)
|
||||
phctx = &pollServer{
|
||||
srtEpollDescr: eid,
|
||||
pollDescs: make(map[C.SRTSOCKET]*pollDesc),
|
||||
}
|
||||
go phctx.run()
|
||||
}
|
||||
|
||||
type pollServer struct {
|
||||
srtEpollDescr C.int
|
||||
pollDescLock sync.Mutex
|
||||
pollDescs map[C.SRTSOCKET]*pollDesc
|
||||
}
|
||||
|
||||
func (p *pollServer) pollOpen(pd *pollDesc) {
|
||||
//use uint because otherwise with ET it would overflow :/ (srt should accept an uint instead, or fix it's SRT_EPOLL_ET definition)
|
||||
events := C.uint(C.SRT_EPOLL_IN | C.SRT_EPOLL_OUT | C.SRT_EPOLL_ERR | C.SRT_EPOLL_ET)
|
||||
//via unsafe.Pointer because we cannot cast *C.uint to *C.int directly
|
||||
//block poller
|
||||
p.pollDescLock.Lock()
|
||||
ret := C.srt_epoll_add_usock(p.srtEpollDescr, pd.fd, (*C.int)(unsafe.Pointer(&events)))
|
||||
if ret == -1 {
|
||||
panic("ERROR ADDING FD TO EPOLL")
|
||||
}
|
||||
p.pollDescs[pd.fd] = pd
|
||||
p.pollDescLock.Unlock()
|
||||
}
|
||||
|
||||
func (p *pollServer) pollClose(pd *pollDesc) {
|
||||
sockstate := C.srt_getsockstate(pd.fd)
|
||||
//Broken/closed sockets get removed internally by SRT lib
|
||||
if sockstate == C.SRTS_BROKEN || sockstate == C.SRTS_CLOSING || sockstate == C.SRTS_CLOSED || sockstate == C.SRTS_NONEXIST {
|
||||
return
|
||||
}
|
||||
ret := C.srt_epoll_remove_usock(p.srtEpollDescr, pd.fd)
|
||||
if ret == -1 {
|
||||
panic("ERROR REMOVING FD FROM EPOLL")
|
||||
}
|
||||
p.pollDescLock.Lock()
|
||||
delete(p.pollDescs, pd.fd)
|
||||
p.pollDescLock.Unlock()
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
}
|
||||
|
||||
func (p *pollServer) run() {
|
||||
timeoutMs := C.int64_t(-1)
|
||||
fds := [128]C.SRT_EPOLL_EVENT{}
|
||||
fdlen := C.int(128)
|
||||
for {
|
||||
res := C.srt_epoll_uwait(p.srtEpollDescr, &fds[0], fdlen, timeoutMs)
|
||||
if res == 0 {
|
||||
continue //Shouldn't happen with -1
|
||||
} else if res == -1 {
|
||||
panic("srt_epoll_error")
|
||||
} else if res > 0 {
|
||||
max := int(res)
|
||||
if fdlen < res {
|
||||
max = int(fdlen)
|
||||
}
|
||||
p.pollDescLock.Lock()
|
||||
for i := 0; i < max; i++ {
|
||||
s := fds[i].fd
|
||||
events := fds[i].events
|
||||
|
||||
pd := p.pollDescs[s]
|
||||
if events&C.SRT_EPOLL_ERR != 0 {
|
||||
pd.unblock(ModeRead, true, false)
|
||||
pd.unblock(ModeWrite, true, false)
|
||||
continue
|
||||
}
|
||||
if events&C.SRT_EPOLL_IN != 0 {
|
||||
pd.unblock(ModeRead, false, true)
|
||||
}
|
||||
if events&C.SRT_EPOLL_OUT != 0 {
|
||||
pd.unblock(ModeWrite, false, true)
|
||||
}
|
||||
}
|
||||
p.pollDescLock.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
54
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/read.go
generated
vendored
Normal file
54
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/read.go
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include <srt/srt.h>
|
||||
|
||||
int srt_recvmsg2_wrapped(SRTSOCKET u, char* buf, int len, SRT_MSGCTRL *mctrl, int *srterror, int *syserror)
|
||||
{
|
||||
int ret = srt_recvmsg2(u, buf, len, mctrl);
|
||||
if (ret < 0) {
|
||||
*srterror = srt_getlasterror(syserror);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func srtRecvMsg2Impl(u C.SRTSOCKET, buf []byte, msgctrl *C.SRT_MSGCTRL) (n int, err error) {
|
||||
srterr := C.int(0)
|
||||
syserr := C.int(0)
|
||||
n = int(C.srt_recvmsg2_wrapped(u, (*C.char)(unsafe.Pointer(&buf[0])), C.int(len(buf)), msgctrl, &srterr, &syserr))
|
||||
if n < 0 {
|
||||
srterror := SRTErrno(srterr)
|
||||
if syserr < 0 {
|
||||
srterror.wrapSysErr(syscall.Errno(syserr))
|
||||
}
|
||||
err = srterror
|
||||
n = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Read data from the SRT socket
|
||||
func (s SrtSocket) Read(b []byte) (n int, err error) {
|
||||
//Fastpath
|
||||
if !s.blocking {
|
||||
s.pd.reset(ModeRead)
|
||||
}
|
||||
n, err = srtRecvMsg2Impl(s.socket, b, nil)
|
||||
|
||||
for {
|
||||
if !errors.Is(err, error(EAsyncRCV)) || s.blocking {
|
||||
return
|
||||
}
|
||||
s.pd.wait(ModeRead)
|
||||
n, err = srtRecvMsg2Impl(s.socket, b, nil)
|
||||
}
|
||||
}
|
578
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/srtgo.go
generated
vendored
Normal file
578
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/srtgo.go
generated
vendored
Normal file
|
@ -0,0 +1,578 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include <srt/srt.h>
|
||||
#include <srt/access_control.h>
|
||||
#include "callback.h"
|
||||
static const SRTSOCKET get_srt_invalid_sock() { return SRT_INVALID_SOCK; };
|
||||
static const int get_srt_error() { return SRT_ERROR; };
|
||||
static const int get_srt_error_reject_predefined() { return SRT_REJC_PREDEFINED; };
|
||||
static const int get_srt_error_reject_userdefined() { return SRT_REJC_USERDEFINED; };
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
gopointer "github.com/mattn/go-pointer"
|
||||
)
|
||||
|
||||
// SRT Socket mode
|
||||
const (
|
||||
ModeFailure = iota
|
||||
ModeListener
|
||||
ModeCaller
|
||||
ModeRendezvouz
|
||||
)
|
||||
|
||||
// Binding ops
|
||||
const (
|
||||
bindingPre = 0
|
||||
bindingPost = 1
|
||||
)
|
||||
|
||||
// SrtSocket - SRT socket
|
||||
type SrtSocket struct {
|
||||
socket C.int
|
||||
blocking bool
|
||||
pd *pollDesc
|
||||
host string
|
||||
port uint16
|
||||
options map[string]string
|
||||
mode int
|
||||
pktSize int
|
||||
pollTimeout int64
|
||||
}
|
||||
|
||||
var (
|
||||
callbackMutex sync.Mutex
|
||||
listenCallbackMap map[C.int]unsafe.Pointer = make(map[C.int]unsafe.Pointer)
|
||||
connectCallbackMap map[C.int]unsafe.Pointer = make(map[C.int]unsafe.Pointer)
|
||||
)
|
||||
|
||||
// Static consts from library
|
||||
var (
|
||||
SRT_INVALID_SOCK = C.get_srt_invalid_sock()
|
||||
SRT_ERROR = C.get_srt_error()
|
||||
SRTS_CONNECTED = C.SRTS_CONNECTED
|
||||
)
|
||||
|
||||
const defaultPacketSize = 1456
|
||||
|
||||
// InitSRT - Initialize srt library
|
||||
func InitSRT() {
|
||||
C.srt_startup()
|
||||
}
|
||||
|
||||
// CleanupSRT - Cleanup SRT lib
|
||||
func CleanupSRT() {
|
||||
C.srt_cleanup()
|
||||
}
|
||||
|
||||
// NewSrtSocket - Create a new SRT Socket
|
||||
func NewSrtSocket(host string, port uint16, options map[string]string) *SrtSocket {
|
||||
s := new(SrtSocket)
|
||||
|
||||
s.socket = C.srt_create_socket()
|
||||
if s.socket == SRT_INVALID_SOCK {
|
||||
return nil
|
||||
}
|
||||
|
||||
s.host = host
|
||||
s.port = port
|
||||
s.options = options
|
||||
s.pollTimeout = -1
|
||||
|
||||
val, exists := options["pktsize"]
|
||||
if exists {
|
||||
pktSize, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
s.pktSize = pktSize
|
||||
}
|
||||
}
|
||||
if s.pktSize <= 0 {
|
||||
s.pktSize = defaultPacketSize
|
||||
}
|
||||
|
||||
val, exists = options["blocking"]
|
||||
if exists && val != "0" {
|
||||
s.blocking = true
|
||||
}
|
||||
|
||||
if !s.blocking {
|
||||
s.pd = pollDescInit(s.socket)
|
||||
}
|
||||
|
||||
finalizer := func(obj interface{}) {
|
||||
sf := obj.(*SrtSocket)
|
||||
sf.Close()
|
||||
if sf.pd != nil {
|
||||
sf.pd.release()
|
||||
}
|
||||
}
|
||||
|
||||
//Cleanup SrtSocket if no references exist anymore
|
||||
runtime.SetFinalizer(s, finalizer)
|
||||
|
||||
var err error
|
||||
s.mode, err = s.preconfiguration()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func newFromSocket(acceptSocket *SrtSocket, socket C.SRTSOCKET) (*SrtSocket, error) {
|
||||
s := new(SrtSocket)
|
||||
s.socket = socket
|
||||
s.pktSize = acceptSocket.pktSize
|
||||
s.blocking = acceptSocket.blocking
|
||||
s.pollTimeout = acceptSocket.pollTimeout
|
||||
|
||||
err := acceptSocket.postconfiguration(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !s.blocking {
|
||||
s.pd = pollDescInit(s.socket)
|
||||
}
|
||||
|
||||
finalizer := func(obj interface{}) {
|
||||
sf := obj.(*SrtSocket)
|
||||
sf.Close()
|
||||
if sf.pd != nil {
|
||||
sf.pd.release()
|
||||
}
|
||||
}
|
||||
|
||||
//Cleanup SrtSocket if no references exist anymore
|
||||
runtime.SetFinalizer(s, finalizer)
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s SrtSocket) GetSocket() C.int {
|
||||
return s.socket
|
||||
}
|
||||
|
||||
// Listen for incoming connections. The backlog setting defines how many sockets
|
||||
// may be allowed to wait until they are accepted (excessive connection requests
|
||||
// are rejected in advance)
|
||||
func (s *SrtSocket) Listen(backlog int) error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
nbacklog := C.int(backlog)
|
||||
|
||||
sa, salen, err := CreateAddrInet(s.host, s.port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res := C.srt_bind(s.socket, sa, C.int(salen))
|
||||
if res == SRT_ERROR {
|
||||
C.srt_close(s.socket)
|
||||
return fmt.Errorf("Error in srt_bind: %w", srtGetAndClearError())
|
||||
}
|
||||
|
||||
res = C.srt_listen(s.socket, nbacklog)
|
||||
if res == SRT_ERROR {
|
||||
C.srt_close(s.socket)
|
||||
return fmt.Errorf("Error in srt_listen: %w", srtGetAndClearError())
|
||||
}
|
||||
|
||||
err = s.postconfiguration(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error setting post socket options")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Connect to a remote endpoint
|
||||
func (s *SrtSocket) Connect() error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
sa, salen, err := CreateAddrInet(s.host, s.port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res := C.srt_connect(s.socket, sa, C.int(salen))
|
||||
if res == SRT_ERROR {
|
||||
C.srt_close(s.socket)
|
||||
return srtGetAndClearError()
|
||||
}
|
||||
|
||||
if !s.blocking {
|
||||
if err := s.pd.wait(ModeWrite); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = s.postconfiguration(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error setting post socket options in connect")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stats - Retrieve stats from the SRT socket
|
||||
func (s SrtSocket) Stats() (*SrtStats, error) {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
var stats C.SRT_TRACEBSTATS = C.SRT_TRACEBSTATS{}
|
||||
var b C.int = 1
|
||||
if C.srt_bstats(s.socket, &stats, b) == SRT_ERROR {
|
||||
return nil, fmt.Errorf("Error getting stats, %w", srtGetAndClearError())
|
||||
}
|
||||
|
||||
return newSrtStats(&stats), nil
|
||||
}
|
||||
|
||||
// Mode - Return working mode of the SRT socket
|
||||
func (s SrtSocket) Mode() int {
|
||||
return s.mode
|
||||
}
|
||||
|
||||
// PacketSize - Return packet size of the SRT socket
|
||||
func (s SrtSocket) PacketSize() int {
|
||||
return s.pktSize
|
||||
}
|
||||
|
||||
// PollTimeout - Return polling max time, for connect/read/write operations.
|
||||
// Only applied when socket is in non-blocking mode.
|
||||
func (s SrtSocket) PollTimeout() time.Duration {
|
||||
return time.Duration(s.pollTimeout) * time.Millisecond
|
||||
}
|
||||
|
||||
// SetPollTimeout - Sets polling max time, for connect/read/write operations.
|
||||
// Only applied when socket is in non-blocking mode.
|
||||
func (s *SrtSocket) SetPollTimeout(pollTimeout time.Duration) {
|
||||
s.pollTimeout = pollTimeout.Milliseconds()
|
||||
}
|
||||
|
||||
func (s *SrtSocket) SetDeadline(deadline time.Time) {
|
||||
s.pd.setDeadline(deadline, ModeRead+ModeWrite)
|
||||
}
|
||||
|
||||
func (s *SrtSocket) SetReadDeadline(deadline time.Time) {
|
||||
s.pd.setDeadline(deadline, ModeRead)
|
||||
}
|
||||
|
||||
func (s *SrtSocket) SetWriteDeadline(deadline time.Time) {
|
||||
s.pd.setDeadline(deadline, ModeWrite)
|
||||
}
|
||||
|
||||
// Close the SRT socket
|
||||
func (s *SrtSocket) Close() {
|
||||
|
||||
C.srt_close(s.socket)
|
||||
s.socket = SRT_INVALID_SOCK
|
||||
if !s.blocking {
|
||||
s.pd.close()
|
||||
}
|
||||
callbackMutex.Lock()
|
||||
if ptr, exists := listenCallbackMap[s.socket]; exists {
|
||||
gopointer.Unref(ptr)
|
||||
}
|
||||
if ptr, exists := connectCallbackMap[s.socket]; exists {
|
||||
gopointer.Unref(ptr)
|
||||
}
|
||||
callbackMutex.Unlock()
|
||||
}
|
||||
|
||||
// ListenCallbackFunc specifies a function to be called before a connecting socket is passed to accept
|
||||
type ListenCallbackFunc func(socket *SrtSocket, version int, addr *net.UDPAddr, streamid string) bool
|
||||
|
||||
//export srtListenCBWrapper
|
||||
func srtListenCBWrapper(arg unsafe.Pointer, socket C.SRTSOCKET, hsVersion C.int, peeraddr *C.struct_sockaddr, streamid *C.char) C.int {
|
||||
userCB := gopointer.Restore(arg).(ListenCallbackFunc)
|
||||
|
||||
s := new(SrtSocket)
|
||||
s.socket = socket
|
||||
udpAddr, _ := udpAddrFromSockaddr((*syscall.RawSockaddrAny)(unsafe.Pointer(peeraddr)))
|
||||
|
||||
if userCB(s, int(hsVersion), udpAddr, C.GoString(streamid)) {
|
||||
return 0
|
||||
}
|
||||
return SRT_ERROR
|
||||
}
|
||||
|
||||
// SetListenCallback - set a function to be called early in the handshake before a client
|
||||
// is handed to accept on a listening socket.
|
||||
// The connection can be rejected by returning false from the callback.
|
||||
// See examples/echo-receiver for more details.
|
||||
func (s SrtSocket) SetListenCallback(cb ListenCallbackFunc) {
|
||||
ptr := gopointer.Save(cb)
|
||||
C.srt_listen_callback(s.socket, (*C.srt_listen_callback_fn)(C.srtListenCB), ptr)
|
||||
|
||||
callbackMutex.Lock()
|
||||
defer callbackMutex.Unlock()
|
||||
if listenCallbackMap[s.socket] != nil {
|
||||
gopointer.Unref(listenCallbackMap[s.socket])
|
||||
}
|
||||
listenCallbackMap[s.socket] = ptr
|
||||
}
|
||||
|
||||
// ConnectCallbackFunc specifies a function to be called after a socket or connection in a group has failed.
|
||||
type ConnectCallbackFunc func(socket *SrtSocket, err error, addr *net.UDPAddr, token int)
|
||||
|
||||
//export srtConnectCBWrapper
|
||||
func srtConnectCBWrapper(arg unsafe.Pointer, socket C.SRTSOCKET, errcode C.int, peeraddr *C.struct_sockaddr, token C.int) {
|
||||
userCB := gopointer.Restore(arg).(ConnectCallbackFunc)
|
||||
|
||||
s := new(SrtSocket)
|
||||
s.socket = socket
|
||||
udpAddr, _ := udpAddrFromSockaddr((*syscall.RawSockaddrAny)(unsafe.Pointer(peeraddr)))
|
||||
|
||||
userCB(s, SRTErrno(errcode), udpAddr, int(token))
|
||||
}
|
||||
|
||||
// SetConnectCallback - set a function to be called after a socket or connection in a group has failed
|
||||
// Note that the function is not guaranteed to be called if the socket is set to blocking mode.
|
||||
func (s SrtSocket) SetConnectCallback(cb ConnectCallbackFunc) {
|
||||
ptr := gopointer.Save(cb)
|
||||
C.srt_connect_callback(s.socket, (*C.srt_connect_callback_fn)(C.srtConnectCB), ptr)
|
||||
|
||||
callbackMutex.Lock()
|
||||
defer callbackMutex.Unlock()
|
||||
if connectCallbackMap[s.socket] != nil {
|
||||
gopointer.Unref(connectCallbackMap[s.socket])
|
||||
}
|
||||
connectCallbackMap[s.socket] = ptr
|
||||
}
|
||||
|
||||
// Rejection reasons
|
||||
var (
|
||||
// Start of range for predefined rejection reasons
|
||||
RejectionReasonPredefined = int(C.get_srt_error_reject_predefined())
|
||||
|
||||
// General syntax error in the SocketID specification (also a fallback code for undefined cases)
|
||||
RejectionReasonBadRequest = RejectionReasonPredefined + 400
|
||||
|
||||
// Authentication failed, provided that the user was correctly identified and access to the required resource would be granted
|
||||
RejectionReasonUnauthorized = RejectionReasonPredefined + 401
|
||||
|
||||
// The server is too heavily loaded, or you have exceeded credits for accessing the service and the resource.
|
||||
RejectionReasonOverload = RejectionReasonPredefined + 402
|
||||
|
||||
// Access denied to the resource by any kind of reason
|
||||
RejectionReasonForbidden = RejectionReasonPredefined + 403
|
||||
|
||||
// Resource not found at this time.
|
||||
RejectionReasonNotFound = RejectionReasonPredefined + 404
|
||||
|
||||
// The mode specified in `m` key in StreamID is not supported for this request.
|
||||
RejectionReasonBadMode = RejectionReasonPredefined + 405
|
||||
|
||||
// The requested parameters specified in SocketID cannot be satisfied for the requested resource. Also when m=publish and the data format is not acceptable.
|
||||
RejectionReasonUnacceptable = RejectionReasonPredefined + 406
|
||||
|
||||
// Start of range for application defined rejection reasons
|
||||
RejectionReasonUserDefined = int(C.get_srt_error_reject_predefined())
|
||||
)
|
||||
|
||||
// SetRejectReason - set custom reason for connection reject
|
||||
func (s SrtSocket) SetRejectReason(value int) error {
|
||||
res := C.srt_setrejectreason(s.socket, C.int(value))
|
||||
if res == SRT_ERROR {
|
||||
return errors.New(C.GoString(C.srt_getlasterror_str()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSockOptByte - return byte value obtained with srt_getsockopt
|
||||
func (s SrtSocket) GetSockOptByte(opt int) (byte, error) {
|
||||
var v byte
|
||||
l := 1
|
||||
|
||||
err := s.getSockOpt(opt, unsafe.Pointer(&v), &l)
|
||||
return v, err
|
||||
}
|
||||
|
||||
// GetSockOptBool - return bool value obtained with srt_getsockopt
|
||||
func (s SrtSocket) GetSockOptBool(opt int) (bool, error) {
|
||||
var v int32
|
||||
l := 4
|
||||
|
||||
err := s.getSockOpt(opt, unsafe.Pointer(&v), &l)
|
||||
if v == 1 {
|
||||
return true, err
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
// GetSockOptInt - return int value obtained with srt_getsockopt
|
||||
func (s SrtSocket) GetSockOptInt(opt int) (int, error) {
|
||||
var v int32
|
||||
l := 4
|
||||
|
||||
err := s.getSockOpt(opt, unsafe.Pointer(&v), &l)
|
||||
return int(v), err
|
||||
}
|
||||
|
||||
// GetSockOptInt64 - return int64 value obtained with srt_getsockopt
|
||||
func (s SrtSocket) GetSockOptInt64(opt int) (int64, error) {
|
||||
var v int64
|
||||
l := 8
|
||||
|
||||
err := s.getSockOpt(opt, unsafe.Pointer(&v), &l)
|
||||
return v, err
|
||||
}
|
||||
|
||||
// GetSockOptString - return string value obtained with srt_getsockopt
|
||||
func (s SrtSocket) GetSockOptString(opt int) (string, error) {
|
||||
buf := make([]byte, 256)
|
||||
l := len(buf)
|
||||
|
||||
err := s.getSockOpt(opt, unsafe.Pointer(&buf[0]), &l)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(buf[:l]), nil
|
||||
}
|
||||
|
||||
// SetSockOptByte - set byte value using srt_setsockopt
|
||||
func (s SrtSocket) SetSockOptByte(opt int, value byte) error {
|
||||
return s.setSockOpt(opt, unsafe.Pointer(&value), 1)
|
||||
}
|
||||
|
||||
// SetSockOptBool - set bool value using srt_setsockopt
|
||||
func (s SrtSocket) SetSockOptBool(opt int, value bool) error {
|
||||
val := int(0)
|
||||
if value {
|
||||
val = 1
|
||||
}
|
||||
return s.setSockOpt(opt, unsafe.Pointer(&val), 4)
|
||||
}
|
||||
|
||||
// SetSockOptInt - set int value using srt_setsockopt
|
||||
func (s SrtSocket) SetSockOptInt(opt int, value int) error {
|
||||
return s.setSockOpt(opt, unsafe.Pointer(&value), 4)
|
||||
}
|
||||
|
||||
// SetSockOptInt64 - set int64 value using srt_setsockopt
|
||||
func (s SrtSocket) SetSockOptInt64(opt int, value int64) error {
|
||||
return s.setSockOpt(opt, unsafe.Pointer(&value), 8)
|
||||
}
|
||||
|
||||
// SetSockOptString - set string value using srt_setsockopt
|
||||
func (s SrtSocket) SetSockOptString(opt int, value string) error {
|
||||
return s.setSockOpt(opt, unsafe.Pointer(&[]byte(value)[0]), len(value))
|
||||
}
|
||||
|
||||
func (s SrtSocket) setSockOpt(opt int, data unsafe.Pointer, size int) error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
res := C.srt_setsockopt(s.socket, 0, C.SRT_SOCKOPT(opt), data, C.int(size))
|
||||
if res == -1 {
|
||||
return fmt.Errorf("Error calling srt_setsockopt %w", srtGetAndClearError())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s SrtSocket) getSockOpt(opt int, data unsafe.Pointer, size *int) error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
res := C.srt_getsockopt(s.socket, 0, C.SRT_SOCKOPT(opt), data, (*C.int)(unsafe.Pointer(size)))
|
||||
if res == -1 {
|
||||
return fmt.Errorf("Error calling srt_getsockopt %w", srtGetAndClearError())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s SrtSocket) preconfiguration() (int, error) {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
var blocking C.int
|
||||
if s.blocking {
|
||||
blocking = C.int(1)
|
||||
} else {
|
||||
blocking = C.int(0)
|
||||
}
|
||||
result := C.srt_setsockopt(s.socket, 0, C.SRTO_RCVSYN, unsafe.Pointer(&blocking), C.int(unsafe.Sizeof(blocking)))
|
||||
if result == -1 {
|
||||
return ModeFailure, fmt.Errorf("could not set SRTO_RCVSYN flag: %w", srtGetAndClearError())
|
||||
}
|
||||
|
||||
var mode int
|
||||
modeVal, ok := s.options["mode"]
|
||||
if !ok {
|
||||
modeVal = "default"
|
||||
}
|
||||
|
||||
if modeVal == "client" || modeVal == "caller" {
|
||||
mode = ModeCaller
|
||||
} else if modeVal == "server" || modeVal == "listener" {
|
||||
mode = ModeListener
|
||||
} else if modeVal == "default" {
|
||||
if s.host == "" {
|
||||
mode = ModeListener
|
||||
} else {
|
||||
// Host is given, so check also "adapter"
|
||||
if _, ok := s.options["adapter"]; ok {
|
||||
mode = ModeRendezvouz
|
||||
} else {
|
||||
mode = ModeCaller
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mode = ModeFailure
|
||||
}
|
||||
|
||||
if linger, ok := s.options["linger"]; ok {
|
||||
li, err := strconv.Atoi(linger)
|
||||
if err == nil {
|
||||
if err := setSocketLingerOption(s.socket, int32(li)); err != nil {
|
||||
return ModeFailure, fmt.Errorf("could not set LINGER option %w", err)
|
||||
}
|
||||
} else {
|
||||
return ModeFailure, fmt.Errorf("could not set LINGER option %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err := setSocketOptions(s.socket, bindingPre, s.options)
|
||||
if err != nil {
|
||||
return ModeFailure, fmt.Errorf("Error setting socket options: %w", err)
|
||||
}
|
||||
|
||||
return mode, nil
|
||||
}
|
||||
|
||||
func (s SrtSocket) postconfiguration(sck *SrtSocket) error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
var blocking C.int
|
||||
if s.blocking {
|
||||
blocking = 1
|
||||
} else {
|
||||
blocking = 0
|
||||
}
|
||||
|
||||
res := C.srt_setsockopt(sck.socket, 0, C.SRTO_SNDSYN, unsafe.Pointer(&blocking), C.int(unsafe.Sizeof(blocking)))
|
||||
if res == -1 {
|
||||
return fmt.Errorf("Error in postconfiguration setting SRTO_SNDSYN: %w", srtGetAndClearError())
|
||||
}
|
||||
|
||||
res = C.srt_setsockopt(sck.socket, 0, C.SRTO_RCVSYN, unsafe.Pointer(&blocking), C.int(unsafe.Sizeof(blocking)))
|
||||
if res == -1 {
|
||||
return fmt.Errorf("Error in postconfiguration setting SRTO_RCVSYN: %w", srtGetAndClearError())
|
||||
}
|
||||
|
||||
err := setSocketOptions(sck.socket, bindingPost, s.options)
|
||||
return err
|
||||
}
|
191
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/srtsocketoptions.go
generated
vendored
Normal file
191
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/srtsocketoptions.go
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
|||
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
|
||||
}
|
188
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/srtstats.go
generated
vendored
Normal file
188
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/srtstats.go
generated
vendored
Normal file
|
@ -0,0 +1,188 @@
|
|||
package srtgo
|
||||
|
||||
// #cgo LDFLAGS: -lsrt
|
||||
// #include <srt/srt.h>
|
||||
import "C"
|
||||
|
||||
type SrtStats struct {
|
||||
// Global measurements
|
||||
MsTimeStamp int64 // time since the UDT entity is started, in milliseconds
|
||||
PktSentTotal int64 // total number of sent data packets, including retransmissions
|
||||
PktRecvTotal int64 // total number of received packets
|
||||
PktSndLossTotal int // total number of lost packets (sender side)
|
||||
PktRcvLossTotal int // total number of lost packets (receiver side)
|
||||
PktRetransTotal int // total number of retransmitted packets
|
||||
PktSentACKTotal int // total number of sent ACK packets
|
||||
PktRecvACKTotal int // total number of received ACK packets
|
||||
PktSentNAKTotal int // total number of sent NAK packets
|
||||
PktRecvNAKTotal int // total number of received NAK packets
|
||||
UsSndDurationTotal int64 // total time duration when UDT is sending data (idle time exclusive)
|
||||
|
||||
PktSndDropTotal int // number of too-late-to-send dropped packets
|
||||
PktRcvDropTotal int // number of too-late-to play missing packets
|
||||
PktRcvUndecryptTotal int // number of undecrypted packets
|
||||
ByteSentTotal int64 // total number of sent data bytes, including retransmissions
|
||||
ByteRecvTotal int64 // total number of received bytes
|
||||
ByteRcvLossTotal int64 // total number of lost bytes
|
||||
|
||||
ByteRetransTotal int64 // total number of retransmitted bytes
|
||||
ByteSndDropTotal int64 // number of too-late-to-send dropped bytes
|
||||
ByteRcvDropTotal int64 // number of too-late-to play missing bytes (estimate based on average packet size)
|
||||
ByteRcvUndecryptTotal int64 // number of undecrypted bytes
|
||||
|
||||
// Local measurements
|
||||
PktSent int64 // number of sent data packets, including retransmissions
|
||||
PktRecv int64 // number of received packets
|
||||
PktSndLoss int // number of lost packets (sender side)
|
||||
PktRcvLoss int // number of lost packets (receiver side)
|
||||
PktRetrans int // number of retransmitted packets
|
||||
PktRcvRetrans int // number of retransmitted packets received
|
||||
PktSentACK int // number of sent ACK packets
|
||||
PktRecvACK int // number of received ACK packets
|
||||
PktSentNAK int // number of sent NAK packets
|
||||
PktRecvNAK int // number of received NAK packets
|
||||
MbpsSendRate float64 // sending rate in Mb/s
|
||||
MbpsRecvRate float64 // receiving rate in Mb/s
|
||||
UsSndDuration int64 // busy sending time (i.e., idle time exclusive)
|
||||
PktReorderDistance int // size of order discrepancy in received sequences
|
||||
PktRcvAvgBelatedTime float64 // average time of packet delay for belated packets (packets with sequence past the ACK)
|
||||
PktRcvBelated int64 // number of received AND IGNORED packets due to having come too late
|
||||
|
||||
PktSndDrop int // number of too-late-to-send dropped packets
|
||||
PktRcvDrop int // number of too-late-to play missing packets
|
||||
PktRcvUndecrypt int // number of undecrypted packets
|
||||
ByteSent int64 // number of sent data bytes, including retransmissions
|
||||
ByteRecv int64 // number of received bytes
|
||||
|
||||
ByteRcvLoss int64 // number of retransmitted Bytes
|
||||
ByteRetrans int64 // number of retransmitted Bytes
|
||||
ByteSndDrop int64 // number of too-late-to-send dropped Bytes
|
||||
ByteRcvDrop int64 // number of too-late-to play missing Bytes (estimate based on average packet size)
|
||||
ByteRcvUndecrypt int64 // number of undecrypted bytes
|
||||
|
||||
// Instant measurements
|
||||
UsPktSndPeriod float64 // packet sending period, in microseconds
|
||||
PktFlowWindow int // flow window size, in number of packets
|
||||
PktCongestionWindow int // congestion window size, in number of packets
|
||||
PktFlightSize int // number of packets on flight
|
||||
MsRTT float64 // RTT, in milliseconds
|
||||
MbpsBandwidth float64 // estimated bandwidth, in Mb/s
|
||||
ByteAvailSndBuf int // available UDT sender buffer size
|
||||
ByteAvailRcvBuf int // available UDT receiver buffer size
|
||||
|
||||
MbpsMaxBW float64 // Transmit Bandwidth ceiling (Mbps)
|
||||
ByteMSS int // MTU
|
||||
|
||||
PktSndBuf int // UnACKed packets in UDT sender
|
||||
ByteSndBuf int // UnACKed bytes in UDT sender
|
||||
MsSndBuf int // UnACKed timespan (msec) of UDT sender
|
||||
MsSndTsbPdDelay int // Timestamp-based Packet Delivery Delay
|
||||
|
||||
PktRcvBuf int // Undelivered packets in UDT receiver
|
||||
ByteRcvBuf int // Undelivered bytes of UDT receiver
|
||||
MsRcvBuf int // Undelivered timespan (msec) of UDT receiver
|
||||
MsRcvTsbPdDelay int // Timestamp-based Packet Delivery Delay
|
||||
|
||||
PktSndFilterExtraTotal int // number of control packets supplied by packet filter
|
||||
PktRcvFilterExtraTotal int // number of control packets received and not supplied back
|
||||
PktRcvFilterSupplyTotal int // number of packets that the filter supplied extra (e.g. FEC rebuilt)
|
||||
PktRcvFilterLossTotal int // number of packet loss not coverable by filter
|
||||
|
||||
PktSndFilterExtra int // number of control packets supplied by packet filter
|
||||
PktRcvFilterExtra int // number of control packets received and not supplied back
|
||||
PktRcvFilterSupply int // number of packets that the filter supplied extra (e.g. FEC rebuilt)
|
||||
PktRcvFilterLoss int // number of packet loss not coverable by filter
|
||||
PktReorderTolerance int // packet reorder tolerance value
|
||||
}
|
||||
|
||||
func newSrtStats(stats *C.SRT_TRACEBSTATS) *SrtStats {
|
||||
s := new(SrtStats)
|
||||
|
||||
s.MsTimeStamp = int64(stats.msTimeStamp)
|
||||
s.PktSentTotal = int64(stats.pktSentTotal)
|
||||
s.PktRecvTotal = int64(stats.pktRecvTotal)
|
||||
s.PktSndLossTotal = int(stats.pktSndLossTotal)
|
||||
s.PktRcvLossTotal = int(stats.pktRcvLossTotal)
|
||||
s.PktRetransTotal = int(stats.pktRetransTotal)
|
||||
s.PktSentACKTotal = int(stats.pktSentACKTotal)
|
||||
s.PktRecvACKTotal = int(stats.pktRecvACKTotal)
|
||||
s.PktSentNAKTotal = int(stats.pktSentNAKTotal)
|
||||
s.PktRecvNAKTotal = int(stats.pktRecvNAKTotal)
|
||||
s.UsSndDurationTotal = int64(stats.usSndDurationTotal)
|
||||
|
||||
s.PktSndDropTotal = int(stats.pktSndDropTotal)
|
||||
s.PktRcvDropTotal = int(stats.pktRcvDropTotal)
|
||||
s.PktRcvUndecryptTotal = int(stats.pktRcvUndecryptTotal)
|
||||
s.ByteSentTotal = int64(stats.byteSentTotal)
|
||||
s.ByteRecvTotal = int64(stats.byteRecvTotal)
|
||||
s.ByteRcvLossTotal = int64(stats.byteRcvLossTotal)
|
||||
|
||||
s.ByteRetransTotal = int64(stats.byteRetransTotal)
|
||||
s.ByteSndDropTotal = int64(stats.byteSndDropTotal)
|
||||
s.ByteRcvDropTotal = int64(stats.byteRcvDropTotal)
|
||||
s.ByteRcvUndecryptTotal = int64(stats.byteRcvUndecryptTotal)
|
||||
|
||||
s.PktSent = int64(stats.pktSent)
|
||||
s.PktRecv = int64(stats.pktRecv)
|
||||
s.PktSndLoss = int(stats.pktSndLoss)
|
||||
s.PktRcvLoss = int(stats.pktRcvLoss)
|
||||
s.PktRetrans = int(stats.pktRetrans)
|
||||
s.PktRcvRetrans = int(stats.pktRcvRetrans)
|
||||
s.PktSentACK = int(stats.pktSentACK)
|
||||
s.PktRecvACK = int(stats.pktRecvACK)
|
||||
s.PktSentNAK = int(stats.pktSentNAK)
|
||||
s.PktRecvNAK = int(stats.pktRecvNAK)
|
||||
s.MbpsSendRate = float64(stats.mbpsSendRate)
|
||||
s.MbpsRecvRate = float64(stats.mbpsRecvRate)
|
||||
s.UsSndDuration = int64(stats.usSndDuration)
|
||||
s.PktReorderDistance = int(stats.pktReorderDistance)
|
||||
s.PktRcvAvgBelatedTime = float64(stats.pktRcvAvgBelatedTime)
|
||||
s.PktRcvBelated = int64(stats.pktRcvBelated)
|
||||
|
||||
s.PktSndDrop = int(stats.pktSndDrop)
|
||||
s.PktRcvDrop = int(stats.pktRcvDrop)
|
||||
s.PktRcvUndecrypt = int(stats.pktRcvUndecrypt)
|
||||
s.ByteSent = int64(stats.byteSent)
|
||||
s.ByteRecv = int64(stats.byteRecv)
|
||||
|
||||
s.ByteRcvLoss = int64(stats.byteRcvLoss)
|
||||
s.ByteRetrans = int64(stats.byteRetrans)
|
||||
s.ByteSndDrop = int64(stats.byteSndDrop)
|
||||
s.ByteRcvDrop = int64(stats.byteRcvDrop)
|
||||
s.ByteRcvUndecrypt = int64(stats.byteRcvUndecrypt)
|
||||
|
||||
s.UsPktSndPeriod = float64(stats.usPktSndPeriod)
|
||||
s.PktFlowWindow = int(stats.pktFlowWindow)
|
||||
s.PktCongestionWindow = int(stats.pktCongestionWindow)
|
||||
s.PktFlightSize = int(stats.pktFlightSize)
|
||||
s.MsRTT = float64(stats.msRTT)
|
||||
s.MbpsBandwidth = float64(stats.mbpsBandwidth)
|
||||
s.ByteAvailSndBuf = int(stats.byteAvailSndBuf)
|
||||
s.ByteAvailRcvBuf = int(stats.byteAvailRcvBuf)
|
||||
|
||||
s.MbpsMaxBW = float64(stats.mbpsMaxBW)
|
||||
s.ByteMSS = int(stats.byteMSS)
|
||||
|
||||
s.PktSndBuf = int(stats.pktSndBuf)
|
||||
s.ByteSndBuf = int(stats.byteSndBuf)
|
||||
s.MsSndBuf = int(stats.msSndBuf)
|
||||
s.MsSndTsbPdDelay = int(stats.msSndTsbPdDelay)
|
||||
|
||||
s.PktRcvBuf = int(stats.pktRcvBuf)
|
||||
s.ByteRcvBuf = int(stats.byteRcvBuf)
|
||||
s.MsRcvBuf = int(stats.msRcvBuf)
|
||||
s.MsRcvTsbPdDelay = int(stats.msRcvTsbPdDelay)
|
||||
|
||||
s.PktSndFilterExtraTotal = int(stats.pktSndFilterExtraTotal)
|
||||
s.PktRcvFilterExtraTotal = int(stats.pktRcvFilterExtraTotal)
|
||||
s.PktRcvFilterSupplyTotal = int(stats.pktRcvFilterSupplyTotal)
|
||||
s.PktRcvFilterLossTotal = int(stats.pktRcvFilterLossTotal)
|
||||
|
||||
s.PktSndFilterExtra = int(stats.pktSndFilterExtra)
|
||||
s.PktRcvFilterExtra = int(stats.pktRcvFilterExtra)
|
||||
s.PktRcvFilterSupply = int(stats.pktRcvFilterSupply)
|
||||
s.PktRcvFilterLoss = int(stats.pktRcvFilterLoss)
|
||||
s.PktReorderTolerance = int(stats.pktReorderTolerance)
|
||||
|
||||
return s
|
||||
}
|
55
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/write.go
generated
vendored
Normal file
55
trunk/3rdparty/srs-bench/vendor/github.com/haivision/srtgo/write.go
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
package srtgo
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lsrt
|
||||
#include <srt/srt.h>
|
||||
|
||||
int srt_sendmsg2_wrapped(SRTSOCKET u, const char* buf, int len, SRT_MSGCTRL *mctrl, int *srterror, int *syserror)
|
||||
{
|
||||
int ret = srt_sendmsg2(u, buf, len, mctrl);
|
||||
if (ret < 0) {
|
||||
*srterror = srt_getlasterror(syserror);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func srtSendMsg2Impl(u C.SRTSOCKET, buf []byte, msgctrl *C.SRT_MSGCTRL) (n int, err error) {
|
||||
srterr := C.int(0)
|
||||
syserr := C.int(0)
|
||||
n = int(C.srt_sendmsg2_wrapped(u, (*C.char)(unsafe.Pointer(&buf[0])), C.int(len(buf)), msgctrl, &srterr, &syserr))
|
||||
if n < 0 {
|
||||
srterror := SRTErrno(srterr)
|
||||
if syserr < 0 {
|
||||
srterror.wrapSysErr(syscall.Errno(syserr))
|
||||
}
|
||||
err = srterror
|
||||
n = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Write data to the SRT socket
|
||||
func (s SrtSocket) Write(b []byte) (n int, err error) {
|
||||
|
||||
//Fastpath:
|
||||
if !s.blocking {
|
||||
s.pd.reset(ModeWrite)
|
||||
}
|
||||
n, err = srtSendMsg2Impl(s.socket, b, nil)
|
||||
|
||||
for {
|
||||
if !errors.Is(err, error(EAsyncSND)) || s.blocking {
|
||||
return
|
||||
}
|
||||
s.pd.wait(ModeWrite)
|
||||
n, err = srtSendMsg2Impl(s.socket, b, nil)
|
||||
}
|
||||
}
|
21
trunk/3rdparty/srs-bench/vendor/github.com/mattn/go-pointer/LICENSE
generated
vendored
Normal file
21
trunk/3rdparty/srs-bench/vendor/github.com/mattn/go-pointer/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Yasuhiro Matsumoto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
29
trunk/3rdparty/srs-bench/vendor/github.com/mattn/go-pointer/README.md
generated
vendored
Normal file
29
trunk/3rdparty/srs-bench/vendor/github.com/mattn/go-pointer/README.md
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
# go-pointer
|
||||
|
||||
Utility for cgo
|
||||
|
||||
## Usage
|
||||
|
||||
https://github.com/golang/proposal/blob/master/design/12416-cgo-pointers.md
|
||||
|
||||
In go 1.6, cgo argument can't be passed Go pointer.
|
||||
|
||||
```
|
||||
var s string
|
||||
C.pass_pointer(pointer.Save(&s))
|
||||
v := *(pointer.Restore(C.get_from_pointer()).(*string))
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
go get github.com/mattn/go-pointer
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Author
|
||||
|
||||
Yasuhiro Matsumoto (a.k.a mattn)
|
1
trunk/3rdparty/srs-bench/vendor/github.com/mattn/go-pointer/doc.go
generated
vendored
Normal file
1
trunk/3rdparty/srs-bench/vendor/github.com/mattn/go-pointer/doc.go
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
package pointer
|
57
trunk/3rdparty/srs-bench/vendor/github.com/mattn/go-pointer/pointer.go
generated
vendored
Normal file
57
trunk/3rdparty/srs-bench/vendor/github.com/mattn/go-pointer/pointer.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
package pointer
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
mutex sync.RWMutex
|
||||
store = map[unsafe.Pointer]interface{}{}
|
||||
)
|
||||
|
||||
func Save(v interface{}) unsafe.Pointer {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Generate real fake C pointer.
|
||||
// This pointer will not store any data, but will bi used for indexing purposes.
|
||||
// Since Go doest allow to cast dangling pointer to unsafe.Pointer, we do rally allocate one byte.
|
||||
// Why we need indexing, because Go doest allow C code to store pointers to Go data.
|
||||
var ptr unsafe.Pointer = C.malloc(C.size_t(1))
|
||||
if ptr == nil {
|
||||
panic("can't allocate 'cgo-pointer hack index pointer': ptr == nil")
|
||||
}
|
||||
|
||||
mutex.Lock()
|
||||
store[ptr] = v
|
||||
mutex.Unlock()
|
||||
|
||||
return ptr
|
||||
}
|
||||
|
||||
func Restore(ptr unsafe.Pointer) (v interface{}) {
|
||||
if ptr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
mutex.RLock()
|
||||
v = store[ptr]
|
||||
mutex.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
func Unref(ptr unsafe.Pointer) {
|
||||
if ptr == nil {
|
||||
return
|
||||
}
|
||||
|
||||
mutex.Lock()
|
||||
delete(store, ptr)
|
||||
mutex.Unlock()
|
||||
|
||||
C.free(ptr)
|
||||
}
|
28
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_compare.go
generated
vendored
28
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_compare.go
generated
vendored
|
@ -28,6 +28,8 @@ var (
|
|||
uint32Type = reflect.TypeOf(uint32(1))
|
||||
uint64Type = reflect.TypeOf(uint64(1))
|
||||
|
||||
uintptrType = reflect.TypeOf(uintptr(1))
|
||||
|
||||
float32Type = reflect.TypeOf(float32(1))
|
||||
float64Type = reflect.TypeOf(float64(1))
|
||||
|
||||
|
@ -308,11 +310,11 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
|||
case reflect.Struct:
|
||||
{
|
||||
// All structs enter here. We're not interested in most types.
|
||||
if !canConvert(obj1Value, timeType) {
|
||||
if !obj1Value.CanConvert(timeType) {
|
||||
break
|
||||
}
|
||||
|
||||
// time.Time can compared!
|
||||
// time.Time can be compared!
|
||||
timeObj1, ok := obj1.(time.Time)
|
||||
if !ok {
|
||||
timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
|
||||
|
@ -328,7 +330,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
|||
case reflect.Slice:
|
||||
{
|
||||
// We only care about the []byte type.
|
||||
if !canConvert(obj1Value, bytesType) {
|
||||
if !obj1Value.CanConvert(bytesType) {
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -345,6 +347,26 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
|||
|
||||
return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
|
||||
}
|
||||
case reflect.Uintptr:
|
||||
{
|
||||
uintptrObj1, ok := obj1.(uintptr)
|
||||
if !ok {
|
||||
uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr)
|
||||
}
|
||||
uintptrObj2, ok := obj2.(uintptr)
|
||||
if !ok {
|
||||
uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr)
|
||||
}
|
||||
if uintptrObj1 > uintptrObj2 {
|
||||
return compareGreater, true
|
||||
}
|
||||
if uintptrObj1 == uintptrObj2 {
|
||||
return compareEqual, true
|
||||
}
|
||||
if uintptrObj1 < uintptrObj2 {
|
||||
return compareLess, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return compareEqual, false
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
//go:build go1.17
|
||||
// +build go1.17
|
||||
|
||||
// TODO: once support for Go 1.16 is dropped, this file can be
|
||||
// merged/removed with assertion_compare_go1.17_test.go and
|
||||
// assertion_compare_legacy.go
|
||||
|
||||
package assert
|
||||
|
||||
import "reflect"
|
||||
|
||||
// Wrapper around reflect.Value.CanConvert, for compatibility
|
||||
// reasons.
|
||||
func canConvert(value reflect.Value, to reflect.Type) bool {
|
||||
return value.CanConvert(to)
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
//go:build !go1.17
|
||||
// +build !go1.17
|
||||
|
||||
// TODO: once support for Go 1.16 is dropped, this file can be
|
||||
// merged/removed with assertion_compare_go1.17_test.go and
|
||||
// assertion_compare_can_convert.go
|
||||
|
||||
package assert
|
||||
|
||||
import "reflect"
|
||||
|
||||
// Older versions of Go does not have the reflect.Value.CanConvert
|
||||
// method.
|
||||
func canConvert(value reflect.Value, to reflect.Type) bool {
|
||||
return false
|
||||
}
|
32
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
32
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
|
||||
* THIS FILE MUST NOT BE EDITED BY HAND
|
||||
*/
|
||||
// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
|
||||
|
||||
package assert
|
||||
|
||||
|
@ -107,7 +104,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{},
|
|||
return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||
// EqualValuesf asserts that two objects are equal or convertible to the same types
|
||||
// and equal.
|
||||
//
|
||||
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
|
||||
|
@ -616,6 +613,16 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf
|
|||
return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotImplementsf asserts that an object does not implement the specified interface.
|
||||
//
|
||||
// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||
func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotNilf asserts that the specified object is not nil.
|
||||
//
|
||||
// assert.NotNilf(t, err, "error message %s", "formatted")
|
||||
|
@ -660,10 +667,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
|
|||
return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
|
||||
// contain all elements given in the specified subset list(array, slice...) or
|
||||
// map.
|
||||
//
|
||||
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
|
||||
// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
|
||||
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -747,10 +756,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
|
|||
return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// Subsetf asserts that the specified list(array, slice...) or map contains all
|
||||
// elements given in the specified subset list(array, slice...) or map.
|
||||
//
|
||||
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
|
||||
// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
|
||||
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
|
59
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
59
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
|
||||
* THIS FILE MUST NOT BE EDITED BY HAND
|
||||
*/
|
||||
// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
|
||||
|
||||
package assert
|
||||
|
||||
|
@ -189,7 +186,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface
|
|||
return EqualExportedValuesf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||
// EqualValues asserts that two objects are equal or convertible to the same types
|
||||
// and equal.
|
||||
//
|
||||
// a.EqualValues(uint32(123), int32(123))
|
||||
|
@ -200,7 +197,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
|||
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||
// EqualValuesf asserts that two objects are equal or convertible to the same types
|
||||
// and equal.
|
||||
//
|
||||
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
||||
|
@ -1221,6 +1218,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in
|
|||
return NotErrorIsf(a.t, err, target, msg, args...)
|
||||
}
|
||||
|
||||
// NotImplements asserts that an object does not implement the specified interface.
|
||||
//
|
||||
// a.NotImplements((*MyInterface)(nil), new(MyObject))
|
||||
func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotImplements(a.t, interfaceObject, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotImplementsf asserts that an object does not implement the specified interface.
|
||||
//
|
||||
// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||
func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotImplementsf(a.t, interfaceObject, object, msg, args...)
|
||||
}
|
||||
|
||||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// a.NotNil(err)
|
||||
|
@ -1309,10 +1326,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri
|
|||
return NotSamef(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// NotSubset asserts that the specified list(array, slice...) contains not all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// NotSubset asserts that the specified list(array, slice...) or map does NOT
|
||||
// contain all elements given in the specified subset list(array, slice...) or
|
||||
// map.
|
||||
//
|
||||
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
// a.NotSubset([1, 3, 4], [1, 2])
|
||||
// a.NotSubset({"x": 1, "y": 2}, {"z": 3})
|
||||
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1320,10 +1339,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
|
|||
return NotSubset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
|
||||
// contain all elements given in the specified subset list(array, slice...) or
|
||||
// map.
|
||||
//
|
||||
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
|
||||
// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
|
||||
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1483,10 +1504,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string,
|
|||
return Samef(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// Subset asserts that the specified list(array, slice...) contains all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// Subset asserts that the specified list(array, slice...) or map contains all
|
||||
// elements given in the specified subset list(array, slice...) or map.
|
||||
//
|
||||
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
// a.Subset([1, 2, 3], [1, 2])
|
||||
// a.Subset({"x": 1, "y": 2}, {"x": 1})
|
||||
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1494,10 +1516,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
|
|||
return Subset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// Subsetf asserts that the specified list(array, slice...) or map contains all
|
||||
// elements given in the specified subset list(array, slice...) or map.
|
||||
//
|
||||
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
|
||||
// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
|
||||
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
|
205
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
205
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
|
||||
|
@ -110,7 +110,12 @@ func copyExportedFields(expected interface{}) interface{} {
|
|||
return result.Interface()
|
||||
|
||||
case reflect.Array, reflect.Slice:
|
||||
result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len())
|
||||
var result reflect.Value
|
||||
if expectedKind == reflect.Array {
|
||||
result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem()
|
||||
} else {
|
||||
result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len())
|
||||
}
|
||||
for i := 0; i < expectedValue.Len(); i++ {
|
||||
index := expectedValue.Index(i)
|
||||
if isNil(index) {
|
||||
|
@ -140,6 +145,8 @@ func copyExportedFields(expected interface{}) interface{} {
|
|||
// structures.
|
||||
//
|
||||
// This function does no assertion of any kind.
|
||||
//
|
||||
// Deprecated: Use [EqualExportedValues] instead.
|
||||
func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool {
|
||||
expectedCleaned := copyExportedFields(expected)
|
||||
actualCleaned := copyExportedFields(actual)
|
||||
|
@ -153,19 +160,42 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
actualType := reflect.TypeOf(actual)
|
||||
if actualType == nil {
|
||||
return false
|
||||
}
|
||||
expectedValue := reflect.ValueOf(expected)
|
||||
if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
|
||||
// Attempt comparison after type conversion
|
||||
return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
|
||||
actualValue := reflect.ValueOf(actual)
|
||||
if !expectedValue.IsValid() || !actualValue.IsValid() {
|
||||
return false
|
||||
}
|
||||
|
||||
expectedType := expectedValue.Type()
|
||||
actualType := actualValue.Type()
|
||||
if !expectedType.ConvertibleTo(actualType) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !isNumericType(expectedType) || !isNumericType(actualType) {
|
||||
// Attempt comparison after type conversion
|
||||
return reflect.DeepEqual(
|
||||
expectedValue.Convert(actualType).Interface(), actual,
|
||||
)
|
||||
}
|
||||
|
||||
// If BOTH values are numeric, there are chances of false positives due
|
||||
// to overflow or underflow. So, we need to make sure to always convert
|
||||
// the smaller type to a larger type before comparing.
|
||||
if expectedType.Size() >= actualType.Size() {
|
||||
return actualValue.Convert(expectedType).Interface() == expected
|
||||
}
|
||||
|
||||
return expectedValue.Convert(actualType).Interface() == actual
|
||||
}
|
||||
|
||||
// isNumericType returns true if the type is one of:
|
||||
// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64,
|
||||
// float32, float64, complex64, complex128
|
||||
func isNumericType(t reflect.Type) bool {
|
||||
return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128
|
||||
}
|
||||
|
||||
/* CallerInfo is necessary because the assert functions use the testing object
|
||||
internally, causing it to print the file:line of the assert method, rather than where
|
||||
the problem actually occurred in calling code.*/
|
||||
|
@ -266,7 +296,7 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
|
|||
|
||||
// Aligns the provided message so that all lines after the first line start at the same location as the first line.
|
||||
// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
|
||||
// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the
|
||||
// The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the
|
||||
// basis on which the alignment occurs).
|
||||
func indentMessageLines(message string, longestLabelLen int) string {
|
||||
outBuf := new(bytes.Buffer)
|
||||
|
@ -382,6 +412,25 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg
|
|||
return true
|
||||
}
|
||||
|
||||
// NotImplements asserts that an object does not implement the specified interface.
|
||||
//
|
||||
// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject))
|
||||
func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
||||
|
||||
if object == nil {
|
||||
return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...)
|
||||
}
|
||||
if reflect.TypeOf(object).Implements(interfaceType) {
|
||||
return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
|
@ -496,7 +545,7 @@ func samePointers(first, second interface{}) bool {
|
|||
// representations appropriate to be presented to the user.
|
||||
//
|
||||
// If the values are not of like type, the returned strings will be prefixed
|
||||
// with the type name, and the value will be enclosed in parenthesis similar
|
||||
// with the type name, and the value will be enclosed in parentheses similar
|
||||
// to a type conversion in the Go grammar.
|
||||
func formatUnequalValues(expected, actual interface{}) (e string, a string) {
|
||||
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
|
||||
|
@ -523,7 +572,7 @@ func truncatingFormat(data interface{}) string {
|
|||
return value
|
||||
}
|
||||
|
||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||
// EqualValues asserts that two objects are equal or convertible to the same types
|
||||
// and equal.
|
||||
//
|
||||
// assert.EqualValues(t, uint32(123), int32(123))
|
||||
|
@ -566,12 +615,19 @@ func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ..
|
|||
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
|
||||
}
|
||||
|
||||
if aType.Kind() == reflect.Ptr {
|
||||
aType = aType.Elem()
|
||||
}
|
||||
if bType.Kind() == reflect.Ptr {
|
||||
bType = bType.Elem()
|
||||
}
|
||||
|
||||
if aType.Kind() != reflect.Struct {
|
||||
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...)
|
||||
}
|
||||
|
||||
if bType.Kind() != reflect.Struct {
|
||||
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...)
|
||||
}
|
||||
|
||||
expected = copyExportedFields(expected)
|
||||
|
@ -620,17 +676,6 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
|||
return Fail(t, "Expected value not to be nil.", msgAndArgs...)
|
||||
}
|
||||
|
||||
// containsKind checks if a specified kind in the slice of kinds.
|
||||
func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {
|
||||
for i := 0; i < len(kinds); i++ {
|
||||
if kind == kinds[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// isNil checks if a specified object is nil or not, without Failing.
|
||||
func isNil(object interface{}) bool {
|
||||
if object == nil {
|
||||
|
@ -638,16 +683,13 @@ func isNil(object interface{}) bool {
|
|||
}
|
||||
|
||||
value := reflect.ValueOf(object)
|
||||
kind := value.Kind()
|
||||
isNilableKind := containsKind(
|
||||
[]reflect.Kind{
|
||||
switch value.Kind() {
|
||||
case
|
||||
reflect.Chan, reflect.Func,
|
||||
reflect.Interface, reflect.Map,
|
||||
reflect.Ptr, reflect.Slice, reflect.UnsafePointer},
|
||||
kind)
|
||||
reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
|
||||
|
||||
if isNilableKind && value.IsNil() {
|
||||
return true
|
||||
return value.IsNil()
|
||||
}
|
||||
|
||||
return false
|
||||
|
@ -731,16 +773,14 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
|||
|
||||
}
|
||||
|
||||
// getLen try to get length of object.
|
||||
// return (false, 0) if impossible.
|
||||
func getLen(x interface{}) (ok bool, length int) {
|
||||
// getLen tries to get the length of an object.
|
||||
// It returns (0, false) if impossible.
|
||||
func getLen(x interface{}) (length int, ok bool) {
|
||||
v := reflect.ValueOf(x)
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
ok = false
|
||||
}
|
||||
ok = recover() == nil
|
||||
}()
|
||||
return true, v.Len()
|
||||
return v.Len(), true
|
||||
}
|
||||
|
||||
// Len asserts that the specified object has specific length.
|
||||
|
@ -751,13 +791,13 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
|
|||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ok, l := getLen(object)
|
||||
l, ok := getLen(object)
|
||||
if !ok {
|
||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...)
|
||||
}
|
||||
|
||||
if l != length {
|
||||
return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -919,10 +959,11 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
|
|||
|
||||
}
|
||||
|
||||
// Subset asserts that the specified list(array, slice...) contains all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// Subset asserts that the specified list(array, slice...) or map contains all
|
||||
// elements given in the specified subset list(array, slice...) or map.
|
||||
//
|
||||
// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
// assert.Subset(t, [1, 2, 3], [1, 2])
|
||||
// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1})
|
||||
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -975,10 +1016,12 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
|
|||
return true
|
||||
}
|
||||
|
||||
// NotSubset asserts that the specified list(array, slice...) contains not all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// NotSubset asserts that the specified list(array, slice...) or map does NOT
|
||||
// contain all elements given in the specified subset list(array, slice...) or
|
||||
// map.
|
||||
//
|
||||
// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
// assert.NotSubset(t, [1, 3, 4], [1, 2])
|
||||
// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3})
|
||||
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1439,7 +1482,7 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
|
|||
h.Helper()
|
||||
}
|
||||
if math.IsNaN(epsilon) {
|
||||
return Fail(t, "epsilon must not be NaN")
|
||||
return Fail(t, "epsilon must not be NaN", msgAndArgs...)
|
||||
}
|
||||
actualEpsilon, err := calcRelativeError(expected, actual)
|
||||
if err != nil {
|
||||
|
@ -1458,19 +1501,26 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
|
|||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||
|
||||
if expected == nil || actual == nil {
|
||||
return Fail(t, "Parameters must be slice", msgAndArgs...)
|
||||
}
|
||||
|
||||
actualSlice := reflect.ValueOf(actual)
|
||||
expectedSlice := reflect.ValueOf(expected)
|
||||
actualSlice := reflect.ValueOf(actual)
|
||||
|
||||
for i := 0; i < actualSlice.Len(); i++ {
|
||||
result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon)
|
||||
if !result {
|
||||
return result
|
||||
if expectedSlice.Type().Kind() != reflect.Slice {
|
||||
return Fail(t, "Expected value must be slice", msgAndArgs...)
|
||||
}
|
||||
|
||||
expectedLen := expectedSlice.Len()
|
||||
if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < expectedLen; i++ {
|
||||
if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1870,23 +1920,18 @@ func (c *CollectT) Errorf(format string, args ...interface{}) {
|
|||
}
|
||||
|
||||
// FailNow panics.
|
||||
func (c *CollectT) FailNow() {
|
||||
func (*CollectT) FailNow() {
|
||||
panic("Assertion failed")
|
||||
}
|
||||
|
||||
// Reset clears the collected errors.
|
||||
func (c *CollectT) Reset() {
|
||||
c.errors = nil
|
||||
// Deprecated: That was a method for internal usage that should not have been published. Now just panics.
|
||||
func (*CollectT) Reset() {
|
||||
panic("Reset() is deprecated")
|
||||
}
|
||||
|
||||
// Copy copies the collected errors to the supplied t.
|
||||
func (c *CollectT) Copy(t TestingT) {
|
||||
if tt, ok := t.(tHelper); ok {
|
||||
tt.Helper()
|
||||
}
|
||||
for _, err := range c.errors {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
// Deprecated: That was a method for internal usage that should not have been published. Now just panics.
|
||||
func (*CollectT) Copy(TestingT) {
|
||||
panic("Copy() is deprecated")
|
||||
}
|
||||
|
||||
// EventuallyWithT asserts that given condition will be met in waitFor time,
|
||||
|
@ -1912,8 +1957,8 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
|
|||
h.Helper()
|
||||
}
|
||||
|
||||
collect := new(CollectT)
|
||||
ch := make(chan bool, 1)
|
||||
var lastFinishedTickErrs []error
|
||||
ch := make(chan []error, 1)
|
||||
|
||||
timer := time.NewTimer(waitFor)
|
||||
defer timer.Stop()
|
||||
|
@ -1924,19 +1969,25 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
|
|||
for tick := ticker.C; ; {
|
||||
select {
|
||||
case <-timer.C:
|
||||
collect.Copy(t)
|
||||
for _, err := range lastFinishedTickErrs {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
return Fail(t, "Condition never satisfied", msgAndArgs...)
|
||||
case <-tick:
|
||||
tick = nil
|
||||
collect.Reset()
|
||||
go func() {
|
||||
condition(collect)
|
||||
ch <- len(collect.errors) == 0
|
||||
collect := new(CollectT)
|
||||
defer func() {
|
||||
ch <- collect.errors
|
||||
}()
|
||||
case v := <-ch:
|
||||
if v {
|
||||
condition(collect)
|
||||
}()
|
||||
case errs := <-ch:
|
||||
if len(errs) == 0 {
|
||||
return true
|
||||
}
|
||||
// Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached.
|
||||
lastFinishedTickErrs = errs
|
||||
tick = ticker.C
|
||||
}
|
||||
}
|
||||
|
|
27
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
27
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
|
@ -12,7 +12,7 @@ import (
|
|||
// an error if building a new request fails.
|
||||
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
|
||||
w := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
req, err := http.NewRequest(method, url, http.NoBody)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
|
|||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
|
||||
}
|
||||
|
||||
isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
|
||||
if !isSuccessCode {
|
||||
Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
|
||||
Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
|
||||
}
|
||||
|
||||
return isSuccessCode
|
||||
|
@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
|
|||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
|
||||
}
|
||||
|
||||
isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
|
||||
if !isRedirectCode {
|
||||
Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
|
||||
Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
|
||||
}
|
||||
|
||||
return isRedirectCode
|
||||
|
@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
|
|||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
|
||||
}
|
||||
|
||||
isErrorCode := code >= http.StatusBadRequest
|
||||
if !isErrorCode {
|
||||
Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
|
||||
Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
|
||||
}
|
||||
|
||||
return isErrorCode
|
||||
|
@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
|
|||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
|
||||
}
|
||||
|
||||
successful := code == statuscode
|
||||
if !successful {
|
||||
Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code))
|
||||
Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...)
|
||||
}
|
||||
|
||||
return successful
|
||||
|
@ -113,7 +113,10 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
|
|||
// empty string if building a new request fails.
|
||||
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
|
||||
w := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
||||
if len(values) > 0 {
|
||||
url += "?" + values.Encode()
|
||||
}
|
||||
req, err := http.NewRequest(method, url, http.NoBody)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
@ -135,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
|
|||
|
||||
contains := strings.Contains(body, fmt.Sprint(str))
|
||||
if !contains {
|
||||
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
|
||||
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
|
||||
}
|
||||
|
||||
return contains
|
||||
|
@ -155,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin
|
|||
|
||||
contains := strings.Contains(body, fmt.Sprint(str))
|
||||
if contains {
|
||||
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
|
||||
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
|
||||
}
|
||||
|
||||
return !contains
|
||||
|
|
65
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go
generated
vendored
65
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go
generated
vendored
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
|
||||
* THIS FILE MUST NOT BE EDITED BY HAND
|
||||
*/
|
||||
// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
|
||||
|
||||
package require
|
||||
|
||||
|
@ -235,7 +232,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{},
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||
// EqualValues asserts that two objects are equal or convertible to the same types
|
||||
// and equal.
|
||||
//
|
||||
// assert.EqualValues(t, uint32(123), int32(123))
|
||||
|
@ -249,7 +246,7 @@ func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArg
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||
// EqualValuesf asserts that two objects are equal or convertible to the same types
|
||||
// and equal.
|
||||
//
|
||||
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
|
||||
|
@ -1546,6 +1543,32 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// NotImplements asserts that an object does not implement the specified interface.
|
||||
//
|
||||
// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject))
|
||||
func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.NotImplements(t, interfaceObject, object, msgAndArgs...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// NotImplementsf asserts that an object does not implement the specified interface.
|
||||
//
|
||||
// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||
func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if assert.NotImplementsf(t, interfaceObject, object, msg, args...) {
|
||||
return
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// assert.NotNil(t, err)
|
||||
|
@ -1658,10 +1681,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// NotSubset asserts that the specified list(array, slice...) contains not all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// NotSubset asserts that the specified list(array, slice...) or map does NOT
|
||||
// contain all elements given in the specified subset list(array, slice...) or
|
||||
// map.
|
||||
//
|
||||
// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
// assert.NotSubset(t, [1, 3, 4], [1, 2])
|
||||
// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3})
|
||||
func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1672,10 +1697,12 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
|
||||
// contain all elements given in the specified subset list(array, slice...) or
|
||||
// map.
|
||||
//
|
||||
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
|
||||
// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
|
||||
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1880,10 +1907,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// Subset asserts that the specified list(array, slice...) contains all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// Subset asserts that the specified list(array, slice...) or map contains all
|
||||
// elements given in the specified subset list(array, slice...) or map.
|
||||
//
|
||||
// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
// assert.Subset(t, [1, 2, 3], [1, 2])
|
||||
// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1})
|
||||
func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1894,10 +1922,11 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// Subsetf asserts that the specified list(array, slice...) or map contains all
|
||||
// elements given in the specified subset list(array, slice...) or map.
|
||||
//
|
||||
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
|
||||
// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
|
||||
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
|
59
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go
generated
vendored
59
trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go
generated
vendored
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
|
||||
* THIS FILE MUST NOT BE EDITED BY HAND
|
||||
*/
|
||||
// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
|
||||
|
||||
package require
|
||||
|
||||
|
@ -190,7 +187,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface
|
|||
EqualExportedValuesf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||
// EqualValues asserts that two objects are equal or convertible to the same types
|
||||
// and equal.
|
||||
//
|
||||
// a.EqualValues(uint32(123), int32(123))
|
||||
|
@ -201,7 +198,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
|||
EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||
// EqualValuesf asserts that two objects are equal or convertible to the same types
|
||||
// and equal.
|
||||
//
|
||||
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
||||
|
@ -1222,6 +1219,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in
|
|||
NotErrorIsf(a.t, err, target, msg, args...)
|
||||
}
|
||||
|
||||
// NotImplements asserts that an object does not implement the specified interface.
|
||||
//
|
||||
// a.NotImplements((*MyInterface)(nil), new(MyObject))
|
||||
func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotImplements(a.t, interfaceObject, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotImplementsf asserts that an object does not implement the specified interface.
|
||||
//
|
||||
// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||
func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
NotImplementsf(a.t, interfaceObject, object, msg, args...)
|
||||
}
|
||||
|
||||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// a.NotNil(err)
|
||||
|
@ -1310,10 +1327,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri
|
|||
NotSamef(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// NotSubset asserts that the specified list(array, slice...) contains not all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// NotSubset asserts that the specified list(array, slice...) or map does NOT
|
||||
// contain all elements given in the specified subset list(array, slice...) or
|
||||
// map.
|
||||
//
|
||||
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
// a.NotSubset([1, 3, 4], [1, 2])
|
||||
// a.NotSubset({"x": 1, "y": 2}, {"z": 3})
|
||||
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1321,10 +1340,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
|
|||
NotSubset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotSubsetf asserts that the specified list(array, slice...) contains not all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// NotSubsetf asserts that the specified list(array, slice...) or map does NOT
|
||||
// contain all elements given in the specified subset list(array, slice...) or
|
||||
// map.
|
||||
//
|
||||
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
|
||||
// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
|
||||
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1484,10 +1505,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string,
|
|||
Samef(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// Subset asserts that the specified list(array, slice...) contains all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// Subset asserts that the specified list(array, slice...) or map contains all
|
||||
// elements given in the specified subset list(array, slice...) or map.
|
||||
//
|
||||
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
// a.Subset([1, 2, 3], [1, 2])
|
||||
// a.Subset({"x": 1, "y": 2}, {"x": 1})
|
||||
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
@ -1495,10 +1517,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
|
|||
Subset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||
// elements given in the specified subset(array, slice...).
|
||||
// Subsetf asserts that the specified list(array, slice...) or map contains all
|
||||
// elements given in the specified subset list(array, slice...) or map.
|
||||
//
|
||||
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
|
||||
// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
|
||||
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
|
|
13
trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/asn1.go
generated
vendored
13
trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/asn1.go
generated
vendored
|
@ -733,13 +733,14 @@ func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag
|
|||
return true
|
||||
}
|
||||
|
||||
// ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or,
|
||||
// if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue.
|
||||
// It reports whether the operation was successful.
|
||||
func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool {
|
||||
// ReadOptionalASN1Boolean attempts to read an optional ASN.1 BOOLEAN
|
||||
// explicitly tagged with tag into out and advances. If no element with a
|
||||
// matching tag is present, it sets "out" to defaultValue instead. It reports
|
||||
// whether the read was successful.
|
||||
func (s *String) ReadOptionalASN1Boolean(out *bool, tag asn1.Tag, defaultValue bool) bool {
|
||||
var present bool
|
||||
var child String
|
||||
if !s.ReadOptionalASN1(&child, &present, asn1.BOOLEAN) {
|
||||
if !s.ReadOptionalASN1(&child, &present, tag) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -748,7 +749,7 @@ func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
return s.ReadASN1Boolean(out)
|
||||
return child.ReadASN1Boolean(out)
|
||||
}
|
||||
|
||||
func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool {
|
||||
|
|
5
trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/builder.go
generated
vendored
5
trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/builder.go
generated
vendored
|
@ -95,6 +95,11 @@ func (b *Builder) AddUint32(v uint32) {
|
|||
b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
||||
}
|
||||
|
||||
// AddUint48 appends a big-endian, 48-bit value to the byte string.
|
||||
func (b *Builder) AddUint48(v uint64) {
|
||||
b.add(byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
||||
}
|
||||
|
||||
// AddUint64 appends a big-endian, 64-bit value to the byte string.
|
||||
func (b *Builder) AddUint64(v uint64) {
|
||||
b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
||||
|
|
11
trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/string.go
generated
vendored
11
trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/string.go
generated
vendored
|
@ -81,6 +81,17 @@ func (s *String) ReadUint32(out *uint32) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// ReadUint48 decodes a big-endian, 48-bit value into out and advances over it.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadUint48(out *uint64) bool {
|
||||
v := s.read(6)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
*out = uint64(v[0])<<40 | uint64(v[1])<<32 | uint64(v[2])<<24 | uint64(v[3])<<16 | uint64(v[4])<<8 | uint64(v[5])
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadUint64 decodes a big-endian, 64-bit value into out and advances over it.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadUint64(out *uint64) bool {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
package field
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !amd64 || !gc || purego
|
||||
// +build !amd64 !gc purego
|
||||
|
||||
package field
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64 && gc && !purego
|
||||
// +build arm64,gc,!purego
|
||||
|
||||
package field
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64 && gc && !purego
|
||||
// +build arm64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm64 || !gc || purego
|
||||
// +build !arm64 !gc purego
|
||||
|
||||
package field
|
||||
|
||||
|
|
177
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/dns/dnsmessage/message.go
generated
vendored
177
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/dns/dnsmessage/message.go
generated
vendored
|
@ -260,9 +260,11 @@ var (
|
|||
errReserved = errors.New("segment prefix is reserved")
|
||||
errTooManyPtr = errors.New("too many pointers (>10)")
|
||||
errInvalidPtr = errors.New("invalid pointer")
|
||||
errInvalidName = errors.New("invalid dns name")
|
||||
errNilResouceBody = errors.New("nil resource body")
|
||||
errResourceLen = errors.New("insufficient data for resource body length")
|
||||
errSegTooLong = errors.New("segment length too long")
|
||||
errNameTooLong = errors.New("name too long")
|
||||
errZeroSegLen = errors.New("zero length segment")
|
||||
errResTooLong = errors.New("resource length too long")
|
||||
errTooManyQuestions = errors.New("too many Questions to pack (>65535)")
|
||||
|
@ -271,7 +273,6 @@ var (
|
|||
errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)")
|
||||
errNonCanonicalName = errors.New("name is not in canonical format (it must end with a .)")
|
||||
errStringTooLong = errors.New("character string exceeds maximum length (255)")
|
||||
errCompressedSRV = errors.New("compressed name in SRV resource data")
|
||||
)
|
||||
|
||||
// Internal constants.
|
||||
|
@ -359,6 +360,8 @@ func (m *Header) GoString() string {
|
|||
"Truncated: " + printBool(m.Truncated) + ", " +
|
||||
"RecursionDesired: " + printBool(m.RecursionDesired) + ", " +
|
||||
"RecursionAvailable: " + printBool(m.RecursionAvailable) + ", " +
|
||||
"AuthenticData: " + printBool(m.AuthenticData) + ", " +
|
||||
"CheckingDisabled: " + printBool(m.CheckingDisabled) + ", " +
|
||||
"RCode: " + m.RCode.GoString() + "}"
|
||||
}
|
||||
|
||||
|
@ -488,7 +491,7 @@ func (r *Resource) GoString() string {
|
|||
// A ResourceBody is a DNS resource record minus the header.
|
||||
type ResourceBody interface {
|
||||
// pack packs a Resource except for its header.
|
||||
pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error)
|
||||
pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error)
|
||||
|
||||
// realType returns the actual type of the Resource. This is used to
|
||||
// fill in the header Type field.
|
||||
|
@ -499,7 +502,7 @@ type ResourceBody interface {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the Resource to msg.
|
||||
func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *Resource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
if r.Body == nil {
|
||||
return msg, errNilResouceBody
|
||||
}
|
||||
|
@ -525,12 +528,14 @@ func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff i
|
|||
// When parsing is started, the Header is parsed. Next, each Question can be
|
||||
// either parsed or skipped. Alternatively, all Questions can be skipped at
|
||||
// once. When all Questions have been parsed, attempting to parse Questions
|
||||
// will return (nil, nil) and attempting to skip Questions will return
|
||||
// (true, nil). After all Questions have been either parsed or skipped, all
|
||||
// will return the [ErrSectionDone] error.
|
||||
// After all Questions have been either parsed or skipped, all
|
||||
// Answers, Authorities and Additionals can be either parsed or skipped in the
|
||||
// same way, and each type of Resource must be fully parsed or skipped before
|
||||
// proceeding to the next type of Resource.
|
||||
//
|
||||
// Parser is safe to copy to preserve the parsing state.
|
||||
//
|
||||
// Note that there is no requirement to fully skip or parse the message.
|
||||
type Parser struct {
|
||||
msg []byte
|
||||
|
@ -540,7 +545,9 @@ type Parser struct {
|
|||
off int
|
||||
index int
|
||||
resHeaderValid bool
|
||||
resHeader ResourceHeader
|
||||
resHeaderOffset int
|
||||
resHeaderType Type
|
||||
resHeaderLength uint16
|
||||
}
|
||||
|
||||
// Start parses the header and enables the parsing of Questions.
|
||||
|
@ -591,8 +598,9 @@ func (p *Parser) resource(sec section) (Resource, error) {
|
|||
|
||||
func (p *Parser) resourceHeader(sec section) (ResourceHeader, error) {
|
||||
if p.resHeaderValid {
|
||||
return p.resHeader, nil
|
||||
p.off = p.resHeaderOffset
|
||||
}
|
||||
|
||||
if err := p.checkAdvance(sec); err != nil {
|
||||
return ResourceHeader{}, err
|
||||
}
|
||||
|
@ -602,14 +610,16 @@ func (p *Parser) resourceHeader(sec section) (ResourceHeader, error) {
|
|||
return ResourceHeader{}, err
|
||||
}
|
||||
p.resHeaderValid = true
|
||||
p.resHeader = hdr
|
||||
p.resHeaderOffset = p.off
|
||||
p.resHeaderType = hdr.Type
|
||||
p.resHeaderLength = hdr.Length
|
||||
p.off = off
|
||||
return hdr, nil
|
||||
}
|
||||
|
||||
func (p *Parser) skipResource(sec section) error {
|
||||
if p.resHeaderValid {
|
||||
newOff := p.off + int(p.resHeader.Length)
|
||||
if p.resHeaderValid && p.section == sec {
|
||||
newOff := p.off + int(p.resHeaderLength)
|
||||
if newOff > len(p.msg) {
|
||||
return errResourceLen
|
||||
}
|
||||
|
@ -740,6 +750,9 @@ func (p *Parser) AllAnswers() ([]Resource, error) {
|
|||
}
|
||||
|
||||
// SkipAnswer skips a single Answer Resource.
|
||||
//
|
||||
// It does not perform a complete validation of the resource header, which means
|
||||
// it may return a nil error when the [AnswerHeader] would actually return an error.
|
||||
func (p *Parser) SkipAnswer() error {
|
||||
return p.skipResource(sectionAnswers)
|
||||
}
|
||||
|
@ -790,6 +803,9 @@ func (p *Parser) AllAuthorities() ([]Resource, error) {
|
|||
}
|
||||
|
||||
// SkipAuthority skips a single Authority Resource.
|
||||
//
|
||||
// It does not perform a complete validation of the resource header, which means
|
||||
// it may return a nil error when the [AuthorityHeader] would actually return an error.
|
||||
func (p *Parser) SkipAuthority() error {
|
||||
return p.skipResource(sectionAuthorities)
|
||||
}
|
||||
|
@ -840,6 +856,9 @@ func (p *Parser) AllAdditionals() ([]Resource, error) {
|
|||
}
|
||||
|
||||
// SkipAdditional skips a single Additional Resource.
|
||||
//
|
||||
// It does not perform a complete validation of the resource header, which means
|
||||
// it may return a nil error when the [AdditionalHeader] would actually return an error.
|
||||
func (p *Parser) SkipAdditional() error {
|
||||
return p.skipResource(sectionAdditionals)
|
||||
}
|
||||
|
@ -860,14 +879,14 @@ func (p *Parser) SkipAllAdditionals() error {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) CNAMEResource() (CNAMEResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypeCNAME {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypeCNAME {
|
||||
return CNAMEResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackCNAMEResource(p.msg, p.off)
|
||||
if err != nil {
|
||||
return CNAMEResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -878,14 +897,14 @@ func (p *Parser) CNAMEResource() (CNAMEResource, error) {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) MXResource() (MXResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypeMX {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypeMX {
|
||||
return MXResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackMXResource(p.msg, p.off)
|
||||
if err != nil {
|
||||
return MXResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -896,14 +915,14 @@ func (p *Parser) MXResource() (MXResource, error) {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) NSResource() (NSResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypeNS {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypeNS {
|
||||
return NSResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackNSResource(p.msg, p.off)
|
||||
if err != nil {
|
||||
return NSResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -914,14 +933,14 @@ func (p *Parser) NSResource() (NSResource, error) {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) PTRResource() (PTRResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypePTR {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypePTR {
|
||||
return PTRResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackPTRResource(p.msg, p.off)
|
||||
if err != nil {
|
||||
return PTRResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -932,14 +951,14 @@ func (p *Parser) PTRResource() (PTRResource, error) {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) SOAResource() (SOAResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypeSOA {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypeSOA {
|
||||
return SOAResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackSOAResource(p.msg, p.off)
|
||||
if err != nil {
|
||||
return SOAResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -950,14 +969,14 @@ func (p *Parser) SOAResource() (SOAResource, error) {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) TXTResource() (TXTResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypeTXT {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypeTXT {
|
||||
return TXTResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackTXTResource(p.msg, p.off, p.resHeader.Length)
|
||||
r, err := unpackTXTResource(p.msg, p.off, p.resHeaderLength)
|
||||
if err != nil {
|
||||
return TXTResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -968,14 +987,14 @@ func (p *Parser) TXTResource() (TXTResource, error) {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) SRVResource() (SRVResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypeSRV {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypeSRV {
|
||||
return SRVResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackSRVResource(p.msg, p.off)
|
||||
if err != nil {
|
||||
return SRVResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -986,14 +1005,14 @@ func (p *Parser) SRVResource() (SRVResource, error) {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) AResource() (AResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypeA {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypeA {
|
||||
return AResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackAResource(p.msg, p.off)
|
||||
if err != nil {
|
||||
return AResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -1004,14 +1023,14 @@ func (p *Parser) AResource() (AResource, error) {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) AAAAResource() (AAAAResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypeAAAA {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypeAAAA {
|
||||
return AAAAResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackAAAAResource(p.msg, p.off)
|
||||
if err != nil {
|
||||
return AAAAResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -1022,14 +1041,14 @@ func (p *Parser) AAAAResource() (AAAAResource, error) {
|
|||
// One of the XXXHeader methods must have been called before calling this
|
||||
// method.
|
||||
func (p *Parser) OPTResource() (OPTResource, error) {
|
||||
if !p.resHeaderValid || p.resHeader.Type != TypeOPT {
|
||||
if !p.resHeaderValid || p.resHeaderType != TypeOPT {
|
||||
return OPTResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackOPTResource(p.msg, p.off, p.resHeader.Length)
|
||||
r, err := unpackOPTResource(p.msg, p.off, p.resHeaderLength)
|
||||
if err != nil {
|
||||
return OPTResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -1043,11 +1062,11 @@ func (p *Parser) UnknownResource() (UnknownResource, error) {
|
|||
if !p.resHeaderValid {
|
||||
return UnknownResource{}, ErrNotStarted
|
||||
}
|
||||
r, err := unpackUnknownResource(p.resHeader.Type, p.msg, p.off, p.resHeader.Length)
|
||||
r, err := unpackUnknownResource(p.resHeaderType, p.msg, p.off, p.resHeaderLength)
|
||||
if err != nil {
|
||||
return UnknownResource{}, err
|
||||
}
|
||||
p.off += int(p.resHeader.Length)
|
||||
p.off += int(p.resHeaderLength)
|
||||
p.resHeaderValid = false
|
||||
p.index++
|
||||
return r, nil
|
||||
|
@ -1118,7 +1137,7 @@ func (m *Message) AppendPack(b []byte) ([]byte, error) {
|
|||
// DNS messages can be a maximum of 512 bytes long. Without compression,
|
||||
// many DNS response messages are over this limit, so enabling
|
||||
// compression will help ensure compliance.
|
||||
compression := map[string]int{}
|
||||
compression := map[string]uint16{}
|
||||
|
||||
for i := range m.Questions {
|
||||
var err error
|
||||
|
@ -1209,7 +1228,7 @@ type Builder struct {
|
|||
|
||||
// compression is a mapping from name suffixes to their starting index
|
||||
// in msg.
|
||||
compression map[string]int
|
||||
compression map[string]uint16
|
||||
}
|
||||
|
||||
// NewBuilder creates a new builder with compression disabled.
|
||||
|
@ -1246,7 +1265,7 @@ func NewBuilder(buf []byte, h Header) Builder {
|
|||
//
|
||||
// Compression should be enabled before any sections are added for best results.
|
||||
func (b *Builder) EnableCompression() {
|
||||
b.compression = map[string]int{}
|
||||
b.compression = map[string]uint16{}
|
||||
}
|
||||
|
||||
func (b *Builder) startCheck(s section) error {
|
||||
|
@ -1662,7 +1681,7 @@ func (h *ResourceHeader) GoString() string {
|
|||
// pack appends the wire format of the ResourceHeader to oldMsg.
|
||||
//
|
||||
// lenOff is the offset in msg where the Length field was packed.
|
||||
func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int, compressionOff int) (msg []byte, lenOff int, err error) {
|
||||
func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]uint16, compressionOff int) (msg []byte, lenOff int, err error) {
|
||||
msg = oldMsg
|
||||
if msg, err = h.Name.pack(msg, compression, compressionOff); err != nil {
|
||||
return oldMsg, 0, &nestedError{"Name", err}
|
||||
|
@ -1728,7 +1747,7 @@ const (
|
|||
//
|
||||
// The provided extRCode must be an extended RCode.
|
||||
func (h *ResourceHeader) SetEDNS0(udpPayloadLen int, extRCode RCode, dnssecOK bool) error {
|
||||
h.Name = Name{Data: [nameLen]byte{'.'}, Length: 1} // RFC 6891 section 6.1.2
|
||||
h.Name = Name{Data: [255]byte{'.'}, Length: 1} // RFC 6891 section 6.1.2
|
||||
h.Type = TypeOPT
|
||||
h.Class = Class(udpPayloadLen)
|
||||
h.TTL = uint32(extRCode) >> 4 << 24
|
||||
|
@ -1888,21 +1907,21 @@ func unpackBytes(msg []byte, off int, field []byte) (int, error) {
|
|||
return newOff, nil
|
||||
}
|
||||
|
||||
const nameLen = 255
|
||||
const nonEncodedNameMax = 254
|
||||
|
||||
// A Name is a non-encoded domain name. It is used instead of strings to avoid
|
||||
// A Name is a non-encoded and non-escaped domain name. It is used instead of strings to avoid
|
||||
// allocations.
|
||||
type Name struct {
|
||||
Data [nameLen]byte // 255 bytes
|
||||
Data [255]byte
|
||||
Length uint8
|
||||
}
|
||||
|
||||
// NewName creates a new Name from a string.
|
||||
func NewName(name string) (Name, error) {
|
||||
if len(name) > nameLen {
|
||||
n := Name{Length: uint8(len(name))}
|
||||
if len(name) > len(n.Data) {
|
||||
return Name{}, errCalcLen
|
||||
}
|
||||
n := Name{Length: uint8(len(name))}
|
||||
copy(n.Data[:], name)
|
||||
return n, nil
|
||||
}
|
||||
|
@ -1917,6 +1936,8 @@ func MustNewName(name string) Name {
|
|||
}
|
||||
|
||||
// String implements fmt.Stringer.String.
|
||||
//
|
||||
// Note: characters inside the labels are not escaped in any way.
|
||||
func (n Name) String() string {
|
||||
return string(n.Data[:n.Length])
|
||||
}
|
||||
|
@ -1933,9 +1954,13 @@ func (n *Name) GoString() string {
|
|||
//
|
||||
// The compression map will be updated with new domain suffixes. If compression
|
||||
// is nil, compression will not be used.
|
||||
func (n *Name) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (n *Name) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
oldMsg := msg
|
||||
|
||||
if n.Length > nonEncodedNameMax {
|
||||
return nil, errNameTooLong
|
||||
}
|
||||
|
||||
// Add a trailing dot to canonicalize name.
|
||||
if n.Length == 0 || n.Data[n.Length-1] != '.' {
|
||||
return oldMsg, errNonCanonicalName
|
||||
|
@ -1946,6 +1971,8 @@ func (n *Name) pack(msg []byte, compression map[string]int, compressionOff int)
|
|||
return append(msg, 0), nil
|
||||
}
|
||||
|
||||
var nameAsStr string
|
||||
|
||||
// Emit sequence of counted strings, chopping at dots.
|
||||
for i, begin := 0, 0; i < int(n.Length); i++ {
|
||||
// Check for the end of the segment.
|
||||
|
@ -1976,16 +2003,22 @@ func (n *Name) pack(msg []byte, compression map[string]int, compressionOff int)
|
|||
// segment. A pointer is two bytes with the two most significant
|
||||
// bits set to 1 to indicate that it is a pointer.
|
||||
if (i == 0 || n.Data[i-1] == '.') && compression != nil {
|
||||
if ptr, ok := compression[string(n.Data[i:])]; ok {
|
||||
if ptr, ok := compression[string(n.Data[i:n.Length])]; ok {
|
||||
// Hit. Emit a pointer instead of the rest of
|
||||
// the domain.
|
||||
return append(msg, byte(ptr>>8|0xC0), byte(ptr)), nil
|
||||
}
|
||||
|
||||
// Miss. Add the suffix to the compression table if the
|
||||
// offset can be stored in the available 14 bytes.
|
||||
if len(msg) <= int(^uint16(0)>>2) {
|
||||
compression[string(n.Data[i:])] = len(msg) - compressionOff
|
||||
// offset can be stored in the available 14 bits.
|
||||
newPtr := len(msg) - compressionOff
|
||||
if newPtr <= int(^uint16(0)>>2) {
|
||||
if nameAsStr == "" {
|
||||
// allocate n.Data on the heap once, to avoid allocating it
|
||||
// multiple times (for next labels).
|
||||
nameAsStr = string(n.Data[:n.Length])
|
||||
}
|
||||
compression[nameAsStr[i:]] = uint16(newPtr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1994,10 +2027,6 @@ func (n *Name) pack(msg []byte, compression map[string]int, compressionOff int)
|
|||
|
||||
// unpack unpacks a domain name.
|
||||
func (n *Name) unpack(msg []byte, off int) (int, error) {
|
||||
return n.unpackCompressed(msg, off, true /* allowCompression */)
|
||||
}
|
||||
|
||||
func (n *Name) unpackCompressed(msg []byte, off int, allowCompression bool) (int, error) {
|
||||
// currOff is the current working offset.
|
||||
currOff := off
|
||||
|
||||
|
@ -2029,13 +2058,19 @@ Loop:
|
|||
if endOff > len(msg) {
|
||||
return off, errCalcLen
|
||||
}
|
||||
|
||||
// Reject names containing dots.
|
||||
// See issue golang/go#56246
|
||||
for _, v := range msg[currOff:endOff] {
|
||||
if v == '.' {
|
||||
return off, errInvalidName
|
||||
}
|
||||
}
|
||||
|
||||
name = append(name, msg[currOff:endOff]...)
|
||||
name = append(name, '.')
|
||||
currOff = endOff
|
||||
case 0xC0: // Pointer
|
||||
if !allowCompression {
|
||||
return off, errCompressedSRV
|
||||
}
|
||||
if currOff >= len(msg) {
|
||||
return off, errInvalidPtr
|
||||
}
|
||||
|
@ -2057,8 +2092,8 @@ Loop:
|
|||
if len(name) == 0 {
|
||||
name = append(name, '.')
|
||||
}
|
||||
if len(name) > len(n.Data) {
|
||||
return off, errCalcLen
|
||||
if len(name) > nonEncodedNameMax {
|
||||
return off, errNameTooLong
|
||||
}
|
||||
n.Length = uint8(len(name))
|
||||
if ptr == 0 {
|
||||
|
@ -2116,7 +2151,7 @@ type Question struct {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the Question to msg.
|
||||
func (q *Question) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (q *Question) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
msg, err := q.Name.pack(msg, compression, compressionOff)
|
||||
if err != nil {
|
||||
return msg, &nestedError{"Name", err}
|
||||
|
@ -2212,7 +2247,7 @@ func (r *CNAMEResource) realType() Type {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the CNAMEResource to msg.
|
||||
func (r *CNAMEResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *CNAMEResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
return r.CNAME.pack(msg, compression, compressionOff)
|
||||
}
|
||||
|
||||
|
@ -2240,7 +2275,7 @@ func (r *MXResource) realType() Type {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the MXResource to msg.
|
||||
func (r *MXResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *MXResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
oldMsg := msg
|
||||
msg = packUint16(msg, r.Pref)
|
||||
msg, err := r.MX.pack(msg, compression, compressionOff)
|
||||
|
@ -2279,7 +2314,7 @@ func (r *NSResource) realType() Type {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the NSResource to msg.
|
||||
func (r *NSResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *NSResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
return r.NS.pack(msg, compression, compressionOff)
|
||||
}
|
||||
|
||||
|
@ -2306,7 +2341,7 @@ func (r *PTRResource) realType() Type {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the PTRResource to msg.
|
||||
func (r *PTRResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *PTRResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
return r.PTR.pack(msg, compression, compressionOff)
|
||||
}
|
||||
|
||||
|
@ -2343,7 +2378,7 @@ func (r *SOAResource) realType() Type {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the SOAResource to msg.
|
||||
func (r *SOAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *SOAResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
oldMsg := msg
|
||||
msg, err := r.NS.pack(msg, compression, compressionOff)
|
||||
if err != nil {
|
||||
|
@ -2415,7 +2450,7 @@ func (r *TXTResource) realType() Type {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the TXTResource to msg.
|
||||
func (r *TXTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *TXTResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
oldMsg := msg
|
||||
for _, s := range r.TXT {
|
||||
var err error
|
||||
|
@ -2471,7 +2506,7 @@ func (r *SRVResource) realType() Type {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the SRVResource to msg.
|
||||
func (r *SRVResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *SRVResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
oldMsg := msg
|
||||
msg = packUint16(msg, r.Priority)
|
||||
msg = packUint16(msg, r.Weight)
|
||||
|
@ -2506,7 +2541,7 @@ func unpackSRVResource(msg []byte, off int) (SRVResource, error) {
|
|||
return SRVResource{}, &nestedError{"Port", err}
|
||||
}
|
||||
var target Name
|
||||
if _, err := target.unpackCompressed(msg, off, false /* allowCompression */); err != nil {
|
||||
if _, err := target.unpack(msg, off); err != nil {
|
||||
return SRVResource{}, &nestedError{"Target", err}
|
||||
}
|
||||
return SRVResource{priority, weight, port, target}, nil
|
||||
|
@ -2522,7 +2557,7 @@ func (r *AResource) realType() Type {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the AResource to msg.
|
||||
func (r *AResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *AResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
return packBytes(msg, r.A[:]), nil
|
||||
}
|
||||
|
||||
|
@ -2556,7 +2591,7 @@ func (r *AAAAResource) GoString() string {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the AAAAResource to msg.
|
||||
func (r *AAAAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *AAAAResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
return packBytes(msg, r.AAAA[:]), nil
|
||||
}
|
||||
|
||||
|
@ -2596,7 +2631,7 @@ func (r *OPTResource) realType() Type {
|
|||
return TypeOPT
|
||||
}
|
||||
|
||||
func (r *OPTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *OPTResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
for _, opt := range r.Options {
|
||||
msg = packUint16(msg, opt.Code)
|
||||
l := uint16(len(opt.Data))
|
||||
|
@ -2654,7 +2689,7 @@ func (r *UnknownResource) realType() Type {
|
|||
}
|
||||
|
||||
// pack appends the wire format of the UnknownResource to msg.
|
||||
func (r *UnknownResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
||||
func (r *UnknownResource) pack(msg []byte, compression map[string]uint16, compressionOff int) ([]byte, error) {
|
||||
return packBytes(msg, r.Data[:]), nil
|
||||
}
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd
|
||||
// +build aix darwin dragonfly freebsd netbsd openbsd
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (arm || mips || mipsle || 386 || ppc) && linux
|
||||
// +build arm mips mipsle 386 ppc
|
||||
// +build linux
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (arm64 || amd64 || loong64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
|
||||
// +build arm64 amd64 loong64 ppc64 ppc64le mips64 mips64le riscv64 s390x
|
||||
// +build linux
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && solaris
|
||||
// +build amd64,solaris
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos
|
||||
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || windows || zos
|
||||
// +build aix windows zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/empty.s
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/empty.s
generated
vendored
|
@ -3,6 +3,5 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && go1.12
|
||||
// +build darwin,go1.12
|
||||
|
||||
// This exists solely so we can linkname in symbols from syscall.
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/error_unix.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
2
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
2
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/iovec_32bit.go
generated
vendored
|
@ -3,8 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (arm || mips || mipsle || 386 || ppc) && (darwin || dragonfly || freebsd || linux || netbsd || openbsd)
|
||||
// +build arm mips mipsle 386 ppc
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package socket
|
||||
|
||||
|
|
2
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
2
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/iovec_64bit.go
generated
vendored
|
@ -3,8 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (arm64 || amd64 || loong64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos)
|
||||
// +build arm64 amd64 loong64 ppc64 ppc64le mips64 mips64le riscv64 s390x
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && solaris
|
||||
// +build amd64,solaris
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/iovec_stub.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos
|
||||
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !aix && !linux && !netbsd
|
||||
// +build !aix,!linux,!netbsd
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || linux || netbsd
|
||||
// +build aix linux netbsd
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd
|
||||
// +build aix darwin dragonfly freebsd netbsd openbsd
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || netbsd
|
||||
// +build aix darwin dragonfly freebsd netbsd
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (arm || mips || mipsle || 386 || ppc) && linux
|
||||
// +build arm mips mipsle 386 ppc
|
||||
// +build linux
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (arm64 || amd64 || loong64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux
|
||||
// +build arm64 amd64 loong64 ppc64 ppc64le mips64 mips64le riscv64 s390x
|
||||
// +build linux
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && solaris
|
||||
// +build amd64,solaris
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/msghdr_stub.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/msghdr_stub.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos
|
||||
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/msghdr_zos_s390x.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/msghdr_zos_s390x.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build s390x && zos
|
||||
// +build s390x,zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/norace.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/norace.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !race
|
||||
// +build !race
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/race.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/race.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build race
|
||||
// +build race
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/rawconn_msg.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/rawconn_msg.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos
|
||||
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_bsd.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_bsd.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris
|
||||
// +build aix darwin dragonfly freebsd openbsd solaris
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_const_unix.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_const_unix.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_linux.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_linux.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && !s390x && !386
|
||||
// +build linux,!s390x,!386
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build loong64
|
||||
// +build loong64
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build riscv64
|
||||
// +build riscv64
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_posix.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_posix.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_stub.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_stub.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos
|
||||
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_unix.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/sys_unix.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package socket
|
||||
|
||||
|
|
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go
generated
vendored
1
trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go
generated
vendored
|
@ -3,7 +3,6 @@
|
|||
|
||||
// Added for go1.11 compatibility
|
||||
//go:build aix
|
||||
// +build aix
|
||||
|
||||
package socket
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// cgo -godefs defs_linux.go
|
||||
|
||||
//go:build loong64
|
||||
// +build loong64
|
||||
|
||||
package socket
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue