Skip to content

Commit

Permalink
Merge pull request #215 from zoufou/v0.6-beta
Browse files Browse the repository at this point in the history
v0.6b28
  • Loading branch information
farirat committed Jun 25, 2015
2 parents 3f6436b + a15e1f5 commit 6188d71
Show file tree
Hide file tree
Showing 24 changed files with 350 additions and 103 deletions.
4 changes: 3 additions & 1 deletion .landscape.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ requirements:
- test-requirements
ignore-paths:
- misc
- jasmin/vendor
- jasmin/vendor
ignore-patterns:
- (^|/)test(/|$)
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ python:
# Command to install dependencies
install:
- python setup.py sdist
- sudo pip install dist/jasmin-0.6b27.tar.gz
- sudo pip install dist/jasmin-0.6b28.tar.gz
- sudo cp misc/config/init-script/jasmind-ubuntu /etc/init.d/jasmind
- sudo update-rc.d jasmind defaults
# Commands to run tests:
Expand Down
2 changes: 1 addition & 1 deletion jasmin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

MAJOR = 0
MINOR = 6
PATCH = 27
PATCH = 28
META = 'b'

def get_version():
Expand Down
3 changes: 2 additions & 1 deletion jasmin/managers/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import uuid
import time
import datetime
import jasmin
from twisted.spread import pb
from twisted.internet import defer
from jasmin.protocols.smpp.services import SMPPClientService
Expand Down Expand Up @@ -120,7 +121,7 @@ def perspective_persist(self, profile = 'jcli-prod'):

# Write configuration with datetime stamp
fh = open(path,'w')
fh.write('Persisted on %s\n' % time.strftime("%c"))
fh.write('Persisted on %s [Jasmin %s]\n' % (time.strftime("%c"), jasmin.get_release()))
fh.write(pickle.dumps(connectors, self.pickleProtocol))
fh.close()

