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

     1  // +build windows
     2  
     3  package net
     4  
     5  import (
     6  	nt "net"
     7  	"time"
     8  
     9  	"github.com/angenalZZZ/gofunc/net/pool/bytebuffer"
    10  )
    11  
    12  type eventloop struct {
    13  	ch                chan interface{}        // command channel
    14  	idx               int                     // loop index
    15  	svr               *server                 // server in loop
    16  	codec             ICodec                  // codec for TCP
    17  	connCount         int32                   // number of active connections in event-loop
    18  	connections       map[*stdConn]struct{}   // track all the sockets bound to this loop
    19  	eventHandler      EventHandler            // user eventHandler
    20  	calibrateCallback func(*eventloop, int32) // callback func for re-adjusting connCount
    21  }
    22  
    23  func (el *eventloop) loopRun() {
    24  	var err error
    25  	defer func() {
    26  		if el.idx == 0 && el.svr.opts.Ticker {
    27  			close(el.svr.ticktock)
    28  		}
    29  		el.svr.signalShutdown(err)
    30  		el.svr.loopWG.Done()
    31  		el.loopEgress()
    32  		el.svr.loopWG.Done()
    33  	}()
    34  	if el.idx == 0 && el.svr.opts.Ticker {
    35  		go el.loopTicker()
    36  	}
    37  	for v := range el.ch {
    38  		switch v := v.(type) {
    39  		case error:
    40  			err = v
    41  		case *stdConn:
    42  			err = el.loopAccept(v)
    43  		case *tcpIn:
    44  			err = el.loopRead(v)
    45  		case *udpIn:
    46  			err = el.loopReadUDP(v.c)
    47  		case *stderr:
    48  			err = el.loopError(v.c, v.err)
    49  		case wakeReq:
    50  			err = el.loopWake(v.c)
    51  		case func() error:
    52  			err = v()
    53  		}
    54  		if err != nil {
    55  			el.svr.logger.Printf("event-loop:%d exits with error:%v\n", el.idx, err)
    56  			break
    57  		}
    58  	}
    59  }
    60  
    61  func (el *eventloop) loopAccept(c *stdConn) error {
    62  	el.connections[c] = struct{}{}
    63  	c.localAddr = el.svr.ln.lnaddr
    64  	c.remoteAddr = c.conn.RemoteAddr()
    65  	el.calibrateCallback(el, 1)
    66  
    67  	out, action := el.eventHandler.OnOpened(c)
    68  	if out != nil {
    69  		el.eventHandler.PreWrite()
    70  		_, _ = c.conn.Write(out)
    71  	}
    72  	if el.svr.opts.TCPKeepAlive > 0 {
    73  		if c, ok := c.conn.(*nt.TCPConn); ok {
    74  			_ = c.SetKeepAlive(true)
    75  			_ = c.SetKeepAlivePeriod(el.svr.opts.TCPKeepAlive)
    76  		}
    77  	}
    78  	return el.handleAction(c, action)
    79  }
    80  
    81  func (el *eventloop) loopRead(ti *tcpIn) (err error) {
    82  	c := ti.c
    83  	c.buffer = ti.in
    84  
    85  	for inFrame, _ := c.read(); inFrame != nil; inFrame, _ = c.read() {
    86  		out, action := el.eventHandler.React(inFrame, c)
    87  		if out != nil {
    88  			outFrame, _ := el.codec.Encode(c, out)
    89  			el.eventHandler.PreWrite()
    90  			_, err = c.conn.Write(outFrame)
    91  		}
    92  		switch action {
    93  		case None:
    94  		case Close:
    95  			return el.loopCloseConn(c)
    96  		case Shutdown:
    97  			return errServerShutdown
    98  		}
    99  		if err != nil {
   100  			return el.loopError(c, err)
   101  		}
   102  	}
   103  	_, _ = c.inboundBuffer.Write(c.buffer.Bytes())
   104  	bytebuffer.Put(c.buffer)
   105  	c.buffer = nil
   106  	return
   107  }
   108  
   109  func (el *eventloop) loopCloseConn(c *stdConn) error {
   110  	return c.conn.SetReadDeadline(time.Now())
   111  }
   112  
   113  func (el *eventloop) loopEgress() {
   114  	var closed bool
   115  	for v := range el.ch {
   116  		switch v := v.(type) {
   117  		case error:
   118  			if v == errCloseAllConns {
   119  				closed = true
   120  				for c := range el.connections {
   121  					_ = el.loopCloseConn(c)
   122  				}
   123  			}
   124  		case *stderr:
   125  			_ = el.loopError(v.c, v.err)
   126  		}
   127  		if closed && len(el.connections) == 0 {
   128  			break
   129  		}
   130  	}
   131  }
   132  
   133  func (el *eventloop) loopTicker() {
   134  	var (
   135  		delay time.Duration
   136  		open  bool
   137  	)
   138  	for {
   139  		el.ch <- func() (err error) {
   140  			delay, action := el.eventHandler.Tick()
   141  			el.svr.ticktock <- delay
   142  			switch action {
   143  			case Shutdown:
   144  				err = errServerShutdown
   145  			}
   146  			return
   147  		}
   148  		if delay, open = <-el.svr.ticktock; open {
   149  			time.Sleep(delay)
   150  		} else {
   151  			break
   152  		}
   153  	}
   154  }
   155  
   156  func (el *eventloop) loopError(c *stdConn, err error) (e error) {
   157  	if e = c.conn.Close(); e == nil {
   158  		delete(el.connections, c)
   159  		el.calibrateCallback(el, -1)
   160  		switch el.eventHandler.OnClosed(c, err) {
   161  		case Shutdown:
   162  			return errServerShutdown
   163  		}
   164  		c.releaseTCP()
   165  	} else {
   166  		el.svr.logger.Printf("failed to close connection:%s, error:%v\n", c.remoteAddr.String(), e)
   167  	}
   168  	return
   169  }
   170  
   171  func (el *eventloop) loopWake(c *stdConn) error {
   172  	//if co, ok := el.connections[c]; !ok || co != c {
   173  	//	return nil // ignore stale wakes.
   174  	//}
   175  	out, action := el.eventHandler.React(nil, c)
   176  	if out != nil {
   177  		frame, _ := el.codec.Encode(c, out)
   178  		_, _ = c.conn.Write(frame)
   179  	}
   180  	return el.handleAction(c, action)
   181  }
   182  
   183  func (el *eventloop) handleAction(c *stdConn, action Action) error {
   184  	switch action {
   185  	case None:
   186  		return nil
   187  	case Close:
   188  		return el.loopCloseConn(c)
   189  	case Shutdown:
   190  		return errServerShutdown
   191  	default:
   192  		return nil
   193  	}
   194  }
   195  
   196  func (el *eventloop) loopReadUDP(c *stdConn) error {
   197  	out, action := el.eventHandler.React(c.buffer.Bytes(), c)
   198  	if out != nil {
   199  		el.eventHandler.PreWrite()
   200  		_, _ = el.svr.ln.pconn.WriteTo(out, c.remoteAddr)
   201  	}
   202  	switch action {
   203  	case Shutdown:
   204  		return errServerShutdown
   205  	}
   206  	c.releaseUDP()
   207  	return nil
   208  }