1 /*
2 *
3 * Copyright (C) 1998-2018, OFFIS e.V.
4 * All rights reserved. See COPYRIGHT file for details.
5 *
6 * This software and supporting documentation were developed by
7 *
8 * OFFIS e.V.
9 * R&D Division Health
10 * Escherweg 2
11 * D-26121 Oldenburg, Germany
12 *
13 *
14 * Module: dcmpstat
15 *
16 * Author: Marco Eichelberg
17 *
18 * Purpose:
19 * classes: DVPSPrintMessageHandler
20 *
21 */
22
23 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
24
25 #include "dcmtk/ofstd/ofstring.h"
26 #include "dcmtk/ofstd/ofstd.h"
27 #include "dcmtk/dcmpstat/dvpsdef.h"
28 #include "dcmtk/dcmpstat/dvpspr.h"
29
30 /* --------------- class DVPSPrintMessageHandler --------------- */
31
DVPSPrintMessageHandler()32 DVPSPrintMessageHandler::DVPSPrintMessageHandler()
33 : assoc(NULL)
34 , net(NULL)
35 , eventHandler(NULL)
36 , blockMode(DIMSE_BLOCKING)
37 , timeout(0)
38 {
39 }
40
~DVPSPrintMessageHandler()41 DVPSPrintMessageHandler::~DVPSPrintMessageHandler()
42 {
43 abortAssociation(); // won't do any harm if there is no association in place
44 }
45
dumpNMessage(T_DIMSE_Message & msg,DcmItem * dataset,OFBool outgoing)46 void DVPSPrintMessageHandler::dumpNMessage(T_DIMSE_Message &msg, DcmItem *dataset, OFBool outgoing)
47 {
48 OFString str;
49 if (outgoing) {
50 DIMSE_dumpMessage(str, msg, DIMSE_OUTGOING, dataset);
51 } else {
52 DIMSE_dumpMessage(str, msg, DIMSE_INCOMING, dataset);
53 }
54 DCMPSTAT_DUMP(str);
55 }
56
sendNRequest(T_ASC_PresentationContextID presId,T_DIMSE_Message & request,DcmDataset * rqDataSet,T_DIMSE_Message & response,DcmDataset * & statusDetail,DcmDataset * & rspDataset)57 OFCondition DVPSPrintMessageHandler::sendNRequest(
58 T_ASC_PresentationContextID presId,
59 T_DIMSE_Message &request,
60 DcmDataset *rqDataSet,
61 T_DIMSE_Message &response,
62 DcmDataset* &statusDetail,
63 DcmDataset* &rspDataset)
64 {
65 OFCondition cond = EC_Normal;
66 T_DIMSE_Command expectedResponse;
67 DIC_US expectedMessageID=0;
68 if (assoc == NULL)
69 {
70 return DIMSE_ILLEGALASSOCIATION;
71 }
72
73 T_DIMSE_DataSetType datasetType = DIMSE_DATASET_NULL;
74 if (rqDataSet && (rqDataSet->card() > 0)) datasetType = DIMSE_DATASET_PRESENT;
75
76 switch(request.CommandField)
77 {
78 case DIMSE_N_GET_RQ:
79 request.msg.NGetRQ.DataSetType = datasetType;
80 expectedResponse = DIMSE_N_GET_RSP;
81 expectedMessageID = request.msg.NGetRQ.MessageID;
82 break;
83 case DIMSE_N_SET_RQ:
84 request.msg.NSetRQ.DataSetType = datasetType;
85 expectedResponse = DIMSE_N_SET_RSP;
86 expectedMessageID = request.msg.NSetRQ.MessageID;
87 break;
88 case DIMSE_N_ACTION_RQ:
89 request.msg.NActionRQ.DataSetType = datasetType;
90 expectedResponse = DIMSE_N_ACTION_RSP;
91 expectedMessageID = request.msg.NActionRQ.MessageID;
92 break;
93 case DIMSE_N_CREATE_RQ:
94 request.msg.NCreateRQ.DataSetType = datasetType;
95 expectedResponse = DIMSE_N_CREATE_RSP;
96 expectedMessageID = request.msg.NCreateRQ.MessageID;
97 break;
98 case DIMSE_N_DELETE_RQ:
99 request.msg.NDeleteRQ.DataSetType = datasetType;
100 expectedResponse = DIMSE_N_DELETE_RSP;
101 expectedMessageID = request.msg.NDeleteRQ.MessageID;
102 break;
103 default:
104 return DIMSE_BADCOMMANDTYPE;
105 /* break; */
106 }
107
108 dumpNMessage(request, rqDataSet, OFTrue);
109 cond = DIMSE_sendMessageUsingMemoryData(assoc, presId, &request, NULL, rqDataSet, NULL, NULL);
110 if (cond.bad()) return cond;
111
112 T_ASC_PresentationContextID thisPresId;
113 T_DIMSE_Message eventReportRsp;
114 DIC_US eventReportStatus;
115 do
116 {
117 thisPresId = presId;
118 statusDetail = NULL;
119 cond = DIMSE_receiveCommand(assoc, blockMode, timeout, &thisPresId, &response, &statusDetail);
120 if (cond.bad()) return cond;
121
122 if (response.CommandField == DIMSE_N_EVENT_REPORT_RQ)
123 {
124 /* handle N-EVENT-REPORT-RQ */
125 rspDataset = NULL;
126 if (response.msg.NEventReportRQ.DataSetType == DIMSE_DATASET_PRESENT)
127 {
128 cond = DIMSE_receiveDataSetInMemory(assoc, blockMode, timeout, &thisPresId, &rspDataset, NULL, NULL);
129 if (cond.bad()) return cond;
130 }
131 dumpNMessage(response, rspDataset, OFFalse);
132 // call event handler if registered
133 eventReportStatus = STATUS_Success;
134 if (eventHandler) eventReportStatus = eventHandler->handleEvent(response.msg.NEventReportRQ, rspDataset, statusDetail);
135 if (rspDataset) delete rspDataset;
136 rspDataset = NULL;
137 if (statusDetail) delete statusDetail;
138 statusDetail = NULL;
139
140 // send back N-EVENT-REPORT-RSP */
141 eventReportRsp.CommandField = DIMSE_N_EVENT_REPORT_RSP;
142 eventReportRsp.msg.NEventReportRSP.MessageIDBeingRespondedTo = response.msg.NEventReportRQ.MessageID;
143 eventReportRsp.msg.NEventReportRSP.EventTypeID = response.msg.NEventReportRQ.EventTypeID;
144 eventReportRsp.msg.NEventReportRSP.DimseStatus = eventReportStatus;
145 eventReportRsp.msg.NEventReportRSP.DataSetType = DIMSE_DATASET_NULL;
146 eventReportRsp.msg.NEventReportRSP.opts = O_NEVENTREPORT_EVENTTYPEID;
147 eventReportRsp.msg.NEventReportRSP.AffectedSOPClassUID[0] = 0;
148 eventReportRsp.msg.NEventReportRSP.AffectedSOPInstanceUID[0] = 0;
149 dumpNMessage(eventReportRsp, NULL, OFTrue);
150 cond = DIMSE_sendMessageUsingMemoryData(assoc, thisPresId, &eventReportRsp, NULL, NULL, NULL, NULL);
151 if (cond.bad()) return cond;
152 } else {
153 /* No N-EVENT-REPORT-RQ. Check if this message is what we expected */
154 if (response.CommandField != expectedResponse)
155 {
156 char buf1[256];
157 sprintf(buf1, "DIMSE: Unexpected Response Command Field: 0x%x", (unsigned)response.CommandField);
158 return makeDcmnetCondition(DIMSEC_UNEXPECTEDRESPONSE, OF_error, buf1);
159 }
160 T_DIMSE_DataSetType responseDataset = DIMSE_DATASET_NULL;
161 DIC_US responseMessageID = 0;
162 /** change request to response */
163 switch(expectedResponse)
164 {
165 case DIMSE_N_GET_RSP:
166 responseDataset = response.msg.NGetRSP.DataSetType;
167 responseMessageID = response.msg.NGetRSP.MessageIDBeingRespondedTo;
168 break;
169 case DIMSE_N_SET_RSP:
170 responseDataset = response.msg.NSetRSP.DataSetType;
171 responseMessageID = response.msg.NSetRSP.MessageIDBeingRespondedTo;
172 break;
173 case DIMSE_N_ACTION_RSP:
174 responseDataset = response.msg.NActionRSP.DataSetType;
175 responseMessageID = response.msg.NActionRSP.MessageIDBeingRespondedTo;
176 break;
177 case DIMSE_N_CREATE_RSP:
178 responseDataset = response.msg.NCreateRSP.DataSetType;
179 responseMessageID = response.msg.NCreateRSP.MessageIDBeingRespondedTo;
180 break;
181 case DIMSE_N_DELETE_RSP:
182 responseDataset = response.msg.NDeleteRSP.DataSetType;
183 responseMessageID = response.msg.NDeleteRSP.MessageIDBeingRespondedTo;
184 break;
185 default:
186 {
187 char buf1[256];
188 sprintf(buf1, "DIMSE: Unexpected Response Command Field: 0x%x", (unsigned)response.CommandField);
189 return makeDcmnetCondition(DIMSEC_UNEXPECTEDRESPONSE, OF_error, buf1);
190 }
191 /* break; */
192 }
193 if (responseMessageID != expectedMessageID)
194 {
195 char buf1[256];
196 sprintf(buf1, "DIMSE: Unexpected Response Command Field: 0x%x", (unsigned)response.CommandField);
197 return makeDcmnetCondition(DIMSEC_UNEXPECTEDRESPONSE, OF_error, buf1);
198 }
199 rspDataset = NULL;
200 if (responseDataset == DIMSE_DATASET_PRESENT)
201 {
202 cond = DIMSE_receiveDataSetInMemory(assoc, blockMode, timeout, &thisPresId, &rspDataset, NULL, NULL);
203 if (cond.bad()) return cond;
204 }
205 dumpNMessage(response, rspDataset, OFFalse);
206 }
207 } while (response.CommandField == DIMSE_N_EVENT_REPORT_RQ);
208 return EC_Normal;
209 }
210
createRQ(const char * sopclassUID,OFString & sopinstanceUID,DcmDataset * attributeListIn,Uint16 & status,DcmDataset * & attributeListOut)211 OFCondition DVPSPrintMessageHandler::createRQ(
212 const char *sopclassUID,
213 OFString& sopinstanceUID,
214 DcmDataset *attributeListIn,
215 Uint16& status,
216 DcmDataset* &attributeListOut)
217 {
218 if (assoc == NULL)
219 {
220 return DIMSE_ILLEGALASSOCIATION;
221 }
222 if (sopclassUID==NULL)
223 {
224 return DIMSE_NULLKEY;
225 }
226
227 T_ASC_PresentationContextID presCtx = findAcceptedPC(sopclassUID);
228 if (presCtx == 0)
229 {
230 return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
231 }
232
233 T_DIMSE_Message request;
234 T_DIMSE_Message response;
235 DcmDataset *statusDetail = NULL;
236
237 // construct N-CREATE-RQ
238 request.CommandField = DIMSE_N_CREATE_RQ;
239 request.msg.NCreateRQ.MessageID = assoc->nextMsgID++;
240 OFStandard::strlcpy(request.msg.NCreateRQ.AffectedSOPClassUID, sopclassUID, sizeof(request.msg.NCreateRQ.AffectedSOPClassUID));
241 if (sopinstanceUID.size() > 0)
242 {
243 OFStandard::strlcpy(request.msg.NCreateRQ.AffectedSOPInstanceUID, sopinstanceUID.c_str(), sizeof(request.msg.NCreateRQ.AffectedSOPInstanceUID));
244 request.msg.NCreateRQ.opts = O_NCREATE_AFFECTEDSOPINSTANCEUID;
245 } else {
246 request.msg.NCreateRQ.AffectedSOPInstanceUID[0] = 0;
247 request.msg.NCreateRQ.opts = 0;
248 }
249
250 OFCondition cond = sendNRequest(presCtx, request, attributeListIn, response, statusDetail, attributeListOut);
251 if (cond.good())
252 {
253 status = response.msg.NCreateRSP.DimseStatus;
254 // if response contains SOP Instance UID, copy it.
255 if (response.msg.NCreateRSP.opts & O_NCREATE_AFFECTEDSOPINSTANCEUID)
256 {
257 sopinstanceUID = response.msg.NCreateRSP.AffectedSOPInstanceUID;
258 }
259 }
260 if (statusDetail) delete statusDetail;
261 return cond;
262 }
263
setRQ(const char * sopclassUID,const char * sopinstanceUID,DcmDataset * modificationList,Uint16 & status,DcmDataset * & attributeListOut)264 OFCondition DVPSPrintMessageHandler::setRQ(
265 const char *sopclassUID,
266 const char *sopinstanceUID,
267 DcmDataset *modificationList,
268 Uint16& status,
269 DcmDataset* &attributeListOut)
270 {
271 if (assoc == NULL)
272 {
273 return DIMSE_ILLEGALASSOCIATION;
274 }
275 if ((sopclassUID==NULL)||(sopinstanceUID==NULL)||(modificationList==NULL))
276 {
277 return DIMSE_NULLKEY;
278 }
279
280 T_ASC_PresentationContextID presCtx = findAcceptedPC(sopclassUID);
281 if (presCtx == 0)
282 {
283 return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
284 }
285
286 T_DIMSE_Message request;
287 T_DIMSE_Message response;
288 DcmDataset *statusDetail = NULL;
289
290 // construct N-SET-RQ
291 request.CommandField = DIMSE_N_SET_RQ;
292 request.msg.NSetRQ.MessageID = assoc->nextMsgID++;
293 OFStandard::strlcpy(request.msg.NSetRQ.RequestedSOPClassUID, sopclassUID, sizeof(request.msg.NSetRQ.RequestedSOPClassUID));
294 OFStandard::strlcpy(request.msg.NSetRQ.RequestedSOPInstanceUID, sopinstanceUID, sizeof(request.msg.NSetRQ.RequestedSOPInstanceUID));
295
296 OFCondition cond = sendNRequest(presCtx, request, modificationList, response, statusDetail, attributeListOut);
297 if (cond.good()) status = response.msg.NSetRSP.DimseStatus;
298 if (statusDetail) delete statusDetail;
299 return cond;
300 }
301
getRQ(const char * sopclassUID,const char * sopinstanceUID,const Uint16 * attributeIdentifierList,size_t numShorts,Uint16 & status,DcmDataset * & attributeListOut)302 OFCondition DVPSPrintMessageHandler::getRQ(
303 const char *sopclassUID,
304 const char *sopinstanceUID,
305 const Uint16 *attributeIdentifierList,
306 size_t numShorts,
307 Uint16& status,
308 DcmDataset* &attributeListOut)
309 {
310 if (assoc == NULL)
311 {
312 return DIMSE_ILLEGALASSOCIATION;
313 }
314 if ((sopclassUID==NULL)||(sopinstanceUID==NULL))
315 {
316 return DIMSE_NULLKEY;
317 }
318
319 T_ASC_PresentationContextID presCtx = findAcceptedPC(sopclassUID);
320 if (presCtx == 0)
321 {
322 return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
323 }
324
325 T_DIMSE_Message request;
326 T_DIMSE_Message response;
327 DcmDataset *statusDetail = NULL;
328
329 // construct N-GET-RQ
330 request.CommandField = DIMSE_N_GET_RQ;
331 request.msg.NGetRQ.MessageID = assoc->nextMsgID++;
332 OFStandard::strlcpy(request.msg.NGetRQ.RequestedSOPClassUID, sopclassUID, sizeof(request.msg.NGetRQ.RequestedSOPClassUID));
333 OFStandard::strlcpy(request.msg.NGetRQ.RequestedSOPInstanceUID, sopinstanceUID, sizeof(request.msg.NGetRQ.RequestedSOPInstanceUID));
334 request.msg.NGetRQ.ListCount = 0;
335 if (attributeIdentifierList) request.msg.NGetRQ.ListCount = (int)numShorts;
336 request.msg.NGetRQ.AttributeIdentifierList = (DIC_US *)attributeIdentifierList;
337
338 OFCondition cond = sendNRequest(presCtx, request, NULL, response, statusDetail, attributeListOut);
339 if (cond.good()) status = response.msg.NGetRSP.DimseStatus;
340 if (statusDetail) delete statusDetail;
341 return cond;
342 }
343
344
actionRQ(const char * sopclassUID,const char * sopinstanceUID,Uint16 actionTypeID,DcmDataset * actionInformation,Uint16 & status,DcmDataset * & actionReply)345 OFCondition DVPSPrintMessageHandler::actionRQ(
346 const char *sopclassUID,
347 const char *sopinstanceUID,
348 Uint16 actionTypeID,
349 DcmDataset *actionInformation,
350 Uint16& status,
351 DcmDataset* &actionReply)
352 {
353 if (assoc == NULL)
354 {
355 return DIMSE_ILLEGALASSOCIATION;
356 }
357 if ((sopclassUID==NULL)||(sopinstanceUID==NULL))
358 {
359 return DIMSE_NULLKEY;
360 }
361
362 T_ASC_PresentationContextID presCtx = findAcceptedPC(sopclassUID);
363 if (presCtx == 0)
364 {
365 return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
366 }
367
368 T_DIMSE_Message request;
369 T_DIMSE_Message response;
370 DcmDataset *statusDetail = NULL;
371
372 // construct N-ACTION-RQ
373 request.CommandField = DIMSE_N_ACTION_RQ;
374 request.msg.NActionRQ.MessageID = assoc->nextMsgID++;
375 OFStandard::strlcpy(request.msg.NActionRQ.RequestedSOPClassUID, sopclassUID, sizeof(request.msg.NActionRQ.RequestedSOPClassUID));
376 OFStandard::strlcpy(request.msg.NActionRQ.RequestedSOPInstanceUID, sopinstanceUID, sizeof(request.msg.NActionRQ.RequestedSOPInstanceUID));
377 request.msg.NActionRQ.ActionTypeID = (DIC_US)actionTypeID;
378
379 OFCondition cond = sendNRequest(presCtx, request, actionInformation, response, statusDetail, actionReply);
380 if (cond.good()) status = response.msg.NActionRSP.DimseStatus;
381 if (statusDetail) delete statusDetail;
382 return cond;
383 }
384
deleteRQ(const char * sopclassUID,const char * sopinstanceUID,Uint16 & status)385 OFCondition DVPSPrintMessageHandler::deleteRQ(
386 const char *sopclassUID,
387 const char *sopinstanceUID,
388 Uint16& status)
389 {
390 if (assoc == NULL)
391 {
392 return DIMSE_ILLEGALASSOCIATION;
393 }
394 if ((sopclassUID==NULL)||(sopinstanceUID==NULL))
395 {
396 return DIMSE_NULLKEY;
397 }
398
399 T_ASC_PresentationContextID presCtx = findAcceptedPC(sopclassUID);
400 if (presCtx == 0)
401 {
402 return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
403 }
404
405 T_DIMSE_Message request;
406 T_DIMSE_Message response;
407 DcmDataset *statusDetail = NULL;
408 DcmDataset *attributeListOut = NULL;
409
410 // construct N-DELETE-RQ
411 request.CommandField = DIMSE_N_DELETE_RQ;
412 request.msg.NDeleteRQ.MessageID = assoc->nextMsgID++;
413 OFStandard::strlcpy(request.msg.NDeleteRQ.RequestedSOPClassUID, sopclassUID, sizeof(request.msg.NDeleteRQ.RequestedSOPClassUID));
414 OFStandard::strlcpy(request.msg.NDeleteRQ.RequestedSOPInstanceUID, sopinstanceUID, sizeof(request.msg.NDeleteRQ.RequestedSOPInstanceUID));
415
416 OFCondition cond = sendNRequest(presCtx, request, NULL, response, statusDetail, attributeListOut);
417 if (cond.good()) status = response.msg.NDeleteRSP.DimseStatus;
418 if (statusDetail) delete statusDetail;
419 if (attributeListOut) delete attributeListOut; // should never happen
420 return cond;
421 }
422
releaseAssociation()423 OFCondition DVPSPrintMessageHandler::releaseAssociation()
424 {
425 OFCondition result = EC_Normal;
426 if (assoc)
427 {
428 result = ASC_releaseAssociation(assoc);
429 ASC_destroyAssociation(&assoc);
430 ASC_dropNetwork(&net);
431 assoc = NULL;
432 net = NULL;
433 }
434 return result;
435 }
436
abortAssociation()437 OFCondition DVPSPrintMessageHandler::abortAssociation()
438 {
439 OFCondition result = EC_Normal;
440 if (assoc)
441 {
442 result = ASC_abortAssociation(assoc);
443 ASC_destroyAssociation(&assoc);
444 ASC_dropNetwork(&net);
445 assoc = NULL;
446 net = NULL;
447 }
448 return result;
449 }
450
findAcceptedPC(const char * sopclassuid)451 T_ASC_PresentationContextID DVPSPrintMessageHandler::findAcceptedPC(const char *sopclassuid)
452 {
453 if ((assoc==NULL)||(sopclassuid==NULL)) return 0;
454
455 // if the SOP class is one of the Basic Grayscale Print Management Meta SOP Classes,
456 // look for a presentation context for Basic Grayscale Print.
457 OFString sopclass(sopclassuid);
458 if ((sopclass == UID_BasicFilmSessionSOPClass) ||
459 (sopclass == UID_BasicFilmBoxSOPClass) ||
460 (sopclass == UID_BasicGrayscaleImageBoxSOPClass) ||
461 (sopclass == UID_PrinterSOPClass)) sopclassuid = UID_BasicGrayscalePrintManagementMetaSOPClass;
462 return ASC_findAcceptedPresentationContextID(assoc, sopclassuid);
463 }
464
465
negotiateAssociation(DcmTransportLayer * tlayer,const char * myAEtitle,const char * peerAEtitle,const char * peerHost,int peerPort,long peerMaxPDU,OFBool negotiatePresentationLUT,OFBool negotiateAnnotationBox,OFBool implicitOnly)466 OFCondition DVPSPrintMessageHandler::negotiateAssociation(
467 DcmTransportLayer *tlayer,
468 const char *myAEtitle,
469 const char *peerAEtitle,
470 const char *peerHost,
471 int peerPort,
472 long peerMaxPDU,
473 OFBool negotiatePresentationLUT,
474 OFBool negotiateAnnotationBox,
475 OFBool implicitOnly)
476 {
477 if (assoc)
478 {
479 return makeDcmnetCondition(DIMSEC_ILLEGALASSOCIATION, OF_error, "association already in place");
480 }
481 if ((myAEtitle==NULL)||(peerAEtitle==NULL)||(peerHost==NULL))
482 {
483 return DIMSE_NULLKEY;
484 }
485
486 T_ASC_Parameters *params=NULL;
487 DIC_NODENAME dnpeerHost;
488
489 OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, 30, &net);
490 if (cond.good()) cond = ASC_createAssociationParameters(¶ms, peerMaxPDU);
491
492 if (tlayer && cond.good())
493 {
494 cond = ASC_setTransportLayer(net, tlayer, 0);
495 if (cond.good()) cond = ASC_setTransportLayerType(params, OFTrue /* use TLS */);
496 }
497
498 if (cond.bad()) return cond;
499
500 ASC_setAPTitles(params, myAEtitle, peerAEtitle, NULL);
501 sprintf(dnpeerHost, "%s:%d", peerHost, peerPort);
502 ASC_setPresentationAddresses(params, OFStandard::getHostName().c_str(), dnpeerHost);
503
504 /* presentation contexts */
505 const char* transferSyntaxes[3];
506 int transferSyntaxCount = 0;
507
508 if (implicitOnly)
509 {
510 transferSyntaxes[0] = UID_LittleEndianImplicitTransferSyntax;
511 transferSyntaxCount = 1;
512 } else {
513 /* gLocalByteOrder is defined in dcxfer.h */
514 if (gLocalByteOrder == EBO_LittleEndian) {
515 /* we are on a little endian machine */
516 transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax;
517 transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax;
518 } else {
519 /* we are on a big endian machine */
520 transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax;
521 transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax;
522 }
523 transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
524 transferSyntaxCount = 3;
525 }
526
527 /* we always propose basic grayscale, presentation LUT and annotation box*/
528 if (cond.good()) cond = ASC_addPresentationContext(params, 1, UID_BasicGrayscalePrintManagementMetaSOPClass, transferSyntaxes, transferSyntaxCount);
529 if (negotiatePresentationLUT)
530 {
531 if (cond.good()) cond = ASC_addPresentationContext(params, 3, UID_PresentationLUTSOPClass, transferSyntaxes, transferSyntaxCount);
532 }
533
534 if (negotiateAnnotationBox)
535 {
536 if (cond.good()) cond = ASC_addPresentationContext(params, 5, UID_BasicAnnotationBoxSOPClass, transferSyntaxes, transferSyntaxCount);
537 }
538
539 /* create association */
540 DCMPSTAT_INFO("Requesting Association");
541
542 if (cond.good())
543 {
544 cond = ASC_requestAssociation(net, params, &assoc);
545
546 if (cond == DUL_ASSOCIATIONREJECTED)
547 {
548 OFString temp_str;
549 T_ASC_RejectParameters rej;
550 ASC_getRejectParameters(params, &rej);
551 DCMPSTAT_WARN("Association Rejected" << OFendl << ASC_printRejectParameters(temp_str, &rej));
552 } else {
553 if (cond.bad())
554 {
555 // if assoc is non-NULL, then params has already been moved into the
556 // assoc structure. Make sure we only delete once!
557 if (assoc) ASC_destroyAssociation(&assoc);
558 else if (params) ASC_destroyAssociationParameters(¶ms);
559
560 if (net) ASC_dropNetwork(&net);
561 assoc = NULL;
562 net = NULL;
563 return cond;
564 }
565 }
566 }
567
568 if ((cond.good()) && (0 == ASC_findAcceptedPresentationContextID(assoc, UID_BasicGrayscalePrintManagementMetaSOPClass)))
569 {
570 DCMPSTAT_WARN("Peer does not support Basic Grayscale Print Management, aborting association.");
571 abortAssociation();
572 cond = DIMSE_NOVALIDPRESENTATIONCONTEXTID;
573 }
574
575 if (cond.good())
576 {
577 DCMPSTAT_INFO("Association accepted (Max Send PDV: " << assoc->sendPDVLength << ")");
578 } else {
579 // params is now an alias to assoc->params. Don't call ASC_destroyAssociationParameters.
580 if (assoc) ASC_destroyAssociation(&assoc);
581 if (net) ASC_dropNetwork(&net);
582 assoc = NULL;
583 net = NULL;
584 }
585
586 return cond;
587 }
588
printerSupportsPresentationLUT()589 OFBool DVPSPrintMessageHandler::printerSupportsPresentationLUT()
590 {
591 if ((assoc)&&(0 != ASC_findAcceptedPresentationContextID(assoc, UID_PresentationLUTSOPClass))) return OFTrue;
592 return OFFalse;
593 }
594
printerSupportsAnnotationBox()595 OFBool DVPSPrintMessageHandler::printerSupportsAnnotationBox()
596 {
597 if ((assoc)&&(0 != ASC_findAcceptedPresentationContextID(assoc, UID_BasicAnnotationBoxSOPClass))) return OFTrue;
598 return OFFalse;
599 }
600