Ejemplo n.º 1
0
void FindAssociation::OnAddPresentationContext(T_ASC_Parameters* params)
{
        OFCondition cond = ASC_addPresentationContext(params, 1, m_abstractSyntax.c_str(), AllTransferSyntaxes, 3);
        if (cond.bad()) {
                LOG_ERROR(ambitolog, "Unable to add default presentation context");
        }
}
Ejemplo n.º 2
0
OFCondition PACSConnection::configureEcho()
{
    const char *transferSyntaxes[] = { UID_LittleEndianImplicitTransferSyntax };
    // PresentationContextID always has to be odd
    int presentationContextID = 1;

    return ASC_addPresentationContext(m_associationParameters, presentationContextID, UID_VerificationSOPClass, transferSyntaxes, DIM_OF(transferSyntaxes));
}
Ejemplo n.º 3
0
OFCondition Network::addAllStoragePresentationContexts(T_ASC_Parameters *params, bool bProposeCompression, int lossy)
{
    OFCondition cond = EC_Normal;
    int i;
    int pid = 1;

    /* 
    ** We prefer to accept Explicitly encoded transfer syntaxes.
    ** If we are running on a Little Endian machine we prefer 
    ** LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax.
    ** Some SCP implementations will just select the first transfer
    ** syntax they support (this is not part of the standard) so
    ** organise the proposed transfer syntaxes to take advantage
    ** of such behaviour.
    */

	const char** transferSyntaxes;
	int transferSyntaxes_count;
    const char* const_transferSyntaxes[] = {UID_JPEGProcess14SV1TransferSyntax, NULL, NULL, UID_LittleEndianImplicitTransferSyntax };

	if(bProposeCompression) {
		if(lossy == 8) {
			const_transferSyntaxes[0] = UID_JPEGProcess1TransferSyntax;
		}
		
		if(lossy == 12) {
			const_transferSyntaxes[0] = UID_JPEGProcess2_4TransferSyntax;
		}
	}
	
    /* gLocalByteOrder is defined in dcxfer.h */
    if (gLocalByteOrder == EBO_LittleEndian) {
		/* we are on a little endian machine */
		const_transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax;
		const_transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax;
    } else {
		/* we are on a big endian machine */
		const_transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax;
		const_transferSyntaxes[2] = UID_LittleEndianExplicitTransferSyntax;
    }

	if(bProposeCompression) {
		transferSyntaxes = &const_transferSyntaxes[0];
		transferSyntaxes_count = DIM_OF(const_transferSyntaxes);
	}
	else {
		transferSyntaxes = &const_transferSyntaxes[1];
		transferSyntaxes_count = DIM_OF(const_transferSyntaxes)-1;
	}

	/* the array of Storage SOP Class UIDs comes from dcuid.h */
	for (i=0; i<numberOfAllDcmStorageSOPClassUIDs && cond.good(); i++) {
		cond = ASC_addPresentationContext(params, pid, dcmAllStorageSOPClassUIDs[i], transferSyntaxes, transferSyntaxes_count);
		pid += 2;	/* only odd presentation context id's */
	}

    return cond;
}
Ejemplo n.º 4
0
OFCondition PACSConnection::configureMove()
{
    T_ASC_PresentationContextID associationPresentationContextID = 1;
    const char *transferSyntaxes[] = { NULL, NULL, NULL };

    getTransferSyntaxForFindOrMoveConnection(transferSyntaxes);

    return ASC_addPresentationContext(m_associationParameters, associationPresentationContextID, UID_MOVEStudyRootQueryRetrieveInformationModel,
                                      transferSyntaxes, 3 /*number of TransferSyntaxes*/);
}
Ejemplo n.º 5
0
OFCondition PACSConnection::configureFind()
{
    const char *transferSyntaxes[] = { NULL, NULL, NULL };
    // Sempre ha de ser imparell, el seu valor és 1 perquè només passem un presentation context
    int presentationContextID = 1;

    getTransferSyntaxForFindOrMoveConnection(transferSyntaxes);

    return ASC_addPresentationContext(m_associationParameters, presentationContextID, UID_FINDStudyRootQueryRetrieveInformationModel, transferSyntaxes,
        DIM_OF(transferSyntaxes));
}
Ejemplo n.º 6
0
OFCondition PACSConnection::addPresentationContext(int presentationContextId, const QString &abstractSyntax, QList<const char*> transferSyntaxList)
{
    // Create an array of supported/possible transfer syntaxes
    const char **transferSyntaxes = new const char*[transferSyntaxList.size()];
    int transferSyntaxCount = 0;

    foreach (const char *transferSyntax, transferSyntaxList)
    {
        transferSyntaxes[transferSyntaxCount++] = transferSyntax;
    }

    OFCondition condition = ASC_addPresentationContext(m_associationParameters, presentationContextId, qPrintable(abstractSyntax), transferSyntaxes,
        transferSyntaxCount, ASC_SC_ROLE_DEFAULT);

    delete[] transferSyntaxes;
    return condition;
}
Ejemplo n.º 7
0
OFCondition Association::addAllStoragePresentationContexts(T_ASC_Parameters *params, bool /*bProposeCompression*/, int /*lossy*/)
{
        unsigned int pid = 1;

        OFCondition cond = ASC_addPresentationContext(params, pid, m_abstractSyntax.c_str(), AllTransferSyntaxes, 3);
        if (cond.bad()) {
                LOG_ERROR(ambitolog, "Unable to add presentation context for " << m_abstractSyntax);
                return cond;
        }

        pid += 2;

        if (pid >= 255) {
                LOG_WARN(ambitolog, "Too many PresentationContexts setted");
        }

        return cond;
}
Ejemplo n.º 8
0
OFCondition Network::ASC_ConnectAssociation(Association* assoc, const std::string& peerTitle, const std::string& peer, int port, const std::string& ouraet, const char *abstractSyntax, int lossy)
{
    OFCondition cond;
    T_ASC_Parameters *params;
	bool bProposeCompression = assoc->GetProposeCompression();

	DIC_NODENAME peerHost;
    DIC_NODENAME localHost;

    cond = ASC_createAssociationParameters(&params, ASC_DEFAULTMAXPDU);
    if (!cond.good())
	{
		return cond;
    }
    ASC_setAPTitles(params, ouraet.c_str(), peerTitle.c_str(), NULL);

    gethostname(localHost, sizeof(localHost) - 1);
    snprintf(peerHost, sizeof(peerHost), "%s:%d", peer.c_str(), port);
    ASC_setPresentationAddresses(params, localHost, peerHost);

	if(abstractSyntax == NULL)
	{
		cond = addAllStoragePresentationContexts(params, bProposeCompression, lossy);
		if (!cond.good())
		{
			return cond;
		}
	}
	else
	{
		const char** transferSyntaxes;
		int transferSyntaxes_count;
		const char* const_transferSyntaxes[] = { UID_LittleEndianExplicitTransferSyntax, UID_BigEndianExplicitTransferSyntax, UID_LittleEndianImplicitTransferSyntax };

		transferSyntaxes = &const_transferSyntaxes[0];
		transferSyntaxes_count = DIM_OF(const_transferSyntaxes);

/*		const char* const_transferSyntaxes[] = { UID_JPEGProcess14SV1TransferSyntax, UID_LittleEndianExplicitTransferSyntax, UID_BigEndianExplicitTransferSyntax, UID_LittleEndianImplicitTransferSyntax };
		if(bProposeCompression) {
			if(lossy == 8) {
				const_transferSyntaxes[0] = UID_JPEGProcess1TransferSyntax;
			}
			if(lossy == 12) {
				const_transferSyntaxes[0] = UID_JPEGProcess2_4TransferSyntax;
			}
		}
		const_transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax;
		const_transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax;

		if(bProposeCompression) {
			transferSyntaxes = &const_transferSyntaxes[0];
			transferSyntaxes_count = DIM_OF(const_transferSyntaxes);
		}
		else {
			transferSyntaxes = &const_transferSyntaxes[1];
			transferSyntaxes_count = DIM_OF(const_transferSyntaxes)-1;
		}*/
	
		cond = ASC_addPresentationContext(params, 1, abstractSyntax, transferSyntaxes, transferSyntaxes_count);
		assoc->OnAddPresentationContext(params, transferSyntaxes, transferSyntaxes_count);
	}


    /* create association */
    cond = ASC_requestAssociation(net, params, &(assoc->assoc));
    if (cond != EC_Normal)
	{
		if (cond == DUL_ASSOCIATIONREJECTED)
		{
			T_ASC_RejectParameters rej;

			ASC_getRejectParameters(params, &rej);
			ASC_printRejectParameters(stderr, &rej);
			return cond;
		}
		else
		{
			return cond;
		}
    }

    /* what has been accepted/refused ? */

    if (ASC_countAcceptedPresentationContexts(params) == 0) 
	{
		return cond;
    }

	return EC_Normal;
}
Ejemplo n.º 9
0
void
Association
::associate(Network & network)
{
    if(!network.is_initialized())
    {
        throw Exception("Network is not initialized");
    }

    if(this->is_associated())
    {
        throw Exception("Already associated");
    }

    OFCondition condition;

    T_ASC_Parameters * params;
    condition = ASC_createAssociationParameters(&params, ASC_MAXIMUMPDUSIZE);
    if(condition.bad())
    {
        throw Exception(condition);
    }

    condition = ASC_setAPTitles(params,
        this->_own_ae_title.c_str(), this->_peer_ae_title.c_str(), NULL);
    if(condition.bad())
    {
        ASC_destroyAssociationParameters(&params);
        throw Exception(condition);
    }

    std::string localhost(128, '\0');
    gethostname(&localhost[0], localhost.size()-1);

    std::ostringstream peer;
    peer << this->_peer_host_name << ":" << this->_peer_port;

    condition = ASC_setPresentationAddresses(params,
        "localhost", peer.str().c_str());
    if(condition.bad())
    {
        ASC_destroyAssociationParameters(&params);
        throw Exception(condition);
    }

    unsigned int context_id = 1;
    for(auto const & context: this->_presentation_contexts)
    {
        char const ** transfer_syntaxes = new char const *[context.transfer_syntaxes.size()];
        for(std::size_t i = 0; i < context.transfer_syntaxes.size(); ++i)
        {
            transfer_syntaxes[i] = context.transfer_syntaxes[i].c_str();
        }

        condition = ASC_addPresentationContext(params,
            context_id, context.abstract_syntax.c_str(),
            transfer_syntaxes, context.transfer_syntaxes.size(), context.role);
        if(condition.bad())
        {
            ASC_destroyAssociationParameters(&params);
            throw Exception(condition);
        }

        context_id += 2;
    }

    if(this->_user_identity_type == UserIdentityType::None)
    {
        // Nothing to do.
    }
    else if(this->_user_identity_type == UserIdentityType::Username)
    {
        condition = ASC_setIdentRQUserOnly(params,
            this->_user_identity_primary_field.c_str());
    }
    else if(this->_user_identity_type == UserIdentityType::UsernameAndPassword)
    {
        condition = ASC_setIdentRQUserOnly(params,
            this->_user_identity_primary_field.c_str(),
            this->_user_identity_secondary_field.c_str());
    }
    else if(this->_user_identity_type == UserIdentityType::Kerberos)
    {
        condition = ASC_setIdentRQKerberos(params,
            this->_user_identity_primary_field.c_str(),
            this->_user_identity_primary_field.size());
    }
    else if(this->_user_identity_type == UserIdentityType::SAML)
    {
        condition = ASC_setIdentRQSaml(params,
            this->_user_identity_primary_field.c_str(),
            this->_user_identity_primary_field.size());
    }
    else
    {
        ASC_destroyAssociationParameters(&params);
        throw Exception("Unknown identity type");
    }

    if(condition.bad())
    {
        ASC_destroyAssociationParameters(&params);
        throw Exception(condition);
    }

    condition = ASC_requestAssociation(
        network.get_network(), params, &this->_association);
    if(condition.bad())
    {
        OFString empty;

        if(condition == DUL_ASSOCIATIONREJECTED)
        {
            T_ASC_RejectParameters rej;
            ASC_getRejectParameters(params, &rej);

            ASC_destroyAssociationParameters(&params);
            throw Exception(ASC_printRejectParameters(empty, &rej).c_str());
        }
        else
        {
            ASC_destroyAssociationParameters(&params);
            throw Exception(DimseCondition::dump(empty, condition).c_str());
        }
    }
}
Ejemplo n.º 10
0
// TODO Estudiar si el millor transferSyntax per defecte és UID_LittleEndianExplicitTransferSyntax o com els cas del move és el JPegLossLess
OFCondition PACSConnection::configureStore()
{
    // Each SOP Class will be proposed in two presentation contexts (unless the opt_combineProposedTransferSyntaxes global variable is true).
    // The command line specified a preferred transfer syntax to use. This prefered transfer syntax will be proposed in one presentation context
    // and a set of alternative (fallback) transfer syntaxes will be proposed in a different presentation context.

    // Generally, we prefer to use Explicitly encoded transfer syntaxes and if running on a Little Endian machine we prefer LittleEndianExplicitTransferSyntax
    // to BigEndianTransferSyntax. Some SCP implementations will just select the first transfer syntax they support (this is not part of the standard) so
    // organise the proposed transfer syntaxes to take advantage of such behaviour.

    /// Indiquem que con Transfer syntax preferida volem utilitzar JpegLossless
    const char *preferredTransferSyntax = UID_JPEGProcess14SV1TransferSyntax;

    QList<const char*> fallbackSyntaxes;
    fallbackSyntaxes.append(UID_LittleEndianExplicitTransferSyntax);
    fallbackSyntaxes.append(UID_BigEndianExplicitTransferSyntax);
    fallbackSyntaxes.append(UID_LittleEndianImplicitTransferSyntax);

    // Afegim totes les classes SOP de transfarència d'imatges. com que desconeixem de quina modalitat són
    // les imatges alhora de preparar la connexió les hi incloem totes les modalitats. Si alhora de connectar sabèssim de quina modalitat és
    // l'estudi només caldria afegir-hi la de la motalitat de l'estudi

    // Les sopClass o també conegudes com AbstractSyntax és equivalent amb el Move quina acció volem fer per exemple
    // UID_MOVEStudyRootQueryRetrieveInformationModel, en el case del move, en el cas de StoreScu, el sopClass que tenim van en funció del tipus d'imatge
    // per exemple tenim ComputedRadiographyImageStorage, CTImageStore, etc.. aquestes sopClass indiquen  quin tipus d'imatge anirem a guardar, per això sinó
    // sabem de quin tipus de SOPClass són les imatges que anem a guardar al PACS, li indiquem una llista per defecte que cobreix la gran majoria i més
    // comuns de SOPClass que existeixen

    // Amb l'Abstract syntax o SOPClass definim quina operació volem fer, i amb els transfer syntax indiquem amb quin protocol es farà
    // la transfarència de les dades, LittleEndian, JPegLossLess, etc..

    // TODO Si que la podem arribar a saber la transfer syntax, només hem de mirar la SOPClassUID de cada imatge a enviar, mirar
    // codi storescu.cc a partir de la línia 639
    QStringList sopClasses;
    for (int i = 0; i < numberOfDcmShortSCUStorageSOPClassUIDs; i++)
    {
        // Comprovem que no hi hagi que cap SOPClas duplicada
        if (!sopClasses.contains(QString(dcmShortSCUStorageSOPClassUIDs[i])))
        {
            sopClasses.append(QString(dcmShortSCUStorageSOPClassUIDs[i]));
        }
    }

    OFCondition condition = EC_Normal;
    int presentationContextID = 1;

    // Creem un presentation context per cada SOPClass que tinguem, indicant per cada SOPClass quina transfer syntax utilitzarem
    // En el cas del Store amb el presentation Context indiquem que per cada tipus d'imatge que volem guardar SOPClass amb quins
    // transfer syntax ens podem comunicar, llavors el PACS ens indicarà si ell pot guardar aquest tipus de SOPClass, i amb quin
    // transfer syntax li hem d'enviar la imatge

    foreach (const QString &sopClass, sopClasses)
    {
        // No poden haver més de 255 presentation context
        if (presentationContextID > 255)
        {
            return ASC_BADPRESENTATIONCONTEXTID;
        }

        // Sop class with preferred transfer syntax
        condition = ASC_addPresentationContext(m_associationParameters, presentationContextID, qPrintable(sopClass), &preferredTransferSyntax, 1,
                                               ASC_SC_ROLE_DEFAULT);
        // Only odd presentation context id's
        presentationContextID += 2;
        if (!condition.good())
        {
            break;
        }

        if (fallbackSyntaxes.size() > 0)
        {
            if (presentationContextID > 255)
            {
                return ASC_BADPRESENTATIONCONTEXTID;
            }

            // Sop class with fallback transfer syntax
            condition = addPresentationContext(presentationContextID, sopClass, fallbackSyntaxes);
            // Only odd presentation context id's
            presentationContextID += 2;
            if (!condition.good())
            {
                break;
            }
        }
    }

    return condition;
}
void QtDcmServersDicomSettingsWidget::sendEcho()
{
    if ( !treeWidget->currentItem() ) {
        return;
    }

    QtDcmPreferences* prefs = QtDcmPreferences::instance();
    
    const QString aet = prefs->aetitle();
    const QString serverAet = treeWidget->currentItem()->data ( 1, 1 ).toString();
    const QString hostname = prefs->hostname();
    const QString serverHostname = treeWidget->currentItem()->data ( 3, 1 ).toString();
    const QString serverPort = treeWidget->currentItem()->data ( 2, 1 ).toString();

    T_ASC_Network *net = 0; // network struct, contains DICOM upper layer FSM etc.

    OFCondition cond = ASC_initializeNetwork ( NET_REQUESTOR, 0, 30 /* timeout */, &net );
    if ( cond != EC_Normal ) {
        QMessageBox msgBox( QApplication::activeWindow() );
        msgBox.setIcon ( QMessageBox::Critical );
        msgBox.setText ( "Cannot initialize network" );
        msgBox.exec();
        
        ASC_dropNetwork ( &net );
        
        return;
    }

    QTcpSocket * socket = new QTcpSocket(this);
    socket->connectToHost(serverHostname, serverPort.toInt());
    if (!socket->waitForConnected(1000)) {
        QMessageBox msgBox( QApplication::activeWindow() );
        msgBox.setIcon ( QMessageBox::Information );
        msgBox.setText ( "Cannot connect to server " + serverHostname + " on port " + serverPort + " !" );
        msgBox.exec();
        
        ASC_dropNetwork ( &net );
        
        return;
    }
    
    socket->disconnectFromHost();
    delete socket;
    
    T_ASC_Parameters *params; // parameters of association request

    cond = ASC_createAssociationParameters ( &params, ASC_DEFAULTMAXPDU );

    // set calling and called AE titles
    cond = ASC_setAPTitles ( params, aet.toUtf8().data(), serverAet.toUtf8().data(), NULL );

    // the DICOM server accepts connections at server.nowhere.com port 104
    cond = ASC_setPresentationAddresses ( params, hostname.toUtf8().data(), QString ( serverHostname + ":" + serverPort ).toLatin1().data() );

    // list of transfer syntaxes, only a single entry here
    const char* ts[] = { UID_LittleEndianImplicitTransferSyntax };

    // add presentation context to association request
    cond = ASC_addPresentationContext ( params, 1, UID_VerificationSOPClass, ts, 1 );

    // request DICOM association
    T_ASC_Association *assoc = 0;

    if ( ASC_requestAssociation ( net, params, &assoc ).good() ) {
        if ( ASC_countAcceptedPresentationContexts ( params ) == 1 ) {
            // the remote SCP has accepted the Verification Service Class
            DIC_US id = assoc->nextMsgID++; // generate next message ID
            DIC_US status; // DIMSE status of C-ECHO-RSP will be stored here
            DcmDataset *sd = NULL; // status detail will be stored here
            // send C-ECHO-RQ and handle response
            DIMSE_echoUser ( assoc, id, DIMSE_BLOCKING, 0, &status, &sd );
            delete sd; // we don't care about status detail
            
            QMessageBox msgBox( QApplication::activeWindow() );
            msgBox.setIcon ( QMessageBox::Information );
            msgBox.setText ( "Echo request successful !" );
            msgBox.exec();
        }
        else {
            QMessageBox msgBox( QApplication::activeWindow() );
            msgBox.setIcon ( QMessageBox::Critical );
            msgBox.setText ( "Wrong presentation context, echo request failed" );
            msgBox.exec();
        }
    }
    else {
        QMessageBox msgBox( QApplication::activeWindow() );
        msgBox.setIcon ( QMessageBox::Critical );
        msgBox.setText ( "Wrong dicom association, echo request failed" );
        msgBox.exec();
    }

    ASC_releaseAssociation ( assoc ); // release association
    ASC_destroyAssociation ( &assoc ); // delete assoc structure
    ASC_dropNetwork ( &net ); // delete net structure
    
    net = 0;
    assoc = 0;
}
Ejemplo n.º 12
0
bool echoscu(const QString &peerTitle, const QString &ourTitle,
             const QString &hostname, int port,
             QString &msg)
{
    T_ASC_Network *net;
    T_ASC_Parameters *params;
    T_ASC_Association *assoc;
    OFString temp_str;
    bool ret = false;

#ifdef HAVE_WINSOCK_H
    WSAData winSockData;
    /* we need at least version 1.1 */
    WORD winSockVersionNeeded = MAKEWORD( 1, 1 );
    WSAStartup(winSockVersionNeeded, &winSockData);
#endif

    /* initialize network, i.e. create an instance of T_ASC_Network*. */
    OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, 6, &net);
    if (cond.bad()) {
        DimseCondition::dump(temp_str, cond);
        msg = QString::fromLatin1(temp_str.c_str());
        goto cleanup;
    }

    /* initialize asscociation parameters, i.e. create an instance of T_ASC_Parameters*. */
    cond = ASC_createAssociationParameters(&params, ASC_DEFAULTMAXPDU);
    if (cond.bad()) {
        DimseCondition::dump(temp_str, cond);
        msg = QString::fromLatin1(temp_str.c_str());
        goto cleanup;
    }

    ASC_setAPTitles(params, ourTitle.toLocal8Bit().data(), peerTitle.toLocal8Bit().data(), NULL);

    /* Set the transport layer type (type of network connection) in the params */
    /* strucutre. The default is an insecure connection; where OpenSSL is  */
    /* available the user is able to request an encrypted,secure connection. */
    cond = ASC_setTransportLayerType(params, OFFalse);
    if (cond.bad()) {
        DimseCondition::dump(temp_str, cond);
        msg = QString::fromLatin1(temp_str.c_str());
        goto cleanup;
    }

    /* Figure out the presentation addresses and copy the */
    /* corresponding values into the association parameters.*/
    DIC_NODENAME localHost;
    DIC_NODENAME peerHost;
    gethostname(localHost, sizeof(localHost) - 1);
    sprintf(peerHost, "%s:%d", hostname.toLocal8Bit().data(), port);

    ASC_setPresentationAddresses(params, localHost, peerHost);

    /* Set the presentation contexts which will be negotiated */
    /* when the network connection will be established */
    int presentationContextID = 1; /* odd byte value 1, 3, 5, .. 255 */
    for (unsigned long ii=0; ii<1; ii++)
    {
        cond = ASC_addPresentationContext(params, presentationContextID, UID_VerificationSOPClass,
                 transferSyntaxes, 3);
        presentationContextID += 2;
        if (cond.bad())
        {
            DimseCondition::dump(temp_str, cond);
            msg = QString::fromLatin1(temp_str.c_str());
            goto cleanup;
        }
    }

    /* create association, i.e. try to establish a network connection to another */
    /* DICOM application. This call creates an instance of T_ASC_Association*. */
    cond = ASC_requestAssociation(net, params, &assoc);
    if (cond.bad()) {
        if (cond == DUL_ASSOCIATIONREJECTED)
        {
            T_ASC_RejectParameters rej;

            ASC_getRejectParameters(params, &rej);
            ASC_printRejectParameters(temp_str, &rej);
            msg = QString("Association Rejected: %1").arg(temp_str.c_str());
            goto cleanup;
        } else {
            DimseCondition::dump(temp_str, cond);
            msg = QString("Association Request Failed: %1").arg(temp_str.c_str());
            goto cleanup;
        }
    }

    /* count the presentation contexts which have been accepted by the SCP */
    /* If there are none, finish the execution */
    if (ASC_countAcceptedPresentationContexts(params) == 0) {
        msg = QString("No Acceptable Presentation Contexts");
        goto cleanup;
    }

    /* do the real work, i.e. send a number of C-ECHO-RQ messages to the DICOM application */
    /* this application is connected with and handle corresponding C-ECHO-RSP messages. */
    DIC_US msgId = assoc->nextMsgID++;
    DIC_US status;
    DcmDataset *statusDetail = NULL;

    /* send C-ECHO-RQ and handle response */
    cond = DIMSE_echoUser(assoc, msgId, DIMSE_BLOCKING, 0, &status, &statusDetail);

    /* check for status detail information, there should never be any */
    if (statusDetail != NULL) {
        delete statusDetail;
    }

    /* tear down association, i.e. terminate network connection to SCP */
    if (cond == EC_Normal)
    {
        cond = ASC_releaseAssociation(assoc);
        ret = true;
    }
    else if (cond == DUL_PEERABORTEDASSOCIATION)
    {

    }
    else
    {
        DimseCondition::dump(temp_str, cond);
        msg = QString::fromLatin1(temp_str.c_str());
        cond = ASC_abortAssociation(assoc);
    }

cleanup:
    /* destroy the association, i.e. free memory of T_ASC_Association* structure. This */
    /* call is the counterpart of ASC_requestAssociation(...) which was called above. */
    cond = ASC_destroyAssociation(&assoc);

    /* 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);

#ifdef HAVE_WINSOCK_H
    WSACleanup();
#endif

    return ret;
}