Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Add possibility to change Implementation Class UID and Implementation Version Name #69

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion dcmdata/include/dcmtk/dcmdata/dcfilefo.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "dcmtk/dcmdata/dcsequen.h"
#include "dcmtk/dcmdata/dcdatset.h"
#include "dcmtk/dcmdata/dcuid.h"


// forward declarations
Expand Down Expand Up @@ -390,6 +391,22 @@ class DCMTK_DCMDATA_EXPORT DcmFileFormat
FileReadMode = readMode;
}

/** Method sets Implementation Class UID meta header tag
* @param implementationClassUID tag value
*/
void setImplementationClassUID(const OFString& implementationClassUID)
{
m_implementationClassUID = implementationClassUID;
};

/** Method sets Implementation Version Name meta header tag
* @param implementationVersionName tag value
*/
void setImplementationVersionName(const OFString& implementationVersionName)
{
m_implementationVersionName = implementationVersionName;
}

/** method inherited from base class that shall not be used for instances of this class.
* Method immediately returns with error code.
* @param item item
Expand Down Expand Up @@ -479,14 +496,18 @@ class DCMTK_DCMDATA_EXPORT DcmFileFormat
* Equals NULL if this data element is not existent in the meta header information.
* @param oxfer The transfer syntax which shall be used.
* @param writeMode flag indicating whether to update the file meta information or not
* @param implClassUID meta header tag for Implementation Class UID
* @param implVersionName meta header tag for Implementation Version Name
* @return EC_Normal if successful, an error code otherwise
*/
static OFCondition checkMetaHeaderValue(DcmMetaInfo *metainfo,
DcmDataset *dataset,
const DcmTagKey &atagkey,
DcmObject *obj,
const E_TransferSyntax oxfer,
const E_FileWriteMode writeMode);
const E_FileWriteMode writeMode,
const OFString& implClassUID = OFFIS_IMPLEMENTATION_CLASS_UID,
const OFString& implVersionName = OFFIS_DTK_IMPLEMENTATION_VERSION_NAME);

/** read DCM_TransferSyntaxUID from meta header dataset and return as E_TransferSyntax value
* @param metainfo meta-header dataset
Expand All @@ -496,6 +517,10 @@ class DCMTK_DCMDATA_EXPORT DcmFileFormat

/// file read mode, specifies whether to read the meta header or not
E_FileReadMode FileReadMode;

/// Meta header tags:
OFString m_implementationClassUID;
OFString m_implementationVersionName;
};


Expand Down
29 changes: 19 additions & 10 deletions dcmdata/libsrc/dcfilefo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@

DcmFileFormat::DcmFileFormat()
: DcmSequenceOfItems(DCM_InternalUseTag),
FileReadMode(ERM_autoDetect)
FileReadMode(ERM_autoDetect),
m_implementationClassUID(OFFIS_IMPLEMENTATION_CLASS_UID),
m_implementationVersionName(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME)
{
DcmMetaInfo *MetaInfo = new DcmMetaInfo();
DcmSequenceOfItems::itemList->insert(MetaInfo);
Expand All @@ -67,7 +69,9 @@ DcmFileFormat::DcmFileFormat()
DcmFileFormat::DcmFileFormat(DcmDataset *dataset,
OFBool deepCopy)
: DcmSequenceOfItems(DCM_InternalUseTag),
FileReadMode(ERM_autoDetect)
FileReadMode(ERM_autoDetect),
m_implementationClassUID(OFFIS_IMPLEMENTATION_CLASS_UID),
m_implementationVersionName(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME)
{
DcmMetaInfo *MetaInfo = new DcmMetaInfo();
DcmSequenceOfItems::itemList->insert(MetaInfo);
Expand All @@ -93,7 +97,9 @@ DcmFileFormat::DcmFileFormat(DcmDataset *dataset,

DcmFileFormat::DcmFileFormat(const DcmFileFormat &old)
: DcmSequenceOfItems(old),
FileReadMode(old.FileReadMode)
FileReadMode(old.FileReadMode),
m_implementationClassUID(old.m_implementationClassUID),
m_implementationVersionName(old.m_implementationVersionName)
{
}

Expand All @@ -120,6 +126,8 @@ DcmFileFormat &DcmFileFormat::operator=(const DcmFileFormat &obj)
{
DcmSequenceOfItems::operator=(obj);
FileReadMode = obj.FileReadMode;
m_implementationClassUID = obj.m_implementationClassUID;
m_implementationVersionName = obj.m_implementationVersionName;
}

return *this;
Expand Down Expand Up @@ -270,7 +278,9 @@ OFCondition DcmFileFormat::checkMetaHeaderValue(DcmMetaInfo *metainfo,
const DcmTagKey &atagkey,
DcmObject *obj,
const E_TransferSyntax oxfer,
const E_FileWriteMode writeMode)
const E_FileWriteMode writeMode,
const OFString& implClassUID,
const OFString& implVersionName)
/*
* This function checks if a particular data element of the file meta information header is
* existent. If the element is not existent, it will be inserted. Additionally, this function
Expand Down Expand Up @@ -469,8 +479,7 @@ OFCondition DcmFileFormat::checkMetaHeaderValue(DcmMetaInfo *metainfo,
}
if (elem->ident() == EVR_UI)
{
const char *uid = OFFIS_IMPLEMENTATION_CLASS_UID;
OFstatic_cast(DcmUniqueIdentifier *, elem)->putString(uid);
OFstatic_cast(DcmUniqueIdentifier *, elem)->putString(implClassUID.c_str());
}
}
else if (xtag == DCM_ImplementationVersionName) // (0002,0013)
Expand All @@ -482,8 +491,7 @@ OFCondition DcmFileFormat::checkMetaHeaderValue(DcmMetaInfo *metainfo,
}
if (elem->ident() == EVR_SH)
{
const char *uid = OFFIS_DTK_IMPLEMENTATION_VERSION_NAME;
OFstatic_cast(DcmShortString *, elem)->putString(uid);
OFstatic_cast(DcmShortString *, elem)->putString(implVersionName.c_str());
}
}
else if ((xtag == DCM_SourceApplicationEntityTitle) || // (0002,0016)
Expand Down Expand Up @@ -597,11 +605,12 @@ OFCondition DcmFileFormat::validateMetaInfo(const E_TransferSyntax oxfer,

/* DCM_ImplementationClassUID */
metinf->search(DCM_ImplementationClassUID, stack, ESM_fromHere, OFFalse);
checkMetaHeaderValue(metinf, datset, DCM_ImplementationClassUID, stack.top(), oxfer, writeMode);
checkMetaHeaderValue(metinf, datset, DCM_ImplementationClassUID, stack.top(), oxfer, writeMode, m_implementationClassUID);

