github.com/searKing/golang/go@v1.2.117/net/multi_listener.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package net 6 7 import ( 8 "log" 9 "net" 10 "sync" 11 "time" 12 13 "github.com/searKing/golang/go/errors" 14 ) 15 16 // MultiListener is a net.Listener that accepts all the connections from all listeners. 17 type MultiListener struct { 18 *NotifyListener 19 listeners multiAddrs 20 // ErrorLog specifies an optional logger for errors accepting 21 // connections, unexpected behavior from handlers, and 22 // underlying FileSystem errors. 23 // If nil, logging is done via the log package's standard logger. 24 ErrorLog *log.Logger 25 26 once sync.Once 27 } 28 29 func NewMultiListener(listeners ...net.Listener) *MultiListener { 30 return &MultiListener{ 31 NotifyListener: NewNotifyListener(), 32 listeners: listeners, 33 } 34 } 35 36 // Addr returns the listener's network address. 37 func (l *MultiListener) Addr() net.Addr { 38 return l.listeners 39 } 40 func (l *MultiListener) Accept() (net.Conn, error) { 41 if len(l.listeners) == 0 { 42 return nil, ErrListenerClosed 43 } 44 l.once.Do(func() { 45 for _, listener := range l.listeners { 46 go l.serve(listener) 47 } 48 }) 49 return l.NotifyListener.Accept() 50 } 51 52 func (l *MultiListener) Close() error { 53 var errs []error 54 errs = append(errs, l.NotifyListener.Close()) 55 for _, listener := range l.listeners { 56 errs = append(errs, listener.Close()) 57 } 58 return errors.Multi(errs...) 59 } 60 61 func (l *MultiListener) logf(format string, args ...any) { 62 if l.ErrorLog != nil { 63 l.ErrorLog.Printf(format, args...) 64 } else { 65 log.Printf(format, args...) 66 } 67 } 68 69 // serve accepts incoming connections on the Listener lis, send the 70 // conn accepted to the NotifyListener for each. 71 // 72 // Serve always returns a non-nil error and closes l. 73 // After Close, the returned error is ErrListenerClosed. 74 func (l *MultiListener) serve(lis net.Listener) error { 75 defer l.Close() 76 var tempDelay time.Duration // how long to sleep on accept failure 77 for { 78 // Accept waits for and returns the next connection to the listener. 79 conn, err := lis.Accept() 80 if err != nil { 81 select { 82 case <-l.DoneC(): 83 return ErrListenerClosed 84 default: 85 } 86 87 if ne, ok := err.(net.Error); ok && ne.Temporary() { 88 if tempDelay == 0 { 89 tempDelay = 5 * time.Millisecond 90 } else { 91 tempDelay *= 2 92 } 93 if max := 1 * time.Second; tempDelay > max { 94 tempDelay = max 95 } 96 l.logf("multi listener: Accept error: %v; retrying in %v", err, tempDelay) 97 time.Sleep(tempDelay) 98 continue 99 } 100 return err 101 } 102 tempDelay = 0 103 104 select { 105 case <-l.DoneC(): 106 return ErrListenerClosed 107 case l.C <- conn: 108 } 109 } 110 }