github.com/quic-go/quic-go@v0.44.0/http3/server.go (about) 1 package http3 2 3 import ( 4 "context" 5 "crypto/tls" 6 "errors" 7 "fmt" 8 "io" 9 "log/slog" 10 "net" 11 "net/http" 12 "runtime" 13 "strconv" 14 "strings" 15 "sync" 16 "time" 17 18 "github.com/quic-go/quic-go" 19 "github.com/quic-go/quic-go/internal/protocol" 20 "github.com/quic-go/quic-go/quicvarint" 21 22 "github.com/quic-go/qpack" 23 ) 24 25 // allows mocking of quic.Listen and quic.ListenAddr 26 var ( 27 quicListen = func(conn net.PacketConn, tlsConf *tls.Config, config *quic.Config) (QUICEarlyListener, error) { 28 return quic.ListenEarly(conn, tlsConf, config) 29 } 30 quicListenAddr = func(addr string, tlsConf *tls.Config, config *quic.Config) (QUICEarlyListener, error) { 31 return quic.ListenAddrEarly(addr, tlsConf, config) 32 } 33 ) 34 35 // NextProtoH3 is the ALPN protocol negotiated during the TLS handshake, for QUIC v1 and v2. 36 const NextProtoH3 = "h3" 37 38 // StreamType is the stream type of a unidirectional stream. 39 type StreamType uint64 40 41 const ( 42 streamTypeControlStream = 0 43 streamTypePushStream = 1 44 streamTypeQPACKEncoderStream = 2 45 streamTypeQPACKDecoderStream = 3 46 ) 47 48 // A QUICEarlyListener listens for incoming QUIC connections. 49 type QUICEarlyListener interface { 50 Accept(context.Context) (quic.EarlyConnection, error) 51 Addr() net.Addr 52 io.Closer 53 } 54 55 var _ QUICEarlyListener = &quic.EarlyListener{} 56 57 func versionToALPN(v protocol.Version) string { 58 //nolint:exhaustive // These are all the versions we care about. 59 switch v { 60 case protocol.Version1, protocol.Version2: 61 return NextProtoH3 62 default: 63 return "" 64 } 65 } 66 67 // ConfigureTLSConfig creates a new tls.Config which can be used 68 // to create a quic.Listener meant for serving http3. The created 69 // tls.Config adds the functionality of detecting the used QUIC version 70 // in order to set the correct ALPN value for the http3 connection. 71 func ConfigureTLSConfig(tlsConf *tls.Config) *tls.Config { 72 // The tls.Config used to setup the quic.Listener needs to have the GetConfigForClient callback set. 73 // That way, we can get the QUIC version and set the correct ALPN value. 74 return &tls.Config{ 75 GetConfigForClient: func(ch *tls.ClientHelloInfo) (*tls.Config, error) { 76 // determine the ALPN from the QUIC version used 77 proto := NextProtoH3 78 val := ch.Context().Value(quic.QUICVersionContextKey) 79 if v, ok := val.(quic.Version); ok { 80 proto = versionToALPN(v) 81 } 82 config := tlsConf 83 if tlsConf.GetConfigForClient != nil { 84 getConfigForClient := tlsConf.GetConfigForClient 85 var err error 86 conf, err := getConfigForClient(ch) 87 if err != nil { 88 return nil, err 89 } 90 if conf != nil { 91 config = conf 92 } 93 } 94 if config == nil { 95 return nil, nil 96 } 97 config = config.Clone() 98 config.NextProtos = []string{proto} 99 return config, nil 100 }, 101 } 102 } 103 104 // contextKey is a value for use with context.WithValue. It's used as 105 // a pointer so it fits in an interface{} without allocation. 106 type contextKey struct { 107 name string 108 } 109 110 func (k *contextKey) String() string { return "quic-go/http3 context value " + k.name } 111 112 // ServerContextKey is a context key. It can be used in HTTP 113 // handlers with Context.Value to access the server that 114 // started the handler. The associated value will be of 115 // type *http3.Server. 116 var ServerContextKey = &contextKey{"http3-server"} 117 118 // RemoteAddrContextKey is a context key. It can be used in 119 // HTTP handlers with Context.Value to access the remote 120 // address of the connection. The associated value will be of 121 // type net.Addr. 122 // 123 // Use this value instead of [http.Request.RemoteAddr] if you 124 // require access to the remote address of the connection rather 125 // than its string representation. 126 var RemoteAddrContextKey = &contextKey{"remote-addr"} 127 128 // listenerInfo contains info about specific listener added with addListener 129 type listenerInfo struct { 130 port int // 0 means that no info about port is available 131 } 132 133 // Server is a HTTP/3 server. 134 type Server struct { 135 // Addr optionally specifies the UDP address for the server to listen on, 136 // in the form "host:port". 137 // 138 // When used by ListenAndServe and ListenAndServeTLS methods, if empty, 139 // ":https" (port 443) is used. See net.Dial for details of the address 140 // format. 141 // 142 // Otherwise, if Port is not set and underlying QUIC listeners do not 143 // have valid port numbers, the port part is used in Alt-Svc headers set 144 // with SetQUICHeaders. 145 Addr string 146 147 // Port is used in Alt-Svc response headers set with SetQUICHeaders. If 148 // needed Port can be manually set when the Server is created. 149 // 150 // This is useful when a Layer 4 firewall is redirecting UDP traffic and 151 // clients must use a port different from the port the Server is 152 // listening on. 153 Port int 154 155 // TLSConfig provides a TLS configuration for use by server. It must be 156 // set for ListenAndServe and Serve methods. 157 TLSConfig *tls.Config 158 159 // QUICConfig provides the parameters for QUIC connection created with Serve. 160 // If nil, it uses reasonable default values. 161 // 162 // Configured versions are also used in Alt-Svc response header set with SetQUICHeaders. 163 QUICConfig *quic.Config 164 165 // Handler is the HTTP request handler to use. If not set, defaults to 166 // http.NotFound. 167 Handler http.Handler 168 169 // EnableDatagrams enables support for HTTP/3 datagrams (RFC 9297). 170 // If set to true, QUICConfig.EnableDatagrams will be set. 171 EnableDatagrams bool 172 173 // MaxHeaderBytes controls the maximum number of bytes the server will 174 // read parsing the request HEADERS frame. It does not limit the size of 175 // the request body. If zero or negative, http.DefaultMaxHeaderBytes is 176 // used. 177 MaxHeaderBytes int 178 179 // AdditionalSettings specifies additional HTTP/3 settings. 180 // It is invalid to specify any settings defined by RFC 9114 (HTTP/3) and RFC 9297 (HTTP Datagrams). 181 AdditionalSettings map[uint64]uint64 182 183 // StreamHijacker, when set, is called for the first unknown frame parsed on a bidirectional stream. 184 // It is called right after parsing the frame type. 185 // If parsing the frame type fails, the error is passed to the callback. 186 // In that case, the frame type will not be set. 187 // Callers can either ignore the frame and return control of the stream back to HTTP/3 188 // (by returning hijacked false). 189 // Alternatively, callers can take over the QUIC stream (by returning hijacked true). 190 StreamHijacker func(FrameType, quic.ConnectionTracingID, quic.Stream, error) (hijacked bool, err error) 191 192 // UniStreamHijacker, when set, is called for unknown unidirectional stream of unknown stream type. 193 // If parsing the stream type fails, the error is passed to the callback. 194 // In that case, the stream type will not be set. 195 UniStreamHijacker func(StreamType, quic.ConnectionTracingID, quic.ReceiveStream, error) (hijacked bool) 196 197 // ConnContext optionally specifies a function that modifies 198 // the context used for a new connection c. The provided ctx 199 // has a ServerContextKey value. 200 ConnContext func(ctx context.Context, c quic.Connection) context.Context 201 202 Logger *slog.Logger 203 204 mutex sync.RWMutex 205 listeners map[*QUICEarlyListener]listenerInfo 206 207 closed bool 208 209 altSvcHeader string 210 } 211 212 // ListenAndServe listens on the UDP address s.Addr and calls s.Handler to handle HTTP/3 requests on incoming connections. 213 // 214 // If s.Addr is blank, ":https" is used. 215 func (s *Server) ListenAndServe() error { 216 return s.serveConn(s.TLSConfig, nil) 217 } 218 219 // ListenAndServeTLS listens on the UDP address s.Addr and calls s.Handler to handle HTTP/3 requests on incoming connections. 220 // 221 // If s.Addr is blank, ":https" is used. 222 func (s *Server) ListenAndServeTLS(certFile, keyFile string) error { 223 var err error 224 certs := make([]tls.Certificate, 1) 225 certs[0], err = tls.LoadX509KeyPair(certFile, keyFile) 226 if err != nil { 227 return err 228 } 229 // We currently only use the cert-related stuff from tls.Config, 230 // so we don't need to make a full copy. 231 config := &tls.Config{ 232 Certificates: certs, 233 } 234 return s.serveConn(config, nil) 235 } 236 237 // Serve an existing UDP connection. 238 // It is possible to reuse the same connection for outgoing connections. 239 // Closing the server does not close the connection. 240 func (s *Server) Serve(conn net.PacketConn) error { 241 return s.serveConn(s.TLSConfig, conn) 242 } 243 244 // ServeQUICConn serves a single QUIC connection. 245 func (s *Server) ServeQUICConn(conn quic.Connection) error { 246 return s.handleConn(conn) 247 } 248 249 // ServeListener serves an existing QUIC listener. 250 // Make sure you use http3.ConfigureTLSConfig to configure a tls.Config 251 // and use it to construct a http3-friendly QUIC listener. 252 // Closing the server does close the listener. 253 // ServeListener always returns a non-nil error. After Shutdown or Close, the returned error is http.ErrServerClosed. 254 func (s *Server) ServeListener(ln QUICEarlyListener) error { 255 if err := s.addListener(&ln); err != nil { 256 return err 257 } 258 defer s.removeListener(&ln) 259 for { 260 conn, err := ln.Accept(context.Background()) 261 if err == quic.ErrServerClosed { 262 return http.ErrServerClosed 263 } 264 if err != nil { 265 return err 266 } 267 go func() { 268 if err := s.handleConn(conn); err != nil { 269 if s.Logger != nil { 270 s.Logger.Debug("handling connection failed", "error", err) 271 } 272 } 273 }() 274 } 275 } 276 277 var errServerWithoutTLSConfig = errors.New("use of http3.Server without TLSConfig") 278 279 func (s *Server) serveConn(tlsConf *tls.Config, conn net.PacketConn) error { 280 if tlsConf == nil { 281 return errServerWithoutTLSConfig 282 } 283 284 s.mutex.Lock() 285 closed := s.closed 286 s.mutex.Unlock() 287 if closed { 288 return http.ErrServerClosed 289 } 290 291 baseConf := ConfigureTLSConfig(tlsConf) 292 quicConf := s.QUICConfig 293 if quicConf == nil { 294 quicConf = &quic.Config{Allow0RTT: true} 295 } else { 296 quicConf = s.QUICConfig.Clone() 297 } 298 if s.EnableDatagrams { 299 quicConf.EnableDatagrams = true 300 } 301 302 var ln QUICEarlyListener 303 var err error 304 if conn == nil { 305 addr := s.Addr 306 if addr == "" { 307 addr = ":https" 308 } 309 ln, err = quicListenAddr(addr, baseConf, quicConf) 310 } else { 311 ln, err = quicListen(conn, baseConf, quicConf) 312 } 313 if err != nil { 314 return err 315 } 316 return s.ServeListener(ln) 317 } 318 319 func extractPort(addr string) (int, error) { 320 _, portStr, err := net.SplitHostPort(addr) 321 if err != nil { 322 return 0, err 323 } 324 325 portInt, err := net.LookupPort("tcp", portStr) 326 if err != nil { 327 return 0, err 328 } 329 return portInt, nil 330 } 331 332 func (s *Server) generateAltSvcHeader() { 333 if len(s.listeners) == 0 { 334 // Don't announce any ports since no one is listening for connections 335 s.altSvcHeader = "" 336 return 337 } 338 339 // This code assumes that we will use protocol.SupportedVersions if no quic.Config is passed. 340 supportedVersions := protocol.SupportedVersions 341 if s.QUICConfig != nil && len(s.QUICConfig.Versions) > 0 { 342 supportedVersions = s.QUICConfig.Versions 343 } 344 345 // keep track of which have been seen so we don't yield duplicate values 346 seen := make(map[string]struct{}, len(supportedVersions)) 347 var versionStrings []string 348 for _, version := range supportedVersions { 349 if v := versionToALPN(version); len(v) > 0 { 350 if _, ok := seen[v]; !ok { 351 versionStrings = append(versionStrings, v) 352 seen[v] = struct{}{} 353 } 354 } 355 } 356 357 var altSvc []string 358 addPort := func(port int) { 359 for _, v := range versionStrings { 360 altSvc = append(altSvc, fmt.Sprintf(`%s=":%d"; ma=2592000`, v, port)) 361 } 362 } 363 364 if s.Port != 0 { 365 // if Port is specified, we must use it instead of the 366 // listener addresses since there's a reason it's specified. 367 addPort(s.Port) 368 } else { 369 // if we have some listeners assigned, try to find ports 370 // which we can announce, otherwise nothing should be announced 371 validPortsFound := false 372 for _, info := range s.listeners { 373 if info.port != 0 { 374 addPort(info.port) 375 validPortsFound = true 376 } 377 } 378 if !validPortsFound { 379 if port, err := extractPort(s.Addr); err == nil { 380 addPort(port) 381 } 382 } 383 } 384 385 s.altSvcHeader = strings.Join(altSvc, ",") 386 } 387 388 // We store a pointer to interface in the map set. This is safe because we only 389 // call trackListener via Serve and can track+defer untrack the same pointer to 390 // local variable there. We never need to compare a Listener from another caller. 391 func (s *Server) addListener(l *QUICEarlyListener) error { 392 s.mutex.Lock() 393 defer s.mutex.Unlock() 394 395 if s.closed { 396 return http.ErrServerClosed 397 } 398 if s.listeners == nil { 399 s.listeners = make(map[*QUICEarlyListener]listenerInfo) 400 } 401 402 laddr := (*l).Addr() 403 if port, err := extractPort(laddr.String()); err == nil { 404 s.listeners[l] = listenerInfo{port} 405 } else { 406 logger := s.Logger 407 if logger == nil { 408 logger = slog.Default() 409 } 410 logger.Error("Unable to extract port from listener, will not be announced using SetQUICHeaders", "local addr", laddr, "error", err) 411 s.listeners[l] = listenerInfo{} 412 } 413 s.generateAltSvcHeader() 414 return nil 415 } 416 417 func (s *Server) removeListener(l *QUICEarlyListener) { 418 s.mutex.Lock() 419 defer s.mutex.Unlock() 420 delete(s.listeners, l) 421 s.generateAltSvcHeader() 422 } 423 424 func (s *Server) handleConn(conn quic.Connection) error { 425 // send a SETTINGS frame 426 str, err := conn.OpenUniStream() 427 if err != nil { 428 return fmt.Errorf("opening the control stream failed: %w", err) 429 } 430 b := make([]byte, 0, 64) 431 b = quicvarint.Append(b, streamTypeControlStream) // stream type 432 b = (&settingsFrame{ 433 Datagram: s.EnableDatagrams, 434 ExtendedConnect: true, 435 Other: s.AdditionalSettings, 436 }).Append(b) 437 str.Write(b) 438 439 hconn := newConnection( 440 conn, 441 s.EnableDatagrams, 442 protocol.PerspectiveServer, 443 s.Logger, 444 ) 445 go hconn.HandleUnidirectionalStreams(s.UniStreamHijacker) 446 // Process all requests immediately. 447 // It's the client's responsibility to decide which requests are eligible for 0-RTT. 448 for { 449 str, datagrams, err := hconn.acceptStream(context.Background()) 450 if err != nil { 451 var appErr *quic.ApplicationError 452 if errors.As(err, &appErr) && appErr.ErrorCode == quic.ApplicationErrorCode(ErrCodeNoError) { 453 return nil 454 } 455 return fmt.Errorf("accepting stream failed: %w", err) 456 } 457 go s.handleRequest(hconn, str, datagrams, hconn.decoder) 458 } 459 } 460 461 func (s *Server) maxHeaderBytes() uint64 { 462 if s.MaxHeaderBytes <= 0 { 463 return http.DefaultMaxHeaderBytes 464 } 465 return uint64(s.MaxHeaderBytes) 466 } 467 468 func (s *Server) handleRequest(conn *connection, str quic.Stream, datagrams *datagrammer, decoder *qpack.Decoder) { 469 var ufh unknownFrameHandlerFunc 470 if s.StreamHijacker != nil { 471 ufh = func(ft FrameType, e error) (processed bool, err error) { 472 return s.StreamHijacker( 473 ft, 474 conn.Context().Value(quic.ConnectionTracingKey).(quic.ConnectionTracingID), 475 str, 476 e, 477 ) 478 } 479 } 480 fp := &frameParser{conn: conn, r: str, unknownFrameHandler: ufh} 481 frame, err := fp.ParseNext() 482 if err != nil { 483 if !errors.Is(err, errHijacked) { 484 str.CancelRead(quic.StreamErrorCode(ErrCodeRequestIncomplete)) 485 str.CancelWrite(quic.StreamErrorCode(ErrCodeRequestIncomplete)) 486 } 487 return 488 } 489 hf, ok := frame.(*headersFrame) 490 if !ok { 491 conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameUnexpected), "expected first frame to be a HEADERS frame") 492 return 493 } 494 if hf.Length > s.maxHeaderBytes() { 495 str.CancelRead(quic.StreamErrorCode(ErrCodeFrameError)) 496 str.CancelWrite(quic.StreamErrorCode(ErrCodeFrameError)) 497 return 498 } 499 headerBlock := make([]byte, hf.Length) 500 if _, err := io.ReadFull(str, headerBlock); err != nil { 501 str.CancelRead(quic.StreamErrorCode(ErrCodeRequestIncomplete)) 502 str.CancelWrite(quic.StreamErrorCode(ErrCodeRequestIncomplete)) 503 return 504 } 505 hfs, err := decoder.DecodeFull(headerBlock) 506 if err != nil { 507 // TODO: use the right error code 508 conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeGeneralProtocolError), "expected first frame to be a HEADERS frame") 509 return 510 } 511 req, err := requestFromHeaders(hfs) 512 if err != nil { 513 str.CancelRead(quic.StreamErrorCode(ErrCodeMessageError)) 514 str.CancelWrite(quic.StreamErrorCode(ErrCodeMessageError)) 515 return 516 } 517 518 connState := conn.ConnectionState().TLS 519 req.TLS = &connState 520 req.RemoteAddr = conn.RemoteAddr().String() 521 522 // Check that the client doesn't send more data in DATA frames than indicated by the Content-Length header (if set). 523 // See section 4.1.2 of RFC 9114. 524 contentLength := int64(-1) 525 if _, ok := req.Header["Content-Length"]; ok && req.ContentLength >= 0 { 526 contentLength = req.ContentLength 527 } 528 hstr := newStream(str, conn, datagrams) 529 body := newRequestBody(hstr, contentLength, conn.Context(), conn.ReceivedSettings(), conn.Settings) 530 req.Body = body 531 532 if s.Logger != nil { 533 s.Logger.Debug("handling request", "method", req.Method, "host", req.Host, "uri", req.RequestURI) 534 } 535 536 ctx := str.Context() 537 ctx = context.WithValue(ctx, ServerContextKey, s) 538 ctx = context.WithValue(ctx, http.LocalAddrContextKey, conn.LocalAddr()) 539 ctx = context.WithValue(ctx, RemoteAddrContextKey, conn.RemoteAddr()) 540 if s.ConnContext != nil { 541 ctx = s.ConnContext(ctx, conn.Connection) 542 if ctx == nil { 543 panic("http3: ConnContext returned nil") 544 } 545 } 546 req = req.WithContext(ctx) 547 r := newResponseWriter(hstr, conn, req.Method == http.MethodHead, s.Logger) 548 handler := s.Handler 549 if handler == nil { 550 handler = http.DefaultServeMux 551 } 552 553 // It's the client's responsibility to decide which requests are eligible for 0-RTT. 554 var panicked bool 555 func() { 556 defer func() { 557 if p := recover(); p != nil { 558 panicked = true 559 if p == http.ErrAbortHandler { 560 return 561 } 562 // Copied from net/http/server.go 563 const size = 64 << 10 564 buf := make([]byte, size) 565 buf = buf[:runtime.Stack(buf, false)] 566 logger := s.Logger 567 if logger == nil { 568 logger = slog.Default() 569 } 570 logger.Error("http: panic serving", "arg", p, "trace", buf) 571 } 572 }() 573 handler.ServeHTTP(r, req) 574 }() 575 576 if r.wasStreamHijacked() { 577 return 578 } 579 580 // only write response when there is no panic 581 if !panicked { 582 // response not written to the client yet, set Content-Length 583 if !r.headerWritten { 584 if _, haveCL := r.header["Content-Length"]; !haveCL { 585 r.header.Set("Content-Length", strconv.FormatInt(r.numWritten, 10)) 586 } 587 } 588 r.Flush() 589 } 590 591 // abort the stream when there is a panic 592 if panicked { 593 str.CancelRead(quic.StreamErrorCode(ErrCodeInternalError)) 594 str.CancelWrite(quic.StreamErrorCode(ErrCodeInternalError)) 595 return 596 } 597 598 // If the EOF was read by the handler, CancelRead() is a no-op. 599 str.CancelRead(quic.StreamErrorCode(ErrCodeNoError)) 600 601 str.Close() 602 } 603 604 // Close the server immediately, aborting requests and sending CONNECTION_CLOSE frames to connected clients. 605 // Close in combination with ListenAndServe() (instead of Serve()) may race if it is called before a UDP socket is established. 606 func (s *Server) Close() error { 607 s.mutex.Lock() 608 defer s.mutex.Unlock() 609 610 s.closed = true 611 612 var err error 613 for ln := range s.listeners { 614 if cerr := (*ln).Close(); cerr != nil && err == nil { 615 err = cerr 616 } 617 } 618 return err 619 } 620 621 // CloseGracefully shuts down the server gracefully. The server sends a GOAWAY frame first, then waits for either timeout to trigger, or for all running requests to complete. 622 // CloseGracefully in combination with ListenAndServe() (instead of Serve()) may race if it is called before a UDP socket is established. 623 func (s *Server) CloseGracefully(timeout time.Duration) error { 624 // TODO: implement 625 return nil 626 } 627 628 // ErrNoAltSvcPort is the error returned by SetQUICHeaders when no port was found 629 // for Alt-Svc to announce. This can happen if listening on a PacketConn without a port 630 // (UNIX socket, for example) and no port is specified in Server.Port or Server.Addr. 631 var ErrNoAltSvcPort = errors.New("no port can be announced, specify it explicitly using Server.Port or Server.Addr") 632 633 // SetQUICHeaders can be used to set the proper headers that announce that this server supports HTTP/3. 634 // The values set by default advertise all the ports the server is listening on, but can be 635 // changed to a specific port by setting Server.Port before launching the server. 636 // If no listener's Addr().String() returns an address with a valid port, Server.Addr will be used 637 // to extract the port, if specified. 638 // For example, a server launched using ListenAndServe on an address with port 443 would set: 639 // 640 // Alt-Svc: h3=":443"; ma=2592000 641 func (s *Server) SetQUICHeaders(hdr http.Header) error { 642 s.mutex.RLock() 643 defer s.mutex.RUnlock() 644 645 if s.altSvcHeader == "" { 646 return ErrNoAltSvcPort 647 } 648 // use the map directly to avoid constant canonicalization since the key is already canonicalized 649 hdr["Alt-Svc"] = append(hdr["Alt-Svc"], s.altSvcHeader) 650 return nil 651 } 652 653 // Deprecated: use SetQUICHeaders instead. 654 func (s *Server) SetQuicHeaders(hdr http.Header) error { 655 return s.SetQUICHeaders(hdr) 656 } 657 658 // ListenAndServeQUIC listens on the UDP network address addr and calls the 659 // handler for HTTP/3 requests on incoming connections. http.DefaultServeMux is 660 // used when handler is nil. 661 func ListenAndServeQUIC(addr, certFile, keyFile string, handler http.Handler) error { 662 server := &Server{ 663 Addr: addr, 664 Handler: handler, 665 } 666 return server.ListenAndServeTLS(certFile, keyFile) 667 } 668 669 // Deprecated: use ListenAndServeTLS instead. 670 func ListenAndServe(addr, certFile, keyFile string, handler http.Handler) error { 671 return ListenAndServeTLS(addr, certFile, keyFile, handler) 672 } 673 674 // ListenAndServeTLS listens on the given network address for both TLS/TCP and QUIC 675 // connections in parallel. It returns if one of the two returns an error. 676 // http.DefaultServeMux is used when handler is nil. 677 // The correct Alt-Svc headers for QUIC are set. 678 func ListenAndServeTLS(addr, certFile, keyFile string, handler http.Handler) error { 679 // Load certs 680 var err error 681 certs := make([]tls.Certificate, 1) 682 certs[0], err = tls.LoadX509KeyPair(certFile, keyFile) 683 if err != nil { 684 return err 685 } 686 // We currently only use the cert-related stuff from tls.Config, 687 // so we don't need to make a full copy. 688 config := &tls.Config{ 689 Certificates: certs, 690 } 691 692 if addr == "" { 693 addr = ":https" 694 } 695 696 // Open the listeners 697 udpAddr, err := net.ResolveUDPAddr("udp", addr) 698 if err != nil { 699 return err 700 } 701 udpConn, err := net.ListenUDP("udp", udpAddr) 702 if err != nil { 703 return err 704 } 705 defer udpConn.Close() 706 707 if handler == nil { 708 handler = http.DefaultServeMux 709 } 710 // Start the servers 711 quicServer := &Server{ 712 TLSConfig: config, 713 Handler: handler, 714 } 715 716 hErr := make(chan error, 1) 717 qErr := make(chan error, 1) 718 go func() { 719 hErr <- http.ListenAndServeTLS(addr, certFile, keyFile, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 720 quicServer.SetQUICHeaders(w.Header()) 721 handler.ServeHTTP(w, r) 722 })) 723 }() 724 go func() { 725 qErr <- quicServer.Serve(udpConn) 726 }() 727 728 select { 729 case err := <-hErr: 730 quicServer.Close() 731 return err 732 case err := <-qErr: 733 // Cannot close the HTTP server or wait for requests to complete properly :/ 734 return err 735 } 736 }