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  }