def remote_pass_pdu(pdu, dest_ip): try: log.info('Making SMMP Connection to %s for %s' % (dest_ip, pdu.destination_addr)) smpp_client = smpplib.client.Client(dest_ip, 2775, 5) smpp_client.set_message_sent_handler( lambda pdu: log.info("Sent (%s)", pdu.message_id)) smpp_client.connect() smpp_client.bind_transceiver(system_id="ISMPP", password="******") log.debug('Submitting to %s from %s' % (pdu.destination_addr, pdu.source_addr)) #rand = randint(5, 15) #log.debug('GOING BUSY NOW for %s secs' % rand) #time.sleep(rand) rpdu = smpp.make_pdu('submit_sm', client=smpp_client, service_type=pdu.service_type, sequence=pdu.sequence, source_addr_ton=int(pdu.source_addr_ton), source_addr_npi=int(pdu.source_addr_npi), source_addr=pdu.source_addr, dest_addr_ton=int(pdu.dest_addr_ton), dest_addr_npi=int(pdu.dest_addr_npi), destination_addr=pdu.destination_addr, data_coding=int(pdu.data_coding), esm_class=int(pdu.esm_class), short_message=pdu.short_message, registered_delivery=int(pdu.registered_delivery), user_message_reference=int( pdu.user_message_reference)) rpdu.sequence = pdu.sequence try: smpp_client.send_pdu(rpdu) log.debug('Sumbit_SM is sent. waiting response...') smpp_client.read_once() return smpplib.consts.SMPP_ESME_ROK except smpplib.exceptions.PDUError as ex: smpp_client.unbind() smpp_client.disconnect() raise Exception('Unable to Submit Message via Remote SMPP (%s)' % ex) smpp_client.unbind() smpp_client.disconnect() del smpp_client if p.sequence == rpdu.sequence: log.debug('Remote SMPP Resp Received for Sequence# %s' % pdu.sequence) return smpplib.consts.SMPP_ESME_ROK except (IOError, smpplib.exceptions.ConnectionError) as ex: smpp_client.disconnect() raise Exception('Unable to connect to Remote SMPP (%s)' % ex) except Exception as ex: log.debug("Other Exception: %s", str(ex)) template = "An exception of type {0} occurred. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) log.debug(message) del smpp_client raise Exception(ex)
def _message_received(self, pdu): """Handler for received message event""" status = self.message_received_handler(pdu=pdu) if status is None: status = consts.SMPP_ESME_ROK dsmr = smpp.make_pdu('deliver_sm_resp', client=self, status=status) dsmr.sequence = pdu.sequence self.send_pdu(dsmr)
def _message_received(self, pdu): """Handler for received message event""" status = self.message_received_handler(pdu=pdu) if status is None: status = consts.SMPP_ESME_ROK dsmr = smpp.make_pdu('deliver_sm_resp', client=self, status=status) dsmr.sequence = pdu.sequence self.send_pdu(dsmr)
def unbind(self): """Unbind from the SMSC""" p = smpp.make_pdu('unbind', client=self) self.send_pdu(p) try: return self.read_pdu() except socket.timeout: raise exceptions.ConnectionError()
def unbind(self): """Unbind from the SMSC""" p = smpp.make_pdu('unbind', client=self) self.send_pdu(p) try: return self.read_pdu() except socket.timeout: raise exceptions.ConnectionError()
def test_client_error_pdu_custom_handler(): client = Client("localhost", 5679) error_pdu = make_pdu("submit_sm_resp") error_pdu.status = consts.SMPP_ESME_RINVMSGLEN client.read_pdu = Mock(return_value=error_pdu) mock_error_pdu_handler = Mock() client.set_error_pdu_handler(mock_error_pdu_handler) client.read_once() assert mock_error_pdu_handler.mock_calls == [call(error_pdu)]
def remote_pass_pdu(pdu, dest_ip): try: log.info('Making SMMP Connection to %s for %s' % (dest_ip, pdu.destination_addr)) smpp_client = smpplib.client.Client(dest_ip, 2775, 5) smpp_client.set_message_sent_handler(lambda pdu: log.info("Sent (%s)", pdu.message_id)) smpp_client.connect() smpp_client.bind_transceiver(system_id="ISMPP", password="******") log.debug('Submitting to %s from %s' % (pdu.destination_addr, pdu.source_addr)) #rand = randint(5, 15) #log.debug('GOING BUSY NOW for %s secs' % rand) #time.sleep(rand) rpdu = smpp.make_pdu('submit_sm', client=smpp_client, service_type=pdu.service_type, sequence=pdu.sequence, source_addr_ton=int(pdu.source_addr_ton), source_addr_npi=int(pdu.source_addr_npi), source_addr=pdu.source_addr, dest_addr_ton=int(pdu.dest_addr_ton), dest_addr_npi=int(pdu.dest_addr_npi), destination_addr=pdu.destination_addr, data_coding=int(pdu.data_coding), esm_class=int(pdu.esm_class), short_message=pdu.short_message, registered_delivery=int(pdu.registered_delivery), user_message_reference=int(pdu.user_message_reference) ) rpdu.sequence = pdu.sequence try: smpp_client.send_pdu(rpdu) log.debug('Sumbit_SM is sent. waiting response...') smpp_client.read_once() return smpplib.consts.SMPP_ESME_ROK except smpplib.exceptions.PDUError as ex: smpp_client.unbind() smpp_client.disconnect() raise Exception('Unable to Submit Message via Remote SMPP (%s)' % ex) smpp_client.unbind() smpp_client.disconnect() del smpp_client if p.sequence == rpdu.sequence: log.debug('Remote SMPP Resp Received for Sequence# %s' % pdu.sequence) return smpplib.consts.SMPP_ESME_ROK except (IOError, smpplib.exceptions.ConnectionError) as ex: smpp_client.disconnect() raise Exception('Unable to connect to Remote SMPP (%s)' % ex) except Exception as ex: log.debug("Other Exception: %s", str(ex)) template = "An exception of type {0} occurred. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) log.debug(message) del smpp_client raise Exception(ex)
def query_message(self, **kwargs): """Query message state Required Arguments: message_id -- SMSC assigned Message ID source_addr_ton -- Original source address TON source_addr_npi -- Original source address NPI source_addr -- Original source address (string) """ qsm = smpp.make_pdu('query_sm', client=self, **kwargs) self.send_pdu(qsm) return qsm
def test_client_error_pdu_default(): client = Client("localhost", 5679) error_pdu = make_pdu("submit_sm_resp") error_pdu.status = consts.SMPP_ESME_RINVMSGLEN client.read_pdu = Mock(return_value=error_pdu) with pytest.raises(exceptions.PDUError) as exec_info: client.read_once() assert exec_info.value.args[1] == consts.SMPP_ESME_RINVMSGLEN # Should not raise client.read_once(ignore_error_codes=[consts.SMPP_ESME_RINVMSGLEN])
def send_message(self, **kwargs): """Send message Required Arguments: source_addr_ton -- Source address TON source_addr -- Source address (string) dest_addr_ton -- Destination address TON destination_addr -- Destination address (string) short_message -- Message text (string) """ ssm = smpp.make_pdu('submit_sm', client=self, **kwargs) self.send_pdu(ssm) return ssm
def send_message(self, **kwargs): """Send message Required Arguments: source_addr_ton -- Source address TON source_addr -- Source address (string) dest_addr_ton -- Destination address TON destination_addr -- Destination address (string) short_message -- Message text (string) """ ssm = smpp.make_pdu('submit_sm', client=self, **kwargs) self.send_pdu(ssm) return ssm
def read_once(self, ignore_error_codes=None, auto_send_enquire_link=True): """Read a PDU and act""" if ignore_error_codes is not None: warnings.warn( "ignore_error_codes is deprecated, use set_error_pdu_handler to " "configure a custom error PDU handler instead.", DeprecationWarning, ) 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(): self.error_pdu_handler(pdu) 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
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
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
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
def read_once(self, ignore_error_codes=None): """Read a PDU and act""" try: try: pdu = self.read_pdu() except socket.timeout: 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 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 == 'enquire_link': self._enquire_link_received() elif pdu.command == 'enquire_link_resp': pass elif pdu.command == 'alert_notification': self._alert_notification(pdu) else: 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: logging.warning('(%d) %s. Ignored.', e.args[1], e.args[0]) else: raise
def _enquire_link_received(self): """Response to enquire_link""" ler = smpp.make_pdu('enquire_link_resp', client=self) self.send_pdu(ler) logger.debug("Link Enquiry...")
def _enquire_link_received(self): """Response to enquire_link""" ler = smpp.make_pdu('enquire_link_resp', client=self) self.send_pdu(ler) logger.debug("Link Enquiry...")
def _enquire_link_received(self, pdu): """Response to enquire_link""" ler = smpp.make_pdu('enquire_link_resp', client=self) ler.sequence = pdu.sequence self.send_pdu(ler)
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