/* DCM_ImplementationVersionName */
metinf->search(DCM_ImplementationVersionName, stack, ESM_fromHere, OFFalse);
checkMetaHeaderValue(metinf, datset, DCM_ImplementationVersionName, stack.top(), oxfer, writeMode);
checkMetaHeaderValue(metinf, datset, DCM_ImplementationVersionName, stack.top(), oxfer, writeMode,
m_implementationClassUID, m_implementationVersionName);

/* dump some information if required */
DCMDATA_DEBUG("DcmFileFormat::validateMetaInfo() found " << metinf->card() << " Elements in DcmMetaInfo 'metinf'");
Expand Down
14 changes: 12 additions & 2 deletions dcmnet/include/dcmtk/dcmnet/assoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,13 @@ struct DCMTK_DCMNET_EXPORT T_ASC_RejectParameters
T_ASC_RejectParametersReason reason;
};

struct DCMTK_DCMNET_EXPORT T_ASC_ImplementationIdentification
{
T_ASC_ImplementationIdentification();

DIC_UI ourImplementationClassUID;
DIC_SH ourImplementationVersionName;
};

struct DCMTK_DCMNET_EXPORT T_ASC_Parameters
{
Expand Down Expand Up @@ -295,7 +302,9 @@ DCMTK_DCMNET_EXPORT OFCondition
ASC_createAssociationParameters(
T_ASC_Parameters ** params,
long maxReceivePDUSize,
Sint32 tcpConnectTimeout);
Sint32 tcpConnectTimeout,
const T_ASC_ImplementationIdentification& implIdentification = T_ASC_ImplementationIdentification()
);

/*
* same as before, but uses value of the global dcmConnectionTimeout variable.
Expand Down Expand Up @@ -691,7 +700,8 @@ ASC_receiveAssociation(
unsigned long *associatePDUlength=NULL,
OFBool useSecureLayer=OFFalse,
DUL_BLOCKOPTIONS block=DUL_BLOCK,
int timeout=0);
int timeout=0,
const T_ASC_ImplementationIdentification& implIdentification = T_ASC_ImplementationIdentification());

DCMTK_DCMNET_EXPORT OFCondition
ASC_acknowledgeAssociation(
Expand Down
13 changes: 13 additions & 0 deletions dcmnet/include/dcmtk/dcmnet/scpcfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,16 @@ class DCMTK_DCMNET_EXPORT DcmSCPConfig
OFCondition checkAssociationProfile(const OFString &profileName,
OFString& mangledName) const;

/** Set an association implementation identification parameters
* @param impIndetification [in] Implementation Class UID and Implementation Version Name
*/
void setImplementationIdentification(const T_ASC_ImplementationIdentification& implIndetification);

