Beispiel #1
0
    def test_conversion(self):
        """ Check converting to PDU item works correctly """
        primitive = SCP_SCU_RoleSelectionNegotiation()
        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        primitive.scp_role = True
        primitive.scu_role = False
        item = primitive.from_primitive()

        self.assertTrue(item.encode() == b'\x54\x00\x00\x1d\x00\x19\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30' \
                                         b'\x30\x30\x38\x2e\x35\x2e\x31\x2e\x34\x2e\x31\x2e\x31\x2e\x32\x00' \
                                         b'\x01')

        primitive = SCP_SCU_RoleSelectionNegotiation()
        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        primitive.scp_role = False
        primitive.scu_role = False
        with self.assertRaises(ValueError):
            primitive.from_primitive()
Beispiel #2
0
    def get(self,model=None,to_address=None,to_port=None,to_name=None,
             patient_name=None):

        # Set the extended negotiation SCP/SCU role selection to allow us to receive
        #   C-STORE requests for the supported SOP classes
        # I don't totally understand this, leaving as is until test it out.
        ext_neg = []
        for context in self.ae.presentation_contexts_scu:
            tmp = SCP_SCU_RoleSelectionNegotiation()
            tmp.sop_class_uid = context.AbstractSyntax
            tmp.scu_role = False
            tmp.scp_role = True

            ext_neg.append(tmp)

        if model is None:
            model = 'P'

        self.check_information_model(model)

        if patient_name is None:
            patient_name = "*"

        # Make the association - updates self.assoc
        self.make_assoc(address=to_address,
                        name=to_name,
                        port=to_port,
                        ext_neg=ext_neg)

        # Create a query dataset
        dataset = Dataset()
        dataset.PatientName = patient_name
        dataset.QueryRetrieveLevel = "PATIENT"

        # Send query
        if self.assoc.is_established:
            response = self.assoc.send_c_get(dataset, 
                                             query_model=model)

            time.sleep(1)
            if response is not None:
                for value in response:
                    pass

        self.assoc.release()
        self.ae.quit() # Not sure if we want to quit here
Beispiel #3
0
# Create application entity
# Binding to port 0 lets the OS pick an available port
ae = AE(ae_title=args.calling_aet,
        port=0,
        scu_sop_class=scu_classes,
        scp_sop_class=[],
        transfer_syntax=[ExplicitVRLittleEndian])

# Set the extended negotiation SCP/SCU role selection to allow us to receive
#   C-STORE requests for the supported SOP classes
ext_neg = []
for context in ae.presentation_contexts_scu:
    tmp = SCP_SCU_RoleSelectionNegotiation()
    tmp.sop_class_uid = context.AbstractSyntax
    tmp.scu_role = False
    tmp.scp_role = True

    ext_neg.append(tmp)

# Request association with remote
assoc = ae.associate(args.peer, args.port, args.called_aet, ext_neg=ext_neg)

# Create query dataset
d = Dataset()
d.PatientName = '*'
d.QueryRetrieveLevel = "PATIENT"

if args.worklist:
    query_model = 'W'
elif args.patient:
Beispiel #4
0
# Binding to port 0 lets the OS pick an available port
ae = AE(ae_title=args.calling_aet, port=0)

for context in QueryRetrievePresentationContexts:
    ae.add_requested_context(context.abstract_syntax)
for context in StoragePresentationContexts[:115]:
    ae.add_requested_context(context.abstract_syntax)

# Add SCP/SCU Role Selection Negotiation to the extended negotiation
# We want to act as a Storage SCP
ext_neg = []
for context in StoragePresentationContexts:
    role = SCP_SCU_RoleSelectionNegotiation()
    role.sop_class_uid = context.abstract_syntax
    role.scp_role = True
    role.scu_role = False
    ext_neg.append(role)

# Create query dataset
d = Dataset()
d.PatientName = '*'
d.QueryRetrieveLevel = "PATIENT"

if args.worklist:
    query_model = 'W'
elif args.patient:
    query_model = 'P'
elif args.study:
    query_model = 'S'
