Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

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.

Fail to send DICOM C-Echo, although DICOM Association seems successful.

+6
−0

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:

WireShark capture of traffic from Android emulator to VPS

Capture of the traffic from DCMTK's echoscu to the VPS:

WireShark capture of traffic from DCMTK echoscu to VPS

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

1 comment thread

General comments (13 comments)

0 answers

Sign up to answer this question »