Exemple #1
0
 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)
Exemple #3
0
    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)
Exemple #4
0
    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)
Exemple #5
0
 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'
     )
Exemple #6
0
 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'
     )
Exemple #7
0
 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)
Exemple #8
0
 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')
Exemple #9
0
    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,
        )
Exemple #10
0
 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)
Exemple #11
0
    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)
Exemple #12
0
    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]
Exemple #13
0
    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))
Exemple #14
0
    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,
        ])
Exemple #15
0
 def test_sendDataRequest_when_not_bound(self):
     smpp = self.getProtocolObject()
     smpp.sessionState = SMPPSessionStates.BIND_TX_PENDING
     return self.assertFailure(smpp.sendDataRequest(SubmitSM()),
                               SMPPClientSessionStateError)
Exemple #16
0
    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)
Exemple #17
0
    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