elif args.psonly:
    query_model = 'O'
    def test_assignment_and_exceptions(self):
        """ Check incorrect types/values for properties raise exceptions """
        primitive = SCP_SCU_RoleSelectionNegotiation()

        ## Check assignment
        # SOP Class UID
        reference_uid = UID('1.2.840.10008.5.1.4.1.1.2')

        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        self.assertTrue(primitive.sop_class_uid == reference_uid)

        primitive.sop_class_uid = '1.2.840.10008.5.1.4.1.1.2'
        self.assertTrue(primitive.sop_class_uid == reference_uid)

        primitive.sop_class_uid = UID('1.2.840.10008.5.1.4.1.1.2')
        self.assertTrue(primitive.sop_class_uid == reference_uid)

        # SCP Role
        primitive.scp_role = False
        self.assertTrue(primitive.scp_role == False)

        # SCU Role
        primitive.scu_role = True
        self.assertTrue(primitive.scu_role == True)

        ## Check exceptions
        with pytest.raises(TypeError):
            primitive.sop_class_uid = 10

        with pytest.raises(TypeError):
            primitive.sop_class_uid = 45.2

        with pytest.raises(ValueError):
            primitive.sop_class_uid = 'abc'

        with pytest.raises(TypeError):
            primitive.scp_role = 1

        with pytest.raises(TypeError):
            primitive.scp_role = 'abc'

        with pytest.raises(TypeError):
            primitive.scu_role = 1

        with pytest.raises(TypeError):
            primitive.scu_role = 'abc'

        # No value set
        primitive = SCP_SCU_RoleSelectionNegotiation()
        with pytest.raises(ValueError):
            item = primitive.from_primitive()

        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        with pytest.raises(ValueError):
            item = primitive.from_primitive()

        primitive.scp_role = False
        with pytest.raises(ValueError):
            item = primitive.from_primitive()

        primitive = SCP_SCU_RoleSelectionNegotiation()
        primitive.sop_class_uid = b'1.2.840.10008.5.1.4.1.1.2'
        primitive.scu_role = True
        item = primitive.from_primitive()
        assert item.scu_role
        assert not item.scp_role

        primitive = SCP_SCU_RoleSelectionNegotiation()
        primitive.scp_role = True
        primitive.scu_role = True
        with pytest.raises(ValueError):
            item = primitive.from_primitive()
