in src/message.c [2110:2257]
static qd_message_depth_status_t qd_message_check_LH(qd_message_content_t *content, qd_message_depth_t depth)
{
qd_error_clear();
if (depth <= content->parse_depth || depth == QD_DEPTH_NONE)
return QD_MESSAGE_DEPTH_OK; // We've already parsed at least this deep
// Is there any data to check? This will also check for null messages, which
// are not valid:
//
qd_buffer_t *buffer = DEQ_HEAD(content->buffers);
if (!buffer || qd_buffer_size(buffer) == 0) {
return IS_ATOMIC_FLAG_SET(&content->receive_complete) ? QD_MESSAGE_DEPTH_INVALID : QD_MESSAGE_DEPTH_INCOMPLETE;
}
if (content->buffers_freed) {
// this is likely a bug: the caller is attempting to access a
// section after the start of the message has already been sent and
// released, rendering the parse_buffer/cursor position invalid.
return QD_MESSAGE_DEPTH_INVALID;
}
if (content->parse_buffer == 0) {
content->parse_buffer = buffer;
content->parse_cursor = qd_buffer_base(content->parse_buffer);
}
qd_message_depth_status_t rc = QD_MESSAGE_DEPTH_OK;
int last_section = QD_DEPTH_NONE;
switch (content->parse_depth + 1) { // start checking at the next unparsed section
case QD_DEPTH_HEADER:
//
// MESSAGE HEADER (optional)
//
last_section = QD_DEPTH_HEADER;
rc = message_check_depth_LH(content, QD_DEPTH_HEADER,
MSG_HDR_LONG, MSG_HDR_SHORT, TAGS_LIST,
&content->section_message_header, true, true);
if (rc != QD_MESSAGE_DEPTH_OK || depth == QD_DEPTH_HEADER)
break;
// fallthrough
case QD_DEPTH_DELIVERY_ANNOTATIONS:
//
// DELIVERY ANNOTATIONS (optional)
//
last_section = QD_DEPTH_DELIVERY_ANNOTATIONS;
rc = message_check_depth_LH(content, QD_DEPTH_DELIVERY_ANNOTATIONS,
DELIVERY_ANNOTATION_LONG, DELIVERY_ANNOTATION_SHORT, TAGS_MAP,
&content->section_delivery_annotation, true, true);
if (rc != QD_MESSAGE_DEPTH_OK || depth == QD_DEPTH_DELIVERY_ANNOTATIONS)
break;
// fallthrough
case QD_DEPTH_MESSAGE_ANNOTATIONS:
//
// MESSAGE ANNOTATION (optional)
//
last_section = QD_DEPTH_MESSAGE_ANNOTATIONS;
rc = message_check_depth_LH(content, QD_DEPTH_MESSAGE_ANNOTATIONS,
MESSAGE_ANNOTATION_LONG, MESSAGE_ANNOTATION_SHORT, TAGS_MAP,
&content->section_message_annotation, true, true);
if (rc != QD_MESSAGE_DEPTH_OK || depth == QD_DEPTH_MESSAGE_ANNOTATIONS)
break;
// fallthough
case QD_DEPTH_PROPERTIES:
//
// PROPERTIES (optional)
//
last_section = QD_DEPTH_PROPERTIES;
rc = message_check_depth_LH(content, QD_DEPTH_PROPERTIES,
PROPERTIES_LONG, PROPERTIES_SHORT, TAGS_LIST,
&content->section_message_properties, true, true);
if (rc != QD_MESSAGE_DEPTH_OK || depth == QD_DEPTH_PROPERTIES)
break;
// fallthrough
case QD_DEPTH_APPLICATION_PROPERTIES:
//
// APPLICATION PROPERTIES (optional)
//
last_section = QD_DEPTH_APPLICATION_PROPERTIES;
rc = message_check_depth_LH(content, QD_DEPTH_APPLICATION_PROPERTIES,
APPLICATION_PROPERTIES_LONG, APPLICATION_PROPERTIES_SHORT, TAGS_MAP,
&content->section_application_properties, true, true);
if (rc != QD_MESSAGE_DEPTH_OK || depth == QD_DEPTH_APPLICATION_PROPERTIES)
break;
// fallthrough
case QD_DEPTH_BODY:
//
// BODY (not optional, but proton allows it - see PROTON-2085)
//
// AMQP 1.0 defines 3 valid Body types: Binary, Sequence (list), or Value (any type)
// Since the body is mandatory, we need to match one of these. Setting
// the optional flag to false will force us to check each one until a match is found.
//
last_section = QD_DEPTH_BODY;
rc = message_check_depth_LH(content, QD_DEPTH_BODY,
BODY_VALUE_LONG, BODY_VALUE_SHORT, TAGS_ANY,
&content->section_body, false, false);
if (rc == QD_MESSAGE_DEPTH_INVALID) { // may be a different body type, need to check:
rc = message_check_depth_LH(content, QD_DEPTH_BODY,
BODY_DATA_LONG, BODY_DATA_SHORT, TAGS_BINARY,
&content->section_body, false, false);
if (rc == QD_MESSAGE_DEPTH_INVALID) {
rc = message_check_depth_LH(content, QD_DEPTH_BODY,
BODY_SEQUENCE_LONG, BODY_SEQUENCE_SHORT, TAGS_LIST,
&content->section_body, true, false); // PROTON-2085
}
}
if (rc != QD_MESSAGE_DEPTH_OK || depth == QD_DEPTH_BODY)
break;
// fallthrough
case QD_DEPTH_ALL:
//
// FOOTER (optional)
//
last_section = QD_DEPTH_ALL;
rc = message_check_depth_LH(content, QD_DEPTH_ALL,
FOOTER_LONG, FOOTER_SHORT, TAGS_MAP,
&content->section_footer, true, false);
break;
default:
assert(false); // should not happen!
qd_error(QD_ERROR_MESSAGE, "BUG! Invalid message depth specified: %d",
content->parse_depth + 1);
return QD_MESSAGE_DEPTH_INVALID;
}
if (rc == QD_MESSAGE_DEPTH_INVALID)
qd_error(QD_ERROR_MESSAGE, "Invalid message: %s section invalid",
section_names[last_section]);
return rc;
}