Expand Down
35 changes: 31 additions & 4 deletions jasmin/managers/listeners.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from datetime import datetime, timedelta
from dateutil import parser
from twisted.internet import defer
from jasmin.vendor.smpp.pdu.pdu_types import CommandStatus
from jasmin.vendor.smpp.pdu.pdu_types import CommandStatus, CommandId
from jasmin.vendor.smpp.pdu.operations import SubmitSM
from jasmin.vendor.smpp.pdu.error import *
from txamqp.queue import Closed
Expand Down Expand Up @@ -530,6 +530,31 @@ def concatDeliverSMs(self, HSetReturn, splitMethod, total_segments, msg_ref_num,
# 2. Set the new short_message
pdu.params['short_message'] = short_message
yield self.deliver_sm_event(smpp = None, pdu = pdu, concatenated = True)

def code_dlr_msgid(self, pdu):
"Code the dlr msg id accordingly to SMPPc's dlr_msg_id_bases value"

try:
if pdu.id == CommandId.deliver_sm:
if self.SMPPClientFactory.config.dlr_msg_id_bases == 1:
ret = '%x' % int(pdu.dlr['id'])
elif self.SMPPClientFactory.config.dlr_msg_id_bases == 2:
ret = int(str(pdu.dlr['id']), 16)
else:
ret = pdu.dlr['id']
else:
# TODO: code dlr for submit_sm_resp maybe ? TBC
ret = pdu.dlr['id']
except Exception, e:
self.log.error('code_dlr_msgid, cannot code msgid [%s] with dlr_msg_id_bases:%s' % (
pdu.dlr['id'],
self.SMPPClientFactory.config.dlr_msg_id_bases,
))
self.log.error('code_dlr_msgid, error details: %s' % e)
ret = pdu.dlr['id']

self.log.debug('code_dlr_msgid: %s coded to %s' % (pdu.dlr['id'], ret))
return ret

@defer.inlineCallbacks
def deliver_sm_event(self, smpp, pdu, concatenated = False):
Expand Down Expand Up @@ -621,7 +646,9 @@ def deliver_sm_event(self, smpp, pdu, concatenated = False):
# This is a DLR !
# Check for DLR request
if self.redisClient is not None:
q = yield self.redisClient.get("queue-msgid:%s" % pdu.dlr['id'])
_coded_dlr_id = self.code_dlr_msgid(pdu)

q = yield self.redisClient.get("queue-msgid:%s" % _coded_dlr_id)
submit_sm_queue_id = None
connector_type = None
if q is not None:
Expand Down Expand Up @@ -649,7 +676,7 @@ def deliver_sm_event(self, smpp, pdu, concatenated = False):
# of the actual delivery receipt (2) and not the
# requested one (maybe 2 or 3)
dlr_level = 2,
id_smsc = pdu.dlr['id'],
id_smsc = _coded_dlr_id,
sub = pdu.dlr['sub'],
dlvrd = pdu.dlr['dlvrd'],
subdate = pdu.dlr['sdate'],
Expand Down Expand Up @@ -719,7 +746,7 @@ def deliver_sm_event(self, smpp, pdu, concatenated = False):
self.log.info("DLR [cid:%s] [smpp-msgid:%s] [status:%s] [submit date:%s] [done date:%s] [sub/dlvrd messages:%s/%s] [err:%s] [content:%s]" %
(
self.SMPPClientFactory.config.id,
pdu.dlr['id'],
_coded_dlr_id,
pdu.dlr['stat'],
pdu.dlr['sdate'],
pdu.dlr['ddate'],
Expand Down
3 changes: 2 additions & 1 deletion jasmin/protocols/cli/filtersm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import inspect
import pickle
import time
import jasmin
from dateutil import parser
from jasmin.protocols.cli.managers import PersistableManager, Session
from jasmin.routing.jasminApi import *
Expand Down Expand Up @@ -235,7 +236,7 @@ def persist(self, arg, opts):
try:
# Write configuration with datetime stamp
fh = open(path,'w')
fh.write('Persisted on %s\n' % time.strftime("%c"))
fh.write('Persisted on %s [Jasmin %s]\n' % (time.strftime("%c"), jasmin.get_release()))
fh.write(pickle.dumps(self.filters, 2))
fh.close()
except IOError:
Expand Down
3 changes: 2 additions & 1 deletion jasmin/protocols/cli/httpccm.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pickle
import time
import jasmin
from jasmin.protocols.cli.managers import PersistableManager, Session
from jasmin.routing.jasminApi import HttpConnector

Expand Down Expand Up @@ -89,7 +90,7 @@ def persist(self, arg, opts):
try:
# Write configuration with datetime stamp
fh = open(path,'w')
fh.write('Persisted on %s\n' % time.strftime("%c"))
fh.write('Persisted on %s [Jasmin %s]\n' % (time.strftime("%c"), jasmin.get_release()))
fh.write(pickle.dumps(self.httpccs, 2))
fh.close()
except IOError:
Expand Down
9 changes: 7 additions & 2 deletions jasmin/protocols/cli/smppccm.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
'addr_range': 'addressRange', 'src_addr': 'source_addr', 'proto_id': 'protocol_id',
'priority': 'priority_flag', 'validity': 'validity_period', 'ripf': 'replace_if_present_flag',
'def_msg_id': 'sm_default_msg_id', 'coding': 'data_coding', 'requeue_delay': 'requeue_delay',
'submit_throughput': 'submit_sm_throughput', 'dlr_expiry': 'dlr_expiry'
'submit_throughput': 'submit_sm_throughput', 'dlr_expiry': 'dlr_expiry', 'dlr_msgid': 'dlr_msg_id_bases'
}
# Keys to be kept in string type, as requested in #64 and #105
SMPPClientConfigStringKeys = ['systemType', 'username', 'password', 'addressRange']
Expand Down Expand Up @@ -84,7 +84,12 @@ def set(self, key, value):
def getAll(self):
r = {}
for key, value in SMPPClientConfigKeyMap.iteritems():
r[key] = castOutputToBuiltInType(key, getattr(self, value))
if hasattr(self, value):
r[key] = castOutputToBuiltInType(key, getattr(self, value))
else:
# Related to #192
r[key] = 'Unknown (object is from an old Jasmin release !)'

return r

def SMPPClientConfigBuild(fCallback):
Expand Down
16 changes: 8 additions & 8 deletions jasmin/protocols/cli/statsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def user(self, arg, opts):

user = self.pb['router'].getUser(opts.user)
# SMPP Server stats
for k,v in user.CnxStatus.smpps.iteritems():
for k,v in user.getCnxStatus().smpps.iteritems():
row = []
row.append('#%s' % k)
row.append('SMPP Server')
Expand All @@ -35,7 +35,7 @@ def user(self, arg, opts):
table.append(row)

# HTTP API stats
for k,v in user.CnxStatus.httpapi.iteritems():
for k,v in user.getCnxStatus().httpapi.iteritems():
row = []
row.append('#%s' % k)
row.append('HTTP Api')
Expand All @@ -56,13 +56,13 @@ def users(self, arg, opts):
for user in users:
row = []
row.append('#%s' % user.uid)
row.append(user.CnxStatus.smpps['bound_connections_count']['bind_receiver'] +
user.CnxStatus.smpps['bound_connections_count']['bind_transmitter'] +
user.CnxStatus.smpps['bound_connections_count']['bind_transceiver']
row.append(user.getCnxStatus().smpps['bound_connections_count']['bind_receiver'] +
user.getCnxStatus().smpps['bound_connections_count']['bind_transmitter'] +
user.getCnxStatus().smpps['bound_connections_count']['bind_transceiver']
)
row.append(formatDateTime(user.CnxStatus.smpps['last_activity_at']))
row.append(user.CnxStatus.httpapi['connects_count'])
row.append(formatDateTime(user.CnxStatus.httpapi['last_activity_at']))
row.append(formatDateTime(user.getCnxStatus().smpps['last_activity_at']))
row.append(user.getCnxStatus().httpapi['connects_count'])
row.append(formatDateTime(user.getCnxStatus().httpapi['last_activity_at']))

table.append(row)

Expand Down
2 changes: 2 additions & 0 deletions jasmin/protocols/cli/test/test_smppccm.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def test_add_and_show(self):
'loglevel 20',
'bind transceiver',
'proto_id None',
'dlr_msgid 0',
'con_loss_delay 10',
'bind_ton 0',
'pdu_red_to 10',
Expand Down Expand Up @@ -212,6 +213,7 @@ def test_update_and_show(self):
'loglevel 20',
'bind transceiver',
'proto_id None',
'dlr_msgid 0',
'con_loss_delay 10',
'bind_ton 0',
'pdu_red_to 10',
Expand Down
12 changes: 6 additions & 6 deletions jasmin/protocols/http/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ def render(self, request):
updated_request.args['username'][0])

# Update CnxStatus
user.CnxStatus.httpapi['connects_count']+= 1
user.CnxStatus.httpapi['submit_sm_request_count']+= 1
user.CnxStatus.httpapi['last_activity_at'] = datetime.now()
user.getCnxStatus().httpapi['connects_count']+= 1
user.getCnxStatus().httpapi['submit_sm_request_count']+= 1
user.getCnxStatus().httpapi['last_activity_at'] = datetime.now()

# Build SubmitSmPDU
SubmitSmPDU = self.opFactory.SubmitSM(
Expand Down Expand Up @@ -187,10 +187,10 @@ def render(self, request):
dlr_method = None

# QoS throttling
if user.mt_credential.getQuota('http_throughput') >= 0 and user.CnxStatus.httpapi['qos_last_submit_sm_at'] != 0:
if user.mt_credential.getQuota('http_throughput') >= 0 and user.getCnxStatus().httpapi['qos_last_submit_sm_at'] != 0:
qos_throughput_second = 1 / float(user.mt_credential.getQuota('http_throughput'))
qos_throughput_ysecond_td = timedelta( microseconds = qos_throughput_second * 1000000)
qos_delay = datetime.now() - user.CnxStatus.httpapi['qos_last_submit_sm_at']
qos_delay = datetime.now() - user.getCnxStatus().httpapi['qos_last_submit_sm_at']
if qos_delay < qos_throughput_ysecond_td:
self.stats.inc('throughput_error_count')
self.log.error("QoS: submit_sm_event is faster (%s) than fixed throughput (%s) for user (%s), rejecting message." % (
Expand All @@ -200,7 +200,7 @@ def render(self, request):
))

raise ThroughputExceededError("User throughput exceeded")
user.CnxStatus.httpapi['qos_last_submit_sm_at'] = datetime.now()
user.getCnxStatus().httpapi['qos_last_submit_sm_at'] = datetime.now()

# Get number of PDUs to be sent (for billing purpose)
_pdu = SubmitSmPDU
Expand Down
13 changes: 7 additions & 6 deletions jasmin/protocols/http/test/test_CnxStatus.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,38 @@ class CnxStatusCases(HTTPApiTestCases):

@defer.inlineCallbacks
def test_connects_count(self):
self.assertEqual(self.u1.CnxStatus.httpapi['connects_count'], 0)
self.assertEqual(self.u1.getCnxStatus().httpapi['connects_count'], 0)

for i in range(100):
yield self.web.get("send", {'username': self.u1.username,
'password': 'correct',
'to': '98700177',
'content': 'anycontent'})

self.assertEqual(self.u1.CnxStatus.httpapi['connects_count'], 100)
self.assertEqual(self.u1.getCnxStatus().httpapi['connects_count'], 100)

@defer.inlineCallbacks
def test_last_activity_at(self):
self.assertEqual(self.u1.CnxStatus.httpapi['last_activity_at'], 0)
before_test = self.u1.getCnxStatus().httpapi['last_activity_at']

yield self.web.get("send", {'username': self.u1.username,
'password': 'correct',
'to': '98700177',
'content': 'anycontent'})

self.assertApproximates(datetime.now(),
self.u1.CnxStatus.httpapi['last_activity_at'],
self.u1.getCnxStatus().httpapi['last_activity_at'],
timedelta( seconds = 0.1 ))
self.assertNotEqual(self.u1.getCnxStatus().httpapi['last_activity_at'], before_test)

@defer.inlineCallbacks
def test_submit_sm_request_count(self):
self.assertEqual(self.u1.CnxStatus.httpapi['submit_sm_request_count'], 0)
before_test = self.u1.getCnxStatus().httpapi['submit_sm_request_count']

for i in range(100):
yield self.web.get("send", {'username': self.u1.username,
'password': 'correct',
'to': '98700177',
'content': 'anycontent'})

self.assertEqual(self.u1.CnxStatus.httpapi['submit_sm_request_count'], 100)
self.assertEqual(self.u1.getCnxStatus().httpapi['submit_sm_request_count'], before_test+100)
10 changes: 10 additions & 0 deletions jasmin/protocols/smpp/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,16 @@ def __init__(self, **kwargs):
self.submit_sm_throughput = kwargs.get('submit_sm_throughput', 1)
if not isinstance(self.submit_sm_throughput, int) and not isinstance(self.submit_sm_throughput, float):
raise TypeMismatch('submit_sm_throughput must be an integer or float')

# DLR Message id bases from submit_sm_resp to deliver_sm, possible values:
# [0] (default) : submit_sm_resp and deliver_sm messages IDs are on the same base.
# [1] : submit_sm_resp msg-id is in hexadecimal base, deliver_sm msg-id is in
# decimal base.
# [2] : submit_sm_resp msg-id is in decimal base, deliver_sm msg-id is in
# hexadecimal base.
self.dlr_msg_id_bases = kwargs.get('dlr_msg_id_bases', 0)
if self.dlr_msg_id_bases not in [0, 1, 2]:
raise UnknownValue('Invalid dlr_msg_id_bases: %s' % self.dlr_msg_id_bases)

class SMPPClientServiceConfig(ConfigFile):
def __init__(self, config_file):
Expand Down
22 changes: 11 additions & 11 deletions jasmin/protocols/smpp/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ def submit_sm_event(self, system_id, *args):
SubmitSmPDU = args[1]

# Update CnxStatus
user.CnxStatus.smpps['submit_sm_request_count']+= 1
user.getCnxStatus().smpps['submit_sm_request_count']+= 1

# Basic validation
if len(SubmitSmPDU.params['destination_addr']) < 1 or SubmitSmPDU.params['destination_addr'] is None:
Expand Down Expand Up @@ -277,10 +277,10 @@ def submit_sm_event(self, system_id, *args):
routedConnector = route.getConnector()

# QoS throttling
if user.mt_credential.getQuota('smpps_throughput') >= 0 and user.CnxStatus.smpps['qos_last_submit_sm_at'] != 0:
if user.mt_credential.getQuota('smpps_throughput') >= 0 and user.getCnxStatus().smpps['qos_last_submit_sm_at'] != 0:
qos_throughput_second = 1 / float(user.mt_credential.getQuota('smpps_throughput'))
qos_throughput_ysecond_td = timedelta( microseconds = qos_throughput_second * 1000000)
qos_delay = datetime.now() - user.CnxStatus.smpps['qos_last_submit_sm_at']
qos_delay = datetime.now() - user.getCnxStatus().smpps['qos_last_submit_sm_at']
if qos_delay < qos_throughput_ysecond_td:
self.log.error("QoS: submit_sm_event is faster (%s) than fixed throughput (%s) for user (%s), rejecting message." % (
qos_delay,
Expand All @@ -289,7 +289,7 @@ def submit_sm_event(self, system_id, *args):
))

raise SubmitSmThroughputExceededError()
user.CnxStatus.smpps['qos_last_submit_sm_at'] = datetime.now()
user.getCnxStatus().smpps['qos_last_submit_sm_at'] = datetime.now()

# Pre-sending submit_sm: Billing processing
bill = route.getBillFor(user)
Expand Down Expand Up @@ -401,9 +401,9 @@ def canOpenNewConnection(self, user, bind_type):
return False
# Still didnt reach max_bindings ?
elif user.smpps_credential.getQuota('max_bindings') is not None:
bind_count = user.CnxStatus.smpps['bound_connections_count']['bind_transmitter']
bind_count+= user.CnxStatus.smpps['bound_connections_count']['bind_receiver']
bind_count+= user.CnxStatus.smpps['bound_connections_count']['bind_transceiver']
bind_count = user.getCnxStatus().smpps['bound_connections_count']['bind_transmitter']
bind_count+= user.getCnxStatus().smpps['bound_connections_count']['bind_receiver']
bind_count+= user.getCnxStatus().smpps['bound_connections_count']['bind_transceiver']
if bind_count >= user.smpps_credential.getQuota('max_bindings'):
self.log.warning('New bind rejected for username: "%s", reason: max_bindings limit reached.' %
user.username)
Expand Down Expand Up @@ -433,12 +433,12 @@ def addBinding(self, connection):
_SMPPBindManager.addBinding(self, connection)

# Update CnxStatus
self.user.CnxStatus.smpps['bind_count']+= 1
self.user.CnxStatus.smpps['bound_connections_count'][str(connection.bind_type)]+= 1
self.user.getCnxStatus().smpps['bind_count']+= 1
self.user.getCnxStatus().smpps['bound_connections_count'][str(connection.bind_type)]+= 1

def removeBinding(self, connection):
_SMPPBindManager.removeBinding(self, connection)

# Update CnxStatus
self.user.CnxStatus.smpps['unbind_count']+= 1
self.user.CnxStatus.smpps['bound_connections_count'][str(connection.bind_type)]-= 1
self.user.getCnxStatus().smpps['unbind_count']+= 1
self.user.getCnxStatus().smpps['bound_connections_count'][str(connection.bind_type)]-= 1

0 comments on commit 6188d71

Please sign in to comment.