code: func (c *Client) processor() error {
  	c.backend.Log(NewConnection, c, nil, nil, nil)
  
  	// get first packet from connection
  	pkt, err := c.conn.Receive()
  	if err != nil {
  		return c.die(TransportError, err)
  	}
  
  	c.backend.Log(PacketReceived, c, pkt, nil, nil)
  
  	// get connect
  	connect, ok := pkt.(*packet.Connect)
  	if !ok {
  		return c.die(ClientError, ErrUnexpectedPacket)
  	}
  
  	// process connect
  	err = c.processConnect(connect)
  	if err != nil {
  		return err // error has already been handled
  	}
  
  	// start dequeuer and acker
  	c.tomb.Go(c.dequeuer)
  	c.tomb.Go(c.acker)
  
  	for {
  		// check if still alive
  		if !c.tomb.Alive() {
  			return tomb.ErrDying
  		}
  
  		// receive next packet
  		pkt, err := c.conn.Receive()
  		if err != nil {
  			return c.die(TransportError, err)
  		}
  
  		c.backend.Log(PacketReceived, c, pkt, nil, nil)
  
  		// call callback
  		if c.PacketCallback != nil && pkt.Type() != packet.DISCONNECT {
  			err = c.PacketCallback(pkt)
  			if err != nil {
  				return c.die(ClientError, err)
  			}
  		}
  
  		// process packet
  		err = c.processPacket(pkt)
  		if err != nil {
  			return err // error has already been handled
  		}
  	}
  }
docs: /* goroutines */
  // main processor