code: func (b *blockManager) blockHandler() {
  	candidatePeers := list.New()
  out:
  	for {
  		// Now check peer messages and quit channels.
  		select {
  		case m := <-b.peerChan:
  			switch msg := m.(type) {
  			case *newPeerMsg:
  				b.handleNewPeerMsg(candidatePeers, msg.peer)
  
  			case *invMsg:
  				b.handleInvMsg(msg)
  
  			case *headersMsg:
  				b.handleHeadersMsg(msg)
  
  			case *donePeerMsg:
  				b.handleDonePeerMsg(candidatePeers, msg.peer)
  
  			default:
  				log.Warnf("Invalid message type in block "+
  					"handler: %T", msg)
  			}
  
  		case <-b.quit:
  			break out
  		}
  	}
  
  	b.wg.Done()
  	log.Trace("Block handler done")
  }
docs: // blockHandler is the main handler for the block manager.  It must be run as a
  // goroutine.  It processes block and inv messages in a separate goroutine from
  // the peer handlers so the block (MsgBlock) messages are handled by a single
  // thread without needing to lock memory data structures.  This is important
  // because the block manager controls which blocks are needed and how
  // the fetching should proceed.