Beispiel #1
0
static CONDITION
sendStoreRequest(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params, MSG_C_STORE_REQ * storeRequest)
{
    DUL_PRESENTATIONCONTEXT    	* storePresentationCtx;
    DCM_OBJECT					* storeRequestObject;
    CONDITION					cond;

    /* switch the presentation context to the store presentation context */
    storePresentationCtx = SRVPRV_PresentationContext(params, storeRequest->classUID);
    if (!storePresentationCtx) return COND_PushCondition(SRV_PRESENTATIONCONTEXTERROR, SRV_Message(SRV_PRESENTATIONCONTEXTERROR), "sendStoreRequest");

    /* build a StoreRequest command object */
    cond = MSG_BuildCommand(storeRequest, &storeRequestObject);
    if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "MSG_BuildCommand", "sendStoreRequest");

    /* Now send the store request on the same association */
    cond = SRV_SendCommand(association, storePresentationCtx, &storeRequestObject);
    if (cond != SRV_NORMAL) return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED), "SRV_SendCommand", "sendStoreRequest");

    /* Now send the data set */
    cond = SRV_SendDataSet(association, storePresentationCtx, &storeRequest->dataSet, NULL, NULL, 0);
    if (cond != SRV_NORMAL) return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED), "SRV_SendDataSet", "sendStoreRequest");

    return SRV_NORMAL;
}
Beispiel #2
0
/*
** SRV_NEventReportResponse
**
** Purpose:
**	SRV_NEventReportResponse assists an application that wants to be an SCU
**	of a number of SOP classes. When an application receives an
**	N-EVENT_REPORT request message, it calls this function with the
**	N-EVENT_REPORT request and other parameters. SRV_NEventReportResponse
**	checks the caller's parameters and calls the user's callback function.
**	In the callback	function, the caller fills in the parameters of the
**	N-EVENT_REPORT response	message and then returns to the SRV function.
**
**	After the callback function returns, SRV_NEventReportResponse
**	constructs a N-EVENT_REPORT Response message and sends it to the peer
**	application which sent the request message.
**
**	The arguments to the callback function are:
**		MSG_N_EVENT_REPORT_REQ	*eventRequest
**		MSG_N_EVENT_REPORT_RESP	*eventResponse
**		void			*eventCtx
**		DUL_PRESENTATIONCONTEXT	*pc
**
**	The first two arguments are MSG structures that contain the
**	N-EVENT_REPORT Request and N-EVENT_REPORT Response messages
**	respectively. The third argument is the caller's context variable that
**	is passed to SRV_NEventReportResponse.  The presentation context is
**	the one negotiated for this SOP class.
**
**	The callback function should return SRV_NORMAL. Any other return
**	value will cause the SRV facility to abort the Association.
**
** Parameter Dictionary:
**	association	The key which is used for transmitting the
**			N-EVENT_REPORT response.
**	presentationCtx	Pointer to presentation context to be used when sending
**			the N-EVENT_REPORT response.
**	eventRequest	Pointer to the structure with the N-EVENT_REPORT request
**			parameters which was received by the application.
**	eventResponse	Pointer to structure in the caller's area which will be
**			filled with the parameters of the N-EVENT_REPORT
**			response command. After the parameters are filled in,
**			the N-EVENT_REPORT response is sent to the peer
**			application which sent the request.
**	eventCallback	Address of user callback function to be called
**			with the N-EVENT_REPORT response from SCU.
**	eventCtx	Pointer to user context information which will be
**			passed to the callback function. Caller uses this
**			variable to contain any context required for the
**			callback function.
**      dirName         Name of directory where files may be created.
**
**
** Return Values:
**
**	SRV_CALLBACKABORTEDSERVICE
**	SRV_ILLEGALPARAMETER
**	SRV_NOCALLBACK
**	SRV_NORMAL
**	SRV_OBJECTBUILDFAILED
**	SRV_RESPONSEFAILED
**
** Algorithm:
**	Receive a data set, if any, from the peer application
**	Invoke the callback function, if it exists.
**	Build a command and send it to the requesting peer application.
**	Send a data set, if any, to the peer application.
**
** Notes:
**	The callback function is responsible for explicitly setting the
**	following fields in the N-EVENT_REPORT request message:
**
**	type
**	messageIDRespondedTo
**	classUID
**	dataSetType
**	instanceUID
**	status
**
*/
CONDITION
SRV_NEventReportResponse(DUL_ASSOCIATIONKEY ** association, DUL_PRESENTATIONCONTEXT * presentationCtx, MSG_N_EVENT_REPORT_REQ ** eventRequest,
						 MSG_N_EVENT_REPORT_RESP * eventResponse, SRV_N_EVENTREPORT_RESP_CALLBACK * eventCallback, void *eventCtx, char *dirName)
{
    CONDITION	cond;
    DCM_OBJECT	* responseObject;

    eventResponse->status = MSG_K_SUCCESS;
    if (eventCallback == NULL) {
    	(void) MSG_Free((void **) eventRequest);
    	return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_NEventReportResponse");
    }
    if ((*eventRequest)->dataSetType != DCM_CMDDATANULL){
    	cond = SRV_ReceiveDataSet(association, presentationCtx, DUL_BLOCK, 0, dirName, &(*eventRequest)->dataSet);
    	if (cond != SRV_NORMAL){
    		(void) MSG_Free((void **) eventRequest);
    		return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_NEventReportResponse");
    	}
    }
    eventResponse->dataSetType = DCM_CMDDATANULL;

    cond = DCM_CreateObject(&eventResponse->dataSet, 0);
    if (cond != DCM_NORMAL) {
    	(void) MSG_Free((void **) eventRequest);
    	return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_NEventReportResponse");
    }

    cond = eventCallback(*eventRequest, eventResponse, eventCtx, presentationCtx);
    (void) MSG_Free((void **) eventRequest);
    if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_NEventReportRequest");

    if (eventResponse->type != MSG_K_N_EVENT_REPORT_RESP)
    	return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "N-EVENT_REPORT Response", "SRV_NEventReportResponse");

    cond = MSG_BuildCommand(eventResponse, &responseObject);
    if (cond != MSG_NORMAL) {
    	(void) DCM_CloseObject(&eventResponse->dataSet);
    	return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "N-EVENT_REPORT Response", "SRV_NEventReportResponse");
    }

    cond = SRV_SendCommand(association, presentationCtx, &responseObject);
    (void) DCM_CloseObject(&responseObject);
    if (cond != SRV_NORMAL) {
    	(void) DCM_CloseObject(&eventResponse->dataSet);
    	return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_NEventReportResponse");
    }
    if (eventResponse->dataSetType != DCM_CMDDATANULL){ /* application specific event reply exists */
    	cond = SRV_SendDataSet(association, presentationCtx, &eventResponse->dataSet, NULL, NULL, 0);
    	if (cond != SRV_NORMAL){
    		(void) DCM_CloseObject(&eventResponse->dataSet);
    		return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_NEventReportResponse");
    	}
    }
    (void) DCM_CloseObject(&eventResponse->dataSet);
    return SRV_NORMAL;
}
Beispiel #3
0
/* processGetResponse
**
** Purpose:
**	This function processes the incoming response to the Get request.
**
** Parameter Dictionary:
**	association	Handle to the association
**	presentationCtx	Handle to the presentation context negotiated between
**			the two communicating peers
**	dirName		path name of file where we wish to receive the data
**			set.
**	getRequest	Pointer to the C-GET request structure
**	localResponse	Pointer to the C-GET response structure
**	queryLevelString
**			A string specifying the query at a specified level
**	callback	Pointer to user callback routine that is to be invoked
**			after a response is received
**	callbackCtx	Any user context information that needs to be passed
**			to the callback routine
**	done		A boolean flag indicating whether there are any more
**			pending store requests
**	cancelled	A boolean flag indicating whether a Cancel request had
**			been made
**	getResponse	Pointer to the GetResponse message received
**
** Return Values:
**	SRV_NORMAL unless there is any error
**
** Notes:
**
** Algorithm:
**	Description of the algorithm (optional) and any other notes.
*/
static CONDITION
processGetResponse(DUL_ASSOCIATIONKEY ** association, DUL_PRESENTATIONCONTEXT * presentationCtx, char *dirName, MSG_C_GET_REQ * getRequest, MSG_C_GET_RESP * localResponse,
				   char *queryLevelString, CONDITION(*callback) (), void *callbackCtx, CTNBOOLEAN * done, CTNBOOLEAN * cancelled, MSG_C_GET_RESP * getResponse, unsigned long *responseCount)
{
    CONDITION    				cond;
    MSG_STATUS_DESCRIPTION		statusDescription;
    DCM_OBJECT					* commandObject;
    MSG_C_CANCEL_REQ			cancelRequest = {MSG_K_C_CANCEL_REQ, 0, 0, DCM_CMDDATANULL};

    cond = MSG_StatusLookup(localResponse->status, MSG_K_C_GET_RESP, &statusDescription);
    if (cond != MSG_NORMAL)	return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CGetRequest");

    /* find the general category of the status received */
    if (statusDescription.statusClass != MSG_K_CLASS_PENDING) *done = TRUE;		/* No more pending requests */

    if (localResponse->dataSetType != DCM_CMDDATANULL) { /* Some data set (identifier) has been sent back */
    	cond = SRV_ReceiveDataSet(association, presentationCtx, DUL_BLOCK, 0, dirName, &localResponse->identifier);
    	if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CGetRequest");
    }
    *responseCount++;

    if (!*cancelled) {		/* no cancel request made */
    	cond = callback(getRequest, localResponse, *responseCount, presentationCtx->abstractSyntax, queryLevelString, callbackCtx);
    	if (cond == SRV_OPERATIONCANCELLED) {
    		*cancelled = TRUE;
    		/* build a cancel request */
    		cancelRequest.messageIDRespondedTo = getRequest->messageID;

    		cond = MSG_BuildCommand(&cancelRequest, &commandObject);
    		if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "CANCEL Request", "SRV_CGetRequest");

    		cond = SRV_SendCommand(association, presentationCtx, &commandObject);
    		(void) DCM_CloseObject(&commandObject);
    		if (cond != SRV_NORMAL)	return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CGetRequest");
    	}else if (cond != SRV_NORMAL){
    		*done = TRUE;	/* callback did not return SRV_NORMAL. Hence we opt to quit the loop */
    	}
    }
    if (getResponse != NULL) {
    	*getResponse = *localResponse;
    	getResponse->identifier = NULL;
    }
    return SRV_NORMAL;
}
Beispiel #4
0
/* processStoreRequest
**
** Purpose:
**	Process the Store sub operation request.
**
** Parameter Dictionary:
**	association	Handle to the association
**	presentationCtx	The presentation context negotiated between the peers
**	storeRequest	Pointer to the received C-STORE request
**	callback	Pointer to user callback function to be invoked during
**			store operation
**	callbackCtx	Any context information that needs to be passed to the
**			callback function
**
** Return Values:
**	SRV_NORMAL unless there is any error
**
** Notes:
**
** Algorithm:
**	Description of the algorithm (optional) and any other notes.
*/
static CONDITION
processStoreRequest(DUL_ASSOCIATIONKEY ** association, DUL_PRESENTATIONCONTEXT * presentationCtx, MSG_C_STORE_REQ * storeRequest, CONDITION(*callback) (), void *callbackCtx)
{
    CONDITION   		cond;
    int        			fd;			/* file descriptor */
    CTNBOOLEAN			first = TRUE,		/* to tell the callback function if it was invoked the first time or not */	done = FALSE;
    unsigned long       total, estimatedSize, nextCallback;
    unsigned short      sendStatus = 0x0000;
    DUL_PDV				pdv;
    DCM_OBJECT			* object;
    char        		fileName[1024];		/* name of image file */
    MSG_C_STORE_RESP	storeResponse;

    storeResponse.messageIDRespondedTo = storeRequest->messageID;
    storeResponse.type = MSG_K_C_STORE_RESP;
    (void) strcpy(storeResponse.classUID, storeRequest->classUID);
    (void) strcpy(storeResponse.instanceUID, storeRequest->instanceUID);
    storeResponse.conditionalFields = MSG_K_C_STORERESP_CLASSUID | MSG_K_C_STORERESP_INSTANCEUID;
    storeResponse.dataSetType = DCM_CMDDATANULL;
    storeResponse.status = MSG_K_SUCCESS;	/* we initialize it to success but the callback can change it */

    /* invoke the call back for the first time and get the file name */
    total = 0;
    estimatedSize = genericImageSize(storeRequest->classUID);
    cond = callback(storeRequest, &storeResponse, first, fileName, total, estimatedSize, NULL, callbackCtx);
    first = FALSE;
    if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "processStoreRequest");

