Exemplo n.º 1
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
Exemplo n.º 2
0
    def read_pdu(self):
        """Read PDU from the SMSC"""

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

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

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

        raw_pdu = self._socket.recv(length - 4)
        raw_pdu = raw_len + raw_pdu

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

        pdu = smpp.parse_pdu(raw_pdu, client=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
Exemplo n.º 3
0
    def listen(self):
        """This method implements the actual SMPP server. Note that we can
        only talk to one client at a time; removing that restriction
        would make the code much more complicated and we don't really
        need it.

        """

        msg_count = 0
        while True:
            self._sock.listen()
            sock, address = self._sock.accept()
            done = False
            while not done:
                # Note how we're leveraging `smpplib` to avoid the –
                # considerable – inconvenience of parsing (and
                # generating) SMPP PDUs ourselves.

                try:
                    pdu = smpp.parse_pdu(
                        self.read_raw_pdu(sock),
                        client=self,
                        allow_unknown_opt_params=None,
                    )
                    self.pdus.append(pdu)
                except exceptions.ConnectionError:
                    break

                # Do something with the PDU.

                print(f"> {pdu.command}", end="")
                if pdu.command == "bind_transceiver":
                    status = consts.SMPP_ESME_ROK
                    if self.password is not None:
                        if (pdu.system_id.decode() != self.system_id
                                or pdu.password.decode() != self.password):
                            status = consts.SMPP_ESME_RBINDFAIL

                    res_pdu = smpp.make_pdu(
                        "bind_transceiver_resp",
                        status=status,
                        sequence=pdu._sequence,
                    )
                    print("\n< OK")
                elif pdu.command == "submit_sm":
                    text = pdu.short_message.decode()
                    print(f": from={pdu.source_addr.decode()} "
                          f"to={pdu.destination_addr.decode()} "
                          f'text="{text}"')

                    # You can get the server to return any of a bunch
                    # of error codes simply by including the (textual
                    # representation of the) error code in the
                    # message. E.g., send the message `Ahoy SUBMITFAIL
                    # Ahoy` to elicit the error code,
                    # `ESME_RSUBMITFAIL`.

                    data = {
                        "status": pdu.status,
                        "sequence": pdu._sequence,
                    }
                    for err in (
                            "SYSERR",
                            "MSGQFUL",
                            "SUBMITFAIL",
                            "THROTTLED",
                            "X_T_APPN",
                            "DELIVERYFAILURE",
                    ):
                        if err in text:
                            data["status"] = getattr(consts,
                                                     "SMPP_ESME_R" + err)
                            out_msg = f"ERR {err}"
                            break
                    else:
                        msg_count += 1
                        msg_id = f"{MC_ID}:{msg_count:04d}"
                        data["message_id"] = msg_id
                        out_msg = f"OK {msg_id}"
                        self.messages.append(text)

                    res_pdu = smpp.make_pdu("submit_sm_resp", **data)
                    print(f"< {out_msg}")
                elif pdu.command == "unbind":
                    res_pdu = smpp.make_pdu(
                        "unbind_resp",
                        status=pdu.status,
                        sequence=pdu._sequence,
                    )
                    done = True
                    print("\n< OK")
                else:
                    raise ValueError(f"Unsupported SMPP command {pdu.command}")
                self.pdus.append(res_pdu)
                response = res_pdu.generate()
                # self.logger.debug(f'<< {response.hex(" ", -4)}')  # Python 3.8
                self.logger.debug("<< %s", response.hex())
                sock.send(response)
            sock.close()
            done = False