Skip to content

Commit 8a86543

Browse files
committed
Update dicom.py
1 parent 1c216bb commit 8a86543

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

scapy/contrib/dicom.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,7 @@ def build_user_information(max_pdu_length: int = 16384,
13811381
return DICOMVariableItem() / DICOMUserInformation(sub_items=sub_items)
13821382

13831383

1384+
class DICOMSocket:
13841385
"""DICOM application-layer socket for associations and DIMSE operations."""
13851386

13861387
def __init__(self, dst_ip: str, dst_port: int, dst_ae: str,
@@ -1406,6 +1407,7 @@ def _normalize_ae_title(title: Union[str, bytes]) -> bytes:
14061407
if isinstance(title, bytes):
14071408
return title.ljust(16, b" ")[:16]
14081409
return title.encode("ascii").ljust(16, b" ")[:16]
1410+
14091411
def __enter__(self) -> "DICOMSocket":
14101412
return self
14111413

@@ -1506,27 +1508,34 @@ def associate(self, requested_contexts: Optional[Dict[str, List[str]]] = None
15061508
log.error("Association failed: no valid response received")
15071509
return False
15081510

1509-
def _parse_max_pdu_length(self, response):
1511+
def _parse_max_pdu_length(self, response: Packet) -> None:
15101512
try:
15111513
for item in response[A_ASSOCIATE_AC].variable_items:
15121514
if item.item_type == 0x50:
15131515
if item.haslayer(DICOMUserInformation):
15141516
user_info = item[DICOMUserInformation]
15151517
for sub_item in user_info.sub_items:
1518+
if sub_item.item_type == 0x51:
1519+
if sub_item.haslayer(DICOMMaximumLength):
1520+
max_len = sub_item[DICOMMaximumLength]
1521+
server_max = max_len.max_pdu_length
1522+
self.max_pdu_length = min(
1523+
self._proposed_max_pdu, server_max
1524+
)
1525+
return
1526+
except (KeyError, IndexError, AttributeError):
15161527
pass
15171528
self.max_pdu_length = self._proposed_max_pdu
15181529

15191530
def _parse_accepted_contexts(self, response: Packet) -> None:
15201531
for item in response[A_ASSOCIATE_AC].variable_items:
1521-
pctx = item[DICOMPresentationContextAC]
1522-
ctx_id = pctx.context_id
1523-
"Server accepted context ID %d which we didn't propose!",
1524-
ctx_id
1525-
)
1526-
continue
1527-
break
1528-
1529-
def _get_next_message_id(self):
1532+
if item.item_type == 0x21:
1533+
if item.haslayer(DICOMPresentationContextAC):
1534+
pctx = item[DICOMPresentationContextAC]
1535+
ctx_id = pctx.context_id
1536+
result = pctx.result
1537+
1538+
if result != 0:
15301539
continue
15311540

15321541
abs_syntax = self._proposed_context_map.get(ctx_id)
@@ -1535,6 +1544,10 @@ def _get_next_message_id(self):
15351544

15361545
for sub_item in pctx.sub_items:
15371546
if sub_item.item_type == 0x40:
1547+
if sub_item.haslayer(DICOMTransferSyntax):
1548+
ts_uid = sub_item[DICOMTransferSyntax].uid
1549+
if isinstance(ts_uid, bytes):
1550+
ts_uid = ts_uid.rstrip(b"\x00")
15381551
ts_uid = ts_uid.decode("ascii")
15391552
self.accepted_contexts[ctx_id] = (
15401553
abs_syntax, ts_uid
@@ -1547,6 +1560,7 @@ def _get_next_message_id(self) -> int:
15471560

15481561
def _find_accepted_context_id(self, sop_class_uid: str,
15491562
transfer_syntax_uid: Optional[str] = None
1563+
) -> Optional[int]:
15501564
for ctx_id, (abs_syntax, ts_syntax) in self.accepted_contexts.items():
15511565
if abs_syntax == sop_class_uid:
15521566
if transfer_syntax_uid is None or transfer_syntax_uid == ts_syntax:

0 commit comments

Comments
 (0)