Beispiel #6
0
def negotiate_as_acceptor(rq_contexts, ac_contexts, roles=None):
    """Process the Presentation Contexts as an Association acceptor.

    Parameters
    ----------
    rq_contexts : list of PresentationContext
        The Presentation Contexts proposed by the peer. Each item has
        values for Context ID, Abstract Syntax and Transfer Syntax.
    ac_contexts : list of PresentationContext
        The Presentation Contexts supported by the local AE when acting
        as an Association acceptor. Each item has values for Context ID
        Abstract Syntax and Transfer Syntax.
    roles : dict or None
        If the requestor has included one or more SCP/SCU Role Selection
        Negotiation items then this will be a dict of
        {SOP Class UID : (SCU role, SCP role)}, otherwise None (default)

    Returns
    -------
    list of PresentationContext
        The accepted presentation context items, each with a Result value
        a Context ID, an Abstract Syntax and one Transfer Syntax item.
        Items are sorted in increasing Context ID value.
    list of SCP_SCU_RoleSelectionNegotiation
        If `roles` is not None then this is a list of SCP/SCU Role Selection
        Negotiation items that can be sent back to the requestor.
    """
    from pynetdicom3.pdu_primitives import SCP_SCU_RoleSelectionNegotiation

    roles = roles or {}
    result_contexts = []
    reply_roles = {}

    # No requestor presentation contexts
    if not rq_contexts:
        return result_contexts, []

    # Acceptor doesn't support any presentation contexts
    if not ac_contexts:
        for rq_context in rq_contexts:
            context = PresentationContext()
            context.context_id = rq_context.context_id
            context.abstract_syntax = rq_context.abstract_syntax
            context.transfer_syntax = [rq_context.transfer_syntax[0]]
            context.result = 0x03
            result_contexts.append(context)
        return result_contexts, []

    # Optimisation notes (for iterating through contexts only, not
    #   including actual context negotiation)
    # - Create dict, use set intersection/difference of dict keys: ~600 us
    # - Create dict, iterate over dict keys: ~400 us
    # - Iterate over lists: ~52000 us

    # Requestor may use the same Abstract Syntax in multiple Presentation
    #   Contexts so we need a more specific key than UID
    requestor_contexts = {(cx.context_id, cx.abstract_syntax): cx
                          for cx in rq_contexts}
    # Acceptor supported SOP Classes must be unique so we can use UID as
    #   the key
    acceptor_contexts = {cx.abstract_syntax: cx for cx in ac_contexts}

    for (cntx_id, ab_syntax) in requestor_contexts:
        # Convenience variable
        rq_context = requestor_contexts[(cntx_id, ab_syntax)]

        # Create a new PresentationContext item that will store the
        #   results of the negotiation
        context = PresentationContext()
        context.context_id = cntx_id
        context.abstract_syntax = ab_syntax
        context._as_scu = False
        context._as_scp = False

        # Check if the acceptor supports the Abstract Syntax
        if ab_syntax in acceptor_contexts:
            # Convenience variables
            ac_context = acceptor_contexts[ab_syntax]
            ac_roles = (ac_context.scu_role, ac_context.scp_role)
            try:
                rq_roles = roles[ab_syntax]
                has_role = True
            except KeyError:
                rq_roles = (None, None)
                has_role = False

            # Abstract syntax supported so check Transfer Syntax
            for tr_syntax in rq_context.transfer_syntax:
                # If transfer syntax supported then (provisionally) accept
                if tr_syntax in ac_context.transfer_syntax:
                    context.transfer_syntax = [tr_syntax]
                    context.result = 0x00
                    result_contexts.append(context)
                    break

            ## SCP/SCU Role Selection Negotiation
            #   Only for (provisionally) accepted contexts
            if context.result == 0x00:
                if None in ac_roles:
                    # Default roles
                    context._as_scu = False
                    context._as_scp = True
                    # If either aq.scu_role or ac.scp_role is None then
                    #   don't send an SCP/SCU negotiation reply
                    has_role = False
                else:
                    # Use a LUT to make changes to outcomes easier
                    #   also its much simpler than coding if/then branches
                    outcome = SCP_SCU_ROLES[rq_roles][ac_roles]
                    context._as_scu = outcome[2]
                    context._as_scp = outcome[3]

                # If can't act as either SCU nor SCP then reject the context
                if context.as_scu is False and context.as_scp is False:
                    # User rejection
                    context.result = 0x01

            # Need to check against None as 0x00 is a possible value
            if context.result is None:
                # Reject context - transfer syntax not supported
                context.result = 0x04
                context.transfer_syntax = [rq_context.transfer_syntax[0]]
                result_contexts.append(context)
            elif context.result == 0x00 and has_role:
                # Create new SCP/SCU Role Selection Negotiation item
                role = SCP_SCU_RoleSelectionNegotiation()
                role.sop_class_uid = context.abstract_syntax

                # Can't return 0x01 if proposed 0x00
                if rq_roles[0] is False:
                    role.scu_role = False
                else:
                    role.scu_role = ac_context.scu_role

                if rq_roles[1] is False:
                    role.scp_role = False
                else:
                    role.scp_role = ac_context.scp_role

                reply_roles[context.abstract_syntax] = role
        else:
            # Reject context - abstract syntax not supported
            context.result = 0x03
            context.transfer_syntax = [rq_context.transfer_syntax[0]]
            result_contexts.append(context)

    # Sort by presentation context ID
    #   This isn't required by the DICOM Standard but its a nice thing to do
    result_contexts = sorted(result_contexts, key=lambda x: x.context_id)

    # Sort role selection by abstract syntax, also not required but nice
    reply_roles = sorted(reply_roles.values(), key=lambda x: x.sop_class_uid)

    return result_contexts, reply_roles