From fb5f1124757cda4e947e3cdbadafefa933ebd250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Mon, 24 Jun 2024 10:05:10 +0800 Subject: [PATCH] Update quic-go to v0.45.1 --- congestion_meta1/bbr_sender.go | 20 ++---------------- congestion_meta1/cubic.go | 2 +- congestion_meta2/bbr_sender.go | 15 -------------- go.mod | 13 ++++++------ go.sum | 38 +++++++++++++++++----------------- hysteria/packet.go | 8 +++---- hysteria2/client.go | 2 +- hysteria2/packet.go | 8 +++---- hysteria2/service.go | 2 +- tuic/congestion.go | 8 +++---- tuic/packet.go | 8 +++---- 11 files changed, 46 insertions(+), 78 deletions(-) diff --git a/congestion_meta1/bbr_sender.go b/congestion_meta1/bbr_sender.go index 24e7324..1cc3af2 100644 --- a/congestion_meta1/bbr_sender.go +++ b/congestion_meta1/bbr_sender.go @@ -6,7 +6,6 @@ import ( "fmt" "math" "math/rand" - "net" "time" "github.com/sagernet/quic-go/congestion" @@ -14,27 +13,12 @@ import ( const ( // InitialMaxDatagramSize is the default maximum packet size used in QUIC for congestion window computations in bytes. - InitialMaxDatagramSize = 1252 - InitialPacketSizeIPv4 = 1252 - InitialPacketSizeIPv6 = 1232 + InitialMaxDatagramSize = 1280 + InitialPacketSize = 1280 InitialCongestionWindow = 32 DefaultBBRMaxCongestionWindow = 10000 ) -func GetInitialPacketSize(addr net.Addr) congestion.ByteCount { - maxSize := congestion.ByteCount(1200) - // If this is not a UDP address, we don't know anything about the MTU. - // Use the minimum size of an Initial packet as the max packet size. - if udpAddr, ok := addr.(*net.UDPAddr); ok { - if udpAddr.IP.To4() != nil { - maxSize = InitialPacketSizeIPv4 - } else { - maxSize = InitialPacketSizeIPv6 - } - } - return congestion.ByteCount(maxSize) -} - var ( // Default initial rtt used before any samples are received. diff --git a/congestion_meta1/cubic.go b/congestion_meta1/cubic.go index d437c54..bc33b59 100644 --- a/congestion_meta1/cubic.go +++ b/congestion_meta1/cubic.go @@ -21,7 +21,7 @@ const ( cubeCongestionWindowScale = 410 cubeFactor congestion.ByteCount = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize // TODO: when re-enabling cubic, make sure to use the actual packet size here - maxDatagramSize = congestion.ByteCount(InitialPacketSizeIPv4) + maxDatagramSize = congestion.ByteCount(congestion.InitialPacketSizeIPv4) ) const defaultNumConnections = 1 diff --git a/congestion_meta2/bbr_sender.go b/congestion_meta2/bbr_sender.go index c377877..37d0bae 100644 --- a/congestion_meta2/bbr_sender.go +++ b/congestion_meta2/bbr_sender.go @@ -5,7 +5,6 @@ package congestion import ( "fmt" "math/rand" - "net" "time" "github.com/sagernet/quic-go/congestion" @@ -929,17 +928,3 @@ func (b *bbrSender) shouldExitStartupDueToLoss(lastPacketSendState *sendTimeStat func bdpFromRttAndBandwidth(rtt time.Duration, bandwidth Bandwidth) congestion.ByteCount { return congestion.ByteCount(rtt) * congestion.ByteCount(bandwidth) / congestion.ByteCount(BytesPerSecond) / congestion.ByteCount(time.Second) } - -func GetInitialPacketSize(addr net.Addr) congestion.ByteCount { - // If this is not a UDP address, we don't know anything about the MTU. - // Use the minimum size of an Initial packet as the max packet size. - if udpAddr, ok := addr.(*net.UDPAddr); ok { - if udpAddr.IP.To4() != nil { - return congestion.InitialPacketSizeIPv4 - } else { - return congestion.InitialPacketSizeIPv6 - } - } else { - return congestion.MinInitialPacketSize - } -} diff --git a/go.mod b/go.mod index 62dfd2a..3024b53 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.20 require ( github.com/gofrs/uuid/v5 v5.2.0 - github.com/sagernet/quic-go v0.43.1-beta.1 - github.com/sagernet/sing v0.4.0-beta.19 + github.com/sagernet/quic-go v0.45.1-beta.2 + github.com/sagernet/sing v0.4.1 golang.org/x/crypto v0.23.0 - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 + golang.org/x/exp v0.0.0-20190121172915-509febef88a4 ) require ( @@ -17,8 +17,7 @@ require ( github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect golang.org/x/net v0.25.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect - golang.org/x/tools v0.21.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect ) diff --git a/go.sum b/go.sum index 2cf7218..dae78fb 100644 --- a/go.sum +++ b/go.sum @@ -6,9 +6,7 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM= github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= @@ -21,29 +19,31 @@ github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/sagernet/quic-go v0.43.1-beta.1 h1:alizUjpvWYcz08dBCQsULOd+1xu0o7UtlyYf6SLbRNg= -github.com/sagernet/quic-go v0.43.1-beta.1/go.mod h1:BkrQYeop7Jx3hN3TW8/76CXcdhYiNPyYEBL/BVJ1ifc= -github.com/sagernet/sing v0.4.0-beta.19 h1:Kzh2f6eaxt09S+bEL8F4Bgy03qkNf+4Tt8g7/5lxp/o= -github.com/sagernet/sing v0.4.0-beta.19/go.mod h1:PFQKbElc2Pke7faBLv8oEba5ehtKO21Ho+TkYemTI3Y= +github.com/sagernet/quic-go v0.45.1-beta.2 h1:zkEeCbhdFFkrxKcuIRBtXNKci/1t2J/39QSG/sPvlmc= +github.com/sagernet/quic-go v0.45.1-beta.2/go.mod h1:+N3FqM9DAzOWfe64uxXuBejVJwX7DeW7BslzLO6N/xI= +github.com/sagernet/sing v0.4.1 h1:zVlpE+7k7AFoC2pv6ReqLf0PIHjihL/jsBl5k05PQFk= +github.com/sagernet/sing v0.4.1/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/hysteria/packet.go b/hysteria/packet.go index d19bbc3..54ee52c 100644 --- a/hysteria/packet.go +++ b/hysteria/packet.go @@ -182,7 +182,7 @@ func (c *udpPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) default: } if buffer.Len() > 0xffff { - return &quic.DatagramTooLargeError{PeerMaxDatagramFrameSize: 0xffff} + return &quic.DatagramTooLargeError{MaxDatagramPayloadSize: 0xffff} } packetId := uint16(c.packetId.Add(1) % math.MaxUint16) message := allocMessage() @@ -208,7 +208,7 @@ func (c *udpPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) if !errors.As(err, &tooLargeErr) { return err } - return c.writePackets(fragUDPMessage(message, int(tooLargeErr.PeerMaxDatagramFrameSize-3))) + return c.writePackets(fragUDPMessage(message, int(tooLargeErr.MaxDatagramPayloadSize-3))) } func (c *udpPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { @@ -218,7 +218,7 @@ func (c *udpPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { default: } if len(p) > 0xffff { - return 0, &quic.DatagramTooLargeError{PeerMaxDatagramFrameSize: 0xffff} + return 0, &quic.DatagramTooLargeError{MaxDatagramPayloadSize: 0xffff} } packetId := uint16(c.packetId.Add(1) % math.MaxUint16) message := allocMessage() @@ -246,7 +246,7 @@ func (c *udpPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { if !errors.As(err, &tooLargeErr) { return } - err = c.writePackets(fragUDPMessage(message, int(tooLargeErr.PeerMaxDatagramFrameSize-3))) + err = c.writePackets(fragUDPMessage(message, int(tooLargeErr.MaxDatagramPayloadSize-3))) if err == nil { return len(p), nil } diff --git a/hysteria2/client.go b/hysteria2/client.go index 894aa0c..981f123 100644 --- a/hysteria2/client.go +++ b/hysteria2/client.go @@ -166,7 +166,7 @@ func (c *Client) offerNew(ctx context.Context) (*clientQUICConnection, error) { } quicConn.SetCongestionControl(congestion_meta2.NewBbrSender( congestion_meta2.DefaultClock{TimeFunc: timeFunc}, - congestion_meta2.GetInitialPacketSize(quicConn.RemoteAddr()), + congestion.ByteCount(quicConn.Config().InitialPacketSize), congestion.ByteCount(congestion_meta1.InitialCongestionWindow), )) } diff --git a/hysteria2/packet.go b/hysteria2/packet.go index a314808..5b54fce 100644 --- a/hysteria2/packet.go +++ b/hysteria2/packet.go @@ -178,7 +178,7 @@ func (c *udpPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) default: } if buffer.Len() > 0xffff { - return &quic.DatagramTooLargeError{PeerMaxDatagramFrameSize: 0xffff} + return &quic.DatagramTooLargeError{MaxDatagramPayloadSize: 0xffff} } packetId := uint16(c.packetId.Add(1) % math.MaxUint16) message := allocMessage() @@ -203,7 +203,7 @@ func (c *udpPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) if !errors.As(err, &tooLargeErr) { return err } - return c.writePackets(fragUDPMessage(message, int(tooLargeErr.PeerMaxDatagramFrameSize-3))) + return c.writePackets(fragUDPMessage(message, int(tooLargeErr.MaxDatagramPayloadSize-3))) } func (c *udpPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { @@ -213,7 +213,7 @@ func (c *udpPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { default: } if len(p) > 0xffff { - return 0, &quic.DatagramTooLargeError{PeerMaxDatagramFrameSize: 0xffff} + return 0, &quic.DatagramTooLargeError{MaxDatagramPayloadSize: 0xffff} } packetId := uint16(c.packetId.Add(1) % math.MaxUint16) message := allocMessage() @@ -239,7 +239,7 @@ func (c *udpPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { if !errors.As(err, &tooLargeErr) { return } - err = c.writePackets(fragUDPMessage(message, int(tooLargeErr.PeerMaxDatagramFrameSize-3))) + err = c.writePackets(fragUDPMessage(message, int(tooLargeErr.MaxDatagramPayloadSize-3))) if err == nil { return len(p), nil } diff --git a/hysteria2/service.go b/hysteria2/service.go index ed54963..d9c6eb6 100644 --- a/hysteria2/service.go +++ b/hysteria2/service.go @@ -214,7 +214,7 @@ func (s *serverSession[U]) ServeHTTP(w http.ResponseWriter, r *http.Request) { } s.quicConn.SetCongestionControl(congestion_meta2.NewBbrSender( congestion_meta2.DefaultClock{TimeFunc: timeFunc}, - congestion_meta2.GetInitialPacketSize(s.quicConn.RemoteAddr()), + congestion.ByteCount(s.quicConn.Config().InitialPacketSize), congestion.ByteCount(congestion_meta1.InitialCongestionWindow), )) } diff --git a/tuic/congestion.go b/tuic/congestion.go index e6aae31..c407d46 100644 --- a/tuic/congestion.go +++ b/tuic/congestion.go @@ -21,7 +21,7 @@ func setCongestion(ctx context.Context, connection quic.Connection, congestionNa connection.SetCongestionControl( congestion_meta1.NewCubicSender( congestion_meta1.DefaultClock{TimeFunc: timeFunc}, - congestion_meta1.GetInitialPacketSize(connection.RemoteAddr()), + congestion.ByteCount(connection.Config().InitialPacketSize), false, nil, ), @@ -30,7 +30,7 @@ func setCongestion(ctx context.Context, connection quic.Connection, congestionNa connection.SetCongestionControl( congestion_meta1.NewCubicSender( congestion_meta1.DefaultClock{TimeFunc: timeFunc}, - congestion_meta1.GetInitialPacketSize(connection.RemoteAddr()), + congestion.ByteCount(connection.Config().InitialPacketSize), true, nil, ), @@ -38,14 +38,14 @@ func setCongestion(ctx context.Context, connection quic.Connection, congestionNa case "bbr_meta_v1": connection.SetCongestionControl(congestion_meta1.NewBBRSender( congestion_meta1.DefaultClock{TimeFunc: timeFunc}, - congestion_meta1.GetInitialPacketSize(connection.RemoteAddr()), + congestion.ByteCount(connection.Config().InitialPacketSize), congestion_meta1.InitialCongestionWindow*congestion_meta1.InitialMaxDatagramSize, congestion_meta1.DefaultBBRMaxCongestionWindow*congestion_meta1.InitialMaxDatagramSize, )) case "bbr": connection.SetCongestionControl(congestion_meta2.NewBbrSender( congestion_meta2.DefaultClock{TimeFunc: timeFunc}, - congestion_meta2.GetInitialPacketSize(connection.RemoteAddr()), + congestion.ByteCount(connection.Config().InitialPacketSize), congestion.ByteCount(congestion_meta1.InitialCongestionWindow), )) } diff --git a/tuic/packet.go b/tuic/packet.go index 5b49591..306f63b 100644 --- a/tuic/packet.go +++ b/tuic/packet.go @@ -187,7 +187,7 @@ func (c *udpPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) default: } if buffer.Len() > 0xffff { - return &quic.DatagramTooLargeError{PeerMaxDatagramFrameSize: 0xffff} + return &quic.DatagramTooLargeError{MaxDatagramPayloadSize: 0xffff} } if !destination.IsValid() { return E.New("invalid destination address") @@ -215,7 +215,7 @@ func (c *udpPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) if !errors.As(err, &tooLargeErr) { return err } - c.udpMTU = int(tooLargeErr.PeerMaxDatagramFrameSize) - 3 + c.udpMTU = int(tooLargeErr.MaxDatagramPayloadSize) - 3 return c.writePackets(fragUDPMessage(message, c.udpMTU)) } @@ -226,7 +226,7 @@ func (c *udpPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { default: } if len(p) > 0xffff { - return 0, &quic.DatagramTooLargeError{PeerMaxDatagramFrameSize: 0xffff} + return 0, &quic.DatagramTooLargeError{MaxDatagramPayloadSize: 0xffff} } destination := M.SocksaddrFromNet(addr) if !destination.IsValid() { @@ -256,7 +256,7 @@ func (c *udpPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { if !errors.As(err, &tooLargeErr) { return } - c.udpMTU = int(tooLargeErr.PeerMaxDatagramFrameSize) - 3 + c.udpMTU = int(tooLargeErr.MaxDatagramPayloadSize) - 3 err = c.writePackets(fragUDPMessage(message, c.udpMTU)) if err == nil { return len(p), nil