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 }