#include "gdcmServiceClassUser.h"
#include "gdcmULTransitionTable.h"
#include "gdcmULConnection.h"
#include "gdcmULConnectionInfo.h"
#include "gdcmPresentationContextAC.h"
#include "gdcmPresentationDataValue.h"
#include "gdcmULConnectionCallback.h"
#include "gdcmULBasicCallback.h"
#include "gdcmPDUFactory.h"
#include "gdcmAttribute.h"
#include "gdcmULWritingCallback.h"
#include "gdcmPrinter.h"
#include "gdcmReader.h"
namespace gdcm
{
static const char GDCM_AETITLE[] = "GDCMSCU";
using namespace network;
class ServiceClassUserInternals
{
public:
ULConnection* mConnection{nullptr};
ULConnection* mSecondaryConnection{nullptr};
ULTransitionTable mTransitions;
std::string hostname;
int port;
int portscp;
std::string aetitle;
std::string calledaetitle;
double timeout;
ServiceClassUserInternals()= default;
~ServiceClassUserInternals(){
delete mConnection;
delete mSecondaryConnection;
}
};
ServiceClassUser::ServiceClassUser()
{
Internals = new ServiceClassUserInternals;
Internals->hostname = "localhost";
Internals->port = 104;
Internals->portscp = 104;
Internals->aetitle = GDCM_AETITLE;
Internals->calledaetitle = "ANY-SCP";
Internals->timeout = 10;
}
ServiceClassUser::~ServiceClassUser()
{
delete Internals;
}
void ServiceClassUser::SetPresentationContexts(std::vector<PresentationContext> const & pcs)
{
if( Internals->mConnection )
{
Internals->mConnection->SetPresentationContexts(pcs);
}
}
bool ServiceClassUser::IsPresentationContextAccepted(const PresentationContext& pc) const
{
bool found = false;
const std::vector<PresentationContextAC> &acceptedContexts =
Internals->mConnection->GetAcceptedPresentationContexts();
std::vector<PresentationContextAC>::const_iterator itor;
uint8_t contextID = pc.GetPresentationContextID();
for (itor = acceptedContexts.begin();
itor != acceptedContexts.end() && !found;
itor++)
{
if (contextID == itor->GetPresentationContextID())
found = true;
}
return found;
}
bool ServiceClassUser::InitializeConnection()
{
UserInformation userInfo;
ULConnectionInfo connectInfo;
if (Internals->aetitle.size() > 16)
{
return false;
}
if (Internals->calledaetitle.size() > 16)
{
return false;
}
if (!Internals->port)
{
return false;
}
if (Internals->hostname.empty())
{
return false;
}
if (!connectInfo.Initialize(userInfo, Internals->calledaetitle.c_str(),
Internals->aetitle.c_str(), 0, Internals->port, Internals->hostname))
{
return false;
}
ULConnection* mConnection = Internals->mConnection;
delete mConnection;
Internals->mConnection = new ULConnection(connectInfo);
Internals->mConnection->GetTimer().SetTimeout(Internals->timeout);
return true;
}
bool ServiceClassUser::StartAssociation()
{
Internals->mConnection->GetAcceptedPresentationContexts().clear();
if( Internals->mConnection->GetPresentationContexts().empty() )
{
return false;
}
ULEvent theEvent(eAASSOCIATERequestLocalUser, nullptr);
network::EStateID theState = RunEventLoop(theEvent, Internals->mConnection, nullptr, false);
if(theState != eSta6TransferReady)
{
std::vector<BasePDU*> const & thePDUs = theEvent.GetPDUs();
for( std::vector<BasePDU*>::const_iterator itor
= thePDUs.begin(); itor != thePDUs.end(); itor++)
{
gdcm_assert(*itor);
if (*itor == nullptr) continue; (*itor)->Print(Trace::GetErrorStream());
}
}
return theState == eSta6TransferReady;
}
bool ServiceClassUser::StopAssociation()
{
ULConnection* mConnection = Internals->mConnection;
BasePDU* thePDU = PDUFactory::ConstructReleasePDU();
ULEvent theEvent(eARELEASERequest, thePDU);
EStateID theState = RunEventLoop(theEvent, mConnection, nullptr, false);
return theState == eSta1Idle;
}
void ServiceClassUser::SetTimeout(double t)
{
Internals->timeout = t;
}
double ServiceClassUser::GetTimeout() const
{
return Internals->timeout;
}
void ServiceClassUser::SetCalledAETitle(const char *aetitle)
{
if( aetitle )
Internals->calledaetitle = aetitle;
}
void ServiceClassUser::SetAETitle(const char *aetitle)
{
if( aetitle )
Internals->aetitle = aetitle;
}
const char *ServiceClassUser::GetCalledAETitle() const
{
return Internals->calledaetitle.c_str();
}
const char *ServiceClassUser::GetAETitle() const
{
return Internals->aetitle.c_str();
}
void ServiceClassUser::SetHostname( const char *hostname )
{
if( hostname )
Internals->hostname = hostname;
}
void ServiceClassUser::SetPort( uint16_t port )
{
Internals->port = port;
}
void ServiceClassUser::SetPortSCP( uint16_t portscp )
{
Internals->portscp = portscp;
}
bool ServiceClassUser::SendEcho()
{
ULConnection* mConnection = Internals->mConnection;
std::vector<BasePDU*> theDataPDU = PDUFactory::CreateCEchoPDU(*mConnection);
ULEvent theEvent(ePDATArequest, theDataPDU);
EStateID theState = RunEventLoop(theEvent, mConnection, nullptr, false);
return theState == eSta6TransferReady;
}
bool ServiceClassUser::SendStore(const char *filename)
{
if( !filename ) return false;
Reader reader;
reader.SetFileName( filename );
bool b = reader.Read();
if( !b )
{
gdcmDebugMacro( "Could not read: " << filename );
return false;
}
const File & file = reader.GetFile();
return SendStore( file );
}
bool ServiceClassUser::SendStore(DataSet const &ds)
{
SmartPointer<File> file = new File;
file->SetDataSet( ds );
file->GetHeader().SetDataSetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian );
file->GetHeader().FillFromDataSet( ds );
return SendStore(*file);
}
bool ServiceClassUser::SendStore(File const &file)
{
ULConnection* mConnection = Internals->mConnection;
std::vector<BasePDU*> theDataPDU;
try
{
theDataPDU = PDUFactory::CreateCStoreRQPDU(*mConnection, file);
}
catch ( std::exception &ex )
{
(void)ex; gdcmErrorMacro( "Could not C-STORE: " << ex.what() );
return false;
}
network::ULBasicCallback theCallback;
network::ULConnectionCallback* inCallback = &theCallback;
ULEvent theEvent(ePDATArequest, theDataPDU);
EStateID stateid = RunEventLoop(theEvent, mConnection, inCallback, false);
gdcm_assert( stateid == eSta6TransferReady ); (void)stateid;
std::vector<DataSet> const &theDataSets = theCallback.GetResponses();
bool ret = true;
gdcm_assert( theDataSets.size() == 1 );
const DataSet &ds = theDataSets[0];
assert ( ds.FindDataElement(Tag(0x0, 0x0900)) );
DataElement const & de = ds.GetDataElement(Tag(0x0,0x0900));
Attribute<0x0,0x0900> at;
at.SetFromDataElement( de );
const uint16_t theVal = at.GetValue();
switch( theVal )
{
case 0x0:
gdcmDebugMacro( "C-Store of file was successful." );
break;
case 0xA700:
case 0xA900:
case 0xC000:
{
gdcmErrorMacro( "C-Store of file was a failure." );
Attribute<0x0,0x0902> errormsg;
errormsg.SetFromDataSet( ds );
const char *themsg = errormsg.GetValue();
gdcm_assert( themsg ); (void)themsg;
gdcmErrorMacro( "Response Status: " << themsg );
ret = false; }
break;
default:
gdcmErrorMacro( "Unhandle error code: " << theVal );
gdcmAssertAlwaysMacro( 0 );
}
return ret;
}
bool ServiceClassUser::SendFind(const BaseRootQuery* query, std::vector<DataSet> &retDataSets)
{
ULConnection* mConnection = Internals->mConnection;
network::ULBasicCallback theCallback;
network::ULConnectionCallback* inCallback = &theCallback;
std::vector<BasePDU*> theDataPDU = PDUFactory::CreateCFindPDU( *mConnection, query);
ULEvent theEvent(ePDATArequest, theDataPDU);
RunEventLoop(theEvent, mConnection, inCallback, false);
std::vector<DataSet> const & theDataSets = theCallback.GetDataSets();
std::vector<DataSet> const & theResponses = theCallback.GetResponses();
bool ret = false; gdcm_assert( !theResponses.empty() );
const DataSet &ds = theResponses[ theResponses.size() - 1 ]; assert ( ds.FindDataElement(Tag(0x0, 0x0900)) );
Attribute<0x0,0x0900> at;
at.SetFromDataSet( ds );
const uint16_t theVal = at.GetValue();
switch( theVal )
{
case 0x0: gdcmDebugMacro( "C-Find was successful." );
retDataSets.insert( retDataSets.end(), theDataSets.begin(), theDataSets.end() );
ret = true;
break;
case 0xA900: {
Attribute<0x0,0x0901> errormsg;
if( ds.FindDataElement( errormsg.GetTag() ) )
{
errormsg.SetFromDataSet( ds );
gdcm::Tag const & t = errormsg.GetValue();
gdcmErrorMacro( "Offending Element: " << t ); (void)t;
}
else
{
gdcmErrorMacro( "Offending Element ??" );
}
}
break;
case 0xA700: {
Attribute<0x0,0x0902> errormsg;
errormsg.SetFromDataSet( ds );
const char *themsg = errormsg.GetValue();
gdcm_assert( themsg ); (void)themsg;
gdcmErrorMacro( "Response Status: [" << themsg << "]" );
}
break;
case 0x0122: gdcmErrorMacro( "SOP Class not Supported" );
break;
case 0xfe00: gdcmErrorMacro( "Matching terminated due to Cancel request" );
break;
default:
{
if( theVal >= 0xC000 && theVal <= 0xCFFF ) {
Attribute<0x0,0x0902> errormsg;
errormsg.SetFromDataSet( ds );
const char *themsg = errormsg.GetValue();
gdcm_assert( themsg ); (void)themsg;
gdcmErrorMacro( "Response Status: " << themsg );
}
}
}
return ret;
}
bool ServiceClassUser::SendMove(const BaseRootQuery* query, const char *outputdir)
{
UserInformation userInfo2;
ULConnectionInfo connectInfo2;
if (!connectInfo2.Initialize(userInfo2, Internals->aetitle.c_str(),
Internals->calledaetitle.c_str(), 0, Internals->portscp, Internals->hostname))
{
return false;
}
ULConnection* mSecondaryConnection = Internals->mSecondaryConnection;
delete mSecondaryConnection;
Internals->mSecondaryConnection = new ULConnection(connectInfo2);
Internals->mSecondaryConnection->GetTimer().SetTimeout(Internals->timeout);
ULConnection* mConnection = Internals->mConnection;
network::ULWritingCallback theCallback;
theCallback.SetDirectory(outputdir);
network::ULConnectionCallback* inCallback = &theCallback;
std::vector<BasePDU*> theDataPDU = PDUFactory::CreateCMovePDU( *mConnection, query );
ULEvent theEvent(ePDATArequest, theDataPDU);
EStateID stateid = RunMoveEventLoop(theEvent, inCallback);
if( stateid != gdcm::network::eSta6TransferReady )
{
return false;
}
return true;
}
bool ServiceClassUser::SendMove(const BaseRootQuery* query, std::vector<DataSet> &retDataSets)
{
UserInformation userInfo2;
ULConnectionInfo connectInfo2;
if (!connectInfo2.Initialize(userInfo2, Internals->aetitle.c_str(),
Internals->calledaetitle.c_str(), 0, Internals->portscp, Internals->hostname))
{
return false;
}
ULConnection* mSecondaryConnection = Internals->mSecondaryConnection;
delete mSecondaryConnection;
Internals->mSecondaryConnection = new ULConnection(connectInfo2);
Internals->mSecondaryConnection->GetTimer().SetTimeout(Internals->timeout);
ULConnection* mConnection = Internals->mConnection;
network::ULBasicCallback theCallback;
network::ULConnectionCallback* inCallback = &theCallback;
std::vector<BasePDU*> theDataPDU = PDUFactory::CreateCMovePDU( *mConnection, query );
ULEvent theEvent(ePDATArequest, theDataPDU);
EStateID stateid = RunMoveEventLoop(theEvent, inCallback);
if( stateid != gdcm::network::eSta6TransferReady )
{
return false;
}
std::vector<DataSet> const & theDataSets = theCallback.GetDataSets();
retDataSets.insert( retDataSets.end(), theDataSets.begin(), theDataSets.end() );
return true;
}
bool ServiceClassUser::SendMove(const BaseRootQuery* query, std::vector<File> &retFiles)
{
(void)query;
(void)retFiles;
gdcm_assert( 0 && "unimplemented do not use" );
return false;
}
EStateID ServiceClassUser::RunEventLoop(network::ULEvent& currentEvent,
network::ULConnection* inWhichConnection,
network::ULConnectionCallback* inCallback,
const bool& startWaiting = false)
{
EStateID theState = eStaDoesNotExist;
bool waitingForEvent = startWaiting; EEventID raisedEvent;
bool receivingData = false;
do {
raisedEvent = eEventDoesNotExist;
if (!waitingForEvent){ Internals->mTransitions.HandleEvent(this, currentEvent, *inWhichConnection, waitingForEvent, raisedEvent);
theState = inWhichConnection->GetState();
}
std::istream &is = *inWhichConnection->GetProtocol();
BasePDU* theFirstPDU = nullptr;
std::vector<BasePDU*> incomingPDUs;
if (waitingForEvent){
while (waitingForEvent){ uint8_t itemtype = 0x0;
try {
is.read( (char*)&itemtype, 1 );
theFirstPDU = PDUFactory::ConstructPDU(itemtype);
if (theFirstPDU != nullptr){
incomingPDUs.push_back(theFirstPDU);
theFirstPDU->Read(is);
gdcmDebugMacro("PDU code: " << static_cast<int>(itemtype) << std::endl);
if (Trace::GetDebugFlag())
{
theFirstPDU->Print(Trace::GetStream());
}
if (theFirstPDU->IsLastFragment()) waitingForEvent = false;
} else {
waitingForEvent = false; }
}
catch (...)
{
gdcm_assert( 0 );
}
}
theState = inWhichConnection->GetState();
if (!incomingPDUs.empty()){
currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(incomingPDUs[0]));
currentEvent.SetPDU(incomingPDUs);
if (Internals->mConnection->GetTimer().GetHasExpired()){
currentEvent.SetEvent(eARTIMTimerExpired);
}
switch(currentEvent.GetEvent()){
case ePDATATFPDU:
{
uint32_t pendingDE1, pendingDE2, success, theVal;
pendingDE1 = 0xff01;
pendingDE2 = 0xff00;
success = 0x0000;
theVal = pendingDE1;
uint32_t theCommandCode = 0; DataSet theRSP =
PresentationDataValue::ConcatenatePDVBlobs(
PDUFactory::GetPDVs(currentEvent.GetPDUs()));
if (inCallback)
{
inCallback->HandleResponse(theRSP);
}
if (theRSP.FindDataElement(Tag(0x0, 0x0900))){
DataElement de = theRSP.GetDataElement(Tag(0x0,0x0900));
Attribute<0x0,0x0900> at;
at.SetFromDataElement( de );
theVal = at.GetValues()[0];
}
if (Trace::GetDebugFlag())
{
Printer thePrinter;
thePrinter.PrintDataSet(theRSP, Trace::GetStream());
}
if (theRSP.FindDataElement(Tag(0x0, 0x0100)))
{
DataElement de2 = theRSP.GetDataElement(Tag(0x0,0x0100));
Attribute<0x0,0x0100> at2;
at2.SetFromDataElement( de2 );
theCommandCode = at2.GetValues()[0];
}
if (theVal != pendingDE1 && theVal != pendingDE2 && theVal != success)
{
const ByteValue *err1 = nullptr, *err2 = nullptr;
gdcmErrorMacro( "Transfer failed with code " << theVal << std::endl);
switch (theVal){
case 0xA701:
gdcmErrorMacro( "Refused: Out of Resources Unable to calculate number of matches" << std::endl);
break;
case 0xA702:
gdcmErrorMacro( "Refused: Out of Resources Unable to perform sub-operations" << std::endl);
break;
case 0xA801:
gdcmErrorMacro( "Refused: Move Destination unknown" << std::endl);
break;
case 0xA900:
gdcmErrorMacro( "Identifier does not match SOP Class" << std::endl);
break;
case 0xAA00:
gdcmErrorMacro( "None of the frames requested were found in the SOP Instance" << std::endl);
break;
case 0xAA01:
gdcmErrorMacro( "Unable to create new object for this SOP class" << std::endl);
break;
case 0xAA02:
gdcmErrorMacro( "Unable to extract frames" << std::endl);
break;
case 0xAA03:
gdcmErrorMacro( "Time-based request received for a non-time-based original SOP Instance. " << std::endl);
break;
case 0xAA04:
gdcmErrorMacro( "Invalid Request" << std::endl);
break;
case 0xFE00:
gdcmErrorMacro( "Sub-operations terminated due to Cancel Indication" << std::endl);
break;
case 0xB000:
gdcmErrorMacro( "Sub-operations Complete One or more Failures or Warnings" << std::endl);
break;
default:
gdcmErrorMacro( "Unable to process" << std::endl);
break;
}
if (theRSP.FindDataElement(Tag(0x0,0x0901))){
DataElement de = theRSP.GetDataElement(Tag(0x0,0x0901));
err1 = de.GetByteValue();
gdcmErrorMacro( " Tag 0x0,0x901 reported as " << *err1 << std::endl); (void)err1;
}
if (theRSP.FindDataElement(Tag(0x0,0x0902))){
DataElement de = theRSP.GetDataElement(Tag(0x0,0x0902));
err2 = de.GetByteValue();
gdcmErrorMacro( " Tag 0x0,0x902 reported as " << *err2 << std::endl); (void)err2;
}
}
receivingData = false;
if (theVal == pendingDE1 || theVal == pendingDE2) {
receivingData = true; waitingForEvent = true;
}
if (theVal == pendingDE1 || theVal == pendingDE2 ){
std::vector<DataSet> final;
std::vector<BasePDU*> theData;
BasePDU* thePDU; bool interrupted = false;
do {
uint8_t itemtype = 0x0;
is.read( (char*)&itemtype, 1 );
thePDU = PDUFactory::ConstructPDU(itemtype);
if (itemtype != 0x4 && thePDU != nullptr){ std::vector<BasePDU*> interruptingPDUs;
interruptingPDUs.push_back(thePDU);
currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(interruptingPDUs[0]));
currentEvent.SetPDU(interruptingPDUs);
interrupted= true;
break;
}
if (thePDU != nullptr){
thePDU->Read(is);
theData.push_back(thePDU);
} else{
break;
}
} while(!thePDU->IsLastFragment());
if (!interrupted){ DataSet theCompleteFindResponse =
PresentationDataValue::ConcatenatePDVBlobs(PDUFactory::GetPDVs(theData));
for (size_t i = 0; i < theData.size(); i++)
{
delete theData[i];
}
if (inCallback)
{
inCallback->HandleDataSet(theCompleteFindResponse);
}
if (theCommandCode == 1){ std::vector<BasePDU*> theCStoreRSPPDU = PDUFactory::CreateCStoreRSPPDU(&theRSP, theFirstPDU); std::vector<BasePDU*>::iterator itor;
for (itor = theCStoreRSPPDU.begin(); itor < theCStoreRSPPDU.end(); itor++){
(*itor)->Write(*inWhichConnection->GetProtocol());
}
inWhichConnection->GetProtocol()->flush();
receivingData = false; }
}
}
}
break;
case eARELEASERequest: waitingForEvent = false;
break;
case eARELEASE_RQPDUReceivedOpen: waitingForEvent = false;
receivingData = true; break;
case eAABORTRequest:
waitingForEvent = false;
inWhichConnection->StopProtocol();
break;
case eASSOCIATE_ACPDUreceived:
default:
waitingForEvent = false;
break;
}
}
}
else {
currentEvent.SetEvent(raisedEvent); }
} while (currentEvent.GetEvent() != eEventDoesNotExist &&
theState != eStaDoesNotExist && theState != eSta13AwaitingClose && theState != eSta1Idle &&
(theState != eSta6TransferReady || (theState == eSta6TransferReady && receivingData )));
return theState;
}
EStateID ServiceClassUser::RunMoveEventLoop(ULEvent& currentEvent, ULConnectionCallback* inCallback){
EStateID theState = eStaDoesNotExist;
bool waitingForEvent = false;
EEventID raisedEvent;
bool receivingData = false;
bool justWaiting = false;
do {
if (!justWaiting){
Internals->mTransitions.HandleEvent(this,currentEvent, *Internals->mConnection, waitingForEvent, raisedEvent);
}
theState = Internals->mConnection->GetState();
std::istream &is = *Internals->mConnection->GetProtocol();
EStateID theCStoreStateID = eSta6TransferReady;
bool secondConnectionEstablished = false;
if (Internals->mSecondaryConnection->GetProtocol() == nullptr){
try
{
secondConnectionEstablished =
Internals->mSecondaryConnection->InitializeIncomingConnection();
}
catch ( std::exception & e )
{
gdcmErrorMacro( "Error 2nd connection:" << e.what() ); (void)e;
}
catch ( ... )
{
gdcm_assert( 0 );
}
}
if (secondConnectionEstablished &&
(Internals->mSecondaryConnection->GetState()== eSta1Idle ||
Internals->mSecondaryConnection->GetState() == eSta2Open)){
ULEvent theCStoreEvent(eEventDoesNotExist, nullptr); theCStoreStateID = RunEventLoop(theCStoreEvent, Internals->mSecondaryConnection, inCallback, true);
}
std::vector<BasePDU*> incomingPDUs;
if (waitingForEvent){
while (waitingForEvent)
{ uint8_t itemtype = 0x0;
is.read( (char*)&itemtype, 1 );
BasePDU* thePDU = PDUFactory::ConstructPDU(itemtype);
if (thePDU != nullptr)
{
incomingPDUs.push_back(thePDU);
thePDU->Read(is);
gdcmDebugMacro("PDU code: " << static_cast<int>(itemtype) << std::endl);
if (Trace::GetDebugFlag())
{
thePDU->Print(Trace::GetStream());
}
if (thePDU->IsLastFragment()) waitingForEvent = false;
}
else
{
waitingForEvent = false; }
}
if (!incomingPDUs.empty())
{
currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(incomingPDUs[0]));
currentEvent.SetPDU(incomingPDUs);
if (Internals->mConnection->GetTimer().GetHasExpired())
{
currentEvent.SetEvent(eARTIMTimerExpired);
}
if (theState == eSta6TransferReady){ uint32_t pendingDE1, pendingDE2, success, theVal;
pendingDE1 = 0xff01;
pendingDE2 = 0xff00;
success = 0x0000;
theVal = pendingDE1;
uint32_t theNumLeft = 0; DataSet theRSP = PresentationDataValue::ConcatenatePDVBlobs(PDUFactory::GetPDVs(currentEvent.GetPDUs()));
if (Trace::GetDebugFlag()){
Printer thePrinter;
thePrinter.PrintDataSet(theRSP, Trace::GetStream());
}
if (theRSP.FindDataElement(Tag(0x0, 0x0900))){
DataElement de = theRSP.GetDataElement(Tag(0x0,0x0900));
Attribute<0x0,0x0900> at;
at.SetFromDataElement( de );
theVal = at.GetValues()[0];
}
uint32_t theCommandCode = 0;
if (theRSP.FindDataElement(Tag(0x0,0x0100))){
DataElement de = theRSP.GetDataElement(Tag(0x0,0x0100));
Attribute<0x0,0x0100> at;
at.SetFromDataElement( de );
theCommandCode = at.GetValues()[0];
}
if (theRSP.FindDataElement(Tag(0x0, 0x1020))){
DataElement de = theRSP.GetDataElement(Tag(0x0,0x1020));
Attribute<0x0,0x1020> at;
at.SetFromDataElement( de );
theNumLeft = at.GetValues()[0];
}
if (theVal != pendingDE1 && theVal != pendingDE2 && theVal != success){
const ByteValue *err1 = nullptr, *err2 = nullptr;
gdcmErrorMacro( "Transfer failed with code " << theVal << std::endl);
switch (theVal){
case 0xA701:
gdcmErrorMacro( "Refused: Out of Resources Unable to calculate number of matches" << std::endl);
break;
case 0xA702:
gdcmErrorMacro( "Refused: Out of Resources Unable to perform sub-operations" << std::endl);
break;
case 0xA801:
gdcmErrorMacro( "Refused: Move Destination unknown" << std::endl);
break;
case 0xA900:
gdcmErrorMacro( "Identifier does not match SOP Class" << std::endl);
break;
case 0xAA00:
gdcmErrorMacro( "None of the frames requested were found in the SOP Instance" << std::endl);
break;
case 0xAA01:
gdcmErrorMacro( "Unable to create new object for this SOP class" << std::endl);
break;
case 0xAA02:
gdcmErrorMacro( "Unable to extract frames" << std::endl);
break;
case 0xAA03:
gdcmErrorMacro( "Time-based request received for a non-time-based original SOP Instance. " << std::endl);
break;
case 0xAA04:
gdcmErrorMacro( "Invalid Request" << std::endl);
break;
case 0xFE00:
gdcmErrorMacro( "Sub-operations terminated due to Cancel Indication" << std::endl);
break;
case 0xB000:
gdcmErrorMacro( "Sub-operations Complete One or more Failures or Warnings" << std::endl);
break;
default:
gdcmErrorMacro( "Unable to process" << std::endl);
break;
}
if (theRSP.FindDataElement(Tag(0x0,0x0901))){
DataElement de = theRSP.GetDataElement(Tag(0x0,0x0901));
err1 = de.GetByteValue();
gdcmErrorMacro( " Tag 0x0,0x901 reported as " << *err1 << std::endl); (void)err1;
}
if (theRSP.FindDataElement(Tag(0x0,0x0902))){
DataElement de = theRSP.GetDataElement(Tag(0x0,0x0902));
err2 = de.GetByteValue();
gdcmErrorMacro( " Tag 0x0,0x902 reported as " << *err2 << std::endl); (void)err2;
}
}
receivingData = false;
justWaiting = false;
if (theVal == pendingDE1 || theVal == pendingDE2 || (theVal == success && theNumLeft != 0)) {
receivingData = true; justWaiting = true;
waitingForEvent = true;
if (theCommandCode == 0x8021){
bool dataSetCountIncremented = true; if (Internals->mSecondaryConnection->GetProtocol() == nullptr){
secondConnectionEstablished =
Internals->mSecondaryConnection->InitializeIncomingConnection();
if (secondConnectionEstablished &&
(Internals->mSecondaryConnection->GetState()== eSta1Idle ||
Internals->mSecondaryConnection->GetState() == eSta2Open)){
ULEvent theCStoreEvent(eEventDoesNotExist, nullptr); theCStoreStateID = RunEventLoop(theCStoreEvent, Internals->mSecondaryConnection, inCallback, true);
} else { gdcmErrorMacro( "Unable to establish secondary connection with server, aborting." << std::endl);
return eStaDoesNotExist;
}
}
if (secondConnectionEstablished){
while (theCStoreStateID == eSta6TransferReady && dataSetCountIncremented){
ULEvent theCStoreEvent(eEventDoesNotExist, nullptr); theCStoreStateID = RunEventLoop(theCStoreEvent, Internals->mSecondaryConnection, inCallback, true);
if (inCallback){
dataSetCountIncremented = true;
inCallback->ResetHandledDataSet();
} else {
dataSetCountIncremented = false;
}
}
}
} else {
std::vector<DataSet> final;
std::vector<BasePDU*> theData;
BasePDU* thePDU; bool interrupted = false;
do {
uint8_t itemtype = 0x0;
is.read( (char*)&itemtype, 1 );
thePDU = PDUFactory::ConstructPDU(itemtype);
if (itemtype != 0x4 && thePDU != nullptr){ std::vector<BasePDU*> interruptingPDUs;
currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(interruptingPDUs[0]));
currentEvent.SetPDU(interruptingPDUs);
interrupted= true;
break;
}
if (thePDU != nullptr){
thePDU->Read(is);
theData.push_back(thePDU);
} else{
break;
}
} while( !thePDU->IsLastFragment());
if (!interrupted){ DataSet theCompleteFindResponse =
PresentationDataValue::ConcatenatePDVBlobs(PDUFactory::GetPDVs(theData));
for (size_t i = 0; i < theData.size(); i++){
delete theData[i];
}
if (inCallback){
inCallback->HandleDataSet(theCompleteFindResponse);
}
}
}
}
}
} else {
raisedEvent = eEventDoesNotExist;
waitingForEvent = false;
}
}
else {
currentEvent.SetEvent(raisedEvent); }
} while (currentEvent.GetEvent() != eEventDoesNotExist &&
theState != eStaDoesNotExist && theState != eSta13AwaitingClose && theState != eSta1Idle &&
(theState != eSta6TransferReady || (theState == eSta6TransferReady && receivingData )));
return theState;
}
}