github.com/MerlinKodo/quic-go@v0.39.2/http3/server.go (about) 1 package http3 2 3 import ( 4 "context" 5 "crypto/tls" 6 "errors" 7 "fmt" 8 "io" 9 "net" 10 "net/http" 11 "runtime" 12 "strconv" 13 "strings" 14 "sync" 15 "time" 16 17 "github.com/MerlinKodo/quic-go" 18 "github.com/MerlinKodo/quic-go/internal/protocol" 19 "github.com/MerlinKodo/quic-go/internal/utils" 20 "github.com/MerlinKodo/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.VersionNumber) 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.VersionNumber); 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 type requestError struct { 119 err error 120 streamErr ErrCode 121 connErr ErrCode 122 } 123 124 func newStreamError(code ErrCode, err error) requestError { 125 return requestError{err: err, streamErr: code} 126 } 127 128 func newConnError(code ErrCode, err error) requestError { 129 return requestError{err: err, connErr: code} 130 } 131 132 // listenerInfo contains info about specific listener added with addListener 133 type listenerInfo struct { 134 port int // 0 means that no info about port is available 135 } 136 137 // Server is a HTTP/3 server. 138 type Server struct { 139 // Addr optionally specifies the UDP address for the server to listen on, 140 // in the form "host:port". 141 // 142 // When used by ListenAndServe and ListenAndServeTLS methods, if empty, 143 // ":https" (port 443) is used. See net.Dial for details of the address 144 // format. 145 // 146 // Otherwise, if Port is not set and underlying QUIC listeners do not 147 // have valid port numbers, the port part is used in Alt-Svc headers set 148 // with SetQuicHeaders. 149 Addr string 150 151 // Port is used in Alt-Svc response headers set with SetQuicHeaders. If 152 // needed Port can be manually set when the Server is created. 153 // 154 // This is useful when a Layer 4 firewall is redirecting UDP traffic and 155 // clients must use a port different from the port the Server is 156 // listening on. 157 Port int 158 159 // TLSConfig provides a TLS configuration for use by server. It must be 160 // set for ListenAndServe and Serve methods. 161 TLSConfig *tls.Config 162 163 // QuicConfig provides the parameters for QUIC connection created with 164 // Serve. If nil, it uses reasonable default values. 165 // 166 // Configured versions are also used in Alt-Svc response header set with 167 // SetQuicHeaders. 168 QuicConfig *quic.Config 169 170 // Handler is the HTTP request handler to use. If not set, defaults to 171 // http.NotFound. 172 Handler http.Handler 173 174 // EnableDatagrams enables support for HTTP/3 datagrams. 175 // If set to true, QuicConfig.EnableDatagram will be set. 176 // See https://datatracker.ietf.org/doc/html/rfc9297. 177 EnableDatagrams bool 178 179 // MaxHeaderBytes controls the maximum number of bytes the server will 180 // read parsing the request HEADERS frame. It does not limit the size of 181 // the request body. If zero or negative, http.DefaultMaxHeaderBytes is 182 // used. 183 MaxHeaderBytes int 184 185 // AdditionalSettings specifies additional HTTP/3 settings. 186 // It is invalid to specify any settings defined by the HTTP/3 draft and the datagram draft. 187 AdditionalSettings map[uint64]uint64 188 189 // StreamHijacker, when set, is called for the first unknown frame parsed on a bidirectional stream. 190 // It is called right after parsing the frame type. 191 // If parsing the frame type fails, the error is passed to the callback. 192 // In that case, the frame type will not be set. 193 // Callers can either ignore the frame and return control of the stream back to HTTP/3 194 // (by returning hijacked false). 195 // Alternatively, callers can take over the QUIC stream (by returning hijacked true). 196 StreamHijacker func(FrameType, quic.Connection, quic.Stream, error) (hijacked bool, err error) 197 198 // UniStreamHijacker, when set, is called for unknown unidirectional stream of unknown stream type. 199 // If parsing the stream type fails, the error is passed to the callback. 200 // In that case, the stream type will not be set. 201 UniStreamHijacker func(StreamType, quic.Connection, quic.ReceiveStream, error) (hijacked bool) 202 203 mutex sync.RWMutex 204 listeners map[*QUICEarlyListener]listenerInfo 205 206 closed bool 207 208 altSvcHeader string 209 210 logger utils.Logger 211 } 212 213 // ListenAndServe listens on the UDP address s.Addr and calls s.Handler to handle HTTP/3 requests on incoming connections. 214 // 215 // If s.Addr is blank, ":https" is used. 216 func (s *Server) ListenAndServe() error { 217 return s.serveConn(s.TLSConfig, nil) 218 } 219 220 // ListenAndServeTLS listens on the UDP address s.Addr and calls s.Handler to handle HTTP/3 requests on incoming connections. 221 // 222 // If s.Addr is blank, ":https" is used. 223 func (s *Server) ListenAndServeTLS(certFile, keyFile string) error { 224 var err error 225 certs := make([]tls.Certificate, 1) 226 certs[0], err = tls.LoadX509KeyPair(certFile, keyFile) 227 if err != nil { 228 return err 229 } 230 // We currently only use the cert-related stuff from tls.Config, 231 // so we don't need to make a full copy. 232 config := &tls.Config{ 233 Certificates: certs, 234 } 235 return s.serveConn(config, nil) 236 } 237 238 // Serve an existing UDP connection. 239 // It is possible to reuse the same connection for outgoing connections. 240 // Closing the server does not close the connection. 241 func (s *Server) Serve(conn net.PacketConn) error { 242 return s.serveConn(s.TLSConfig, conn) 243 } 244 245 // ServeQUICConn serves a single QUIC connection. 246 func (s *Server) ServeQUICConn(conn quic.Connection) error { 247 s.mutex.Lock() 248 if s.logger == nil { 249 s.logger = utils.DefaultLogger.WithPrefix("server") 250 } 251 s.mutex.Unlock() 252 253 return s.handleConn(conn) 254 } 255 256 // ServeListener serves an existing QUIC listener. 257 // Make sure you use http3.ConfigureTLSConfig to configure a tls.Config 258 // and use it to construct a http3-friendly QUIC listener. 259 // Closing the server does close the listener. 260 // ServeListener always returns a non-nil error. After Shutdown or Close, the returned error is http.ErrServerClosed. 261 func (s *Server) ServeListener(ln QUICEarlyListener) error { 262 if err := s.addListener(&ln); err != nil { 263 return err 264 } 265 defer s.removeListener(&ln) 266 for { 267 conn, err := ln.Accept(context.Background()) 268 if err == quic.ErrServerClosed { 269 return http.ErrServerClosed 270 } 271 if err != nil { 272 return err 273 } 274 go func() { 275 if err := s.handleConn(conn); err != nil { 276 s.logger.Debugf(err.Error()) 277 } 278 }() 279 } 280 } 281 282 var errServerWithoutTLSConfig = errors.New("use of http3.Server without TLSConfig") 283 284 func (s *Server) serveConn(tlsConf *tls.Config, conn net.PacketConn) error { 285 if tlsConf == nil { 286 return errServerWithoutTLSConfig 287 } 288 289 s.mutex.Lock() 290 closed := s.closed 291 s.mutex.Unlock() 292 if closed { 293 return http.ErrServerClosed 294 } 295 296 baseConf := ConfigureTLSConfig(tlsConf) 297 quicConf := s.QuicConfig 298 if quicConf == nil { 299 quicConf = &quic.Config{Allow0RTT: true} 300 } else { 301 quicConf = s.QuicConfig.Clone() 302 } 303 if s.EnableDatagrams { 304 quicConf.EnableDatagrams = true 305 } 306 307 var ln QUICEarlyListener 308 var err error 309 if conn == nil { 310 addr := s.Addr 311 if addr == "" { 312 addr = ":https" 313 } 314 ln, err = quicListenAddr(addr, baseConf, quicConf) 315 } else { 316 ln, err = quicListen(conn, baseConf, quicConf) 317 } 318 if err != nil { 319 return err 320 } 321 return s.ServeListener(ln) 322 } 323 324 func extractPort(addr string) (int, error) { 325 _, portStr, err := net.SplitHostPort(addr) 326 if err != nil { 327 return 0, err 328 } 329 330 portInt, err := net.LookupPort("tcp", portStr) 331 if err != nil { 332 return 0, err 333 } 334 return portInt, nil 335 } 336 337 func (s *Server) generateAltSvcHeader() { 338 if len(s.listeners) == 0 { 339 // Don't announce any ports since no one is listening for connections 340 s.altSvcHeader = "" 341 return 342 } 343 344 // This code assumes that we will use protocol.SupportedVersions if no quic.Config is passed. 345 supportedVersions := protocol.SupportedVersions 346 if s.QuicConfig != nil && len(s.QuicConfig.Versions) > 0 { 347 supportedVersions = s.QuicConfig.Versions 348 } 349 350 // keep track of which have been seen so we don't yield duplicate values 351 seen := make(map[string]struct{}, len(supportedVersions)) 352 var versionStrings []string 353 for _, version := range supportedVersions { 354 if v := versionToALPN(version); len(v) > 0 { 355 if _, ok := seen[v]; !ok { 356 versionStrings = append(versionStrings, v) 357 seen[v] = struct{}{} 358 } 359 } 360 } 361 362 var altSvc []string 363 addPort := func(port int) { 364 for _, v := range versionStrings { 365 altSvc = append(altSvc, fmt.Sprintf(`%s=":%d"; ma=2592000`, v, port)) 366 } 367 } 368 369 if s.Port != 0 { 370 // if Port is specified, we must use it instead of the 371 // listener addresses since there's a reason it's specified. 372 addPort(s.Port) 373 } else { 374 // if we have some listeners assigned, try to find ports 375 // which we can announce, otherwise nothing should be announced 376 validPortsFound := false 377 for _, info := range s.listeners { 378 if info.port != 0 { 379 addPort(info.port) 380 validPortsFound = true 381 } 382 } 383 if !validPortsFound { 384 if port, err := extractPort(s.Addr); err == nil { 385 addPort(port) 386 } 387 } 388 } 389 390 s.altSvcHeader = strings.Join(altSvc, ",") 391 } 392 393 // We store a pointer to interface in the map set. This is safe because we only 394 // call trackListener via Serve and can track+defer untrack the same pointer to 395 // local variable there. We never need to compare a Listener from another caller. 396 func (s *Server) addListener(l *QUICEarlyListener) error { 397 s.mutex.Lock() 398 defer s.mutex.Unlock() 399 400 if s.closed { 401 return http.ErrServerClosed 402 } 403 if s.logger == nil { 404 s.logger = utils.DefaultLogger.WithPrefix("server") 405 } 406 if s.listeners == nil { 407 s.listeners = make(map[*QUICEarlyListener]listenerInfo) 408 } 409 410 if port, err := extractPort((*l).Addr().String()); err == nil { 411 s.listeners[l] = listenerInfo{port} 412 } else { 413 s.logger.Errorf("Unable to extract port from listener %+v, will not be announced using SetQuicHeaders: %s", err) 414 s.listeners[l] = listenerInfo{} 415 } 416 s.generateAltSvcHeader() 417 return nil 418 } 419 420 func (s *Server) removeListener(l *QUICEarlyListener) { 421 s.mutex.Lock() 422 defer s.mutex.Unlock() 423 delete(s.listeners, l) 424 s.generateAltSvcHeader() 425 } 426 427 func (s *Server) handleConn(conn quic.Connection) error { 428 decoder := qpack.NewDecoder(nil) 429 430 // send a SETTINGS frame 431 str, err := conn.OpenUniStream() 432 if err != nil { 433 return fmt.Errorf("opening the control stream failed: %w", err) 434 } 435 b := make([]byte, 0, 64) 436 b = quicvarint.Append(b, streamTypeControlStream) // stream type 437 b = (&settingsFrame{Datagram: s.EnableDatagrams, Other: s.AdditionalSettings}).Append(b) 438 str.Write(b) 439 440 go s.handleUnidirectionalStreams(conn) 441 442 // Process all requests immediately. 443 // It's the client's responsibility to decide which requests are eligible for 0-RTT. 444 for { 445 str, err := conn.AcceptStream(context.Background()) 446 if err != nil { 447 var appErr *quic.ApplicationError 448 if errors.As(err, &appErr) && appErr.ErrorCode == quic.ApplicationErrorCode(ErrCodeNoError) { 449 return nil 450 } 451 return fmt.Errorf("accepting stream failed: %w", err) 452 } 453 go func() { 454 rerr := s.handleRequest(conn, str, decoder, func() { 455 conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameUnexpected), "") 456 }) 457 if rerr.err == errHijacked { 458 return 459 } 460 if rerr.err != nil || rerr.streamErr != 0 || rerr.connErr != 0 { 461 s.logger.Debugf("Handling request failed: %s", err) 462 if rerr.streamErr != 0 { 463 str.CancelWrite(quic.StreamErrorCode(rerr.streamErr)) 464 } 465 if rerr.connErr != 0 { 466 var reason string 467 if rerr.err != nil { 468 reason = rerr.err.Error() 469 } 470 conn.CloseWithError(quic.ApplicationErrorCode(rerr.connErr), reason) 471 } 472 return 473 } 474 str.Close() 475 }() 476 } 477 } 478 479 func (s *Server) handleUnidirectionalStreams(conn quic.Connection) { 480 for { 481 str, err := conn.AcceptUniStream(context.Background()) 482 if err != nil { 483 s.logger.Debugf("accepting unidirectional stream failed: %s", err) 484 return 485 } 486 487 go func(str quic.ReceiveStream) { 488 streamType, err := quicvarint.Read(quicvarint.NewReader(str)) 489 if err != nil { 490 if s.UniStreamHijacker != nil && s.UniStreamHijacker(StreamType(streamType), conn, str, err) { 491 return 492 } 493 s.logger.Debugf("reading stream type on stream %d failed: %s", str.StreamID(), err) 494 return 495 } 496 // We're only interested in the control stream here. 497 switch streamType { 498 case streamTypeControlStream: 499 case streamTypeQPACKEncoderStream, streamTypeQPACKDecoderStream: 500 // Our QPACK implementation doesn't use the dynamic table yet. 501 // TODO: check that only one stream of each type is opened. 502 return 503 case streamTypePushStream: // only the server can push 504 conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeStreamCreationError), "") 505 return 506 default: 507 if s.UniStreamHijacker != nil && s.UniStreamHijacker(StreamType(streamType), conn, str, nil) { 508 return 509 } 510 str.CancelRead(quic.StreamErrorCode(ErrCodeStreamCreationError)) 511 return 512 } 513 f, err := parseNextFrame(str, nil) 514 if err != nil { 515 conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameError), "") 516 return 517 } 518 sf, ok := f.(*settingsFrame) 519 if !ok { 520 conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeMissingSettings), "") 521 return 522 } 523 if !sf.Datagram { 524 return 525 } 526 // If datagram support was enabled on our side as well as on the client side, 527 // we can expect it to have been negotiated both on the transport and on the HTTP/3 layer. 528 // Note: ConnectionState() will block until the handshake is complete (relevant when using 0-RTT). 529 if s.EnableDatagrams && !conn.ConnectionState().SupportsDatagrams { 530 conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeSettingsError), "missing QUIC Datagram support") 531 } 532 }(str) 533 } 534 } 535 536 func (s *Server) maxHeaderBytes() uint64 { 537 if s.MaxHeaderBytes <= 0 { 538 return http.DefaultMaxHeaderBytes 539 } 540 return uint64(s.MaxHeaderBytes) 541 } 542 543 func (s *Server) handleRequest(conn quic.Connection, str quic.Stream, decoder *qpack.Decoder, onFrameError func()) requestError { 544 var ufh unknownFrameHandlerFunc 545 if s.StreamHijacker != nil { 546 ufh = func(ft FrameType, e error) (processed bool, err error) { return s.StreamHijacker(ft, conn, str, e) } 547 } 548 frame, err := parseNextFrame(str, ufh) 549 if err != nil { 550 if err == errHijacked { 551 return requestError{err: errHijacked} 552 } 553 return newStreamError(ErrCodeRequestIncomplete, err) 554 } 555 hf, ok := frame.(*headersFrame) 556 if !ok { 557 return newConnError(ErrCodeFrameUnexpected, errors.New("expected first frame to be a HEADERS frame")) 558 } 559 if hf.Length > s.maxHeaderBytes() { 560 return newStreamError(ErrCodeFrameError, fmt.Errorf("HEADERS frame too large: %d bytes (max: %d)", hf.Length, s.maxHeaderBytes())) 561 } 562 headerBlock := make([]byte, hf.Length) 563 if _, err := io.ReadFull(str, headerBlock); err != nil { 564 return newStreamError(ErrCodeRequestIncomplete, err) 565 } 566 hfs, err := decoder.DecodeFull(headerBlock) 567 if err != nil { 568 // TODO: use the right error code 569 return newConnError(ErrCodeGeneralProtocolError, err) 570 } 571 req, err := requestFromHeaders(hfs) 572 if err != nil { 573 return newStreamError(ErrCodeMessageError, err) 574 } 575 576 connState := conn.ConnectionState().TLS 577 req.TLS = &connState 578 req.RemoteAddr = conn.RemoteAddr().String() 579 580 // Check that the client doesn't send more data in DATA frames than indicated by the Content-Length header (if set). 581 // See section 4.1.2 of RFC 9114. 582 var httpStr Stream 583 if _, ok := req.Header["Content-Length"]; ok && req.ContentLength >= 0 { 584 httpStr = newLengthLimitedStream(newStream(str, onFrameError), req.ContentLength) 585 } else { 586 httpStr = newStream(str, onFrameError) 587 } 588 body := newRequestBody(httpStr) 589 req.Body = body 590 591 if s.logger.Debug() { 592 s.logger.Infof("%s %s%s, on stream %d", req.Method, req.Host, req.RequestURI, str.StreamID()) 593 } else { 594 s.logger.Infof("%s %s%s", req.Method, req.Host, req.RequestURI) 595 } 596 597 ctx := str.Context() 598 ctx = context.WithValue(ctx, ServerContextKey, s) 599 ctx = context.WithValue(ctx, http.LocalAddrContextKey, conn.LocalAddr()) 600 req = req.WithContext(ctx) 601 r := newResponseWriter(str, conn, s.logger) 602 handler := s.Handler 603 if handler == nil { 604 handler = http.DefaultServeMux 605 } 606 607 var panicked bool 608 func() { 609 defer func() { 610 if p := recover(); p != nil { 611 panicked = true 612 if p == http.ErrAbortHandler { 613 return 614 } 615 // Copied from net/http/server.go 616 const size = 64 << 10 617 buf := make([]byte, size) 618 buf = buf[:runtime.Stack(buf, false)] 619 s.logger.Errorf("http: panic serving: %v\n%s", p, buf) 620 } 621 }() 622 handler.ServeHTTP(r, req) 623 }() 624 625 if body.wasStreamHijacked() { 626 return requestError{err: errHijacked} 627 } 628 629 // only write response when there is no panic 630 if !panicked { 631 // response not written to the client yet, set Content-Length 632 if !r.written { 633 if _, haveCL := r.header["Content-Length"]; !haveCL { 634 r.header.Set("Content-Length", strconv.FormatInt(r.numWritten, 10)) 635 } 636 } 637 r.Flush() 638 } 639 // If the EOF was read by the handler, CancelRead() is a no-op. 640 str.CancelRead(quic.StreamErrorCode(ErrCodeNoError)) 641 return requestError{} 642 } 643 644 // Close the server immediately, aborting requests and sending CONNECTION_CLOSE frames to connected clients. 645 // Close in combination with ListenAndServe() (instead of Serve()) may race if it is called before a UDP socket is established. 646 func (s *Server) Close() error { 647 s.mutex.Lock() 648 defer s.mutex.Unlock() 649 650 s.closed = true 651 652 var err error 653 for ln := range s.listeners { 654 if cerr := (*ln).Close(); cerr != nil && err == nil { 655 err = cerr 656 } 657 } 658 return err 659 } 660 661 // 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. 662 // CloseGracefully in combination with ListenAndServe() (instead of Serve()) may race if it is called before a UDP socket is established. 663 func (s *Server) CloseGracefully(timeout time.Duration) error { 664 // TODO: implement 665 return nil 666 } 667 668 // ErrNoAltSvcPort is the error returned by SetQuicHeaders when no port was found 669 // for Alt-Svc to announce. This can happen if listening on a PacketConn without a port 670 // (UNIX socket, for example) and no port is specified in Server.Port or Server.Addr. 671 var ErrNoAltSvcPort = errors.New("no port can be announced, specify it explicitly using Server.Port or Server.Addr") 672 673 // SetQuicHeaders can be used to set the proper headers that announce that this server supports HTTP/3. 674 // The values set by default advertise all of the ports the server is listening on, but can be 675 // changed to a specific port by setting Server.Port before launching the serverr. 676 // If no listener's Addr().String() returns an address with a valid port, Server.Addr will be used 677 // to extract the port, if specified. 678 // For example, a server launched using ListenAndServe on an address with port 443 would set: 679 // 680 // Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 681 func (s *Server) SetQuicHeaders(hdr http.Header) error { 682 s.mutex.RLock() 683 defer s.mutex.RUnlock() 684 685 if s.altSvcHeader == "" { 686 return ErrNoAltSvcPort 687 } 688 // use the map directly to avoid constant canonicalization 689 // since the key is already canonicalized 690 hdr["Alt-Svc"] = append(hdr["Alt-Svc"], s.altSvcHeader) 691 return nil 692 } 693 694 // ListenAndServeQUIC listens on the UDP network address addr and calls the 695 // handler for HTTP/3 requests on incoming connections. http.DefaultServeMux is 696 // used when handler is nil. 697 func ListenAndServeQUIC(addr, certFile, keyFile string, handler http.Handler) error { 698 server := &Server{ 699 Addr: addr, 700 Handler: handler, 701 } 702 return server.ListenAndServeTLS(certFile, keyFile) 703 } 704 705 // ListenAndServe listens on the given network address for both, TLS and QUIC 706 // connections in parallel. It returns if one of the two returns an error. 707 // http.DefaultServeMux is used when handler is nil. 708 // The correct Alt-Svc headers for QUIC are set. 709 func ListenAndServe(addr, certFile, keyFile string, handler http.Handler) error { 710 // Load certs 711 var err error 712 certs := make([]tls.Certificate, 1) 713 certs[0], err = tls.LoadX509KeyPair(certFile, keyFile) 714 if err != nil { 715 return err 716 } 717 // We currently only use the cert-related stuff from tls.Config, 718 // so we don't need to make a full copy. 719 config := &tls.Config{ 720 Certificates: certs, 721 } 722 723 if addr == "" { 724 addr = ":https" 725 } 726 727 // Open the listeners 728 udpAddr, err := net.ResolveUDPAddr("udp", addr) 729 if err != nil { 730 return err 731 } 732 udpConn, err := net.ListenUDP("udp", udpAddr) 733 if err != nil { 734 return err 735 } 736 defer udpConn.Close() 737 738 if handler == nil { 739 handler = http.DefaultServeMux 740 } 741 // Start the servers 742 quicServer := &Server{ 743 TLSConfig: config, 744 Handler: handler, 745 } 746 747 hErr := make(chan error) 748 qErr := make(chan error) 749 go func() { 750 hErr <- http.ListenAndServeTLS(addr, certFile, keyFile, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 751 quicServer.SetQuicHeaders(w.Header()) 752 handler.ServeHTTP(w, r) 753 })) 754 }() 755 go func() { 756 qErr <- quicServer.Serve(udpConn) 757 }() 758 759 select { 760 case err := <-hErr: 761 quicServer.Close() 762 return err 763 case err := <-qErr: 764 // Cannot close the HTTP server or wait for requests to complete properly :/ 765 return err 766 } 767 }