From 796f5cfc547a627b095c118b46281de806c0ecd4 Mon Sep 17 00:00:00 2001 From: Lynesth Date: Sat, 7 Sep 2019 19:24:29 +1100 Subject: [PATCH 1/5] Implement Outstanding Operations management --- smpplib/client.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/smpplib/client.py b/smpplib/client.py index 9c4d0c7..3c4abff 100644 --- a/smpplib/client.py +++ b/smpplib/client.py @@ -28,6 +28,7 @@ import socket import struct +from time import sleep from smpplib import consts, exceptions, smpp logger = logging.getLogger('smpplib.client') @@ -64,11 +65,13 @@ class Client(object): _socket = None sequence_generator = None - def __init__(self, host, port, timeout=5, sequence_generator=None): + def __init__(self, host, port, timeout=5, sequence_generator=None, max_outstanding_operation=None): self.host = host self.port = int(port) self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._socket.settimeout(timeout) + self.outstanding_operations = 0 + self.max_outstanding_operations = max_outstanding_operation if sequence_generator is None: sequence_generator = SimpleSequenceGenerator() self.sequence_generator = sequence_generator @@ -176,6 +179,10 @@ def send_pdu(self, p): consts.DESCRIPTIONS[consts.SMPP_ESME_RINVBNDSTS], )) + if self.max_outstanding_operations: + while self.outstanding_operations >= self.max_outstanding_operations: + sleep(.1) + logger.debug('Sending %s PDU', p.command) generated = p.generate() @@ -194,6 +201,7 @@ def send_pdu(self, p): raise exceptions.ConnectionError() sent += sent_last + self.outstanding_operations += 1 return True def read_pdu(self): @@ -201,6 +209,9 @@ def read_pdu(self): logger.debug('Waiting for PDU...') + if self.outstanding_operations <= 0: + self.logger.warning('Number of outstanding operations <= 0') + try: raw_len = self._socket.recv(4) except socket.timeout: @@ -227,6 +238,8 @@ def read_pdu(self): logger.debug('Read %s PDU', pdu.command) + self.outstanding_operations -= 1 + if pdu.is_error(): return pdu From b92fc5cbb1e2fc079786e6bccc85729e17b6845a Mon Sep 17 00:00:00 2001 From: Lynesth Date: Sat, 7 Sep 2019 19:29:16 +1100 Subject: [PATCH 2/5] Fix typo --- smpplib/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/smpplib/client.py b/smpplib/client.py index 3c4abff..ad4b233 100644 --- a/smpplib/client.py +++ b/smpplib/client.py @@ -65,13 +65,13 @@ class Client(object): _socket = None sequence_generator = None - def __init__(self, host, port, timeout=5, sequence_generator=None, max_outstanding_operation=None): + def __init__(self, host, port, timeout=5, sequence_generator=None, max_outstanding_operations=None): self.host = host self.port = int(port) self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._socket.settimeout(timeout) self.outstanding_operations = 0 - self.max_outstanding_operations = max_outstanding_operation + self.max_outstanding_operations = max_outstanding_operations if sequence_generator is None: sequence_generator = SimpleSequenceGenerator() self.sequence_generator = sequence_generator From 8b8e5d44e67d94757643791e9d65df1b67816966 Mon Sep 17 00:00:00 2001 From: Lynesth Date: Fri, 13 Sep 2019 09:57:22 +1100 Subject: [PATCH 3/5] Update client.py --- smpplib/client.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/smpplib/client.py b/smpplib/client.py index ad4b233..bc01681 100644 --- a/smpplib/client.py +++ b/smpplib/client.py @@ -179,7 +179,7 @@ def send_pdu(self, p): consts.DESCRIPTIONS[consts.SMPP_ESME_RINVBNDSTS], )) - if self.max_outstanding_operations: + if self.max_outstanding_operations and p.command[-5:] != '_resp': while self.outstanding_operations >= self.max_outstanding_operations: sleep(.1) @@ -201,7 +201,11 @@ def send_pdu(self, p): raise exceptions.ConnectionError() sent += sent_last - self.outstanding_operations += 1 + if p.command[-5:] == '_resp': + self.outstanding_operations -= 1 + else: + self.outstanding_operations += 1 + return True def read_pdu(self): @@ -209,8 +213,12 @@ def read_pdu(self): logger.debug('Waiting for PDU...') - if self.outstanding_operations <= 0: - self.logger.warning('Number of outstanding operations <= 0') + if pdu.command[-5:] == '_resp': + self.outstanding_operations -= 1 + if self.outstanding_operations < 0: + self.logger.warning('Number of outstanding operations < 0') + else: + self.outstanding_operations += 1 try: raw_len = self._socket.recv(4) @@ -238,8 +246,6 @@ def read_pdu(self): logger.debug('Read %s PDU', pdu.command) - self.outstanding_operations -= 1 - if pdu.is_error(): return pdu From 97f2d7fc171fd003492b483f8236ced7b2fdb9dd Mon Sep 17 00:00:00 2001 From: Lynesth Date: Fri, 13 Sep 2019 09:58:51 +1100 Subject: [PATCH 4/5] Fix indent --- smpplib/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/smpplib/client.py b/smpplib/client.py index bc01681..941b3dc 100644 --- a/smpplib/client.py +++ b/smpplib/client.py @@ -215,8 +215,8 @@ def read_pdu(self): if pdu.command[-5:] == '_resp': self.outstanding_operations -= 1 - if self.outstanding_operations < 0: - self.logger.warning('Number of outstanding operations < 0') + if self.outstanding_operations < 0: + self.logger.warning('Number of outstanding operations < 0') else: self.outstanding_operations += 1 From b1207ce49dbfc9c534e4a3047bcbc5bbae7f1ab6 Mon Sep 17 00:00:00 2001 From: Lynesth Date: Sat, 5 Oct 2019 12:31:33 +1100 Subject: [PATCH 5/5] Use a set to keep track of outstanding operations --- smpplib/client.py | 49 +++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/smpplib/client.py b/smpplib/client.py index 215f9c9..fe82ad9 100644 --- a/smpplib/client.py +++ b/smpplib/client.py @@ -68,7 +68,7 @@ def __init__(self, host, port, timeout=5, sequence_generator=None, max_outstandi self.port = int(port) self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.timeout = timeout - self.outstanding_operations = 0 + self.outstanding_operations = set() self.max_outstanding_operations = max_outstanding_operations self.logger = logging.getLogger(logger_name or 'smpp.Client.{}'.format(id(self))) if sequence_generator is None: @@ -170,22 +170,41 @@ def unbind(self): except socket.timeout: raise exceptions.ConnectionError() - def send_pdu(self, p): + def manage_outstanding_operations(self, sending, pdu): + if not self.max_outstanding_operations: + return + + if pdu.is_response(): + operation = '{}{}'.format('S' if sending else 'C', pdu.sequence) + try: + self.outstanding_operations.remove(operation) + self.logger.debug('Unregistering outstanding operation {}'.format(operation)) + except KeyError: + self.logger.warning('Failed to unregistered outstanding operation {}'.format(operation)) + else: + operation = '{}{}'.format('C' if sending else 'S', pdu.sequence) + if pdu.sequence in self.outstanding_operations: + self.logger.warning('Outstanding operation {} already registered'.format(operation)) + else: + self.outstanding_operations.add(operation) + self.logger.debug('Registering outstanding operation {}'.format(operation)) + + def send_pdu(self, pdu): """Send PDU to the SMSC""" - if self.state not in consts.COMMAND_STATES[p.command]: + if self.state not in consts.COMMAND_STATES[pdu.command]: raise exceptions.PDUError("Command %s failed: %s" % ( - p.command, + pdu.command, consts.DESCRIPTIONS[consts.SMPP_ESME_RINVBNDSTS], )) - if self.max_outstanding_operations and p.command[-5:] != '_resp': - while self.outstanding_operations >= self.max_outstanding_operations: + if self.max_outstanding_operations and pdu.is_request(): + while len(self.outstanding_operations) >= self.max_outstanding_operations: sleep(.1) - self.logger.debug('Sending %s PDU', p.command) + self.logger.debug('Sending %s PDU', pdu.command) - generated = p.generate() + generated = pdu.generate() self.logger.debug('>>%s (%d bytes)', binascii.b2a_hex(generated), len(generated)) @@ -201,10 +220,7 @@ def send_pdu(self, p): raise exceptions.ConnectionError() sent += sent_last - if p.command[-5:] == '_resp': - self.outstanding_operations -= 1 - else: - self.outstanding_operations += 1 + self.manage_outstanding_operations(sending=True, pdu=pdu) return True @@ -213,13 +229,6 @@ def read_pdu(self): self.logger.debug('Waiting for PDU...') - if pdu.command[-5:] == '_resp': - self.outstanding_operations -= 1 - if self.outstanding_operations < 0: - self.logger.warning('Number of outstanding operations < 0') - else: - self.outstanding_operations += 1 - try: raw_len = self._socket.recv(4) except socket.timeout: @@ -246,6 +255,8 @@ def read_pdu(self): self.logger.debug('Read %s PDU', pdu.command) + self.manage_outstanding_operations(sending=False, pdu=pdu) + if pdu.is_error(): return pdu