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
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
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 connect(self): """Connect to SMSC""" self.logger.info('Connecting to %s:%s...', self.host, self.port) try: if self._socket is None: self._socket = self._create_socket() self._socket.connect((self.host, self.port)) self.state = consts.SMPP_CLIENT_STATE_OPEN except socket.error: raise exceptions.ConnectionError("Connection refused")
def connect(self): """Connect to SMSC""" self.logger.info('Connecting to %s:%s...', self.host, self.port) try: if self._socket is None: self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._socket.settimeout(self.timeout) self._socket.connect((self.host, self.port)) self.state = consts.SMPP_CLIENT_STATE_OPEN except socket.error: raise exceptions.ConnectionError("Connection refused")
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
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