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 }