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; }
/* ** 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; }
/* 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; }
/* 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; }
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; }
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; } }
/* 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 */ }
/* 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; }
/* 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; }
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; }
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; }