示例#1
0
    def send_pdu(self, p):
        """Send PDU to the SMSC"""

        if self.state not in consts.COMMAND_STATES[p.command]:
            raise exceptions.PDUError("Command %s failed: %s" % (
                p.command,
                consts.DESCRIPTIONS[consts.SMPP_ESME_RINVBNDSTS],
            ))

        logger.debug('Sending %s PDU', p.command)

        generated = p.generate()

        logger.debug('>>%s (%d bytes)', binascii.b2a_hex(generated),
                     len(generated))

        sent = 0

        while sent < len(generated):
            try:
                sent_last = self._socket.send(generated[sent:])
            except socket.error as e:
                logger.warning(e)
                raise exceptions.ConnectionError()
            if sent_last == 0:
                raise exceptions.ConnectionError()
            sent += sent_last

        return True
示例#2
0
 def error_pdu_handler(self, pdu):
     raise exceptions.PDUError(
         '({}) {}: {}'.format(
             pdu.status, pdu.command,
             consts.DESCRIPTIONS.get(pdu.status, 'Unknown status')),
         int(pdu.status),
     )
示例#3
0
    def read_pdu(self):
        """Read PDU from the SMSC"""

        self.logger.debug('Waiting for PDU...')

        try:
            raw_len = self._socket.recv(4)
        except socket.timeout:
            raise
        except socket.error as e:
            self.logger.warning(e)
            raise exceptions.ConnectionError()
        if not raw_len:
            raise exceptions.ConnectionError()

        try:
            length = struct.unpack('>L', raw_len)[0]
        except struct.error:
            self.logger.warning('Receive broken pdu... %s', repr(raw_len))
            raise exceptions.PDUError('Broken PDU')

        raw_pdu = raw_len
        while len(raw_pdu) < length:
            try:
                raw_pdu_part = self._socket.recv(length - len(raw_pdu))
            except socket.timeout:
                raise
            except socket.error as e:
                self.logger.warning(e)
                raise exceptions.ConnectionError()
            if not raw_pdu:
                raise exceptions.ConnectionError()
            raw_pdu += raw_pdu_part

        self.logger.debug('<<%s (%d bytes)', binascii.b2a_hex(raw_pdu),
                          len(raw_pdu))

        pdu = smpp.parse_pdu(
            raw_pdu,
            client=self,
            allow_unknown_opt_params=self.allow_unknown_opt_params,
        )

        self.logger.debug('Read %s PDU', pdu.command)

        if pdu.is_error():
            return pdu

        elif pdu.command in consts.STATE_SETTERS:
            self.state = consts.STATE_SETTERS[pdu.command]

        return pdu
示例#4
0
    def read_once(self, ignore_error_codes=None, auto_send_enquire_link=True):
        """Read a PDU and act"""
        try:
            try:
                pdu = self.read_pdu()
            except socket.timeout:
                if not auto_send_enquire_link:
                    raise
                self.logger.debug('Socket timeout, listening again')
                pdu = smpp.make_pdu('enquire_link', client=self)
                self.send_pdu(pdu)
                return

            if pdu.is_error():
                raise exceptions.PDUError(
                    '({}) {}: {}'.format(
                        pdu.status, pdu.command,
                        consts.DESCRIPTIONS.get(pdu.status, 'Unknown status')),
                    int(pdu.status),
                )

            if pdu.command == 'unbind':  # unbind_res
                self.logger.info('Unbind command received')
                return
            elif pdu.command == 'submit_sm_resp':
                self.message_sent_handler(pdu=pdu)
            elif pdu.command == 'deliver_sm':
                self._message_received(pdu)
            elif pdu.command == 'query_sm_resp':
                self.query_resp_handler(pdu)
            elif pdu.command == 'enquire_link':
                self._enquire_link_received(pdu)
            elif pdu.command == 'enquire_link_resp':
                pass
            elif pdu.command == 'alert_notification':
                self._alert_notification(pdu)
            else:
                self.logger.warning('Unhandled SMPP command "%s"', pdu.command)
        except exceptions.PDUError as e:
            if ignore_error_codes and len(
                    e.args) > 1 and e.args[1] in ignore_error_codes:
                self.logger.warning('(%d) %s. Ignored.', e.args[1], e.args[0])
            else:
                raise
示例#5
0
    def _bind(self, command_name, **kwargs):
        """Send bind_transmitter command to the SMSC"""

        if command_name in ('bind_receiver', 'bind_transceiver'):
            logger.debug('Receiver mode')

        p = smpp.make_pdu(command_name, client=self, **kwargs)

        self.send_pdu(p)
        try:
            resp = self.read_pdu()
        except socket.timeout:
            raise exceptions.ConnectionError()
        if resp.is_error():
            raise exceptions.PDUError(
                '({}) {}: {}'.format(
                    resp.status, resp.command,
                    consts.DESCRIPTIONS.get(resp.status, 'Unknown code')),
                int(resp.status),
            )
        return resp
示例#6
0
    def read_raw_pdu(self, sock):
        """Read a SMPP PDU from the client and return it as a `bytes` object."""
        # This part of the code is inspired by^W^Wlargely cribbed from
        # `smpplib.Client.read_pdu()`.

        try:
            pdu_bytes = sock.recv(4)
        except socket.timeout:
            raise
        except socket.error as e:
            self.logger.warning(e)
            raise exceptions.ConnectionError()
        if not pdu_bytes:
            raise exceptions.ConnectionError()

        try:
            length = struct.unpack(">L", pdu_bytes)[0]
        except struct.error:
            bad_pdu_msg = "Bad PDU: %r"
            self.logger.warning(bad_pdu_msg, pdu_bytes)
            raise exceptions.PDUError(bad_pdu_msg.format(pdu_bytes))

        while len(pdu_bytes) < length:
            try:
                more_bytes = sock.recv(length - len(pdu_bytes))
            except socket.timeout:
                raise
            except socket.error as e:
                self.logger.warning(e)
                raise exceptions.ConnectionError()
            if not pdu_bytes:
                raise exceptions.ConnectionError()
            pdu_bytes += more_bytes
        # self.logger.debug(f'>> {pdu_bytes.hex(" ", -4)}')  # Python >=3.8
        self.logger.debug(">> %s", pdu_bytes.hex())

        return pdu_bytes