ruby-smpp 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.1.1 2008-10-20
2
+
3
+ * Contributions:
4
+ * See NEWS.txt
5
+
1
6
  == 0.1.0 2008-04-07
2
7
 
3
8
  * 1 major enhancement:
data/Manifest.txt CHANGED
@@ -17,13 +17,14 @@ lib/smpp/pdu/deliver_sm_response.rb
17
17
  lib/smpp/pdu/enquire_link.rb
18
18
  lib/smpp/pdu/enquire_link_response.rb
19
19
  lib/smpp/pdu/generic_nack.rb
20
+ lib/smpp/pdu/submit_multi.rb
21
+ lib/smpp/pdu/submit_multi_response.rb
20
22
  lib/smpp/pdu/submit_sm.rb
21
23
  lib/smpp/pdu/submit_sm_response.rb
22
24
  lib/smpp/pdu/unbind.rb
23
25
  lib/smpp/pdu/unbind_response.rb
24
26
  lib/smpp/transceiver.rb
25
27
  lib/sms.rb
26
- log/
27
28
  script/console
28
29
  script/destroy
29
30
  script/generate
data/README.txt CHANGED
@@ -1,7 +1,5 @@
1
1
  = Ruby-SMPP
2
2
 
3
- * http://ruby-smpp.rubyforge.org
4
-
5
3
  == DESCRIPTION:
6
4
 
7
5
  Ruby-SMPP is a Ruby implementation of the SMPP v3.4 protocol. It is suitable for writing gateway daemons that communicate with SMSCs for sending and receiving SMS messages.
@@ -20,14 +18,26 @@ Protocol
20
18
  -----------------
21
19
  The SMPP 3.4 protocol spec can be downloaded here: http://smsforum.net/SMPP_v3_4_Issue1_2.zip
22
20
 
23
- Testing
24
- -----------------
21
+ Testing/Sample Code
22
+ -------------------
25
23
  Logica provides an SMPP simulator that you can download from http://opensmpp.logica.com/. You can
26
24
  also sign up for a demo SMPP account at one of the many bulk-SMS providers out there.
27
25
 
26
+ For a quick test, download smscsim.jar and smpp.jar from the Logica site, and start the simulator by typing:
27
+
28
+ java -cp smscsim.jar:smpp.jar com.logica.smscsim.Simulator
29
+
30
+ Then type 1 (start simulation), and enter 6000 for port number. The simulator then starts a server socket on a background thread. In another terminal window, start the sample sms gateway from the ruby-smpp/examples directory by typing:
31
+
32
+ ./sample_gateway.rb
33
+
34
+ You will be able to send MT messages from the sample gateway terminal window by typing the message body. In the simulator terminal window you should see SMPP PDUs being sent from the sample gateway.
35
+
36
+ You can also send MO messages from the simulator to the sample gateway by typing 7 (log to screen off) and then 4 (send message). MO messages received by the sample gateway will be logged to ./sms_gateway.log.
37
+
28
38
  == FEATURES/PROBLEMS:
29
39
 
30
- * Implements only typical client subset of SMPP 3.4 with single-connection Transceiver as opposed to dual-connection Transmitter + Receiver.
40
+ * Implements only typical client subset of SMPP 3.4 with single-connection Transceiver as opposed to dual-connection Transmitter + Receiver (UPDATE: see NEWS re. patch from Taryn East)
31
41
  * Contributors are encouraged to add missing PDUs.
32
42
  * Need more test cases!
33
43
 
@@ -56,7 +66,7 @@ For a more complete example, see examples/sample_gateway.rb
56
66
 
57
67
  == REQUIREMENTS:
58
68
 
59
- * Eventmachine 0.10.0
69
+ * Eventmachine >= 0.10.0
60
70
 
61
71
  == INSTALL:
62
72
 
@@ -13,11 +13,12 @@
13
13
  # and accepts outgoing (MT) messages from the console. This may be useful for
14
14
  # testing your SMPP setup.
15
15
 
16
+ require 'rubygems'
16
17
  gem 'ruby-smpp'
17
18
  require 'smpp'
18
19
 
19
20
  # set up logger
20
- Smpp::Base.logger = Logger.new(File.join(File.dirname(__FILE__), '..', 'log/sms_gateway.log'))
21
+ Smpp::Base.logger = Logger.new('sms_gateway.log')
21
22
 
