| Server IP : 209.209.40.120 / Your IP : 216.73.217.112 Web Server : Microsoft-IIS/10.0 System : Windows NT NEWWWW 10.0 build 17763 (Windows Server 2019) i586 User : NEWWWW$ ( 0) PHP Version : 8.3.30 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /Python312/Lib/site-packages/smpplib/ |
Upload File : |
#
# smpplib -- SMPP Library for Python
# Copyright (c) 2005 Martynas Jocius <mjoc@akl.lt>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""SMPP Commands module"""
import logging
import struct
import six
from smpplib import consts, exceptions, pdu
from smpplib.ptypes import flag, ostr
logger = logging.getLogger('smpplib.command')
def factory(command_name, **kwargs):
"""Return instance of a specific command class"""
try:
return {
'bind_transmitter': BindTransmitter,
'bind_transmitter_resp': BindTransmitterResp,
'bind_receiver': BindReceiver,
'bind_receiver_resp': BindReceiverResp,
'bind_transceiver': BindTransceiver,
'bind_transceiver_resp': BindTransceiverResp,
'data_sm': DataSM,
'data_sm_resp': DataSMResp,
'generic_nack': GenericNAck,
'submit_sm': SubmitSM,
'submit_sm_resp': SubmitSMResp,
'deliver_sm': DeliverSM,
'deliver_sm_resp': DeliverSMResp,
'query_sm': QuerySM,
'query_sm_resp': QuerySMResp,
'unbind': Unbind,
'unbind_resp': UnbindResp,
'enquire_link': EnquireLink,
'enquire_link_resp': EnquireLinkResp,
'alert_notification': AlertNotification,
}[command_name](command_name, **kwargs)
except KeyError:
raise exceptions.UnknownCommandError('Command "%s" is not supported' % command_name)
def get_optional_name(code):
"""Return optional_params name by given code. If code is unknown, raise
UnkownCommandError exception"""
for key, value in six.iteritems(consts.OPTIONAL_PARAMS):
if value == code:
return key
raise exceptions.UnknownCommandError('Unknown SMPP command code "0x%x"' % code)
def get_optional_code(name):
"""Return optional_params code by given command name. If name is unknown,
raise UnknownCommandError exception"""
try:
return consts.OPTIONAL_PARAMS[name]
except KeyError:
raise exceptions.UnknownCommandError('Unknown SMPP command name "%s"' % name)
def unpack_short(data, pos):
return struct.unpack('>H', data[pos:pos+2])[0], pos + 2
class Command(pdu.PDU):
"""SMPP PDU Command class"""
params = {}
def __init__(self, command, need_sequence=True, allow_unknown_opt_params=False, **kwargs):
super(Command, self).__init__(**kwargs)
self.allow_unknown_opt_params = allow_unknown_opt_params
self.command = command
if need_sequence and (kwargs.get('sequence') is None):
self.sequence = self._next_seq()
if kwargs.get('status') is None:
self.status = consts.SMPP_ESME_ROK
self._set_vars(**kwargs)
def _set_vars(self, **kwargs):
"""set attributes accordingly to kwargs"""
for key, value in six.iteritems(kwargs):
if not hasattr(self, key) or getattr(self, key) is None:
setattr(self, key, value)
def generate_params(self):
"""Generate binary data from the object"""
if hasattr(self, 'prep') and callable(self.prep):
self.prep()
body = consts.EMPTY_STRING
for field in self.params_order:
param = self.params[field]
if self.field_is_optional(field):
if param.type is int:
value = self._generate_int_tlv(field)
if value:
body += value
elif param.type is str:
value = self._generate_string_tlv(field)
if value:
body += value
elif param.type is ostr:
value = self._generate_ostring_tlv(field)
if value:
body += value
else:
if param.type is int:
value = self._generate_int(field)
body += value
elif param.type is str:
value = self._generate_string(field)
body += value
elif param.type is ostr:
value = self._generate_ostring(field)
if value:
body += value
return body
def _generate_opt_header(self, field):
"""Generate a header for an optional parameter"""
raise NotImplementedError('Vendors not supported')
def _generate_int(self, field):
"""Generate integer value"""
fmt = self._int_pack_format(field)
data = getattr(self, field)
if data:
return struct.pack(">" + fmt, data)
else:
return consts.NULL_STRING
def _generate_string(self, field):
"""Generate string value"""
field_value = getattr(self, field)
if hasattr(self.params[field], 'size'):
size = self.params[field].size
value = field_value.ljust(size, chr(0))
elif hasattr(self.params[field], 'max'):
if len(field_value or '') >= self.params[field].max:
field_value = field_value[0:self.params[field].max - 1]
if field_value:
value = field_value + chr(0)
else:
value = chr(0)
setattr(self, field, field_value)
return six.b(value)
def _generate_ostring(self, field):
"""Generate octet string value (no null terminator)"""
value = getattr(self, field)
if value:
return value
else:
return None # chr(0)
def _generate_int_tlv(self, field):
"""Generate integer value"""
fmt = self._int_pack_format(field)
data = getattr(self, field)
field_code = get_optional_code(field)
field_length = self.params[field].size
value = None
if data is not None:
value = struct.pack(">HH" + fmt, field_code, field_length, data)
return value
def _generate_string_tlv(self, field):
"""Generate string value"""
field_value = getattr(self, field)
field_code = get_optional_code(field)
if hasattr(self.params[field], 'size'):
size = self.params[field].size
fvalue = field_value.ljust(size, chr(0))
value = struct.pack(">HH", field_code, size) + fvalue
elif hasattr(self.params[field], 'max'):
if len(field_value or '') > self.params[field].max:
field_value = field_value[0:self.params[field].max - 1]
if field_value:
fvalue = field_value + chr(0)
field_length = len(fvalue)
value = struct.pack(">HH", field_code, field_length) + fvalue.encode()
else:
value = None # chr(0)
return value
def _generate_ostring_tlv(self, field):
"""Generate octet string value (no null terminator)"""
try:
field_value = getattr(self, field)
except:
return None
field_code = get_optional_code(field)
value = None
if field_value:
field_length = len(field_value)
value = struct.pack(">HH", field_code, field_length) + field_value
return value
def _int_pack_format(self, field):
"""Return format type"""
return consts.INT_PACK_FORMATS[self.params[field].size]
def _parse_int(self, field, data, pos):
"""
Parse fixed-length chunk from a PDU.
Return (data, pos) tuple.
"""
size = self.params[field].size
fmt = self._int_pack_format(field)
field_value, = struct.unpack(">" + fmt, data[pos:pos + size])
setattr(self, field, field_value)
pos += size
return data, pos
def _parse_string(self, field, data, pos, length=None):
"""
Parse variable-length string from a PDU.
Return (data, pos) tuple.
"""
if length is None:
end = data.find(consts.NULL_STRING, pos)
length = end - pos
else:
length -= 1 # length includes trailing NULL character
setattr(self, field, data[pos:pos + length])
pos += length + 1
return data, pos
def _parse_ostring(self, field, data, pos, length=None):
"""
Parse an octet string from a PDU.
Return (data, pos) tuple.
"""
if length is None:
length_field = self.params[field].len_field
length = int(getattr(self, length_field))
setattr(self, field, data[pos:pos + length])
pos += length
return data, pos
def is_fixed(self, field):
"""Return True if field has fixed length, False otherwise"""
if hasattr(self.params[field], 'size'):
return True
return False
def parse_params(self, data):
"""Parse data into the object structure"""
pos = 0
dlen = len(data)
for field in self.params_order:
param = self.params[field]
if pos == dlen or self.field_is_optional(field):
break
if param.type is int:
data, pos = self._parse_int(field, data, pos)
elif param.type is str:
data, pos = self._parse_string(field, data, pos)
elif param.type is ostr:
data, pos = self._parse_ostring(field, data, pos)
if pos < dlen:
self.parse_optional_params(data[pos:])
def parse_optional_params(self, data):
"""Parse optional parameters.
Optional parameters have the following format:
* type (2 bytes)
* length (2 bytes)
* value (variable, <length> bytes)
"""
dlen = len(data)
pos = 0
while pos < dlen:
type_code, pos = unpack_short(data, pos)
length, pos = unpack_short(data, pos)
try:
field = get_optional_name(type_code)
except exceptions.UnknownCommandError as e:
if self.allow_unknown_opt_params:
logger.warning("Unknown optional parameter type 0x%x, skipping", type_code)
pos += length
continue
raise
param = self.params[field]
if param.type is int:
data, pos = self._parse_int(field, data, pos)
elif param.type is str:
data, pos = self._parse_string(field, data, pos, length)
elif param.type is ostr:
data, pos = self._parse_ostring(field, data, pos, length)
def field_exists(self, field):
"""Return True if field exists, False otherwise"""
return hasattr(self.params, field)
def field_is_optional(self, field):
"""Return True if field is optional, False otherwise"""
if hasattr(self, 'mandatory_fields') and field in self.mandatory_fields:
return False
elif field in consts.OPTIONAL_PARAMS:
return True
elif self.is_vendor():
# FIXME: No vendor support yet
return False
return False
class Param(object):
"""Command parameter info class"""
def __init__(self, **kwargs):
if 'type' not in kwargs:
raise KeyError('Parameter Type not defined')
if kwargs.get('type') not in (int, str, ostr, flag):
raise ValueError("Invalid parameter type: %s" % kwargs.get('type'))
valid_keys = ('type', 'size', 'min', 'max', 'len_field')
for k in kwargs:
if k not in valid_keys:
raise KeyError("Key '%s' not allowed here" % k)
self.type = kwargs.get('type')
for param in ('size', 'min', 'max', 'len_field'):
if param in kwargs:
setattr(self, param, kwargs[param])
def __repr__(self):
"""Shows type of Param in console"""
return ''.join(('<Param of ', str(self.type), '>'))
class BindTransmitter(Command):
"""Bind as a transmitter command"""
params = {
'system_id': Param(type=str, max=16),
'password': Param(type=str, max=9),
'system_type': Param(type=str, max=13),
'interface_version': Param(type=int, size=1),
'addr_ton': Param(type=int, size=1),
'addr_npi': Param(type=int, size=1),
'address_range': Param(type=str, max=41),
}
# Order is important, but params dictionary is unordered
params_order = (
'system_id', 'password', 'system_type',
'interface_version', 'addr_ton', 'addr_npi', 'address_range',
)
def __init__(self, command, **kwargs):
super(BindTransmitter, self).__init__(command, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
self.interface_version = consts.SMPP_VERSION_34
class BindReceiver(BindTransmitter):
"""Bind as a receiver command"""
def __init__(self, command, **kwargs):
super(BindReceiver, self).__init__(command, **kwargs)
class BindTransceiver(BindTransmitter):
"""Bind as receiver and transmitter command"""
def __init__(self, command, **kwargs):
super(BindTransceiver, self).__init__(command, **kwargs)
class BindTransmitterResp(Command):
"""Response for bind as a transmitter command"""
params = {
'system_id': Param(type=str, max=16),
'sc_interface_version': Param(type=int, size=1),
}
params_order = ('system_id', 'sc_interface_version')
def __init__(self, command, **kwargs):
super(BindTransmitterResp, self).__init__(command, need_sequence=False,
**kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
class BindReceiverResp(BindTransmitterResp):
"""Response for bind as a reciever command"""
def __init__(self, command, **kwargs):
super(BindReceiverResp, self).__init__(command, **kwargs)
class BindTransceiverResp(BindTransmitterResp):
"""Response for bind as a transceiver command"""
def __init__(self, command, **kwargs):
super(BindTransceiverResp, self).__init__(command, **kwargs)
class DataSM(Command):
"""data_sm command is used to transfer data between SMSC and the ESME"""
params = {
'service_type': Param(type=str, max=6),
'source_addr_ton': Param(type=int, size=1),
'source_addr_npi': Param(type=int, size=1),
'source_addr': Param(type=str, max=21),
'dest_addr_ton': Param(type=int, size=1),
'dest_addr_npi': Param(type=int, size=1),
'destination_addr': Param(type=str, max=21),
'esm_class': Param(type=int, size=1),
'registered_delivery': Param(type=int, size=1),
'data_coding': Param(type=int, size=1),
# Optional params:
'source_port': Param(type=int, size=2),
'source_addr_subunit': Param(type=int, size=1),
'source_network_type': Param(type=int, size=1),
'source_bearer_type': Param(type=int, size=1),
'source_telematics_id': Param(type=int, size=2),
'destination_port': Param(type=int, size=2),
'dest_addr_subunit': Param(type=int, size=1),
'dest_network_type': Param(type=int, size=1),
'dest_bearer_type': Param(type=int, size=1),
'dest_telematics_id': Param(type=int, size=2),
'sar_msg_ref_num': Param(type=int, size=2),
'sar_total_segments': Param(type=int, size=1),
'sar_segment_seqnum': Param(type=int, size=1),
'more_messages_to_send': Param(type=int, size=1),
'qos_time_to_live': Param(type=int, size=4),
'payload_type': Param(type=int, size=1),
'message_payload': Param(type=ostr, max=260),
'receipted_message_id': Param(type=str, max=65),
'message_state': Param(type=int, size=1),
'network_error_code': Param(type=ostr, size=3),
'user_message_reference': Param(type=int, size=2),
'privacy_indicator': Param(type=int, size=1),
'callback_num': Param(type=ostr, min=4, max=19),
'callback_num_pres_ind': Param(type=int, size=1),
'callback_num_atag': Param(type=str, max=65),
'source_subaddress': Param(type=str, min=2, max=23),
'dest_subaddress': Param(type=str, min=2, max=23),
'user_response_code': Param(type=int, size=1),
'display_time': Param(type=int, size=1),
'sms_signal': Param(type=int, size=2),
'ms_validity': Param(type=int, size=1),
'ms_msg_wait_facilities': Param(type=int, size=1),
'number_of_messages': Param(type=int, size=1),
'alert_on_message_delivery': Param(type=flag),
'language_indicator': Param(type=int, size=1),
'its_reply_type': Param(type=int, size=1),
'its_session_info': Param(type=int, size=2),
}
params_order = (
'service_type', 'source_addr_ton', 'source_addr_npi',
'source_addr', 'dest_addr_ton', 'dest_addr_npi', 'destination_addr',
'esm_class', 'registered_delivery', 'data_coding',
# Optional params:
'source_port', 'source_addr_subunit', 'source_network_type',
'source_bearer_type', 'source_telematics_id', 'destination_port',
'dest_addr_subunit', 'dest_network_type', 'dest_bearer_type',
'dest_telematics_id', 'sar_msg_ref_num', 'sar_total_segments',
'sar_segment_seqnum', 'more_messages_to_send', 'qos_time_to_live',
'payload_type', 'message_payload', 'receipted_message_id',
'message_state', 'network_error_code', 'user_message_reference',
'privacy_indicator', 'callback_num', 'callback_num_pres_ind',
'callback_num_atag', 'source_subaddress', 'dest_subaddress',
'user_response_code', 'display_time', 'sms_signal',
'ms_validity', 'ms_msg_wait_facilities', 'number_of_messages',
'alert_on_message_delivery', 'language_indicator', 'its_reply_type',
'its_session_info',
)
def __init__(self, command, **kwargs):
super(DataSM, self).__init__(command, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
class DataSMResp(Command):
"""Reponse command for data_sm"""
params = {
'message_id': Param(type=str, max=65),
# Optional params:
#type size is implementation specific.
'delivery_failure_reason': Param(type=str, max=256),
'network_error_code': Param(type=str, max=3),
'additional_status_info_text': Param(type=str, max=256),
'dpf_result': Param(type=int, size=1),
}
params_order = (
'message_id',
# Optional params:
'delivery_failure_reason', 'network_error_code', 'additional_status_info_text',
'dpf_result',
)
def __init__(self, command, **kwargs):
super(DataSMResp, self).__init__(command, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
class GenericNAck(Command):
"""General Negative Acknowledgement class"""
params = {}
params_order = ()
_defs = []
def __init__(self, command, **kwargs):
super(GenericNAck, self).__init__(command, need_sequence=False, **kwargs)
class SubmitSM(Command):
"""submit_sm command class
This command is used by an ESME to submit short message to the SMSC.
submit_sm PDU does not support the transaction mode."""
#
# Service type
# The following generic service types are defined:
# '' -- default
# 'CMT' -- Cellural Messaging
# 'CPT' -- Cellural Paging
# 'VMN' -- Voice Mail Notification
# 'VMA' -- Voice Mail Alerting
# 'WAP' -- Wireless Application Protocol
# 'USSD' -- Unstructured Supplementary Services Data
service_type = None
# Type of Number for source address
source_addr_ton = None
# Numbering Plan Indicator for source address
source_addr_npi = None
# Address of SME which originated this message
source_addr = None
# TON for destination
dest_addr_ton = None
# NPI for destination
dest_addr_npi = None
# Destination address for this message
destination_addr = None
# Message mode and message type
esm_class = None # SMPP_MSGMODE_DEFAULT
# Protocol Identifier
protocol_id = None
# Priority level of this message
priority_flag = None
# Message is to be scheduled by the SMSC for delivery
schedule_delivery_time = None
# Validity period of this message
validity_period = None
# Indicator to signify if an SMSC delivery receipt or and SME
# acknowledgement is required.
registered_delivery = None
# This flag indicates if submitted message should replace an existing
# message
replace_if_present_flag = None
# Encoding scheme of the short messaege data
data_coding = None # SMPP_ENCODING_DEFAULT#ISO10646
# Indicates the short message to send from a list of predefined
# ('canned') short messages stored on the SMSC
sm_default_msg_id = None
# Message length in octets
sm_length = 0
# Up to 254 octets of short message user data
short_message = None
# Optional are taken from params list and are set dynamically when
# __init__ is called.
params = {
'service_type': Param(type=str, max=6),
'source_addr_ton': Param(type=int, size=1),
'source_addr_npi': Param(type=int, size=1),
'source_addr': Param(type=str, max=21),
'dest_addr_ton': Param(type=int, size=1),
'dest_addr_npi': Param(type=int, size=1),
'destination_addr': Param(type=str, max=21),
'esm_class': Param(type=int, size=1),
'protocol_id': Param(type=int, size=1),
'priority_flag': Param(type=int, size=1),
'schedule_delivery_time': Param(type=str, max=17),
'validity_period': Param(type=str, max=17),
'registered_delivery': Param(type=int, size=1),
'replace_if_present_flag': Param(type=int, size=1),
'data_coding': Param(type=int, size=1),
'sm_default_msg_id': Param(type=int, size=1),
'sm_length': Param(type=int, size=1),
'short_message': Param(type=ostr, max=254, len_field='sm_length'),
# Optional params
'user_message_reference': Param(type=int, size=2),
'source_port': Param(type=int, size=2),
'source_addr_subunit': Param(type=int, size=2),
'destination_port': Param(type=int, size=2),
'dest_addr_subunit': Param(type=int, size=1),
'sar_msg_ref_num': Param(type=int, size=2),
'sar_total_segments': Param(type=int, size=1),
'sar_segment_seqnum': Param(type=int, size=1),
'more_messages_to_send': Param(type=int, size=1),
'payload_type': Param(type=int, size=1),
'message_payload': Param(type=ostr, max=260),
'privacy_indicator': Param(type=int, size=1),
'callback_num': Param(type=ostr, min=4, max=19),
'callback_num_pres_ind': Param(type=int, size=1),
'source_subaddress': Param(type=str, min=2, max=23),
'dest_subaddress': Param(type=str, min=2, max=23),
'user_response_code': Param(type=int, size=1),
'display_time': Param(type=int, size=1),
'sms_signal': Param(type=int, size=2),
'ms_validity': Param(type=int, size=1),
'ms_msg_wait_facilities': Param(type=int, size=1),
'number_of_messages': Param(type=int, size=1),
'alert_on_message_delivery': Param(type=flag),
'language_indicator': Param(type=int, size=1),
'its_reply_type': Param(type=int, size=1),
'its_session_info': Param(type=int, size=2),
'ussd_service_op': Param(type=int, size=1),
}
params_order = (
'service_type', 'source_addr_ton', 'source_addr_npi',
'source_addr', 'dest_addr_ton', 'dest_addr_npi',
'destination_addr', 'esm_class', 'protocol_id', 'priority_flag',
'schedule_delivery_time', 'validity_period', 'registered_delivery',
'replace_if_present_flag', 'data_coding', 'sm_default_msg_id',
'sm_length', 'short_message',
# Optional params
'user_message_reference', 'source_port', 'source_addr_subunit',
'destination_port', 'dest_addr_subunit', 'sar_msg_ref_num',
'sar_total_segments', 'sar_segment_seqnum', 'more_messages_to_send',
'payload_type', 'message_payload', 'privacy_indicator',
'callback_num', 'callback_num_pres_ind', 'source_subaddress',
'dest_subaddress', 'user_response_code', 'display_time',
'sms_signal', 'ms_validity', 'ms_msg_wait_facilities',
'number_of_messages', 'alert_on_message_delivery',
'language_indicator', 'its_reply_type', 'its_session_info',
'ussd_service_op',
)
def __init__(self, command, **kwargs):
super(SubmitSM, self).__init__(command, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
def prep(self):
"""Prepare to generate binary data"""
if self.short_message:
if getattr(self, 'message_payload', None):
raise ValueError('`message_payload` can not be used with `short_message`')
self.sm_length = len(self.short_message)
else:
self.sm_length = 0
class SubmitSMResp(Command):
"""Response command for submit_sm"""
params = {
'message_id': Param(type=str, max=65),
}
params_order = ('message_id',)
def __init__(self, command, **kwargs):
super(SubmitSMResp, self).__init__(command, need_sequence=False, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
class DeliverSM(SubmitSM):
"""deliver_sm command class, similar to submit_sm
but has different optional params"""
params = {
'service_type': Param(type=str, max=6),
'source_addr_ton': Param(type=int, size=1),
'source_addr_npi': Param(type=int, size=1),
'source_addr': Param(type=str, max=21),
'dest_addr_ton': Param(type=int, size=1),
'dest_addr_npi': Param(type=int, size=1),
'destination_addr': Param(type=str, max=21),
'esm_class': Param(type=int, size=1),
'protocol_id': Param(type=int, size=1),
'priority_flag': Param(type=int, size=1),
'schedule_delivery_time': Param(type=str, max=17),
'validity_period': Param(type=str, max=17),
'registered_delivery': Param(type=int, size=1),
'replace_if_present_flag': Param(type=int, size=1),
'data_coding': Param(type=int, size=1),
'sm_default_msg_id': Param(type=int, size=1),
'sm_length': Param(type=int, size=1),
'short_message': Param(type=ostr, max=254, len_field='sm_length'),
# Optional params
'user_message_reference': Param(type=int, size=2),
'source_port': Param(type=int, size=2),
'destination_port': Param(type=int, size=2),
'sar_msg_ref_num': Param(type=int, size=2),
'sar_total_segments': Param(type=int, size=1),
'sar_segment_seqnum': Param(type=int, size=1),
'user_response_code': Param(type=int, size=1),
'privacy_indicator': Param(type=int, size=1),
'payload_type': Param(type=int, size=1),
'message_payload': Param(type=ostr, max=260),
'callback_num': Param(type=ostr, min=4, max=19),
'source_subaddress': Param(type=str, min=2, max=23),
'dest_subaddress': Param(type=str, min=2, max=23),
'language_indicator': Param(type=int, size=1),
'its_session_info': Param(type=int, size=2),
'network_error_code': Param(type=ostr, size=3),
'message_state': Param(type=int, size=1),
'receipted_message_id': Param(type=str, max=65),
'source_network_type': Param(type=int, size=1),
'dest_network_type': Param(type=int, size=1),
'more_messages_to_send': Param(type=int, size=1),
}
params_order = (
'service_type', 'source_addr_ton', 'source_addr_npi',
'source_addr', 'dest_addr_ton', 'dest_addr_npi',
'destination_addr', 'esm_class', 'protocol_id', 'priority_flag',
'schedule_delivery_time', 'validity_period', 'registered_delivery',
'replace_if_present_flag', 'data_coding', 'sm_default_msg_id',
'sm_length', 'short_message',
# Optional params
'user_message_reference', 'source_port', 'destination_port',
'sar_msg_ref_num', 'sar_total_segments', 'sar_segment_seqnum',
'user_response_code', 'privacy_indicator',
'payload_type', 'message_payload',
'callback_num', 'source_subaddress',
'dest_subaddress', 'language_indicator', 'its_session_info',
'network_error_code', 'message_state', 'receipted_message_id',
'source_network_type', 'dest_network_type', 'more_messages_to_send',
)
def __init__(self, command, **kwargs):
super(DeliverSM, self).__init__(command, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
class DeliverSMResp(SubmitSMResp):
"""deliver_sm_response response class, same as submit_sm"""
message_id = None
def __init__(self, command, **kwargs):
super(DeliverSMResp, self).__init__(command, **kwargs)
class QuerySM(Command):
"""query_sm command class
This command is used by an ESME to query the state of a short message to the SMSC.
source_addr* values must match those supplied when the message was submitted."""
# Message ID of the message whose state is to be queried.
message_id = None
# Type of Number for source address
source_addr_ton = None
# Numbering Plan Indicator for source address
source_addr_npi = None
# Address of SME which originated this message
source_addr = None
# Optional are taken from params list and are set dynamically when
# __init__ is called.
params = {
'message_id': Param(type=str, max=65),
'source_addr_ton': Param(type=int, size=1),
'source_addr_npi': Param(type=int, size=1),
'source_addr': Param(type=str, max=21),
}
params_order = (
'message_id', 'source_addr_ton', 'source_addr_npi',
'source_addr',
)
def __init__(self, command, **kwargs):
super(QuerySM, self).__init__(command, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
def prep(self):
"""Prepare to generate binary data"""
if not self.message_id:
raise ValueError('`message_id` is mandatory')
class QuerySMResp(Command):
"""Response command for query_sm"""
mandatory_fields = ('message_state')
params = {
'message_id': Param(type=str, max=65),
'final_date': Param(type=str, max=17),
'message_state': Param(type=int, size=1),
'error_code': Param(type=int, size=1),
}
params_order = (
'message_id', 'final_date', 'message_state',
'error_code',
)
def __init__(self, command, **kwargs):
super(QuerySMResp, self).__init__(command, need_sequence=False, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
class Unbind(Command):
"""Unbind command"""
params = {}
params_order = ()
def __init__(self, command, **kwargs):
super(Unbind, self).__init__(command, **kwargs)
class UnbindResp(Command):
"""Unbind response command"""
params = {}
params_order = ()
def __init__(self, command, **kwargs):
super(UnbindResp, self).__init__(command, need_sequence=False, **kwargs)
class EnquireLink(Command):
"""Enquire link command"""
params = {}
params_order = ()
def __init__(self, command, **kwargs):
super(EnquireLink, self).__init__(command, **kwargs)
class EnquireLinkResp(Command):
"""Enquire link command response"""
params = {}
params_order = ()
def __init__(self, command, **kwargs):
super(EnquireLinkResp, self).__init__(command, need_sequence=False, **kwargs)
class AlertNotification(Command):
"""`alert_notification` command class"""
# Type of Number for source address
source_addr_ton = None
# Numbering Plan Indicator for source address
source_addr_npi = None
# Address of SME which originated this message
source_addr = None
# TON for destination
esme_addr_ton = None
# NPI for destination
esme_addr_npi = None
# Destination address for this message
esme_addr = None
# Optional are taken from params list and are set dynamically when
# __init__ is called.
params = {
'source_addr_ton': Param(type=int, size=1),
'source_addr_npi': Param(type=int, size=1),
'source_addr': Param(type=str, max=21),
'esme_addr_ton': Param(type=int, size=1),
'esme_addr_npi': Param(type=int, size=1),
'esme_addr': Param(type=str, max=21),
# Optional params
'ms_availability_status' : Param(type=int, size=1),
}
params_order = (
'source_addr_ton', 'source_addr_npi',
'source_addr', 'esme_addr_ton', 'esme_addr_npi',
'esme_addr',
# Optional params
'ms_availability_status',
)
def __init__(self, command, **kwargs):
super(AlertNotification, self).__init__(command, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))