FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Add ThreadSafeClient implementation · python-smpplib/python-smpplib@097d6f3 · GitHub

Commit 097d6f3

Browse files
committed
Add ThreadSafeClient implementation
1 parent ab70a51 commit 097d6f3

3 files changed

Lines changed: 94 additions & 5 deletions

File tree

‎smpplib/client.py‎

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
"""SMPP client module"""
2020

2121
import binascii
22+
import collections
2223
import logging
2324
import select
2425
import socket
2526
import struct
27+
import time
2628
import warnings
2729

2830
from smpplib import consts, exceptions, smpp
@@ -91,7 +93,6 @@ def __init__(
9193
else:
9294
self.allow_unknown_opt_params = allow_unknown_opt_params
9395

94-
9596
self._socket = self._create_socket()
9697

9798
def __enter__(self):
@@ -301,7 +302,7 @@ def set_message_received_handler(self, func):
301302
def set_message_sent_handler(self, func):
302303
"""Set new function to handle message sent event"""
303304
self.message_sent_handler = func
304-
305+
305306
def set_query_resp_handler(self, func):
306307
"""Set new function to handle query resp event"""
307308
self.query_resp_handler = func
@@ -421,3 +422,75 @@ def query_message(self, **kwargs):
421422
qsm = smpp.make_pdu('query_sm', client=self, **kwargs)
422423
self.send_pdu(qsm)
423424
return qsm
425+
426+
427+
class ThreadSafeClient(Client):
428+
should_stop = False
429+
430+
def __init__(
431+
self,
432+
*args,
433+
select_timeout=1.0,
434+
**kwargs,
435+
):
436+
super().__init__(*args, **kwargs)
437+
438+
self._select_timeout = select_timeout
439+
440+
self._send_queue = collections.deque()
441+
self._read_sock, self._send_sock = socket.socketpair()
442+
443+
# It will help not to spam the server
444+
self._last_active_time = 0.0
445+
446+
def accept(self, obj):
447+
"""Accept an object"""
448+
raise NotImplementedError('not implemented')
449+
450+
def send_pdu(self, pdu, send_later=False) -> bool:
451+
if send_later:
452+
self._send_queue.append(pdu)
453+
self._send_sock.send(b'\x00')
454+
return True
455+
else:
456+
pdu_sent = super().send_pdu(pdu)
457+
self._last_active_time = time.monotonic()
458+
return pdu_sent
459+
460+
def send_message(self, send_later=True, **kwargs):
461+
submit_sm_pdu = smpp.make_pdu('submit_sm', client=self, **kwargs)
462+
self.send_pdu(submit_sm_pdu, send_later=send_later)
463+
return submit_sm_pdu
464+
465+
def _should_prolong_session(self):
466+
# We need some time to send enquire_link before the next `select` call comes
467+
passed_from_last_message = time.monotonic() - self._last_active_time
468+
469+
return self.timeout - self._select_timeout <= passed_from_last_message
470+
471+
def observe(self, ignore_error_codes=None, auto_send_enquire_link=True) -> None:
472+
while not self.should_stop:
473+
rlist, _, _ = select.select(
474+
[self._socket, self._read_sock], [], [], self._select_timeout,
475+
)
476+
477+
if self.should_stop:
478+
break
479+
480+
if not rlist:
481+
if self._should_prolong_session():
482+
if not auto_send_enquire_link:
483+
raise exceptions.SessionProlongationDisabled()
484+
485+
self.logger.debug('Sending enquire_link')
486+
pdu = smpp.make_pdu('enquire_link', client=self)
487+
self.send_pdu(pdu)
488+
else:
489+
for ready_socket in rlist:
490+
if ready_socket is self._socket:
491+
self.read_once(ignore_error_codes, auto_send_enquire_link)
492+
else:
493+
self._read_sock.recv(1)
494+
self.send_pdu(self._send_queue.pop())
495+
496+
self.logger.info('Finished observing...')

‎smpplib/exceptions.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ class PDUError(RuntimeError):
1717

1818
class MessageTooLong(ValueError):
1919
"""Text too long to fit 255 SMS"""
20+
21+
22+
class SessionProlongationDisabled(Exception):
23+
"""Server send nothing and we do not want to continue"""

‎smpplib/tests/test_client.py‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
import time
12
import warnings
3+
24
import pytest
3-
from mock import Mock, call
5+
from mock import call, Mock
46

5-
from smpplib.client import Client
6-
from smpplib.smpp import make_pdu
77
from smpplib import consts
88
from smpplib import exceptions
9+
from smpplib.client import Client, ThreadSafeClient
10+
from smpplib.smpp import make_pdu
911

1012

1113
def test_client_construction_allow_unknown_opt_params_warning():
@@ -44,3 +46,13 @@ def test_client_error_pdu_custom_handler():
4446
client.read_once()
4547

4648
assert mock_error_pdu_handler.mock_calls == [call(error_pdu)]
49+
50+
51+
def test_prolongation():
52+
client = ThreadSafeClient("localhost", 5679)
53+
client._last_active_time = time.monotonic()
54+
assert not client._should_prolong_session()
55+
56+
time.sleep(client.timeout - client._select_timeout)
57+
58+
assert client._should_prolong_session()

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL