19#ifndef PACS_NETWORK_ASSOCIATION_HPP
20#define PACS_NETWORK_ASSOCIATION_HPP
38#include <kcenon/thread/lockfree/lockfree_queue.h>
96 default:
return "Unknown";
147 default:
return "Unknown error";
165 std::vector<std::string> ts_list)
186 , transfer_syntax(std::move(
ts))
285 using clock = std::chrono::steady_clock;
334 const std::string& host,
380 [[nodiscard]]
bool is_closed() const noexcept;
389 [[nodiscard]] std::string_view
calling_ae() const noexcept;
394 [[nodiscard]] std::string_view
called_ae() const noexcept;
433 uint8_t pc_id) const;
454 const dimse::dimse_message& msg);
526 void abort(uint8_t source = 0, uint8_t reason = 0);
640 std::make_unique<message_queue_type>()};
std::map< std::string, uint8_t > abstract_syntax_to_context_
Map from abstract syntax to accepted context ID.
std::string_view remote_implementation_version() const noexcept
Get remote implementation version name.
kcenon::thread::detail::concurrent_queue< message_type > message_queue_type
std::chrono::steady_clock clock
std::unique_ptr< message_queue_type > incoming_queue_
static association accept(const associate_rq &rq, const scp_config &config)
Accept an incoming SCP association.
std::string remote_implementation_class_
Remote implementation class UID.
std::vector< proposed_presentation_context > proposed_contexts_
Proposed presentation contexts (SCU)
uint8_t abort_reason_
Abort reason (if aborted)
bool process_associate_ac(const associate_ac &ac)
Process received A-ASSOCIATE-AC PDU.
void enqueue_message(uint8_t context_id, dimse::dimse_message msg)
Enqueue message from peer (for in-memory testing).
association()
Default constructor (creates idle association).
static Result< association > connect(const std::string &host, uint16_t port, const association_config &config, duration timeout=default_timeout)
Initiate an SCU association to a remote SCP.
std::optional< rejection_info > get_rejection_info() const
Get rejection info if association was rejected.
std::string called_ae_
Called AE Title.
std::string our_implementation_class_
Our implementation class UID.
std::string our_ae_
Our AE Title (may be calling or called depending on role)
~association()
Destructor (aborts if still established).
void process_release_rp()
Process received A-RELEASE-RP.
void build_context_map()
Build presentation context map from accepted contexts.
bool can_transition_to(association_state new_state) const
Validate state transition.
void set_state(association_state new_state)
Force state transition (for testing).
const std::vector< accepted_presentation_context > & accepted_contexts() const noexcept
Get all accepted presentation contexts.
bool is_established() const noexcept
Check if association is established and ready for DIMSE.
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.
void update_peer(association *old_peer, association *new_peer)
Update peer pointer (for in-memory testing).
uint32_t max_pdu_size() const noexcept
Get negotiated maximum PDU size.
void process_release_rq()
Process received A-RELEASE-RQ.
bool is_scu_
Is this an SCU (true) or SCP (false)?
std::mutex mutex_
Thread safety mutex.
association & operator=(association &&other) noexcept
Move assignment operator.
associate_ac build_associate_ac() const
Build A-ASSOCIATE-AC PDU for sending.
std::string calling_ae_
Calling AE Title.
association_state state_
Current state.
associate_rq build_associate_rq() const
Build A-ASSOCIATE-RQ PDU for sending.
association_state state() const noexcept
Get current association state.
std::string our_implementation_version_
Our implementation version name.
Result< encoding::transfer_syntax > context_transfer_syntax(uint8_t pc_id) const
Get the transfer syntax for an accepted context.
void transition(association_state new_state)
Perform state transition.
void set_peer(association *peer)
Set peer association for in-memory testing.
std::chrono::milliseconds duration
std::map< uint8_t, encoding::transfer_syntax > context_to_transfer_syntax_
Map from context ID to transfer syntax.
Result< std::monostate > release(duration timeout=default_timeout)
Gracefully release the association.
association * peer_
Peer association for in-memory testing.
bool has_accepted_context(std::string_view abstract_syntax) const
Check if a presentation context for the abstract syntax was accepted.
clock::time_point time_point
uint8_t abort_source_
Abort source (if aborted)
association(const association &)=delete
Result< std::pair< uint8_t, dimse::dimse_message > > receive_dimse(duration timeout=default_timeout)
Receive a DIMSE message.
uint32_t max_pdu_size_
Negotiated maximum PDU size.
bool is_closed() const noexcept
Check if association has been released or aborted.
association & operator=(const association &)=delete
std::pair< uint8_t, dimse::dimse_message > message_type
Incoming message queue for in-memory testing (thread-safe)
std::string remote_implementation_version_
Remote implementation version name.
static constexpr duration default_timeout
Default timeout for operations.
std::vector< accepted_presentation_context > accepted_contexts_
Accepted presentation contexts.
void process_associate_rj(const associate_rj &rj)
Process received A-ASSOCIATE-RJ PDU.
void negotiate_contexts(const associate_rq &rq, const scp_config &config)
Negotiate presentation contexts for SCP.
static associate_rj reject(reject_result result, uint8_t source, uint8_t reason)
Reject an incoming association request.
std::optional< rejection_info > rejection_info_
Rejection information (if rejected)
std::string_view remote_implementation_class() const noexcept
Get remote implementation class UID.
void process_abort(const abort_source &source, const abort_reason &reason)
Process received A-ABORT PDU.
std::optional< uint8_t > accepted_context_id(std::string_view abstract_syntax) const
Get the presentation context ID for an abstract syntax.
DIMSE message encoding and decoding.
reject_result
Reject result values.
@ rejected_permanent
Rejected-permanent.
@ abstract_syntax
Abstract Syntax Sub-item.
abort_reason
Abort reason values when source is service-provider.
constexpr uint32_t DEFAULT_MAX_PDU_LENGTH
Maximum PDU length recommended by DICOM (16384 bytes)
constexpr const char * to_string(association_state state) noexcept
Convert association_state to string representation.
kcenon::pacs::VoidResult VoidResult
VoidResult type alias for operations without return value.
association_error
Error codes for association operations.
abort_source
Abort source values.
presentation_context_result
Result values for A-ASSOCIATE-AC presentation context.
association_state
DICOM Association state machine states per PS3.8.
@ released
Association gracefully released.
@ awaiting_release_rp
Sta7: Awaiting A-RELEASE response (initiator)
@ awaiting_associate_ac
Sta5: Awaiting A-ASSOCIATE response (SCU)
@ established
Sta6: Association established, ready for DIMSE.
@ aborted
Association aborted (error condition)
@ awaiting_release_rq
Sta8: Awaiting potential A-RELEASE request.
@ awaiting_associate_rq
Sta2: Awaiting A-ASSOCIATE request (SCP)
@ idle
Sta1: No TCP connection, waiting for transport.
Result<T> type aliases and helpers for PACS system.
Accepted presentation context after negotiation.
uint8_t id
Presentation Context ID.
accepted_presentation_context(uint8_t ctx_id, std::string abs_syntax, std::string ts, presentation_context_result res)
presentation_context_result result
Negotiation result.
std::string transfer_syntax
Accepted Transfer Syntax UID.
accepted_presentation_context()
std::string abstract_syntax
Abstract Syntax UID.
bool is_accepted() const noexcept
Configuration for SCU association request.
association_config()=default
std::string called_ae_title
Remote AE Title (16 chars max)
std::string calling_ae_title
Our AE Title (16 chars max)
std::string implementation_class_uid
std::string implementation_version_name
std::vector< proposed_presentation_context > proposed_contexts
Proposed presentation context for SCU association request.
std::string abstract_syntax
Abstract Syntax UID (SOP Class)
uint8_t id
Presentation Context ID (odd 1-255)
std::vector< std::string > transfer_syntaxes
Proposed Transfer Syntaxes.
proposed_presentation_context(uint8_t ctx_id, std::string abs_syntax, std::vector< std::string > ts_list)
proposed_presentation_context()
Information about an association rejection.
rejection_info(reject_result res, uint8_t src, uint8_t rsn)
Configuration for SCP to accept associations.
std::string implementation_class_uid
std::vector< std::string > accepted_ae_titles
Allowed calling AE titles (empty = all)
std::string ae_title
Our AE Title.
std::vector< std::string > supported_abstract_syntaxes
std::vector< std::string > supported_transfer_syntaxes
std::string implementation_version_name