Mercurial > hg > orthanc
comparison OrthancServer/Internals/CommandDispatcher.cpp @ 1163:3db41779d8f9
abstraction to allow/prevent transfer syntaxes on AET basis
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 17 Sep 2014 17:23:08 +0200 |
parents | b161593551db |
children | 0a55d8eb194e |
comparison
equal
deleted
inserted
replaced
1160:80671157d051 | 1163:3db41779d8f9 |
---|---|
457 // no matter what kind of error occurred, we need to do a cleanup | 457 // no matter what kind of error occurred, we need to do a cleanup |
458 AssociationCleanup(assoc); | 458 AssociationCleanup(assoc); |
459 return NULL; | 459 return NULL; |
460 } | 460 } |
461 | 461 |
462 LOG(INFO) << "Association Received"; | 462 // Retrieve the AET and the IP address of the remote modality |
463 | 463 std::string callingAet; |
464 std::vector<const char*> transferSyntaxes; | |
465 | |
466 // This is the list of the transfer syntaxes that were supported up to Orthanc 0.7.1 | |
467 transferSyntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); | |
468 transferSyntaxes.push_back(UID_BigEndianExplicitTransferSyntax); | |
469 transferSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); | |
470 | |
471 // New transfer syntaxes supported since Orthanc 0.7.2 | |
472 transferSyntaxes.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax); | |
473 transferSyntaxes.push_back(UID_JPEGProcess1TransferSyntax); | |
474 transferSyntaxes.push_back(UID_JPEGProcess2_4TransferSyntax); | |
475 transferSyntaxes.push_back(UID_JPEGProcess3_5TransferSyntax); | |
476 transferSyntaxes.push_back(UID_JPEGProcess6_8TransferSyntax); | |
477 transferSyntaxes.push_back(UID_JPEGProcess7_9TransferSyntax); | |
478 transferSyntaxes.push_back(UID_JPEGProcess10_12TransferSyntax); | |
479 transferSyntaxes.push_back(UID_JPEGProcess11_13TransferSyntax); | |
480 transferSyntaxes.push_back(UID_JPEGProcess14TransferSyntax); | |
481 transferSyntaxes.push_back(UID_JPEGProcess15TransferSyntax); | |
482 transferSyntaxes.push_back(UID_JPEGProcess16_18TransferSyntax); | |
483 transferSyntaxes.push_back(UID_JPEGProcess17_19TransferSyntax); | |
484 transferSyntaxes.push_back(UID_JPEGProcess20_22TransferSyntax); | |
485 transferSyntaxes.push_back(UID_JPEGProcess21_23TransferSyntax); | |
486 transferSyntaxes.push_back(UID_JPEGProcess24_26TransferSyntax); | |
487 transferSyntaxes.push_back(UID_JPEGProcess25_27TransferSyntax); | |
488 transferSyntaxes.push_back(UID_JPEGProcess28TransferSyntax); | |
489 transferSyntaxes.push_back(UID_JPEGProcess29TransferSyntax); | |
490 transferSyntaxes.push_back(UID_JPEGProcess14SV1TransferSyntax); | |
491 transferSyntaxes.push_back(UID_JPEGLSLosslessTransferSyntax); | |
492 transferSyntaxes.push_back(UID_JPEGLSLossyTransferSyntax); | |
493 transferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax); | |
494 transferSyntaxes.push_back(UID_JPEG2000TransferSyntax); | |
495 transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax); | |
496 transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax); | |
497 transferSyntaxes.push_back(UID_JPIPReferencedTransferSyntax); | |
498 transferSyntaxes.push_back(UID_JPIPReferencedDeflateTransferSyntax); | |
499 transferSyntaxes.push_back(UID_MPEG2MainProfileAtMainLevelTransferSyntax); | |
500 transferSyntaxes.push_back(UID_MPEG2MainProfileAtHighLevelTransferSyntax); | |
501 transferSyntaxes.push_back(UID_RLELosslessTransferSyntax); | |
502 | |
503 /* accept the Verification SOP Class if presented */ | |
504 cond = ASC_acceptContextsWithPreferredTransferSyntaxes(assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), &transferSyntaxes[0], transferSyntaxes.size()); | |
505 if (cond.bad()) | |
506 { | |
507 LOG(INFO) << cond.text(); | |
508 AssociationCleanup(assoc); | |
509 return NULL; | |
510 } | |
511 | |
512 /* the array of Storage SOP Class UIDs comes from dcuid.h */ | |
513 cond = ASC_acceptContextsWithPreferredTransferSyntaxes(assoc->params, orthancStorageSOPClassUIDs, orthancStorageSOPClassUIDsCount, &transferSyntaxes[0], transferSyntaxes.size()); | |
514 if (cond.bad()) | |
515 { | |
516 LOG(INFO) << cond.text(); | |
517 AssociationCleanup(assoc); | |
518 return NULL; | |
519 } | |
520 | |
521 #if ORTHANC_PROMISCUOUS == 1 | |
522 /* accept everything not known not to be a storage SOP class */ | |
523 cond = acceptUnknownContextsWithPreferredTransferSyntaxes( | |
524 assoc->params, &transferSyntaxes[0], transferSyntaxes.size()); | |
525 if (cond.bad()) | |
526 { | |
527 LOG(INFO) << cond.text(); | |
528 AssociationCleanup(assoc); | |
529 return NULL; | |
530 } | |
531 #endif | |
532 | |
533 /* set our app title */ | |
534 ASC_setAPTitles(assoc->params, NULL, NULL, server.GetApplicationEntityTitle().c_str()); | |
535 | |
536 /* acknowledge or reject this association */ | |
537 cond = ASC_getApplicationContextName(assoc->params, buf); | |
538 if ((cond.bad()) || strcmp(buf, UID_StandardApplicationContext) != 0) | |
539 { | |
540 /* reject: the application context name is not supported */ | |
541 T_ASC_RejectParameters rej = | |
542 { | |
543 ASC_RESULT_REJECTEDPERMANENT, | |
544 ASC_SOURCE_SERVICEUSER, | |
545 ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED | |
546 }; | |
547 | |
548 LOG(INFO) << "Association Rejected: Bad Application Context Name: " << buf; | |
549 cond = ASC_rejectAssociation(assoc, &rej); | |
550 if (cond.bad()) | |
551 { | |
552 LOG(INFO) << cond.text(); | |
553 } | |
554 AssociationCleanup(assoc); | |
555 return NULL; | |
556 } | |
557 | |
558 std::string callingIP; | 464 std::string callingIP; |
559 std::string callingTitle; | 465 std::string calledAet; |
560 | 466 |
561 /* check the AETs */ | 467 { |
562 { | 468 DIC_AE callingAet_C; |
563 DIC_AE callingTitle_C; | 469 DIC_AE calledAet_C; |
564 DIC_AE calledTitle_C; | |
565 DIC_AE callingIP_C; | 470 DIC_AE callingIP_C; |
566 DIC_AE calledIP_C; | 471 DIC_AE calledIP_C; |
567 if (ASC_getAPTitles(assoc->params, callingTitle_C, calledTitle_C, NULL).bad() || | 472 if (ASC_getAPTitles(assoc->params, callingAet_C, calledAet_C, NULL).bad() || |
568 ASC_getPresentationAddresses(assoc->params, callingIP_C, calledIP_C).bad()) | 473 ASC_getPresentationAddresses(assoc->params, callingIP_C, calledIP_C).bad()) |
569 { | 474 { |
570 T_ASC_RejectParameters rej = | 475 T_ASC_RejectParameters rej = |
571 { | 476 { |
572 ASC_RESULT_REJECTEDPERMANENT, | 477 ASC_RESULT_REJECTEDPERMANENT, |
577 AssociationCleanup(assoc); | 482 AssociationCleanup(assoc); |
578 return NULL; | 483 return NULL; |
579 } | 484 } |
580 | 485 |
581 callingIP = std::string(/*OFSTRING_GUARD*/(callingIP_C)); | 486 callingIP = std::string(/*OFSTRING_GUARD*/(callingIP_C)); |
582 callingTitle = std::string(/*OFSTRING_GUARD*/(callingTitle_C)); | 487 callingAet = std::string(/*OFSTRING_GUARD*/(callingAet_C)); |
583 std::string calledTitle(/*OFSTRING_GUARD*/(calledTitle_C)); | 488 calledAet = (/*OFSTRING_GUARD*/(calledAet_C)); |
584 | 489 } |
585 if (!server.IsMyAETitle(calledTitle)) | 490 |
586 { | 491 LOG(INFO) << "Association Received from AET " << callingAet |
587 T_ASC_RejectParameters rej = | 492 << " on IP " << callingIP; |
588 { | 493 |
589 ASC_RESULT_REJECTEDPERMANENT, | 494 |
590 ASC_SOURCE_SERVICEUSER, | 495 std::vector<const char*> transferSyntaxes; |
591 ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED | 496 |
592 }; | 497 // This is the list of the transfer syntaxes that were supported up to Orthanc 0.7.1 |
593 ASC_rejectAssociation(assoc, &rej); | 498 transferSyntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); |
594 AssociationCleanup(assoc); | 499 transferSyntaxes.push_back(UID_BigEndianExplicitTransferSyntax); |
595 return NULL; | 500 transferSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); |
596 } | 501 |
597 | 502 // New transfer syntaxes supported since Orthanc 0.7.2 |
598 if (server.HasApplicationEntityFilter() && | 503 if (!server.HasApplicationEntityFilter() || |
599 !server.GetApplicationEntityFilter().IsAllowedConnection(callingIP, callingTitle)) | 504 server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Deflated)) |
600 { | 505 { |
601 T_ASC_RejectParameters rej = | 506 transferSyntaxes.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax); |
602 { | 507 } |
603 ASC_RESULT_REJECTEDPERMANENT, | 508 |
604 ASC_SOURCE_SERVICEUSER, | 509 if (!server.HasApplicationEntityFilter() || |
605 ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED | 510 server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Jpeg)) |
606 }; | 511 { |
607 ASC_rejectAssociation(assoc, &rej); | 512 transferSyntaxes.push_back(UID_JPEGProcess1TransferSyntax); |
608 AssociationCleanup(assoc); | 513 transferSyntaxes.push_back(UID_JPEGProcess2_4TransferSyntax); |
609 return NULL; | 514 transferSyntaxes.push_back(UID_JPEGProcess3_5TransferSyntax); |
610 } | 515 transferSyntaxes.push_back(UID_JPEGProcess6_8TransferSyntax); |
611 } | 516 transferSyntaxes.push_back(UID_JPEGProcess7_9TransferSyntax); |
612 | 517 transferSyntaxes.push_back(UID_JPEGProcess10_12TransferSyntax); |
613 if (opt_rejectWithoutImplementationUID && strlen(assoc->params->theirImplementationClassUID) == 0) | 518 transferSyntaxes.push_back(UID_JPEGProcess11_13TransferSyntax); |
519 transferSyntaxes.push_back(UID_JPEGProcess14TransferSyntax); | |
520 transferSyntaxes.push_back(UID_JPEGProcess15TransferSyntax); | |
521 transferSyntaxes.push_back(UID_JPEGProcess16_18TransferSyntax); | |
522 transferSyntaxes.push_back(UID_JPEGProcess17_19TransferSyntax); | |
523 transferSyntaxes.push_back(UID_JPEGProcess20_22TransferSyntax); | |
524 transferSyntaxes.push_back(UID_JPEGProcess21_23TransferSyntax); | |
525 transferSyntaxes.push_back(UID_JPEGProcess24_26TransferSyntax); | |
526 transferSyntaxes.push_back(UID_JPEGProcess25_27TransferSyntax); | |
527 transferSyntaxes.push_back(UID_JPEGProcess28TransferSyntax); | |
528 transferSyntaxes.push_back(UID_JPEGProcess29TransferSyntax); | |
529 transferSyntaxes.push_back(UID_JPEGProcess14SV1TransferSyntax); | |
530 transferSyntaxes.push_back(UID_JPEGLSLosslessTransferSyntax); | |
531 transferSyntaxes.push_back(UID_JPEGLSLossyTransferSyntax); | |
532 } | |
533 | |
534 if (!server.HasApplicationEntityFilter() || | |
535 server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Jpeg2000)) | |
536 { | |
537 transferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax); | |
538 transferSyntaxes.push_back(UID_JPEG2000TransferSyntax); | |
539 } | |
540 | |
541 if (!server.HasApplicationEntityFilter() || | |
542 server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_JpegLossless)) | |
543 { | |
544 transferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax); | |
545 transferSyntaxes.push_back(UID_JPEG2000TransferSyntax); | |
546 transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax); | |
547 transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax); | |
548 } | |
549 | |
550 if (!server.HasApplicationEntityFilter() || | |
551 server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Jpip)) | |
552 { | |
553 transferSyntaxes.push_back(UID_JPIPReferencedTransferSyntax); | |
554 transferSyntaxes.push_back(UID_JPIPReferencedDeflateTransferSyntax); | |
555 } | |
556 | |
557 if (!server.HasApplicationEntityFilter() || | |
558 server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Mpeg2)) | |
559 { | |
560 transferSyntaxes.push_back(UID_MPEG2MainProfileAtMainLevelTransferSyntax); | |
561 transferSyntaxes.push_back(UID_MPEG2MainProfileAtHighLevelTransferSyntax); | |
562 } | |
563 | |
564 if (!server.HasApplicationEntityFilter() || | |
565 server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Rle)) | |
566 { | |
567 transferSyntaxes.push_back(UID_RLELosslessTransferSyntax); | |
568 } | |
569 | |
570 /* accept the Verification SOP Class if presented */ | |
571 cond = ASC_acceptContextsWithPreferredTransferSyntaxes(assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), &transferSyntaxes[0], transferSyntaxes.size()); | |
572 if (cond.bad()) | |
573 { | |
574 LOG(INFO) << cond.text(); | |
575 AssociationCleanup(assoc); | |
576 return NULL; | |
577 } | |
578 | |
579 /* the array of Storage SOP Class UIDs comes from dcuid.h */ | |
580 cond = ASC_acceptContextsWithPreferredTransferSyntaxes(assoc->params, orthancStorageSOPClassUIDs, orthancStorageSOPClassUIDsCount, &transferSyntaxes[0], transferSyntaxes.size()); | |
581 if (cond.bad()) | |
582 { | |
583 LOG(INFO) << cond.text(); | |
584 AssociationCleanup(assoc); | |
585 return NULL; | |
586 } | |
587 | |
588 #if ORTHANC_PROMISCUOUS == 1 | |
589 /* accept everything not known not to be a storage SOP class */ | |
590 cond = acceptUnknownContextsWithPreferredTransferSyntaxes( | |
591 assoc->params, &transferSyntaxes[0], transferSyntaxes.size()); | |
592 if (cond.bad()) | |
593 { | |
594 LOG(INFO) << cond.text(); | |
595 AssociationCleanup(assoc); | |
596 return NULL; | |
597 } | |
598 #endif | |
599 | |
600 /* set our app title */ | |
601 ASC_setAPTitles(assoc->params, NULL, NULL, server.GetApplicationEntityTitle().c_str()); | |
602 | |
603 /* acknowledge or reject this association */ | |
604 cond = ASC_getApplicationContextName(assoc->params, buf); | |
605 if ((cond.bad()) || strcmp(buf, UID_StandardApplicationContext) != 0) | |
606 { | |
607 /* reject: the application context name is not supported */ | |
608 T_ASC_RejectParameters rej = | |
609 { | |
610 ASC_RESULT_REJECTEDPERMANENT, | |
611 ASC_SOURCE_SERVICEUSER, | |
612 ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED | |
613 }; | |
614 | |
615 LOG(INFO) << "Association Rejected: Bad Application Context Name: " << buf; | |
616 cond = ASC_rejectAssociation(assoc, &rej); | |
617 if (cond.bad()) | |
618 { | |
619 LOG(INFO) << cond.text(); | |
620 } | |
621 AssociationCleanup(assoc); | |
622 return NULL; | |
623 } | |
624 | |
625 /* check the AETs */ | |
626 if (!server.IsMyAETitle(calledAet)) | |
627 { | |
628 LOG(WARNING) << "Rejected association, because of a bad called AET in the request (" << calledAet << ")"; | |
629 T_ASC_RejectParameters rej = | |
630 { | |
631 ASC_RESULT_REJECTEDPERMANENT, | |
632 ASC_SOURCE_SERVICEUSER, | |
633 ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED | |
634 }; | |
635 ASC_rejectAssociation(assoc, &rej); | |
636 AssociationCleanup(assoc); | |
637 return NULL; | |
638 } | |
639 | |
640 if (server.HasApplicationEntityFilter() && | |
641 !server.GetApplicationEntityFilter().IsAllowedConnection(callingIP, callingAet)) | |
642 { | |
643 LOG(WARNING) << "Rejected association for remote AET " << callingAet << " on IP " << callingIP; | |
644 T_ASC_RejectParameters rej = | |
645 { | |
646 ASC_RESULT_REJECTEDPERMANENT, | |
647 ASC_SOURCE_SERVICEUSER, | |
648 ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED | |
649 }; | |
650 ASC_rejectAssociation(assoc, &rej); | |
651 AssociationCleanup(assoc); | |
652 return NULL; | |
653 } | |
654 | |
655 if (opt_rejectWithoutImplementationUID && | |
656 strlen(assoc->params->theirImplementationClassUID) == 0) | |
614 { | 657 { |
615 /* reject: the no implementation Class UID provided */ | 658 /* reject: the no implementation Class UID provided */ |
616 T_ASC_RejectParameters rej = | 659 T_ASC_RejectParameters rej = |
617 { | 660 { |
618 ASC_RESULT_REJECTEDPERMANENT, | 661 ASC_RESULT_REJECTEDPERMANENT, |
642 if (ASC_countAcceptedPresentationContexts(assoc->params) == 0) | 685 if (ASC_countAcceptedPresentationContexts(assoc->params) == 0) |
643 LOG(INFO) << " (but no valid presentation contexts)"; | 686 LOG(INFO) << " (but no valid presentation contexts)"; |
644 } | 687 } |
645 | 688 |
646 IApplicationEntityFilter* filter = server.HasApplicationEntityFilter() ? &server.GetApplicationEntityFilter() : NULL; | 689 IApplicationEntityFilter* filter = server.HasApplicationEntityFilter() ? &server.GetApplicationEntityFilter() : NULL; |
647 return new CommandDispatcher(server, assoc, callingIP, callingTitle, filter); | 690 return new CommandDispatcher(server, assoc, callingIP, callingAet, filter); |
648 } | 691 } |
649 | 692 |
650 bool CommandDispatcher::Step() | 693 bool CommandDispatcher::Step() |
651 /* | 694 /* |
652 * This function receives DIMSE commmands over the network connection | 695 * This function receives DIMSE commmands over the network connection |