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

Add ThreadSafeClient implementation by PaulWasTaken · Pull Request #203 · python-smpplib/python-smpplib · GitHub

Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (4) All 1 file type selected
Only manifest files
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
2 changes: 1 addition & 1 deletion setup.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
url='https://github.com/python-smpplib/python-smpplib',
description='SMPP library for python',
packages=find_packages(),
install_requires=['six'],
install_requires=['six', 'monotonic'],
extras_require=dict(
tests=('typing; python_version < "3.5"', 'pytest', 'mock'),
),
Expand Down
75 changes: 73 additions & 2 deletions smpplib/client.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
"""SMPP client module"""

import binascii
import collections
import logging
import select
import socket
import struct
import warnings

from monotonic import monotonic
from smpplib import consts, exceptions, smpp


Expand Down Expand Up @@ -91,7 +93,6 @@ def __init__(
else:
self.allow_unknown_opt_params = allow_unknown_opt_params


self._socket = self._create_socket()

def __enter__(self):
Expand Down Expand Up @@ -301,7 +302,7 @@ def set_message_received_handler(self, func):
def set_message_sent_handler(self, func):
"""Set new function to handle message sent event"""
self.message_sent_handler = func

def set_query_resp_handler(self, func):
"""Set new function to handle query resp event"""
self.query_resp_handler = func
Expand Down Expand Up @@ -421,3 +422,73 @@ def query_message(self, **kwargs):
qsm = smpp.make_pdu('query_sm', client=self, **kwargs)
self.send_pdu(qsm)
return qsm


class ThreadSafeClient(Client):
should_stop = False

def __init__(self, *args, **kwargs):
# Socket polling period
select_timeout = kwargs.get('select_timeout', 1.0)

super(ThreadSafeClient, self).__init__(*args, **kwargs)

self._select_timeout = select_timeout

self._send_queue = collections.deque()
self._read_sock, self._send_sock = socket.socketpair()

# It will help not to spam the server
self._last_active_time = 0.0

def accept(self, obj):
"""Accept an object"""
raise NotImplementedError('not implemented')

def send_pdu(self, pdu, send_later=False):
if send_later:
self._send_queue.append(pdu)
self._send_sock.send(b'\x00')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Why are we sending a 00? Is it a no-op? If so, why are we sending it?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

It is some sort of notification frame. We put it into the send socket to wake up our read socket

return True
else:
pdu_sent = super(ThreadSafeClient, self).send_pdu(pdu)
self._last_active_time = monotonic()
return pdu_sent

def send_message(self, send_later=True, **kwargs):
submit_sm_pdu = smpp.make_pdu('submit_sm', client=self, **kwargs)
self.send_pdu(submit_sm_pdu, send_later=send_later)
return submit_sm_pdu

def _should_prolong_session(self):
# We need some time to send enquire_link before the next `select` call comes
passed_from_last_message = monotonic() - self._last_active_time

return self.timeout - self._select_timeout <= passed_from_last_message

def observe(self, ignore_error_codes=None, auto_send_enquire_link=True):
while not self.should_stop:
rlist, _, _ = select.select(
[self._socket, self._read_sock], [], [], self._select_timeout,
)

if self.should_stop:
break

if not rlist:
if self._should_prolong_session():
if not auto_send_enquire_link:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

TODO: check auto_send_enquire_link before self._should_prolong_session() call

raise exceptions.SessionProlongationDisabled()

self.logger.debug('Sending enquire_link')
pdu = smpp.make_pdu('enquire_link', client=self)
self.send_pdu(pdu)
else:
for ready_socket in rlist:
if ready_socket is self._socket:
self.read_once(ignore_error_codes, auto_send_enquire_link)
else:
self._read_sock.recv(1)
self.send_pdu(self._send_queue.pop())

self.logger.info('Finished observing...')
4 changes: 4 additions & 0 deletions smpplib/exceptions.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ class PDUError(RuntimeError):

class MessageTooLong(ValueError):
"""Text too long to fit 255 SMS"""


class SessionProlongationDisabled(Exception):
"""Server send nothing and we do not want to continue"""
19 changes: 16 additions & 3 deletions smpplib/tests/test_client.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import time
import warnings

import pytest
from mock import Mock, call
from mock import call, Mock
from monotonic import monotonic

from smpplib.client import Client
from smpplib.smpp import make_pdu
from smpplib import consts
from smpplib import exceptions
from smpplib.client import Client, ThreadSafeClient
from smpplib.smpp import make_pdu


def test_client_construction_allow_unknown_opt_params_warning():
Expand Down Expand Up @@ -44,3 +47,13 @@ def test_client_error_pdu_custom_handler():
client.read_once()

assert mock_error_pdu_handler.mock_calls == [call(error_pdu)]


def test_prolongation():
client = ThreadSafeClient("localhost", 5679)
client._last_active_time = monotonic()
assert not client._should_prolong_session()

time.sleep(client.timeout - client._select_timeout)

assert client._should_prolong_session()

Back | FazBrowse Home | New Git URL