ruby-smpp 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem "jeweler"
4
+ gem "rake"
5
+ gem "eventmachine"
@@ -0,0 +1,22 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ eventmachine (0.12.10)
5
+ gemcutter (0.6.1)
6
+ git (1.2.5)
7
+ jeweler (1.4.0)
8
+ gemcutter (>= 0.1.0)
9
+ git (>= 1.2.5)
10
+ rubyforge (>= 2.0.0)
11
+ json_pure (1.4.6)
12
+ rake (0.8.7)
13
+ rubyforge (2.0.4)
14
+ json_pure (>= 1.1.7)
15
+
16
+ PLATFORMS
17
+ ruby
18
+
19
+ DEPENDENCIES
20
+ eventmachine
21
+ jeweler
22
+ rake
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- require 'rubygems'
1
+ require File.expand_path('../config/environment', __FILE__)
2
2
  require 'rake'
3
3
 
4
4
  begin
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -0,0 +1,2 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
@@ -10,6 +10,7 @@ require 'logger'
10
10
  $:.unshift(File.dirname(__FILE__))
11
11
  require 'smpp/base.rb'
12
12
  require 'smpp/transceiver.rb'
13
+ require 'smpp/receiver.rb'
13
14
  require 'smpp/optional_parameter'
14
15
  require 'smpp/pdu/base.rb'
15
16
  require 'smpp/pdu/bind_base.rb'
@@ -0,0 +1,4 @@
1
+ class Smpp::Pdu::BindReceiver < Smpp::Pdu::BindBase
2
+ @command_id = BIND_RECEIVER
3
+ handles_cmd BIND_RECEIVER
4
+ end
@@ -0,0 +1,4 @@
1
+ class Smpp::Pdu::BindReceiverResponse < Smpp::Pdu::BindRespBase
2
+ @command_id = BIND_RECEIVER_RESP
3
+ handles_cmd BIND_RECEIVER_RESP
4
+ end
@@ -27,7 +27,7 @@ class Smpp::Pdu::DeliverSm < Smpp::Pdu::Base
27
27
  @data_coding = options[:data_coding]?options[:data_coding]:3 # iso-8859-1
28
28
  @sm_default_msg_id = options[:sm_default_msg_id]?options[:sm_default_msg_id]:0
29
29
  @short_message = short_message
30
- payload = @udh ? @udh + @short_message : @short_message
30
+ payload = @udh ? @udh.to_s + @short_message : @short_message
31
31
  @sm_length = payload.length
32
32
 
33
33
  #fields set for delivery report
@@ -46,6 +46,18 @@ class Smpp::Pdu::DeliverSm < Smpp::Pdu::Base
46
46
  super(DELIVER_SM, 0, seq, pdu_body)
47
47
  end
48
48
 
49
+ def total_parts
50
+ @udh ? @udh[4] : 0
51
+ end
52
+
53
+ def part
54
+ @udh ? @udh[5] : 0
55
+ end
56
+
57
+ def message_id
58
+ @udh ? @udh[3] : 0
59
+ end
60
+
49
61
  def self.from_wire_data(seq, status, body)
50
62
  options = {}
51
63
  # brutally unpack it
@@ -85,7 +97,10 @@ class Smpp::Pdu::DeliverSm < Smpp::Pdu::Base
85
97
  end
86
98
  end
87
99
 
88
-
100
+ # Check to see if body has a 5 bit header
101
+ if short_message.unpack("c")[0] == 5
102
+ options[:udh] = short_message.slice!(0..5).unpack("CCCCCC")
103
+ end
89
104
 
90
105
  #Note: if the SM is a delivery receipt (esm_class=4) then the short_message _may_ be in this format:
91
106
  # "id:Smsc2013 sub:1 dlvrd:1 submit date:0610171515 done date:0610171515 stat:0 err:0 text:blah"
