OFCondition GIL::DICOM::DCMTK::Network::DropNetwork() { OFCondition cond = ASC_dropNetwork(&m_pDCMTKNetwork); m_pDCMTKNetwork = NULL; return cond; }
OFCondition Network::DropNetwork() { OFCondition cond = ASC_dropNetwork(&net); net = NULL; #ifdef _WIN32 WSACleanup(); #endif return cond; }
void DicomServer::Stop() { if (continue_) { continue_ = false; if (pimpl_->thread_.joinable()) { pimpl_->thread_.join(); } pimpl_->workers_.reset(NULL); /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */ /* is the counterpart of ASC_initializeNetwork(...) which was called above. */ OFCondition cond = ASC_dropNetwork(&pimpl_->network_); if (cond.bad()) { LOG(ERROR) << "Error while dropping the network: " << cond.text(); } } }
void PACSConnection::disconnect() { OFCondition condition = ASC_releaseAssociation(m_dicomAssociation); if (condition.bad()) { ERROR_LOG("No s'ha pogut desconnectar del PACS, descripcio error: " + QString(condition.text())); } condition = ASC_destroyAssociation(&m_dicomAssociation); if (condition.bad()) { ERROR_LOG("Error al destruir la connexio amb el PACS, descripcio error: " + QString(condition.text())); } // Destrueix l'objecte i tanca el socket obert, fins que no es fa el drop de l'objecte no es tanca el socket condition = ASC_dropNetwork(&m_associationNetwork); if (condition.bad()) { ERROR_LOG("Error al tancar el port de connexions entrants, descripcio error: " + QString(condition.text())); } }
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 ( ¶ms, 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; }
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; }
void DicomServer::ServerThread(DicomServer* server) { /* Disable "gethostbyaddr" (which results in memory leaks) and use raw IP addresses */ dcmDisableGethostbyaddr.set(OFTrue); dcmDataDict.clear(); DcmDataDictionary& d = dcmDataDict.wrlock(); #if DCMTK_USE_EMBEDDED_DICTIONARIES == 1 LOG(WARNING) << "Loading the embedded dictionaries"; /** * Do not load DICONDE dictionary, it breaks the other tags. The * command "strace storescu 2>&1 |grep dic" shows that DICONDE * dictionary is not loaded by storescu. **/ //LoadEmbeddedDictionary(d, EmbeddedResources::DICTIONARY_DICONDE); LoadEmbeddedDictionary(d, EmbeddedResources::DICTIONARY_DICOM); LoadEmbeddedDictionary(d, EmbeddedResources::DICTIONARY_PRIVATE); #elif defined(__linux) std::string path = "/usr/share/dcmtk"; const char* env = std::getenv(DCM_DICT_ENVIRONMENT_VARIABLE); if (env != NULL) { path = std::string(env); } LoadExternalDictionary(d, path, "dicom.dic"); LoadExternalDictionary(d, path, "private.dic"); #else #error Support your platform here #endif dcmDataDict.unlock(); /* make sure data dictionary is loaded */ if (!dcmDataDict.isDictionaryLoaded()) { LOG(ERROR) << "No DICOM dictionary loaded, check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE; throw OrthancException(ErrorCode_InternalError); } { // Test the dictionary with a simple DICOM tag DcmTag key(0x0010, 0x1030); // This is PatientWeight if (key.getEVR() != EVR_DS) { LOG(ERROR) << "The DICOM dictionary has not been correctly read"; throw OrthancException(ErrorCode_InternalError); } } /* initialize network, i.e. create an instance of T_ASC_Network*. */ T_ASC_Network *net; OFCondition cond = ASC_initializeNetwork (NET_ACCEPTOR, OFstatic_cast(int, server->port_), /*opt_acse_timeout*/ 30, &net); if (cond.bad()) { LOG(ERROR) << "cannot create network: " << cond.text(); throw OrthancException("Cannot create network"); } LOG(INFO) << "DICOM server started"; server->started_ = true; while (server->continue_) { /* receive an association and acknowledge or reject it. If the association was */ /* acknowledged, offer corresponding services and invoke one or more if required. */ std::auto_ptr<Internals::CommandDispatcher> dispatcher(Internals::AcceptAssociation(*server, net)); if (dispatcher.get() != NULL) { if (server->isThreaded_) { server->bagOfDispatchers_.Add(dispatcher.release()); } else { IRunnableBySteps::RunUntilDone(*dispatcher); } } } LOG(INFO) << "DICOM server stopping"; /* 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()) { LOG(ERROR) << "Error while dropping the network: " << cond.text(); } }