class TestAssociateService(unittest.TestCase): # ef setUp(self): def test_normal_accept(self): self.dul1 = DULServiceProvider(Port=None, Name='Dul1, Requestor') self.dul2 = DULServiceProvider(Port=server_port, Name='Dul2, Acceptor') self.dul1.Send(assoc) ass1 = self.dul2.Receive(True) ass1.PresentationContextDefinitionResultList = [[ 1, 0, '1.2.840.10008.1.2' ]] ass1.PresentationContextDefinitionList = None ass1.Result = 0 self.dul2.Send(ass1) res = self.dul1.Receive(True) self.dul1.Kill() self.dul2.Kill() def test_normal_reject(self): self.dul1 = DULServiceProvider(Port=None, Name='Dul1, Requestor') self.dul2 = DULServiceProvider(Port=server_port, Name='Dul2, Acceptor') self.dul1.Send(assoc) ass1 = self.dul2.Receive(True) ass1.PresentationContextDefinitionResultList = [[ 1, 0, '1.2.840.10008.1.2' ]] ass1.PresentationContextDefinitionList = None ass1.Result = 1 self.dul2.Send(ass1) res = self.dul1.Receive(True) self.dul1.Kill() self.dul2.Kill() def test_accept_no_acceptor(self): self.dul1 = DULServiceProvider(Port=4567, Name='Dul1, Requestor') self.assertRaises(socket.error, self.dul1.Send(assoc)) self.dul1.Kill() def test_accept_long_to_respond(self): self.dul1 = DULServiceProvider(Port=4567, Name='Dul1, Requestor') self.dul2 = DULServiceProvider(Port=server_port, Name='Dul2, Acceptor') self.dul1.Send(assoc) ass1 = self.dul2.Receive(True) ass1.PresentationContextDefinitionResultList = [[ 1, 0, '1.2.840.10008.1.2' ]] ass1.PresentationContextDefinitionList = None ass1.Result = 1 time.sleep(10) self.dul2.Send(ass1) res = self.dul1.Receive(True) self.dul1.Kill() self.dul2.Kill()
class ACSEServiceProvider(object): def __init__(self, DUL): self.DUL = DUL self.ApplicationContextName = '1.2.840.10008.3.1.1.1' def Request(self, localAE, remoteAE, mp, pcdl, userspdu=None, timeout=30): """Requests an association with a remote AE and waits for association response.""" self.LocalAE = localAE self.RemoteAE = remoteAE self.MaxPDULength = mp # build association service parameters object assrq = A_ASSOCIATE_ServiceParameters() assrq.ApplicationContextName = self.ApplicationContextName assrq.CallingAETitle = self.LocalAE['AET'] assrq.CalledAETitle = self.RemoteAE['AET'] MaxPDULengthPar = MaximumLengthParameters() MaxPDULengthPar.MaximumLengthReceived = mp if userspdu is not None: assrq.UserInformation = [MaxPDULengthPar] + userspdu else: assrq.UserInformation = [MaxPDULengthPar] assrq.CallingPresentationAddress = ( self.LocalAE['Address'], self.LocalAE['Port']) assrq.CalledPresentationAddress = ( self.RemoteAE['Address'], self.RemoteAE['Port']) assrq.PresentationContextDefinitionList = pcdl logger.debug(pcdl) # send A-Associate request logger.debug("Sending Association Request") self.DUL.Send(assrq) # get answer logger.debug("Waiting for Association Response") assrsp = self.DUL.Receive(True, timeout) if not assrsp: return False logger.debug(assrsp) try: if assrsp.Result != 'Accepted': return False except AttributeError: return False # Get maximum pdu length from answer try: self.MaxPDULength = assrsp.UserInformation[0].MaximumLengthReceived except: self.MaxPDULength = 16000 # Get accepted presentation contexts self.AcceptedPresentationContexts = [] for cc in assrsp.PresentationContextDefinitionResultList: if cc[1] == 0: uid = [x[1] for x in pcdl if x[0] == cc[0]][0] self.AcceptedPresentationContexts.append( (cc[0], uid, UID(cc[2]))) return True def Accept(self, client_socket=None, AcceptablePresentationContexts=None, Wait=True, result=None, diag=None): """Waits for an association request from a remote AE. Upon reception of the request sends association response based on AcceptablePresentationContexts""" if self.DUL is None: self.DUL = DULServiceProvider(Socket=client_socket) assoc = self.DUL.Receive(Wait=True) if assoc is None: return None self.MaxPDULength = assoc.UserInformation[0].MaximumLengthReceived if result is not None and diag is not None: # Association is rejected res = assoc res.PresentationContextDefinitionList = [] res.PresentationContextDefinitionResultList = [] res.Result = result res.Diagnostic = diag res.UserInformation = [] #res.UserInformation = ass.UserInformation self.DUL.Send(res) return None # analyse proposed presentation contexts rsp = [] self.AcceptedPresentationContexts = [] acceptable_sop = [x[0] for x in AcceptablePresentationContexts] for ii in assoc.PresentationContextDefinitionList: pcid = ii[0] proposed_sop = ii[1] proposed_ts = ii[2] if proposed_sop in acceptable_sop: acceptable_ts = [x[1] for x in AcceptablePresentationContexts if x[0] == proposed_sop][0] for ts in proposed_ts: ok = False if ts in acceptable_ts: # accept sop class and ts rsp.append((ii[0], 0, ts)) self.AcceptedPresentationContexts.append( (ii[0], proposed_sop, UID(ts))) ok = True break if not ok: # Refuse sop class because of TS not supported rsp.append((ii[0], 1, '')) else: # Refuse sop class because of SOP class not supported rsp.append((ii[0], 1, '')) # Send response res = copy.copy(assoc) res.CallingAETitle = assoc.CalledAETitle res.CalledAETitle = assoc.CallingAETitle res.PresentationContextDefinitionList = [] res.PresentationContextDefinitionResultList = rsp res.Result = 0 #res.UserInformation = [] #res.UserInformation = [ass.UserInformation[0]] res.UserInformation = assoc.UserInformation self.DUL.Send(res) return assoc # def Receive(self, Wait): # return self.DUL.ReceiveACSE(Wait) def Release(self, Reason): """Requests the release of the associations and waits for confirmation""" rel = A_RELEASE_ServiceParameters() rel.Reason = Reason self.DUL.Send(rel) rsp = self.DUL.Receive(Wait=True) return rsp # self.DUL.Kill() def Abort(self): """Signifies the abortion of the association.""" ab = A_ABORT_ServiceParameters() self.DUL.Send(ab) time.sleep(0.5) # self.DUL.Kill() def CheckRelease(self): """Checks for release request from the remote AE. Upon reception of the request a confirmation is sent""" rel = self.DUL.Peek() if rel.__class__ == A_RELEASE_ServiceParameters: self.DUL.Receive(Wait=False) relrsp = A_RELEASE_ServiceParameters() relrsp.Result = 0 self.DUL.Send(relrsp) return True else: return False def CheckAbort(self): """Checks for abort indication from the remote AE. """ rel = self.DUL.Peek() if rel.__class__ in (A_ABORT_ServiceParameters, A_P_ABORT_ServiceParameters): self.DUL.Receive(Wait=False) return True else: return False def Status(self): return self.DUL.SM.CurrentState() def Kill(self): self.DUL.Kill()
class ACSEServiceProvider(object): def __init__(self, DUL): self.DUL = DUL self.ApplicationContextName = '1.2.840.10008.3.1.1.1' self.remote_ae_title = None def Accept(self, client_socket=None, AcceptablePresentationContexts=None, Wait=True): """Waits for an association request from a remote AE. Upon reception of the request sends association response based on AcceptablePresentationContexts""" if self.DUL is None: self.DUL = DULServiceProvider(Socket=client_socket) ass = self.DUL.Receive(Wait=True) if ass is None: return None # 写死 self.MaxPDULength = 16352 # analyse proposed presentation contexts rsp = [] self.AcceptedPresentationContexts = [] acceptable_sop = [x[0] for x in AcceptablePresentationContexts] ok = False for ii in ass.PresentationContextDefinitionList: pcid = ii[0] proposed_sop = ii[1] proposed_ts = ii[2] if proposed_sop in acceptable_sop: acceptable_ts = [ x[1] for x in AcceptablePresentationContexts if x[0] == proposed_sop ][0] for ts in proposed_ts: ok = False if ts in acceptable_ts: # accept sop class and ts rsp.append((ii[0], 0, ts)) self.AcceptedPresentationContexts.append( (ii[0], proposed_sop, UID(ts))) ok = True break if not ok: # Refuse sop class because of TS not supported rsp.append((ii[0], 1, '')) else: # Refuse sop class because of SOP class not supported rsp.append((ii[0], 1, '')) # Send response res = copy.copy(ass) res.CallingAETitle = ass.CalledAETitle res.CalledAETitle = ass.CallingAETitle res.PresentationContextDefinitionList = [] res.PresentationContextDefinitionResultList = rsp res.Result = 0 max_len = MaximumLengthParameters() max_len.MaximumLengthReceived = self.MaxPDULength async_oper_window = AsynchronousOperationsWindowSubItem() async_oper_window.MaximumNumberOperationsInvoked = 16 async_oper_window.MaximumNumberOperationsPerformed = 16 res.UserInformation = [max_len, async_oper_window] self.DUL.Send(res) return True