Merge pull request #2090 from lucas-clemente/h3-alpn-handling

rework H3 ALPN handling
This commit is contained in:
Marten Seemann
2019-08-31 17:32:12 +07:00
committed by GitHub
4 changed files with 57 additions and 25 deletions

View File

@@ -57,10 +57,11 @@ func newClient(
) *client {
if tlsConf == nil {
tlsConf = &tls.Config{}
} else {
tlsConf = tlsConf.Clone()
}
if !strSliceContains(tlsConf.NextProtos, nextProtoH3) {
tlsConf.NextProtos = append(tlsConf.NextProtos, nextProtoH3)
}
// Replace existing ALPNs by H3
tlsConf.NextProtos = []string{nextProtoH3}
if quicConfig == nil {
quicConfig = defaultQuicConfig
}

View File

@@ -85,13 +85,15 @@ var _ = Describe("Client", func() {
) (quic.Session, error) {
Expect(hostname).To(Equal("localhost:1337"))
Expect(tlsConfP.ServerName).To(Equal(tlsConf.ServerName))
Expect(tlsConfP.NextProtos).To(Equal([]string{"proto foo", "proto bar", nextProtoH3}))
Expect(tlsConfP.NextProtos).To(Equal([]string{nextProtoH3}))
Expect(quicConfP.IdleTimeout).To(Equal(quicConf.IdleTimeout))
dialAddrCalled = true
return nil, errors.New("test done")
}
client.RoundTrip(req)
Expect(dialAddrCalled).To(BeTrue())
// make sure the original tls.Config was not modified
Expect(tlsConf.NextProtos).To(Equal([]string{"proto foo", "proto bar"}))
})
It("uses the custom dialer, if provided", func() {
@@ -102,7 +104,7 @@ var _ = Describe("Client", func() {
dialer := func(network, address string, tlsConfP *tls.Config, quicConfP *quic.Config) (quic.Session, error) {
Expect(network).To(Equal("udp"))
Expect(address).To(Equal("localhost:1337"))
Expect(tlsConfP).To(Equal(tlsConf))
Expect(tlsConfP.ServerName).To(Equal("foo.bar"))
Expect(quicConfP.IdleTimeout).To(Equal(quicConf.IdleTimeout))
dialerCalled = true
return nil, testErr

View File

@@ -77,7 +77,7 @@ func (s *Server) Serve(conn net.PacketConn) error {
return s.serveImpl(s.TLSConfig, conn)
}
func (s *Server) serveImpl(tlsConfig *tls.Config, conn net.PacketConn) error {
func (s *Server) serveImpl(tlsConf *tls.Config, conn net.PacketConn) error {
if s.Server == nil {
return errors.New("use of http3.Server without http.Server")
}
@@ -92,20 +92,31 @@ func (s *Server) serveImpl(tlsConfig *tls.Config, conn net.PacketConn) error {
return errors.New("ListenAndServe may only be called once")
}
if tlsConfig == nil {
tlsConfig = &tls.Config{}
if tlsConf == nil {
tlsConf = &tls.Config{}
} else {
tlsConf = tlsConf.Clone()
}
if !strSliceContains(tlsConfig.NextProtos, nextProtoH3) {
tlsConfig.NextProtos = append(tlsConfig.NextProtos, nextProtoH3)
// Replace existing ALPNs by H3
tlsConf.NextProtos = []string{nextProtoH3}
if tlsConf.GetConfigForClient != nil {
getConfigForClient := tlsConf.GetConfigForClient
tlsConf.GetConfigForClient = func(ch *tls.ClientHelloInfo) (*tls.Config, error) {
conf, err := getConfigForClient(ch)
if err != nil || conf == nil {
return conf, err
}
conf.NextProtos = []string{nextProtoH3}
return conf, nil
}
}
var ln quic.Listener
var err error
if conn == nil {
ln, err = quicListenAddr(s.Addr, tlsConfig, s.QuicConfig)
ln, err = quicListenAddr(s.Addr, tlsConf, s.QuicConfig)
} else {
ln, err = quicListen(conn, tlsConfig, s.QuicConfig)
ln, err = quicListen(conn, tlsConf, s.QuicConfig)
}
if err != nil {
s.listenerMutex.Unlock()
@@ -385,12 +396,3 @@ func ListenAndServe(addr, certFile, keyFile string, handler http.Handler) error
return err
}
}
func strSliceContains(ss []string, s string) bool {
for _, v := range ss {
if v == s {
return true
}
}
return false
}

View File

@@ -383,15 +383,18 @@ var _ = Describe("Server", func() {
Expect(receivedConf).To(Equal(conf))
})
It("adds the ALPN token to the tls.Config", func() {
It("replaces the ALPN token to the tls.Config", func() {
tlsConf := &tls.Config{NextProtos: []string{"foo", "bar"}}
var receivedConf *tls.Config
quicListenAddr = func(addr string, tlsConf *tls.Config, _ *quic.Config) (quic.Listener, error) {
receivedConf = tlsConf
return nil, errors.New("listen err")
}
s.TLSConfig = &tls.Config{NextProtos: []string{"foo", "bar"}}
s.TLSConfig = tlsConf
Expect(s.ListenAndServe()).To(HaveOccurred())
Expect(receivedConf.NextProtos).To(Equal([]string{"foo", "bar", nextProtoH3}))
Expect(receivedConf.NextProtos).To(Equal([]string{nextProtoH3}))
// make sure the original tls.Config was not modified
Expect(tlsConf.NextProtos).To(Equal([]string{"foo", "bar"}))
})
It("uses the ALPN token if no tls.Config is given", func() {
@@ -403,6 +406,30 @@ var _ = Describe("Server", func() {
Expect(s.ListenAndServe()).To(HaveOccurred())
Expect(receivedConf.NextProtos).To(Equal([]string{nextProtoH3}))
})
It("sets the ALPN for tls.Configs returned by the tls.GetConfigForClient", func() {
tlsConf := &tls.Config{
GetConfigForClient: func(ch *tls.ClientHelloInfo) (*tls.Config, error) {
return &tls.Config{NextProtos: []string{"foo", "bar"}}, nil
},
}
var receivedConf *tls.Config
quicListenAddr = func(addr string, conf *tls.Config, _ *quic.Config) (quic.Listener, error) {
receivedConf = conf
return nil, errors.New("listen err")
}
s.TLSConfig = tlsConf
Expect(s.ListenAndServe()).To(HaveOccurred())
// check that the config used by QUIC uses the h3 ALPN
conf, err := receivedConf.GetConfigForClient(&tls.ClientHelloInfo{})
Expect(err).ToNot(HaveOccurred())
Expect(conf.NextProtos).To(Equal([]string{nextProtoH3}))
// check that the original config was not modified
conf, err = tlsConf.GetConfigForClient(&tls.ClientHelloInfo{})
Expect(err).ToNot(HaveOccurred())
Expect(conf.NextProtos).To(Equal([]string{"foo", "bar"}))
})
})
Context("ListenAndServeTLS", func() {