19#include <kcenon/common/patterns/event_bus.h>
64 std::shared_ptr<kcenon::pacs::security::atna_service_auditor> auditor) {
84 using namespace network::dimse;
85 auto start_time = std::chrono::steady_clock::now();
89 if (request.
command() != command_field::c_find_rq) {
92 "Expected C-FIND-RQ but received " +
98 kcenon::common::get_event_bus().publish(
102 "No query handler configured"
107 "No query handler configured");
117 sop_class_uid, status_error_cannot_understand);
121 const auto& query_keys = request.
dataset().value().get();
124 if (!level.has_value()) {
128 sop_class_uid, status_error_cannot_understand);
132 auto results =
handler_(level.value(), query_keys, calling_ae);
140 for (
const auto& result : results) {
149 sop_class_uid, status_cancel);
155 sop_class_uid, result);
157 if (send_result.is_err()) {
166 auto end_time = std::chrono::steady_clock::now();
167 auto execution_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
168 end_time - start_time).count();
171 kcenon::common::get_event_bus().publish(
173 to_event_level(level.value()),
176 static_cast<uint64_t
>(execution_time_ms)
185 std::string(to_string(level.value())),
192 sop_class_uid, status_success);
221 if (level_str.empty()) {
232 std::string_view sop_class_uid,
235 using namespace network::dimse;
238 auto response = make_c_find_rsp(
245 response.set_dataset(result);
248 return assoc.
send_dimse(context_id, response);
255 std::string_view sop_class_uid,
258 using namespace network::dimse;
261 auto response = make_c_find_rsp(
268 return assoc.
send_dimse(context_id, response);
High-level facade for ATNA audit logging in DICOM services.
auto get_string(dicom_tag tag, std::string_view default_value="") const -> std::string
Get the string value of an element.
Result< std::monostate > send_dimse(uint8_t context_id, const dimse::dimse_message &msg)
Send a DIMSE message.
std::string_view calling_ae() const noexcept
Get calling AE title.
std::string_view called_ae() const noexcept
Get called AE title.
auto message_id() const noexcept -> uint16_t
Get the message ID.
auto affected_sop_class_uid() const -> std::string
Get the Affected SOP Class UID.
auto has_dataset() const noexcept -> bool
Check if the message has an associated data set.
auto dataset() -> kcenon::pacs::Result< std::reference_wrapper< core::dicom_dataset > >
Get mutable reference to the data set.
auto command() const noexcept -> command_field
Get the command field.
void audit_query(const std::string &calling_ae, const std::string &called_ae, const std::string &query_level, bool success)
Audit a C-FIND (Query) event.
std::vector< std::string > supported_sop_classes() const override
Get supported SOP Class UIDs.
void set_audit_handler(std::shared_ptr< kcenon::pacs::security::atna_service_auditor > auditor)
Set the ATNA audit handler for C-FIND operations.
std::optional< query_level > extract_query_level(const core::dicom_dataset &dataset) const
Extract query level from request dataset.
network::Result< std::monostate > send_pending_response(network::association &assoc, uint8_t context_id, uint16_t message_id, std::string_view sop_class_uid, const core::dicom_dataset &result)
Send a pending C-FIND response with matching dataset.
size_t max_results() const noexcept
Get maximum number of results.
void set_cancel_check(cancel_check check)
Set the cancel check function.
void reset_statistics() noexcept
Reset statistics counters.
std::shared_ptr< kcenon::pacs::security::atna_service_auditor > auditor_
std::atomic< size_t > queries_processed_
void set_handler(query_handler handler)
Set the query handler function.
std::string_view service_name() const noexcept override
Get the service name.
network::Result< std::monostate > handle_message(network::association &assoc, uint8_t context_id, const network::dimse::dimse_message &request) override
Handle an incoming DIMSE message (C-FIND-RQ)
cancel_check cancel_check_
network::Result< std::monostate > send_final_response(network::association &assoc, uint8_t context_id, uint16_t message_id, std::string_view sop_class_uid, network::dimse::status_code status)
Send the final C-FIND response (success or cancel)
void set_max_results(size_t max) noexcept
Set maximum number of results to return.
size_t queries_processed() const noexcept
Get total number of queries processed.
query_scp(std::shared_ptr< di::ILogger > logger=nullptr)
Construct Query SCP with optional logger.
DIMSE command field enumeration.
Compile-time constants for commonly used DICOM tags.
DICOM event definitions for event-based communication.
constexpr int find_handler_not_set
constexpr int find_unexpected_command
query_level
Query level enumeration.
uint16_t status_code
DIMSE status code type alias.
constexpr std::string_view study_root_find_sop_class_uid
Study Root Query/Retrieve Information Model - FIND.
constexpr std::string_view patient_root_find_sop_class_uid
Patient Root Query/Retrieve Information Model - FIND.
std::function< std::vector< core::dicom_dataset >( query_level level, const core::dicom_dataset &query_keys, const std::string &calling_ae)> query_handler
Query handler function type.
std::optional< query_level > parse_query_level(std::string_view level_str) noexcept
Parse query level from DICOM string.
auto to_string(mpps_status status) -> std::string_view
Convert mpps_status to DICOM string representation.
std::function< bool()> cancel_check
Cancel check function type.
@ study
Study level - query study information.
@ image
Image (Instance) level - query instance information.
@ patient
Patient level - query patient demographics.
@ series
Series level - query series information.
VoidResult pacs_void_error(int code, const std::string &message, const std::string &details="")
Create a PACS void error result.
DICOM Query SCP service (C-FIND handler)
Result<T> type aliases and helpers for PACS system.
Event published when a C-FIND query is executed.
Event published when a C-FIND query fails.