github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/eventloop_unix.go (about)

     1  // +build linux darwin netbsd freebsd openbsd dragonfly
     2  
     3  package net
     4  
     5  import (
     6  	nt "net"
     7  	"time"
     8  
     9  	"github.com/angenalZZZ/gofunc/net/internal/netpoll"
    10  	"golang.org/x/sys/unix"
    11  )
    12  
    13  type eventloop struct {
    14  	idx               int                     // loop index in the server loops list
    15  	svr               *server                 // server in loop
    16  	codec             ICodec                  // codec for TCP
    17  	packet            []byte                  // read packet buffer
    18  	poller            *netpoll.Poller         // epoll or kqueue
    19  	connCount         int32                   // number of active connections in event-loop
    20  	connections       map[int]*conn           // loop connections fd -> conn
    21  	eventHandler      EventHandler            // user eventHandler
    22  	calibrateCallback func(*eventloop, int32) // callback func for re-adjusting connCount
    23  }
    24  
    25  func (el *eventloop) closeAllConns() {
    26  	// Close loops and all outstanding connections
    27  	for _, c := range el.connections {
    28  		_ = el.loopCloseConn(c, nil)
    29  	}
    30  }
    31  
    32  func (el *eventloop) loopRun() {
    33  	defer func() {
    34  		el.closeAllConns()
    35  		if el.idx == 0 && el.svr.opts.Ticker {
    36  			close(el.svr.ticktock)
    37  		}
    38  		el.svr.signalShutdown()
    39  	}()
    40  
    41  	if el.idx == 0 && el.svr.opts.Ticker {
    42  		go el.loopTicker()
    43  	}
    44  
    45  	el.svr.logger.Printf("event-loop:%d exits with error: %v\n", el.idx, el.poller.Polling(el.handleEvent))
    46  }
    47  
    48  func (el *eventloop) loopAccept(fd int) error {
    49  	if fd == el.svr.ln.fd {
    50  		if el.svr.ln.pconn != nil {
    51  			return el.loopReadUDP(fd)
    52  		}
    53  		nfd, sa, err := unix.Accept(fd)
    54  		if err != nil {
    55  			if err == unix.EAGAIN {
    56  				return nil
    57  			}
    58  			return err
    59  		}
    60  		if err = unix.SetNonblock(nfd, true); err != nil {
    61  			return err
    62  		}
    63  		c := newTCPConn(nfd, el, sa)
    64  		if err = el.poller.AddRead(c.fd); err == nil {
    65  			el.connections[c.fd] = c
    66  			el.calibrateCallback(el, 1)
    67  			return el.loopOpen(c)
    68  		}
    69  		return err
    70  	}
    71  	return nil
    72  }
    73  
    74  func (el *eventloop) loopOpen(c *conn) error {
    75  	c.opened = true
    76  	c.localAddr = el.svr.ln.lnaddr
    77  	c.remoteAddr = netpoll.SockaddrToTCPOrUnixAddr(c.sa)
    78  	out, action := el.eventHandler.OnOpened(c)
    79  	if el.svr.opts.TCPKeepAlive > 0 {
    80  		if _, ok := el.svr.ln.ln.(*nt.TCPListener); ok {
    81  			_ = netpoll.SetKeepAlive(c.fd, int(el.svr.opts.TCPKeepAlive/time.Second))
    82  		}
    83  	}
    84  	if out != nil {
    85  		c.open(out)
    86  	}
    87  
    88  	if !c.outboundBuffer.IsEmpty() {
    89  		_ = el.poller.AddWrite(c.fd)
    90  	}
    91  
    92  	return el.handleAction(c, action)
    93  }
    94  
    95  func (el *eventloop) loopRead(c *conn) error {
    96  	n, err := unix.Read(c.fd, el.packet)
    97  	if n == 0 || err != nil {
    98  		if err == unix.EAGAIN {
    99  			return nil
   100  		}
   101  		return el.loopCloseConn(c, err)
   102  	}
   103  	c.buffer = el.packet[:n]
   104  
   105  	for inFrame, _ := c.read(); inFrame != nil; inFrame, _ = c.read() {
   106  		out, action := el.eventHandler.React(inFrame, c)
   107  		if out != nil {
   108  			outFrame, _ := el.codec.Encode(c, out)
   109  			el.eventHandler.PreWrite()
   110  			c.write(outFrame)
   111  		}
   112  		switch action {
   113  		case None:
   114  		case Close:
   115  			return el.loopCloseConn(c, nil)
   116  		case Shutdown:
   117  			return errServerShutdown
   118  		}
   119  		if !c.opened {
   120  			return nil
   121  		}
   122  	}
   123  	_, _ = c.inboundBuffer.Write(c.buffer)
   124  
   125  	return nil
   126  }
   127  
   128  func (el *eventloop) loopWrite(c *conn) error {
   129  	el.eventHandler.PreWrite()
   130  
   131  	head, tail := c.outboundBuffer.LazyReadAll()
   132  	n, err := unix.Write(c.fd, head)
   133  	if err != nil {
   134  		if err == unix.EAGAIN {
   135  			return nil
   136  		}
   137  		return el.loopCloseConn(c, err)
   138  	}
   139  	c.outboundBuffer.Shift(n)
   140  
   141  	if len(head) == n && tail != nil {
   142  		n, err = unix.Write(c.fd, tail)
   143  		if err != nil {
   144  			if err == unix.EAGAIN {
   145  				return nil
   146  			}
   147  			return el.loopCloseConn(c, err)
   148  		}
   149  		c.outboundBuffer.Shift(n)
   150  	}
   151  
   152  	if c.outboundBuffer.IsEmpty() {
   153  		_ = el.poller.ModRead(c.fd)
   154  	}
   155  	return nil
   156  }
   157  
   158  func (el *eventloop) loopCloseConn(c *conn, err error) error {
   159  	if !c.outboundBuffer.IsEmpty() && err == nil {
   160  		_ = el.loopWrite(c)
   161  	}
   162  	err0, err1 := el.poller.Delete(c.fd), unix.Close(c.fd)
   163  	if err0 == nil && err1 == nil {
   164  		delete(el.connections, c.fd)
   165  		el.calibrateCallback(el, -1)
   166  		switch el.eventHandler.OnClosed(c, err) {
   167  		case Shutdown:
   168  			return errServerShutdown
   169  		}
   170  		c.releaseTCP()
   171  	} else {
   172  		if err0 != nil {
   173  			el.svr.logger.Printf("failed to delete fd:%d from poller, error:%v\n", c.fd, err0)
   174  		}
   175  		if err1 != nil {
   176  			el.svr.logger.Printf("failed to close fd:%d, error:%v\n", c.fd, err1)
   177  		}
   178  	}
   179  	return nil
   180  }
   181  
   182  func (el *eventloop) loopWake(c *conn) error {
   183  	//if co, ok := el.connections[c.fd]; !ok || co != c {
   184  	//	return nil // ignore stale wakes.
   185  	//}
   186  	out, action := el.eventHandler.React(nil, c)
   187  	if out != nil {
   188  		frame, _ := el.codec.Encode(c, out)
   189  		c.write(frame)
   190  	}
   191  	return el.handleAction(c, action)
   192  }
   193  
   194  func (el *eventloop) loopTicker() {
   195  	var (
   196  		delay time.Duration
   197  		open  bool
   198  		err   error
   199  	)
   200  	for {
   201  		err = el.poller.Trigger(func() (err error) {
   202  			delay, action := el.eventHandler.Tick()
   203  			el.svr.ticktock <- delay
   204  			switch action {
   205  			case None:
   206  			case Shutdown:
   207  				err = errServerShutdown
   208  			}
   209  			return
   210  		})
   211  		if err != nil {
   212  			el.svr.logger.Printf("failed to awake poller with error:%v, stopping ticker\n", err)
   213  			break
   214  		}
   215  		if delay, open = <-el.svr.ticktock; open {
   216  			time.Sleep(delay)
   217  		} else {
   218  			break
   219  		}
   220  	}
   221  }
   222  
   223  func (el *eventloop) handleAction(c *conn, action Action) error {
   224  	switch action {
   225  	case None:
   226  		return nil
   227  	case Close:
   228  		return el.loopCloseConn(c, nil)
   229  	case Shutdown:
   230  		return errServerShutdown
   231  	default:
   232  		return nil
   233  	}
   234  }
   235  
   236  func (el *eventloop) loopReadUDP(fd int) error {
   237  	n, sa, err := unix.Recvfrom(fd, el.packet, 0)
   238  	if err != nil || n == 0 {
   239  		if err != nil && err != unix.EAGAIN {
   240  			el.svr.logger.Printf("failed to read UDP packet from fd:%d, error:%v\n", fd, err)
   241  		}
   242  		return nil
   243  	}
   244  	c := newUDPConn(fd, el, sa)
   245  	out, action := el.eventHandler.React(el.packet[:n], c)
   246  	if out != nil {
   247  		el.eventHandler.PreWrite()
   248  		_ = c.sendTo(out)
   249  	}
   250  	switch action {
   251  	case Shutdown:
   252  		return errServerShutdown
   253  	}
   254  	c.releaseUDP()
   255  	return nil
   256  }