ruby-smpp 0.1.2 → 0.1.3.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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