mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
	enum module_ext_state s, enum module_ev* ev)
{
	mstate->num_activated++;
	if(mstate->num_activated > MESH_MAX_ACTIVATION) {
		/* module is looping. Stop it. */
		log_err("internal error: looping module (%s) stopped",
			mesh->mods.mod[mstate->s.curmod]->name);
		log_query_info(NO_VERBOSE, "pass error for qstate",
			&mstate->s.qinfo);
		s = module_error;
	}
	if(s == module_wait_module || s == module_restart_next) {
		/* start next module */
		mstate->s.curmod++;
		if(mesh->mods.num == mstate->s.curmod) {
			log_err("Cannot pass to next module; at last module");
			log_query_info(VERB_QUERY, "pass error for qstate",
				&mstate->s.qinfo);
			mstate->s.curmod--;
			return mesh_continue(mesh, mstate, module_error, ev);
		}
		if(s == module_restart_next) {
			int curmod = mstate->s.curmod;
			for(; mstate->s.curmod < mesh->mods.num; 
				mstate->s.curmod++) {
				fptr_ok(fptr_whitelist_mod_clear(
					mesh->mods.mod[mstate->s.curmod]->clear));
				(*mesh->mods.mod[mstate->s.curmod]->clear)
					(&mstate->s, mstate->s.curmod);
				mstate->s.minfo[mstate->s.curmod] = NULL;
			}
			mstate->s.curmod = curmod;
		}
		*ev = module_event_pass;
		return 1;
	}
	if(s == module_wait_subquery && mstate->sub_set.count == 0) {
		log_err("module cannot wait for subquery, subquery list empty");
		log_query_info(VERB_QUERY, "pass error for qstate",
			&mstate->s.qinfo);
		s = module_error;
	}
	if(s == module_error && mstate->s.return_rcode == LDNS_RCODE_NOERROR) {
		/* error is bad, handle pass back up below */
		mstate->s.return_rcode = LDNS_RCODE_SERVFAIL;
	}
	if(s == module_error) {
		mesh_query_done(mstate);
		mesh_walk_supers(mesh, mstate);
		mesh_state_delete(&mstate->s);
		return 0;
	}
	if(s == module_finished) {
		if(mstate->s.curmod == 0) {
			struct query_info* qinfo = NULL;
			uint16_t qflags;
			int rpz_p = 0;

			mesh_query_done(mstate);
			mesh_walk_supers(mesh, mstate);

			/* If the answer to the query needs to be refetched
			 * from an external DNS server, we'll need to schedule
			 * a prefetch after removing the current state, so
			 * we need to make a copy of the query info here. */
			if(mstate->s.need_refetch) {
				mesh_copy_qinfo(mstate, &qinfo, &qflags);
				rpz_p = mstate->s.rpz_passthru;
			}

			mesh_state_delete(&mstate->s);
			if(qinfo) {
				mesh_schedule_prefetch(mesh, qinfo, qflags,
					0, 1, rpz_p);
			}
			return 0;
		}
		/* pass along the locus of control */
		mstate->s.curmod --;
		*ev = module_event_moddone;
		return 1;
	}
	return 0;
}
mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
	enum module_ext_state s, enum module_ev* ev)
{
	mstate->num_activated++;
	if(mstate->num_activated > MESH_MAX_ACTIVATION) {
		 
		log_err("internal error: looping module (%s) stopped",
			mesh->mods.mod[mstate->s.curmod]->name);
		log_query_info(NO_VERBOSE, "pass error for qstate",
			&mstate->s.qinfo);
		s = module_error;
	}
	if(s == module_wait_module || s == module_restart_next) {
		 
		mstate->s.curmod++;
		if(mesh->mods.num == mstate->s.curmod) {
			log_err("Cannot pass to next module; at last module");
			log_query_info(VERB_QUERY, "pass error for qstate",
				&mstate->s.qinfo);
			mstate->s.curmod--;
			return mesh_continue(mesh, mstate, module_error, ev);
		}
		if(s == module_restart_next) {
			int curmod = mstate->s.curmod;
			for(; mstate->s.curmod < mesh->mods.num; 
				mstate->s.curmod++) {
				fptr_ok(fptr_whitelist_mod_clear(
					mesh->mods.mod[mstate->s.curmod]->clear));
				(*mesh->mods.mod[mstate->s.curmod]->clear)
					(&mstate->s, mstate->s.curmod);
				mstate->s.minfo[mstate->s.curmod] = NULL;
			}
			mstate->s.curmod = curmod;
		}
		*ev = module_event_pass;
		return 1;
	}
	if(s == module_wait_subquery && mstate->sub_set.count == 0) {
		log_err("module cannot wait for subquery, subquery list empty");
		log_query_info(VERB_QUERY, "pass error for qstate",
			&mstate->s.qinfo);
		s = module_error;
	}
	if(s == module_error && mstate->s.return_rcode == LDNS_RCODE_NOERROR) {
		 
		mstate->s.return_rcode = LDNS_RCODE_SERVFAIL;
	}
	if(s == module_error) {
		mesh_query_done(mstate);
		mesh_walk_supers(mesh, mstate);
		mesh_state_delete(&mstate->s);
		return 0;
	}
	if(s == module_finished) {
		if(mstate->s.curmod == 0) {
			struct query_info* qinfo = NULL;
			uint16_t qflags;
			int rpz_p = 0;

			mesh_query_done(mstate);
			mesh_walk_supers(mesh, mstate);

			 
			if(mstate->s.need_refetch) {
				mesh_copy_qinfo(mstate, &qinfo, &qflags);
				rpz_p = mstate->s.rpz_passthru;
			}

			mesh_state_delete(&mstate->s);
			if(qinfo) {
				mesh_schedule_prefetch(mesh, qinfo, qflags,
					0, 1, rpz_p);
			}
			return 0;
		}
		 
		mstate->s.curmod --;
		*ev = module_event_moddone;
		return 1;
	}
	return 0;
}