76 lines
1.4 KiB
Go
76 lines
1.4 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/quic-go/quic-go/http3"
|
|
)
|
|
|
|
func ListenAndServe(addr string, tlsConfig *tls.Config, handler http.Handler) (err error) {
|
|
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
|
if err != nil {
|
|
return
|
|
}
|
|
udpConn, err := net.ListenUDP("udp", udpAddr)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer udpConn.Close()
|
|
|
|
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
|
|
if err != nil {
|
|
return
|
|
}
|
|
tcpConn, err := net.ListenTCP("tcp", tcpAddr)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer tcpConn.Close()
|
|
|
|
tlsConn := tls.NewListener(tcpConn, tlsConfig)
|
|
defer tlsConn.Close()
|
|
|
|
if handler == nil {
|
|
handler = http.DefaultServeMux
|
|
}
|
|
// Start the servers
|
|
quicServer := &http3.Server{
|
|
TLSConfig: tlsConfig,
|
|
Handler: handler,
|
|
}
|
|
if publicQuicPort, ok := os.LookupEnv("PUBLIC_QUIC_PORT"); ok {
|
|
quicServer.Port, err = strconv.Atoi(publicQuicPort)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
httpServer := &http.Server{
|
|
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
quicServer.SetQuicHeaders(w.Header())
|
|
handler.ServeHTTP(w, r)
|
|
}),
|
|
}
|
|
|
|
hErr := make(chan error)
|
|
qErr := make(chan error)
|
|
go func() {
|
|
hErr <- httpServer.Serve(tlsConn)
|
|
}()
|
|
go func() {
|
|
qErr <- quicServer.Serve(udpConn)
|
|
}()
|
|
|
|
select {
|
|
case err := <-hErr:
|
|
quicServer.Close()
|
|
return err
|
|
case err := <-qErr:
|
|
// Cannot close the HTTP server or wait for requests to complete properly :/
|
|
return err
|
|
}
|
|
}
|