#ifdef _MSC_VER
    fd = open(fileName, O_BINARY | O_CREAT | O_WRONLY | O_TRUNC, S_IREAD | S_IWRITE);
#else
    fd = open(fileName, O_CREAT | O_WRONLY | O_TRUNC, 0666);
#endif
    if (fd < 0) return COND_PushCondition(SRV_FILECREATEFAILED, SRV_Message(SRV_FILECREATEFAILED), fileName, "SRV_CGetRequest");

    done = FALSE;
    nextCallback = estimatedSize / 10;
    while (!done) {
    	cond = SRVPRV_ReadNextPDV(association, DUL_BLOCK, 0, &pdv);
    	if (cond != SRV_NORMAL) return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetRequest");

    	if (pdv.pdvType != DUL_DATASETPDV) return COND_PushCondition(SRV_UNEXPECTEDPDVTYPE, SRV_Message(SRV_UNEXPECTEDPDVTYPE), (int) pdv.pdvType, "SRV_CGetRequest");

    	if (sendStatus == 0) {
    		if (write(fd, pdv.data, pdv.fragmentLength) !=	(int) pdv.fragmentLength) sendStatus = 0xaf01;
    	}
    	total += pdv.fragmentLength;

    	if (pdv.lastPDV) done = TRUE;

    	if (total > nextCallback) {
    		cond = callback(storeRequest, &storeResponse, first, NULL, total, estimatedSize, NULL, callbackCtx);
    		if (cond != SRV_NORMAL) return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetRequest");
	        nextCallback += estimatedSize / 10;
    	}
    }
    (void) close(fd);

    cond = DCM_OpenFile(fileName, DCM_ORDERLITTLEENDIAN, &object);
    if (cond != DCM_NORMAL) return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetRequest");

    /* invoke the callback the last time with a valid object */
    cond = callback(storeRequest, &storeResponse, first, NULL, total, estimatedSize, &object, callbackCtx);
    if (cond != SRV_NORMAL) {
    	(void) DCM_CloseObject(&object);
    	return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_CGetRequest");
    }

    (void) DCM_CloseObject(&object);

    /* Now build a C-Store response message and send it to the peer */
    cond = MSG_BuildCommand(&storeResponse, &object);
    if (cond != MSG_NORMAL)	return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "storeResponse", "processStoreRequest");

    cond = SRV_SendCommand(association, presentationCtx, &object);
    (void) DCM_CloseObject(&object);
    if (cond != SRV_NORMAL)	return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetRequest");
    return SRV_NORMAL;
}
Beispiel #5
0
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;
}
Beispiel #6
0
CONDITION
SRV_CGetRequest(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params,	MSG_C_GET_REQ * getRequest, MSG_C_GET_RESP * getResponse,
				SRV_C_GET_REQ_CALLBACK * getCallback, void *getCallbackCtx, CONDITION(*storageCallback) (), void *storageCallbackCtx, char *dirName)
{
    DCM_OBJECT					* commandObject;	/* Handle for a command object */
    CONDITION					cond;			/* Return value from function calls */
    DUL_PRESENTATIONCONTEXT		* presentationCtx,	/* Presentation context for GET service */	*storePresentationCtx;	/* for the arriving store request */
    DUL_PRESENTATIONCONTEXTID	ctxID;
    void      					*message;
    MSG_TYPE					messageType;
    CTNBOOLEAN					done = FALSE;
    U32							l;
    unsigned long        		responseCount = 0;
    MSG_C_STORE_REQ				* storeRequest;
    void       					*ctx;
    char        				queryLevelString[48] = "";	/* Initialization for AIX compiler */
    DCM_ELEMENT					queryLevelElement = {DCM_IDQUERYLEVEL, DCM_CS, "", 1, sizeof(queryLevelString), NULL};
    unsigned short		        command;
    CTNBOOLEAN					cancelled = FALSE;
    MSG_C_CANCEL_REQ			cancelRequest = {MSG_K_C_CANCEL_REQ, 0, 0, DCM_CMDDATANULL};

    queryLevelElement.d.string = queryLevelString;

    if ((getCallback == NULL) || (storageCallback == NULL))	return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_CGetRequest");
    if (getRequest->type != MSG_K_C_GET_REQ) return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "GET Request", "SRV_CGetRequest");
    if (getRequest->dataSetType == DCM_CMDDATANULL)	return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "dataSetType", "GET Request", "SRV_CGetRequest");

    ctx = NULL;
    cond = DCM_GetElementValue(&getRequest->identifier, &queryLevelElement, &l, &ctx);
    if (cond != DCM_NORMAL)	return COND_PushCondition(SRV_OBJECTACCESSFAILED, SRV_Message(SRV_OBJECTACCESSFAILED), "Query Identifier", "SRV_CGetRequest");

    queryLevelString[l] = '\0';
    if (queryLevelString[l - 1] == ' ')	queryLevelString[l - 1] = '\0';

    presentationCtx = SRVPRV_PresentationContext(params, getRequest->classUID);
    if (presentationCtx == NULL) return COND_PushCondition(SRV_NOSERVICEINASSOCIATION, SRV_Message(SRV_NOSERVICEINASSOCIATION), getRequest->classUID, "SRV_CGetRequest");

    cond = MSG_BuildCommand(getRequest, &commandObject);
    if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "GET Request", "SRV_CGetRequest");

    cond = SRV_SendCommand(association, presentationCtx, &commandObject);
    (void) DCM_CloseObject(&commandObject);
    if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CGetRequest");

    cond = SRV_SendDataSet(association, presentationCtx, &getRequest->identifier, NULL, NULL, 0);
    if (cond != SRV_NORMAL)	return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CGetRequest");

    while (!done) {		/* do until there are no more pending requests */
    	cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID, &command, &messageType, &message);
    	if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CGetRequest");

    	switch (messageType) {
			case MSG_K_C_GET_RESP:
											cond = processGetResponse(association, presentationCtx, dirName, getRequest, (MSG_C_GET_RESP *) message,
																	  queryLevelString, getCallback, getCallbackCtx, &done, &cancelled, getResponse, &responseCount);
											(void) MSG_Free(&message);
											if ((CTN_FATAL(cond)) || (CTN_ERROR(cond)))	return cond;
											break;
			case MSG_K_C_STORE_REQ:
											storeRequest = (MSG_C_STORE_REQ *) message;
											storePresentationCtx = SRVPRV_PresentationContext(params, storeRequest->classUID);
											if (storePresentationCtx == NULL)
												return COND_PushCondition(SRV_PRESENTATIONCONTEXTERROR, SRV_Message(SRV_PRESENTATIONCONTEXTERROR), "SRV_CGetRequest");

											cond = processStoreRequest(association, storePresentationCtx, storeRequest, storageCallback, storageCallbackCtx);
											if ((CTN_FATAL(cond)) || (CTN_ERROR(cond)))	return cond;
											break;
			default:
											(void) MSG_Free(&message);
											return COND_PushCondition(SRV_UNEXPECTEDCOMMAND, SRV_Message(SRV_UNEXPECTEDCOMMAND), (int) command, "SRV_CGetRequest");
    	}
    }
    if (cancelled){
    	return SRV_OPERATIONCANCELLED;
    }else{
    	return SRV_NORMAL;
    }
}
Beispiel #7
0
/* SRV_NActionResponse
**
** Purpose:
**	SRV_NActionResponse assists an application that wants to be an SCP
**	of a number of SOP classes. When an application receives an N-ACTION
**	request message, it calls this function with the N-ACTION request
**	and other parameters. SRV_NActionResponse checks the caller's
**	parameters and calls the user's callback function. In the callback
**	function, the caller fills in the parameters of the N-ACTION response
**	message and then returns to the SRV function.
**
**	After the callback function returns, SRV_NActionResponse constructs a
**	N-ACTION Response message and sends it to the peer application which
**	sent the request message.
**
**	The arguments to the callback function are:
**		MSG_N_ACTION_REQ	*actionRequest
**		MSG_N_ACTION_RESP	*actionResponse
**		void			*actionCtx
**		DUL_PRESENTATIONCONTEXT	*pc
**
**	The first two arguments are MSG structures that contain the N-ACTION
**	Request and N-ACTION Response messages respectively. The third
**	argument is the caller's context variable that is passed to
**	SRV_NActionResponse.  The presentation context describes the SOP
**	class that was negotiated for this message.
**
**	The callback function should return SRV_NORMAL. Any other return
**	value will cause the SRV facility to abort the Association.
**
** Parameter Dictionary:
**	association	The key which is used for transmitting the N-ACTION
**			response.
**	presentationCtx	Pointer to presentation context to be used when sending
**			the N-ACTION response.
**	actionRequest	Pointer to the structure with the N-ACTION request
**			parameters which was received by the application.
**	actionResponse	Pointer to structure in the caller's area which will be
**			filled with the parameters of the N-ACTION response
**			command. After the parameters are filled in, the
**			N-ACTION response is sent to the peer application
**			which sent the request.
**	actionCallback	Address of user callback function to be called
**			with the N-ACTION response from SCP.
**	actionCtx	Pointer to user context information which will be
**			passed to the callback function. Caller uses this
**			variable to contain any context required for the
**			callback function.
**      dirName         Name of directory where files may be created.
**
**
** Return Values:
**
**	SRV_CALLBACKABORTEDSERVICE
**	SRV_ILLEGALPARAMETER
**	SRV_NOCALLBACK
**	SRV_NORMAL
**	SRV_OBJECTBUILDFAILED
**	SRV_RESPONSEFAILED
**
** Algorithm:
**	Receive a data set, if any, from the peer application
**	Invoke the callback function, if it exists.
**	Build a command and send it to the requesting peer application.
**	Send a data set, if any, to the peer application.
**
** Notes:
**	The callback function is responsible for explicitly setting the
**	following fields in the N-ACTION response message:
**
**	type
**	messageIDRespondedTo
**	classUID
**	dataSetType
**	instanceUID
**	status
**	actionReply (if any)
**
*/
CONDITION
SRV_NActionResponse(DUL_ASSOCIATIONKEY ** association,
		    DUL_PRESENTATIONCONTEXT * presentationCtx,
		    MSG_N_ACTION_REQ ** actionRequest,
		    MSG_N_ACTION_RESP * actionResponse,
	       SRV_N_ACTION_RESP_CALLBACK * actionCallback, void *actionCtx,
		    char *dirName)
{
    CONDITION
	rtnCond = SRV_NORMAL,
	cond;
    DCM_OBJECT
	* responseObject = NULL;

    actionResponse->status = MSG_K_SUCCESS;	/* initialize */
    actionResponse->dataSetType = DCM_CMDDATANULL;
    actionResponse->actionReply = NULL;

    if (actionCallback == NULL) {
	rtnCond = COND_PushCondition(SRV_NOCALLBACK,
			SRV_Message(SRV_NOCALLBACK), "SRV_NActionResponse");
	actionResponse->status = MSG_K_RESOURCELIMITATION;
	goto SEND_RESPONSE;
    }
    /* check if there is any data coming over the network */
    if ((*actionRequest)->dataSetType != DCM_CMDDATANULL) {
	cond = SRV_ReceiveDataSet(association, presentationCtx,
	       DUL_BLOCK, 0, dirName, &(*actionRequest)->actionInformation);
	if (cond != SRV_NORMAL) {
	    rtnCond = COND_PushCondition(SRV_RECEIVEDATASETFAILED,
				      SRV_Message(SRV_RECEIVEDATASETFAILED),
					 "SRV_NActionResponse");
	    actionResponse->status = MSG_K_PROCESSINGFAILURE;
	    goto SEND_RESPONSE;
	}
    }
    /* SRV routine allocates space for the action reply */
    cond = DCM_CreateObject(&actionResponse->actionReply, 0);
    if (cond != DCM_NORMAL) {
	rtnCond = COND_PushCondition(SRV_OBJECTBUILDFAILED,
		 SRV_Message(SRV_OBJECTBUILDFAILED), "SRV_NActionResponse");
	actionResponse->status = MSG_K_PROCESSINGFAILURE;
	goto SEND_RESPONSE;
    }
    cond = actionCallback(*actionRequest, actionResponse, actionCtx,
			  presentationCtx);
    if (cond != SRV_NORMAL) {
	rtnCond = COND_PushCondition(SRV_CALLBACKABORTEDSERVICE,
	     SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_NActionRequest");
	goto SEND_RESPONSE;
    }
    if (actionResponse->type != MSG_K_N_ACTION_RESP) {
	rtnCond = COND_PushCondition(SRV_ILLEGALPARAMETER,
	     SRV_Message(SRV_ILLEGALPARAMETER), "type", "N-ACTION Response",
				     "SRV_NActionResponse");
	goto SEND_RESPONSE;
    }
SEND_RESPONSE:
    /* At this point we free the request pointer */
    (void) MSG_Free((void **) actionRequest);

    /*
     * If there are any errors in the following steps, it is necessary for
     * the SRV routine to free the data set object it had created earlier.
     * But we must verify that such a data set creation operation itself was
     * successful before we try to free the data set
     */

    /* send the action reply (if any) only on success status */
    if (actionResponse->status != MSG_K_SUCCESS) {
	actionResponse->dataSetType = DCM_CMDDATANULL;
	if (actionResponse->actionReply)
	    (void) DCM_CloseObject(&actionResponse->actionReply);
	return rtnCond;
    }
    /* build a command object */
    cond = MSG_BuildCommand(actionResponse, &responseObject);
    if (cond != MSG_NORMAL) {
	if (actionResponse->actionReply)
	    (void) DCM_CloseObject(&actionResponse->actionReply);
	return COND_PushCondition(SRV_OBJECTBUILDFAILED,
		    SRV_Message(SRV_OBJECTBUILDFAILED), "N-ACTION Response",
				  "SRV_NActionResponse");
    }
    cond = SRV_SendCommand(association, presentationCtx, &responseObject);
    (void) DCM_CloseObject(&responseObject);
    if (cond != SRV_NORMAL) {
	if (actionResponse->actionReply)
	    (void) DCM_CloseObject(&actionResponse->actionReply);
	return COND_PushCondition(SRV_SENDFAILED,
				  SRV_Message(SRV_SENDFAILED), "Command",
				  "SRV_NActionResponse");
    }
    /*
     * At this point, the response message status is "SUCCESS". This also
     * implies that the "data set" object exists but may be empty (not NULL)
     * Hence if there is any error, we need to close it first before we
     * return.
     */
    if (actionResponse->dataSetType != DCM_CMDDATANULL) {
	cond = SRV_SendDataSet(association, presentationCtx,
			       &actionResponse->actionReply, NULL, NULL, 0);
	if (cond != SRV_NORMAL) {
	    (void) DCM_CloseObject(&actionResponse->actionReply);
	    return COND_PushCondition(SRV_SENDFAILED,
				    SRV_Message(SRV_SENDFAILED), "Data Set",
				      "SRV_NActionResponse");
	}
    }
    (void) DCM_CloseObject(&actionResponse->actionReply);	/* was allocated memory */
    return SRV_NORMAL;		/* everything is successful at this point */
}
Beispiel #8
0
/* SRV_NActionRequest
**
** Purpose:
**	SRV_NActionRequest assists an application that wants to be an SCU of
**	a number of SOP classes. This function constructs an N-ACTION-REQ
**	message and sends it to the peer application which is acting as the
**	SCP for a SOP class. This function waits for the response from the
**	peer application and invokes the caller's callback function.
**
**	The arguments to the callback function are:
**		MSG_N_ACTION_REQ	*actionRequest
**		MSG_N_ACTION_RESP	*actionResponse
**		void			*actionCtx
**
**	The first two arguments are MSG structures that contain the N-ACTION
**	Request and N-ACTION Response messages respectively. The final
**	argument is the caller's context variable that is passed to
**	SRV_NActionRequest.
**
**	The callback function should return SRV_NORMAL. Any other return
**	value will cause the SRV facility to abort the Association.
**
** Parameter Dictionary:
**	association	The key which is used to access an existing
**			association.
**	params		The list of parameters for the association. This
**			list includes the list of presentation contexts.
**	SOPClass	UID of the SOP class used when the association was
**			negotiated. Since this can be a meta class, it may
**			not be the same as the class UID in the N-ACTION
**			request message.
**	actionRequest	Pointer to the structure with the N-ACTION request
**			parameters.
**	actionResponse	Pointer to caller's pointer to an N-ACTION response.
**			This function will allocate an MSG_N_ACTION_RESP
**			message and return the pointer to the caller.
**	actionCallback	Address of user callback function to be called
**			with the N-ACTION response from SCP.
**	actionCtx	Pointer to user context information which will be
**			passed to the callback function. Caller uses this
**			variable to contain any context required for the
**			callback function.
**      dirName         Name of directory where files may be created.
**
**
** Return Values:
**
**	SRV_CALLBACKABORTEDSERVICE
**	SRV_ILLEGALPARAMETER
**	SRV_NOCALLBACK
**	SRV_NORMAL
**	SRV_OBJECTBUILDFAILED
**	SRV_REQUESTFAILED
**	SRV_UNEXPECTEDCOMMAND
**	SRV_UNSUPPORTEDSERVICE
**
** Algorithm:
**	Check if the callback function has been provided.
**	Determine the presentation context
**	Encode the N-ACTION request message as a command object and
**		send it to an SCP
**	Send data set, if one exists, to the SCP.
**	Wait for a response message to arrive from the SCP
**	Receive a data set, if one exists, from the SCP
**	Return address of Response message structure to caller.
**
** Notes:
**	The caller is responsible for explicitly setting the following
**	fields in the N-ACTION request message:
**
**	type
**	messageID
**	classUID
**	dataSetType
**	instanceUID
**	actionTypeID
**
**	The caller is also responsible for releasing the Response message
**	structure after the SRV_NActionRequest function returns,
**	using MSG_Free.
*/
CONDITION
SRV_NActionRequest(DUL_ASSOCIATIONKEY ** association,
		   DUL_ASSOCIATESERVICEPARAMETERS * params,
		   char *SOPClass,
		   MSG_N_ACTION_REQ * actionRequest,
		   MSG_N_ACTION_RESP * actionResponse,
		SRV_N_ACTION_REQ_CALLBACK * actionCallback, void *actionCtx,
		   char *dirName)
{
    DCM_OBJECT
	* commandObject;	/* Handle for a command object */
    CONDITION
	cond;			/* Return value from function calls */
    DUL_PRESENTATIONCONTEXT
	* presentationCtx;	/* Presentation context for this service */
    DUL_PRESENTATIONCONTEXTID
	ctxID;
    void
       *message;
    MSG_TYPE
	messageType;
    MSG_N_ACTION_RESP
	* localResponse;
    unsigned short
        command;

    if (actionCallback == NULL)
	return COND_PushCondition(SRV_NOCALLBACK,
			 SRV_Message(SRV_NOCALLBACK), "SRV_NActionRequest");

    presentationCtx = SRVPRV_PresentationContext(params, SOPClass);
    if (presentationCtx == NULL)
	return COND_PushCondition(SRV_UNSUPPORTEDSERVICE,
				  SRV_Message(SRV_UNSUPPORTEDSERVICE),
			     actionRequest->classUID, "SRV_NActionRequest");

    if (actionRequest->type != MSG_K_N_ACTION_REQ)
	return COND_PushCondition(SRV_ILLEGALPARAMETER,
	      SRV_Message(SRV_ILLEGALPARAMETER), "type", "N-ACTION Request",
				  "SRV_NActionRequest");

    cond = MSG_BuildCommand(actionRequest, &commandObject);
    if (cond != MSG_NORMAL)
	return COND_PushCondition(SRV_OBJECTBUILDFAILED,
		     SRV_Message(SRV_OBJECTBUILDFAILED), "N-ACTION Request",
				  "SRV_NActionRequest");

    cond = SRV_SendCommand(association, presentationCtx, &commandObject);
    (void) DCM_CloseObject(&commandObject);
    if (cond != SRV_NORMAL)
	return COND_PushCondition(SRV_REQUESTFAILED,
		      SRV_Message(SRV_REQUESTFAILED), "SRV_NActionRequest");

    if (actionRequest->dataSetType != DCM_CMDDATANULL) {
	/* application specific action information exists */
	cond = SRV_SendDataSet(association, presentationCtx,
			  &actionRequest->actionInformation, NULL, NULL, 0);
	if (cond != SRV_NORMAL)
	    return COND_PushCondition(SRV_REQUESTFAILED,
		      SRV_Message(SRV_REQUESTFAILED), "SRV_NActionRequest");

    }
    cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID,
			      &command, &messageType, &message);
    if (cond != SRV_NORMAL)
	return COND_PushCondition(SRV_REQUESTFAILED,
		      SRV_Message(SRV_REQUESTFAILED), "SRV_NActionRequest");

    if (messageType != MSG_K_N_ACTION_RESP) {
	(void) MSG_Free(&message);
	return COND_PushCondition(SRV_UNEXPECTEDCOMMAND,
			  SRV_Message(SRV_UNEXPECTEDCOMMAND), (int) command,
				  "SRV_NActionRequest");
    }
    localResponse = (MSG_N_ACTION_RESP *) message;

    if (localResponse->dataSetType == DCM_CMDDATANULL) {
	localResponse->actionReply = NULL;
    } else {
	/* application specific action reply needs to be received */
	cond = SRV_ReceiveDataSet(association, presentationCtx, DUL_BLOCK,
				  0, dirName, &localResponse->actionReply);
	if (cond != SRV_NORMAL) {
	    (void) MSG_Free(&message);
	    return COND_PushCondition(SRV_REQUESTFAILED,
		      SRV_Message(SRV_REQUESTFAILED), "SRV_NActionRequest");
	}
    }
    cond = actionCallback(actionRequest, localResponse, actionCtx);
    (void) MSG_Free(&message);
    if (localResponse->actionReply != NULL) {
	(void) DCM_CloseObject(&localResponse->actionReply);
	localResponse->actionReply = NULL;
    }
    if (actionResponse != NULL)
	*actionResponse = *localResponse;

    if (cond != SRV_NORMAL)
	return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE,
	     SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_NActionRequest");

    return SRV_NORMAL;
}
Beispiel #9
0
/* SRV_NSetRequest
**
** Purpose:
**	SRV_NSetRequest assists an application that wants to be an SCU of
**	a number of SOP classes. This function constructs an N-SET-REQ
**	message and sends it to the peer application which is acting as the
**	SCP for a SOP class. This function waits for the response from the
**	peer application and invokes the caller's callback function.
**
**	The arguments to the callback function are:
**		MSG_N_SET_REQ	*setRequest
**		MSG_N_SET_RESP	*setResponse
**		void		*setCtx
**
**	The first two arguments are MSG structures that contain the N-SET
**	Request and N-SET Response messages respectively. The final
**	argument is the caller's context variable that is passed to
**	SRV_NSetRequest.
**
**	The callback function should return SRV_NORMAL. Any other return
**	value will cause the SRV facility to abort the Association.
**
** Parameter Dictionary:
**	association	The key which is used to access an existing
**			association.
**	params		The list of parameters for the association. This
**			list includes the list of presentation contexts.
**	SOPClass	UID of the SOP class used when the association was
**			negotiated. Since this can be a meta class, it may
**			not be the same as the class UID in the N-SET
**			request message.
**	setRequest	Pointer to the structure with the N-SET request
**			parameters.
**	setResponse	Pointer to caller's pointer to an N-SET response.
**			This function will allocate an MSG_N_SET_RESP
**			message and return the pointer to the caller.
**	setCallback	Address of user callback function to be called
**			with the N-SET response from SCP.
**	setCtx		Pointer to user context information which will be
**			passed to the callback function. Caller uses this
**			variable to contain any context required for the
**			callback function.
**      dirName         Name of directory where files may be created.
**
**
** Return Values:
**
**	SRV_CALLBACKABORTEDSERVICE
**	SRV_ILLEGALPARAMETER
**	SRV_NOCALLBACK
**	SRV_NORMAL
**	SRV_OBJECTBUILDFAILED
**	SRV_REQUESTFAILED
**	SRV_UNEXPECTEDCOMMAND
**	SRV_UNSUPPORTEDSERVICE
**
** Algorithm:
**	Check if the callback function has been provided.
**	Determine the presentation context
**	Encode the N-SET request message as a command object and
**		send it to an SCP
**	Send data set, if one exists, to the SCP.
**	Wait for a response message to arrive from the SCP
**	Receive a data set, if one exists, from the SCP
**	Return address of Response message structure to caller.
**
** Notes:
**	The caller is responsible for explicitly setting the following
**	fields in the N-SET request message:
**
**	type
**	messageID
**	classUID
**	dataSetType
**	dataSet
**	instanceUID
**
**	The caller is also responsible for releasing the Response message
**	structure after the SRV_NSetRequest function returns,
**	using MSG_Free.
*/
CONDITION
SRV_NSetRequest(DUL_ASSOCIATIONKEY ** association,
		DUL_ASSOCIATESERVICEPARAMETERS * params,
		char *SOPClass,
		MSG_N_SET_REQ * setRequest, MSG_N_SET_RESP * setResponse,
	  SRV_N_SET_REQ_CALLBACK * setCallback, void *setCtx, char *dirName)
{
    DCM_OBJECT
	* commandObject;	/* Handle for a command object */
    CONDITION
	cond;			/* Return value from function calls */
    DUL_PRESENTATIONCONTEXT
	* presentationCtx;	/* Presentation context for this service */
    DUL_PRESENTATIONCONTEXTID
	ctxID;
    void
       *message;
    MSG_TYPE
	messageType;
    MSG_N_SET_RESP
	* localResponse;
    unsigned short
        command;

    if (setCallback == NULL)
	return COND_PushCondition(SRV_NOCALLBACK,
			    SRV_Message(SRV_NOCALLBACK), "SRV_NSetRequest");

    presentationCtx = SRVPRV_PresentationContext(params, SOPClass);
    if (presentationCtx == NULL)
	return COND_PushCondition(SRV_UNSUPPORTEDSERVICE,
				  SRV_Message(SRV_UNSUPPORTEDSERVICE),
				  setRequest->classUID, "SRV_NSetRequest");

    if (setRequest->type != MSG_K_N_SET_REQ)
	return COND_PushCondition(SRV_ILLEGALPARAMETER,
		 SRV_Message(SRV_ILLEGALPARAMETER), "type", "N-SET Request",
				  "SRV_NSetRequest");

    cond = MSG_BuildCommand(setRequest, &commandObject);
    if (cond != MSG_NORMAL)
	return COND_PushCondition(SRV_OBJECTBUILDFAILED,
			SRV_Message(SRV_OBJECTBUILDFAILED), "N-SET Request",
				  "SRV_NSetRequest");

    cond = SRV_SendCommand(association, presentationCtx, &commandObject);
    (void) DCM_CloseObject(&commandObject);
    if (cond != SRV_NORMAL)
	return COND_PushCondition(SRV_REQUESTFAILED,
			 SRV_Message(SRV_REQUESTFAILED), "SRV_NSetRequest");

    if (setRequest->dataSetType == DCM_CMDDATANULL)
	/* sending attribute list is mandatory */
	return COND_PushCondition(SRV_ILLEGALPARAMETER,
	  SRV_Message(SRV_ILLEGALPARAMETER), "dataSetType", "N-SET Request",
				  "SRV_NSetRequest");

    cond = SRV_SendDataSet(association, presentationCtx,
			   &setRequest->dataSet, NULL, NULL, 0);
    if (cond != SRV_NORMAL)
	return COND_PushCondition(SRV_REQUESTFAILED,
			 SRV_Message(SRV_REQUESTFAILED), "SRV_NSetRequest");

    cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID,
			      &command, &messageType, &message);
    if (cond != SRV_NORMAL)
	return COND_PushCondition(SRV_REQUESTFAILED,
			 SRV_Message(SRV_REQUESTFAILED), "SRV_NSetRequest");

    if (messageType != MSG_K_N_SET_RESP) {
	(void) MSG_Free(&message);
	return COND_PushCondition(SRV_UNEXPECTEDCOMMAND,
			  SRV_Message(SRV_UNEXPECTEDCOMMAND), (int) command,
				  "SRV_NSetRequest");
    }
    localResponse = (MSG_N_SET_RESP *) message;

    if (localResponse->dataSetType == DCM_CMDDATANULL) {
	localResponse->dataSet = NULL;
    } else {
	cond = SRV_ReceiveDataSet(association, presentationCtx,
			    DUL_BLOCK, 0, dirName, &localResponse->dataSet);
	if (cond != SRV_NORMAL) {
	    (void) MSG_Free(&message);
	    return COND_PushCondition(SRV_REQUESTFAILED,
			 SRV_Message(SRV_REQUESTFAILED), "SRV_NSetRequest");
	}
    }
    cond = setCallback(setRequest, localResponse, setCtx);
    (void) MSG_Free(&message);
    if (localResponse->dataSet != NULL) {
	(void) DCM_CloseObject(&localResponse->dataSet);
	localResponse->dataSet = NULL;
    }
    if (setResponse != NULL)
	*setResponse = *localResponse;
    if (cond != SRV_NORMAL)
	return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE,
		SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_NSetRequest");

    return SRV_NORMAL;
}
Beispiel #10
0
CONDITION
SRV_CStoreResponse(DUL_ASSOCIATIONKEY ** association, DUL_PRESENTATIONCONTEXT * ctx, MSG_C_STORE_REQ ** storeRequest, MSG_C_STORE_RESP * storeReply,
				   char *fileName, SRV_C_STORE_RESP_CALLBACK * callback, void *callbackCtx, char *dirName)
{
    int		        	fd, done;
    unsigned long		total, estimatedSize, nextCallback;
    unsigned short      sendStatus = 0x0000;
    DUL_PDV				pdv;
    CONDITION			cond;
    DCM_OBJECT			* object;
    DCM_FILE_META 		fileMeta;
    int 				storeAsPart10 = 0;
    char* 				paramValue;

    storeReply->messageIDRespondedTo = (*storeRequest)->messageID;
    storeReply->type = MSG_K_C_STORE_RESP;
    (void) strcpy(storeReply->classUID, (*storeRequest)->classUID);
    (void) strcpy(storeReply->instanceUID, (*storeRequest)->instanceUID);
    storeReply->conditionalFields = MSG_K_C_STORERESP_CLASSUID | MSG_K_C_STORERESP_INSTANCEUID;
    storeReply->dataSetType = DCM_CMDDATANULL;

    if (strlen(fileName) == 0 || fileName == NULL) {
    	fd = -1;
    }else{
#ifdef _MSC_VER
    	fd = _open(fileName, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, _S_IREAD | _S_IWRITE);
#else
    	fd = open(fileName, O_CREAT | O_WRONLY | O_TRUNC, 0666);
#endif
    	if (fd < 0) (void) COND_PushCondition(SRV_FILECREATEFAILED, SRV_Message(SRV_FILECREATEFAILED), fileName, "SRV_CStoreResponse");
    }
    if (strcmp(ctx->acceptedTransferSyntax, DICOM_TRANSFERLITTLEENDIAN) != 0){
    	storeAsPart10 = 1;
    }else{
    	paramValue = UTL_GetConfigParameter("STORAGE/PART10FLAG");
    	if (paramValue != NULL) {
    		if (strcmp(paramValue, "1") == 0) storeAsPart10 = 1;
    	}
    }
    if ((storeAsPart10 == 1) && (fd > 0)){
    	int localStatus = 0;
    	memset(&fileMeta, 0, sizeof(fileMeta));
    	setFileMeta(&fileMeta, *storeRequest, ctx->acceptedTransferSyntax);
    	localStatus = writePart10MetaHeader(fd, &fileMeta);
    	if (localStatus != 0) fd = -1;
    }
    if (fd < 0) {
    	sendStatus = MSG_K_C_STORE_OUTOFRESOURCES;
    	storeReply->conditionalFields |= MSG_K_C_STORERESP_ERRORCOMMENT;
    	strcpy(storeReply->errorComment, "Storage Service unable to create local file");
    	fprintf(stderr,"Storage Service unable to create local file\n");
    }
    done = 0;
    total = 0;
    estimatedSize = genericImageSize((*storeRequest)->classUID);
    nextCallback = estimatedSize / 10;

    while (!done) {
    	cond = SRVPRV_ReadNextPDV(association, DUL_BLOCK, 0, &pdv);
    	if (cond != SRV_NORMAL) {
    		(void) MSG_Free((void **) storeRequest);
    		return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse");
    	}

    	if (pdv.pdvType != DUL_DATASETPDV) {
    		(void) MSG_Free((void **) storeRequest);
    		return COND_PushCondition(SRV_UNEXPECTEDPDVTYPE, SRV_Message(SRV_UNEXPECTEDPDVTYPE), (int) pdv.pdvType, "SRV_CStoreResponse");
    	}

    	if (sendStatus == 0) if (write(fd, pdv.data, pdv.fragmentLength) != (int) pdv.fragmentLength) sendStatus = MSG_K_C_STORE_OUTOFRESOURCES;

    	total += pdv.fragmentLength;
    	if (pdv.lastPDV) done++;

    	if (total > nextCallback){
    		cond = callback(*storeRequest, NULL, total, estimatedSize, NULL, callbackCtx, ctx);
    		if (cond != SRV_NORMAL){
    			(void) MSG_Free((void **) storeRequest);
    			return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse");
    		}
    		nextCallback += estimatedSize / 10;
    	}
    }
    if (fd >= 0) (void) close(fd);

    storeReply->status = sendStatus;

    if (sendStatus == 0x0000) {
    	unsigned long options = DCM_ORDERLITTLEENDIAN;
    	if (storeAsPart10 == 1) options = DCM_PART10FILE;

    	cond = DCM_OpenFile(fileName, options, &object);
    	if (cond != DCM_NORMAL) {
    		(void) MSG_Free((void **) storeRequest);
    		return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse");
    	}

    	cond = callback(*storeRequest, storeReply, total, estimatedSize, &object, callbackCtx, ctx);
    	if (cond != SRV_NORMAL) {
    		(void) DCM_CloseObject(&object);
    		return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse");
    	}
    	(void) DCM_CloseObject(&object);
    }
    (void) MSG_Free((void **) storeRequest);

    cond = MSG_BuildCommand(storeReply, &object);
    if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "STORE Request", "SRV_CStoreResponse");

    cond = SRV_SendCommand(association, ctx, &object);
    (void) DCM_CloseObject(&object);
    if (cond != SRV_NORMAL)	return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse");

    return SRV_NORMAL;
}
Beispiel #11
0
CONDITION
SRV_CStoreRequest(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params, MSG_C_STORE_REQ * storeRequest, MSG_C_STORE_RESP * storeResponse,
				  SRV_C_STORE_REQ_CALLBACK * callback, void *callbackCtx, char *dirName)
{
    DCM_OBJECT					* commandObject,	/* Handle for a command object */
								*dataSetObject;		/* Handle for a Data Set object */
    CONDITION					cond;				/* Return value from function calls */
    DUL_PRESENTATIONCONTEXT		* presentationCtx;	/* Presentation context for this service */
    DUL_PRESENTATIONCONTEXTID	ctxID;
    void				       *message;
    MSG_TYPE					messageType;
    unsigned long		        objectSize;
    unsigned short		        command;
    STORAGE_CTX					localCtx;
    MSG_C_STORE_RESP			* response;

    localCtx.callback = callback;
    localCtx.storeRequest = storeRequest;
    localCtx.storeResponse = NULL;
    localCtx.userCtx = callbackCtx;

    if (callback == NULL)
    	return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_CStoreRequest");
    if (storeRequest->type != MSG_K_C_STORE_REQ)
    	return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "STORE Request", "SRV_CStoreRequest");
    if (storeRequest->dataSetType == DCM_CMDDATANULL)
    	return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "dataSetType", "STORE Request", "SRV_CStoreRequest");

    presentationCtx = SRVPRV_PresentationContext(params, storeRequest->classUID);
    if (presentationCtx == NULL)
    	return COND_PushCondition(SRV_NOSERVICEINASSOCIATION, SRV_Message(SRV_NOSERVICEINASSOCIATION), storeRequest->classUID, "SRV_CStoreRequest");

    cond = MSG_BuildCommand(storeRequest, &commandObject);
    if (cond != MSG_NORMAL)	return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "STORE Request", "SRV_CStoreRequest");

    dataSetObject = storeRequest->dataSet;
    if (dataSetObject == NULL) {
    	cond = DCM_OpenFile(storeRequest->fileName, DCM_ORDERLITTLEENDIAN, &dataSetObject);
    	if (cond != DCM_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest");
    }

    cond = DCM_GetObjectSize(&dataSetObject, &objectSize);
    if (cond != DCM_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest");


    cond = SRV_SendCommand(association, presentationCtx, &commandObject);
    (void) DCM_CloseObject(&commandObject);
    if (cond != SRV_NORMAL)	return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest");

    cond = callback(storeRequest, NULL, 0, objectSize, callbackCtx);
    if (cond != SRV_NORMAL)	return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest");

    cond = SRV_SendDataSet(association, presentationCtx, &dataSetObject, localCallback, &localCtx, objectSize);
    if (storeRequest->dataSet == NULL) (void) DCM_CloseObject(&dataSetObject);
    if (cond != SRV_NORMAL)	return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest");


    cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID, &command, &messageType, &message);
    if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest");

    if (messageType != MSG_K_C_STORE_RESP) {
    	(void) MSG_Free(&message);
    	return COND_PushCondition(SRV_UNEXPECTEDCOMMAND, SRV_Message(SRV_UNEXPECTEDCOMMAND), (int) command, "SRV_CStoreRequest");
    }
    response = (MSG_C_STORE_RESP *) message;
    if (storeResponse != NULL) *storeResponse = *response;

    cond = callback(storeRequest, response, objectSize, objectSize, callbackCtx);
    (void) MSG_Free(&message);
    if (cond != SRV_NORMAL)	return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_CStoreRequest");

    return SRV_NORMAL;
}