PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
pdu_decoder.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
11#ifndef PACS_NETWORK_PDU_DECODER_HPP
12#define PACS_NETWORK_PDU_DECODER_HPP
13
14#include "pdu_types.h"
16
17#include <cstdint>
18#include <optional>
19#include <span>
20#include <variant>
21#include <vector>
22
23namespace kcenon::pacs::network {
24
32struct release_rq_pdu {};
33struct release_rp_pdu {};
34
47
52 std::vector<presentation_data_value> pdvs;
53
54 p_data_tf_pdu() = default;
55 explicit p_data_tf_pdu(std::vector<presentation_data_value> values)
56 : pdvs(std::move(values)) {}
57};
58
62using pdu = std::variant<
70>;
71
75enum class pdu_decode_error : int {
76 success = 0,
78 incomplete_pdu = 2,
82 malformed_pdu = 6,
83 buffer_overflow = 7,
84};
85
89[[nodiscard]] constexpr const char* to_string(pdu_decode_error err) noexcept {
90 switch (err) {
91 case pdu_decode_error::success: return "Success";
92 case pdu_decode_error::incomplete_header: return "Incomplete PDU header";
93 case pdu_decode_error::incomplete_pdu: return "Incomplete PDU data";
94 case pdu_decode_error::invalid_pdu_type: return "Invalid PDU type";
95 case pdu_decode_error::invalid_protocol_version: return "Invalid protocol version";
96 case pdu_decode_error::invalid_item_type: return "Invalid item type";
97 case pdu_decode_error::malformed_pdu: return "Malformed PDU";
98 case pdu_decode_error::buffer_overflow: return "Buffer overflow";
99 default: return "Unknown error";
100 }
101}
102
104template<typename T>
106
128public:
131
140 [[nodiscard]] static DecodeResult<pdu> decode(std::span<const uint8_t> data);
141
151 [[nodiscard]] static std::optional<size_t> pdu_length(
152 std::span<const uint8_t> data);
153
159 [[nodiscard]] static std::optional<pdu_type> peek_pdu_type(
160 std::span<const uint8_t> data);
161
163
166
173 std::span<const uint8_t> data);
174
181 std::span<const uint8_t> data);
182
189 std::span<const uint8_t> data);
190
197 std::span<const uint8_t> data);
198
205 std::span<const uint8_t> data);
206
213 std::span<const uint8_t> data);
214
220 [[nodiscard]] static DecodeResult<abort_pdu> decode_abort(
221 std::span<const uint8_t> data);
222
224
225private:
228
232 [[nodiscard]] static uint16_t read_uint16_be(
233 std::span<const uint8_t> data, size_t offset);
234
238 [[nodiscard]] static uint32_t read_uint32_be(
239 std::span<const uint8_t> data, size_t offset);
240
244 [[nodiscard]] static std::string read_ae_title(
245 std::span<const uint8_t> data, size_t offset);
246
250 [[nodiscard]] static std::string read_uid(
251 std::span<const uint8_t> data, size_t offset, size_t length);
252
259 [[nodiscard]] static DecodeResult<uint32_t> validate_pdu_header(
260 std::span<const uint8_t> data, uint8_t expected_type = 0);
261
265 [[nodiscard]] static DecodeResult<std::tuple<
266 std::string, // application_context
267 std::vector<presentation_context_rq>, // presentation_contexts_rq
268 std::vector<presentation_context_ac>, // presentation_contexts_ac
269 user_information // user_info
270 >> decode_variable_items(std::span<const uint8_t> data, bool is_rq);
271
276 std::span<const uint8_t> data);
277
279};
280
281} // namespace kcenon::pacs::network
282
283#endif // PACS_NETWORK_PDU_DECODER_HPP
Decoder for DICOM PDU (Protocol Data Unit) messages.
static DecodeResult< std::tuple< std::string, std::vector< presentation_context_rq >, std::vector< presentation_context_ac >, user_information > > decode_variable_items(std::span< const uint8_t > data, bool is_rq)
Decode variable items from ASSOCIATE-RQ/AC PDUs.
static DecodeResult< user_information > decode_user_info_item(std::span< const uint8_t > data)
Decode User Information sub-items.
static DecodeResult< associate_ac > decode_associate_ac(std::span< const uint8_t > data)
Decode an A-ASSOCIATE-AC PDU.
static DecodeResult< associate_rq > decode_associate_rq(std::span< const uint8_t > data)
Decode an A-ASSOCIATE-RQ PDU.
static DecodeResult< release_rp_pdu > decode_release_rp(std::span< const uint8_t > data)
Decode an A-RELEASE-RP PDU.
static DecodeResult< pdu > decode(std::span< const uint8_t > data)
Decode any PDU from bytes.
static uint16_t read_uint16_be(std::span< const uint8_t > data, size_t offset)
Read a 16-bit unsigned integer in big-endian format.
static std::string read_ae_title(std::span< const uint8_t > data, size_t offset)
Read an AE Title (16 bytes, space-trimmed).
static DecodeResult< abort_pdu > decode_abort(std::span< const uint8_t > data)
Decode an A-ABORT PDU.
static uint32_t read_uint32_be(std::span< const uint8_t > data, size_t offset)
Read a 32-bit unsigned integer in big-endian format.
static std::string read_uid(std::span< const uint8_t > data, size_t offset, size_t length)
Read a UID string (trim trailing null/space padding).
static DecodeResult< uint32_t > validate_pdu_header(std::span< const uint8_t > data, uint8_t expected_type=0)
Validate PDU header and extract length.
static DecodeResult< release_rq_pdu > decode_release_rq(std::span< const uint8_t > data)
Decode an A-RELEASE-RQ PDU.
static DecodeResult< associate_rj > decode_associate_rj(std::span< const uint8_t > data)
Decode an A-ASSOCIATE-RJ PDU.
static std::optional< size_t > pdu_length(std::span< const uint8_t > data)
Check if a complete PDU is available in the buffer.
static std::optional< pdu_type > peek_pdu_type(std::span< const uint8_t > data)
Get the PDU type from buffer without full decoding.
static DecodeResult< p_data_tf_pdu > decode_p_data_tf(std::span< const uint8_t > data)
Decode a P-DATA-TF PDU.
@ associate_rj
A-ASSOCIATE-RJ (Association Reject)
@ associate_ac
A-ASSOCIATE-AC (Association Accept)
@ associate_rq
A-ASSOCIATE-RQ (Association Request)
abort_reason
Abort reason values when source is service-provider.
Definition pdu_types.h:79
@ not_specified
Reason not specified.
std::variant< associate_rq, associate_ac, associate_rj, p_data_tf_pdu, release_rq_pdu, release_rp_pdu, abort_pdu > pdu
Variant type that can hold any PDU.
Definition pdu_decoder.h:62
constexpr const char * to_string(association_state state) noexcept
Convert association_state to string representation.
Definition association.h:86
abort_source
Abort source values.
Definition pdu_types.h:70
@ service_user
DICOM UL service-user.
pdu_decode_error
Error codes for PDU decoding errors.
Definition pdu_decoder.h:75
@ incomplete_header
Less than 6 bytes available.
@ buffer_overflow
Item length exceeds PDU bounds.
@ malformed_pdu
PDU structure is invalid.
@ incomplete_pdu
PDU length exceeds available data.
@ invalid_item_type
Unknown item type in variable items.
@ invalid_protocol_version
Unsupported protocol version.
@ invalid_pdu_type
Unknown PDU type byte.
Result<T> type aliases and helpers for PACS system.
abort_pdu(abort_source src, abort_reason rsn)
Definition pdu_decoder.h:44
abort_source source
Source of abort.
Definition pdu_decoder.h:39
abort_reason reason
Reason for abort.
Definition pdu_decoder.h:40
std::vector< presentation_data_value > pdvs
Presentation Data Values.
Definition pdu_decoder.h:52
p_data_tf_pdu(std::vector< presentation_data_value > values)
Definition pdu_decoder.h:55
A-RELEASE-RP has no data fields.
Definition pdu_decoder.h:33
PDU variant type representing any DICOM Upper Layer PDU.A-RELEASE-RQ has no data fields.
Definition pdu_decoder.h:32
User Information for A-ASSOCIATE-RQ/AC.
Definition pdu_types.h:193