github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/tcp/socket.go (about)

     1  /* For license and copyright information please see LEGAL file in repository */
     2  
     3  package tcp
     4  
     5  import (
     6  	"../protocol"
     7  	"../timer"
     8  )
     9  
    10  /*
    11  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
    12  
    13                                +---------+ ---------\      active OPEN
    14                                |  CLOSED |            \    -----------
    15                                +---------+<---------\   \   create TCB
    16                                  |     ^              \   \  snd SYN
    17                     passive OPEN |     |   CLOSE        \   \
    18                     ------------ |     | ----------       \   \
    19                      create TCB  |     | delete TCB         \   \
    20                                  V     |                      \   \
    21                                +---------+            CLOSE    |    \
    22                                |  LISTEN |          ---------- |     |
    23                                +---------+          delete TCB |     |
    24                     rcv SYN      |     |     SEND              |     |
    25                    -----------   |     |    -------            |     V
    26   +---------+      snd SYN,ACK  /       \   snd SYN          +---------+
    27   |         |<-----------------           ------------------>|         |
    28   |   SYN   |                    rcv SYN                     |   SYN   |
    29   |   RCVD  |<-----------------------------------------------|   SENT  |
    30   |         |                    snd ACK                     |         |
    31   |         |------------------           -------------------|         |
    32   +---------+   rcv ACK of SYN  \       /  rcv SYN,ACK       +---------+
    33     |           --------------   |     |   -----------
    34     |                  x         |     |     snd ACK
    35     |                            V     V
    36     |  CLOSE                   +---------+
    37     | -------                  |  ESTAB  |
    38     | snd FIN                  +---------+
    39     |                   CLOSE    |     |    rcv FIN
    40     V                  -------   |     |    -------
    41   +---------+          snd FIN  /       \   snd ACK          +---------+
    42   |  FIN    |<-----------------           ------------------>|  CLOSE  |
    43   | WAIT-1  |------------------                              |   WAIT  |
    44   +---------+          rcv FIN  \                            +---------+
    45     | rcv ACK of FIN   -------   |                            CLOSE  |
    46     | --------------   snd ACK   |                           ------- |
    47     V        x                   V                           snd FIN V
    48   +---------+                  +---------+                   +---------+
    49   |FINWAIT-2|                  | CLOSING |                   | LAST-ACK|
    50   +---------+                  +---------+                   +---------+
    51     |                rcv ACK of FIN |                 rcv ACK of FIN |
    52     |  rcv FIN       -------------- |    Timeout=2MSL -------------- |
    53     |  -------              x       V    ------------        x       V
    54      \ snd ACK                 +---------+delete TCB         +---------+
    55       ------------------------>|TIME WAIT|------------------>| CLOSED  |
    56                                +---------+                   +---------+
    57  */
    58  type Socket struct {
    59  	Connection      protocol.Connection
    60  	Stream          protocol.Stream
    61  	mtu             int
    62  	mss             int // Max Segment Length
    63  	sourcePort      uint16
    64  	destinationPort uint16
    65  	status          SocketState
    66  	state           chan SocketState
    67  
    68  	// TODO::: Cookie, save socket in nvm
    69  
    70  	socketTimer timer.Timer
    71  	readTimer   timer.Timer // read deadline timer
    72  	writeTimer  timer.Timer // write deadline timer
    73  
    74  	// Rx means Receive, and Tx means Transmit
    75  	send sendSequenceSpace
    76  	recv recvSequenceSpace
    77  }
    78  
    79  // Init use to initialize the socket after allocation in both server or client
    80  func (s *Socket) Init() {
    81  	// TODO:::
    82  	s.mss = OptionDefault_MSS
    83  	s.setState(SocketState_LISTEN)
    84  	// TODO::: set default timeout
    85  	s.readTimer.Init()
    86  	s.writeTimer.Init()
    87  	checkTimeout(s)
    88  
    89  	s.recv.init()
    90  	s.send.init()
    91  }
    92  
    93  // Reset use to reset the socket to store in a sync.Pool to reuse in near future before 2 GC period to dealloc forever
    94  func (s *Socket) Reset() {
    95  	// TODO:::
    96  }
    97  
    98  // Open call when a client want to open the socket on the client side.
    99  func (s *Socket) Open() (err protocol.Error) {
   100  	err = s.sendSYN()
   101  	s.setState(SocketState_SYN_SENT)
   102  	// TODO::: timer, retry, change status, block on status change until SocketState_ESTABLISHED
   103  	return
   104  }
   105  
   106  // CloseSending shutdown the sending side of a socket. Much like close except that we don't receive shut down
   107  func (s *Socket) CloseSending() (err protocol.Error) {
   108  	return
   109  }
   110  
   111  func (s *Socket) SetTimeout(d protocol.Duration) (err protocol.Error) {
   112  	err = s.SetReadTimeout(d)
   113  	if err != nil {
   114  		return
   115  	}
   116  	err = s.SetWriteTimeout(d)
   117  	return
   118  }
   119  func (s *Socket) SetReadTimeout(d protocol.Duration) (err protocol.Error) {
   120  	err = s.checkSocket()
   121  	if err != nil {
   122  		return
   123  	}
   124  
   125  	if d < 0 {
   126  		// no timeout
   127  		return
   128  	}
   129  	s.readTimer.Reset(d)
   130  	return
   131  }
   132  func (s *Socket) SetWriteTimeout(d protocol.Duration) (err protocol.Error) {
   133  	err = s.checkSocket()
   134  	if err != nil {
   135  		return
   136  	}
   137  
   138  	if d < 0 {
   139  		// no timeout
   140  		return
   141  	}
   142  	s.writeTimer.Reset(d)
   143  	return
   144  }
   145  
   146  // Receive Don't hold segment, So caller can reuse packet slice for any purpose.
   147  // It must be non blocking and just route packet not to wait for anything else.
   148  // for each socket upper layer must call by same CPU(core), so we don't need implement any locking mechanism.
   149  // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_ipv4.c#n1965
   150  func (s *Socket) Receive(segment Packet) (err protocol.Error) {
   151  	err = segment.CheckPacket()
   152  	if err != nil {
   153  		return
   154  	}
   155  
   156  	// TODO:::
   157  
   158  	switch s.status {
   159  	case SocketState_LISTEN:
   160  		err = s.incomeSegmentOnListenState(segment)
   161  	case SocketState_SYN_SENT:
   162  		err = s.incomeSegmentOnSynSentState(segment)
   163  	case SocketState_SYN_RECEIVED:
   164  		err = s.incomeSegmentOnSynReceivedState(segment)
   165  	case SocketState_ESTABLISHED:
   166  		err = s.incomeSegmentOnEstablishedState(segment)
   167  	case SocketState_FIN_WAIT_1:
   168  		err = s.incomeSegmentOnFinWait1State(segment)
   169  	case SocketState_FIN_WAIT_2:
   170  		err = s.incomeSegmentOnFinWait2State(segment)
   171  	case SocketState_CLOSE:
   172  		err = s.incomeSegmentOnCloseState(segment)
   173  	case SocketState_CLOSE_WAIT:
   174  		err = s.incomeSegmentOnCloseWaitState(segment)
   175  	case SocketState_CLOSING:
   176  		err = s.incomeSegmentOnClosingState(segment)
   177  	case SocketState_LAST_ACK:
   178  		err = s.incomeSegmentOnLastAckState(segment)
   179  	case SocketState_TIME_WAIT:
   180  		err = s.incomeSegmentOnTimeWaitState(segment)
   181  	}
   182  	checkTimeout(s)
   183  	return
   184  }