25 , on_request_(std::
move(on_request))
26 , on_association_(std::
move(on_association))
27 , on_error_(std::
move(on_error)) {
33 std::chrono::duration_cast<std::chrono::nanoseconds>(
34 std::chrono::steady_clock::now().time_since_epoch()
42 return process_association_pdu();
46 auto request_result = process_p_data();
47 if (!request_result.is_ok()) {
49 auto err = request_result.error();
50 on_error_(context_.session_id, err.message);
55 auto request = request_result.value();
58 context_.message_id = request.message_id;
61 switch (request.command_type) {
93 uint16_t cmd_type =
static_cast<uint16_t
>(request.command_type);
94 if (cmd_type & 0x8000) {
101 auto exec_job = std::make_unique<storage_query_exec_job>(
107 exec_job->get_context() = context_;
110 return coordinator.submit_to_stage(
125 return "dimse_process_job[session=" +
127 ", pdu_type=" + std::to_string(
static_cast<int>(
pdu_.
type)) +
"]";
140 if (pdu_.data.size() < 6) {
142 "PDV data too short");
147 const auto& data = pdu_.data;
152 while (offset + 8 <= data.size()) {
154 uint16_t group =
static_cast<uint16_t
>(data[offset]) |
155 (
static_cast<uint16_t
>(data[offset + 1]) << 8);
156 uint16_t element =
static_cast<uint16_t
>(data[offset + 2]) |
157 (
static_cast<uint16_t
>(data[offset + 3]) << 8);
162 if (offset + 4 > data.size())
break;
163 uint32_t length =
static_cast<uint32_t
>(data[offset]) |
164 (
static_cast<uint32_t
>(data[offset + 1]) << 8) |
165 (
static_cast<uint32_t
>(data[offset + 2]) << 16) |
166 (
static_cast<uint32_t
>(data[offset + 3]) << 24);
169 if (offset + length > data.size())
break;
172 if (group == 0x0000) {
177 static_cast<uint16_t
>(data[offset]) |
178 (
static_cast<uint16_t
>(data[offset + 1]) << 8)
184 request.
message_id =
static_cast<uint16_t
>(data[offset]) |
185 (
static_cast<uint16_t
>(data[offset + 1]) << 8);
191 reinterpret_cast<const char*
>(&data[offset]), length);
202 reinterpret_cast<const char*
>(&data[offset]), length);
211 request.
priority =
static_cast<uint16_t
>(data[offset]) |
212 (
static_cast<uint16_t
>(data[offset + 1]) << 8);
224 return ok(std::move(request));
229 if (on_association_) {
230 on_association_(pdu_.session_id, pdu_.type, pdu_.data);
std::function< void(uint64_t session_id, const std::string &error)> error_callback
Callback type for processing errors.
auto get_name() const -> std::string override
Get the job name.
std::function< void(uint64_t session_id, kcenon::pacs::network::pdu_type type, const std::vector< uint8_t > &data)> association_callback
Callback type for association handling.
auto process_association_pdu() -> VoidResult
Process association PDUs (A-ASSOCIATE, A-RELEASE, A-ABORT)
auto get_context() const noexcept -> const job_context &override
Get the job context.
auto get_pdu() const noexcept -> const decoded_pdu &
Get the decoded PDU.
dimse_process_job(decoded_pdu pdu, request_callback on_request=nullptr, association_callback on_association=nullptr, error_callback on_error=nullptr)
Construct a DIMSE process job from decoded PDU.
auto process_p_data() -> Result< dimse_request >
Process P-DATA-TF PDU.
auto execute(pipeline_coordinator &coordinator) -> VoidResult override
Execute the DIMSE process job.
std::function< void(const dimse_request &request)> request_callback
Callback type for processed request.
Coordinates the 6-stage DICOM I/O pipeline.
DIMSE processing job for Stage 3 of the pipeline.
constexpr int insufficient_data
@ move
C-MOVE move request/response.
@ other
Unknown or other category.
@ store
C-STORE storage request/response.
@ get
C-GET retrieve request/response.
@ echo
C-ECHO verification request/response.
@ find
C-FIND query request/response.
dimse_command_type
DICOM DIMSE command types.
@ storage_query_exec
Stage 4: Execute storage/query operations (blocking allowed)
@ dimse_process
Stage 3: Process DIMSE messages and route requests.
@ p_data_tf
P-DATA-TF (Data Transfer)
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.
kcenon::pacs::VoidResult VoidResult
VoidResult type alias for operations without return value.
Result< T > pacs_error(int code, const std::string &message, const std::string &details="")
Create a PACS error result with module context.
Storage and query execution job for Stage 4 of the pipeline.
Result of PDU decoding containing the PDU type and data.
uint64_t session_id
Session this PDU belongs to.
kcenon::pacs::network::pdu_type type
The type of PDU that was decoded.
Parsed DIMSE request for service execution.
uint64_t session_id
Session ID.
uint16_t priority
Priority (0=medium, 1=high, 2=low)
uint8_t presentation_context_id
Presentation context ID.
dimse_command_type command_type
The DIMSE command type.
std::vector< uint8_t > command_data
Command data set (serialized)
std::string sop_instance_uid
Affected/Requested SOP Instance UID.
uint16_t message_id
Message ID for correlation.
std::string sop_class_uid
Affected/Requested SOP Class UID.
Context information attached to pipeline jobs for tracking.
pipeline_stage stage
Current pipeline stage.
job_category category
Job category for metrics.
uint64_t enqueue_time_ns
Timestamp when job entered the pipeline (nanoseconds since epoch)
uint64_t session_id
Session/association identifier.