func (c *client) recvLoop() { delay := backoff.Exp{Min: time.Millisecond * 5} loop: for { p, err := packet.SplitDecode(c.r) if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Temporary() { c.logTemporaryError(nerr) delay.Wait() continue } c.stop(err) break loop } delay.Reset() if err := c.dispatch(p); err != nil { c.stop(err) break loop } } if c.p.OnDisconnect != nil { c.p.OnDisconnect(c.derr, c.p) } c.r = nil }
// Serve accepts incoming connections on the Listener. func (srv *Server) Serve(l net.Listener) error { if !atomic.CompareAndSwapInt32(&srv.st, none, starting) { return ErrAlreadyServerd } srv.logger = srv.options().Logger srv.quit = make(chan bool, 1) srv.listener = l srv.wg = sync.WaitGroup{} srv.cs = make(map[*client]bool) atomic.StoreInt32(&srv.st, running) srv.logServerStart() delay := backoff.Exp{Min: time.Millisecond * 5} for { conn, err := srv.listener.Accept() select { case <-srv.quit: go srv.terminateAllClients() return nil default: } if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Temporary() { srv.logTemporaryError(nerr, &delay, nil) delay.Wait() continue } if atomic.CompareAndSwapInt32(&srv.st, running, closed) { srv.listener.Close() } go srv.terminateAllClients() return err } delay.Reset() // start client goroutine. c := newClient(srv, conn) srv.wg.Add(1) go func() { c.serve() srv.wg.Done() }() } }
func (c *client) recvLoop() error { delay := backoff.Exp{Min: time.Millisecond * 5} for { p, err := packet.SplitDecode(c.rd) select { case <-c.quit: return nil default: } if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Temporary() { c.srv.logTemporaryError(nerr, &delay, c) delay.Wait() continue } c.terminate() return err } delay.Reset() c.monitorExtend() err = c.process(p) if err != nil { if aerr, ok := err.(AdapterError); ok { if aerr.Continue() { c.srv.logAdapterError(aerr, p, c) continue } if aerr == ErrDisconnected { c.terminate() return nil } } c.terminate() return err } } }