DIMSE_storeProvider's association parameter

All other questions regarding DCMTK

Moderator: Moderator Team

Post Reply
Message
Author
martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

DIMSE_storeProvider's association parameter

#1 Post by martinrame »

Hi, I'm trying to implement my own DcmSCP class to handle C-Store requests.

In handleIncomingCommand, I have to call DIMSE_storeProvider before calling sendStoreResponse. Otherwise the SCU stops with a "Connection reset by peer" message.

DIMSE_storeProvider needs an T_ASC_ASSOCIATION param, but m_assoc is private in DcmSCP.

How can I get the association from my inherited class?.

Michael Onken
DCMTK Developer
Posts: 2051
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#2 Post by Michael Onken »

Hi,

overwrite DcmSCP's function handleIncomingCommand and call in case of a DIMSE store packet your own handler.

For all others, you may call from your own handleIncomingCommand() implementation the orginal DcmSCP implementation (e.g. to handle the ECHO requests). Thus, call in the end of your function DcmSCP::handleIncomingComand(...).

Michael

martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

#3 Post by martinrame »

Michael, thanks for your answer.
overwrite DcmSCP's function handleIncomingCommand and call in case of a DIMSE store packet your own handler.
I did exactly that. Here is my handleIncomingCommand:

Code: Select all

OFCondition DicomSCP::handleIncomingCommand(T_DIMSE_Message *incomingMsg, 
  const DcmPresentationContextInfo &presContextInfo)
{
  OFCondition cond;
  OFString tempStr;
  T_ASC_PresentationContextID presID = presContextInfo.presentationContextID;

  if( incomingMsg->CommandField == DIMSE_C_ECHO_RQ )
  {
    // Process C-ECHO request
    cond = handleECHORequest( incomingMsg->msg.CEchoRQ, presID );
  } else {
    OFString tempStr;
    T_DIMSE_C_StoreRSP response;
    T_DIMSE_C_StoreRQ request = incomingMsg->msg.CStoreRQ;
    DcmDataset *statusDetail = NULL;
    char imageFileName[2048];
    getFileName(imageFileName);

    bzero((char*)&response, sizeof(response));
    response.DimseStatus = STATUS_Success;  /* assume */
    response.MessageIDBeingRespondedTo = request.MessageID;
    response.DataSetType = DIMSE_DATASET_NULL;  /* always for C-STORE-RSP */
    strcpy(response.AffectedSOPClassUID, request.AffectedSOPClassUID);
    strcpy(response.AffectedSOPInstanceUID, request.AffectedSOPInstanceUID);
    response.opts = (O_STORE_AFFECTEDSOPCLASSUID | O_STORE_AFFECTEDSOPINSTANCEUID);
    if (request.opts & O_STORE_RQ_BLANK_PADDING) response.opts |= O_STORE_RSP_BLANK_PADDING;
    if (dcmPeerRequiresExactUIDCopy.get()) response.opts |= O_STORE_PEER_REQUIRES_EXACT_UID_COPY;

    // Dump debug information
    DCMNET_INFO("C-STORE request");
    DCMNET_INFO(DIMSE_dumpMessage(tempStr, request, DIMSE_INCOMING, NULL, presID));
    DCMNET_INFO("Sending C-STORE Response");

    // DIMSE_storeProvider needs a T_ASC_ASSOCIATION pointer
    // how can I get it?

    cond = DIMSE_storeProvider(m_assoc, presID, &request, imageFileName, true, NULL, NULL, NULL, DIMSE_BLOCKING, 0);

    if(cond.bad())
      DCMNET_INFO("Cannot storeProvider" << DimseCondition::dump(tempStr, cond));
    else
      DCMNET_INFO("Ok");
    
    // Send an cstore response
    OFCondition cond = sendSTOREResponse(presID, request, response, statusDetail);
    if( cond.bad() )
      DCMNET_INFO("Cannot send C-ECHO Response: " << DimseCondition::dump(tempStr, cond));
    else
      DCMNET_INFO("C-STORE Response successfully sent");
  }

  // return result
  return cond;
}
As you can see in the comment in my code, DIMSE_storeProvider needs a T_ASC_ASSOCIATION pointer, how can I get it?. Is DIMSE_storeProvider really needed?.

I copied it from /dcmnet/apps/storescp.cc

This is what I get if I call storescu against my SCP:

Code: Select all

storescu -v -aet TEST -aec PACSERVER 127.0.0.1 5678 test.dcm
I: checking input files ...
I: Requesting Association
I: Association Accepted (Max Send PDV: 16372)
I: Sending file: test.dcm
I: Transfer Syntax: LittleEndianExplicit -> LittleEndianImplicit
I: Sending Store Request: MsgID 1, (CR)
XMIT: ....E: Store Failed, file: test.dcm:
E: 0006:020e DIMSE Failed to send message
E: 0006:031d TCP I/O Error (Connection reset by peer) occurred in routine: writeDataPDU
E: Store SCU Failed: 0006:020e DIMSE Failed to send message
E: 0006:031d TCP I/O Error (Connection reset by peer) occurred in routine: writeDataPDU
I: Aborting Association
E: Association Abort Failed: 0006:031d TCP I/O Error (Broken pipe) occurred in routine: sendAbortTCP
Any hint?

Michael Onken
DCMTK Developer
Posts: 2051
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#4 Post by Michael Onken »

Hi,

you should just not use DIMSE_storeProvider()! First, you receive the C-STORE command set which seems to work, right?

Then, the dataset should arrive, which you can receive by calling DcmSCP's function receiveDIMSEDataset(). For that you only need the presentation context and a pointer where the dataset should be stored. The last two parameters can be NULL.

You can then look into storescp (for example) how a received dataset can be stored to disk.

Michael

martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

#5 Post by martinrame »

Thanks!, that worked wonderfully.

Michael Onken
DCMTK Developer
Posts: 2051
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#6 Post by Michael Onken »

:) Happy to hear that!

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 1 guest