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 }