22
23
  # the transceiver
23
24
  $tx = nil
@@ -32,6 +33,29 @@ module KeyboardHandler
32
33
  from = '2210'
33
34
  to = '4790000000'
34
35
  $tx.send_mt(123, from, to, data)
36
+
37
+
38
+ # if you want to send messages with custom options, uncomment below code, this configuration allows the sender ID to be alpha numeric
39
+ # $tx.send_mt(123, "RubySmpp", to, "Testing RubySmpp as sender id",{
40
+ # :source_addr_ton=> 5,
41
+ # :service_type => 1,
42
+ # :source_addr_ton => 5,
43
+ # :source_addr_npi => 0 ,
44
+ # :dest_addr_ton => 2,
45
+ # :dest_addr_npi => 1,
46
+ # :esm_class => 3 ,
47
+ # :protocol_id => 0,
48
+ # :priority_flag => 0,
49
+ # :schedule_delivery_time => nil,
50
+ # :validity_period => nil,
51
+ # :registered_delivery=> 1,
52
+ # :replace_if_present_flag => 0,
53
+ # :data_coding => 0,
54
+ # :sm_default_msg_id => 0
55
+ # })
56
+
57
+ # if you want to send message to multiple destinations , uncomment below code
58
+ # $tx.send_multi_mt(123, from, ["919900000001","919900000002","919900000003"], "I am echoing that ruby-smpp is great")
35
59
  prompt
36
60
  end
37
61
  end
