Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Comments on Fail to send DICOM C-Echo, although DICOM Association seems successful.
Post
Fail to send DICOM C-Echo, although DICOM Association seems successful.
I am building an Android app to perform a DICOM C-Echo. (DICOM is a standard for storing and transferring medical images; the specification is at dicom.nema.org). My purpose is to learn more about how DICOM works, by implementing things myself.
To test my application, I use DCMTk's storescp
command, which implements the receiving party of a DICOM C-Echo.
So, on my VPS, which runs Ubuntu, I give this command:
sudo storescp -d 104
(The "-d" flag is for "debug", giving me extra information).
When I use DCMTk to create a DICOM Association, I get the following response:
D: $dcmtk: storescp v3.6.2 2017-07-14 $
D:
D: DcmDataDictionary: Loading file: /usr/share/libdcmtk12/dicom.dic
D: DcmDataDictionary: Loading file: /usr/share/libdcmtk12/private.dic
D: setting network send timeout to 60 seconds
D: setting network receive timeout to 60 seconds
D: PDU Type: Associate Request, PDU Length: 205 + 6 bytes PDU header
D: 01 00 00 00 00 cd 00 01 00 00 41 4e 59 2d 53 43
D: 50 20 20 20 20 20 20 20 20 20 45 43 48 4f 53 43
D: 55 20 20 20 20 20 20 20 20 20 00 00 00 00 00 00
D: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
D: 00 00 00 00 00 00 00 00 00 00 10 00 00 15 31 2e
D: 32 2e 38 34 30 2e 31 30 30 30 38 2e 33 2e 31 2e
D: 31 2e 31 20 00 00 2e 01 00 ff 00 30 00 00 11 31
D: 2e 32 2e 38 34 30 2e 31 30 30 30 38 2e 31 2e 31
D: 40 00 00 11 31 2e 32 2e 38 34 30 2e 31 30 30 30
D: 38 2e 31 2e 32 50 00 00 3a 51 00 00 04 00 00 40
D: 00 52 00 00 1b 31 2e 32 2e 32 37 36 2e 30 2e 37
D: 32 33 30 30 31 30 2e 33 2e 30 2e 33 2e 36 2e 32
D: 55 00 00 0f 4f 46 46 49 53 5f 44 43 4d 54 4b 5f
D: 33 36 32
D: Parsing an A-ASSOCIATE PDU
I: Association Received
D: Parameters:
D: ====================== BEGIN A-ASSOCIATE-RQ =====================
D: Our Implementation Class UID: 1.2.276.0.7230010.3.0.3.6.2
D: Our Implementation Version Name: OFFIS_DCMTK_362
D: Their Implementation Class UID: 1.2.276.0.7230010.3.0.3.6.2
D: Their Implementation Version Name: OFFIS_DCMTK_362
D: Application Context Name: 1.2.840.10008.3.1.1.1
D: Calling Application Name: ECHOSCU
D: Called Application Name: ANY-SCP
D: Responding Application Name:
D: Our Max PDU Receive Size: 16384
D: Their Max PDU Receive Size: 16384
D: Presentation Contexts:
D: Context ID: 1 (Proposed)
D: Abstract Syntax: =VerificationSOPClass
D: Proposed SCP/SCU Role: Default
D: Proposed Transfer Syntax(es):
D: =LittleEndianImplicit
D: Requested Extended Negotiation: none
D: Accepted Extended Negotiation: none
D: Requested User Identity Negotiation: none
D: User Identity Negotiation Response: none
D: ======================= END A-ASSOCIATE-RQ ======================
D: Constructing Associate AC PDU
I: Association Acknowledged (Max Send PDV: 16372)
D: ====================== BEGIN A-ASSOCIATE-AC =====================
D: Our Implementation Class UID: 1.2.276.0.7230010.3.0.3.6.2
D: Our Implementation Version Name: OFFIS_DCMTK_362
D: Their Implementation Class UID: 1.2.276.0.7230010.3.0.3.6.2
D: Their Implementation Version Name: OFFIS_DCMTK_362
D: Application Context Name: 1.2.840.10008.3.1.1.1
D: Calling Application Name: ECHOSCU
D: Called Application Name: ANY-SCP
D: Responding Application Name: ANY-SCP
D: Our Max PDU Receive Size: 16384
D: Their Max PDU Receive Size: 16384
D: Presentation Contexts:
D: Context ID: 1 (Accepted)
D: Abstract Syntax: =VerificationSOPClass
D: Proposed SCP/SCU Role: Default
D: Accepted SCP/SCU Role: Default
D: Accepted Transfer Syntax: =LittleEndianImplicit
D: Requested Extended Negotiation: none
D: Accepted Extended Negotiation: none
D: Requested User Identity Negotiation: none
D: User Identity Negotiation Response: none
D: ======================= END A-ASSOCIATE-AC ======================
D: DcmDataset::read() TransferSyntax="Little Endian Implicit"
I: Received Echo Request
D: ===================== INCOMING DIMSE MESSAGE ====================
D: Message Type : C-ECHO RQ
D: Presentation Context ID : 1
D: Message ID : 1
D: Data Set : none
D: ======================= END DIMSE MESSAGE =======================
I: Association Release
When I use my app to establish the DICOM Association, I get a similar result:
D: setting network send timeout to 60 seconds
D: setting network receive timeout to 60 seconds
D: PDU Type: Associate Request, PDU Length: 188 + 6 bytes PDU header
D: 01 00 00 00 00 bc 00 01 00 00 41 4e 59 2d 53 43
D: 50 20 20 20 20 20 20 20 20 20 45 43 48 4f 53 43
D: 55 20 20 20 20 20 20 20 20 20 00 00 00 00 00 00
D: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
D: 00 00 00 00 00 00 00 00 00 00 10 00 00 15 31 2e
D: 32 2e 38 34 30 2e 31 30 30 30 38 2e 33 2e 31 2e
D: 31 2e 31 20 00 00 2e 01 00 00 00 30 00 00 11 31
D: 2e 32 2e 38 34 30 2e 31 30 30 30 38 2e 31 2e 31
D: 40 00 00 11 31 2e 32 2e 38 34 30 2e 31 30 30 30
D: 38 2e 31 2e 32 50 00 00 29 51 00 00 04 00 00 40
D: 00 52 00 00 15 31 2e 32 2e 38 34 30 2e 31 30 30
D: 30 38 2e 33 2e 31 2e 31 2e 31 53 00 00 04 00 01
D: 00 01
D: Parsing an A-ASSOCIATE PDU
I: Association Received
D: Parameters:
D: ====================== BEGIN A-ASSOCIATE-RQ =====================
D: Our Implementation Class UID: 1.2.276.0.7230010.3.0.3.6.2
D: Our Implementation Version Name: OFFIS_DCMTK_362
D: Their Implementation Class UID: 1.2.840.10008.3.1.1.1
D: Their Implementation Version Name:
D: Application Context Name: 1.2.840.10008.3.1.1.1
D: Calling Application Name: ECHOSCU
D: Called Application Name: ANY-SCP
D: Responding Application Name:
D: Our Max PDU Receive Size: 16384
D: Their Max PDU Receive Size: 16384
D: Presentation Contexts:
D: Context ID: 1 (Proposed)
D: Abstract Syntax: =VerificationSOPClass
D: Proposed SCP/SCU Role: Default
D: Proposed Transfer Syntax(es):
D: =LittleEndianImplicit
D: Requested Extended Negotiation: none
D: Accepted Extended Negotiation: none
D: Requested User Identity Negotiation: none
D: User Identity Negotiation Response: none
D: ======================= END A-ASSOCIATE-RQ ======================
D: Constructing Associate AC PDU
I: Association Acknowledged (Max Send PDV: 16372)
D: ====================== BEGIN A-ASSOCIATE-AC =====================
D: Our Implementation Class UID: 1.2.276.0.7230010.3.0.3.6.2
D: Our Implementation Version Name: OFFIS_DCMTK_362
D: Their Implementation Class UID: 1.2.840.10008.3.1.1.1
D: Their Implementation Version Name:
D: Application Context Name: 1.2.840.10008.3.1.1.1
D: Calling Application Name: ECHOSCU
D: Called Application Name: ANY-SCP
D: Responding Application Name: ANY-SCP
D: Our Max PDU Receive Size: 16384
D: Their Max PDU Receive Size: 16384
D: Presentation Contexts:
D: Context ID: 1 (Accepted)
D: Abstract Syntax: =VerificationSOPClass
D: Proposed SCP/SCU Role: Default
D: Accepted SCP/SCU Role: Default
D: Accepted Transfer Syntax: =LittleEndianImplicit
D: Requested Extended Negotiation: none
D: Accepted Extended Negotiation: none
D: Requested User Identity Negotiation: none
D: User Identity Negotiation Response: none
D: ======================= END A-ASSOCIATE-AC ======================
E: DIMSE failure (aborting association): 0006:020d DIMSE Failed to receive message
E: 0006:020c DIMSE Read PDV failed
E: 0006:0321 Unrecognized PDU type: 0
So, in both cases, the response is A-ASSOCIATE-AC, meaning the DICOM Association is accepted. (The other possible responses are A-ASSOCIATE-RJ, when it is rejected, and A-ABORT, when it fails disastrously).
When I use DCMTk's echoscu
to send an Echo request, things work smooth:
D: DcmDataset::read() TransferSyntax="Little Endian Implicit"
I: Received Echo Request
D: ===================== INCOMING DIMSE MESSAGE ====================
D: Message Type : C-ECHO RQ
D: Presentation Context ID : 1
D: Message ID : 1
D: Data Set : none
D: ======================= END DIMSE MESSAGE =======================
However, when I use my app to send the request message, I get this:
E: DIMSE failure (aborting association): 0006:020d DIMSE Failed to receive message
E: 0006:020c DIMSE Read PDV failed
E: 0006:0321 Unrecognized PDU type: 0
I have inspected DCMTk's echoscu
message using Wireshark. and it sends almost the same bytes that I send.
These are the bytes that DCMTK's echoscu
sends, broken down into DICOM Elements.
00 00 g = 0000
00 00 e = 0000
04 00 00 00 VR length = 4
38 00 00 00 VR value = 0x38 = 56 dec
00 00 g=0000
02 00 e=0000
12 00 00 00 VR length = 0x12 = 18dec
31 2e 32 2e 38 34 30 2e 31 30 30 30 38 2e 31 2e 31 00 VR value = 1.2.840.10008.1.1
00 00 g=0000
00 01 e=0100
02 00 00 00 VR length = 2
30 00 VR value = 0030
00 00 g=0000
10 01 e=0110
02 00 00 00 vR length = 2
01 00 VR value = 0001
00 00 g=0000
00 08 e=0800
02 00 00 00 VR length = 2
01 01 VR Value = 0101
These are the bytes that my app sends, again broken down into DICOM elements:
00 00 g=0000
00 00 e=0000
04 00 00 00 VR length = 4
38 00 00 00 VR value = 56 dec
00 00 g=0000
02 00 e=0002
12 00 00 00 VR length = 18
31 2e 32 2e 38 34 30 2e 31 30 30 30 38 2e 31 2e 31 00 VR value = 1.2.840.10008.1.1
00 00 g=0000
00 01 e=0100
02 00 00 00 VR length = 2
30 00 VR value = 0
00 00 g=0000
10 01 e=0110
02 00 00 00 VR length = 2
01 00 VR value = 0x0001
00 00 g=0000
00 08 e=0800
02 00 00 00 VR length = 2
01 01 VR value = 0101
So, it seems a DICOM Association was created succesfully in both cases, and in both cases a very similar series of bytes is sent. So why does the first case succeed, whereas the second case fails?
The error message suggests that I should have sent more: "Unrecognized PDU type: 0". It sounds as if I need to embed my DICOM C-Echo request in something else. Or as if storescp
expects me to create a new command at the level of creating and releasing associations, rather than just a DICOM C-Echo request. In fact, when I don't send the bytes for a DICOM C-Echo but just the 10 bytes to release the Assocation (DICOM A-Release-RQ), the association is released smoothly.
So.. what am I missing?
- Is there an error in the way I set up the DICOM Association?
- Do I need to embed my DICOM C-Echo Request inside something else?
- Do I need to set the receiving party (
storescp
) in a different mode to receive C-Echo, rather than to expect A-Associate-RQ or A-Release-RQ?
Code of the app is on my Github.
EDIT: Since I don't have Wireshark on Android, I decided to run my app from the Android emulator. As @ghost-in-the-zsh suggested, I have made sure that the bytes sent by my app are exactly the same as those sent by DCMTk's echoscu
program.
If I do this, I see that Wireshark does not recognize my C-Echo bytes as DICOM. It labels them as TCP.
But it does label echoscu
's C-Echo bytes as DICOM.
So I'm probably just making a mistake in my networking code.
I have added screenshots of my captures, with the relevant message selected. I can add the captures themselves, if necessary.
Capture of the traffic from the Android emulator to the VPS:
Capture of the traffic from DCMTK's echoscu
to the VPS:
1 comment thread