Skip to content

Commit 0ca138b

Browse files
use new quic-go API
1 parent c47486b commit 0ca138b

File tree

11 files changed

+345
-338
lines changed

11 files changed

+345
-338
lines changed

client.go

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ func (d *Dialer) init() {
6363
func (d *Dialer) Dial(ctx context.Context, urlStr string, reqHdr http.Header) (*http.Response, *Session, error) {
6464
d.initOnce.Do(func() { d.init() })
6565

66-
// Technically, this is not true. DATAGRAMs could be sent using the Capsule protocol.
67-
// However, quic-go currently enforces QUIC datagram support if HTTP/3 datagrams are enabled.
6866
quicConf := d.QUICConfig
6967
if quicConf == nil {
7068
quicConf = &quic.Config{EnableDatagrams: true}
@@ -117,35 +115,65 @@ func (d *Dialer) Dial(ctx context.Context, urlStr string, reqHdr http.Header) (*
117115
if err != nil {
118116
return nil, nil, err
119117
}
120-
tr := &http3.Transport{
121-
EnableDatagrams: true,
122-
StreamHijacker: func(ft http3.FrameType, connTracingID quic.ConnectionTracingID, str *quic.Stream, e error) (hijacked bool, err error) {
123-
if isWebTransportError(e) {
124-
return true, nil
125-
}
126-
if ft != webTransportFrameType {
127-
return false, nil
128-
}
129-
id, err := quicvarint.Read(quicvarint.NewReader(str))
118+
tr := &http3.Transport{EnableDatagrams: true}
119+
120+
conn := tr.NewRawClientConn(qconn)
121+
122+
go func() {
123+
for {
124+
str, err := qconn.AcceptStream(context.Background())
130125
if err != nil {
131-
if isWebTransportError(err) {
132-
return true, nil
133-
}
134-
return false, err
126+
return
135127
}
136-
d.conns.AddStream(connTracingID, str, sessionID(id))
137-
return true, nil
138-
},
139-
UniStreamHijacker: func(st http3.StreamType, connTracingID quic.ConnectionTracingID, str *quic.ReceiveStream, err error) (hijacked bool) {
140-
if st != webTransportUniStreamType && !isWebTransportError(err) {
141-
return false
128+
129+
go func() {
130+
typ, err := quicvarint.Peek(str)
131+
if err != nil {
132+
return
133+
}
134+
if typ != webTransportFrameType {
135+
conn.HandleBidirectionalStream(str)
136+
return
137+
}
138+
// read the frame type (already peeked above)
139+
if _, err := quicvarint.Read(quicvarint.NewReader(str)); err != nil {
140+
return
141+
}
142+
// read the session ID
143+
id, err := quicvarint.Read(quicvarint.NewReader(str))
144+
if err != nil {
145+
return
146+
}
147+
d.conns.AddStream(qconn, str, sessionID(id))
148+
}()
149+
}
150+
}()
151+
152+
go func() {
153+
for {
154+
str, err := qconn.AcceptUniStream(context.Background())
155+
if err != nil {
156+
return
142157
}
143-
d.conns.AddUniStream(connTracingID, str)
144-
return true
145-
},
146-
}
147158

148-
conn := tr.NewClientConn(qconn)
159+
go func() {
160+
typ, err := quicvarint.Peek(str)
161+
if err != nil {
162+
return
163+
}
164+
if typ != webTransportUniStreamType {
165+
conn.HandleUnidirectionalStream(str)
166+
return
167+
}
168+
// read the stream type (already peeked above)
169+
if _, err := quicvarint.Read(quicvarint.NewReader(str)); err != nil {
170+
return
171+
}
172+
d.conns.AddUniStream(qconn, str)
173+
}()
174+
}
175+
}()
176+
149177
select {
150178
case <-conn.ReceivedSettings():
151179
case <-ctx.Done():
@@ -168,7 +196,7 @@ func (d *Dialer) Dial(ctx context.Context, urlStr string, reqHdr http.Header) (*
168196
return nil, nil, errNoWebTransport
169197
}
170198

171-
requestStr, err := conn.OpenRequestStream(ctx) // TODO: put this on the Connection (maybe introduce a ClientConnection?)
199+
requestStr, err := conn.OpenRequestStream(ctx)
172200
if err != nil {
173201
return nil, nil, err
174202
}
@@ -188,7 +216,7 @@ func (d *Dialer) Dial(ctx context.Context, urlStr string, reqHdr http.Header) (*
188216
protocol = d.negotiateProtocol(protocolHeader)
189217
}
190218
sessID := sessionID(requestStr.StreamID())
191-
return rsp, d.conns.AddSession(context.WithoutCancel(ctx), conn.Conn(), sessID, requestStr, protocol), nil
219+
return rsp, d.conns.AddSession(context.WithoutCancel(ctx), qconn, sessID, requestStr, protocol), nil
192220
}
193221

194222
func (d *Dialer) negotiateProtocol(theirs []string) string {

errors.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,6 @@ func httpCodeToWebtransportCode(h quic.StreamErrorCode) (StreamErrorCode, error)
3333
return StreamErrorCode(shifted - shifted/0x1f), nil
3434
}
3535

36-
func isWebTransportError(e error) bool {
37-
if e == nil {
38-
return false
39-
}
40-
var strErr *quic.StreamError
41-
if !errors.As(e, &strErr) {
42-
return false
43-
}
44-
if strErr.ErrorCode == WTSessionGoneErrorCode {
45-
return true
46-
}
47-
_, err := httpCodeToWebtransportCode(strErr.ErrorCode)
48-
return err == nil
49-
}
50-
5136
const (
5237
// WTBufferedStreamRejectedErrorCode is the error code of the
5338
// WT_BUFFERED_STREAM_REJECTED error.

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.24
44

55
require (
66
github.com/dunglas/httpsfv v1.1.0
7-
github.com/quic-go/quic-go v0.57.1
7+
github.com/quic-go/quic-go v0.58.1-0.20260103101554-29b1a154ebc8
88
github.com/stretchr/testify v1.11.1
99
)
1010

go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
1111
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1212
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
1313
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
14-
github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10=
15-
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
14+
github.com/quic-go/quic-go v0.58.1-0.20260103101554-29b1a154ebc8 h1:5tj3IFn2lUw0063zA+91YC8Vsg2uTbJEggwOcmi5xMA=
15+
github.com/quic-go/quic-go v0.58.1-0.20260103101554-29b1a154ebc8/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
1616
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
1717
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
1818
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
@@ -27,8 +27,6 @@ golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
2727
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
2828
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
2929
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
30-
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
31-
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
3230
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3331
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
3432
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

interop/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func main() {
5353
},
5454
CheckOrigin: func(r *http.Request) bool { return true },
5555
}
56+
webtransport.ConfigureHTTP3Server(s.H3)
5657
defer s.Close()
5758

5859
wmux.HandleFunc("/unidirectional", func(w http.ResponseWriter, r *http.Request) {
@@ -111,13 +112,13 @@ func getTLSConf(start, end time.Time) (*tls.Config, error) {
111112
if err != nil {
112113
return nil, err
113114
}
114-
return &tls.Config{
115+
return http3.ConfigureTLSConfig(&tls.Config{
115116
Certificates: []tls.Certificate{{
116117
Certificate: [][]byte{cert.Raw},
117118
PrivateKey: priv,
118119
Leaf: cert,
119120
}},
120-
}, nil
121+
}), nil
121122
}
122123

123124
func generateCert(start, end time.Time) (*x509.Certificate, *ecdsa.PrivateKey, error) {

0 commit comments

Comments
 (0)