@@ -103,8 +127,10 @@ begin
103
127
  config = {
104
128
  :host => 'localhost',
105
129
  :port => 6000,
106
- :system_id => 'jorge',
107
- :password => 'jorge',
130
+ :system_id => 'hugo',
131
+ :password => 'ggoohu',
132
+ :system_type => 'vma', # default given according to SMPP 3.4 Spec
133
+ :interface_version => 52,
108
134
  :source_ton => 0,
109
135
  :source_npi => 1,
110
136
  :destination_ton => 1,
@@ -117,4 +143,4 @@ begin
117
143
  start(config)
118
144
  rescue Exception => ex
119
145
  puts "Exception in SMS Gateway: #{ex} at #{ex.backtrace[0]}"
120
- end
146
+ end
data/lib/smpp/base.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require 'rubygems'
2
+ gem 'eventmachine'
3
+
1
4
  require 'timeout'
2
5
  require 'iconv'
3
6
  require 'scanf'
@@ -27,6 +30,7 @@ module Smpp
27
30
 
28
31
  def initialize(config)
29
32
  @config = config
33
+ @data = ""
30
34
  end
31
35
 
32
36
  # invoked by EventMachine when connected
@@ -54,11 +58,25 @@ module Smpp
54
58
 
55
59
  # EventMachine::Connection#receive_data
56
60
  def receive_data(data)
57
- # parse incoming PDU
58
- pdu = read_pdu(data)
59
-
60
- # let subclass process it
61
- process_pdu(pdu) if pdu
61
+ #append data to buffer
62
+ @data << data
63
+
64
+ while (@data.length >=4)
65
+ cmd_length = @data[0..3].unpack('N').first
66
+ if(@data.length < cmd_length)
67
+ #not complete packet ... break
68
+ break
69
+ end
70
+
71
+ pkt = @data.slice!(0,cmd_length)
72
+
73
+ # parse incoming PDU
74
+ pdu = read_pdu(pkt)
75
+
76
+ # let subclass process it
77
+ process_pdu(pdu) if pdu
78
+
79
+ end
62
80
  end
63
81
 
64
82
  # EventMachine::Connection#unbind
@@ -121,4 +139,4 @@ module Smpp
121
139
  pdu
122
140
  end
123
141
  end
124
- end
142
+ end
data/lib/smpp/pdu/base.rb CHANGED
@@ -59,7 +59,8 @@ module Smpp::Pdu
59
59
  CANCEL_SM_RESP = 0X80000008
60
60
  ENQUIRE_LINK = 0X00000015
61
61
  ENQUIRE_LINK_RESP = 0X80000015
62
-
62
+ SUBMIT_MULTI = 0X00000021
63
+ SUBMIT_MULTI_RESP = 0X80000021
63
64
  # PDU sequence number.
64
65
  @@seq = [Time.now.to_i]
65
66
 
@@ -129,6 +130,8 @@ module Smpp::Pdu
129
130
  BindTransceiverResponse.new(seq, status, body)
130
131
  when SUBMIT_SM_RESP:
131
132
  SubmitSmResponse.new(seq, status, body)
133
+ when SUBMIT_MULTI_RESP:
134
+ SubmitMultiResponse.new(seq, status, body)
132
135
  when DELIVER_SM:
133
136
  DeliverSm.new(seq, status, body)
134
137
  else
@@ -137,4 +140,4 @@ module Smpp::Pdu
137
140
  end
138
141
  end
139
142
  end
140
- end
143
+ end
@@ -1,6 +1,6 @@
1
1
  class Smpp::Pdu::BindTransceiver < Smpp::Pdu::Base
2
- def initialize(system_id, password, addr_ton, addr_npi, address_range)
3
- body = sprintf("%s\0%s\0\0%c%c%c%s\0", system_id, password, 0x34, addr_ton, addr_npi, address_range)
2
+ def initialize(system_id, password, system_type, addr_ton, addr_npi, address_range)
3
+ body = sprintf("%s\0%s\0%s\0%c%c%c%s\0", system_id, password,system_type, 0x34, addr_ton, addr_npi, address_range)
4
4
  super(BIND_TRANSCEIVER, 0, next_sequence_number, body)
5
5
  end
6
6
  end
@@ -0,0 +1,67 @@
1
+ # Sending an MT message to multiple addresses
2
+ # Author: Abhishek Parolkar, (abhishek[at]parolkar.com)
3
+ class Smpp::Pdu::SubmitMulti < Smpp::Pdu::Base
4
+ IS_SMEADDR = 1 # type of dest_flag
5
+ IS_DISTLISTNAME = 2 #type of dest_flag
6
+
7
+ # Note: short_message (the SMS body) must be in iso-8859-1 format
8
+ def initialize(source_addr, destination_addr_array, short_message, options={})
9
+ options.merge!(
10
+ :esm_class => 0, # default smsc mode
11
+ :dcs => 3 # iso-8859-1
12
+ ) { |key, old_val, new_val| old_val }
13
+
14
+ @msg_body = short_message
15
+
16
+ udh = options[:udh]
17
+ service_type = ''
18
+ source_addr_ton = 0 # network specific
19
+ source_addr_npi = 1 # unknown
20
+ number_of_dests = destination_addr_array.length # Max value can be 254
21
+ dest_addr_ton = 1 # international
22
+ dest_addr_npi = 1 # unknown
23
+ dest_addresses = build_destination_addresses(destination_addr_array,dest_addr_ton,dest_addr_npi,IS_SMEADDR)
24
+ esm_class = options[:esm_class]
25
+ protocol_id = 0
26
+ priority_flag = 1
27
+ schedule_delivery_time = ''
28
+ validity_period = ''
29
+ registered_delivery = 1 # we want delivery notifications
30
+ replace_if_present_flag = 0
31
+ data_coding = options[:dcs]
32
+ sm_default_msg_id = 0
33
+ payload = udh ? udh + short_message : short_message # this used to be (short_message + "\0")
34
+ sm_length = payload.length
35
+
36
+ # craft the string/byte buffer
37
+ pdu_body = sprintf("%s\0%c%c%s\0%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, number_of_dests,dest_addresses, esm_class, protocol_id, priority_flag, schedule_delivery_time, validity_period,
38
+ registered_delivery, replace_if_present_flag, data_coding, sm_default_msg_id, sm_length, payload)
39
+ super(SUBMIT_MULTI, 0, next_sequence_number, pdu_body)
40
+ end
41
+
42
+ # some special formatting is needed for SubmitSm PDUs to show the actual message content
43
+ def to_human
44
+ # convert header (4 bytes) to array of 4-byte ints
45
+ a = @data.to_s.unpack('N4')
46
+ sprintf("(%22s) len=%3d cmd=%8s status=%1d seq=%03d (%s)", self.class.to_s[11..-1], a[0], a[1].to_s(16), a[2], a[3], @msg_body[0..30])
47
+ end
48
+ def build_destination_addresses(dest_array,dest_addr_ton,dest_addr_npi, dest_flag = IS_SMEADDR)
49
+
50
+ formatted_array = Array.new
51
+ dest_array.each { |dest_elem|
52
+ if dest_flag == IS_SMEADDR
53
+ packet_str = sprintf("%c%c%c%s",IS_SMEADDR,dest_addr_ton,dest_addr_npi,dest_elem)
54
+ formatted_array.push(packet_str)
55
+
56
+ elsif dest_flag == IS_DISTLISTNAME
57
+ packet_str = sprintf("%c%s",IS_SMEADDR,dest_elem)
58
+ formatted_array.push(packet_str)
59
+
60
+ end
61
+
62
+ }
63
+
64
+ formatted_array.join('\0');
65
+ end
66
+
67
+ end
@@ -0,0 +1,10 @@
1
+ # Recieving response for an MT message sent to multiple addresses
2
+ # Author: Abhishek Parolkar, (abhishek[at]parolkar.com)
3
+ class Smpp::Pdu::SubmitMultiResponse < Smpp::Pdu::Base
4
+ attr_accessor :message_id
5
+ def initialize(seq, status, message_id)
6
+ message_id = message_id.chomp("\000")
7
+ super(SUBMIT_MULTI_RESP, status, seq, message_id)
8
+ @message_id = message_id
9
+ end
10
+ end
@@ -3,29 +3,25 @@ class Smpp::Pdu::SubmitSm < Smpp::Pdu::Base
3
3
 
4
4
  # Note: short_message (the SMS body) must be in iso-8859-1 format
5
5
  def initialize(source_addr, destination_addr, short_message, options={})
6
- options.merge!(
7
- :esm_class => 0, # default smsc mode
8
- :dcs => 3 # iso-8859-1
9
- ) { |key, old_val, new_val| old_val }
10
-
6
+
11
7
  @msg_body = short_message
12
8
 
13
9
  udh = options[:udh]
14
- service_type = ''
15
- source_addr_ton = 0 # network specific
16
- source_addr_npi = 1 # unknown
17
- dest_addr_ton = 1 # international
18
- dest_addr_npi = 1 # unknown
19
- esm_class = options[:esm_class]
20
- protocol_id = 0
21
- priority_flag = 1
22
- schedule_delivery_time = ''
23
- validity_period = ''
24
- registered_delivery = 1 # we want delivery notifications
25
- replace_if_present_flag = 0
26
- data_coding = options[:dcs]
27
- sm_default_msg_id = 0
28
- payload = udh ? udh + short_message : (short_message + "\0")
10
+ service_type = options[:service_type]? options[:service_type] :''
11
+ source_addr_ton = options[:source_addr_ton]?options[:source_addr_ton]:0 # network specific
12
+ source_addr_npi = options[:source_addr_npi]?options[:source_addr_npi]:1 # unknown
13
+ dest_addr_ton = options[:dest_addr_ton]?options[:dest_addr_ton]:1 # international
14
+ dest_addr_npi = options[:dest_addr_npi]?options[:dest_addr_npi]:1 # unknown
15
+ esm_class = options[:esm_class]?options[:esm_class]:0 # default smsc mode
16
+ protocol_id = options[:protocol_id]?options[:protocol_id]:0
17
+ priority_flag = options[:priority_flag]?options[:priority_flag]:1
18
+ schedule_delivery_time = options[:schedule_delivery_time]?options[:schedule_delivery_time]:''
19
+ validity_period = options[:validity_period]?options[:validity_period]:''
20
+ registered_delivery = options[:registered_delivery]?options[:registered_delivery]:1 # we want delivery notifications
21
+ replace_if_present_flag = options[:replace_if_present_flag]?options[:replace_if_present_flag]:0
22
+ data_coding = options[:data_coding]?options[:data_coding]:3 # iso-8859-1
23
+ sm_default_msg_id = options[:sm_default_msg_id]?options[:sm_default_msg_id]:0
24
+ payload = udh ? udh + short_message : short_message # this used to be (short_message + "\0")
29
25
  sm_length = payload.length
30
26
 
31
27
  # craft the string/byte buffer
@@ -37,6 +37,23 @@ class Smpp::Transceiver < Smpp::Base
37
37
  raise InvalidStateException, "Transceiver is unbound. Cannot send MT messages."
38
38
  end
39
39
  end
40
+ # Send MT SMS message for multiple dest_address
41
+ # Author: Abhishek Parolkar (abhishek[at]parolkar.com)
42
+ # USAGE: $tx.send_multi_mt(123, "9100000000", ["9199000000000","91990000000001","9199000000002"], "Message here")
43
+ def send_multi_mt(message_id, source_addr, destination_addr_arr, short_message, options={})
44
+ logger.debug "Sending Multiple MT: #{short_message}"
45
+ if @state == :bound
46
+ pdu = Pdu::SubmitMulti.new(source_addr, destination_addr_arr, short_message, options)
47
+ write_pdu pdu
48
+
49
+ # keep the message ID so we can associate the SMSC message ID with our message
50
+ # when the response arrives.
51
+ @ack_ids[pdu.sequence_number] = message_id
52
+ else
53
+ raise InvalidStateException, "Transceiver is unbound. Cannot send MT messages."
54
+ end
55
+ end
56
+
40
57
 
41
58
  # a PDU is received
42
59
  def process_pdu(pdu)
@@ -78,6 +95,16 @@ class Smpp::Transceiver < Smpp::Base
78
95
  end
79
96
  # Now we got the SMSC message id; create pending delivery report
80
97
  @pdr_storage[pdu.message_id] = mt_message_id
98
+ when Pdu::SubmitMultiResponse
99
+ mt_message_id = @ack_ids[pdu.sequence_number]
100
+ if !mt_message_id
101
+ raise "Got SubmitMultiResponse for unknown sequence_number: #{pdu.sequence_number}"
102
+ end
103
+ if pdu.command_status != Pdu::Base::ESME_ROK
104
+ logger.error "Error status in SubmitMultiResponse: #{pdu.command_status}"
105
+ else
106
+ logger.info "Got OK SubmitMultiResponse (#{pdu.message_id} -> #{mt_message_id})"
107
+ end
81
108
  else
82
109
  super
83
110
  end
@@ -88,10 +115,11 @@ class Smpp::Transceiver < Smpp::Base
88
115
  raise IOError, 'Receiver already bound.' unless @state == :unbound
89
116
  pdu = Pdu::BindTransceiver.new(
90
117
  @config[:system_id],
91
- @config[:password],
118
+ @config[:password],
119
+ @config[:system_type],
92
120
  @config[:source_ton],
93
121
  @config[:source_npi],
94
122
  @config[:source_address_range])
95
123
  write_pdu(pdu)
96
124
  end
97
- end
125
+ end
data/lib/smpp/version.rb CHANGED
@@ -2,7 +2,7 @@ module Smpp #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 0
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/script/console CHANGED
File without changes
data/script/destroy CHANGED
File without changes
data/script/generate CHANGED
File without changes
data/script/txt2html CHANGED
File without changes
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-smpp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - August Z. Flatby
@@ -9,11 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-04-09 00:00:00 +02:00
12
+ date: 2008-10-20 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: eventmachine
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
@@ -21,6 +22,16 @@ dependencies:
21
22
  - !ruby/object:Gem::Version
22
23
  version: 0.10.0
23
24
  version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hoe
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.0
34
+ version:
24
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.
25
36
  email:
26
37
  - august@apparat.no
@@ -53,13 +64,14 @@ files:
53
64
  - lib/smpp/pdu/enquire_link.rb
54
65
  - lib/smpp/pdu/enquire_link_response.rb
55
66
  - lib/smpp/pdu/generic_nack.rb
67
+ - lib/smpp/pdu/submit_multi.rb
68
+ - lib/smpp/pdu/submit_multi_response.rb
56
69
  - lib/smpp/pdu/submit_sm.rb
57
70
  - lib/smpp/pdu/submit_sm_response.rb
58
71
  - lib/smpp/pdu/unbind.rb
59
72
  - lib/smpp/pdu/unbind_response.rb
60
73
  - lib/smpp/transceiver.rb
61
74
  - lib/sms.rb
62
- - log/
63
75
  - script/console
64
76
  - script/destroy
65
77
  - script/generate
@@ -92,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
104
  requirements: []
93
105
 
94
106
  rubyforge_project: ruby-smpp
95
- rubygems_version: 1.0.1
107
+ rubygems_version: 1.3.0
96
108
  signing_key:
97
109
  specification_version: 2
98
110
  summary: 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.