update pion/webrtc to v4. v7.0.34 (#4359)
To enable H.265 support for the WebRTC protocol, upgrade the pion/webrtc library to version 4. --------- Co-authored-by: john <hondaxiao@tencent.com> Co-authored-by: winlin <winlinvip@gmail.com>
This commit is contained in:
parent
53a6af659f
commit
974826800f
11
trunk/3rdparty/srs-bench/gb28181/ingester.go
vendored
11
trunk/3rdparty/srs-bench/gb28181/ingester.go
vendored
|
|
@ -22,11 +22,6 @@ package gb28181
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/ghettovoice/gosip/sip"
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/pion/webrtc/v3/pkg/media/h264reader"
|
||||
"github.com/yapingcat/gomedia/mpeg2"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
|
|
@ -34,6 +29,12 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ghettovoice/gosip/sip"
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/pion/webrtc/v4/pkg/media/h264reader"
|
||||
"github.com/yapingcat/gomedia/mpeg2"
|
||||
)
|
||||
|
||||
type GBSessionConfig struct {
|
||||
|
|
|
|||
47
trunk/3rdparty/srs-bench/go.mod
vendored
47
trunk/3rdparty/srs-bench/go.mod
vendored
|
|
@ -1,53 +1,50 @@
|
|||
module github.com/ossrs/srs-bench
|
||||
|
||||
go 1.17
|
||||
go 1.21
|
||||
|
||||
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
|
||||
github.com/pion/logging v0.2.2
|
||||
github.com/pion/rtcp v1.2.10
|
||||
github.com/pion/rtp v1.7.13
|
||||
github.com/pion/sdp/v3 v3.0.6
|
||||
github.com/pion/transport/v2 v2.2.1
|
||||
github.com/pion/webrtc/v3 v3.2.9
|
||||
github.com/pion/ice/v4 v4.0.10
|
||||
github.com/pion/interceptor v0.1.37
|
||||
github.com/pion/logging v0.2.3
|
||||
github.com/pion/rtcp v1.2.15
|
||||
github.com/pion/rtp v1.8.15
|
||||
github.com/pion/sdp/v3 v3.0.11
|
||||
github.com/pion/transport/v3 v3.0.7
|
||||
github.com/pion/webrtc/v4 v4.1.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/yapingcat/gomedia/codec v0.0.0-20220617074658-94762898dc25
|
||||
github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.1.0-rc.1 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
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
|
||||
github.com/pion/mdns v0.0.7 // indirect
|
||||
github.com/pion/datachannel v1.5.10 // indirect
|
||||
github.com/pion/dtls/v3 v3.0.6 // indirect
|
||||
github.com/pion/mdns/v2 v2.0.7 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/pion/sctp v1.8.7 // indirect
|
||||
github.com/pion/srtp/v2 v2.0.15 // indirect
|
||||
github.com/pion/stun v0.6.0 // indirect
|
||||
github.com/pion/turn/v2 v2.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pion/sctp v1.8.39 // indirect
|
||||
github.com/pion/srtp/v3 v3.0.4 // indirect
|
||||
github.com/pion/stun/v3 v3.0.0 // indirect
|
||||
github.com/pion/turn/v4 v4.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.9.0 // indirect
|
||||
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5 // indirect
|
||||
github.com/wlynxg/anet v0.0.5 // indirect
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // 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
|
||||
golang.org/x/crypto v0.33.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/term v0.29.0 // indirect
|
||||
)
|
||||
|
|
|
|||
187
trunk/3rdparty/srs-bench/go.sum
vendored
187
trunk/3rdparty/srs-bench/go.sum
vendored
|
|
@ -1,4 +1,3 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/discoviking/fsm v0.0.0-20150126104936-f4a273feecca/go.mod h1:W+3LQaEkN8qAwwcw0KC546sUEnX86GIT8CcMLZC4mG0=
|
||||
|
|
@ -7,7 +6,6 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
|
|||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/ghettovoice/gosip v0.0.0-20220929080231-de8ba881be83 h1:4v14bwSGZH2usyuG9XWZgMbGkVU33ayg0cb68nvKfj0=
|
||||
github.com/ghettovoice/gosip v0.0.0-20220929080231-de8ba881be83/go.mod h1:yTr3BEYSFe9As6XM7ldyrVgqsPwlnw8Ahc4N28VFM2g=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||
|
|
@ -21,16 +19,13 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
|||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.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=
|
||||
|
|
@ -39,9 +34,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3
|
|||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
|
|
@ -51,13 +45,11 @@ github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnU
|
|||
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=
|
||||
github.com/nxadm/tail v1.4.5 h1:obHEce3upls1IBn1gTw/o7bCv7OJb6Ib/o7wNO+4eKw=
|
||||
github.com/nxadm/tail v1.4.5/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
|
|
@ -67,71 +59,54 @@ github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE=
|
|||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/ossrs/go-oryx-lib v0.0.9 h1:piZkzit/1hqAcXP31/mvDEDpHVjCmBMmvzF3hN8hUuQ=
|
||||
github.com/ossrs/go-oryx-lib v0.0.9/go.mod h1:i2tH4TZBzAw5h+HwGrNOKvP/nmZgSQz0OEnLLdzcT/8=
|
||||
github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
|
||||
github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0=
|
||||
github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
|
||||
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
||||
github.com/pion/ice/v2 v2.3.6 h1:Jgqw36cAud47iD+N6rNX225uHvrgWtAlHfVyOQc3Heg=
|
||||
github.com/pion/ice/v2 v2.3.6/go.mod h1:9/TzKDRwBVAPsC+YOrKH/e3xDrubeTRACU9/sHQarsU=
|
||||
github.com/pion/interceptor v0.1.17 h1:prJtgwFh/gB8zMqGZoOgJPHivOwVAp61i2aG61Du/1w=
|
||||
github.com/pion/interceptor v0.1.17/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI=
|
||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||
github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U=
|
||||
github.com/pion/mdns v0.0.7/go.mod h1:4iP2UbeFhLI/vWju/bw6ZfwjJzk0z8DNValjGxR/dD8=
|
||||
github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
|
||||
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
|
||||
github.com/pion/dtls/v3 v3.0.6 h1:7Hkd8WhAJNbRgq9RgdNh1aaWlZlGpYTzdqjy9x9sK2E=
|
||||
github.com/pion/dtls/v3 v3.0.6/go.mod h1:iJxNQ3Uhn1NZWOMWlLxEEHAN5yX7GyPvvKw04v9bzYU=
|
||||
github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4=
|
||||
github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
|
||||
github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
|
||||
github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
|
||||
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
|
||||
github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
|
||||
github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
|
||||
github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc=
|
||||
github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I=
|
||||
github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA=
|
||||
github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0=
|
||||
github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw=
|
||||
github.com/pion/sctp v1.8.7/go.mod h1:g1Ul+ARqZq5JEmoFy87Q/4CePtKnTJ1QCL9dBBdN6AU=
|
||||
github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw=
|
||||
github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw=
|
||||
github.com/pion/srtp/v2 v2.0.15 h1:+tqRtXGsGwHC0G0IUIAzRmdkHvriF79IHVfZGfHrQoA=
|
||||
github.com/pion/srtp/v2 v2.0.15/go.mod h1:b/pQOlDrbB0HEH5EUAQXzSYxikFbNcNuKmF8tM0hCtw=
|
||||
github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw=
|
||||
github.com/pion/stun v0.6.0 h1:JHT/2iyGDPrFWE8NNC15wnddBN8KifsEDw8swQmrEmU=
|
||||
github.com/pion/stun v0.6.0/go.mod h1:HPqcfoeqQn9cuaet7AOmB5e5xkObu9DwBdurwLKO9oA=
|
||||
github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40=
|
||||
github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI=
|
||||
github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc=
|
||||
github.com/pion/transport/v2 v2.1.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ=
|
||||
github.com/pion/transport/v2 v2.2.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ=
|
||||
github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c=
|
||||
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
|
||||
github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI=
|
||||
github.com/pion/turn/v2 v2.1.0/go.mod h1:yrT5XbXSGX1VFSF31A3c1kCNB5bBZgk/uu5LET162qs=
|
||||
github.com/pion/webrtc/v3 v3.2.9 h1:U8NSjQDlZZ+Iy/hg42Q/u6mhEVSXYvKrOIZiZwYTfLc=
|
||||
github.com/pion/webrtc/v3 v3.2.9/go.mod h1:gjQLMZeyN3jXBGdxGmUYCyKjOuYX/c99BDjGqmadq0A=
|
||||
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
|
||||
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
|
||||
github.com/pion/rtp v1.8.15 h1:MuhuGn1cxpVCPLNY1lI7F1tQ8Spntpgf12ob+pOYT8s=
|
||||
github.com/pion/rtp v1.8.15/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk=
|
||||
github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE=
|
||||
github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
|
||||
github.com/pion/sdp/v3 v3.0.11 h1:VhgVSopdsBKwhCFoyyPmT1fKMeV9nLMrEKxNOdy3IVI=
|
||||
github.com/pion/sdp/v3 v3.0.11/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
|
||||
github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
|
||||
github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
|
||||
github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
|
||||
github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
|
||||
github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
|
||||
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
|
||||
github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
|
||||
github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
|
||||
github.com/pion/webrtc/v4 v4.1.1 h1:PMFPtLg1kpD2pVtun+LGUzA3k54JdFl87WO0Z1+HKug=
|
||||
github.com/pion/webrtc/v4 v4.1.1/go.mod h1:cgEGkcpxGkT6Di2ClBYO5lP9mFXbCfEOrkYUpjjCQO4=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM=
|
||||
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
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=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
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/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/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.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/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
||||
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||
github.com/yapingcat/gomedia/codec v0.0.0-20220609081842-9e0c0e8a19a0/go.mod h1:obSECV6X3NPUsLL0olA7DurvQHKMq7J3iBTNQ4bL/vQ=
|
||||
|
|
@ -139,44 +114,22 @@ github.com/yapingcat/gomedia/codec v0.0.0-20220617074658-94762898dc25 h1:1mq/skG
|
|||
github.com/yapingcat/gomedia/codec v0.0.0-20220617074658-94762898dc25/go.mod h1:obSECV6X3NPUsLL0olA7DurvQHKMq7J3iBTNQ4bL/vQ=
|
||||
github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25 h1:51qjqT2jsOESm/jDi0k0AdQX33Sg4vhw8X6eooj7c8A=
|
||||
github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25/go.mod h1:bvxj2Oi5Rwj7eHm2OjqgOIs8x2T0j+V068eS/SAyZLA=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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/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/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
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=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
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/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/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
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=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -189,54 +142,19 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
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=
|
||||
golang.org/x/sys v0.0.0-20201214095126-aec9a390925b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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/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=
|
||||
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/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/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
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=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
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/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/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
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=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
@ -246,19 +164,14 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
|
|||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
|||
8
trunk/3rdparty/srs-bench/janus/ingester.go
vendored
8
trunk/3rdparty/srs-bench/janus/ingester.go
vendored
|
|
@ -32,10 +32,10 @@ import (
|
|||
"github.com/pion/interceptor"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"github.com/pion/webrtc/v3/pkg/media"
|
||||
"github.com/pion/webrtc/v3/pkg/media/h264reader"
|
||||
"github.com/pion/webrtc/v3/pkg/media/oggreader"
|
||||
"github.com/pion/webrtc/v4"
|
||||
"github.com/pion/webrtc/v4/pkg/media"
|
||||
"github.com/pion/webrtc/v4/pkg/media/h264reader"
|
||||
"github.com/pion/webrtc/v4/pkg/media/oggreader"
|
||||
)
|
||||
|
||||
type videoIngester struct {
|
||||
|
|
|
|||
11
trunk/3rdparty/srs-bench/janus/player.go
vendored
11
trunk/3rdparty/srs-bench/janus/player.go
vendored
|
|
@ -23,16 +23,17 @@ package janus
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/pion/interceptor"
|
||||
"github.com/pion/rtcp"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
func startPlay(ctx context.Context, r string, enableAudioLevel, enableTWCC bool, pli int) error {
|
||||
|
|
|
|||
11
trunk/3rdparty/srs-bench/janus/publisher.go
vendored
11
trunk/3rdparty/srs-bench/janus/publisher.go
vendored
|
|
@ -23,16 +23,17 @@ package janus
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/pion/interceptor"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"io"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/pion/interceptor"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
func startPublish(ctx context.Context, r, sourceAudio, sourceVideo string, fps int, enableAudioLevel, enableTWCC bool) error {
|
||||
|
|
|
|||
10
trunk/3rdparty/srs-bench/janus/util.go
vendored
10
trunk/3rdparty/srs-bench/janus/util.go
vendored
|
|
@ -44,9 +44,9 @@ import (
|
|||
"github.com/pion/interceptor"
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/rtcp"
|
||||
"github.com/pion/transport/v2/vnet"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"github.com/pion/webrtc/v3/pkg/media/h264reader"
|
||||
"github.com/pion/transport/v3/vnet"
|
||||
"github.com/pion/webrtc/v4"
|
||||
"github.com/pion/webrtc/v4/pkg/media/h264reader"
|
||||
)
|
||||
|
||||
var srsHttps *bool
|
||||
|
|
@ -647,7 +647,7 @@ func (v *testWebRTCAPI) Setup(vnetClientIP string, options ...testWebRTCAPIOptio
|
|||
return errors.Wrapf(err, "create network for api")
|
||||
}
|
||||
|
||||
v.settingEngine.SetVNet(v.network)
|
||||
v.settingEngine.SetNet(v.network)
|
||||
|
||||
// Create a proxy bind to the router.
|
||||
if v.proxy, err = vnet_proxy.NewProxy(v.router); err != nil {
|
||||
|
|
@ -1012,7 +1012,7 @@ func (v *testPublisher) Run(ctx context.Context, cancel context.CancelFunc) erro
|
|||
logger.Tf(ctx, "State signaling=%v, ice=%v, conn=%v", pc.SignalingState(), pc.ICEConnectionState(), pc.ConnectionState())
|
||||
|
||||
// ICE state management.
|
||||
pc.OnICEGatheringStateChange(func(state webrtc.ICEGathererState) {
|
||||
pc.OnICEGatheringStateChange(func(state webrtc.ICEGatheringState) {
|
||||
logger.Tf(ctx, "ICE gather state %v", state)
|
||||
})
|
||||
pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
|
||||
|
|
|
|||
8
trunk/3rdparty/srs-bench/srs/ingester.go
vendored
8
trunk/3rdparty/srs-bench/srs/ingester.go
vendored
|
|
@ -32,10 +32,10 @@ import (
|
|||
"github.com/pion/interceptor"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"github.com/pion/webrtc/v3/pkg/media"
|
||||
"github.com/pion/webrtc/v3/pkg/media/h264reader"
|
||||
"github.com/pion/webrtc/v3/pkg/media/oggreader"
|
||||
"github.com/pion/webrtc/v4"
|
||||
"github.com/pion/webrtc/v4/pkg/media"
|
||||
"github.com/pion/webrtc/v4/pkg/media/h264reader"
|
||||
"github.com/pion/webrtc/v4/pkg/media/oggreader"
|
||||
)
|
||||
|
||||
type videoIngester struct {
|
||||
|
|
|
|||
10
trunk/3rdparty/srs-bench/srs/player.go
vendored
10
trunk/3rdparty/srs-bench/srs/player.go
vendored
|
|
@ -32,11 +32,11 @@ import (
|
|||
"github.com/pion/interceptor"
|
||||
"github.com/pion/rtcp"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"github.com/pion/webrtc/v3/pkg/media"
|
||||
"github.com/pion/webrtc/v3/pkg/media/h264writer"
|
||||
"github.com/pion/webrtc/v3/pkg/media/ivfwriter"
|
||||
"github.com/pion/webrtc/v3/pkg/media/oggwriter"
|
||||
"github.com/pion/webrtc/v4"
|
||||
"github.com/pion/webrtc/v4/pkg/media"
|
||||
"github.com/pion/webrtc/v4/pkg/media/h264writer"
|
||||
"github.com/pion/webrtc/v4/pkg/media/ivfwriter"
|
||||
"github.com/pion/webrtc/v4/pkg/media/oggwriter"
|
||||
)
|
||||
|
||||
// @see https://github.com/pion/webrtc/blob/master/examples/save-to-disk/main.go
|
||||
|
|
|
|||
2
trunk/3rdparty/srs-bench/srs/publisher.go
vendored
2
trunk/3rdparty/srs-bench/srs/publisher.go
vendored
|
|
@ -30,7 +30,7 @@ import (
|
|||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
"github.com/pion/interceptor"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
// @see https://github.com/pion/webrtc/blob/master/examples/play-from-disk/main.go
|
||||
|
|
|
|||
4
trunk/3rdparty/srs-bench/srs/rtc_test.go
vendored
4
trunk/3rdparty/srs-bench/srs/rtc_test.go
vendored
|
|
@ -34,8 +34,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pion/transport/v2/vnet"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"github.com/pion/transport/v3/vnet"
|
||||
"github.com/pion/webrtc/v4"
|
||||
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/flv"
|
||||
|
|
|
|||
25
trunk/3rdparty/srs-bench/srs/util.go
vendored
25
trunk/3rdparty/srs-bench/srs/util.go
vendored
|
|
@ -31,13 +31,6 @@ import (
|
|||
"crypto/x509/pkix"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/ossrs/go-oryx-lib/amf0"
|
||||
"github.com/ossrs/go-oryx-lib/avc"
|
||||
"github.com/ossrs/go-oryx-lib/flv"
|
||||
"github.com/ossrs/go-oryx-lib/rtmp"
|
||||
"github.com/pion/ice/v2"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/rtp/codecs"
|
||||
"io"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
|
|
@ -51,15 +44,23 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ossrs/go-oryx-lib/amf0"
|
||||
"github.com/ossrs/go-oryx-lib/avc"
|
||||
"github.com/ossrs/go-oryx-lib/flv"
|
||||
"github.com/ossrs/go-oryx-lib/rtmp"
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/rtp/codecs"
|
||||
|
||||
"github.com/ossrs/go-oryx-lib/errors"
|
||||
"github.com/ossrs/go-oryx-lib/logger"
|
||||
vnet_proxy "github.com/ossrs/srs-bench/vnet"
|
||||
"github.com/pion/interceptor"
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/rtcp"
|
||||
"github.com/pion/transport/v2/vnet"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"github.com/pion/webrtc/v3/pkg/media/h264reader"
|
||||
"github.com/pion/transport/v3/vnet"
|
||||
"github.com/pion/webrtc/v4"
|
||||
"github.com/pion/webrtc/v4/pkg/media/h264reader"
|
||||
)
|
||||
|
||||
var srsHttps *bool
|
||||
|
|
@ -735,7 +736,7 @@ func (v *testWebRTCAPI) Setup(vnetClientIP string, options ...testWebRTCAPIOptio
|
|||
return errors.Wrapf(err, "create network for api")
|
||||
}
|
||||
|
||||
v.settingEngine.SetVNet(v.network)
|
||||
v.settingEngine.SetNet(v.network)
|
||||
|
||||
// Create a proxy bind to the router.
|
||||
if v.proxy, err = vnet_proxy.NewProxy(v.router); err != nil {
|
||||
|
|
@ -1213,7 +1214,7 @@ func (v *testPublisher) Run(ctx context.Context, cancel context.CancelFunc) erro
|
|||
logger.Tf(ctx, "State signaling=%v, ice=%v, conn=%v", pc.SignalingState(), pc.ICEConnectionState(), pc.ConnectionState())
|
||||
|
||||
// ICE state management.
|
||||
pc.OnICEGatheringStateChange(func(state webrtc.ICEGathererState) {
|
||||
pc.OnICEGatheringStateChange(func(state webrtc.ICEGatheringState) {
|
||||
logger.Tf(ctx, "ICE gather state %v", state)
|
||||
})
|
||||
pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
|
||||
|
|
|
|||
15
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
15
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
|
|
@ -1,15 +0,0 @@
|
|||
ISC License
|
||||
|
||||
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
145
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
145
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
|
|
@ -1,145 +0,0 @@
|
|||
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
||||
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// Go versions prior to 1.4 are disabled because they use a different layout
|
||||
// for interfaces which make the implementation of unsafeReflectValue more complex.
|
||||
// +build !js,!appengine,!safe,!disableunsafe,go1.4
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// UnsafeDisabled is a build-time constant which specifies whether or
|
||||
// not access to the unsafe package is available.
|
||||
UnsafeDisabled = false
|
||||
|
||||
// ptrSize is the size of a pointer on the current arch.
|
||||
ptrSize = unsafe.Sizeof((*byte)(nil))
|
||||
)
|
||||
|
||||
type flag uintptr
|
||||
|
||||
var (
|
||||
// flagRO indicates whether the value field of a reflect.Value
|
||||
// is read-only.
|
||||
flagRO flag
|
||||
|
||||
// flagAddr indicates whether the address of the reflect.Value's
|
||||
// value may be taken.
|
||||
flagAddr flag
|
||||
)
|
||||
|
||||
// flagKindMask holds the bits that make up the kind
|
||||
// part of the flags field. In all the supported versions,
|
||||
// it is in the lower 5 bits.
|
||||
const flagKindMask = flag(0x1f)
|
||||
|
||||
// Different versions of Go have used different
|
||||
// bit layouts for the flags type. This table
|
||||
// records the known combinations.
|
||||
var okFlags = []struct {
|
||||
ro, addr flag
|
||||
}{{
|
||||
// From Go 1.4 to 1.5
|
||||
ro: 1 << 5,
|
||||
addr: 1 << 7,
|
||||
}, {
|
||||
// Up to Go tip.
|
||||
ro: 1<<5 | 1<<6,
|
||||
addr: 1 << 8,
|
||||
}}
|
||||
|
||||
var flagValOffset = func() uintptr {
|
||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||
if !ok {
|
||||
panic("reflect.Value has no flag field")
|
||||
}
|
||||
return field.Offset
|
||||
}()
|
||||
|
||||
// flagField returns a pointer to the flag field of a reflect.Value.
|
||||
func flagField(v *reflect.Value) *flag {
|
||||
return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
|
||||
}
|
||||
|
||||
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
|
||||
// the typical safety restrictions preventing access to unaddressable and
|
||||
// unexported data. It works by digging the raw pointer to the underlying
|
||||
// value out of the protected value and generating a new unprotected (unsafe)
|
||||
// reflect.Value to it.
|
||||
//
|
||||
// This allows us to check for implementations of the Stringer and error
|
||||
// interfaces to be used for pretty printing ordinarily unaddressable and
|
||||
// inaccessible values such as unexported struct fields.
|
||||
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
||||
if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
|
||||
return v
|
||||
}
|
||||
flagFieldPtr := flagField(&v)
|
||||
*flagFieldPtr &^= flagRO
|
||||
*flagFieldPtr |= flagAddr
|
||||
return v
|
||||
}
|
||||
|
||||
// Sanity checks against future reflect package changes
|
||||
// to the type or semantics of the Value.flag field.
|
||||
func init() {
|
||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||
if !ok {
|
||||
panic("reflect.Value has no flag field")
|
||||
}
|
||||
if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
|
||||
panic("reflect.Value flag field has changed kind")
|
||||
}
|
||||
type t0 int
|
||||
var t struct {
|
||||
A t0
|
||||
// t0 will have flagEmbedRO set.
|
||||
t0
|
||||
// a will have flagStickyRO set
|
||||
a t0
|
||||
}
|
||||
vA := reflect.ValueOf(t).FieldByName("A")
|
||||
va := reflect.ValueOf(t).FieldByName("a")
|
||||
vt0 := reflect.ValueOf(t).FieldByName("t0")
|
||||
|
||||
// Infer flagRO from the difference between the flags
|
||||
// for the (otherwise identical) fields in t.
|
||||
flagPublic := *flagField(&vA)
|
||||
flagWithRO := *flagField(&va) | *flagField(&vt0)
|
||||
flagRO = flagPublic ^ flagWithRO
|
||||
|
||||
// Infer flagAddr from the difference between a value
|
||||
// taken from a pointer and not.
|
||||
vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
|
||||
flagNoPtr := *flagField(&vA)
|
||||
flagPtr := *flagField(&vPtrA)
|
||||
flagAddr = flagNoPtr ^ flagPtr
|
||||
|
||||
// Check that the inferred flags tally with one of the known versions.
|
||||
for _, f := range okFlags {
|
||||
if flagRO == f.ro && flagAddr == f.addr {
|
||||
return
|
||||
}
|
||||
}
|
||||
panic("reflect.Value read-only flag has changed semantics")
|
||||
}
|
||||
38
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
38
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||
// when the code is running on Google App Engine, compiled by GopherJS, or
|
||||
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// +build js appengine safe disableunsafe !go1.4
|
||||
|
||||
package spew
|
||||
|
||||
import "reflect"
|
||||
|
||||
const (
|
||||
// UnsafeDisabled is a build-time constant which specifies whether or
|
||||
// not access to the unsafe package is available.
|
||||
UnsafeDisabled = true
|
||||
)
|
||||
|
||||
// unsafeReflectValue typically converts the passed reflect.Value into a one
|
||||
// that bypasses the typical safety restrictions preventing access to
|
||||
// unaddressable and unexported data. However, doing this relies on access to
|
||||
// the unsafe package. This is a stub version which simply returns the passed
|
||||
// reflect.Value when the unsafe package is not available.
|
||||
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
||||
return v
|
||||
}
|
||||
341
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
341
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
|
|
@ -1,341 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Some constants in the form of bytes to avoid string overhead. This mirrors
|
||||
// the technique used in the fmt package.
|
||||
var (
|
||||
panicBytes = []byte("(PANIC=")
|
||||
plusBytes = []byte("+")
|
||||
iBytes = []byte("i")
|
||||
trueBytes = []byte("true")
|
||||
falseBytes = []byte("false")
|
||||
interfaceBytes = []byte("(interface {})")
|
||||
commaNewlineBytes = []byte(",\n")
|
||||
newlineBytes = []byte("\n")
|
||||
openBraceBytes = []byte("{")
|
||||
openBraceNewlineBytes = []byte("{\n")
|
||||
closeBraceBytes = []byte("}")
|
||||
asteriskBytes = []byte("*")
|
||||
colonBytes = []byte(":")
|
||||
colonSpaceBytes = []byte(": ")
|
||||
openParenBytes = []byte("(")
|
||||
closeParenBytes = []byte(")")
|
||||
spaceBytes = []byte(" ")
|
||||
pointerChainBytes = []byte("->")
|
||||
nilAngleBytes = []byte("<nil>")
|
||||
maxNewlineBytes = []byte("<max depth reached>\n")
|
||||
maxShortBytes = []byte("<max>")
|
||||
circularBytes = []byte("<already shown>")
|
||||
circularShortBytes = []byte("<shown>")
|
||||
invalidAngleBytes = []byte("<invalid>")
|
||||
openBracketBytes = []byte("[")
|
||||
closeBracketBytes = []byte("]")
|
||||
percentBytes = []byte("%")
|
||||
precisionBytes = []byte(".")
|
||||
openAngleBytes = []byte("<")
|
||||
closeAngleBytes = []byte(">")
|
||||
openMapBytes = []byte("map[")
|
||||
closeMapBytes = []byte("]")
|
||||
lenEqualsBytes = []byte("len=")
|
||||
capEqualsBytes = []byte("cap=")
|
||||
)
|
||||
|
||||
// hexDigits is used to map a decimal value to a hex digit.
|
||||
var hexDigits = "0123456789abcdef"
|
||||
|
||||
// catchPanic handles any panics that might occur during the handleMethods
|
||||
// calls.
|
||||
func catchPanic(w io.Writer, v reflect.Value) {
|
||||
if err := recover(); err != nil {
|
||||
w.Write(panicBytes)
|
||||
fmt.Fprintf(w, "%v", err)
|
||||
w.Write(closeParenBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// handleMethods attempts to call the Error and String methods on the underlying
|
||||
// type the passed reflect.Value represents and outputes the result to Writer w.
|
||||
//
|
||||
// It handles panics in any called methods by catching and displaying the error
|
||||
// as the formatted value.
|
||||
func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
|
||||
// We need an interface to check if the type implements the error or
|
||||
// Stringer interface. However, the reflect package won't give us an
|
||||
// interface on certain things like unexported struct fields in order
|
||||
// to enforce visibility rules. We use unsafe, when it's available,
|
||||
// to bypass these restrictions since this package does not mutate the
|
||||
// values.
|
||||
if !v.CanInterface() {
|
||||
if UnsafeDisabled {
|
||||
return false
|
||||
}
|
||||
|
||||
v = unsafeReflectValue(v)
|
||||
}
|
||||
|
||||
// Choose whether or not to do error and Stringer interface lookups against
|
||||
// the base type or a pointer to the base type depending on settings.
|
||||
// Technically calling one of these methods with a pointer receiver can
|
||||
// mutate the value, however, types which choose to satisify an error or
|
||||
// Stringer interface with a pointer receiver should not be mutating their
|
||||
// state inside these interface methods.
|
||||
if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
|
||||
v = unsafeReflectValue(v)
|
||||
}
|
||||
if v.CanAddr() {
|
||||
v = v.Addr()
|
||||
}
|
||||
|
||||
// Is it an error or Stringer?
|
||||
switch iface := v.Interface().(type) {
|
||||
case error:
|
||||
defer catchPanic(w, v)
|
||||
if cs.ContinueOnMethod {
|
||||
w.Write(openParenBytes)
|
||||
w.Write([]byte(iface.Error()))
|
||||
w.Write(closeParenBytes)
|
||||
w.Write(spaceBytes)
|
||||
return false
|
||||
}
|
||||
|
||||
w.Write([]byte(iface.Error()))
|
||||
return true
|
||||
|
||||
case fmt.Stringer:
|
||||
defer catchPanic(w, v)
|
||||
if cs.ContinueOnMethod {
|
||||
w.Write(openParenBytes)
|
||||
w.Write([]byte(iface.String()))
|
||||
w.Write(closeParenBytes)
|
||||
w.Write(spaceBytes)
|
||||
return false
|
||||
}
|
||||
w.Write([]byte(iface.String()))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// printBool outputs a boolean value as true or false to Writer w.
|
||||
func printBool(w io.Writer, val bool) {
|
||||
if val {
|
||||
w.Write(trueBytes)
|
||||
} else {
|
||||
w.Write(falseBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// printInt outputs a signed integer value to Writer w.
|
||||
func printInt(w io.Writer, val int64, base int) {
|
||||
w.Write([]byte(strconv.FormatInt(val, base)))
|
||||
}
|
||||
|
||||
// printUint outputs an unsigned integer value to Writer w.
|
||||
func printUint(w io.Writer, val uint64, base int) {
|
||||
w.Write([]byte(strconv.FormatUint(val, base)))
|
||||
}
|
||||
|
||||
// printFloat outputs a floating point value using the specified precision,
|
||||
// which is expected to be 32 or 64bit, to Writer w.
|
||||
func printFloat(w io.Writer, val float64, precision int) {
|
||||
w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
|
||||
}
|
||||
|
||||
// printComplex outputs a complex value using the specified float precision
|
||||
// for the real and imaginary parts to Writer w.
|
||||
func printComplex(w io.Writer, c complex128, floatPrecision int) {
|
||||
r := real(c)
|
||||
w.Write(openParenBytes)
|
||||
w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
|
||||
i := imag(c)
|
||||
if i >= 0 {
|
||||
w.Write(plusBytes)
|
||||
}
|
||||
w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
|
||||
w.Write(iBytes)
|
||||
w.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
|
||||
// prefix to Writer w.
|
||||
func printHexPtr(w io.Writer, p uintptr) {
|
||||
// Null pointer.
|
||||
num := uint64(p)
|
||||
if num == 0 {
|
||||
w.Write(nilAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
|
||||
buf := make([]byte, 18)
|
||||
|
||||
// It's simpler to construct the hex string right to left.
|
||||
base := uint64(16)
|
||||
i := len(buf) - 1
|
||||
for num >= base {
|
||||
buf[i] = hexDigits[num%base]
|
||||
num /= base
|
||||
i--
|
||||
}
|
||||
buf[i] = hexDigits[num]
|
||||
|
||||
// Add '0x' prefix.
|
||||
i--
|
||||
buf[i] = 'x'
|
||||
i--
|
||||
buf[i] = '0'
|
||||
|
||||
// Strip unused leading bytes.
|
||||
buf = buf[i:]
|
||||
w.Write(buf)
|
||||
}
|
||||
|
||||
// valuesSorter implements sort.Interface to allow a slice of reflect.Value
|
||||
// elements to be sorted.
|
||||
type valuesSorter struct {
|
||||
values []reflect.Value
|
||||
strings []string // either nil or same len and values
|
||||
cs *ConfigState
|
||||
}
|
||||
|
||||
// newValuesSorter initializes a valuesSorter instance, which holds a set of
|
||||
// surrogate keys on which the data should be sorted. It uses flags in
|
||||
// ConfigState to decide if and how to populate those surrogate keys.
|
||||
func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
|
||||
vs := &valuesSorter{values: values, cs: cs}
|
||||
if canSortSimply(vs.values[0].Kind()) {
|
||||
return vs
|
||||
}
|
||||
if !cs.DisableMethods {
|
||||
vs.strings = make([]string, len(values))
|
||||
for i := range vs.values {
|
||||
b := bytes.Buffer{}
|
||||
if !handleMethods(cs, &b, vs.values[i]) {
|
||||
vs.strings = nil
|
||||
break
|
||||
}
|
||||
vs.strings[i] = b.String()
|
||||
}
|
||||
}
|
||||
if vs.strings == nil && cs.SpewKeys {
|
||||
vs.strings = make([]string, len(values))
|
||||
for i := range vs.values {
|
||||
vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
|
||||
}
|
||||
}
|
||||
return vs
|
||||
}
|
||||
|
||||
// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
|
||||
// directly, or whether it should be considered for sorting by surrogate keys
|
||||
// (if the ConfigState allows it).
|
||||
func canSortSimply(kind reflect.Kind) bool {
|
||||
// This switch parallels valueSortLess, except for the default case.
|
||||
switch kind {
|
||||
case reflect.Bool:
|
||||
return true
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
return true
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
return true
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return true
|
||||
case reflect.String:
|
||||
return true
|
||||
case reflect.Uintptr:
|
||||
return true
|
||||
case reflect.Array:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Len returns the number of values in the slice. It is part of the
|
||||
// sort.Interface implementation.
|
||||
func (s *valuesSorter) Len() int {
|
||||
return len(s.values)
|
||||
}
|
||||
|
||||
// Swap swaps the values at the passed indices. It is part of the
|
||||
// sort.Interface implementation.
|
||||
func (s *valuesSorter) Swap(i, j int) {
|
||||
s.values[i], s.values[j] = s.values[j], s.values[i]
|
||||
if s.strings != nil {
|
||||
s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
|
||||
}
|
||||
}
|
||||
|
||||
// valueSortLess returns whether the first value should sort before the second
|
||||
// value. It is used by valueSorter.Less as part of the sort.Interface
|
||||
// implementation.
|
||||
func valueSortLess(a, b reflect.Value) bool {
|
||||
switch a.Kind() {
|
||||
case reflect.Bool:
|
||||
return !a.Bool() && b.Bool()
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
return a.Int() < b.Int()
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
return a.Uint() < b.Uint()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return a.Float() < b.Float()
|
||||
case reflect.String:
|
||||
return a.String() < b.String()
|
||||
case reflect.Uintptr:
|
||||
return a.Uint() < b.Uint()
|
||||
case reflect.Array:
|
||||
// Compare the contents of both arrays.
|
||||
l := a.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
av := a.Index(i)
|
||||
bv := b.Index(i)
|
||||
if av.Interface() == bv.Interface() {
|
||||
continue
|
||||
}
|
||||
return valueSortLess(av, bv)
|
||||
}
|
||||
}
|
||||
return a.String() < b.String()
|
||||
}
|
||||
|
||||
// Less returns whether the value at index i should sort before the
|
||||
// value at index j. It is part of the sort.Interface implementation.
|
||||
func (s *valuesSorter) Less(i, j int) bool {
|
||||
if s.strings == nil {
|
||||
return valueSortLess(s.values[i], s.values[j])
|
||||
}
|
||||
return s.strings[i] < s.strings[j]
|
||||
}
|
||||
|
||||
// sortValues is a sort function that handles both native types and any type that
|
||||
// can be converted to error or Stringer. Other inputs are sorted according to
|
||||
// their Value.String() value to ensure display stability.
|
||||
func sortValues(values []reflect.Value, cs *ConfigState) {
|
||||
if len(values) == 0 {
|
||||
return
|
||||
}
|
||||
sort.Sort(newValuesSorter(values, cs))
|
||||
}
|
||||
306
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
306
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/config.go
generated
vendored
|
|
@ -1,306 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ConfigState houses the configuration options used by spew to format and
|
||||
// display values. There is a global instance, Config, that is used to control
|
||||
// all top-level Formatter and Dump functionality. Each ConfigState instance
|
||||
// provides methods equivalent to the top-level functions.
|
||||
//
|
||||
// The zero value for ConfigState provides no indentation. You would typically
|
||||
// want to set it to a space or a tab.
|
||||
//
|
||||
// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
|
||||
// with default settings. See the documentation of NewDefaultConfig for default
|
||||
// values.
|
||||
type ConfigState struct {
|
||||
// Indent specifies the string to use for each indentation level. The
|
||||
// global config instance that all top-level functions use set this to a
|
||||
// single space by default. If you would like more indentation, you might
|
||||
// set this to a tab with "\t" or perhaps two spaces with " ".
|
||||
Indent string
|
||||
|
||||
// MaxDepth controls the maximum number of levels to descend into nested
|
||||
// data structures. The default, 0, means there is no limit.
|
||||
//
|
||||
// NOTE: Circular data structures are properly detected, so it is not
|
||||
// necessary to set this value unless you specifically want to limit deeply
|
||||
// nested data structures.
|
||||
MaxDepth int
|
||||
|
||||
// DisableMethods specifies whether or not error and Stringer interfaces are
|
||||
// invoked for types that implement them.
|
||||
DisableMethods bool
|
||||
|
||||
// DisablePointerMethods specifies whether or not to check for and invoke
|
||||
// error and Stringer interfaces on types which only accept a pointer
|
||||
// receiver when the current type is not a pointer.
|
||||
//
|
||||
// NOTE: This might be an unsafe action since calling one of these methods
|
||||
// with a pointer receiver could technically mutate the value, however,
|
||||
// in practice, types which choose to satisify an error or Stringer
|
||||
// interface with a pointer receiver should not be mutating their state
|
||||
// inside these interface methods. As a result, this option relies on
|
||||
// access to the unsafe package, so it will not have any effect when
|
||||
// running in environments without access to the unsafe package such as
|
||||
// Google App Engine or with the "safe" build tag specified.
|
||||
DisablePointerMethods bool
|
||||
|
||||
// DisablePointerAddresses specifies whether to disable the printing of
|
||||
// pointer addresses. This is useful when diffing data structures in tests.
|
||||
DisablePointerAddresses bool
|
||||
|
||||
// DisableCapacities specifies whether to disable the printing of capacities
|
||||
// for arrays, slices, maps and channels. This is useful when diffing
|
||||
// data structures in tests.
|
||||
DisableCapacities bool
|
||||
|
||||
// ContinueOnMethod specifies whether or not recursion should continue once
|
||||
// a custom error or Stringer interface is invoked. The default, false,
|
||||
// means it will print the results of invoking the custom error or Stringer
|
||||
// interface and return immediately instead of continuing to recurse into
|
||||
// the internals of the data type.
|
||||
//
|
||||
// NOTE: This flag does not have any effect if method invocation is disabled
|
||||
// via the DisableMethods or DisablePointerMethods options.
|
||||
ContinueOnMethod bool
|
||||
|
||||
// SortKeys specifies map keys should be sorted before being printed. Use
|
||||
// this to have a more deterministic, diffable output. Note that only
|
||||
// native types (bool, int, uint, floats, uintptr and string) and types
|
||||
// that support the error or Stringer interfaces (if methods are
|
||||
// enabled) are supported, with other types sorted according to the
|
||||
// reflect.Value.String() output which guarantees display stability.
|
||||
SortKeys bool
|
||||
|
||||
// SpewKeys specifies that, as a last resort attempt, map keys should
|
||||
// be spewed to strings and sorted by those strings. This is only
|
||||
// considered if SortKeys is true.
|
||||
SpewKeys bool
|
||||
}
|
||||
|
||||
// Config is the active configuration of the top-level functions.
|
||||
// The configuration can be changed by modifying the contents of spew.Config.
|
||||
var Config = ConfigState{Indent: " "}
|
||||
|
||||
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the formatted string as a value that satisfies error. See NewFormatter
|
||||
// for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
|
||||
return fmt.Errorf(format, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprint(w, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprintf(w, format, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
|
||||
// passed with a Formatter interface returned by c.NewFormatter. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprintln(w, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Print is a wrapper for fmt.Print that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
|
||||
return fmt.Print(c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
|
||||
return fmt.Printf(format, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Println is a wrapper for fmt.Println that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
|
||||
return fmt.Println(c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Sprint(a ...interface{}) string {
|
||||
return fmt.Sprint(c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
|
||||
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||
// the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
|
||||
return fmt.Sprintf(format, c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
|
||||
// were passed with a Formatter interface returned by c.NewFormatter. It
|
||||
// returns the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
|
||||
func (c *ConfigState) Sprintln(a ...interface{}) string {
|
||||
return fmt.Sprintln(c.convertArgs(a)...)
|
||||
}
|
||||
|
||||
/*
|
||||
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
|
||||
interface. As a result, it integrates cleanly with standard fmt package
|
||||
printing functions. The formatter is useful for inline printing of smaller data
|
||||
types similar to the standard %v format specifier.
|
||||
|
||||
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
||||
addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
|
||||
combinations. Any other verbs such as %x and %q will be sent to the the
|
||||
standard fmt package for formatting. In addition, the custom formatter ignores
|
||||
the width and precision arguments (however they will still work on the format
|
||||
specifiers not handled by the custom formatter).
|
||||
|
||||
Typically this function shouldn't be called directly. It is much easier to make
|
||||
use of the custom formatter by calling one of the convenience functions such as
|
||||
c.Printf, c.Println, or c.Printf.
|
||||
*/
|
||||
func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
|
||||
return newFormatter(c, v)
|
||||
}
|
||||
|
||||
// Fdump formats and displays the passed arguments to io.Writer w. It formats
|
||||
// exactly the same as Dump.
|
||||
func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
|
||||
fdump(c, w, a...)
|
||||
}
|
||||
|
||||
/*
|
||||
Dump displays the passed parameters to standard out with newlines, customizable
|
||||
indentation, and additional debug information such as complete types and all
|
||||
pointer addresses used to indirect to the final value. It provides the
|
||||
following features over the built-in printing facilities provided by the fmt
|
||||
package:
|
||||
|
||||
* Pointers are dereferenced and followed
|
||||
* Circular data structures are detected and handled properly
|
||||
* Custom Stringer/error interfaces are optionally invoked, including
|
||||
on unexported types
|
||||
* Custom types which only implement the Stringer/error interfaces via
|
||||
a pointer receiver are optionally invoked when passing non-pointer
|
||||
variables
|
||||
* Byte arrays and slices are dumped like the hexdump -C command which
|
||||
includes offsets, byte values in hex, and ASCII output
|
||||
|
||||
The configuration options are controlled by modifying the public members
|
||||
of c. See ConfigState for options documentation.
|
||||
|
||||
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
|
||||
get the formatted result as a string.
|
||||
*/
|
||||
func (c *ConfigState) Dump(a ...interface{}) {
|
||||
fdump(c, os.Stdout, a...)
|
||||
}
|
||||
|
||||
// Sdump returns a string with the passed arguments formatted exactly the same
|
||||
// as Dump.
|
||||
func (c *ConfigState) Sdump(a ...interface{}) string {
|
||||
var buf bytes.Buffer
|
||||
fdump(c, &buf, a...)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// convertArgs accepts a slice of arguments and returns a slice of the same
|
||||
// length with each argument converted to a spew Formatter interface using
|
||||
// the ConfigState associated with s.
|
||||
func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
|
||||
formatters = make([]interface{}, len(args))
|
||||
for index, arg := range args {
|
||||
formatters[index] = newFormatter(c, arg)
|
||||
}
|
||||
return formatters
|
||||
}
|
||||
|
||||
// NewDefaultConfig returns a ConfigState with the following default settings.
|
||||
//
|
||||
// Indent: " "
|
||||
// MaxDepth: 0
|
||||
// DisableMethods: false
|
||||
// DisablePointerMethods: false
|
||||
// ContinueOnMethod: false
|
||||
// SortKeys: false
|
||||
func NewDefaultConfig() *ConfigState {
|
||||
return &ConfigState{Indent: " "}
|
||||
}
|
||||
211
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
211
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
|
|
@ -1,211 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Package spew implements a deep pretty printer for Go data structures to aid in
|
||||
debugging.
|
||||
|
||||
A quick overview of the additional features spew provides over the built-in
|
||||
printing facilities for Go data types are as follows:
|
||||
|
||||
* Pointers are dereferenced and followed
|
||||
* Circular data structures are detected and handled properly
|
||||
* Custom Stringer/error interfaces are optionally invoked, including
|
||||
on unexported types
|
||||
* Custom types which only implement the Stringer/error interfaces via
|
||||
a pointer receiver are optionally invoked when passing non-pointer
|
||||
variables
|
||||
* Byte arrays and slices are dumped like the hexdump -C command which
|
||||
includes offsets, byte values in hex, and ASCII output (only when using
|
||||
Dump style)
|
||||
|
||||
There are two different approaches spew allows for dumping Go data structures:
|
||||
|
||||
* Dump style which prints with newlines, customizable indentation,
|
||||
and additional debug information such as types and all pointer addresses
|
||||
used to indirect to the final value
|
||||
* A custom Formatter interface that integrates cleanly with the standard fmt
|
||||
package and replaces %v, %+v, %#v, and %#+v to provide inline printing
|
||||
similar to the default %v while providing the additional functionality
|
||||
outlined above and passing unsupported format verbs such as %x and %q
|
||||
along to fmt
|
||||
|
||||
Quick Start
|
||||
|
||||
This section demonstrates how to quickly get started with spew. See the
|
||||
sections below for further details on formatting and configuration options.
|
||||
|
||||
To dump a variable with full newlines, indentation, type, and pointer
|
||||
information use Dump, Fdump, or Sdump:
|
||||
spew.Dump(myVar1, myVar2, ...)
|
||||
spew.Fdump(someWriter, myVar1, myVar2, ...)
|
||||
str := spew.Sdump(myVar1, myVar2, ...)
|
||||
|
||||
Alternatively, if you would prefer to use format strings with a compacted inline
|
||||
printing style, use the convenience wrappers Printf, Fprintf, etc with
|
||||
%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
|
||||
%#+v (adds types and pointer addresses):
|
||||
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||
|
||||
Configuration Options
|
||||
|
||||
Configuration of spew is handled by fields in the ConfigState type. For
|
||||
convenience, all of the top-level functions use a global state available
|
||||
via the spew.Config global.
|
||||
|
||||
It is also possible to create a ConfigState instance that provides methods
|
||||
equivalent to the top-level functions. This allows concurrent configuration
|
||||
options. See the ConfigState documentation for more details.
|
||||
|
||||
The following configuration options are available:
|
||||
* Indent
|
||||
String to use for each indentation level for Dump functions.
|
||||
It is a single space by default. A popular alternative is "\t".
|
||||
|
||||
* MaxDepth
|
||||
Maximum number of levels to descend into nested data structures.
|
||||
There is no limit by default.
|
||||
|
||||
* DisableMethods
|
||||
Disables invocation of error and Stringer interface methods.
|
||||
Method invocation is enabled by default.
|
||||
|
||||
* DisablePointerMethods
|
||||
Disables invocation of error and Stringer interface methods on types
|
||||
which only accept pointer receivers from non-pointer variables.
|
||||
Pointer method invocation is enabled by default.
|
||||
|
||||
* DisablePointerAddresses
|
||||
DisablePointerAddresses specifies whether to disable the printing of
|
||||
pointer addresses. This is useful when diffing data structures in tests.
|
||||
|
||||
* DisableCapacities
|
||||
DisableCapacities specifies whether to disable the printing of
|
||||
capacities for arrays, slices, maps and channels. This is useful when
|
||||
diffing data structures in tests.
|
||||
|
||||
* ContinueOnMethod
|
||||
Enables recursion into types after invoking error and Stringer interface
|
||||
methods. Recursion after method invocation is disabled by default.
|
||||
|
||||
* SortKeys
|
||||
Specifies map keys should be sorted before being printed. Use
|
||||
this to have a more deterministic, diffable output. Note that
|
||||
only native types (bool, int, uint, floats, uintptr and string)
|
||||
and types which implement error or Stringer interfaces are
|
||||
supported with other types sorted according to the
|
||||
reflect.Value.String() output which guarantees display
|
||||
stability. Natural map order is used by default.
|
||||
|
||||
* SpewKeys
|
||||
Specifies that, as a last resort attempt, map keys should be
|
||||
spewed to strings and sorted by those strings. This is only
|
||||
considered if SortKeys is true.
|
||||
|
||||
Dump Usage
|
||||
|
||||
Simply call spew.Dump with a list of variables you want to dump:
|
||||
|
||||
spew.Dump(myVar1, myVar2, ...)
|
||||
|
||||
You may also call spew.Fdump if you would prefer to output to an arbitrary
|
||||
io.Writer. For example, to dump to standard error:
|
||||
|
||||
spew.Fdump(os.Stderr, myVar1, myVar2, ...)
|
||||
|
||||
A third option is to call spew.Sdump to get the formatted output as a string:
|
||||
|
||||
str := spew.Sdump(myVar1, myVar2, ...)
|
||||
|
||||
Sample Dump Output
|
||||
|
||||
See the Dump example for details on the setup of the types and variables being
|
||||
shown here.
|
||||
|
||||
(main.Foo) {
|
||||
unexportedField: (*main.Bar)(0xf84002e210)({
|
||||
flag: (main.Flag) flagTwo,
|
||||
data: (uintptr) <nil>
|
||||
}),
|
||||
ExportedField: (map[interface {}]interface {}) (len=1) {
|
||||
(string) (len=3) "one": (bool) true
|
||||
}
|
||||
}
|
||||
|
||||
Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
|
||||
command as shown.
|
||||
([]uint8) (len=32 cap=32) {
|
||||
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
|
||||
00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
|
||||
00000020 31 32 |12|
|
||||
}
|
||||
|
||||
Custom Formatter
|
||||
|
||||
Spew provides a custom formatter that implements the fmt.Formatter interface
|
||||
so that it integrates cleanly with standard fmt package printing functions. The
|
||||
formatter is useful for inline printing of smaller data types similar to the
|
||||
standard %v format specifier.
|
||||
|
||||
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
||||
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
|
||||
combinations. Any other verbs such as %x and %q will be sent to the the
|
||||
standard fmt package for formatting. In addition, the custom formatter ignores
|
||||
the width and precision arguments (however they will still work on the format
|
||||
specifiers not handled by the custom formatter).
|
||||
|
||||
Custom Formatter Usage
|
||||
|
||||
The simplest way to make use of the spew custom formatter is to call one of the
|
||||
convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
|
||||
functions have syntax you are most likely already familiar with:
|
||||
|
||||
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||
spew.Println(myVar, myVar2)
|
||||
spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||
spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||
|
||||
See the Index for the full list convenience functions.
|
||||
|
||||
Sample Formatter Output
|
||||
|
||||
Double pointer to a uint8:
|
||||
%v: <**>5
|
||||
%+v: <**>(0xf8400420d0->0xf8400420c8)5
|
||||
%#v: (**uint8)5
|
||||
%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
|
||||
|
||||
Pointer to circular struct with a uint8 field and a pointer to itself:
|
||||
%v: <*>{1 <*><shown>}
|
||||
%+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
|
||||
%#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
|
||||
%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
|
||||
|
||||
See the Printf example for details on the setup of variables being shown
|
||||
here.
|
||||
|
||||
Errors
|
||||
|
||||
Since it is possible for custom Stringer/error interfaces to panic, spew
|
||||
detects them and handles them internally by printing the panic information
|
||||
inline with the output. Since spew is intended to provide deep pretty printing
|
||||
capabilities on structures, it intentionally does not return any errors.
|
||||
*/
|
||||
package spew
|
||||
509
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
509
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
|
|
@ -1,509 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// uint8Type is a reflect.Type representing a uint8. It is used to
|
||||
// convert cgo types to uint8 slices for hexdumping.
|
||||
uint8Type = reflect.TypeOf(uint8(0))
|
||||
|
||||
// cCharRE is a regular expression that matches a cgo char.
|
||||
// It is used to detect character arrays to hexdump them.
|
||||
cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
|
||||
|
||||
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
|
||||
// char. It is used to detect unsigned character arrays to hexdump
|
||||
// them.
|
||||
cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
|
||||
|
||||
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
|
||||
// It is used to detect uint8_t arrays to hexdump them.
|
||||
cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
|
||||
)
|
||||
|
||||
// dumpState contains information about the state of a dump operation.
|
||||
type dumpState struct {
|
||||
w io.Writer
|
||||
depth int
|
||||
pointers map[uintptr]int
|
||||
ignoreNextType bool
|
||||
ignoreNextIndent bool
|
||||
cs *ConfigState
|
||||
}
|
||||
|
||||
// indent performs indentation according to the depth level and cs.Indent
|
||||
// option.
|
||||
func (d *dumpState) indent() {
|
||||
if d.ignoreNextIndent {
|
||||
d.ignoreNextIndent = false
|
||||
return
|
||||
}
|
||||
d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
|
||||
}
|
||||
|
||||
// unpackValue returns values inside of non-nil interfaces when possible.
|
||||
// This is useful for data types like structs, arrays, slices, and maps which
|
||||
// can contain varying types packed inside an interface.
|
||||
func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
|
||||
if v.Kind() == reflect.Interface && !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// dumpPtr handles formatting of pointers by indirecting them as necessary.
|
||||
func (d *dumpState) dumpPtr(v reflect.Value) {
|
||||
// Remove pointers at or below the current depth from map used to detect
|
||||
// circular refs.
|
||||
for k, depth := range d.pointers {
|
||||
if depth >= d.depth {
|
||||
delete(d.pointers, k)
|
||||
}
|
||||
}
|
||||
|
||||
// Keep list of all dereferenced pointers to show later.
|
||||
pointerChain := make([]uintptr, 0)
|
||||
|
||||
// Figure out how many levels of indirection there are by dereferencing
|
||||
// pointers and unpacking interfaces down the chain while detecting circular
|
||||
// references.
|
||||
nilFound := false
|
||||
cycleFound := false
|
||||
indirects := 0
|
||||
ve := v
|
||||
for ve.Kind() == reflect.Ptr {
|
||||
if ve.IsNil() {
|
||||
nilFound = true
|
||||
break
|
||||
}
|
||||
indirects++
|
||||
addr := ve.Pointer()
|
||||
pointerChain = append(pointerChain, addr)
|
||||
if pd, ok := d.pointers[addr]; ok && pd < d.depth {
|
||||
cycleFound = true
|
||||
indirects--
|
||||
break
|
||||
}
|
||||
d.pointers[addr] = d.depth
|
||||
|
||||
ve = ve.Elem()
|
||||
if ve.Kind() == reflect.Interface {
|
||||
if ve.IsNil() {
|
||||
nilFound = true
|
||||
break
|
||||
}
|
||||
ve = ve.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
// Display type information.
|
||||
d.w.Write(openParenBytes)
|
||||
d.w.Write(bytes.Repeat(asteriskBytes, indirects))
|
||||
d.w.Write([]byte(ve.Type().String()))
|
||||
d.w.Write(closeParenBytes)
|
||||
|
||||
// Display pointer information.
|
||||
if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
|
||||
d.w.Write(openParenBytes)
|
||||
for i, addr := range pointerChain {
|
||||
if i > 0 {
|
||||
d.w.Write(pointerChainBytes)
|
||||
}
|
||||
printHexPtr(d.w, addr)
|
||||
}
|
||||
d.w.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// Display dereferenced value.
|
||||
d.w.Write(openParenBytes)
|
||||
switch {
|
||||
case nilFound:
|
||||
d.w.Write(nilAngleBytes)
|
||||
|
||||
case cycleFound:
|
||||
d.w.Write(circularBytes)
|
||||
|
||||
default:
|
||||
d.ignoreNextType = true
|
||||
d.dump(ve)
|
||||
}
|
||||
d.w.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// dumpSlice handles formatting of arrays and slices. Byte (uint8 under
|
||||
// reflection) arrays and slices are dumped in hexdump -C fashion.
|
||||
func (d *dumpState) dumpSlice(v reflect.Value) {
|
||||
// Determine whether this type should be hex dumped or not. Also,
|
||||
// for types which should be hexdumped, try to use the underlying data
|
||||
// first, then fall back to trying to convert them to a uint8 slice.
|
||||
var buf []uint8
|
||||
doConvert := false
|
||||
doHexDump := false
|
||||
numEntries := v.Len()
|
||||
if numEntries > 0 {
|
||||
vt := v.Index(0).Type()
|
||||
vts := vt.String()
|
||||
switch {
|
||||
// C types that need to be converted.
|
||||
case cCharRE.MatchString(vts):
|
||||
fallthrough
|
||||
case cUnsignedCharRE.MatchString(vts):
|
||||
fallthrough
|
||||
case cUint8tCharRE.MatchString(vts):
|
||||
doConvert = true
|
||||
|
||||
// Try to use existing uint8 slices and fall back to converting
|
||||
// and copying if that fails.
|
||||
case vt.Kind() == reflect.Uint8:
|
||||
// We need an addressable interface to convert the type
|
||||
// to a byte slice. However, the reflect package won't
|
||||
// give us an interface on certain things like
|
||||
// unexported struct fields in order to enforce
|
||||
// visibility rules. We use unsafe, when available, to
|
||||
// bypass these restrictions since this package does not
|
||||
// mutate the values.
|
||||
vs := v
|
||||
if !vs.CanInterface() || !vs.CanAddr() {
|
||||
vs = unsafeReflectValue(vs)
|
||||
}
|
||||
if !UnsafeDisabled {
|
||||
vs = vs.Slice(0, numEntries)
|
||||
|
||||
// Use the existing uint8 slice if it can be
|
||||
// type asserted.
|
||||
iface := vs.Interface()
|
||||
if slice, ok := iface.([]uint8); ok {
|
||||
buf = slice
|
||||
doHexDump = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// The underlying data needs to be converted if it can't
|
||||
// be type asserted to a uint8 slice.
|
||||
doConvert = true
|
||||
}
|
||||
|
||||
// Copy and convert the underlying type if needed.
|
||||
if doConvert && vt.ConvertibleTo(uint8Type) {
|
||||
// Convert and copy each element into a uint8 byte
|
||||
// slice.
|
||||
buf = make([]uint8, numEntries)
|
||||
for i := 0; i < numEntries; i++ {
|
||||
vv := v.Index(i)
|
||||
buf[i] = uint8(vv.Convert(uint8Type).Uint())
|
||||
}
|
||||
doHexDump = true
|
||||
}
|
||||
}
|
||||
|
||||
// Hexdump the entire slice as needed.
|
||||
if doHexDump {
|
||||
indent := strings.Repeat(d.cs.Indent, d.depth)
|
||||
str := indent + hex.Dump(buf)
|
||||
str = strings.Replace(str, "\n", "\n"+indent, -1)
|
||||
str = strings.TrimRight(str, d.cs.Indent)
|
||||
d.w.Write([]byte(str))
|
||||
return
|
||||
}
|
||||
|
||||
// Recursively call dump for each item.
|
||||
for i := 0; i < numEntries; i++ {
|
||||
d.dump(d.unpackValue(v.Index(i)))
|
||||
if i < (numEntries - 1) {
|
||||
d.w.Write(commaNewlineBytes)
|
||||
} else {
|
||||
d.w.Write(newlineBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dump is the main workhorse for dumping a value. It uses the passed reflect
|
||||
// value to figure out what kind of object we are dealing with and formats it
|
||||
// appropriately. It is a recursive function, however circular data structures
|
||||
// are detected and handled properly.
|
||||
func (d *dumpState) dump(v reflect.Value) {
|
||||
// Handle invalid reflect values immediately.
|
||||
kind := v.Kind()
|
||||
if kind == reflect.Invalid {
|
||||
d.w.Write(invalidAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle pointers specially.
|
||||
if kind == reflect.Ptr {
|
||||
d.indent()
|
||||
d.dumpPtr(v)
|
||||
return
|
||||
}
|
||||
|
||||
// Print type information unless already handled elsewhere.
|
||||
if !d.ignoreNextType {
|
||||
d.indent()
|
||||
d.w.Write(openParenBytes)
|
||||
d.w.Write([]byte(v.Type().String()))
|
||||
d.w.Write(closeParenBytes)
|
||||
d.w.Write(spaceBytes)
|
||||
}
|
||||
d.ignoreNextType = false
|
||||
|
||||
// Display length and capacity if the built-in len and cap functions
|
||||
// work with the value's kind and the len/cap itself is non-zero.
|
||||
valueLen, valueCap := 0, 0
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.Chan:
|
||||
valueLen, valueCap = v.Len(), v.Cap()
|
||||
case reflect.Map, reflect.String:
|
||||
valueLen = v.Len()
|
||||
}
|
||||
if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
|
||||
d.w.Write(openParenBytes)
|
||||
if valueLen != 0 {
|
||||
d.w.Write(lenEqualsBytes)
|
||||
printInt(d.w, int64(valueLen), 10)
|
||||
}
|
||||
if !d.cs.DisableCapacities && valueCap != 0 {
|
||||
if valueLen != 0 {
|
||||
d.w.Write(spaceBytes)
|
||||
}
|
||||
d.w.Write(capEqualsBytes)
|
||||
printInt(d.w, int64(valueCap), 10)
|
||||
}
|
||||
d.w.Write(closeParenBytes)
|
||||
d.w.Write(spaceBytes)
|
||||
}
|
||||
|
||||
// Call Stringer/error interfaces if they exist and the handle methods flag
|
||||
// is enabled
|
||||
if !d.cs.DisableMethods {
|
||||
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
|
||||
if handled := handleMethods(d.cs, d.w, v); handled {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case reflect.Invalid:
|
||||
// Do nothing. We should never get here since invalid has already
|
||||
// been handled above.
|
||||
|
||||
case reflect.Bool:
|
||||
printBool(d.w, v.Bool())
|
||||
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
printInt(d.w, v.Int(), 10)
|
||||
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
printUint(d.w, v.Uint(), 10)
|
||||
|
||||
case reflect.Float32:
|
||||
printFloat(d.w, v.Float(), 32)
|
||||
|
||||
case reflect.Float64:
|
||||
printFloat(d.w, v.Float(), 64)
|
||||
|
||||
case reflect.Complex64:
|
||||
printComplex(d.w, v.Complex(), 32)
|
||||
|
||||
case reflect.Complex128:
|
||||
printComplex(d.w, v.Complex(), 64)
|
||||
|
||||
case reflect.Slice:
|
||||
if v.IsNil() {
|
||||
d.w.Write(nilAngleBytes)
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case reflect.Array:
|
||||
d.w.Write(openBraceNewlineBytes)
|
||||
d.depth++
|
||||
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
||||
d.indent()
|
||||
d.w.Write(maxNewlineBytes)
|
||||
} else {
|
||||
d.dumpSlice(v)
|
||||
}
|
||||
d.depth--
|
||||
d.indent()
|
||||
d.w.Write(closeBraceBytes)
|
||||
|
||||
case reflect.String:
|
||||
d.w.Write([]byte(strconv.Quote(v.String())))
|
||||
|
||||
case reflect.Interface:
|
||||
// The only time we should get here is for nil interfaces due to
|
||||
// unpackValue calls.
|
||||
if v.IsNil() {
|
||||
d.w.Write(nilAngleBytes)
|
||||
}
|
||||
|
||||
case reflect.Ptr:
|
||||
// Do nothing. We should never get here since pointers have already
|
||||
// been handled above.
|
||||
|
||||
case reflect.Map:
|
||||
// nil maps should be indicated as different than empty maps
|
||||
if v.IsNil() {
|
||||
d.w.Write(nilAngleBytes)
|
||||
break
|
||||
}
|
||||
|
||||
d.w.Write(openBraceNewlineBytes)
|
||||
d.depth++
|
||||
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
||||
d.indent()
|
||||
d.w.Write(maxNewlineBytes)
|
||||
} else {
|
||||
numEntries := v.Len()
|
||||
keys := v.MapKeys()
|
||||
if d.cs.SortKeys {
|
||||
sortValues(keys, d.cs)
|
||||
}
|
||||
for i, key := range keys {
|
||||
d.dump(d.unpackValue(key))
|
||||
d.w.Write(colonSpaceBytes)
|
||||
d.ignoreNextIndent = true
|
||||
d.dump(d.unpackValue(v.MapIndex(key)))
|
||||
if i < (numEntries - 1) {
|
||||
d.w.Write(commaNewlineBytes)
|
||||
} else {
|
||||
d.w.Write(newlineBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
d.depth--
|
||||
d.indent()
|
||||
d.w.Write(closeBraceBytes)
|
||||
|
||||
case reflect.Struct:
|
||||
d.w.Write(openBraceNewlineBytes)
|
||||
d.depth++
|
||||
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
||||
d.indent()
|
||||
d.w.Write(maxNewlineBytes)
|
||||
} else {
|
||||
vt := v.Type()
|
||||
numFields := v.NumField()
|
||||
for i := 0; i < numFields; i++ {
|
||||
d.indent()
|
||||
vtf := vt.Field(i)
|
||||
d.w.Write([]byte(vtf.Name))
|
||||
d.w.Write(colonSpaceBytes)
|
||||
d.ignoreNextIndent = true
|
||||
d.dump(d.unpackValue(v.Field(i)))
|
||||
if i < (numFields - 1) {
|
||||
d.w.Write(commaNewlineBytes)
|
||||
} else {
|
||||
d.w.Write(newlineBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
d.depth--
|
||||
d.indent()
|
||||
d.w.Write(closeBraceBytes)
|
||||
|
||||
case reflect.Uintptr:
|
||||
printHexPtr(d.w, uintptr(v.Uint()))
|
||||
|
||||
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
||||
printHexPtr(d.w, v.Pointer())
|
||||
|
||||
// There were not any other types at the time this code was written, but
|
||||
// fall back to letting the default fmt package handle it in case any new
|
||||
// types are added.
|
||||
default:
|
||||
if v.CanInterface() {
|
||||
fmt.Fprintf(d.w, "%v", v.Interface())
|
||||
} else {
|
||||
fmt.Fprintf(d.w, "%v", v.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fdump is a helper function to consolidate the logic from the various public
|
||||
// methods which take varying writers and config states.
|
||||
func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
|
||||
for _, arg := range a {
|
||||
if arg == nil {
|
||||
w.Write(interfaceBytes)
|
||||
w.Write(spaceBytes)
|
||||
w.Write(nilAngleBytes)
|
||||
w.Write(newlineBytes)
|
||||
continue
|
||||
}
|
||||
|
||||
d := dumpState{w: w, cs: cs}
|
||||
d.pointers = make(map[uintptr]int)
|
||||
d.dump(reflect.ValueOf(arg))
|
||||
d.w.Write(newlineBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// Fdump formats and displays the passed arguments to io.Writer w. It formats
|
||||
// exactly the same as Dump.
|
||||
func Fdump(w io.Writer, a ...interface{}) {
|
||||
fdump(&Config, w, a...)
|
||||
}
|
||||
|
||||
// Sdump returns a string with the passed arguments formatted exactly the same
|
||||
// as Dump.
|
||||
func Sdump(a ...interface{}) string {
|
||||
var buf bytes.Buffer
|
||||
fdump(&Config, &buf, a...)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
/*
|
||||
Dump displays the passed parameters to standard out with newlines, customizable
|
||||
indentation, and additional debug information such as complete types and all
|
||||
pointer addresses used to indirect to the final value. It provides the
|
||||
following features over the built-in printing facilities provided by the fmt
|
||||
package:
|
||||
|
||||
* Pointers are dereferenced and followed
|
||||
* Circular data structures are detected and handled properly
|
||||
* Custom Stringer/error interfaces are optionally invoked, including
|
||||
on unexported types
|
||||
* Custom types which only implement the Stringer/error interfaces via
|
||||
a pointer receiver are optionally invoked when passing non-pointer
|
||||
variables
|
||||
* Byte arrays and slices are dumped like the hexdump -C command which
|
||||
includes offsets, byte values in hex, and ASCII output
|
||||
|
||||
The configuration options are controlled by an exported package global,
|
||||
spew.Config. See ConfigState for options documentation.
|
||||
|
||||
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
|
||||
get the formatted result as a string.
|
||||
*/
|
||||
func Dump(a ...interface{}) {
|
||||
fdump(&Config, os.Stdout, a...)
|
||||
}
|
||||
419
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
419
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
|
|
@ -1,419 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// supportedFlags is a list of all the character flags supported by fmt package.
|
||||
const supportedFlags = "0-+# "
|
||||
|
||||
// formatState implements the fmt.Formatter interface and contains information
|
||||
// about the state of a formatting operation. The NewFormatter function can
|
||||
// be used to get a new Formatter which can be used directly as arguments
|
||||
// in standard fmt package printing calls.
|
||||
type formatState struct {
|
||||
value interface{}
|
||||
fs fmt.State
|
||||
depth int
|
||||
pointers map[uintptr]int
|
||||
ignoreNextType bool
|
||||
cs *ConfigState
|
||||
}
|
||||
|
||||
// buildDefaultFormat recreates the original format string without precision
|
||||
// and width information to pass in to fmt.Sprintf in the case of an
|
||||
// unrecognized type. Unless new types are added to the language, this
|
||||
// function won't ever be called.
|
||||
func (f *formatState) buildDefaultFormat() (format string) {
|
||||
buf := bytes.NewBuffer(percentBytes)
|
||||
|
||||
for _, flag := range supportedFlags {
|
||||
if f.fs.Flag(int(flag)) {
|
||||
buf.WriteRune(flag)
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteRune('v')
|
||||
|
||||
format = buf.String()
|
||||
return format
|
||||
}
|
||||
|
||||
// constructOrigFormat recreates the original format string including precision
|
||||
// and width information to pass along to the standard fmt package. This allows
|
||||
// automatic deferral of all format strings this package doesn't support.
|
||||
func (f *formatState) constructOrigFormat(verb rune) (format string) {
|
||||
buf := bytes.NewBuffer(percentBytes)
|
||||
|
||||
for _, flag := range supportedFlags {
|
||||
if f.fs.Flag(int(flag)) {
|
||||
buf.WriteRune(flag)
|
||||
}
|
||||
}
|
||||
|
||||
if width, ok := f.fs.Width(); ok {
|
||||
buf.WriteString(strconv.Itoa(width))
|
||||
}
|
||||
|
||||
if precision, ok := f.fs.Precision(); ok {
|
||||
buf.Write(precisionBytes)
|
||||
buf.WriteString(strconv.Itoa(precision))
|
||||
}
|
||||
|
||||
buf.WriteRune(verb)
|
||||
|
||||
format = buf.String()
|
||||
return format
|
||||
}
|
||||
|
||||
// unpackValue returns values inside of non-nil interfaces when possible and
|
||||
// ensures that types for values which have been unpacked from an interface
|
||||
// are displayed when the show types flag is also set.
|
||||
// This is useful for data types like structs, arrays, slices, and maps which
|
||||
// can contain varying types packed inside an interface.
|
||||
func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
|
||||
if v.Kind() == reflect.Interface {
|
||||
f.ignoreNextType = false
|
||||
if !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// formatPtr handles formatting of pointers by indirecting them as necessary.
|
||||
func (f *formatState) formatPtr(v reflect.Value) {
|
||||
// Display nil if top level pointer is nil.
|
||||
showTypes := f.fs.Flag('#')
|
||||
if v.IsNil() && (!showTypes || f.ignoreNextType) {
|
||||
f.fs.Write(nilAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
// Remove pointers at or below the current depth from map used to detect
|
||||
// circular refs.
|
||||
for k, depth := range f.pointers {
|
||||
if depth >= f.depth {
|
||||
delete(f.pointers, k)
|
||||
}
|
||||
}
|
||||
|
||||
// Keep list of all dereferenced pointers to possibly show later.
|
||||
pointerChain := make([]uintptr, 0)
|
||||
|
||||
// Figure out how many levels of indirection there are by derferencing
|
||||
// pointers and unpacking interfaces down the chain while detecting circular
|
||||
// references.
|
||||
nilFound := false
|
||||
cycleFound := false
|
||||
indirects := 0
|
||||
ve := v
|
||||
for ve.Kind() == reflect.Ptr {
|
||||
if ve.IsNil() {
|
||||
nilFound = true
|
||||
break
|
||||
}
|
||||
indirects++
|
||||
addr := ve.Pointer()
|
||||
pointerChain = append(pointerChain, addr)
|
||||
if pd, ok := f.pointers[addr]; ok && pd < f.depth {
|
||||
cycleFound = true
|
||||
indirects--
|
||||
break
|
||||
}
|
||||
f.pointers[addr] = f.depth
|
||||
|
||||
ve = ve.Elem()
|
||||
if ve.Kind() == reflect.Interface {
|
||||
if ve.IsNil() {
|
||||
nilFound = true
|
||||
break
|
||||
}
|
||||
ve = ve.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
// Display type or indirection level depending on flags.
|
||||
if showTypes && !f.ignoreNextType {
|
||||
f.fs.Write(openParenBytes)
|
||||
f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
|
||||
f.fs.Write([]byte(ve.Type().String()))
|
||||
f.fs.Write(closeParenBytes)
|
||||
} else {
|
||||
if nilFound || cycleFound {
|
||||
indirects += strings.Count(ve.Type().String(), "*")
|
||||
}
|
||||
f.fs.Write(openAngleBytes)
|
||||
f.fs.Write([]byte(strings.Repeat("*", indirects)))
|
||||
f.fs.Write(closeAngleBytes)
|
||||
}
|
||||
|
||||
// Display pointer information depending on flags.
|
||||
if f.fs.Flag('+') && (len(pointerChain) > 0) {
|
||||
f.fs.Write(openParenBytes)
|
||||
for i, addr := range pointerChain {
|
||||
if i > 0 {
|
||||
f.fs.Write(pointerChainBytes)
|
||||
}
|
||||
printHexPtr(f.fs, addr)
|
||||
}
|
||||
f.fs.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// Display dereferenced value.
|
||||
switch {
|
||||
case nilFound:
|
||||
f.fs.Write(nilAngleBytes)
|
||||
|
||||
case cycleFound:
|
||||
f.fs.Write(circularShortBytes)
|
||||
|
||||
default:
|
||||
f.ignoreNextType = true
|
||||
f.format(ve)
|
||||
}
|
||||
}
|
||||
|
||||
// format is the main workhorse for providing the Formatter interface. It
|
||||
// uses the passed reflect value to figure out what kind of object we are
|
||||
// dealing with and formats it appropriately. It is a recursive function,
|
||||
// however circular data structures are detected and handled properly.
|
||||
func (f *formatState) format(v reflect.Value) {
|
||||
// Handle invalid reflect values immediately.
|
||||
kind := v.Kind()
|
||||
if kind == reflect.Invalid {
|
||||
f.fs.Write(invalidAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle pointers specially.
|
||||
if kind == reflect.Ptr {
|
||||
f.formatPtr(v)
|
||||
return
|
||||
}
|
||||
|
||||
// Print type information unless already handled elsewhere.
|
||||
if !f.ignoreNextType && f.fs.Flag('#') {
|
||||
f.fs.Write(openParenBytes)
|
||||
f.fs.Write([]byte(v.Type().String()))
|
||||
f.fs.Write(closeParenBytes)
|
||||
}
|
||||
f.ignoreNextType = false
|
||||
|
||||
// Call Stringer/error interfaces if they exist and the handle methods
|
||||
// flag is enabled.
|
||||
if !f.cs.DisableMethods {
|
||||
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
|
||||
if handled := handleMethods(f.cs, f.fs, v); handled {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case reflect.Invalid:
|
||||
// Do nothing. We should never get here since invalid has already
|
||||
// been handled above.
|
||||
|
||||
case reflect.Bool:
|
||||
printBool(f.fs, v.Bool())
|
||||
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
printInt(f.fs, v.Int(), 10)
|
||||
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
printUint(f.fs, v.Uint(), 10)
|
||||
|
||||
case reflect.Float32:
|
||||
printFloat(f.fs, v.Float(), 32)
|
||||
|
||||
case reflect.Float64:
|
||||
printFloat(f.fs, v.Float(), 64)
|
||||
|
||||
case reflect.Complex64:
|
||||
printComplex(f.fs, v.Complex(), 32)
|
||||
|
||||
case reflect.Complex128:
|
||||
printComplex(f.fs, v.Complex(), 64)
|
||||
|
||||
case reflect.Slice:
|
||||
if v.IsNil() {
|
||||
f.fs.Write(nilAngleBytes)
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case reflect.Array:
|
||||
f.fs.Write(openBracketBytes)
|
||||
f.depth++
|
||||
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
||||
f.fs.Write(maxShortBytes)
|
||||
} else {
|
||||
numEntries := v.Len()
|
||||
for i := 0; i < numEntries; i++ {
|
||||
if i > 0 {
|
||||
f.fs.Write(spaceBytes)
|
||||
}
|
||||
f.ignoreNextType = true
|
||||
f.format(f.unpackValue(v.Index(i)))
|
||||
}
|
||||
}
|
||||
f.depth--
|
||||
f.fs.Write(closeBracketBytes)
|
||||
|
||||
case reflect.String:
|
||||
f.fs.Write([]byte(v.String()))
|
||||
|
||||
case reflect.Interface:
|
||||
// The only time we should get here is for nil interfaces due to
|
||||
// unpackValue calls.
|
||||
if v.IsNil() {
|
||||
f.fs.Write(nilAngleBytes)
|
||||
}
|
||||
|
||||
case reflect.Ptr:
|
||||
// Do nothing. We should never get here since pointers have already
|
||||
// been handled above.
|
||||
|
||||
case reflect.Map:
|
||||
// nil maps should be indicated as different than empty maps
|
||||
if v.IsNil() {
|
||||
f.fs.Write(nilAngleBytes)
|
||||
break
|
||||
}
|
||||
|
||||
f.fs.Write(openMapBytes)
|
||||
f.depth++
|
||||
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
||||
f.fs.Write(maxShortBytes)
|
||||
} else {
|
||||
keys := v.MapKeys()
|
||||
if f.cs.SortKeys {
|
||||
sortValues(keys, f.cs)
|
||||
}
|
||||
for i, key := range keys {
|
||||
if i > 0 {
|
||||
f.fs.Write(spaceBytes)
|
||||
}
|
||||
f.ignoreNextType = true
|
||||
f.format(f.unpackValue(key))
|
||||
f.fs.Write(colonBytes)
|
||||
f.ignoreNextType = true
|
||||
f.format(f.unpackValue(v.MapIndex(key)))
|
||||
}
|
||||
}
|
||||
f.depth--
|
||||
f.fs.Write(closeMapBytes)
|
||||
|
||||
case reflect.Struct:
|
||||
numFields := v.NumField()
|
||||
f.fs.Write(openBraceBytes)
|
||||
f.depth++
|
||||
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
||||
f.fs.Write(maxShortBytes)
|
||||
} else {
|
||||
vt := v.Type()
|
||||
for i := 0; i < numFields; i++ {
|
||||
if i > 0 {
|
||||
f.fs.Write(spaceBytes)
|
||||
}
|
||||
vtf := vt.Field(i)
|
||||
if f.fs.Flag('+') || f.fs.Flag('#') {
|
||||
f.fs.Write([]byte(vtf.Name))
|
||||
f.fs.Write(colonBytes)
|
||||
}
|
||||
f.format(f.unpackValue(v.Field(i)))
|
||||
}
|
||||
}
|
||||
f.depth--
|
||||
f.fs.Write(closeBraceBytes)
|
||||
|
||||
case reflect.Uintptr:
|
||||
printHexPtr(f.fs, uintptr(v.Uint()))
|
||||
|
||||
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
||||
printHexPtr(f.fs, v.Pointer())
|
||||
|
||||
// There were not any other types at the time this code was written, but
|
||||
// fall back to letting the default fmt package handle it if any get added.
|
||||
default:
|
||||
format := f.buildDefaultFormat()
|
||||
if v.CanInterface() {
|
||||
fmt.Fprintf(f.fs, format, v.Interface())
|
||||
} else {
|
||||
fmt.Fprintf(f.fs, format, v.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
|
||||
// details.
|
||||
func (f *formatState) Format(fs fmt.State, verb rune) {
|
||||
f.fs = fs
|
||||
|
||||
// Use standard formatting for verbs that are not v.
|
||||
if verb != 'v' {
|
||||
format := f.constructOrigFormat(verb)
|
||||
fmt.Fprintf(fs, format, f.value)
|
||||
return
|
||||
}
|
||||
|
||||
if f.value == nil {
|
||||
if fs.Flag('#') {
|
||||
fs.Write(interfaceBytes)
|
||||
}
|
||||
fs.Write(nilAngleBytes)
|
||||
return
|
||||
}
|
||||
|
||||
f.format(reflect.ValueOf(f.value))
|
||||
}
|
||||
|
||||
// newFormatter is a helper function to consolidate the logic from the various
|
||||
// public methods which take varying config states.
|
||||
func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
|
||||
fs := &formatState{value: v, cs: cs}
|
||||
fs.pointers = make(map[uintptr]int)
|
||||
return fs
|
||||
}
|
||||
|
||||
/*
|
||||
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
|
||||
interface. As a result, it integrates cleanly with standard fmt package
|
||||
printing functions. The formatter is useful for inline printing of smaller data
|
||||
types similar to the standard %v format specifier.
|
||||
|
||||
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
||||
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
|
||||
combinations. Any other verbs such as %x and %q will be sent to the the
|
||||
standard fmt package for formatting. In addition, the custom formatter ignores
|
||||
the width and precision arguments (however they will still work on the format
|
||||
specifiers not handled by the custom formatter).
|
||||
|
||||
Typically this function shouldn't be called directly. It is much easier to make
|
||||
use of the custom formatter by calling one of the convenience functions such as
|
||||
Printf, Println, or Fprintf.
|
||||
*/
|
||||
func NewFormatter(v interface{}) fmt.Formatter {
|
||||
return newFormatter(&Config, v)
|
||||
}
|
||||
148
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
148
trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package spew
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the formatted string as a value that satisfies error. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Errorf(format string, a ...interface{}) (err error) {
|
||||
return fmt.Errorf(format, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprint(w, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprintf(w, format, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
|
||||
// passed with a default Formatter interface returned by NewFormatter. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
return fmt.Fprintln(w, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Print is a wrapper for fmt.Print that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Print(a ...interface{}) (n int, err error) {
|
||||
return fmt.Print(convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Printf(format string, a ...interface{}) (n int, err error) {
|
||||
return fmt.Printf(format, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Println is a wrapper for fmt.Println that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the number of bytes written and any write error encountered. See
|
||||
// NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Println(a ...interface{}) (n int, err error) {
|
||||
return fmt.Println(convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Sprint(a ...interface{}) string {
|
||||
return fmt.Sprint(convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
|
||||
// passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Sprintf(format string, a ...interface{}) string {
|
||||
return fmt.Sprintf(format, convertArgs(a)...)
|
||||
}
|
||||
|
||||
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
|
||||
// were passed with a default Formatter interface returned by NewFormatter. It
|
||||
// returns the resulting string. See NewFormatter for formatting details.
|
||||
//
|
||||
// This function is shorthand for the following syntax:
|
||||
//
|
||||
// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||
func Sprintln(a ...interface{}) string {
|
||||
return fmt.Sprintln(convertArgs(a)...)
|
||||
}
|
||||
|
||||
// convertArgs accepts a slice of arguments and returns a slice of the same
|
||||
// length with each argument converted to a default spew Formatter interface.
|
||||
func convertArgs(args []interface{}) (formatters []interface{}) {
|
||||
formatters = make([]interface{}, len(args))
|
||||
for index, arg := range args {
|
||||
formatters[index] = NewFormatter(arg)
|
||||
}
|
||||
return formatters
|
||||
}
|
||||
9
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/.travis.yml
generated
vendored
9
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/.travis.yml
generated
vendored
|
|
@ -1,9 +0,0 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.4.3
|
||||
- 1.5.3
|
||||
- tip
|
||||
|
||||
script:
|
||||
- go test -v ./...
|
||||
41
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CHANGELOG.md
generated
vendored
Normal file
41
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CHANGELOG.md
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Changelog
|
||||
|
||||
## [1.6.0](https://github.com/google/uuid/compare/v1.5.0...v1.6.0) (2024-01-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add Max UUID constant ([#149](https://github.com/google/uuid/issues/149)) ([c58770e](https://github.com/google/uuid/commit/c58770eb495f55fe2ced6284f93c5158a62e53e3))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix typo in version 7 uuid documentation ([#153](https://github.com/google/uuid/issues/153)) ([016b199](https://github.com/google/uuid/commit/016b199544692f745ffc8867b914129ecb47ef06))
|
||||
* Monotonicity in UUIDv7 ([#150](https://github.com/google/uuid/issues/150)) ([a2b2b32](https://github.com/google/uuid/commit/a2b2b32373ff0b1a312b7fdf6d38a977099698a6))
|
||||
|
||||
## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Validate UUID without creating new UUID ([#141](https://github.com/google/uuid/issues/141)) ([9ee7366](https://github.com/google/uuid/commit/9ee7366e66c9ad96bab89139418a713dc584ae29))
|
||||
|
||||
## [1.4.0](https://github.com/google/uuid/compare/v1.3.1...v1.4.0) (2023-10-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* UUIDs slice type with Strings() convenience method ([#133](https://github.com/google/uuid/issues/133)) ([cd5fbbd](https://github.com/google/uuid/commit/cd5fbbdd02f3e3467ac18940e07e062be1f864b4))
|
||||
|
||||
### Fixes
|
||||
|
||||
* Clarify that Parse's job is to parse but not necessarily validate strings. (Documents current behavior)
|
||||
|
||||
## [1.3.1](https://github.com/google/uuid/compare/v1.3.0...v1.3.1) (2023-08-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Use .EqualFold() to parse urn prefixed UUIDs ([#118](https://github.com/google/uuid/issues/118)) ([574e687](https://github.com/google/uuid/commit/574e6874943741fb99d41764c705173ada5293f0))
|
||||
|
||||
## Changelog
|
||||
16
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CONTRIBUTING.md
generated
vendored
16
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CONTRIBUTING.md
generated
vendored
|
|
@ -2,6 +2,22 @@
|
|||
|
||||
We definitely welcome patches and contribution to this project!
|
||||
|
||||
### Tips
|
||||
|
||||
Commits must be formatted according to the [Conventional Commits Specification](https://www.conventionalcommits.org).
|
||||
|
||||
Always try to include a test case! If it is not possible or not necessary,
|
||||
please explain why in the pull request description.
|
||||
|
||||
### Releasing
|
||||
|
||||
Commits that would precipitate a SemVer change, as described in the Conventional
|
||||
Commits Specification, will trigger [`release-please`](https://github.com/google-github-actions/release-please-action)
|
||||
to create a release candidate pull request. Once submitted, `release-please`
|
||||
will create a release.
|
||||
|
||||
For tips on how to work with `release-please`, see its documentation.
|
||||
|
||||
### Legal requirements
|
||||
|
||||
In order to protect both you and ourselves, you will need to sign the
|
||||
|
|
|
|||
10
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/README.md
generated
vendored
10
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/README.md
generated
vendored
|
|
@ -1,6 +1,6 @@
|
|||
# uuid 
|
||||
# uuid
|
||||
The uuid package generates and inspects UUIDs based on
|
||||
[RFC 4122](http://tools.ietf.org/html/rfc4122)
|
||||
[RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122)
|
||||
and DCE 1.1: Authentication and Security Services.
|
||||
|
||||
This package is based on the github.com/pborman/uuid package (previously named
|
||||
|
|
@ -9,10 +9,12 @@ a UUID is a 16 byte array rather than a byte slice. One loss due to this
|
|||
change is the ability to represent an invalid UUID (vs a NIL UUID).
|
||||
|
||||
###### Install
|
||||
`go get github.com/google/uuid`
|
||||
```sh
|
||||
go get github.com/google/uuid
|
||||
```
|
||||
|
||||
###### Documentation
|
||||
[](http://godoc.org/github.com/google/uuid)
|
||||
[](https://pkg.go.dev/github.com/google/uuid)
|
||||
|
||||
Full `go doc` style documentation for the package can be viewed online without
|
||||
installing this package by using the GoDoc site here:
|
||||
|
|
|
|||
6
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/hash.go
generated
vendored
6
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/hash.go
generated
vendored
|
|
@ -17,6 +17,12 @@ var (
|
|||
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
|
||||
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
|
||||
Nil UUID // empty UUID, all zeros
|
||||
|
||||
// The Max UUID is special form of UUID that is specified to have all 128 bits set to 1.
|
||||
Max = UUID{
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
}
|
||||
)
|
||||
|
||||
// NewHash returns a new UUID derived from the hash of space concatenated with
|
||||
|
|
|
|||
2
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/node_js.go
generated
vendored
2
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/node_js.go
generated
vendored
|
|
@ -7,6 +7,6 @@
|
|||
package uuid
|
||||
|
||||
// getHardwareInterface returns nil values for the JS version of the code.
|
||||
// This remvoves the "net" dependency, because it is not used in the browser.
|
||||
// This removes the "net" dependency, because it is not used in the browser.
|
||||
// Using the "net" library inflates the size of the transpiled JS code by 673k bytes.
|
||||
func getHardwareInterface(name string) (string, []byte) { return "", nil }
|
||||
|
|
|
|||
21
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/time.go
generated
vendored
21
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/time.go
generated
vendored
|
|
@ -108,12 +108,23 @@ func setClockSequence(seq int) {
|
|||
}
|
||||
|
||||
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
|
||||
// uuid. The time is only defined for version 1 and 2 UUIDs.
|
||||
// uuid. The time is only defined for version 1, 2, 6 and 7 UUIDs.
|
||||
func (uuid UUID) Time() Time {
|
||||
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
||||
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
||||
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
||||
return Time(time)
|
||||
var t Time
|
||||
switch uuid.Version() {
|
||||
case 6:
|
||||
time := binary.BigEndian.Uint64(uuid[:8]) // Ignore uuid[6] version b0110
|
||||
t = Time(time)
|
||||
case 7:
|
||||
time := binary.BigEndian.Uint64(uuid[:8])
|
||||
t = Time((time>>16)*10000 + g1582ns100)
|
||||
default: // forward compatible
|
||||
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
||||
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
||||
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
||||
t = Time(time)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// ClockSequence returns the clock sequence encoded in uuid.
|
||||
|
|
|
|||
89
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/uuid.go
generated
vendored
89
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/uuid.go
generated
vendored
|
|
@ -56,11 +56,15 @@ func IsInvalidLengthError(err error) bool {
|
|||
return ok
|
||||
}
|
||||
|
||||
// Parse decodes s into a UUID or returns an error. Both the standard UUID
|
||||
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
|
||||
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
|
||||
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
|
||||
// Parse decodes s into a UUID or returns an error if it cannot be parsed. Both
|
||||
// the standard UUID forms defined in RFC 4122
|
||||
// (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) are decoded. In addition,
|
||||
// Parse accepts non-standard strings such as the raw hex encoding
|
||||
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and 38 byte "Microsoft style" encodings,
|
||||
// e.g. {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}. Only the middle 36 bytes are
|
||||
// examined in the latter case. Parse should not be used to validate strings as
|
||||
// it parses non-standard encodings as indicated above.
|
||||
func Parse(s string) (UUID, error) {
|
||||
var uuid UUID
|
||||
switch len(s) {
|
||||
|
|
@ -69,7 +73,7 @@ func Parse(s string) (UUID, error) {
|
|||
|
||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
case 36 + 9:
|
||||
if strings.ToLower(s[:9]) != "urn:uuid:" {
|
||||
if !strings.EqualFold(s[:9], "urn:uuid:") {
|
||||
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
|
||||
}
|
||||
s = s[9:]
|
||||
|
|
@ -101,7 +105,8 @@ func Parse(s string) (UUID, error) {
|
|||
9, 11,
|
||||
14, 16,
|
||||
19, 21,
|
||||
24, 26, 28, 30, 32, 34} {
|
||||
24, 26, 28, 30, 32, 34,
|
||||
} {
|
||||
v, ok := xtob(s[x], s[x+1])
|
||||
if !ok {
|
||||
return uuid, errors.New("invalid UUID format")
|
||||
|
|
@ -117,7 +122,7 @@ func ParseBytes(b []byte) (UUID, error) {
|
|||
switch len(b) {
|
||||
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
|
||||
if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) {
|
||||
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
|
||||
}
|
||||
b = b[9:]
|
||||
|
|
@ -145,7 +150,8 @@ func ParseBytes(b []byte) (UUID, error) {
|
|||
9, 11,
|
||||
14, 16,
|
||||
19, 21,
|
||||
24, 26, 28, 30, 32, 34} {
|
||||
24, 26, 28, 30, 32, 34,
|
||||
} {
|
||||
v, ok := xtob(b[x], b[x+1])
|
||||
if !ok {
|
||||
return uuid, errors.New("invalid UUID format")
|
||||
|
|
@ -180,6 +186,59 @@ func Must(uuid UUID, err error) UUID {
|
|||
return uuid
|
||||
}
|
||||
|
||||
// Validate returns an error if s is not a properly formatted UUID in one of the following formats:
|
||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
||||
// It returns an error if the format is invalid, otherwise nil.
|
||||
func Validate(s string) error {
|
||||
switch len(s) {
|
||||
// Standard UUID format
|
||||
case 36:
|
||||
|
||||
// UUID with "urn:uuid:" prefix
|
||||
case 36 + 9:
|
||||
if !strings.EqualFold(s[:9], "urn:uuid:") {
|
||||
return fmt.Errorf("invalid urn prefix: %q", s[:9])
|
||||
}
|
||||
s = s[9:]
|
||||
|
||||
// UUID enclosed in braces
|
||||
case 36 + 2:
|
||||
if s[0] != '{' || s[len(s)-1] != '}' {
|
||||
return fmt.Errorf("invalid bracketed UUID format")
|
||||
}
|
||||
s = s[1 : len(s)-1]
|
||||
|
||||
// UUID without hyphens
|
||||
case 32:
|
||||
for i := 0; i < len(s); i += 2 {
|
||||
_, ok := xtob(s[i], s[i+1])
|
||||
if !ok {
|
||||
return errors.New("invalid UUID format")
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return invalidLengthError{len(s)}
|
||||
}
|
||||
|
||||
// Check for standard UUID format
|
||||
if len(s) == 36 {
|
||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
||||
return errors.New("invalid UUID format")
|
||||
}
|
||||
for _, x := range []int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} {
|
||||
if _, ok := xtob(s[x], s[x+1]); !ok {
|
||||
return errors.New("invalid UUID format")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
// , or "" if uuid is invalid.
|
||||
func (uuid UUID) String() string {
|
||||
|
|
@ -292,3 +351,15 @@ func DisableRandPool() {
|
|||
poolMu.Lock()
|
||||
poolPos = randPoolSize
|
||||
}
|
||||
|
||||
// UUIDs is a slice of UUID types.
|
||||
type UUIDs []UUID
|
||||
|
||||
// Strings returns a string slice containing the string form of each UUID in uuids.
|
||||
func (uuids UUIDs) Strings() []string {
|
||||
var uuidStrs = make([]string, len(uuids))
|
||||
for i, uuid := range uuids {
|
||||
uuidStrs[i] = uuid.String()
|
||||
}
|
||||
return uuidStrs
|
||||
}
|
||||
|
|
|
|||
56
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version6.go
generated
vendored
Normal file
56
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version6.go
generated
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package uuid
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// UUID version 6 is a field-compatible version of UUIDv1, reordered for improved DB locality.
|
||||
// It is expected that UUIDv6 will primarily be used in contexts where there are existing v1 UUIDs.
|
||||
// Systems that do not involve legacy UUIDv1 SHOULD consider using UUIDv7 instead.
|
||||
//
|
||||
// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#uuidv6
|
||||
//
|
||||
// NewV6 returns a Version 6 UUID based on the current NodeID and clock
|
||||
// sequence, and the current time. If the NodeID has not been set by SetNodeID
|
||||
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
|
||||
// be set NewV6 set NodeID is random bits automatically . If clock sequence has not been set by
|
||||
// SetClockSequence then it will be set automatically. If GetTime fails to
|
||||
// return the current NewV6 returns Nil and an error.
|
||||
func NewV6() (UUID, error) {
|
||||
var uuid UUID
|
||||
now, seq, err := GetTime()
|
||||
if err != nil {
|
||||
return uuid, err
|
||||
}
|
||||
|
||||
/*
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| time_high |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| time_mid | time_low_and_version |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|clk_seq_hi_res | clk_seq_low | node (0-1) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| node (2-5) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
binary.BigEndian.PutUint64(uuid[0:], uint64(now))
|
||||
binary.BigEndian.PutUint16(uuid[8:], seq)
|
||||
|
||||
uuid[6] = 0x60 | (uuid[6] & 0x0F)
|
||||
uuid[8] = 0x80 | (uuid[8] & 0x3F)
|
||||
|
||||
nodeMu.Lock()
|
||||
if nodeID == zeroID {
|
||||
setNodeInterface("")
|
||||
}
|
||||
copy(uuid[10:], nodeID[:])
|
||||
nodeMu.Unlock()
|
||||
|
||||
return uuid, nil
|
||||
}
|
||||
104
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version7.go
generated
vendored
Normal file
104
trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version7.go
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// UUID version 7 features a time-ordered value field derived from the widely
|
||||
// implemented and well known Unix Epoch timestamp source,
|
||||
// the number of milliseconds seconds since midnight 1 Jan 1970 UTC, leap seconds excluded.
|
||||
// As well as improved entropy characteristics over versions 1 or 6.
|
||||
//
|
||||
// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#name-uuid-version-7
|
||||
//
|
||||
// Implementations SHOULD utilize UUID version 7 over UUID version 1 and 6 if possible.
|
||||
//
|
||||
// NewV7 returns a Version 7 UUID based on the current time(Unix Epoch).
|
||||
// Uses the randomness pool if it was enabled with EnableRandPool.
|
||||
// On error, NewV7 returns Nil and an error
|
||||
func NewV7() (UUID, error) {
|
||||
uuid, err := NewRandom()
|
||||
if err != nil {
|
||||
return uuid, err
|
||||
}
|
||||
makeV7(uuid[:])
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// NewV7FromReader returns a Version 7 UUID based on the current time(Unix Epoch).
|
||||
// it use NewRandomFromReader fill random bits.
|
||||
// On error, NewV7FromReader returns Nil and an error.
|
||||
func NewV7FromReader(r io.Reader) (UUID, error) {
|
||||
uuid, err := NewRandomFromReader(r)
|
||||
if err != nil {
|
||||
return uuid, err
|
||||
}
|
||||
|
||||
makeV7(uuid[:])
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6])
|
||||
// uuid[8] already has the right version number (Variant is 10)
|
||||
// see function NewV7 and NewV7FromReader
|
||||
func makeV7(uuid []byte) {
|
||||
/*
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| unix_ts_ms |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| unix_ts_ms | ver | rand_a (12 bit seq) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|var| rand_b |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| rand_b |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
_ = uuid[15] // bounds check
|
||||
|
||||
t, s := getV7Time()
|
||||
|
||||
uuid[0] = byte(t >> 40)
|
||||
uuid[1] = byte(t >> 32)
|
||||
uuid[2] = byte(t >> 24)
|
||||
uuid[3] = byte(t >> 16)
|
||||
uuid[4] = byte(t >> 8)
|
||||
uuid[5] = byte(t)
|
||||
|
||||
uuid[6] = 0x70 | (0x0F & byte(s>>8))
|
||||
uuid[7] = byte(s)
|
||||
}
|
||||
|
||||
// lastV7time is the last time we returned stored as:
|
||||
//
|
||||
// 52 bits of time in milliseconds since epoch
|
||||
// 12 bits of (fractional nanoseconds) >> 8
|
||||
var lastV7time int64
|
||||
|
||||
const nanoPerMilli = 1000000
|
||||
|
||||
// getV7Time returns the time in milliseconds and nanoseconds / 256.
|
||||
// The returned (milli << 12 + seq) is guarenteed to be greater than
|
||||
// (milli << 12 + seq) returned by any previous call to getV7Time.
|
||||
func getV7Time() (milli, seq int64) {
|
||||
timeMu.Lock()
|
||||
defer timeMu.Unlock()
|
||||
|
||||
nano := timeNow().UnixNano()
|
||||
milli = nano / nanoPerMilli
|
||||
// Sequence number is between 0 and 3906 (nanoPerMilli>>8)
|
||||
seq = (nano - milli*nanoPerMilli) >> 8
|
||||
now := milli<<12 + seq
|
||||
if now <= lastV7time {
|
||||
now = lastV7time + 1
|
||||
milli = now >> 12
|
||||
seq = now & 0xfff
|
||||
}
|
||||
lastV7time = now
|
||||
return milli, seq
|
||||
}
|
||||
2
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/LICENSE
generated
vendored
2
trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/LICENSE
generated
vendored
|
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2025 winlin
|
||||
Copyright (c) 2013-2017 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
|
||||
|
|
|
|||
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.gitignore
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.gitignore
generated
vendored
|
|
@ -1,3 +1,6 @@
|
|||
# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
### JetBrains IDE ###
|
||||
#####################
|
||||
.idea/
|
||||
|
|
|
|||
48
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.golangci.yml
generated
vendored
48
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.golangci.yml
generated
vendored
|
|
@ -1,6 +1,13 @@
|
|||
# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
run:
|
||||
timeout: 5m
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
enable:
|
||||
- shadow
|
||||
misspell:
|
||||
locale: US
|
||||
exhaustive:
|
||||
|
|
@ -10,7 +17,14 @@ linters-settings:
|
|||
modules:
|
||||
- github.com/pkg/errors:
|
||||
recommendations:
|
||||
- errors
|
||||
- errors
|
||||
forbidigo:
|
||||
forbid:
|
||||
- ^fmt.Print(f|ln)?$
|
||||
- ^log.(Panic|Fatal|Print)(f|ln)?$
|
||||
- ^os.Exit$
|
||||
- ^panic$
|
||||
- ^print(ln)?$
|
||||
|
||||
linters:
|
||||
enable:
|
||||
|
|
@ -18,9 +32,7 @@ linters:
|
|||
- bidichk # Checks for dangerous unicode character sequences
|
||||
- bodyclose # checks whether HTTP response body is closed successfully
|
||||
- contextcheck # check the function whether use a non-inherited context
|
||||
- deadcode # Finds unused code
|
||||
- decorder # check declaration order and count of types, constants, variables and functions
|
||||
- depguard # Go linter that checks if package imports are in a list of acceptable packages
|
||||
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
|
||||
- dupl # Tool for code clone detection
|
||||
- durationcheck # check for two durations multiplied together
|
||||
|
|
@ -30,6 +42,7 @@ linters:
|
|||
- errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13.
|
||||
- exhaustive # check exhaustiveness of enum switch statements
|
||||
- exportloopref # checks for pointers to enclosing loop variables
|
||||
- forbidigo # Forbids identifiers
|
||||
- forcetypeassert # finds forced type assertions
|
||||
- gci # Gci control golang package import order and make it always deterministic.
|
||||
- gochecknoglobals # Checks that no globals are present in Go code
|
||||
|
|
@ -38,7 +51,7 @@ linters:
|
|||
- goconst # Finds repeated strings that could be replaced by a constant
|
||||
- gocritic # The most opinionated Go source code linter
|
||||
- godox # Tool for detection of FIXME, TODO and other comment keywords
|
||||
- goerr113 # Golang linter to check the errors handling expressions
|
||||
- err113 # Golang linter to check the errors handling expressions
|
||||
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
|
||||
- gofumpt # Gofumpt checks whether code was gofumpt-ed.
|
||||
- goheader # Checks is file header matches to pattern
|
||||
|
|
@ -53,14 +66,12 @@ linters:
|
|||
- importas # Enforces consistent import aliases
|
||||
- ineffassign # Detects when assignments to existing variables are not used
|
||||
- misspell # Finds commonly misspelled English words in comments
|
||||
- nakedret # Finds naked returns in functions greater than a specified function length
|
||||
- nilerr # Finds the code that returns nil even if it checks that the error is not nil.
|
||||
- nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value.
|
||||
- noctx # noctx finds sending http request without context.Context
|
||||
- predeclared # find code that shadows one of Go's predeclared identifiers
|
||||
- revive # golint replacement, finds style mistakes
|
||||
- staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks
|
||||
- structcheck # Finds unused struct fields
|
||||
- stylecheck # Stylecheck is a replacement for golint
|
||||
- tagliatelle # Checks the struct tags.
|
||||
- tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17
|
||||
|
|
@ -69,24 +80,21 @@ linters:
|
|||
- unconvert # Remove unnecessary type conversions
|
||||
- unparam # Reports unused function parameters
|
||||
- unused # Checks Go code for unused constants, variables, functions and types
|
||||
- varcheck # Finds unused global variables and constants
|
||||
- wastedassign # wastedassign finds wasted assignment statements
|
||||
- whitespace # Tool for detection of leading and trailing whitespace
|
||||
disable:
|
||||
- depguard # Go linter that checks if package imports are in a list of acceptable packages
|
||||
- containedctx # containedctx is a linter that detects struct contained context.Context field
|
||||
- cyclop # checks function and package cyclomatic complexity
|
||||
- exhaustivestruct # Checks if all struct's fields are initialized
|
||||
- forbidigo # Forbids identifiers
|
||||
- funlen # Tool for detection of long functions
|
||||
- gocyclo # Computes and checks the cyclomatic complexity of functions
|
||||
- godot # Check if comments end in a period
|
||||
- gomnd # An analyzer to detect magic numbers.
|
||||
- ifshort # Checks that your code uses short syntax for if-statements whenever possible
|
||||
- ireturn # Accept Interfaces, Return Concrete Types
|
||||
- lll # Reports long lines
|
||||
- maintidx # maintidx measures the maintainability index of each function.
|
||||
- makezero # Finds slice declarations with non-zero initial length
|
||||
- maligned # Tool to detect Go structs that would take less memory if their fields were sorted
|
||||
- nakedret # Finds naked returns in functions greater than a specified function length
|
||||
- nestif # Reports deeply nested if statements
|
||||
- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity
|
||||
- nolintlint # Reports ill-formed or insufficient nolint directives
|
||||
|
|
@ -103,17 +111,15 @@ linters:
|
|||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
exclude-dirs-use-default: false
|
||||
exclude-rules:
|
||||
# Allow complex tests, better to be self contained
|
||||
- path: _test\.go
|
||||
# Allow complex tests and examples, better to be self contained
|
||||
- path: (examples|main\.go|_test\.go)
|
||||
linters:
|
||||
- forbidigo
|
||||
- gocognit
|
||||
|
||||
# Allow complex main function in examples
|
||||
- path: examples
|
||||
text: "of func `main` is high"
|
||||
# Allow forbidden identifiers in CLI commands
|
||||
- path: cmd
|
||||
linters:
|
||||
- gocognit
|
||||
|
||||
run:
|
||||
skip-dirs-use-default: false
|
||||
- forbidigo
|
||||
|
|
|
|||
17
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/AUTHORS.txt
generated
vendored
17
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/AUTHORS.txt
generated
vendored
|
|
@ -1,17 +0,0 @@
|
|||
# Thank you to everyone that made Pion possible. If you are interested in contributing
|
||||
# we would love to have you https://github.com/pion/webrtc/wiki/Contributing
|
||||
#
|
||||
# This file is auto generated, using git to list all individuals contributors.
|
||||
# see `.github/generate-authors.sh` for the scripting
|
||||
Atsushi Watanabe <atsushi.w@ieee.org>
|
||||
backkem <mail@backkem.me>
|
||||
Benny Daon <benny@tuzig.com>
|
||||
Chinmay Kousik <chinmaykousik1@gmail.com>
|
||||
Eric Daniels <eric@erdaniels.com>
|
||||
Hugo Arregui <hugo.arregui@gmail.com>
|
||||
Hugo Arregui <hugo@decentraland.org>
|
||||
John Bradley <jrb@turrettech.com>
|
||||
Norman Rasmussen <norman@rasmussen.co.za>
|
||||
Sean DuBois <seaduboi@amazon.com>
|
||||
Sean DuBois <sean@siobud.com>
|
||||
Yutaka Takeda <yt0916@gmail.com>
|
||||
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/DESIGN.md
generated
vendored
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/DESIGN.md
generated
vendored
|
|
@ -1,20 +0,0 @@
|
|||
<h1 align="center">
|
||||
Design
|
||||
</h1>
|
||||
|
||||
### Portable
|
||||
Pion Data Channels is written in Go and extremely portable. Anywhere Golang runs, Pion Data Channels should work as well! Instead of dealing with complicated
|
||||
cross-compiling of multiple libraries, you now can run anywhere with one `go build`
|
||||
|
||||
### Simple API
|
||||
The API is based on an io.ReadWriteCloser.
|
||||
|
||||
### Readable
|
||||
If code comes from an RFC we try to make sure everything is commented with a link to the spec.
|
||||
This makes learning and debugging easier, this library was written to also serve as a guide for others.
|
||||
|
||||
### Tested
|
||||
Every commit is tested via travis-ci Go provides fantastic facilities for testing, and more will be added as time goes on.
|
||||
|
||||
### Shared libraries
|
||||
Every pion product is built using shared libraries, allowing others to review and reuse our libraries.
|
||||
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/LICENSE
generated
vendored
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/LICENSE
generated
vendored
|
|
@ -1,21 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018
|
||||
Copyright (c) 2023 The Pion community <https://pion.ly>
|
||||
|
||||
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:
|
||||
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 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.
|
||||
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.
|
||||
|
|
|
|||
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/README.md
generated
vendored
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/README.md
generated
vendored
|
|
@ -6,32 +6,29 @@
|
|||
<h4 align="center">A Go implementation of WebRTC Data Channels</h4>
|
||||
<p align="center">
|
||||
<a href="https://pion.ly"><img src="https://img.shields.io/badge/pion-datachannel-gray.svg?longCache=true&colorB=brightgreen" alt="Pion Data Channels"></a>
|
||||
<!--<a href="https://sourcegraph.com/github.com/pion/webrtc?badge"><img src="https://sourcegraph.com/github.com/pion/webrtc/-/badge.svg" alt="Sourcegraph Widget"></a>-->
|
||||
<a href="https://pion.ly/slack"><img src="https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen" alt="Slack Widget"></a>
|
||||
<br>
|
||||
<a href="https://travis-ci.org/pion/datachannel"><img src="https://travis-ci.org/pion/datachannel.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://pkg.go.dev/github.com/pion/datachannel"><img src="https://godoc.org/github.com/pion/datachannel?status.svg" alt="GoDoc"></a>
|
||||
<img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/pion/datachannel/test.yaml">
|
||||
<a href="https://pkg.go.dev/github.com/pion/datachannel"><img src="https://pkg.go.dev/badge/github.com/pion/datachannel.svg" alt="Go Reference"></a>
|
||||
<a href="https://codecov.io/gh/pion/datachannel"><img src="https://codecov.io/gh/pion/datachannel/branch/master/graph/badge.svg" alt="Coverage Status"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/pion/datachannel"><img src="https://goreportcard.com/badge/github.com/pion/datachannel" alt="Go Report Card"></a>
|
||||
<!--<a href="https://www.codacy.com/app/Sean-Der/webrtc"><img src="https://api.codacy.com/project/badge/Grade/18f4aec384894e6aac0b94effe51961d" alt="Codacy Badge"></a>-->
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
||||
</p>
|
||||
<br>
|
||||
|
||||
See [DESIGN.md](DESIGN.md) for an overview of features and future goals.
|
||||
|
||||
### Roadmap
|
||||
The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones.
|
||||
|
||||
### Community
|
||||
Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion).
|
||||
Pion has an active community on the [Slack](https://pion.ly/slack).
|
||||
|
||||
Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news.
|
||||
|
||||
We are always looking to support **your projects**. Please reach out if you have something to build!
|
||||
|
||||
If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly)
|
||||
|
||||
### Contributing
|
||||
Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible:
|
||||
Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible
|
||||
|
||||
### License
|
||||
MIT License - see [LICENSE](LICENSE) for full text
|
||||
|
|
|
|||
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/codecov.yml
generated
vendored
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/codecov.yml
generated
vendored
|
|
@ -3,6 +3,8 @@
|
|||
#
|
||||
# It is automatically copied from https://github.com/pion/.goassets repository.
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
coverage:
|
||||
status:
|
||||
|
|
|
|||
38
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/datachannel.go
generated
vendored
38
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/datachannel.go
generated
vendored
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package datachannel implements WebRTC Data Channels
|
||||
package datachannel
|
||||
|
||||
|
|
@ -32,6 +35,11 @@ type Writer interface {
|
|||
WriteDataChannel([]byte, bool) (int, error)
|
||||
}
|
||||
|
||||
// WriteDeadliner extends an io.Writer to expose setting a write deadline.
|
||||
type WriteDeadliner interface {
|
||||
SetWriteDeadline(time.Time) error
|
||||
}
|
||||
|
||||
// ReadWriteCloser is an extended io.ReadWriteCloser
|
||||
// that also implements our Reader and Writer.
|
||||
type ReadWriteCloser interface {
|
||||
|
|
@ -42,6 +50,14 @@ type ReadWriteCloser interface {
|
|||
io.Closer
|
||||
}
|
||||
|
||||
// ReadWriteCloserDeadliner is an extended ReadWriteCloser
|
||||
// that also implements r/w deadline.
|
||||
type ReadWriteCloserDeadliner interface {
|
||||
ReadWriteCloser
|
||||
ReadDeadliner
|
||||
WriteDeadliner
|
||||
}
|
||||
|
||||
// DataChannel represents a data channel
|
||||
type DataChannel struct {
|
||||
Config
|
||||
|
|
@ -71,12 +87,12 @@ type Config struct {
|
|||
LoggerFactory logging.LoggerFactory
|
||||
}
|
||||
|
||||
func newDataChannel(stream *sctp.Stream, config *Config) (*DataChannel, error) {
|
||||
func newDataChannel(stream *sctp.Stream, config *Config) *DataChannel {
|
||||
return &DataChannel{
|
||||
Config: *config,
|
||||
stream: stream,
|
||||
log: config.LoggerFactory.NewLogger("datachannel"),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Dial opens a data channels over SCTP
|
||||
|
|
@ -115,7 +131,7 @@ func Client(stream *sctp.Stream, config *Config) (*DataChannel, error) {
|
|||
return nil, fmt.Errorf("failed to send ChannelOpen %w", err)
|
||||
}
|
||||
}
|
||||
return newDataChannel(stream, config)
|
||||
return newDataChannel(stream, config), nil
|
||||
}
|
||||
|
||||
// Accept is used to accept incoming data channels over SCTP
|
||||
|
|
@ -164,10 +180,7 @@ func Server(stream *sctp.Stream, config *Config) (*DataChannel, error) {
|
|||
config.Label = string(openMsg.Label)
|
||||
config.Protocol = string(openMsg.Protocol)
|
||||
|
||||
dataChannel, err := newDataChannel(stream, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dataChannel := newDataChannel(stream, config)
|
||||
|
||||
err = dataChannel.writeDataChannelAck()
|
||||
if err != nil {
|
||||
|
|
@ -224,6 +237,12 @@ func (c *DataChannel) SetReadDeadline(t time.Time) error {
|
|||
return c.stream.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline sets a deadline for writes to return,
|
||||
// only available if the BlockWrite is enabled for sctp
|
||||
func (c *DataChannel) SetWriteDeadline(t time.Time) error {
|
||||
return c.stream.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
// MessagesSent returns the number of messages sent
|
||||
func (c *DataChannel) MessagesSent() uint32 {
|
||||
return atomic.LoadUint32(&c.messagesSent)
|
||||
|
|
@ -280,13 +299,12 @@ func (c *DataChannel) handleDCEP(data []byte) error {
|
|||
|
||||
switch msg := msg.(type) {
|
||||
case *channelAck:
|
||||
c.log.Debug("Received DATA_CHANNEL_ACK")
|
||||
if err = c.commitReliabilityParams(); err != nil {
|
||||
if err := c.commitReliabilityParams(); err != nil {
|
||||
return err
|
||||
}
|
||||
c.onOpenComplete()
|
||||
default:
|
||||
return fmt.Errorf("%w %v", ErrInvalidMessageType, msg)
|
||||
return fmt.Errorf("%w, wanted ACK got %v", ErrUnexpectedDataChannelType, msg)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/errors.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/errors.go
generated
vendored
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package datachannel
|
||||
|
||||
import "errors"
|
||||
|
|
|
|||
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message.go
generated
vendored
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message.go
generated
vendored
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package datachannel
|
||||
|
||||
import (
|
||||
|
|
@ -8,6 +11,7 @@ import (
|
|||
type message interface {
|
||||
Marshal() ([]byte, error)
|
||||
Unmarshal([]byte) error
|
||||
String() string
|
||||
}
|
||||
|
||||
// messageType is the first byte in a DataChannel message that specifies type
|
||||
|
|
@ -71,3 +75,18 @@ func parseExpectDataChannelOpen(raw []byte) (*channelOpen, error) {
|
|||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// TryMarshalUnmarshal attempts to marshal and unmarshal a message. Added for fuzzing.
|
||||
func TryMarshalUnmarshal(msg []byte) int {
|
||||
message, err := parse(msg)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
_, err = message.Marshal()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
|
|
|||
9
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_ack.go
generated
vendored
9
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_ack.go
generated
vendored
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package datachannel
|
||||
|
||||
// channelAck is used to ACK a DataChannel open
|
||||
|
|
@ -16,7 +19,11 @@ func (c *channelAck) Marshal() ([]byte, error) {
|
|||
}
|
||||
|
||||
// Unmarshal populates the struct with the given raw data
|
||||
func (c *channelAck) Unmarshal(raw []byte) error {
|
||||
func (c *channelAck) Unmarshal(_ []byte) error {
|
||||
// Message type already checked in Parse and there is no further data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c channelAck) String() string {
|
||||
return "ACK"
|
||||
}
|
||||
|
|
|
|||
26
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_open.go
generated
vendored
26
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_open.go
generated
vendored
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package datachannel
|
||||
|
||||
import (
|
||||
|
|
@ -72,6 +75,23 @@ const (
|
|||
ChannelTypePartialReliableTimedUnordered ChannelType = 0x82
|
||||
)
|
||||
|
||||
func (c ChannelType) String() string {
|
||||
switch c {
|
||||
case ChannelTypeReliable:
|
||||
case ChannelTypeReliableUnordered:
|
||||
return "ReliableUnordered"
|
||||
case ChannelTypePartialReliableRexmit:
|
||||
return "PartialReliableRexmit"
|
||||
case ChannelTypePartialReliableRexmitUnordered:
|
||||
return "PartialReliableRexmitUnordered"
|
||||
case ChannelTypePartialReliableTimed:
|
||||
return "PartialReliableTimed"
|
||||
case ChannelTypePartialReliableTimedUnordered:
|
||||
return "PartialReliableTimedUnordered"
|
||||
}
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
// ChannelPriority enums
|
||||
const (
|
||||
ChannelPriorityBelowNormal uint16 = 128
|
||||
|
|
@ -113,7 +133,7 @@ func (c *channelOpen) Unmarshal(raw []byte) error {
|
|||
labelLength := binary.BigEndian.Uint16(raw[8:])
|
||||
protocolLength := binary.BigEndian.Uint16(raw[10:])
|
||||
|
||||
if expectedLen := int(channelOpenHeaderLength + labelLength + protocolLength); len(raw) != expectedLen {
|
||||
if expectedLen := channelOpenHeaderLength + int(labelLength) + int(protocolLength); len(raw) != expectedLen {
|
||||
return fmt.Errorf("%w expected(%d) actual(%d)", ErrExpectedAndActualLengthMismatch, expectedLen, len(raw))
|
||||
}
|
||||
|
||||
|
|
@ -121,3 +141,7 @@ func (c *channelOpen) Unmarshal(raw []byte) error {
|
|||
c.Protocol = raw[channelOpenHeaderLength+labelLength : channelOpenHeaderLength+labelLength+protocolLength]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c channelOpen) String() string {
|
||||
return fmt.Sprintf("Open ChannelType(%s) Priority(%v) ReliabilityParameter(%d) Label(%s) Protocol(%s)", c.ChannelType, c.Priority, c.ReliabilityParameter, string(c.Label), string(c.Protocol))
|
||||
}
|
||||
|
|
|
|||
25
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/renovate.json
generated
vendored
25
trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/renovate.json
generated
vendored
|
|
@ -1,27 +1,6 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base",
|
||||
":disableDependencyDashboard"
|
||||
],
|
||||
"postUpdateOptions": [
|
||||
"gomodTidy"
|
||||
],
|
||||
"commitBody": "Generated by renovateBot",
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
|
||||
"automerge": true
|
||||
},
|
||||
{
|
||||
"packagePatterns": ["^golang.org/x/"],
|
||||
"schedule": ["on the first day of the month"]
|
||||
}
|
||||
],
|
||||
"ignorePaths": [
|
||||
".github/workflows/generate-authors.yml",
|
||||
".github/workflows/lint.yaml",
|
||||
".github/workflows/renovate-go-mod-fix.yaml",
|
||||
".github/workflows/test.yaml",
|
||||
".github/workflows/tidy-check.yaml"
|
||||
"github>pion/renovate-config"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
57
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/AUTHORS.txt
generated
vendored
57
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/AUTHORS.txt
generated
vendored
|
|
@ -1,57 +0,0 @@
|
|||
# Thank you to everyone that made Pion possible. If you are interested in contributing
|
||||
# we would love to have you https://github.com/pion/webrtc/wiki/Contributing
|
||||
#
|
||||
# This file is auto generated, using git to list all individuals contributors.
|
||||
# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting
|
||||
Aleksandr Razumov <ar@gortc.io>
|
||||
alvarowolfx <alvarowolfx@gmail.com>
|
||||
Arlo Breault <arlolra@gmail.com>
|
||||
Atsushi Watanabe <atsushi.w@ieee.org>
|
||||
backkem <mail@backkem.me>
|
||||
bjdgyc <bjdgyc@163.com>
|
||||
boks1971 <raja.gobi@tutanota.com>
|
||||
Bragadeesh <bragboy@gmail.com>
|
||||
Carson Hoffman <c@rsonhoffman.com>
|
||||
Cecylia Bocovich <cohosh@torproject.org>
|
||||
Chris Hiszpanski <thinkski@users.noreply.github.com>
|
||||
cnderrauber <zengjie9004@gmail.com>
|
||||
Daniele Sluijters <daenney@users.noreply.github.com>
|
||||
folbrich <frank.olbricht@gmail.com>
|
||||
Hayden James <hayden.james@gmail.com>
|
||||
Hugo Arregui <hugo.arregui@gmail.com>
|
||||
Hugo Arregui <hugo@decentraland.org>
|
||||
igolaizola <11333576+igolaizola@users.noreply.github.com>
|
||||
Jeffrey Stoke <me@arhat.dev>
|
||||
Jeroen de Bruijn <vidavidorra+jdbruijn@gmail.com>
|
||||
Jeroen de Bruijn <vidavidorra@gmail.com>
|
||||
Jim Wert <jimwert@gmail.com>
|
||||
jinleileiking <jinleileiking@gmail.com>
|
||||
Jozef Kralik <jojo.lwin@gmail.com>
|
||||
Julien Salleyron <julien.salleyron@gmail.com>
|
||||
Juliusz Chroboczek <jch@irif.fr>
|
||||
Kegan Dougal <kegan@matrix.org>
|
||||
Kevin Wang <kevmo314@gmail.com>
|
||||
Lander Noterman <lander.noterman@basalte.be>
|
||||
Len <len@hpcnt.com>
|
||||
Lukas Lihotzki <lukas@lihotzki.de>
|
||||
ManuelBk <26275612+ManuelBk@users.noreply.github.com>
|
||||
Michael Zabka <zabka.michael@gmail.com>
|
||||
Michiel De Backker <mail@backkem.me>
|
||||
Rachel Chen <rachel@chens.email>
|
||||
Robert Eperjesi <eperjesi@uber.com>
|
||||
Ryan Gordon <ryan.gordon@getcruise.com>
|
||||
Sam Lancia <sam.lancia@motorolasolutions.com>
|
||||
Sean DuBois <duboisea@justin.tv>
|
||||
Sean DuBois <seaduboi@amazon.com>
|
||||
Sean DuBois <sean@siobud.com>
|
||||
Shelikhoo <xiaokangwang@outlook.com>
|
||||
Stefan Tatschner <stefan@rumpelsepp.org>
|
||||
Steffen Vogel <post@steffenvogel.de>
|
||||
Vadim <fffilimonov@yandex.ru>
|
||||
Vadim Filimonov <fffilimonov@yandex.ru>
|
||||
wmiao <wu.miao@viasat.com>
|
||||
ZHENK <chengzhenyang@gmail.com>
|
||||
吕海涛 <hi@taoshu.in>
|
||||
|
||||
# List of contributors not appearing in Git history
|
||||
|
||||
1032
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/conn.go
generated
vendored
1032
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/conn.go
generated
vendored
File diff suppressed because it is too large
Load Diff
157
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors.go
generated
vendored
157
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors.go
generated
vendored
|
|
@ -1,157 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package dtls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
)
|
||||
|
||||
// Typed errors
|
||||
var (
|
||||
ErrConnClosed = &FatalError{Err: errors.New("conn is closed")} //nolint:goerr113
|
||||
|
||||
errDeadlineExceeded = &TimeoutError{Err: fmt.Errorf("read/write timeout: %w", context.DeadlineExceeded)}
|
||||
errInvalidContentType = &TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113
|
||||
|
||||
errBufferTooSmall = &TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113
|
||||
errContextUnsupported = &TemporaryError{Err: errors.New("context is not supported for ExportKeyingMaterial")} //nolint:goerr113
|
||||
errHandshakeInProgress = &TemporaryError{Err: errors.New("handshake is in progress")} //nolint:goerr113
|
||||
errReservedExportKeyingMaterial = &TemporaryError{Err: errors.New("ExportKeyingMaterial can not be used with a reserved label")} //nolint:goerr113
|
||||
errApplicationDataEpochZero = &TemporaryError{Err: errors.New("ApplicationData with epoch of 0")} //nolint:goerr113
|
||||
errUnhandledContextType = &TemporaryError{Err: errors.New("unhandled contentType")} //nolint:goerr113
|
||||
|
||||
errCertificateVerifyNoCertificate = &FatalError{Err: errors.New("client sent certificate verify but we have no certificate to verify")} //nolint:goerr113
|
||||
errCipherSuiteNoIntersection = &FatalError{Err: errors.New("client+server do not support any shared cipher suites")} //nolint:goerr113
|
||||
errClientCertificateNotVerified = &FatalError{Err: errors.New("client sent certificate but did not verify it")} //nolint:goerr113
|
||||
errClientCertificateRequired = &FatalError{Err: errors.New("server required client verification, but got none")} //nolint:goerr113
|
||||
errClientNoMatchingSRTPProfile = &FatalError{Err: errors.New("server responded with SRTP Profile we do not support")} //nolint:goerr113
|
||||
errClientRequiredButNoServerEMS = &FatalError{Err: errors.New("client required Extended Master Secret extension, but server does not support it")} //nolint:goerr113
|
||||
errCookieMismatch = &FatalError{Err: errors.New("client+server cookie does not match")} //nolint:goerr113
|
||||
errIdentityNoPSK = &FatalError{Err: errors.New("PSK Identity Hint provided but PSK is nil")} //nolint:goerr113
|
||||
errInvalidCertificate = &FatalError{Err: errors.New("no certificate provided")} //nolint:goerr113
|
||||
errInvalidCipherSuite = &FatalError{Err: errors.New("invalid or unknown cipher suite")} //nolint:goerr113
|
||||
errInvalidECDSASignature = &FatalError{Err: errors.New("ECDSA signature contained zero or negative values")} //nolint:goerr113
|
||||
errInvalidPrivateKey = &FatalError{Err: errors.New("invalid private key type")} //nolint:goerr113
|
||||
errInvalidSignatureAlgorithm = &FatalError{Err: errors.New("invalid signature algorithm")} //nolint:goerr113
|
||||
errKeySignatureMismatch = &FatalError{Err: errors.New("expected and actual key signature do not match")} //nolint:goerr113
|
||||
errNilNextConn = &FatalError{Err: errors.New("Conn can not be created with a nil nextConn")} //nolint:goerr113
|
||||
errNoAvailableCipherSuites = &FatalError{Err: errors.New("connection can not be created, no CipherSuites satisfy this Config")} //nolint:goerr113
|
||||
errNoAvailablePSKCipherSuite = &FatalError{Err: errors.New("connection can not be created, pre-shared key present but no compatible CipherSuite")} //nolint:goerr113
|
||||
errNoAvailableCertificateCipherSuite = &FatalError{Err: errors.New("connection can not be created, certificate present but no compatible CipherSuite")} //nolint:goerr113
|
||||
errNoAvailableSignatureSchemes = &FatalError{Err: errors.New("connection can not be created, no SignatureScheme satisfy this Config")} //nolint:goerr113
|
||||
errNoCertificates = &FatalError{Err: errors.New("no certificates configured")} //nolint:goerr113
|
||||
errNoConfigProvided = &FatalError{Err: errors.New("no config provided")} //nolint:goerr113
|
||||
errNoSupportedEllipticCurves = &FatalError{Err: errors.New("client requested zero or more elliptic curves that are not supported by the server")} //nolint:goerr113
|
||||
errUnsupportedProtocolVersion = &FatalError{Err: errors.New("unsupported protocol version")} //nolint:goerr113
|
||||
errPSKAndIdentityMustBeSetForClient = &FatalError{Err: errors.New("PSK and PSK Identity Hint must both be set for client")} //nolint:goerr113
|
||||
errRequestedButNoSRTPExtension = &FatalError{Err: errors.New("SRTP support was requested but server did not respond with use_srtp extension")} //nolint:goerr113
|
||||
errServerNoMatchingSRTPProfile = &FatalError{Err: errors.New("client requested SRTP but we have no matching profiles")} //nolint:goerr113
|
||||
errServerRequiredButNoClientEMS = &FatalError{Err: errors.New("server requires the Extended Master Secret extension, but the client does not support it")} //nolint:goerr113
|
||||
errVerifyDataMismatch = &FatalError{Err: errors.New("expected and actual verify data does not match")} //nolint:goerr113
|
||||
errNotAcceptableCertificateChain = &FatalError{Err: errors.New("certificate chain is not signed by an acceptable CA")} //nolint:goerr113
|
||||
|
||||
errInvalidFlight = &InternalError{Err: errors.New("invalid flight number")} //nolint:goerr113
|
||||
errKeySignatureGenerateUnimplemented = &InternalError{Err: errors.New("unable to generate key signature, unimplemented")} //nolint:goerr113
|
||||
errKeySignatureVerifyUnimplemented = &InternalError{Err: errors.New("unable to verify key signature, unimplemented")} //nolint:goerr113
|
||||
errLengthMismatch = &InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113
|
||||
errSequenceNumberOverflow = &InternalError{Err: errors.New("sequence number overflow")} //nolint:goerr113
|
||||
errInvalidFSMTransition = &InternalError{Err: errors.New("invalid state machine transition")} //nolint:goerr113
|
||||
errFailedToAccessPoolReadBuffer = &InternalError{Err: errors.New("failed to access pool read buffer")} //nolint:goerr113
|
||||
errFragmentBufferOverflow = &InternalError{Err: errors.New("fragment buffer overflow")} //nolint:goerr113
|
||||
)
|
||||
|
||||
// FatalError indicates that the DTLS connection is no longer available.
|
||||
// It is mainly caused by wrong configuration of server or client.
|
||||
type FatalError = protocol.FatalError
|
||||
|
||||
// InternalError indicates and internal error caused by the implementation, and the DTLS connection is no longer available.
|
||||
// It is mainly caused by bugs or tried to use unimplemented features.
|
||||
type InternalError = protocol.InternalError
|
||||
|
||||
// TemporaryError indicates that the DTLS connection is still available, but the request was failed temporary.
|
||||
type TemporaryError = protocol.TemporaryError
|
||||
|
||||
// TimeoutError indicates that the request was timed out.
|
||||
type TimeoutError = protocol.TimeoutError
|
||||
|
||||
// HandshakeError indicates that the handshake failed.
|
||||
type HandshakeError = protocol.HandshakeError
|
||||
|
||||
// errInvalidCipherSuite indicates an attempt at using an unsupported cipher suite.
|
||||
type invalidCipherSuiteError struct {
|
||||
id CipherSuiteID
|
||||
}
|
||||
|
||||
func (e *invalidCipherSuiteError) Error() string {
|
||||
return fmt.Sprintf("CipherSuite with id(%d) is not valid", e.id)
|
||||
}
|
||||
|
||||
func (e *invalidCipherSuiteError) Is(err error) bool {
|
||||
var other *invalidCipherSuiteError
|
||||
if errors.As(err, &other) {
|
||||
return e.id == other.id
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// errAlert wraps DTLS alert notification as an error
|
||||
type alertError struct {
|
||||
*alert.Alert
|
||||
}
|
||||
|
||||
func (e *alertError) Error() string {
|
||||
return fmt.Sprintf("alert: %s", e.Alert.String())
|
||||
}
|
||||
|
||||
func (e *alertError) IsFatalOrCloseNotify() bool {
|
||||
return e.Level == alert.Fatal || e.Description == alert.CloseNotify
|
||||
}
|
||||
|
||||
func (e *alertError) Is(err error) bool {
|
||||
var other *alertError
|
||||
if errors.As(err, &other) {
|
||||
return e.Level == other.Level && e.Description == other.Description
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// netError translates an error from underlying Conn to corresponding net.Error.
|
||||
func netError(err error) error {
|
||||
switch {
|
||||
case errors.Is(err, io.EOF), errors.Is(err, context.Canceled), errors.Is(err, context.DeadlineExceeded):
|
||||
// Return io.EOF and context errors as is.
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
ne net.Error
|
||||
opError *net.OpError
|
||||
se *os.SyscallError
|
||||
)
|
||||
|
||||
if errors.As(err, &opError) {
|
||||
if errors.As(opError, &se) {
|
||||
if se.Timeout() {
|
||||
return &TimeoutError{Err: err}
|
||||
}
|
||||
if isOpErrorTemporary(se) {
|
||||
return &TemporaryError{Err: err}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if errors.As(err, &ne) {
|
||||
return err
|
||||
}
|
||||
|
||||
return &FatalError{Err: err}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ciphersuite
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
)
|
||||
|
||||
// NewTLSEcdheEcdsaWithAes128Ccm constructs a TLS_ECDHE_ECDSA_WITH_AES_128_CCM Cipher
|
||||
func NewTLSEcdheEcdsaWithAes128Ccm() *Aes128Ccm {
|
||||
return newAes128Ccm(clientcertificate.ECDSASign, TLS_ECDHE_ECDSA_WITH_AES_128_CCM, false, ciphersuite.CCMTagLength, KeyExchangeAlgorithmEcdhe, true)
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ciphersuite
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
)
|
||||
|
||||
// NewTLSEcdheEcdsaWithAes128Ccm8 creates a new TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuite
|
||||
func NewTLSEcdheEcdsaWithAes128Ccm8() *Aes128Ccm {
|
||||
return newAes128Ccm(clientcertificate.ECDSASign, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, false, ciphersuite.CCMTagLength8, KeyExchangeAlgorithmEcdhe, true)
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ciphersuite
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
)
|
||||
|
||||
// NewTLSPskWithAes128Ccm returns the TLS_PSK_WITH_AES_128_CCM CipherSuite
|
||||
func NewTLSPskWithAes128Ccm() *Aes128Ccm {
|
||||
return newAes128Ccm(clientcertificate.Type(0), TLS_PSK_WITH_AES_128_CCM, true, ciphersuite.CCMTagLength, KeyExchangeAlgorithmPsk, false)
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ciphersuite
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
)
|
||||
|
||||
// NewTLSPskWithAes128Ccm8 returns the TLS_PSK_WITH_AES_128_CCM_8 CipherSuite
|
||||
func NewTLSPskWithAes128Ccm8() *Aes128Ccm {
|
||||
return newAes128Ccm(clientcertificate.Type(0), TLS_PSK_WITH_AES_128_CCM_8, true, ciphersuite.CCMTagLength8, KeyExchangeAlgorithmPsk, false)
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ciphersuite
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
)
|
||||
|
||||
// NewTLSPskWithAes256Ccm8 returns the TLS_PSK_WITH_AES_256_CCM_8 CipherSuite
|
||||
func NewTLSPskWithAes256Ccm8() *Aes256Ccm {
|
||||
return newAes256Ccm(clientcertificate.Type(0), TLS_PSK_WITH_AES_256_CCM_8, true, ciphersuite.CCMTagLength8, KeyExchangeAlgorithmPsk, false)
|
||||
}
|
||||
177
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/cbc.go
generated
vendored
177
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/cbc.go
generated
vendored
|
|
@ -1,177 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ciphersuite
|
||||
|
||||
import ( //nolint:gci
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
|
||||
"github.com/pion/dtls/v2/internal/util"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
// block ciphers using cipher block chaining.
|
||||
type cbcMode interface {
|
||||
cipher.BlockMode
|
||||
SetIV([]byte)
|
||||
}
|
||||
|
||||
// CBC Provides an API to Encrypt/Decrypt DTLS 1.2 Packets
|
||||
type CBC struct {
|
||||
writeCBC, readCBC cbcMode
|
||||
writeMac, readMac []byte
|
||||
h prf.HashFunc
|
||||
}
|
||||
|
||||
// NewCBC creates a DTLS CBC Cipher
|
||||
func NewCBC(localKey, localWriteIV, localMac, remoteKey, remoteWriteIV, remoteMac []byte, h prf.HashFunc) (*CBC, error) {
|
||||
writeBlock, err := aes.NewCipher(localKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
readBlock, err := aes.NewCipher(remoteKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
writeCBC, ok := cipher.NewCBCEncrypter(writeBlock, localWriteIV).(cbcMode)
|
||||
if !ok {
|
||||
return nil, errFailedToCast
|
||||
}
|
||||
|
||||
readCBC, ok := cipher.NewCBCDecrypter(readBlock, remoteWriteIV).(cbcMode)
|
||||
if !ok {
|
||||
return nil, errFailedToCast
|
||||
}
|
||||
|
||||
return &CBC{
|
||||
writeCBC: writeCBC,
|
||||
writeMac: localMac,
|
||||
|
||||
readCBC: readCBC,
|
||||
readMac: remoteMac,
|
||||
h: h,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encrypt encrypt a DTLS RecordLayer message
|
||||
func (c *CBC) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) {
|
||||
payload := raw[recordlayer.HeaderSize:]
|
||||
raw = raw[:recordlayer.HeaderSize]
|
||||
blockSize := c.writeCBC.BlockSize()
|
||||
|
||||
// Generate + Append MAC
|
||||
h := pkt.Header
|
||||
|
||||
MAC, err := c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, payload, c.writeMac, c.h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payload = append(payload, MAC...)
|
||||
|
||||
// Generate + Append padding
|
||||
padding := make([]byte, blockSize-len(payload)%blockSize)
|
||||
paddingLen := len(padding)
|
||||
for i := 0; i < paddingLen; i++ {
|
||||
padding[i] = byte(paddingLen - 1)
|
||||
}
|
||||
payload = append(payload, padding...)
|
||||
|
||||
// Generate IV
|
||||
iv := make([]byte, blockSize)
|
||||
if _, err := rand.Read(iv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set IV + Encrypt + Prepend IV
|
||||
c.writeCBC.SetIV(iv)
|
||||
c.writeCBC.CryptBlocks(payload, payload)
|
||||
payload = append(iv, payload...)
|
||||
|
||||
// Prepend unencrypte header with encrypted payload
|
||||
raw = append(raw, payload...)
|
||||
|
||||
// Update recordLayer size to include IV+MAC+Padding
|
||||
binary.BigEndian.PutUint16(raw[recordlayer.HeaderSize-2:], uint16(len(raw)-recordlayer.HeaderSize))
|
||||
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts a DTLS RecordLayer message
|
||||
func (c *CBC) Decrypt(in []byte) ([]byte, error) {
|
||||
body := in[recordlayer.HeaderSize:]
|
||||
blockSize := c.readCBC.BlockSize()
|
||||
mac := c.h()
|
||||
|
||||
var h recordlayer.Header
|
||||
err := h.Unmarshal(in)
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
case h.ContentType == protocol.ContentTypeChangeCipherSpec:
|
||||
// Nothing to encrypt with ChangeCipherSpec
|
||||
return in, nil
|
||||
case len(body)%blockSize != 0 || len(body) < blockSize+util.Max(mac.Size()+1, blockSize):
|
||||
return nil, errNotEnoughRoomForNonce
|
||||
}
|
||||
|
||||
// Set + remove per record IV
|
||||
c.readCBC.SetIV(body[:blockSize])
|
||||
body = body[blockSize:]
|
||||
|
||||
// Decrypt
|
||||
c.readCBC.CryptBlocks(body, body)
|
||||
|
||||
// Padding+MAC needs to be checked in constant time
|
||||
// Otherwise we reveal information about the level of correctness
|
||||
paddingLen, paddingGood := examinePadding(body)
|
||||
if paddingGood != 255 {
|
||||
return nil, errInvalidMAC
|
||||
}
|
||||
|
||||
macSize := mac.Size()
|
||||
if len(body) < macSize {
|
||||
return nil, errInvalidMAC
|
||||
}
|
||||
|
||||
dataEnd := len(body) - macSize - paddingLen
|
||||
|
||||
expectedMAC := body[dataEnd : dataEnd+macSize]
|
||||
actualMAC, err := c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, body[:dataEnd], c.readMac, c.h)
|
||||
|
||||
// Compute Local MAC and compare
|
||||
if err != nil || !hmac.Equal(actualMAC, expectedMAC) {
|
||||
return nil, errInvalidMAC
|
||||
}
|
||||
|
||||
return append(in[:recordlayer.HeaderSize], body[:dataEnd]...), nil
|
||||
}
|
||||
|
||||
func (c *CBC) hmac(epoch uint16, sequenceNumber uint64, contentType protocol.ContentType, protocolVersion protocol.Version, payload []byte, key []byte, hf func() hash.Hash) ([]byte, error) {
|
||||
h := hmac.New(hf, key)
|
||||
|
||||
msg := make([]byte, 13)
|
||||
|
||||
binary.BigEndian.PutUint16(msg, epoch)
|
||||
util.PutBigEndianUint48(msg[2:], sequenceNumber)
|
||||
msg[8] = byte(contentType)
|
||||
msg[9] = protocolVersion.Major
|
||||
msg[10] = protocolVersion.Minor
|
||||
binary.BigEndian.PutUint16(msg[11:], uint16(len(payload)))
|
||||
|
||||
if _, err := h.Write(msg); err != nil {
|
||||
return nil, err
|
||||
} else if _, err := h.Write(payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/errors.go
generated
vendored
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/errors.go
generated
vendored
|
|
@ -1,20 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package extension
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrALPNInvalidFormat is raised when the ALPN format is invalid
|
||||
ErrALPNInvalidFormat = &protocol.FatalError{Err: errors.New("invalid alpn format")} //nolint:goerr113
|
||||
errALPNNoAppProto = &protocol.FatalError{Err: errors.New("no application protocol")} //nolint:goerr113
|
||||
errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113
|
||||
errInvalidExtensionType = &protocol.FatalError{Err: errors.New("invalid extension type")} //nolint:goerr113
|
||||
errInvalidSNIFormat = &protocol.FatalError{Err: errors.New("invalid server name format")} //nolint:goerr113
|
||||
errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113
|
||||
)
|
||||
28
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/errors.go
generated
vendored
28
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/errors.go
generated
vendored
|
|
@ -1,28 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package handshake
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
)
|
||||
|
||||
// Typed errors
|
||||
var (
|
||||
errUnableToMarshalFragmented = &protocol.InternalError{Err: errors.New("unable to marshal fragmented handshakes")} //nolint:goerr113
|
||||
errHandshakeMessageUnset = &protocol.InternalError{Err: errors.New("handshake message unset, unable to marshal")} //nolint:goerr113
|
||||
errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113
|
||||
errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113
|
||||
errInvalidClientKeyExchange = &protocol.FatalError{Err: errors.New("unable to determine if ClientKeyExchange is a public key or PSK Identity")} //nolint:goerr113
|
||||
errInvalidHashAlgorithm = &protocol.FatalError{Err: errors.New("invalid hash algorithm")} //nolint:goerr113
|
||||
errInvalidSignatureAlgorithm = &protocol.FatalError{Err: errors.New("invalid signature algorithm")} //nolint:goerr113
|
||||
errCookieTooLong = &protocol.FatalError{Err: errors.New("cookie must not be longer then 255 bytes")} //nolint:goerr113
|
||||
errInvalidEllipticCurveType = &protocol.FatalError{Err: errors.New("invalid or unknown elliptic curve type")} //nolint:goerr113
|
||||
errInvalidNamedCurve = &protocol.FatalError{Err: errors.New("invalid named curve")} //nolint:goerr113
|
||||
errCipherSuiteUnset = &protocol.FatalError{Err: errors.New("server hello can not be created without a cipher suite")} //nolint:goerr113
|
||||
errCompressionMethodUnset = &protocol.FatalError{Err: errors.New("server hello can not be created without a compression method")} //nolint:goerr113
|
||||
errInvalidCompressionMethod = &protocol.FatalError{Err: errors.New("invalid or unknown compression method")} //nolint:goerr113
|
||||
errNotImplemented = &protocol.InternalError{Err: errors.New("feature has not been implemented yet")} //nolint:goerr113
|
||||
)
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package recordlayer implements the TLS Record Layer https://tools.ietf.org/html/rfc5246#section-6
|
||||
package recordlayer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
)
|
||||
|
||||
var (
|
||||
errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113
|
||||
errInvalidPacketLength = &protocol.TemporaryError{Err: errors.New("packet length and declared length do not match")} //nolint:goerr113
|
||||
errSequenceNumberOverflow = &protocol.InternalError{Err: errors.New("sequence number overflow")} //nolint:goerr113
|
||||
errUnsupportedProtocolVersion = &protocol.FatalError{Err: errors.New("unsupported protocol version")} //nolint:goerr113
|
||||
errInvalidContentType = &protocol.TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113
|
||||
)
|
||||
138
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.golangci.yml
generated
vendored
Normal file
138
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.golangci.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
run:
|
||||
timeout: 5m
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
enable:
|
||||
- shadow
|
||||
misspell:
|
||||
locale: US
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
gomodguard:
|
||||
blocked:
|
||||
modules:
|
||||
- github.com/pkg/errors:
|
||||
recommendations:
|
||||
- errors
|
||||
forbidigo:
|
||||
forbid:
|
||||
- ^fmt.Print(f|ln)?$
|
||||
- ^log.(Panic|Fatal|Print)(f|ln)?$
|
||||
- ^os.Exit$
|
||||
- ^panic$
|
||||
- ^print(ln)?$
|
||||
varnamelen:
|
||||
max-distance: 12
|
||||
min-name-length: 2
|
||||
ignore-type-assert-ok: true
|
||||
ignore-map-index-ok: true
|
||||
ignore-chan-recv-ok: true
|
||||
ignore-decls:
|
||||
- i int
|
||||
- n int
|
||||
- w io.Writer
|
||||
- r io.Reader
|
||||
- b []byte
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers
|
||||
- bidichk # Checks for dangerous unicode character sequences
|
||||
- bodyclose # checks whether HTTP response body is closed successfully
|
||||
- containedctx # containedctx is a linter that detects struct contained context.Context field
|
||||
- contextcheck # check the function whether use a non-inherited context
|
||||
- cyclop # checks function and package cyclomatic complexity
|
||||
- decorder # check declaration order and count of types, constants, variables and functions
|
||||
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
|
||||
- dupl # Tool for code clone detection
|
||||
- durationcheck # check for two durations multiplied together
|
||||
- err113 # Golang linter to check the errors handling expressions
|
||||
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
|
||||
- errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted.
|
||||
- errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`.
|
||||
- errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13.
|
||||
- exhaustive # check exhaustiveness of enum switch statements
|
||||
- exportloopref # checks for pointers to enclosing loop variables
|
||||
- forbidigo # Forbids identifiers
|
||||
- forcetypeassert # finds forced type assertions
|
||||
- gci # Gci control golang package import order and make it always deterministic.
|
||||
- gochecknoglobals # Checks that no globals are present in Go code
|
||||
- gocognit # Computes and checks the cognitive complexity of functions
|
||||
- goconst # Finds repeated strings that could be replaced by a constant
|
||||
- gocritic # The most opinionated Go source code linter
|
||||
- gocyclo # Computes and checks the cyclomatic complexity of functions
|
||||
- godot # Check if comments end in a period
|
||||
- godox # Tool for detection of FIXME, TODO and other comment keywords
|
||||
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
|
||||
- gofumpt # Gofumpt checks whether code was gofumpt-ed.
|
||||
- goheader # Checks is file header matches to pattern
|
||||
- goimports # Goimports does everything that gofmt does. Additionally it checks unused imports
|
||||
- gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod.
|
||||
- goprintffuncname # Checks that printf-like functions are named with `f` at the end
|
||||
- gosec # Inspects source code for security problems
|
||||
- gosimple # Linter for Go source code that specializes in simplifying a code
|
||||
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
|
||||
- grouper # An analyzer to analyze expression groups.
|
||||
- importas # Enforces consistent import aliases
|
||||
- ineffassign # Detects when assignments to existing variables are not used
|
||||
- lll # Reports long lines
|
||||
- maintidx # maintidx measures the maintainability index of each function.
|
||||
- makezero # Finds slice declarations with non-zero initial length
|
||||
- misspell # Finds commonly misspelled English words in comments
|
||||
- nakedret # Finds naked returns in functions greater than a specified function length
|
||||
- nestif # Reports deeply nested if statements
|
||||
- nilerr # Finds the code that returns nil even if it checks that the error is not nil.
|
||||
- nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value.
|
||||
- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity
|
||||
- noctx # noctx finds sending http request without context.Context
|
||||
- predeclared # find code that shadows one of Go's predeclared identifiers
|
||||
- revive # golint replacement, finds style mistakes
|
||||
- staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks
|
||||
- stylecheck # Stylecheck is a replacement for golint
|
||||
- tagliatelle # Checks the struct tags.
|
||||
- tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17
|
||||
- thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers
|
||||
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code
|
||||
- unconvert # Remove unnecessary type conversions
|
||||
- unparam # Reports unused function parameters
|
||||
- unused # Checks Go code for unused constants, variables, functions and types
|
||||
- varnamelen # checks that the length of a variable's name matches its scope
|
||||
- wastedassign # wastedassign finds wasted assignment statements
|
||||
- whitespace # Tool for detection of leading and trailing whitespace
|
||||
disable:
|
||||
- depguard # Go linter that checks if package imports are in a list of acceptable packages
|
||||
- funlen # Tool for detection of long functions
|
||||
- gochecknoinits # Checks that no init functions are present in Go code
|
||||
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations.
|
||||
- interfacebloat # A linter that checks length of interface.
|
||||
- ireturn # Accept Interfaces, Return Concrete Types
|
||||
- mnd # An analyzer to detect magic numbers
|
||||
- nolintlint # Reports ill-formed or insufficient nolint directives
|
||||
- paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test
|
||||
- prealloc # Finds slice declarations that could potentially be preallocated
|
||||
- promlinter # Check Prometheus metrics naming via promlint
|
||||
- rowserrcheck # checks whether Err of rows is checked successfully
|
||||
- sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed.
|
||||
- testpackage # linter that makes you use a separate _test package
|
||||
- tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes
|
||||
- wrapcheck # Checks that errors returned from external packages are wrapped
|
||||
- wsl # Whitespace Linter - Forces you to use empty lines!
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
exclude-dirs-use-default: false
|
||||
exclude-rules:
|
||||
# Allow complex tests and examples, better to be self contained
|
||||
- path: (examples|main\.go|_test\.go)
|
||||
linters:
|
||||
- forbidigo
|
||||
- gocognit
|
||||
|
||||
# Allow forbidden identifiers in CLI commands
|
||||
- path: cmd
|
||||
linters:
|
||||
- forbidigo
|
||||
|
|
@ -10,9 +10,9 @@
|
|||
<a href="https://pion.ly/slack"><img src="https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen" alt="Slack Widget"></a>
|
||||
<br>
|
||||
<img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/pion/dtls/test.yaml">
|
||||
<a href="https://pkg.go.dev/github.com/pion/dtls/v2"><img src="https://pkg.go.dev/badge/github.com/pion/dtls/v2.svg" alt="Go Reference"></a>
|
||||
<a href="https://pkg.go.dev/github.com/pion/dtls/v3"><img src="https://pkg.go.dev/badge/github.com/pion/dtls/v3.svg" alt="Go Reference"></a>
|
||||
<a href="https://codecov.io/gh/pion/dtls"><img src="https://codecov.io/gh/pion/dtls/branch/master/graph/badge.svg" alt="Coverage Status"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/pion/dtls/v2"><img src="https://goreportcard.com/badge/github.com/pion/dtls/v2" alt="Go Report Card"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/pion/dtls/v3"><img src="https://goreportcard.com/badge/github.com/pion/dtls/v3" alt="Go Report Card"></a>
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
||||
</p>
|
||||
<br>
|
||||
|
|
@ -145,7 +145,7 @@ We are always looking to support **your projects**. Please reach out if you have
|
|||
If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly)
|
||||
|
||||
### Contributing
|
||||
Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt)
|
||||
Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible
|
||||
|
||||
### License
|
||||
MIT License - see [LICENSE](LICENSE) for full text
|
||||
|
|
@ -9,6 +9,8 @@ import (
|
|||
"crypto/x509"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
)
|
||||
|
||||
// ClientHelloInfo contains information from a ClientHello message in order to
|
||||
|
|
@ -22,6 +24,9 @@ type ClientHelloInfo struct {
|
|||
// CipherSuites lists the CipherSuites supported by the client (e.g.
|
||||
// TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256).
|
||||
CipherSuites []CipherSuiteID
|
||||
|
||||
// RandomBytes stores the client hello random bytes
|
||||
RandomBytes [handshake.RandomBytesLength]byte
|
||||
}
|
||||
|
||||
// CertificateRequestInfo contains information from a server's
|
||||
|
|
@ -38,7 +43,8 @@ type CertificateRequestInfo struct {
|
|||
// SupportsCertificate returns nil if the provided certificate is supported by
|
||||
// the server that sent the CertificateRequest. Otherwise, it returns an error
|
||||
// describing the reason for the incompatibility.
|
||||
// NOTE: original src: https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/common.go#L1273
|
||||
// NOTE: original src:
|
||||
// https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/common.go#L1273
|
||||
func (cri *CertificateRequestInfo) SupportsCertificate(c *tls.Certificate) error {
|
||||
if len(cri.AcceptableCAs) == 0 {
|
||||
return nil
|
||||
|
|
@ -61,6 +67,7 @@ func (cri *CertificateRequestInfo) SupportsCertificate(c *tls.Certificate) error
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errNotAcceptableCertificateChain
|
||||
}
|
||||
|
||||
|
|
@ -86,6 +93,7 @@ func (c *handshakeConfig) setNameToCertificateLocked() {
|
|||
c.nameToCertificate = nameToCertificate
|
||||
}
|
||||
|
||||
//nolint:cyclop
|
||||
func (c *handshakeConfig) getCertificate(clientHelloInfo *ClientHelloInfo) (*tls.Certificate, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
|
@ -136,7 +144,8 @@ func (c *handshakeConfig) getCertificate(clientHelloInfo *ClientHelloInfo) (*tls
|
|||
return &c.localCertificates[0], nil
|
||||
}
|
||||
|
||||
// NOTE: original src: https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/handshake_client.go#L974
|
||||
// NOTE: original src:
|
||||
// https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/handshake_client.go#L974
|
||||
func (c *handshakeConfig) getClientCertificate(cri *CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
|
@ -149,6 +158,7 @@ func (c *handshakeConfig) getClientCertificate(cri *CertificateRequestInfo) (*tl
|
|||
if err := cri.SupportsCertificate(&chain); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
return &chain, nil
|
||||
}
|
||||
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
package dtls
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/rsa"
|
||||
|
|
@ -11,54 +12,68 @@ import (
|
|||
"fmt"
|
||||
"hash"
|
||||
|
||||
"github.com/pion/dtls/v2/internal/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/internal/ciphersuite"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
// CipherSuiteID is an ID for our supported CipherSuites
|
||||
// CipherSuiteID is an ID for our supported CipherSuites.
|
||||
type CipherSuiteID = ciphersuite.ID
|
||||
|
||||
// Supported Cipher Suites
|
||||
// Supported Cipher Suites.
|
||||
const (
|
||||
// AES-128-CCM
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM //nolint:revive,stylecheck
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 //nolint:revive,stylecheck
|
||||
//nolint:revive,stylecheck
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM
|
||||
//nolint:revive,stylecheck
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
|
||||
|
||||
// AES-128-GCM-SHA256
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 //nolint:revive,stylecheck
|
||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 //nolint:revive,stylecheck
|
||||
//nolint:revive,stylecheck
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
|
||||
//nolint:revive,stylecheck
|
||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 //nolint:revive,stylecheck
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 //nolint:revive,stylecheck
|
||||
//nolint:revive,stylecheck
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
|
||||
//nolint:revive,stylecheck
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||
|
||||
// AES-256-CBC-SHA
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA //nolint:revive,stylecheck
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA //nolint:revive,stylecheck
|
||||
//nolint:revive,stylecheck
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
|
||||
//nolint:revive,stylecheck
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
TLS_PSK_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM //nolint:revive,stylecheck
|
||||
TLS_PSK_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM_8 //nolint:revive,stylecheck
|
||||
TLS_PSK_WITH_AES_256_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_256_CCM_8 //nolint:revive,stylecheck
|
||||
TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_GCM_SHA256 //nolint:revive,stylecheck
|
||||
TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CBC_SHA256 //nolint:revive,stylecheck
|
||||
//nolint:revive,stylecheck
|
||||
TLS_PSK_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM
|
||||
//nolint:revive,stylecheck
|
||||
TLS_PSK_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM_8
|
||||
//nolint:revive,stylecheck
|
||||
TLS_PSK_WITH_AES_256_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_256_CCM_8
|
||||
//nolint:revive,stylecheck
|
||||
TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_GCM_SHA256
|
||||
//nolint:revive,stylecheck
|
||||
TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CBC_SHA256
|
||||
|
||||
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 //nolint:revive,stylecheck
|
||||
//nolint:revive,stylecheck
|
||||
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
|
||||
)
|
||||
|
||||
// CipherSuiteAuthenticationType controls what authentication method is using during the handshake for a CipherSuite
|
||||
// CipherSuiteAuthenticationType controls what authentication method is using during the handshake for a CipherSuite.
|
||||
type CipherSuiteAuthenticationType = ciphersuite.AuthenticationType
|
||||
|
||||
// AuthenticationType Enums
|
||||
// AuthenticationType Enums.
|
||||
const (
|
||||
CipherSuiteAuthenticationTypeCertificate CipherSuiteAuthenticationType = ciphersuite.AuthenticationTypeCertificate
|
||||
CipherSuiteAuthenticationTypePreSharedKey CipherSuiteAuthenticationType = ciphersuite.AuthenticationTypePreSharedKey
|
||||
CipherSuiteAuthenticationTypeAnonymous CipherSuiteAuthenticationType = ciphersuite.AuthenticationTypeAnonymous
|
||||
)
|
||||
|
||||
// CipherSuiteKeyExchangeAlgorithm controls what exchange algorithm is using during the handshake for a CipherSuite
|
||||
// CipherSuiteKeyExchangeAlgorithm controls what exchange algorithm is using during the handshake for a CipherSuite.
|
||||
type CipherSuiteKeyExchangeAlgorithm = ciphersuite.KeyExchangeAlgorithm
|
||||
|
||||
// CipherSuiteKeyExchangeAlgorithm Bitmask
|
||||
// CipherSuiteKeyExchangeAlgorithm Bitmask.
|
||||
const (
|
||||
CipherSuiteKeyExchangeAlgorithmNone CipherSuiteKeyExchangeAlgorithm = ciphersuite.KeyExchangeAlgorithmNone
|
||||
CipherSuiteKeyExchangeAlgorithmPsk CipherSuiteKeyExchangeAlgorithm = ciphersuite.KeyExchangeAlgorithmPsk
|
||||
|
|
@ -67,7 +82,7 @@ const (
|
|||
|
||||
var _ = allCipherSuites() // Necessary until this function isn't only used by Go 1.14
|
||||
|
||||
// CipherSuite is an interface that all DTLS CipherSuites must satisfy
|
||||
// CipherSuite is an interface that all DTLS CipherSuites must satisfy.
|
||||
type CipherSuite interface {
|
||||
// String of CipherSuite, only used for logging
|
||||
String() string
|
||||
|
|
@ -95,7 +110,7 @@ type CipherSuite interface {
|
|||
Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error
|
||||
IsInitialized() bool
|
||||
Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error)
|
||||
Decrypt(in []byte) ([]byte, error)
|
||||
Decrypt(h recordlayer.Header, in []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// CipherSuiteName provides the same functionality as tls.CipherSuiteName
|
||||
|
|
@ -108,13 +123,14 @@ func CipherSuiteName(id CipherSuiteID) string {
|
|||
if suite != nil {
|
||||
return suite.String()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("0x%04X", uint16(id))
|
||||
}
|
||||
|
||||
// Taken from https://www.iana.org/assignments/tls-parameters/tls-parameters.xml
|
||||
// A cipherSuite is a specific combination of key agreement, cipher and MAC
|
||||
// function.
|
||||
func cipherSuiteForID(id CipherSuiteID, customCiphers func() []CipherSuite) CipherSuite {
|
||||
func cipherSuiteForID(id CipherSuiteID, customCiphers func() []CipherSuite) CipherSuite { //nolint:cyclop
|
||||
switch id { //nolint:exhaustive
|
||||
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
|
||||
return ciphersuite.NewTLSEcdheEcdsaWithAes128Ccm()
|
||||
|
|
@ -157,7 +173,7 @@ func cipherSuiteForID(id CipherSuiteID, customCiphers func() []CipherSuite) Ciph
|
|||
return nil
|
||||
}
|
||||
|
||||
// CipherSuites we support in order of preference
|
||||
// CipherSuites we support in order of preference.
|
||||
func defaultCipherSuites() []CipherSuite {
|
||||
return []CipherSuite{
|
||||
&ciphersuite.TLSEcdheEcdsaWithAes128GcmSha256{},
|
||||
|
|
@ -191,10 +207,16 @@ func cipherSuiteIDs(cipherSuites []CipherSuite) []uint16 {
|
|||
for _, c := range cipherSuites {
|
||||
rtrn = append(rtrn, uint16(c.ID()))
|
||||
}
|
||||
|
||||
return rtrn
|
||||
}
|
||||
|
||||
func parseCipherSuites(userSelectedSuites []CipherSuiteID, customCipherSuites func() []CipherSuite, includeCertificateSuites, includePSKSuites bool) ([]CipherSuite, error) {
|
||||
//nolint:cyclop
|
||||
func parseCipherSuites(
|
||||
userSelectedSuites []CipherSuiteID,
|
||||
customCipherSuites func() []CipherSuite,
|
||||
includeCertificateSuites, includePSKSuites bool,
|
||||
) ([]CipherSuite, error) {
|
||||
cipherSuitesForIDs := func(ids []CipherSuiteID) ([]CipherSuite, error) {
|
||||
cipherSuites := []CipherSuite{}
|
||||
for _, id := range ids {
|
||||
|
|
@ -204,6 +226,7 @@ func parseCipherSuites(userSelectedSuites []CipherSuiteID, customCipherSuites fu
|
|||
}
|
||||
cipherSuites = append(cipherSuites, c)
|
||||
}
|
||||
|
||||
return cipherSuites, nil
|
||||
}
|
||||
|
||||
|
|
@ -258,11 +281,16 @@ func filterCipherSuitesForCertificate(cert *tls.Certificate, cipherSuites []Ciph
|
|||
if cert == nil || cert.PrivateKey == nil {
|
||||
return cipherSuites
|
||||
}
|
||||
signer, ok := cert.PrivateKey.(crypto.Signer)
|
||||
if !ok {
|
||||
return cipherSuites
|
||||
}
|
||||
|
||||
var certType clientcertificate.Type
|
||||
switch cert.PrivateKey.(type) {
|
||||
case ed25519.PrivateKey, *ecdsa.PrivateKey:
|
||||
switch signer.Public().(type) {
|
||||
case ed25519.PublicKey, *ecdsa.PublicKey:
|
||||
certType = clientcertificate.ECDSASign
|
||||
case *rsa.PrivateKey:
|
||||
case *rsa.PublicKey:
|
||||
certType = clientcertificate.RSASign
|
||||
}
|
||||
|
||||
|
|
@ -272,5 +300,6 @@ func filterCipherSuitesForCertificate(cert *tls.Certificate, cipherSuites []Ciph
|
|||
filtered = append(filtered, c)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
|
@ -11,10 +11,10 @@ import (
|
|||
)
|
||||
|
||||
// VersionDTLS12 is the DTLS version in the same style as
|
||||
// VersionTLSXX from crypto/tls
|
||||
// VersionTLSXX from crypto/tls.
|
||||
const VersionDTLS12 = 0xfefd
|
||||
|
||||
// Convert from our cipherSuite interface to a tls.CipherSuite struct
|
||||
// Convert from our cipherSuite interface to a tls.CipherSuite struct.
|
||||
func toTLSCipherSuite(c CipherSuite) *tls.CipherSuite {
|
||||
return &tls.CipherSuite{
|
||||
ID: uint16(c.ID()),
|
||||
|
|
@ -33,6 +33,7 @@ func CipherSuites() []*tls.CipherSuite {
|
|||
for i, c := range suites {
|
||||
res[i] = toTLSCipherSuite(c)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
|
|
@ -40,5 +41,6 @@ func CipherSuites() []*tls.CipherSuite {
|
|||
// this package and which have security issues.
|
||||
func InsecureCipherSuites() []*tls.CipherSuite {
|
||||
var res []*tls.CipherSuite
|
||||
|
||||
return res
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
package dtls
|
||||
|
||||
import "github.com/pion/dtls/v2/pkg/protocol"
|
||||
import "github.com/pion/dtls/v3/pkg/protocol"
|
||||
|
||||
func defaultCompressionMethods() []*protocol.CompressionMethod {
|
||||
return []*protocol.CompressionMethod{
|
||||
|
|
@ -4,16 +4,18 @@
|
|||
package dtls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/logging"
|
||||
)
|
||||
|
||||
|
|
@ -44,6 +46,10 @@ type Config struct {
|
|||
// Servers will assert that clients send one of these profiles and will respond as needed
|
||||
SRTPProtectionProfiles []SRTPProtectionProfile
|
||||
|
||||
// SRTPMasterKeyIdentifier value (if any) is sent via the use_srtp
|
||||
// extension for Clients and Servers
|
||||
SRTPMasterKeyIdentifier []byte
|
||||
|
||||
// ClientAuth determines the server's policy for
|
||||
// TLS Client Authentication. The default is NoClientCert.
|
||||
ClientAuth ClientAuthType
|
||||
|
|
@ -56,6 +62,10 @@ type Config struct {
|
|||
// defaults to time.Second
|
||||
FlightInterval time.Duration
|
||||
|
||||
// DisableRetransmitBackoff can be used to the disable the backoff feature
|
||||
// when sending outbound messages as specified in RFC 4347 4.2.4.1
|
||||
DisableRetransmitBackoff bool
|
||||
|
||||
// PSK sets the pre-shared key used by this DTLS connection
|
||||
// If PSK is non-nil only PSK CipherSuites will be used
|
||||
PSK PSKCallback
|
||||
|
|
@ -112,15 +122,6 @@ type Config struct {
|
|||
|
||||
LoggerFactory logging.LoggerFactory
|
||||
|
||||
// ConnectContextMaker is a function to make a context used in Dial(),
|
||||
// Client(), Server(), and Accept(). If nil, the default ConnectContextMaker
|
||||
// is used. It can be implemented as following.
|
||||
//
|
||||
// func ConnectContextMaker() (context.Context, func()) {
|
||||
// return context.WithTimeout(context.Background(), 30*time.Second)
|
||||
// }
|
||||
ConnectContextMaker func() (context.Context, func())
|
||||
|
||||
// MTU is the length at which handshake messages will be fragmented to
|
||||
// fit within the maximum transmission unit (default is 1200 bytes)
|
||||
MTU int
|
||||
|
|
@ -176,17 +177,53 @@ type Config struct {
|
|||
// skip hello verify phase and receive ServerHello after initial ClientHello.
|
||||
// This have implication on DoS attack resistance.
|
||||
InsecureSkipVerifyHello bool
|
||||
}
|
||||
|
||||
func defaultConnectContextMaker() (context.Context, func()) {
|
||||
return context.WithTimeout(context.Background(), 30*time.Second)
|
||||
}
|
||||
// ConnectionIDGenerator generates connection identifiers that should be
|
||||
// sent by the remote party if it supports the DTLS Connection Identifier
|
||||
// extension, as determined during the handshake. Generated connection
|
||||
// identifiers must always have the same length. Returning a zero-length
|
||||
// connection identifier indicates that the local party supports sending
|
||||
// connection identifiers but does not require the remote party to send
|
||||
// them. A nil ConnectionIDGenerator indicates that connection identifiers
|
||||
// are not supported.
|
||||
// https://datatracker.ietf.org/doc/html/rfc9146
|
||||
ConnectionIDGenerator func() []byte
|
||||
|
||||
func (c *Config) connectContextMaker() (context.Context, func()) {
|
||||
if c.ConnectContextMaker == nil {
|
||||
return defaultConnectContextMaker()
|
||||
}
|
||||
return c.ConnectContextMaker()
|
||||
// PaddingLengthGenerator generates the number of padding bytes used to
|
||||
// inflate ciphertext size in order to obscure content size from observers.
|
||||
// The length of the content is passed to the generator such that both
|
||||
// deterministic and random padding schemes can be applied while not
|
||||
// exceeding maximum record size.
|
||||
// If no PaddingLengthGenerator is specified, padding will not be applied.
|
||||
// https://datatracker.ietf.org/doc/html/rfc9146#section-4
|
||||
PaddingLengthGenerator func(uint) uint
|
||||
|
||||
// HelloRandomBytesGenerator generates custom client hello random bytes.
|
||||
HelloRandomBytesGenerator func() [handshake.RandomBytesLength]byte
|
||||
|
||||
// Handshake hooks: hooks can be used for testing invalid messages,
|
||||
// mimicking other implementations or randomizing fields, which is valuable
|
||||
// for applications that need censorship-resistance by making
|
||||
// fingerprinting more difficult.
|
||||
|
||||
// ClientHelloMessageHook, if not nil, is called when a Client Hello message is sent
|
||||
// from a client. The returned handshake message replaces the original message.
|
||||
ClientHelloMessageHook func(handshake.MessageClientHello) handshake.Message
|
||||
|
||||
// ServerHelloMessageHook, if not nil, is called when a Server Hello message is sent
|
||||
// from a server. The returned handshake message replaces the original message.
|
||||
ServerHelloMessageHook func(handshake.MessageServerHello) handshake.Message
|
||||
|
||||
// CertificateRequestMessageHook, if not nil, is called when a Certificate Request
|
||||
// message is sent from a server. The returned handshake message replaces the original message.
|
||||
CertificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message
|
||||
|
||||
// OnConnectionAttempt is fired Whenever a connection attempt is made,
|
||||
// the server or application can call this callback function.
|
||||
// The callback function can then implement logic to handle the connection attempt, such as logging the attempt,
|
||||
// checking against a list of blocked IPs, or counting the attempts to prevent brute force attacks.
|
||||
// If the callback function returns an error, the connection attempt will be aborted.
|
||||
OnConnectionAttempt func(net.Addr) error
|
||||
}
|
||||
|
||||
func (c *Config) includeCertificateSuites() bool {
|
||||
|
|
@ -198,14 +235,14 @@ const defaultMTU = 1200 // bytes
|
|||
var defaultCurves = []elliptic.Curve{elliptic.X25519, elliptic.P256, elliptic.P384} //nolint:gochecknoglobals
|
||||
|
||||
// PSKCallback is called once we have the remote's PSKIdentityHint.
|
||||
// If the remote provided none it will be nil
|
||||
// If the remote provided none it will be nil.
|
||||
type PSKCallback func([]byte) ([]byte, error)
|
||||
|
||||
// ClientAuthType declares the policy the server will follow for
|
||||
// TLS Client Authentication.
|
||||
type ClientAuthType int
|
||||
|
||||
// ClientAuthType enums
|
||||
// ClientAuthType enums.
|
||||
const (
|
||||
NoClientCert ClientAuthType = iota
|
||||
RequestClientCert
|
||||
|
|
@ -215,17 +252,17 @@ const (
|
|||
)
|
||||
|
||||
// ExtendedMasterSecretType declares the policy the client and server
|
||||
// will follow for the Extended Master Secret extension
|
||||
// will follow for the Extended Master Secret extension.
|
||||
type ExtendedMasterSecretType int
|
||||
|
||||
// ExtendedMasterSecretType enums
|
||||
// ExtendedMasterSecretType enums.
|
||||
const (
|
||||
RequestExtendedMasterSecret ExtendedMasterSecretType = iota
|
||||
RequireExtendedMasterSecret
|
||||
DisableExtendedMasterSecret
|
||||
)
|
||||
|
||||
func validateConfig(config *Config) error {
|
||||
func validateConfig(config *Config) error { //nolint:cyclop
|
||||
switch {
|
||||
case config == nil:
|
||||
return errNoConfigProvided
|
||||
|
|
@ -238,16 +275,23 @@ func validateConfig(config *Config) error {
|
|||
return errInvalidCertificate
|
||||
}
|
||||
if cert.PrivateKey != nil {
|
||||
switch cert.PrivateKey.(type) {
|
||||
case ed25519.PrivateKey:
|
||||
case *ecdsa.PrivateKey:
|
||||
case *rsa.PrivateKey:
|
||||
signer, ok := cert.PrivateKey.(crypto.Signer)
|
||||
if !ok {
|
||||
return errInvalidPrivateKey
|
||||
}
|
||||
switch signer.Public().(type) {
|
||||
case ed25519.PublicKey:
|
||||
case *ecdsa.PublicKey:
|
||||
case *rsa.PublicKey:
|
||||
default:
|
||||
return errInvalidPrivateKey
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil)
|
||||
_, err := parseCipherSuites(
|
||||
config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil,
|
||||
)
|
||||
|
||||
return err
|
||||
}
|
||||
1330
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/conn.go
generated
vendored
Normal file
1330
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/conn.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
105
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/connection_id.go
generated
vendored
Normal file
105
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/connection_id.go
generated
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package dtls
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
// RandomCIDGenerator is a random Connection ID generator where CID is the
|
||||
// specified size. Specifying a size of 0 will indicate to peers that sending a
|
||||
// Connection ID is not necessary.
|
||||
func RandomCIDGenerator(size int) func() []byte {
|
||||
return func() []byte {
|
||||
cid := make([]byte, size)
|
||||
if _, err := rand.Read(cid); err != nil {
|
||||
panic(err) //nolint -- nonrecoverable
|
||||
}
|
||||
|
||||
return cid
|
||||
}
|
||||
}
|
||||
|
||||
// OnlySendCIDGenerator enables sending Connection IDs negotiated with a peer,
|
||||
// but indicates to the peer that sending Connection IDs in return is not
|
||||
// necessary.
|
||||
func OnlySendCIDGenerator() func() []byte {
|
||||
return func() []byte {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// cidDatagramRouter extracts connection IDs from incoming datagram payloads and
|
||||
// uses them to route to the proper connection.
|
||||
// NOTE: properly routing datagrams based on connection IDs requires using
|
||||
// constant size connection IDs.
|
||||
func cidDatagramRouter(size int) func([]byte) (string, bool) {
|
||||
return func(packet []byte) (string, bool) {
|
||||
pkts, err := recordlayer.ContentAwareUnpackDatagram(packet, size)
|
||||
if err != nil || len(pkts) < 1 {
|
||||
return "", false
|
||||
}
|
||||
for _, pkt := range pkts {
|
||||
h := &recordlayer.Header{
|
||||
ConnectionID: make([]byte, size),
|
||||
}
|
||||
if err := h.Unmarshal(pkt); err != nil {
|
||||
continue
|
||||
}
|
||||
if h.ContentType != protocol.ContentTypeConnectionID {
|
||||
continue
|
||||
}
|
||||
|
||||
return string(h.ConnectionID), true
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
|
||||
// cidConnIdentifier extracts connection IDs from outgoing ServerHello records
|
||||
// and associates them with the associated connection.
|
||||
// NOTE: a ServerHello should always be the first record in a datagram if
|
||||
// multiple are present, so we avoid iterating through all packets if the first
|
||||
// is not a ServerHello.
|
||||
func cidConnIdentifier() func([]byte) (string, bool) { //nolint:cyclop
|
||||
return func(packet []byte) (string, bool) {
|
||||
pkts, err := recordlayer.UnpackDatagram(packet)
|
||||
if err != nil || len(pkts) < 1 {
|
||||
return "", false
|
||||
}
|
||||
var h recordlayer.Header
|
||||
if hErr := h.Unmarshal(pkts[0]); hErr != nil {
|
||||
return "", false
|
||||
}
|
||||
if h.ContentType != protocol.ContentTypeHandshake {
|
||||
return "", false
|
||||
}
|
||||
var hh handshake.Header
|
||||
var sh handshake.MessageServerHello
|
||||
for _, pkt := range pkts {
|
||||
if hhErr := hh.Unmarshal(pkt[recordlayer.FixedHeaderSize:]); hhErr != nil {
|
||||
continue
|
||||
}
|
||||
if err = sh.Unmarshal(pkt[recordlayer.FixedHeaderSize+handshake.HeaderLength:]); err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
for _, ext := range sh.Extensions {
|
||||
if e, ok := ext.(*extension.ConnectionID); ok {
|
||||
return string(e.CID), true
|
||||
}
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
|
|
@ -9,15 +9,14 @@ import (
|
|||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/binary"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/hash"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/hash"
|
||||
)
|
||||
|
||||
type ecdsaSignature struct {
|
||||
|
|
@ -44,24 +43,36 @@ func valueKeyMessage(clientRandom, serverRandom, publicKey []byte, namedCurve el
|
|||
// hash/signature algorithm pair that appears in that extension
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc5246#section-7.4.2
|
||||
func generateKeySignature(clientRandom, serverRandom, publicKey []byte, namedCurve elliptic.Curve, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) {
|
||||
func generateKeySignature(
|
||||
clientRandom, serverRandom, publicKey []byte,
|
||||
namedCurve elliptic.Curve,
|
||||
signer crypto.Signer,
|
||||
hashAlgorithm hash.Algorithm,
|
||||
) ([]byte, error) {
|
||||
msg := valueKeyMessage(clientRandom, serverRandom, publicKey, namedCurve)
|
||||
switch p := privateKey.(type) {
|
||||
case ed25519.PrivateKey:
|
||||
switch signer.Public().(type) {
|
||||
case ed25519.PublicKey:
|
||||
// https://crypto.stackexchange.com/a/55483
|
||||
return p.Sign(rand.Reader, msg, crypto.Hash(0))
|
||||
case *ecdsa.PrivateKey:
|
||||
return signer.Sign(rand.Reader, msg, crypto.Hash(0))
|
||||
case *ecdsa.PublicKey:
|
||||
hashed := hashAlgorithm.Digest(msg)
|
||||
return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
|
||||
case *rsa.PrivateKey:
|
||||
|
||||
return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
|
||||
case *rsa.PublicKey:
|
||||
hashed := hashAlgorithm.Digest(msg)
|
||||
return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
|
||||
|
||||
return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
|
||||
}
|
||||
|
||||
return nil, errKeySignatureGenerateUnimplemented
|
||||
}
|
||||
|
||||
func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.Algorithm, rawCertificates [][]byte) error { //nolint:dupl
|
||||
//nolint:dupl,cyclop
|
||||
func verifyKeySignature(
|
||||
message, remoteKeySignature []byte,
|
||||
hashAlgorithm hash.Algorithm,
|
||||
rawCertificates [][]byte,
|
||||
) error {
|
||||
if len(rawCertificates) == 0 {
|
||||
return errLengthMismatch
|
||||
}
|
||||
|
|
@ -70,11 +81,12 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A
|
|||
return err
|
||||
}
|
||||
|
||||
switch p := certificate.PublicKey.(type) {
|
||||
switch pubKey := certificate.PublicKey.(type) {
|
||||
case ed25519.PublicKey:
|
||||
if ok := ed25519.Verify(p, message, remoteKeySignature); !ok {
|
||||
if ok := ed25519.Verify(pubKey, message, remoteKeySignature); !ok {
|
||||
return errKeySignatureMismatch
|
||||
}
|
||||
|
||||
return nil
|
||||
case *ecdsa.PublicKey:
|
||||
ecdsaSig := &ecdsaSignature{}
|
||||
|
|
@ -85,18 +97,18 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A
|
|||
return errInvalidECDSASignature
|
||||
}
|
||||
hashed := hashAlgorithm.Digest(message)
|
||||
if !ecdsa.Verify(p, hashed, ecdsaSig.R, ecdsaSig.S) {
|
||||
if !ecdsa.Verify(pubKey, hashed, ecdsaSig.R, ecdsaSig.S) {
|
||||
return errKeySignatureMismatch
|
||||
}
|
||||
|
||||
return nil
|
||||
case *rsa.PublicKey:
|
||||
switch certificate.SignatureAlgorithm {
|
||||
case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
|
||||
hashed := hashAlgorithm.Digest(message)
|
||||
return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature)
|
||||
default:
|
||||
return errKeySignatureVerifyUnimplemented
|
||||
hashed := hashAlgorithm.Digest(message)
|
||||
if rsa.VerifyPKCS1v15(pubKey, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature) != nil {
|
||||
return errKeySignatureMismatch
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errKeySignatureVerifyUnimplemented
|
||||
|
|
@ -110,31 +122,37 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A
|
|||
// CertificateVerify message is sent to explicitly verify possession of
|
||||
// the private key in the certificate.
|
||||
// https://tools.ietf.org/html/rfc5246#section-7.3
|
||||
func generateCertificateVerify(handshakeBodies []byte, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) {
|
||||
if p, ok := privateKey.(ed25519.PrivateKey); ok {
|
||||
func generateCertificateVerify(
|
||||
handshakeBodies []byte,
|
||||
signer crypto.Signer,
|
||||
hashAlgorithm hash.Algorithm,
|
||||
) ([]byte, error) {
|
||||
if _, ok := signer.Public().(ed25519.PublicKey); ok {
|
||||
// https://pkg.go.dev/crypto/ed25519#PrivateKey.Sign
|
||||
// Sign signs the given message with priv. Ed25519 performs two passes over
|
||||
// messages to be signed and therefore cannot handle pre-hashed messages.
|
||||
return p.Sign(rand.Reader, handshakeBodies, crypto.Hash(0))
|
||||
return signer.Sign(rand.Reader, handshakeBodies, crypto.Hash(0))
|
||||
}
|
||||
|
||||
h := sha256.New()
|
||||
if _, err := h.Write(handshakeBodies); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hashed := h.Sum(nil)
|
||||
hashed := hashAlgorithm.Digest(handshakeBodies)
|
||||
|
||||
switch p := privateKey.(type) {
|
||||
case *ecdsa.PrivateKey:
|
||||
return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
|
||||
case *rsa.PrivateKey:
|
||||
return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
|
||||
switch signer.Public().(type) {
|
||||
case *ecdsa.PublicKey:
|
||||
return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
|
||||
case *rsa.PublicKey:
|
||||
return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
|
||||
}
|
||||
|
||||
return nil, errInvalidSignatureAlgorithm
|
||||
}
|
||||
|
||||
func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorithm, remoteKeySignature []byte, rawCertificates [][]byte) error { //nolint:dupl
|
||||
//nolint:dupl,cyclop
|
||||
func verifyCertificateVerify(
|
||||
handshakeBodies []byte,
|
||||
hashAlgorithm hash.Algorithm,
|
||||
remoteKeySignature []byte,
|
||||
rawCertificates [][]byte,
|
||||
) error {
|
||||
if len(rawCertificates) == 0 {
|
||||
return errLengthMismatch
|
||||
}
|
||||
|
|
@ -143,11 +161,12 @@ func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorith
|
|||
return err
|
||||
}
|
||||
|
||||
switch p := certificate.PublicKey.(type) {
|
||||
switch pubKey := certificate.PublicKey.(type) {
|
||||
case ed25519.PublicKey:
|
||||
if ok := ed25519.Verify(p, handshakeBodies, remoteKeySignature); !ok {
|
||||
if ok := ed25519.Verify(pubKey, handshakeBodies, remoteKeySignature); !ok {
|
||||
return errKeySignatureMismatch
|
||||
}
|
||||
|
||||
return nil
|
||||
case *ecdsa.PublicKey:
|
||||
ecdsaSig := &ecdsaSignature{}
|
||||
|
|
@ -158,18 +177,18 @@ func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorith
|
|||
return errInvalidECDSASignature
|
||||
}
|
||||
hash := hashAlgorithm.Digest(handshakeBodies)
|
||||
if !ecdsa.Verify(p, hash, ecdsaSig.R, ecdsaSig.S) {
|
||||
if !ecdsa.Verify(pubKey, hash, ecdsaSig.R, ecdsaSig.S) {
|
||||
return errKeySignatureMismatch
|
||||
}
|
||||
|
||||
return nil
|
||||
case *rsa.PublicKey:
|
||||
switch certificate.SignatureAlgorithm {
|
||||
case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
|
||||
hash := hashAlgorithm.Digest(handshakeBodies)
|
||||
return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature)
|
||||
default:
|
||||
return errKeySignatureVerifyUnimplemented
|
||||
hash := hashAlgorithm.Digest(handshakeBodies)
|
||||
if rsa.VerifyPKCS1v15(pubKey, hashAlgorithm.CryptoHash(), hash, remoteKeySignature) != nil {
|
||||
return errKeySignatureMismatch
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errKeySignatureVerifyUnimplemented
|
||||
|
|
@ -188,6 +207,7 @@ func loadCerts(rawCertificates [][]byte) ([]*x509.Certificate, error) {
|
|||
}
|
||||
certs = append(certs, cert)
|
||||
}
|
||||
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
|
|
@ -206,10 +226,15 @@ func verifyClientCert(rawCertificates [][]byte, roots *x509.CertPool) (chains []
|
|||
Intermediates: intermediateCAPool,
|
||||
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
|
||||
return certificate[0].Verify(opts)
|
||||
}
|
||||
|
||||
func verifyServerCert(rawCertificates [][]byte, roots *x509.CertPool, serverName string) (chains [][]*x509.Certificate, err error) {
|
||||
func verifyServerCert(
|
||||
rawCertificates [][]byte,
|
||||
roots *x509.CertPool,
|
||||
serverName string,
|
||||
) (chains [][]*x509.Certificate, err error) {
|
||||
certificate, err := loadCerts(rawCertificates)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -224,5 +249,6 @@ func verifyServerCert(rawCertificates [][]byte, roots *x509.CertPool, serverName
|
|||
DNSName: serverName,
|
||||
Intermediates: intermediateCAPool,
|
||||
}
|
||||
|
||||
return certificate[0].Verify(opts)
|
||||
}
|
||||
227
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors.go
generated
vendored
Normal file
227
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors.go
generated
vendored
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package dtls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
)
|
||||
|
||||
// Typed errors.
|
||||
var (
|
||||
ErrConnClosed = &FatalError{Err: errors.New("conn is closed")} //nolint:goerr113
|
||||
|
||||
errDeadlineExceeded = &TimeoutError{Err: fmt.Errorf("read/write timeout: %w", context.DeadlineExceeded)}
|
||||
errInvalidContentType = &TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113
|
||||
|
||||
//nolint:goerr113
|
||||
errBufferTooSmall = &TemporaryError{Err: errors.New("buffer is too small")}
|
||||
//nolint:goerr113
|
||||
errContextUnsupported = &TemporaryError{Err: errors.New("context is not supported for ExportKeyingMaterial")}
|
||||
//nolint:goerr113
|
||||
errHandshakeInProgress = &TemporaryError{Err: errors.New("handshake is in progress")}
|
||||
//nolint:goerr113
|
||||
errReservedExportKeyingMaterial = &TemporaryError{
|
||||
Err: errors.New("ExportKeyingMaterial can not be used with a reserved label"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errApplicationDataEpochZero = &TemporaryError{Err: errors.New("ApplicationData with epoch of 0")}
|
||||
//nolint:goerr113
|
||||
errUnhandledContextType = &TemporaryError{Err: errors.New("unhandled contentType")}
|
||||
|
||||
//nolint:goerr113
|
||||
errCertificateVerifyNoCertificate = &FatalError{
|
||||
Err: errors.New("client sent certificate verify but we have no certificate to verify"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errCipherSuiteNoIntersection = &FatalError{Err: errors.New("client+server do not support any shared cipher suites")}
|
||||
//nolint:goerr113
|
||||
errClientCertificateNotVerified = &FatalError{Err: errors.New("client sent certificate but did not verify it")}
|
||||
//nolint:goerr113
|
||||
errClientCertificateRequired = &FatalError{Err: errors.New("server required client verification, but got none")}
|
||||
//nolint:goerr113
|
||||
errClientNoMatchingSRTPProfile = &FatalError{Err: errors.New("server responded with SRTP Profile we do not support")}
|
||||
//nolint:goerr113
|
||||
errClientRequiredButNoServerEMS = &FatalError{
|
||||
Err: errors.New("client required Extended Master Secret extension, but server does not support it"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errCookieMismatch = &FatalError{Err: errors.New("client+server cookie does not match")}
|
||||
//nolint:goerr113
|
||||
errIdentityNoPSK = &FatalError{Err: errors.New("PSK Identity Hint provided but PSK is nil")}
|
||||
//nolint:goerr113
|
||||
errInvalidCertificate = &FatalError{Err: errors.New("no certificate provided")}
|
||||
//nolint:goerr113
|
||||
errInvalidCipherSuite = &FatalError{Err: errors.New("invalid or unknown cipher suite")}
|
||||
//nolint:goerr113
|
||||
errInvalidECDSASignature = &FatalError{Err: errors.New("ECDSA signature contained zero or negative values")}
|
||||
//nolint:goerr113
|
||||
errInvalidPrivateKey = &FatalError{Err: errors.New("invalid private key type")}
|
||||
//nolint:goerr113
|
||||
errInvalidSignatureAlgorithm = &FatalError{Err: errors.New("invalid signature algorithm")}
|
||||
//nolint:goerr113
|
||||
errKeySignatureMismatch = &FatalError{Err: errors.New("expected and actual key signature do not match")}
|
||||
//nolint:goerr113
|
||||
errNilNextConn = &FatalError{Err: errors.New("Conn can not be created with a nil nextConn")}
|
||||
//nolint:goerr113
|
||||
errNoAvailableCipherSuites = &FatalError{
|
||||
Err: errors.New("connection can not be created, no CipherSuites satisfy this Config"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errNoAvailablePSKCipherSuite = &FatalError{
|
||||
Err: errors.New("connection can not be created, pre-shared key present but no compatible CipherSuite"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errNoAvailableCertificateCipherSuite = &FatalError{
|
||||
Err: errors.New("connection can not be created, certificate present but no compatible CipherSuite"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errNoAvailableSignatureSchemes = &FatalError{
|
||||
Err: errors.New("connection can not be created, no SignatureScheme satisfy this Config"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errNoCertificates = &FatalError{Err: errors.New("no certificates configured")}
|
||||
//nolint:goerr113
|
||||
errNoConfigProvided = &FatalError{Err: errors.New("no config provided")}
|
||||
//nolint:goerr113
|
||||
errNoSupportedEllipticCurves = &FatalError{
|
||||
Err: errors.New("client requested zero or more elliptic curves that are not supported by the server"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errUnsupportedProtocolVersion = &FatalError{Err: errors.New("unsupported protocol version")}
|
||||
//nolint:goerr113
|
||||
errPSKAndIdentityMustBeSetForClient = &FatalError{
|
||||
Err: errors.New("PSK and PSK Identity Hint must both be set for client"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errRequestedButNoSRTPExtension = &FatalError{
|
||||
Err: errors.New("SRTP support was requested but server did not respond with use_srtp extension"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errServerNoMatchingSRTPProfile = &FatalError{Err: errors.New("client requested SRTP but we have no matching profiles")}
|
||||
//nolint:goerr113
|
||||
errServerRequiredButNoClientEMS = &FatalError{
|
||||
Err: errors.New("server requires the Extended Master Secret extension, but the client does not support it"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errVerifyDataMismatch = &FatalError{Err: errors.New("expected and actual verify data does not match")}
|
||||
//nolint:goerr113
|
||||
errNotAcceptableCertificateChain = &FatalError{Err: errors.New("certificate chain is not signed by an acceptable CA")}
|
||||
|
||||
//nolint:goerr113
|
||||
errInvalidFlight = &InternalError{Err: errors.New("invalid flight number")}
|
||||
//nolint:goerr113
|
||||
errKeySignatureGenerateUnimplemented = &InternalError{
|
||||
Err: errors.New("unable to generate key signature, unimplemented"),
|
||||
}
|
||||
//nolint:goerr113
|
||||
errKeySignatureVerifyUnimplemented = &InternalError{Err: errors.New("unable to verify key signature, unimplemented")}
|
||||
//nolint:goerr113
|
||||
errLengthMismatch = &InternalError{Err: errors.New("data length and declared length do not match")}
|
||||
//nolint:goerr113
|
||||
errSequenceNumberOverflow = &InternalError{Err: errors.New("sequence number overflow")}
|
||||
//nolint:goerr113
|
||||
errInvalidFSMTransition = &InternalError{Err: errors.New("invalid state machine transition")}
|
||||
//nolint:goerr113
|
||||
errFailedToAccessPoolReadBuffer = &InternalError{Err: errors.New("failed to access pool read buffer")}
|
||||
//nolint:goerr113
|
||||
errFragmentBufferOverflow = &InternalError{Err: errors.New("fragment buffer overflow")}
|
||||
)
|
||||
|
||||
// FatalError indicates that the DTLS connection is no longer available.
|
||||
// It is mainly caused by wrong configuration of server or client.
|
||||
type FatalError = protocol.FatalError
|
||||
|
||||
// InternalError indicates and internal error caused by the implementation,
|
||||
// and the DTLS connection is no longer available.
|
||||
// It is mainly caused by bugs or tried to use unimplemented features.
|
||||
type InternalError = protocol.InternalError
|
||||
|
||||
// TemporaryError indicates that the DTLS connection is still available, but the request was failed temporary.
|
||||
type TemporaryError = protocol.TemporaryError
|
||||
|
||||
// TimeoutError indicates that the request was timed out.
|
||||
type TimeoutError = protocol.TimeoutError
|
||||
|
||||
// HandshakeError indicates that the handshake failed.
|
||||
type HandshakeError = protocol.HandshakeError
|
||||
|
||||
// errInvalidCipherSuite indicates an attempt at using an unsupported cipher suite.
|
||||
type invalidCipherSuiteError struct {
|
||||
id CipherSuiteID
|
||||
}
|
||||
|
||||
func (e *invalidCipherSuiteError) Error() string {
|
||||
return fmt.Sprintf("CipherSuite with id(%d) is not valid", e.id)
|
||||
}
|
||||
|
||||
func (e *invalidCipherSuiteError) Is(err error) bool {
|
||||
var other *invalidCipherSuiteError
|
||||
if errors.As(err, &other) {
|
||||
return e.id == other.id
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// errAlert wraps DTLS alert notification as an error.
|
||||
type alertError struct {
|
||||
*alert.Alert
|
||||
}
|
||||
|
||||
func (e *alertError) Error() string {
|
||||
return fmt.Sprintf("alert: %s", e.Alert.String())
|
||||
}
|
||||
|
||||
func (e *alertError) IsFatalOrCloseNotify() bool {
|
||||
return e.Level == alert.Fatal || e.Description == alert.CloseNotify
|
||||
}
|
||||
|
||||
func (e *alertError) Is(err error) bool {
|
||||
var other *alertError
|
||||
if errors.As(err, &other) {
|
||||
return e.Level == other.Level && e.Description == other.Description
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// netError translates an error from underlying Conn to corresponding net.Error.
|
||||
func netError(err error) error {
|
||||
switch {
|
||||
case errors.Is(err, io.EOF), errors.Is(err, context.Canceled), errors.Is(err, context.DeadlineExceeded):
|
||||
// Return io.EOF and context errors as is.
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
ne net.Error
|
||||
opError *net.OpError
|
||||
se *os.SyscallError
|
||||
)
|
||||
|
||||
if errors.As(err, &opError) { //nolint:nestif
|
||||
if errors.As(opError, &se) {
|
||||
if se.Timeout() {
|
||||
return &TimeoutError{Err: err}
|
||||
}
|
||||
if isOpErrorTemporary(se) {
|
||||
return &TemporaryError{Err: err}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if errors.As(err, &ne) {
|
||||
return err
|
||||
}
|
||||
|
||||
return &FatalError{Err: err}
|
||||
}
|
||||
|
|
@ -70,7 +70,7 @@ const (
|
|||
flight6
|
||||
)
|
||||
|
||||
func (f flightVal) String() string {
|
||||
func (f flightVal) String() string { //nolint:cyclop
|
||||
switch f {
|
||||
case flight0:
|
||||
return "Flight 0"
|
||||
|
|
@ -7,14 +7,21 @@ import (
|
|||
"context"
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
)
|
||||
|
||||
func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) {
|
||||
//nolint:cyclop
|
||||
func flight0Parse(
|
||||
_ context.Context,
|
||||
_ flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
seq, msgs, ok := cache.fullPullMap(0, state.cipherSuite,
|
||||
handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false},
|
||||
)
|
||||
|
|
@ -22,6 +29,12 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak
|
|||
// No valid message received. Keep reading
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
// Connection Identifiers must be negotiated afresh on session resumption.
|
||||
// https://datatracker.ietf.org/doc/html/rfc9146#name-the-connection_id-extension
|
||||
state.setLocalConnectionID(nil)
|
||||
state.remoteConnectionID = nil
|
||||
|
||||
state.handshakeRecvSequence = seq
|
||||
|
||||
var clientHello *handshake.MessageClientHello
|
||||
|
|
@ -49,29 +62,42 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak
|
|||
}
|
||||
|
||||
for _, val := range clientHello.Extensions {
|
||||
switch e := val.(type) {
|
||||
switch ext := val.(type) {
|
||||
case *extension.SupportedEllipticCurves:
|
||||
if len(e.EllipticCurves) == 0 {
|
||||
if len(ext.EllipticCurves) == 0 {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoSupportedEllipticCurves
|
||||
}
|
||||
state.namedCurve = e.EllipticCurves[0]
|
||||
state.namedCurve = ext.EllipticCurves[0]
|
||||
case *extension.UseSRTP:
|
||||
profile, ok := findMatchingSRTPProfile(e.ProtectionProfiles, cfg.localSRTPProtectionProfiles)
|
||||
profile, ok := findMatchingSRTPProfile(ext.ProtectionProfiles, cfg.localSRTPProtectionProfiles)
|
||||
if !ok {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerNoMatchingSRTPProfile
|
||||
}
|
||||
state.srtpProtectionProfile = profile
|
||||
state.setSRTPProtectionProfile(profile)
|
||||
state.remoteSRTPMasterKeyIdentifier = ext.MasterKeyIdentifier
|
||||
case *extension.UseExtendedMasterSecret:
|
||||
if cfg.extendedMasterSecret != DisableExtendedMasterSecret {
|
||||
state.extendedMasterSecret = true
|
||||
}
|
||||
case *extension.ServerName:
|
||||
state.serverName = e.ServerName // remote server name
|
||||
state.serverName = ext.ServerName // remote server name
|
||||
case *extension.ALPN:
|
||||
state.peerSupportedProtocols = e.ProtocolNameList
|
||||
state.peerSupportedProtocols = ext.ProtocolNameList
|
||||
case *extension.ConnectionID:
|
||||
// Only set connection ID to be sent if server supports connection
|
||||
// IDs.
|
||||
if cfg.connectionIDGenerator != nil {
|
||||
state.remoteConnectionID = ext.CID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the client doesn't support connection IDs, the server should not
|
||||
// expect one to be sent.
|
||||
if state.remoteConnectionID == nil {
|
||||
state.setLocalConnectionID(nil)
|
||||
}
|
||||
|
||||
if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerRequiredButNoClientEMS
|
||||
}
|
||||
|
|
@ -93,7 +119,12 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak
|
|||
return handleHelloResume(clientHello.SessionID, state, cfg, nextFlight)
|
||||
}
|
||||
|
||||
func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, next flightVal) (flightVal, *alert.Alert, error) {
|
||||
func handleHelloResume(
|
||||
sessionID []byte,
|
||||
state *State,
|
||||
cfg *handshakeConfig,
|
||||
next flightVal,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
if len(sessionID) > 0 && cfg.sessionStore != nil {
|
||||
if s, err := cfg.sessionStore.Get(sessionID); err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
|
|
@ -113,10 +144,16 @@ func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, nex
|
|||
return flight4b, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
return next, nil, nil
|
||||
}
|
||||
|
||||
func flight0Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
|
||||
func flight0Generate(
|
||||
_ flightConn,
|
||||
state *State,
|
||||
_ *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) ([]*packet, *alert.Alert, error) {
|
||||
// Initialize
|
||||
if !cfg.insecureSkipHelloVerify {
|
||||
state.cookie = make([]byte, cookieLength)
|
||||
|
|
@ -6,15 +6,21 @@ package dtls
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) {
|
||||
func flight1Parse(
|
||||
ctx context.Context,
|
||||
conn flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
// HelloVerifyRequest can be skipped by the server,
|
||||
// so allow ServerHello during flight1 also
|
||||
seq, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite,
|
||||
|
|
@ -29,7 +35,7 @@ func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
if _, ok := msgs[handshake.TypeServerHello]; ok {
|
||||
// Flight1 and flight2 were skipped.
|
||||
// Parse as flight3.
|
||||
return flight3Parse(ctx, c, state, cache, cfg)
|
||||
return flight3Parse(ctx, conn, state, cache, cfg)
|
||||
}
|
||||
|
||||
if h, ok := msgs[handshake.TypeHelloVerifyRequest].(*handshake.MessageHelloVerifyRequest); ok {
|
||||
|
|
@ -40,13 +46,20 @@ func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
}
|
||||
state.cookie = append([]byte{}, h.Cookie...)
|
||||
state.handshakeRecvSequence = seq
|
||||
|
||||
return flight3, nil, nil
|
||||
}
|
||||
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, nil
|
||||
}
|
||||
|
||||
func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
|
||||
//nolint:cyclop
|
||||
func flight1Generate(
|
||||
conn flightConn,
|
||||
state *State,
|
||||
_ *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) ([]*packet, *alert.Alert, error) {
|
||||
var zeroEpoch uint16
|
||||
state.localEpoch.Store(zeroEpoch)
|
||||
state.remoteEpoch.Store(zeroEpoch)
|
||||
|
|
@ -57,6 +70,10 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
if cfg.helloRandomBytesGenerator != nil {
|
||||
state.localRandom.RandomBytes = cfg.helloRandomBytesGenerator()
|
||||
}
|
||||
|
||||
extensions := []extension.Extension{
|
||||
&extension.SupportedSignatureAlgorithms{
|
||||
SignatureHashAlgorithms: cfg.localSignatureSchemes,
|
||||
|
|
@ -70,6 +87,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
for _, c := range cfg.localCipherSuites {
|
||||
if c.ECC() {
|
||||
setEllipticCurveCryptographyClientHelloExtensions = true
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -87,7 +105,8 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
|
||||
if len(cfg.localSRTPProtectionProfiles) > 0 {
|
||||
extensions = append(extensions, &extension.UseSRTP{
|
||||
ProtectionProfiles: cfg.localSRTPProtectionProfiles,
|
||||
ProtectionProfiles: cfg.localSRTPProtectionProfiles,
|
||||
MasterKeyIdentifier: cfg.localSRTPMasterKeyIdentifier,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +127,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
|
||||
if cfg.sessionStore != nil {
|
||||
cfg.log.Tracef("[handshake] try to resume session")
|
||||
if s, err := cfg.sessionStore.Get(c.sessionKey()); err != nil {
|
||||
if s, err := cfg.sessionStore.Get(conn.sessionKey()); err != nil {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
} else if s.ID != nil {
|
||||
cfg.log.Tracef("[handshake] get saved session: %x", s.ID)
|
||||
|
|
@ -118,23 +137,46 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
}
|
||||
}
|
||||
|
||||
// If we have a connection ID generator, use it. The CID may be zero length,
|
||||
// in which case we are just requesting that the server send us a CID to
|
||||
// use.
|
||||
if cfg.connectionIDGenerator != nil {
|
||||
state.setLocalConnectionID(cfg.connectionIDGenerator())
|
||||
// The presence of a generator indicates support for connection IDs. We
|
||||
// use the presence of a non-nil local CID in flight 3 to determine
|
||||
// whether we send a CID in the second ClientHello, so we convert any
|
||||
// nil CID returned by a generator to []byte{}.
|
||||
if state.getLocalConnectionID() == nil {
|
||||
state.setLocalConnectionID([]byte{})
|
||||
}
|
||||
extensions = append(extensions, &extension.ConnectionID{CID: state.getLocalConnectionID()})
|
||||
}
|
||||
|
||||
clientHello := &handshake.MessageClientHello{
|
||||
Version: protocol.Version1_2,
|
||||
SessionID: state.SessionID,
|
||||
Cookie: state.cookie,
|
||||
Random: state.localRandom,
|
||||
CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites),
|
||||
CompressionMethods: defaultCompressionMethods(),
|
||||
Extensions: extensions,
|
||||
}
|
||||
|
||||
var content handshake.Handshake
|
||||
|
||||
if cfg.clientHelloMessageHook != nil {
|
||||
content = handshake.Handshake{Message: cfg.clientHelloMessageHook(*clientHello)}
|
||||
} else {
|
||||
content = handshake.Handshake{Message: clientHello}
|
||||
}
|
||||
|
||||
return []*packet{
|
||||
{
|
||||
record: &recordlayer.RecordLayer{
|
||||
Header: recordlayer.Header{
|
||||
Version: protocol.Version1_2,
|
||||
},
|
||||
Content: &handshake.Handshake{
|
||||
Message: &handshake.MessageClientHello{
|
||||
Version: protocol.Version1_2,
|
||||
SessionID: state.SessionID,
|
||||
Cookie: state.cookie,
|
||||
Random: state.localRandom,
|
||||
CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites),
|
||||
CompressionMethods: defaultCompressionMethods(),
|
||||
Extensions: extensions,
|
||||
},
|
||||
},
|
||||
Content: &content,
|
||||
},
|
||||
},
|
||||
}, nil, nil
|
||||
|
|
@ -7,13 +7,19 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
func flight2Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) {
|
||||
func flight2Parse(
|
||||
ctx context.Context,
|
||||
c flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
seq, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite,
|
||||
handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false},
|
||||
)
|
||||
|
|
@ -41,11 +47,18 @@ func flight2Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
if !bytes.Equal(state.cookie, clientHello.Cookie) {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.AccessDenied}, errCookieMismatch
|
||||
}
|
||||
|
||||
return flight4, nil, nil
|
||||
}
|
||||
|
||||
func flight2Generate(_ flightConn, state *State, _ *handshakeCache, _ *handshakeConfig) ([]*packet, *alert.Alert, error) {
|
||||
func flight2Generate(
|
||||
_ flightConn,
|
||||
state *State,
|
||||
_ *handshakeCache,
|
||||
_ *handshakeConfig,
|
||||
) ([]*packet, *alert.Alert, error) {
|
||||
state.handshakeSendSequence = 0
|
||||
|
||||
return []*packet{
|
||||
{
|
||||
record: &recordlayer.RecordLayer{
|
||||
|
|
@ -7,17 +7,24 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/pion/dtls/v2/internal/ciphersuite/types"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/internal/ciphersuite/types"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { //nolint:gocognit
|
||||
//nolint:gocognit,gocyclo,maintidx,cyclop
|
||||
func flight3Parse(
|
||||
ctx context.Context,
|
||||
conn flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
// Clients may receive multiple HelloVerifyRequest messages with different cookies.
|
||||
// Clients SHOULD handle this by sending a new ClientHello with a cookie in response
|
||||
// to the new HelloVerifyRequest. RFC 6347 Section 4.2.1
|
||||
|
|
@ -33,6 +40,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
}
|
||||
state.cookie = append([]byte{}, h.Cookie...)
|
||||
state.handshakeRecvSequence = seq
|
||||
|
||||
return flight3, nil, nil
|
||||
}
|
||||
}
|
||||
|
|
@ -45,37 +53,53 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
return 0, nil, nil
|
||||
}
|
||||
|
||||
if h, msgOk := msgs[handshake.TypeServerHello].(*handshake.MessageServerHello); msgOk {
|
||||
if !h.Version.Equal(protocol.Version1_2) {
|
||||
if serverHelloMsg, msgOk := msgs[handshake.TypeServerHello].(*handshake.MessageServerHello); msgOk { //nolint:nestif
|
||||
if !serverHelloMsg.Version.Equal(protocol.Version1_2) {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.ProtocolVersion}, errUnsupportedProtocolVersion
|
||||
}
|
||||
for _, v := range h.Extensions {
|
||||
switch e := v.(type) {
|
||||
for _, v := range serverHelloMsg.Extensions {
|
||||
switch ext := v.(type) {
|
||||
case *extension.UseSRTP:
|
||||
profile, found := findMatchingSRTPProfile(e.ProtectionProfiles, cfg.localSRTPProtectionProfiles)
|
||||
profile, found := findMatchingSRTPProfile(ext.ProtectionProfiles, cfg.localSRTPProtectionProfiles)
|
||||
if !found {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, errClientNoMatchingSRTPProfile
|
||||
}
|
||||
state.srtpProtectionProfile = profile
|
||||
state.setSRTPProtectionProfile(profile)
|
||||
state.remoteSRTPMasterKeyIdentifier = ext.MasterKeyIdentifier
|
||||
case *extension.UseExtendedMasterSecret:
|
||||
if cfg.extendedMasterSecret != DisableExtendedMasterSecret {
|
||||
state.extendedMasterSecret = true
|
||||
}
|
||||
case *extension.ALPN:
|
||||
if len(e.ProtocolNameList) > 1 { // This should be exactly 1, the zero case is handle when unmarshalling
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, extension.ErrALPNInvalidFormat // Meh, internal error?
|
||||
if len(ext.ProtocolNameList) > 1 { // This should be exactly 1, the zero case is handle when unmarshalling
|
||||
return 0, &alert.Alert{
|
||||
Level: alert.Fatal,
|
||||
Description: alert.InternalError,
|
||||
}, extension.ErrALPNInvalidFormat // Meh, internal error?
|
||||
}
|
||||
state.NegotiatedProtocol = ext.ProtocolNameList[0]
|
||||
case *extension.ConnectionID:
|
||||
// Only set connection ID to be sent if client supports connection
|
||||
// IDs.
|
||||
if cfg.connectionIDGenerator != nil {
|
||||
state.remoteConnectionID = ext.CID
|
||||
}
|
||||
state.NegotiatedProtocol = e.ProtocolNameList[0]
|
||||
}
|
||||
}
|
||||
// If the server doesn't support connection IDs, the client should not
|
||||
// expect one to be sent.
|
||||
if state.remoteConnectionID == nil {
|
||||
state.setLocalConnectionID(nil)
|
||||
}
|
||||
|
||||
if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errClientRequiredButNoServerEMS
|
||||
}
|
||||
if len(cfg.localSRTPProtectionProfiles) > 0 && state.srtpProtectionProfile == 0 {
|
||||
if len(cfg.localSRTPProtectionProfiles) > 0 && state.getSRTPProtectionProfile() == 0 {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errRequestedButNoSRTPExtension
|
||||
}
|
||||
|
||||
remoteCipherSuite := cipherSuiteForID(CipherSuiteID(*h.CipherSuiteID), cfg.customCipherSuites)
|
||||
remoteCipherSuite := cipherSuiteForID(CipherSuiteID(*serverHelloMsg.CipherSuiteID), cfg.customCipherSuites)
|
||||
if remoteCipherSuite == nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errCipherSuiteNoIntersection
|
||||
}
|
||||
|
|
@ -86,11 +110,11 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
}
|
||||
|
||||
state.cipherSuite = selectedCipherSuite
|
||||
state.remoteRandom = h.Random
|
||||
state.remoteRandom = serverHelloMsg.Random
|
||||
cfg.log.Tracef("[handshake] use cipher suite: %s", selectedCipherSuite.String())
|
||||
|
||||
if len(h.SessionID) > 0 && bytes.Equal(state.SessionID, h.SessionID) {
|
||||
return handleResumption(ctx, c, state, cache, cfg)
|
||||
if len(serverHelloMsg.SessionID) > 0 && bytes.Equal(state.SessionID, serverHelloMsg.SessionID) {
|
||||
return handleResumption(ctx, conn, state, cache, cfg)
|
||||
}
|
||||
|
||||
if len(state.SessionID) > 0 {
|
||||
|
|
@ -103,7 +127,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
if cfg.sessionStore == nil {
|
||||
state.SessionID = []byte{}
|
||||
} else {
|
||||
state.SessionID = h.SessionID
|
||||
state.SessionID = serverHelloMsg.SessionID
|
||||
}
|
||||
|
||||
state.masterSecret = []byte{}
|
||||
|
|
@ -135,20 +159,27 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
}
|
||||
|
||||
if h, ok := msgs[handshake.TypeServerKeyExchange].(*handshake.MessageServerKeyExchange); ok {
|
||||
alertPtr, err := handleServerKeyExchange(c, state, cfg, h)
|
||||
alertPtr, err := handleServerKeyExchange(conn, state, cfg, h)
|
||||
if err != nil {
|
||||
return 0, alertPtr, err
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok {
|
||||
if creq, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok {
|
||||
state.remoteCertRequestAlgs = creq.SignatureHashAlgorithms
|
||||
state.remoteRequestedCertificate = true
|
||||
}
|
||||
|
||||
return flight5, nil, nil
|
||||
}
|
||||
|
||||
func handleResumption(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) {
|
||||
func handleResumption(
|
||||
ctx context.Context,
|
||||
c flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
if err := state.initCipherSuite(); err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
|
|
@ -189,25 +220,36 @@ func handleResumption(ctx context.Context, c flightConn, state *State, cache *ha
|
|||
return flight5b, nil, nil
|
||||
}
|
||||
|
||||
func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h *handshake.MessageServerKeyExchange) (*alert.Alert, error) {
|
||||
//nolint:cyclop
|
||||
func handleServerKeyExchange(
|
||||
_ flightConn,
|
||||
state *State,
|
||||
cfg *handshakeConfig,
|
||||
keyExchangeMessage *handshake.MessageServerKeyExchange,
|
||||
) (*alert.Alert, error) {
|
||||
var err error
|
||||
if state.cipherSuite == nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errInvalidCipherSuite
|
||||
}
|
||||
if cfg.localPSKCallback != nil {
|
||||
if cfg.localPSKCallback != nil { //nolint:nestif
|
||||
var psk []byte
|
||||
if psk, err = cfg.localPSKCallback(h.IdentityHint); err != nil {
|
||||
if psk, err = cfg.localPSKCallback(keyExchangeMessage.IdentityHint); err != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
state.IdentityHint = h.IdentityHint
|
||||
state.IdentityHint = keyExchangeMessage.IdentityHint
|
||||
switch state.cipherSuite.KeyExchangeAlgorithm() {
|
||||
case types.KeyExchangeAlgorithmPsk:
|
||||
state.preMasterSecret = prf.PSKPreMasterSecret(psk)
|
||||
case (types.KeyExchangeAlgorithmEcdhe | types.KeyExchangeAlgorithmPsk):
|
||||
if state.localKeypair, err = elliptic.GenerateKeypair(h.NamedCurve); err != nil {
|
||||
if state.localKeypair, err = elliptic.GenerateKeypair(keyExchangeMessage.NamedCurve); err != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
state.preMasterSecret, err = prf.EcdhePSKPreMasterSecret(psk, h.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve)
|
||||
state.preMasterSecret, err = prf.EcdhePSKPreMasterSecret(
|
||||
psk,
|
||||
keyExchangeMessage.PublicKey,
|
||||
state.localKeypair.PrivateKey,
|
||||
state.localKeypair.Curve,
|
||||
)
|
||||
if err != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
|
|
@ -215,11 +257,15 @@ func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h
|
|||
return &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errInvalidCipherSuite
|
||||
}
|
||||
} else {
|
||||
if state.localKeypair, err = elliptic.GenerateKeypair(h.NamedCurve); err != nil {
|
||||
if state.localKeypair, err = elliptic.GenerateKeypair(keyExchangeMessage.NamedCurve); err != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
|
||||
if state.preMasterSecret, err = prf.PreMasterSecret(h.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve); err != nil {
|
||||
if state.preMasterSecret, err = prf.PreMasterSecret(
|
||||
keyExchangeMessage.PublicKey,
|
||||
state.localKeypair.PrivateKey,
|
||||
state.localKeypair.Curve,
|
||||
); err != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
}
|
||||
|
|
@ -227,7 +273,12 @@ func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h
|
|||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
|
||||
func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
|
||||
func flight3Generate(
|
||||
_ flightConn,
|
||||
state *State,
|
||||
_ *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) ([]*packet, *alert.Alert, error) {
|
||||
extensions := []extension.Extension{
|
||||
&extension.SupportedSignatureAlgorithms{
|
||||
SignatureHashAlgorithms: cfg.localSignatureSchemes,
|
||||
|
|
@ -236,10 +287,11 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
RenegotiatedConnection: 0,
|
||||
},
|
||||
}
|
||||
|
||||
if state.namedCurve != 0 {
|
||||
extensions = append(extensions, []extension.Extension{
|
||||
&extension.SupportedEllipticCurves{
|
||||
EllipticCurves: []elliptic.Curve{elliptic.X25519, elliptic.P256, elliptic.P384},
|
||||
EllipticCurves: cfg.ellipticCurves,
|
||||
},
|
||||
&extension.SupportedPointFormats{
|
||||
PointFormats: []elliptic.CurvePointFormat{elliptic.CurvePointFormatUncompressed},
|
||||
|
|
@ -268,23 +320,37 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
extensions = append(extensions, &extension.ALPN{ProtocolNameList: cfg.supportedProtocols})
|
||||
}
|
||||
|
||||
// If we sent a connection ID on the first ClientHello, send it on the
|
||||
// second.
|
||||
if state.getLocalConnectionID() != nil {
|
||||
extensions = append(extensions, &extension.ConnectionID{CID: state.getLocalConnectionID()})
|
||||
}
|
||||
|
||||
clientHello := &handshake.MessageClientHello{
|
||||
Version: protocol.Version1_2,
|
||||
SessionID: state.SessionID,
|
||||
Cookie: state.cookie,
|
||||
Random: state.localRandom,
|
||||
CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites),
|
||||
CompressionMethods: defaultCompressionMethods(),
|
||||
Extensions: extensions,
|
||||
}
|
||||
|
||||
var content handshake.Handshake
|
||||
|
||||
if cfg.clientHelloMessageHook != nil {
|
||||
content = handshake.Handshake{Message: cfg.clientHelloMessageHook(*clientHello)}
|
||||
} else {
|
||||
content = handshake.Handshake{Message: clientHello}
|
||||
}
|
||||
|
||||
return []*packet{
|
||||
{
|
||||
record: &recordlayer.RecordLayer{
|
||||
Header: recordlayer.Header{
|
||||
Version: protocol.Version1_2,
|
||||
},
|
||||
Content: &handshake.Handshake{
|
||||
Message: &handshake.MessageClientHello{
|
||||
Version: protocol.Version1_2,
|
||||
SessionID: state.SessionID,
|
||||
Cookie: state.cookie,
|
||||
Random: state.localRandom,
|
||||
CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites),
|
||||
CompressionMethods: defaultCompressionMethods(),
|
||||
Extensions: extensions,
|
||||
},
|
||||
},
|
||||
Content: &content,
|
||||
},
|
||||
},
|
||||
}, nil, nil
|
||||
|
|
@ -7,15 +7,21 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
func flight4bParse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) {
|
||||
func flight4bParse(
|
||||
_ context.Context,
|
||||
_ flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
_, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite,
|
||||
handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, true, false},
|
||||
)
|
||||
|
|
@ -47,7 +53,13 @@ func flight4bParse(_ context.Context, _ flightConn, state *State, cache *handsha
|
|||
return flight4b, nil, nil
|
||||
}
|
||||
|
||||
func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
|
||||
//nolint:cyclop
|
||||
func flight4bGenerate(
|
||||
_ flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) ([]*packet, *alert.Alert, error) {
|
||||
var pkts []*packet
|
||||
|
||||
extensions := []extension.Extension{&extension.RenegotiationInfo{
|
||||
|
|
@ -59,9 +71,10 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha
|
|||
Supported: true,
|
||||
})
|
||||
}
|
||||
if state.srtpProtectionProfile != 0 {
|
||||
if state.getSRTPProtectionProfile() != 0 {
|
||||
extensions = append(extensions, &extension.UseSRTP{
|
||||
ProtectionProfiles: []SRTPProtectionProfile{state.srtpProtectionProfile},
|
||||
ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()},
|
||||
MasterKeyIdentifier: cfg.localSRTPMasterKeyIdentifier,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -77,18 +90,24 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha
|
|||
}
|
||||
|
||||
cipherSuiteID := uint16(state.cipherSuite.ID())
|
||||
serverHello := &handshake.Handshake{
|
||||
Message: &handshake.MessageServerHello{
|
||||
Version: protocol.Version1_2,
|
||||
Random: state.localRandom,
|
||||
SessionID: state.SessionID,
|
||||
CipherSuiteID: &cipherSuiteID,
|
||||
CompressionMethod: defaultCompressionMethods()[0],
|
||||
Extensions: extensions,
|
||||
},
|
||||
var serverHello handshake.Handshake
|
||||
|
||||
serverHelloMessage := &handshake.MessageServerHello{
|
||||
Version: protocol.Version1_2,
|
||||
Random: state.localRandom,
|
||||
SessionID: state.SessionID,
|
||||
CipherSuiteID: &cipherSuiteID,
|
||||
CompressionMethod: defaultCompressionMethods()[0],
|
||||
Extensions: extensions,
|
||||
}
|
||||
|
||||
serverHello.Header.MessageSequence = uint16(state.handshakeSendSequence)
|
||||
if cfg.serverHelloMessageHook != nil {
|
||||
serverHello = handshake.Handshake{Message: cfg.serverHelloMessageHook(*serverHelloMessage)}
|
||||
} else {
|
||||
serverHello = handshake.Handshake{Message: serverHelloMessage}
|
||||
}
|
||||
|
||||
serverHello.Header.MessageSequence = uint16(state.handshakeSendSequence) //nolint:gosec // G115
|
||||
|
||||
if len(state.localVerifyData) == 0 {
|
||||
plainText := cache.pullAndMerge(
|
||||
|
|
@ -112,7 +131,7 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha
|
|||
Header: recordlayer.Header{
|
||||
Version: protocol.Version1_2,
|
||||
},
|
||||
Content: serverHello,
|
||||
Content: &serverHello,
|
||||
},
|
||||
},
|
||||
&packet{
|
||||
|
|
@ -5,22 +5,30 @@ package dtls
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
|
||||
"github.com/pion/dtls/v2/internal/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/signaturehash"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/internal/ciphersuite"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/signaturehash"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/extension"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { //nolint:gocognit
|
||||
//nolint:gocognit,gocyclo,lll,cyclop,maintidx
|
||||
func flight4Parse(
|
||||
ctx context.Context,
|
||||
conn flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
seq, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite,
|
||||
handshakeCachePullRule{handshake.TypeCertificate, cfg.initialEpoch, true, true},
|
||||
handshakeCachePullRule{handshake.TypeClientKeyExchange, cfg.initialEpoch, true, false},
|
||||
|
|
@ -47,7 +55,8 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
state.SessionID = nil
|
||||
}
|
||||
|
||||
if h, hasCertVerify := msgs[handshake.TypeCertificateVerify].(*handshake.MessageCertificateVerify); hasCertVerify {
|
||||
//nolint:nestif
|
||||
if verify, hasVerify := msgs[handshake.TypeCertificateVerify].(*handshake.MessageCertificateVerify); hasVerify {
|
||||
if state.PeerCertificates == nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.NoCertificate}, errCertificateVerifyNoCertificate
|
||||
}
|
||||
|
|
@ -66,8 +75,9 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
// Verify that the pair of hash algorithm and signiture is listed.
|
||||
var validSignatureScheme bool
|
||||
for _, ss := range cfg.localSignatureSchemes {
|
||||
if ss.Hash == h.HashAlgorithm && ss.Signature == h.SignatureAlgorithm {
|
||||
if ss.Hash == verify.HashAlgorithm && ss.Signature == verify.SignatureAlgorithm {
|
||||
validSignatureScheme = true
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -75,7 +85,12 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoAvailableSignatureSchemes
|
||||
}
|
||||
|
||||
if err := verifyCertificateVerify(plainText, h.HashAlgorithm, h.Signature, state.PeerCertificates); err != nil {
|
||||
if err := verifyCertificateVerify(
|
||||
plainText,
|
||||
verify.HashAlgorithm,
|
||||
verify.Signature,
|
||||
state.PeerCertificates,
|
||||
); err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err
|
||||
}
|
||||
var chains [][]*x509.Certificate
|
||||
|
|
@ -99,7 +114,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
return 0, nil, nil
|
||||
}
|
||||
|
||||
if !state.cipherSuite.IsInitialized() {
|
||||
if !state.cipherSuite.IsInitialized() { //nolint:nestif
|
||||
serverRandom := state.localRandom.MarshalFixed()
|
||||
clientRandom := state.remoteRandom.MarshalFixed()
|
||||
|
||||
|
|
@ -115,14 +130,23 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
case CipherSuiteKeyExchangeAlgorithmPsk:
|
||||
preMasterSecret = prf.PSKPreMasterSecret(psk)
|
||||
case (CipherSuiteKeyExchangeAlgorithmPsk | CipherSuiteKeyExchangeAlgorithmEcdhe):
|
||||
if preMasterSecret, err = prf.EcdhePSKPreMasterSecret(psk, clientKeyExchange.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve); err != nil {
|
||||
if preMasterSecret, err = prf.EcdhePSKPreMasterSecret(
|
||||
psk,
|
||||
clientKeyExchange.PublicKey,
|
||||
state.localKeypair.PrivateKey,
|
||||
state.localKeypair.Curve,
|
||||
); err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
default:
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errInvalidCipherSuite
|
||||
}
|
||||
} else {
|
||||
preMasterSecret, err = prf.PreMasterSecret(clientKeyExchange.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve)
|
||||
preMasterSecret, err = prf.PreMasterSecret(
|
||||
clientKeyExchange.PublicKey,
|
||||
state.localKeypair.PrivateKey,
|
||||
state.localKeypair.Curve,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, err
|
||||
}
|
||||
|
|
@ -140,7 +164,12 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
} else {
|
||||
state.masterSecret, err = prf.MasterSecret(preMasterSecret, clientRandom[:], serverRandom[:], state.cipherSuite.HashFunc())
|
||||
state.masterSecret, err = prf.MasterSecret(
|
||||
preMasterSecret,
|
||||
clientRandom[:],
|
||||
serverRandom[:],
|
||||
state.cipherSuite.HashFunc(),
|
||||
)
|
||||
if err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
|
|
@ -164,7 +193,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
}
|
||||
|
||||
// Now, encrypted packets can be handled
|
||||
if err := c.handleQueuedPackets(ctx); err != nil {
|
||||
if err := conn.handleQueuedPackets(ctx); err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
|
||||
|
|
@ -181,12 +210,17 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, nil
|
||||
}
|
||||
|
||||
if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeAnonymous {
|
||||
if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeAnonymous { //nolint:nestif
|
||||
if cfg.verifyConnection != nil {
|
||||
if err := cfg.verifyConnection(state.clone()); err != nil {
|
||||
stateClone, err := state.clone()
|
||||
if err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
if err := cfg.verifyConnection(stateClone); err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err
|
||||
}
|
||||
}
|
||||
|
||||
return flight6, nil, nil
|
||||
}
|
||||
|
||||
|
|
@ -210,7 +244,11 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
// go to flight6
|
||||
}
|
||||
if cfg.verifyConnection != nil {
|
||||
if err := cfg.verifyConnection(state.clone()); err != nil {
|
||||
stateClone, err := state.clone()
|
||||
if err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
if err := cfg.verifyConnection(stateClone); err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err
|
||||
}
|
||||
}
|
||||
|
|
@ -218,7 +256,13 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
|
|||
return flight6, nil, nil
|
||||
}
|
||||
|
||||
func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
|
||||
//nolint:gocognit,cyclop,maintidx
|
||||
func flight4Generate(
|
||||
_ flightConn,
|
||||
state *State,
|
||||
_ *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) ([]*packet, *alert.Alert, error) {
|
||||
extensions := []extension.Extension{&extension.RenegotiationInfo{
|
||||
RenegotiatedConnection: 0,
|
||||
}}
|
||||
|
|
@ -228,9 +272,10 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
Supported: true,
|
||||
})
|
||||
}
|
||||
if state.srtpProtectionProfile != 0 {
|
||||
if state.getSRTPProtectionProfile() != 0 {
|
||||
extensions = append(extensions, &extension.UseSRTP{
|
||||
ProtectionProfiles: []SRTPProtectionProfile{state.srtpProtectionProfile},
|
||||
ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()},
|
||||
MasterKeyIdentifier: cfg.localSRTPMasterKeyIdentifier,
|
||||
})
|
||||
}
|
||||
if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate {
|
||||
|
|
@ -250,6 +295,15 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
state.NegotiatedProtocol = selectedProto
|
||||
}
|
||||
|
||||
// If we have a connection ID generator, we are willing to use connection
|
||||
// IDs. We already know whether the client supports connection IDs from
|
||||
// parsing the ClientHello, so avoid setting local connection ID if the
|
||||
// client won't send it.
|
||||
if cfg.connectionIDGenerator != nil && state.remoteConnectionID != nil {
|
||||
state.setLocalConnectionID(cfg.connectionIDGenerator())
|
||||
extensions = append(extensions, &extension.ConnectionID{CID: state.getLocalConnectionID()})
|
||||
}
|
||||
|
||||
var pkts []*packet
|
||||
cipherSuiteID := uint16(state.cipherSuite.ID())
|
||||
|
||||
|
|
@ -260,21 +314,29 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
}
|
||||
}
|
||||
|
||||
serverHello := &handshake.MessageServerHello{
|
||||
Version: protocol.Version1_2,
|
||||
Random: state.localRandom,
|
||||
SessionID: state.SessionID,
|
||||
CipherSuiteID: &cipherSuiteID,
|
||||
CompressionMethod: defaultCompressionMethods()[0],
|
||||
Extensions: extensions,
|
||||
}
|
||||
|
||||
var content handshake.Handshake
|
||||
|
||||
if cfg.serverHelloMessageHook != nil {
|
||||
content = handshake.Handshake{Message: cfg.serverHelloMessageHook(*serverHello)}
|
||||
} else {
|
||||
content = handshake.Handshake{Message: serverHello}
|
||||
}
|
||||
|
||||
pkts = append(pkts, &packet{
|
||||
record: &recordlayer.RecordLayer{
|
||||
Header: recordlayer.Header{
|
||||
Version: protocol.Version1_2,
|
||||
},
|
||||
Content: &handshake.Handshake{
|
||||
Message: &handshake.MessageServerHello{
|
||||
Version: protocol.Version1_2,
|
||||
Random: state.localRandom,
|
||||
SessionID: state.SessionID,
|
||||
CipherSuiteID: &cipherSuiteID,
|
||||
CompressionMethod: defaultCompressionMethods()[0],
|
||||
Extensions: extensions,
|
||||
},
|
||||
},
|
||||
Content: &content,
|
||||
},
|
||||
})
|
||||
|
||||
|
|
@ -283,6 +345,7 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
certificate, err := cfg.getCertificate(&ClientHelloInfo{
|
||||
ServerName: state.serverName,
|
||||
CipherSuites: []ciphersuite.ID{state.cipherSuite.ID()},
|
||||
RandomBytes: state.remoteRandom.RandomBytes,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, err
|
||||
|
|
@ -304,13 +367,25 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
serverRandom := state.localRandom.MarshalFixed()
|
||||
clientRandom := state.remoteRandom.MarshalFixed()
|
||||
|
||||
signer, ok := certificate.PrivateKey.(crypto.Signer)
|
||||
if !ok {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errInvalidPrivateKey
|
||||
}
|
||||
|
||||
// Find compatible signature scheme
|
||||
signatureHashAlgo, err := signaturehash.SelectSignatureScheme(cfg.localSignatureSchemes, certificate.PrivateKey)
|
||||
signatureHashAlgo, err := signaturehash.SelectSignatureScheme(cfg.localSignatureSchemes, signer)
|
||||
if err != nil {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, err
|
||||
}
|
||||
|
||||
signature, err := generateKeySignature(clientRandom[:], serverRandom[:], state.localKeypair.PublicKey, state.namedCurve, certificate.PrivateKey, signatureHashAlgo.Hash)
|
||||
signature, err := generateKeySignature(
|
||||
clientRandom[:],
|
||||
serverRandom[:],
|
||||
state.localKeypair.PublicKey,
|
||||
state.namedCurve,
|
||||
signer,
|
||||
signatureHashAlgo.Hash,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
|
|
@ -342,25 +417,37 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha
|
|||
// an appropriate certificate to give to us.
|
||||
var certificateAuthorities [][]byte
|
||||
if cfg.clientCAs != nil {
|
||||
// nolint:staticcheck // ignoring tlsCert.RootCAs.Subjects is deprecated ERR because cert does not come from SystemCertPool and it's ok if certificate authorities is empty.
|
||||
// nolint:staticcheck // ignoring tlsCert.RootCAs.Subjects is deprecated ERR
|
||||
// because cert does not come from SystemCertPool and it's ok if certificate
|
||||
// authorities is empty.
|
||||
certificateAuthorities = cfg.clientCAs.Subjects()
|
||||
}
|
||||
|
||||
certReq := &handshake.MessageCertificateRequest{
|
||||
CertificateTypes: []clientcertificate.Type{clientcertificate.RSASign, clientcertificate.ECDSASign},
|
||||
SignatureHashAlgorithms: cfg.localSignatureSchemes,
|
||||
CertificateAuthoritiesNames: certificateAuthorities,
|
||||
}
|
||||
|
||||
var content handshake.Handshake
|
||||
|
||||
if cfg.certificateRequestMessageHook != nil {
|
||||
content = handshake.Handshake{Message: cfg.certificateRequestMessageHook(*certReq)}
|
||||
} else {
|
||||
content = handshake.Handshake{Message: certReq}
|
||||
}
|
||||
|
||||
pkts = append(pkts, &packet{
|
||||
record: &recordlayer.RecordLayer{
|
||||
Header: recordlayer.Header{
|
||||
Version: protocol.Version1_2,
|
||||
},
|
||||
Content: &handshake.Handshake{
|
||||
Message: &handshake.MessageCertificateRequest{
|
||||
CertificateTypes: []clientcertificate.Type{clientcertificate.RSASign, clientcertificate.ECDSASign},
|
||||
SignatureHashAlgorithms: cfg.localSignatureSchemes,
|
||||
CertificateAuthoritiesNames: certificateAuthorities,
|
||||
},
|
||||
},
|
||||
Content: &content,
|
||||
},
|
||||
})
|
||||
}
|
||||
case cfg.localPSKIdentityHint != nil || state.cipherSuite.KeyExchangeAlgorithm().Has(CipherSuiteKeyExchangeAlgorithmEcdhe):
|
||||
case cfg.localPSKIdentityHint != nil ||
|
||||
state.cipherSuite.KeyExchangeAlgorithm().Has(CipherSuiteKeyExchangeAlgorithmEcdhe):
|
||||
// To help the client in selecting which identity to use, the server
|
||||
// can provide a "PSK identity hint" in the ServerKeyExchange message.
|
||||
// If no hint is provided and cipher suite doesn't use elliptic curve,
|
||||
|
|
@ -6,14 +6,20 @@ package dtls
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
func flight5bParse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) {
|
||||
func flight5bParse(
|
||||
_ context.Context,
|
||||
_ flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
_, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-1, state.cipherSuite,
|
||||
handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, false, false},
|
||||
)
|
||||
|
|
@ -30,7 +36,12 @@ func flight5bParse(_ context.Context, _ flightConn, state *State, cache *handsha
|
|||
return flight5b, nil, nil
|
||||
}
|
||||
|
||||
func flight5bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
|
||||
func flight5bGenerate(
|
||||
_ flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) ([]*packet, *alert.Alert, error) { //nolint:gocognit
|
||||
var pkts []*packet
|
||||
|
||||
pkts = append(pkts,
|
||||
|
|
@ -9,15 +9,21 @@ import (
|
|||
"crypto"
|
||||
"crypto/x509"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/signaturehash"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/signaturehash"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) {
|
||||
func flight5Parse(
|
||||
_ context.Context,
|
||||
conn flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
_, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite,
|
||||
handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, false, false},
|
||||
)
|
||||
|
|
@ -57,7 +63,7 @@ func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshak
|
|||
Secret: state.masterSecret,
|
||||
}
|
||||
cfg.log.Tracef("[handshake] save new session: %x", s.ID)
|
||||
if err := cfg.sessionStore.Set(c.sessionKey(), s); err != nil {
|
||||
if err := cfg.sessionStore.Set(conn.sessionKey(), s); err != nil {
|
||||
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
}
|
||||
|
|
@ -65,17 +71,23 @@ func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshak
|
|||
return flight5, nil, nil
|
||||
}
|
||||
|
||||
func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
|
||||
var privateKey crypto.PrivateKey
|
||||
//nolint:gocognit,cyclop,maintidx
|
||||
func flight5Generate(
|
||||
conn flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) ([]*packet, *alert.Alert, error) {
|
||||
var signer crypto.Signer
|
||||
var pkts []*packet
|
||||
if state.remoteRequestedCertificate {
|
||||
if state.remoteRequestedCertificate { //nolint:nestif
|
||||
_, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-2, state.cipherSuite,
|
||||
handshakeCachePullRule{handshake.TypeCertificateRequest, cfg.initialEpoch, false, false})
|
||||
if !ok {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errClientCertificateRequired
|
||||
}
|
||||
reqInfo := CertificateRequestInfo{}
|
||||
if r, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok {
|
||||
if r, ok2 := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok2 {
|
||||
reqInfo.AcceptableCAs = r.CertificateAuthoritiesNames
|
||||
} else {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errClientCertificateRequired
|
||||
|
|
@ -88,7 +100,10 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errNotAcceptableCertificateChain
|
||||
}
|
||||
if certificate.Certificate != nil {
|
||||
privateKey = certificate.PrivateKey
|
||||
signer, ok = certificate.PrivateKey.(crypto.Signer)
|
||||
if !ok {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errInvalidPrivateKey
|
||||
}
|
||||
}
|
||||
pkts = append(pkts,
|
||||
&packet{
|
||||
|
|
@ -135,7 +150,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
|
||||
// handshakeMessageServerKeyExchange is optional for PSK
|
||||
if len(serverKeyExchangeData) == 0 {
|
||||
alertPtr, err := handleServerKeyExchange(c, state, cfg, &handshake.MessageServerKeyExchange{})
|
||||
alertPtr, err := handleServerKeyExchange(conn, state, cfg, &handshake.MessageServerKeyExchange{})
|
||||
if err != nil {
|
||||
return nil, alertPtr, err
|
||||
}
|
||||
|
|
@ -158,7 +173,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
|
||||
// Append not-yet-sent packets
|
||||
merged := []byte{}
|
||||
seqPred := uint16(state.handshakeSendSequence)
|
||||
seqPred := uint16(state.handshakeSendSequence) //nolint:gosec // G115
|
||||
for _, p := range pkts {
|
||||
h, ok := p.record.Content.(*handshake.Handshake)
|
||||
if !ok {
|
||||
|
|
@ -173,14 +188,14 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
merged = append(merged, raw...)
|
||||
}
|
||||
|
||||
if alertPtr, err := initalizeCipherSuite(state, cache, cfg, serverKeyExchange, merged); err != nil {
|
||||
if alertPtr, err := initializeCipherSuite(state, cache, cfg, serverKeyExchange, merged); err != nil {
|
||||
return nil, alertPtr, err
|
||||
}
|
||||
|
||||
// If the client has sent a certificate with signing ability, a digitally-signed
|
||||
// CertificateVerify message is sent to explicitly verify possession of the
|
||||
// private key in the certificate.
|
||||
if state.remoteRequestedCertificate && privateKey != nil {
|
||||
if state.remoteRequestedCertificate && signer != nil {
|
||||
plainText := append(cache.pullAndMerge(
|
||||
handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false},
|
||||
handshakeCachePullRule{handshake.TypeServerHello, cfg.initialEpoch, false, false},
|
||||
|
|
@ -193,18 +208,19 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
), merged...)
|
||||
|
||||
// Find compatible signature scheme
|
||||
signatureHashAlgo, err := signaturehash.SelectSignatureScheme(cfg.localSignatureSchemes, privateKey)
|
||||
|
||||
signatureHashAlgo, err := signaturehash.SelectSignatureScheme(state.remoteCertRequestAlgs, signer)
|
||||
if err != nil {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, err
|
||||
}
|
||||
|
||||
certVerify, err := generateCertificateVerify(plainText, privateKey, signatureHashAlgo.Hash)
|
||||
certVerify, err := generateCertificateVerify(plainText, signer, signatureHashAlgo.Hash)
|
||||
if err != nil {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
state.localCertificatesVerify = certVerify
|
||||
|
||||
p := &packet{
|
||||
pkt := &packet{
|
||||
record: &recordlayer.RecordLayer{
|
||||
Header: recordlayer.Header{
|
||||
Version: protocol.Version1_2,
|
||||
|
|
@ -218,9 +234,9 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
},
|
||||
},
|
||||
}
|
||||
pkts = append(pkts, p)
|
||||
pkts = append(pkts, pkt)
|
||||
|
||||
h, ok := p.record.Content.(*handshake.Handshake)
|
||||
h, ok := pkt.record.Content.(*handshake.Handshake)
|
||||
if !ok {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errInvalidContentType
|
||||
}
|
||||
|
|
@ -258,7 +274,11 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
)
|
||||
|
||||
var err error
|
||||
state.localVerifyData, err = prf.VerifyDataClient(state.masterSecret, append(plainText, merged...), state.cipherSuite.HashFunc())
|
||||
state.localVerifyData, err = prf.VerifyDataClient(
|
||||
state.masterSecret,
|
||||
append(plainText, merged...),
|
||||
state.cipherSuite.HashFunc(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
|
|
@ -277,6 +297,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
},
|
||||
},
|
||||
},
|
||||
shouldWrapCID: len(state.remoteConnectionID) > 0,
|
||||
shouldEncrypt: true,
|
||||
resetLocalSequenceNumber: true,
|
||||
})
|
||||
|
|
@ -284,7 +305,14 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
return pkts, nil, nil
|
||||
}
|
||||
|
||||
func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeConfig, h *handshake.MessageServerKeyExchange, sendingPlainText []byte) (*alert.Alert, error) { //nolint:gocognit
|
||||
//nolint:gocognit,cyclop
|
||||
func initializeCipherSuite(
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
handshakeKeyExchange *handshake.MessageServerKeyExchange,
|
||||
sendingPlainText []byte,
|
||||
) (*alert.Alert, error) {
|
||||
if state.cipherSuite.IsInitialized() {
|
||||
return nil, nil //nolint
|
||||
}
|
||||
|
|
@ -306,18 +334,24 @@ func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCon
|
|||
return &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, err
|
||||
}
|
||||
} else {
|
||||
state.masterSecret, err = prf.MasterSecret(state.preMasterSecret, clientRandom[:], serverRandom[:], state.cipherSuite.HashFunc())
|
||||
state.masterSecret, err = prf.MasterSecret(
|
||||
state.preMasterSecret,
|
||||
clientRandom[:],
|
||||
serverRandom[:],
|
||||
state.cipherSuite.HashFunc(),
|
||||
)
|
||||
if err != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
|
||||
}
|
||||
}
|
||||
|
||||
if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate {
|
||||
if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate { //nolint:nestif
|
||||
// Verify that the pair of hash algorithm and signiture is listed.
|
||||
var validSignatureScheme bool
|
||||
for _, ss := range cfg.localSignatureSchemes {
|
||||
if ss.Hash == h.HashAlgorithm && ss.Signature == h.SignatureAlgorithm {
|
||||
if ss.Hash == handshakeKeyExchange.HashAlgorithm && ss.Signature == handshakeKeyExchange.SignatureAlgorithm {
|
||||
validSignatureScheme = true
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -325,8 +359,19 @@ func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCon
|
|||
return &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoAvailableSignatureSchemes
|
||||
}
|
||||
|
||||
expectedMsg := valueKeyMessage(clientRandom[:], serverRandom[:], h.PublicKey, h.NamedCurve)
|
||||
if err = verifyKeySignature(expectedMsg, h.Signature, h.HashAlgorithm, state.PeerCertificates); err != nil {
|
||||
expectedMsg := valueKeyMessage(
|
||||
clientRandom[:],
|
||||
serverRandom[:],
|
||||
handshakeKeyExchange.PublicKey,
|
||||
handshakeKeyExchange.NamedCurve,
|
||||
)
|
||||
if err = verifyKeySignature(
|
||||
expectedMsg,
|
||||
handshakeKeyExchange.
|
||||
Signature,
|
||||
handshakeKeyExchange.HashAlgorithm,
|
||||
state.PeerCertificates,
|
||||
); err != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err
|
||||
}
|
||||
var chains [][]*x509.Certificate
|
||||
|
|
@ -342,8 +387,12 @@ func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCon
|
|||
}
|
||||
}
|
||||
if cfg.verifyConnection != nil {
|
||||
if err = cfg.verifyConnection(state.clone()); err != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err
|
||||
stateClone, errC := state.clone()
|
||||
if errC != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errC
|
||||
}
|
||||
if errC = cfg.verifyConnection(stateClone); errC != nil {
|
||||
return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, errC
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6,14 +6,20 @@ package dtls
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) {
|
||||
func flight6Parse(
|
||||
_ context.Context,
|
||||
_ flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error) {
|
||||
_, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-1, state.cipherSuite,
|
||||
handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, true, false},
|
||||
)
|
||||
|
|
@ -30,7 +36,12 @@ func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshak
|
|||
return flight6, nil, nil
|
||||
}
|
||||
|
||||
func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
|
||||
func flight6Generate(
|
||||
_ flightConn,
|
||||
state *State,
|
||||
cache *handshakeCache,
|
||||
cfg *handshakeConfig,
|
||||
) ([]*packet, *alert.Alert, error) {
|
||||
var pkts []*packet
|
||||
|
||||
pkts = append(pkts,
|
||||
|
|
@ -77,9 +88,11 @@ func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *han
|
|||
},
|
||||
},
|
||||
},
|
||||
shouldWrapCID: len(state.remoteConnectionID) > 0,
|
||||
shouldEncrypt: true,
|
||||
resetLocalSequenceNumber: true,
|
||||
},
|
||||
)
|
||||
|
||||
return pkts, nil, nil
|
||||
}
|
||||
|
|
@ -6,16 +6,22 @@ package dtls
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
)
|
||||
|
||||
// Parse received handshakes and return next flightVal
|
||||
type flightParser func(context.Context, flightConn, *State, *handshakeCache, *handshakeConfig) (flightVal, *alert.Alert, error)
|
||||
// Parse received handshakes and return next flightVal.
|
||||
type flightParser func(
|
||||
context.Context,
|
||||
flightConn,
|
||||
*State,
|
||||
*handshakeCache,
|
||||
*handshakeConfig,
|
||||
) (flightVal, *alert.Alert, error)
|
||||
|
||||
// Generate flights
|
||||
// Generate flights.
|
||||
type flightGenerator func(flightConn, *State, *handshakeCache, *handshakeConfig) ([]*packet, *alert.Alert, error)
|
||||
|
||||
func (f flightVal) getFlightParser() (flightParser, error) {
|
||||
func (f flightVal) getFlightParser() (flightParser, error) { //nolint:cyclop
|
||||
switch f {
|
||||
case flight0:
|
||||
return flight0Parse, nil
|
||||
|
|
@ -40,7 +46,7 @@ func (f flightVal) getFlightParser() (flightParser, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (f flightVal) getFlightGenerator() (gen flightGenerator, retransmit bool, err error) {
|
||||
func (f flightVal) getFlightGenerator() (gen flightGenerator, retransmit bool, err error) { //nolint:cyclop
|
||||
switch f {
|
||||
case flight0:
|
||||
return flight0Generate, true, nil
|
||||
|
|
@ -4,12 +4,12 @@
|
|||
package dtls
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
// 2 megabytes
|
||||
// 2 megabytes.
|
||||
const fragmentBufferMaxSize = 2000000
|
||||
|
||||
type fragment struct {
|
||||
|
|
@ -29,7 +29,7 @@ func newFragmentBuffer() *fragmentBuffer {
|
|||
return &fragmentBuffer{cache: map[uint16][]*fragment{}}
|
||||
}
|
||||
|
||||
// current total size of buffer
|
||||
// current total size of buffer.
|
||||
func (f *fragmentBuffer) size() int {
|
||||
size := 0
|
||||
for i := range f.cache {
|
||||
|
|
@ -37,32 +37,37 @@ func (f *fragmentBuffer) size() int {
|
|||
size += len(f.cache[i][j].data)
|
||||
}
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
// Attempts to push a DTLS packet to the fragmentBuffer
|
||||
// when it returns true it means the fragmentBuffer has inserted and the buffer shouldn't be handled
|
||||
// when an error returns it is fatal, and the DTLS connection should be stopped
|
||||
func (f *fragmentBuffer) push(buf []byte) (bool, error) {
|
||||
// when an error returns it is fatal, and the DTLS connection should be stopped.
|
||||
func (f *fragmentBuffer) push(buf []byte) (isHandshake, isRetransmit bool, err error) {
|
||||
if f.size()+len(buf) >= fragmentBufferMaxSize {
|
||||
return false, errFragmentBufferOverflow
|
||||
return false, false, errFragmentBufferOverflow
|
||||
}
|
||||
|
||||
frag := new(fragment)
|
||||
if err := frag.recordLayerHeader.Unmarshal(buf); err != nil {
|
||||
return false, err
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
// fragment isn't a handshake, we don't need to handle it
|
||||
if frag.recordLayerHeader.ContentType != protocol.ContentTypeHandshake {
|
||||
return false, nil
|
||||
return false, false, nil
|
||||
}
|
||||
|
||||
for buf = buf[recordlayer.HeaderSize:]; len(buf) != 0; frag = new(fragment) {
|
||||
for buf = buf[recordlayer.FixedHeaderSize:]; len(buf) != 0; frag = new(fragment) {
|
||||
if err := frag.handshakeHeader.Unmarshal(buf); err != nil {
|
||||
return false, err
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
// Fragment is a retransmission. We have already assembled it before successfully
|
||||
isRetransmit = frag.handshakeHeader.FragmentOffset == 0 &&
|
||||
frag.handshakeHeader.MessageSequence < f.currentMessageSequenceNumber
|
||||
|
||||
if _, ok := f.cache[frag.handshakeHeader.MessageSequence]; !ok {
|
||||
f.cache[frag.handshakeHeader.MessageSequence] = []*fragment{}
|
||||
}
|
||||
|
|
@ -80,7 +85,7 @@ func (f *fragmentBuffer) push(buf []byte) (bool, error) {
|
|||
buf = buf[end:]
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return true, isRetransmit, nil
|
||||
}
|
||||
|
||||
func (f *fragmentBuffer) pop() (content []byte, epoch uint16) {
|
||||
|
|
@ -104,9 +109,11 @@ func (f *fragmentBuffer) pop() (content []byte, epoch uint16) {
|
|||
}
|
||||
|
||||
rawMessage = append(f.data, rawMessage...)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -128,5 +135,6 @@ func (f *fragmentBuffer) pop() (content []byte, epoch uint16) {
|
|||
|
||||
delete(f.cache, f.currentMessageSequenceNumber)
|
||||
f.currentMessageSequenceNumber++
|
||||
|
||||
return append(rawHeader, rawMessage...), messageEpoch
|
||||
}
|
||||
|
|
@ -6,8 +6,8 @@ package dtls
|
|||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
)
|
||||
|
||||
type handshakeCacheItem struct {
|
||||
|
|
@ -49,7 +49,7 @@ func (h *handshakeCache) push(data []byte, epoch, messageSequence uint16, typ ha
|
|||
|
||||
// returns a list handshakes that match the requested rules
|
||||
// the list will contain null entries for rules that can't be satisfied
|
||||
// multiple entries may match a rule, but only the last match is returned (ie ClientHello with cookies)
|
||||
// multiple entries may match a rule, but only the last match is returned (ie ClientHello with cookies).
|
||||
func (h *handshakeCache) pull(rules ...handshakeCachePullRule) []*handshakeCacheItem {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
|
|
@ -72,15 +72,21 @@ func (h *handshakeCache) pull(rules ...handshakeCachePullRule) []*handshakeCache
|
|||
}
|
||||
|
||||
// fullPullMap pulls all handshakes between rules[0] to rules[len(rules)-1] as map.
|
||||
func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rules ...handshakeCachePullRule) (int, map[handshake.Type]handshake.Message, bool) {
|
||||
//
|
||||
//nolint:cyclop
|
||||
func (h *handshakeCache) fullPullMap(
|
||||
startSeq int,
|
||||
cipherSuite CipherSuite,
|
||||
rules ...handshakeCachePullRule,
|
||||
) (int, map[handshake.Type]handshake.Message, bool) {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
|
||||
ci := make(map[handshake.Type]*handshakeCacheItem)
|
||||
for _, r := range rules {
|
||||
for _, rule := range rules {
|
||||
var item *handshakeCacheItem
|
||||
for _, c := range h.cache {
|
||||
if c.typ == r.typ && c.isClient == r.isClient && c.epoch == r.epoch {
|
||||
if c.typ == rule.typ && c.isClient == rule.isClient && c.epoch == rule.epoch {
|
||||
switch {
|
||||
case item == nil:
|
||||
item = c
|
||||
|
|
@ -89,17 +95,18 @@ func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rule
|
|||
}
|
||||
}
|
||||
}
|
||||
if !r.optional && item == nil {
|
||||
if !rule.optional && item == nil {
|
||||
// Missing mandatory message.
|
||||
return startSeq, nil, false
|
||||
}
|
||||
ci[r.typ] = item
|
||||
ci[rule.typ] = item
|
||||
}
|
||||
out := make(map[handshake.Type]handshake.Message)
|
||||
seq := startSeq
|
||||
ok := false
|
||||
for _, r := range rules {
|
||||
t := r.typ
|
||||
i := ci[t]
|
||||
typ := r.typ
|
||||
i := ci[typ]
|
||||
if i == nil {
|
||||
continue
|
||||
}
|
||||
|
|
@ -113,17 +120,22 @@ func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rule
|
|||
if err := rawHandshake.Unmarshal(i.data); err != nil {
|
||||
return startSeq, nil, false
|
||||
}
|
||||
if uint16(seq) != rawHandshake.Header.MessageSequence {
|
||||
if uint16(seq) != rawHandshake.Header.MessageSequence { //nolint:gosec // G115
|
||||
// There is a gap. Some messages are not arrived.
|
||||
return startSeq, nil, false
|
||||
}
|
||||
seq++
|
||||
out[t] = rawHandshake.Message
|
||||
ok = true
|
||||
out[typ] = rawHandshake.Message
|
||||
}
|
||||
if !ok {
|
||||
return seq, nil, false
|
||||
}
|
||||
|
||||
return seq, out, true
|
||||
}
|
||||
|
||||
// pullAndMerge calls pull and then merges the results, ignoring any null entries
|
||||
// pullAndMerge calls pull and then merges the results, ignoring any null entries.
|
||||
func (h *handshakeCache) pullAndMerge(rules ...handshakeCachePullRule) []byte {
|
||||
merged := []byte{}
|
||||
|
||||
|
|
@ -132,6 +144,7 @@ func (h *handshakeCache) pullAndMerge(rules ...handshakeCachePullRule) []byte {
|
|||
merged = append(merged, p.data...)
|
||||
}
|
||||
}
|
||||
|
||||
return merged
|
||||
}
|
||||
|
||||
|
|
@ -12,10 +12,10 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/signaturehash"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/handshake"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/elliptic"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/signaturehash"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/alert"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/logging"
|
||||
)
|
||||
|
||||
|
|
@ -82,37 +82,42 @@ func (s handshakeState) String() string {
|
|||
}
|
||||
|
||||
type handshakeFSM struct {
|
||||
currentFlight flightVal
|
||||
flights []*packet
|
||||
retransmit bool
|
||||
state *State
|
||||
cache *handshakeCache
|
||||
cfg *handshakeConfig
|
||||
closed chan struct{}
|
||||
currentFlight flightVal
|
||||
flights []*packet
|
||||
retransmit bool
|
||||
retransmitInterval time.Duration
|
||||
state *State
|
||||
cache *handshakeCache
|
||||
cfg *handshakeConfig
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
type handshakeConfig struct {
|
||||
localPSKCallback PSKCallback
|
||||
localPSKIdentityHint []byte
|
||||
localCipherSuites []CipherSuite // Available CipherSuites
|
||||
localSignatureSchemes []signaturehash.Algorithm // Available signature schemes
|
||||
extendedMasterSecret ExtendedMasterSecretType // Policy for the Extended Master Support extension
|
||||
localSRTPProtectionProfiles []SRTPProtectionProfile // Available SRTPProtectionProfiles, if empty no SRTP support
|
||||
serverName string
|
||||
supportedProtocols []string
|
||||
clientAuth ClientAuthType // If we are a client should we request a client certificate
|
||||
localCertificates []tls.Certificate
|
||||
nameToCertificate map[string]*tls.Certificate
|
||||
insecureSkipVerify bool
|
||||
verifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
|
||||
verifyConnection func(*State) error
|
||||
sessionStore SessionStore
|
||||
rootCAs *x509.CertPool
|
||||
clientCAs *x509.CertPool
|
||||
retransmitInterval time.Duration
|
||||
customCipherSuites func() []CipherSuite
|
||||
ellipticCurves []elliptic.Curve
|
||||
insecureSkipHelloVerify bool
|
||||
localPSKCallback PSKCallback
|
||||
localPSKIdentityHint []byte
|
||||
localCipherSuites []CipherSuite // Available CipherSuites
|
||||
localSignatureSchemes []signaturehash.Algorithm // Available signature schemes
|
||||
extendedMasterSecret ExtendedMasterSecretType // Policy for the Extended Master Support extension
|
||||
localSRTPProtectionProfiles []SRTPProtectionProfile // Available SRTPProtectionProfiles, if empty no SRTP support
|
||||
localSRTPMasterKeyIdentifier []byte
|
||||
serverName string
|
||||
supportedProtocols []string
|
||||
clientAuth ClientAuthType // If we are a client should we request a client certificate
|
||||
localCertificates []tls.Certificate
|
||||
nameToCertificate map[string]*tls.Certificate
|
||||
insecureSkipVerify bool
|
||||
verifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
|
||||
verifyConnection func(*State) error
|
||||
sessionStore SessionStore
|
||||
rootCAs *x509.CertPool
|
||||
clientCAs *x509.CertPool
|
||||
initialRetransmitInterval time.Duration
|
||||
disableRetransmitBackoff bool
|
||||
customCipherSuites func() []CipherSuite
|
||||
ellipticCurves []elliptic.Curve
|
||||
insecureSkipHelloVerify bool
|
||||
connectionIDGenerator func() []byte
|
||||
helloRandomBytesGenerator func() [handshake.RandomBytesLength]byte
|
||||
|
||||
onFlightState func(flightVal, handshakeState)
|
||||
log logging.LeveledLogger
|
||||
|
|
@ -124,12 +129,18 @@ type handshakeConfig struct {
|
|||
initialEpoch uint16
|
||||
|
||||
mu sync.Mutex
|
||||
|
||||
clientHelloMessageHook func(handshake.MessageClientHello) handshake.Message
|
||||
serverHelloMessageHook func(handshake.MessageServerHello) handshake.Message
|
||||
certificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message
|
||||
|
||||
resumeState *State
|
||||
}
|
||||
|
||||
type flightConn interface {
|
||||
notify(ctx context.Context, level alert.Level, desc alert.Description) error
|
||||
writePackets(context.Context, []*packet) error
|
||||
recvHandshake() <-chan chan struct{}
|
||||
recvHandshake() <-chan recvHandshakeState
|
||||
setLocalEpoch(epoch uint16)
|
||||
handleQueuedPackets(context.Context) error
|
||||
sessionKey() []byte
|
||||
|
|
@ -151,6 +162,7 @@ func srvCliStr(isClient bool) string {
|
|||
if isClient {
|
||||
return "client"
|
||||
}
|
||||
|
||||
return "server"
|
||||
}
|
||||
|
||||
|
|
@ -159,15 +171,16 @@ func newHandshakeFSM(
|
|||
initialFlight flightVal,
|
||||
) *handshakeFSM {
|
||||
return &handshakeFSM{
|
||||
currentFlight: initialFlight,
|
||||
state: s,
|
||||
cache: cache,
|
||||
cfg: cfg,
|
||||
closed: make(chan struct{}),
|
||||
currentFlight: initialFlight,
|
||||
state: s,
|
||||
cache: cache,
|
||||
cfg: cfg,
|
||||
retransmitInterval: cfg.initialRetransmitInterval,
|
||||
closed: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *handshakeFSM) Run(ctx context.Context, c flightConn, initialState handshakeState) error {
|
||||
func (s *handshakeFSM) Run(ctx context.Context, conn flightConn, initialState handshakeState) error {
|
||||
state := initialState
|
||||
defer func() {
|
||||
close(s.closed)
|
||||
|
|
@ -180,13 +193,13 @@ func (s *handshakeFSM) Run(ctx context.Context, c flightConn, initialState hands
|
|||
var err error
|
||||
switch state {
|
||||
case handshakePreparing:
|
||||
state, err = s.prepare(ctx, c)
|
||||
state, err = s.prepare(ctx, conn)
|
||||
case handshakeSending:
|
||||
state, err = s.send(ctx, c)
|
||||
state, err = s.send(ctx, conn)
|
||||
case handshakeWaiting:
|
||||
state, err = s.wait(ctx, c)
|
||||
state, err = s.wait(ctx, conn)
|
||||
case handshakeFinished:
|
||||
state, err = s.finish(ctx, c)
|
||||
state, err = s.finish(ctx, conn)
|
||||
default:
|
||||
return errInvalidFSMTransition
|
||||
}
|
||||
|
|
@ -200,24 +213,24 @@ func (s *handshakeFSM) Done() <-chan struct{} {
|
|||
return s.closed
|
||||
}
|
||||
|
||||
func (s *handshakeFSM) prepare(ctx context.Context, c flightConn) (handshakeState, error) {
|
||||
func (s *handshakeFSM) prepare(ctx context.Context, conn flightConn) (handshakeState, error) {
|
||||
s.flights = nil
|
||||
// Prepare flights
|
||||
var (
|
||||
a *alert.Alert
|
||||
err error
|
||||
pkts []*packet
|
||||
dtlsAlert *alert.Alert
|
||||
err error
|
||||
pkts []*packet
|
||||
)
|
||||
gen, retransmit, errFlight := s.currentFlight.getFlightGenerator()
|
||||
if errFlight != nil {
|
||||
err = errFlight
|
||||
a = &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}
|
||||
dtlsAlert = &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}
|
||||
} else {
|
||||
pkts, a, err = gen(c, s.state, s.cache, s.cfg)
|
||||
pkts, dtlsAlert, err = gen(conn, s.state, s.cache, s.cfg)
|
||||
s.retransmit = retransmit
|
||||
}
|
||||
if a != nil {
|
||||
if alertErr := c.notify(ctx, a.Level, a.Description); alertErr != nil {
|
||||
if dtlsAlert != nil {
|
||||
if alertErr := conn.notify(ctx, dtlsAlert.Level, dtlsAlert.Description); alertErr != nil {
|
||||
if err != nil {
|
||||
err = alertErr
|
||||
}
|
||||
|
|
@ -236,14 +249,15 @@ func (s *handshakeFSM) prepare(ctx context.Context, c flightConn) (handshakeStat
|
|||
nextEpoch = p.record.Header.Epoch
|
||||
}
|
||||
if h, ok := p.record.Content.(*handshake.Handshake); ok {
|
||||
h.Header.MessageSequence = uint16(s.state.handshakeSendSequence)
|
||||
h.Header.MessageSequence = uint16(s.state.handshakeSendSequence) //nolint:gosec // G115
|
||||
s.state.handshakeSendSequence++
|
||||
}
|
||||
}
|
||||
if epoch != nextEpoch {
|
||||
s.cfg.log.Tracef("[handshake:%s] -> changeCipherSpec (epoch: %d)", srvCliStr(s.state.isClient), nextEpoch)
|
||||
c.setLocalEpoch(nextEpoch)
|
||||
conn.setLocalEpoch(nextEpoch)
|
||||
}
|
||||
|
||||
return handshakeSending, nil
|
||||
}
|
||||
|
||||
|
|
@ -256,28 +270,35 @@ func (s *handshakeFSM) send(ctx context.Context, c flightConn) (handshakeState,
|
|||
if s.currentFlight.isLastSendFlight() {
|
||||
return handshakeFinished, nil
|
||||
}
|
||||
|
||||
return handshakeWaiting, nil
|
||||
}
|
||||
|
||||
func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, error) { //nolint:gocognit
|
||||
func (s *handshakeFSM) wait(ctx context.Context, conn flightConn) (handshakeState, error) { //nolint:gocognit,cyclop
|
||||
parse, errFlight := s.currentFlight.getFlightParser()
|
||||
if errFlight != nil {
|
||||
if alertErr := c.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil {
|
||||
if errFlight != nil {
|
||||
return handshakeErrored, alertErr
|
||||
}
|
||||
if alertErr := conn.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil {
|
||||
return handshakeErrored, alertErr
|
||||
}
|
||||
|
||||
return handshakeErrored, errFlight
|
||||
}
|
||||
|
||||
retransmitTimer := time.NewTimer(s.cfg.retransmitInterval)
|
||||
retransmitTimer := time.NewTimer(s.retransmitInterval)
|
||||
for {
|
||||
select {
|
||||
case done := <-c.recvHandshake():
|
||||
nextFlight, alert, err := parse(ctx, c, s.state, s.cache, s.cfg)
|
||||
close(done)
|
||||
case state := <-conn.recvHandshake():
|
||||
if state.isRetransmit {
|
||||
close(state.done)
|
||||
|
||||
return handshakeSending, nil
|
||||
}
|
||||
|
||||
nextFlight, alert, err := parse(ctx, conn, s.state, s.cache, s.cfg)
|
||||
s.retransmitInterval = s.cfg.initialRetransmitInterval
|
||||
close(state.done)
|
||||
if alert != nil {
|
||||
if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil {
|
||||
if alertErr := conn.notify(ctx, alert.Level, alert.Description); alertErr != nil {
|
||||
if err != nil {
|
||||
err = alertErr
|
||||
}
|
||||
|
|
@ -289,62 +310,53 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState,
|
|||
if nextFlight == 0 {
|
||||
break
|
||||
}
|
||||
s.cfg.log.Tracef("[handshake:%s] %s -> %s", srvCliStr(s.state.isClient), s.currentFlight.String(), nextFlight.String())
|
||||
s.cfg.log.Tracef(
|
||||
"[handshake:%s] %s -> %s",
|
||||
srvCliStr(s.state.isClient),
|
||||
s.currentFlight.String(),
|
||||
nextFlight.String(),
|
||||
)
|
||||
if nextFlight.isLastRecvFlight() && s.currentFlight == nextFlight {
|
||||
return handshakeFinished, nil
|
||||
}
|
||||
s.currentFlight = nextFlight
|
||||
|
||||
return handshakePreparing, nil
|
||||
|
||||
case <-retransmitTimer.C:
|
||||
if !s.retransmit {
|
||||
return handshakeWaiting, nil
|
||||
}
|
||||
|
||||
// RFC 4347 4.2.4.1:
|
||||
// Implementations SHOULD use an initial timer value of 1 second (the minimum defined in RFC 2988 [RFC2988])
|
||||
// and double the value at each retransmission, up to no less than the RFC 2988 maximum of 60 seconds.
|
||||
if !s.cfg.disableRetransmitBackoff {
|
||||
s.retransmitInterval *= 2
|
||||
}
|
||||
if s.retransmitInterval > time.Second*60 {
|
||||
s.retransmitInterval = time.Second * 60
|
||||
}
|
||||
|
||||
return handshakeSending, nil
|
||||
case <-ctx.Done():
|
||||
s.retransmitInterval = s.cfg.initialRetransmitInterval
|
||||
|
||||
return handshakeErrored, ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *handshakeFSM) finish(ctx context.Context, c flightConn) (handshakeState, error) {
|
||||
parse, errFlight := s.currentFlight.getFlightParser()
|
||||
if errFlight != nil {
|
||||
if alertErr := c.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil {
|
||||
if errFlight != nil {
|
||||
return handshakeErrored, alertErr
|
||||
}
|
||||
}
|
||||
return handshakeErrored, errFlight
|
||||
}
|
||||
|
||||
retransmitTimer := time.NewTimer(s.cfg.retransmitInterval)
|
||||
select {
|
||||
case done := <-c.recvHandshake():
|
||||
nextFlight, alert, err := parse(ctx, c, s.state, s.cache, s.cfg)
|
||||
close(done)
|
||||
if alert != nil {
|
||||
if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil {
|
||||
if err != nil {
|
||||
err = alertErr
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return handshakeErrored, err
|
||||
}
|
||||
if nextFlight == 0 {
|
||||
break
|
||||
}
|
||||
if nextFlight.isLastRecvFlight() && s.currentFlight == nextFlight {
|
||||
case state := <-c.recvHandshake():
|
||||
close(state.done)
|
||||
if s.state.isClient {
|
||||
return handshakeFinished, nil
|
||||
} else {
|
||||
return handshakeSending, nil
|
||||
}
|
||||
<-retransmitTimer.C
|
||||
// Retransmit last flight
|
||||
return handshakeSending, nil
|
||||
|
||||
case <-ctx.Done():
|
||||
return handshakeErrored, ctx.Err()
|
||||
}
|
||||
return handshakeFinished, nil
|
||||
}
|
||||
|
|
@ -4,16 +4,23 @@
|
|||
package ciphersuite
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/clientcertificate"
|
||||
)
|
||||
|
||||
// Aes128Ccm is a base class used by multiple AES-CCM Ciphers
|
||||
// Aes128Ccm is a base class used by multiple AES-CCM Ciphers.
|
||||
type Aes128Ccm struct {
|
||||
AesCcm
|
||||
}
|
||||
|
||||
func newAes128Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, cryptoCCMTagLen ciphersuite.CCMTagLen, keyExchangeAlgorithm KeyExchangeAlgorithm, ecc bool) *Aes128Ccm {
|
||||
func newAes128Ccm(
|
||||
clientCertificateType clientcertificate.Type,
|
||||
id ID,
|
||||
psk bool,
|
||||
cryptoCCMTagLen ciphersuite.CCMTagLen,
|
||||
keyExchangeAlgorithm KeyExchangeAlgorithm,
|
||||
ecc bool,
|
||||
) *Aes128Ccm {
|
||||
return &Aes128Ccm{
|
||||
AesCcm: AesCcm{
|
||||
clientCertificateType: clientCertificateType,
|
||||
|
|
@ -26,8 +33,9 @@ func newAes128Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool,
|
|||
}
|
||||
}
|
||||
|
||||
// Init initializes the internal Cipher with keying material
|
||||
// Init initializes the internal Cipher with keying material.
|
||||
func (c *Aes128Ccm) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error {
|
||||
const prfKeyLen = 16
|
||||
|
||||
return c.AesCcm.Init(masterSecret, clientRandom, serverRandom, isClient, prfKeyLen)
|
||||
}
|
||||
|
|
@ -4,16 +4,23 @@
|
|||
package ciphersuite
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/clientcertificate"
|
||||
)
|
||||
|
||||
// Aes256Ccm is a base class used by multiple AES-CCM Ciphers
|
||||
// Aes256Ccm is a base class used by multiple AES-CCM Ciphers.
|
||||
type Aes256Ccm struct {
|
||||
AesCcm
|
||||
}
|
||||
|
||||
func newAes256Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, cryptoCCMTagLen ciphersuite.CCMTagLen, keyExchangeAlgorithm KeyExchangeAlgorithm, ecc bool) *Aes256Ccm {
|
||||
func newAes256Ccm(
|
||||
clientCertificateType clientcertificate.Type,
|
||||
id ID,
|
||||
psk bool,
|
||||
cryptoCCMTagLen ciphersuite.CCMTagLen,
|
||||
keyExchangeAlgorithm KeyExchangeAlgorithm,
|
||||
ecc bool,
|
||||
) *Aes256Ccm {
|
||||
return &Aes256Ccm{
|
||||
AesCcm: AesCcm{
|
||||
clientCertificateType: clientCertificateType,
|
||||
|
|
@ -26,8 +33,9 @@ func newAes256Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool,
|
|||
}
|
||||
}
|
||||
|
||||
// Init initializes the internal Cipher with keying material
|
||||
// Init initializes the internal Cipher with keying material.
|
||||
func (c *Aes256Ccm) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error {
|
||||
const prfKeyLen = 32
|
||||
|
||||
return c.AesCcm.Init(masterSecret, clientRandom, serverRandom, isClient, prfKeyLen)
|
||||
}
|
||||
|
|
@ -9,13 +9,13 @@ import (
|
|||
"hash"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
// AesCcm is a base class used by multiple AES-CCM Ciphers
|
||||
// AesCcm is a base class used by multiple AES-CCM Ciphers.
|
||||
type AesCcm struct {
|
||||
ccm atomic.Value // *cryptoCCM
|
||||
clientCertificateType clientcertificate.Type
|
||||
|
|
@ -26,12 +26,12 @@ type AesCcm struct {
|
|||
ecc bool
|
||||
}
|
||||
|
||||
// CertificateType returns what type of certificate this CipherSuite exchanges
|
||||
// CertificateType returns what type of certificate this CipherSuite exchanges.
|
||||
func (c *AesCcm) CertificateType() clientcertificate.Type {
|
||||
return c.clientCertificateType
|
||||
}
|
||||
|
||||
// ID returns the ID of the CipherSuite
|
||||
// ID returns the ID of the CipherSuite.
|
||||
func (c *AesCcm) ID() ID {
|
||||
return c.id
|
||||
}
|
||||
|
|
@ -40,59 +40,66 @@ func (c *AesCcm) String() string {
|
|||
return c.id.String()
|
||||
}
|
||||
|
||||
// ECC uses Elliptic Curve Cryptography
|
||||
// ECC uses Elliptic Curve Cryptography.
|
||||
func (c *AesCcm) ECC() bool {
|
||||
return c.ecc
|
||||
}
|
||||
|
||||
// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake
|
||||
// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake.
|
||||
func (c *AesCcm) KeyExchangeAlgorithm() KeyExchangeAlgorithm {
|
||||
return c.keyExchangeAlgorithm
|
||||
}
|
||||
|
||||
// HashFunc returns the hashing func for this CipherSuite
|
||||
// HashFunc returns the hashing func for this CipherSuite.
|
||||
func (c *AesCcm) HashFunc() func() hash.Hash {
|
||||
return sha256.New
|
||||
}
|
||||
|
||||
// AuthenticationType controls what authentication method is using during the handshake
|
||||
// AuthenticationType controls what authentication method is using during the handshake.
|
||||
func (c *AesCcm) AuthenticationType() AuthenticationType {
|
||||
if c.psk {
|
||||
return AuthenticationTypePreSharedKey
|
||||
}
|
||||
|
||||
return AuthenticationTypeCertificate
|
||||
}
|
||||
|
||||
// IsInitialized returns if the CipherSuite has keying material and can
|
||||
// encrypt/decrypt packets
|
||||
// encrypt/decrypt packets.
|
||||
func (c *AesCcm) IsInitialized() bool {
|
||||
return c.ccm.Load() != nil
|
||||
}
|
||||
|
||||
// Init initializes the internal Cipher with keying material
|
||||
// Init initializes the internal Cipher with keying material.
|
||||
func (c *AesCcm) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool, prfKeyLen int) error {
|
||||
const (
|
||||
prfMacLen = 0
|
||||
prfIvLen = 4
|
||||
)
|
||||
|
||||
keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc())
|
||||
keys, err := prf.GenerateEncryptionKeys(
|
||||
masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var ccm *ciphersuite.CCM
|
||||
if isClient {
|
||||
ccm, err = ciphersuite.NewCCM(c.cryptoCCMTagLen, keys.ClientWriteKey, keys.ClientWriteIV, keys.ServerWriteKey, keys.ServerWriteIV)
|
||||
ccm, err = ciphersuite.NewCCM(
|
||||
c.cryptoCCMTagLen, keys.ClientWriteKey, keys.ClientWriteIV, keys.ServerWriteKey, keys.ServerWriteIV,
|
||||
)
|
||||
} else {
|
||||
ccm, err = ciphersuite.NewCCM(c.cryptoCCMTagLen, keys.ServerWriteKey, keys.ServerWriteIV, keys.ClientWriteKey, keys.ClientWriteIV)
|
||||
ccm, err = ciphersuite.NewCCM(
|
||||
c.cryptoCCMTagLen, keys.ServerWriteKey, keys.ServerWriteIV, keys.ClientWriteKey, keys.ClientWriteIV,
|
||||
)
|
||||
}
|
||||
c.ccm.Store(ccm)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Encrypt encrypts a single TLS RecordLayer
|
||||
// Encrypt encrypts a single TLS RecordLayer.
|
||||
func (c *AesCcm) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) {
|
||||
cipherSuite, ok := c.ccm.Load().(*ciphersuite.CCM)
|
||||
if !ok {
|
||||
|
|
@ -102,12 +109,12 @@ func (c *AesCcm) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, erro
|
|||
return cipherSuite.Encrypt(pkt, raw)
|
||||
}
|
||||
|
||||
// Decrypt decrypts a single TLS RecordLayer
|
||||
func (c *AesCcm) Decrypt(raw []byte) ([]byte, error) {
|
||||
// Decrypt decrypts a single TLS RecordLayer.
|
||||
func (c *AesCcm) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) {
|
||||
cipherSuite, ok := c.ccm.Load().(*ciphersuite.CCM)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit)
|
||||
}
|
||||
|
||||
return cipherSuite.Decrypt(raw)
|
||||
return cipherSuite.Decrypt(h, raw)
|
||||
}
|
||||
|
|
@ -1,23 +1,25 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package ciphersuite provides TLS Ciphers as registered with the IANA https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
|
||||
// Package ciphersuite provides TLS Ciphers as registered with the IANA
|
||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
|
||||
package ciphersuite
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pion/dtls/v2/internal/ciphersuite/types"
|
||||
"github.com/pion/dtls/v2/pkg/protocol"
|
||||
"github.com/pion/dtls/v3/internal/ciphersuite/types"
|
||||
"github.com/pion/dtls/v3/pkg/protocol"
|
||||
)
|
||||
|
||||
var errCipherSuiteNotInit = &protocol.TemporaryError{Err: errors.New("CipherSuite has not been initialized")} //nolint:goerr113
|
||||
//nolint:goerr113
|
||||
var errCipherSuiteNotInit = &protocol.TemporaryError{Err: errors.New("CipherSuite has not been initialized")}
|
||||
|
||||
// ID is an ID for our supported CipherSuites
|
||||
// ID is an ID for our supported CipherSuites.
|
||||
type ID uint16
|
||||
|
||||
func (i ID) String() string {
|
||||
func (i ID) String() string { //nolint:cyclop
|
||||
switch i {
|
||||
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
|
||||
return "TLS_ECDHE_ECDSA_WITH_AES_128_CCM"
|
||||
|
|
@ -52,19 +54,19 @@ func (i ID) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
// Supported Cipher Suites
|
||||
// Supported Cipher Suites.
|
||||
const (
|
||||
// AES-128-CCM
|
||||
// AES-128-CCM.
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM ID = 0xc0ac //nolint:revive,stylecheck
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ID = 0xc0ae //nolint:revive,stylecheck
|
||||
|
||||
// AES-128-GCM-SHA256
|
||||
// AES-128-GCM-SHA256.
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ID = 0xc02b //nolint:revive,stylecheck
|
||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ID = 0xc02f //nolint:revive,stylecheck
|
||||
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ID = 0xc02c //nolint:revive,stylecheck
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ID = 0xc030 //nolint:revive,stylecheck
|
||||
// AES-256-CBC-SHA
|
||||
// AES-256-CBC-SHA.
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ID = 0xc00a //nolint:revive,stylecheck
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ID = 0xc014 //nolint:revive,stylecheck
|
||||
|
||||
|
|
@ -77,10 +79,10 @@ const (
|
|||
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 ID = 0xC037 //nolint:revive,stylecheck
|
||||
)
|
||||
|
||||
// AuthenticationType controls what authentication method is using during the handshake
|
||||
// AuthenticationType controls what authentication method is using during the handshake.
|
||||
type AuthenticationType = types.AuthenticationType
|
||||
|
||||
// AuthenticationType Enums
|
||||
// AuthenticationType Enums.
|
||||
const (
|
||||
AuthenticationTypeCertificate AuthenticationType = types.AuthenticationTypeCertificate
|
||||
AuthenticationTypePreSharedKey AuthenticationType = types.AuthenticationTypePreSharedKey
|
||||
|
|
@ -90,7 +92,7 @@ const (
|
|||
// KeyExchangeAlgorithm controls what exchange algorithm was chosen.
|
||||
type KeyExchangeAlgorithm = types.KeyExchangeAlgorithm
|
||||
|
||||
// KeyExchangeAlgorithm Bitmask
|
||||
// KeyExchangeAlgorithm Bitmask.
|
||||
const (
|
||||
KeyExchangeAlgorithmNone KeyExchangeAlgorithm = types.KeyExchangeAlgorithmNone
|
||||
KeyExchangeAlgorithmPsk KeyExchangeAlgorithm = types.KeyExchangeAlgorithmPsk
|
||||
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go
generated
vendored
Normal file
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ciphersuite
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v3/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/clientcertificate"
|
||||
)
|
||||
|
||||
// NewTLSEcdheEcdsaWithAes128Ccm constructs a TLS_ECDHE_ECDSA_WITH_AES_128_CCM Cipher.
|
||||
func NewTLSEcdheEcdsaWithAes128Ccm() *Aes128Ccm {
|
||||
return newAes128Ccm(
|
||||
clientcertificate.ECDSASign,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
|
||||
false,
|
||||
ciphersuite.CCMTagLength,
|
||||
KeyExchangeAlgorithmEcdhe,
|
||||
true,
|
||||
)
|
||||
}
|
||||
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go
generated
vendored
Normal file
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ciphersuite
|
||||
|
||||
import (
|
||||
"github.com/pion/dtls/v3/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/clientcertificate"
|
||||
)
|
||||
|
||||
// NewTLSEcdheEcdsaWithAes128Ccm8 creates a new TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuite.
|
||||
func NewTLSEcdheEcdsaWithAes128Ccm8() *Aes128Ccm {
|
||||
return newAes128Ccm(
|
||||
clientcertificate.ECDSASign,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
|
||||
false,
|
||||
ciphersuite.CCMTagLength8,
|
||||
KeyExchangeAlgorithmEcdhe,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
|
@ -9,33 +9,33 @@ import (
|
|||
"hash"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
// TLSEcdheEcdsaWithAes128GcmSha256 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite
|
||||
// TLSEcdheEcdsaWithAes128GcmSha256 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite.
|
||||
type TLSEcdheEcdsaWithAes128GcmSha256 struct {
|
||||
gcm atomic.Value // *cryptoGCM
|
||||
}
|
||||
|
||||
// CertificateType returns what type of certficate this CipherSuite exchanges
|
||||
// CertificateType returns what type of certficate this CipherSuite exchanges.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) CertificateType() clientcertificate.Type {
|
||||
return clientcertificate.ECDSASign
|
||||
}
|
||||
|
||||
// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake
|
||||
// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) KeyExchangeAlgorithm() KeyExchangeAlgorithm {
|
||||
return KeyExchangeAlgorithmEcdhe
|
||||
}
|
||||
|
||||
// ECC uses Elliptic Curve Cryptography
|
||||
// ECC uses Elliptic Curve Cryptography.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) ECC() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ID returns the ID of the CipherSuite
|
||||
// ID returns the ID of the CipherSuite.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) ID() ID {
|
||||
return TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
|
||||
}
|
||||
|
|
@ -44,24 +44,31 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) String() string {
|
|||
return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
|
||||
}
|
||||
|
||||
// HashFunc returns the hashing func for this CipherSuite
|
||||
// HashFunc returns the hashing func for this CipherSuite.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) HashFunc() func() hash.Hash {
|
||||
return sha256.New
|
||||
}
|
||||
|
||||
// AuthenticationType controls what authentication method is using during the handshake
|
||||
// AuthenticationType controls what authentication method is using during the handshake.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) AuthenticationType() AuthenticationType {
|
||||
return AuthenticationTypeCertificate
|
||||
}
|
||||
|
||||
// IsInitialized returns if the CipherSuite has keying material and can
|
||||
// encrypt/decrypt packets
|
||||
// encrypt/decrypt packets.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) IsInitialized() bool {
|
||||
return c.gcm.Load() != nil
|
||||
}
|
||||
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) init(masterSecret, clientRandom, serverRandom []byte, isClient bool, prfMacLen, prfKeyLen, prfIvLen int, hashFunc func() hash.Hash) error {
|
||||
keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, hashFunc)
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) init(
|
||||
masterSecret, clientRandom, serverRandom []byte,
|
||||
isClient bool,
|
||||
prfMacLen, prfKeyLen, prfIvLen int,
|
||||
hashFunc func() hash.Hash,
|
||||
) error {
|
||||
keys, err := prf.GenerateEncryptionKeys(
|
||||
masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, hashFunc,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -73,10 +80,11 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) init(masterSecret, clientRandom, serv
|
|||
gcm, err = ciphersuite.NewGCM(keys.ServerWriteKey, keys.ServerWriteIV, keys.ClientWriteKey, keys.ClientWriteIV)
|
||||
}
|
||||
c.gcm.Store(gcm)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Init initializes the internal Cipher with keying material
|
||||
// Init initializes the internal Cipher with keying material.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error {
|
||||
const (
|
||||
prfMacLen = 0
|
||||
|
|
@ -87,7 +95,7 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) Init(masterSecret, clientRandom, serv
|
|||
return c.init(masterSecret, clientRandom, serverRandom, isClient, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc())
|
||||
}
|
||||
|
||||
// Encrypt encrypts a single TLS RecordLayer
|
||||
// Encrypt encrypts a single TLS RecordLayer.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) {
|
||||
cipherSuite, ok := c.gcm.Load().(*ciphersuite.GCM)
|
||||
if !ok {
|
||||
|
|
@ -97,12 +105,12 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) Encrypt(pkt *recordlayer.RecordLayer,
|
|||
return cipherSuite.Encrypt(pkt, raw)
|
||||
}
|
||||
|
||||
// Decrypt decrypts a single TLS RecordLayer
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) Decrypt(raw []byte) ([]byte, error) {
|
||||
// Decrypt decrypts a single TLS RecordLayer.
|
||||
func (c *TLSEcdheEcdsaWithAes128GcmSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) {
|
||||
cipherSuite, ok := c.gcm.Load().(*ciphersuite.GCM)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit)
|
||||
}
|
||||
|
||||
return cipherSuite.Decrypt(raw)
|
||||
return cipherSuite.Decrypt(h, raw)
|
||||
}
|
||||
|
|
@ -10,33 +10,33 @@ import (
|
|||
"hash"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v2/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/ciphersuite"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/clientcertificate"
|
||||
"github.com/pion/dtls/v3/pkg/crypto/prf"
|
||||
"github.com/pion/dtls/v3/pkg/protocol/recordlayer"
|
||||
)
|
||||
|
||||
// TLSEcdheEcdsaWithAes256CbcSha represents a TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuite
|
||||
// TLSEcdheEcdsaWithAes256CbcSha represents a TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuite.
|
||||
type TLSEcdheEcdsaWithAes256CbcSha struct {
|
||||
cbc atomic.Value // *cryptoCBC
|
||||
}
|
||||
|
||||
// CertificateType returns what type of certficate this CipherSuite exchanges
|
||||
// CertificateType returns what type of certficate this CipherSuite exchanges.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) CertificateType() clientcertificate.Type {
|
||||
return clientcertificate.ECDSASign
|
||||
}
|
||||
|
||||
// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake
|
||||
// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) KeyExchangeAlgorithm() KeyExchangeAlgorithm {
|
||||
return KeyExchangeAlgorithmEcdhe
|
||||
}
|
||||
|
||||
// ECC uses Elliptic Curve Cryptography
|
||||
// ECC uses Elliptic Curve Cryptography.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) ECC() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ID returns the ID of the CipherSuite
|
||||
// ID returns the ID of the CipherSuite.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) ID() ID {
|
||||
return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
|
||||
}
|
||||
|
|
@ -45,23 +45,23 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) String() string {
|
|||
return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"
|
||||
}
|
||||
|
||||
// HashFunc returns the hashing func for this CipherSuite
|
||||
// HashFunc returns the hashing func for this CipherSuite.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) HashFunc() func() hash.Hash {
|
||||
return sha256.New
|
||||
}
|
||||
|
||||
// AuthenticationType controls what authentication method is using during the handshake
|
||||
// AuthenticationType controls what authentication method is using during the handshake.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) AuthenticationType() AuthenticationType {
|
||||
return AuthenticationTypeCertificate
|
||||
}
|
||||
|
||||
// IsInitialized returns if the CipherSuite has keying material and can
|
||||
// encrypt/decrypt packets
|
||||
// encrypt/decrypt packets.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) IsInitialized() bool {
|
||||
return c.cbc.Load() != nil
|
||||
}
|
||||
|
||||
// Init initializes the internal Cipher with keying material
|
||||
// Init initializes the internal Cipher with keying material.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error {
|
||||
const (
|
||||
prfMacLen = 20
|
||||
|
|
@ -69,7 +69,9 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverR
|
|||
prfIvLen = 16
|
||||
)
|
||||
|
||||
keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc())
|
||||
keys, err := prf.GenerateEncryptionKeys(
|
||||
masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -93,7 +95,7 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverR
|
|||
return err
|
||||
}
|
||||
|
||||
// Encrypt encrypts a single TLS RecordLayer
|
||||
// Encrypt encrypts a single TLS RecordLayer.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) {
|
||||
cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC)
|
||||
if !ok {
|
||||
|
|
@ -103,12 +105,12 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Encrypt(pkt *recordlayer.RecordLayer, ra
|
|||
return cipherSuite.Encrypt(pkt, raw)
|
||||
}
|
||||
|
||||
// Decrypt decrypts a single TLS RecordLayer
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) Decrypt(raw []byte) ([]byte, error) {
|
||||
// Decrypt decrypts a single TLS RecordLayer.
|
||||
func (c *TLSEcdheEcdsaWithAes256CbcSha) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) {
|
||||
cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit)
|
||||
}
|
||||
|
||||
return cipherSuite.Decrypt(raw)
|
||||
return cipherSuite.Decrypt(h, raw)
|
||||
}
|
||||
|
|
@ -8,12 +8,12 @@ import (
|
|||
"hash"
|
||||
)
|
||||
|
||||
// TLSEcdheEcdsaWithAes256GcmSha384 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite
|
||||
// TLSEcdheEcdsaWithAes256GcmSha384 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite.
|
||||
type TLSEcdheEcdsaWithAes256GcmSha384 struct {
|
||||
TLSEcdheEcdsaWithAes128GcmSha256
|
||||
}
|
||||
|
||||
// ID returns the ID of the CipherSuite
|
||||
// ID returns the ID of the CipherSuite.
|
||||
func (c *TLSEcdheEcdsaWithAes256GcmSha384) ID() ID {
|
||||
return TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
|
||||
}
|
||||
|
|
@ -22,12 +22,12 @@ func (c *TLSEcdheEcdsaWithAes256GcmSha384) String() string {
|
|||
return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
|
||||
}
|
||||
|
||||
// HashFunc returns the hashing func for this CipherSuite
|
||||
// HashFunc returns the hashing func for this CipherSuite.
|
||||
func (c *TLSEcdheEcdsaWithAes256GcmSha384) HashFunc() func() hash.Hash {
|
||||
return sha512.New384
|
||||
}
|
||||
|
||||
// Init initializes the internal Cipher with keying material
|
||||
// Init initializes the internal Cipher with keying material.
|
||||
func (c *TLSEcdheEcdsaWithAes256GcmSha384) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error {
|
||||
const (
|
||||
prfMacLen = 0
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user