From a8654e198e2eee7c8ce40ee564a5213dbaaae458 Mon Sep 17 00:00:00 2001 From: hahahrfool <75717694+hahahrfool@users.noreply.github.com> Date: Sat, 2 Apr 2022 09:24:15 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=95=E5=9B=BE=E4=BF=AE=E5=A4=8Dudp=20close?= =?UTF-8?q?=E6=97=A0=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98,=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E5=AF=BC=E8=87=B4=20too=20many=20opened=20sockets.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.go | 9 +++++---- netLayer/dns.go | 3 +++ netLayer/listen.go | 3 --- netLayer/udpConn.go | 41 +++++++++++++++++++++++++++++++++++++---- utils/log.go | 7 +++++++ 5 files changed, 52 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index d0943c3..32a7623 100644 --- a/main.go +++ b/main.go @@ -652,7 +652,6 @@ func handshakeInserver_and_passToOutClient(iics incomingInserverConnState) { zap.String("handler", inServer.AddrStr()), zap.Error(err), ) - //log.Printf("failed in inServer proxy handshake from %s %s\n", inServer.AddrStr(), err) } if !inServer.CanFallback() { @@ -672,6 +671,11 @@ func handshakeInserver_and_passToOutClient(iics incomingInserverConnState) { iics.theFallbackFirstBuffer = fe.First if iics.theFallbackFirstBuffer == nil { //不应该,至少能读到1字节的。 + + if ce := utils.CanLogFatal("No FirstBuffer"); ce != nil { + ce.Write() + } + log.Fatalf("No FirstBuffer\n") } } @@ -683,7 +687,6 @@ checkFallback: if mainFallback != nil { if ce := utils.CanLogDebug("checkFallback"); ce != nil { - //log.Printf("checkFallback\n") ce.Write() } @@ -712,7 +715,6 @@ checkFallback: if inServerTlsConn := iics.inServerTlsConn; inServerTlsConn != nil { //默认似乎默认tls不会给出alpn和sni项?获得的是空值,也许是因为我用了自签名+insecure,所以导致server并不会设置连接好后所协商的ServerName // 而alpn则也是正常的, 不设置肯定就是空值 - // TODO: 配置中加一个 alpn选项. alpn := inServerTlsConn.GetAlpn() if alpn != "" { @@ -731,7 +733,6 @@ checkFallback: fbAddr := mainFallback.GetFallback(thisFallbackType, fallback_params...) if ce := utils.CanLogDebug("checkFallback"); ce != nil { - //log.Printf("checkFallback ,matched fallback: %s\n", fbAddr.String()) ce.Write( zap.String("matched fallback", fbAddr.String()), ) diff --git a/netLayer/dns.go b/netLayer/dns.go index 4dda228..f63d72c 100644 --- a/netLayer/dns.go +++ b/netLayer/dns.go @@ -117,6 +117,9 @@ func NewDnsMachine(defaultDnsServerAddr *Addr) *DNSMachine { var conn net.Conn var err error + //实测 miekg/dns 必须用 net.PacketConn,不过本作udp最新代码已经支持了. + // 不过dns还是没必要额外包装一次, 直接用原始的udp即可. + if defaultDnsServerAddr.IsUDP() { conn, err = net.DialUDP("udp", nil, defaultDnsServerAddr.ToUDPAddr()) } else { diff --git a/netLayer/listen.go b/netLayer/listen.go index 9411119..2ace135 100644 --- a/netLayer/listen.go +++ b/netLayer/listen.go @@ -17,19 +17,16 @@ func loopAccept(listener net.Listener, acceptFunc func(net.Conn)) { errStr := err.Error() if strings.Contains(errStr, "closed") { if ce := utils.CanLogDebug("local connection closed"); ce != nil { - //log.Println("local connection closed", err) ce.Write(zap.Error(err)) } break } if ce := utils.CanLogWarn("failed to accept connection"); ce != nil { - //log.Println("failed to accept connection: ", err) ce.Write(zap.Error(err)) } if strings.Contains(errStr, "too many") { if ce := utils.CanLogWarn("To many incoming conn! Will Sleep."); ce != nil { - //log.Println("To many incoming conn! Sleep ", errStr) ce.Write(zap.String("err", errStr)) } diff --git a/netLayer/udpConn.go b/netLayer/udpConn.go index 68e16a0..0a896ee 100644 --- a/netLayer/udpConn.go +++ b/netLayer/udpConn.go @@ -23,6 +23,8 @@ type UDPConn struct { readDeadline PipeDeadline writeDeadline PipeDeadline + clientFirstWriteChan chan int + unread []byte isClient bool } @@ -35,10 +37,11 @@ func DialUDP(raddr *net.UDPAddr) (net.Conn, error) { return NewUDPConn(raddr, conn, true), nil } +//如果isClient为true,则本函数返回后,必须要调用一次 Write,才能在Read读到数据 func NewUDPConn(raddr *net.UDPAddr, conn *net.UDPConn, isClient bool) *UDPConn { inDataChan := make(chan []byte, 50) theUDPConn := &UDPConn{raddr, conn, inDataChan, MakePipeDeadline(), - MakePipeDeadline(), []byte{}, isClient} + MakePipeDeadline(), make(chan int), []byte{}, isClient} //不设置缓存的话,会导致发送过快 而导致丢包 conn.SetReadBuffer(MaxUDP_packetLen) @@ -46,8 +49,9 @@ func NewUDPConn(raddr *net.UDPAddr, conn *net.UDPConn, isClient bool) *UDPConn { if isClient { - //客户端要自己循环读取udp, + //客户端要自己循环读取udp,(但是要等待先Write之后) go func() { + <-theUDPConn.clientFirstWriteChan for { buf := utils.GetPacket() n, _, err := conn.ReadFromUDP(buf) @@ -80,6 +84,28 @@ func (uc *UDPConn) ReadMsg() (b []byte, err error) { return nil, ErrTimeout } } + +//实现 net.PacketConn, 可以与 miekg/dns 配合 +func (uc *UDPConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { + select { + case msg, ok := <-uc.inMsgChan: + if !ok { + return 0, uc.peerAddr, io.EOF + } + n = copy(msg, p) + return n, uc.peerAddr, io.EOF + + case <-uc.readDeadline.Wait(): + return 0, uc.peerAddr, ErrTimeout + } +} + +//实现 net.PacketConn, 可以与 miekg/dns 配合 +func (uc *UDPConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { + return uc.Write(p) + +} + func (uc *UDPConn) GetReadChan() chan []byte { return uc.inMsgChan } @@ -91,6 +117,7 @@ func (uc *UDPConn) Read(buf []byte) (n int, err error) { return } var msg []byte + msg, err = uc.ReadMsg() if err != nil { return @@ -115,7 +142,7 @@ func (uc *UDPConn) Write(buf []byte) (n int, err error) { return 0, ErrTimeout default: if uc.isClient { - time.Sleep(time.Millisecond) //不能发送太快,否则会出现丢包,实测简单1毫秒即可避免 + //time.Sleep(time.Millisecond) //不能发送太快,否则会出现丢包,实测简单1毫秒即可避免 /* 一些常见的丢包后出现的错误: @@ -132,6 +159,7 @@ func (uc *UDPConn) Write(buf []byte) (n int, err error) { //if use writeToUDP at client end, we will get err Write write udp 127.0.0.1:50361->:60006: use of WriteTo with pre-connected connection + defer close(uc.clientFirstWriteChan) return uc.realConn.Write(buf) } else { return uc.realConn.WriteToUDP(buf, uc.peerAddr) @@ -140,7 +168,12 @@ func (uc *UDPConn) Write(buf []byte) (n int, err error) { } } -func (*UDPConn) Close() error { return nil } +func (uc *UDPConn) Close() error { + if uc.isClient { + return uc.realConn.Close() + } + return nil +} func (b *UDPConn) LocalAddr() net.Addr { return b.realConn.LocalAddr() } func (b *UDPConn) RemoteAddr() net.Addr { return b.peerAddr } diff --git a/utils/log.go b/utils/log.go index 2ec87d5..2b51947 100644 --- a/utils/log.go +++ b/utils/log.go @@ -95,3 +95,10 @@ func CanLogDebug(msg string) *zapcore.CheckedEntry { return ZapLogger.Check(zap.DebugLevel, msg) } +func CanLogFatal(msg string) *zapcore.CheckedEntry { + if LogLevel > Log_fatal { + return nil + } + return ZapLogger.Check(zap.FatalLevel, msg) + +}