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 @@ +
+ +
+ # A QUIC implementation in pure Go - [![Documentation](https://img.shields.io/badge/docs-quic--go.net-red?style=flat)](https://quic-go.net/docs/) [![PkgGoDev](https://pkg.go.dev/badge/github.com/quic-go/quic-go)](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+). ![smooth bandwidth curve](assets/curve.jpg) 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