12#include <kcenon/network/interfaces/i_session.h>
13#include <kcenon/network/session/session.h>
27 std::shared_ptr<network_system::session::messaging_session> session)
28 : session_(std::move(session)) {
29 if (
auto* s = std::get_if<
30 std::shared_ptr<network_system::session::messaging_session>>(&
session_)) {
32 (*s)->set_receive_callback(
33 [
this](
const std::vector<uint8_t>& data) {
37 (*s)->set_error_callback(
38 [
this](std::error_code ec) {
45 std::shared_ptr<network_system::session::secure_session> session)
46 : session_(std::move(session)) {
47 if (
auto* s = std::get_if<
48 std::shared_ptr<network_system::session::secure_session>>(&
session_)) {
50 (*s)->set_receive_callback(
51 [
this](
const std::vector<uint8_t>& data) {
55 (*s)->set_error_callback(
56 [
this](std::error_code ec) {
63 std::shared_ptr<kcenon::network::interfaces::i_session> session)
64 : session_(std::move(session)) {
74 : session_(std::move(other.session_))
75 , receive_buffer_(std::move(other.receive_buffer_))
76 , received_pdus_(std::move(other.received_pdus_))
77 , pdu_callback_(std::move(other.pdu_callback_))
78 , error_callback_(std::move(other.error_callback_))
79 , last_error_(other.last_error_)
80 , closed_(other.closed_) {
88 std::lock_guard<std::mutex> lock(mutex_);
89 session_ = std::move(other.session_);
90 receive_buffer_ = std::move(other.receive_buffer_);
91 received_pdus_ = std::move(other.received_pdus_);
92 pdu_callback_ = std::move(other.pdu_callback_);
93 error_callback_ = std::move(other.error_callback_);
94 last_error_ = other.last_error_;
95 closed_ = other.closed_;
108 const std::vector<uint8_t>& payload) {
109 std::lock_guard<std::mutex> lock(
mutex_);
124 pdu_data.reserve(header.size() + payload.size());
136 std::lock_guard<std::mutex> lock(
mutex_);
147 std::vector<uint8_t> copy = data;
155 std::unique_lock<std::mutex> lock(
mutex_);
162 auto deadline = clock::now() + timeout;
169 auto status =
receive_cv_.wait_until(lock, deadline);
170 if (status == std::cv_status::timeout) {
187 std::function<
void(
const pdu_data&)> callback) {
188 std::lock_guard<std::mutex> lock(
mutex_);
193 std::lock_guard<std::mutex> lock(
mutex_);
202 std::lock_guard<std::mutex> lock(
mutex_);
211 std::visit([](
auto&& session) {
213 if constexpr (std::is_same_v<std::decay_t<
decltype(session)>,
214 std::shared_ptr<kcenon::network::interfaces::i_session>>) {
217 session->stop_session();
227 std::lock_guard<std::mutex> lock(
mutex_);
233 return std::visit([](
auto&& session) ->
bool {
235 if constexpr (std::is_same_v<std::decay_t<
decltype(session)>,
236 std::shared_ptr<kcenon::network::interfaces::i_session>>) {
237 return session->is_connected();
239 return !session->is_stopped();
247 std::lock_guard<std::mutex> lock(
mutex_);
255 std::lock_guard<std::mutex> lock(
mutex_);
257 return std::visit([](
auto&& session) -> std::string {
259 if constexpr (std::is_same_v<std::decay_t<
decltype(session)>,
260 std::shared_ptr<kcenon::network::interfaces::i_session>>) {
261 return std::string(session->id());
263 return session->server_id();
271 return std::holds_alternative<
272 std::shared_ptr<network_system::session::secure_session>>(
session_);
292 std::function<
void(std::error_code)> callback) {
293 std::lock_guard<std::mutex> lock(
mutex_);
298 std::lock_guard<std::mutex> lock(
mutex_);
307 std::lock_guard<std::mutex> lock(
mutex_);
321 std::function<void(std::error_code)> callback;
324 std::lock_guard<std::mutex> lock(
mutex_);
346 last_error_ = std::make_error_code(std::errc::protocol_error);
353 last_error_ = std::make_error_code(std::errc::message_size);
366 std::vector<uint8_t> payload(
376 pdu_data pdu(type, std::move(payload));
393 header[0] =
static_cast<uint8_t
>(type);
399 header[2] =
static_cast<uint8_t
>((length >> 24) & 0xFF);
400 header[3] =
static_cast<uint8_t
>((length >> 16) & 0xFF);
401 header[4] =
static_cast<uint8_t
>((length >> 8) & 0xFF);
402 header[5] =
static_cast<uint8_t
>(length & 0xFF);
415 uint8_t type_byte = buffer[0];
418 if (type_byte < 0x01 || type_byte > 0x07) {
427 length = (
static_cast<uint32_t
>(buffer[2]) << 24) |
428 (
static_cast<uint32_t
>(buffer[3]) << 16) |
429 (
static_cast<uint32_t
>(buffer[4]) << 8) |
430 static_cast<uint32_t
>(buffer[5]);
436 std::visit([&data](
auto&& session) {
438 if constexpr (std::is_same_v<std::decay_t<
decltype(session)>,
439 std::shared_ptr<kcenon::network::interfaces::i_session>>) {
440 (void)session->send(std::move(data));
442 session->send_packet(std::move(data));
Simple result type for error handling when common_system is unavailable.
DICOM session wrapper for network_system sessions.
Result< std::monostate > send_raw(const std::vector< uint8_t > &data)
Send raw PDU data (with header already included)
void process_buffer()
Process buffered data for complete PDUs.
void set_pdu_callback(std::function< void(const pdu_data &)> callback)
Set callback for asynchronous PDU reception.
std::condition_variable receive_cv_
Condition variable for synchronous receive.
static constexpr size_t pdu_header_size
PDU header size per DICOM PS3.8.
bool is_open() const noexcept
Check if the session is open.
void feed_error(std::error_code ec)
Feed an error from external source.
Result< std::monostate > send_pdu(network::pdu_type type, const std::vector< uint8_t > &payload)
Send a complete DICOM PDU.
std::error_code last_error() const noexcept
Get the last error code.
bool closed_
Session closed flag.
bool is_secure() const noexcept
Check if this is a secure (TLS) session.
std::function< void(const pdu_data &)> pdu_callback_
PDU callback for async reception.
void clear_pdu_callback()
Clear the PDU callback.
std::vector< uint8_t > receive_buffer_
Receive buffer for PDU framing.
void feed_data(const std::vector< uint8_t > &data)
Feed received data from external source.
static bool parse_pdu_header(const std::vector< uint8_t > &buffer, network::pdu_type &type, uint32_t &length)
Parse PDU header from buffer.
void on_data_received(const std::vector< uint8_t > &data)
Handle incoming data from network.
session_variant session_
Underlying network session.
std::error_code last_error_
Last error code.
dicom_session(std::shared_ptr< network_system::session::messaging_session > session)
Construct a DICOM session wrapping a messaging_session.
dicom_session & operator=(const dicom_session &)=delete
std::function< void(std::error_code)> error_callback_
Error callback.
void set_error_callback(std::function< void(std::error_code)> callback)
Set callback for error events.
Result< pdu_data > receive_pdu(duration timeout=default_timeout)
Receive a complete DICOM PDU.
std::chrono::milliseconds duration
void close()
Close the session.
std::mutex mutex_
Mutex for thread safety.
static std::vector< uint8_t > encode_pdu_header(network::pdu_type type, uint32_t length)
Encode PDU header.
static constexpr size_t max_pdu_payload_size
Maximum PDU payload size (sanity check)
std::string remote_address() const
Get the remote peer address.
std::vector< pdu_data > received_pdus_
Queue of received complete PDUs.
std::string session_id() const
Get session identifier.
void on_error(std::error_code ec)
Handle connection errors.
void send_data(std::vector< uint8_t > &&data)
Send data through the underlying session.
~dicom_session()
Destructor (closes session if open)
DICOM session wrapper for network_system sessions.
pdu_type
PDU (Protocol Data Unit) types as defined in DICOM PS3.8.
kcenon::common::Result< T > Result
Result type alias for PACS operations.
kcenon::common::error_info error_info
Error information type.
Container for received PDU data.