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