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