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.
@@ -3,9 +3,8 @@
3
3
  # Sample SMPP SMS Gateway.
4
4
 
5
5
  require 'rubygems'
6
- gem 'ruby-smpp'
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 = 0X00000021
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
- sprintf("%c%c%c%c", value >> 24, value >> 16, value >> 8, value & 0xff)
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: 0x#{cmd.to_s(16)}"
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
@@ -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
- short_message = body.unpack('Z*CCZ*CCZ*CCCZ*Z*CCCCCa*')
66
- Smpp::Base.logger.debug "DeliverSM with source_addr=#{source_addr}, destination_addr=#{destination_addr}"
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
- options[:msg_reference] = short_message.scanf('id:%s').to_s
77
- # @stat must be parsed according to the SMSC vendor's specifications (see comment above)
78
- options[:stat] = 0
79
- end
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
- # the opposite of a client-based receiver, the server transmitter waill send
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
 
@@ -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, source_addr, destination_addr, short_message)
9
- # delivery_report_received(transceiver, msg_reference, stat, pdu)
10
- # message_accepted(transceiver, mt_message_id, smsc_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.source_addr, pdu.destination_addr, pdu.short_message)
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.msg_reference.to_s, pdu.stat, 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.message_id)
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.message_id)
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.2"
8
+ s.version = "0.1.3.pre1"
4
9
 
5
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
- s.authors = ["August Z. Flatby"]
7
- s.date = %q{2009-01-04}
8
- 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.}
9
- s.email = ["august@apparat.no"]
10
- s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "README.txt", "CONTRIBUTORS.txt"]
11
- s.files = ["History.txt", "License.txt", "Manifest.txt", "README.txt", "CONTRIBUTORS.txt", "Rakefile", "examples/PDU1.example", "examples/PDU2.example", "examples/sample_gateway.rb", "examples/sample_smsc.rb", "config/hoe.rb", "config/requirements.rb", "lib/smpp.rb", "lib/smpp/base.rb", "lib/smpp/pdu/base.rb", "lib/smpp/pdu/bind_base.rb", "lib/smpp/pdu/bind_receiver.rb", "lib/smpp/pdu/bind_receiver_response.rb", "lib/smpp/pdu/bind_resp_base.rb", "lib/smpp/pdu/bind_transceiver.rb", "lib/smpp/pdu/bind_transceiver_response.rb", "lib/smpp/pdu/bind_transmitter.rb", "lib/smpp/pdu/bind_transmitter_response.rb", "lib/smpp/pdu/deliver_sm.rb", "lib/smpp/pdu/deliver_sm_response.rb", "lib/smpp/pdu/enquire_link.rb", "lib/smpp/pdu/enquire_link_response.rb", "lib/smpp/pdu/generic_nack.rb", "lib/smpp/pdu/submit_multi.rb", "lib/smpp/pdu/submit_multi_response.rb", "lib/smpp/pdu/submit_sm.rb", "lib/smpp/pdu/submit_sm_response.rb", "lib/smpp/pdu/unbind.rb", "lib/smpp/pdu/unbind_response.rb", "lib/smpp/server.rb", "lib/smpp/transceiver.rb", "lib/smpp/version.rb", "lib/sms.rb", "script/console", "script/destroy", "script/generate", "script/txt2html", "setup.rb", "tasks/deployment.rake", "tasks/environment.rake", "test/smpp_test.rb", "test/test_helper.rb"]
12
- s.has_rdoc = true
13
- s.homepage = %q{http://ruby-smpp.rubyforge.org}
14
- s.rdoc_options = ["--main", "README.txt"]
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.0}
18
- s.summary = %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.}
19
- s.test_files = ["test/test_helper.rb"]
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 = 2
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<hoe>, [">= 1.8.0"])
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<hoe>, [">= 1.8.0"])
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<hoe>, [">= 1.8.0"])
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 Server1
10
- def receive_data(data)
11
- send_data Smpp::Pdu::Unbind.new.data
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 Server2
16
- def receive_data(data)
17
- # problem: our Pdu's should have factory methods for "both ways"; ie. when created
18
- # by client, and when created from wire data.
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
- def mo_received(transceiver, source_addr, destination_addr, short_message)
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, msg_reference, stat, pdu)
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, smsc_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, Server1
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