/** Returns association implementation identification parameters
* @return Implementation Class UID and Implementation Version Name
*/
const T_ASC_ImplementationIdentification& getImplementationIdentification();

/** Force every association request to be refused by SCP, no matter what the SCU is
* offering
* @param doRefuse [in] If OFTrue, every association is being refused. DcmSCP's default
Expand Down Expand Up @@ -360,6 +370,9 @@ class DCMTK_DCMNET_EXPORT DcmSCPConfig
/// called "DEFAULT" is used.
OFString m_assocCfgProfileName;

/// Implementation Class UID and Implementation Version Name
T_ASC_ImplementationIdentification m_implIdentification;

/// Port on which the SCP is listening for association requests. The default port is 104.
Uint16 m_port;

Expand Down
8 changes: 8 additions & 0 deletions dcmnet/include/dcmtk/dcmnet/scu.h
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,11 @@ class DCMTK_DCMNET_EXPORT DcmSCU
*/
void setAssocConfigFileAndProfile(const OFString& filename, const OFString& profile);

/** Set an association implementation identification parameters
* @param implIndetification [in] Implementation Class UID and Implementation Version Name
*/
void setImplementationIdentification(const T_ASC_ImplementationIdentification& implIndetification);

/** Set the directory that should be used by the standard C-GET handler to store objects
* that come in with the corresponding C-STORE requests
* @param storeDir [in] The directory to store to. It is checked in handleSTORERequest()
Expand Down Expand Up @@ -1060,6 +1065,9 @@ class DCMTK_DCMNET_EXPORT DcmSCU
/// Configuration file containing association parameters
OFString m_assocConfigFile;

/// Implementation Class UID and Implementation Version Name
T_ASC_ImplementationIdentification m_implIdentification;

/// The last DIMSE successfully sent, unresponded DIMSE request
T_DIMSE_Message* m_openDIMSERequest;

Expand Down
34 changes: 23 additions & 11 deletions dcmnet/libsrc/assoc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,22 @@ typedef struct {
} T_ASC_ExtendedNegotiationItem;


T_ASC_ImplementationIdentification::T_ASC_ImplementationIdentification()
{
OFStandard::strlcpy(ourImplementationClassUID,
OFFIS_IMPLEMENTATION_CLASS_UID,
sizeof(ourImplementationClassUID));
OFStandard::strlcpy(ourImplementationVersionName,
OFFIS_DTK_IMPLEMENTATION_VERSION_NAME,
sizeof(ourImplementationVersionName));

if (strlen(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME) > 16)
{
DCMNET_WARN("DICOM implementation version name too long: " << OFFIS_DTK_IMPLEMENTATION_VERSION_NAME);
}
}


/*
** Function Bodies
*/
Expand Down Expand Up @@ -274,25 +290,20 @@ ASC_dropNetwork(T_ASC_Network ** network)
OFCondition
ASC_createAssociationParameters(T_ASC_Parameters ** params,
long maxReceivePDUSize,
Sint32 tcpConnectTimeout)
Sint32 tcpConnectTimeout,
const T_ASC_ImplementationIdentification& implIdentification)
{

*params = (T_ASC_Parameters *) malloc(sizeof(**params));
if (*params == NULL) return EC_MemoryExhausted;
memset((char*)*params, 0, sizeof(**params));

OFStandard::strlcpy((*params)->ourImplementationClassUID,
OFFIS_IMPLEMENTATION_CLASS_UID,
implIdentification.ourImplementationClassUID,
sizeof((*params)->ourImplementationClassUID));
OFStandard::strlcpy((*params)->ourImplementationVersionName,
OFFIS_DTK_IMPLEMENTATION_VERSION_NAME,
implIdentification.ourImplementationVersionName,
sizeof((*params)->ourImplementationVersionName));

if (strlen(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME) > 16)
{
DCMNET_WARN("DICOM implementation version name too long: " << OFFIS_DTK_IMPLEMENTATION_VERSION_NAME);
}

OFStandard::strlcpy((*params)->DULparams.callingImplementationClassUID,
(*params)->ourImplementationClassUID, DICOM_UI_LENGTH + 1);
OFStandard::strlcpy((*params)->DULparams.callingImplementationVersionName,
Expand Down Expand Up @@ -1756,7 +1767,8 @@ ASC_receiveAssociation(T_ASC_Network * network,
unsigned long *associatePDUlength,
OFBool useSecureLayer,
DUL_BLOCKOPTIONS block,
int timeout)
int timeout,
const T_ASC_ImplementationIdentification& implIdentification)
{
T_ASC_Parameters *params;
DUL_ASSOCIATIONKEY *DULassociation;
Expand All @@ -1766,7 +1778,7 @@ ASC_receiveAssociation(T_ASC_Network * network,
int retrieveRawPDU = 0;
if (associatePDU && associatePDUlength) retrieveRawPDU = 1;

OFCondition cond = ASC_createAssociationParameters(&params, maxReceivePDUSize, dcmConnectionTimeout.get());
OFCondition cond = ASC_createAssociationParameters(&params, maxReceivePDUSize, dcmConnectionTimeout.get(), implIdentification);
if (cond.bad()) return cond;

cond = ASC_setTransportLayerType(params, useSecureLayer);
Expand Down
3 changes: 2 additions & 1 deletion dcmnet/libsrc/scp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ OFCondition DcmSCP::waitForAssociationRQ(T_ASC_Network* network)
NULL,
useSecureLayer,
m_cfg->getConnectionBlockingMode(),
OFstatic_cast(int, timeout));
OFstatic_cast(int, timeout),
m_cfg->getImplementationIdentification());

// In case of a timeout in non-blocking mode, call notifier (and return
// to main event loop later)
Expand Down
14 changes: 14 additions & 0 deletions dcmnet/libsrc/scpcfg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ DcmSCPConfig::~DcmSCPConfig()
DcmSCPConfig::DcmSCPConfig(const DcmSCPConfig &old) :
m_assocConfig(old.m_assocConfig),
m_assocCfgProfileName(old.m_assocCfgProfileName),
m_implIdentification(old.m_implIdentification),
m_port(old.m_port),
m_aetitle(old.m_aetitle),
m_refuseAssociation(old.m_refuseAssociation),
Expand All @@ -81,6 +82,7 @@ DcmSCPConfig& DcmSCPConfig::operator=(const DcmSCPConfig &obj)
{
m_assocConfig = obj.m_assocConfig; // performs deep copy
m_assocCfgProfileName = obj.m_assocCfgProfileName;
m_implIdentification = obj.m_implIdentification;
m_port = obj.m_port;
m_aetitle = obj.m_aetitle;
m_refuseAssociation = obj.m_refuseAssociation;
Expand Down Expand Up @@ -399,6 +401,18 @@ OFCondition DcmSCPConfig::checkAssociationProfile(const OFString& profileName,
}


void DcmSCPConfig::setImplementationIdentification(const T_ASC_ImplementationIdentification& implIndetification)
{
m_implIdentification = implIndetification;
}


const T_ASC_ImplementationIdentification& DcmSCPConfig::getImplementationIdentification()
{
return m_implIdentification;
}


OFCondition DcmSCPConfig::addPresentationContext(const OFString &abstractSyntax,
const OFList<OFString> &xferSyntaxes,
const T_ASC_SC_ROLE role,
Expand Down
11 changes: 9 additions & 2 deletions dcmnet/libsrc/scppool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,15 @@ OFCondition DcmBaseSCPPool::listen()
OFBool useSecureLayer = m_cfg.transportLayerEnabled();

// Listen to a socket for timeout seconds for an association request, accepts TCP connection.
cond = ASC_receiveAssociation( network, &assoc, m_cfg.getMaxReceivePDULength(), NULL, NULL, useSecureLayer,
m_cfg.getConnectionBlockingMode(), OFstatic_cast(int, m_cfg.getConnectionTimeout()) );
cond = ASC_receiveAssociation(network,
&assoc,
m_cfg.getMaxReceivePDULength(),
NULL,
NULL,
useSecureLayer,
m_cfg.getConnectionBlockingMode(),
OFstatic_cast(int, m_cfg.getConnectionTimeout()),
m_cfg.getImplementationIdentification());

/* If we have a connection request, try to find/create a worker to handle it */
if (cond.good())
Expand Down
7 changes: 6 additions & 1 deletion dcmnet/libsrc/scu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ OFCondition DcmSCU::initNetwork()
}

/* initialize association parameters, i.e. create an instance of T_ASC_Parameters*. */
cond = ASC_createAssociationParameters(&m_params, m_maxReceivePDULength, m_tcpConnectTimeout);
cond = ASC_createAssociationParameters(&m_params, m_maxReceivePDULength, m_tcpConnectTimeout, m_implIdentification);
if (cond.bad())
{
DCMNET_ERROR(DimseCondition::dump(tempStr, cond));
Expand Down Expand Up @@ -2555,6 +2555,11 @@ void DcmSCU::setAssocConfigFileAndProfile(const OFString& filename, const OFStri
m_assocConfigProfile = profile;
}

void DcmSCU::setImplementationIdentification(const T_ASC_ImplementationIdentification& implIndetification)
{
m_implIdentification = implIndetification;
}

void DcmSCU::setStorageDir(const OFString& storeDir)
{
m_storageDir = storeDir;
Expand Down