@@ -0,0 +1,80 @@
1
+
2
+ # The SMPP Receiver maintains a unidirectional connection to an SMSC.
3
+ # Provide a config hash with connection options to get started.
4
+ # See the sample_gateway.rb for examples of config values.
5
+ # The receiver accepts a delegate object that may implement
6
+ # the following (all optional) methods:
7
+ #
8
+ # mo_received(receiver, pdu)
9
+ # delivery_report_received(receiver, pdu)
10
+ # bound(receiver)
11
+ # unbound(receiver)
12
+
13
+ class Smpp::Receiver < Smpp::Base
14
+
15
+ def initialize(config, delegate)
16
+ super(config)
17
+ @delegate = delegate
18
+
19
+ ed = @config[:enquire_link_delay_secs] || 5
20
+ comm_inactivity_timeout = 2 * ed
21
+ rescue Exception => ex
22
+ logger.error "Exception setting up receiver: #{ex} at #{ex.backtrace.join("\n")}"
23
+ raise
24
+ end
25
+
26
+ # a PDU is received. Parse it and invoke delegate methods.
27
+ def process_pdu(pdu)
28
+ case pdu
29
+ when Pdu::DeliverSm
30
+ write_pdu(Pdu::DeliverSmResponse.new(pdu.sequence_number))
31
+ logger.debug "ESM CLASS #{pdu.esm_class}"
32
+ if pdu.esm_class != 4
33
+ # MO message
34
+ if @delegate.respond_to?(:mo_received)
35
+ @delegate.mo_received(self, pdu)
36
+ end
37
+ else
38
+ # Delivery report
39
+ if @delegate.respond_to?(:delivery_report_received)
40
+ @delegate.delivery_report_received(self, pdu)
41
+ end
42
+ end
43
+ when Pdu::BindReceiverResponse
44
+ case pdu.command_status
45
+ when Pdu::Base::ESME_ROK
46
+ logger.debug "Bound OK."
47
+ @state = :bound
48
+ if @delegate.respond_to?(:bound)
49
+ @delegate.bound(self)
50
+ end
51
+ when Pdu::Base::ESME_RINVPASWD
52
+ logger.warn "Invalid password."
53
+ # scheduele the connection to close, which eventually will cause the unbound() delegate
54
+ # method to be invoked.
55
+ close_connection
56
+ when Pdu::Base::ESME_RINVSYSID
57
+ logger.warn "Invalid system id."
58
+ close_connection
59
+ else
60
+ logger.warn "Unexpected BindReceiverResponse. Command status: #{pdu.command_status}"
61
+ close_connection
62
+ end
63
+ else
64
+ super
65
+ end
66
+ end
67
+
68
+ # Send BindReceiverResponse PDU.
69
+ def send_bind
70
+ raise IOError, 'Receiver already bound.' unless unbound?
71
+ pdu = Pdu::BindReceiver.new(
72
+ @config[:system_id],
73
+ @config[:password],
74
+ @config[:system_type],
75
+ @config[:source_ton],
76
+ @config[:source_npi],
77
+ @config[:source_address_range])
78
+ write_pdu(pdu)
79
+ end
80
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruby-smpp}
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ray Krueger", "August Z. Flatby"]
12
- s.date = %q{2010-06-14}
12
+ s.date = %q{2011-01-06}
13
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
14
  s.email = %q{raykrueger@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -21,10 +21,13 @@ Gem::Specification.new do |s|
21
21
  ".gitignore",
22
22
  "CHANGELOG",
23
23
  "CONTRIBUTORS.txt",
24
+ "Gemfile",
25
+ "Gemfile.lock",
24
26
  "LICENSE",
25
27
  "README.rdoc",
26
28
  "Rakefile",
27
29
  "VERSION",
30
+ "config/environment.rb",
28
31
  "examples/PDU1.example",
29
32
  "examples/PDU2.example",
30
33
  "examples/sample_gateway.rb",
@@ -34,6 +37,8 @@ Gem::Specification.new do |s|
34
37
  "lib/smpp/optional_parameter.rb",
35
38
  "lib/smpp/pdu/base.rb",
36
39
  "lib/smpp/pdu/bind_base.rb",
40
+ "lib/smpp/pdu/bind_receiver.rb",
41
+ "lib/smpp/pdu/bind_receiver_response.rb",
37
42
  "lib/smpp/pdu/bind_resp_base.rb",
38
43
  "lib/smpp/pdu/bind_transceiver.rb",
39
44
  "lib/smpp/pdu/bind_transceiver_response.rb",
@@ -48,11 +53,17 @@ Gem::Specification.new do |s|
48
53
  "lib/smpp/pdu/submit_sm_response.rb",
49
54
  "lib/smpp/pdu/unbind.rb",
50
55
  "lib/smpp/pdu/unbind_response.rb",
56
+ "lib/smpp/receiver.rb",
51
57
  "lib/smpp/server.rb",
52
58
  "lib/smpp/transceiver.rb",
53
59
  "lib/sms.rb",
54
60
  "ruby-smpp.gemspec",
61
+ "test/delegate.rb",
55
62
  "test/optional_parameter_test.rb",
63
+ "test/pdu_parsing_test.rb",
64
+ "test/receiver_test.rb",
65
+ "test/responsive_delegate.rb",
66
+ "test/server.rb",
56
67
  "test/smpp_test.rb",
57
68
  "test/submit_sm_test.rb"
58
69
  ]
