github.com/searKing/golang/go@v1.2.117/net/tcp/server.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 tcp
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"io"
    11  	"log"
    12  	"net"
    13  	"sync"
    14  	"sync/atomic"
    15  	"time"
    16  
    17  	slices_ "github.com/searKing/golang/go/exp/slices"
    18  	time_ "github.com/searKing/golang/go/time"
    19  )
    20  
    21  type Handler interface {
    22  	OnOpenHandler
    23  	OnMsgReadHandler
    24  	OnMsgHandleHandler
    25  	OnCloseHandler
    26  	OnErrorHandler
    27  }
    28  
    29  func NewServerFunc(
    30  	onOpen OnOpenHandler,
    31  	onMsgRead OnMsgReadHandler,
    32  	onMsgHandle OnMsgHandleHandler,
    33  	onClose OnCloseHandler,
    34  	onError OnErrorHandler) *Server {
    35  	return &Server{
    36  		onOpenHandler:      slices_.FirstOrZero[OnOpenHandler](onOpen, NopOnOpenHandler),
    37  		onMsgReadHandler:   slices_.FirstOrZero[OnMsgReadHandler](onMsgRead, NopOnMsgReadHandler),
    38  		onMsgHandleHandler: slices_.FirstOrZero[OnMsgHandleHandler](onMsgHandle, NopOnMsgHandleHandler),
    39  		onCloseHandler:     slices_.FirstOrZero[OnCloseHandler](onClose, NopOnCloseHandler),
    40  		onErrorHandler:     slices_.FirstOrZero[OnErrorHandler](onError, NopOnErrorHandler),
    41  	}
    42  }
    43  func NewServer(h Handler) *Server {
    44  	return NewServerFunc(h, h, h, h, h)
    45  }
    46  
    47  type Server struct {
    48  	Addr               string // TCP address to listen on, ":tcp" if empty
    49  	onOpenHandler      OnOpenHandler
    50  	onMsgReadHandler   OnMsgReadHandler
    51  	onMsgHandleHandler OnMsgHandleHandler
    52  	onCloseHandler     OnCloseHandler
    53  	onErrorHandler     OnErrorHandler
    54  
    55  	ReadTimeout  time.Duration
    56  	WriteTimeout time.Duration
    57  	IdleTimeout  time.Duration
    58  	MaxBytes     int
    59  
    60  	ErrorLog *log.Logger
    61  
    62  	mu         sync.Mutex
    63  	listeners  map[*net.Listener]struct{}
    64  	activeConn map[*conn]struct{}
    65  	doneChan   chan struct{}
    66  	onShutdown []func()
    67  
    68  	// server state
    69  	inShutdown atomic.Bool
    70  
    71  	// ConnState specifies an optional callback function that is
    72  	// called when a client connection changes state. See the
    73  	// ConnState type and associated constants for details.
    74  	ConnState func(net.Conn, ConnState)
    75  }
    76  
    77  func (srv *Server) CheckError(w io.Writer, r io.Reader, err error) error {
    78  	if err == nil {
    79  		return nil
    80  	}
    81  	return srv.onErrorHandler.OnError(w, r, err)
    82  }
    83  
    84  func (srv *Server) ListenAndServe() error {
    85  	if srv.shuttingDown() {
    86  		return srv.CheckError(nil, nil, ErrServerClosed)
    87  	}
    88  	addr := srv.Addr
    89  	if addr == "" {
    90  		addr = ":tcp"
    91  	}
    92  	ln, err := net.Listen("tcp", addr)
    93  	if srv.CheckError(nil, nil, err) != nil {
    94  		return err
    95  	}
    96  	return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
    97  }
    98  
    99  func (srv *Server) Serve(l net.Listener) error {
   100  	l = &onceCloseListener{Listener: l}
   101  	defer l.Close()
   102  
   103  	// how long to sleep on accept failure
   104  	var tempDelay = time_.NewExponentialBackOff(
   105  		time_.WithExponentialBackOffOptionInitialInterval(5*time.Millisecond),
   106  		time_.WithExponentialBackOffOptionMaxInterval(time.Second),
   107  		time_.WithExponentialBackOffOptionMaxElapsedDuration(-1),
   108  		time_.WithExponentialBackOffOptionMaxElapsedCount(-1))
   109  	ctx := context.WithValue(context.Background(), ServerContextKey, srv)
   110  	for {
   111  		rw, e := l.Accept()
   112  		if e != nil {
   113  			// return if server is cancaled, means normally close
   114  			select {
   115  			case <-srv.getDoneChan():
   116  				return ErrServerClosed
   117  			default:
   118  			}
   119  			// retry if it's recoverable
   120  			var ne net.Error
   121  			if errors.As(e, &ne) && ne.Temporary() {
   122  				delay, ok := tempDelay.NextBackOff()
   123  				if !ok {
   124  					srv.logf("http: Accept error: %v; retried canceled as time exceed(%v)", e, tempDelay.GetMaxElapsedDuration())
   125  					// return if timeout
   126  					return srv.CheckError(nil, nil, e)
   127  				}
   128  				srv.logf("http: Accept error: %v; retrying in %v", e, delay)
   129  				time.Sleep(delay)
   130  				continue
   131  			}
   132  			// return otherwise
   133  			return srv.CheckError(nil, nil, e)
   134  		}
   135  		tempDelay.Reset()
   136  
   137  		// takeover this connect
   138  		c := srv.newConn(rw)
   139  		// Handle websocket On
   140  		err := srv.onOpenHandler.OnOpen(c.rwc)
   141  		if err = srv.CheckError(c.w, c.r, err); err != nil {
   142  			c.close()
   143  			return err
   144  		}
   145  		c.setState(c.rwc, StateNew) // before Serve can return
   146  		go c.serve(ctx)
   147  	}
   148  }
   149  
   150  func (srv *Server) trackConn(c *conn, add bool) {
   151  	srv.mu.Lock()
   152  	defer srv.mu.Unlock()
   153  	if srv.activeConn == nil {
   154  		srv.activeConn = make(map[*conn]struct{})
   155  	}
   156  	if add {
   157  		srv.activeConn[c] = struct{}{}
   158  	} else {
   159  		delete(srv.activeConn, c)
   160  	}
   161  }
   162  
   163  // Create new connection from rwc.
   164  func (srv *Server) newConn(rwc net.Conn) *conn {
   165  	c := &conn{
   166  		server: srv,
   167  		rwc:    rwc,
   168  	}
   169  	return c
   170  }
   171  
   172  func (srv *Server) logf(format string, args ...any) {
   173  	if srv.ErrorLog != nil {
   174  		srv.ErrorLog.Printf(format, args...)
   175  	} else {
   176  		log.Printf(format, args...)
   177  	}
   178  }
   179  
   180  func ListenAndServe(addr string, readMsg OnMsgReadHandler, handleMsg OnMsgHandleHandler) error {
   181  	server := &Server{Addr: addr, onMsgReadHandler: readMsg, onMsgHandleHandler: handleMsg}
   182  	return server.ListenAndServe()
   183  }