Example #1
0
static void handleStudyQueries(DUL_ASSOCIATIONKEY** association,
			       DUL_ASSOCIATESERVICEPARAMETERS* params,
			       MSG_C_FIND_REQ* patientRequest,
			       LST_HEAD* patientList,
			       const char* queryLevel)
{
  ITEM* item;
  CONDITION cond;
  MSG_C_FIND_RESP response;

  item = (ITEM*)LST_Head(&patientList);
  (void)LST_Position(&patientList, item);
  while (item != 0) {
    char* patientName;
    char* patientID;
    char* charSet;
    MSG_C_FIND_REQ studyRequest;
    DCM_OBJECT* q;

    patientName = getString(item->obj, DCM_PATNAME);
    patientID = getString(item->obj, DCM_PATID);
    charSet = getString(patientRequest->identifier, DCM_IDSPECIFICCHARACTER);

    printf("%s %s\n", patientID, patientName);

    studyRequest = *patientRequest;
    studyRequest.identifier = 0;
    DCM_CreateObject(&q, 0);

    addString(q, DCM_PATID, patientID);
    addString(q, DCM_IDSPECIFICCHARACTER, charSet);
    addString(q, DCM_IDQUERYLEVEL, "STUDY");
    addString(q, DCM_RELSTUDYINSTANCEUID, "");
    addString(q, DCM_IDSTUDYDATE, "");
    addString(q, DCM_IDSTUDYTIME, "");
    addString(q, DCM_IDACCESSIONNUMBER, "");
    addString(q, DCM_IDSTUDYDESCRIPTION, "");

    studyRequest.identifier = q;
    studyRequest.messageID = SRV_MessageIDOut();

    item->lst = LST_Create();

    cond = SRV_CFindRequest(association, params,
			    &studyRequest, &response,
			    queryCallback, item->lst, "");
    if (!(CTN_SUCCESS(cond))) {
      (void) printf("Verification Request unsuccessful\n");
      COND_DumpConditions();
    } else {

    }

    item = LST_Next(&patientList);
  }
}
Example #2
0
File: iap.c Project: bhavik86/Dicom
CONDITION
IAP_SendInfoObject(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params, const char *fileName, const char *fileXferSyntax,
				   const char *moveAETitle, unsigned short moveMessageID, CONDITION(*sendCallback) (), void *callbackCtx)
{
    static MSG_C_STORE_REQ      request;
    CONDITION					cond;
    DCM_OBJECT					* object;
    static DCM_ELEMENT 			list[] = {
									{DCM_IDSOPCLASSUID, DCM_UI, "", 1, sizeof(request.classUID), (void *) &request.classUID[0]},
									{DCM_IDSOPINSTANCEUID, DCM_UI, "", 1, sizeof(request.instanceUID), (void *) &request.instanceUID[0]},
								};
    U32 						l;
    void 						*ctx;
    int 						index;

    if (fileName == NULL) return IAP_NORMAL;
    if (fileName[0] == '\0') return IAP_NORMAL;

    cond = DCM_OpenFile(fileName, DCM_PART10FILE, &object);
    if (cond != DCM_NORMAL)	return COND_PushCondition(IAP_OBJECTACCESSFAILED, IAP_Message(IAP_OBJECTACCESSFAILED), "IAP_SendInfoObject");

    for (index = 0; index < (int) DIM_OF(list); index++) {
    	ctx = NULL;
    	cond = DCM_GetElementValue(&object, &list[index], &l, &ctx);
    	if (cond != DCM_NORMAL) {
    		(void) DCM_CloseObject(&object);
    		return COND_PushCondition(IAP_OBJECTACCESSFAILED, IAP_Message(IAP_OBJECTACCESSFAILED), "IAP_SendInfoObject");
    	}
    	list[index].d.string[l] = '\0';
    }
    (void) DCM_RemoveGroup(&object, DCM_GROUPFILEMETA);

    request.type = MSG_K_C_STORE_REQ;
    request.messageID = SRV_MessageIDOut();
    request.priority = DCM_PRIORITYMEDIUM;
    request.dataSetType = DCM_CMDDATAIMAGE;
    request.dataSet = object;
    request.fileName = NULL;
    request.conditionalFields = 0;

    if (moveAETitle != NULL) {
    	strcpy(request.moveAETitle, moveAETitle);
    	request.moveMessageID = moveMessageID;
    	request.conditionalFields |= MSG_K_C_STORE_MOVEMESSAGEID | MSG_K_C_STORE_MOVEAETITLE;
    }else{
    	request.moveAETitle[0] = '\0';
    }
    cond = SRV_CStoreRequest(association, params, &request, NULL, sendCallback, callbackCtx, "");

    (void) DCM_CloseObject(&object);
    if (cond != SRV_NORMAL)	return COND_PushCondition(IAP_SENDFAILED, IAP_Message(IAP_SENDFAILED), "IAP_SendInfoObject");

    return IAP_NORMAL;
}
Example #3
0
File: get.c Project: bhavik86/Dicom
CONDITION
SRV_CGetResponse(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params, DUL_PRESENTATIONCONTEXT * getPresentationCtx,
				 MSG_C_GET_REQ ** getRequest, MSG_C_GET_RESP * getResponse, SRV_C_GET_RESP_CALLBACK * getCallback, void *getCtx, char *dirName)
{
    int      		flag, responseCount = 0;
    U32				l;
    char        	queryLevelString[48] = "";	/* Initialization for AIX compiler */
    CONDITION		cond, rtnCond = SRV_NORMAL;
    DCM_OBJECT		* responseObject;	/* get response object */
    void       		*ctx;
    DCM_ELEMENT		queryLevelElement = {DCM_IDQUERYLEVEL, DCM_CS, "", 1, sizeof(queryLevelString), NULL};
    static char 	*allowedQueryLevels[] = {
							DCM_QUERYLEVELPATIENT,
							DCM_QUERYLEVELSTUDY,
							DCM_QUERYLEVELSERIES,
							DCM_QUERYLEVELIMAGE};
    MSG_STATUS_DESCRIPTION	statusDescription;
    char pendingMsg[] = "\
In SRV_CGetResponse, the response message returned by your callback has \n\
a status of pending and data set that is not null.\n";
    MSG_TYPE		messageType;
    void	       *message;
    DUL_PRESENTATIONCONTEXTID	ctxID;
    MSG_C_STORE_REQ				storeRequest;
    char				        classUID[DICOM_UI_LENGTH + 1];

    queryLevelElement.d.string = queryLevelString;

    if (getCallback == NULL) {
    	(void) MSG_Free((void **) getRequest);
    	return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_CGetResponse");
    }
    if (getResponse->type != MSG_K_C_GET_RESP) {
    	(void) MSG_Free((void **) getRequest);
    	return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "GET Request", "SRV_CGetResponse");
    }
    (void) strcpy(classUID, (*getRequest)->classUID);

    cond = DCM_CreateObject(&getResponse->identifier, 0);
    if (cond != DCM_NORMAL)	return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse");

    cond = SRV_ReceiveDataSet(association, getPresentationCtx, DUL_BLOCK, 0, dirName, &(*getRequest)->identifier);
    if (PRVSRV_debug && (cond == SRV_NORMAL)) (void) DCM_DumpElements(&(*getRequest)->identifier, 0);

    if (cond != SRV_NORMAL) {
    	(void) MSG_Free((void **) getRequest);
    	return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse");
    }
    ctx = NULL;

    cond = DCM_GetElementValue(&(*getRequest)->identifier, &queryLevelElement, &l, &ctx);
    if (cond != DCM_NORMAL) {
    	(void) MSG_Free((void **) getRequest);
    	(void) COND_PushCondition(SRV_QUERYLEVELATTRIBUTEMISSING, SRV_Message(SRV_QUERYLEVELATTRIBUTEMISSING), "SRV_CGetResponse");
    	return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse");
    }
    queryLevelString[l] = '\0';
    if (queryLevelString[l - 1] == ' ')	queryLevelString[l - 1] = '\0';

    for (flag = 0, l = 0; l < DIM_OF(allowedQueryLevels) && !flag; l++){
    	if (strcmp(queryLevelString, allowedQueryLevels[l]) == 0) flag = 1;
    }
    if (!flag) {
    	(void) MSG_Free((void **) getRequest);
    	(void) COND_PushCondition(SRV_ILLEGALQUERYLEVELATTRIBUTE, SRV_Message(SRV_ILLEGALQUERYLEVELATTRIBUTE), queryLevelString, "SRV_CGetResponse");
    	return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse");
    }
    getResponse->messageIDRespondedTo = (*getRequest)->messageID;
    getResponse->conditionalFields = 0;
    getResponse->remainingSubOperations = 0;
    getResponse->completedSubOperations = 0;
    getResponse->failedSubOperations = 0;
    getResponse->warningSubOperations = 0;

    /*
     * Fill up the Store request and let the callback routine do the matching
     * and fill the rest of the fields
     */
    storeRequest.type = MSG_K_C_STORE_REQ;
    storeRequest.conditionalFields = 0;
    storeRequest.messageID = SRV_MessageIDOut();
    storeRequest.priority = 0;
    storeRequest.moveMessageID = (*getRequest)->messageID;

    /*
     * We invoke the callback for the first time without any StoreResponse so
     * that the callback can deal with the query and fill the Store Request
     * message and the GET response message. We also pass responseCount as 0
     * when we invoke the callback for the first time
     */
    cond = getCallback(*getRequest, getResponse, &storeRequest, NULL, 0, getPresentationCtx->abstractSyntax, queryLevelString, getCtx);
    if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_CGetRespose");

    if (storeRequest.dataSetType != DCM_CMDDATANULL) {
    	/* Send a Store Request */
    	cond = sendStoreRequest(association, params, &storeRequest);
    	if (cond != SRV_NORMAL) return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED),"sendStoreRequest", "SRV_CGetResponse");
	}else{
		/*
		 * No images are to be transferred as the query may have been
		 * unsuccessful in the call back routine. We expect the callback
		 * routine to have supplied the appropriate values for the various
		 * fields of the getResponse message.
		 *
		 * Send the CGetResponse Message and return from the routine
		 */
		cond = MSG_BuildCommand(getResponse, &responseObject);
		if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "getResponse", "SRV_CGetResponse");

		cond = SRV_SendCommand(association, getPresentationCtx, &responseObject);
		if (cond != SRV_NORMAL) return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED),"SRV_SendCommand", "SRV_CGetResponse");

		if (getResponse->dataSetType != DCM_CMDDATANULL) {
			cond = SRV_SendDataSet(association, getPresentationCtx, &getResponse->identifier, NULL, NULL, 0);
			if (cond != SRV_NORMAL) return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED), "SRV_SendDataSet", "SRV_CGetResponse");
		}
		return SRV_NORMAL;
    }
    flag = 0;
    while (!flag) {
    	/*
    	 * Now wait for incoming Store Responses or a Cancel Request. If it
    	 * is a Store Response, invoke the callback routine, with the Store
    	 * Response. The callback will update the Get Response message
    	 * accordingly and also fill the Store Request message if any more
    	 * requests are to be made
    	 */
    	cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID, NULL, &messageType, (void **) &message);
    	if (cond != SRV_NORMAL) return COND_PushCondition(SRV_RECEIVEFAILED, SRV_Message(SRV_RECEIVEFAILED), "SRV_CGetResponse");

    	switch (messageType) {
			case MSG_K_C_CANCEL_REQ:
											rtnCond = SRV_OPERATIONCANCELLED;
											getResponse->status = MSG_K_CANCEL;
											(void) MSG_Free(&message);

											cond = getCallback(*getRequest, getResponse, NULL, NULL, responseCount, getPresentationCtx->abstractSyntax, queryLevelString, getCtx);
											if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_CGetRespose");

											getResponse->messageIDRespondedTo = (*getRequest)->messageID;
											break;
			case MSG_K_C_STORE_RESP:
											responseCount++;
											getResponse->dataSetType = DCM_CMDDATANULL;
											getResponse->status = 0xffff;

											/*
											 * Fill up the Store request and let the callback routine do the
											 * matching and fill the rest of the fields
											 */
											storeRequest.type = MSG_K_C_STORE_REQ;
											storeRequest.conditionalFields = 0;
											storeRequest.messageID = SRV_MessageIDOut();
											storeRequest.priority = 0;
											storeRequest.moveMessageID = (*getRequest)->messageID;
											cond = getCallback(*getRequest, getResponse, &storeRequest, (MSG_C_STORE_RESP *) message, responseCount,
															   getPresentationCtx->abstractSyntax, queryLevelString, getCtx);
											if (cond != SRV_NORMAL)
												return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_CGetRespose");

											if (storeRequest.dataSetType != DCM_CMDDATANULL) {
												/* make the next store request */
												cond = sendStoreRequest(association, params, &storeRequest);
												if (cond != SRV_NORMAL)
													return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED), "sendStoreRequest", "SRV_CGetResponse");
											}
											break;
			default:
											break;
    	}

    	if (cond == SRV_NORMAL) {
    		cond = MSG_StatusLookup(getResponse->status, MSG_K_C_GET_RESP, &statusDescription);
    		if (cond != MSG_NORMAL)	return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse");

    		if (statusDescription.statusClass != MSG_K_CLASS_PENDING) flag = 1;

    		/* Consistency check */
    		if ((statusDescription.statusClass == MSG_K_CLASS_PENDING) && (getResponse->dataSetType != DCM_CMDDATANULL)) {

    			if (PRVSRV_debug) fprintf(DEBUG_DEVICE, pendingMsg);
    			rtnCond = COND_PushCondition(SRV_SUSPICIOUSRESPONSE, SRV_Message(SRV_SUSPICIOUSRESPONSE), "C-GET", "pending", "not null", "SRV_CGetResponse");
    		}
    	}else{
    		flag = 1;
    	}

    	strcpy(getResponse->classUID, classUID);
    	getResponse->conditionalFields |= MSG_K_C_GETRESP_CLASSUID;

    	cond = MSG_BuildCommand(getResponse, &responseObject);
    	if (cond != MSG_NORMAL) {
    		(void) MSG_Free((void **) getRequest);
    		return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse");
    	}

    	cond = SRV_SendCommand(association, getPresentationCtx, &responseObject);
    	if (cond != SRV_NORMAL) {
    		(void) MSG_Free((void **) getRequest);
    		return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse");
    	}

    	if (getResponse->dataSetType != DCM_CMDDATANULL) {
    		cond = SRV_SendDataSet(association, getPresentationCtx, &getResponse->identifier, NULL, NULL, 0);
    		if (cond != SRV_NORMAL) {
    			(void) MSG_Free((void **) getRequest);
    			return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse");
    		}
    	}
    }
    (void) MSG_Free((void **) getRequest);
    return rtnCond;
}
Example #4
0
main(int argc, char **argv)
{

  CONDITION cond;

  DUL_NETWORKKEY* network = NULL;
  DUL_ASSOCIATIONKEY* association = NULL;
  DUL_ASSOCIATESERVICEPARAMETERS params;
  char
    *calledAPTitle = "QUERY_SCP",
    *callingAPTitle = "QUERY_SCU";

  char localHost[40];

  int port;			/* TCP port used to establish Association */
  char* node;			/* The node we are calling */

  CTNBOOLEAN
    verbose = FALSE,
    abortFlag = FALSE,
    paramsFlag = FALSE;
  char *fileName = NULL;
  DUL_SC_ROLE role = DUL_SC_ROLE_DEFAULT;
  MSG_C_FIND_RESP response;
  MSG_C_FIND_REQ findRequest = {MSG_K_C_FIND_REQ, 0, 0,
				DCM_CMDDATAIDENTIFIER,
				0, NULL, DICOM_SOPPATIENTQUERY_FIND};
  char* queryLevel = "patient";
  LST_HEAD* patientList = 0;
  LST_HEAD* studyList = 0;

  while (--argc > 0 && (*++argv)[0] == '-') {
    switch (*(argv[0] + 1)) {
    case 'a':
      argc--;
      argv++;
      if (argc <= 0)
	usageerror();
      callingAPTitle = *argv;
      break;
    case 'c':
      argc--;
      argv++;
      if (argc <= 0)
	usageerror();
      calledAPTitle = *argv;
      break;
    case 'f':
      argc--;
      argv++;
      if (argc <= 0)
	usageerror();
      fileName = *argv;
      break;
    case 'l':
      argc--;
      argv++;
      if (argc <= 0)
	usageerror();
      queryLevel = *argv;
      break;
    case 'p':
      paramsFlag = TRUE;
      break;
    case 'v':
      verbose = TRUE;
      break;
    default:
      break;
    }
  }

  if (argc < 2)
    usageerror();

  THR_Init();
  DUL_Debug(verbose);
  SRV_Debug(verbose);
  
  node = *argv;
  if (sscanf(*++argv, "%d", &port) != 1)
    usageerror();
  (void) gethostname(localHost, sizeof(localHost));

  cond = DUL_InitializeNetwork(DUL_NETWORK_TCP, DUL_AEREQUESTOR,
			       NULL, 10, DUL_ORDERBIGENDIAN, &network);
  if (cond != DUL_NORMAL)
    myExit(&association);

  DUL_DefaultServiceParameters(&params);
  sprintf(params.calledPresentationAddress, "%s:%s", node, *argv);
  strcpy(params.callingPresentationAddress, localHost);
  strcpy(params.calledAPTitle, calledAPTitle);
  strcpy(params.callingAPTitle, callingAPTitle);
  cond = SRV_RequestServiceClass(DICOM_SOPPATIENTQUERY_FIND, role, &params);
  if (cond != SRV_NORMAL) {
    COND_DumpConditions();
    THR_Shutdown();
    exit(1);
  }
  cond = DUL_RequestAssociation(&network, &params, &association);
  if (cond != DUL_NORMAL) {
    if (cond == DUL_ASSOCIATIONREJECTED) {
      fprintf(stderr, "Association Rejected\n");
      fprintf(stderr, " Result: %2x Source %2x Reason %2x\n",
	      params.result, params.resultSource,
	      params.diagnostic);
    }
    myExit(&association);
  }
  if (verbose || paramsFlag) {
    (void) printf("Association accepted, parameters:\n");
    DUL_DumpParams(&params);
  }
  findRequest.messageID = SRV_MessageIDOut();
  findRequest.identifier = createQueryObject(fileName);


  patientList = LST_Create();
  studyList = LST_Create();

  cond = SRV_CFindRequest(&association, &params,
			  &findRequest, &response,
			  queryCallback, patientList, "");
  if (!(CTN_SUCCESS(cond))) {
    (void) printf("Verification Request unsuccessful\n");
    COND_DumpConditions();
  } else {
    MSG_DumpMessage(&response, stdout);
  }
  SRV_MessageIDIn(findRequest.messageID);

  if (strcmp(queryLevel, "patient") != 0) {
    handleStudyQueries(&association, &params, &findRequest,
		       patientList, queryLevel);
  }

  if (strcmp(queryLevel, "series") == 0) {
    handleSeriesQueries(&association, &params, &findRequest,
			patientList, queryLevel);
  }

  cond = DUL_ReleaseAssociation(&association);
  if (cond != DUL_RELEASECONFIRMED) {
    (void) fprintf(stderr, "%x\n", cond);
    COND_DumpConditions();
  }
  (void) DUL_ClearServiceParameters(&params);

  printResults(patientList);

  (void) DUL_DropNetwork(&network);
  THR_Shutdown();
  return 0;
}
Example #5
0
static void handleSeriesQueries(DUL_ASSOCIATIONKEY** association,
				DUL_ASSOCIATESERVICEPARAMETERS* params,
				MSG_C_FIND_REQ* patientRequest,
				LST_HEAD* patientList,
				const char* queryLevel)
{
  ITEM* item;
  ITEM* studyItem;
  CONDITION cond;
  MSG_C_FIND_RESP response;

  item = (ITEM*)LST_Head(&patientList);
  (void)LST_Position(&patientList, item);
  while (item != 0) {
    char* patientName;
    char* patientID;
    char* studyInstanceUID;
    char* charSet;

    patientName = getString(item->obj, DCM_PATNAME);
    patientID = getString(item->obj, DCM_PATID);
    charSet = getString(patientRequest->identifier, DCM_IDSPECIFICCHARACTER);

    printf("%s %s\n", patientID, patientName);

    studyItem = (ITEM*)LST_Head(&item->lst);
    (void)LST_Position(&item->lst, studyItem);
    while (studyItem != NULL) {
      DCM_OBJECT* q;
      MSG_C_FIND_REQ seriesRequest;

      seriesRequest = *patientRequest;
      seriesRequest.identifier = 0;
      DCM_CreateObject(&q, 0);

      studyInstanceUID = getString(studyItem->obj, DCM_RELSTUDYINSTANCEUID);

      addString(q, DCM_PATID, patientID);
      addString(q, DCM_IDSPECIFICCHARACTER, charSet);
      addString(q, DCM_IDQUERYLEVEL, "SERIES");
      addString(q, DCM_RELSTUDYINSTANCEUID, studyInstanceUID);
      addString(q, DCM_IDMODALITY, "");
      addString(q, DCM_RELSERIESNUMBER, "");
      addString(q, DCM_ACQBODYPARTEXAMINED, "");
      addString(q, DCM_ACQVIEWPOSITION, "");

      seriesRequest.identifier = q;
      seriesRequest.messageID = SRV_MessageIDOut();

      studyItem->lst = LST_Create();

      cond = SRV_CFindRequest(association, params,
			      &seriesRequest, &response,
			      queryCallback, studyItem->lst, "");
      if (!(CTN_SUCCESS(cond))) {
	(void) printf("C-Find Request unsuccessful\n");
	COND_DumpConditions();
      } else {
	
      }

      studyItem = LST_Next(&item->lst);
    }
    item = LST_Next(&patientList);
  }
}
Example #6
0
main(int argc, char **argv)
{

    CONDITION			/* Return values from DUL and ACR routines */
	cond;
    DUL_NETWORKKEY		/* Used to initialize our network */
	* network = NULL;
    DUL_ASSOCIATIONKEY		/* Describes the Association with the
				 * Acceptor */
	* association = NULL;
    DUL_ASSOCIATESERVICEPARAMETERS	/* The items which describe this
					 * Association */
	params = {
	DICOM_STDAPPLICATIONCONTEXT, "DICOM_TEST", "DICOM_VERIFY",
	    "", 16384, 0, 0, 0,
	    "calling presentation addr", "called presentation addr",
	    NULL, NULL, 0, 0,
	    MIR_IMPLEMENTATIONCLASSUID, MIR_IMPLEMENTATIONVERSIONNAME,
	    "", ""
    };
    char
       *calledAPTitle = "DICOM_STORAGE",
       *callingAPTitle = "DICOM_ECHO";

    char
        localHost[256];

    int
        port;			/* TCP port used to establish Association */
    char
       *node;			/* The node we are calling */

    CTNBOOLEAN
	verbose = FALSE,
	abortFlag = FALSE,
	paramsFlag = FALSE,
	drop = FALSE,
	noRelease = FALSE;
    int
        repeat = 1,
        connections = 1,
        repeatCopy,
        sleepTime = 0;
    DUL_SC_ROLE
	role = DUL_SC_ROLE_DEFAULT;
    MSG_C_ECHO_RESP
	response;
    char *classFile = NULL;

    while (--argc > 0 && (*++argv)[0] == '-') {
	switch (*(argv[0] + 1)) {
	case 'a':
	    argc--;
	    argv++;
	    if (argc <= 0)
		usageerror();
	    callingAPTitle = *argv;
	    break;
	case 'c':
	    argc--;
	    argv++;
	    if (argc <= 0)
		usageerror();
	    calledAPTitle = *argv;
	    break;
	case 'd':
	    drop = TRUE;
	    break;
	case 'f':
	    argc--;
	    argv++;
	    if (argc <= 0) {
		usageerror();
	    }
	    classFile = *argv;
	    break;
	case 'm':
	    argc--;
	    argv++;
	    if (argc <= 0)
		usageerror();
	    if (strcmp(*argv, "SCU") == 0)
		role = DUL_SC_ROLE_SCU;
	    else if (strcmp(*argv, "SCP") == 0)
		role = DUL_SC_ROLE_SCP;
	    else if (strcmp(*argv, "SCUSCP") == 0)
		role = DUL_SC_ROLE_SCUSCP;
	    else
		usageerror();
	    break;
	case 'n':
	    argc--;
	    argv++;
	    if (argc <= 0)
		usageerror();
	    if (sscanf(*argv, "%d", &connections) != 1)
		usageerror();
	    break;
	case 'p':
	    paramsFlag = TRUE;
	    break;
	case 'r':
	    argc--;
	    argv++;
	    if (argc <= 0)
		usageerror();
	    if (sscanf(*argv, "%d", &repeat) != 1)
		usageerror();
	    if (repeat <= 0)	/* A special case */
		repeat = 32 * 1024 * 1024;
	    break;
	case 's':
	    argc--;
	    argv++;
	    if (argc <= 0)
		usageerror();
	    if (sscanf(*argv, "%d", &sleepTime) != 1)
		usageerror();
	    break;
	case 'v':
	    verbose = TRUE;
	    break;
	case 'x':
	    noRelease = TRUE;
	    break;
	default:
	    break;
	}
    }
    if (argc < 2)
	usageerror();

    THR_Init();
    DUL_Debug(verbose);
    SRV_Debug(verbose);

    node = *argv;
    if (sscanf(*++argv, "%d", &port) != 1)
	usageerror();
    (void) gethostname(localHost, sizeof(localHost));

    cond = DUL_InitializeNetwork(DUL_NETWORK_TCP, DUL_AEREQUESTOR,
				 NULL, 10, DUL_ORDERBIGENDIAN, &network);
    if (cond != DUL_NORMAL)
	myExit(&association);
	
    if (classFile != NULL) {
	testSOPClasses(network, classFile, callingAPTitle, localHost,
	  calledAPTitle, node, port);
	connections = 0;			/* This will force us to skip the next section of echo code */
    }

    while (connections-- > 0) {
	sprintf(params.calledPresentationAddress, "%s:%s", node, *argv);
	strcpy(params.callingPresentationAddress, localHost);
	strcpy(params.calledAPTitle, calledAPTitle);
	strcpy(params.callingAPTitle, callingAPTitle);
	cond = SRV_RequestServiceClass(DICOM_SOPCLASSVERIFICATION, role,
				       &params);
	if (cond != SRV_NORMAL) {
	    COND_DumpConditions();
	    THR_Shutdown();
	    exit(1);
	}
	cond = DUL_RequestAssociation(&network, &params, &association);
	if (cond != DUL_NORMAL) {
	    if (cond == DUL_ASSOCIATIONREJECTED) {
		fprintf(stderr, "Association Rejected\n");
		fprintf(stderr, " Result: %2x Source %2x Reason %2x\n",
			params.result, params.resultSource,
			params.diagnostic);
	    }
	    myExit(&association);
	}
	if (verbose || paramsFlag) {
	    (void) printf("Association accepted, parameters:\n");
	    DUL_DumpParams(&params);
	}
	repeatCopy = repeat;
	while (repeatCopy-- > 0) {
	    MSG_C_ECHO_REQ echoRequest = {MSG_K_C_ECHO_REQ, 0, 0, DCM_CMDDATANULL,
	    DICOM_SOPCLASSVERIFICATION};

	    echoRequest.messageID = SRV_MessageIDOut();

	    cond = SRV_CEchoRequest(&association, &params,
				    &echoRequest, &response,
				    echoCallback, "Context", "");
	    if (!(CTN_SUCCESS(cond))) {
		(void) printf("Verification Request unsuccessful\n");
		COND_DumpConditions();
	    } else {
		MSG_DumpMessage(&response, stdout);
	    }
	    SRV_MessageIDIn(echoRequest.messageID);
#ifdef _MSC_VER
	    if (sleepTime > 0)
		Sleep(sleepTime * 1000);
#else
	    if (sleepTime > 0)
		sleep(sleepTime);
#endif
	}

	if (abortFlag) {
	    cond = DUL_AbortAssociation(&association);
	} else if (drop) {
	    cond = DUL_DropAssociation(&association);
	} else if (noRelease == FALSE) {
	    cond = DUL_ReleaseAssociation(&association);
	    if (cond != DUL_RELEASECONFIRMED) {
		(void) COND_PopCondition(TRUE);
#if 0
		(void) fprintf(stderr, "%x\n", cond);
		COND_DumpConditions();
#endif
	    }
	}
	(void) DUL_ClearServiceParameters(&params);
    }
    (void) DUL_DropNetwork(&network);
    THR_Shutdown();
    return 0;
}