Esempio n. 1
0
OFCondition Association::Drop(OFCondition cond) {
	// tear down association
	if(cond == EC_Normal) {
		/* release association */
		cond = ASC_releaseAssociation(assoc);
	}
	else if(cond == DUL_PEERREQUESTEDRELEASE) {
		cond = ASC_abortAssociation(assoc);
		if (cond.good()) {
			return cond;
		}
	}
	else if(cond == DUL_PEERABORTEDASSOCIATION) {
		return cond;
	}
	else {
		cond = ASC_abortAssociation(assoc);
		if (cond.good()) {
			return cond;
		}
	}

	Destroy();
	return cond;
}
Esempio n. 2
0
void
Association
::abort()
{
    if(!this->is_associated())
    {
        throw Exception("Not associated");
    }

    ASC_abortAssociation(this->_association);
    ASC_destroyAssociation(&this->_association);
    this->_association = NULL;
}
Esempio n. 3
0
    bool CommandDispatcher::Step()
    /*
     * This function receives DIMSE commmands over the network connection
     * and handles these commands correspondingly. Note that in case of
     * storscp only C-ECHO-RQ and C-STORE-RQ commands can be processed.
     */
    {
      bool finished = false;

      // receive a DIMSE command over the network, with a timeout of 1 second
      DcmDataset *statusDetail = NULL;
      T_ASC_PresentationContextID presID = 0;
      T_DIMSE_Message msg;

      OFCondition cond = DIMSE_receiveCommand(assoc_, DIMSE_NONBLOCKING, 1, &presID, &msg, &statusDetail);
      elapsedTimeSinceLastCommand_++;
    
      // if the command which was received has extra status
      // detail information, dump this information
      if (statusDetail != NULL)
      {
        //LOG4CPP_WARN(Internals::GetLogger(), "Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail));
        delete statusDetail;
      }

      if (cond == DIMSE_OUTOFRESOURCES)
      {
        finished = true;
      }
      else if (cond == DIMSE_NODATAAVAILABLE)
      {
        // Timeout due to DIMSE_NONBLOCKING
        if (clientTimeout_ != 0 && 
            elapsedTimeSinceLastCommand_ >= clientTimeout_)
        {
          // This timeout is actually a client timeout
          finished = true;
        }
      }
      else if (cond == EC_Normal)
      {
        // Reset the client timeout counter
        elapsedTimeSinceLastCommand_ = 0;

        // in case we received a valid message, process this command
        // note that storescp can only process a C-ECHO-RQ and a C-STORE-RQ
        switch (msg.CommandField)
        {
        case DIMSE_C_ECHO_RQ:
          // process C-ECHO-Request
          cond = EchoScp(assoc_, &msg, presID);
          break;

        case DIMSE_C_STORE_RQ:
          // process C-STORE-Request
          if (server_.HasStoreRequestHandlerFactory())
          {
            std::auto_ptr<IStoreRequestHandler> handler
              (server_.GetStoreRequestHandlerFactory().ConstructStoreRequestHandler());
            cond = Internals::storeScp(assoc_, &msg, presID, *handler);
          }
          else
            cond = DIMSE_BADCOMMANDTYPE;  // Should never happen
          break;

        case DIMSE_C_MOVE_RQ:
          // process C-MOVE-Request
          if (server_.HasMoveRequestHandlerFactory())
          {
            std::auto_ptr<IMoveRequestHandler> handler
              (server_.GetMoveRequestHandlerFactory().ConstructMoveRequestHandler());
            cond = Internals::moveScp(assoc_, &msg, presID, *handler);
          }
          else
            cond = DIMSE_BADCOMMANDTYPE;  // Should never happen
          break;

        case DIMSE_C_FIND_RQ:
          // process C-FIND-Request
          if (server_.HasFindRequestHandlerFactory())
          {
            std::auto_ptr<IFindRequestHandler> handler
              (server_.GetFindRequestHandlerFactory().ConstructFindRequestHandler());
            cond = Internals::findScp(assoc_, &msg, presID, *handler);
          }
          else
            cond = DIMSE_BADCOMMANDTYPE;  // Should never happen
          break;

        default:
          // we cannot handle this kind of message
          cond = DIMSE_BADCOMMANDTYPE;
          LOG(ERROR) << "cannot handle command: 0x" << std::hex << msg.CommandField;
          break;
        }
      }
      else
      {
        // Bad status, which indicates the closing of the connection by
        // the peer or a network error
        finished = true;
      }
    
      if (finished)
      {
        if (cond == DUL_PEERREQUESTEDRELEASE)
        {
          LOG(INFO) << "Association Release";
          ASC_acknowledgeRelease(assoc_);
        }
        else if (cond == DUL_PEERABORTEDASSOCIATION)
        {
          LOG(INFO) << "Association Aborted";
        }
        else
        {
          OFString temp_str;
          LOG(ERROR) << "DIMSE failure (aborting association): " << cond.text();
          /* some kind of error so abort the association */
          ASC_abortAssociation(assoc_);
        }
      }

      return !finished;
    }
