This is an automated email from the ASF dual-hosted git repository. astitcher pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-proton.git
The following commit(s) were added to refs/heads/main by this push: new c80482bf6 PROTON-2873: Fix decoding of dispositions in transfer frames c80482bf6 is described below commit c80482bf61bbddabe4064a70c67a691e34179237 Author: Andrew Stitcher <astitc...@apache.org> AuthorDate: Tue Mar 18 17:18:56 2025 -0400 PROTON-2873: Fix decoding of dispositions in transfer frames There was a bug that decoded dispositions in transfer frames and disposition frames differently. --- c/src/core/transport.c | 30 +++++++++++++----------------- c/tools/codec-generator/specs.json | 9 +++++---- python/tests/proton_tests/engine.py | 14 +++++++------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/c/src/core/transport.c b/c/src/core/transport.c index 24a2a4d6f..6f633511e 100644 --- a/c/src/core/transport.c +++ b/c/src/core/transport.c @@ -1556,7 +1556,7 @@ static void pni_amqp_decode_disposition (uint64_t type, pn_bytes_t disp_data, pn uint32_t number; bool qoffset; uint64_t offset; - pn_amqp_decode_DqEQIQLe(disp_data, &qnumber, &number, &qoffset, &offset); + pn_amqp_decode_EQIQLe(disp_data, &qnumber, &number, &qoffset, &offset); disp->type = PN_DISP_RECEIVED; @@ -1576,7 +1576,7 @@ static void pni_amqp_decode_disposition (uint64_t type, pn_bytes_t disp_data, pn pn_bytes_t cond; pn_bytes_t desc; pn_bytes_t info; - pn_amqp_decode_DqEDqEsSRee(disp_data, &cond, &desc, &info); + pn_amqp_decode_EDqEsSRee(disp_data, &cond, &desc, &info); disp->type = PN_DISP_REJECTED; pn_condition_set(&disp->u.s_rejected.condition, cond, desc, info); @@ -1592,7 +1592,7 @@ static void pni_amqp_decode_disposition (uint64_t type, pn_bytes_t disp_data, pn bool qundeliverable; bool undeliverable; pn_bytes_t annotations_raw = (pn_bytes_t){0, NULL}; - pn_amqp_decode_DqEQoQoRe(disp_data, &qfailed, &failed, &qundeliverable, &undeliverable, &annotations_raw); + pn_amqp_decode_EQoQoRe(disp_data, &qfailed, &failed, &qundeliverable, &undeliverable, &annotations_raw); disp->type = PN_DISP_MODIFIED; pn_bytes_free(disp->u.s_modified.annotations_raw); disp->u.s_modified.annotations_raw = pn_bytes_dup(annotations_raw); @@ -1609,7 +1609,7 @@ static void pni_amqp_decode_disposition (uint64_t type, pn_bytes_t disp_data, pn pn_bytes_t id; bool qoutcome; pn_bytes_t outcome_raw; - pn_amqp_decode_DqEzQRe(disp_data, &id, &qoutcome, &outcome_raw); + pn_amqp_decode_EzQRe(disp_data, &id, &qoutcome, &outcome_raw); disp->type = PN_DISP_TRANSACTIONAL; pn_bytes_free(disp->u.s_transactional.id); disp->u.s_transactional.id = pn_bytes_dup(id); @@ -1621,7 +1621,7 @@ static void pni_amqp_decode_disposition (uint64_t type, pn_bytes_t disp_data, pn } default: { pn_bytes_t data_raw = (pn_bytes_t){0, NULL}; - pn_amqp_decode_DqR(disp_data, &data_raw); + pn_amqp_decode_R(disp_data, &data_raw); disp->type = PN_DISP_CUSTOM; disp->u.s_custom.type = type; pn_bytes_free(disp->u.s_custom.data_raw); @@ -1631,10 +1631,10 @@ static void pni_amqp_decode_disposition (uint64_t type, pn_bytes_t disp_data, pn } } -static int pni_do_delivery_disposition(pn_transport_t * transport, pn_delivery_t *delivery, bool settled, bool remote_data, bool type_init, uint64_t type, pn_bytes_t disp_data) { +static int pni_do_delivery_disposition(pn_transport_t * transport, pn_delivery_t *delivery, bool settled, bool type_init, uint64_t type, pn_bytes_t disp_data) { pn_disposition_t *remote = &delivery->remote; - if (remote_data && type_init) { + if (type_init) { pni_amqp_decode_disposition(type, disp_data, remote); } @@ -1652,8 +1652,10 @@ int pn_do_disposition(pn_transport_t *transport, uint8_t frame_type, uint16_t ch pn_sequence_t first, last; bool last_init, settled; pn_bytes_t disp_data; - pn_amqp_decode_DqEoIQIoRe(payload, &role, &first, &last_init, - &last, &settled, &disp_data); + bool type_init; + uint64_t type; + pn_amqp_decode_DqEoIQIoDQLRe(payload, &role, &first, &last_init, + &last, &settled, &type_init, &type, &disp_data); if (!last_init) last = first; pn_session_t *ssn = pni_channel_state(transport, channel); @@ -1672,12 +1674,6 @@ int pn_do_disposition(pn_transport_t *transport, uint8_t frame_type, uint16_t ch deliveries = &ssn->state.incoming; } - bool type_init; - uint64_t type; - bool remote_data; - pn_amqp_decode_DQLQq(disp_data, &type_init, &type, &remote_data); - - // Do some validation of received first and last values // TODO: We should really also clamp the first value here, but we're not keeping track of the earliest // unsettled delivery sequence no @@ -1691,14 +1687,14 @@ int pn_do_disposition(pn_transport_t *transport, uint8_t frame_type, uint16_t ch pn_sequence_t key = pn_hash_key(dh, entry); if (sequence_lte(first, key) && sequence_lte(key, last)) { pn_delivery_t *delivery = (pn_delivery_t*) pn_hash_value(dh, entry); - pni_do_delivery_disposition(transport, delivery, settled, remote_data, type_init, type, disp_data); + pni_do_delivery_disposition(transport, delivery, settled, type_init, type, disp_data); } } } else { for (pn_sequence_t id = first; sequence_lte(id, last); ++id) { pn_delivery_t *delivery = pni_delivery_map_get(deliveries, id); if (delivery) { - pni_do_delivery_disposition(transport, delivery, settled, remote_data, type_init, type, disp_data); + pni_do_delivery_disposition(transport, delivery, settled, type_init, type, disp_data); } } } diff --git a/c/tools/codec-generator/specs.json b/c/tools/codec-generator/specs.json index 82b4a013f..735d076ed 100644 --- a/c/tools/codec-generator/specs.json +++ b/c/tools/codec-generator/specs.json @@ -23,6 +23,10 @@ ], "scan_specs": [ "R", + "[?I?L]", + "[D.[sSR]]", + "[?o?oR]", + "[z?R]", "D.R", "D.[.....D..D.[.....RR]]", "D.[.....D..D.[R]...]", @@ -38,14 +42,11 @@ "D.[SIo?B?BD.[SIsIo.s]D.[SIsIo]..IL..?R]", "D.[azSSSassttSIS]", "D.[o?BIoI]", - "D.[oI?IoR]", - "D.[?o?oR]", - "D.[?I?L]", + "D.[oI?IoD?LR]", "D.[sz]", "D.[s]", "D.[z]", "D.[Bz]", - "D.[z?R]", "D.[R]", "D?L.", "D?L?." diff --git a/python/tests/proton_tests/engine.py b/python/tests/proton_tests/engine.py index 94010d61e..5289db059 100644 --- a/python/tests/proton_tests/engine.py +++ b/python/tests/proton_tests/engine.py @@ -2320,7 +2320,7 @@ class ReceivedTester(DispositionTester): assert dlv.remote_state == self._type assert dlv.remote.type == self._type assert dlv.remote.section_number == self._section_number, (dlv.remote.section_number, self._section_number) - assert dlv.remote.section_offset == self._section_offset + assert dlv.remote.section_offset == self._section_offset, (dlv.remote.section_offset, self._section_offset) class NewReceivedTester(DispositionTester): @@ -2356,8 +2356,8 @@ class ModifiedTester(DispositionTester): def check(self, dlv: Delivery): assert dlv.remote_state == self._type assert dlv.remote.type == self._type - assert dlv.remote.failed == self._failed - assert dlv.remote.undeliverable == self._undeliverable + assert dlv.remote.failed == self._failed, (dlv.remote.failed, self._failed) + assert dlv.remote.undeliverable == self._undeliverable, (dlv.remote.undeliverable, self._undeliverable) assert dlv.remote.annotations == self._annotations, (dlv.remote.annotations, self._annotations) @@ -2375,8 +2375,8 @@ class NewModifiedTester(DispositionTester): def check(self, dlv: Delivery): assert dlv.remote_state == self._type assert dlv.remote.type == self._type - assert dlv.remote.failed == self._failed - assert dlv.remote.undeliverable == self._undeliverable + assert dlv.remote.failed == self._failed, (dlv.remote.failed, self._failed) + assert dlv.remote.undeliverable == self._undeliverable, (dlv.remote.undeliverable, self._undeliverable) assert dlv.remote.annotations == self._annotations, (dlv.remote.annotations, self._annotations) @@ -2392,7 +2392,7 @@ class CustomTester(DispositionTester): def check(self, dlv: Delivery): assert dlv.remote_state == self._type assert dlv.remote.type == self._type - assert dlv.remote.data == self._data, (dlv.data, self._data) + assert dlv.remote.data == self._data, (dlv.remote.data, self._data) class NewCustomTester(DispositionTester): @@ -2407,7 +2407,7 @@ class NewCustomTester(DispositionTester): def check(self, dlv: Delivery): assert dlv.remote_state == self._type assert dlv.remote.type == self._type, (dlv.remote.type, self._type) - assert dlv.remote.data == self._data, (dlv.data, self._data) + assert dlv.remote.data == self._data, (dlv.remote.data, self._data) class TransactionalTester(DispositionTester): --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org