diff --git a/go.mod b/go.mod index 82757da84..0762c9fe6 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/skycoin/dmsg -go 1.25.1 +go 1.25.4 require ( github.com/ActiveState/termtest/conpty v0.5.0 @@ -19,8 +19,8 @@ require ( github.com/pires/go-proxyproto v0.8.1 github.com/sirupsen/logrus v1.9.3 github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6 - github.com/skycoin/skycoin v0.28.1-0.20251215160458-f84f07154eae //MUST TRACK COBRA-CLI BRANCH FOR NOW v0.28.1-0.20251215160458-f84f07154eae - github.com/skycoin/skywire v1.3.32-0.20251108143835-4a7d00a050e1 + github.com/skycoin/skycoin v0.28.2 + github.com/skycoin/skywire v1.3.32-0.20251215232901-7d4328a5ca17 github.com/spf13/cobra v1.10.2 github.com/stretchr/testify v1.11.1 golang.org/x/net v0.48.0 @@ -30,7 +30,7 @@ require ( require ( github.com/docker/docker v28.5.2+incompatible - github.com/xtaci/smux v1.5.47 + github.com/xtaci/smux v1.5.49 ) require ( @@ -57,9 +57,9 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.29.0 // indirect + github.com/go-playground/validator/v10 v10.30.1 // indirect github.com/goccy/go-json v0.10.5 // indirect - github.com/goccy/go-yaml v1.19.0 // indirect + github.com/goccy/go-yaml v1.19.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/itchyny/gojq v0.12.18 // indirect github.com/itchyny/timefmt-go v0.1.7 // indirect @@ -80,7 +80,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/quic-go/qpack v0.6.0 // indirect - github.com/quic-go/quic-go v0.57.1 // indirect + github.com/quic-go/quic-go v0.58.0 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.1 // indirect @@ -95,7 +95,6 @@ require ( golang.org/x/arch v0.23.0 // indirect golang.org/x/crypto v0.46.0 // indirect golang.org/x/text v0.32.0 // indirect - golang.org/x/time v0.14.0 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.2 // indirect @@ -115,8 +114,8 @@ require ( // Below should reflect current versions of the following deps // To update deps to specific commit hash: // 1) Uncomment one of the following lines and substituite version with desired commit hash: -//replace github.com/skycoin/skycoin => github.com/skycoin/skycoin v0.28.1-0.20251215160458-f84f07154eae -//replace github.com/skycoin/skywire => github.com/skycoin/skywire v1.3.32-0.20251108143835-4a7d00a050e1 +//replace github.com/skycoin/skycoin => github.com/skycoin/skycoin v0.28.2 +//replace github.com/skycoin/skywire => github.com/skycoin/skywire v1.3.32-0.20251215232901-7d4328a5ca17 // 2) Run `go mod tidy && go mod vendor` // 3) Copy the populated version string to the correct place in require(...) above - replacing the specified version string // 4) Re-comment the uncommented replace directive above diff --git a/go.sum b/go.sum index 9e44488d0..927b3f00f 100644 --- a/go.sum +++ b/go.sum @@ -78,16 +78,16 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.29.0 h1:lQlF5VNJWNlRbRZNeOIkWElR+1LL/OuHcc0Kp14w1xk= -github.com/go-playground/validator/v10 v10.29.0/go.mod h1:D6QxqeMlgIPuT02L66f2ccrZ7AGgHkzKmmTMZhk/Kc4= +github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= +github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/goccy/go-yaml v1.19.0 h1:EmkZ9RIsX+Uq4DYFowegAuJo8+xdX3T/2dwNPXbxEYE= -github.com/goccy/go-yaml v1.19.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.19.1 h1:3rG3+v8pkhRqoQ/88NYNMHYVGYztCOCIZ7UQhu7H+NE= +github.com/goccy/go-yaml v1.19.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -161,8 +161,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= -github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10= -github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s= +github.com/quic-go/quic-go v0.58.0 h1:ggY2pvZaVdB9EyojxL1p+5mptkuHyX5MOSv4dgWF4Ug= +github.com/quic-go/quic-go v0.58.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -170,10 +170,10 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6 h1:1Nc5EBY6pjfw1kwW0duwyG+7WliWz5u9kgk1h5MnLuA= github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:UXghlricA7J3aRD/k7p/zBObQfmBawwCxIVPVjz2Q3o= -github.com/skycoin/skycoin v0.28.1-0.20251215160458-f84f07154eae h1:CjmnI6mIcmel4hGr8zi/X0yl2uLIfhRnggwwU/NapcM= -github.com/skycoin/skycoin v0.28.1-0.20251215160458-f84f07154eae/go.mod h1:ZMRZ/7/4rNnisdkZjWNsAHEDtRCG5o8YN7Xe8GtHs6s= -github.com/skycoin/skywire v1.3.32-0.20251108143835-4a7d00a050e1 h1:+S3Hr+EVnsj79ku9gPFxr1F8wiIwzJXwG94J1KQf5RU= -github.com/skycoin/skywire v1.3.32-0.20251108143835-4a7d00a050e1/go.mod h1:EwDfO34iivOLo4C8QmPT7g4Q1qDpM2k+anOIrxID/ss= +github.com/skycoin/skycoin v0.28.2 h1:N0whDAn9CIfYyHkw+LUDaLRZjE5qxuGzk5MG6I0QEpo= +github.com/skycoin/skycoin v0.28.2/go.mod h1:ZMRZ/7/4rNnisdkZjWNsAHEDtRCG5o8YN7Xe8GtHs6s= +github.com/skycoin/skywire v1.3.32-0.20251215232901-7d4328a5ca17 h1:3Ty366mIVSAr1zargF2QWGWoOa+hkfwWaFO7nCzrOCE= +github.com/skycoin/skywire v1.3.32-0.20251215232901-7d4328a5ca17/go.mod h1:z2340or9VHKuJ45C+FZQzoHn0FfSIKiFDHE18HynXy8= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= @@ -201,8 +201,8 @@ github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ= github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY= -github.com/xtaci/smux v1.5.47 h1:VzvwiCt7P2Y1eA7FR2ViwAUns8DG/wQMyMBVOCRNbys= -github.com/xtaci/smux v1.5.47/go.mod h1:IGQ9QYrBphmb/4aTnLEcJby0TNr3NV+OslIOMrX825Q= +github.com/xtaci/smux v1.5.49 h1:V3pdyzGLGDMX4R/rbx+e7yo5nB9ticxCcCkQZMxCWwE= +github.com/xtaci/smux v1.5.49/go.mod h1:IGQ9QYrBphmb/4aTnLEcJby0TNr3NV+OslIOMrX825Q= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= @@ -247,12 +247,12 @@ golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= -google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY= -google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba h1:B14OtaXuMaCQsl2deSvNkyPKIzq3BjfxQp8d00QyWx4= +google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:G5IanEx8/PgI9w6CFcYQf7jMtHQhZruvfM1i3qOqk5U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/vendor/github.com/go-playground/validator/v10/README.md b/vendor/github.com/go-playground/validator/v10/README.md index 16b16d8dd..c6012b586 100644 --- a/vendor/github.com/go-playground/validator/v10/README.md +++ b/vendor/github.com/go-playground/validator/v10/README.md @@ -123,6 +123,7 @@ validate := validator.New(validator.WithRequiredStructEnabled()) | udp6_addr | User Datagram Protocol Address UDPv6 | | udp_addr | User Datagram Protocol Address UDP | | unix_addr | Unix domain socket end point Address | +| uds_exists | Unix domain socket exists (checks filesystem sockets and Linux abstract sockets) | | uri | URI String | | url | URL String | | http_url | HTTP(s) URL String | diff --git a/vendor/github.com/go-playground/validator/v10/baked_in.go b/vendor/github.com/go-playground/validator/v10/baked_in.go index e90c98e46..7fcc6737a 100644 --- a/vendor/github.com/go-playground/validator/v10/baked_in.go +++ b/vendor/github.com/go-playground/validator/v10/baked_in.go @@ -1,6 +1,7 @@ package validator import ( + "bufio" "bytes" "cmp" "context" @@ -15,6 +16,7 @@ import ( "net/url" "os" "reflect" + "runtime" "strconv" "strings" "sync" @@ -206,6 +208,7 @@ var ( "ip6_addr": isIP6AddrResolvable, "ip_addr": isIPAddrResolvable, "unix_addr": isUnixAddrResolvable, + "uds_exists": isUnixDomainSocketExists, "mac": isMAC, "hostname": isHostnameRFC952, // RFC 952 "hostname_rfc1123": isHostnameRFC1123, // RFC 1123 @@ -2611,6 +2614,70 @@ func isUnixAddrResolvable(fl FieldLevel) bool { return err == nil } +// isUnixDomainSocketExists is the validation function for validating if the field's value is an existing Unix domain socket. +// It handles both filesystem-based sockets and Linux abstract sockets. +// It always returns false for Windows. +func isUnixDomainSocketExists(fl FieldLevel) bool { + if runtime.GOOS == "windows" { + return false + } + + sockpath := fl.Field().String() + + if sockpath == "" { + return false + } + + // On Linux, check for abstract sockets (prefixed with @) + if runtime.GOOS == "linux" && strings.HasPrefix(sockpath, "@") { + return isAbstractSocketExists(sockpath) + } + + // For filesystem-based sockets, check if the path exists and is a socket + stats, err := os.Stat(sockpath) + if err != nil { + return false + } + + return stats.Mode().Type() == fs.ModeSocket +} + +// isAbstractSocketExists checks if a Linux abstract socket exists by reading /proc/net/unix. +// Abstract sockets are identified by an @ prefix in human-readable form. +func isAbstractSocketExists(sockpath string) bool { + file, err := os.Open("/proc/net/unix") + if err != nil { + return false + } + defer func() { + _ = file.Close() + }() + + scanner := bufio.NewScanner(file) + + // Skip the header line + if !scanner.Scan() { + return false + } + + // Abstract sockets in /proc/net/unix are represented with @ prefix + // The socket path is the last field in each line + for scanner.Scan() { + line := scanner.Text() + fields := strings.Fields(line) + + // The path is the last field (8th field typically) + if len(fields) >= 8 { + path := fields[len(fields)-1] + if path == sockpath { + return true + } + } + } + + return false +} + func isIP4Addr(fl FieldLevel) bool { val := fl.Field().String() diff --git a/vendor/github.com/go-playground/validator/v10/cache.go b/vendor/github.com/go-playground/validator/v10/cache.go index fb101b064..ab7ffd47f 100644 --- a/vendor/github.com/go-playground/validator/v10/cache.go +++ b/vendor/github.com/go-playground/validator/v10/cache.go @@ -289,6 +289,24 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s if wrapper, ok := v.validations[current.tag]; ok { current.fn = wrapper.fn current.runValidationWhenNil = wrapper.runValidationOnNil + } else if aliasTag, isAlias := v.aliases[current.tag]; isAlias { + aliasFirst, aliasLast := v.parseFieldTagsRecursive(aliasTag, fieldName, current.tag, true) + + current.tag = aliasFirst.tag + current.fn = aliasFirst.fn + current.runValidationWhenNil = aliasFirst.runValidationWhenNil + current.hasParam = aliasFirst.hasParam + current.param = aliasFirst.param + current.typeof = aliasFirst.typeof + current.hasAlias = true + + if aliasFirst.next != nil { + nextInChain := current.next + current.next = aliasFirst.next + aliasLast.next = nextInChain + aliasLast.isBlockEnd = false + current = aliasLast + } } else { panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, current.tag, fieldName))) } diff --git a/vendor/github.com/go-playground/validator/v10/country_codes.go b/vendor/github.com/go-playground/validator/v10/country_codes.go index b5f10d3c1..a9330c808 100644 --- a/vendor/github.com/go-playground/validator/v10/country_codes.go +++ b/vendor/github.com/go-playground/validator/v10/country_codes.go @@ -258,7 +258,7 @@ var iso3166_2 = map[string]struct{}{ "BD-56": {}, "BD-57": {}, "BD-58": {}, "BD-59": {}, "BD-60": {}, "BD-61": {}, "BD-62": {}, "BD-63": {}, "BD-64": {}, "BD-A": {}, "BD-B": {}, "BD-C": {}, "BD-D": {}, "BD-E": {}, "BD-F": {}, - "BD-G": {}, "BE-BRU": {}, "BE-VAN": {}, "BE-VBR": {}, "BE-VLG": {}, + "BD-G": {}, "BD-H": {}, "BE-BRU": {}, "BE-VAN": {}, "BE-VBR": {}, "BE-VLG": {}, "BE-VLI": {}, "BE-VOV": {}, "BE-VWV": {}, "BE-WAL": {}, "BE-WBR": {}, "BE-WHT": {}, "BE-WLG": {}, "BE-WLX": {}, "BE-WNA": {}, "BF-01": {}, "BF-02": {}, "BF-03": {}, "BF-04": {}, "BF-05": {}, "BF-06": {}, @@ -573,7 +573,7 @@ var iso3166_2 = map[string]struct{}{ "ID-KB": {}, "ID-KI": {}, "ID-KU": {}, "ID-KR": {}, "ID-KS": {}, "ID-KT": {}, "ID-LA": {}, "ID-MA": {}, "ID-ML": {}, "ID-MU": {}, "ID-NB": {}, "ID-NT": {}, "ID-NU": {}, "ID-PA": {}, "ID-PB": {}, - "ID-PE": {}, "ID-PP": {}, "ID-PS": {}, "ID-PT": {}, "ID-RI": {}, + "ID-PD": {}, "ID-PE": {}, "ID-PP": {}, "ID-PS": {}, "ID-PT": {}, "ID-RI": {}, "ID-SA": {}, "ID-SB": {}, "ID-SG": {}, "ID-SL": {}, "ID-SM": {}, "ID-SN": {}, "ID-SR": {}, "ID-SS": {}, "ID-ST": {}, "ID-SU": {}, "ID-YO": {}, "IE-C": {}, "IE-CE": {}, "IE-CN": {}, "IE-CO": {}, @@ -587,7 +587,7 @@ var iso3166_2 = map[string]struct{}{ "IN-AS": {}, "IN-BR": {}, "IN-CH": {}, "IN-CT": {}, "IN-DH": {}, "IN-DL": {}, "IN-DN": {}, "IN-GA": {}, "IN-GJ": {}, "IN-HP": {}, "IN-HR": {}, "IN-JH": {}, "IN-JK": {}, "IN-KA": {}, "IN-KL": {}, - "IN-LD": {}, "IN-MH": {}, "IN-ML": {}, "IN-MN": {}, "IN-MP": {}, + "IN-LA": {}, "IN-LD": {}, "IN-MH": {}, "IN-ML": {}, "IN-MN": {}, "IN-MP": {}, "IN-MZ": {}, "IN-NL": {}, "IN-TG": {}, "IN-OR": {}, "IN-PB": {}, "IN-PY": {}, "IN-RJ": {}, "IN-SK": {}, "IN-TN": {}, "IN-TR": {}, "IN-UP": {}, "IN-UT": {}, "IN-WB": {}, "IQ-AN": {}, "IQ-AR": {}, "IQ-BA": {}, @@ -667,7 +667,7 @@ var iso3166_2 = map[string]struct{}{ "KP-08": {}, "KP-09": {}, "KP-10": {}, "KP-13": {}, "KR-11": {}, "KR-26": {}, "KR-27": {}, "KR-28": {}, "KR-29": {}, "KR-30": {}, "KR-31": {}, "KR-41": {}, "KR-42": {}, "KR-43": {}, "KR-44": {}, - "KR-45": {}, "KR-46": {}, "KR-47": {}, "KR-48": {}, "KR-49": {}, + "KR-45": {}, "KR-46": {}, "KR-47": {}, "KR-48": {}, "KR-49": {}, "KR-50": {}, "KW-AH": {}, "KW-FA": {}, "KW-HA": {}, "KW-JA": {}, "KW-KU": {}, "KW-MU": {}, "KZ-10": {}, "KZ-75": {}, "KZ-19": {}, "KZ-11": {}, "KZ-15": {}, "KZ-71": {}, "KZ-23": {}, "KZ-27": {}, "KZ-47": {}, @@ -758,7 +758,7 @@ var iso3166_2 = map[string]struct{}{ "ME-02": {}, "ME-03": {}, "ME-04": {}, "ME-05": {}, "ME-06": {}, "ME-07": {}, "ME-08": {}, "ME-09": {}, "ME-10": {}, "ME-11": {}, "ME-12": {}, "ME-13": {}, "ME-14": {}, "ME-15": {}, "ME-16": {}, - "ME-17": {}, "ME-18": {}, "ME-19": {}, "ME-20": {}, "ME-21": {}, "ME-24": {}, + "ME-17": {}, "ME-18": {}, "ME-19": {}, "ME-20": {}, "ME-21": {}, "ME-22": {}, "ME-23": {}, "ME-24": {}, "ME-25": {}, "MG-A": {}, "MG-D": {}, "MG-F": {}, "MG-M": {}, "MG-T": {}, "MG-U": {}, "MH-ALK": {}, "MH-ALL": {}, "MH-ARN": {}, "MH-AUR": {}, "MH-EBO": {}, "MH-ENI": {}, "MH-JAB": {}, "MH-JAL": {}, "MH-KIL": {}, @@ -856,7 +856,7 @@ var iso3166_2 = map[string]struct{}{ "NO-22": {}, "NP-1": {}, "NP-2": {}, "NP-3": {}, "NP-4": {}, "NP-5": {}, "NP-BA": {}, "NP-BH": {}, "NP-DH": {}, "NP-GA": {}, "NP-JA": {}, "NP-KA": {}, "NP-KO": {}, "NP-LU": {}, "NP-MA": {}, - "NP-ME": {}, "NP-NA": {}, "NP-RA": {}, "NP-SA": {}, "NP-SE": {}, + "NP-ME": {}, "NP-NA": {}, "NP-P1": {}, "NP-P2": {}, "NP-P3": {}, "NP-P4": {}, "NP-P5": {}, "NP-P6": {}, "NP-P7": {}, "NP-RA": {}, "NP-SA": {}, "NP-SE": {}, "NR-01": {}, "NR-02": {}, "NR-03": {}, "NR-04": {}, "NR-05": {}, "NR-06": {}, "NR-07": {}, "NR-08": {}, "NR-09": {}, "NR-10": {}, "NR-11": {}, "NR-12": {}, "NR-13": {}, "NR-14": {}, "NZ-AUK": {}, diff --git a/vendor/github.com/go-playground/validator/v10/doc.go b/vendor/github.com/go-playground/validator/v10/doc.go index 612bcf555..7b9e77c65 100644 --- a/vendor/github.com/go-playground/validator/v10/doc.go +++ b/vendor/github.com/go-playground/validator/v10/doc.go @@ -201,6 +201,15 @@ only for the nil-values). Usage: omitnil +# Omit Zero + +Allows to skip the validation if the value is a zero value. +For pointers, it checks if the pointer is nil or the underlying value is a zero value. +For slices and maps, it checks if the value is nil or empty. +Otherwise, behaves the same as omitempty. + + Usage: omitzero + # Dive This tells the validator to dive into a slice, array or map and validate that @@ -1269,6 +1278,15 @@ This validates that a string value contains a valid Unix Address. Usage: unix_addr +# Unix Domain Socket Exists + +This validates that a Unix domain socket file exists at the specified path. +It checks both filesystem-based sockets and Linux abstract sockets (prefixed with @). +For filesystem sockets, it verifies the path exists and is a socket file. +For abstract sockets on Linux, it checks /proc/net/unix. + + Usage: uds_exists + # Media Access Control Address MAC This validates that a string value contains a valid MAC Address. diff --git a/vendor/github.com/go-playground/validator/v10/regexes.go b/vendor/github.com/go-playground/validator/v10/regexes.go index 6b564b6f9..5cf063534 100644 --- a/vendor/github.com/go-playground/validator/v10/regexes.go +++ b/vendor/github.com/go-playground/validator/v10/regexes.go @@ -21,7 +21,7 @@ const ( hslRegexString = "^hsl\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*\\)$" hslaRegexString = "^hsla\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$" emailRegexString = "^(?:(?:(?:(?:[a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(?:\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|(?:(?:\\x22)(?:(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(?:\\x20|\\x09)+)?(?:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(\\x20|\\x09)+)?(?:\\x22))))@(?:(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$" - e164RegexString = "^\\+?[1-9]\\d{1,14}$" + e164RegexString = "^\\+?[1-9]\\d{7,14}$" base32RegexString = "^(?:[A-Z2-7]{8})*(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}=|[A-Z2-7]{8})$" base64RegexString = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$" base64URLRegexString = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2}==|[A-Za-z0-9-_]{3}=|[A-Za-z0-9-_]{4})$" diff --git a/vendor/github.com/go-playground/validator/v10/util.go b/vendor/github.com/go-playground/validator/v10/util.go index b1fd8cc11..b74961efd 100644 --- a/vendor/github.com/go-playground/validator/v10/util.go +++ b/vendor/github.com/go-playground/validator/v10/util.go @@ -214,7 +214,9 @@ BEGIN: } // if got here there was more namespace, cannot go any deeper - panic("Invalid field namespace") + // return found=false instead of panicking to handle cases like ValidateMap + // where cross-field validators (required_if, etc.) can't navigate non-struct parents + return } // asInt returns the parameter as an int64 diff --git a/vendor/github.com/goccy/go-yaml/ast/ast.go b/vendor/github.com/goccy/go-yaml/ast/ast.go index ca1505381..a8078a5f5 100644 --- a/vendor/github.com/goccy/go-yaml/ast/ast.go +++ b/vendor/github.com/goccy/go-yaml/ast/ast.go @@ -1623,7 +1623,11 @@ func (n *SequenceNode) flowStyleString() string { for _, value := range n.Values { values = append(values, value.String()) } - return fmt.Sprintf("[%s]", strings.Join(values, ", ")) + seqText := fmt.Sprintf("[%s]", strings.Join(values, ", ")) + if n.Comment != nil { + return addCommentString(seqText, n.Comment) + } + return seqText } func (n *SequenceNode) blockStyleString() string { diff --git a/vendor/github.com/goccy/go-yaml/decode.go b/vendor/github.com/goccy/go-yaml/decode.go index 43c317f8f..d490add63 100644 --- a/vendor/github.com/goccy/go-yaml/decode.go +++ b/vendor/github.com/goccy/go-yaml/decode.go @@ -288,7 +288,9 @@ func (d *Decoder) addSequenceNodeCommentToMap(node *ast.SequenceNode) { texts = append(texts, comment.Token.Value) } if len(texts) != 0 { - d.addCommentToMap(node.Values[0].GetPath(), HeadComment(texts...)) + if len(node.Values) != 0 { + d.addCommentToMap(node.Values[0].GetPath(), HeadComment(texts...)) + } } } } @@ -1750,14 +1752,11 @@ func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node return err } } else { - keyVal, err := d.nodeToValue(ctx, key) + keyVal, err := d.createDecodedNewValue(ctx, keyType, reflect.Value{}, key) if err != nil { return err } - k = reflect.ValueOf(keyVal) - if k.IsValid() && k.Type().ConvertibleTo(keyType) { - k = k.Convert(keyType) - } + k = keyVal } if k.IsValid() { diff --git a/vendor/github.com/goccy/go-yaml/internal/format/format.go b/vendor/github.com/goccy/go-yaml/internal/format/format.go index 2d55652ff..461dc36d2 100644 --- a/vendor/github.com/goccy/go-yaml/internal/format/format.go +++ b/vendor/github.com/goccy/go-yaml/internal/format/format.go @@ -351,8 +351,9 @@ func (f *Formatter) formatMapping(n *ast.MappingNode) string { var ret string if n.IsFlowStyle { ret = f.origin(n.Start) + } else { + ret += f.formatCommentGroup(n.Comment) } - ret += f.formatCommentGroup(n.Comment) for _, value := range n.Values { if value.CollectEntry != nil { ret += f.origin(value.CollectEntry) @@ -361,6 +362,7 @@ func (f *Formatter) formatMapping(n *ast.MappingNode) string { } if n.IsFlowStyle { ret += f.origin(n.End) + ret += f.formatCommentGroup(n.Comment) } return ret } @@ -377,8 +379,7 @@ func (f *Formatter) formatSequence(n *ast.SequenceNode) string { var ret string if n.IsFlowStyle { ret = f.origin(n.Start) - } - if n.Comment != nil { + } else { // add head comment. ret += f.formatCommentGroup(n.Comment) } @@ -387,6 +388,7 @@ func (f *Formatter) formatSequence(n *ast.SequenceNode) string { } if n.IsFlowStyle { ret += f.origin(n.End) + ret += f.formatCommentGroup(n.Comment) } ret += f.formatCommentGroup(n.FootComment) return ret diff --git a/vendor/github.com/goccy/go-yaml/parser/parser.go b/vendor/github.com/goccy/go-yaml/parser/parser.go index 2c79d3690..f5bfd1a96 100644 --- a/vendor/github.com/goccy/go-yaml/parser/parser.go +++ b/vendor/github.com/goccy/go-yaml/parser/parser.go @@ -426,6 +426,11 @@ func (p *parser) parseFlowMap(ctx *context) (*ast.MappingNode, error) { if node.End == nil { return nil, errors.ErrSyntax("could not find flow mapping end token '}'", node.Start) } + + // set line comment if exists. e.g.) } # comment + if err := setLineComment(ctx, node, ctx.currentToken()); err != nil { + return nil, err + } ctx.goNext() // skip mapping end token. return node, nil } @@ -1066,6 +1071,11 @@ func (p *parser) parseFlowSequence(ctx *context) (*ast.SequenceNode, error) { if node.End == nil { return nil, errors.ErrSyntax("sequence end token ']' not found", node.Start) } + + // set line comment if exists. e.g.) ] # comment + if err := setLineComment(ctx, node, ctx.currentToken()); err != nil { + return nil, err + } ctx.goNext() // skip sequence end token. return node, nil } diff --git a/vendor/github.com/quic-go/quic-go/README.md b/vendor/github.com/quic-go/quic-go/README.md index 53bbf4a0a..85751dbe7 100644 --- a/vendor/github.com/quic-go/quic-go/README.md +++ b/vendor/github.com/quic-go/quic-go/README.md @@ -1,6 +1,9 @@ +
+
[](https://quic-go.net/docs/)
[](https://pkg.go.dev/github.com/quic-go/quic-go)
@@ -52,3 +55,7 @@ quic-go always aims to support the latest two Go releases.
## Contributing
We are always happy to welcome new contributors! We have a number of self-contained issues that are suitable for first-time contributors, they are tagged with [help wanted](https://github.com/quic-go/quic-go/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). If you have any questions, please feel free to reach out by opening an issue or leaving a comment.
+
+## License
+
+The code is licensed under the MIT license. The logo and brand assets are excluded from the MIT license. See [assets/LICENSE.md](https://github.com/quic-go/quic-go/tree/master/assets/LICENSE.md) for the full usage policy and details.
diff --git a/vendor/github.com/quic-go/quic-go/connection.go b/vendor/github.com/quic-go/quic-go/connection.go
index faf9f1101..e300e938e 100644
--- a/vendor/github.com/quic-go/quic-go/connection.go
+++ b/vendor/github.com/quic-go/quic-go/connection.go
@@ -57,6 +57,11 @@ type receivedPacket struct {
info packetInfo // only valid if the contained IP address is valid
}
+type receivedPacketWithDatagramID struct {
+ receivedPacket
+ datagramID qlog.DatagramID
+}
+
func (p *receivedPacket) Size() protocol.ByteCount { return protocol.ByteCount(len(p.data)) }
func (p *receivedPacket) Clone() *receivedPacket {
@@ -183,8 +188,8 @@ type Conn struct {
ctxCancel context.CancelCauseFunc
handshakeCompleteChan chan struct{}
- undecryptablePackets []receivedPacket // undecryptable packets, waiting for a change in encryption level
- undecryptablePacketsToProcess []receivedPacket
+ undecryptablePackets []receivedPacketWithDatagramID // undecryptable packets, waiting for a change in encryption level
+ undecryptablePacketsToProcess []receivedPacketWithDatagramID
earlyConnReadyChan chan struct{}
sentFirstPacket bool
@@ -308,13 +313,14 @@ var newConnection = func(
)
s.preSetup()
s.rttStats.SetInitialRTT(rtt)
- s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler(
+ s.sentPacketHandler = ackhandler.NewSentPacketHandler(
0,
protocol.ByteCount(s.config.InitialPacketSize),
s.rttStats,
&s.connStats,
clientAddressValidated,
s.conn.capabilities().ECN,
+ s.receivedPacketHandler.IgnorePacketsBelow,
s.perspective,
s.qlogger,
s.logger,
@@ -365,7 +371,7 @@ var newConnection = func(
s.version,
)
s.cryptoStreamHandler = cs
- s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, s.initialStream, s.handshakeStream, s.sentPacketHandler, s.retransmissionQueue, cs, s.framer, s.receivedPacketHandler, s.datagramQueue, s.perspective)
+ s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, s.initialStream, s.handshakeStream, s.sentPacketHandler, s.retransmissionQueue, cs, s.framer, &s.receivedPacketHandler, s.datagramQueue, s.perspective)
s.unpacker = newPacketUnpacker(cs, s.srcConnIDLen)
s.cryptoStreamManager = newCryptoStreamManager(s.initialStream, s.handshakeStream, s.oneRTTStream)
return &wrappedConn{Conn: s}
@@ -436,13 +442,14 @@ var newClientConnection = func(
)
s.ctx, s.ctxCancel = context.WithCancelCause(ctx)
s.preSetup()
- s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler(
+ s.sentPacketHandler = ackhandler.NewSentPacketHandler(
initialPacketNumber,
protocol.ByteCount(s.config.InitialPacketSize),
s.rttStats,
&s.connStats,
false, // has no effect
s.conn.capabilities().ECN,
+ s.receivedPacketHandler.IgnorePacketsBelow,
s.perspective,
s.qlogger,
s.logger,
@@ -490,7 +497,7 @@ var newClientConnection = func(
s.cryptoStreamHandler = cs
s.cryptoStreamManager = newCryptoStreamManager(s.initialStream, s.handshakeStream, oneRTTStream)
s.unpacker = newPacketUnpacker(cs, s.srcConnIDLen)
- s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, s.initialStream, s.handshakeStream, s.sentPacketHandler, s.retransmissionQueue, cs, s.framer, s.receivedPacketHandler, s.datagramQueue, s.perspective)
+ s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, s.initialStream, s.handshakeStream, s.sentPacketHandler, s.retransmissionQueue, cs, s.framer, &s.receivedPacketHandler, s.datagramQueue, s.perspective)
if len(tlsConf.ServerName) > 0 {
s.tokenStoreKey = tlsConf.ServerName
} else {
@@ -550,6 +557,8 @@ func (c *Conn) preSetup() {
c.lastPacketReceivedTime = now
c.creationTime = now
+ c.receivedPacketHandler = *ackhandler.NewReceivedPacketHandler(c.logger)
+
c.datagramQueue = newDatagramQueue(c.scheduleSending, c.logger)
c.connState.Version = c.version
}
@@ -615,7 +624,7 @@ runLoop:
queue := c.undecryptablePacketsToProcess
c.undecryptablePacketsToProcess = nil
for _, p := range queue {
- processed, err := c.handleOnePacket(p)
+ processed, err := c.handleOnePacket(p.receivedPacket, p.datagramID)
if err != nil {
c.setCloseError(&closeError{err: err})
break runLoop
@@ -986,41 +995,48 @@ func (c *Conn) handleHandshakeConfirmed(now monotime.Time) error {
return nil
}
+const maxPacketsToProcess = 32
+
func (c *Conn) handlePackets() (wasProcessed bool, _ error) {
- // Now process all packets in the receivedPackets channel.
- // Limit the number of packets to the length of the receivedPackets channel,
+ // Process packets from the receivedPackets queue.
+ // Limit the number of packets to process to maxPacketsToProcess,
// so we eventually get a chance to send out an ACK when receiving a lot of packets.
c.receivedPacketMx.Lock()
- numPackets := c.receivedPackets.Len()
- if numPackets == 0 {
+
+ if c.receivedPackets.Empty() {
c.receivedPacketMx.Unlock()
return false, nil
}
var hasMorePackets bool
- for i := 0; i < numPackets; i++ {
- if i > 0 {
- c.receivedPacketMx.Lock()
- }
+ for range maxPacketsToProcess {
p := c.receivedPackets.PopFront()
- hasMorePackets = !c.receivedPackets.Empty()
c.receivedPacketMx.Unlock()
- processed, err := c.handleOnePacket(p)
+ var datagramID qlog.DatagramID
+ if c.qlogger != nil && wire.IsLongHeaderPacket(p.data[0]) {
+ datagramID = qlog.CalculateDatagramID(p.data)
+ }
+ processed, err := c.handleOnePacket(p, datagramID)
if err != nil {
return false, err
}
if processed {
wasProcessed = true
}
+ c.receivedPacketMx.Lock()
+ hasMorePackets = !c.receivedPackets.Empty()
if !hasMorePackets {
break
}
- // only process a single packet at a time before handshake completion
- if !c.handshakeComplete {
+ // Prioritize sending of new CRYPTO data.
+ // This is especially relevant when processing 0-RTT packets.
+ if !c.handshakeComplete && (c.initialStream.HasData() || c.handshakeStream.HasData()) {
break
}
}
+ c.receivedPacketMx.Unlock()
+
if hasMorePackets {
select {
case c.notifyReceivedPacket <- struct{}{}:
@@ -1030,12 +1046,11 @@ func (c *Conn) handlePackets() (wasProcessed bool, _ error) {
return wasProcessed, nil
}
-func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
+func (c *Conn) handleOnePacket(rp receivedPacket, datagramID qlog.DatagramID) (wasProcessed bool, _ error) {
c.sentPacketHandler.ReceivedBytes(rp.Size(), rp.rcvTime)
if wire.IsVersionNegotiationPacket(rp.data) {
- c.handleVersionNegotiationPacket(rp)
- return false, nil
+ return false, c.handleVersionNegotiationPacket(rp)
}
var counter uint8
@@ -1051,8 +1066,9 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
if err != nil {
if c.qlogger != nil {
c.qlogger.RecordEvent(qlog.PacketDropped{
- Raw: qlog.RawInfo{Length: len(data)},
- Trigger: qlog.PacketDropHeaderParseError,
+ Raw: qlog.RawInfo{Length: len(data)},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropHeaderParseError,
})
}
c.logger.Debugf("error parsing packet, couldn't parse connection ID: %s", err)
@@ -1061,9 +1077,10 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
if destConnID != lastConnID {
if c.qlogger != nil {
c.qlogger.RecordEvent(qlog.PacketDropped{
- Header: qlog.PacketHeader{DestConnectionID: destConnID},
- Raw: qlog.RawInfo{Length: len(data)},
- Trigger: qlog.PacketDropUnknownConnectionID,
+ Header: qlog.PacketHeader{DestConnectionID: destConnID},
+ Raw: qlog.RawInfo{Length: len(data)},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropUnknownConnectionID,
})
}
c.logger.Debugf("coalesced packet has different destination connection ID: %s, expected %s", destConnID, lastConnID)
@@ -1077,14 +1094,16 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
if c.qlogger != nil {
if err == wire.ErrUnsupportedVersion {
c.qlogger.RecordEvent(qlog.PacketDropped{
- Header: qlog.PacketHeader{Version: hdr.Version},
- Raw: qlog.RawInfo{Length: len(data)},
- Trigger: qlog.PacketDropUnsupportedVersion,
+ Header: qlog.PacketHeader{Version: hdr.Version},
+ Raw: qlog.RawInfo{Length: len(data)},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropUnsupportedVersion,
})
} else {
c.qlogger.RecordEvent(qlog.PacketDropped{
- Raw: qlog.RawInfo{Length: len(data)},
- Trigger: qlog.PacketDropHeaderParseError,
+ Raw: qlog.RawInfo{Length: len(data)},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropHeaderParseError,
})
}
}
@@ -1096,8 +1115,9 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
if hdr.Version != c.version {
if c.qlogger != nil {
c.qlogger.RecordEvent(qlog.PacketDropped{
- Raw: qlog.RawInfo{Length: len(data)},
- Trigger: qlog.PacketDropUnexpectedVersion,
+ Raw: qlog.RawInfo{Length: len(data)},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropUnexpectedVersion,
})
}
c.logger.Debugf("Dropping packet with version %x. Expected %x.", hdr.Version, c.version)
@@ -1116,7 +1136,7 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
p.data = packetData
- processed, err := c.handleLongHeaderPacket(p, hdr)
+ processed, err := c.handleLongHeaderPacket(p, hdr, datagramID)
if err != nil {
return false, err
}
@@ -1128,7 +1148,7 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
if counter > 0 {
p.buffer.Split()
}
- processed, err := c.handleShortHeaderPacket(p, counter > 0)
+ processed, err := c.handleShortHeaderPacket(p, counter > 0, datagramID)
if err != nil {
return false, err
}
@@ -1144,7 +1164,11 @@ func (c *Conn) handleOnePacket(rp receivedPacket) (wasProcessed bool, _ error) {
return wasProcessed, nil
}
-func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasProcessed bool, _ error) {
+func (c *Conn) handleShortHeaderPacket(
+ p receivedPacket,
+ isCoalesced bool,
+ datagramID qlog.DatagramID, // only for logging
+) (wasProcessed bool, _ error) {
var wasQueued bool
defer func() {
@@ -1161,8 +1185,9 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
PacketType: qlog.PacketType1RTT,
PacketNumber: protocol.InvalidPacketNumber,
},
- Raw: qlog.RawInfo{Length: len(p.data)},
- Trigger: qlog.PacketDropHeaderParseError,
+ Raw: qlog.RawInfo{Length: len(p.data)},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropHeaderParseError,
})
return false, nil
}
@@ -1179,7 +1204,7 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
return false, &StatelessResetError{}
}
}
- wasQueued, err = c.handleUnpackError(err, p, qlog.PacketType1RTT)
+ wasQueued, err = c.handleUnpackError(err, p, qlog.PacketType1RTT, datagramID)
return false, err
}
c.largestRcvdAppData = max(c.largestRcvdAppData, pn)
@@ -1197,8 +1222,9 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
PacketType: qlog.PacketType1RTT,
PacketNumber: pn,
},
- Raw: qlog.RawInfo{Length: int(p.Size())},
- Trigger: qlog.PacketDropDuplicate,
+ Raw: qlog.RawInfo{Length: int(p.Size())},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropDuplicate,
})
}
return false, nil
@@ -1218,8 +1244,9 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
Length: int(p.Size()),
PayloadLength: int(p.Size() - wire.ShortHeaderLen(destConnID, pnLen)),
},
- Frames: frames,
- ECN: toQlogECN(p.ecn),
+ DatagramID: datagramID,
+ Frames: frames,
+ ECN: toQlogECN(p.ecn),
})
}
}
@@ -1251,7 +1278,7 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
return true, err
}
c.logger.Debugf("sending path probe packet to %s", p.remoteAddr)
- c.logShortHeaderPacket(probe.DestConnID, probe.Ack, probe.Frames, probe.StreamFrames, probe.PacketNumber, probe.PacketNumberLen, probe.KeyPhase, protocol.ECNNon, buf.Len(), false)
+ c.logShortHeaderPacketWithDatagramID(probe, protocol.ECNNon, buf.Len(), false, datagramID)
c.registerPackedShortHeaderPacket(probe, protocol.ECNNon, p.rcvTime)
c.sendQueue.SendProbe(buf, p.remoteAddr)
}
@@ -1275,7 +1302,7 @@ func (c *Conn) handleShortHeaderPacket(p receivedPacket, isCoalesced bool) (wasP
return true, nil
}
-func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasProcessed bool, _ error) {
+func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header, datagramID qlog.DatagramID) (wasProcessed bool, _ error) {
var wasQueued bool
defer func() {
@@ -1298,8 +1325,9 @@ func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasPr
PacketType: qlog.PacketTypeInitial,
PacketNumber: protocol.InvalidPacketNumber,
},
- Raw: qlog.RawInfo{Length: int(p.Size())},
- Trigger: qlog.PacketDropUnknownConnectionID,
+ Raw: qlog.RawInfo{Length: int(p.Size())},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropUnknownConnectionID,
})
}
c.logger.Debugf("Dropping Initial packet (%d bytes) with unexpected source connection ID: %s (expected %s)", p.Size(), hdr.SrcConnectionID, c.handshakeDestConnID)
@@ -1313,8 +1341,9 @@ func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasPr
PacketType: qlog.PacketType0RTT,
PacketNumber: protocol.InvalidPacketNumber,
},
- Raw: qlog.RawInfo{Length: int(p.Size())},
- Trigger: qlog.PacketDropUnexpectedPacket,
+ Raw: qlog.RawInfo{Length: int(p.Size())},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropUnexpectedPacket,
})
}
return false, nil
@@ -1322,7 +1351,7 @@ func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasPr
packet, err := c.unpacker.UnpackLongHeader(hdr, p.data)
if err != nil {
- wasQueued, err = c.handleUnpackError(err, p, toQlogPacketType(hdr.Type))
+ wasQueued, err = c.handleUnpackError(err, p, toQlogPacketType(hdr.Type), datagramID)
return false, err
}
@@ -1342,20 +1371,21 @@ func (c *Conn) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) (wasPr
PacketNumber: pn,
Version: packet.hdr.Version,
},
- Raw: qlog.RawInfo{Length: int(p.Size()), PayloadLength: int(packet.hdr.Length)},
- Trigger: qlog.PacketDropDuplicate,
+ Raw: qlog.RawInfo{Length: int(p.Size()), PayloadLength: int(packet.hdr.Length)},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropDuplicate,
})
}
return false, nil
}
- if err := c.handleUnpackedLongHeaderPacket(packet, p.ecn, p.rcvTime, p.Size()); err != nil {
+ if err := c.handleUnpackedLongHeaderPacket(packet, p.ecn, p.rcvTime, datagramID, p.Size()); err != nil {
return false, err
}
return true, nil
}
-func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType) (wasQueued bool, _ error) {
+func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType, datagramID qlog.DatagramID) (wasQueued bool, _ error) {
switch err {
case handshake.ErrKeysDropped:
if c.qlogger != nil {
@@ -1366,8 +1396,9 @@ func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType
DestConnectionID: connID,
PacketNumber: protocol.InvalidPacketNumber,
},
- Raw: qlog.RawInfo{Length: int(p.Size())},
- Trigger: qlog.PacketDropKeyUnavailable,
+ Raw: qlog.RawInfo{Length: int(p.Size())},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropKeyUnavailable,
})
}
c.logger.Debugf("Dropping %s packet (%d bytes) because we already dropped the keys.", pt, p.Size())
@@ -1375,7 +1406,7 @@ func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType
case handshake.ErrKeysNotYetAvailable:
// Sealer for this encryption level not yet available.
// Try again later.
- c.tryQueueingUndecryptablePacket(p, pt)
+ c.tryQueueingUndecryptablePacket(p, pt, datagramID)
return true, nil
case wire.ErrInvalidReservedBits:
return false, &qerr.TransportError{
@@ -1392,8 +1423,9 @@ func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType
DestConnectionID: connID,
PacketNumber: protocol.InvalidPacketNumber,
},
- Raw: qlog.RawInfo{Length: int(p.Size())},
- Trigger: qlog.PacketDropPayloadDecryptError,
+ Raw: qlog.RawInfo{Length: int(p.Size())},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropPayloadDecryptError,
})
}
c.logger.Debugf("Dropping %s packet (%d bytes) that could not be unpacked. Error: %s", pt, p.Size(), err)
@@ -1410,8 +1442,9 @@ func (c *Conn) handleUnpackError(err error, p receivedPacket, pt qlog.PacketType
DestConnectionID: connID,
PacketNumber: protocol.InvalidPacketNumber,
},
- Raw: qlog.RawInfo{Length: int(p.Size())},
- Trigger: qlog.PacketDropHeaderParseError,
+ Raw: qlog.RawInfo{Length: int(p.Size())},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropHeaderParseError,
})
}
c.logger.Debugf("Dropping %s packet (%d bytes) for which we couldn't unpack the header. Error: %s", pt, p.Size(), err)
@@ -1529,7 +1562,7 @@ func (c *Conn) handleRetryPacket(hdr *wire.Header, data []byte, rcvTime monotime
return true
}
-func (c *Conn) handleVersionNegotiationPacket(p receivedPacket) {
+func (c *Conn) handleVersionNegotiationPacket(p receivedPacket) error {
if c.perspective == protocol.PerspectiveServer || // servers never receive version negotiation packets
c.receivedFirstPacket || c.versionNegotiated { // ignore delayed / duplicated version negotiation packets
if c.qlogger != nil {
@@ -1539,7 +1572,7 @@ func (c *Conn) handleVersionNegotiationPacket(p receivedPacket) {
Trigger: qlog.PacketDropUnexpectedPacket,
})
}
- return
+ return nil
}
src, dest, supportedVersions, err := wire.ParseVersionNegotiationPacket(p.data)
@@ -1552,7 +1585,7 @@ func (c *Conn) handleVersionNegotiationPacket(p receivedPacket) {
})
}
c.logger.Debugf("Error parsing Version Negotiation packet: %s", err)
- return
+ return nil
}
if slices.Contains(supportedVersions, c.version) {
@@ -1565,7 +1598,7 @@ func (c *Conn) handleVersionNegotiationPacket(p receivedPacket) {
}
// The Version Negotiation packet contains the version that we offered.
// This might be a packet sent by an attacker, or it was corrupted.
- return
+ return nil
}
c.logger.Infof("Received a Version Negotiation packet. Supported Versions: %s", supportedVersions)
@@ -1585,7 +1618,7 @@ func (c *Conn) handleVersionNegotiationPacket(p receivedPacket) {
Theirs: supportedVersions,
})
c.logger.Infof("No compatible QUIC version found.")
- return
+ return nil
}
if c.qlogger != nil {
c.qlogger.RecordEvent(qlog.VersionInformation{
@@ -1597,16 +1630,17 @@ func (c *Conn) handleVersionNegotiationPacket(p receivedPacket) {
c.logger.Infof("Switching to QUIC version %s.", newVersion)
nextPN, _ := c.sentPacketHandler.PeekPacketNumber(protocol.EncryptionInitial)
- c.destroyImpl(&errCloseForRecreating{
+ return &errCloseForRecreating{
nextPacketNumber: nextPN,
nextVersion: newVersion,
- })
+ }
}
func (c *Conn) handleUnpackedLongHeaderPacket(
packet *unpackedPacket,
ecn protocol.ECN,
rcvTime monotime.Time,
+ datagramID qlog.DatagramID, // only for logging
packetSize protocol.ByteCount, // only for logging
) error {
if !c.receivedFirstPacket {
@@ -1692,8 +1726,9 @@ func (c *Conn) handleUnpackedLongHeaderPacket(
Length: int(packetSize),
PayloadLength: int(packet.hdr.Length),
},
- Frames: frames,
- ECN: toQlogECN(ecn),
+ DatagramID: datagramID,
+ Frames: frames,
+ ECN: toQlogECN(ecn),
})
}
}
@@ -1701,6 +1736,7 @@ func (c *Conn) handleUnpackedLongHeaderPacket(
if err != nil {
return err
}
+ c.sentPacketHandler.ReceivedPacket(packet.encryptionLevel, rcvTime)
return c.receivedPacketHandler.ReceivedPacket(packet.hdr.PacketNumber, ecn, packet.encryptionLevel, rcvTime, isAckEliciting)
}
@@ -1720,6 +1756,7 @@ func (c *Conn) handleUnpackedShortHeaderPacket(
if err != nil {
return false, nil, err
}
+ c.sentPacketHandler.ReceivedPacket(protocol.Encryption1RTT, rcvTime)
if err := c.receivedPacketHandler.ReceivedPacket(pn, ecn, protocol.Encryption1RTT, rcvTime, isAckEliciting); err != nil {
return false, nil, err
}
@@ -1916,9 +1953,14 @@ func (c *Conn) handlePacket(p receivedPacket) {
// the channel size, protocol.MaxConnUnprocessedPackets
if c.receivedPackets.Len() >= protocol.MaxConnUnprocessedPackets {
if c.qlogger != nil {
+ var datagramID qlog.DatagramID
+ if wire.IsLongHeaderPacket(p.data[0]) {
+ datagramID = qlog.CalculateDatagramID(p.data)
+ }
c.qlogger.RecordEvent(qlog.PacketDropped{
- Raw: qlog.RawInfo{Length: int(p.Size())},
- Trigger: qlog.PacketDropDOSPrevention,
+ Raw: qlog.RawInfo{Length: int(p.Size())},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropDOSPrevention,
})
}
c.receivedPacketMx.Unlock()
@@ -2456,7 +2498,7 @@ func (c *Conn) sendPackets(now monotime.Time) error {
return err
}
c.logger.Debugf("sending path probe packet from %s", c.LocalAddr())
- c.logShortHeaderPacket(probe.DestConnID, probe.Ack, probe.Frames, probe.StreamFrames, probe.PacketNumber, probe.PacketNumberLen, probe.KeyPhase, protocol.ECNNon, buf.Len(), false)
+ c.logShortHeaderPacket(probe, protocol.ECNNon, buf.Len())
c.registerPackedShortHeaderPacket(probe, protocol.ECNNon, now)
tr.WriteTo(buf.Data, c.conn.RemoteAddr())
// There's (likely) more data to send. Loop around again.
@@ -2477,7 +2519,7 @@ func (c *Conn) sendPackets(now monotime.Time) error {
return err
}
ecn := c.sentPacketHandler.ECNMode(true)
- c.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, buf.Len(), false)
+ c.logShortHeaderPacket(p, ecn, buf.Len())
c.registerPackedShortHeaderPacket(p, ecn, now)
c.sendQueue.Send(buf, 0, ecn)
// There's (likely) more data to send. Loop around again.
@@ -2646,7 +2688,7 @@ func (c *Conn) maybeSendAckOnlyPacket(now monotime.Time) error {
}
return err
}
- c.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, buf.Len(), false)
+ c.logShortHeaderPacket(p, ecn, buf.Len())
c.registerPackedShortHeaderPacket(p, ecn, now)
c.sendQueue.Send(buf, 0, ecn)
return nil
@@ -2700,7 +2742,7 @@ func (c *Conn) appendOneShortHeaderPacket(buf *packetBuffer, maxSize protocol.By
return 0, err
}
size := buf.Len() - startLen
- c.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, size, false)
+ c.logShortHeaderPacket(p, ecn, size)
c.registerPackedShortHeaderPacket(p, ecn, now)
return size, nil
}
@@ -2920,7 +2962,7 @@ func (c *Conn) scheduleSending() {
// tryQueueingUndecryptablePacket queues a packet for which we're missing the decryption keys.
// The qlogevents.PacketType is only used for logging purposes.
-func (c *Conn) tryQueueingUndecryptablePacket(p receivedPacket, pt qlog.PacketType) {
+func (c *Conn) tryQueueingUndecryptablePacket(p receivedPacket, pt qlog.PacketType, datagramID qlog.DatagramID) {
if c.handshakeComplete {
panic("shouldn't queue undecryptable packets after handshake completion")
}
@@ -2931,8 +2973,9 @@ func (c *Conn) tryQueueingUndecryptablePacket(p receivedPacket, pt qlog.PacketTy
PacketType: pt,
PacketNumber: protocol.InvalidPacketNumber,
},
- Raw: qlog.RawInfo{Length: int(p.Size())},
- Trigger: qlog.PacketDropDOSPrevention,
+ Raw: qlog.RawInfo{Length: int(p.Size())},
+ DatagramID: datagramID,
+ Trigger: qlog.PacketDropDOSPrevention,
})
}
c.logger.Infof("Dropping undecryptable packet (%d bytes). Undecryptable packet queue full.", p.Size())
@@ -2945,10 +2988,11 @@ func (c *Conn) tryQueueingUndecryptablePacket(p receivedPacket, pt qlog.PacketTy
PacketType: pt,
PacketNumber: protocol.InvalidPacketNumber,
},
- Raw: qlog.RawInfo{Length: int(p.Size())},
+ Raw: qlog.RawInfo{Length: int(p.Size())},
+ DatagramID: datagramID,
})
}
- c.undecryptablePackets = append(c.undecryptablePackets, p)
+ c.undecryptablePackets = append(c.undecryptablePackets, receivedPacketWithDatagramID{receivedPacket: p, datagramID: datagramID})
}
func (c *Conn) queueControlFrame(f wire.Frame) {
diff --git a/vendor/github.com/quic-go/quic-go/connection_logging.go b/vendor/github.com/quic-go/quic-go/connection_logging.go
index 0c6221d5b..c828c8be0 100644
--- a/vendor/github.com/quic-go/quic-go/connection_logging.go
+++ b/vendor/github.com/quic-go/quic-go/connection_logging.go
@@ -5,7 +5,6 @@ import (
"net/netip"
"slices"
- "github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/wire"
"github.com/quic-go/quic-go/qlog"
@@ -58,7 +57,7 @@ func toQlogAckFrame(f *wire.AckFrame) *qlog.AckFrame {
return ack
}
-func (c *Conn) logLongHeaderPacket(p *longHeaderPacket, ecn protocol.ECN) {
+func (c *Conn) logLongHeaderPacket(p *longHeaderPacket, ecn protocol.ECN, datagramID qlog.DatagramID) {
// quic-go logging
if c.logger.Debug() {
p.header.Log(c.logger)
@@ -102,91 +101,85 @@ func (c *Conn) logLongHeaderPacket(p *longHeaderPacket, ecn protocol.ECN) {
Length: int(p.length),
PayloadLength: int(p.header.Length),
},
- Frames: frames,
- ECN: toQlogECN(ecn),
+ DatagramID: datagramID,
+ Frames: frames,
+ ECN: toQlogECN(ecn),
})
}
}
-func (c *Conn) logShortHeaderPacket(
- destConnID protocol.ConnectionID,
- ackFrame *wire.AckFrame,
- frames []ackhandler.Frame,
- streamFrames []ackhandler.StreamFrame,
- pn protocol.PacketNumber,
- pnLen protocol.PacketNumberLen,
- kp protocol.KeyPhaseBit,
- ecn protocol.ECN,
- size protocol.ByteCount,
- isCoalesced bool,
-) {
+func (c *Conn) logShortHeaderPacket(p shortHeaderPacket, ecn protocol.ECN, size protocol.ByteCount) {
+ c.logShortHeaderPacketWithDatagramID(p, ecn, size, false, 0)
+}
+
+func (c *Conn) logShortHeaderPacketWithDatagramID(p shortHeaderPacket, ecn protocol.ECN, size protocol.ByteCount, isCoalesced bool, datagramID qlog.DatagramID) {
if c.logger.Debug() && !isCoalesced {
- c.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, 1-RTT (ECN: %s)", pn, size, c.logID, ecn)
+ c.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, 1-RTT (ECN: %s)", p.PacketNumber, size, c.logID, ecn)
}
// quic-go logging
if c.logger.Debug() {
- wire.LogShortHeader(c.logger, destConnID, pn, pnLen, kp)
- if ackFrame != nil {
- wire.LogFrame(c.logger, ackFrame, true)
+ wire.LogShortHeader(c.logger, p.DestConnID, p.PacketNumber, p.PacketNumberLen, p.KeyPhase)
+ if p.Ack != nil {
+ wire.LogFrame(c.logger, p.Ack, true)
}
- for _, f := range frames {
+ for _, f := range p.Frames {
wire.LogFrame(c.logger, f.Frame, true)
}
- for _, f := range streamFrames {
+ for _, f := range p.StreamFrames {
wire.LogFrame(c.logger, f.Frame, true)
}
}
// tracing
if c.qlogger != nil {
- numFrames := len(frames) + len(streamFrames)
- if ackFrame != nil {
+ numFrames := len(p.Frames) + len(p.StreamFrames)
+ if p.Ack != nil {
numFrames++
}
fs := make([]qlog.Frame, 0, numFrames)
- if ackFrame != nil {
- fs = append(fs, toQlogFrame(ackFrame))
+ if p.Ack != nil {
+ fs = append(fs, toQlogFrame(p.Ack))
}
- for _, f := range frames {
+ for _, f := range p.Frames {
fs = append(fs, toQlogFrame(f.Frame))
}
- for _, f := range streamFrames {
+ for _, f := range p.StreamFrames {
fs = append(fs, toQlogFrame(f.Frame))
}
c.qlogger.RecordEvent(qlog.PacketSent{
Header: qlog.PacketHeader{
PacketType: qlog.PacketType1RTT,
- KeyPhaseBit: kp,
- PacketNumber: pn,
+ KeyPhaseBit: p.KeyPhase,
+ PacketNumber: p.PacketNumber,
Version: c.version,
- DestConnectionID: destConnID,
+ DestConnectionID: p.DestConnID,
},
Raw: qlog.RawInfo{
Length: int(size),
- PayloadLength: int(size - wire.ShortHeaderLen(destConnID, pnLen)),
+ PayloadLength: int(size - wire.ShortHeaderLen(p.DestConnID, p.PacketNumberLen)),
},
- Frames: fs,
- ECN: toQlogECN(ecn),
+ DatagramID: datagramID,
+ Frames: fs,
+ ECN: toQlogECN(ecn),
})
}
}
func (c *Conn) logCoalescedPacket(packet *coalescedPacket, ecn protocol.ECN) {
+ var datagramID qlog.DatagramID
+ if c.qlogger != nil {
+ datagramID = qlog.CalculateDatagramID(packet.buffer.Data)
+ }
if c.logger.Debug() {
// There's a short period between dropping both Initial and Handshake keys and completion of the handshake,
// during which we might call PackCoalescedPacket but just pack a short header packet.
if len(packet.longHdrPackets) == 0 && packet.shortHdrPacket != nil {
- c.logShortHeaderPacket(
- packet.shortHdrPacket.DestConnID,
- packet.shortHdrPacket.Ack,
- packet.shortHdrPacket.Frames,
- packet.shortHdrPacket.StreamFrames,
- packet.shortHdrPacket.PacketNumber,
- packet.shortHdrPacket.PacketNumberLen,
- packet.shortHdrPacket.KeyPhase,
+ c.logShortHeaderPacketWithDatagramID(
+ *packet.shortHdrPacket,
ecn,
packet.shortHdrPacket.Length,
false,
+ datagramID,
)
return
}
@@ -197,10 +190,10 @@ func (c *Conn) logCoalescedPacket(packet *coalescedPacket, ecn protocol.ECN) {
}
}
for _, p := range packet.longHdrPackets {
- c.logLongHeaderPacket(p, ecn)
+ c.logLongHeaderPacket(p, ecn, datagramID)
}
if p := packet.shortHdrPacket; p != nil {
- c.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, p.Length, true)
+ c.logShortHeaderPacketWithDatagramID(*p, ecn, p.Length, true, datagramID)
}
}
diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/ackhandler.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/ackhandler.go
deleted file mode 100644
index c399358f2..000000000
--- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/ackhandler.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package ackhandler
-
-import (
- "github.com/quic-go/quic-go/internal/protocol"
- "github.com/quic-go/quic-go/internal/utils"
- "github.com/quic-go/quic-go/qlogwriter"
-)
-
-// NewAckHandler creates a new SentPacketHandler and a new ReceivedPacketHandler.
-// clientAddressValidated indicates whether the address was validated beforehand by an address validation token.
-// clientAddressValidated has no effect for a client.
-func NewAckHandler(
- initialPacketNumber protocol.PacketNumber,
- initialMaxDatagramSize protocol.ByteCount,
- rttStats *utils.RTTStats,
- connStats *utils.ConnectionStats,
- clientAddressValidated bool,
- enableECN bool,
- pers protocol.Perspective,
- qlogger qlogwriter.Recorder,
- logger utils.Logger,
-) (SentPacketHandler, ReceivedPacketHandler) {
- sph := newSentPacketHandler(initialPacketNumber, initialMaxDatagramSize, rttStats, connStats, clientAddressValidated, enableECN, pers, qlogger, logger)
- return sph, newReceivedPacketHandler(sph, logger)
-}
diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/interfaces.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/interfaces.go
index 9ee9da7d9..620a5e11f 100644
--- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/interfaces.go
+++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/interfaces.go
@@ -13,6 +13,7 @@ type SentPacketHandler interface {
// ReceivedAck processes an ACK frame.
// It does not store a copy of the frame.
ReceivedAck(f *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime monotime.Time) (bool /* 1-RTT packet acked */, error)
+ ReceivedPacket(protocol.EncryptionLevel, monotime.Time)
ReceivedBytes(_ protocol.ByteCount, rcvTime monotime.Time)
DropPackets(_ protocol.EncryptionLevel, rcvTime monotime.Time)
ResetForRetry(rcvTime monotime.Time)
@@ -36,18 +37,3 @@ type SentPacketHandler interface {
MigratedPath(now monotime.Time, initialMaxPacketSize protocol.ByteCount)
}
-
-type sentPacketTracker interface {
- GetLowestPacketNotConfirmedAcked() protocol.PacketNumber
- ReceivedPacket(_ protocol.EncryptionLevel, rcvTime monotime.Time)
-}
-
-// ReceivedPacketHandler handles ACKs needed to send for incoming packets
-type ReceivedPacketHandler interface {
- IsPotentiallyDuplicate(protocol.PacketNumber, protocol.EncryptionLevel) bool
- ReceivedPacket(pn protocol.PacketNumber, ecn protocol.ECN, encLevel protocol.EncryptionLevel, rcvTime monotime.Time, ackEliciting bool) error
- DropPackets(protocol.EncryptionLevel)
-
- GetAlarmTimeout() monotime.Time
- GetAckFrame(_ protocol.EncryptionLevel, now monotime.Time, onlyIfQueued bool) *wire.AckFrame
-}
diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/mockgen.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/mockgen.go
index 323d9fde9..3add80d1f 100644
--- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/mockgen.go
+++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/mockgen.go
@@ -2,8 +2,5 @@
package ackhandler
-//go:generate sh -c "go tool mockgen -typed -build_flags=\"-tags=gomock\" -package ackhandler -destination mock_sent_packet_tracker_test.go github.com/quic-go/quic-go/internal/ackhandler SentPacketTracker"
-type SentPacketTracker = sentPacketTracker
-
//go:generate sh -c "go tool mockgen -typed -build_flags=\"-tags=gomock\" -package ackhandler -destination mock_ecn_handler_test.go github.com/quic-go/quic-go/internal/ackhandler ECNHandler"
type ECNHandler = ecnHandler
diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/packet.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/packet.go
index f0500e9f2..7bfe599f4 100644
--- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/packet.go
+++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/packet.go
@@ -28,8 +28,12 @@ type packet struct {
isPathProbePacket bool
}
-func (p *packet) outstanding() bool {
- return !p.declaredLost && !p.IsPathMTUProbePacket && !p.isPathProbePacket
+func (p *packet) Outstanding() bool {
+ return !p.declaredLost && !p.IsPathMTUProbePacket && !p.isPathProbePacket && p.IsAckEliciting()
+}
+
+func (p *packet) IsAckEliciting() bool {
+ return len(p.StreamFrames) > 0 || len(p.Frames) > 0
}
var packetPool = sync.Pool{New: func() any { return &packet{} }}
diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_handler.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_handler.go
index 7180db85f..d0d24bf30 100644
--- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_handler.go
+++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_handler.go
@@ -9,9 +9,7 @@ import (
"github.com/quic-go/quic-go/internal/wire"
)
-type receivedPacketHandler struct {
- sentPackets sentPacketTracker
-
+type ReceivedPacketHandler struct {
initialPackets *receivedPacketTracker
handshakePackets *receivedPacketTracker
appDataPackets appDataReceivedPacketTracker
@@ -19,11 +17,8 @@ type receivedPacketHandler struct {
lowest1RTTPacket protocol.PacketNumber
}
-var _ ReceivedPacketHandler = &receivedPacketHandler{}
-
-func newReceivedPacketHandler(sentPackets sentPacketTracker, logger utils.Logger) ReceivedPacketHandler {
- return &receivedPacketHandler{
- sentPackets: sentPackets,
+func NewReceivedPacketHandler(logger utils.Logger) *ReceivedPacketHandler {
+ return &ReceivedPacketHandler{
initialPackets: newReceivedPacketTracker(),
handshakePackets: newReceivedPacketTracker(),
appDataPackets: *newAppDataReceivedPacketTracker(logger),
@@ -31,14 +26,13 @@ func newReceivedPacketHandler(sentPackets sentPacketTracker, logger utils.Logger
}
}
-func (h *receivedPacketHandler) ReceivedPacket(
+func (h *ReceivedPacketHandler) ReceivedPacket(
pn protocol.PacketNumber,
ecn protocol.ECN,
encLevel protocol.EncryptionLevel,
rcvTime monotime.Time,
ackEliciting bool,
) error {
- h.sentPackets.ReceivedPacket(encLevel, rcvTime)
switch encLevel {
case protocol.EncryptionInitial:
return h.initialPackets.ReceivedPacket(pn, ecn, ackEliciting)
@@ -58,17 +52,17 @@ func (h *receivedPacketHandler) ReceivedPacket(
if h.lowest1RTTPacket == protocol.InvalidPacketNumber || pn < h.lowest1RTTPacket {
h.lowest1RTTPacket = pn
}
- if err := h.appDataPackets.ReceivedPacket(pn, ecn, rcvTime, ackEliciting); err != nil {
- return err
- }
- h.appDataPackets.IgnoreBelow(h.sentPackets.GetLowestPacketNotConfirmedAcked())
- return nil
+ return h.appDataPackets.ReceivedPacket(pn, ecn, rcvTime, ackEliciting)
default:
panic(fmt.Sprintf("received packet with unknown encryption level: %s", encLevel))
}
}
-func (h *receivedPacketHandler) DropPackets(encLevel protocol.EncryptionLevel) {
+func (h *ReceivedPacketHandler) IgnorePacketsBelow(pn protocol.PacketNumber) {
+ h.appDataPackets.IgnoreBelow(pn)
+}
+
+func (h *ReceivedPacketHandler) DropPackets(encLevel protocol.EncryptionLevel) {
//nolint:exhaustive // 1-RTT packet number space is never dropped.
switch encLevel {
case protocol.EncryptionInitial:
@@ -83,11 +77,11 @@ func (h *receivedPacketHandler) DropPackets(encLevel protocol.EncryptionLevel) {
}
}
-func (h *receivedPacketHandler) GetAlarmTimeout() monotime.Time {
+func (h *ReceivedPacketHandler) GetAlarmTimeout() monotime.Time {
return h.appDataPackets.GetAlarmTimeout()
}
-func (h *receivedPacketHandler) GetAckFrame(encLevel protocol.EncryptionLevel, now monotime.Time, onlyIfQueued bool) *wire.AckFrame {
+func (h *ReceivedPacketHandler) GetAckFrame(encLevel protocol.EncryptionLevel, now monotime.Time, onlyIfQueued bool) *wire.AckFrame {
//nolint:exhaustive // 0-RTT packets can't contain ACK frames.
switch encLevel {
case protocol.EncryptionInitial:
@@ -108,7 +102,7 @@ func (h *receivedPacketHandler) GetAckFrame(encLevel protocol.EncryptionLevel, n
}
}
-func (h *receivedPacketHandler) IsPotentiallyDuplicate(pn protocol.PacketNumber, encLevel protocol.EncryptionLevel) bool {
+func (h *ReceivedPacketHandler) IsPotentiallyDuplicate(pn protocol.PacketNumber, encLevel protocol.EncryptionLevel) bool {
switch encLevel {
case protocol.EncryptionInitial:
if h.initialPackets != nil {
diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go
index e134232c4..f9aa2d60d 100644
--- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go
+++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go
@@ -69,6 +69,8 @@ type sentPacketHandler struct {
handshakePackets *packetNumberSpace
appDataPackets *packetNumberSpace
lostPackets lostPacketTracker // only for application-data packet number space
+ // send time of the largest acknowledged packet, across all packet number spaces
+ largestAckedTime monotime.Time
// Do we know that the peer completed address validation yet?
// Always true for the server.
@@ -81,11 +83,7 @@ type sentPacketHandler struct {
handshakeConfirmed bool
- // lowestNotConfirmedAcked is the lowest packet number that we sent an ACK for, but haven't received confirmation, that this ACK actually arrived
- // example: we send an ACK for packets 90-100 with packet number 20
- // once we receive an ACK from the peer for packet 20, the lowestNotConfirmedAcked is 101
- // Only applies to the application-data packet number space.
- lowestNotConfirmedAcked protocol.PacketNumber
+ ignorePacketsBelow func(protocol.PacketNumber)
ackedPackets []packetWithPacketNumber // to avoid allocations in detectAndRemoveAckedPackets
@@ -115,24 +113,22 @@ type sentPacketHandler struct {
logger utils.Logger
}
-var (
- _ SentPacketHandler = &sentPacketHandler{}
- _ sentPacketTracker = &sentPacketHandler{}
-)
+var _ SentPacketHandler = &sentPacketHandler{}
// clientAddressValidated indicates whether the address was validated beforehand by an address validation token.
// If the address was validated, the amplification limit doesn't apply. It has no effect for a client.
-func newSentPacketHandler(
+func NewSentPacketHandler(
initialPN protocol.PacketNumber,
initialMaxDatagramSize protocol.ByteCount,
rttStats *utils.RTTStats,
connStats *utils.ConnectionStats,
clientAddressValidated bool,
enableECN bool,
+ ignorePacketsBelow func(protocol.PacketNumber),
pers protocol.Perspective,
qlogger qlogwriter.Recorder,
logger utils.Logger,
-) *sentPacketHandler {
+) SentPacketHandler {
congestion := congestion.NewCubicSender(
congestion.DefaultClock{},
rttStats,
@@ -152,6 +148,7 @@ func newSentPacketHandler(
rttStats: rttStats,
connStats: connStats,
congestion: congestion,
+ ignorePacketsBelow: ignorePacketsBelow,
perspective: pers,
qlogger: qlogger,
logger: logger,
@@ -275,15 +272,19 @@ func (h *sentPacketHandler) SentPacket(
}
pnSpace.largestSent = pn
- isAckEliciting := len(streamFrames) > 0 || len(frames) > 0
+
+ p := getPacket()
+ p.SendTime = t
+ p.EncryptionLevel = encLevel
+ p.Length = size
+ p.Frames = frames
+ p.LargestAcked = largestAcked
+ p.StreamFrames = streamFrames
+ p.IsPathMTUProbePacket = isPathMTUProbePacket
+ p.isPathProbePacket = isPathProbePacket
+ isAckEliciting := p.IsAckEliciting()
if isPathProbePacket {
- p := getPacket()
- p.SendTime = t
- p.EncryptionLevel = encLevel
- p.Length = size
- p.Frames = frames
- p.isPathProbePacket = true
pnSpace.history.SentPathProbePacket(pn, p)
h.setLossDetectionTimer(t)
return
@@ -291,6 +292,7 @@ func (h *sentPacketHandler) SentPacket(
if isAckEliciting {
pnSpace.lastAckElicitingPacketTime = t
h.bytesInFlight += size
+ p.includedInBytesInFlight = true
if h.numProbesToSend > 0 {
h.numProbesToSend--
}
@@ -301,25 +303,13 @@ func (h *sentPacketHandler) SentPacket(
h.ecnTracker.SentPacket(pn, ecn)
}
+ pnSpace.history.SentPacket(pn, p)
if !isAckEliciting {
- pnSpace.history.SentNonAckElicitingPacket(pn)
if !h.peerCompletedAddressValidation {
h.setLossDetectionTimer(t)
}
return
}
-
- p := getPacket()
- p.SendTime = t
- p.EncryptionLevel = encLevel
- p.Length = size
- p.LargestAcked = largestAcked
- p.StreamFrames = streamFrames
- p.Frames = frames
- p.IsPathMTUProbePacket = isPathMTUProbePacket
- p.includedInBytesInFlight = true
-
- pnSpace.history.SentAckElicitingPacket(pn, p)
if h.qlogger != nil {
h.qlogMetricsUpdated()
}
@@ -405,21 +395,26 @@ func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.En
}
priorInFlight := h.bytesInFlight
- ackedPackets, err := h.detectAndRemoveAckedPackets(ack, encLevel)
+ ackedPackets, hasAckEliciting, err := h.detectAndRemoveAckedPackets(ack, encLevel)
if err != nil || len(ackedPackets) == 0 {
return false, err
}
- // update the RTT, if the largest acked is newly acknowledged
+ // update the RTT, if:
+ // * the largest acked is newly acknowledged, AND
+ // * at least one new ack-eliciting packet was acknowledged
if len(ackedPackets) > 0 {
- if p := ackedPackets[len(ackedPackets)-1]; p.PacketNumber == ack.LargestAcked() && !p.isPathProbePacket {
+ if p := ackedPackets[len(ackedPackets)-1]; p.PacketNumber == ack.LargestAcked() && !p.isPathProbePacket && hasAckEliciting {
// don't use the ack delay for Initial and Handshake packets
var ackDelay time.Duration
if encLevel == protocol.Encryption1RTT {
ackDelay = min(ack.DelayTime, h.rttStats.MaxAckDelay())
}
- h.rttStats.UpdateRTT(rcvTime.Sub(p.SendTime), ackDelay)
- if h.logger.Debug() {
- h.logger.Debugf("\tupdated RTT: %s (σ: %s)", h.rttStats.SmoothedRTT(), h.rttStats.MeanDeviation())
+ if h.largestAckedTime.IsZero() || !p.SendTime.Before(h.largestAckedTime) {
+ h.rttStats.UpdateRTT(rcvTime.Sub(p.SendTime), ackDelay)
+ if h.logger.Debug() {
+ h.logger.Debugf("\tupdated RTT: %s (σ: %s)", h.rttStats.SmoothedRTT(), h.rttStats.MeanDeviation())
+ }
+ h.largestAckedTime = p.SendTime
}
h.congestion.MaybeExitSlowStart()
}
@@ -526,14 +521,13 @@ func (h *sentPacketHandler) detectSpuriousLosses(ack *wire.AckFrame, ackTime mon
}
}
-func (h *sentPacketHandler) GetLowestPacketNotConfirmedAcked() protocol.PacketNumber {
- return h.lowestNotConfirmedAcked
-}
-
// Packets are returned in ascending packet number order.
-func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encLevel protocol.EncryptionLevel) ([]packetWithPacketNumber, error) {
+func (h *sentPacketHandler) detectAndRemoveAckedPackets(
+ ack *wire.AckFrame,
+ encLevel protocol.EncryptionLevel,
+) (_ []packetWithPacketNumber, hasAckEliciting bool, _ error) {
if len(h.ackedPackets) > 0 {
- return nil, errors.New("ackhandler BUG: ackedPackets slice not empty")
+ return nil, false, errors.New("ackhandler BUG: ackedPackets slice not empty")
}
pnSpace := h.getPacketNumberSpace(encLevel)
@@ -541,7 +535,7 @@ func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encL
if encLevel == protocol.Encryption1RTT {
for p := range pnSpace.history.SkippedPackets() {
if ack.AcksPacket(p) {
- return nil, &qerr.TransportError{
+ return nil, false, &qerr.TransportError{
ErrorCode: qerr.ProtocolViolation,
ErrorMessage: fmt.Sprintf("received an ACK for skipped packet number: %d (%s)", p, encLevel),
}
@@ -573,7 +567,7 @@ func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encL
continue
}
if pn > ackRange.Largest {
- return nil, fmt.Errorf("BUG: ackhandler would have acked wrong packet %d, while evaluating range %d -> %d", pn, ackRange.Smallest, ackRange.Largest)
+ return nil, false, fmt.Errorf("BUG: ackhandler would have acked wrong packet %d, while evaluating range %d -> %d", pn, ackRange.Smallest, ackRange.Largest)
}
}
if p.isPathProbePacket {
@@ -584,6 +578,9 @@ func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encL
}
continue
}
+ if p.IsAckEliciting() {
+ hasAckEliciting = true
+ }
h.ackedPackets = append(h.ackedPackets, packetWithPacketNumber{PacketNumber: pn, packet: p})
}
if h.logger.Debug() && len(h.ackedPackets) > 0 {
@@ -595,8 +592,8 @@ func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encL
}
for _, p := range h.ackedPackets {
- if p.LargestAcked != protocol.InvalidPacketNumber && encLevel == protocol.Encryption1RTT {
- h.lowestNotConfirmedAcked = max(h.lowestNotConfirmedAcked, p.LargestAcked+1)
+ if p.LargestAcked != protocol.InvalidPacketNumber && encLevel == protocol.Encryption1RTT && h.ignorePacketsBelow != nil {
+ h.ignorePacketsBelow(p.LargestAcked + 1)
}
for _, f := range p.Frames {
@@ -610,11 +607,11 @@ func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encL
}
}
if err := pnSpace.history.Remove(p.PacketNumber); err != nil {
- return nil, err
+ return nil, false, err
}
}
// TODO: add support for the transport:packets_acked qlog event
- return h.ackedPackets, nil
+ return h.ackedPackets, hasAckEliciting, nil
}
func (h *sentPacketHandler) getLossTimeAndSpace() (monotime.Time, protocol.EncryptionLevel) {
@@ -808,7 +805,7 @@ func (h *sentPacketHandler) detectLostPackets(now monotime.Time, encLevel protoc
var packetLost bool
if !p.SendTime.After(lostSendTime) {
packetLost = true
- if !p.isPathProbePacket {
+ if !p.isPathProbePacket && p.IsAckEliciting() {
if h.logger.Debug() {
h.logger.Debugf("\tlost packet %d (time threshold)", pn)
}
@@ -824,7 +821,7 @@ func (h *sentPacketHandler) detectLostPackets(now monotime.Time, encLevel protoc
}
} else if pnSpace.history.Difference(pnSpace.largestAcked, pn) >= packetThreshold {
packetLost = true
- if !p.isPathProbePacket {
+ if !p.isPathProbePacket && p.IsAckEliciting() {
if h.logger.Debug() {
h.logger.Debugf("\tlost packet %d (reordering threshold)", pn)
}
@@ -851,7 +848,7 @@ func (h *sentPacketHandler) detectLostPackets(now monotime.Time, encLevel protoc
h.lostPackets.Add(pn, p.SendTime)
}
pnSpace.history.DeclareLost(pn)
- if !p.isPathProbePacket {
+ if !p.isPathProbePacket && p.IsAckEliciting() {
// the bytes in flight need to be reduced no matter if the frames in this packet will be retransmitted
h.removeFromBytesInFlight(p)
h.queueFramesForRetransmission(p)
@@ -1079,14 +1076,14 @@ func (h *sentPacketHandler) ResetForRetry(now monotime.Time) {
if firstPacketSendTime.IsZero() {
firstPacketSendTime = p.SendTime
}
- if !p.declaredLost {
+ if !p.declaredLost && p.IsAckEliciting() {
h.queueFramesForRetransmission(p)
}
}
// All application data packets sent at this point are 0-RTT packets.
// In the case of a Retry, we can assume that the server dropped all of them.
for _, p := range h.appDataPackets.history.Packets() {
- if !p.declaredLost {
+ if !p.declaredLost && p.IsAckEliciting() {
h.queueFramesForRetransmission(p)
}
}
@@ -1124,7 +1121,9 @@ func (h *sentPacketHandler) MigratedPath(now monotime.Time, initialMaxDatagramSi
h.appDataPackets.history.DeclareLost(pn)
if !p.isPathProbePacket {
h.removeFromBytesInFlight(p)
- h.queueFramesForRetransmission(p)
+ if p.IsAckEliciting() {
+ h.queueFramesForRetransmission(p)
+ }
}
}
for pn := range h.appDataPackets.history.PathProbes() {
diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go
index 54b74cf74..14a7049c2 100644
--- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go
+++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go
@@ -58,17 +58,10 @@ func (h *sentPacketHistory) SkippedPacket(pn protocol.PacketNumber) {
h.skippedPackets = append(h.skippedPackets, pn)
}
-func (h *sentPacketHistory) SentNonAckElicitingPacket(pn protocol.PacketNumber) {
- h.checkSequentialPacketNumberUse(pn)
- if len(h.packets) > 0 {
- h.packets = append(h.packets, nil)
- }
-}
-
-func (h *sentPacketHistory) SentAckElicitingPacket(pn protocol.PacketNumber, p *packet) {
+func (h *sentPacketHistory) SentPacket(pn protocol.PacketNumber, p *packet) {
h.checkSequentialPacketNumberUse(pn)
h.packets = append(h.packets, p)
- if p.outstanding() {
+ if p.Outstanding() {
h.numOutstanding++
}
}
@@ -111,7 +104,7 @@ func (h *sentPacketHistory) FirstOutstanding() (protocol.PacketNumber, *packet)
return protocol.InvalidPacketNumber, nil
}
for i, p := range h.packets {
- if p != nil && p.outstanding() {
+ if p != nil && p.Outstanding() {
return h.firstPacketNumber + protocol.PacketNumber(i), p
}
}
@@ -148,7 +141,7 @@ func (h *sentPacketHistory) Remove(pn protocol.PacketNumber) error {
return fmt.Errorf("packet %d not found in sent packet history", pn)
}
p := h.packets[idx]
- if p.outstanding() {
+ if p.Outstanding() {
h.numOutstanding--
if h.numOutstanding < 0 {
panic("negative number of outstanding packets")
@@ -243,7 +236,7 @@ func (h *sentPacketHistory) DeclareLost(pn protocol.PacketNumber) {
return
}
p := h.packets[idx]
- if p.outstanding() {
+ if p.Outstanding() {
h.numOutstanding--
if h.numOutstanding < 0 {
panic("negative number of outstanding packets")
diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/aead.go b/vendor/github.com/quic-go/quic-go/internal/handshake/aead.go
index 1baf5d6b0..ce83ab18c 100644
--- a/vendor/github.com/quic-go/quic-go/internal/handshake/aead.go
+++ b/vendor/github.com/quic-go/quic-go/internal/handshake/aead.go
@@ -6,7 +6,7 @@ import (
"github.com/quic-go/quic-go/internal/protocol"
)
-func createAEAD(suite *cipherSuite, trafficSecret []byte, v protocol.Version) *xorNonceAEAD {
+func createAEAD(suite cipherSuite, trafficSecret []byte, v protocol.Version) *xorNonceAEAD {
keyLabel := hkdfLabelKeyV1
ivLabel := hkdfLabelIVV1
if v == protocol.Version2 {
diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/cipher_suite.go b/vendor/github.com/quic-go/quic-go/internal/handshake/cipher_suite.go
index d8a381daf..03fe0dad8 100644
--- a/vendor/github.com/quic-go/quic-go/internal/handshake/cipher_suite.go
+++ b/vendor/github.com/quic-go/quic-go/internal/handshake/cipher_suite.go
@@ -23,14 +23,14 @@ type cipherSuite struct {
func (s cipherSuite) IVLen() int { return aeadNonceLength }
-func getCipherSuite(id uint16) *cipherSuite {
+func getCipherSuite(id uint16) cipherSuite {
switch id {
case tls.TLS_AES_128_GCM_SHA256:
- return &cipherSuite{ID: tls.TLS_AES_128_GCM_SHA256, Hash: crypto.SHA256, KeyLen: 16, AEAD: aeadAESGCMTLS13}
+ return cipherSuite{ID: tls.TLS_AES_128_GCM_SHA256, Hash: crypto.SHA256, KeyLen: 16, AEAD: aeadAESGCMTLS13}
case tls.TLS_CHACHA20_POLY1305_SHA256:
- return &cipherSuite{ID: tls.TLS_CHACHA20_POLY1305_SHA256, Hash: crypto.SHA256, KeyLen: 32, AEAD: aeadChaCha20Poly1305}
+ return cipherSuite{ID: tls.TLS_CHACHA20_POLY1305_SHA256, Hash: crypto.SHA256, KeyLen: 32, AEAD: aeadChaCha20Poly1305}
case tls.TLS_AES_256_GCM_SHA384:
- return &cipherSuite{ID: tls.TLS_AES_256_GCM_SHA384, Hash: crypto.SHA384, KeyLen: 32, AEAD: aeadAESGCMTLS13}
+ return cipherSuite{ID: tls.TLS_AES_256_GCM_SHA384, Hash: crypto.SHA384, KeyLen: 32, AEAD: aeadAESGCMTLS13}
default:
panic(fmt.Sprintf("unknown cypher suite: %d", id))
}
diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/header_protector.go b/vendor/github.com/quic-go/quic-go/internal/handshake/header_protector.go
index 2c5ee42f1..93c3cd980 100644
--- a/vendor/github.com/quic-go/quic-go/internal/handshake/header_protector.go
+++ b/vendor/github.com/quic-go/quic-go/internal/handshake/header_protector.go
@@ -24,7 +24,7 @@ func hkdfHeaderProtectionLabel(v protocol.Version) string {
return "quic hp"
}
-func newHeaderProtector(suite *cipherSuite, trafficSecret []byte, isLongHeader bool, v protocol.Version) headerProtector {
+func newHeaderProtector(suite cipherSuite, trafficSecret []byte, isLongHeader bool, v protocol.Version) headerProtector {
hkdfLabel := hkdfHeaderProtectionLabel(v)
switch suite.ID {
case tls.TLS_AES_128_GCM_SHA256, tls.TLS_AES_256_GCM_SHA384:
@@ -44,7 +44,7 @@ type aesHeaderProtector struct {
var _ headerProtector = &aesHeaderProtector{}
-func newAESHeaderProtector(suite *cipherSuite, trafficSecret []byte, isLongHeader bool, hkdfLabel string) headerProtector {
+func newAESHeaderProtector(suite cipherSuite, trafficSecret []byte, isLongHeader bool, hkdfLabel string) headerProtector {
hpKey := hkdfExpandLabel(suite.Hash, trafficSecret, []byte{}, hkdfLabel, suite.KeyLen)
block, err := aes.NewCipher(hpKey)
if err != nil {
@@ -88,7 +88,7 @@ type chachaHeaderProtector struct {
var _ headerProtector = &chachaHeaderProtector{}
-func newChaChaHeaderProtector(suite *cipherSuite, trafficSecret []byte, isLongHeader bool, hkdfLabel string) headerProtector {
+func newChaChaHeaderProtector(suite cipherSuite, trafficSecret []byte, isLongHeader bool, hkdfLabel string) headerProtector {
hpKey := hkdfExpandLabel(suite.Hash, trafficSecret, []byte{}, hkdfLabel, suite.KeyLen)
p := &chachaHeaderProtector{
diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/updatable_aead.go b/vendor/github.com/quic-go/quic-go/internal/handshake/updatable_aead.go
index ae63eec89..f88f76ad8 100644
--- a/vendor/github.com/quic-go/quic-go/internal/handshake/updatable_aead.go
+++ b/vendor/github.com/quic-go/quic-go/internal/handshake/updatable_aead.go
@@ -32,7 +32,7 @@ func SetKeyUpdateInterval(v uint64) (reset func()) {
var FirstKeyUpdateInterval uint64 = 100
type updatableAEAD struct {
- suite *cipherSuite
+ suite cipherSuite
keyPhase protocol.KeyPhase
largestAcked protocol.PacketNumber
@@ -136,10 +136,10 @@ func (a *updatableAEAD) getNextTrafficSecret(hash crypto.Hash, ts []byte) []byte
// SetReadKey sets the read key.
// For the client, this function is called before SetWriteKey.
// For the server, this function is called after SetWriteKey.
-func (a *updatableAEAD) SetReadKey(suite *cipherSuite, trafficSecret []byte) {
+func (a *updatableAEAD) SetReadKey(suite cipherSuite, trafficSecret []byte) {
a.rcvAEAD = createAEAD(suite, trafficSecret, a.version)
a.headerDecrypter = newHeaderProtector(suite, trafficSecret, false, a.version)
- if a.suite == nil {
+ if a.suite.ID == 0 { // suite is not set yet
a.setAEADParameters(a.rcvAEAD, suite)
}
@@ -150,10 +150,10 @@ func (a *updatableAEAD) SetReadKey(suite *cipherSuite, trafficSecret []byte) {
// SetWriteKey sets the write key.
// For the client, this function is called after SetReadKey.
// For the server, this function is called before SetReadKey.
-func (a *updatableAEAD) SetWriteKey(suite *cipherSuite, trafficSecret []byte) {
+func (a *updatableAEAD) SetWriteKey(suite cipherSuite, trafficSecret []byte) {
a.sendAEAD = createAEAD(suite, trafficSecret, a.version)
a.headerEncrypter = newHeaderProtector(suite, trafficSecret, false, a.version)
- if a.suite == nil {
+ if a.suite.ID == 0 { // suite is not set yet
a.setAEADParameters(a.sendAEAD, suite)
}
@@ -161,7 +161,7 @@ func (a *updatableAEAD) SetWriteKey(suite *cipherSuite, trafficSecret []byte) {
a.nextSendAEAD = createAEAD(suite, a.nextSendTrafficSecret, a.version)
}
-func (a *updatableAEAD) setAEADParameters(aead cipher.AEAD, suite *cipherSuite) {
+func (a *updatableAEAD) setAEADParameters(aead cipher.AEAD, suite cipherSuite) {
a.nonceBuf = make([]byte, aead.NonceSize())
a.aeadOverhead = aead.Overhead()
a.suite = suite
diff --git a/vendor/github.com/quic-go/quic-go/internal/protocol/params.go b/vendor/github.com/quic-go/quic-go/internal/protocol/params.go
index fe86317fb..0861d57fc 100644
--- a/vendor/github.com/quic-go/quic-go/internal/protocol/params.go
+++ b/vendor/github.com/quic-go/quic-go/internal/protocol/params.go
@@ -112,16 +112,13 @@ const MinStreamFrameSize ByteCount = 128
// we send after the handshake completes.
const MaxPostHandshakeCryptoFrameSize = 1000
-// MaxAckFrameSize is the maximum size for an ACK frame that we write
-// Due to the varint encoding, ACK frames can grow (almost) indefinitely large.
-// The MaxAckFrameSize should be large enough to encode many ACK range,
-// but must ensure that a maximum size ACK frame fits into one packet.
-const MaxAckFrameSize ByteCount = 1000
-
// MaxNumAckRanges is the maximum number of ACK ranges that we send in an ACK frame.
// It also serves as a limit for the packet history.
// If at any point we keep track of more ranges, old ranges are discarded.
-const MaxNumAckRanges = 32
+//
+// This value also guarantees that ACK Range Count value in the ACK frame can be encoded
+// in a single byte varint.
+const MaxNumAckRanges = 64
// MinPacingDelay is the minimum duration that is used for packet pacing
// If the packet packing frequency is higher, multiple packets might be sent at once.
diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go
index 68bebfa79..191e15307 100644
--- a/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go
+++ b/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go
@@ -64,7 +64,7 @@ func parseAckFrame(frame *AckFrame, b []byte, typ FrameType, ackDelayExponent ui
frame.AckRanges = append(frame.AckRanges, AckRange{Smallest: smallest, Largest: largestAcked})
// read all the other ACK ranges
- for i := uint64(0); i < numBlocks; i++ {
+ for range numBlocks {
g, l, err := quicvarint.Parse(b)
if err != nil {
return 0, replaceUnexpectedEOF(err)
@@ -129,7 +129,7 @@ func (f *AckFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
b = quicvarint.Append(b, uint64(f.LargestAcked()))
b = quicvarint.Append(b, encodeAckDelay(f.DelayTime))
- numRanges := f.numEncodableAckRanges()
+ numRanges := min(len(f.AckRanges), protocol.MaxNumAckRanges)
b = quicvarint.Append(b, uint64(numRanges-1))
// write the first range
@@ -154,46 +154,69 @@ func (f *AckFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
// Length of a written frame
func (f *AckFrame) Length(_ protocol.Version) protocol.ByteCount {
largestAcked := f.AckRanges[0].Largest
- numRanges := f.numEncodableAckRanges()
- length := 1 + quicvarint.Len(uint64(largestAcked)) + quicvarint.Len(encodeAckDelay(f.DelayTime))
+ // The number of ACK ranges is limited to 64, which guarantees that the
+ // ACK Range Count value can be encoded in a single byte varint.
+ length := 1 + quicvarint.Len(uint64(largestAcked)) + quicvarint.Len(encodeAckDelay(f.DelayTime)) + 1
- length += quicvarint.Len(uint64(numRanges - 1))
lowestInFirstRange := f.AckRanges[0].Smallest
length += quicvarint.Len(uint64(largestAcked - lowestInFirstRange))
- for i := 1; i < numRanges; i++ {
+ for i := 1; i < min(len(f.AckRanges), protocol.MaxNumAckRanges); i++ {
gap, len := f.encodeAckRange(i)
length += quicvarint.Len(gap)
length += quicvarint.Len(len)
}
if f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0 {
- length += quicvarint.Len(f.ECT0)
- length += quicvarint.Len(f.ECT1)
- length += quicvarint.Len(f.ECNCE)
+ length += quicvarint.Len(f.ECT0) + quicvarint.Len(f.ECT1) + quicvarint.Len(f.ECNCE)
}
return protocol.ByteCount(length)
}
+// Truncate truncates the ACK frame to fit into maxSize,
+// and to at most 64 ACK ranges.
+// maxSize must be large enough to fit at least one ACK range.
+func (f *AckFrame) Truncate(maxSize protocol.ByteCount, _ protocol.Version) {
+ f.AckRanges = f.AckRanges[:f.numEncodableAckRanges(maxSize)]
+}
+
// gets the number of ACK ranges that can be encoded
-// such that the resulting frame is smaller than the maximum ACK frame size
-func (f *AckFrame) numEncodableAckRanges() int {
- length := 1 + quicvarint.Len(uint64(f.LargestAcked())) + quicvarint.Len(encodeAckDelay(f.DelayTime))
- length += 2 // assume that the number of ranges will consume 2 bytes
- for i := 1; i < len(f.AckRanges); i++ {
- gap, len := f.encodeAckRange(i)
- rangeLen := quicvarint.Len(gap) + quicvarint.Len(len)
- if protocol.ByteCount(length+rangeLen) > protocol.MaxAckFrameSize {
- // Writing range i would exceed the MaxAckFrameSize.
- // So encode one range less than that.
- return i - 1
+// such that the resulting frame is smaller than maxSize
+func (f *AckFrame) numEncodableAckRanges(maxSize protocol.ByteCount) int {
+ // Fast path: Most ACK frames are relatively small, and we don't need to calculate the exact length.
+ // We just assume the worst case scenario: every varint is encoded to 8 bytes.
+ // If the result is still smaller than the maximum ACK frame size, the actual ACK frame will definitely fit.
+ length := 1 + 8 /* largest acked */ + 8 /* delay */ + 1 /* ack range count */ + 8 /* first range */
+ if f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0 {
+ length += 8 + 8 + 8
+ }
+ numRanges := min(len(f.AckRanges), protocol.MaxNumAckRanges)
+ length += 2 * 8 * (numRanges - 1)
+ if protocol.ByteCount(length) <= maxSize {
+ return numRanges
+ }
+
+ // Slow path: Calculate the exact length of the ACK frame.
+ length = 1 + quicvarint.Len(uint64(f.LargestAcked())) + quicvarint.Len(encodeAckDelay(f.DelayTime)) + 1
+ _, firstRange := f.encodeAckRange(0)
+ length += quicvarint.Len(firstRange)
+ if f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0 {
+ length += quicvarint.Len(f.ECT0) + quicvarint.Len(f.ECT1) + quicvarint.Len(f.ECNCE)
+ }
+ for i := 1; i < numRanges; i++ {
+ gap, l := f.encodeAckRange(i)
+ rangeLen := quicvarint.Len(gap) + quicvarint.Len(l)
+ if protocol.ByteCount(length+rangeLen) > maxSize {
+ // Writing range i would exceed the maximum size,
+ // so encode one range less than that.
+ return i
}
length += rangeLen
}
- return len(f.AckRanges)
+ return numRanges
}
-func (f *AckFrame) encodeAckRange(i int) (uint64 /* gap */, uint64 /* length */) {
+func (f *AckFrame) encodeAckRange(i int) (gap, length uint64) {
if i == 0 {
return 0, uint64(f.AckRanges[0].Largest - f.AckRanges[0].Smallest)
}
@@ -218,7 +241,7 @@ func (f *AckFrame) validateAckRanges() bool {
}
}
- // check the consistency for ACK with multiple NACK ranges
+ // check the consistency for ACK with multiple ACK ranges
for i, ackRange := range f.AckRanges {
if i == 0 {
continue
diff --git a/vendor/github.com/quic-go/quic-go/packet_packer.go b/vendor/github.com/quic-go/quic-go/packet_packer.go
index e3933da6b..175d3c86d 100644
--- a/vendor/github.com/quic-go/quic-go/packet_packer.go
+++ b/vendor/github.com/quic-go/quic-go/packet_packer.go
@@ -350,7 +350,6 @@ func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxSize protocol.ByteCo
now,
false,
onlyAck,
- true,
v,
)
if initialPayload.length > 0 {
@@ -373,7 +372,6 @@ func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxSize protocol.ByteCo
now,
false,
onlyAck,
- size == 0,
v,
)
if handshakePayload.length > 0 {
@@ -399,7 +397,7 @@ func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxSize protocol.ByteCo
connID = p.getDestConnID()
oneRTTPacketNumber, oneRTTPacketNumberLen = p.pnManager.PeekPacketNumber(protocol.Encryption1RTT)
hdrLen := wire.ShortHeaderLen(connID, oneRTTPacketNumberLen)
- oneRTTPayload = p.maybeGetShortHeaderPacket(oneRTTSealer, hdrLen, maxSize-size, onlyAck, size == 0, now, v)
+ oneRTTPayload = p.maybeGetShortHeaderPacket(oneRTTSealer, hdrLen, maxSize-size, onlyAck, now, v)
if oneRTTPayload.length > 0 {
size += p.shortHeaderPacketLength(connID, oneRTTPacketNumberLen, oneRTTPayload) + protocol.ByteCount(oneRTTSealer.Overhead())
}
@@ -486,7 +484,7 @@ func (p *packetPacker) appendPacket(
pn, pnLen := p.pnManager.PeekPacketNumber(protocol.Encryption1RTT)
connID := p.getDestConnID()
hdrLen := wire.ShortHeaderLen(connID, pnLen)
- pl := p.maybeGetShortHeaderPacket(sealer, hdrLen, maxPacketSize, onlyAck, true, now, v)
+ pl := p.maybeGetShortHeaderPacket(sealer, hdrLen, maxPacketSize, onlyAck, now, v)
if pl.length == 0 {
return shortHeaderPacket{}, errNothingToPack
}
@@ -500,17 +498,17 @@ func (p *packetPacker) maybeGetCryptoPacket(
encLevel protocol.EncryptionLevel,
now monotime.Time,
addPingIfEmpty bool,
- onlyAck, ackAllowed bool,
+ onlyAck bool,
v protocol.Version,
) (*wire.ExtendedHeader, payload) {
if onlyAck {
if ack := p.acks.GetAckFrame(encLevel, now, true); ack != nil {
- return p.getLongHeader(encLevel, v), payload{
- ack: ack,
- length: ack.Length(v),
- }
+ hdr := p.getLongHeader(encLevel, v)
+ maxPacketSize -= hdr.GetLength(v)
+ ack.Truncate(maxPacketSize, v)
+ return hdr, payload{ack: ack, length: ack.Length(v)}
}
- return nil, payload{}
+ return nil, payload{length: 0}
}
var hasCryptoData func() bool
@@ -527,10 +525,7 @@ func (p *packetPacker) maybeGetCryptoPacket(
handler := p.retransmissionQueue.AckHandler(encLevel)
hasRetransmission := p.retransmissionQueue.HasData(encLevel)
- var ack *wire.AckFrame
- if ackAllowed {
- ack = p.acks.GetAckFrame(encLevel, now, !hasRetransmission && !hasCryptoData())
- }
+ ack := p.acks.GetAckFrame(encLevel, now, !hasRetransmission && !hasCryptoData())
var pl payload
if !hasCryptoData() && !hasRetransmission && ack == nil {
if !addPingIfEmpty {
@@ -542,13 +537,15 @@ func (p *packetPacker) maybeGetCryptoPacket(
pl.length += ping.Length(v)
}
+ hdr := p.getLongHeader(encLevel, v)
+ maxPacketSize -= hdr.GetLength(v)
+
if ack != nil {
+ ack.Truncate(maxPacketSize, v)
pl.ack = ack
pl.length = ack.Length(v)
maxPacketSize -= pl.length
}
- hdr := p.getLongHeader(encLevel, v)
- maxPacketSize -= hdr.GetLength(v)
if hasRetransmission {
for {
frame := p.retransmissionQueue.GetFrame(encLevel, maxPacketSize, v)
@@ -591,12 +588,12 @@ func (p *packetPacker) maybeGetAppDataPacketFor0RTT(sealer sealer, maxSize proto
func (p *packetPacker) maybeGetShortHeaderPacket(
sealer handshake.ShortHeaderSealer,
hdrLen, maxPacketSize protocol.ByteCount,
- onlyAck, ackAllowed bool,
+ onlyAck bool,
now monotime.Time,
v protocol.Version,
) payload {
maxPayloadSize := maxPacketSize - hdrLen - protocol.ByteCount(sealer.Overhead())
- return p.maybeGetAppDataPacket(maxPayloadSize, onlyAck, ackAllowed, now, v)
+ return p.maybeGetAppDataPacket(maxPayloadSize, onlyAck, true, now, v)
}
func (p *packetPacker) maybeGetAppDataPacket(
@@ -635,6 +632,7 @@ func (p *packetPacker) composeNextPacket(
) payload {
if onlyAck {
if ack := p.acks.GetAckFrame(protocol.Encryption1RTT, now, true); ack != nil {
+ ack.Truncate(maxPayloadSize, v)
return payload{ack: ack, length: ack.Length(v)}
}
return payload{}
@@ -643,13 +641,12 @@ func (p *packetPacker) composeNextPacket(
hasData := p.framer.HasData()
hasRetransmission := p.retransmissionQueue.HasData(protocol.Encryption1RTT)
- var hasAck bool
var pl payload
if ackAllowed {
if ack := p.acks.GetAckFrame(protocol.Encryption1RTT, now, !hasRetransmission && !hasData); ack != nil {
+ ack.Truncate(maxPayloadSize, v)
pl.ack = ack
pl.length += ack.Length(v)
- hasAck = true
}
}
@@ -660,7 +657,7 @@ func (p *packetPacker) composeNextPacket(
pl.frames = append(pl.frames, ackhandler.Frame{Frame: f})
pl.length += size
p.datagramQueue.Pop()
- } else if !hasAck {
+ } else if pl.ack == nil {
// The DATAGRAM frame doesn't fit, and the packet doesn't contain an ACK.
// Discard this frame. There's no point in retrying this in the next packet,
// as it's unlikely that the available packet size will increase.
@@ -670,7 +667,7 @@ func (p *packetPacker) composeNextPacket(
}
}
- if hasAck && !hasData && !hasRetransmission {
+ if pl.ack != nil && !hasData && !hasRetransmission {
return pl
}
@@ -747,7 +744,6 @@ func (p *packetPacker) PackPTOProbePacket(
now,
addPingIfEmpty,
false,
- true,
v,
)
if pl.length == 0 {
diff --git a/vendor/github.com/quic-go/quic-go/qlog/event.go b/vendor/github.com/quic-go/quic-go/qlog/event.go
index 77cdff232..83ca71f13 100644
--- a/vendor/github.com/quic-go/quic-go/qlog/event.go
+++ b/vendor/github.com/quic-go/quic-go/qlog/event.go
@@ -214,6 +214,7 @@ func (e ConnectionClosed) Encode(enc *jsontext.Encoder, _ time.Time) error {
type PacketSent struct {
Header PacketHeader
Raw RawInfo
+ DatagramID DatagramID
Frames []Frame
ECN ECN
IsCoalesced bool
@@ -234,6 +235,10 @@ func (e PacketSent) Encode(enc *jsontext.Encoder, _ time.Time) error {
if err := e.Raw.encode(enc); err != nil {
return err
}
+ if e.DatagramID != 0 {
+ h.WriteToken(jsontext.String("datagram_id"))
+ h.WriteToken(jsontext.Uint(uint64(e.DatagramID)))
+ }
if len(e.Frames) > 0 {
h.WriteToken(jsontext.String("frames"))
if err := frames(e.Frames).encode(enc); err != nil {
@@ -259,6 +264,7 @@ func (e PacketSent) Encode(enc *jsontext.Encoder, _ time.Time) error {
type PacketReceived struct {
Header PacketHeader
Raw RawInfo
+ DatagramID DatagramID
Frames []Frame
ECN ECN
IsCoalesced bool
@@ -278,6 +284,10 @@ func (e PacketReceived) Encode(enc *jsontext.Encoder, _ time.Time) error {
if err := e.Raw.encode(enc); err != nil {
return err
}
+ if e.DatagramID != 0 {
+ h.WriteToken(jsontext.String("datagram_id"))
+ h.WriteToken(jsontext.Uint(uint64(e.DatagramID)))
+ }
if len(e.Frames) > 0 {
h.WriteToken(jsontext.String("frames"))
if err := frames(e.Frames).encode(enc); err != nil {
@@ -345,8 +355,9 @@ func (e VersionNegotiationSent) Encode(enc *jsontext.Encoder, _ time.Time) error
}
type PacketBuffered struct {
- Header PacketHeader
- Raw RawInfo
+ Header PacketHeader
+ Raw RawInfo
+ DatagramID DatagramID
}
func (e PacketBuffered) Name() string { return "transport:packet_buffered" }
@@ -362,6 +373,10 @@ func (e PacketBuffered) Encode(enc *jsontext.Encoder, _ time.Time) error {
if err := e.Raw.encode(enc); err != nil {
return err
}
+ if e.DatagramID != 0 {
+ h.WriteToken(jsontext.String("datagram_id"))
+ h.WriteToken(jsontext.Uint(uint64(e.DatagramID)))
+ }
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String("keys_unavailable"))
h.WriteToken(jsontext.EndObject)
@@ -370,9 +385,10 @@ func (e PacketBuffered) Encode(enc *jsontext.Encoder, _ time.Time) error {
// PacketDropped is the transport:packet_dropped event.
type PacketDropped struct {
- Header PacketHeader
- Raw RawInfo
- Trigger PacketDropReason
+ Header PacketHeader
+ Raw RawInfo
+ DatagramID DatagramID
+ Trigger PacketDropReason
}
func (e PacketDropped) Name() string { return "transport:packet_dropped" }
@@ -388,6 +404,10 @@ func (e PacketDropped) Encode(enc *jsontext.Encoder, _ time.Time) error {
if err := e.Raw.encode(enc); err != nil {
return err
}
+ if e.DatagramID != 0 {
+ h.WriteToken(jsontext.String("datagram_id"))
+ h.WriteToken(jsontext.Uint(uint64(e.DatagramID)))
+ }
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String(string(e.Trigger)))
h.WriteToken(jsontext.EndObject)
@@ -805,3 +825,25 @@ func (e ALPNInformation) Encode(enc *jsontext.Encoder, _ time.Time) error {
h.WriteToken(jsontext.EndObject)
return h.err
}
+
+// DebugEvent is a generic event that can be used to log arbitrary messages.
+type DebugEvent struct {
+ EventName string
+ Message string
+}
+
+func (e DebugEvent) Name() string {
+ if e.EventName == "" {
+ return "transport:debug"
+ }
+ return fmt.Sprintf("transport:%s", e.EventName)
+}
+
+func (e DebugEvent) Encode(enc *jsontext.Encoder, _ time.Time) error {
+ h := encoderHelper{enc: enc}
+ h.WriteToken(jsontext.BeginObject)
+ h.WriteToken(jsontext.String("message"))
+ h.WriteToken(jsontext.String(e.Message))
+ h.WriteToken(jsontext.EndObject)
+ return h.err
+}
diff --git a/vendor/github.com/quic-go/quic-go/qlog/types.go b/vendor/github.com/quic-go/quic-go/qlog/types.go
index 4cd2bb64c..dfa4066d2 100644
--- a/vendor/github.com/quic-go/quic-go/qlog/types.go
+++ b/vendor/github.com/quic-go/quic-go/qlog/types.go
@@ -2,6 +2,7 @@ package qlog
import (
"fmt"
+ "hash/crc32"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
@@ -293,3 +294,11 @@ const (
// StatelessReset indicates the connection was closed due to receiving a stateless reset from the peer
ConnectionCloseTriggerStatelessReset ConnectionCloseTrigger = "stateless_reset"
)
+
+// DatagramID is a unique identifier for a datagram
+type DatagramID uint32
+
+// CalculateDatagramID computes a DatagramID for a given packet
+func CalculateDatagramID(packet []byte) DatagramID {
+ return DatagramID(crc32.ChecksumIEEE(packet))
+}
diff --git a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/calvin/calvin.go b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/calvin/calvin.go
index 5019a5bc1..bb724a458 100644
--- a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/calvin/calvin.go
+++ b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/calvin/calvin.go
@@ -1,11 +1,12 @@
-// Package calvin pkg/skywire-utilities/pkg/calvin/calvin.go
/*
+Package calvin pkg/skywire-utilities/pkg/calvin/calvin.go
convert text to ascii art font i.e.:
go run pkg/skywire-utilities/calvin/cmd/calvin@develop convert text to ascii art font
┌─┐┌─┐┌┐┌┬ ┬┌─┐┬─┐┌┬┐ ┌┬┐┌─┐─┐ ┬┌┬┐ ┌┬┐┌─┐ ┌─┐┌─┐┌─┐┬┬ ┌─┐┬─┐┌┬┐ ┌─┐┌─┐┌┐┌┌┬┐
│ │ ││││└┐┌┘├┤ ├┬┘ │ │ ├┤ ┌┴┬┘ │ │ │ │ ├─┤└─┐│ ││ ├─┤├┬┘ │ ├┤ │ ││││ │
└─┘└─┘┘└┘ └┘ └─┘┴└─ ┴ ┴ └─┘┴ └─ ┴ ┴ └─┘ ┴ ┴└─┘└─┘┴┴ ┴ ┴┴└─ ┴ └ └─┘┘└┘ ┴
*/
+
package calvin
import (
@@ -84,7 +85,9 @@ var boxFont = map[rune][]string{
}
// AsciiFont converts a string to box drawing characters.
-func AsciiFont(input string) string { //nolint
+//
+//nolint:revive
+func AsciiFont(input string) string {
var output [3]string
for _, char := range input {
diff --git a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cipher/README.md b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cipher/README.md
new file mode 100644
index 000000000..a2dc4b4fc
--- /dev/null
+++ b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cipher/README.md
@@ -0,0 +1,89 @@
+# Cipher Package - Signature Verification
+
+This package provides optimized signature verification for Skywire.
+
+## Performance Optimization
+
+The package has two implementations:
+
+### 1. Pure Go (Default)
+- **Build tag**: None (default)
+- **Dependencies**: None
+- **Speed**: Fast, but 3-5x slower than CGO
+- **Used by**: `go run`, `go build` without tags
+
+### 2. CGO with libsecp256k1 (Optimized)
+- **Build tag**: `-tags=cgo`
+- **Dependencies**: `libsecp256k1-dev`
+- **Speed**: 3-5x faster signature verification
+- **Used by**: Official Linux releases, optional for local builds
+
+## Why This Matters
+
+DMSG uses Noise protocol with frequent signature verifications during handshakes. Under high load, this can cause:
+- High CPU usage
+- Increased memory consumption
+- Slower connection establishment
+
+The CGO implementation using Bitcoin's secp256k1 library provides significant performance improvements.
+
+## Building with CGO Optimization
+
+### System Requirements
+
+**Arch/Manjaro:**
+```bash
+sudo pacman -S libsecp256k1
+```
+
+**Ubuntu/Debian:**
+```bash
+sudo apt install libsecp256k1-dev
+```
+
+### Local Development
+
+```bash
+# Pure Go (default, no dependencies)
+make build
+
+# With CGO optimization (requires libsecp256k1-dev)
+make build-merged-cgo
+```
+
+Or directly:
+```bash
+go build -tags=cgo ./cmd/skywire
+```
+
+### Official Releases
+
+Linux releases are automatically built with CGO optimization using statically-linked secp256k1 libraries. This provides maximum performance while maintaining portability (no runtime dependencies).
+
+## Implementation Details
+
+- **cipher_nocgo.go**: Pure Go implementation (build tag: `!cgo`)
+- **cipher_cgo.go**: CGO implementation (build tag: `cgo && !windows`)
+- **cipher_windows.go**: Windows-specific pure Go (build tag: `windows`)
+
+The appropriate implementation is selected at compile time based on build tags and platform.
+
+## Testing
+
+Both implementations are tested to ensure identical behavior:
+
+```bash
+# Test pure Go version
+go test ./pkg/skywire-utilities/pkg/cipher
+
+# Test CGO version (requires libsecp256k1-dev)
+go test -tags=cgo ./pkg/skywire-utilities/pkg/cipher
+```
+
+## Troubleshooting
+
+**Error: `secp256k1.h: No such file or directory`**
+
+This means you're building with `-tags=cgo` but don't have libsecp256k1-dev installed. Either:
+1. Install the library (see System Requirements above)
+2. Build without `-tags=cgo` to use pure Go implementation
diff --git a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cipher/cipher.go b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cipher/cipher.go
index 9b140badf..ca5a00e9c 100644
--- a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cipher/cipher.go
+++ b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/cipher/cipher.go
@@ -9,6 +9,7 @@ import (
"strings"
"github.com/skycoin/skycoin/src/cipher"
+ "github.com/skycoin/skycoin/src/cipher/secp256k1-go"
)
func init() {
@@ -242,7 +243,7 @@ func SignPayload(payload []byte, sec SecKey) (Sig, error) {
// VerifyPubKeySignedPayload verifies that SHA256 hash of the payload was signed by PubKey
func VerifyPubKeySignedPayload(pubkey PubKey, sig Sig, payload []byte) error {
- return cipher.VerifyPubKeySignedHash(cipher.PubKey(pubkey), cipher.Sig(sig), cipher.SumSHA256(payload))
+ return VerifyPubKeySignedHashLight(cipher.PubKey(pubkey), cipher.Sig(sig), cipher.SumSHA256(payload))
}
// RandByte returns rand N bytes
@@ -264,3 +265,24 @@ func SHA256FromBytes(b []byte) (SHA256, error) {
func SumSHA256(b []byte) SHA256 {
return SHA256(cipher.SumSHA256(b))
}
+
+// VerifyPubKeySignedHashLight uses standard Skycoin implementation
+// This is your original optimized version that skips pubkey recovery
+func VerifyPubKeySignedHashLight(pubkey cipher.PubKey, sig cipher.Sig, hash cipher.SHA256) error {
+ // Validate pubkey format (fast)
+ if secp256k1.VerifyPubkey(pubkey[:]) != 1 {
+ return cipher.ErrInvalidSigInvalidPubKey
+ }
+
+ // Validate signature format (fast)
+ if secp256k1.VerifySignatureValidity(sig[:]) != 1 {
+ return cipher.ErrInvalidSigValidity
+ }
+
+ // Verify signature (expensive, but still faster than full recovery)
+ if secp256k1.VerifySignature(hash[:], sig[:], pubkey[:]) != 1 {
+ return cipher.ErrInvalidSigForMessage
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/flags/flags.go b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/flags/flags.go
index 1a8a1b239..e20ddb520 100644
--- a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/flags/flags.go
+++ b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/flags/flags.go
@@ -16,7 +16,7 @@ func InitFlags(cmd *cobra.Command, usage bool) {
}
cmd.PersistentFlags().BoolVarP(&helpflag, "help", "h", false, "show help menu")
cmd.SetHelpCommand(&cobra.Command{Hidden: true})
- cmd.PersistentFlags().MarkHidden("help") //nolint
+ cmd.PersistentFlags().MarkHidden("help") //nolint:errcheck,gosec
cc.Init(&cc.Config{
RootCmd: cmd,
@@ -30,8 +30,24 @@ func InitFlags(cmd *cobra.Command, usage bool) {
NoExtraNewlines: true,
NoBottomNewline: true,
})
+
+ // Set help template AFTER cc.Init() to ensure it's not overridden
+ if !usage {
+ cmd.SetHelpTemplate(helpTemplateNoUsage)
+ }
}
+const helpTemplateNoUsage = `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}}
+
+{{end}}{{if .HasAvailableSubCommands}}Available Commands:{{range .Commands}}{{if and (ne .Name "completion") .IsAvailableCommand}}
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}
+
+{{end}}{{if .HasAvailableLocalFlags}}Flags:
+{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
+
+Global Flags:
+{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}`
+
const help = `{{if gt (len .Aliases) 0}}{{.NameAndAliases}}{{end}}{{if .HasAvailableSubCommands}}Available Commands:{{range .Commands}}{{if and (ne .Name "completion") .IsAvailableCommand}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
diff --git a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/metricsutil/http.go b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/metricsutil/http.go
index 6957dc290..a6f863a58 100644
--- a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/metricsutil/http.go
+++ b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/metricsutil/http.go
@@ -1,4 +1,5 @@
// Package metricsutil pkg/metricsutil/http.go
+
package metricsutil
import (
@@ -34,6 +35,6 @@ func ServeHTTPMetrics(log logrus.FieldLogger, addr string) {
log.WithField("addr", addr).Info("Serving metrics.")
go func() {
- log.Fatal(http.ListenAndServe(addr, r)) //nolint
+ log.Fatal(http.ListenAndServe(addr, r)) //nolint:gosec
}()
}
diff --git a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/metricsutil/request_duration_middleware.go b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/metricsutil/request_duration_middleware.go
index 050c7878c..686953fb2 100644
--- a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/metricsutil/request_duration_middleware.go
+++ b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/metricsutil/request_duration_middleware.go
@@ -1,4 +1,5 @@
// Package metricsutil pkg/metricsutil/request_duration_middleware.go
+
package metricsutil
import (
diff --git a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/netutil/net.go b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/netutil/net.go
index fe5e56893..a9a589fd5 100644
--- a/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/netutil/net.go
+++ b/vendor/github.com/skycoin/skywire/pkg/skywire-utilities/pkg/netutil/net.go
@@ -126,9 +126,11 @@ func HasPublicIP() (bool, error) {
func ExtractPort(addr net.Addr) (uint16, error) {
switch address := addr.(type) {
case *net.TCPAddr:
- return uint16(address.Port), nil //nolint
+ //nolint:gosec
+ return uint16(address.Port), nil
case *net.UDPAddr:
- return uint16(address.Port), nil //nolint
+ //nolint:gosec
+ return uint16(address.Port), nil
default:
return 0, fmt.Errorf("extract port: invalid address: %s", addr.String())
}
diff --git a/vendor/github.com/xtaci/smux/README.md b/vendor/github.com/xtaci/smux/README.md
index c3306515e..8bce5d65f 100644
--- a/vendor/github.com/xtaci/smux/README.md
+++ b/vendor/github.com/xtaci/smux/README.md
@@ -19,16 +19,16 @@
## Introduction
-Smux ( **S**imple **MU**ltiple**X**ing) is a multiplexing library for Golang. It relies on an underlying connection to provide reliability and ordering, such as TCP or [KCP](https://github.com/xtaci/kcp-go), and provides stream-oriented multiplexing. The original intention of this library is to power the connection management for [kcp-go](https://github.com/xtaci/kcp-go).
+Smux (**S**imple **MU**ltiple**X**ing) is a multiplexing library for Golang. It relies on an underlying connection to provide reliability and ordering, such as TCP or [KCP](https://github.com/xtaci/kcp-go), and provides stream-oriented multiplexing. This library was originally designed to power connection management for [kcp-go](https://github.com/xtaci/kcp-go).
## Features
-1. ***Token bucket*** controlled receiving, which provides smoother bandwidth graph(see picture below).
-2. Session-wide receive buffer, shared among streams, **fully controlled** overall memory usage.
-3. Minimized header(8Bytes), maximized payload.
-4. Well-tested on millions of devices in [kcptun](https://github.com/xtaci/kcptun).
-5. Builtin fair queue traffic shaping.
-6. Per-stream sliding window to control congestion.(protocol version 2+).
+1. ***Token bucket*** controlled receiving, providing a smoother bandwidth graph (see picture below).
+2. Session-wide receive buffer shared among streams for **fully controlled** overall memory usage.
+3. Minimized header (8 bytes), maximized payload.
+4. Battle-tested on millions of devices in [kcptun](https://github.com/xtaci/kcptun).
+5. Built-in fair queue traffic shaping.
+6. Per-stream sliding window for congestion control (protocol version 2+).

diff --git a/vendor/github.com/xtaci/smux/mux.go b/vendor/github.com/xtaci/smux/mux.go
index 39815c711..f25f723ec 100644
--- a/vendor/github.com/xtaci/smux/mux.go
+++ b/vendor/github.com/xtaci/smux/mux.go
@@ -92,6 +92,9 @@ func VerifyConfig(config *Config) error {
if config.MaxReceiveBuffer <= 0 {
return errors.New("max receive buffer must be positive")
}
+ if config.MaxReceiveBuffer > math.MaxInt32 {
+ return errors.New("max receive buffer cannot be larger than 2147483647")
+ }
if config.MaxStreamBuffer <= 0 {
return errors.New("max stream buffer must be positive")
}
diff --git a/vendor/github.com/xtaci/smux/session.go b/vendor/github.com/xtaci/smux/session.go
index 8c8b5dfa5..7018ac277 100644
--- a/vendor/github.com/xtaci/smux/session.go
+++ b/vendor/github.com/xtaci/smux/session.go
@@ -416,16 +416,21 @@ func (s *Session) recvLoop() {
switch hdr.Cmd() {
case cmdNOP:
case cmdSYN: // stream opening
+ var accepted *stream
s.streamLock.Lock()
if _, ok := s.streams[sid]; !ok {
stream := newStream(sid, s.config.MaxFrameSize, s)
s.streams[sid] = stream
+ accepted = stream
+ }
+ s.streamLock.Unlock()
+
+ if accepted != nil {
select {
- case s.chAccepts <- stream:
+ case s.chAccepts <- accepted:
case <-s.die:
}
}
- s.streamLock.Unlock()
case cmdFIN: // stream closing
s.streamLock.Lock()
diff --git a/vendor/github.com/xtaci/smux/stream.go b/vendor/github.com/xtaci/smux/stream.go
index 615e44f2f..ede72f2a3 100644
--- a/vendor/github.com/xtaci/smux/stream.go
+++ b/vendor/github.com/xtaci/smux/stream.go
@@ -41,7 +41,7 @@ type stream struct {
id uint32 // Stream identifier
sess *Session
- buffers []*[]byte // slice of buffers holding ordered incoming data
+ buffers [][]byte // slice of buffers holding ordered incoming data
heads []*[]byte // slice heads of the buffers above, kept for recycle
bufferLock sync.Mutex // Mutex to protect access to buffers
@@ -123,11 +123,11 @@ func (s *stream) tryReadV1(b []byte) (n int, err error) {
// A critical section to copy data from buffers to b
s.bufferLock.Lock()
if len(s.buffers) > 0 {
- n = copy(b, *s.buffers[0])
- *s.buffers[0] = (*s.buffers[0])[n:]
+ n = copy(b, s.buffers[0])
+ s.buffers[0] = s.buffers[0][n:]
// recycle buffer when fully consumed
- if len(*s.buffers[0]) == 0 {
+ if len(s.buffers[0]) == 0 {
s.buffers[0] = nil
s.buffers = s.buffers[1:]
defaultAllocator.Put(s.heads[0])
@@ -161,11 +161,11 @@ func (s *stream) tryReadV2(b []byte) (n int, err error) {
var notifyConsumed uint32
s.bufferLock.Lock()
if len(s.buffers) > 0 {
- n = copy(b, *s.buffers[0])
- *s.buffers[0] = (*s.buffers[0])[n:]
+ n = copy(b, s.buffers[0])
+ s.buffers[0] = s.buffers[0][n:]
// recycle buffer when fully consumed
- if len(*s.buffers[0]) == 0 {
+ if len(s.buffers[0]) == 0 {
s.buffers[0] = nil
s.buffers = s.buffers[1:]
defaultAllocator.Put(s.heads[0])
@@ -227,23 +227,25 @@ func (s *stream) WriteTo(w io.Writer) (n int64, err error) {
// check comments in WriteTo
func (s *stream) writeToV1(w io.Writer) (n int64, err error) {
for {
- var pbuf *[]byte
+ var buf []byte
+ var head *[]byte
// get the next buffer to write
s.bufferLock.Lock()
if len(s.buffers) > 0 {
- pbuf = s.buffers[0]
+ buf = s.buffers[0]
+ head = s.heads[0]
s.buffers = s.buffers[1:]
s.heads = s.heads[1:]
}
s.bufferLock.Unlock()
// write the buffer to w
- if pbuf != nil {
- nw, ew := w.Write(*pbuf)
+ if buf != nil {
+ nw, ew := w.Write(buf)
// NOTE: WriteTo is a reader, so we need to return tokens here
- s.sess.returnTokens(len(*pbuf))
- defaultAllocator.Put(pbuf)
+ s.sess.returnTokens(len(buf))
+ defaultAllocator.Put(head)
if nw > 0 {
n += int64(nw)
}
@@ -261,20 +263,22 @@ func (s *stream) writeToV1(w io.Writer) (n int64, err error) {
func (s *stream) writeToV2(w io.Writer) (n int64, err error) {
for {
var notifyConsumed uint32
- var pbuf *[]byte
+ var buf []byte
+ var head *[]byte
// get the next buffer to write
s.bufferLock.Lock()
if len(s.buffers) > 0 {
- pbuf = s.buffers[0]
+ buf = s.buffers[0]
+ head = s.heads[0]
s.buffers = s.buffers[1:]
s.heads = s.heads[1:]
}
// in v2, we need to track the number of bytes read
var bufLen uint32
- if pbuf != nil {
- bufLen = uint32(len(*pbuf))
+ if buf != nil {
+ bufLen = uint32(len(buf))
}
s.numRead += bufLen
s.incr += bufLen
@@ -287,11 +291,11 @@ func (s *stream) writeToV2(w io.Writer) (n int64, err error) {
s.bufferLock.Unlock()
// same as v1, write the buffer to w
- if pbuf != nil {
- nw, ew := w.Write(*pbuf)
+ if buf != nil {
+ nw, ew := w.Write(buf)
// NOTE: WriteTo is a reader, so we need to return tokens here
- s.sess.returnTokens(len(*pbuf))
- defaultAllocator.Put(pbuf)
+ s.sess.returnTokens(len(buf))
+ defaultAllocator.Put(head)
if nw > 0 {
n += int64(nw)
}
@@ -412,7 +416,7 @@ func (s *stream) writeV1(b []byte) (n int, err error) {
frame.data = b[:size]
n, err := s.sess.writeFrameInternal(frame, deadline, CLSDATA)
- s.numWritten++
+ atomic.AddUint32(&s.numWritten, uint32(size))
sent += n
if err != nil {
return sent, err
@@ -444,13 +448,28 @@ func (s *stream) writeV2(b []byte) (n int, err error) {
sent := 0
frame := newFrame(byte(s.sess.config.Version), cmdPSH, s.id)
+ var deadlineTimer *time.Timer
+ defer func() {
+ stopTimer(deadlineTimer)
+ }()
+
for {
- // update write deadline timer
- var deadline <-chan time.Time
+ deadline := (<-chan time.Time)(nil)
if d, ok := s.writeDeadline.Load().(time.Time); ok && !d.IsZero() {
- timer := time.NewTimer(time.Until(d))
- defer timer.Stop()
- deadline = timer.C
+ dur := time.Until(d)
+ if dur < 0 {
+ dur = 0
+ }
+ if deadlineTimer == nil {
+ deadlineTimer = time.NewTimer(dur)
+ } else {
+ stopTimer(deadlineTimer)
+ deadlineTimer.Reset(dur)
+ }
+ deadline = deadlineTimer.C
+ } else if deadlineTimer != nil {
+ stopTimer(deadlineTimer)
+ deadlineTimer = nil
}
// per stream sliding window control
@@ -613,7 +632,7 @@ func (s *stream) pushBytes(pbuf *[]byte) {
s.bufferLock.Lock()
defer s.bufferLock.Unlock()
- s.buffers = append(s.buffers, pbuf)
+ s.buffers = append(s.buffers, *pbuf)
s.heads = append(s.heads, pbuf)
}
@@ -623,7 +642,7 @@ func (s *stream) recycleTokens() (n int) {
defer s.bufferLock.Unlock()
for k := range s.buffers {
- n += len(*s.buffers[k])
+ n += len(s.buffers[k])
defaultAllocator.Put(s.heads[k])
}
s.buffers = nil
@@ -666,3 +685,16 @@ func (s *stream) fin() {
close(s.chFinEvent)
})
}
+
+// stopTimer stops the supplied timer and drains its channel if needed.
+func stopTimer(t *time.Timer) {
+ if t == nil {
+ return
+ }
+ if !t.Stop() {
+ select {
+ case <-t.C:
+ default:
+ }
+ }
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index cf3f7203b..f4c269538 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -184,7 +184,7 @@ github.com/go-playground/locales/currency
# github.com/go-playground/universal-translator v0.18.1
## explicit; go 1.18
github.com/go-playground/universal-translator
-# github.com/go-playground/validator/v10 v10.29.0
+# github.com/go-playground/validator/v10 v10.30.1
## explicit; go 1.24.0
github.com/go-playground/validator/v10
# github.com/go-redis/redis/v8 v8.11.5
@@ -208,7 +208,7 @@ github.com/goccy/go-json/internal/encoder/vm_color_indent
github.com/goccy/go-json/internal/encoder/vm_indent
github.com/goccy/go-json/internal/errors
github.com/goccy/go-json/internal/runtime
-# github.com/goccy/go-yaml v1.19.0
+# github.com/goccy/go-yaml v1.19.1
## explicit; go 1.21.0
github.com/goccy/go-yaml
github.com/goccy/go-yaml/ast
@@ -294,7 +294,7 @@ github.com/pmezard/go-difflib/difflib
# github.com/quic-go/qpack v0.6.0
## explicit; go 1.24
github.com/quic-go/qpack
-# github.com/quic-go/quic-go v0.57.1
+# github.com/quic-go/quic-go v0.58.0
## explicit; go 1.24
github.com/quic-go/quic-go
github.com/quic-go/quic-go/http3
@@ -321,7 +321,7 @@ github.com/sirupsen/logrus/hooks/syslog
# github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6
## explicit
github.com/skycoin/noise
-# github.com/skycoin/skycoin v0.28.1-0.20251215160458-f84f07154eae
+# github.com/skycoin/skycoin v0.28.2
## explicit; go 1.25.1
github.com/skycoin/skycoin/src/cipher
github.com/skycoin/skycoin/src/cipher/base58
@@ -329,8 +329,8 @@ github.com/skycoin/skycoin/src/cipher/ripemd160
github.com/skycoin/skycoin/src/cipher/secp256k1-go
github.com/skycoin/skycoin/src/cipher/secp256k1-go/secp256k1-go2
github.com/skycoin/skycoin/src/util/logging
-# github.com/skycoin/skywire v1.3.32-0.20251108143835-4a7d00a050e1
-## explicit; go 1.25.1
+# github.com/skycoin/skywire v1.3.32-0.20251215232901-7d4328a5ca17
+## explicit; go 1.25.4
github.com/skycoin/skywire/deployment
github.com/skycoin/skywire/pkg/skywire-utilities/pkg/buildinfo
github.com/skycoin/skywire/pkg/skywire-utilities/pkg/calvin
@@ -381,7 +381,7 @@ github.com/valyala/fastrand
# github.com/valyala/histogram v1.2.0
## explicit; go 1.12
github.com/valyala/histogram
-# github.com/xtaci/smux v1.5.47
+# github.com/xtaci/smux v1.5.49
## explicit; go 1.18
github.com/xtaci/smux
# go.opentelemetry.io/auto/sdk v1.1.0
@@ -469,8 +469,6 @@ golang.org/x/text/secure/bidirule
golang.org/x/text/transform
golang.org/x/text/unicode/bidi
golang.org/x/text/unicode/norm
-# golang.org/x/time v0.14.0
-## explicit; go 1.24.0
# google.golang.org/protobuf v1.36.11
## explicit; go 1.23
google.golang.org/protobuf/encoding/protowire