github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/connection_unix.go (about) 1 // +build linux darwin netbsd freebsd openbsd dragonfly 2 3 package net 4 5 import ( 6 nt "net" 7 8 "github.com/angenalZZZ/gofunc/net/internal/netpoll" 9 "github.com/angenalZZZ/gofunc/net/pool/bytebuffer" 10 prb "github.com/angenalZZZ/gofunc/net/pool/ringbuffer" 11 "github.com/angenalZZZ/gofunc/net/ringbuffer" 12 "golang.org/x/sys/unix" 13 ) 14 15 type conn struct { 16 fd int // file descriptor 17 sa unix.Sockaddr // remote socket address 18 ctx interface{} // user-defined context 19 loop *eventloop // connected event-loop 20 buffer []byte // reuse memory of inbound data as a temporary buffer 21 codec ICodec // codec for TCP 22 opened bool // connection opened event fired 23 localAddr nt.Addr // local addr 24 remoteAddr nt.Addr // remote addr 25 byteBuffer *bytebuffer.ByteBuffer // bytes buffer for buffering current packet and data in ring-buffer 26 inboundBuffer *ringbuffer.RingBuffer // buffer for data from client 27 outboundBuffer *ringbuffer.RingBuffer // buffer for data that is ready to write to client 28 } 29 30 func newTCPConn(fd int, el *eventloop, sa unix.Sockaddr) *conn { 31 return &conn{ 32 fd: fd, 33 sa: sa, 34 loop: el, 35 codec: el.codec, 36 inboundBuffer: prb.Get(), 37 outboundBuffer: prb.Get(), 38 } 39 } 40 41 func (c *conn) releaseTCP() { 42 c.opened = false 43 c.sa = nil 44 c.ctx = nil 45 c.buffer = nil 46 c.localAddr = nil 47 c.remoteAddr = nil 48 prb.Put(c.inboundBuffer) 49 prb.Put(c.outboundBuffer) 50 c.inboundBuffer = nil 51 c.outboundBuffer = nil 52 bytebuffer.Put(c.byteBuffer) 53 c.byteBuffer = nil 54 } 55 56 func newUDPConn(fd int, el *eventloop, sa unix.Sockaddr) *conn { 57 return &conn{ 58 fd: fd, 59 sa: sa, 60 localAddr: el.svr.ln.lnaddr, 61 remoteAddr: netpoll.SockaddrToUDPAddr(sa), 62 } 63 } 64 65 func (c *conn) releaseUDP() { 66 c.ctx = nil 67 c.localAddr = nil 68 c.remoteAddr = nil 69 } 70 71 func (c *conn) open(buf []byte) { 72 n, err := unix.Write(c.fd, buf) 73 if err != nil { 74 _, _ = c.outboundBuffer.Write(buf) 75 return 76 } 77 78 if n < len(buf) { 79 _, _ = c.outboundBuffer.Write(buf[n:]) 80 } 81 } 82 83 func (c *conn) read() ([]byte, error) { 84 return c.codec.Decode(c) 85 } 86 87 func (c *conn) write(buf []byte) { 88 if !c.outboundBuffer.IsEmpty() { 89 _, _ = c.outboundBuffer.Write(buf) 90 return 91 } 92 n, err := unix.Write(c.fd, buf) 93 if err != nil { 94 if err == unix.EAGAIN { 95 _, _ = c.outboundBuffer.Write(buf) 96 _ = c.loop.poller.ModReadWrite(c.fd) 97 return 98 } 99 _ = c.loop.loopCloseConn(c, err) 100 return 101 } 102 if n < len(buf) { 103 _, _ = c.outboundBuffer.Write(buf[n:]) 104 _ = c.loop.poller.ModReadWrite(c.fd) 105 } 106 } 107 108 func (c *conn) sendTo(buf []byte) error { 109 return unix.Sendto(c.fd, buf, 0, c.sa) 110 } 111 112 // ================================= Public APIs of gnt.Conn ================================= 113 114 func (c *conn) Read() []byte { 115 if c.inboundBuffer.IsEmpty() { 116 return c.buffer 117 } 118 c.byteBuffer = c.inboundBuffer.WithByteBuffer(c.buffer) 119 return c.byteBuffer.Bytes() 120 } 121 122 func (c *conn) ResetBuffer() { 123 c.buffer = c.buffer[:0] 124 c.inboundBuffer.Reset() 125 bytebuffer.Put(c.byteBuffer) 126 c.byteBuffer = nil 127 } 128 129 func (c *conn) ReadN(n int) (size int, buf []byte) { 130 inBufferLen := c.inboundBuffer.Length() 131 tempBufferLen := len(c.buffer) 132 if totalLen := inBufferLen + tempBufferLen; totalLen < n || n <= 0 { 133 n = totalLen 134 } 135 size = n 136 if c.inboundBuffer.IsEmpty() { 137 buf = c.buffer[:n] 138 return 139 } 140 head, tail := c.inboundBuffer.LazyRead(n) 141 c.byteBuffer = bytebuffer.Get() 142 _, _ = c.byteBuffer.Write(head) 143 _, _ = c.byteBuffer.Write(tail) 144 if inBufferLen >= n { 145 buf = c.byteBuffer.Bytes() 146 return 147 } 148 149 restSize := n - inBufferLen 150 _, _ = c.byteBuffer.Write(c.buffer[:restSize]) 151 buf = c.byteBuffer.Bytes() 152 return 153 } 154 155 func (c *conn) ShiftN(n int) (size int) { 156 inBufferLen := c.inboundBuffer.Length() 157 tempBufferLen := len(c.buffer) 158 if inBufferLen+tempBufferLen < n || n <= 0 { 159 c.ResetBuffer() 160 size = inBufferLen + tempBufferLen 161 return 162 } 163 size = n 164 if c.inboundBuffer.IsEmpty() { 165 c.buffer = c.buffer[n:] 166 return 167 } 168 169 bytebuffer.Put(c.byteBuffer) 170 c.byteBuffer = nil 171 172 if inBufferLen >= n { 173 c.inboundBuffer.Shift(n) 174 return 175 } 176 c.inboundBuffer.Reset() 177 178 restSize := n - inBufferLen 179 c.buffer = c.buffer[restSize:] 180 return 181 } 182 183 func (c *conn) BufferLength() int { 184 return c.inboundBuffer.Length() + len(c.buffer) 185 } 186 187 func (c *conn) AsyncWrite(buf []byte) (err error) { 188 var encodedBuf []byte 189 if encodedBuf, err = c.codec.Encode(c, buf); err == nil { 190 return c.loop.poller.Trigger(func() error { 191 if c.opened { 192 c.write(encodedBuf) 193 } 194 return nil 195 }) 196 } 197 return 198 } 199 200 func (c *conn) SendTo(buf []byte) error { 201 return c.sendTo(buf) 202 } 203 204 func (c *conn) Wake() error { 205 return c.loop.poller.Trigger(func() error { 206 return c.loop.loopWake(c) 207 }) 208 } 209 210 func (c *conn) Close() error { 211 return c.loop.poller.Trigger(func() error { 212 return c.loop.loopCloseConn(c, nil) 213 }) 214 } 215 216 func (c *conn) Context() interface{} { return c.ctx } 217 func (c *conn) SetContext(ctx interface{}) { c.ctx = ctx } 218 func (c *conn) LocalAddr() nt.Addr { return c.localAddr } 219 func (c *conn) RemoteAddr() nt.Addr { return c.remoteAddr }