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(¶ms, 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; }
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(¶ms, 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; }
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(¶ms, 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); throw Exception("Unknown identity type"); } if(condition.bad()) { ASC_destroyAssociationParameters(¶ms); 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(¶ms); throw Exception(ASC_printRejectParameters(empty, &rej).c_str()); } else { ASC_destroyAssociationParameters(¶ms); throw Exception(DimseCondition::dump(empty, condition).c_str()); } } }
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(¶ms, 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; }