bool PACSConnection::connectToPACS(PACSServiceToRequest pacsServiceToRequest)
{
    // Hi ha invocacions de mètodes de dcmtk que no se'ls hi comprova el condition que retornen, perquè se'ls hi ha mirat el codi i sempre retornen EC_NORMAL
    Settings settings;

    // Create the parameters of the connection
    OFCondition condition = ASC_createAssociationParameters(&m_associationParameters, ASC_DEFAULTMAXPDU);
    if (!condition.good())
    {
        ERROR_LOG("Error al crear els parametres de l'associacio, descripcio error: " + QString(condition.text()));
        return false;
    }

    // Set calling and called AE titles
    ASC_setAPTitles(m_associationParameters, qPrintable(settings.getValue(InputOutputSettings::LocalAETitle).toString()), qPrintable(m_pacs.getAETitle()),
                    NULL);

    // Defineix el nivell de seguretat de la connexió en aquest cas diem que no utilitzem cap nivell de seguretat
    ASC_setTransportLayerType(m_associationParameters, OFFalse);

    ASC_setPresentationAddresses(m_associationParameters, qPrintable(QHostInfo::localHostName()),
        qPrintable(constructPacsServerAddress(pacsServiceToRequest, m_pacs)));

    // Especifiquem el timeout de connexió, si amb aquest temps no rebem resposta donem error per time out
    dcmConnectionTimeout.set(settings.getValue(InputOutputSettings::PACSConnectionTimeout).toInt());

    switch (pacsServiceToRequest)
    {
        case Echo:
            condition = configureEcho();
            break;
        case Query:
            condition = configureFind();
            break;
        case RetrieveDICOMFiles:
            condition = configureMove();
            break;
        case SendDICOMFiles:
            condition = configureStore();
            break;
    }

    if (!condition.good())
    {
        ERROR_LOG("S'ha produit un error al configurar la connexio. AE Title: " + m_pacs.getAETitle() + ", adreca: " +
            constructPacsServerAddress(pacsServiceToRequest, m_pacs) + ". Descripcio error: " + QString(condition.text()));
        return false;
    }

    // Inicialitzem l'objecte network però la connexió no s'obre fins a l'invocacació del mètode ASC_requestAssociation
    m_associationNetwork = initializeAssociationNetwork(pacsServiceToRequest);

    if (m_associationNetwork == NULL)
    {
        ERROR_LOG("S'ha produit un error inicialitzant els parametres de la connexio. AE Title: " + m_pacs.getAETitle() + ", adreca: " +
            constructPacsServerAddress(pacsServiceToRequest, m_pacs));
        return false;
    }

    // Intentem connectar
    condition = ASC_requestAssociation(m_associationNetwork, m_associationParameters, &m_dicomAssociation);

    if (condition.good())
    {
        if (ASC_countAcceptedPresentationContexts(m_associationParameters) == 0)
        {
            ERROR_LOG("El PACS no ens ha acceptat cap dels Presentation Context presentats. AE Title: " + m_pacs.getAETitle() + ", adreca: " +
                constructPacsServerAddress(pacsServiceToRequest, m_pacs));
            return false;
        }
    }
    else
    {
        ERROR_LOG("S'ha produit un error al intentar connectar amb el PACS. AE Title: " + m_pacs.getAETitle() + ", adreca: " +
            constructPacsServerAddress(pacsServiceToRequest, m_pacs) + ". Descripcio error: " + QString(condition.text()));

        // Si no hem pogut connectar al PACS i és una descàrrega haurem obert el port per rebre connexions entrants DICOM, com no que podrem descarregar
        // les imatges perquè no hem pogut connectar amb el PACS per sol·licitar-ne la descarrega, tanquem el port local que espera per connexions entrants.
        if (pacsServiceToRequest == RetrieveDICOMFiles)
        {
            disconnect();
        }

        return false;
    }

    return true;
}
Exemple #2
0
OFCondition GIL::DICOM::DCMTK::Network::ASC_ConnectAssociation(Association* assoc, const std::string& peerTitle, const std::string& peer, int port, const std::string& ouraet, int pdu)
{
    OFCondition cond;

    GTLSTransportLayer *tLayer = NULL;

    if (assoc->IsSecure()) {
        tLayer = new GTLSTransportLayer(DICOM_APPLICATION_REQUESTOR, NULL);
        if (tLayer == NULL) {
            return makeOFCondition(OFM_dcmtls, DULC_TLSERROR, OF_error, "TLS Error: Unable to create TLS transport layer");
        }
        tLayer->setCertificateFromString(assoc->GetCliCert());
        tLayer->setPrivateKeyFromString(assoc->GetCliKey());

        if (! tLayer->checkPrivateKeyMatchesCertificate()) {
            delete tLayer;
            return makeOFCondition(OFM_dcmtls, DULC_TLSERROR, OF_error, "TLS Error: Private key and certificate do not match");
        }

        tLayer->addSystemTrustedCertificates();

        if (assoc->GetValidate()) {
            tLayer->setCertificateVerification(DCV_requireCertificate);
        } else {
            tLayer->setCertificateVerification(DCV_ignoreCertificate);
        }
        /*
         if (opt_dhparam && ! (tLayer->setTempDHParameters(opt_dhparam)))
         {
         LOG_WARN(assoc->ambitolog, "unable to load temporary DH parameters. Ignoring");
         }
         */

        cond = ASC_setTransportLayer(m_pDCMTKNetwork, tLayer, 0);
        if (cond.bad()) {
            return cond;
        }
    }

    T_ASC_Parameters *params;

    std::string peerHost;
    char localHost[129];

    cond = ASC_createAssociationParameters(&params, pdu);
    if (!cond.good()) {
        return cond;
    }

    //user identity
    if (assoc->UseUserPass()) {
        cond = ASC_setIdentRQUserPassword(params, assoc->GetUser().c_str(), assoc->GetPass().c_str());
        if (!cond.good()) {
            return cond;
        }
    }

    ASC_setAPTitles(params, ouraet.c_str(), peerTitle.c_str(), NULL);

    cond = ASC_setTransportLayerType(params, assoc->IsSecure());
    if (cond.bad()) {
        return cond;
    }

    gethostname(localHost, sizeof (localHost) - 1);
    {
        std::ostringstream os;
        os << peer.c_str() << ":" << port;
        peerHost = os.str();
    }
    ASC_setPresentationAddresses(params, localHost, peerHost.c_str());

    assoc->OnAddPresentationContext(params);

    {
        OFString str;
        ASC_dumpParameters(str, params, ASC_ASSOC_RQ);
        LOG_DEBUG(assoc->ambitolog, "Requesting association" << std::endl << str.c_str());

    }

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

            ASC_getRejectParameters(params, &rej);
            OFString str;
            ASC_printRejectParameters(str, &rej);
            return makeOFCondition(OFM_dcmnet, DULC_ASSOCIATIONREJECTED, OF_error, str.c_str());
        } else {
            return cond;
        }
    }

    {
        OFString str;
        ASC_dumpParameters(str, params, ASC_ASSOC_AC);
        LOG_DEBUG(assoc->ambitolog, "Association accepted" << std::endl << str.c_str());
    }

    /* what has been accepted/refused ? */

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

    return EC_Normal;
}
Exemple #3
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;
}