h2_rx_settings(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
{
	const uint8_t *p;
	unsigned l;
	h2_error retval = 0;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	ASSERT_RXTHR(h2);
	CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
	assert(r2 == h2->req0);
	AZ(h2->rxf_stream);

	if (h2->rxf_flags == H2FF_SETTINGS_ACK) {
		if (h2->rxf_len > 0)			// rfc7540,l,2047,2049
			return (H2CE_FRAME_SIZE_ERROR);
		return (0);
	} else {
		if (h2->rxf_len % 6)			// rfc7540,l,2062,2064
			return (H2CE_PROTOCOL_ERROR);
		p = h2->rxf_data;
		for (l = h2->rxf_len; l >= 6; l -= 6, p += 6) {
			retval = h2_set_setting(h2, p);
			if (retval)
				return (retval);
		}
		H2_Send_Get(wrk, h2, r2);
		H2_Send_Frame(wrk, h2,
		    H2_F_SETTINGS, H2FF_SETTINGS_ACK, 0, 0, NULL);
		H2_Send_Rel(h2, r2);
	}
	return (0);
}
h2_rx_settings(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
{
	const uint8_t *p;
	unsigned l;
	h2_error retval = 0;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	ASSERT_RXTHR(h2);
	CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
	assert(r2 == h2->req0);
	AZ(h2->rxf_stream);

	if (h2->rxf_flags == H2FF_SETTINGS_ACK) {
		if (h2->rxf_len > 0)			 
			return (H2CE_FRAME_SIZE_ERROR);
		return (0);
	} else {
		if (h2->rxf_len % 6)			 
			return (H2CE_PROTOCOL_ERROR);
		p = h2->rxf_data;
		for (l = h2->rxf_len; l >= 6; l -= 6, p += 6) {
			retval = h2_set_setting(h2, p);
			if (retval)
				return (retval);
		}
		H2_Send_Get(wrk, h2, r2);
		H2_Send_Frame(wrk, h2,
		    H2_F_SETTINGS, H2FF_SETTINGS_ACK, 0, 0, NULL);
		H2_Send_Rel(h2, r2);
	}
	return (0);
}