code: func (p *Peer) HandleMsg(ctx context.Context, msg interface{}) error {
  	select {
  	case <-p.streamer.quit:
  		log.Trace("message received after the streamer is closed", "peer", p.ID())
  		// return without an error since streamer is closed and
  		// no messages should be handled as other subcomponents like
  		// storage leveldb may be closed
  		return nil
  	default:
  	}
  
  	switch msg := msg.(type) {
  
  	case *SubscribeMsg:
  		return p.handleSubscribeMsg(ctx, msg)
  
  	case *SubscribeErrorMsg:
  		return p.handleSubscribeErrorMsg(msg)
  
  	case *UnsubscribeMsg:
  		return p.handleUnsubscribeMsg(msg)
  
  	case *OfferedHashesMsg:
  		return p.handleOfferedHashesMsg(ctx, msg)
  
  	case *TakeoverProofMsg:
  		return p.handleTakeoverProofMsg(ctx, msg)
  
  	case *WantedHashesMsg:
  		return p.handleWantedHashesMsg(ctx, msg)
  
  	case *ChunkDeliveryMsgRetrieval:
  		// handling chunk delivery is the same for retrieval and syncing, so let's cast the msg
  		return p.streamer.delivery.handleChunkDeliveryMsg(ctx, p, ((*ChunkDeliveryMsg)(msg)))
  
  	case *ChunkDeliveryMsgSyncing:
  		// handling chunk delivery is the same for retrieval and syncing, so let's cast the msg
  		return p.streamer.delivery.handleChunkDeliveryMsg(ctx, p, ((*ChunkDeliveryMsg)(msg)))
  
  	case *RetrieveRequestMsg:
  		return p.streamer.delivery.handleRetrieveRequestMsg(ctx, p, msg)
  
  	case *RequestSubscriptionMsg:
  		return p.handleRequestSubscription(ctx, msg)
  
  	case *QuitMsg:
  		return p.handleQuitMsg(msg)
  
  	default:
  		return fmt.Errorf("unknown message type: %T", msg)
  	}
  }
docs: // HandleMsg is the message handler that delegates incoming messages