Skip to content

Commit

Permalink
polishing
Browse files Browse the repository at this point in the history
  • Loading branch information
knopkem committed Apr 5, 2020
1 parent a87cded commit 5492c50
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 66 deletions.
7 changes: 7 additions & 0 deletions src/BaseAsyncWorker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@

#include "Utils.h"

#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */

#include "dcmtk/oflog/oflog.h"


BaseAsyncWorker::BaseAsyncWorker(std::string data, Function &callback) : AsyncProgressWorker<char>(callback),
_input(data)
{
// disable verbose logging
OFLog::configure(OFLogger::WARN_LOG_LEVEL);
}

void BaseAsyncWorker::OnOK()
Expand Down
2 changes: 2 additions & 0 deletions src/MoveAsyncWorker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,14 @@ void MoveAsyncWorker::Execute(const ExecutionProgress &progress)
{

/* output final status report */
/*
std::cout << "Final status report from last C-MOVE message:" << std::endl;
RetrieveResponse *rsp = (*(--responses.end()));
std::cout << "Number of Remaining sub-operations : " << rsp->m_numberOfRemainingSubops << std::endl;
std::cout << "Number of Completed sub-operations : " << rsp->m_numberOfCompletedSubops << std::endl;
std::cout << "Number of Failed sub-operations : " << rsp->m_numberOfFailedSubops << std::endl;
std::cout << "Number of Warning sub-operations : " << rsp->m_numberOfWarningSubops << std::endl;
*/

/* delete responses */
OFListIterator(RetrieveResponse *) iter = responses.begin();
Expand Down
100 changes: 34 additions & 66 deletions src/ServerAsyncWorker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,6 @@ using json = nlohmann::json;

namespace
{
/* sort study mode */
enum E_SortStudyMode
{
ESM_None,
ESM_Timestamp,
ESM_StudyInstanceUID,
ESM_PatientName
};

struct StoreCallbackData
{
Expand All @@ -65,7 +57,7 @@ struct StoreCallbackData

// ------------------------------------------------------------------------------------------------------------

OFCondition echoSCP( T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID)
OFCondition echoSCP(T_ASC_Association *assoc, T_DIMSE_Message *msg, T_ASC_PresentationContextID presID)
{
// assign the actual information of the C-Echo-RQ command to a local variable
T_DIMSE_C_EchoRQ *req = &msg->msg.CEchoRQ;
Expand All @@ -77,7 +69,6 @@ OFCondition echoSCP( T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_Pre

// ------------------------------------------------------------------------------------------------------------


void storeSCPCallback(void *callbackData, T_DIMSE_StoreProgress *progress, T_DIMSE_C_StoreRQ *req,
char * /*imageFileName*/, DcmDataset **imageDataSet, T_DIMSE_C_StoreRSP *rsp, DcmDataset **statusDetail)
{
Expand All @@ -96,13 +87,16 @@ void storeSCPCallback(void *callbackData, T_DIMSE_StoreProgress *progress, T_DIM
// remember callback data
StoreCallbackData *cbdata = OFstatic_cast(StoreCallbackData *, callbackData);

// compose directory and filename structure
OFString studyInstanceUID;
(*imageDataSet)->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID);

OFString baseStr;
OFStandard::combineDirAndFilename(baseStr, cbdata->storageDir, studyInstanceUID, OFTrue);
if (!OFStandard::dirExists(baseStr)) {
if (OFStandard::createDirectory(baseStr, cbdata->storageDir).bad()) {
if (!OFStandard::dirExists(baseStr))
{
if (OFStandard::createDirectory(baseStr, cbdata->storageDir).bad())
{
std::cerr << "failed to create directory " << baseStr.c_str() << std::endl;
return;
}
Expand All @@ -111,24 +105,17 @@ void storeSCPCallback(void *callbackData, T_DIMSE_StoreProgress *progress, T_DIM
OFString fileName;
OFStandard::combineDirAndFilename(fileName, baseStr, cbdata->imageFileName, OFTrue);


if ((imageDataSet != NULL) && (*imageDataSet != NULL))
{

// determine the transfer syntax which shall be used to write the information to the file
E_TransferSyntax xfer = xfer = (*imageDataSet)->getOriginalXfer();

// store file either with meta header or as pure dataset
// OFLOG_INFO(storescpLogger, "storing DICOM file: " << fileName);
if (OFStandard::fileExists(fileName))
{
// OFLOG_WARN(storescpLogger, "DICOM file already exists, overwriting: " << fileName);
}
OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, EET_ExplicitLength, EGL_recalcGL,
EPD_withoutPadding, 0, 0, EWM_fileformat);
if (cond.bad())
{
// OFLOG_ERROR(storescpLogger, "cannot write DICOM file: " << fileName << ": " << cond.text());
std::cerr << "cannot write DICOM file " << fileName.c_str() << std::endl;
rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources;

// delete incomplete file
Expand All @@ -142,7 +129,7 @@ void storeSCPCallback(void *callbackData, T_DIMSE_StoreProgress *progress, T_DIM
// which SOP class and SOP instance ?
if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sizeof(sopClass), sopInstance, sizeof(sopInstance), OFFalse))
{
// OFLOG_ERROR(storescpLogger, "bad DICOM file: " << fileName);
std::cerr << "bad DICOM file " << fileName.c_str() << std::endl;
rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand;
}
else if (strcmp(sopClass, req->AffectedSOPClassUID) != 0)
Expand All @@ -158,7 +145,7 @@ void storeSCPCallback(void *callbackData, T_DIMSE_StoreProgress *progress, T_DIM
}
}

OFCondition storeSCP(T_ASC_Association *assoc, T_DIMSE_Message *msg, T_ASC_PresentationContextID presID, const OFString& outputDirectory)
OFCondition storeSCP(T_ASC_Association *assoc, T_DIMSE_Message *msg, T_ASC_PresentationContextID presID, const OFString &outputDirectory)
{
OFCondition cond = EC_Normal;
T_DIMSE_C_StoreRQ *req;
Expand All @@ -167,6 +154,7 @@ OFCondition storeSCP(T_ASC_Association *assoc, T_DIMSE_Message *msg, T_ASC_Prese
// assign the actual information of the C-STORE-RQ command to a local variable
req = &msg->msg.CStoreRQ;

// format output
sprintf(imageFileName, "%s.%s", req->AffectedSOPInstanceUID, "dcm");

// initialize some variables
Expand All @@ -177,15 +165,6 @@ OFCondition storeSCP(T_ASC_Association *assoc, T_DIMSE_Message *msg, T_ASC_Prese
DcmFileFormat dcmff;
callbackData.dcmff = &dcmff;

// store SourceApplicationEntityTitle in metaheader
if (assoc && assoc->params)
{
const char *aet = assoc->params->DULparams.callingAPTitle;
if (aet) {
// dcmff.getMetaInfo()->putAndInsertString(DCM_SourceApplicationEntityTitle, aet);
}
}

// define an address where the information which will be received over the network will be stored
DcmDataset *dset = dcmff.getDataset();

Expand All @@ -194,20 +173,18 @@ OFCondition storeSCP(T_ASC_Association *assoc, T_DIMSE_Message *msg, T_ASC_Prese
// if some error occurred, dump corresponding information and remove the outfile if necessary
if (cond.bad())
{
OFString temp_str;
// OFLOG_ERROR(storescpLogger, "Store SCP Failed: " << DimseCondition::dump(temp_str, cond));
std::cerr << "Store SCP failed: " << cond.text() << std::endl;

// remove file
if (strcmp(imageFileName, NULL_DEVICE_NAME) != 0)
OFStandard::deleteFile(imageFileName);
}

// return return value
return cond;
}

// ------------------------------------------------------------------------------------------------------------

OFCondition processCommands(T_ASC_Association *assoc, const OFString& outputDirectory)
OFCondition processCommands(T_ASC_Association *assoc, const OFString &outputDirectory)
{
OFCondition cond = EC_Normal;
T_DIMSE_Message msg;
Expand All @@ -220,7 +197,7 @@ OFCondition processCommands(T_ASC_Association *assoc, const OFString& outputDire
// receive a DIMSE command over the network
cond = DIMSE_receiveCommand(assoc, DIMSE_BLOCKING, 0, &presID, &msg, &statusDetail);

// if the command which was received has extra status
// if the command which was received has extra status
// detail information, dump this information
if (statusDetail != NULL)
{
Expand All @@ -247,12 +224,7 @@ OFCondition processCommands(T_ASC_Association *assoc, const OFString& outputDire
OFString tempStr;
// we cannot handle this kind of message
cond = DIMSE_BADCOMMANDTYPE;
/*
OFLOG_ERROR(storescpLogger, "Expected C-ECHO or C-STORE request but received DIMSE command 0x"
<< STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4)
<< OFstatic_cast(unsigned, msg.CommandField));
OFLOG_DEBUG(storescpLogger, DIMSE_dumpMessage(tempStr, msg, DIMSE_INCOMING, NULL, presID));
*/
std::cerr << "unsupported DIMSE command received" << std::endl;
break;
}
}
Expand All @@ -262,7 +234,7 @@ OFCondition processCommands(T_ASC_Association *assoc, const OFString& outputDire

// ------------------------------------------------------------------------------------------------------------

OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfiguration &asccfg, OFBool secureConnection, const OFString& outputDirectory)
OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfiguration &asccfg, OFBool secureConnection, const OFString &outputDirectory, const OFString &aet, const OFString &ts)
{
char buf[BUFSIZ];
T_ASC_Association *assoc;
Expand Down Expand Up @@ -291,15 +263,13 @@ OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfiguration &a
// If something else was wrong we might have to dump an error message.
else
{
// OFLOG_ERROR(storescpLogger, "Receiving Association failed: " << DimseCondition::dump(temp_str, cond));
std::cerr << "Receiving Assocition failed: " << cond.text() << std::endl;
}

// no matter what kind of error occurred, we need to do a cleanup
goto cleanup;
}

// OFLOG_INFO(storescpLogger, "Association Received");

if (gLocalByteOrder == EBO_LittleEndian) /* defined in dcxfer.h */
{
transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax;
Expand All @@ -318,21 +288,19 @@ OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfiguration &a
cond = ASC_acceptContextsWithPreferredTransferSyntaxes(assoc->params, knownAbstractSyntaxes, DIM_OF(knownAbstractSyntaxes), transferSyntaxes, numTransferSyntaxes);
if (cond.bad())
{
// OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond));
goto cleanup;
}

/* the array of Storage SOP Class UIDs comes from dcuid.h */
cond = ASC_acceptContextsWithPreferredTransferSyntaxes(assoc->params, dcmAllStorageSOPClassUIDs, numberOfDcmAllStorageSOPClassUIDs, transferSyntaxes, numTransferSyntaxes);
if (cond.bad())
{
// OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond));
goto cleanup;
}
}

/* set our app title */
ASC_setAPTitles(assoc->params, NULL, NULL, "IMEBRA"/*in.source.aet.c_str()*/);
ASC_setAPTitles(assoc->params, NULL, NULL, aet.c_str());

/* acknowledge or reject this association */
cond = ASC_getApplicationContextName(assoc->params, buf, sizeof(buf));
Expand All @@ -345,11 +313,12 @@ OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfiguration &a
ASC_SOURCE_SERVICEUSER,
ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED};

// OFLOG_INFO(storescpLogger, "Association Rejected: Bad Application Context Name: " << buf);
std::cerr << "Association Rejected: Bad Application Context Name:" << buf << std::endl;

cond = ASC_rejectAssociation(assoc, &rej);
if (cond.bad())
{
// OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond));
std::cerr << cond.text() << std::endl;
}
goto cleanup;
}
Expand All @@ -358,7 +327,7 @@ OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfiguration &a
cond = ASC_acknowledgeAssociation(assoc);
if (cond.bad())
{
// OFLOG_ERROR(storescpLogger, DimseCondition::dump(temp_str, cond));
std::cerr << cond.text() << std::endl;
goto cleanup;
}
}
Expand All @@ -370,38 +339,36 @@ OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfiguration &a

if (cond == DUL_PEERREQUESTEDRELEASE)
{
// OFLOG_INFO(storescpLogger, "Association Release");
cond = ASC_acknowledgeRelease(assoc);
}
else if (cond == DUL_PEERABORTEDASSOCIATION)
{
// OFLOG_INFO(storescpLogger, "Association Aborted");
std::cerr << "Peer aborted association" << std::endl;
}
else
{
// OFLOG_ERROR(storescpLogger, "DIMSE failure (aborting association): " << DimseCondition::dump(temp_str, cond));
/* some kind of error so abort the association */
std::cerr << "DIMSE failure (aborting association): " << cond.text() << std::endl;

cond = ASC_abortAssociation(assoc);
}

cleanup:
cond = ASC_dropSCPAssociation(assoc);
if (cond.bad())
{
// OFLOG_FATAL(storescpLogger, DimseCondition::dump(temp_str, cond));
std::cerr << cond.text() << std::endl;
return cond;
}
cond = ASC_destroyAssociation(&assoc);
if (cond.bad())
{
// OFLOG_FATAL(storescpLogger, DimseCondition::dump(temp_str, cond));
std::cerr << cond.text() << std::endl;
}

return cond;
}



} // end namespace

ServerAsyncWorker::ServerAsyncWorker(std::string data, Function &callback) : BaseAsyncWorker(data, callback)
Expand Down Expand Up @@ -437,7 +404,7 @@ void ServerAsyncWorker::Execute(const ExecutionProgress &progress)
/* make sure data dictionary is loaded */
if (!dcmDataDict.isDictionaryLoaded())
{
// OFLOG_WARN(storescpLogger, "no data dictionary loaded, check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE);
SetErrorJson(std::string("No data dictionary loaded"));
}

/* if the output directory does not equal "." (default directory) */
Expand All @@ -451,46 +418,47 @@ void ServerAsyncWorker::Execute(const ExecutionProgress &progress)
*/
if (!OFStandard::dirExists(opt_outputDirectory))
{
// OFLOG_FATAL(storescpLogger, "specified output directory does not exist");
SetErrorJson(std::string("Specified output directory does not exist: ") + std::string(opt_outputDirectory.c_str()));
return;
}
}

/* check if the output directory is writeable */
if (!OFStandard::isWriteable(opt_outputDirectory))
{
// OFLOG_FATAL(storescpLogger, "specified output directory is not writeable");
SetErrorJson(std::string("Specified output directory is not writeable: ") + std::string(opt_outputDirectory.c_str()));
return;
}

/* initialize network, i.e. create an instance of T_ASC_Network*. */
OFCondition cond = ASC_initializeNetwork(NET_ACCEPTOR, opt_port, 30, &net);
if (cond.bad())
{
// OFLOG_ERROR(storescpLogger, "cannot create network: " << DimseCondition::dump(temp_str, cond));
SetErrorJson(std::string("Cannot create network: ") + std::string(cond.text()));
return;
}

/* drop root privileges now and revert to the calling user id (if we are running as setuid root) */
if (OFStandard::dropPrivileges().bad())
{
// OFLOG_FATAL(storescpLogger, "setuid() failed, maximum number of processes/threads for uid already running.");
SetErrorJson(std::string("setuid() failed, maximum number of threads for uid already running"));
return;
}

while (cond.good())
{
/* receive an association and acknowledge or reject it. If the association was */
/* acknowledged, offer corresponding services and invoke one or more if required. */
cond = acceptAssociation(net, asccfg, false, opt_outputDirectory);
cond = acceptAssociation(net, asccfg, false, opt_outputDirectory, OFString(in.source.aet.c_str()), "");
}

/* drop the network, i.e. free memory of T_ASC_Network* structure. This call */
/* is the counterpart of ASC_initializeNetwork(...) which was called above. */
cond = ASC_dropNetwork(&net);
if (cond.bad())
{
// OFLOG_ERROR(storescpLogger, DimseCondition::dump(temp_str, cond));
SetErrorJson(std::string(cond.text()));
return;
}

Expand Down

0 comments on commit 5492c50

Please sign in to comment.