OFCondition RetrieveDICOMFilesFromPACS::subOperationSCP(T_ASC_Association **subAssociation)
{
    // Ens convertim com en un servei. El PACS ens fa peticions que nosaltres hem de respondre, ens pot demanar descarregar una imatge o fer un echo
    T_DIMSE_Message dimseMessage;
    T_ASC_PresentationContextID presentationContextID;

    if (!ASC_dataWaiting(*subAssociation, 0))
    {
        return DIMSE_NODATAAVAILABLE;
    }

    OFCondition condition = DIMSE_receiveCommand(*subAssociation, DIMSE_BLOCKING, 0, &presentationContextID, &dimseMessage, NULL);

    if (condition == EC_Normal)
    {
        switch (dimseMessage.CommandField)
        {
            case DIMSE_C_STORE_RQ:
                condition = storeSCP(*subAssociation, &dimseMessage, presentationContextID);
                break;

            case DIMSE_C_ECHO_RQ:
                condition = echoSCP(*subAssociation, &dimseMessage, presentationContextID);
                break;

            default:
                ERROR_LOG("El PACS ens ha sol.licitat un tipus d'operacio invalida");
                condition = DIMSE_BADCOMMANDTYPE;
                break;
        }
    }
    // Clean up on association termination
    if (condition == DUL_PEERREQUESTEDRELEASE)
    {
        INFO_LOG("El PACS sol.licita tancar la connexio per on ens ha enviat els fitxers");
        condition = ASC_acknowledgeRelease(*subAssociation);
        ASC_dropSCPAssociation(*subAssociation);
        ASC_destroyAssociation(subAssociation);
        return condition;
    }
    else if (condition == DUL_PEERABORTEDASSOCIATION)
    {
        INFO_LOG("El PACS ha abortat la connexió");
    }
    else if (condition != EC_Normal)
    {
        ERROR_LOG("S'ha produit un error reben la peticio d'una suboperacio, descripcio error: " + QString(condition.text()));
        condition = ASC_abortAssociation(*subAssociation);
    }
    else if (m_abortIsRequested)
    {
        INFO_LOG("Abortarem les connexions amb el PACS, perque han sol.licitant cancel.lar la descarrega");
        condition = ASC_abortAssociation(*subAssociation);
        if (!condition.good())
        {
            ERROR_LOG("Error al abortar la connexio pel qual rebem les imatges" + QString(condition.text()));
        }

        // Tanquem la connexió amb el PACS perquè segons indica la documentació DICOM al PS 3.4 (Baseline Behavior of SCP) C.4.2.3.1 si abortem
        // la connexió per la qual rebem les imatges, el comportament del PACS és desconegut, per exemple DCM4CHEE tanca la connexió amb el PACS, però
        // el RAIM_Server no la tanca i la manté fent que no sortim mai d'aquesta classe. Degut a que no es pot saber en aquesta situació com actuaran
        // els PACS es tanca aquí la connexió amb el PACS.
        condition = ASC_abortAssociation(m_pacsConnection->getConnection());
        if (!condition.good())
        {
            ERROR_LOG("Error al abortar la connexio pel amb el PACS" + QString(condition.text()));
        }
        else
        {
            INFO_LOG("Abortada la connexio amb el PACS");
        }
    }

    if (condition != EC_Normal)
    {
        ASC_dropAssociation(*subAssociation);
        ASC_destroyAssociation(subAssociation);
    }
    return condition;
}
Esempio n. 5
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;
}