@@ -63,7 +74,12 @@ Gem::Specification.new do |s|
63
74
  s.rubygems_version = %q{1.3.6}
64
75
  s.summary = %q{Ruby implementation of the SMPP protocol, based on EventMachine.}
65
76
  s.test_files = [
66
- "test/optional_parameter_test.rb",
77
+ "test/delegate.rb",
78
+ "test/optional_parameter_test.rb",
79
+ "test/pdu_parsing_test.rb",
80
+ "test/receiver_test.rb",
81
+ "test/responsive_delegate.rb",
82
+ "test/server.rb",
67
83
  "test/smpp_test.rb",
68
84
  "test/submit_sm_test.rb",
69
85
  "examples/sample_gateway.rb",
@@ -0,0 +1,28 @@
1
+ # the delagate receives callbacks when interesting things happen on the connection
2
+ class Delegate
3
+
4
+ def mo_received(transceiver, pdu)
5
+ puts "** mo_received"
6
+ end
7
+
8
+ def delivery_report_received(transceiver, pdu)
9
+ puts "** delivery_report_received"
10
+ end
11
+
12
+ def message_accepted(transceiver, mt_message_id, pdu)
13
+ puts "** message_sent"
14
+ end
15
+
16
+ def message_rejected(transceiver, mt_message_id, pdu)
17
+ puts "** message_rejected"
18
+ end
19
+
20
+ def bound(transceiver)
21
+ puts "** bound"
22
+ end
23
+
24
+ def unbound(transceiver)
25
+ puts "** unbound"
26
+ EventMachine::stop_event_loop
27
+ end
28
+ end
@@ -0,0 +1,84 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require File.expand_path(File.dirname(__FILE__) + "../../lib/smpp")
4
+
5
+ class PduParsingTest < Test::Unit::TestCase
6
+
7
+ def test_recieve_single_message
8
+ raw_data = <<-EOF
9
+ 0000 003d 0000 0005 0000 0000 0000 0002
10
+ 0001 0134 3437 3830 3330 3239 3833 3700
11
+ 0101 3434 3738 3033 3032 3938 3337 0000
12
+ 0000 0000 0000 0000 0454 6573 74
13
+ EOF
14
+
15
+ pdu = create_pdu(raw_data)
16
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
17
+ assert_equal "447803029837", pdu.source_addr
18
+ assert_equal "447803029837", pdu.destination_addr
19
+ assert_nil pdu.udh
20
+ assert_equal "Test", pdu.short_message
21
+ end
22
+
23
+ def test_recieve_part_one_of_multi_part_message
24
+ part_one_message = <<-EOF
25
+ 0000 00d8 0000 0005 0000 0000 0000 0001
26
+ 0001 0134 3437 3937 3334 3238 3634 3400
27
+ 0101 3434 3739 3736 3232 3430 3137 0000
28
+ 0000 0000 0000 0000 9f05 0003 b402 0154
29
+ 6869 7320 6973 2061 206c 6f6e 6720 6d65
30
+ 7373 6167 6520 746f 2074 6573 7420 7768
31
+ 6574 6865 7220 6f72 206e 6f74 2077 6520
32
+ 6765 7420 7468 6520 6865 6164 6572 2069
33
+ 6e66 6f20 7669 6120 7468 6520 534d 5343
34
+ 2074 6861 7420 7765 2077 6f75 6c64 2072
35
+ 6571 7569 7265 2074 6f20 6265 2061 626c
36
+ 6520 746f 2072 6563 6f6d 706f 7365 206c
37
+ 6f6e 6720 6d65 7373 6167 6573 2069 6e20
38
+ 6861 7368 626c 7565
39
+ EOF
40
+
41
+ pdu = create_pdu(part_one_message)
42
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
43
+ assert_equal "447973428644", pdu.source_addr
44
+ assert_equal "447976224017", pdu.destination_addr
45
+ assert_equal [5, 0, 3, 180, 2, 1], pdu.udh
46
+
47
+ assert_equal 2, pdu.total_parts, "Have total parts of the message"
48
+ assert_equal 1, pdu.part, "Correctly show the part"
49
+ assert_equal 180, pdu.message_id
50
+
51
+ assert_equal "This is a long message to test whether or not we get the header info via the SMSC that we would require to be able to recompose long messages in hashblue", pdu.short_message
52
+ end
53
+
54
+ def test_recieve_part_two_of_multi_part_message
55
+ part_one_message = <<-EOF
56
+ 0000 0062 0000 0005 0000 0000 0000 0002
57
+ 0001 0134 3437 3937 3334 3238 3634 3400
58
+ 0101 3434 3739 3736 3232 3430 3137 0000
59
+ 0000 0000 0000 0000 2905 0003 b402 0220
60
+ 616e 6420 7072 6f76 6964 6520 6120 676f
61
+ 6f64 2075 7365 7220 6578 7065 7269 656e
62
+ 6365
63
+ EOF
64
+
65
+ pdu = create_pdu(part_one_message)
66
+ assert_equal Smpp::Pdu::DeliverSm, pdu.class
67
+ assert_equal "447973428644", pdu.source_addr
68
+ assert_equal "447976224017", pdu.destination_addr
69
+ assert_equal [5, 0, 3, 180, 2, 2], pdu.udh
70
+
71
+ assert_equal 2, pdu.total_parts, "Have total parts of the message"
72
+ assert_equal 2, pdu.part, "Correctly show the part"
73
+ assert_equal 180, pdu.message_id
74
+
75
+ assert_equal " and provide a good user experience", pdu.short_message
76
+ end
77
+
78
+ protected
79
+ def create_pdu(raw_data)
80
+ hex_data = [raw_data.chomp.gsub(" ","").gsub(/\n/,"")].pack("H*")
81
+ Smpp::Pdu::Base.create(hex_data)
82
+ end
83
+
84
+ end
@@ -0,0 +1,197 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'smpp'
4
+
5
+ class ReceiverTest < Test::Unit::TestCase
6
+
7
+ class RecordingDelegate
8
+ attr_reader :received_pdus, :received_delivery_report_pdus, :states
9
+ def initialize
10
+ @received_pdus, @received_delivery_report_pdus, @states = [], [], []
11
+ end
12
+ def mo_received(receiver, pdu)
13
+ @received_pdus << pdu
14
+ end
15
+ def delivery_report_received(receiver, pdu)
16
+ @received_delivery_report_pdus << pdu
17
+ end
18
+ def bound(receiver)
19
+ @states << :bound
20
+ end
21
+ end
22
+
23
+ def test_receiving_bind_receiver_response_with_ok_status_should_become_bound
24
+ receiver = build_receiver
25
+ bind_receiver_response = Smpp::Pdu::BindReceiverResponse.new(nil, Smpp::Pdu::Base::ESME_ROK, 1)
26
+
27
+ receiver.process_pdu(bind_receiver_response)
28
+
29
+ assert receiver.bound?
30
+ end
31
+
32
+ def test_receiving_bind_receiver_response_with_ok_status_should_invoke_bound_on_delegate
33
+ delegate = RecordingDelegate.new
34
+ receiver = build_receiver(delegate)
35
+ bind_receiver_response = Smpp::Pdu::BindReceiverResponse.new(nil, Smpp::Pdu::Base::ESME_ROK, 1)
36
+
37
+ receiver.process_pdu(bind_receiver_response)
38
+
39
+ assert_equal [:bound], delegate.states
40
+ end
41
+
42
+ def test_receiving_bind_receiver_response_with_ok_status_should_not_error_if_method_doesnt_exist_on_delegate
43
+ delegate = Object.new
44
+ receiver = build_receiver(delegate)
45
+ bind_receiver_response = Smpp::Pdu::BindReceiverResponse.new(nil, Smpp::Pdu::Base::ESME_ROK, 1)
46
+
47
+ assert_nothing_raised { receiver.process_pdu(bind_receiver_response) }
48
+ end
49
+
50
+ def test_receiving_bind_receiver_response_with_error_status_should_not_become_bound
51
+ receiver = build_receiver
52
+ bind_receiver_response = Smpp::Pdu::BindReceiverResponse.new(nil, Smpp::Pdu::Base::ESME_RBINDFAIL, 1)
53
+
54
+ receiver.process_pdu(bind_receiver_response)
55
+
56
+ assert receiver.unbound?
57
+ end
58
+
59
+ def test_receiving_bind_receiver_response_with_error_status_should_not_invoke_bound_on_delegate
60
+ delegate = RecordingDelegate.new
61
+ receiver = build_receiver(delegate)
62
+ bind_receiver_response = Smpp::Pdu::BindReceiverResponse.new(nil, Smpp::Pdu::Base::ESME_RBINDFAIL, 1)
63
+
64
+ receiver.process_pdu(bind_receiver_response)
65
+
66
+ assert_equal [], delegate.states
67
+ end
68
+
69
+ def test_receiving_bind_receiver_response_with_error_status_should_close_connection
70
+ receiver = build_receiver
71
+ bind_receiver_response = Smpp::Pdu::BindReceiverResponse.new(nil, Smpp::Pdu::Base::ESME_RBINDFAIL, 1)
72
+
73
+ receiver.process_pdu(bind_receiver_response)
74
+
75
+ assert_equal 1, receiver.close_connections
76
+ end
77
+
78
+ def test_receiving_deliver_sm_should_send_deliver_sm_response
79
+ receiver = build_receiver
80
+ deliver_sm = Smpp::Pdu::DeliverSm.new("from", "to", "message")
81
+
82
+ receiver.process_pdu(deliver_sm)
83
+
84
+ first_sent_data = receiver.sent_data.first
85
+ assert_not_nil first_sent_data
86
+ actual_response = Smpp::Pdu::Base.create(first_sent_data)
87
+ expected_response = Smpp::Pdu::DeliverSmResponse.new(deliver_sm.sequence_number)
88
+ assert_equal expected_response.to_human, actual_response.to_human
89
+ end
90
+
91
+ def test_receiving_deliver_sm_should_invoke_mo_received_on_delegate
92
+ delegate = RecordingDelegate.new
93
+ receiver = build_receiver(delegate)
94
+ deliver_sm = Smpp::Pdu::DeliverSm.new("from", "to", "message")
95
+
96
+ receiver.process_pdu(deliver_sm)
97
+
98
+ first_received_pdu = delegate.received_pdus.first
99
+ assert_not_nil first_received_pdu
100
+ assert_equal deliver_sm.to_human, first_received_pdu.to_human
101
+ end
102
+
103
+ def test_receiving_deliver_sm_should_not_error_if_mo_received_method_doesnt_exist_on_delegate
104
+ delegate = Object.new
105
+ receiver = build_receiver(delegate)
106
+ deliver_sm = Smpp::Pdu::DeliverSm.new("from", "to", "message")
107
+
108
+ assert_nothing_raised { receiver.process_pdu(deliver_sm) }
109
+ end
110
+
111
+ def test_receiving_deliver_sm_for_esm_class_4_should_invoke_delivery_report_received_on_delegate
112
+ delegate = RecordingDelegate.new
113
+ receiver = build_receiver(delegate)
114
+ deliver_sm = Smpp::Pdu::DeliverSm.new("from", "to", "message", :esm_class => 4)
115
+
116
+ receiver.process_pdu(deliver_sm)
117
+
118
+ first_received_delivery_report_pdu = delegate.received_delivery_report_pdus.first
119
+ assert_not_nil first_received_delivery_report_pdu
120
+ assert_equal deliver_sm.to_human, first_received_delivery_report_pdu.to_human
121
+ end
122
+
123
+ def test_receiving_deliver_sm_should_not_error_if_received_delivery_report_method_doesnt_exist_on_delegate
124
+ delegate = Object.new
125
+ receiver = build_receiver(delegate)
126
+ deliver_sm = Smpp::Pdu::DeliverSm.new("from", "to", "message", :esm_class => 4)
127
+
128
+ assert_nothing_raised { receiver.process_pdu(deliver_sm) }
129
+ end
130
+
131
+ private
132
+
133
+ def build_receiver(delegate = nil)
134
+ receiver = Smpp::Receiver.new(1, {}, delegate)
135
+ class << receiver
136
+ attr_reader :sent_data, :close_connections
137
+ def send_data(data)
138
+ @sent_data = (@sent_data || []) + [data]
139
+ end
140
+ def close_connection
141
+ @close_connections = (@close_connections || 0) + 1
142
+ end
143
+ end
144
+ receiver
145
+ end
146
+
147
+ end
148
+
149
+ require 'server'
150
+ require 'delegate'
151
+
152
+ class SmppTest < Test::Unit::TestCase
153
+
154
+ def config
155
+ Server::config
156
+ end
157
+
158
+ def test_transceiver_should_bind_and_unbind_then_stop
159
+ EventMachine.run {
160
+ EventMachine.start_server "localhost", 9000, Server::Unbind
161
+ EventMachine.connect "localhost", 9000, Smpp::Receiver, config, Delegate.new
162
+ }
163
+ # should not hang here: the server's response should have caused the client to terminate
164
+ end
165
+
166
+ def test_bind_receiver
167
+ pdu1 = Smpp::Pdu::BindReceiver.new(
168
+ config[:system_id],
169
+ config[:password],
170
+ config[:system_type],
171
+ config[:source_ton],
172
+ config[:source_npi],
173
+ config[:source_address_range]
174
+ )
175
+
176
+ pdu2 = Smpp::Pdu::Base.create(pdu1.data)
177
+
178
+ assert_instance_of(Smpp::Pdu::BindReceiver, pdu2)
179
+ assert_equal(pdu1.system_id, pdu2.system_id)
180
+ assert_equal(pdu1.password, pdu2.password)
181
+ assert_equal(pdu1.system_type, pdu2.system_type)
182
+ assert_equal(pdu1.addr_ton, pdu2.addr_ton)
183
+ assert_equal(pdu1.addr_npi, pdu2.addr_npi)
184
+ assert_equal(pdu1.address_range, pdu2.address_range)
185
+ assert_equal(pdu1.sequence_number, pdu2.sequence_number)
186
+ assert_equal(pdu1.command_status, pdu2.command_status)
187
+ end
188
+
189
+ def test_bind_receiver_response
190
+ pdu1 = Smpp::Pdu::BindReceiverResponse.new(nil, Smpp::Pdu::Base::ESME_ROK, config[:system_id])
191
+ pdu2 = Smpp::Pdu::Base.create(pdu1.data)
192
+ assert_instance_of(Smpp::Pdu::BindReceiverResponse, pdu2)
193
+ assert_equal(pdu1.system_id, pdu2.system_id)
194
+ assert_equal(pdu1.sequence_number, pdu2.sequence_number)
195
+ assert_equal(pdu1.command_status, pdu2.command_status)
196
+ end
197
+ end
@@ -0,0 +1,53 @@
1
+ #TODO This should be made prettier with mocha
2
+ class ResponsiveDelegate
3
+ attr_reader :seq, :event_counter
4
+
5
+ def initialize
6
+ @seq = 0
7
+ @event_counter = nil
8
+ end
9
+ def seq
10
+ @seq += 1
11
+ end
12
+ def count_function
13
+ func = caller(1)[0].split("`")[1].split("'")[0].to_sym
14
+ @event_counter = {} unless @event_counter.is_a?(Hash)
15
+ @event_counter[func] = 0 if @event_counter[func].nil?
16
+ @event_counter[func]+=1
17
+ end
18
+
19
+ def mo_received(transceiver, pdu)
20
+ count_function
21
+ puts "** mo_received"
22
+ end
23
+
24
+ def delivery_report_received(transceiver, pdu)
25
+ count_function
26
+ puts "** delivery_report_received"
27
+ end
28
+
29
+ def message_accepted(transceiver, mt_message_id, pdu)
30
+ count_function
31
+ puts "** message_sent"
32
+ #sending messages from delegate to escape making a fake message sender - not nice :(
33
+ $tx.send_mt(self.seq, 1, 2, "short_message @ message_accepted")
34
+ end
35
+
36
+ def message_rejected(transceiver, mt_message_id, pdu)
37
+ count_function
38
+ puts "** message_rejected"
39
+ $tx.send_mt(self.seq, 1, 2, "short_message @ message_rejected")
40
+ end
41
+
42
+ def bound(transceiver)
43
+ count_function
44
+ puts "** bound"
45
+ $tx.send_mt(self.seq, 1, 2, "short_message @ bound")
46
+ end
47
+
48
+ def unbound(transceiver)
49
+ count_function
50
+ puts "** unbound"
51
+ EventMachine::stop_event_loop
52
+ end
53
+ end
@@ -0,0 +1,56 @@
1
+ # a server which immediately requests the client to unbind
2
+ module Server
3
+ def self.config
4
+ {
5
+ :host => 'localhost',
6
+ :port => 2775,
7
+ :system_id => 'foo',
8
+ :password => 'bar',
9
+ :system_type => '',
10
+ :source_ton => 0,
11
+ :source_npi => 1,
12
+ :destination_ton => 1,
13
+ :destination_npi => 1,
14
+ :source_address_range => '',
15
+ :destination_address_range => ''
16
+ }
17
+ end
18
+
19
+ module Unbind
20
+ def receive_data(data)
21
+ send_data Smpp::Pdu::Unbind.new.data
22
+ end
23
+ end
24
+
25
+ module SubmitSmResponse
26
+ def receive_data(data)
27
+ # problem: our Pdu's should have factory methods for "both ways"; ie. when created
28
+ # by client, and when created from wire data.
29
+ send_data Smpp::Pdu::SubmitSmResponse.new(1, 2, "100").data
30
+ end
31
+ end
32
+
33
+ module SubmitSmResponseWithErrorStatus
34
+ attr_reader :state #state=nil => bind => state=bound => send =>state=sent => unbind => state=unbound
35
+ def receive_data(data)
36
+ if @state.nil?
37
+ @state = 'bound'
38
+ pdu = Smpp::Pdu::Base.create(data)
39
+ response_pdu = Smpp::Pdu::BindTransceiverResponse.new(pdu.sequence_number,Smpp::Pdu::Base::ESME_ROK,Server::config[:system_id])
40
+ send_data response_pdu.data
41
+ elsif @state == 'bound'
42
+ @state = 'sent'
43
+ pdu = Smpp::Pdu::Base.create(data)
44
+ pdu.to_human
45
+ send_data Smpp::Pdu::SubmitSmResponse.new(pdu.sequence_number, Smpp::Pdu::Base::ESME_RINVDSTADR, pdu.body).data
46
+ #send_data Smpp::Pdu::SubmitSmResponse.new(1, 2, "100").data
47
+ elsif @state == 'sent'
48
+ @state = 'unbound'
49
+ send_data Smpp::Pdu::Unbind.new.data
50
+ else
51
+ raise "unexpected state"
52
+ end
53
+ end
54
+ end
55
+
56
+ end
@@ -1,147 +1,9 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
3
  require 'smpp'
4
-
5
- # a server which immediately requests the client to unbind
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
- }
21
- end
22
-
23
- module Unbind
24
- def receive_data(data)
25
- send_data Smpp::Pdu::Unbind.new.data
26
- end
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
-
60
- end
61
-
62
-
63
- # the delagate receives callbacks when interesting things happen on the connection
64
- class Delegate
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
112
- puts "** mo_received"
113
- end
114
-
115
- def delivery_report_received(transceiver, pdu)
116
- count_function
117
- puts "** delivery_report_received"
118
- end
119
-
120
- def message_accepted(transceiver, mt_message_id, pdu)
121
- count_function
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")
131
- end
132
-
133
- def bound(transceiver)
134
- count_function
135
- puts "** bound"
136
- $tx.send_mt(self.seq, 1, 2, "short_message @ bound")
137
- end
138
-
139
- def unbound(transceiver)
140
- count_function
141
- puts "** unbound"
142
- EventMachine::stop_event_loop
143
- end
144
- end
4
+ require 'server'
5
+ require 'delegate'
6
+ require 'responsive_delegate'
145
7
 
