github.com/searKing/golang/go@v1.2.117/net/tcp/conn.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  	"net"
    12  	"runtime"
    13  	"sync/atomic"
    14  	"time"
    15  
    16  	"github.com/searKing/golang/go/x/dispatch"
    17  )
    18  
    19  // maxInt64 is the effective "infinite" value for the Server and
    20  // Transport's byte-limiting readers.
    21  const maxInt64 = 1<<63 - 1
    22  
    23  // aLongTimeAgo is a non-zero time, far in the past, used for
    24  // immediate cancelation of network operations.
    25  var aLongTimeAgo = time.Unix(1, 0)
    26  
    27  // A conn represents the server side of an HTTP connection.
    28  type conn struct {
    29  	// server is the server on which the connection arrived.
    30  	// Immutable; never nil.
    31  	server *Server
    32  
    33  	// cancelCtx cancels the connection-level context.
    34  	cancelCtx context.CancelFunc
    35  
    36  	// rwc is the underlying network connection.
    37  	// This is never wrapped by other types and is the value given out
    38  	// to CloseNotifier callers. It is usually of type *net.TCPConn or
    39  	// *tls.Conn.
    40  	rwc net.Conn
    41  
    42  	// remoteAddr is rwc.RemoteAddr().String(). It is not populated synchronously
    43  	// inside the Listener's Accept goroutine, as some implementations block.
    44  	// It is populated immediately inside the (*conn).serve goroutine.
    45  	// This is the value of a onMsgHandle's (*Request).RemoteAddr.
    46  	remoteAddr string
    47  
    48  	// werr is set to the first write error to rwc.
    49  	// It is set via checkConnErrorWriter{w}, where bufw writes.
    50  	werr error
    51  
    52  	// r is bufr's read source. It's a wrapper around rwc that provides
    53  	// io.LimitedReader-style limiting (while reading request headers)
    54  	// and functionality to support CloseNotifier. See *connReader docs.
    55  	r *connReader
    56  	w *checkConnErrorWriter
    57  
    58  	curState struct{ atomic uint64 } // packed (unixtime<<8|uint8(ConnState))
    59  }
    60  
    61  func (c *conn) finalFlush() {
    62  }
    63  
    64  // Close the connection.
    65  func (c *conn) close() error {
    66  	err := c.server.onCloseHandler.OnClose(c.w, c.r)
    67  	c.rwc.Close()
    68  	c.r.abortPendingRead()
    69  	return err
    70  }
    71  
    72  // rstAvoidanceDelay is the amount of time we sleep after closing the
    73  // write side of a TCP connection before closing the entire socket.
    74  // By sleeping, we increase the chances that the client sees our FIN
    75  // and processes its final data before they process the subsequent RST
    76  // from closing a connection with known unread data.
    77  // This RST seems to occur mostly on BSD systems. (And Windows?)
    78  // This timeout is somewhat arbitrary (~latency around the planet).
    79  const rstAvoidanceDelay = 500 * time.Millisecond
    80  
    81  type closeWriter interface {
    82  	CloseWrite() error
    83  }
    84  
    85  var _ closeWriter = (*net.TCPConn)(nil)
    86  
    87  // closeWrite flushes any outstanding data and sends a FIN packet (if
    88  // client is connected via TCP), signalling that we're done. We then
    89  // pause for a bit, hoping the client processes it before any
    90  // subsequent RST.
    91  //
    92  // See https://golang.org/issue/3595
    93  func (c *conn) closeWriteAndWait() {
    94  	c.finalFlush()
    95  	if tcp, ok := c.rwc.(closeWriter); ok {
    96  		tcp.CloseWrite()
    97  	}
    98  	time.Sleep(rstAvoidanceDelay)
    99  }
   100  
   101  func (c *conn) setState(nc net.Conn, state ConnState) {
   102  	srv := c.server
   103  	switch state {
   104  	case StateNew:
   105  		srv.trackConn(c, true)
   106  	case StateHijacked, StateClosed:
   107  		srv.trackConn(c, false)
   108  	}
   109  	if state > 0xff || state < 0 {
   110  		panic("internal error")
   111  	}
   112  	packedState := uint64(time.Now().Unix()<<8) | uint64(state)
   113  	atomic.StoreUint64(&c.curState.atomic, packedState)
   114  	if hook := srv.ConnState; hook != nil {
   115  		hook(nc, state)
   116  	}
   117  }
   118  
   119  func (c *conn) getState() (state ConnState, unixSec int64) {
   120  	packedState := atomic.LoadUint64(&c.curState.atomic)
   121  	return ConnState(packedState & 0xff), int64(packedState >> 8)
   122  }
   123  
   124  // ErrAbortHandler is a sentinel panic value to abort a handler.
   125  // While any panic from OnHandshake aborts the response to the client,
   126  // panicking with ErrAbortHandler also suppresses logging of a stack
   127  // trace to the server's error log.
   128  var ErrAbortHandler = errors.New("net/tcp: abort onMsgHandle")
   129  var errTooLarge = errors.New("tcp: read too large")
   130  
   131  // isCommonNetReadError reports whether err is a common error
   132  // encountered during reading a request off the network when the
   133  // client has gone away or had its read fail somehow. This is used to
   134  // determine which logs are interesting enough to log about.
   135  func isCommonNetReadError(err error) bool {
   136  	if err == io.EOF {
   137  		return true
   138  	}
   139  	if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
   140  		return true
   141  	}
   142  	if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {
   143  		return true
   144  	}
   145  	return false
   146  }
   147  
   148  // onMsgRead next request from connection.
   149  func (c *conn) readRequest(ctx context.Context) (req any, err error) {
   150  
   151  	var (
   152  		wholeReqDeadline time.Time // or zero if none
   153  		hdrDeadline      time.Time // or zero if none
   154  	)
   155  	t0 := time.Now()
   156  	if d := c.server.readTimeout(); d != 0 {
   157  		hdrDeadline = t0.Add(d)
   158  	}
   159  	if d := c.server.ReadTimeout; d != 0 {
   160  		wholeReqDeadline = t0.Add(d)
   161  	}
   162  	c.rwc.SetReadDeadline(hdrDeadline)
   163  	if d := c.server.WriteTimeout; d != 0 {
   164  		defer func() {
   165  			c.rwc.SetWriteDeadline(time.Now().Add(d))
   166  		}()
   167  	}
   168  
   169  	c.r.setReadLimit(c.server.initialReadLimitSize())
   170  	req, err = c.server.onMsgReadHandler.OnMsgRead(c.r)
   171  	if err != nil {
   172  		if c.r.hitReadLimit() {
   173  			return nil, errTooLarge
   174  		}
   175  		return nil, err
   176  	}
   177  
   178  	c.r.setInfiniteReadLimit()
   179  
   180  	// Adjust the read deadline if necessary.
   181  	if !hdrDeadline.Equal(wholeReqDeadline) {
   182  		c.rwc.SetReadDeadline(wholeReqDeadline)
   183  	}
   184  
   185  	return req, nil
   186  }
   187  
   188  // Serve a new connection.
   189  func (c *conn) serve(ctx context.Context) {
   190  	c.remoteAddr = c.rwc.RemoteAddr().String()
   191  	ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())
   192  	// handle close
   193  	defer func() {
   194  		if err := recover(); err != nil && err != ErrAbortHandler {
   195  			const size = 64 << 10
   196  			buf := make([]byte, size)
   197  			buf = buf[:runtime.Stack(buf, false)]
   198  			c.server.logf("tcp: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
   199  		}
   200  		c.server.CheckError(c.w, c.r, c.close())
   201  		c.setState(c.rwc, StateClosed)
   202  	}()
   203  
   204  	// TCP from here on.
   205  	// cancel after this connection is handled
   206  	ctx, cancelCtx := context.WithCancel(ctx)
   207  	c.cancelCtx = cancelCtx
   208  	defer cancelCtx()
   209  
   210  	// wrap original conn itself with buffer
   211  	c.r = &connReader{conn: c}
   212  	c.w = &checkConnErrorWriter{c: c}
   213  
   214  	// read and handle the msg
   215  	dispatch.NewDispatch(dispatch.ReaderFunc(func(ctx context.Context) (any, error) {
   216  		msg, err := c.readRequest(ctx)
   217  		if c.r.remain != c.server.initialReadLimitSize() {
   218  			// If we read any bytes off the wire, we're active.
   219  			c.setState(c.rwc, StateActive)
   220  		}
   221  		if err = c.server.CheckError(c.w, c.r, err); err != nil {
   222  			if isCommonNetReadError(err) {
   223  				return nil, err // don't reply
   224  			}
   225  			// otherwise, close socket's Write channel and wait for a monment
   226  			c.closeWriteAndWait()
   227  			return nil, err
   228  		}
   229  		return msg, nil
   230  	}), dispatch.HandlerFunc(func(ctx context.Context, msg any) error {
   231  		return c.server.CheckError(c.w, c.r, c.server.onMsgHandleHandler.OnMsgHandle(c.w, msg))
   232  	})).WithContext(ctx).Start()
   233  	// after onMsgHandle, read all left data
   234  	c.r.startBackgroundRead()
   235  }
   236  
   237  // checkConnErrorWriter writes to c.rwc and records any write errors to c.werr.
   238  // It only contains one field (and a pointer field at that), so it
   239  // fits in an interface value without an extra allocation.
   240  type checkConnErrorWriter struct {
   241  	c *conn
   242  }
   243  
   244  func (w checkConnErrorWriter) Write(p []byte) (n int, err error) {
   245  	n, err = w.c.rwc.Write(p)
   246  	if err != nil && w.c.werr == nil {
   247  		w.c.werr = err
   248  		w.c.cancelCtx()
   249  	}
   250  	return
   251  }