41 auto encode_result = encode_response();
42 if (!encode_result.is_ok()) {
44 auto err = encode_result.error();
45 on_error_(result_.session_id, err.message);
50 auto responses = encode_result.value();
53 for (
auto& response : responses) {
56 on_encoded_(response);
61 auto send_job = std::make_unique<send_network_io_job>(
63 std::move(response.pdu_data),
67 send_job->get_context() = context_;
70 auto submit_result = coordinator.submit_to_stage(
75 if (!submit_result.is_ok()) {
105 std::vector<encoded_response> responses;
108 auto command_result = encode_dimse_command();
109 if (!command_result.is_ok()) {
113 auto command_data = command_result.value();
116 auto command_fragments = fragment_data(command_data);
119 for (
size_t i = 0; i < command_fragments.size(); ++i) {
123 response.
is_final = (i == command_fragments.size() - 1) && result_.data_set.empty();
129 const auto& frag = command_fragments[i];
130 size_t pdv_length = 2 + frag.size();
131 size_t pdu_length = 4 + pdv_length;
133 response.
pdu_data.resize(6 + pdu_length);
140 response.
pdu_data[2] =
static_cast<uint8_t
>((pdu_length >> 24) & 0xFF);
141 response.
pdu_data[3] =
static_cast<uint8_t
>((pdu_length >> 16) & 0xFF);
142 response.
pdu_data[4] =
static_cast<uint8_t
>((pdu_length >> 8) & 0xFF);
143 response.
pdu_data[5] =
static_cast<uint8_t
>(pdu_length & 0xFF);
147 response.
pdu_data[offset++] =
static_cast<uint8_t
>((pdv_length >> 24) & 0xFF);
148 response.
pdu_data[offset++] =
static_cast<uint8_t
>((pdv_length >> 16) & 0xFF);
149 response.
pdu_data[offset++] =
static_cast<uint8_t
>((pdv_length >> 8) & 0xFF);
150 response.
pdu_data[offset++] =
static_cast<uint8_t
>(pdv_length & 0xFF);
153 response.
pdu_data[offset++] = result_.presentation_context_id;
157 if (i == command_fragments.size() - 1) {
163 std::copy(frag.begin(), frag.end(), response.
pdu_data.begin() + offset);
165 responses.push_back(std::move(response));
169 if (!result_.data_set.empty()) {
170 auto data_fragments = fragment_data(result_.data_set);
172 for (
size_t i = 0; i < data_fragments.size(); ++i) {
176 response.
is_final = (i == data_fragments.size() - 1);
178 const auto& frag = data_fragments[i];
179 size_t pdv_length = 2 + frag.size();
180 size_t pdu_length = 4 + pdv_length;
182 response.
pdu_data.resize(6 + pdu_length);
188 response.
pdu_data[2] =
static_cast<uint8_t
>((pdu_length >> 24) & 0xFF);
189 response.
pdu_data[3] =
static_cast<uint8_t
>((pdu_length >> 16) & 0xFF);
190 response.
pdu_data[4] =
static_cast<uint8_t
>((pdu_length >> 8) & 0xFF);
191 response.
pdu_data[5] =
static_cast<uint8_t
>(pdu_length & 0xFF);
194 response.
pdu_data[offset++] =
static_cast<uint8_t
>((pdv_length >> 24) & 0xFF);
195 response.
pdu_data[offset++] =
static_cast<uint8_t
>((pdv_length >> 16) & 0xFF);
196 response.
pdu_data[offset++] =
static_cast<uint8_t
>((pdv_length >> 8) & 0xFF);
197 response.
pdu_data[offset++] =
static_cast<uint8_t
>(pdv_length & 0xFF);
199 response.
pdu_data[offset++] = result_.presentation_context_id;
202 if (i == data_fragments.size() - 1) {
207 std::copy(frag.begin(), frag.end(), response.
pdu_data.begin() + offset);
209 responses.push_back(std::move(response));
213 return ok(std::move(responses));
219 std::vector<uint8_t> command;
220 command.reserve(256);
223 auto append_element = [&command](uint16_t group, uint16_t element,
224 const void* data, uint32_t length) {
226 command.push_back(
static_cast<uint8_t
>(group & 0xFF));
227 command.push_back(
static_cast<uint8_t
>((group >> 8) & 0xFF));
228 command.push_back(
static_cast<uint8_t
>(element & 0xFF));
229 command.push_back(
static_cast<uint8_t
>((element >> 8) & 0xFF));
231 command.push_back(
static_cast<uint8_t
>(length & 0xFF));
232 command.push_back(
static_cast<uint8_t
>((length >> 8) & 0xFF));
233 command.push_back(
static_cast<uint8_t
>((length >> 16) & 0xFF));
234 command.push_back(
static_cast<uint8_t
>((length >> 24) & 0xFF));
236 const auto* bytes =
static_cast<const uint8_t*
>(data);
237 command.insert(command.end(), bytes, bytes + length);
240 auto append_uint16 = [&append_element](uint16_t group, uint16_t element,
242 append_element(group, element, &value, 2);
245 auto append_string = [&append_element](uint16_t group, uint16_t element,
246 const std::string& value) {
247 std::string padded = value;
248 if (padded.size() % 2 != 0) {
249 padded.push_back(
' ');
251 append_element(group, element, padded.data(),
252 static_cast<uint32_t
>(padded.size()));
256 size_t group_length_offset = command.size();
257 uint32_t placeholder = 0;
258 append_element(0x0000, 0x0000, &placeholder, 4);
261 if (!result_.sop_class_uid.empty()) {
262 append_string(0x0000, 0x0002, result_.sop_class_uid);
266 append_uint16(0x0000, 0x0100,
static_cast<uint16_t
>(result_.response_type));
269 append_uint16(0x0000, 0x0120, result_.message_id);
273 uint16_t data_set_type = result_.data_set.empty() ? 0x0101 : 0x0001;
274 append_uint16(0x0000, 0x0800, data_set_type);
277 append_uint16(0x0000, 0x0900,
static_cast<uint16_t
>(result_.status));
280 if (!result_.sop_instance_uid.empty()) {
281 append_string(0x0000, 0x1000, result_.sop_instance_uid);
289 append_uint16(0x0000, 0x1020, result_.remaining_sub_ops);
290 append_uint16(0x0000, 0x1021, result_.completed_sub_ops);
291 append_uint16(0x0000, 0x1022, result_.failed_sub_ops);
292 append_uint16(0x0000, 0x1023, result_.warning_sub_ops);
297 if (!result_.error_comment.empty()) {
298 append_string(0x0000, 0x0902, result_.error_comment);
302 uint32_t group_length =
static_cast<uint32_t
>(command.size() - group_length_offset - 8);
303 command[group_length_offset + 4] =
static_cast<uint8_t
>(group_length & 0xFF);
304 command[group_length_offset + 5] =
static_cast<uint8_t
>((group_length >> 8) & 0xFF);
305 command[group_length_offset + 6] =
static_cast<uint8_t
>((group_length >> 16) & 0xFF);
306 command[group_length_offset + 7] =
static_cast<uint8_t
>((group_length >> 24) & 0xFF);
308 return ok(std::move(command));
312 -> std::vector<std::vector<uint8_t>> {
314 std::vector<std::vector<uint8_t>> fragments;
317 size_t max_fragment_size = max_pdu_size_ - 12;
318 if (max_fragment_size > 16376) {
319 max_fragment_size = 16376;
323 while (offset < data.size()) {
324 size_t fragment_size = std::min(max_fragment_size, data.size() - offset);
325 fragments.emplace_back(data.begin() + offset,
326 data.begin() + offset + fragment_size);
327 offset += fragment_size;
330 if (fragments.empty()) {
331 fragments.emplace_back();
Context information attached to pipeline jobs for tracking.
uint16_t message_id
Message ID from DIMSE command (if applicable)
uint64_t enqueue_time_ns
Timestamp when job entered the pipeline (nanoseconds since epoch)