146
8
  class Poller
147
9
  def start
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 3
7
+ - 4
8
8
  - 0
9
- version: 0.3.0
9
+ version: 0.4.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Ray Krueger
@@ -15,13 +15,13 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-14 00:00:00 -05:00
18
+ date: 2011-01-06 00:00:00 -06:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: eventmachine
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
23
+ type: :runtime
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
@@ -30,8 +30,8 @@ dependencies:
30
30
  - 10
31
31
  - 0
32
32
  version: 0.10.0
33
- type: :runtime
34
- version_requirements: *id001
33
+ prerelease: false
34
+ requirement: *id001
35
35
  description: 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.
36
36
  email: raykrueger@gmail.com
37
37
  executables: []
@@ -46,10 +46,13 @@ files:
46
46
  - .gitignore
47
47
  - CHANGELOG
48
48
  - CONTRIBUTORS.txt
49
+ - Gemfile
50
+ - Gemfile.lock
49
51
  - LICENSE
50
52
  - README.rdoc
51
53
  - Rakefile
52
54
  - VERSION
55
+ - config/environment.rb
53
56
  - examples/PDU1.example
54
57
  - examples/PDU2.example
55
58
  - examples/sample_gateway.rb
@@ -59,6 +62,8 @@ files:
59
62
  - lib/smpp/optional_parameter.rb
