diff --git a/c/include/proton/disposition.h b/c/include/proton/disposition.h index e80bf8ffd..db0d1cea6 100644 --- a/c/include/proton/disposition.h +++ b/c/include/proton/disposition.h @@ -227,6 +227,162 @@ PN_EXTERN void pn_disposition_set_undeliverable(pn_disposition_t *disposition, b */ PN_EXTERN pn_data_t *pn_disposition_annotations(pn_disposition_t *disposition); +/** + * There are different types of delivery status some of which hold their + * own different specific data and some of which hold no extra data + */ +typedef struct pn_received_disposition_t pn_received_disposition_t; +typedef struct pn_rejected_disposition_t pn_rejected_disposition_t; +typedef struct pn_modified_disposition_t pn_modified_disposition_t; +typedef struct pn_custom_disposition_t pn_custom_disposition_t; + +/** + * Convert a delivery disposition to a custom disposition + * + * @param[in] disposition delivery disposition object + * @return a pointer to the equivalent custom disposition type + */ +PN_EXTERN pn_custom_disposition_t *pn_custom_disposition(pn_disposition_t *disposition); + +/** + * Convert a delivery disposition to more specific disposition types + * + * @param[in] disposition delivery disposition object + * @return a pointer to the desired specific disposition type or NULL + * if the delivery is not that type + */ +PN_EXTERN pn_received_disposition_t *pn_received_disposition(pn_disposition_t *disposition); +PN_EXTERN pn_rejected_disposition_t *pn_rejected_disposition(pn_disposition_t *disposition); +PN_EXTERN pn_modified_disposition_t *pn_modified_disposition(pn_disposition_t *disposition); + +/** + * Access the disposition as a raw pn_data_t. + * + * Dispositions are an extension point in the AMQP protocol. The + * disposition interface provides setters/getters for those + * dispositions that are predefined by the specification, however + * access to the raw disposition data is provided so that other + * dispositions can be used. + * + * The ::pn_data_t pointer returned by this operation is valid until + * the parent delivery is settled. + * + * @param[in] disposition a custom disposition object + * @return a pointer to the raw disposition data + */ +PN_EXTERN pn_data_t *pn_custom_disposition_data(pn_custom_disposition_t *disposition); + +/** + * Get the type of a custom disposition. + * + * @param[in] disposition a custom disposition object + * @return the type of the disposition + */ +PN_EXTERN uint64_t pn_custom_disposition_get_type(pn_custom_disposition_t *disposition); + +/** + * Set the type of a custom disposition. + * + * @param[in] disposition a custom disposition object + * @param[in] type the type of the disposition + */ +PN_EXTERN void pn_custom_disposition_set_type(pn_custom_disposition_t *disposition, uint64_t type); + +/** + * Access the condition object associated with a rejected disposition. + * + * The ::pn_condition_t object retrieved by this operation may be + * modified prior to updating a delivery. When a delivery is updated, + * the condition described by the disposition is reported to the peer. + * + * The pointer returned by this operation is valid until the parent + * delivery is settled. + * + * @param[in] disposition a disposition object + * @return a pointer to the disposition condition + */ +PN_EXTERN pn_condition_t *pn_rejected_disposition_condition(pn_rejected_disposition_t *disposition); + +/** + * Get the section number associated with a received disposition. + * + * @param[in] disposition a disposition object + * @return a section number + */ +PN_EXTERN uint32_t pn_received_disposition_get_section_number(pn_received_disposition_t *disposition); + +/** + * Set the section number associated with a received disposition. + * + * @param[in] disposition a disposition object + * @param[in] section_number a section number + */ +PN_EXTERN void pn_received_disposition_set_section_number(pn_received_disposition_t *disposition, uint32_t section_number); + +/** + * Get the section offset associated with a received disposition. + * + * @param[in] disposition a disposition object + * @return a section offset + */ +PN_EXTERN uint64_t pn_received_disposition_get_section_offset(pn_received_disposition_t *disposition); + +/** + * Set the section offset associated with a received disposition. + * + * @param[in] disposition a disposition object + * @param[in] section_offset a section offset + */ +PN_EXTERN void pn_received_disposition_set_section_offset(pn_received_disposition_t *disposition, uint64_t section_offset); + +/** + * Check if a modified disposition has the failed flag set. + * + * @param[in] disposition a disposition object + * @return true if the disposition has the failed flag set, false otherwise + */ +PN_EXTERN bool pn_modified_disposition_is_failed(pn_modified_disposition_t *disposition); + +/** + * Set the failed flag on a modified disposition. + * + * @param[in] disposition a disposition object + * @param[in] failed the value of the failed flag + */ +PN_EXTERN void pn_modified_disposition_set_failed(pn_modified_disposition_t *disposition, bool failed); + +/** + * Check if a modified disposition has the undeliverable flag set. + * + * @param[in] disposition a disposition object + * @return true if the disposition has the undeliverable flag set, false otherwise + */ +PN_EXTERN bool pn_modified_disposition_is_undeliverable(pn_modified_disposition_t *disposition); + +/** + * Set the undeliverable flag on a modified disposition. + * + * @param[in] disposition a disposition object + * @param[in] undeliverable the value of the undeliverable flag + */ +PN_EXTERN void pn_modified_disposition_set_undeliverable(pn_modified_disposition_t *disposition, bool undeliverable); + +/** + * Access the annotations associated with a modified disposition. + * + * The ::pn_data_t object retrieved by this operation may be modified + * prior to updating a delivery. When a delivery is updated, the + * annotations described by the ::pn_data_t are reported to the peer. + * The ::pn_data_t must be empty or contain a symbol keyed map. + * + * The pointer returned by this operation is valid until the parent + * delivery is settled. + * + * @param[in] disposition a disposition object + * @return the annotations associated with the disposition + */ +PN_EXTERN pn_data_t *pn_modified_disposition_annotations(pn_modified_disposition_t *disposition); + /** * @} */ diff --git a/c/src/core/engine-internal.h b/c/src/core/engine-internal.h index 171489db6..d50b02bdf 100644 --- a/c/src/core/engine-internal.h +++ b/c/src/core/engine-internal.h @@ -338,27 +338,27 @@ typedef enum pn_disposition_type_t { PN_DISP_MODIFIED = PN_MODIFIED, } pn_disposition_type_t; -typedef struct pn_received_disposition_t { +struct pn_received_disposition_t { uint64_t section_offset; uint32_t section_number; -} pn_received_disposition_t; +}; -typedef struct pn_rejected_disposition_t { +struct pn_rejected_disposition_t { pn_condition_t condition; -} pn_rejected_disposition_t; +}; -typedef struct pn_modified_disposition_t { +struct pn_modified_disposition_t { pn_data_t *annotations; pn_bytes_t annotations_raw; bool failed; bool undeliverable; -} pn_modified_disposition_t; +}; -typedef struct pn_custom_disposition_t { +struct pn_custom_disposition_t { pn_data_t *data; - uint64_t type; pn_bytes_t data_raw; -} pn_custom_disposition_t; + uint64_t type; +}; struct pn_disposition_t { union { diff --git a/c/src/core/engine.c b/c/src/core/engine.c index ca07a8c5f..685e89a85 100644 --- a/c/src/core/engine.c +++ b/c/src/core/engine.c @@ -1911,6 +1911,112 @@ pn_condition_t *pn_disposition_condition(pn_disposition_t *disposition) return &disposition->u.s_rejected.condition; } +pn_custom_disposition_t *pn_custom_disposition(pn_disposition_t *disposition) +{ + pni_disposition_to_raw(disposition); + return &disposition->u.s_custom; +} + +pn_received_disposition_t *pn_received_disposition(pn_disposition_t *disposition) +{ + if (disposition->type==PN_DISP_EMPTY) disposition->type = PN_DISP_RECEIVED; + else if (disposition->type!=PN_DISP_RECEIVED) return NULL; + return &disposition->u.s_received; +} + +pn_rejected_disposition_t *pn_rejected_disposition(pn_disposition_t *disposition) +{ + if (disposition->type==PN_DISP_EMPTY) disposition->type = PN_DISP_REJECTED; + else if (disposition->type!=PN_DISP_REJECTED) return NULL; + return &disposition->u.s_rejected; +} + +pn_modified_disposition_t *pn_modified_disposition(pn_disposition_t *disposition) +{ + if (disposition->type==PN_DISP_EMPTY) disposition->type = PN_DISP_MODIFIED; + else if (disposition->type!=PN_DISP_MODIFIED) return NULL; + return &disposition->u.s_modified; +} + +pn_data_t *pn_custom_disposition_data(pn_custom_disposition_t *disposition) +{ + assert(disposition); + pni_switch_to_data(&disposition->data_raw, &disposition->data); + return disposition->data; +} + +uint64_t pn_custom_disposition_get_type(pn_custom_disposition_t *disposition) +{ + assert(disposition); + return disposition->type; +} + +void pn_custom_disposition_set_type(pn_custom_disposition_t *disposition, uint64_t type) +{ + assert(disposition); + disposition->type = type; +} + +pn_condition_t *pn_rejected_disposition_condition(pn_rejected_disposition_t *disposition) +{ + assert(disposition); + return &disposition->condition; +} + +uint32_t pn_received_disposition_get_section_number(pn_received_disposition_t *disposition) +{ + assert(disposition); + return disposition->section_number; +} + +void pn_received_disposition_set_section_number(pn_received_disposition_t *disposition, uint32_t section_number) +{ + assert(disposition); + disposition->section_number = section_number; +} + +uint64_t pn_received_disposition_get_section_offset(pn_received_disposition_t *disposition) +{ + assert(disposition); + return disposition->section_offset; +} + +void pn_received_disposition_set_section_offset(pn_received_disposition_t *disposition, uint64_t section_offset) +{ + assert(disposition); + disposition->section_offset = section_offset; +} + +bool pn_modified_disposition_is_failed(pn_modified_disposition_t *disposition) { + assert(disposition); + return disposition->failed; +} + +void pn_modified_disposition_set_failed(pn_modified_disposition_t *disposition, bool failed) +{ + assert(disposition); + disposition->failed = failed; +} + +bool pn_modified_disposition_is_undeliverable(pn_modified_disposition_t *disposition) +{ + assert(disposition); + return disposition->undeliverable; +} + +void pn_modified_disposition_set_undeliverable(pn_modified_disposition_t *disposition, bool undeliverable) +{ + assert(disposition); + disposition->undeliverable = undeliverable; +} + +pn_data_t *pn_modified_disposition_annotations(pn_modified_disposition_t *disposition) +{ + assert(disposition); + pni_switch_to_data(&disposition->annotations_raw, &disposition->annotations); + return disposition->annotations; +} + pn_delivery_tag_t pn_delivery_tag(pn_delivery_t *delivery) { if (delivery) { diff --git a/python/cproton.h b/python/cproton.h index 29dc30ba4..f98915693 100644 --- a/python/cproton.h +++ b/python/cproton.h @@ -29,7 +29,7 @@ typedef struct pn_collector_t pn_collector_t; typedef struct pn_condition_t pn_condition_t; typedef struct pn_connection_t pn_connection_t; typedef struct pn_data_t pn_data_t; -typedef struct +typedef struct { char bytes[16]; } pn_decimal128_t; @@ -38,13 +38,13 @@ typedef uint64_t pn_decimal64_t; typedef struct pn_delivery_t pn_delivery_t; typedef pn_bytes_t pn_delivery_tag_t; typedef struct pn_disposition_t pn_disposition_t; -typedef enum +typedef enum { PN_DIST_MODE_UNSPECIFIED = 0, PN_DIST_MODE_COPY = 1, PN_DIST_MODE_MOVE = 2 } pn_distribution_mode_t; -typedef enum +typedef enum { PN_NONDURABLE = 0, PN_CONFIGURATION = 1, @@ -52,7 +52,7 @@ typedef enum } pn_durability_t; typedef struct pn_error_t pn_error_t; typedef struct pn_event_t pn_event_t; -typedef enum +typedef enum { PN_EVENT_NONE = 0, PN_REACTOR_INIT, @@ -114,7 +114,7 @@ typedef enum PN_RAW_CONNECTION_WAKE, PN_RAW_CONNECTION_DRAIN_BUFFERS } pn_event_type_t; -typedef enum +typedef enum { PN_EXPIRE_WITH_LINK, PN_EXPIRE_WITH_SESSION, @@ -130,7 +130,7 @@ typedef enum PN_RCV_SECOND = 1 } pn_rcv_settle_mode_t; typedef struct pn_record_t pn_record_t; -typedef enum +typedef enum { PN_SASL_NONE = -1, PN_SASL_OK = 0, @@ -143,13 +143,13 @@ typedef struct pn_sasl_t pn_sasl_t; typedef uint32_t pn_seconds_t; typedef uint32_t pn_sequence_t; typedef struct pn_session_t pn_session_t; -typedef enum +typedef enum { PN_SND_UNSETTLED = 0, PN_SND_SETTLED = 1, PN_SND_MIXED = 2 } pn_snd_settle_mode_t; -typedef enum +typedef enum { PN_SSL_CERT_SUBJECT_COUNTRY_NAME, PN_SSL_CERT_SUBJECT_STATE_OR_PROVINCE, @@ -159,26 +159,26 @@ typedef enum PN_SSL_CERT_SUBJECT_COMMON_NAME } pn_ssl_cert_subject_subfield; typedef struct pn_ssl_domain_t pn_ssl_domain_t; -typedef enum +typedef enum { PN_SSL_SHA1, PN_SSL_SHA256, PN_SSL_SHA512, PN_SSL_MD5 } pn_ssl_hash_alg; -typedef enum +typedef enum { PN_SSL_MODE_CLIENT = 1, PN_SSL_MODE_SERVER } pn_ssl_mode_t; -typedef enum +typedef enum { PN_SSL_RESUME_UNKNOWN, PN_SSL_RESUME_NEW, PN_SSL_RESUME_REUSED } pn_ssl_resume_status_t; typedef struct pn_ssl_t pn_ssl_t; -typedef enum +typedef enum { PN_SSL_VERIFY_NULL = 0, PN_SSL_VERIFY_PEER, @@ -187,7 +187,7 @@ typedef enum } pn_ssl_verify_mode_t; typedef int pn_state_t; typedef struct pn_terminus_t pn_terminus_t; -typedef enum +typedef enum { PN_UNSPECIFIED = 0, PN_SOURCE = 1, @@ -197,7 +197,7 @@ typedef enum typedef int64_t pn_timestamp_t; typedef int pn_trace_t; typedef struct pn_transport_t pn_transport_t; -typedef enum +typedef enum { PN_NULL = 1, PN_BOOL = 2, @@ -226,7 +226,7 @@ typedef enum PN_MAP = 25, PN_INVALID = -1 } pn_type_t; -typedef struct +typedef struct { char bytes[16]; } pn_uuid_t; @@ -406,6 +406,25 @@ void pn_disposition_set_section_offset(pn_disposition_t *disposition, uint64_t s void pn_disposition_set_undeliverable(pn_disposition_t *disposition, _Bool undeliverable); uint64_t pn_disposition_type(pn_disposition_t *disposition); +typedef struct pn_received_disposition_t pn_received_disposition_t; +typedef struct pn_rejected_disposition_t pn_rejected_disposition_t; +typedef struct pn_modified_disposition_t pn_modified_disposition_t; + +pn_received_disposition_t *pn_received_disposition(pn_disposition_t *disposition); +pn_rejected_disposition_t *pn_rejected_disposition(pn_disposition_t *disposition); +pn_modified_disposition_t *pn_modified_disposition(pn_disposition_t *disposition); + +pn_condition_t *pn_rejected_disposition_condition(pn_rejected_disposition_t *disposition); +uint32_t pn_received_disposition_get_section_number(pn_received_disposition_t *disposition); +void pn_received_disposition_set_section_number(pn_received_disposition_t *disposition, uint32_t section_number); +uint64_t pn_received_disposition_get_section_offset(pn_received_disposition_t *disposition); +void pn_received_disposition_set_section_offset(pn_received_disposition_t *disposition, uint64_t section_offset); +_Bool pn_modified_disposition_is_failed(pn_modified_disposition_t *disposition); +void pn_modified_disposition_set_failed(pn_modified_disposition_t *disposition, _Bool failed); +_Bool pn_modified_disposition_is_undeliverable(pn_modified_disposition_t *disposition); +void pn_modified_disposition_set_undeliverable(pn_modified_disposition_t *disposition, _Bool undeliverable); +pn_data_t *pn_modified_disposition_annotations(pn_modified_disposition_t *disposition); + int pn_error_code(pn_error_t *error); const char *pn_error_text(pn_error_t *error); diff --git a/python/cproton.py b/python/cproton.py index 61a60589e..0e772f4ea 100644 --- a/python/cproton.py +++ b/python/cproton.py @@ -158,7 +158,24 @@ pn_transport_require_encryption, pn_transport_set_channel_max, pn_transport_set_idle_timeout, pn_transport_set_max_frame, pn_transport_set_server, pn_transport_tick, pn_transport_trace, - pn_transport_unbind) + pn_transport_unbind, + pn_custom_disposition, + pn_custom_disposition_get_type, + pn_custom_disposition_set_type, + pn_custom_disposition_data, + pn_rejected_disposition, + pn_rejected_disposition_condition, + pn_received_disposition, + pn_received_disposition_get_section_number, + pn_received_disposition_set_section_number, + pn_received_disposition_get_section_offset, + pn_received_disposition_set_section_offset, + pn_modified_disposition, + pn_modified_disposition_is_failed, + pn_modified_disposition_set_failed, + pn_modified_disposition_is_undeliverable, + pn_modified_disposition_set_undeliverable, + pn_modified_disposition_annotations) def isnull(obj):