| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ab70a51 commit 097d6f3
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,10 +19,12 @@ | |||
| 19 | 19 | """SMPP client module""" | |
| 20 | 20 | ||
| 21 | 21 | import binascii | |
| 22 | + import collections | ||
| 22 | 23 | import logging | |
| 23 | 24 | import select | |
| 24 | 25 | import socket | |
| 25 | 26 | import struct | |
| 27 | + import time | ||
| 26 | 28 | import warnings | |
| 27 | 29 | ||
| 28 | 30 | from smpplib import consts, exceptions, smpp | |
@@ -91,7 +93,6 @@ def __init__( | |||
| 91 | 93 | else: | |
| 92 | 94 | self.allow_unknown_opt_params = allow_unknown_opt_params | |
| 93 | 95 | ||
| 94 | - | ||
| 95 | 96 | self._socket = self._create_socket() | |
| 96 | 97 | ||
| 97 | 98 | def __enter__(self): | |
@@ -301,7 +302,7 @@ def set_message_received_handler(self, func): | |||
| 301 | 302 | def set_message_sent_handler(self, func): | |
| 302 | 303 | """Set new function to handle message sent event""" | |
| 303 | 304 | self.message_sent_handler = func | |
| 304 | - | ||
| 305 | + | ||
| 305 | 306 | def set_query_resp_handler(self, func): | |
| 306 | 307 | """Set new function to handle query resp event""" | |
| 307 | 308 | self.query_resp_handler = func | |
@@ -421,3 +422,75 @@ def query_message(self, **kwargs): | |||
| 421 | 422 | qsm = smpp.make_pdu('query_sm', client=self, **kwargs) | |
| 422 | 423 | self.send_pdu(qsm) | |
| 423 | 424 | 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...') | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,3 +17,7 @@ class PDUError(RuntimeError): | |||
| 17 | 17 | ||
| 18 | 18 | class MessageTooLong(ValueError): | |
| 19 | 19 | """Text too long to fit 255 SMS""" | |
| 20 | + | ||
| 21 | + | ||
| 22 | + class SessionProlongationDisabled(Exception): | ||
| 23 | + """Server send nothing and we do not want to continue""" | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,11 +1,13 @@ | |||
| 1 | + import time | ||
| 1 | 2 | import warnings | |
| 3 | + | ||
| 2 | 4 | import pytest | |
| 3 | - from mock import Mock, call | ||
| 5 | + from mock import call, Mock | ||
| 4 | 6 | ||
| 5 | - from smpplib.client import Client | ||
| 6 | - from smpplib.smpp import make_pdu | ||
| 7 | 7 | from smpplib import consts | |
| 8 | 8 | from smpplib import exceptions | |
| 9 | + from smpplib.client import Client, ThreadSafeClient | ||
| 10 | + from smpplib.smpp import make_pdu | ||
| 9 | 11 | ||
| 10 | 12 | ||
| 11 | 13 | def test_client_construction_allow_unknown_opt_params_warning(): | |
@@ -44,3 +46,13 @@ def test_client_error_pdu_custom_handler(): | |||
| 44 | 46 | client.read_once() | |
| 45 | 47 | ||
| 46 | 48 | 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() | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments