def test_cancelOutboundTransactions(self): smpp = self.getProtocolObject() smpp.sendPDU = Mock() smpp.sessionState = SMPPSessionStates.BOUND_TRX #start two transactions submitPdu1 = SubmitSM( source_addr_ton=AddrTon.ALPHANUMERIC, source_addr='mobileway', dest_addr_ton=AddrTon.INTERNATIONAL, dest_addr_npi=AddrNpi.ISDN, destination_addr='1208230', short_message='HELLO1', ) submitPdu2 = SubmitSM( source_addr_ton=AddrTon.ALPHANUMERIC, source_addr='mobileway', dest_addr_ton=AddrTon.INTERNATIONAL, dest_addr_npi=AddrNpi.ISDN, destination_addr='1208230', short_message='HELLO2', ) d1 = smpp.sendDataRequest(submitPdu1) d2 = smpp.sendDataRequest(submitPdu2) self.assertEquals(2, len(smpp.outTxns)) smpp.cancelOutboundTransactions(FakeClientError('test')) return defer.DeferredList([ self.assertFailure(d1, FakeClientError), self.assertFailure(d2, FakeClientError), ])
def setUp(self): self.script1 = MTInterceptorScript('abc') self.script2 = MTInterceptorScript('def') self.script3 = MTInterceptorScript('ghi') self.script4 = MTInterceptorScript('jkl') self.group100 = Group(100) self.user1 = User(1, self.group100, 'username', 'password') self.user2 = User(2, self.group100, 'username', 'password') self.mt_filter1 = [UserFilter(self.user1)] self.mt_filter2 = [DestinationAddrFilter('^10\d+')] self.transparent_filter = [TransparentFilter()] self.interceptor1 = StaticMTInterceptor(self.mt_filter1, self.script1) self.interceptor2 = StaticMTInterceptor(self.mt_filter2, self.script2) self.interceptor3 = StaticMTInterceptor(self.transparent_filter, self.script3) self.interceptor4 = DefaultInterceptor(self.script4) self.PDU_dst_1 = SubmitSM( source_addr=b'x', destination_addr=b'200', short_message=b'hello world', ) self.PDU_dst_2 = SubmitSM( source_addr=b'x', destination_addr=b'100', short_message=b'hello world', ) self.routable_matching_interceptor1 = RoutableSubmitSm( self.PDU_dst_1, self.user1) self.routable_matching_interceptor2 = RoutableSubmitSm( self.PDU_dst_2, self.user2) self.routable_notmatching_any = RoutableSubmitSm( self.PDU_dst_1, self.user2)
def setUp(self): self.connector1 = SmppClientConnector('abc') self.connector2 = SmppClientConnector('def') self.connector3 = SmppClientConnector('ghi') self.connector4 = SmppClientConnector('jkl') self.group100 = Group(100) self.user1 = User(1, self.group100, 'username', 'password') self.user2 = User(2, self.group100, 'username', 'password') self.mt_filter1 = [UserFilter(self.user1)] self.mt_filter2 = [DestinationAddrFilter('^10\d+')] self.transparent_filter = [TransparentFilter()] self.route1 = StaticMTRoute(self.mt_filter1, self.connector1, 0.0) self.route2 = StaticMTRoute(self.mt_filter2, self.connector2, 0.0) self.route3 = StaticMTRoute(self.transparent_filter, self.connector3, 0.0) self.route4 = DefaultRoute(self.connector4) self.PDU_dst_1 = SubmitSM( source_addr=b'x', destination_addr=b'200', short_message=b'hello world', ) self.PDU_dst_2 = SubmitSM( source_addr=b'x', destination_addr=b'100', short_message=b'hello world', ) self.routable_matching_route1 = RoutableSubmitSm( self.PDU_dst_1, self.user1) self.routable_matching_route2 = RoutableSubmitSm( self.PDU_dst_2, self.user2) self.routable_notmatching_any = RoutableSubmitSm( self.PDU_dst_1, self.user2)
def test_graceful_unbind(self): smpp = self.getProtocolObject() smpp.sendPDU = Mock() smpp.sessionState = SMPPSessionStates.BOUND_TRX #setup outbound txn outPdu = SubmitSM( seqNum=98790, source_addr='mobileway', destination_addr='1208230', short_message='HELLO1', ) outRespPdu = outPdu.requireAck(seqNum=outPdu.seqNum) outDeferred = smpp.startOutboundTransaction(outPdu, 1) #setup inbound txn inPdu = DeliverSM( seqNum=764765, source_addr='mobileway', destination_addr='1208230', short_message='HELLO1', ) inDeferred = smpp.startInboundTransaction(inPdu) #Call unbind unbindDeferred = smpp.unbind() #Assert unbind request not sent and deferred not fired self.assertEquals(0, smpp.sendPDU.call_count) self.assertFalse(unbindDeferred.called) #Simulate inbound txn finishing smpp.endInboundTransaction(inPdu) #Assert unbind request not sent and deferred not fired self.assertEquals(0, smpp.sendPDU.call_count) self.assertFalse(unbindDeferred.called) #Simulate outbound txn finishing smpp.endOutboundTransaction(outRespPdu) #Assert unbind request was sent but deferred not yet fired self.assertEquals(1, smpp.sendPDU.call_count) sentPdu = smpp.sendPDU.call_args[0][0] self.assertTrue(isinstance(sentPdu, Unbind)) self.assertFalse(unbindDeferred.called) bindResp = UnbindResp(seqNum=sentPdu.seqNum) #Simulate unbind_resp smpp.endOutboundTransaction(bindResp) #Assert unbind deferred fired self.assertTrue(unbindDeferred.called) self.assertTrue( isinstance(unbindDeferred.result, SMPPOutboundTxnResult)) expectedResult = SMPPOutboundTxnResult(smpp, sentPdu, bindResp) self.assertEquals(expectedResult, unbindDeferred.result)
def test_SubmitSM_ringtone_conversion(self): pdu = SubmitSM( 455569, service_type='', source_addr_ton=AddrTon.ALPHANUMERIC, source_addr_npi=AddrNpi.UNKNOWN, source_addr='mobileway', dest_addr_ton=AddrTon.INTERNATIONAL, dest_addr_npi=AddrNpi.ISDN, destination_addr='3369809342', esm_class=EsmClass(EsmClassMode.DEFAULT, EsmClassType.DEFAULT, [EsmClassGsmFeatures.UDHI_INDICATOR_SET]), protocol_id=0, priority_flag=PriorityFlag.LEVEL_0, registered_delivery=RegisteredDelivery( RegisteredDeliveryReceipt.SMSC_DELIVERY_RECEIPT_REQUESTED), replace_if_present_flag=ReplaceIfPresentFlag.DO_NOT_REPLACE, data_coding=DataCoding( DataCodingScheme.GSM_MESSAGE_CLASS, DataCodingGsmMsg(DataCodingGsmMsgCoding.DATA_8BIT, DataCodingGsmMsgClass.CLASS_1)), short_message=binascii.a2b_hex( b'06050415811581024a3a5db5a5cdcda5bdb8040084d8c51381481381481381481381481381381481581681781881881061881061b81081181081881061881061681081781081881061881061b81081181081881061881061681081781081b81881321081b81881221081b818811210824dc1446000' )) self.do_conversion_test( PDUEncoder(), pdu, b'000000a900000004000000000006f3910005006d6f62696c65776179000101333336393830393334320040000000000100f5007506050415811581024a3a5db5a5cdcda5bdb8040084d8c51381481381481381481381481381381481581681781881881061881061b81081181081881061881061681081781081881061881061b81081181081881061881061681081781081b81881321081b81881221081b818811210824dc1446000' )
def test_SubmitSM_conversion(self): pdu = SubmitSM( 9284, service_type='', source_addr_ton=AddrTon.ALPHANUMERIC, source_addr_npi=AddrNpi.UNKNOWN, source_addr='mobileway', dest_addr_ton=AddrTon.INTERNATIONAL, dest_addr_npi=AddrNpi.ISDN, destination_addr='1208230', esm_class=EsmClass(EsmClassMode.DEFAULT, EsmClassType.DEFAULT), protocol_id=0, priority_flag=PriorityFlag.LEVEL_0, registered_delivery=RegisteredDelivery( RegisteredDeliveryReceipt.SMSC_DELIVERY_RECEIPT_REQUESTED), replace_if_present_flag=ReplaceIfPresentFlag.DO_NOT_REPLACE, data_coding=DataCoding( DataCodingScheme.GSM_MESSAGE_CLASS, DataCodingGsmMsg(DataCodingGsmMsgCoding.DEFAULT_ALPHABET, DataCodingGsmMsgClass.CLASS_2)), short_message=b'HELLO', ) self.do_conversion_test( PDUEncoder(), pdu, b'000000360000000400000000000024440005006d6f62696c65776179000101313230383233300000000000000100f2000548454c4c4f' )
def test_corruptData(self): smpp = self.getProtocolObject() self.assertEquals(b'', smpp.recvBuffer) smpp.sendPDU = Mock() smpp.cancelOutboundTransactions = Mock() smpp.shutdown = Mock() smpp.sessionState = SMPPSessionStates.BOUND_TRX smpp.corruptDataRecvd() #Assert that corrupt data #Triggers a shutdown call self.assertEquals(1, smpp.shutdown.call_count) #Causes outbound transactions to be canceled self.assertEquals(1, smpp.cancelOutboundTransactions.call_count) #Responds with a generic nack with invalid cmd len error status nackResp = smpp.sendPDU.call_args[0][0] self.assertEquals( GenericNack(seqNum=None, status=CommandStatus.ESME_RINVCMDLEN), nackResp) #Causes new data received to be ignored newDataHex = b'afc4' smpp.dataReceived(binascii.a2b_hex(newDataHex)) self.assertEquals(newDataHex, binascii.b2a_hex(smpp.recvBuffer)) #Causes new data requests to fail immediately submitPdu = SubmitSM( source_addr_ton=AddrTon.ALPHANUMERIC, source_addr='mobileway', dest_addr_ton=AddrTon.INTERNATIONAL, dest_addr_npi=AddrNpi.ISDN, destination_addr='1208230', short_message='HELLO', ) return self.assertFailure(smpp.sendDataRequest(submitPdu), SMPPClientConnectionCorruptedError)
def setUp(self): self.PDU = SubmitSM( source_addr='20203060', destination_addr='20203060', short_message='hello world', ) self.connector = Connector('abc') self.user = User(1, Group(100), 'username', 'password')
def setUp(self, interceptorpb_client=None): yield HappySMSCTestCase.setUp(self) self.encoder = pdu_encoding.PDUEncoder() # SMPPServerConfig init self.smpps_config = SMPPServerConfig() # Portal init _portal = portal.Portal(SmppsRealm(self.smpps_config.id, self.pbRoot_f)) _portal.registerChecker(RouterAuthChecker(self.pbRoot_f)) # Install mocks self.clientManager_f.perspective_submit_sm = Mock( wraps=self.clientManager_f.perspective_submit_sm) # SMPPServerFactory init self.smpps_factory = LastProtoSMPPServerFactory( self.smpps_config, auth_portal=_portal, RouterPB=self.pbRoot_f, SMPPClientManagerPB=self.clientManager_f, interceptorpb_client=interceptorpb_client) self.smpps_port = reactor.listenTCP(self.smpps_config.port, self.smpps_factory) # Init protocol for testing self.smpps_proto = self.smpps_factory.buildProtocol(('127.0.0.1', 0)) self.smpps_tr = proto_helpers.StringTransport() self.smpps_proto.makeConnection(self.smpps_tr) # Add SMPPs factory to DLRThrower self.DLRThrower.addSmpps(self.smpps_factory) # Install mocks self.smpps_proto.sendPDU = Mock(wraps=self.smpps_proto.sendPDU) # PDUs used for tests self.SubmitSmPDU = SubmitSM( source_addr='1234', destination_addr='4567', short_message='hello !', seqNum=1, ) self.DeliverSmPDU = DeliverSM( source_addr='4567', destination_addr='1234', short_message='any content', seqNum=1, ) self.DataSmPDU = DataSM( source_addr='4567', destination_addr='1234', message_payload='any content', seqNum=1, )
def setUp(self): self.connector = Connector('abc') self.PDU = SubmitSM( source_addr='20203060', destination_addr='20203060', short_message='hello world', ) self.group = Group(100) self.user = User(1, self.group, 'username', 'password') self.routable = SimpleRoutablePDU(self.connector, self.PDU, self.user)
def setUp(self): InterceptorTestCase.setUp(self) self.PDU_dst_1 = SubmitSM( source_addr='20203060', destination_addr='1', short_message='hello world', ) self.routable_user1 = RoutableSubmitSm(self.PDU_dst_1, self.user1)
def setUp(self): RouteTestCase.setUp(self) self.PDU_dst_1 = SubmitSM( source_addr='20203060', destination_addr='1', short_message='hello world', ) self.routable_user1 = RoutableSubmitSm(self.PDU_dst_1, self.user1) self.routable_user2 = RoutableSubmitSm(self.PDU_dst_1, self.user2) self.connectors = [self.connector1, self.connector2]
def test_message_payload(self): """Related to #380 Consider 'message_payload' when there is no 'short_message' parameter """ PDU_message_payload = SubmitSM( source_addr='20203060', destination_addr='20203060', message_payload='hello world', ) del PDU_message_payload.params['short_message'] _routable = SimpleRoutablePDU(self.connector, PDU_message_payload, self.user) self.assertTrue(self.f.match(_routable))
def test_finish_txns(self): smpp = self.getProtocolObject() smpp.sendPDU = Mock() smpp.sessionState = SMPPSessionStates.BOUND_TRX #setup outbound txns outPdu1 = SubmitSM( seqNum=98790, source_addr='mobileway', destination_addr='1208230', short_message='HELLO1', ) outRespPdu1 = outPdu1.requireAck(seqNum=outPdu1.seqNum) outPdu2 = SubmitSM( seqNum=875, source_addr='mobileway', destination_addr='1208230', short_message='HELLO1', ) outRespPdu2 = outPdu2.requireAck(seqNum=outPdu2.seqNum, status=CommandStatus.ESME_RINVSRCTON) outDeferred1 = smpp.startOutboundTransaction(outPdu1, 1) outDeferred2 = smpp.startOutboundTransaction(outPdu2, 1) finishOutTxns = smpp.finishOutboundTxns() #Simulate second txn having error smpp.endOutboundTransactionErr(outRespPdu2, FakeClientError('test')) #Assert txns not done yet self.assertFalse(finishOutTxns.called) #Simulate first txn finishing smpp.endOutboundTransaction(outRespPdu1) #Assert txns are all done self.assertTrue(finishOutTxns.called) return defer.DeferredList([ outDeferred1, self.assertFailure(outDeferred2, FakeClientError), finishOutTxns, ])
def test_sendDataRequest_when_not_bound(self): smpp = self.getProtocolObject() smpp.sessionState = SMPPSessionStates.BIND_TX_PENDING return self.assertFailure(smpp.sendDataRequest(SubmitSM()), SMPPClientSessionStateError)
async def handle_data_received(self, data: bytes): self.app.logger.debug(f'Received {len(data)} bytes.') self.app.logger.debug(data) file = io.BytesIO(data) pdu = PDUEncoder().decode(file) self.app.logger.debug(f'Command received: {pdu.command_id}') if pdu.command_id == CommandId.submit_sm: submit_sm = SubmitSM(sequence_number=pdu.sequence_number, **pdu.params) sms = SMStringEncoder().decode_SM(submit_sm).str self._send_response( submit_sm.require_ack( sequence_number=submit_sm.sequence_number)) # Check if the message is only a part from a series while (submit_sm.params.get('more_messages_to_send') == MoreMessagesToSend.MORE_MESSAGES): pdu = PDUEncoder().decode(file) if pdu.command_id != CommandId.submit_sm: raise Exception( f'Received {pdu.command_id} instead ' f'of {CommandId.submit_sm} for concatenated messages') submit_sm = SubmitSM(sequence_number=pdu.sequence_number, **pdu.params) sms += SMStringEncoder().decode_SM(submit_sm).str self._send_response( submit_sm.require_ack( sequence_number=submit_sm.sequence_number)) await self.app.handle_sms_received( client=self._client, source_number=submit_sm.params['source_addr'], dest_number=submit_sm.params['destination_addr'], text=sms) elif pdu.command_id == CommandId.bind_transceiver: request = BindTransceiver(sequence_number=pdu.sequence_number, **pdu.params) if self.is_bound: smpp_status = CommandStatus.ESME_RALYBND else: client = SmppClient( protocol=self, system_id=request.params['system_id'], password=request.params['password'], system_type=request.params['system_type'], interface_version=request.params['interface_version'], addr_ton=request.params['addr_ton'], addr_npi=request.params['addr_npi']) self._client = client try: client = await self.app.handle_bound_client(client=client) except Exception as e: self.app.logger.error( f'Exception in handle_bound_client: {e}') smpp_status = CommandStatus.ESME_RBINDFAIL else: if client: self.is_bound = True smpp_status = CommandStatus.ESME_ROK else: self.is_bound = False # Generic bind error smpp_status = CommandStatus.ESME_RBINDFAIL resp = BindTransceiverResp(sequence_number=request.sequence_number, status=smpp_status, system_id=self.app.name) self._send_response(resp) elif pdu.command_id == CommandId.unbind: self.is_bound = False request = Unbind(sequence_number=pdu.sequence_number, **pdu.params) resp = UnbindResp(sequence_number=request.sequence_number) self._send_response(resp) await self.app.handle_unbound_client(self._client) else: await self.request_handler(pdu)
def SubmitSM(self, short_message, data_coding=0, **kwargs): """Depending on the short_message length, this method will return a classical SubmitSM or a serie of linked SubmitSMs (parted message) """ kwargs['short_message'] = short_message kwargs['data_coding'] = data_coding # Possible data_coding values : 0,1,2,3,4,5,6,7,8,9,10,13,14 # Set the max short message length depending on the # coding (7, 8 or 16 bits) if kwargs['data_coding'] in [3, 6, 7, 10]: # 8 bit coding bits = 8 maxSmLength = 140 slicedMaxSmLength = maxSmLength - 6 elif kwargs['data_coding'] in [2, 4, 5, 8, 9, 13, 14]: # 16 bit coding bits = 16 maxSmLength = 70 slicedMaxSmLength = maxSmLength - 3 else: # 7 bit coding is the default # for data_coding in [0, 1] or any other invalid value bits = 7 maxSmLength = 160 slicedMaxSmLength = 153 longMessage = kwargs['short_message'] if bits == 16: smLength = len(kwargs['short_message']) / 2 else: smLength = len(kwargs['short_message']) # if SM is longer than maxSmLength, build multiple SubmitSMs # and link them if smLength > maxSmLength: total_segments = int(math.ceil(smLength / float(slicedMaxSmLength))) # Obey to configured longContentMaxParts if total_segments > self.long_content_max_parts: total_segments = self.long_content_max_parts msg_ref_num = self.claimLongMsgRefNum() for i in range(total_segments): segment_seqnum = i + 1 # Keep in memory previous PDU in order to set nextPdu in it later try: tmpPdu previousPdu = tmpPdu except NameError: previousPdu = None if bits == 16: kwargs['short_message'] = longMessage[slicedMaxSmLength * i * 2:slicedMaxSmLength * (i + 1) * 2] else: kwargs['short_message'] = longMessage[slicedMaxSmLength * i:slicedMaxSmLength * (i + 1)] tmpPdu = self._setConfigParamsInPDU(SubmitSM(**kwargs), kwargs) if self.long_content_split == 'sar': # Slice short_message and create the PDU using SAR options tmpPdu.params['sar_total_segments'] = total_segments tmpPdu.params['sar_segment_seqnum'] = segment_seqnum tmpPdu.params['sar_msg_ref_num'] = msg_ref_num elif self.long_content_split == 'udh': # Slice short_message and create the PDU using UDH options tmpPdu.params['esm_class'] = EsmClass( EsmClassMode.DEFAULT, EsmClassType.DEFAULT, [EsmClassGsmFeatures.UDHI_INDICATOR_SET]) if segment_seqnum < total_segments: tmpPdu.params[ 'more_messages_to_send'] = MoreMessagesToSend.MORE_MESSAGES else: tmpPdu.params[ 'more_messages_to_send'] = MoreMessagesToSend.NO_MORE_MESSAGES # UDH composition: udh = [] # Length of User Data Header udh.append(struct.pack('!B', 5)) # Information Element Identifier, equal to 00 # (Concatenated short messages, 8-bit reference number) udh.append(struct.pack('!B', 0)) # Length of the header, excluding the first two fields; equal to 03 udh.append(struct.pack('!B', 3)) udh.append(struct.pack('!B', msg_ref_num)) udh.append(struct.pack('!B', total_segments)) udh.append(struct.pack('!B', segment_seqnum)) if isinstance(kwargs['short_message'], str): tmpPdu.params['short_message'] = b''.join( udh) + kwargs['short_message'].encode() else: tmpPdu.params['short_message'] = b''.join( udh) + kwargs['short_message'] # - The first PDU is the one we return back # - sar_msg_ref_num takes the seqnum of the initial submit_sm if i == 0: pdu = tmpPdu # PDU chaining if previousPdu is not None: previousPdu.nextPdu = tmpPdu else: pdu = self._setConfigParamsInPDU(SubmitSM(**kwargs), kwargs) return pdu