Update datarhei/gosrt dependency

This commit is contained in:
Ingo Oppermann 2023-07-20 21:18:04 +02:00
parent 496722c88a
commit 7fa68778b7
No known key found for this signature in database
GPG key ID: 2AB32426E9DD229E
134 changed files with 3751 additions and 3016 deletions

16
go.mod
View file

@ -7,7 +7,7 @@ require (
github.com/Masterminds/semver/v3 v3.1.1 github.com/Masterminds/semver/v3 v3.1.1
github.com/atrox/haikunatorgo/v2 v2.0.1 github.com/atrox/haikunatorgo/v2 v2.0.1
github.com/caddyserver/certmagic v0.17.2 github.com/caddyserver/certmagic v0.17.2
github.com/datarhei/gosrt v0.3.1 github.com/datarhei/gosrt v0.5.2
github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a
github.com/go-playground/validator/v10 v10.11.1 github.com/go-playground/validator/v10 v10.11.1
github.com/gobwas/glob v0.2.3 github.com/gobwas/glob v0.2.3
@ -22,13 +22,13 @@ require (
github.com/prep/average v0.0.0-20200506183628-d26c465f48c3 github.com/prep/average v0.0.0-20200506183628-d26c465f48c3
github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_golang v1.14.0
github.com/shirou/gopsutil/v3 v3.23.3 github.com/shirou/gopsutil/v3 v3.23.3
github.com/stretchr/testify v1.8.2 github.com/stretchr/testify v1.8.4
github.com/swaggo/echo-swagger v1.3.5 github.com/swaggo/echo-swagger v1.3.5
github.com/swaggo/swag v1.8.7 github.com/swaggo/swag v1.8.7
github.com/vektah/gqlparser/v2 v2.5.1 github.com/vektah/gqlparser/v2 v2.5.1
github.com/xeipuuv/gojsonschema v1.2.0 github.com/xeipuuv/gojsonschema v1.2.0
go.uber.org/zap v1.24.0 go.uber.org/zap v1.24.0
golang.org/x/mod v0.7.0 golang.org/x/mod v0.8.0
) )
require ( require (
@ -94,12 +94,12 @@ require (
go.uber.org/atomic v1.10.0 // indirect go.uber.org/atomic v1.10.0 // indirect
go.uber.org/goleak v1.1.12 // indirect go.uber.org/goleak v1.1.12 // indirect
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.5.0 // indirect golang.org/x/crypto v0.10.0 // indirect
golang.org/x/net v0.7.0 // indirect golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.6.0 // indirect golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.7.0 // indirect golang.org/x/text v0.10.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.4.0 // indirect golang.org/x/tools v0.6.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

37
go.sum
View file

@ -32,8 +32,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/datarhei/gosrt v0.3.1 h1:9A75hIvnY74IUFyeguqYXh1lsGF8Qt8fjxJS2Ewr12Q= github.com/datarhei/gosrt v0.5.2 h1:eagqZwEIiGPNJW0rLep3gwceObyaZ17+iKRc+l4VEpc=
github.com/datarhei/gosrt v0.3.1/go.mod h1:M2nl2WPrawncUc1FtUBK6gZX4tpZRC7FqL8NjOdBZV0= github.com/datarhei/gosrt v0.5.2/go.mod h1:0308GQhAu5hxe2KYdbss901aKceSSKXnwCr8Vs++eiw=
github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a h1:Tf4DSHY1xruBglr+yYP5Wct7czM86GKMYgbXH8a7OFo= github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a h1:Tf4DSHY1xruBglr+yYP5Wct7czM86GKMYgbXH8a7OFo=
github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a/go.mod h1:Jcw/6jZDQQmPx8A7INEkXmuEF7E9jjBbSTfVSLwmiQw= github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a/go.mod h1:Jcw/6jZDQQmPx8A7INEkXmuEF7E9jjBbSTfVSLwmiQw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -176,7 +176,6 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -225,9 +224,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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.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 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/swaggo/echo-swagger v1.3.5 h1:kCx1wvX5AKhjI6Ykt48l3PTsfL9UD40ZROOx/tYzWyY= github.com/swaggo/echo-swagger v1.3.5 h1:kCx1wvX5AKhjI6Ykt48l3PTsfL9UD40ZROOx/tYzWyY=
github.com/swaggo/echo-swagger v1.3.5/go.mod h1:3IMHd2Z8KftdWFEEjGmv6QpWj370LwMCOfovuh7vF34= github.com/swaggo/echo-swagger v1.3.5/go.mod h1:3IMHd2Z8KftdWFEEjGmv6QpWj370LwMCOfovuh7vF34=
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a h1:kAe4YSu0O0UFn1DowNo2MY5p6xzqtJ/wQ7LZynSvGaY= github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a h1:kAe4YSu0O0UFn1DowNo2MY5p6xzqtJ/wQ7LZynSvGaY=
@ -282,15 +281,14 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -304,9 +302,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 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.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -335,20 +332,18 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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.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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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.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.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.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -361,8 +356,8 @@ golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyj
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= 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-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-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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View file

@ -7,6 +7,10 @@ all: build
test: test:
go test -race -coverprofile=/dev/null -v ./... go test -race -coverprofile=/dev/null -v ./...
## fuzz: Run fuzz tests
fuzz:
go test -fuzz=Fuzz -run=^Fuzz ./internal/packet -fuzztime 30s
## vet: Analyze code for potential errors ## vet: Analyze code for potential errors
vet: vet:
go vet ./... go vet ./...
@ -58,7 +62,7 @@ docker:
logtopics: logtopics:
grep -ERho 'log\("([^"]+)' *.go | sed -E -e 's/log\("//' | sort -u grep -ERho 'log\("([^"]+)' *.go | sed -E -e 's/log\("//' | sort -u
.PHONY: help test vet fmt vendor commit coverage lint client server update logtopics .PHONY: help test fuzz vet fmt vendor commit coverage lint client server update logtopics
## help: Show all commands ## help: Show all commands
help: Makefile help: Makefile

View file

@ -1,5 +1,13 @@
# GoSRT
Implementation of the SRT protocol in pure Go with minimal dependencies. Implementation of the SRT protocol in pure Go with minimal dependencies.
<p align="left">
<a href="http://srtalliance.org/">
<img alt="SRT" src="https://github.com/datarhei/misc/blob/main/img/gosrt.png?raw=true" width="600"/>
</a>
</p>
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![Tests](https://github.com/datarhei/gosrt/actions/workflows/go-tests.yml/badge.svg) ![Tests](https://github.com/datarhei/gosrt/actions/workflows/go-tests.yml/badge.svg)
[![codecov](https://codecov.io/gh/datarhei/gosrt/branch/main/graph/badge.svg?token=90YMPZRAFK)](https://codecov.io/gh/datarhei/gosrt) [![codecov](https://codecov.io/gh/datarhei/gosrt/branch/main/graph/badge.svg?token=90YMPZRAFK)](https://codecov.io/gh/datarhei/gosrt)
@ -10,11 +18,14 @@ Implementation of the SRT protocol in pure Go with minimal dependencies.
- [SRT RFC](https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html) - [SRT RFC](https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html)
- [SRT Technical Overview](https://github.com/Haivision/srt/files/2489142/SRT_Protocol_TechnicalOverview_DRAFT_2018-10-17.pdf) - [SRT Technical Overview](https://github.com/Haivision/srt/files/2489142/SRT_Protocol_TechnicalOverview_DRAFT_2018-10-17.pdf)
## Implementations
This implementation of the SRT protocol has live streaming of video/audio in mind. Because of this, the buffer mode and File Transfer This implementation of the SRT protocol has live streaming of video/audio in mind. Because of this, the buffer mode and File Transfer
Congestion Control (FileCC) are not implemented. Congestion Control (FileCC) are not implemented.
| | | | | |
| --- | ----------------------------------------- | | --- | ----------------------------------------- |
| ✅ | Handshake v4 and v5 |
| ✅ | Message mode | | ✅ | Message mode |
| ✅ | Caller-Listener Handshake | | ✅ | Caller-Listener Handshake |
| ✅ | Timestamp-Based Packet Delivery (TSBPD) | | ✅ | Timestamp-Based Packet Delivery (TSBPD) |
@ -29,17 +40,17 @@ Congestion Control (FileCC) are not implemented.
The parts that are implemented are based on what has been published in the SRT RFC. The parts that are implemented are based on what has been published in the SRT RFC.
# Requirements ## Requirements
A Go version of 1.16+ is required. A Go version of 1.18+ is required.
# Installation ## Installation
``` ```
go get github.com/datarhei/gosrt go get github.com/datarhei/gosrt
``` ```
# Caller example ## Caller example
``` ```
import "github.com/datarhei/gosrt" import "github.com/datarhei/gosrt"
@ -67,7 +78,7 @@ conn.Close()
In the `contrib/client` directory you'll find a complete example of a SRT client. In the `contrib/client` directory you'll find a complete example of a SRT client.
# Listener example ## Listener example
``` ```
import "github.com/datarhei/gosrt" import "github.com/datarhei/gosrt"
@ -103,7 +114,7 @@ In the `contrib/server` directory you'll find a complete example of a SRT server
this modules provides the `Server` type which is a light framework for creating your own SRT server. The this modules provides the `Server` type which is a light framework for creating your own SRT server. The
example server is based on this type. example server is based on this type.
## PUBLISH / SUBSCRIBE ### PUBLISH / SUBSCRIBE
The `Accept` function from the `Listener` expects a function that handles the connection requests. It can The `Accept` function from the `Listener` expects a function that handles the connection requests. It can
return 3 different values: `srt.PUBLISH`, `srt.SUBSCRIBE`, and `srt.REJECT`. `srt.PUBLISH` means that the return 3 different values: `srt.PUBLISH`, `srt.SUBSCRIBE`, and `srt.REJECT`. `srt.PUBLISH` means that the
@ -111,7 +122,7 @@ server expects the caller to send data, whereas `srt.SUBSCRIBE` means that the s
the caller. This is opiniated towards a streaming server, however in your implementation of a listener the caller. This is opiniated towards a streaming server, however in your implementation of a listener
you are free to handle connections requests to your liking. you are free to handle connections requests to your liking.
# Contributed client ## Contributed client
In the `contrib/client` directory you'll find an example implementation of a SRT client. In the `contrib/client` directory you'll find an example implementation of a SRT client.
@ -130,7 +141,7 @@ The application requires only two options:
Both options accept an address. Valid addresses are: `-` for `stdin`, resp. `stdout`, a `srt://` address, or an `udp://` address. Both options accept an address. Valid addresses are: `-` for `stdin`, resp. `stdout`, a `srt://` address, or an `udp://` address.
## SRT URL ### SRT URL
A SRT URL is of the form `srt://[host]:[port]/?[options]` where options are in the form of a `HTTP` query string. These are the A SRT URL is of the form `srt://[host]:[port]/?[options]` where options are in the form of a `HTTP` query string. These are the
known options (similar to [srt-live-transmit](https://github.com/Haivision/srt/blob/master/docs/apps/srt-live-transmit.md)): known options (similar to [srt-live-transmit](https://github.com/Haivision/srt/blob/master/docs/apps/srt-live-transmit.md)):
@ -172,7 +183,7 @@ known options (similar to [srt-live-transmit](https://github.com/Haivision/srt/b
| `transtype` | `live` | Transmission type. Must be `live`. | | `transtype` | `live` | Transmission type. Must be `live`. |
| `tsbpdmode` | `bool` | Enable timestamp-based packet delivery mode. | | `tsbpdmode` | `bool` | Enable timestamp-based packet delivery mode. |
## Usage ### Usage
Reading from a SRT sender and play with `ffplay`: Reading from a SRT sender and play with `ffplay`:
@ -204,7 +215,7 @@ In the third console connect to that stream and play the video with `ffplay`:
./client -from "srt://127.0.0.1:6001/?mode=caller&streamid=foobar" -to - | ffplay -f mpegts -i - ./client -from "srt://127.0.0.1:6001/?mode=caller&streamid=foobar" -to - | ffplay -f mpegts -i -
``` ```
# Contributed server ## Contributed server
In the `contrib/server` directory you'll find an example implementation of a SRT server. This server allows you to publish In the `contrib/server` directory you'll find an example implementation of a SRT server. This server allows you to publish
a stream that can be read by many clients. a stream that can be read by many clients.
@ -237,7 +248,7 @@ Use `-logtopics` in order to write debug output. The value are a comma separated
Use `-profile` in order to write a CPU profile. Use `-profile` in order to write a CPU profile.
## StreamID ### StreamID
In SRT the StreamID is used to transport somewhat arbitrary information from the caller to the listener. The provided example server uses this In SRT the StreamID is used to transport somewhat arbitrary information from the caller to the listener. The provided example server uses this
machanism to decide who is the sender and who is the receiver. The server must know if the connecting client wants to publish a stream or machanism to decide who is the sender and who is the receiver. The server must know if the connecting client wants to publish a stream or
@ -249,7 +260,7 @@ receive data.
If you implement your own server you are free to interpret the streamID as you wish. If you implement your own server you are free to interpret the streamID as you wish.
## Usage ### Usage
Running a server listening on port 6001 with defaults: Running a server listening on port 6001 with defaults:
@ -280,7 +291,7 @@ ffplay -f mpegts -transtype live -i "srt://127.0.0.1:6001?streamid=/live/stream"
You will most likely first see some error messages from `ffplay` because it tries to make sense of the received data until a keyframe arrives. If you You will most likely first see some error messages from `ffplay` because it tries to make sense of the received data until a keyframe arrives. If you
get more errors during playback, you might increase the receive buffer by adding e.g. `-rcvlatency 1000000` to the command line. get more errors during playback, you might increase the receive buffer by adding e.g. `-rcvlatency 1000000` to the command line.
## Encryption ### Encryption
The stream can be encrypted with a passphrase. First start the server with a passphrase. If you are using `srt-live-transmit`, the passphrase has to be at least 10 characters long otherwise it will not be accepted. The stream can be encrypted with a passphrase. First start the server with a passphrase. If you are using `srt-live-transmit`, the passphrase has to be at least 10 characters long otherwise it will not be accepted.
@ -303,7 +314,7 @@ ffplay -f mpegts -transtype live -i "srt://127.0.0.1:6001?streamid=/live/stream&
You will most likely first see some error messages from `ffplay` because it tries to make sense of the received data until a keyframe arrives. If you You will most likely first see some error messages from `ffplay` because it tries to make sense of the received data until a keyframe arrives. If you
get more errors during playback, you might increase the receive buffer by adding e.g. `-rcvlatency 1000000` to the command line. get more errors during playback, you might increase the receive buffer by adding e.g. `-rcvlatency 1000000` to the command line.
# Logging ## Logging
This SRT module has a built-in logging facility for debugging purposes. Check the `Logger` interface and the `NewLogger(topics []string)` function. Because logging everything would be too much output if you wonly want to debug something specific, you have the possibility to limit the logging to specific areas like everything regarding a connection or only the handshake. That's why there are various topics. This SRT module has a built-in logging facility for debugging purposes. Check the `Logger` interface and the `NewLogger(topics []string)` function. Because logging everything would be too much output if you wonly want to debug something specific, you have the possibility to limit the logging to specific areas like everything regarding a connection or only the handshake. That's why there are various topics.
@ -380,7 +391,7 @@ packet:send:dump
You can run `make logtopics` in order to extract the list of topics. You can run `make logtopics` in order to extract the list of topics.
# Docker ## Docker
The docker image you can build with `docker build -t srt .` provides the example SRT client and server as mentioned in the paragraph above. The docker image you can build with `docker build -t srt .` provides the example SRT client and server as mentioned in the paragraph above.
E.g. run the server with `docker run -it --rm -p 6001:6001/udp srt srt-server -addr :6001`. E.g. run the server with `docker run -it --rm -p 6001:6001/udp srt srt-server -addr :6001`.

View file

@ -217,9 +217,10 @@ func DefaultConfig() Config {
} }
// UnmarshalURL takes a SRT URL and parses out the configuration. A SRT URL is // UnmarshalURL takes a SRT URL and parses out the configuration. A SRT URL is
// srt://[host]:[port]?[key1]=[value1]&[key2]=[value2]... // srt://[host]:[port]?[key1]=[value1]&[key2]=[value2]... It returns the host:port
func (c *Config) UnmarshalURL(addr string) (string, error) { // of the URL.
u, err := url.Parse(addr) func (c *Config) UnmarshalURL(srturl string) (string, error) {
u, err := url.Parse(srturl)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -471,9 +472,9 @@ func (c *Config) UnmarshalQuery(query string) error {
return nil return nil
} }
// MarshalURL returns the SRT URL for this config and the given host and port. // MarshalURL returns the SRT URL for this config and the given address (host:port).
func (c *Config) MarshalURL(host string, port uint) string { func (c *Config) MarshalURL(address string) string {
return "srt://" + host + ":" + strconv.FormatUint(uint64(port), 10) + "?" + c.MarshalQuery() return "srt://" + address + "?" + c.MarshalQuery()
} }
// MarshalQuery returns the corresponding query string for a configuration. // MarshalQuery returns the corresponding query string for a configuration.
@ -625,9 +626,9 @@ func (c *Config) MarshalQuery() string {
return q.Encode() return q.Encode()
} }
// Validate validates a configuration or returns an error if a field // Validate validates a configuration, returns an error if a field
// has an invalid value. // has an invalid value.
func (c Config) Validate() error { func (c *Config) Validate() error {
if c.TransmissionType != "live" { if c.TransmissionType != "live" {
return fmt.Errorf("config: TransmissionType must be 'live'") return fmt.Errorf("config: TransmissionType must be 'live'")
} }

View file

@ -54,6 +54,9 @@ type Conn interface {
// Stats returns accumulated and instantaneous statistics of the connection. // Stats returns accumulated and instantaneous statistics of the connection.
Stats(s *Statistics) Stats(s *Statistics)
// Version returns the connection version, either 4 or 5. With version 4, the streamid is not available
Version() uint32
} }
type connStats struct { type connStats struct {
@ -80,6 +83,9 @@ type connStats struct {
var _ net.Conn = &srtConn{} var _ net.Conn = &srtConn{}
type srtConn struct { type srtConn struct {
version uint32
isCaller bool // Only relevant if version == 4
localAddr net.Addr localAddr net.Addr
remoteAddr net.Addr remoteAddr net.Addr
@ -155,9 +161,15 @@ type srtConn struct {
expectedRcvPacketSequenceNumber circular.Number expectedRcvPacketSequenceNumber circular.Number
expectedReadPacketSequenceNumber circular.Number expectedReadPacketSequenceNumber circular.Number
} }
// HSv4
stopHSRequests context.CancelFunc
stopKMRequests context.CancelFunc
} }
type srtConnConfig struct { type srtConnConfig struct {
version uint32
isCaller bool
localAddr net.Addr localAddr net.Addr
remoteAddr net.Addr remoteAddr net.Addr
config Config config Config
@ -177,6 +189,8 @@ type srtConnConfig struct {
func newSRTConn(config srtConnConfig) *srtConn { func newSRTConn(config srtConnConfig) *srtConn {
c := &srtConn{ c := &srtConn{
version: config.version,
isCaller: config.isCaller,
localAddr: config.localAddr, localAddr: config.localAddr,
remoteAddr: config.remoteAddr, remoteAddr: config.remoteAddr,
config: config.config, config: config.config,
@ -217,7 +231,14 @@ func newSRTConn(config srtConnConfig) *srtConn {
c.networkQueue = make(chan packet.Packet, 1024) c.networkQueue = make(chan packet.Packet, 1024)
c.writeQueue = make(chan packet.Packet, 1024) c.writeQueue = make(chan packet.Packet, 1024)
if c.version == 4 {
// libsrt-1.2.3 receiver doesn't like it when the payload is larger than 7*188 bytes.
// Here we just take a multiple of a mpegts chunk size.
c.writeData = make([]byte, int(c.config.PayloadSize/188*188))
} else {
// For v5 we use the max. payload size: https://github.com/Haivision/srt/issues/876
c.writeData = make([]byte, int(c.config.PayloadSize)) c.writeData = make([]byte, int(c.config.PayloadSize))
}
c.readQueue = make(chan packet.Packet, 1024) c.readQueue = make(chan packet.Packet, 1024)
@ -281,6 +302,18 @@ func newSRTConn(config srtConnConfig) *srtConn {
c.statistics.headerSize += 40 // 40 bytes IPv6 header c.statistics.headerSize += 40 // 40 bytes IPv6 header
} }
if c.version == 4 && c.isCaller {
var hsrequestsCtx context.Context
hsrequestsCtx, c.stopHSRequests = context.WithCancel(context.Background())
go c.sendHSRequests(hsrequestsCtx)
if c.crypto != nil {
var kmrequestsCtx context.Context
kmrequestsCtx, c.stopKMRequests = context.WithCancel(context.Background())
go c.sendKMRequests(kmrequestsCtx)
}
}
return c return c
} }
@ -306,6 +339,10 @@ func (c *srtConn) StreamId() string {
return c.config.StreamId return c.config.StreamId
} }
func (c *srtConn) Version() uint32 {
return c.version
}
// ticker invokes the congestion control in regular intervals with // ticker invokes the congestion control in regular intervals with
// the current connection time. // the current connection time.
func (c *srtConn) ticker(ctx context.Context) { func (c *srtConn) ticker(ctx context.Context) {
@ -475,7 +512,7 @@ func (c *srtConn) pop(p packet.Packet) {
c.kmRefreshCountdown-- c.kmRefreshCountdown--
if c.kmPreAnnounceCountdown == 0 && !c.kmConfirmed { if c.kmPreAnnounceCountdown == 0 && !c.kmConfirmed {
c.sendKMRequest() c.sendKMRequest(c.keyBaseEncryption.Opposite())
// Resend the request until we get a response // Resend the request until we get a response
c.kmPreAnnounceCountdown = c.config.KMPreAnnounce/10 + 1 c.kmPreAnnounceCountdown = c.config.KMPreAnnounce/10 + 1
@ -578,6 +615,17 @@ func (c *srtConn) handlePacket(p packet.Packet) {
} else if header.ControlType == packet.CTRLTYPE_ACKACK { } else if header.ControlType == packet.CTRLTYPE_ACKACK {
c.handleACKACK(p) c.handleACKACK(p)
} else if header.ControlType == packet.CTRLTYPE_USER { } else if header.ControlType == packet.CTRLTYPE_USER {
c.log("connection:recv:ctrl:user", func() string {
return fmt.Sprintf("got CTRLTYPE_USER packet, subType: %s", header.SubType)
})
// HSv4 Extension
if header.SubType == packet.EXTTYPE_HSREQ {
c.handleHSRequest(p)
} else if header.SubType == packet.EXTTYPE_HSRSP {
c.handleHSResponse(p)
}
// 3.2.2. Key Material // 3.2.2. Key Material
if header.SubType == packet.EXTTYPE_KMREQ { if header.SubType == packet.EXTTYPE_KMREQ {
c.handleKMRequest(p) c.handleKMRequest(p)
@ -585,7 +633,10 @@ func (c *srtConn) handlePacket(p packet.Packet) {
c.handleKMResponse(p) c.handleKMResponse(p)
} }
} }
} else {
return
}
if header.PacketSequenceNumber.Gt(c.debug.expectedRcvPacketSequenceNumber) { if header.PacketSequenceNumber.Gt(c.debug.expectedRcvPacketSequenceNumber) {
c.log("connection:error", func() string { c.log("connection:error", func() string {
return fmt.Sprintf("recv lost packets. got: %d, expected: %d (%d)\n", header.PacketSequenceNumber.Val(), c.debug.expectedRcvPacketSequenceNumber.Val(), c.debug.expectedRcvPacketSequenceNumber.Distance(header.PacketSequenceNumber)) return fmt.Sprintf("recv lost packets. got: %d, expected: %d (%d)\n", header.PacketSequenceNumber.Val(), c.debug.expectedRcvPacketSequenceNumber.Val(), c.debug.expectedRcvPacketSequenceNumber.Distance(header.PacketSequenceNumber))
@ -647,7 +698,6 @@ func (c *srtConn) handlePacket(p packet.Packet) {
// Put the packet into receive congestion control // Put the packet into receive congestion control
c.recv.Push(p) c.recv.Push(p)
}
} }
// handleKeepAlive resets the idle timeout and sends a keepalive to the peer. // handleKeepAlive resets the idle timeout and sends a keepalive to the peer.
@ -775,35 +825,221 @@ func (c *srtConn) recalculateRTT(rtt time.Duration) {
}) })
} }
// handleKMRequest checks if the key material is valid and responds with a KM response. // handleHSRequest handles the HSv4 handshake extension request and sends the response
func (c *srtConn) handleKMRequest(p packet.Packet) { func (c *srtConn) handleHSRequest(p packet.Packet) {
c.log("control:recv:KM:dump", func() string { return p.Dump() }) c.log("control:recv:HSReq:dump", func() string { return p.Dump() })
c.statistics.pktRecvKM++ cif := &packet.CIFHandshakeExtension{}
c.cryptoLock.Lock()
if c.crypto == nil {
c.log("control:recv:KM:error", func() string { return "connection is not encrypted" })
c.cryptoLock.Unlock()
return
}
cif := &packet.CIFKM{}
if err := p.UnmarshalCIF(cif); err != nil { if err := p.UnmarshalCIF(cif); err != nil {
c.statistics.pktRecvInvalid++ c.statistics.pktRecvInvalid++
c.log("control:recv:KM:error", func() string { return fmt.Sprintf("invalid KM: %s", err) }) c.log("control:recv:HSReq:error", func() string { return fmt.Sprintf("invalid HSReq: %s", err) })
return
}
c.log("control:recv:HSReq:cif", func() string { return cif.String() })
// Check for version
if cif.SRTVersion < 0x010200 || cif.SRTVersion >= 0x010300 {
c.log("control:recv:HSReq:error", func() string { return fmt.Sprintf("unsupported version: %#08x", cif.SRTVersion) })
c.close()
return
}
// Check the required SRT flags
if !cif.SRTFlags.TSBPDSND {
c.log("control:recv:HSRes:error", func() string { return "TSBPDSND flag must be set" })
c.close()
return
}
if !cif.SRTFlags.TLPKTDROP {
c.log("control:recv:HSRes:error", func() string { return "TLPKTDROP flag must be set" })
c.close()
return
}
if !cif.SRTFlags.CRYPT {
c.log("control:recv:HSRes:error", func() string { return "CRYPT flag must be set" })
c.close()
return
}
if !cif.SRTFlags.REXMITFLG {
c.log("control:recv:HSRes:error", func() string { return "REXMITFLG flag must be set" })
c.close()
return
}
// we as receiver don't need this
cif.SRTFlags.TSBPDSND = false
// we as receiver are supporting these
cif.SRTFlags.TSBPDRCV = true
cif.SRTFlags.PERIODICNAK = true
// These flag was introduced in HSv5 and should not be set in HSv4
if cif.SRTFlags.STREAM {
c.log("control:recv:HSReq:error", func() string { return "STREAM flag is set" })
c.close()
return
}
if cif.SRTFlags.PACKET_FILTER {
c.log("control:recv:HSReq:error", func() string { return "PACKET_FILTER flag is set" })
c.close()
return
}
recvTsbpdDelay := uint16(c.config.ReceiverLatency.Milliseconds())
if cif.SendTSBPDDelay > recvTsbpdDelay {
recvTsbpdDelay = cif.SendTSBPDDelay
}
c.tsbpdDelay = uint64(recvTsbpdDelay) * 1000
cif.RecvTSBPDDelay = 0
cif.SendTSBPDDelay = recvTsbpdDelay
p.MarshalCIF(cif)
// Send HS Response
p.Header().SubType = packet.EXTTYPE_HSRSP
c.pop(p)
}
// handleHSResponse handles the HSv4 handshake extension response
func (c *srtConn) handleHSResponse(p packet.Packet) {
c.log("control:recv:HSRes:dump", func() string { return p.Dump() })
cif := &packet.CIFHandshakeExtension{}
if err := p.UnmarshalCIF(cif); err != nil {
c.statistics.pktRecvInvalid++
c.log("control:recv:HSRes:error", func() string { return fmt.Sprintf("invalid HSRes: %s", err) })
return
}
c.log("control:recv:HSRes:cif", func() string { return cif.String() })
if c.version == 4 {
// Check for version
if cif.SRTVersion < 0x010200 || cif.SRTVersion >= 0x010300 {
c.log("control:recv:HSRes:error", func() string { return fmt.Sprintf("unsupported version: %#08x", cif.SRTVersion) })
c.close()
return
}
// TSBPDSND is not relevant from the receiver
// PERIODICNAK is the sender's decision, we don't care, but will handle them
// Check the required SRT flags
if !cif.SRTFlags.TSBPDRCV {
c.log("control:recv:HSRes:error", func() string { return "TSBPDRCV flag must be set" })
c.close()
return
}
if !cif.SRTFlags.TLPKTDROP {
c.log("control:recv:HSRes:error", func() string { return "TLPKTDROP flag must be set" })
c.close()
return
}
if !cif.SRTFlags.CRYPT {
c.log("control:recv:HSRes:error", func() string { return "CRYPT flag must be set" })
c.close()
return
}
if !cif.SRTFlags.REXMITFLG {
c.log("control:recv:HSRes:error", func() string { return "REXMITFLG flag must be set" })
c.close()
return
}
// These flag was introduced in HSv5 and should not be set in HSv4
if cif.SRTFlags.STREAM {
c.log("control:recv:HSReq:error", func() string { return "STREAM flag is set" })
c.close()
return
}
if cif.SRTFlags.PACKET_FILTER {
c.log("control:recv:HSReq:error", func() string { return "PACKET_FILTER flag is set" })
c.close()
return
}
sendTsbpdDelay := uint16(c.config.PeerLatency.Milliseconds())
if cif.SendTSBPDDelay > sendTsbpdDelay {
sendTsbpdDelay = cif.SendTSBPDDelay
}
c.dropThreshold = uint64(float64(sendTsbpdDelay)*1.25) + uint64(c.config.SendDropDelay.Microseconds())
if c.dropThreshold < uint64(time.Second.Microseconds()) {
c.dropThreshold = uint64(time.Second.Microseconds())
}
c.dropThreshold += 20_000
c.snd.SetDropThreshold(c.dropThreshold)
c.stopHSRequests()
}
}
// handleKMRequest checks if the key material is valid and responds with a KM response.
func (c *srtConn) handleKMRequest(p packet.Packet) {
c.log("control:recv:KMReq:dump", func() string { return p.Dump() })
c.statistics.pktRecvKM++
cif := &packet.CIFKeyMaterialExtension{}
if err := p.UnmarshalCIF(cif); err != nil {
c.statistics.pktRecvInvalid++
c.log("control:recv:KMReq:error", func() string { return fmt.Sprintf("invalid KMReq: %s", err) })
return
}
c.log("control:recv:KMReq:cif", func() string { return cif.String() })
c.cryptoLock.Lock()
if c.version == 4 && c.crypto == nil {
cr, err := crypto.New(int(cif.KLen))
if err != nil {
c.log("control:recv:KMReq:error", func() string { return fmt.Sprintf("crypto: %s", err) })
c.cryptoLock.Unlock()
c.close()
return
}
c.keyBaseEncryption = cif.KeyBasedEncryption.Opposite()
c.crypto = cr
}
if c.crypto == nil {
c.log("control:recv:KMReq:error", func() string { return "connection is not encrypted" })
c.cryptoLock.Unlock() c.cryptoLock.Unlock()
return return
} }
c.log("control:recv:KM:cif", func() string { return cif.String() })
if cif.KeyBasedEncryption == c.keyBaseEncryption { if cif.KeyBasedEncryption == c.keyBaseEncryption {
c.statistics.pktRecvInvalid++ c.statistics.pktRecvInvalid++
c.log("control:recv:KM:error", func() string { c.log("control:recv:KMReq:error", func() string {
return "invalid KM. wants to reset the key that is already in use" return "invalid KM request. wants to reset the key that is already in use"
}) })
c.cryptoLock.Unlock() c.cryptoLock.Unlock()
return return
@ -811,7 +1047,7 @@ func (c *srtConn) handleKMRequest(p packet.Packet) {
if err := c.crypto.UnmarshalKM(cif, c.config.Passphrase); err != nil { if err := c.crypto.UnmarshalKM(cif, c.config.Passphrase); err != nil {
c.statistics.pktRecvInvalid++ c.statistics.pktRecvInvalid++
c.log("control:recv:KM:error", func() string { return fmt.Sprintf("invalid KM: %s", err) }) c.log("control:recv:KMReq:error", func() string { return fmt.Sprintf("invalid KMReq: %s", err) })
c.cryptoLock.Unlock() c.cryptoLock.Unlock()
return return
} }
@ -831,20 +1067,44 @@ func (c *srtConn) handleKMRequest(p packet.Packet) {
// handleKMResponse confirms the change of encryption keys. // handleKMResponse confirms the change of encryption keys.
func (c *srtConn) handleKMResponse(p packet.Packet) { func (c *srtConn) handleKMResponse(p packet.Packet) {
c.log("control:recv:KM:dump", func() string { return p.Dump() }) c.log("control:recv:KMRes:dump", func() string { return p.Dump() })
c.statistics.pktRecvKM++ c.statistics.pktRecvKM++
cif := &packet.CIFKeyMaterialExtension{}
if err := p.UnmarshalCIF(cif); err != nil {
c.statistics.pktRecvInvalid++
c.log("control:recv:KMRes:error", func() string { return fmt.Sprintf("invalid KMRes: %s", err) })
return
}
c.cryptoLock.Lock() c.cryptoLock.Lock()
defer c.cryptoLock.Unlock() defer c.cryptoLock.Unlock()
if c.crypto == nil { if c.crypto == nil {
c.log("control:recv:KM:error", func() string { return "connection is not encrypted" }) c.log("control:recv:KMRes:error", func() string { return "connection is not encrypted" })
return return
} }
if c.version == 4 {
c.stopKMRequests()
if cif.Error != 0 {
if cif.Error == packet.KM_NOSECRET {
c.log("control:recv:KMRes:error", func() string { return "peer didn't enabled encryption" })
} else if cif.Error == packet.KM_BADSECRET {
c.log("control:recv:KMRes:error", func() string { return "peer has a different passphrase" })
}
c.close()
return
}
}
c.log("control:recv:KMRes:cif", func() string { return cif.String() })
if c.kmPreAnnounceCountdown >= c.config.KMPreAnnounce { if c.kmPreAnnounceCountdown >= c.config.KMPreAnnounce {
c.log("control:recv:KM:error", func() string { return "not in pre-announce period" }) c.log("control:recv:KMRes:error", func() string { return "not in pre-announce period, ignored" })
// Ignore the response, we're not in the pre-announce period // Ignore the response, we're not in the pre-announce period
return return
} }
@ -964,16 +1224,73 @@ func (c *srtConn) sendACKACK(ackSequence uint32) {
c.pop(p) c.pop(p)
} }
func (c *srtConn) sendHSRequests(ctx context.Context) {
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
select {
case <-ctx.Done():
return
case <-ticker.C:
c.sendHSRequest()
}
}
func (c *srtConn) sendHSRequest() {
cif := &packet.CIFHandshakeExtension{
SRTVersion: 0x00010203,
SRTFlags: packet.CIFHandshakeExtensionFlags{
TSBPDSND: true, // we send in TSBPD mode
TSBPDRCV: false, // not relevant for us as sender
CRYPT: true, // must be always set
TLPKTDROP: true, // must be set in live mode
PERIODICNAK: false, // not relevant for us as sender
REXMITFLG: true, // must alwasy be set
STREAM: false, // has been introducet in HSv5
PACKET_FILTER: false, // has been introducet in HSv5
},
RecvTSBPDDelay: 0,
SendTSBPDDelay: uint16(c.config.ReceiverLatency.Milliseconds()),
}
p := packet.NewPacket(c.remoteAddr, nil)
p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_USER
p.Header().SubType = packet.EXTTYPE_HSREQ
p.Header().Timestamp = c.getTimestampForPacket()
p.MarshalCIF(cif)
c.log("control:send:HSReq:dump", func() string { return p.Dump() })
c.log("control:send:HSReq:cif", func() string { return cif.String() })
c.pop(p)
}
func (c *srtConn) sendKMRequests(ctx context.Context) {
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
select {
case <-ctx.Done():
return
case <-ticker.C:
c.sendKMRequest(c.keyBaseEncryption)
}
}
// sendKMRequest sends a KM request to the peer. // sendKMRequest sends a KM request to the peer.
func (c *srtConn) sendKMRequest() { func (c *srtConn) sendKMRequest(key packet.PacketEncryption) {
if c.crypto == nil { if c.crypto == nil {
c.log("control:send:KM:error", func() string { return "connection is not encrypted" }) c.log("control:send:KMReq:error", func() string { return "connection is not encrypted" })
return return
} }
cif := &packet.CIFKM{} cif := &packet.CIFKeyMaterialExtension{}
c.crypto.MarshalKM(cif, c.config.Passphrase, c.keyBaseEncryption.Opposite()) c.crypto.MarshalKM(cif, c.config.Passphrase, key)
p := packet.NewPacket(c.remoteAddr, nil) p := packet.NewPacket(c.remoteAddr, nil)
@ -985,8 +1302,8 @@ func (c *srtConn) sendKMRequest() {
p.MarshalCIF(cif) p.MarshalCIF(cif)
c.log("control:send:KM:dump", func() string { return p.Dump() }) c.log("control:send:KMReq:dump", func() string { return p.Dump() })
c.log("control:send:KM:cif", func() string { return cif.String() }) c.log("control:send:KMReq:cif", func() string { return cif.String() })
c.statistics.pktSentKM++ c.statistics.pktSentKM++

View file

@ -10,7 +10,6 @@ import (
"net" "net"
"os" "os"
"sync" "sync"
"syscall"
"time" "time"
"github.com/datarhei/gosrt/internal/circular" "github.com/datarhei/gosrt/internal/circular"
@ -24,6 +23,8 @@ var ErrClientClosed = errors.New("srt: client closed")
// dialer implements the Conn interface // dialer implements the Conn interface
type dialer struct { type dialer struct {
version uint32
pc *net.UDPConn pc *net.UDPConn
localAddr net.Addr localAddr net.Addr
@ -87,35 +88,18 @@ func Dial(network, address string, config Config) (Conn, error) {
config: config, config: config,
} }
raddr, err := net.ResolveUDPAddr("udp", address) netdialer := net.Dialer{
if err != nil { Control: DialControl(config),
return nil, fmt.Errorf("unable to resolve address: %w", err)
} }
pc, err := net.DialUDP("udp", nil, raddr) conn, err := netdialer.Dial("udp", address)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed dialing: %w", err) return nil, fmt.Errorf("failed dialing: %w", err)
} }
file, err := pc.File() pc, ok := conn.(*net.UDPConn)
if err != nil { if !ok {
return nil, err return nil, fmt.Errorf("failed dialing: connection is not a UDP connection")
}
// Set TOS
if config.IPTOS > 0 {
err = syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_TOS, config.IPTOS)
if err != nil {
return nil, fmt.Errorf("failed setting socket option TOS: %w", err)
}
}
// Set TTL
if config.IPTTL > 0 {
err = syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_TTL, config.IPTTL)
if err != nil {
return nil, fmt.Errorf("failed setting socket option TTL: %w", err)
}
} }
dl.pc = pc dl.pc = pc
@ -331,28 +315,25 @@ func (dl *dialer) handleHandshake(p packet.Packet) {
p.Header().SubType = 0 p.Header().SubType = 0
p.Header().TypeSpecific = 0 p.Header().TypeSpecific = 0
p.Header().Timestamp = uint32(time.Since(dl.start).Microseconds()) p.Header().Timestamp = uint32(time.Since(dl.start).Microseconds())
p.Header().DestinationSocketId = cif.SRTSocketId p.Header().DestinationSocketId = 0 // must be 0 for handshake
if cif.HandshakeType == packet.HSTYPE_INDUCTION { if cif.HandshakeType == packet.HSTYPE_INDUCTION {
// Verify version if cif.Version < 4 || cif.Version > 5 {
if cif.Version != 5 {
dl.connChan <- connResponse{ dl.connChan <- connResponse{
conn: nil, conn: nil,
err: fmt.Errorf("peer doesn't support handshake v5"), err: fmt.Errorf("peer responded with unsupported handshake version (%d)", cif.Version),
} }
return return
} }
// Verify magic number cif.IsRequest = true
if cif.ExtensionField != 0x4A17 { cif.HandshakeType = packet.HSTYPE_CONCLUSION
dl.connChan <- connResponse{ cif.InitialPacketSequenceNumber = dl.initialPacketSequenceNumber
conn: nil, cif.MaxTransmissionUnitSize = dl.config.MSS // MTU size
err: fmt.Errorf("peer sent the wrong magic number"), cif.MaxFlowWindowSize = dl.config.FC
} cif.SRTSocketId = dl.socketId
cif.PeerIP.FromNetAddr(dl.localAddr)
return
}
// Setup crypto context // Setup crypto context
if len(dl.config.Passphrase) != 0 { if len(dl.config.Passphrase) != 0 {
@ -382,33 +363,43 @@ func (dl *dialer) handleHandshake(p packet.Packet) {
dl.crypto = cr dl.crypto = cr
} }
cif.IsRequest = true // Verify version
cif.HandshakeType = packet.HSTYPE_CONCLUSION if cif.Version == 5 {
cif.InitialPacketSequenceNumber = dl.initialPacketSequenceNumber dl.version = 5
cif.MaxTransmissionUnitSize = dl.config.MSS // MTU size
cif.MaxFlowWindowSize = dl.config.FC // Verify magic number
cif.SRTSocketId = dl.socketId if cif.ExtensionField != 0x4A17 {
cif.PeerIP.FromNetAddr(dl.localAddr) dl.connChan <- connResponse{
conn: nil,
err: fmt.Errorf("peer sent the wrong magic number"),
}
return
}
cif.HasHS = true cif.HasHS = true
cif.SRTVersion = SRT_VERSION cif.SRTHS = &packet.CIFHandshakeExtension{
cif.SRTFlags.TSBPDSND = true SRTVersion: SRT_VERSION,
cif.SRTFlags.TSBPDRCV = true SRTFlags: packet.CIFHandshakeExtensionFlags{
cif.SRTFlags.CRYPT = true // must always set to true TSBPDSND: true,
cif.SRTFlags.TLPKTDROP = true TSBPDRCV: true,
cif.SRTFlags.PERIODICNAK = true CRYPT: true, // must always set to true
cif.SRTFlags.REXMITFLG = true TLPKTDROP: true,
cif.SRTFlags.STREAM = false PERIODICNAK: true,
cif.SRTFlags.PACKET_FILTER = false REXMITFLG: true,
cif.RecvTSBPDDelay = uint16(dl.config.ReceiverLatency.Milliseconds()) STREAM: false,
cif.SendTSBPDDelay = uint16(dl.config.PeerLatency.Milliseconds()) PACKET_FILTER: false,
},
RecvTSBPDDelay: uint16(dl.config.ReceiverLatency.Milliseconds()),
SendTSBPDDelay: uint16(dl.config.PeerLatency.Milliseconds()),
}
cif.HasSID = true cif.HasSID = true
cif.StreamId = dl.config.StreamId cif.StreamId = dl.config.StreamId
if dl.crypto != nil { if dl.crypto != nil {
cif.HasKM = true cif.HasKM = true
cif.SRTKM = &packet.CIFKM{} cif.SRTKM = &packet.CIFKeyMaterialExtension{}
if err := dl.crypto.MarshalKM(cif.SRTKM, dl.config.Passphrase, packet.EvenKeyEncrypted); err != nil { if err := dl.crypto.MarshalKM(cif.SRTKM, dl.config.Passphrase, packet.EvenKeyEncrypted); err != nil {
dl.connChan <- connResponse{ dl.connChan <- connResponse{
@ -419,6 +410,16 @@ func (dl *dialer) handleHandshake(p packet.Packet) {
return return
} }
} }
} else {
dl.version = 4
cif.EncryptionField = 0
cif.ExtensionField = 2
cif.HasHS = false
cif.HasKM = false
cif.HasSID = false
}
p.MarshalCIF(cif) p.MarshalCIF(cif)
@ -427,20 +428,21 @@ func (dl *dialer) handleHandshake(p packet.Packet) {
dl.send(p) dl.send(p)
} else if cif.HandshakeType == packet.HSTYPE_CONCLUSION { } else if cif.HandshakeType == packet.HSTYPE_CONCLUSION {
// We only support HSv5 if cif.Version < 4 || cif.Version > 5 {
if cif.Version != 5 {
dl.sendShutdown(cif.SRTSocketId)
dl.connChan <- connResponse{ dl.connChan <- connResponse{
conn: nil, conn: nil,
err: fmt.Errorf("peer doesn't support handshake v5"), err: fmt.Errorf("peer responded with unsupported handshake version (%d)", cif.Version),
} }
return return
} }
recvTsbpdDelay := uint16(dl.config.ReceiverLatency.Milliseconds())
sendTsbpdDelay := uint16(dl.config.PeerLatency.Milliseconds())
if cif.Version == 5 {
// Check if the peer version is sufficient // Check if the peer version is sufficient
if cif.SRTVersion < dl.config.MinVersion { if cif.SRTHS.SRTVersion < dl.config.MinVersion {
dl.sendShutdown(cif.SRTSocketId) dl.sendShutdown(cif.SRTSocketId)
dl.connChan <- connResponse{ dl.connChan <- connResponse{
@ -452,7 +454,7 @@ func (dl *dialer) handleHandshake(p packet.Packet) {
} }
// Check the required SRT flags // Check the required SRT flags
if !cif.SRTFlags.TSBPDSND || !cif.SRTFlags.TSBPDRCV || !cif.SRTFlags.TLPKTDROP || !cif.SRTFlags.PERIODICNAK || !cif.SRTFlags.REXMITFLG { if !cif.SRTHS.SRTFlags.TSBPDSND || !cif.SRTHS.SRTFlags.TSBPDRCV || !cif.SRTHS.SRTFlags.TLPKTDROP || !cif.SRTHS.SRTFlags.PERIODICNAK || !cif.SRTHS.SRTFlags.REXMITFLG {
dl.sendShutdown(cif.SRTSocketId) dl.sendShutdown(cif.SRTSocketId)
dl.connChan <- connResponse{ dl.connChan <- connResponse{
@ -464,7 +466,7 @@ func (dl *dialer) handleHandshake(p packet.Packet) {
} }
// We only support live streaming // We only support live streaming
if cif.SRTFlags.STREAM { if cif.SRTHS.SRTFlags.STREAM {
dl.sendShutdown(cif.SRTSocketId) dl.sendShutdown(cif.SRTSocketId)
dl.connChan <- connResponse{ dl.connChan <- connResponse{
@ -476,15 +478,13 @@ func (dl *dialer) handleHandshake(p packet.Packet) {
} }
// Select the largest TSBPD delay advertised by the listener, but at least 120ms // Select the largest TSBPD delay advertised by the listener, but at least 120ms
recvTsbpdDelay := uint16(dl.config.ReceiverLatency.Milliseconds()) if cif.SRTHS.SendTSBPDDelay > recvTsbpdDelay {
sendTsbpdDelay := uint16(dl.config.PeerLatency.Milliseconds()) recvTsbpdDelay = cif.SRTHS.SendTSBPDDelay
if cif.SendTSBPDDelay > recvTsbpdDelay {
recvTsbpdDelay = cif.SendTSBPDDelay
} }
if cif.RecvTSBPDDelay > sendTsbpdDelay { if cif.SRTHS.RecvTSBPDDelay > sendTsbpdDelay {
sendTsbpdDelay = cif.RecvTSBPDDelay sendTsbpdDelay = cif.SRTHS.RecvTSBPDDelay
}
} }
// If the peer has a smaller MTU size, adjust to it // If the peer has a smaller MTU size, adjust to it
@ -506,6 +506,8 @@ func (dl *dialer) handleHandshake(p packet.Packet) {
// Create a new connection // Create a new connection
conn := newSRTConn(srtConnConfig{ conn := newSRTConn(srtConnConfig{
version: cif.Version,
isCaller: true,
localAddr: dl.localAddr, localAddr: dl.localAddr,
remoteAddr: dl.remoteAddr, remoteAddr: dl.remoteAddr,
config: dl.config, config: dl.config,
@ -621,6 +623,10 @@ func (dl *dialer) StreamId() string {
return dl.conn.StreamId() return dl.conn.StreamId()
} }
func (dl *dialer) Version() uint32 {
return dl.conn.Version()
}
func (dl *dialer) isShutdown() bool { func (dl *dialer) isShutdown() bool {
dl.shutdownLock.RLock() dl.shutdownLock.RLock()
defer dl.shutdownLock.RUnlock() defer dl.shutdownLock.RUnlock()

View file

@ -115,8 +115,12 @@ func (s *liveSend) Push(p packet.Packet) {
return return
} }
// give to the packet a sequence number // Give to the packet a sequence number
p.Header().PacketSequenceNumber = s.nextSequenceNumber p.Header().PacketSequenceNumber = s.nextSequenceNumber
p.Header().PacketPositionFlag = packet.SinglePacket
p.Header().OrderFlag = false
p.Header().MessageNumber = 1
s.nextSequenceNumber = s.nextSequenceNumber.Inc() s.nextSequenceNumber = s.nextSequenceNumber.Inc()
pktLen := p.Len() pktLen := p.Len()
@ -124,7 +128,7 @@ func (s *liveSend) Push(p packet.Packet) {
s.statistics.PktBuf++ s.statistics.PktBuf++
s.statistics.ByteBuf += pktLen s.statistics.ByteBuf += pktLen
// input bandwidth calculation // Input bandwidth calculation
s.rate.bytes += pktLen s.rate.bytes += pktLen
p.Header().Timestamp = uint32(p.Header().PktTsbpdTime & uint64(packet.MAX_TIMESTAMP)) p.Header().Timestamp = uint32(p.Header().PktTsbpdTime & uint64(packet.MAX_TIMESTAMP))
@ -148,7 +152,7 @@ func (s *liveSend) Push(p packet.Packet) {
} }
func (s *liveSend) Tick(now uint64) { func (s *liveSend) Tick(now uint64) {
// deliver packets whose PktTsbpdTime is ripe // Deliver packets whose PktTsbpdTime is ripe
s.lock.Lock() s.lock.Lock()
removeList := make([]*list.Element, 0, s.packetList.Len()) removeList := make([]*list.Element, 0, s.packetList.Len())
for e := s.packetList.Front(); e != nil; e = e.Next() { for e := s.packetList.Front(); e != nil; e = e.Next() {
@ -188,7 +192,7 @@ func (s *liveSend) Tick(now uint64) {
p := e.Value.(packet.Packet) p := e.Value.(packet.Packet)
if p.Header().PktTsbpdTime+s.dropThreshold <= now { if p.Header().PktTsbpdTime+s.dropThreshold <= now {
// dropped packet because too old // Dropped packet because too old
s.statistics.PktDrop++ s.statistics.PktDrop++
s.statistics.PktLoss++ s.statistics.PktLoss++
s.statistics.ByteDrop += p.Len() s.statistics.ByteDrop += p.Len()
@ -241,7 +245,7 @@ func (s *liveSend) ACK(sequenceNumber circular.Number) {
for e := s.lossList.Front(); e != nil; e = e.Next() { for e := s.lossList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet) p := e.Value.(packet.Packet)
if p.Header().PacketSequenceNumber.Lt(sequenceNumber) { if p.Header().PacketSequenceNumber.Lt(sequenceNumber) {
// remove packet from buffer because it has been successfully transmitted // Remove packet from buffer because it has been successfully transmitted
removeList = append(removeList, e) removeList = append(removeList, e)
} else { } else {
break break
@ -466,7 +470,7 @@ func (r *liveReceive) Push(pkt packet.Packet) {
r.avgPayloadSize = 0.875*r.avgPayloadSize + 0.125*float64(pktLen) r.avgPayloadSize = 0.875*r.avgPayloadSize + 0.125*float64(pktLen)
if pkt.Header().PacketSequenceNumber.Lte(r.lastDeliveredSequenceNumber) { if pkt.Header().PacketSequenceNumber.Lte(r.lastDeliveredSequenceNumber) {
// too old, because up until r.lastDeliveredSequenceNumber, we already delivered // Too old, because up until r.lastDeliveredSequenceNumber, we already delivered
r.statistics.PktBelated++ r.statistics.PktBelated++
r.statistics.ByteBelated += pktLen r.statistics.ByteBelated += pktLen
@ -477,7 +481,7 @@ func (r *liveReceive) Push(pkt packet.Packet) {
} }
if pkt.Header().PacketSequenceNumber.Lt(r.lastACKSequenceNumber) { if pkt.Header().PacketSequenceNumber.Lt(r.lastACKSequenceNumber) {
// already acknowledged, ignoring // Already acknowledged, ignoring
r.statistics.PktDrop++ r.statistics.PktDrop++
r.statistics.ByteDrop += pktLen r.statistics.ByteDrop += pktLen
@ -485,21 +489,21 @@ func (r *liveReceive) Push(pkt packet.Packet) {
} }
if pkt.Header().PacketSequenceNumber.Equals(r.maxSeenSequenceNumber.Inc()) { if pkt.Header().PacketSequenceNumber.Equals(r.maxSeenSequenceNumber.Inc()) {
// in order, the packet we expected // In order, the packet we expected
r.maxSeenSequenceNumber = pkt.Header().PacketSequenceNumber r.maxSeenSequenceNumber = pkt.Header().PacketSequenceNumber
} else if pkt.Header().PacketSequenceNumber.Lte(r.maxSeenSequenceNumber) { } else if pkt.Header().PacketSequenceNumber.Lte(r.maxSeenSequenceNumber) {
// out of order, is it a missing piece? put it in the correct position // Out of order, is it a missing piece? put it in the correct position
for e := r.packetList.Front(); e != nil; e = e.Next() { for e := r.packetList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet) p := e.Value.(packet.Packet)
if p.Header().PacketSequenceNumber == pkt.Header().PacketSequenceNumber { if p.Header().PacketSequenceNumber == pkt.Header().PacketSequenceNumber {
// already received (has been sent more than once), ignoring // Already received (has been sent more than once), ignoring
r.statistics.PktDrop++ r.statistics.PktDrop++
r.statistics.ByteDrop += pktLen r.statistics.ByteDrop += pktLen
break break
} else if p.Header().PacketSequenceNumber.Gt(pkt.Header().PacketSequenceNumber) { } else if p.Header().PacketSequenceNumber.Gt(pkt.Header().PacketSequenceNumber) {
// late arrival, this fills a gap // Late arrival, this fills a gap
r.statistics.PktBuf++ r.statistics.PktBuf++
r.statistics.PktUnique++ r.statistics.PktUnique++
@ -514,7 +518,7 @@ func (r *liveReceive) Push(pkt packet.Packet) {
return return
} else { } else {
// too far ahead, there are some missing sequence numbers, immediate NAK report // Too far ahead, there are some missing sequence numbers, immediate NAK report
// here we can prevent a possibly unnecessary NAK with SRTO_LOXXMAXTTL // here we can prevent a possibly unnecessary NAK with SRTO_LOXXMAXTTL
r.sendNAK(r.maxSeenSequenceNumber.Inc(), pkt.Header().PacketSequenceNumber.Dec()) r.sendNAK(r.maxSeenSequenceNumber.Inc(), pkt.Header().PacketSequenceNumber.Dec())
@ -541,7 +545,7 @@ func (r *liveReceive) periodicACK(now uint64) (ok bool, sequenceNumber circular.
// 4.8.1. Packet Acknowledgement (ACKs, ACKACKs) // 4.8.1. Packet Acknowledgement (ACKs, ACKACKs)
if now-r.lastPeriodicACK < r.periodicACKInterval { if now-r.lastPeriodicACK < r.periodicACKInterval {
if r.nPackets >= 64 { if r.nPackets >= 64 {
lite = true // send light ACK lite = true // Send light ACK
} else { } else {
return return
} }
@ -551,8 +555,9 @@ func (r *liveReceive) periodicACK(now uint64) (ok bool, sequenceNumber circular.
ackSequenceNumber := r.lastDeliveredSequenceNumber ackSequenceNumber := r.lastDeliveredSequenceNumber
// find the sequence number up until we have all in a row. // Find the sequence number up until we have all in a row.
// where the first gap is (or at the end of the list) is where we can ACK to. // Where the first gap is (or at the end of the list) is where we can ACK to.
e := r.packetList.Front() e := r.packetList.Front()
if e != nil { if e != nil {
p := e.Value.(packet.Packet) p := e.Value.(packet.Packet)
@ -560,6 +565,25 @@ func (r *liveReceive) periodicACK(now uint64) (ok bool, sequenceNumber circular.
minPktTsbpdTime = p.Header().PktTsbpdTime minPktTsbpdTime = p.Header().PktTsbpdTime
maxPktTsbpdTime = p.Header().PktTsbpdTime maxPktTsbpdTime = p.Header().PktTsbpdTime
// If there are packets that should be delivered by now, move foward.
if p.Header().PktTsbpdTime <= now {
for e = e.Next(); e != nil; e = e.Next() {
p = e.Value.(packet.Packet)
if p.Header().PktTsbpdTime > now {
break
}
}
ackSequenceNumber = p.Header().PacketSequenceNumber
maxPktTsbpdTime = p.Header().PktTsbpdTime
if e != nil {
e = e.Next()
p = e.Value.(packet.Packet)
}
}
if p.Header().PacketSequenceNumber.Equals(ackSequenceNumber.Inc()) { if p.Header().PacketSequenceNumber.Equals(ackSequenceNumber.Inc()) {
ackSequenceNumber = p.Header().PacketSequenceNumber ackSequenceNumber = p.Header().PacketSequenceNumber
@ -577,7 +601,7 @@ func (r *liveReceive) periodicACK(now uint64) (ok bool, sequenceNumber circular.
ok = true ok = true
sequenceNumber = ackSequenceNumber.Inc() sequenceNumber = ackSequenceNumber.Inc()
// keep track of the last ACK's sequence. with this we can faster ignore // Keep track of the last ACK's sequence. with this we can faster ignore
// packets that come in that have a lower sequence number. // packets that come in that have a lower sequence number.
r.lastACKSequenceNumber = ackSequenceNumber r.lastACKSequenceNumber = ackSequenceNumber
} }
@ -598,12 +622,12 @@ func (r *liveReceive) periodicNAK(now uint64) (ok bool, from, to circular.Number
return return
} }
// send a periodic NAK // Send a periodic NAK
ackSequenceNumber := r.lastDeliveredSequenceNumber ackSequenceNumber := r.lastDeliveredSequenceNumber
// send a NAK only for the first gap. // Send a NAK only for the first gap.
// alternatively send a NAK for max. X gaps because the size of the NAK packet is limited // Alternatively send a NAK for max. X gaps because the size of the NAK packet is limited.
for e := r.packetList.Front(); e != nil; e = e.Next() { for e := r.packetList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet) p := e.Value.(packet.Packet)
@ -634,7 +658,7 @@ func (r *liveReceive) Tick(now uint64) {
r.sendNAK(from, to) r.sendNAK(from, to)
} }
// deliver packets whose PktTsbpdTime is ripe // Deliver packets whose PktTsbpdTime is ripe
r.lock.Lock() r.lock.Lock()
removeList := make([]*list.Element, 0, r.packetList.Len()) removeList := make([]*list.Element, 0, r.packetList.Len())
for e := r.packetList.Front(); e != nil; e = e.Next() { for e := r.packetList.Front(); e != nil; e = e.Next() {
@ -815,12 +839,12 @@ func (r *fakeLiveReceive) Push(pkt packet.Packet) {
r.avgPayloadSize = 0.875*r.avgPayloadSize + 0.125*float64(pktLen) r.avgPayloadSize = 0.875*r.avgPayloadSize + 0.125*float64(pktLen)
if pkt.Header().PacketSequenceNumber.Lte(r.lastDeliveredSequenceNumber) { if pkt.Header().PacketSequenceNumber.Lte(r.lastDeliveredSequenceNumber) {
// too old, because up until r.lastDeliveredSequenceNumber, we already delivered // Too old, because up until r.lastDeliveredSequenceNumber, we already delivered
return return
} }
if pkt.Header().PacketSequenceNumber.Lt(r.lastACKSequenceNumber) { if pkt.Header().PacketSequenceNumber.Lt(r.lastACKSequenceNumber) {
// already acknowledged, ignoring // Already acknowledged, ignoring
return return
} }
@ -838,7 +862,7 @@ func (r *fakeLiveReceive) periodicACK(now uint64) (ok bool, sequenceNumber circu
// 4.8.1. Packet Acknowledgement (ACKs, ACKACKs) // 4.8.1. Packet Acknowledgement (ACKs, ACKACKs)
if now-r.lastPeriodicACK < r.periodicACKInterval { if now-r.lastPeriodicACK < r.periodicACKInterval {
if r.nPackets >= 64 { if r.nPackets >= 64 {
lite = true // send light ACK lite = true // Send light ACK
} else { } else {
return return
} }
@ -860,7 +884,7 @@ func (r *fakeLiveReceive) Tick(now uint64) {
r.sendACK(sequenceNumber, lite) r.sendACK(sequenceNumber, lite)
} }
// deliver packets whose PktTsbpdTime is ripe // Deliver packets whose PktTsbpdTime is ripe
r.lock.Lock() r.lock.Lock()
defer r.lock.Unlock() defer r.lock.Unlock()

View file

@ -23,10 +23,10 @@ type Crypto interface {
// UnmarshalMK unwraps the key with the passphrase in a Key Material Extension Message. If the passphrase // UnmarshalMK unwraps the key with the passphrase in a Key Material Extension Message. If the passphrase
// is wrong an error is returned. // is wrong an error is returned.
UnmarshalKM(km *packet.CIFKM, passphrase string) error UnmarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string) error
// MarshalKM wraps the key with the passphrase and the odd/even SEK for a Key Material Extension Message. // MarshalKM wraps the key with the passphrase and the odd/even SEK for a Key Material Extension Message.
MarshalKM(km *packet.CIFKM, passphrase string, key packet.PacketEncryption) error MarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string, key packet.PacketEncryption) error
// EncryptOrDecryptPayload encrypts or decrypts the data of a packet with an even or odd SEK and // EncryptOrDecryptPayload encrypts or decrypts the data of a packet with an even or odd SEK and
// the sequence number. // the sequence number.
@ -64,15 +64,17 @@ func New(keyLength int) (Crypto, error) {
return nil, fmt.Errorf("crypto: can't generate salt: %w", err) return nil, fmt.Errorf("crypto: can't generate salt: %w", err)
} }
c.evenSEK = make([]byte, c.keyLength) sek, err := c.generateSEK(c.keyLength)
if err := c.GenerateSEK(packet.EvenKeyEncrypted); err != nil { if err != nil {
return nil, err return nil, err
} }
c.evenSEK = sek
c.oddSEK = make([]byte, c.keyLength) sek, err = c.generateSEK(c.keyLength)
if err := c.GenerateSEK(packet.OddKeyEncrypted); err != nil { if err != nil {
return nil, err return nil, err
} }
c.oddSEK = sek
return c, nil return c, nil
} }
@ -82,26 +84,38 @@ func (c *crypto) GenerateSEK(key packet.PacketEncryption) error {
return fmt.Errorf("crypto: unknown key type") return fmt.Errorf("crypto: unknown key type")
} }
sek, err := c.generateSEK(c.keyLength)
if err != nil {
return err
}
if key == packet.EvenKeyEncrypted { if key == packet.EvenKeyEncrypted {
if err := c.prng(c.evenSEK); err != nil { c.evenSEK = sek
return fmt.Errorf("crypto: can't generate even key: %w", err)
}
} else if key == packet.OddKeyEncrypted { } else if key == packet.OddKeyEncrypted {
if err := c.prng(c.oddSEK); err != nil { c.oddSEK = sek
return fmt.Errorf("crypto: can't generate odd key: %w", err)
}
} }
return nil return nil
} }
func (c *crypto) generateSEK(keyLength int) ([]byte, error) {
sek := make([]byte, keyLength)
err := c.prng(sek)
if err != nil {
return nil, fmt.Errorf("crypto: can't generate SEK: %w", err)
}
return sek, nil
}
// ErrInvalidKey is returned when the packet encryption is invalid // ErrInvalidKey is returned when the packet encryption is invalid
var ErrInvalidKey = errors.New("crypto: invalid key for encryption. Must be even, odd, or both") var ErrInvalidKey = errors.New("crypto: invalid key for encryption. Must be even, odd, or both")
// ErrInvalidWrap is returned when the packet encryption indicates a different length of the wrapped key // ErrInvalidWrap is returned when the packet encryption indicates a different length of the wrapped key
var ErrInvalidWrap = errors.New("crypto: the unwrapped key has the wrong length") var ErrInvalidWrap = errors.New("crypto: the unwrapped key has the wrong length")
func (c *crypto) UnmarshalKM(km *packet.CIFKM, passphrase string) error { func (c *crypto) UnmarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string) error {
if km.KeyBasedEncryption == packet.UnencryptedPacket || !km.KeyBasedEncryption.IsValid() { if km.KeyBasedEncryption == packet.UnencryptedPacket || !km.KeyBasedEncryption.IsValid() {
return ErrInvalidKey return ErrInvalidKey
} }
@ -110,7 +124,7 @@ func (c *crypto) UnmarshalKM(km *packet.CIFKM, passphrase string) error {
copy(c.salt, km.Salt) copy(c.salt, km.Salt)
} }
kek := c.calculateKEK(passphrase) kek := c.calculateKEK(passphrase, c.salt, c.keyLength)
unwrap, err := keywrap.Unwrap(kek, km.Wrap) unwrap, err := keywrap.Unwrap(kek, km.Wrap)
if err != nil { if err != nil {
@ -138,7 +152,7 @@ func (c *crypto) UnmarshalKM(km *packet.CIFKM, passphrase string) error {
return nil return nil
} }
func (c *crypto) MarshalKM(km *packet.CIFKM, passphrase string, key packet.PacketEncryption) error { func (c *crypto) MarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string, key packet.PacketEncryption) error {
if key == packet.UnencryptedPacket || !key.IsValid() { if key == packet.UnencryptedPacket || !key.IsValid() {
return ErrInvalidKey return ErrInvalidKey
} }
@ -176,7 +190,7 @@ func (c *crypto) MarshalKM(km *packet.CIFKM, passphrase string, key packet.Packe
copy(w[c.keyLength:], c.oddSEK) copy(w[c.keyLength:], c.oddSEK)
} }
kek := c.calculateKEK(passphrase) kek := c.calculateKEK(passphrase, c.salt, c.keyLength)
wrap, err := keywrap.Wrap(kek, w) wrap, err := keywrap.Wrap(kek, w)
if err != nil { if err != nil {
@ -240,9 +254,9 @@ func (c *crypto) EncryptOrDecryptPayload(data []byte, key packet.PacketEncryptio
} }
// calculateKEK calculates a KEK based on the passphrase. // calculateKEK calculates a KEK based on the passphrase.
func (c *crypto) calculateKEK(passphrase string) []byte { func (c *crypto) calculateKEK(passphrase string, salt []byte, keyLength int) []byte {
// 6.1.4. Key Encrypting Key (KEK) // 6.1.4. Key Encrypting Key (KEK)
return pbkdf2.Key([]byte(passphrase), c.salt[8:], 2048, c.keyLength, sha1.New) return pbkdf2.Key([]byte(passphrase), salt[8:], 2048, keyLength, sha1.New)
} }
// prng generates a random sequence of byte into the given slice p. // prng generates a random sequence of byte into the given slice p.

View file

@ -21,19 +21,52 @@ const MAX_TIMESTAMP uint32 = 0b11111111_11111111_11111111_11111111
const MAX_PAYLOAD_SIZE = 1456 const MAX_PAYLOAD_SIZE = 1456
// Table 1: SRT Control Packet Types // Table 1: SRT Control Packet Types
type CtrlType uint16
const ( const (
CTRLTYPE_HANDSHAKE uint16 = 0x0000 CTRLTYPE_HANDSHAKE CtrlType = 0x0000
CTRLTYPE_KEEPALIVE uint16 = 0x0001 CTRLTYPE_KEEPALIVE CtrlType = 0x0001
CTRLTYPE_ACK uint16 = 0x0002 CTRLTYPE_ACK CtrlType = 0x0002
CTRLTYPE_NAK uint16 = 0x0003 CTRLTYPE_NAK CtrlType = 0x0003
CTRLTYPE_WARN uint16 = 0x0004 // unimplemented, receiver->sender CTRLTYPE_WARN CtrlType = 0x0004 // unimplemented, receiver->sender
CTRLTYPE_SHUTDOWN uint16 = 0x0005 CTRLTYPE_SHUTDOWN CtrlType = 0x0005
CTRLTYPE_ACKACK uint16 = 0x0006 CTRLTYPE_ACKACK CtrlType = 0x0006
CRTLTYPE_DROPREQ uint16 = 0x0007 // unimplemented, sender->receiver CRTLTYPE_DROPREQ CtrlType = 0x0007 // unimplemented, sender->receiver
CRTLTYPE_PEERERROR uint16 = 0x0008 // unimplemented, receiver->sender CRTLTYPE_PEERERROR CtrlType = 0x0008 // unimplemented, receiver->sender
CTRLTYPE_USER uint16 = 0x7FFF CTRLTYPE_USER CtrlType = 0x7FFF
) )
func (h CtrlType) String() string {
switch h {
case CTRLTYPE_HANDSHAKE:
return "HANDSHAKE"
case CTRLTYPE_KEEPALIVE:
return "KEEPALIVE"
case CTRLTYPE_ACK:
return "ACK"
case CTRLTYPE_NAK:
return "NAK"
case CTRLTYPE_WARN:
return "WARN"
case CTRLTYPE_SHUTDOWN:
return "SHUTDOWN"
case CTRLTYPE_ACKACK:
return "ACKACK"
case CRTLTYPE_DROPREQ:
return "DROPREQ"
case CRTLTYPE_PEERERROR:
return "PEERERROR"
case CTRLTYPE_USER:
return "USER"
}
return "unknown"
}
func (h CtrlType) Value() uint16 {
return uint16(h)
}
type HandshakeType uint32 type HandshakeType uint32
// Table 4: Handshake Type // Table 4: Handshake Type
@ -159,17 +192,49 @@ const (
) )
// Table 5: Handshake Extension Type values // Table 5: Handshake Extension Type values
type CtrlSubType uint16
const ( const (
EXTTYPE_HSREQ uint16 = 1 CTRLSUBTYPE_NONE CtrlSubType = 0
EXTTYPE_HSRSP uint16 = 2 EXTTYPE_HSREQ CtrlSubType = 1
EXTTYPE_KMREQ uint16 = 3 EXTTYPE_HSRSP CtrlSubType = 2
EXTTYPE_KMRSP uint16 = 4 EXTTYPE_KMREQ CtrlSubType = 3
EXTTYPE_SID uint16 = 5 EXTTYPE_KMRSP CtrlSubType = 4
EXTTYPE_CONGESTION uint16 = 6 EXTTYPE_SID CtrlSubType = 5
EXTTYPE_FILTER uint16 = 7 EXTTYPE_CONGESTION CtrlSubType = 6
EXTTYPE_GROUP uint16 = 8 EXTTYPE_FILTER CtrlSubType = 7
EXTTYPE_GROUP CtrlSubType = 8
) )
func (h CtrlSubType) String() string {
switch h {
case CTRLSUBTYPE_NONE:
return "NONE"
case EXTTYPE_HSREQ:
return "EXTTYPE_HSREQ"
case EXTTYPE_HSRSP:
return "EXTTYPE_HSRSP"
case EXTTYPE_KMREQ:
return "EXTTYPE_KMREQ"
case EXTTYPE_KMRSP:
return "EXTTYPE_KMRSP"
case EXTTYPE_SID:
return "EXTTYPE_SID"
case EXTTYPE_CONGESTION:
return "EXTTYPE_CONGESTION"
case EXTTYPE_FILTER:
return "EXTTYPE_FILTER"
case EXTTYPE_GROUP:
return "EXTTYPE_GROUP"
}
return "unknown"
}
func (h CtrlSubType) Value() uint16 {
return uint16(h)
}
type Packet interface { type Packet interface {
String() string String() string
Clone() Packet Clone() Packet
@ -194,18 +259,18 @@ type PacketHeader struct {
// control packet fields // control packet fields
ControlType uint16 ControlType CtrlType // Control Packet Type. The use of these bits is determined by the control packet type definition.
SubType uint16 SubType CtrlSubType // This field specifies an additional subtype for specific packets.
TypeSpecific uint32 TypeSpecific uint32 // The use of this field depends on the particular control packet type. Handshake packets do not use this field.
// data packet fields // data packet fields
PacketSequenceNumber circular.Number PacketSequenceNumber circular.Number // The sequential number of the data packet.
PacketPositionFlag PacketPosition PacketPositionFlag PacketPosition // This field indicates the position of the data packet in the message. The value "10b" (binary) means the first packet of the message. "00b" indicates a packet in the middle. "01b" designates the last packet. If a single data packet forms the whole message, the value is "11b".
OrderFlag bool OrderFlag bool // Indicates whether the message should be delivered by the receiver in order (1) or not (0). Certain restrictions apply depending on the data transmission mode used (Section 4.2).
KeyBaseEncryptionFlag PacketEncryption KeyBaseEncryptionFlag PacketEncryption // The flag bits indicate whether or not data is encrypted. The value "00b" (binary) means data is not encrypted. "01b" indicates that data is encrypted with an even key, and "10b" is used for odd key encryption. Refer to Section 6. The value "11b" is only used in control packets.
RetransmittedPacketFlag bool RetransmittedPacketFlag bool // This flag is clear when a packet is transmitted the first time. The flag is set to "1" when a packet is retransmitted.
MessageNumber uint32 MessageNumber uint32 // The sequential number of consecutive data packets that form a message (see PP field).
// common fields // common fields
@ -250,8 +315,9 @@ func NewPacket(addr net.Addr, rawdata []byte) Packet {
p := &pkt{ p := &pkt{
header: PacketHeader{ header: PacketHeader{
Addr: addr, Addr: addr,
PacketSequenceNumber: circular.New(0, 0b01111111_11111111_11111111_11111111), PacketSequenceNumber: circular.New(0, MAX_SEQUENCENUMBER),
PacketPositionFlag: SinglePacket, PacketPositionFlag: SinglePacket,
OrderFlag: false,
KeyBaseEncryptionFlag: UnencryptedPacket, KeyBaseEncryptionFlag: UnencryptedPacket,
MessageNumber: 1, MessageNumber: 1,
}, },
@ -284,8 +350,8 @@ func (p pkt) String() string {
if p.header.IsControlPacket { if p.header.IsControlPacket {
fmt.Fprintf(&b, "control packet:\n") fmt.Fprintf(&b, "control packet:\n")
fmt.Fprintf(&b, " controlType=%#04x\n", p.header.ControlType) fmt.Fprintf(&b, " controlType=%#04x (%s)\n", p.header.ControlType.Value(), p.header.ControlType.String())
fmt.Fprintf(&b, " subType=%#04x\n", p.header.SubType) fmt.Fprintf(&b, " subType=%#04x (%s)\n", p.header.SubType.Value(), p.header.SubType.String())
fmt.Fprintf(&b, " typeSpecific=%#08x\n", p.header.TypeSpecific) fmt.Fprintf(&b, " typeSpecific=%#08x\n", p.header.TypeSpecific)
} else { } else {
fmt.Fprintf(&b, "data packet:\n") fmt.Fprintf(&b, "data packet:\n")
@ -336,8 +402,8 @@ func (p *pkt) Unmarshal(data []byte) error {
p.header.IsControlPacket = (data[0] & 0x80) != 0 p.header.IsControlPacket = (data[0] & 0x80) != 0
if p.header.IsControlPacket { if p.header.IsControlPacket {
p.header.ControlType = binary.BigEndian.Uint16(data[0:]) & ^uint16(1<<15) // clear the first bit p.header.ControlType = CtrlType(binary.BigEndian.Uint16(data[0:]) & ^uint16(1<<15)) // clear the first bit
p.header.SubType = binary.BigEndian.Uint16(data[2:]) p.header.SubType = CtrlSubType(binary.BigEndian.Uint16(data[2:]))
p.header.TypeSpecific = binary.BigEndian.Uint32(data[4:]) p.header.TypeSpecific = binary.BigEndian.Uint32(data[4:])
} else { } else {
p.header.PacketSequenceNumber = circular.New(binary.BigEndian.Uint32(data[0:]), MAX_SEQUENCENUMBER) p.header.PacketSequenceNumber = circular.New(binary.BigEndian.Uint32(data[0:]), MAX_SEQUENCENUMBER)
@ -345,7 +411,7 @@ func (p *pkt) Unmarshal(data []byte) error {
p.header.OrderFlag = (data[4] & 0b00100000) != 0 p.header.OrderFlag = (data[4] & 0b00100000) != 0
p.header.KeyBaseEncryptionFlag = PacketEncryption((data[4] & 0b00011000) >> 3) p.header.KeyBaseEncryptionFlag = PacketEncryption((data[4] & 0b00011000) >> 3)
p.header.RetransmittedPacketFlag = (data[4] & 0b00000100) != 0 p.header.RetransmittedPacketFlag = (data[4] & 0b00000100) != 0
p.header.MessageNumber = binary.BigEndian.Uint32(data[4:]) & ^uint32(0b11111000<<24) p.header.MessageNumber = binary.BigEndian.Uint32(data[4:]) & ^uint32(0b11111100<<24)
} }
p.header.Timestamp = binary.BigEndian.Uint32(data[8:]) p.header.Timestamp = binary.BigEndian.Uint32(data[8:])
@ -365,28 +431,28 @@ func (p *pkt) Marshal(w io.Writer) error {
} }
if p.header.IsControlPacket { if p.header.IsControlPacket {
binary.BigEndian.PutUint16(buffer[0:], p.header.ControlType) // control type binary.BigEndian.PutUint16(buffer[0:], p.header.ControlType.Value()) // control type
binary.BigEndian.PutUint16(buffer[2:], p.header.SubType) // sub type binary.BigEndian.PutUint16(buffer[2:], p.header.SubType.Value()) // sub type
binary.BigEndian.PutUint32(buffer[4:], p.header.TypeSpecific) // type specific binary.BigEndian.PutUint32(buffer[4:], p.header.TypeSpecific) // type specific
buffer[0] |= 0x80 buffer[0] |= 0x80
} else { } else {
binary.BigEndian.PutUint32(buffer[0:], p.header.PacketSequenceNumber.Val()) // sequence number binary.BigEndian.PutUint32(buffer[0:], p.header.PacketSequenceNumber.Val()) // sequence number
p.header.TypeSpecific = 0 var field uint32 = 0
p.header.TypeSpecific |= (uint32(p.header.PacketPositionFlag) << 6) field |= ((p.header.PacketPositionFlag.Val() & 0b11) << 6) // 0b11000000
if p.header.OrderFlag { if p.header.OrderFlag {
p.header.TypeSpecific |= (1 << 5) field |= (1 << 5) // 0b11100000
} }
p.header.TypeSpecific |= (uint32(p.header.KeyBaseEncryptionFlag) << 3) field |= ((p.header.KeyBaseEncryptionFlag.Val() & 0b11) << 3) // 0b11111000
if p.header.RetransmittedPacketFlag { if p.header.RetransmittedPacketFlag {
p.header.TypeSpecific |= (1 << 2) field |= (1 << 2) // 0b11111100
} }
p.header.TypeSpecific = p.header.TypeSpecific << 24 field = field << 24 // 0b11111100_00000000_00000000_00000000
p.header.TypeSpecific += p.header.MessageNumber field += (p.header.MessageNumber & 0b00000011_11111111_11111111_11111111)
binary.BigEndian.PutUint32(buffer[4:], p.header.TypeSpecific) // sequence number binary.BigEndian.PutUint32(buffer[4:], field) // sequence number
} }
binary.BigEndian.PutUint32(buffer[8:], p.header.Timestamp) // timestamp binary.BigEndian.PutUint32(buffer[8:], p.header.Timestamp) // timestamp
@ -425,6 +491,7 @@ func (p *pkt) UnmarshalCIF(c CIF) error {
type CIF interface { type CIF interface {
Marshal(w io.Writer) Marshal(w io.Writer)
Unmarshal(data []byte) error Unmarshal(data []byte) error
String() string
} }
// 3.2.1. Handshake // 3.2.1. Handshake
@ -432,39 +499,26 @@ type CIF interface {
type CIFHandshake struct { type CIFHandshake struct {
IsRequest bool IsRequest bool
Version uint32 Version uint32 // A base protocol version number. Currently used values are 4 and 5. Values greater than 5 are reserved for future use.
EncryptionField uint16 EncryptionField uint16 // Block cipher family and key size. The values of this field are described in Table 2. The default value is AES-128.
ExtensionField uint16 ExtensionField uint16 // This field is message specific extension related to Handshake Type field. The value MUST be set to 0 except for the following cases. (1) If the handshake control packet is the INDUCTION message, this field is sent back by the Listener. (2) In the case of a CONCLUSION message, this field value should contain a combination of Extension Type values. For more details, see Section 4.3.1.
InitialPacketSequenceNumber circular.Number InitialPacketSequenceNumber circular.Number // The sequence number of the very first data packet to be sent.
MaxTransmissionUnitSize uint32 MaxTransmissionUnitSize uint32 // This value is typically set to 1500, which is the default Maximum Transmission Unit (MTU) size for Ethernet, but can be less.
MaxFlowWindowSize uint32 MaxFlowWindowSize uint32 // The value of this field is the maximum number of data packets allowed to be "in flight" (i.e. the number of sent packets for which an ACK control packet has not yet been received).
HandshakeType HandshakeType HandshakeType HandshakeType // This field indicates the handshake packet type. The possible values are described in Table 4. For more details refer to Section 4.3.
SRTSocketId uint32 SRTSocketId uint32 // This field holds the ID of the source SRT socket from which a handshake packet is issued.
SynCookie uint32 SynCookie uint32 // Randomized value for processing a handshake. The value of this field is specified by the handshake message type. See Section 4.3.
PeerIP srtnet.IP PeerIP srtnet.IP // IPv4 or IPv6 address of the packet's sender. The value consists of four 32-bit fields. In the case of IPv4 addresses, fields 2, 3 and 4 are filled with zeroes.
HasHS bool HasHS bool
HasKM bool HasKM bool
HasSID bool HasSID bool
// 3.2.1.1. Handshake Extension Message // 3.2.1.1. Handshake Extension Message
SRTHS *CIFHandshakeExtension
SRTVersion uint32
SRTFlags struct { // 3.2.1.1.1. Handshake Extension Message Flags
TSBPDSND bool
TSBPDRCV bool
CRYPT bool
TLPKTDROP bool
PERIODICNAK bool
REXMITFLG bool
STREAM bool
PACKET_FILTER bool
}
RecvTSBPDDelay uint16 // milliseconds, see "4.4. SRT Buffer Latency"
SendTSBPDDelay uint16 // milliseconds, see "4.4. SRT Buffer Latency"
// 3.2.1.2. Key Material Extension Message // 3.2.1.2. Key Material Extension Message
SRTKM *CIFKM SRTKM *CIFKeyMaterialExtension
// 3.2.1.3. Stream ID Extension Message // 3.2.1.3. Stream ID Extension Message
StreamId string StreamId string
@ -486,45 +540,20 @@ func (c CIFHandshake) String() string {
fmt.Fprintf(&b, " synCookie: %#08x\n", c.SynCookie) fmt.Fprintf(&b, " synCookie: %#08x\n", c.SynCookie)
fmt.Fprintf(&b, " peerIP: %s\n", c.PeerIP) fmt.Fprintf(&b, " peerIP: %s\n", c.PeerIP)
if c.Version == 5 {
if c.HasHS { if c.HasHS {
fmt.Fprintf(&b, " SRT_CMD_HS(REQ/RSP)\n") fmt.Fprintf(&b, "%s\n", c.SRTHS.String())
fmt.Fprintf(&b, " srtVersion: %#08x\n", c.SRTVersion)
fmt.Fprintf(&b, " srtFlags:\n")
fmt.Fprintf(&b, " TSBPDSND : %v\n", c.SRTFlags.TSBPDSND)
fmt.Fprintf(&b, " TSBPDRCV : %v\n", c.SRTFlags.TSBPDRCV)
fmt.Fprintf(&b, " CRYPT : %v\n", c.SRTFlags.CRYPT)
fmt.Fprintf(&b, " TLPKTDROP : %v\n", c.SRTFlags.TLPKTDROP)
fmt.Fprintf(&b, " PERIODICNAK : %v\n", c.SRTFlags.PERIODICNAK)
fmt.Fprintf(&b, " REXMITFLG : %v\n", c.SRTFlags.REXMITFLG)
fmt.Fprintf(&b, " STREAM : %v\n", c.SRTFlags.STREAM)
fmt.Fprintf(&b, " PACKET_FILTER: %v\n", c.SRTFlags.PACKET_FILTER)
fmt.Fprintf(&b, " recvTSBPDDelay: %#04x (%dms)\n", c.RecvTSBPDDelay, c.RecvTSBPDDelay)
fmt.Fprintf(&b, " sendTSBPDDelay: %#04x (%dms)\n", c.SendTSBPDDelay, c.SendTSBPDDelay)
} }
if c.HasKM { if c.HasKM {
fmt.Fprintf(&b, " SRT_CMD_KM(REQ/RSP)\n") fmt.Fprintf(&b, "%s\n", c.SRTKM.String())
fmt.Fprintf(&b, " s: %d\n", c.SRTKM.S)
fmt.Fprintf(&b, " version: %d\n", c.SRTKM.Version)
fmt.Fprintf(&b, " packetType: %d\n", c.SRTKM.PacketType)
fmt.Fprintf(&b, " sign: %#08x\n", c.SRTKM.Sign)
fmt.Fprintf(&b, " resv1: %d\n", c.SRTKM.Resv1)
fmt.Fprintf(&b, " keyBasedEncryption: %s\n", c.SRTKM.KeyBasedEncryption.String())
fmt.Fprintf(&b, " keyEncryptionKeyIndex: %d\n", c.SRTKM.KeyEncryptionKeyIndex)
fmt.Fprintf(&b, " cipher: %d\n", c.SRTKM.Cipher)
fmt.Fprintf(&b, " authentication: %d\n", c.SRTKM.Authentication)
fmt.Fprintf(&b, " streamEncapsulation: %d\n", c.SRTKM.StreamEncapsulation)
fmt.Fprintf(&b, " resv2: %d\n", c.SRTKM.Resv2)
fmt.Fprintf(&b, " resv3: %d\n", c.SRTKM.Resv3)
fmt.Fprintf(&b, " sLen: %d (%d)\n", c.SRTKM.SLen, c.SRTKM.SLen/4)
fmt.Fprintf(&b, " kLen: %d (%d)\n", c.SRTKM.KLen, c.SRTKM.KLen/4)
fmt.Fprintf(&b, " salt: %#08x\n", c.SRTKM.Salt)
fmt.Fprintf(&b, " wrap: %#08x\n", c.SRTKM.Wrap)
} }
if c.HasSID { if c.HasSID {
fmt.Fprintf(&b, " SRT_CMD_SID\n") fmt.Fprintf(&b, "--- SIDExt ---\n")
fmt.Fprintf(&b, " streamId : %s\n", c.StreamId) fmt.Fprintf(&b, " streamId : %s\n", c.StreamId)
fmt.Fprintf(&b, "--- /SIDExt ---\n")
}
} }
fmt.Fprintf(&b, "--- /handshake ---") fmt.Fprintf(&b, "--- /handshake ---")
@ -548,10 +577,6 @@ func (c *CIFHandshake) Unmarshal(data []byte) error {
c.SynCookie = binary.BigEndian.Uint32(data[28:]) c.SynCookie = binary.BigEndian.Uint32(data[28:])
c.PeerIP.Unmarshal(data[32:48]) c.PeerIP.Unmarshal(data[32:48])
//if c.handshakeType != HSTYPE_INDUCTION && c.handshakeType != HSTYPE_CONCLUSION {
// return fmt.Errorf("unimplemented handshake type")
//}
if c.HandshakeType == HSTYPE_INDUCTION { if c.HandshakeType == HSTYPE_INDUCTION {
// Nothing more to unmarshal // Nothing more to unmarshal
return nil return nil
@ -567,7 +592,8 @@ func (c *CIFHandshake) Unmarshal(data []byte) error {
} }
if len(data) <= 48 { if len(data) <= 48 {
return fmt.Errorf("data too short to unmarshal") // No extension data
return nil
} }
switch c.EncryptionField { switch c.EncryptionField {
@ -582,7 +608,7 @@ func (c *CIFHandshake) Unmarshal(data []byte) error {
pivot := data[48:] pivot := data[48:]
for { for {
extensionType := binary.BigEndian.Uint16(pivot[0:]) extensionType := CtrlSubType(binary.BigEndian.Uint16(pivot[0:]))
extensionLength := int(binary.BigEndian.Uint16(pivot[2:])) * 4 extensionLength := int(binary.BigEndian.Uint16(pivot[2:])) * 4
pivot = pivot[4:] pivot = pivot[4:]
@ -595,20 +621,11 @@ func (c *CIFHandshake) Unmarshal(data []byte) error {
c.HasHS = true c.HasHS = true
c.SRTVersion = binary.BigEndian.Uint32(pivot[0:]) c.SRTHS = &CIFHandshakeExtension{}
srtFlags := binary.BigEndian.Uint32(pivot[4:])
c.SRTFlags.TSBPDSND = (srtFlags&SRTFLAG_TSBPDSND != 0) if err := c.SRTHS.Unmarshal(pivot); err != nil {
c.SRTFlags.TSBPDRCV = (srtFlags&SRTFLAG_TSBPDRCV != 0) return fmt.Errorf("CIFHandshakeExtension: %w", err)
c.SRTFlags.CRYPT = (srtFlags&SRTFLAG_CRYPT != 0) }
c.SRTFlags.TLPKTDROP = (srtFlags&SRTFLAG_TLPKTDROP != 0)
c.SRTFlags.PERIODICNAK = (srtFlags&SRTFLAG_PERIODICNAK != 0)
c.SRTFlags.REXMITFLG = (srtFlags&SRTFLAG_REXMITFLG != 0)
c.SRTFlags.STREAM = (srtFlags&SRTFLAG_STREAM != 0)
c.SRTFlags.PACKET_FILTER = (srtFlags&SRTFLAG_PACKET_FILTER != 0)
c.RecvTSBPDDelay = binary.BigEndian.Uint16(pivot[8:])
c.SendTSBPDDelay = binary.BigEndian.Uint16(pivot[10:])
} else if extensionType == EXTTYPE_KMREQ || extensionType == EXTTYPE_KMRSP { } else if extensionType == EXTTYPE_KMREQ || extensionType == EXTTYPE_KMRSP {
// 3.2.1.2. Key Material Extension Message // 3.2.1.2. Key Material Extension Message
if len(pivot) < extensionLength { if len(pivot) < extensionLength {
@ -617,10 +634,10 @@ func (c *CIFHandshake) Unmarshal(data []byte) error {
c.HasKM = true c.HasKM = true
c.SRTKM = &CIFKM{} c.SRTKM = &CIFKeyMaterialExtension{}
if err := c.SRTKM.Unmarshal(pivot); err != nil { if err := c.SRTKM.Unmarshal(pivot); err != nil {
return err return fmt.Errorf("CIFKeyMaterialExtension: %w", err)
} }
if c.EncryptionField == 0 { if c.EncryptionField == 0 {
@ -674,6 +691,7 @@ func (c *CIFHandshake) Marshal(w io.Writer) {
c.HasSID = false c.HasSID = false
} }
if c.Version == 5 {
if c.HandshakeType == HSTYPE_CONCLUSION { if c.HandshakeType == HSTYPE_CONCLUSION {
c.ExtensionField = 0 c.ExtensionField = 0
} }
@ -683,12 +701,17 @@ func (c *CIFHandshake) Marshal(w io.Writer) {
} }
if c.HasKM { if c.HasKM {
c.EncryptionField = c.SRTKM.KLen / 8
c.ExtensionField = c.ExtensionField | 2 c.ExtensionField = c.ExtensionField | 2
} }
if c.HasSID { if c.HasSID {
c.ExtensionField = c.ExtensionField | 4 c.ExtensionField = c.ExtensionField | 4
} }
} else {
c.EncryptionField = 0
c.ExtensionField = 2
}
binary.BigEndian.PutUint32(buffer[0:], c.Version) // version binary.BigEndian.PutUint32(buffer[0:], c.Version) // version
binary.BigEndian.PutUint16(buffer[4:], c.EncryptionField) // encryption field binary.BigEndian.PutUint16(buffer[4:], c.EncryptionField) // encryption field
@ -704,15 +727,138 @@ func (c *CIFHandshake) Marshal(w io.Writer) {
w.Write(buffer[:48]) w.Write(buffer[:48])
if c.HasHS { if c.HasHS {
var data bytes.Buffer
c.SRTHS.Marshal(&data)
if c.IsRequest { if c.IsRequest {
binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_HSREQ) binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_HSREQ.Value())
} else { } else {
binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_HSRSP) binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_HSRSP.Value())
} }
binary.BigEndian.PutUint16(buffer[2:], 3) binary.BigEndian.PutUint16(buffer[2:], 3)
binary.BigEndian.PutUint32(buffer[4:], c.SRTVersion) w.Write(buffer[:4])
w.Write(data.Bytes())
}
if c.HasKM {
var data bytes.Buffer
c.SRTKM.Marshal(&data)
if c.IsRequest {
binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_KMREQ.Value())
} else {
binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_KMRSP.Value())
}
binary.BigEndian.PutUint16(buffer[2:], uint16(data.Len()/4))
w.Write(buffer[:4])
w.Write(data.Bytes())
}
if c.HasSID {
streamId := bytes.NewBufferString(c.StreamId)
missing := (4 - streamId.Len()%4)
if missing < 4 {
for i := 0; i < missing; i++ {
streamId.WriteByte(0)
}
}
binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_SID.Value())
binary.BigEndian.PutUint16(buffer[2:], uint16(streamId.Len()/4))
w.Write(buffer[:4])
b := streamId.Bytes()
for i := 0; i < len(b); i += 4 {
buffer[0] = b[i+3]
buffer[1] = b[i+2]
buffer[2] = b[i+1]
buffer[3] = b[i+0]
w.Write(buffer[:4])
}
}
}
// 3.2.1.1.1. Handshake Extension Message Flags
type CIFHandshakeExtensionFlags struct {
TSBPDSND bool // Defines if the TSBPD mechanism (Section 4.5) will be used for sending.
TSBPDRCV bool // Defines if the TSBPD mechanism (Section 4.5) will be used for receiving.
CRYPT bool // MUST be set. It is a legacy flag that indicates the party understands KK field of the SRT Packet (Figure 3).
TLPKTDROP bool // Should be set if too-late packet drop mechanism will be used during transmission. See Section 4.6.
PERIODICNAK bool // Indicates the peer will send periodic NAK packets. See Section 4.8.2.
REXMITFLG bool // MUST be set. It is a legacy flag that indicates the peer understands the R field of the SRT DATA Packet
STREAM bool // Identifies the transmission mode (Section 4.2) to be used in the connection. If the flag is set, the buffer mode (Section 4.2.2) is used. Otherwise, the message mode (Section 4.2.1) is used.
PACKET_FILTER bool // Indicates if the peer supports packet filter.
}
// 3.2.1.1. Handshake Extension Message
type CIFHandshakeExtension struct {
SRTVersion uint32
SRTFlags CIFHandshakeExtensionFlags
RecvTSBPDDelay uint16 // milliseconds, see "4.4. SRT Buffer Latency"
SendTSBPDDelay uint16 // milliseconds, see "4.4. SRT Buffer Latency"
}
func (c CIFHandshakeExtension) String() string {
var b strings.Builder
fmt.Fprintf(&b, "--- HSExt ---\n")
fmt.Fprintf(&b, " srtVersion: %#08x\n", c.SRTVersion)
fmt.Fprintf(&b, " srtFlags:\n")
fmt.Fprintf(&b, " TSBPDSND : %v\n", c.SRTFlags.TSBPDSND)
fmt.Fprintf(&b, " TSBPDRCV : %v\n", c.SRTFlags.TSBPDRCV)
fmt.Fprintf(&b, " CRYPT : %v\n", c.SRTFlags.CRYPT)
fmt.Fprintf(&b, " TLPKTDROP : %v\n", c.SRTFlags.TLPKTDROP)
fmt.Fprintf(&b, " PERIODICNAK : %v\n", c.SRTFlags.PERIODICNAK)
fmt.Fprintf(&b, " REXMITFLG : %v\n", c.SRTFlags.REXMITFLG)
fmt.Fprintf(&b, " STREAM : %v\n", c.SRTFlags.STREAM)
fmt.Fprintf(&b, " PACKET_FILTER: %v\n", c.SRTFlags.PACKET_FILTER)
fmt.Fprintf(&b, " recvTSBPDDelay: %#04x (%dms)\n", c.RecvTSBPDDelay, c.RecvTSBPDDelay)
fmt.Fprintf(&b, " sendTSBPDDelay: %#04x (%dms)\n", c.SendTSBPDDelay, c.SendTSBPDDelay)
fmt.Fprintf(&b, "--- /HSExt ---")
return b.String()
}
func (c *CIFHandshakeExtension) Unmarshal(data []byte) error {
if len(data) < 12 {
return fmt.Errorf("data too short to unmarshal")
}
c.SRTVersion = binary.BigEndian.Uint32(data[0:])
srtFlags := binary.BigEndian.Uint32(data[4:])
c.SRTFlags.TSBPDSND = (srtFlags&SRTFLAG_TSBPDSND != 0)
c.SRTFlags.TSBPDRCV = (srtFlags&SRTFLAG_TSBPDRCV != 0)
c.SRTFlags.CRYPT = (srtFlags&SRTFLAG_CRYPT != 0)
c.SRTFlags.TLPKTDROP = (srtFlags&SRTFLAG_TLPKTDROP != 0)
c.SRTFlags.PERIODICNAK = (srtFlags&SRTFLAG_PERIODICNAK != 0)
c.SRTFlags.REXMITFLG = (srtFlags&SRTFLAG_REXMITFLG != 0)
c.SRTFlags.STREAM = (srtFlags&SRTFLAG_STREAM != 0)
c.SRTFlags.PACKET_FILTER = (srtFlags&SRTFLAG_PACKET_FILTER != 0)
c.RecvTSBPDDelay = binary.BigEndian.Uint16(data[8:])
c.SendTSBPDDelay = binary.BigEndian.Uint16(data[10:])
return nil
}
func (c *CIFHandshakeExtension) Marshal(w io.Writer) {
var buffer [12]byte
binary.BigEndian.PutUint32(buffer[0:], c.SRTVersion)
var srtFlags uint32 = 0 var srtFlags uint32 = 0
if c.SRTFlags.TSBPDSND { if c.SRTFlags.TSBPDSND {
@ -747,83 +893,44 @@ func (c *CIFHandshake) Marshal(w io.Writer) {
srtFlags |= SRTFLAG_PACKET_FILTER srtFlags |= SRTFLAG_PACKET_FILTER
} }
binary.BigEndian.PutUint32(buffer[8:], srtFlags) binary.BigEndian.PutUint32(buffer[4:], srtFlags)
binary.BigEndian.PutUint16(buffer[12:], c.RecvTSBPDDelay) binary.BigEndian.PutUint16(buffer[8:], c.RecvTSBPDDelay)
binary.BigEndian.PutUint16(buffer[14:], c.SendTSBPDDelay) binary.BigEndian.PutUint16(buffer[10:], c.SendTSBPDDelay)
w.Write(buffer[:16]) w.Write(buffer[:12])
}
if c.HasKM {
var data bytes.Buffer
c.SRTKM.Marshal(&data)
if c.IsRequest {
binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_KMREQ)
} else {
binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_KMRSP)
}
binary.BigEndian.PutUint16(buffer[2:], uint16(data.Len()/4))
w.Write(buffer[:4])
w.Write(data.Bytes())
}
if c.HasSID {
streamId := bytes.NewBufferString(c.StreamId)
missing := (4 - streamId.Len()%4)
if missing < 4 {
for i := 0; i < missing; i++ {
streamId.WriteByte(0)
}
}
binary.BigEndian.PutUint16(buffer[0:], EXTTYPE_SID)
binary.BigEndian.PutUint16(buffer[2:], uint16(streamId.Len()/4))
w.Write(buffer[:4])
b := streamId.Bytes()
for i := 0; i < len(b); i += 4 {
buffer[0] = b[i+3]
buffer[1] = b[i+2]
buffer[2] = b[i+1]
buffer[3] = b[i+0]
w.Write(buffer[:4])
}
}
} }
// 3.2.2. Key Material // 3.2.2. Key Material
type CIFKM struct { const (
S uint8 KM_NOSECRET uint32 = 3
Version uint8 KM_BADSECRET uint32 = 4
PacketType uint8 )
Sign uint16
Resv1 uint8 type CIFKeyMaterialExtension struct {
KeyBasedEncryption PacketEncryption Error uint32
KeyEncryptionKeyIndex uint32 S uint8 // This is a fixed-width field that is reserved for future usage. value = {0}
Cipher uint8 Version uint8 // This is a fixed-width field that indicates the SRT version. value = {1}
Authentication uint8 PacketType uint8 // This is a fixed-width field that indicates the Packet Type: 0: Reserved, 1: Media Stream Message (MSmsg), 2: Keying Material Message (KMmsg), 7: Reserved to discriminate MPEG-TS packet (0x47=sync byte). value = {2}
StreamEncapsulation uint8 Sign uint16 // This is a fixed-width field that contains the signature 'HAI' encoded as a PnP Vendor ID [PNPID] (in big-endian order). value = {0x2029}
Resv2 uint8 Resv1 uint8 // This is a fixed-width field reserved for flag extension or other usage. value = {0}
Resv3 uint16 KeyBasedEncryption PacketEncryption // This is a fixed-width field that indicates which SEKs (odd and/or even) are provided in the extension: 00b: No SEK is provided (invalid extension format); 01b: Even key is provided; 10b: Odd key is provided; 11b: Both even and odd keys are provided.
SLen uint16 KeyEncryptionKeyIndex uint32 // This is a fixed-width field for specifying the KEK index (big-endian order) was used to wrap (and optionally authenticate) the SEK(s). The value 0 is used to indicate the default key of the current stream. Other values are reserved for the possible use of a key management system in the future to retrieve a cryptographic context. 0: Default stream associated key (stream/system default); 1..255: Reserved for manually indexed keys. value = {0}
KLen uint16 Cipher uint8 // This is a fixed-width field for specifying encryption cipher and mode: 0: None or KEKI indexed crypto context; 2: AES-CTR [SP800-38A].
Salt []byte Authentication uint8 // This is a fixed-width field for specifying a message authentication code algorithm: 0: None or KEKI indexed crypto context.
Wrap []byte StreamEncapsulation uint8 // This is a fixed-width field for describing the stream encapsulation: 0: Unspecified or KEKI indexed crypto context; 1: MPEG-TS/UDP; 2: MPEG-TS/SRT. value = {2}
Resv2 uint8 // This is a fixed-width field reserved for future use. value = {0}
Resv3 uint16 // This is a fixed-width field reserved for future use. value = {0}
SLen uint16 // This is a fixed-width field for specifying salt length SLen in bytes divided by 4. Can be zero if no salt/IV present. The only valid length of salt defined is 128 bits.
KLen uint16 // This is a fixed-width field for specifying SEK length in bytes divided by 4. Size of one key even if two keys present. MUST match the key size specified in the Encryption Field of the handshake packet Table 2.
Salt []byte // This is a variable-width field that complements the keying material by specifying a salt key.
Wrap []byte // (64 + n * KLen * 8) bits. This is a variable- width field for specifying Wrapped key(s), where n = (KK + 1)/2 and the size of the wrap field is ((n * KLen) + 8) bytes.
} }
func (c CIFKM) String() string { func (c CIFKeyMaterialExtension) String() string {
var b strings.Builder var b strings.Builder
fmt.Fprintf(&b, "--- KM ---\n") fmt.Fprintf(&b, "--- KMExt ---\n")
fmt.Fprintf(&b, " s: %d\n", c.S) fmt.Fprintf(&b, " s: %d\n", c.S)
fmt.Fprintf(&b, " version: %d\n", c.Version) fmt.Fprintf(&b, " version: %d\n", c.Version)
@ -842,13 +949,20 @@ func (c CIFKM) String() string {
fmt.Fprintf(&b, " salt: %#08x\n", c.Salt) fmt.Fprintf(&b, " salt: %#08x\n", c.Salt)
fmt.Fprintf(&b, " wrap: %#08x\n", c.Wrap) fmt.Fprintf(&b, " wrap: %#08x\n", c.Wrap)
fmt.Fprintf(&b, "--- /KM ---") fmt.Fprintf(&b, "--- /KMExt ---")
return b.String() return b.String()
} }
func (c *CIFKM) Unmarshal(data []byte) error { func (c *CIFKeyMaterialExtension) Unmarshal(data []byte) error {
if len(data) < 16 { if len(data) == 4 {
// This is an error response
c.Error = binary.LittleEndian.Uint32(data[0:])
if c.Error != KM_NOSECRET && c.Error != KM_BADSECRET {
return fmt.Errorf("invalid error (%d)", c.Error)
}
return nil
} else if len(data) < 16 {
return fmt.Errorf("data too short to unmarshal") return fmt.Errorf("data too short to unmarshal")
} }
@ -935,7 +1049,7 @@ func (c *CIFKM) Unmarshal(data []byte) error {
return nil return nil
} }
func (c *CIFKM) Marshal(w io.Writer) { func (c *CIFKeyMaterialExtension) Marshal(w io.Writer) {
var buffer [128]byte var buffer [128]byte
b := byte(0) b := byte(0)
@ -1217,6 +1331,10 @@ func (p PacketPosition) IsValid() bool {
return p < 4 return p < 4
} }
func (p PacketPosition) Val() uint32 {
return uint32(p)
}
// 3.1. Data Packets // 3.1. Data Packets
type PacketEncryption uint type PacketEncryption uint
@ -1258,3 +1376,7 @@ func (p PacketEncryption) Opposite() PacketEncryption {
return p return p
} }
func (p PacketEncryption) Val() uint32 {
return uint32(p)
}

View file

@ -8,7 +8,6 @@ import (
"net" "net"
"os" "os"
"sync" "sync"
"syscall"
"time" "time"
"github.com/datarhei/gosrt/internal/crypto" "github.com/datarhei/gosrt/internal/crypto"
@ -46,6 +45,12 @@ type ConnRequest interface {
// is a copy and can be used at will. // is a copy and can be used at will.
RemoteAddr() net.Addr RemoteAddr() net.Addr
// Version returns the handshake version of the incoming request. Currently
// known versions are 4 and 5. With version 4 the StreamId will always be
// empty and IsEncrypted will always return false. An incoming version 4
// connection will always be publishing.
Version() uint32
// StreamId returns the streamid of the requesting connection. Use this // StreamId returns the streamid of the requesting connection. Use this
// to decide what to do with the connection. // to decide what to do with the connection.
StreamId() string StreamId() string
@ -77,6 +82,10 @@ func (req *connRequest) RemoteAddr() net.Addr {
return addr return addr
} }
func (req *connRequest) Version() uint32 {
return req.handshake.Version
}
func (req *connRequest) StreamId() string { func (req *connRequest) StreamId() string {
return req.handshake.StreamId return req.handshake.StreamId
} }
@ -86,6 +95,7 @@ func (req *connRequest) IsEncrypted() bool {
} }
func (req *connRequest) SetPassphrase(passphrase string) error { func (req *connRequest) SetPassphrase(passphrase string) error {
if req.handshake.Version == 5 {
if req.crypto == nil { if req.crypto == nil {
return fmt.Errorf("listen: request without encryption") return fmt.Errorf("listen: request without encryption")
} }
@ -93,6 +103,7 @@ func (req *connRequest) SetPassphrase(passphrase string) error {
if err := req.crypto.UnmarshalKM(req.handshake.SRTKM, passphrase); err != nil { if err := req.crypto.UnmarshalKM(req.handshake.SRTKM, passphrase); err != nil {
return err return err
} }
}
req.passphrase = passphrase req.passphrase = passphrase
@ -179,36 +190,7 @@ func Listen(network, address string, config Config) (Listener, error) {
} }
lc := net.ListenConfig{ lc := net.ListenConfig{
Control: func(network, address string, c syscall.RawConn) error { Control: ListenControl(config),
var opErr error
err := c.Control(func(fd uintptr) {
// Set REUSEADDR
opErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
if opErr != nil {
return
}
// Set TOS
if config.IPTOS > 0 {
opErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TOS, config.IPTOS)
if opErr != nil {
return
}
}
// Set TTL
if config.IPTTL > 0 {
opErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TTL, config.IPTTL)
if opErr != nil {
return
}
}
})
if err != nil {
return err
}
return opErr
},
} }
lp, err := lc.ListenPacket(context.Background(), "udp", address) lp, err := lc.ListenPacket(context.Background(), "udp", address)
@ -312,23 +294,27 @@ func (ln *listener) Accept(acceptFn AcceptFunc) (Conn, ConnType, error) {
// Create a new socket ID // Create a new socket ID
socketId := uint32(time.Since(ln.start).Microseconds()) socketId := uint32(time.Since(ln.start).Microseconds())
// Select the largest TSBPD delay advertised by the listener, but at least 120ms // Select the largest TSBPD delay advertised by the caller, but at least 120ms
recvTsbpdDelay := uint16(ln.config.ReceiverLatency.Milliseconds()) recvTsbpdDelay := uint16(ln.config.ReceiverLatency.Milliseconds())
sendTsbpdDelay := uint16(ln.config.PeerLatency.Milliseconds()) sendTsbpdDelay := uint16(ln.config.PeerLatency.Milliseconds())
if request.handshake.SendTSBPDDelay > recvTsbpdDelay { if request.handshake.Version == 5 {
recvTsbpdDelay = request.handshake.SendTSBPDDelay if request.handshake.SRTHS.SendTSBPDDelay > recvTsbpdDelay {
recvTsbpdDelay = request.handshake.SRTHS.SendTSBPDDelay
} }
if request.handshake.RecvTSBPDDelay > sendTsbpdDelay { if request.handshake.SRTHS.RecvTSBPDDelay > sendTsbpdDelay {
sendTsbpdDelay = request.handshake.RecvTSBPDDelay sendTsbpdDelay = request.handshake.SRTHS.RecvTSBPDDelay
} }
ln.config.StreamId = request.handshake.StreamId ln.config.StreamId = request.handshake.StreamId
}
ln.config.Passphrase = request.passphrase ln.config.Passphrase = request.passphrase
// Create a new connection // Create a new connection
conn := newSRTConn(srtConnConfig{ conn := newSRTConn(srtConnConfig{
version: request.handshake.Version,
localAddr: ln.addr, localAddr: ln.addr,
remoteAddr: request.addr, remoteAddr: request.addr,
config: ln.config, config: ln.config,
@ -351,24 +337,26 @@ func (ln *listener) Accept(acceptFn AcceptFunc) (Conn, ConnType, error) {
request.handshake.SRTSocketId = socketId request.handshake.SRTSocketId = socketId
request.handshake.SynCookie = 0 request.handshake.SynCookie = 0
if request.handshake.Version == 5 {
// 3.2.1.1.1. Handshake Extension Message Flags // 3.2.1.1.1. Handshake Extension Message Flags
request.handshake.SRTVersion = 0x00010402 request.handshake.SRTHS.SRTVersion = SRT_VERSION
request.handshake.SRTFlags.TSBPDSND = true request.handshake.SRTHS.SRTFlags.TSBPDSND = true
request.handshake.SRTFlags.TSBPDRCV = true request.handshake.SRTHS.SRTFlags.TSBPDRCV = true
request.handshake.SRTFlags.CRYPT = true request.handshake.SRTHS.SRTFlags.CRYPT = true
request.handshake.SRTFlags.TLPKTDROP = true request.handshake.SRTHS.SRTFlags.TLPKTDROP = true
request.handshake.SRTFlags.PERIODICNAK = true request.handshake.SRTHS.SRTFlags.PERIODICNAK = true
request.handshake.SRTFlags.REXMITFLG = true request.handshake.SRTHS.SRTFlags.REXMITFLG = true
request.handshake.SRTFlags.STREAM = false request.handshake.SRTHS.SRTFlags.STREAM = false
request.handshake.SRTFlags.PACKET_FILTER = false request.handshake.SRTHS.SRTFlags.PACKET_FILTER = false
request.handshake.RecvTSBPDDelay = recvTsbpdDelay request.handshake.SRTHS.RecvTSBPDDelay = recvTsbpdDelay
request.handshake.SendTSBPDDelay = sendTsbpdDelay request.handshake.SRTHS.SendTSBPDDelay = sendTsbpdDelay
}
ln.accept(request) ln.accept(request)
// Add the connection to the list of known connections // Add the connection to the list of known connections
ln.lock.Lock() ln.lock.Lock()
ln.conns[conn.socketId] = conn ln.conns[socketId] = conn
ln.lock.Unlock() ln.lock.Unlock()
return conn, mode, nil return conn, mode, nil
@ -574,7 +562,7 @@ func (ln *listener) handleHandshake(p packet.Packet) {
//cif.initialPacketSequenceNumber = newCircular(0, MAX_SEQUENCENUMBER) //cif.initialPacketSequenceNumber = newCircular(0, MAX_SEQUENCENUMBER)
//cif.maxTransmissionUnitSize = 0 //cif.maxTransmissionUnitSize = 0
//cif.maxFlowWindowSize = 0 //cif.maxFlowWindowSize = 0
cif.SRTSocketId = 0 //cif.SRTSocketId = 0
cif.SynCookie = ln.syncookie.Get(p.Header().Addr.String()) cif.SynCookie = ln.syncookie.Get(p.Header().Addr.String())
p.MarshalCIF(cif) p.MarshalCIF(cif)
@ -596,56 +584,6 @@ func (ln *listener) handleHandshake(p packet.Packet) {
return return
} }
// We only support HSv5
if cif.Version != 5 {
cif.HandshakeType = packet.REJ_ROGUE
ln.log("handshake:recv:error", func() string { return "only HSv5 is supported" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return
}
// Check if the peer version is sufficient
if cif.SRTVersion < ln.config.MinVersion {
cif.HandshakeType = packet.REJ_VERSION
ln.log("handshake:recv:error", func() string {
return fmt.Sprintf("peer version insufficient (%#06x), expecting at least %#06x", cif.SRTVersion, ln.config.MinVersion)
})
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return
}
// Check the required SRT flags
if !cif.SRTFlags.TSBPDSND || !cif.SRTFlags.TSBPDRCV || !cif.SRTFlags.TLPKTDROP || !cif.SRTFlags.PERIODICNAK || !cif.SRTFlags.REXMITFLG {
cif.HandshakeType = packet.REJ_ROGUE
ln.log("handshake:recv:error", func() string { return "not all required flags are set" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return
}
// We only support live streaming
if cif.SRTFlags.STREAM {
cif.HandshakeType = packet.REJ_MESSAGEAPI
ln.log("handshake:recv:error", func() string { return "only live streaming is supported" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return
}
// Peer is advertising a too big MSS // Peer is advertising a too big MSS
if cif.MaxTransmissionUnitSize > MAX_MSS_SIZE { if cif.MaxTransmissionUnitSize > MAX_MSS_SIZE {
cif.HandshakeType = packet.REJ_ROGUE cif.HandshakeType = packet.REJ_ROGUE
@ -673,6 +611,68 @@ func (ln *listener) handleHandshake(p packet.Packet) {
} }
} }
// We only support HSv4 and HSv5
if cif.Version == 4 {
// Check if the type (encryption field + extension field) has the value 2
if cif.EncryptionField != 0 || cif.ExtensionField != 2 {
cif.HandshakeType = packet.REJ_ROGUE
ln.log("handshake:recv:error", func() string { return "invalid type, expecting a value of 2 (UDT_DGRAM)" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return
}
} else if cif.Version == 5 {
// Check if the peer version is sufficient
if cif.SRTHS.SRTVersion < ln.config.MinVersion {
cif.HandshakeType = packet.REJ_VERSION
ln.log("handshake:recv:error", func() string {
return fmt.Sprintf("peer version insufficient (%#06x), expecting at least %#06x", cif.SRTHS.SRTVersion, ln.config.MinVersion)
})
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return
}
// Check the required SRT flags
if !cif.SRTHS.SRTFlags.TSBPDSND || !cif.SRTHS.SRTFlags.TSBPDRCV || !cif.SRTHS.SRTFlags.TLPKTDROP || !cif.SRTHS.SRTFlags.PERIODICNAK || !cif.SRTHS.SRTFlags.REXMITFLG {
cif.HandshakeType = packet.REJ_ROGUE
ln.log("handshake:recv:error", func() string { return "not all required flags are set" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return
}
// We only support live streaming
if cif.SRTHS.SRTFlags.STREAM {
cif.HandshakeType = packet.REJ_MESSAGEAPI
ln.log("handshake:recv:error", func() string { return "only live streaming is supported" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return
}
} else {
cif.HandshakeType = packet.REJ_ROGUE
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("only HSv4 and HSv5 are supported (got HSv%d)", cif.Version) })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return
}
// Fill up a connection request with all relevant data and put it into the backlog // Fill up a connection request with all relevant data and put it into the backlog
c := connRequest{ c := connRequest{

65
vendor/github.com/datarhei/gosrt/net.go generated vendored Normal file
View file

@ -0,0 +1,65 @@
//go:build !windows
package srt
import "syscall"
func ListenControl(config Config) func(network, address string, c syscall.RawConn) error {
return func(network, address string, c syscall.RawConn) error {
var opErr error
err := c.Control(func(fd uintptr) {
// Set REUSEADDR
opErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
if opErr != nil {
return
}
// Set TOS
if config.IPTOS > 0 {
opErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TOS, config.IPTOS)
if opErr != nil {
return
}
}
// Set TTL
if config.IPTTL > 0 {
opErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TTL, config.IPTTL)
if opErr != nil {
return
}
}
})
if err != nil {
return err
}
return opErr
}
}
func DialControl(config Config) func(network string, address string, c syscall.RawConn) error {
return func(network, address string, c syscall.RawConn) error {
var opErr error
err := c.Control(func(fd uintptr) {
// Set TOS
if config.IPTOS > 0 {
opErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TOS, config.IPTOS)
if opErr != nil {
return
}
}
// Set TTL
if config.IPTTL > 0 {
opErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TTL, config.IPTTL)
if opErr != nil {
return
}
}
})
if err != nil {
return err
}
return opErr
}
}

69
vendor/github.com/datarhei/gosrt/net_windows.go generated vendored Normal file
View file

@ -0,0 +1,69 @@
//go:build windows
package srt
import (
"syscall"
"golang.org/x/sys/windows"
)
func ListenControl(config Config) func(network, address string, c syscall.RawConn) error {
return func(network, address string, c syscall.RawConn) error {
var opErr error
err := c.Control(func(fd uintptr) {
// Set REUSEADDR
opErr = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
if opErr != nil {
return
}
// Set TOS
if config.IPTOS > 0 {
opErr = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, windows.IP_TOS, config.IPTOS)
if opErr != nil {
return
}
}
// Set TTL
if config.IPTTL > 0 {
opErr = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, windows.IP_TTL, config.IPTTL)
if opErr != nil {
return
}
}
})
if err != nil {
return err
}
return opErr
}
}
func DialControl(config Config) func(network string, address string, c syscall.RawConn) error {
return func(network, address string, c syscall.RawConn) error {
var opErr error
err := c.Control(func(fd uintptr) {
// Set TOS
if config.IPTOS > 0 {
opErr = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, windows.IP_TOS, config.IPTOS)
if opErr != nil {
return
}
}
// Set TTL
if config.IPTTL > 0 {
opErr = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, windows.IP_TTL, config.IPTTL)
if opErr != nil {
return
}
}
})
if err != nil {
return err
}
return opErr
}
}

View file

@ -90,6 +90,23 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
} }
// EqualExportedValuesf asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// EqualValuesf asserts that two objects are equal or convertable to the same types // EqualValuesf asserts that two objects are equal or convertable to the same types
// and equal. // and equal.
// //
@ -155,6 +172,31 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick
return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
} }
// EventuallyWithTf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return EventuallyWithT(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
}
// Exactlyf asserts that two objects are equal in value and type. // Exactlyf asserts that two objects are equal in value and type.
// //
// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") // assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")

View file

@ -155,6 +155,40 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a
return EqualErrorf(a.t, theError, errString, msg, args...) return EqualErrorf(a.t, theError, errString, msg, args...)
} }
// EqualExportedValues asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true
// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false
func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return EqualExportedValues(a.t, expected, actual, msgAndArgs...)
}
// EqualExportedValuesf asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return EqualExportedValuesf(a.t, expected, actual, msg, args...)
}
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertable to the same types
// and equal. // and equal.
// //
@ -288,6 +322,56 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti
return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) return Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
} }
// EventuallyWithT asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// a.EventuallyWithT(func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...)
}
// EventuallyWithTf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...)
}
// Eventuallyf asserts that given condition will be met in waitFor time, // Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. // periodically checking target function each tick.
// //

View file

@ -75,6 +75,77 @@ func ObjectsAreEqual(expected, actual interface{}) bool {
return bytes.Equal(exp, act) return bytes.Equal(exp, act)
} }
// copyExportedFields iterates downward through nested data structures and creates a copy
// that only contains the exported struct fields.
func copyExportedFields(expected interface{}) interface{} {
if isNil(expected) {
return expected
}
expectedType := reflect.TypeOf(expected)
expectedKind := expectedType.Kind()
expectedValue := reflect.ValueOf(expected)
switch expectedKind {
case reflect.Struct:
result := reflect.New(expectedType).Elem()
for i := 0; i < expectedType.NumField(); i++ {
field := expectedType.Field(i)
isExported := field.IsExported()
if isExported {
fieldValue := expectedValue.Field(i)
if isNil(fieldValue) || isNil(fieldValue.Interface()) {
continue
}
newValue := copyExportedFields(fieldValue.Interface())
result.Field(i).Set(reflect.ValueOf(newValue))
}
}
return result.Interface()
case reflect.Ptr:
result := reflect.New(expectedType.Elem())
unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface())
result.Elem().Set(reflect.ValueOf(unexportedRemoved))
return result.Interface()
case reflect.Array, reflect.Slice:
result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len())
for i := 0; i < expectedValue.Len(); i++ {
index := expectedValue.Index(i)
if isNil(index) {
continue
}
unexportedRemoved := copyExportedFields(index.Interface())
result.Index(i).Set(reflect.ValueOf(unexportedRemoved))
}
return result.Interface()
case reflect.Map:
result := reflect.MakeMap(expectedType)
for _, k := range expectedValue.MapKeys() {
index := expectedValue.MapIndex(k)
unexportedRemoved := copyExportedFields(index.Interface())
result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved))
}
return result.Interface()
default:
return expected
}
}
// ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are
// considered equal. This comparison of only exported fields is applied recursively to nested data
// structures.
//
// This function does no assertion of any kind.
func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool {
expectedCleaned := copyExportedFields(expected)
actualCleaned := copyExportedFields(actual)
return ObjectsAreEqualValues(expectedCleaned, actualCleaned)
}
// ObjectsAreEqualValues gets whether two objects are equal, or if their // ObjectsAreEqualValues gets whether two objects are equal, or if their
// values are equal. // values are equal.
func ObjectsAreEqualValues(expected, actual interface{}) bool { func ObjectsAreEqualValues(expected, actual interface{}) bool {
@ -473,6 +544,50 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa
} }
// EqualExportedValues asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true
// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false
func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
aType := reflect.TypeOf(expected)
bType := reflect.TypeOf(actual)
if aType != bType {
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
}
if aType.Kind() != reflect.Struct {
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...)
}
if bType.Kind() != reflect.Struct {
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...)
}
expected = copyExportedFields(expected)
actual = copyExportedFields(actual)
if !ObjectsAreEqualValues(expected, actual) {
diff := diff(expected, actual)
expected, actual = formatUnequalValues(expected, actual)
return Fail(t, fmt.Sprintf("Not equal (comparing only exported fields): \n"+
"expected: %s\n"+
"actual : %s%s", expected, actual, diff), msgAndArgs...)
}
return true
}
// Exactly asserts that two objects are equal in value and type. // Exactly asserts that two objects are equal in value and type.
// //
// assert.Exactly(t, int32(123), int64(123)) // assert.Exactly(t, int32(123), int64(123))
@ -794,10 +909,10 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
ok, found := containsElement(s, contains) ok, found := containsElement(s, contains)
if !ok { if !ok {
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
} }
if found { if found {
return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...)
} }
return true return true
@ -1744,6 +1859,89 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
} }
} }
// CollectT implements the TestingT interface and collects all errors.
type CollectT struct {
errors []error
}
// Errorf collects the error.
func (c *CollectT) Errorf(format string, args ...interface{}) {
c.errors = append(c.errors, fmt.Errorf(format, args...))
}
// FailNow panics.
func (c *CollectT) FailNow() {
panic("Assertion failed")
}
// Reset clears the collected errors.
func (c *CollectT) Reset() {
c.errors = nil
}
// Copy copies the collected errors to the supplied t.
func (c *CollectT) Copy(t TestingT) {
if tt, ok := t.(tHelper); ok {
tt.Helper()
}
for _, err := range c.errors {
t.Errorf("%v", err)
}
}
// EventuallyWithT asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// assert.EventuallyWithT(t, func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
collect := new(CollectT)
ch := make(chan bool, 1)
timer := time.NewTimer(waitFor)
defer timer.Stop()
ticker := time.NewTicker(tick)
defer ticker.Stop()
for tick := ticker.C; ; {
select {
case <-timer.C:
collect.Copy(t)
return Fail(t, "Condition never satisfied", msgAndArgs...)
case <-tick:
tick = nil
collect.Reset()
go func() {
condition(collect)
ch <- len(collect.errors) == 0
}()
case v := <-ch:
if v {
return true
}
tick = ticker.C
}
}
}
// Never asserts that the given condition doesn't satisfy in waitFor time, // Never asserts that the given condition doesn't satisfy in waitFor time,
// periodically checking the target function each tick. // periodically checking the target function each tick.
// //

View file

@ -1,8 +1,9 @@
// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
// //
// Example Usage // # Example Usage
// //
// The following is a complete example using assert in a standard test function: // The following is a complete example using assert in a standard test function:
//
// import ( // import (
// "testing" // "testing"
// "github.com/stretchr/testify/assert" // "github.com/stretchr/testify/assert"
@ -33,7 +34,7 @@
// assert.Equal(a, b, "The two words should be the same.") // assert.Equal(a, b, "The two words should be the same.")
// } // }
// //
// Assertions // # Assertions
// //
// Assertions allow you to easily write test code, and are global funcs in the `assert` package. // Assertions allow you to easily write test code, and are global funcs in the `assert` package.
// All assertion functions take, as the first argument, the `*testing.T` object provided by the // All assertion functions take, as the first argument, the `*testing.T` object provided by the

View file

@ -1,9 +1,10 @@
// Package require implements the same assertions as the `assert` package but // Package require implements the same assertions as the `assert` package but
// stops test execution when a test fails. // stops test execution when a test fails.
// //
// Example Usage // # Example Usage
// //
// The following is a complete example using require in a standard test function: // The following is a complete example using require in a standard test function:
//
// import ( // import (
// "testing" // "testing"
// "github.com/stretchr/testify/require" // "github.com/stretchr/testify/require"
@ -18,7 +19,7 @@
// //
// } // }
// //
// Assertions // # Assertions
// //
// The `require` package have same global functions as in the `assert` package, // The `require` package have same global functions as in the `assert` package,
// but instead of returning a boolean result they call `t.FailNow()`. // but instead of returning a boolean result they call `t.FailNow()`.

View file

@ -195,6 +195,46 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
t.FailNow() t.FailNow()
} }
// EqualExportedValues asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true
// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false
func EqualExportedValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.EqualExportedValues(t, expected, actual, msgAndArgs...) {
return
}
t.FailNow()
}
// EqualExportedValuesf asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.EqualExportedValuesf(t, expected, actual, msg, args...) {
return
}
t.FailNow()
}
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertable to the same types
// and equal. // and equal.
// //
@ -364,6 +404,62 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
t.FailNow() t.FailNow()
} }
// EventuallyWithT asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// assert.EventuallyWithT(t, func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.EventuallyWithT(t, condition, waitFor, tick, msgAndArgs...) {
return
}
t.FailNow()
}
// EventuallyWithTf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.EventuallyWithTf(t, condition, waitFor, tick, msg, args...) {
return
}
t.FailNow()
}
// Eventuallyf asserts that given condition will be met in waitFor time, // Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. // periodically checking target function each tick.
// //

View file

@ -156,6 +156,40 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a
EqualErrorf(a.t, theError, errString, msg, args...) EqualErrorf(a.t, theError, errString, msg, args...)
} }
// EqualExportedValues asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true
// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false
func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
EqualExportedValues(a.t, expected, actual, msgAndArgs...)
}
// EqualExportedValuesf asserts that the types of two objects are equal and their public
// fields are also equal. This is useful for comparing structs that have private fields
// that could potentially differ.
//
// type S struct {
// Exported int
// notExported int
// }
// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
EqualExportedValuesf(a.t, expected, actual, msg, args...)
}
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertable to the same types
// and equal. // and equal.
// //
@ -289,6 +323,56 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti
Eventually(a.t, condition, waitFor, tick, msgAndArgs...) Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
} }
// EventuallyWithT asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// a.EventuallyWithT(func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...)
}
// EventuallyWithTf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
// function can use the CollectT to call other assertions.
// The condition is considered "met" if no errors are raised in a tick.
// The supplied CollectT collects all errors from one tick (if there are any).
// If the condition is not met before waitFor, the collected errors of
// the last tick are copied to t.
//
// externalValue := false
// go func() {
// time.Sleep(8*time.Second)
// externalValue = true
// }()
// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...)
}
// Eventuallyf asserts that given condition will be met in waitFor time, // Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. // periodically checking target function each tick.
// //

View file

@ -117,7 +117,7 @@ func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error)
return responseAccount(res) return responseAccount(res)
} }
// getGegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555. // getRegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555.
// It expects c.Discover to have already been called. // It expects c.Discover to have already been called.
func (c *Client) getRegRFC(ctx context.Context) (*Account, error) { func (c *Client) getRegRFC(ctx context.Context) (*Account, error) {
req := json.RawMessage(`{"onlyReturnExisting": true}`) req := json.RawMessage(`{"onlyReturnExisting": true}`)

View file

@ -88,13 +88,9 @@ func (p *pipe) Write(d []byte) (n int, err error) {
p.c.L = &p.mu p.c.L = &p.mu
} }
defer p.c.Signal() defer p.c.Signal()
if p.err != nil { if p.err != nil || p.breakErr != nil {
return 0, errClosedPipeWrite return 0, errClosedPipeWrite
} }
if p.breakErr != nil {
p.unread += len(d)
return len(d), nil // discard when there is no reader
}
return p.b.Write(d) return p.b.Write(d)
} }

View file

@ -1822,15 +1822,18 @@ func (sc *serverConn) processData(f *DataFrame) error {
} }
if len(data) > 0 { if len(data) > 0 {
st.bodyBytes += int64(len(data))
wrote, err := st.body.Write(data) wrote, err := st.body.Write(data)
if err != nil { if err != nil {
// The handler has closed the request body.
// Return the connection-level flow control for the discarded data,
// but not the stream-level flow control.
sc.sendWindowUpdate(nil, int(f.Length)-wrote) sc.sendWindowUpdate(nil, int(f.Length)-wrote)
return sc.countError("body_write_err", streamError(id, ErrCodeStreamClosed)) return nil
} }
if wrote != len(data) { if wrote != len(data) {
panic("internal error: bad Writer") panic("internal error: bad Writer")
} }
st.bodyBytes += int64(len(data))
} }
// Return any padded flow control now, since we won't // Return any padded flow control now, since we won't

View file

@ -560,10 +560,11 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
traceGotConn(req, cc, reused) traceGotConn(req, cc, reused)
res, err := cc.RoundTrip(req) res, err := cc.RoundTrip(req)
if err != nil && retry <= 6 { if err != nil && retry <= 6 {
roundTripErr := err
if req, err = shouldRetryRequest(req, err); err == nil { if req, err = shouldRetryRequest(req, err); err == nil {
// After the first retry, do exponential backoff with 10% jitter. // After the first retry, do exponential backoff with 10% jitter.
if retry == 0 { if retry == 0 {
t.vlogf("RoundTrip retrying after failure: %v", err) t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
continue continue
} }
backoff := float64(uint(1) << (uint(retry) - 1)) backoff := float64(uint(1) << (uint(retry) - 1))
@ -572,7 +573,7 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
timer := backoffNewTimer(d) timer := backoffNewTimer(d)
select { select {
case <-timer.C: case <-timer.C:
t.vlogf("RoundTrip retrying after failure: %v", err) t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
continue continue
case <-req.Context().Done(): case <-req.Context().Done():
timer.Stop() timer.Stop()
@ -1265,6 +1266,27 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
return res, nil return res, nil
} }
cancelRequest := func(cs *clientStream, err error) error {
cs.cc.mu.Lock()
defer cs.cc.mu.Unlock()
cs.abortStreamLocked(err)
if cs.ID != 0 {
// This request may have failed because of a problem with the connection,
// or for some unrelated reason. (For example, the user might have canceled
// the request without waiting for a response.) Mark the connection as
// not reusable, since trying to reuse a dead connection is worse than
// unnecessarily creating a new one.
//
// If cs.ID is 0, then the request was never allocated a stream ID and
// whatever went wrong was unrelated to the connection. We might have
// timed out waiting for a stream slot when StrictMaxConcurrentStreams
// is set, for example, in which case retrying on a different connection
// will not help.
cs.cc.doNotReuse = true
}
return err
}
for { for {
select { select {
case <-cs.respHeaderRecv: case <-cs.respHeaderRecv:
@ -1279,15 +1301,12 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
return handleResponseHeaders() return handleResponseHeaders()
default: default:
waitDone() waitDone()
return nil, cs.abortErr return nil, cancelRequest(cs, cs.abortErr)
} }
case <-ctx.Done(): case <-ctx.Done():
err := ctx.Err() return nil, cancelRequest(cs, ctx.Err())
cs.abortStream(err)
return nil, err
case <-cs.reqCancel: case <-cs.reqCancel:
cs.abortStream(errRequestCanceled) return nil, cancelRequest(cs, errRequestCanceled)
return nil, errRequestCanceled
} }
} }
} }
@ -2555,6 +2574,9 @@ func (b transportResponseBody) Close() error {
cs := b.cs cs := b.cs
cc := cs.cc cc := cs.cc
cs.bufPipe.BreakWithError(errClosedResponseBody)
cs.abortStream(errClosedResponseBody)
unread := cs.bufPipe.Len() unread := cs.bufPipe.Len()
if unread > 0 { if unread > 0 {
cc.mu.Lock() cc.mu.Lock()
@ -2573,9 +2595,6 @@ func (b transportResponseBody) Close() error {
cc.wmu.Unlock() cc.wmu.Unlock()
} }
cs.bufPipe.BreakWithError(errClosedResponseBody)
cs.abortStream(errClosedResponseBody)
select { select {
case <-cs.donec: case <-cs.donec:
case <-cs.ctx.Done(): case <-cs.ctx.Done():

View file

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh //go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh || wasm
// +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh // +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh wasm
package cpu package cpu

70
vendor/golang.org/x/sys/unix/ioctl_signed.go generated vendored Normal file
View file

@ -0,0 +1,70 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build aix || solaris
// +build aix solaris
package unix
import (
"unsafe"
)
// ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible.
// IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number.
func IoctlSetInt(fd int, req int, value int) error {
return ioctl(fd, req, uintptr(value))
}
// IoctlSetPointerInt performs an ioctl operation which sets an
// integer value on fd, using the specified request number. The ioctl
// argument is called with a pointer to the integer value, rather than
// passing the integer value directly.
func IoctlSetPointerInt(fd int, req int, value int) error {
v := int32(value)
return ioctlPtr(fd, req, unsafe.Pointer(&v))
}
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
//
// To change fd's window size, the req argument should be TIOCSWINSZ.
func IoctlSetWinsize(fd int, req int, value *Winsize) error {
// TODO: if we get the chance, remove the req parameter and
// hardcode TIOCSWINSZ.
return ioctlPtr(fd, req, unsafe.Pointer(value))
}
// IoctlSetTermios performs an ioctl on fd with a *Termios.
//
// The req value will usually be TCSETA or TIOCSETA.
func IoctlSetTermios(fd int, req int, value *Termios) error {
// TODO: if we get the chance, remove the req parameter.
return ioctlPtr(fd, req, unsafe.Pointer(value))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
//
// A few ioctl requests use the return value as an output parameter;
// for those, IoctlRetInt should be used instead of this function.
func IoctlGetInt(fd int, req int) (int, error) {
var value int
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return value, err
}
func IoctlGetWinsize(fd int, req int) (*Winsize, error) {
var value Winsize
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return &value, err
}
func IoctlGetTermios(fd int, req int) (*Termios, error) {
var value Termios
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return &value, err
}

View file

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris //go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris // +build darwin dragonfly freebsd hurd linux netbsd openbsd
package unix package unix

View file

@ -17,14 +17,14 @@ import (
// IoctlSetInt performs an ioctl operation which sets an integer value // IoctlSetInt performs an ioctl operation which sets an integer value
// on fd, using the specified request number. // on fd, using the specified request number.
func IoctlSetInt(fd int, req uint, value int) error { func IoctlSetInt(fd int, req int, value int) error {
return ioctl(fd, req, uintptr(value)) return ioctl(fd, req, uintptr(value))
} }
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. // IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
// //
// To change fd's window size, the req argument should be TIOCSWINSZ. // To change fd's window size, the req argument should be TIOCSWINSZ.
func IoctlSetWinsize(fd int, req uint, value *Winsize) error { func IoctlSetWinsize(fd int, req int, value *Winsize) error {
// TODO: if we get the chance, remove the req parameter and // TODO: if we get the chance, remove the req parameter and
// hardcode TIOCSWINSZ. // hardcode TIOCSWINSZ.
return ioctlPtr(fd, req, unsafe.Pointer(value)) return ioctlPtr(fd, req, unsafe.Pointer(value))
@ -33,7 +33,7 @@ func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
// IoctlSetTermios performs an ioctl on fd with a *Termios. // IoctlSetTermios performs an ioctl on fd with a *Termios.
// //
// The req value is expected to be TCSETS, TCSETSW, or TCSETSF // The req value is expected to be TCSETS, TCSETSW, or TCSETSF
func IoctlSetTermios(fd int, req uint, value *Termios) error { func IoctlSetTermios(fd int, req int, value *Termios) error {
if (req != TCSETS) && (req != TCSETSW) && (req != TCSETSF) { if (req != TCSETS) && (req != TCSETSW) && (req != TCSETSF) {
return ENOSYS return ENOSYS
} }
@ -47,13 +47,13 @@ func IoctlSetTermios(fd int, req uint, value *Termios) error {
// //
// A few ioctl requests use the return value as an output parameter; // A few ioctl requests use the return value as an output parameter;
// for those, IoctlRetInt should be used instead of this function. // for those, IoctlRetInt should be used instead of this function.
func IoctlGetInt(fd int, req uint) (int, error) { func IoctlGetInt(fd int, req int) (int, error) {
var value int var value int
err := ioctlPtr(fd, req, unsafe.Pointer(&value)) err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return value, err return value, err
} }
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { func IoctlGetWinsize(fd int, req int) (*Winsize, error) {
var value Winsize var value Winsize
err := ioctlPtr(fd, req, unsafe.Pointer(&value)) err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return &value, err return &value, err
@ -62,7 +62,7 @@ func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
// IoctlGetTermios performs an ioctl on fd with a *Termios. // IoctlGetTermios performs an ioctl on fd with a *Termios.
// //
// The req value is expected to be TCGETS // The req value is expected to be TCGETS
func IoctlGetTermios(fd int, req uint) (*Termios, error) { func IoctlGetTermios(fd int, req int) (*Termios, error) {
var value Termios var value Termios
if req != TCGETS { if req != TCGETS {
return &value, ENOSYS return &value, ENOSYS

View file

@ -50,7 +50,7 @@ if [[ "$GOOS" = "linux" ]]; then
# Use the Docker-based build system # Use the Docker-based build system
# Files generated through docker (use $cmd so you can Ctl-C the build or run) # Files generated through docker (use $cmd so you can Ctl-C the build or run)
$cmd docker build --tag generate:$GOOS $GOOS $cmd docker build --tag generate:$GOOS $GOOS
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && /bin/pwd):/build generate:$GOOS $cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && pwd):/build generate:$GOOS
exit exit
fi fi

View file

@ -66,6 +66,7 @@ includes_Darwin='
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/sys_domain.h> #include <sys/sys_domain.h>
@ -203,6 +204,7 @@ struct ltchars {
#include <sys/timerfd.h> #include <sys/timerfd.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/xattr.h> #include <sys/xattr.h>
#include <netinet/udp.h>
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/can.h> #include <linux/can.h>
@ -517,10 +519,11 @@ ccflags="$@"
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
$2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT)_/ || $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ || $2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
$2 ~ /^NFC_.*_(MAX)?SIZE$/ || $2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
$2 ~ /^RAW_PAYLOAD_/ || $2 ~ /^RAW_PAYLOAD_/ ||
$2 ~ /^[US]F_/ ||
$2 ~ /^TP_STATUS_/ || $2 ~ /^TP_STATUS_/ ||
$2 ~ /^FALLOC_/ || $2 ~ /^FALLOC_/ ||
$2 ~ /^ICMPV?6?_(FILTER|SEC)/ || $2 ~ /^ICMPV?6?_(FILTER|SEC)/ ||
@ -738,7 +741,8 @@ main(void)
e = errors[i].num; e = errors[i].num;
if(i > 0 && errors[i-1].num == e) if(i > 0 && errors[i-1].num == e)
continue; continue;
strcpy(buf, strerror(e)); strncpy(buf, strerror(e), sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
// lowercase first letter: Bad -> bad, but STREAM -> STREAM. // lowercase first letter: Bad -> bad, but STREAM -> STREAM.
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
buf[0] += a - A; buf[0] += a - A;
@ -757,7 +761,8 @@ main(void)
e = signals[i].num; e = signals[i].num;
if(i > 0 && signals[i-1].num == e) if(i > 0 && signals[i-1].num == e)
continue; continue;
strcpy(buf, strsignal(e)); strncpy(buf, strsignal(e), sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
// lowercase first letter: Bad -> bad, but STREAM -> STREAM. // lowercase first letter: Bad -> bad, but STREAM -> STREAM.
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
buf[0] += a - A; buf[0] += a - A;

View file

@ -408,8 +408,8 @@ func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 }
func (w WaitStatus) TrapCause() int { return -1 } func (w WaitStatus) TrapCause() int { return -1 }
//sys ioctl(fd int, req uint, arg uintptr) (err error) //sys ioctl(fd int, req int, arg uintptr) (err error)
//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = ioctl //sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = ioctl
// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX // fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX
// There is no way to create a custom fcntl and to keep //sys fcntl easily, // There is no way to create a custom fcntl and to keep //sys fcntl easily,

View file

@ -8,7 +8,6 @@
package unix package unix
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = getrlimit64 //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = getrlimit64
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error) = setrlimit64
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = lseek64 //sys Seek(fd int, offset int64, whence int) (off int64, err error) = lseek64
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) //sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)

View file

@ -8,7 +8,6 @@
package unix package unix
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = lseek //sys Seek(fd int, offset int64, whence int) (off int64, err error) = lseek
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) = mmap64 //sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) = mmap64

View file

@ -613,6 +613,7 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
//sys Rmdir(path string) (err error) //sys Rmdir(path string) (err error)
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sys Setattrlist(path string, attrlist *Attrlist, attrBuf []byte, options int) (err error)
//sys Setegid(egid int) (err error) //sys Setegid(egid int) (err error)
//sysnb Seteuid(euid int) (err error) //sysnb Seteuid(euid int) (err error)
//sysnb Setgid(gid int) (err error) //sysnb Setgid(gid int) (err error)
@ -622,7 +623,6 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
//sys Setprivexec(flag int) (err error) //sys Setprivexec(flag int) (err error)
//sysnb Setregid(rgid int, egid int) (err error) //sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error)
//sysnb Setrlimit(which int, lim *Rlimit) (err error)
//sysnb Setsid() (pid int, err error) //sysnb Setsid() (pid int, err error)
//sysnb Settimeofday(tp *Timeval) (err error) //sysnb Settimeofday(tp *Timeval) (err error)
//sysnb Setuid(uid int) (err error) //sysnb Setuid(uid int) (err error)
@ -676,7 +676,6 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
// Kqueue_from_portset_np // Kqueue_from_portset_np
// Kqueue_portset // Kqueue_portset
// Getattrlist // Getattrlist
// Setattrlist
// Getdirentriesattr // Getdirentriesattr
// Searchfs // Searchfs
// Delete // Delete

View file

@ -326,7 +326,6 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error)
//sysnb Setrlimit(which int, lim *Rlimit) (err error)
//sysnb Setsid() (pid int, err error) //sysnb Setsid() (pid int, err error)
//sysnb Settimeofday(tp *Timeval) (err error) //sysnb Settimeofday(tp *Timeval) (err error)
//sysnb Setuid(uid int) (err error) //sysnb Setuid(uid int) (err error)

View file

@ -433,7 +433,6 @@ func Dup3(oldfd, newfd, flags int) error {
//sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error)
//sysnb Setrlimit(which int, lim *Rlimit) (err error)
//sysnb Setsid() (pid int, err error) //sysnb Setsid() (pid int, err error)
//sysnb Settimeofday(tp *Timeval) (err error) //sysnb Settimeofday(tp *Timeval) (err error)
//sysnb Setuid(uid int) (err error) //sysnb Setuid(uid int) (err error)

View file

@ -1699,12 +1699,23 @@ func PtracePokeUser(pid int, addr uintptr, data []byte) (count int, err error) {
return ptracePoke(PTRACE_POKEUSR, PTRACE_PEEKUSR, pid, addr, data) return ptracePoke(PTRACE_POKEUSR, PTRACE_PEEKUSR, pid, addr, data)
} }
// elfNT_PRSTATUS is a copy of the debug/elf.NT_PRSTATUS constant so
// x/sys/unix doesn't need to depend on debug/elf and thus
// compress/zlib, debug/dwarf, and other packages.
const elfNT_PRSTATUS = 1
func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) { func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
return ptracePtr(PTRACE_GETREGS, pid, 0, unsafe.Pointer(regsout)) var iov Iovec
iov.Base = (*byte)(unsafe.Pointer(regsout))
iov.SetLen(int(unsafe.Sizeof(*regsout)))
return ptracePtr(PTRACE_GETREGSET, pid, uintptr(elfNT_PRSTATUS), unsafe.Pointer(&iov))
} }
func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
return ptracePtr(PTRACE_SETREGS, pid, 0, unsafe.Pointer(regs)) var iov Iovec
iov.Base = (*byte)(unsafe.Pointer(regs))
iov.SetLen(int(unsafe.Sizeof(*regs)))
return ptracePtr(PTRACE_SETREGSET, pid, uintptr(elfNT_PRSTATUS), unsafe.Pointer(&iov))
} }
func PtraceSetOptions(pid int, options int) (err error) { func PtraceSetOptions(pid int, options int) (err error) {
@ -1873,7 +1884,6 @@ func Getpgrp() (pid int) {
//sys OpenTree(dfd int, fileName string, flags uint) (r int, err error) //sys OpenTree(dfd int, fileName string, flags uint) (r int, err error)
//sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) //sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error)
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT //sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
//sysnb Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64
//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) //sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)
//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) = SYS_PSELECT6 //sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) = SYS_PSELECT6
//sys read(fd int, p []byte) (n int, err error) //sys read(fd int, p []byte) (n int, err error)
@ -1887,6 +1897,15 @@ func Getpgrp() (pid int) {
//sysnb Settimeofday(tv *Timeval) (err error) //sysnb Settimeofday(tv *Timeval) (err error)
//sys Setns(fd int, nstype int) (err error) //sys Setns(fd int, nstype int) (err error)
//go:linkname syscall_prlimit syscall.prlimit
func syscall_prlimit(pid, resource int, newlimit, old *syscall.Rlimit) error
func Prlimit(pid, resource int, newlimit, old *Rlimit) error {
// Just call the syscall version, because as of Go 1.21
// it will affect starting a new process.
return syscall_prlimit(pid, resource, (*syscall.Rlimit)(newlimit), (*syscall.Rlimit)(old))
}
// PrctlRetInt performs a prctl operation specified by option and further // PrctlRetInt performs a prctl operation specified by option and further
// optional arguments arg2 through arg5 depending on option. It returns a // optional arguments arg2 through arg5 depending on option. It returns a
// non-negative integer that is returned by the prctl syscall. // non-negative integer that is returned by the prctl syscall.
@ -2412,6 +2431,21 @@ func PthreadSigmask(how int, set, oldset *Sigset_t) error {
return rtSigprocmask(how, set, oldset, _C__NSIG/8) return rtSigprocmask(how, set, oldset, _C__NSIG/8)
} }
//sysnb getresuid(ruid *_C_int, euid *_C_int, suid *_C_int)
//sysnb getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int)
func Getresuid() (ruid, euid, suid int) {
var r, e, s _C_int
getresuid(&r, &e, &s)
return int(r), int(e), int(s)
}
func Getresgid() (rgid, egid, sgid int) {
var r, e, s _C_int
getresgid(&r, &e, &s)
return int(r), int(e), int(s)
}
/* /*
* Unimplemented * Unimplemented
*/ */

View file

@ -97,33 +97,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
return return
} }
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
err = Prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}
rl := rlimit32{}
if rlim.Cur == rlimInf64 {
rl.Cur = rlimInf32
} else if rlim.Cur < uint64(rlimInf32) {
rl.Cur = uint32(rlim.Cur)
} else {
return EINVAL
}
if rlim.Max == rlimInf64 {
rl.Max = rlimInf32
} else if rlim.Max < uint64(rlimInf32) {
rl.Max = uint32(rlim.Max)
} else {
return EINVAL
}
return setrlimit(resource, &rl)
}
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
newoffset, errno := seek(fd, offset, whence) newoffset, errno := seek(fd, offset, whence)
if errno != 0 { if errno != 0 {

View file

@ -46,7 +46,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys setfsgid(gid int) (prev int, err error) //sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sys Shutdown(fd int, how int) (err error) //sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)

View file

@ -171,33 +171,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
return return
} }
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
err = Prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}
rl := rlimit32{}
if rlim.Cur == rlimInf64 {
rl.Cur = rlimInf32
} else if rlim.Cur < uint64(rlimInf32) {
rl.Cur = uint32(rlim.Cur)
} else {
return EINVAL
}
if rlim.Max == rlimInf64 {
rl.Max = rlimInf32
} else if rlim.Max < uint64(rlimInf32) {
rl.Max = uint32(rlim.Max)
} else {
return EINVAL
}
return setrlimit(resource, &rl)
}
func (r *PtraceRegs) PC() uint64 { return uint64(r.Uregs[15]) } func (r *PtraceRegs) PC() uint64 { return uint64(r.Uregs[15]) }
func (r *PtraceRegs) SetPC(pc uint64) { r.Uregs[15] = uint32(pc) } func (r *PtraceRegs) SetPC(pc uint64) { r.Uregs[15] = uint32(pc) }

View file

@ -39,7 +39,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys setfsgid(gid int) (prev int, err error) //sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb setrlimit(resource int, rlim *Rlimit) (err error)
//sys Shutdown(fd int, how int) (err error) //sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
@ -143,15 +142,6 @@ func Getrlimit(resource int, rlim *Rlimit) error {
return getrlimit(resource, rlim) return getrlimit(resource, rlim)
} }
// Setrlimit prefers the prlimit64 system call. See issue 38604.
func Setrlimit(resource int, rlim *Rlimit) error {
err := Prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}
return setrlimit(resource, rlim)
}
func (r *PtraceRegs) PC() uint64 { return r.Pc } func (r *PtraceRegs) PC() uint64 { return r.Pc }
func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc }

View file

@ -126,11 +126,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
return return
} }
func Setrlimit(resource int, rlim *Rlimit) (err error) {
err = Prlimit(0, resource, rlim, nil)
return
}
func futimesat(dirfd int, path string, tv *[2]Timeval) (err error) { func futimesat(dirfd int, path string, tv *[2]Timeval) (err error) {
if tv == nil { if tv == nil {
return utimensat(dirfd, path, nil, 0) return utimensat(dirfd, path, nil, 0)

View file

@ -37,7 +37,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys setfsgid(gid int) (prev int, err error) //sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sys Shutdown(fd int, how int) (err error) //sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys Statfs(path string, buf *Statfs_t) (err error) //sys Statfs(path string, buf *Statfs_t) (err error)

View file

@ -151,33 +151,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
return return
} }
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
err = Prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}
rl := rlimit32{}
if rlim.Cur == rlimInf64 {
rl.Cur = rlimInf32
} else if rlim.Cur < uint64(rlimInf32) {
rl.Cur = uint32(rlim.Cur)
} else {
return EINVAL
}
if rlim.Max == rlimInf64 {
rl.Max = rlimInf32
} else if rlim.Max < uint64(rlimInf32) {
rl.Max = uint32(rlim.Max)
} else {
return EINVAL
}
return setrlimit(resource, &rl)
}
func (r *PtraceRegs) PC() uint64 { return r.Epc } func (r *PtraceRegs) PC() uint64 { return r.Epc }
func (r *PtraceRegs) SetPC(pc uint64) { r.Epc = pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Epc = pc }

View file

@ -159,33 +159,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
return return
} }
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
err = Prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}
rl := rlimit32{}
if rlim.Cur == rlimInf64 {
rl.Cur = rlimInf32
} else if rlim.Cur < uint64(rlimInf32) {
rl.Cur = uint32(rlim.Cur)
} else {
return EINVAL
}
if rlim.Max == rlimInf64 {
rl.Max = rlimInf32
} else if rlim.Max < uint64(rlimInf32) {
rl.Max = uint32(rlim.Max)
} else {
return EINVAL
}
return setrlimit(resource, &rl)
}
func (r *PtraceRegs) PC() uint32 { return r.Nip } func (r *PtraceRegs) PC() uint32 { return r.Nip }
func (r *PtraceRegs) SetPC(pc uint32) { r.Nip = pc } func (r *PtraceRegs) SetPC(pc uint32) { r.Nip = pc }

View file

@ -34,7 +34,6 @@ package unix
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys setfsgid(gid int) (prev int, err error) //sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sys Shutdown(fd int, how int) (err error) //sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys Stat(path string, stat *Stat_t) (err error) //sys Stat(path string, stat *Stat_t) (err error)

View file

@ -38,7 +38,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys setfsgid(gid int) (prev int, err error) //sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sys Shutdown(fd int, how int) (err error) //sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)

View file

@ -34,7 +34,6 @@ import (
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys setfsgid(gid int) (prev int, err error) //sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys Stat(path string, stat *Stat_t) (err error) //sys Stat(path string, stat *Stat_t) (err error)
//sys Statfs(path string, buf *Statfs_t) (err error) //sys Statfs(path string, buf *Statfs_t) (err error)

View file

@ -31,7 +31,6 @@ package unix
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys setfsgid(gid int) (prev int, err error) //sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error) //sys setfsuid(uid int) (prev int, err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sys Shutdown(fd int, how int) (err error) //sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys Stat(path string, stat *Stat_t) (err error) //sys Stat(path string, stat *Stat_t) (err error)

View file

@ -340,7 +340,6 @@ func Statvfs(path string, buf *Statvfs_t) (err error) {
//sys Setpriority(which int, who int, prio int) (err error) //sys Setpriority(which int, who int, prio int) (err error)
//sysnb Setregid(rgid int, egid int) (err error) //sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error)
//sysnb Setrlimit(which int, lim *Rlimit) (err error)
//sysnb Setsid() (pid int, err error) //sysnb Setsid() (pid int, err error)
//sysnb Settimeofday(tp *Timeval) (err error) //sysnb Settimeofday(tp *Timeval) (err error)
//sysnb Setuid(uid int) (err error) //sysnb Setuid(uid int) (err error)
@ -501,7 +500,6 @@ func Statvfs(path string, buf *Statvfs_t) (err error) {
// compat_43_osendmsg // compat_43_osendmsg
// compat_43_osethostid // compat_43_osethostid
// compat_43_osethostname // compat_43_osethostname
// compat_43_osetrlimit
// compat_43_osigblock // compat_43_osigblock
// compat_43_osigsetmask // compat_43_osigsetmask
// compat_43_osigstack // compat_43_osigstack

View file

@ -151,6 +151,21 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
return return
} }
//sysnb getresuid(ruid *_C_int, euid *_C_int, suid *_C_int)
//sysnb getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int)
func Getresuid() (ruid, euid, suid int) {
var r, e, s _C_int
getresuid(&r, &e, &s)
return int(r), int(e), int(s)
}
func Getresgid() (rgid, egid, sgid int) {
var r, e, s _C_int
getresgid(&r, &e, &s)
return int(r), int(e), int(s)
}
//sys ioctl(fd int, req uint, arg uintptr) (err error) //sys ioctl(fd int, req uint, arg uintptr) (err error)
//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL //sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL
@ -294,7 +309,6 @@ func Uname(uname *Utsname) error {
//sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error) //sysnb Setresuid(ruid int, euid int, suid int) (err error)
//sysnb Setrlimit(which int, lim *Rlimit) (err error)
//sysnb Setrtable(rtable int) (err error) //sysnb Setrtable(rtable int) (err error)
//sysnb Setsid() (pid int, err error) //sysnb Setsid() (pid int, err error)
//sysnb Settimeofday(tp *Timeval) (err error) //sysnb Settimeofday(tp *Timeval) (err error)
@ -339,8 +353,6 @@ func Uname(uname *Utsname) error {
// getgid // getgid
// getitimer // getitimer
// getlogin // getlogin
// getresgid
// getresuid
// getthrid // getthrid
// ktrace // ktrace
// lfs_bmapv // lfs_bmapv

View file

@ -545,24 +545,24 @@ func Minor(dev uint64) uint32 {
* Expose the ioctl function * Expose the ioctl function
*/ */
//sys ioctlRet(fd int, req uint, arg uintptr) (ret int, err error) = libc.ioctl //sys ioctlRet(fd int, req int, arg uintptr) (ret int, err error) = libc.ioctl
//sys ioctlPtrRet(fd int, req uint, arg unsafe.Pointer) (ret int, err error) = libc.ioctl //sys ioctlPtrRet(fd int, req int, arg unsafe.Pointer) (ret int, err error) = libc.ioctl
func ioctl(fd int, req uint, arg uintptr) (err error) { func ioctl(fd int, req int, arg uintptr) (err error) {
_, err = ioctlRet(fd, req, arg) _, err = ioctlRet(fd, req, arg)
return err return err
} }
func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
_, err = ioctlPtrRet(fd, req, arg) _, err = ioctlPtrRet(fd, req, arg)
return err return err
} }
func IoctlSetTermio(fd int, req uint, value *Termio) error { func IoctlSetTermio(fd int, req int, value *Termio) error {
return ioctlPtr(fd, req, unsafe.Pointer(value)) return ioctlPtr(fd, req, unsafe.Pointer(value))
} }
func IoctlGetTermio(fd int, req uint) (*Termio, error) { func IoctlGetTermio(fd int, req int) (*Termio, error) {
var value Termio var value Termio
err := ioctlPtr(fd, req, unsafe.Pointer(&value)) err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return &value, err return &value, err
@ -665,7 +665,6 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Setpriority(which int, who int, prio int) (err error) //sys Setpriority(which int, who int, prio int) (err error)
//sysnb Setregid(rgid int, egid int) (err error) //sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setreuid(ruid int, euid int) (err error) //sysnb Setreuid(ruid int, euid int) (err error)
//sysnb Setrlimit(which int, lim *Rlimit) (err error)
//sysnb Setsid() (pid int, err error) //sysnb Setsid() (pid int, err error)
//sysnb Setuid(uid int) (err error) //sysnb Setuid(uid int) (err error)
//sys Shutdown(s int, how int) (err error) = libsocket.shutdown //sys Shutdown(s int, how int) (err error) = libsocket.shutdown
@ -1080,11 +1079,11 @@ func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags
return retCl, retData, flags, nil return retCl, retData, flags, nil
} }
func IoctlSetIntRetInt(fd int, req uint, arg int) (int, error) { func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) {
return ioctlRet(fd, req, uintptr(arg)) return ioctlRet(fd, req, uintptr(arg))
} }
func IoctlSetString(fd int, req uint, val string) error { func IoctlSetString(fd int, req int, val string) error {
bs := make([]byte, len(val)+1) bs := make([]byte, len(val)+1)
copy(bs[:len(bs)-1], val) copy(bs[:len(bs)-1], val)
err := ioctlPtr(fd, req, unsafe.Pointer(&bs[0])) err := ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
@ -1120,7 +1119,7 @@ func (l *Lifreq) GetLifruUint() uint {
return *(*uint)(unsafe.Pointer(&l.Lifru[0])) return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
} }
func IoctlLifreq(fd int, req uint, l *Lifreq) error { func IoctlLifreq(fd int, req int, l *Lifreq) error {
return ioctlPtr(fd, req, unsafe.Pointer(l)) return ioctlPtr(fd, req, unsafe.Pointer(l))
} }
@ -1131,6 +1130,6 @@ func (s *Strioctl) SetInt(i int) {
s.Dp = (*int8)(unsafe.Pointer(&i)) s.Dp = (*int8)(unsafe.Pointer(&i))
} }
func IoctlSetStrioctlRetInt(fd int, req uint, s *Strioctl) (int, error) { func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
return ioctlPtrRet(fd, req, unsafe.Pointer(s)) return ioctlPtrRet(fd, req, unsafe.Pointer(s))
} }

View file

@ -587,3 +587,10 @@ func emptyIovecs(iov []Iovec) bool {
} }
return true return true
} }
// Setrlimit sets a resource limit.
func Setrlimit(resource int, rlim *Rlimit) error {
// Just call the syscall version, because as of Go 1.21
// it will affect starting a new process.
return syscall.Setrlimit(resource, (*syscall.Rlimit)(rlim))
}

View file

@ -212,8 +212,8 @@ func (cmsg *Cmsghdr) SetLen(length int) {
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP
//sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP //sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP
//sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL //sys ioctl(fd int, req int, arg uintptr) (err error) = SYS_IOCTL
//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL //sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = SYS_IOCTL
//sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A //sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A
//sys Chdir(path string) (err error) = SYS___CHDIR_A //sys Chdir(path string) (err error) = SYS___CHDIR_A

View file

@ -1270,6 +1270,16 @@ const (
SEEK_END = 0x2 SEEK_END = 0x2
SEEK_HOLE = 0x3 SEEK_HOLE = 0x3
SEEK_SET = 0x0 SEEK_SET = 0x0
SF_APPEND = 0x40000
SF_ARCHIVED = 0x10000
SF_DATALESS = 0x40000000
SF_FIRMLINK = 0x800000
SF_IMMUTABLE = 0x20000
SF_NOUNLINK = 0x100000
SF_RESTRICTED = 0x80000
SF_SETTABLE = 0x3fff0000
SF_SUPPORTED = 0x9f0000
SF_SYNTHETIC = 0xc0000000
SHUT_RD = 0x0 SHUT_RD = 0x0
SHUT_RDWR = 0x2 SHUT_RDWR = 0x2
SHUT_WR = 0x1 SHUT_WR = 0x1
@ -1543,6 +1553,15 @@ const (
TIOCTIMESTAMP = 0x40107459 TIOCTIMESTAMP = 0x40107459
TIOCUCNTL = 0x80047466 TIOCUCNTL = 0x80047466
TOSTOP = 0x400000 TOSTOP = 0x400000
UF_APPEND = 0x4
UF_COMPRESSED = 0x20
UF_DATAVAULT = 0x80
UF_HIDDEN = 0x8000
UF_IMMUTABLE = 0x2
UF_NODUMP = 0x1
UF_OPAQUE = 0x8
UF_SETTABLE = 0xffff
UF_TRACKED = 0x40
VDISCARD = 0xf VDISCARD = 0xf
VDSUSP = 0xb VDSUSP = 0xb
VEOF = 0x0 VEOF = 0x0

View file

@ -1270,6 +1270,16 @@ const (
SEEK_END = 0x2 SEEK_END = 0x2
SEEK_HOLE = 0x3 SEEK_HOLE = 0x3
SEEK_SET = 0x0 SEEK_SET = 0x0
SF_APPEND = 0x40000
SF_ARCHIVED = 0x10000
SF_DATALESS = 0x40000000
SF_FIRMLINK = 0x800000
SF_IMMUTABLE = 0x20000
SF_NOUNLINK = 0x100000
SF_RESTRICTED = 0x80000
SF_SETTABLE = 0x3fff0000
SF_SUPPORTED = 0x9f0000
SF_SYNTHETIC = 0xc0000000
SHUT_RD = 0x0 SHUT_RD = 0x0
SHUT_RDWR = 0x2 SHUT_RDWR = 0x2
SHUT_WR = 0x1 SHUT_WR = 0x1
@ -1543,6 +1553,15 @@ const (
TIOCTIMESTAMP = 0x40107459 TIOCTIMESTAMP = 0x40107459
TIOCUCNTL = 0x80047466 TIOCUCNTL = 0x80047466
TOSTOP = 0x400000 TOSTOP = 0x400000
UF_APPEND = 0x4
UF_COMPRESSED = 0x20
UF_DATAVAULT = 0x80
UF_HIDDEN = 0x8000
UF_IMMUTABLE = 0x2
UF_NODUMP = 0x1
UF_OPAQUE = 0x8
UF_SETTABLE = 0xffff
UF_TRACKED = 0x40
VDISCARD = 0xf VDISCARD = 0xf
VDSUSP = 0xb VDSUSP = 0xb
VEOF = 0x0 VEOF = 0x0

View file

@ -2967,6 +2967,7 @@ const (
SOL_TCP = 0x6 SOL_TCP = 0x6
SOL_TIPC = 0x10f SOL_TIPC = 0x10f
SOL_TLS = 0x11a SOL_TLS = 0x11a
SOL_UDP = 0x11
SOL_X25 = 0x106 SOL_X25 = 0x106
SOL_XDP = 0x11b SOL_XDP = 0x11b
SOMAXCONN = 0x1000 SOMAXCONN = 0x1000
@ -3251,6 +3252,19 @@ const (
TRACEFS_MAGIC = 0x74726163 TRACEFS_MAGIC = 0x74726163
TS_COMM_LEN = 0x20 TS_COMM_LEN = 0x20
UDF_SUPER_MAGIC = 0x15013346 UDF_SUPER_MAGIC = 0x15013346
UDP_CORK = 0x1
UDP_ENCAP = 0x64
UDP_ENCAP_ESPINUDP = 0x2
UDP_ENCAP_ESPINUDP_NON_IKE = 0x1
UDP_ENCAP_GTP0 = 0x4
UDP_ENCAP_GTP1U = 0x5
UDP_ENCAP_L2TPINUDP = 0x3
UDP_GRO = 0x68
UDP_NO_CHECK6_RX = 0x66
UDP_NO_CHECK6_TX = 0x65
UDP_SEGMENT = 0x67
UDP_V4_FLOW = 0x2
UDP_V6_FLOW = 0x6
UMOUNT_NOFOLLOW = 0x8 UMOUNT_NOFOLLOW = 0x8
USBDEVICE_SUPER_MAGIC = 0x9fa2 USBDEVICE_SUPER_MAGIC = 0x9fa2
UTIME_NOW = 0x3fffffff UTIME_NOW = 0x3fffffff

View file

@ -329,6 +329,54 @@ const (
SCM_WIFI_STATUS = 0x25 SCM_WIFI_STATUS = 0x25
SFD_CLOEXEC = 0x400000 SFD_CLOEXEC = 0x400000
SFD_NONBLOCK = 0x4000 SFD_NONBLOCK = 0x4000
SF_FP = 0x38
SF_I0 = 0x20
SF_I1 = 0x24
SF_I2 = 0x28
SF_I3 = 0x2c
SF_I4 = 0x30
SF_I5 = 0x34
SF_L0 = 0x0
SF_L1 = 0x4
SF_L2 = 0x8
SF_L3 = 0xc
SF_L4 = 0x10
SF_L5 = 0x14
SF_L6 = 0x18
SF_L7 = 0x1c
SF_PC = 0x3c
SF_RETP = 0x40
SF_V9_FP = 0x70
SF_V9_I0 = 0x40
SF_V9_I1 = 0x48
SF_V9_I2 = 0x50
SF_V9_I3 = 0x58
SF_V9_I4 = 0x60
SF_V9_I5 = 0x68
SF_V9_L0 = 0x0
SF_V9_L1 = 0x8
SF_V9_L2 = 0x10
SF_V9_L3 = 0x18
SF_V9_L4 = 0x20
SF_V9_L5 = 0x28
SF_V9_L6 = 0x30
SF_V9_L7 = 0x38
SF_V9_PC = 0x78
SF_V9_RETP = 0x80
SF_V9_XARG0 = 0x88
SF_V9_XARG1 = 0x90
SF_V9_XARG2 = 0x98
SF_V9_XARG3 = 0xa0
SF_V9_XARG4 = 0xa8
SF_V9_XARG5 = 0xb0
SF_V9_XXARG = 0xb8
SF_XARG0 = 0x44
SF_XARG1 = 0x48
SF_XARG2 = 0x4c
SF_XARG3 = 0x50
SF_XARG4 = 0x54
SF_XARG5 = 0x58
SF_XXARG = 0x5c
SIOCATMARK = 0x8905 SIOCATMARK = 0x8905
SIOCGPGRP = 0x8904 SIOCGPGRP = 0x8904
SIOCGSTAMPNS_NEW = 0x40108907 SIOCGSTAMPNS_NEW = 0x40108907

View file

@ -124,7 +124,6 @@ int utime(uintptr_t, uintptr_t);
unsigned long long getsystemcfg(int); unsigned long long getsystemcfg(int);
int umount(uintptr_t); int umount(uintptr_t);
int getrlimit64(int, uintptr_t); int getrlimit64(int, uintptr_t);
int setrlimit64(int, uintptr_t);
long long lseek64(int, long long, int); long long lseek64(int, long long, int);
uintptr_t mmap(uintptr_t, uintptr_t, int, int, int, long long); uintptr_t mmap(uintptr_t, uintptr_t, int, int, int, long long);
@ -213,7 +212,7 @@ func wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t,
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) { func ioctl(fd int, req int, arg uintptr) (err error) {
r0, er := C.ioctl(C.int(fd), C.int(req), C.uintptr_t(arg)) r0, er := C.ioctl(C.int(fd), C.int(req), C.uintptr_t(arg))
if r0 == -1 && er != nil { if r0 == -1 && er != nil {
err = er err = er
@ -223,7 +222,7 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
r0, er := C.ioctl(C.int(fd), C.int(req), C.uintptr_t(uintptr(arg))) r0, er := C.ioctl(C.int(fd), C.int(req), C.uintptr_t(uintptr(arg)))
if r0 == -1 && er != nil { if r0 == -1 && er != nil {
err = er err = er
@ -1464,16 +1463,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
r0, er := C.setrlimit64(C.int(resource), C.uintptr_t(uintptr(unsafe.Pointer(rlim))))
if r0 == -1 && er != nil {
err = er
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Seek(fd int, offset int64, whence int) (off int64, err error) { func Seek(fd int, offset int64, whence int) (off int64, err error) {
r0, er := C.lseek64(C.int(fd), C.longlong(offset), C.int(whence)) r0, er := C.lseek64(C.int(fd), C.longlong(offset), C.int(whence))
off = int64(r0) off = int64(r0)

View file

@ -93,8 +93,8 @@ func wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t,
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) { func ioctl(fd int, req int, arg uintptr) (err error) {
_, e1 := callioctl(fd, int(req), arg) _, e1 := callioctl(fd, req, arg)
if e1 != 0 { if e1 != 0 {
err = errnoErr(e1) err = errnoErr(e1)
} }
@ -103,8 +103,8 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
_, e1 := callioctl_ptr(fd, int(req), arg) _, e1 := callioctl_ptr(fd, req, arg)
if e1 != 0 { if e1 != 0 {
err = errnoErr(e1) err = errnoErr(e1)
} }
@ -1422,16 +1422,6 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
_, e1 := callsetrlimit(resource, uintptr(unsafe.Pointer(rlim)))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Seek(fd int, offset int64, whence int) (off int64, err error) { func Seek(fd int, offset int64, whence int) (off int64, err error) {
r0, e1 := calllseek(fd, offset, whence) r0, e1 := calllseek(fd, offset, whence)
off = int64(r0) off = int64(r0)

View file

@ -124,7 +124,6 @@ import (
//go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o" //go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_umount umount "libc.a/shr_64.o" //go:cgo_import_dynamic libc_umount umount "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.a/shr_64.o" //go:cgo_import_dynamic libc_getrlimit getrlimit "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_setrlimit setrlimit "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_lseek lseek "libc.a/shr_64.o" //go:cgo_import_dynamic libc_lseek lseek "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_mmap64 mmap64 "libc.a/shr_64.o" //go:cgo_import_dynamic libc_mmap64 mmap64 "libc.a/shr_64.o"
@ -242,7 +241,6 @@ import (
//go:linkname libc_getsystemcfg libc_getsystemcfg //go:linkname libc_getsystemcfg libc_getsystemcfg
//go:linkname libc_umount libc_umount //go:linkname libc_umount libc_umount
//go:linkname libc_getrlimit libc_getrlimit //go:linkname libc_getrlimit libc_getrlimit
//go:linkname libc_setrlimit libc_setrlimit
//go:linkname libc_lseek libc_lseek //go:linkname libc_lseek libc_lseek
//go:linkname libc_mmap64 libc_mmap64 //go:linkname libc_mmap64 libc_mmap64
@ -363,7 +361,6 @@ var (
libc_getsystemcfg, libc_getsystemcfg,
libc_umount, libc_umount,
libc_getrlimit, libc_getrlimit,
libc_setrlimit,
libc_lseek, libc_lseek,
libc_mmap64 syscallFunc libc_mmap64 syscallFunc
) )
@ -1179,13 +1176,6 @@ func callgetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callsetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) {
r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_setrlimit)), 2, uintptr(resource), rlim, 0, 0, 0, 0)
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func calllseek(fd int, offset int64, whence int) (r1 uintptr, e1 Errno) { func calllseek(fd int, offset int64, whence int) (r1 uintptr, e1 Errno) {
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_lseek)), 3, uintptr(fd), uintptr(offset), uintptr(whence), 0, 0, 0) r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_lseek)), 3, uintptr(fd), uintptr(offset), uintptr(whence), 0, 0, 0)
return return

View file

@ -123,7 +123,6 @@ int utime(uintptr_t, uintptr_t);
unsigned long long getsystemcfg(int); unsigned long long getsystemcfg(int);
int umount(uintptr_t); int umount(uintptr_t);
int getrlimit(int, uintptr_t); int getrlimit(int, uintptr_t);
int setrlimit(int, uintptr_t);
long long lseek(int, long long, int); long long lseek(int, long long, int);
uintptr_t mmap64(uintptr_t, uintptr_t, int, int, int, long long); uintptr_t mmap64(uintptr_t, uintptr_t, int, int, int, long long);
@ -131,6 +130,7 @@ uintptr_t mmap64(uintptr_t, uintptr_t, int, int, int, long long);
import "C" import "C"
import ( import (
"syscall" "syscall"
"unsafe"
) )
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@ -1055,14 +1055,6 @@ func callgetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func callsetrlimit(resource int, rlim uintptr) (r1 uintptr, e1 Errno) {
r1 = uintptr(C.setrlimit(C.int(resource), C.uintptr_t(rlim)))
e1 = syscall.GetErrno()
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func calllseek(fd int, offset int64, whence int) (r1 uintptr, e1 Errno) { func calllseek(fd int, offset int64, whence int) (r1 uintptr, e1 Errno) {
r1 = uintptr(C.lseek(C.int(fd), C.longlong(offset), C.int(whence))) r1 = uintptr(C.lseek(C.int(fd), C.longlong(offset), C.int(whence)))
e1 = syscall.GetErrno() e1 = syscall.GetErrno()

View file

@ -1992,6 +1992,31 @@ var libc_select_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setattrlist(path string, attrlist *Attrlist, attrBuf []byte, options int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(attrBuf) > 0 {
_p1 = unsafe.Pointer(&attrBuf[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
_, _, e1 := syscall_syscall6(libc_setattrlist_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(attrlist)), uintptr(_p1), uintptr(len(attrBuf)), uintptr(options), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setattrlist_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setegid(egid int) (err error) { func Setegid(egid int) (err error) {
_, _, e1 := syscall_syscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) _, _, e1 := syscall_syscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0)
if e1 != 0 { if e1 != 0 {
@ -2123,20 +2148,6 @@ var libc_setreuid_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setrlimit_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -705,6 +705,11 @@ TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8
DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB) DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB)
TEXT libc_setattrlist_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setattrlist(SB)
GLOBL ·libc_setattrlist_trampoline_addr(SB), RODATA, $8
DATA ·libc_setattrlist_trampoline_addr(SB)/8, $libc_setattrlist_trampoline<>(SB)
TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setegid(SB) JMP libc_setegid(SB)
@ -759,12 +764,6 @@ TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8
DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB) DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB)
TEXT libc_setrlimit_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrlimit(SB)
GLOBL ·libc_setrlimit_trampoline_addr(SB), RODATA, $8
DATA ·libc_setrlimit_trampoline_addr(SB)/8, $libc_setrlimit_trampoline<>(SB)
TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setsid(SB) JMP libc_setsid(SB)

View file

@ -1992,6 +1992,31 @@ var libc_select_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setattrlist(path string, attrlist *Attrlist, attrBuf []byte, options int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(attrBuf) > 0 {
_p1 = unsafe.Pointer(&attrBuf[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
_, _, e1 := syscall_syscall6(libc_setattrlist_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(attrlist)), uintptr(_p1), uintptr(len(attrBuf)), uintptr(options), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setattrlist_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setegid(egid int) (err error) { func Setegid(egid int) (err error) {
_, _, e1 := syscall_syscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0) _, _, e1 := syscall_syscall(libc_setegid_trampoline_addr, uintptr(egid), 0, 0)
if e1 != 0 { if e1 != 0 {
@ -2123,20 +2148,6 @@ var libc_setreuid_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setrlimit_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setrlimit setrlimit "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0) r0, _, e1 := syscall_rawSyscall(libc_setsid_trampoline_addr, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -705,6 +705,11 @@ TEXT libc_select_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_select_trampoline_addr(SB), RODATA, $8
DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB) DATA ·libc_select_trampoline_addr(SB)/8, $libc_select_trampoline<>(SB)
TEXT libc_setattrlist_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setattrlist(SB)
GLOBL ·libc_setattrlist_trampoline_addr(SB), RODATA, $8
DATA ·libc_setattrlist_trampoline_addr(SB)/8, $libc_setattrlist_trampoline<>(SB)
TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_setegid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setegid(SB) JMP libc_setegid(SB)
@ -759,12 +764,6 @@ TEXT libc_setreuid_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_setreuid_trampoline_addr(SB), RODATA, $8
DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB) DATA ·libc_setreuid_trampoline_addr(SB)/8, $libc_setreuid_trampoline<>(SB)
TEXT libc_setrlimit_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrlimit(SB)
GLOBL ·libc_setrlimit_trampoline_addr(SB), RODATA, $8
DATA ·libc_setrlimit_trampoline_addr(SB)/8, $libc_setrlimit_trampoline<>(SB)
TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_setsid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setsid(SB) JMP libc_setsid(SB)

View file

@ -1410,16 +1410,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -1645,16 +1645,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -1645,16 +1645,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -1645,16 +1645,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -1645,16 +1645,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -1645,16 +1645,6 @@ func Setresuid(ruid int, euid int, suid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -1346,16 +1346,6 @@ func PivotRoot(newroot string, putold string) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) {
_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(newlimit)), uintptr(unsafe.Pointer(old)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { func Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) {
_, _, e1 := Syscall6(SYS_PRCTL, uintptr(option), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5), 0) _, _, e1 := Syscall6(SYS_PRCTL, uintptr(option), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5), 0)
if e1 != 0 { if e1 != 0 {
@ -2182,3 +2172,17 @@ func rtSigprocmask(how int, set *Sigset_t, oldset *Sigset_t, sigsetsize uintptr)
} }
return return
} }
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) {
RawSyscallNoError(SYS_GETRESUID, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid)))
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) {
RawSyscallNoError(SYS_GETRESGID, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid)))
return
}

View file

@ -411,16 +411,6 @@ func getrlimit(resource int, rlim *rlimit32) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setrlimit(resource int, rlim *rlimit32) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func futimesat(dirfd int, path string, times *[2]Timeval) (err error) { func futimesat(dirfd int, path string, times *[2]Timeval) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(path) _p0, err = BytePtrFromString(path)

View file

@ -334,16 +334,6 @@ func setfsuid(uid int) (prev int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Shutdown(fd int, how int) (err error) { func Shutdown(fd int, how int) (err error) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
if e1 != 0 { if e1 != 0 {

View file

@ -578,16 +578,6 @@ func getrlimit(resource int, rlim *rlimit32) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setrlimit(resource int, rlim *rlimit32) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func armSyncFileRange(fd int, flags int, off int64, n int64) (err error) { func armSyncFileRange(fd int, flags int, off int64, n int64) (err error) {
_, _, e1 := Syscall6(SYS_ARM_SYNC_FILE_RANGE, uintptr(fd), uintptr(flags), uintptr(off), uintptr(off>>32), uintptr(n), uintptr(n>>32)) _, _, e1 := Syscall6(SYS_ARM_SYNC_FILE_RANGE, uintptr(fd), uintptr(flags), uintptr(off), uintptr(off>>32), uintptr(n), uintptr(n>>32))
if e1 != 0 { if e1 != 0 {

View file

@ -289,16 +289,6 @@ func setfsuid(uid int) (prev int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Shutdown(fd int, how int) (err error) { func Shutdown(fd int, how int) (err error) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
if e1 != 0 { if e1 != 0 {

View file

@ -644,16 +644,6 @@ func getrlimit(resource int, rlim *rlimit32) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setrlimit(resource int, rlim *rlimit32) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Alarm(seconds uint) (remaining uint, err error) { func Alarm(seconds uint) (remaining uint, err error) {
r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0)
remaining = uint(r0) remaining = uint(r0)

View file

@ -278,16 +278,6 @@ func setfsuid(uid int) (prev int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Shutdown(fd int, how int) (err error) { func Shutdown(fd int, how int) (err error) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
if e1 != 0 { if e1 != 0 {

View file

@ -278,16 +278,6 @@ func setfsuid(uid int) (prev int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Shutdown(fd int, how int) (err error) { func Shutdown(fd int, how int) (err error) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
if e1 != 0 { if e1 != 0 {

View file

@ -644,16 +644,6 @@ func getrlimit(resource int, rlim *rlimit32) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setrlimit(resource int, rlim *rlimit32) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Alarm(seconds uint) (remaining uint, err error) { func Alarm(seconds uint) (remaining uint, err error) {
r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0)
remaining = uint(r0) remaining = uint(r0)

View file

@ -624,16 +624,6 @@ func getrlimit(resource int, rlim *rlimit32) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setrlimit(resource int, rlim *rlimit32) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { func syncFileRange2(fd int, flags int, off int64, n int64) (err error) {
_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off>>32), uintptr(off), uintptr(n>>32), uintptr(n)) _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off>>32), uintptr(off), uintptr(n>>32), uintptr(n))
if e1 != 0 { if e1 != 0 {

View file

@ -349,16 +349,6 @@ func setfsuid(uid int) (prev int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Shutdown(fd int, how int) (err error) { func Shutdown(fd int, how int) (err error) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
if e1 != 0 { if e1 != 0 {

View file

@ -349,16 +349,6 @@ func setfsuid(uid int) (prev int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Shutdown(fd int, how int) (err error) { func Shutdown(fd int, how int) (err error) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
if e1 != 0 { if e1 != 0 {

View file

@ -269,16 +269,6 @@ func setfsuid(uid int) (prev int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Shutdown(fd int, how int) (err error) { func Shutdown(fd int, how int) (err error) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
if e1 != 0 { if e1 != 0 {

View file

@ -319,16 +319,6 @@ func setfsuid(uid int) (prev int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) { func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags)) r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
n = int64(r0) n = int64(r0)

View file

@ -329,16 +329,6 @@ func setfsuid(uid int) (prev int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Shutdown(fd int, how int) (err error) { func Shutdown(fd int, how int) (err error) {
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) _, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
if e1 != 0 { if e1 != 0 {

View file

@ -1607,16 +1607,6 @@ func Setreuid(ruid int, euid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -1607,16 +1607,6 @@ func Setreuid(ruid int, euid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -1607,16 +1607,6 @@ func Setreuid(ruid int, euid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -1607,16 +1607,6 @@ func Setreuid(ruid int, euid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) { func Setsid() (pid int, err error) {
r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
pid = int(r0) pid = int(r0)

View file

@ -519,6 +519,28 @@ var libc_getcwd_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) {
syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid)))
return
}
var libc_getresuid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresuid getresuid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) {
syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid)))
return
}
var libc_getresgid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresgid getresgid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) { func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 { if e1 != 0 {
@ -1894,20 +1916,6 @@ var libc_setresuid_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setrlimit_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setrlimit setrlimit "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrtable(rtable int) (err error) { func Setrtable(rtable int) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0)
if e1 != 0 { if e1 != 0 {

View file

@ -158,6 +158,16 @@ TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $4 GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $4
DATA ·libc_getcwd_trampoline_addr(SB)/4, $libc_getcwd_trampoline<>(SB) DATA ·libc_getcwd_trampoline_addr(SB)/4, $libc_getcwd_trampoline<>(SB)
TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_getresuid(SB)
GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $4
DATA ·libc_getresuid_trampoline_addr(SB)/4, $libc_getresuid_trampoline<>(SB)
TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_getresgid(SB)
GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $4
DATA ·libc_getresgid_trampoline_addr(SB)/4, $libc_getresgid_trampoline<>(SB)
TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_ioctl(SB) JMP libc_ioctl(SB)
GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $4 GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $4
@ -573,11 +583,6 @@ TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $4 GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $4
DATA ·libc_setresuid_trampoline_addr(SB)/4, $libc_setresuid_trampoline<>(SB) DATA ·libc_setresuid_trampoline_addr(SB)/4, $libc_setresuid_trampoline<>(SB)
TEXT libc_setrlimit_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrlimit(SB)
GLOBL ·libc_setrlimit_trampoline_addr(SB), RODATA, $4
DATA ·libc_setrlimit_trampoline_addr(SB)/4, $libc_setrlimit_trampoline<>(SB)
TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrtable(SB) JMP libc_setrtable(SB)
GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $4 GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $4

View file

@ -519,15 +519,29 @@ var libc_getcwd_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) { func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) {
_, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid)))
if e1 != 0 {
err = errnoErr(e1)
}
return return
} }
func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { var libc_getresuid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresuid getresuid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) {
syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid)))
return
}
var libc_getresgid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresgid getresgid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 { if e1 != 0 {
err = errnoErr(e1) err = errnoErr(e1)
@ -541,6 +555,16 @@ var libc_ioctl_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) {
_, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
var _p0 unsafe.Pointer var _p0 unsafe.Pointer
if len(mib) > 0 { if len(mib) > 0 {
@ -1894,20 +1918,6 @@ var libc_setresuid_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setrlimit_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setrlimit setrlimit "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrtable(rtable int) (err error) { func Setrtable(rtable int) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0)
if e1 != 0 { if e1 != 0 {

View file

@ -158,6 +158,16 @@ TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8
DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB) DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB)
TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_getresuid(SB)
GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $8
DATA ·libc_getresuid_trampoline_addr(SB)/8, $libc_getresuid_trampoline<>(SB)
TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_getresgid(SB)
GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $8
DATA ·libc_getresgid_trampoline_addr(SB)/8, $libc_getresgid_trampoline<>(SB)
TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_ioctl(SB) JMP libc_ioctl(SB)
GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8
@ -573,11 +583,6 @@ TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $8
DATA ·libc_setresuid_trampoline_addr(SB)/8, $libc_setresuid_trampoline<>(SB) DATA ·libc_setresuid_trampoline_addr(SB)/8, $libc_setresuid_trampoline<>(SB)
TEXT libc_setrlimit_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrlimit(SB)
GLOBL ·libc_setrlimit_trampoline_addr(SB), RODATA, $8
DATA ·libc_setrlimit_trampoline_addr(SB)/8, $libc_setrlimit_trampoline<>(SB)
TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrtable(SB) JMP libc_setrtable(SB)
GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $8

View file

@ -519,6 +519,28 @@ var libc_getcwd_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) {
syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid)))
return
}
var libc_getresuid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresuid getresuid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) {
syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid)))
return
}
var libc_getresgid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresgid getresgid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) { func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 { if e1 != 0 {
@ -1894,20 +1916,6 @@ var libc_setresuid_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setrlimit_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setrlimit setrlimit "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrtable(rtable int) (err error) { func Setrtable(rtable int) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0)
if e1 != 0 { if e1 != 0 {

View file

@ -158,6 +158,16 @@ TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $4 GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $4
DATA ·libc_getcwd_trampoline_addr(SB)/4, $libc_getcwd_trampoline<>(SB) DATA ·libc_getcwd_trampoline_addr(SB)/4, $libc_getcwd_trampoline<>(SB)
TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_getresuid(SB)
GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $4
DATA ·libc_getresuid_trampoline_addr(SB)/4, $libc_getresuid_trampoline<>(SB)
TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_getresgid(SB)
GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $4
DATA ·libc_getresgid_trampoline_addr(SB)/4, $libc_getresgid_trampoline<>(SB)
TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_ioctl(SB) JMP libc_ioctl(SB)
GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $4 GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $4
@ -573,11 +583,6 @@ TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $4 GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $4
DATA ·libc_setresuid_trampoline_addr(SB)/4, $libc_setresuid_trampoline<>(SB) DATA ·libc_setresuid_trampoline_addr(SB)/4, $libc_setresuid_trampoline<>(SB)
TEXT libc_setrlimit_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrlimit(SB)
GLOBL ·libc_setrlimit_trampoline_addr(SB), RODATA, $4
DATA ·libc_setrlimit_trampoline_addr(SB)/4, $libc_setrlimit_trampoline<>(SB)
TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrtable(SB) JMP libc_setrtable(SB)
GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $4 GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $4

View file

@ -519,6 +519,28 @@ var libc_getcwd_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) {
syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid)))
return
}
var libc_getresuid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresuid getresuid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) {
syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid)))
return
}
var libc_getresgid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresgid getresgid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) { func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 { if e1 != 0 {
@ -1894,20 +1916,6 @@ var libc_setresuid_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setrlimit_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setrlimit setrlimit "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrtable(rtable int) (err error) { func Setrtable(rtable int) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0)
if e1 != 0 { if e1 != 0 {

View file

@ -158,6 +158,16 @@ TEXT libc_getcwd_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_getcwd_trampoline_addr(SB), RODATA, $8
DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB) DATA ·libc_getcwd_trampoline_addr(SB)/8, $libc_getcwd_trampoline<>(SB)
TEXT libc_getresuid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_getresuid(SB)
GLOBL ·libc_getresuid_trampoline_addr(SB), RODATA, $8
DATA ·libc_getresuid_trampoline_addr(SB)/8, $libc_getresuid_trampoline<>(SB)
TEXT libc_getresgid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_getresgid(SB)
GLOBL ·libc_getresgid_trampoline_addr(SB), RODATA, $8
DATA ·libc_getresgid_trampoline_addr(SB)/8, $libc_getresgid_trampoline<>(SB)
TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_ioctl(SB) JMP libc_ioctl(SB)
GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8
@ -573,11 +583,6 @@ TEXT libc_setresuid_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_setresuid_trampoline_addr(SB), RODATA, $8
DATA ·libc_setresuid_trampoline_addr(SB)/8, $libc_setresuid_trampoline<>(SB) DATA ·libc_setresuid_trampoline_addr(SB)/8, $libc_setresuid_trampoline<>(SB)
TEXT libc_setrlimit_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrlimit(SB)
GLOBL ·libc_setrlimit_trampoline_addr(SB), RODATA, $8
DATA ·libc_setrlimit_trampoline_addr(SB)/8, $libc_setrlimit_trampoline<>(SB)
TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0 TEXT libc_setrtable_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrtable(SB) JMP libc_setrtable(SB)
GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $8 GLOBL ·libc_setrtable_trampoline_addr(SB), RODATA, $8

View file

@ -519,6 +519,28 @@ var libc_getcwd_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) {
syscall_rawSyscall(libc_getresuid_trampoline_addr, uintptr(unsafe.Pointer(ruid)), uintptr(unsafe.Pointer(euid)), uintptr(unsafe.Pointer(suid)))
return
}
var libc_getresuid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresuid getresuid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getresgid(rgid *_C_int, egid *_C_int, sgid *_C_int) {
syscall_rawSyscall(libc_getresgid_trampoline_addr, uintptr(unsafe.Pointer(rgid)), uintptr(unsafe.Pointer(egid)), uintptr(unsafe.Pointer(sgid)))
return
}
var libc_getresgid_trampoline_addr uintptr
//go:cgo_import_dynamic libc_getresgid getresgid "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req uint, arg uintptr) (err error) { func ioctl(fd int, req uint, arg uintptr) (err error) {
_, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg)) _, _, e1 := syscall_syscall(libc_ioctl_trampoline_addr, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 { if e1 != 0 {
@ -1894,20 +1916,6 @@ var libc_setresuid_trampoline_addr uintptr
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(which int, lim *Rlimit) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrlimit_trampoline_addr, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_setrlimit_trampoline_addr uintptr
//go:cgo_import_dynamic libc_setrlimit setrlimit "libc.so"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrtable(rtable int) (err error) { func Setrtable(rtable int) (err error) {
_, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0) _, _, e1 := syscall_rawSyscall(libc_setrtable_trampoline_addr, uintptr(rtable), 0, 0)
if e1 != 0 { if e1 != 0 {

Some files were not shown because too many files have changed in this diff Show more