github.com/GeniusesGroup/libgo@v0.0.0-20220929090155-5ff932cb408e/tcp/stream.go (about)

     1  /* For license and copyright information please see the LEGAL file in the code repository */
     2  
     3  package tcp
     4  
     5  import (
     6  	"github.com/GeniusesGroup/libgo/protocol"
     7  )
     8  
     9  // Socket provide some fields to hold socket state.
    10  // Because each socket methods just call by a fixed worker on same CPU core in sync order, don't need to lock or changed atomic any field
    11  type Socket struct {
    12  	connection      protocol.Connection
    13  	stream          protocol.Stream
    14  	mtu             int
    15  	mss             int    // Max Segment Length
    16  	sourcePort      uint16 // local
    17  	destinationPort uint16 // remote
    18  	status          SocketState
    19  	state           chan SocketState
    20  
    21  	// TODO::: Cookie, save socket in nvm
    22  
    23  	timing
    24  	send
    25  	recv
    26  }
    27  
    28  // Init use to initialize the socket after allocation in both server or client
    29  func (s *Socket) Init(timeout protocol.Duration) {
    30  	// TODO:::
    31  	s.mss = OptionDefault_MSS
    32  	s.setState(SocketState_LISTEN)
    33  
    34  	if timeout == 0 {
    35  		timeout = KeepAlive_Idle
    36  	}
    37  
    38  	s.timing.init()
    39  	s.recv.init(timeout)
    40  	s.send.init(timeout)
    41  }
    42  
    43  func (s *Socket) Connection() protocol.Connection { return s.connection }
    44  func (s *Socket) Stream() protocol.Stream         { return s.stream }
    45  
    46  // Reset use to reset the socket to store in a sync.Pool to reuse in near future before 2 GC period to dealloc forever
    47  func (s *Socket) Reset() {
    48  	// TODO:::
    49  }
    50  
    51  // Open call when a client want to open the socket on the client side.
    52  func (s *Socket) Open() (err protocol.Error) {
    53  	err = s.sendSYN()
    54  	s.setState(SocketState_SYN_SENT)
    55  	// TODO::: timer, retry, change status, block on status change until SocketState_ESTABLISHED
    56  	return
    57  }
    58  
    59  // CloseSending shutdown the sending side of a socket. Much like close except that we don't receive shut down
    60  func (s *Socket) CloseSending() (err protocol.Error) {
    61  	return
    62  }
    63  
    64  func (s *Socket) SetTimeout(d protocol.Duration) (err protocol.Error) {
    65  	err = s.SetReadTimeout(d)
    66  	if err != nil {
    67  		return
    68  	}
    69  	err = s.SetWriteTimeout(d)
    70  	return
    71  }
    72  func (s *Socket) SetReadTimeout(d protocol.Duration) (err protocol.Error) {
    73  	err = s.checkSocket()
    74  	if err != nil {
    75  		return
    76  	}
    77  
    78  	if d < 0 {
    79  		// no timeout
    80  		// TODO::: is it ok??
    81  		s.recv.readTimer.Stop()
    82  		return
    83  	}
    84  	s.recv.readTimer.Reset(d)
    85  	return
    86  }
    87  func (s *Socket) SetWriteTimeout(d protocol.Duration) (err protocol.Error) {
    88  	err = s.checkSocket()
    89  	if err != nil {
    90  		return
    91  	}
    92  
    93  	if d < 0 {
    94  		// no timeout
    95  		s.send.writeTimer.Stop()
    96  		return
    97  	}
    98  	s.send.writeTimer.Reset(d)
    99  	return
   100  }
   101  
   102  // Receive Don't hold segment, So caller can reuse packet slice for any purpose.
   103  // It must be non blocking and just route packet not to wait for anything else.
   104  // for each socket upper layer must call by same CPU(core), so we don't need implement any locking mechanism.
   105  // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_ipv4.c#n1965
   106  func (s *Socket) Receive(segment Packet) (err protocol.Error) {
   107  	err = segment.CheckPacket()
   108  	if err != nil {
   109  		return
   110  	}
   111  
   112  	// TODO:::
   113  
   114  	switch s.status {
   115  	case SocketState_LISTEN:
   116  		err = s.incomeSegmentOnListenState(segment)
   117  	case SocketState_SYN_SENT:
   118  		err = s.incomeSegmentOnSynSentState(segment)
   119  	case SocketState_SYN_RECEIVED:
   120  		err = s.incomeSegmentOnSynReceivedState(segment)
   121  	case SocketState_ESTABLISHED:
   122  		err = s.incomeSegmentOnEstablishedState(segment)
   123  	case SocketState_FIN_WAIT_1:
   124  		err = s.incomeSegmentOnFinWait1State(segment)
   125  	case SocketState_FIN_WAIT_2:
   126  		err = s.incomeSegmentOnFinWait2State(segment)
   127  	case SocketState_CLOSE:
   128  		err = s.incomeSegmentOnCloseState(segment)
   129  	case SocketState_CLOSE_WAIT:
   130  		err = s.incomeSegmentOnCloseWaitState(segment)
   131  	case SocketState_CLOSING:
   132  		err = s.incomeSegmentOnClosingState(segment)
   133  	case SocketState_LAST_ACK:
   134  		err = s.incomeSegmentOnLastAckState(segment)
   135  	case SocketState_TIME_WAIT:
   136  		err = s.incomeSegmentOnTimeWaitState(segment)
   137  	}
   138  	return
   139  }