60
63
  - lib/smpp/pdu/base.rb
61
64
  - lib/smpp/pdu/bind_base.rb
65
+ - lib/smpp/pdu/bind_receiver.rb
66
+ - lib/smpp/pdu/bind_receiver_response.rb
62
67
  - lib/smpp/pdu/bind_resp_base.rb
63
68
  - lib/smpp/pdu/bind_transceiver.rb
64
69
  - lib/smpp/pdu/bind_transceiver_response.rb
@@ -73,11 +78,17 @@ files:
73
78
  - lib/smpp/pdu/submit_sm_response.rb
74
79
  - lib/smpp/pdu/unbind.rb
75
80
  - lib/smpp/pdu/unbind_response.rb
81
+ - lib/smpp/receiver.rb
76
82
  - lib/smpp/server.rb
77
83
  - lib/smpp/transceiver.rb
78
84
  - lib/sms.rb
79
85
  - ruby-smpp.gemspec
86
+ - test/delegate.rb
80
87
  - test/optional_parameter_test.rb
88
+ - test/pdu_parsing_test.rb
89
+ - test/receiver_test.rb
90
+ - test/responsive_delegate.rb
91
+ - test/server.rb
81
92
  - test/smpp_test.rb
82
93
  - test/submit_sm_test.rb
83
94
  has_rdoc: true
@@ -111,7 +122,12 @@ signing_key:
111
122
  specification_version: 3
112
123
  summary: Ruby implementation of the SMPP protocol, based on EventMachine.
113
124
  test_files:
125
+ - test/delegate.rb
114
126
  - test/optional_parameter_test.rb
127
+ - test/pdu_parsing_test.rb
128
+ - test/receiver_test.rb
129
+ - test/responsive_delegate.rb
130
+ - test/server.rb
115
131
  - test/smpp_test.rb
116
132
  - test/submit_sm_test.rb
117
133
  - examples/sample_gateway.rb