def time_ps_rq_basic(self): """Time a basic presentation service negotiation.""" for ii in range(100): negotiate_as_requestor(self.requestor_contexts, self.acceptor_contexts)
def time_ps_ac_role(self): """Time a presentation service with SCP/SCU role negotiation.""" for ii in range(100): negotiate_as_requestor(self.requestor_contexts, self.acceptor_contexts, self.ac_roles)
def _negotiate_as_requestor(self): """Perform an association negotiation as the association *requestor*.""" if not self.requestor.requested_contexts: LOGGER.error( "One or more requested presentation contexts must be set " "prior to association negotiation") self.assoc.kill() return # Build and send an A-ASSOCIATE (request) PDU to the peer self.send_request() evt.trigger(self.assoc, evt.EVT_REQUESTED, {}) # Wait for response rsp = self.dul.receive_pdu(wait=True, timeout=self.acse_timeout) # Association accepted or rejected if isinstance(rsp, A_ASSOCIATE): self.acceptor.primitive = rsp # Accepted if rsp.result == 0x00: ## Handle SCP/SCU Role Selection response # Apply requestor's proposed SCP/SCU role selection (if any) # to the requested contexts rq_roles = { uid: (ii.scu_role, ii.scp_role) for uid, ii in self.requestor.role_selection.items() } if rq_roles: for cx in self.requestor.requested_contexts: try: (cx.scu_role, cx.scp_role) = rq_roles[cx.abstract_syntax] # If no role was specified then use False # see SCP_SCU_RoleSelectionSubItem.from_primitive cx.scu_role = cx.scu_role or False cx.scp_role = cx.scp_role or False except KeyError: pass # Collate the acceptor's SCP/SCU role selection responses ac_roles = { uid: (ii.scu_role, ii.scp_role) for uid, ii in self.acceptor.role_selection.items() } # Check the negotiated presentation contexts results and # determine their agreed upon SCP/SCU roles negotiated_contexts = negotiate_as_requestor( self.requestor.requested_contexts, rsp.presentation_context_definition_results_list, ac_roles) # pylint: disable=protected-access # Accepted contexts are stored as {context ID : context} self.assoc._accepted_cx = { cx.context_id: cx for cx in negotiated_contexts if cx.result == 0x00 } self.assoc._rejected_cx = [ cx for cx in negotiated_contexts if cx.result != 0x00 ] # pylint: enable=protected-access evt.trigger(self.assoc, evt.EVT_ACCEPTED, {}) # No acceptable presentation contexts if not self.assoc.accepted_contexts: LOGGER.error("No accepted presentation contexts") self.send_abort(0x02) self.assoc.is_aborted = True self.assoc.is_established = False evt.trigger(self.assoc, evt.EVT_ABORTED, {}) self.assoc.kill() else: LOGGER.info('Association Accepted') self.assoc.is_established = True evt.trigger(self.assoc, evt.EVT_ESTABLISHED, {}) elif hasattr(rsp, 'result') and rsp.result in [0x01, 0x02]: # 0x01 is rejected (permanent) # 0x02 is rejected (transient) LOGGER.error('Association Rejected') LOGGER.error( f"Result: {rsp.result_str}, Source: {rsp.source_str}") LOGGER.error(f"Reason: {rsp.reason_str}") self.assoc.is_rejected = True self.assoc.is_established = False evt.trigger(self.assoc, evt.EVT_REJECTED, {}) self.dul.kill_dul() else: LOGGER.error( "Received an invalid A-ASSOCIATE response from the peer") LOGGER.error("Aborting Association") self.send_abort(0x02) self.assoc.is_aborted = True self.assoc.is_established = False # Event handler - association aborted evt.trigger(self.assoc, evt.EVT_ABORTED, {}) self.assoc.kill() # Association aborted elif isinstance(rsp, (A_ABORT, A_P_ABORT)): LOGGER.error("Association Aborted") self.assoc.is_established = False self.assoc.is_aborted = True evt.trigger(self.assoc, evt.EVT_ABORTED, {}) self.dul.kill_dul() elif rsp is None: # ACSE timeout LOGGER.error("ACSE timeout reached while waiting for response to " "association request") self.assoc.abort() else: # Received A-RELEASE or some weird object self.assoc.is_established = False self.dul.kill_dul()