ruby-smpp 0.1.2 → 0.1.3.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +23 -0
- data/{NEWS.txt → CHANGELOG} +7 -2
- data/CONTRIBUTORS.txt +3 -1
- data/{License.txt → LICENSE} +0 -0
- data/{README.txt → README.rdoc} +33 -41
- data/Rakefile +58 -9
- data/VERSION +1 -0
- data/examples/sample_gateway.rb +55 -78
- data/examples/sample_smsc.rb +2 -3
- data/lib/smpp/base.rb +33 -0
- data/lib/smpp/pdu/base.rb +23 -5
- data/lib/smpp/pdu/deliver_sm.rb +39 -7
- data/lib/smpp/server.rb +5 -1
- data/lib/smpp/transceiver.rb +15 -8
- data/ruby-smpp.gemspec +66 -18
- data/test/smpp_test.rb +147 -30
- metadata +26 -37
- data/History.txt +0 -14
- data/Manifest.txt +0 -45
- data/config/hoe.rb +0 -70
- data/config/requirements.rb +0 -15
- data/lib/smpp/version.rb +0 -9
- data/script/console +0 -10
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/script/txt2html +0 -74
- data/setup.rb +0 -1585
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/test/test_helper.rb +0 -2
data/examples/sample_smsc.rb
CHANGED
@@ -3,9 +3,8 @@
|
|
3
3
|
# Sample SMPP SMS Gateway.
|
4
4
|
|
5
5
|
require 'rubygems'
|
6
|
-
|
7
|
-
require 'smpp'
|
8
|
-
require 'smpp/server'
|
6
|
+
require File.dirname(__FILE__) + '/../lib/smpp'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/smpp/server'
|
9
8
|
|
10
9
|
# set up logger
|
11
10
|
Smpp::Base.logger = Logger.new('smsc.log')
|
data/lib/smpp/base.rb
CHANGED
@@ -142,6 +142,7 @@ module Smpp
|
|
142
142
|
private
|
143
143
|
def write_pdu(pdu)
|
144
144
|
logger.debug "<- #{pdu.to_human}"
|
145
|
+
hex_debug pdu.data, "<- "
|
145
146
|
send_data pdu.data
|
146
147
|
end
|
147
148
|
|
@@ -155,11 +156,43 @@ module Smpp
|
|
155
156
|
else
|
156
157
|
logger.debug "-> " + pdu.to_human
|
157
158
|
end
|
159
|
+
hex_debug data, "-> "
|
158
160
|
rescue Exception => ex
|
159
161
|
logger.error "Exception while reading PDUs: #{ex} in #{ex.backtrace[0]}"
|
160
162
|
raise
|
161
163
|
end
|
162
164
|
pdu
|
165
|
+
end
|
166
|
+
|
167
|
+
def hex_debug(data, prefix = "")
|
168
|
+
return unless @config[:hex_debug]
|
169
|
+
logger.debug do
|
170
|
+
message = "Hex dump follows:\n"
|
171
|
+
hexdump(data).each_line do |line|
|
172
|
+
message << (prefix + line.chomp + "\n")
|
173
|
+
end
|
174
|
+
message
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def hexdump(target)
|
179
|
+
width=16
|
180
|
+
group=2
|
181
|
+
|
182
|
+
output = ""
|
183
|
+
n=0
|
184
|
+
ascii=''
|
185
|
+
target.each_byte { |b|
|
186
|
+
if n%width == 0
|
187
|
+
output << "%s\n%08x: "%[ascii,n]
|
188
|
+
ascii='| '
|
189
|
+
end
|
190
|
+
output << "%02x"%b
|
191
|
+
output << ' ' if (n+=1)%group==0
|
192
|
+
ascii << "%s"%b.chr.tr('^ -~','.')
|
193
|
+
}
|
194
|
+
output << ' '*(((2+width-ascii.size)*(2*group+1))/group.to_f).ceil+ascii
|
195
|
+
output[1..-1]
|
163
196
|
end
|
164
197
|
end
|
165
198
|
end
|
data/lib/smpp/pdu/base.rb
CHANGED
@@ -61,8 +61,12 @@ module Smpp::Pdu
|
|
61
61
|
CANCEL_SM_RESP = 0X80000008
|
62
62
|
ENQUIRE_LINK = 0X00000015
|
63
63
|
ENQUIRE_LINK_RESP = 0X80000015
|
64
|
-
SUBMIT_MULTI
|
64
|
+
SUBMIT_MULTI = 0X00000021
|
65
65
|
SUBMIT_MULTI_RESP = 0X80000021
|
66
|
+
|
67
|
+
OPTIONAL_RECEIPTED_MESSAGE_ID = 0x001E
|
68
|
+
OPTIONAL_MESSAGE_STATE = 0x0427
|
69
|
+
|
66
70
|
# PDU sequence number.
|
67
71
|
@@seq = [Time.now.to_i]
|
68
72
|
|
@@ -95,7 +99,8 @@ module Smpp::Pdu
|
|
95
99
|
|
96
100
|
# return int as binary string of 4 octets
|
97
101
|
def fixed_int(value)
|
98
|
-
|
102
|
+
arr = [value >> 24, value >> 16, value >> 8, value & 0xff]
|
103
|
+
arr.pack("cccc")
|
99
104
|
end
|
100
105
|
|
101
106
|
def next_sequence_number
|
@@ -103,7 +108,7 @@ module Smpp::Pdu
|
|
103
108
|
end
|
104
109
|
|
105
110
|
def Base.next_sequence_number
|
106
|
-
@@seq.synchronize do
|
111
|
+
@@seq.synchronize do
|
107
112
|
(@@seq[0] += 1) % 512
|
108
113
|
end
|
109
114
|
end
|
@@ -122,13 +127,13 @@ module Smpp::Pdu
|
|
122
127
|
end
|
123
128
|
len, cmd, status, seq = header.unpack('N4')
|
124
129
|
body = data[16..-1]
|
125
|
-
|
130
|
+
|
126
131
|
#if a class has been registered to handle this command_id, try
|
127
132
|
#to create an instance from the wire data
|
128
133
|
if @@cmd_map[cmd]
|
129
134
|
@@cmd_map[cmd].from_wire_data(seq, status, body)
|
130
135
|
else
|
131
|
-
Smpp::Base.logger.error "Unknown PDU:
|
136
|
+
Smpp::Base.logger.error "Unknown PDU: #{"0x%08x" % cmd}"
|
132
137
|
return nil
|
133
138
|
end
|
134
139
|
end
|
@@ -138,5 +143,18 @@ module Smpp::Pdu
|
|
138
143
|
@@cmd_map[command_id] = self
|
139
144
|
end
|
140
145
|
|
146
|
+
def Base.optional_parameters(remaining_bytes)
|
147
|
+
optionals = {}
|
148
|
+
while not remaining_bytes.empty?
|
149
|
+
optional = {}
|
150
|
+
tag, optional[:length], remaining_bytes = remaining_bytes.unpack('H4na*')
|
151
|
+
optional[:tag] = tag.hex
|
152
|
+
optional[:value] = remaining_bytes.slice!(0...optional[:length])
|
153
|
+
optionals[tag.hex] = optional
|
154
|
+
end
|
155
|
+
|
156
|
+
return optionals
|
157
|
+
end
|
158
|
+
|
141
159
|
end
|
142
160
|
end
|
data/lib/smpp/pdu/deliver_sm.rb
CHANGED
@@ -4,7 +4,8 @@ class Smpp::Pdu::DeliverSm < Smpp::Pdu::Base
|
|
4
4
|
attr_reader :service_type, :source_addr_ton, :source_addr_npi, :source_addr, :dest_addr_ton, :dest_addr_npi,
|
5
5
|
:destination_addr, :esm_class, :protocol_id, :priority_flag, :schedule_delivery_time,
|
6
6
|
:validity_period, :registered_delivery, :replace_if_present_flag, :data_coding,
|
7
|
-
:sm_default_msg_id, :sm_length, :stat, :msg_reference, :udh, :short_message
|
7
|
+
:sm_default_msg_id, :sm_length, :stat, :msg_reference, :udh, :short_message,
|
8
|
+
:message_state, :receipted_message_id, :optional_parameters
|
8
9
|
|
9
10
|
def initialize(source_addr, destination_addr, short_message, options={}, seq=nil)
|
10
11
|
|
@@ -32,6 +33,9 @@ class Smpp::Pdu::DeliverSm < Smpp::Pdu::Base
|
|
32
33
|
#fields set for delivery report
|
33
34
|
@stat = options[:stat]
|
34
35
|
@msg_reference = options[:msg_reference]
|
36
|
+
@receipted_message_id = options[:receipted_message_id]
|
37
|
+
@message_state = options[:message_state]
|
38
|
+
@optional_parameters = options[:optional_parameters]
|
35
39
|
|
36
40
|
pdu_body = sprintf("%s\0%c%c%s\0%c%c%s\0%c%c%c%s\0%s\0%c%c%c%c%c%s", @service_type, @source_addr_ton, @source_addr_npi, @source_addr,
|
37
41
|
@dest_addr_ton, @dest_addr_npi, @destination_addr, @esm_class, @protocol_id, @priority_flag, @schedule_delivery_time, @validity_period,
|
@@ -62,8 +66,26 @@ class Smpp::Pdu::DeliverSm < Smpp::Pdu::Base
|
|
62
66
|
options[:data_coding],
|
63
67
|
options[:sm_default_msg_id],
|
64
68
|
options[:sm_length],
|
65
|
-
|
66
|
-
|
69
|
+
remaining_bytes = body.unpack('Z*CCZ*CCZ*CCCZ*Z*CCCCCa*')
|
70
|
+
|
71
|
+
short_message = remaining_bytes.slice!(0...options[:sm_length])
|
72
|
+
|
73
|
+
#everything left in remaining_bytes is 3.4 optional parameters
|
74
|
+
options[:optional_parameters] = optional_parameters(remaining_bytes)
|
75
|
+
|
76
|
+
#parse the 'standard' optional parameters for delivery receipts
|
77
|
+
options[:optional_parameters].each do |tag, tlv|
|
78
|
+
if OPTIONAL_MESSAGE_STATE == tag
|
79
|
+
value = tlv[:value].unpack('C')
|
80
|
+
options[:message_state] = value[0] if value
|
81
|
+
|
82
|
+
elsif OPTIONAL_RECEIPTED_MESSAGE_ID == tag
|
83
|
+
value = tlv[:value].unpack('A*')
|
84
|
+
options[:receipted_message_id] = value[0] if value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
67
89
|
|
68
90
|
#Note: if the SM is a delivery receipt (esm_class=4) then the short_message _may_ be in this format:
|
69
91
|
# "id:Smsc2013 sub:1 dlvrd:1 submit date:0610171515 done date:0610171515 stat:0 err:0 text:blah"
|
@@ -73,10 +95,20 @@ class Smpp::Pdu::DeliverSm < Smpp::Pdu::Base
|
|
73
95
|
# For example, Tele2 (Norway):
|
74
96
|
# "<msisdn><shortcode>?id:10ea34755d3d4f7a20900cdb3349e549 sub:001 dlvrd:001 submit date:0611011228 done date:0611011230 stat:DELIVRD err:000 Text:abc'!10ea34755d3d4f7a20900cdb3349e549"
|
75
97
|
if options[:esm_class] == 4
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
98
|
+
msg_ref_match = short_message.match(/id:([^ ]*)/)
|
99
|
+
if msg_ref_match
|
100
|
+
options[:msg_reference] = msg_ref_match[1]
|
101
|
+
end
|
102
|
+
|
103
|
+
stat_match = short_message.match(/stat:([^ ]*)/)
|
104
|
+
if stat_match
|
105
|
+
options[:stat] = stat_match[1]
|
106
|
+
end
|
107
|
+
|
108
|
+
Smpp::Base.logger.debug "DeliverSM with source_addr=#{source_addr}, destination_addr=#{destination_addr}, msg_reference=#{options[:msg_reference]}, stat=#{options[:stat]}"
|
109
|
+
else
|
110
|
+
Smpp::Base.logger.debug "DeliverSM with source_addr=#{source_addr}, destination_addr=#{destination_addr}"
|
111
|
+
end
|
80
112
|
|
81
113
|
new(source_addr, destination_addr, short_message, options, seq)
|
82
114
|
end
|
data/lib/smpp/server.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# --------
|
2
|
+
# This is experimental stuff submitted by taryn@taryneast.org
|
3
|
+
# --------
|
4
|
+
|
5
|
+
# the opposite of a client-based receiver, the server transmitter will send
|
2
6
|
# out MOs to the client when set up
|
3
7
|
class Smpp::Server < Smpp::Base
|
4
8
|
|
data/lib/smpp/transceiver.rb
CHANGED
@@ -5,9 +5,10 @@
|
|
5
5
|
# The transceiver accepts a delegate object that may implement
|
6
6
|
# the following (all optional) methods:
|
7
7
|
#
|
8
|
-
# mo_received(transceiver,
|
9
|
-
# delivery_report_received(transceiver,
|
10
|
-
# message_accepted(transceiver, mt_message_id,
|
8
|
+
# mo_received(transceiver, pdu)
|
9
|
+
# delivery_report_received(transceiver, pdu)
|
10
|
+
# message_accepted(transceiver, mt_message_id, pdu)
|
11
|
+
# message_rejected(transceiver, mt_message_id, pdu)
|
11
12
|
# bound(transceiver)
|
12
13
|
# unbound(transceiver)
|
13
14
|
|
@@ -31,7 +32,7 @@ class Smpp::Transceiver < Smpp::Base
|
|
31
32
|
end
|
32
33
|
|
33
34
|
# Send an MT SMS message. Delegate will receive message_accepted callback when SMSC
|
34
|
-
# acknowledges
|
35
|
+
# acknowledges, or the message_rejected callback upon error
|
35
36
|
def send_mt(message_id, source_addr, destination_addr, short_message, options={})
|
36
37
|
logger.debug "Sending MT: #{short_message}"
|
37
38
|
if @state == :bound
|
@@ -106,12 +107,12 @@ class Smpp::Transceiver < Smpp::Base
|
|
106
107
|
if pdu.esm_class != 4
|
107
108
|
# MO message
|
108
109
|
if @delegate.respond_to?(:mo_received)
|
109
|
-
@delegate.mo_received(self, pdu
|
110
|
+
@delegate.mo_received(self, pdu)
|
110
111
|
end
|
111
112
|
else
|
112
113
|
# Delivery report
|
113
114
|
if @delegate.respond_to?(:delivery_report_received)
|
114
|
-
@delegate.delivery_report_received(self, pdu
|
115
|
+
@delegate.delivery_report_received(self, pdu)
|
115
116
|
end
|
116
117
|
end
|
117
118
|
when Pdu::BindTransceiverResponse
|
@@ -141,10 +142,13 @@ class Smpp::Transceiver < Smpp::Base
|
|
141
142
|
end
|
142
143
|
if pdu.command_status != Pdu::Base::ESME_ROK
|
143
144
|
logger.error "Error status in SubmitSmResponse: #{pdu.command_status}"
|
145
|
+
if @delegate.respond_to?(:message_rejected)
|
146
|
+
@delegate.message_rejected(self, mt_message_id, pdu)
|
147
|
+
end
|
144
148
|
else
|
145
149
|
logger.info "Got OK SubmitSmResponse (#{pdu.message_id} -> #{mt_message_id})"
|
146
150
|
if @delegate.respond_to?(:message_accepted)
|
147
|
-
@delegate.message_accepted(self, mt_message_id, pdu
|
151
|
+
@delegate.message_accepted(self, mt_message_id, pdu)
|
148
152
|
end
|
149
153
|
end
|
150
154
|
# Now we got the SMSC message id; create pending delivery report.
|
@@ -156,10 +160,13 @@ class Smpp::Transceiver < Smpp::Base
|
|
156
160
|
end
|
157
161
|
if pdu.command_status != Pdu::Base::ESME_ROK
|
158
162
|
logger.error "Error status in SubmitMultiResponse: #{pdu.command_status}"
|
163
|
+
if @delegate.respond_to?(:message_rejected)
|
164
|
+
@delegate.message_rejected(self, mt_message_id, pdu)
|
165
|
+
end
|
159
166
|
else
|
160
167
|
logger.info "Got OK SubmitMultiResponse (#{pdu.message_id} -> #{mt_message_id})"
|
161
168
|
if @delegate.respond_to?(:message_accepted)
|
162
|
-
@delegate.message_accepted(self, mt_message_id, pdu
|
169
|
+
@delegate.message_accepted(self, mt_message_id, pdu)
|
163
170
|
end
|
164
171
|
end
|
165
172
|
else
|
data/ruby-smpp.gemspec
CHANGED
@@ -1,36 +1,84 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
1
6
|
Gem::Specification.new do |s|
|
2
7
|
s.name = %q{ruby-smpp}
|
3
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.3.pre1"
|
4
9
|
|
5
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
6
|
-
s.authors = ["August Z. Flatby"]
|
7
|
-
s.date = %q{
|
8
|
-
s.description = %q{Ruby
|
9
|
-
s.email =
|
10
|
-
s.extra_rdoc_files = [
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Ray Krueger", "August Z. Flatby"]
|
12
|
+
s.date = %q{2010-02-05}
|
13
|
+
s.description = %q{Ruby implementation of the SMPP protocol, based on EventMachine. SMPP is a protocol that allows ordinary people outside the mobile network to exchange SMS messages directly with mobile operators.}
|
14
|
+
s.email = %q{raykrueger@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"CHANGELOG",
|
17
|
+
"CONTRIBUTORS.txt",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".gitignore",
|
22
|
+
"CHANGELOG",
|
23
|
+
"CONTRIBUTORS.txt",
|
24
|
+
"LICENSE",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"examples/PDU1.example",
|
29
|
+
"examples/PDU2.example",
|
30
|
+
"examples/sample_gateway.rb",
|
31
|
+
"examples/sample_smsc.rb",
|
32
|
+
"lib/smpp.rb",
|
33
|
+
"lib/smpp/base.rb",
|
34
|
+
"lib/smpp/pdu/base.rb",
|
35
|
+
"lib/smpp/pdu/bind_base.rb",
|
36
|
+
"lib/smpp/pdu/bind_resp_base.rb",
|
37
|
+
"lib/smpp/pdu/bind_transceiver.rb",
|
38
|
+
"lib/smpp/pdu/bind_transceiver_response.rb",
|
39
|
+
"lib/smpp/pdu/deliver_sm.rb",
|
40
|
+
"lib/smpp/pdu/deliver_sm_response.rb",
|
41
|
+
"lib/smpp/pdu/enquire_link.rb",
|
42
|
+
"lib/smpp/pdu/enquire_link_response.rb",
|
43
|
+
"lib/smpp/pdu/generic_nack.rb",
|
44
|
+
"lib/smpp/pdu/submit_multi.rb",
|
45
|
+
"lib/smpp/pdu/submit_multi_response.rb",
|
46
|
+
"lib/smpp/pdu/submit_sm.rb",
|
47
|
+
"lib/smpp/pdu/submit_sm_response.rb",
|
48
|
+
"lib/smpp/pdu/unbind.rb",
|
49
|
+
"lib/smpp/pdu/unbind_response.rb",
|
50
|
+
"lib/smpp/server.rb",
|
51
|
+
"lib/smpp/transceiver.rb",
|
52
|
+
"lib/sms.rb",
|
53
|
+
"ruby-smpp.gemspec",
|
54
|
+
"test/smpp_test.rb"
|
55
|
+
]
|
56
|
+
s.homepage = %q{http://github.com/raykrueger/ruby-smpp}
|
57
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
15
58
|
s.require_paths = ["lib"]
|
16
59
|
s.rubyforge_project = %q{ruby-smpp}
|
17
|
-
s.rubygems_version = %q{1.3.
|
18
|
-
s.summary = %q{Ruby
|
19
|
-
s.test_files = [
|
60
|
+
s.rubygems_version = %q{1.3.5}
|
61
|
+
s.summary = %q{Ruby implementation of the SMPP protocol, based on EventMachine.}
|
62
|
+
s.test_files = [
|
63
|
+
"test/smpp_test.rb",
|
64
|
+
"examples/sample_gateway.rb",
|
65
|
+
"examples/sample_smsc.rb"
|
66
|
+
]
|
20
67
|
|
21
68
|
if s.respond_to? :specification_version then
|
22
69
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
-
s.specification_version =
|
70
|
+
s.specification_version = 3
|
24
71
|
|
25
72
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
73
|
s.add_runtime_dependency(%q<eventmachine>, [">= 0.10.0"])
|
27
|
-
s.add_development_dependency(%q<
|
74
|
+
s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
28
75
|
else
|
29
76
|
s.add_dependency(%q<eventmachine>, [">= 0.10.0"])
|
30
|
-
s.add_dependency(%q<
|
77
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
31
78
|
end
|
32
79
|
else
|
33
80
|
s.add_dependency(%q<eventmachine>, [">= 0.10.0"])
|
34
|
-
s.add_dependency(%q<
|
81
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
35
82
|
end
|
36
83
|
end
|
84
|
+
|
data/test/smpp_test.rb
CHANGED
@@ -1,75 +1,179 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__) + '/../lib/'
|
2
|
-
|
3
1
|
require 'rubygems'
|
4
2
|
require 'test/unit'
|
5
|
-
require 'stringio'
|
6
3
|
require 'smpp'
|
7
4
|
|
8
5
|
# a server which immediately requests the client to unbind
|
9
|
-
module
|
10
|
-
def
|
11
|
-
|
6
|
+
module Server
|
7
|
+
def self.config
|
8
|
+
{
|
9
|
+
:host => 'localhost',
|
10
|
+
:port => 2775,
|
11
|
+
:system_id => 'foo',
|
12
|
+
:password => 'bar',
|
13
|
+
:system_type => '',
|
14
|
+
:source_ton => 0,
|
15
|
+
:source_npi => 1,
|
16
|
+
:destination_ton => 1,
|
17
|
+
:destination_npi => 1,
|
18
|
+
:source_address_range => '',
|
19
|
+
:destination_address_range => ''
|
20
|
+
}
|
12
21
|
end
|
13
|
-
end
|
14
22
|
|
15
|
-
module
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
send_data Smpp::Pdu::SubmitSmResponse.new(1, 2, "100").data
|
23
|
+
module Unbind
|
24
|
+
def receive_data(data)
|
25
|
+
send_data Smpp::Pdu::Unbind.new.data
|
26
|
+
end
|
20
27
|
end
|
28
|
+
|
29
|
+
module SubmitSmResponse
|
30
|
+
def receive_data(data)
|
31
|
+
# problem: our Pdu's should have factory methods for "both ways"; ie. when created
|
32
|
+
# by client, and when created from wire data.
|
33
|
+
send_data Smpp::Pdu::SubmitSmResponse.new(1, 2, "100").data
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module SubmitSmResponseWithErrorStatus
|
38
|
+
attr_reader :state #state=nil => bind => state=bound => send =>state=sent => unbind => state=unbound
|
39
|
+
def receive_data(data)
|
40
|
+
if @state.nil?
|
41
|
+
@state = 'bound'
|
42
|
+
pdu = Smpp::Pdu::Base.create(data)
|
43
|
+
response_pdu = Smpp::Pdu::BindTransceiverResponse.new(pdu.sequence_number,Smpp::Pdu::Base::ESME_ROK,Server::config[:system_id])
|
44
|
+
send_data response_pdu.data
|
45
|
+
elsif @state == 'bound'
|
46
|
+
@state = 'sent'
|
47
|
+
pdu = Smpp::Pdu::Base.create(data)
|
48
|
+
pdu.to_human
|
49
|
+
send_data Smpp::Pdu::SubmitSmResponse.new(pdu.sequence_number, Smpp::Pdu::Base::ESME_RINVDSTADR, pdu.body).data
|
50
|
+
#send_data Smpp::Pdu::SubmitSmResponse.new(1, 2, "100").data
|
51
|
+
elsif @state == 'sent'
|
52
|
+
@state = 'unbound'
|
53
|
+
send_data Smpp::Pdu::Unbind.new.data
|
54
|
+
else
|
55
|
+
raise "unexpected state"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
21
60
|
end
|
22
61
|
|
62
|
+
|
23
63
|
# the delagate receives callbacks when interesting things happen on the connection
|
24
64
|
class Delegate
|
25
|
-
|
65
|
+
|
66
|
+
def mo_received(transceiver, pdu)
|
67
|
+
puts "** mo_received"
|
68
|
+
end
|
69
|
+
|
70
|
+
def delivery_report_received(transceiver, pdu)
|
71
|
+
puts "** delivery_report_received"
|
72
|
+
end
|
73
|
+
|
74
|
+
def message_accepted(transceiver, mt_message_id, pdu)
|
75
|
+
puts "** message_sent"
|
76
|
+
end
|
77
|
+
|
78
|
+
def message_rejected(transceiver, mt_message_id, pdu)
|
79
|
+
puts "** message_rejected"
|
80
|
+
end
|
81
|
+
|
82
|
+
def bound(transceiver)
|
83
|
+
puts "** bound"
|
84
|
+
end
|
85
|
+
|
86
|
+
def unbound(transceiver)
|
87
|
+
puts "** unbound"
|
88
|
+
EventMachine::stop_event_loop
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#TODO This should be made prettier with mocha
|
93
|
+
class ResponsiveDelegate
|
94
|
+
attr_reader :seq, :event_counter
|
95
|
+
|
96
|
+
def initialize
|
97
|
+
@seq = 0
|
98
|
+
@event_counter = nil
|
99
|
+
end
|
100
|
+
def seq
|
101
|
+
@seq += 1
|
102
|
+
end
|
103
|
+
def count_function
|
104
|
+
func = caller(1)[0].split("`")[1].split("'")[0].to_sym
|
105
|
+
@event_counter = {} unless @event_counter.is_a?(Hash)
|
106
|
+
@event_counter[func] = 0 if @event_counter[func].nil?
|
107
|
+
@event_counter[func]+=1
|
108
|
+
end
|
109
|
+
|
110
|
+
def mo_received(transceiver, pdu)
|
111
|
+
count_function
|
26
112
|
puts "** mo_received"
|
27
113
|
end
|
28
114
|
|
29
|
-
def delivery_report_received(transceiver,
|
115
|
+
def delivery_report_received(transceiver, pdu)
|
116
|
+
count_function
|
30
117
|
puts "** delivery_report_received"
|
31
118
|
end
|
32
119
|
|
33
|
-
def message_accepted(transceiver, mt_message_id,
|
120
|
+
def message_accepted(transceiver, mt_message_id, pdu)
|
121
|
+
count_function
|
34
122
|
puts "** message_sent"
|
123
|
+
#sending messages from delegate to escape making a fake message sender - not nice :(
|
124
|
+
$tx.send_mt(self.seq, 1, 2, "short_message @ message_accepted")
|
125
|
+
end
|
126
|
+
|
127
|
+
def message_rejected(transceiver, mt_message_id, pdu)
|
128
|
+
count_function
|
129
|
+
puts "** message_rejected"
|
130
|
+
$tx.send_mt(self.seq, 1, 2, "short_message @ message_rejected")
|
35
131
|
end
|
36
132
|
|
37
133
|
def bound(transceiver)
|
134
|
+
count_function
|
38
135
|
puts "** bound"
|
136
|
+
$tx.send_mt(self.seq, 1, 2, "short_message @ bound")
|
39
137
|
end
|
40
138
|
|
41
|
-
def unbound(transceiver)
|
139
|
+
def unbound(transceiver)
|
140
|
+
count_function
|
42
141
|
puts "** unbound"
|
43
142
|
EventMachine::stop_event_loop
|
44
143
|
end
|
45
144
|
end
|
46
145
|
|
146
|
+
class Poller
|
147
|
+
def start
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
47
153
|
class SmppTest < Test::Unit::TestCase
|
48
154
|
|
49
155
|
def config
|
50
|
-
|
51
|
-
:host => 'localhost',
|
52
|
-
:port => 2775,
|
53
|
-
:system_id => 'foo',
|
54
|
-
:password => 'bar',
|
55
|
-
:system_type => '',
|
56
|
-
:source_ton => 0,
|
57
|
-
:source_npi => 1,
|
58
|
-
:destination_ton => 1,
|
59
|
-
:destination_npi => 1,
|
60
|
-
:source_address_range => '',
|
61
|
-
:destination_address_range => ''
|
62
|
-
}
|
156
|
+
Server::config
|
63
157
|
end
|
64
158
|
|
65
159
|
def test_transceiver_should_bind_and_unbind_then_stop
|
66
160
|
EventMachine.run {
|
67
|
-
EventMachine.start_server "localhost", 9000,
|
161
|
+
EventMachine.start_server "localhost", 9000, Server::Unbind
|
68
162
|
EventMachine.connect "localhost", 9000, Smpp::Transceiver, config, Delegate.new
|
69
163
|
}
|
70
164
|
# should not hang here: the server's response should have caused the client to terminate
|
71
165
|
end
|
72
166
|
|
167
|
+
def test_transceiver_api_should_respond_to_message_rejected
|
168
|
+
$tx = nil
|
169
|
+
delegate = ResponsiveDelegate.new
|
170
|
+
EventMachine.run {
|
171
|
+
EventMachine.start_server "localhost", 9000, Server::SubmitSmResponseWithErrorStatus
|
172
|
+
$tx = EventMachine.connect "localhost", 9000, Smpp::Transceiver, config, delegate
|
173
|
+
}
|
174
|
+
assert_equal(delegate.event_counter[:message_rejected], 1)
|
175
|
+
end
|
176
|
+
|
73
177
|
def test_bind_transceiver
|
74
178
|
pdu1 = Smpp::Pdu::BindTransceiver.new(
|
75
179
|
config[:system_id],
|
@@ -158,6 +262,11 @@ class SmppTest < Test::Unit::TestCase
|
|
158
262
|
assert_equal(pdu1.command_status, pdu2.command_status)
|
159
263
|
end
|
160
264
|
|
265
|
+
def test_submit_sm_receiving_invalid_status
|
266
|
+
pdu1 = Smpp::Pdu::SubmitSm.new( '11111', '1111111111', "This is a test" )
|
267
|
+
pdu2 = Smpp::Pdu::Base.create(pdu1.data)
|
268
|
+
end
|
269
|
+
|
161
270
|
def test_deliver_sm_response
|
162
271
|
pdu1 = Smpp::Pdu::DeliverSmResponse.new( nil )
|
163
272
|
pdu2 = Smpp::Pdu::Base.create(pdu1.data)
|
@@ -256,5 +365,13 @@ class SmppTest < Test::Unit::TestCase
|
|
256
365
|
assert_equal(pdu1.sequence_number, pdu2.sequence_number)
|
257
366
|
assert_equal(pdu1.command_status, pdu2.command_status)
|
258
367
|
end
|
368
|
+
|
369
|
+
def test_should_parse_ref_and_stat_from_deliver_sm
|
370
|
+
direct = Smpp::Pdu::DeliverSm.new( '1', '2', "419318028472222#id:11f8f46639bd4f7a209016e1a181e3ae sub:001 dlvrd:001 submit date:0902191702 done date:0902191702 stat:DELIVRD err:000 Text:TVILLING: Sl? ut h?'!11f8f46639bd4f7a209016e1a181e3ae", :esm_class => 4)
|
371
|
+
parsed = Smpp::Pdu::Base.create(direct.data)
|
372
|
+
assert_equal("DELIVRD", parsed.stat)
|
373
|
+
assert_equal("11f8f46639bd4f7a209016e1a181e3ae", parsed.msg_reference)
|
374
|
+
end
|
375
|
+
|
259
376
|
|
260
377
|
end
|