├── .gitignore ├── turn_bench ├── get_cred.sh ├── go.mod ├── bench_seq.sh ├── bench.sh ├── go.sum └── main.go ├── stun_bench ├── pion_bench │ ├── go.mod │ ├── go.sum │ └── stun_test.go └── aiortc_stun_bench.ipynb └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints/ 2 | turn_bench/turn_bench 3 | *.txt -------------------------------------------------------------------------------- /turn_bench/get_cred.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -X POST "https://videoroom5.membrane.ovh/?service=turn&username=johnsmith"| jq -r '. | .username + "=" + .password' 3 | #username=$(jq ".username .password" $ret) 4 | #password=$(jq '.password' $ret) 5 | #echo "$username=$password" 6 | -------------------------------------------------------------------------------- /stun_bench/pion_bench/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/stunbench 2 | 3 | go 1.23 4 | 5 | require ( 6 | github.com/pion/dtls/v2 v2.2.7 // indirect 7 | github.com/pion/logging v0.2.2 // indirect 8 | github.com/pion/stun v0.6.1 // indirect 9 | github.com/pion/transport/v2 v2.2.1 // indirect 10 | golang.org/x/crypto v0.8.0 // indirect 11 | golang.org/x/sys v0.7.0 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /turn_bench/go.mod: -------------------------------------------------------------------------------- 1 | module turn_bench 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/pion/dtls/v2 v2.2.7 // indirect 7 | github.com/pion/logging v0.2.2 // indirect 8 | github.com/pion/randutil v0.1.0 // indirect 9 | github.com/pion/stun v0.6.1 // indirect 10 | github.com/pion/transport/v2 v2.2.1 // indirect 11 | github.com/pion/turn/v2 v2.1.3 // indirect 12 | golang.org/x/crypto v0.8.0 // indirect 13 | golang.org/x/sys v0.9.0 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /turn_bench/bench_seq.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | USAGE=" 4 | Usage: $(basename "$0") [options] turn-server-ip = 5 | 6 | where: 7 | -h show this help text 8 | -s UDP datagram size in bytes 9 | -d session duration in seconds 10 | -t test duration in seconds 11 | -b bitrate in kbps 12 | 13 | Example: $(basename "$0") -b 100 -t1201 127.0.0.1 john=password 14 | " 15 | 16 | PACKET_SIZE=100 17 | DURATION=60 18 | SESSIONS=1 19 | BITRATE=50 20 | TESTDURATION=30 21 | 22 | while getopts ":hc:s:d:n:b:t:" opt; do 23 | case $opt in 24 | h) 25 | echo "$USAGE" 26 | exit 27 | ;; 28 | s) 29 | PACKET_SIZE="$OPTARG" 30 | ;; 31 | d) 32 | DURATION="$OPTARG" 33 | ;; 34 | t) 35 | TESTDURATION="$OPTARG" 36 | ;; 37 | n) 38 | SESSIONS="$OPTARG" 39 | ;; 40 | b) 41 | BITRATE="$OPTARG" 42 | ;; 43 | :) 44 | echo "missing argument for -$OPTARG" 45 | exit 46 | esac 47 | done 48 | 49 | shift $((OPTIND -1)) 50 | 51 | if [ $# -ne 2 ] 52 | then 53 | echo "Bad number of positional arguments. Expected: 2, got: $# $*. Were TURN IP and credentials passed?" 54 | echo "$USAGE" 55 | exit 1 56 | fi 57 | 58 | TURN_IP=$1 59 | CREDENTIALS=$2 60 | 61 | echo " 62 | Runing TURN benchmark with the following configuration 63 | TURN_IP=$TURN_IP 64 | CREDENTIALS=$CREDENTIALS 65 | SESSIONS=$SESSIONS 66 | BITRATE=$BITRATE kbps 67 | DURATION=$DURATION s 68 | TESTDURATION=$TESTDURATION s 69 | PACKET_SIZE=$PACKET_SIZE bytes 70 | " 71 | 72 | i=0 73 | while [ $i -le $TESTDURATION ] 74 | do 75 | ./turn_bench -host $TURN_IP -user $CREDENTIALS -packetSize $PACKET_SIZE -bitrate $BITRATE -duration $DURATION 76 | i=$(( $i + $DURATION )); 77 | done -------------------------------------------------------------------------------- /turn_bench/bench.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | USAGE=" 4 | Usage: $(basename "$0") [options] turn-server-ip = 5 | 6 | where: 7 | -h show this help text 8 | -s UDP datagram size in bytes 9 | -d session duration in seconds 10 | -n number of sessions 11 | -b bitrate in kbps 12 | 13 | Example: $(basename "$0") -b 100 -n 10 127.0.0.1 john=password 14 | " 15 | 16 | PACKET_SIZE=100 17 | DURATION=60 18 | SESSIONS=1 19 | BITRATE=50 20 | 21 | while getopts ":hc:s:d:n:b:" opt; do 22 | case $opt in 23 | h) 24 | echo "$USAGE" 25 | exit 26 | ;; 27 | s) 28 | PACKET_SIZE="$OPTARG" 29 | ;; 30 | d) 31 | DURATION="$OPTARG" 32 | ;; 33 | n) 34 | SESSIONS="$OPTARG" 35 | ;; 36 | b) 37 | BITRATE="$OPTARG" 38 | ;; 39 | :) 40 | echo "missing argument for -$OPTARG" 41 | exit 42 | esac 43 | done 44 | 45 | shift $((OPTIND -1)) 46 | 47 | if [ $# -ne 2 ] 48 | then 49 | echo "Bad number of positional arguments. Expected: 2, got: $# $*. Were TURN IP and credentials passed?" 50 | echo "$USAGE" 51 | exit 1 52 | fi 53 | 54 | TURN_IP=$1 55 | CREDENTIALS=$2 56 | 57 | echo " 58 | Runing TURN benchmark with the following configuration 59 | TURN_IP=$TURN_IP 60 | CREDENTIALS=$CREDENTIALS 61 | SESSIONS=$SESSIONS 62 | BITRATE=$BITRATE kbps 63 | DURATION=$DURATION s 64 | PACKET_SIZE=$PACKET_SIZE bytes 65 | " 66 | 67 | # Use () i.e. subshell to spawn everything within it and trap ctrl+c 68 | # to shutdown all tasks, see https://stackoverflow.com/a/52033580/9620900 69 | ( 70 | trap 'kill 0' SIGINT; 71 | for ((i=0; i < $SESSIONS; i++)); do 72 | echo "Starting session $i" 73 | ./turn_bench -host $TURN_IP \ 74 | -user $CREDENTIALS \ 75 | -packetSize $PACKET_SIZE \ 76 | -bitrate $BITRATE \ 77 | -duration $DURATION & 78 | sleep 0.05 79 | done 80 | wait $(jobs -p) 81 | ) 82 | 83 | -------------------------------------------------------------------------------- /stun_bench/pion_bench/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= 4 | github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= 5 | github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= 6 | github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= 7 | github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= 8 | github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= 9 | github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= 10 | github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= 11 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 12 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 13 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 14 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 15 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 16 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 17 | github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 18 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 19 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 20 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 21 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 22 | golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= 23 | golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= 24 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 25 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 26 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 27 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 28 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 29 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 30 | golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= 31 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 32 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 33 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 34 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 35 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 36 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 37 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 39 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 40 | golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= 41 | golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 42 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 43 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 44 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 45 | golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= 46 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 47 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 48 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 49 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 50 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 51 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 52 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 53 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 54 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 55 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 56 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 57 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 58 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 59 | -------------------------------------------------------------------------------- /turn_bench/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= 4 | github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= 5 | github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= 6 | github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= 7 | github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= 8 | github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= 9 | github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= 10 | github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= 11 | github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= 12 | github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= 13 | github.com/pion/turn/v2 v2.1.3 h1:pYxTVWG2gpC97opdRc5IGsQ1lJ9O/IlNhkzj7MMrGAA= 14 | github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= 15 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 16 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 17 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 18 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 19 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 20 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 21 | github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 22 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 23 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 24 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 25 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 26 | golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= 27 | golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= 28 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 29 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 30 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 31 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 32 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 33 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 34 | golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= 35 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 36 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 37 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 38 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 39 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 40 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 41 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 42 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 43 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 44 | golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 45 | golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= 46 | golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 47 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 48 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 49 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 50 | golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= 51 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 52 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 53 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 54 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 55 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 56 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 57 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 58 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 59 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 60 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 61 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 62 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 63 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 64 | -------------------------------------------------------------------------------- /turn_bench/main.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Pion community 2 | // SPDX-License-Identifier: MIT 3 | 4 | // Package main implements a TURN client using UDP 5 | package main 6 | 7 | import ( 8 | "crypto/rand" 9 | "flag" 10 | "fmt" 11 | "log" 12 | "net" 13 | "strings" 14 | "time" 15 | 16 | "github.com/pion/logging" 17 | "github.com/pion/turn/v2" 18 | ) 19 | 20 | var packetSend, packerReeceived int; 21 | 22 | func main() { 23 | host := flag.String("host", "", "TURN Server name.") 24 | port := flag.Int("port", 3478, "Listening port.") 25 | user := flag.String("user", "", "A pair of username and password (e.g. \"user=pass\")") 26 | realm := flag.String("realm", "pion.ly", "Realm (defaults to \"pion.ly\")") 27 | bitrate := flag.Int("bitrate", 50, "bitrate in kbps") 28 | dur := flag.Int("duration", 30, "time in seconds") 29 | packetSize := flag.Int("packetSize", 50, "UDP datagram size in bytes") 30 | 31 | flag.Parse() 32 | 33 | if len(*host) == 0 { 34 | log.Fatalf("'host' is required") 35 | } 36 | 37 | if len(*user) == 0 { 38 | log.Fatalf("'user' is required") 39 | } 40 | 41 | cred := strings.SplitN(*user, "=", 2) 42 | 43 | // TURN client won't create a local listening socket by itself. 44 | conn, err := net.ListenPacket("udp4", "0.0.0.0:0") 45 | if err != nil { 46 | log.Panicf("Failed to listen: %s", err) 47 | } 48 | defer func() { 49 | if closeErr := conn.Close(); closeErr != nil { 50 | log.Panicf("Failed to close connection: %s", closeErr) 51 | } 52 | }() 53 | 54 | turnServerAddr := fmt.Sprintf("%s:%d", *host, *port) 55 | 56 | cfg := &turn.ClientConfig{ 57 | STUNServerAddr: turnServerAddr, 58 | TURNServerAddr: turnServerAddr, 59 | Conn: conn, 60 | Username: cred[0], 61 | Password: cred[1], 62 | Realm: *realm, 63 | LoggerFactory: logging.NewDefaultLoggerFactory(), 64 | } 65 | 66 | client, err := turn.NewClient(cfg) 67 | if err != nil { 68 | log.Panicf("Failed to create TURN client: %s", err) 69 | } 70 | defer client.Close() 71 | 72 | // Start listening on the conn provided. 73 | err = client.Listen() 74 | if err != nil { 75 | log.Panicf("Failed to listen: %s", err) 76 | } 77 | 78 | // Allocate a relay socket on the TURN server. On success, it 79 | // will return a net.PacketConn which represents the remote 80 | // socket. 81 | relayConn, err := client.Allocate() 82 | if err != nil { 83 | log.Panicf("Failed to allocate: %s", err) 84 | } 85 | defer func() { 86 | if closeErr := relayConn.Close(); closeErr != nil { 87 | log.Panicf("Failed to close connection: %s", closeErr) 88 | } 89 | }() 90 | 91 | // The relayConn's local address is actually the transport 92 | // address assigned on the TURN server. 93 | log.Printf("relayed-address=%s", relayConn.LocalAddr().String()) 94 | 95 | packetSend = 0; 96 | packerReeceived = 0; 97 | err = doPingTest(client, relayConn, *bitrate, *dur, *packetSize) 98 | if err != nil { 99 | log.Panicf("Failed to ping: %s", err) 100 | } 101 | } 102 | 103 | func doPingTest(client *turn.Client, relayConn net.PacketConn, bitrate int, dur int, packetSize int) error { 104 | // Send BindingRequest to learn our external IP 105 | mappedAddr, err := client.SendBindingRequest() 106 | if err != nil { 107 | return err 108 | } 109 | 110 | // Set up pinger socket (pingerConn) 111 | pingerConn, err := net.ListenPacket("udp4", "0.0.0.0:0") 112 | if err != nil { 113 | log.Panicf("Failed to listen: %s", err) 114 | } 115 | defer func() { 116 | if closeErr := pingerConn.Close(); closeErr != nil { 117 | log.Panicf("Failed to close connection: %s", closeErr) 118 | } 119 | }() 120 | 121 | // Punch a UDP hole for the relayConn by sending a data to the mappedAddr. 122 | // This will trigger a TURN client to generate a permission request to the 123 | // TURN server. After this, packets from the IP address will be accepted by 124 | // the TURN server. 125 | _, err = relayConn.WriteTo([]byte("Hello"), mappedAddr) 126 | if err != nil { 127 | return err 128 | } 129 | 130 | // Start read-loop on pingerConn 131 | go func() { 132 | buf := make([]byte, 1600) 133 | for { 134 | _, _, pingerErr := pingerConn.ReadFrom(buf) 135 | if pingerErr != nil { 136 | break 137 | } 138 | packerReeceived++; 139 | //log.Printf("%d bytes from %s \n", n, from.String()) 140 | //fmt.Printf(".") 141 | //msg := string(buf[:n]) 142 | //if sentAt, pingerErr := time.Parse(time.RFC3339Nano, msg); pingerErr == nil { 143 | // rtt := time.Since(sentAt) 144 | // log.Printf("%d bytes from from %s time=%d ms\n", n, from.String(), int(rtt.Seconds()*1000)) 145 | //} 146 | } 147 | }() 148 | 149 | // Start read-loop on relayConn 150 | go func() { 151 | buf := make([]byte, 1600) 152 | for { 153 | n, from, readerErr := relayConn.ReadFrom(buf) 154 | if readerErr != nil { 155 | break 156 | } 157 | 158 | // Echo back 159 | if _, readerErr = relayConn.WriteTo(buf[:n], from); readerErr != nil { 160 | break 161 | } 162 | } 163 | }() 164 | 165 | time.Sleep(500 * time.Millisecond) 166 | 167 | // calculate how many packets we need to send and their interval 168 | // we add 8 for UDP datagram header and 20 for ip packet header 169 | numOfPacketsToSend := bitrate * 1000 * dur / ((packetSize + 20 + 8) * 8) 170 | interval := dur * 1000 / numOfPacketsToSend 171 | 172 | // prepare random data 173 | buf := make([]byte, packetSize) 174 | _, err = rand.Read(buf) 175 | if err != nil { 176 | return err 177 | } 178 | 179 | for i := 0; i < numOfPacketsToSend; i++ { 180 | 181 | _, err = pingerConn.WriteTo(buf, relayConn.LocalAddr()) 182 | if err != nil { 183 | return err 184 | } 185 | packetSend++; 186 | time.Sleep(time.Duration(interval) * time.Millisecond) 187 | } 188 | fmt.Printf("\n") 189 | 190 | time.Sleep(1000 * time.Millisecond) 191 | 192 | log.Printf("PacketSended %d - PacketReceived %d - loss-rate %f \n",packetSend ,packerReeceived, (100.0*(float64((packetSend-packerReeceived))/float64(packetSend)) ) ) 193 | 194 | return nil 195 | } 196 | -------------------------------------------------------------------------------- /stun_bench/aiortc_stun_bench.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "id": "2b86567f-1f34-4314-bcf2-02b04eb123c4", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import aioice.stun as stun\n", 11 | "import aioice.utils as utils\n", 12 | "import timeit\n", 13 | "\n", 14 | "fix_t_id = utils.random_transaction_id()\n", 15 | "fix_st_key = bytes(\"somekey\", \"utf-8\")\n", 16 | "\n", 17 | "def full_msg_enc():\n", 18 | " fix_full_msg = stun.Message(transaction_id=fix_t_id, message_method=stun.Method.BINDING, message_class=stun.Class.RESPONSE)\n", 19 | " fix_full_msg.attributes[\"USERNAME\"] = \"someusername\"\n", 20 | " fix_full_msg.attributes[\"REALM\"] = \"somerealm\"\n", 21 | " fix_full_msg.attributes[\"XOR-MAPPED-ADDRESS\"] = (\"127.0.0.1\", 1234)\n", 22 | " fix_full_msg.add_message_integrity(fix_st_key)\n", 23 | " return bytes(fix_full_msg)\n", 24 | "\n", 25 | "def full_msg_dec():\n", 26 | " return stun.parse_message(fix_full_msg)\n", 27 | "\n", 28 | "def binding_request_enc():\n", 29 | " return bytes(stun.Message(message_method=stun.Method.BINDING, message_class=stun.Class.REQUEST))\n", 30 | "\n", 31 | "def binding_request_dec():\n", 32 | " return stun.parse_message(fix_binding_request)\n", 33 | "\n", 34 | "def binding_response_enc():\n", 35 | " binding_response = stun.Message(transaction_id=fix_t_id, message_method=stun.Method.BINDING, message_class=stun.Class.RESPONSE)\n", 36 | " binding_response.attributes[\"XOR-MAPPED-ADDRESS\"] = (\"127.0.0.1\", 1234)\n", 37 | " return bytes(binding_response)\n", 38 | "\n", 39 | "def binding_response_dec():\n", 40 | " return stun.parse_message(fix_binding_response)\n", 41 | "\n", 42 | "def full_msg_auth_with_fin():\n", 43 | " return stun.parse_message(fix_full_msg, fix_st_key)\n", 44 | "\n", 45 | "def type_enc():\n", 46 | " return stun.Method.BINDING | stun.Class.RESPONSE\n", 47 | "\n", 48 | "def type_dec():\n", 49 | " return (stun.Method(fix_msg_type & 0x3EEF), stun.Class(fix_msg_type & 0x0110))\n", 50 | "\n", 51 | "def error_code_enc():\n", 52 | " return stun.pack_error_code((438, \"Stale Nonce\"))\n", 53 | "\n", 54 | "def error_code_dec():\n", 55 | " return stun.unpack_error_code(fix_error_code)\n", 56 | "\n", 57 | "def software_enc():\n", 58 | " return stun.pack_string(\"software\")\n", 59 | "\n", 60 | "def software_dec():\n", 61 | " return stun.unpack_string(fix_software)\n", 62 | "\n", 63 | "def xor_mapped_address_enc():\n", 64 | " return stun.pack_xor_address((\"127.0.0.1\", 1234), fix_t_id)\n", 65 | "\n", 66 | "def xor_mapped_address_dec():\n", 67 | " return stun.unpack_xor_address(fix_xor_mapped_address, fix_t_id)\n", 68 | "\n", 69 | "\n", 70 | "fix_binding_request = binding_request_enc()\n", 71 | "fix_full_msg = full_msg_enc()\n", 72 | "fix_binding_response = binding_response_enc()\n", 73 | "fix_msg_type = type_enc()\n", 74 | "fix_error_code = error_code_enc()\n", 75 | "fix_software = software_enc()\n", 76 | "fix_xor_mapped_address = xor_mapped_address_enc()" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 30, 82 | "id": "ed407849-55cc-4e61-b33b-3912ed84eb58", 83 | "metadata": {}, 84 | "outputs": [ 85 | { 86 | "name": "stdout", 87 | "output_type": "stream", 88 | "text": [ 89 | "full_msg_enc\n", 90 | "11.7 µs ± 35.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n", 91 | "full_msg_dec\n", 92 | "4.31 µs ± 29.1 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n", 93 | "binding_request_enc\n", 94 | "705 ns ± 2.16 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n", 95 | "binding_request_dec\n", 96 | "742 ns ± 5.24 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n", 97 | "binding_response_enc\n", 98 | "2.67 µs ± 33.4 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n", 99 | "binding_response_dec\n", 100 | "2.64 µs ± 13.3 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n", 101 | "full_msg_auth_with_fin\n", 102 | "5.65 µs ± 33.3 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n", 103 | "type_enc\n", 104 | "80.6 ns ± 0.272 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)\n", 105 | "type_dec\n", 106 | "346 ns ± 0.848 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n", 107 | "error_code_enc\n", 108 | "107 ns ± 0.699 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)\n", 109 | "error_code_dec\n", 110 | "156 ns ± 0.907 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)\n", 111 | "software_enc\n", 112 | "44.3 ns ± 0.106 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)\n", 113 | "software_dec\n", 114 | "49 ns ± 1.44 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)\n", 115 | "xor_mapped_address_enc\n", 116 | "1.77 µs ± 6.79 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n", 117 | "xor_mapped_address_dec\n", 118 | "1.4 µs ± 3.82 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n" 119 | ] 120 | } 121 | ], 122 | "source": [ 123 | "funcs = [\n", 124 | " full_msg_enc,\n", 125 | " full_msg_dec,\n", 126 | " binding_request_enc,\n", 127 | " binding_request_dec,\n", 128 | " binding_response_enc,\n", 129 | " binding_response_dec,\n", 130 | " full_msg_auth_with_fin,\n", 131 | " type_enc,\n", 132 | " type_dec,\n", 133 | " error_code_enc,\n", 134 | " error_code_dec,\n", 135 | " software_enc,\n", 136 | " software_dec,\n", 137 | " xor_mapped_address_enc,\n", 138 | " xor_mapped_address_dec\n", 139 | "]\n", 140 | " \n", 141 | "for f in funcs:\n", 142 | " print(f.__name__)\n", 143 | " %timeit f()" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": null, 149 | "id": "948400e8-b816-4b88-81be-3e37f88bb4e0", 150 | "metadata": {}, 151 | "outputs": [], 152 | "source": [] 153 | } 154 | ], 155 | "metadata": { 156 | "kernelspec": { 157 | "display_name": "Python 3 (ipykernel)", 158 | "language": "python", 159 | "name": "python3" 160 | }, 161 | "language_info": { 162 | "codemirror_mode": { 163 | "name": "ipython", 164 | "version": 3 165 | }, 166 | "file_extension": ".py", 167 | "mimetype": "text/x-python", 168 | "name": "python", 169 | "nbconvert_exporter": "python", 170 | "pygments_lexer": "ipython3", 171 | "version": "3.11.3" 172 | } 173 | }, 174 | "nbformat": 4, 175 | "nbformat_minor": 5 176 | } 177 | -------------------------------------------------------------------------------- /stun_bench/pion_bench/stun_test.go: -------------------------------------------------------------------------------- 1 | package stunbench 2 | 3 | import ( 4 | "encoding/base64" 5 | "encoding/hex" 6 | "net" 7 | "testing" 8 | 9 | "github.com/pion/stun" 10 | ) 11 | 12 | func BenchmarkBindingRequestEncode(b *testing.B) { 13 | b.ReportAllocs() 14 | for i := 0; i < b.N; i++ { 15 | stun.MustBuild(stun.BindingRequest, stun.TransactionID) 16 | } 17 | } 18 | 19 | func BenchmarkBindingRequestDecode(b *testing.B) { 20 | b.ReportAllocs() 21 | bindingRequest := stun.MustBuild(stun.BindingRequest, stun.TransactionID) 22 | m := stun.New() 23 | b.ResetTimer() 24 | for i := 0; i < b.N; i++ { 25 | m.Reset() 26 | if err := stun.Decode(bindingRequest.Raw, m); err != nil { 27 | b.Fatal(err) 28 | } 29 | } 30 | 31 | } 32 | 33 | func BenchmarkBindingResponseEncode(b *testing.B) { 34 | b.ReportAllocs() 35 | tID := stun.NewTransactionID() 36 | b.ResetTimer() 37 | for i := 0; i < b.N; i++ { 38 | stun.MustBuild(stun.BindingSuccess, stun.NewTransactionIDSetter(tID), 39 | &stun.XORMappedAddress{IP: net.IPv4(213, 1, 223, 5), Port: 1234}) 40 | } 41 | } 42 | 43 | func BenchmarkBindingResponseDecode(b *testing.B) { 44 | b.ReportAllocs() 45 | tID := stun.NewTransactionID() 46 | bindingResponse := stun.MustBuild(stun.BindingSuccess, stun.NewTransactionIDSetter(tID), 47 | &stun.XORMappedAddress{IP: net.IPv4(213, 1, 223, 5), Port: 1234}) 48 | m := stun.New() 49 | b.ResetTimer() 50 | for i := 0; i < b.N; i++ { 51 | m.Reset() 52 | if err := stun.Decode(bindingResponse.Raw, m); err != nil { 53 | b.Fatal(err) 54 | } 55 | } 56 | } 57 | 58 | func BenchmarkMessageFullEncode(b *testing.B) { 59 | b.ReportAllocs() 60 | tID := stun.NewTransactionID() 61 | b.ResetTimer() 62 | for i := 0; i < b.N; i++ { 63 | stun.MustBuild(stun.BindingSuccess, stun.NewTransactionIDSetter(tID), 64 | stun.NewUsername("someusername"), 65 | stun.NewRealm("somerealm"), 66 | &stun.XORMappedAddress{IP: net.IPv4(213, 1, 223, 5), Port: 1234}, 67 | stun.NewShortTermIntegrity("somepwd"), 68 | stun.Fingerprint, 69 | ) 70 | } 71 | } 72 | 73 | func BenchmarkMessageFullDecode(b *testing.B) { 74 | b.ReportAllocs() 75 | tID := stun.NewTransactionID() 76 | messageFull := stun.MustBuild(stun.BindingSuccess, stun.NewTransactionIDSetter(tID), 77 | stun.NewUsername("someusername"), 78 | stun.NewRealm("somerealm"), 79 | &stun.XORMappedAddress{IP: net.IPv4(213, 1, 223, 5), Port: 1234}, 80 | stun.NewShortTermIntegrity("somepwd"), 81 | stun.Fingerprint, 82 | ) 83 | m := stun.New() 84 | b.ResetTimer() 85 | for i := 0; i < b.N; i++ { 86 | m.Reset() 87 | if err := stun.Decode(messageFull.Raw, m); err != nil { 88 | b.Fatal(err) 89 | } 90 | } 91 | } 92 | 93 | func BenchmarkAuthenticateSt(b *testing.B) { 94 | b.ReportAllocs() 95 | tID := stun.NewTransactionID() 96 | messageFull := stun.MustBuild(stun.BindingSuccess, stun.NewTransactionIDSetter(tID), 97 | stun.NewUsername("someusername"), 98 | stun.NewRealm("somerealm"), 99 | &stun.XORMappedAddress{IP: net.IPv4(213, 1, 223, 5), Port: 1234}, 100 | stun.NewShortTermIntegrity("somepwd"), 101 | stun.Fingerprint, 102 | ) 103 | b.ResetTimer() 104 | integrity := stun.NewShortTermIntegrity("somepwd") 105 | for i := 0; i < b.N; i++ { 106 | if err := integrity.Check(messageFull); err != nil { 107 | b.Fatal(err) 108 | } 109 | } 110 | } 111 | 112 | func BenchmarkAuthenticateLt(b *testing.B) { 113 | b.ReportAllocs() 114 | tID := stun.NewTransactionID() 115 | messageFull := stun.MustBuild(stun.BindingSuccess, stun.NewTransactionIDSetter(tID), 116 | stun.NewUsername("someusername"), 117 | stun.NewRealm("somerealm"), 118 | &stun.XORMappedAddress{IP: net.IPv4(213, 1, 223, 5), Port: 1234}, 119 | stun.NewLongTermIntegrity("someusername", "somerealm", "somepwd"), 120 | stun.Fingerprint, 121 | ) 122 | b.ResetTimer() 123 | for i := 0; i < b.N; i++ { 124 | integrity := stun.NewLongTermIntegrity("someusername", "somerealm", "somepwd") 125 | if err := integrity.Check(messageFull); err != nil { 126 | b.Fatal(err) 127 | } 128 | } 129 | } 130 | 131 | func BenchmarkFingerprint(b *testing.B) { 132 | b.ReportAllocs() 133 | tID := stun.NewTransactionID() 134 | messageFull := stun.MustBuild(stun.BindingSuccess, stun.NewTransactionIDSetter(tID), 135 | stun.NewUsername("someusername"), 136 | stun.NewRealm("somerealm"), 137 | &stun.XORMappedAddress{IP: net.IPv4(213, 1, 223, 5), Port: 1234}, 138 | stun.NewLongTermIntegrity("someusername", "somerealm", "somepwd"), 139 | stun.Fingerprint, 140 | ) 141 | b.ResetTimer() 142 | for i := 0; i < b.N; i++ { 143 | if err := stun.Fingerprint.Check(messageFull); err != nil { 144 | b.Fatal(err) 145 | } 146 | } 147 | } 148 | 149 | // copied from pion 150 | func BenchmarkErrorCode_AddTo(b *testing.B) { 151 | m := stun.New() 152 | b.ReportAllocs() 153 | for i := 0; i < b.N; i++ { 154 | stun.CodeStaleNonce.AddTo(m) //nolint:errcheck,gosec 155 | m.Reset() 156 | } 157 | } 158 | 159 | // copied from pion 160 | func BenchmarkErrorCodeAttribute_GetFrom(b *testing.B) { 161 | m := stun.New() 162 | b.ReportAllocs() 163 | a := &stun.ErrorCodeAttribute{ 164 | Code: 404, 165 | Reason: []byte("not found!"), 166 | } 167 | a.AddTo(m) //nolint:errcheck,gosec 168 | for i := 0; i < b.N; i++ { 169 | a.GetFrom(m) //nolint:errcheck,gosec 170 | } 171 | } 172 | 173 | func BenchmarkXORMappedAddress_AddTo(b *testing.B) { 174 | m := stun.New() 175 | b.ReportAllocs() 176 | ip := net.ParseIP("192.168.1.32") 177 | for i := 0; i < b.N; i++ { 178 | addr := &stun.XORMappedAddress{IP: ip, Port: 3654} 179 | addr.AddTo(m) //nolint:errcheck,gosec 180 | m.Reset() 181 | } 182 | } 183 | 184 | // this should fail! there is no tid 185 | // func BenchmarkXORMappedAddress_GetFrom(b *testing.B) { 186 | // m := stun.New() 187 | // b.ReportAllocs() 188 | // ip := net.ParseIP("192.168.1.32") 189 | // addr := &stun.XORMappedAddress{IP: ip, Port: 3654} 190 | // addr.AddTo(m) 191 | // decodedAddr := new(stun.XORMappedAddress) 192 | // b.ResetTimer() 193 | // for i := 0; i < b.N; i++ { 194 | // if err := decodedAddr.GetFrom(m); err != nil { 195 | // b.Fatal(err) 196 | // } 197 | // } 198 | // } 199 | 200 | // copied from pion 201 | func BenchmarkXORMappedAddress_GetFrom2(b *testing.B) { 202 | m := stun.New() 203 | transactionID, err := base64.StdEncoding.DecodeString("jxhBARZwX+rsC6er") 204 | if err != nil { 205 | b.Error(err) 206 | } 207 | copy(m.TransactionID[:], transactionID) 208 | addrValue, err := hex.DecodeString("00019cd5f49f38ae") 209 | if err != nil { 210 | b.Error(err) 211 | } 212 | m.Add(stun.AttrXORMappedAddress, addrValue) 213 | addr := new(stun.XORMappedAddress) 214 | b.ReportAllocs() 215 | for i := 0; i < b.N; i++ { 216 | if err := addr.GetFrom(m); err != nil { 217 | b.Fatal(err) 218 | } 219 | } 220 | } 221 | 222 | func BenchmarkSoftware_AddTo(b *testing.B) { 223 | b.ReportAllocs() 224 | m := new(stun.Message) 225 | s := stun.Software("somesoftware") 226 | b.ResetTimer() 227 | for i := 0; i < b.N; i++ { 228 | if err := s.AddTo(m); err != nil { 229 | b.Fatal(err) 230 | } 231 | m.Reset() 232 | } 233 | } 234 | 235 | func BenchmarkSoftware_GetFrom(b *testing.B) { 236 | b.ReportAllocs() 237 | m := stun.New() 238 | s := stun.Software("nonce") 239 | s.AddTo(m) //nolint:errcheck,gosec 240 | b.ResetTimer() 241 | for i := 0; i < b.N; i++ { 242 | s.GetFrom(m) //nolint:errcheck,gosec 243 | } 244 | } 245 | 246 | func BenchmarkTransactionID(b *testing.B) { 247 | b.ReportAllocs() 248 | for i := 0; i < b.N; i++ { 249 | stun.NewTransactionID() 250 | } 251 | } 252 | 253 | // func BenchmarkMessage_NewTransactionID(b *testing.B) { 254 | // b.ReportAllocs() 255 | // m := new(stun.Message) 256 | // m.WriteHeader() 257 | // for i := 0; i < b.N; i++ { 258 | // if err := m.NewTransactionID(); err != nil { 259 | // b.Fatal(err) 260 | // } 261 | // } 262 | // } 263 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2023 Elixir WebRTC Developers 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. --------------------------------------------------------------------------------