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.
100 lines
1.9 KiB
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)
|
|
}
|