You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cloudreve/pkg/h3/server.go

100 lines
1.9 KiB

package h3
import (
"fmt"
"net"
"time"
"github.com/libp2p/go-reuseport"
"github.com/quic-go/quic-go"
"github.com/quic-go/quic-go/http3"
)
type H3Server struct {
*http3.Server
localAddr string
pubAddr string
conn net.PacketConn
incoming chan string
}
func NewH3Server(localAddr string) (*H3Server, error) {
localAddr, pulocalAddr, err := GetPublicAddrWithFallback(localAddr)
if err != nil {
return nil, err
}
conn, err := reuseport.ListenPacket("udp4", localAddr)
if err != nil {
return nil, err
}
tlsConfig := GenerateTLSConfig()
quicConfig := &quic.Config{
KeepAlivePeriod: 15 * time.Second,
EnableDatagrams: true,
MaxIdleTimeout: time.Hour,
}
server := &http3.Server{
Addr: conn.LocalAddr().String(),
QUICConfig: quicConfig,
TLSConfig: tlsConfig,
IdleTimeout: time.Hour,
}
return &H3Server{
localAddr: localAddr,
pubAddr: pulocalAddr,
conn: conn,
Server: server,
incoming: make(chan string, 1),
}, nil
}
func (s *H3Server) GetAddrs() (string, string) {
return s.localAddr, s.pubAddr
}
func (s *H3Server) Serve() error {
go func() {
tk := time.NewTicker(15 * time.Second)
defer tk.Stop()
for range tk.C {
_, pubAddr, err := GetPublicAddrWithFallback(s.localAddr)
if err != nil {
continue
}
s.pubAddr = pubAddr
}
}()
return s.Server.Serve(s.conn)
}
func (s *H3Server) Close() error {
var errs = make([]error, 0, 2)
if s.Server != nil {
if err := s.Close(); err != nil {
errs = append(errs, err)
}
}
if s.conn != nil {
if err := s.conn.Close(); err != nil {
errs = append(errs, err)
}
}
switch len(errs) {
case 0:
return nil
case 1:
return errs[0]
case 2:
return fmt.Errorf("close server err: %v, close conn err: %v", errs[0], errs[1])
}
return nil
}
func (s *H3Server) HandleRemote(remoteAddr string) error {
return PunchHole(s.localAddr, remoteAddr)
}