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.
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ *.log
23
+ nbproject
@@ -1,4 +1,9 @@
1
- = 2009.01.22
1
+ = 0.1.3
2
+ * Transition maintenance from August to Ray Krueger
3
+ * Changed the expected signature of transceiver delegates to use the full PDU instead of picking off attributes one by one
4
+ * Added support for parsing optional parameters from delivery receipts in deliver_sm PDUs (this is also the fix for trailing bytes from MOs)
5
+
6
+ = 0.1.2 2009.01.22
2
7
 
3
8
  == Delegate methods
4
9
 
@@ -41,4 +46,4 @@ I have implemented 4.5.1 section of SMPPv3.4: support for sending an MT message
41
46
 
42
47
  == Initial release (August Z. Flatby)
43
48
 
44
- My first open source project after all these years! Ah.. it feels good.
49
+ My first open source project after all these years! Ah.. it feels good.
data/CONTRIBUTORS.txt CHANGED
@@ -1,4 +1,5 @@
1
1
  Maintainer:
2
+ Ray Krueger <raykrueger@gmail.com>
2
3
  August Z. Flatby <august@apparat.no>
3
4
 
4
5
  Contributors:
@@ -6,4 +7,5 @@ Contributors:
6
7
  Taryn East <taryn@taryneast.org>
7
8
  Josh Bryan <jbryan@cashnetusa.com>
8
9
  Jon Wood <jonathan.wood@uk.clara.net>
9
- Jacob Eiler <jacob.eiler@apide.com>
10
+ Jacob Eiler <jacob.eiler@apide.com>
11
+ Valdis Pornieks <valdis@ithouse.lv>
File without changes
@@ -6,30 +6,33 @@ Ruby-SMPP is a Ruby implementation of the SMPP v3.4 protocol. It is suitable for
6
6
 
7
7
  The implementation is based on the Ruby/EventMachine library.
8
8
 
9
- Glossary
10
- -----------------
11
- SMSC: SMS Center. Mobile operators normally operate an SMSC in their network. The SMSC stores and forwards SMS messages.
12
- MO: Mobile Originated SMS: originated in a mobile phone, ie. sent by an end user.
13
- MT: Mobile Terminated SMS: terminated in a mobile phone, ie. received by an end user.
14
- DR: Delivery Report, or delivery notification. When you send an MT message, you should receive a DR after a while.
15
- PDU: Protcol Base Unit, the data units that SMPP is comprised of. This implementation does _not_ implement all SMPP PDUs.
16
-
17
- Protocol
18
- -----------------
9
+ <b>NOTE: Breaking change from 0.1.2 to 0.1.3</b>. See below.
10
+
11
+ === Glossary
12
+
13
+
14
+ * SMSC: SMS Center. Mobile operators normally operate an SMSC in their network. The SMSC stores and forwards SMS messages.
15
+ * MO: Mobile Originated SMS: originated in a mobile phone, ie. sent by an end user.
16
+ * MT: Mobile Terminated SMS: terminated in a mobile phone, ie. received by an end user.
17
+ * DR: Delivery Report, or delivery notification. When you send an MT message, you should receive a DR after a while.
18
+ * PDU: Protcol Base Unit, the data units that SMPP is comprised of. This implementation does _not_ implement all SMPP PDUs.
19
+
20
+ === Protocol
21
+
19
22
  The SMPP 3.4 protocol spec can be downloaded here: http://smsforum.net/SMPP_v3_4_Issue1_2.zip
20
23
 
21
- Testing/Sample Code
22
- -------------------
23
- Logica provides an SMPP simulator that you can download from http://opensmpp.logica.com/. You can
24
+ === Testing/Sample Code
25
+
26
+ Logica provides an SMPP simulator that you can download from http://opensmpp.logica.com. You can
24
27
  also sign up for a demo SMPP account at one of the many bulk-SMS providers out there.
25
28
 
26
29
  For a quick test, download smscsim.jar and smpp.jar from the Logica site, and start the simulator by typing:
27
30
 
28
- java -cp smscsim.jar:smpp.jar com.logica.smscsim.Simulator
31
+ java -cp smscsim.jar:smpp.jar com.logica.smscsim.Simulator
29
32
 
30
33
  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
34
 
32
- ./sample_gateway.rb
35
+ ruby sample_gateway.rb
33
36
 
34
37
  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
38
 
@@ -37,15 +40,14 @@ You can also send MO messages from the simulator to the sample gateway by typing
37
40
 
38
41
  == FEATURES/PROBLEMS:
39
42
 
43
+
40
44
  * Implements only typical client subset of SMPP 3.4 with single-connection Transceiver.
41
45
  * Contributors are encouraged to add missing PDUs.
42
- * Need more test cases!
43
46
 
44
47
  == BASIC USAGE:
45
48
 
46
49
  Start the transceiver. Receive delegate callbacks whenever incoming messages or delivery reports arrive. Send messages with Transceiver#send_mt.
47
50
 
48
- <pre>
49
51
  # connect to SMSC
50
52
  tx = EventMachine::run do
51
53
  $tx = EventMachine::connect(
@@ -53,44 +55,34 @@ Start the transceiver. Receive delegate callbacks whenever incoming messages or
53
55
  port,
54
56
  Smpp::Transceiver,
55
57
  config, # a property hash
56
- mo_proc, # the proc invoked on incoming (MO) messages
57
- dr_proc, # the proc invoked on delivery reports
58
- pdr_storage) # hash-like storage for pending delivery reports
58
+ delegate # delegate class that will receive callbacks on MOs and DRs and other events
59
59
  end
60
60
 
61
61
  # send a message
62
62
  tx.send_mt(id, from, to, body)
63
- </pre>
63
+
64
+ As of 0.1.3 the delegate method signatures are as follows:
65
+ * mo_received(transceiver, deliver_sm_pdu)
66
+ * delivery_report_received(transceiver, deliver_sm_pdu)
67
+ * message_accepted(transceiver, mt_message_id, submit_sm_response_pdu)
68
+ * message_rejected(transceiver, mt_message_id, submit_sm_response_pdu)
69
+ * bound(transceiver)
70
+ * unbound(transceiver)
71
+
72
+ Where 'pdu' above is the actual actual instance of the Smpp:Pdu:: class created.
64
73
 
65
74
  For a more complete example, see examples/sample_gateway.rb
66
75
 
67
76
  == REQUIREMENTS:
68
77
 
78
+
69
79
  * Eventmachine >= 0.10.0
70
80
 
71
81
  == INSTALL:
72
82
 
73
- * sudo gem install ruby-smpp
83
+ sudo gem install ruby-smpp
74
84
 
75
85
  == LICENSE:
76
86
 
77
87
  Copyright (c) 2008 Apparat AS
78
-
79
- Permission is hereby granted, free of charge, to any person obtaining
80
- a copy of this software and associated documentation files (the
81
- 'Software'), to deal in the Software without restriction, including
82
- without limitation the rights to use, copy, modify, merge, publish,
83
- distribute, sublicense, and/or sell copies of the Software, and to
84
- permit persons to whom the Software is furnished to do so, subject to
85
- the following conditions:
86
-
87
- The above copyright notice and this permission notice shall be
88
- included in all copies or substantial portions of the Software.
89
-
90
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
91
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
92
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
93
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
94
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
95
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
96
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
88
+ Released under the MIT license.
data/Rakefile CHANGED
@@ -1,9 +1,58 @@
1
- task :test do
2
- ruby "test/smpp_test.rb"
3
- end
4
-
5
- require 'config/requirements'
6
- require 'config/hoe' # setup Hoe + all gem configuration
7
-
8
- Dir['tasks/**/*.rake'].each { |rake| load rake }
9
-
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "ruby-smpp"
8
+ gem.summary = %Q{Ruby implementation of the SMPP protocol, based on EventMachine.}
9
+ gem.description = gem.summary + " SMPP is a protocol that allows ordinary people outside the mobile network to exchange SMS messages directly with mobile operators."
10
+ gem.email = "raykrueger@gmail.com"
11
+ gem.homepage = "http://github.com/raykrueger/ruby-smpp"
12
+ gem.authors = ["Ray Krueger", "August Z. Flatby"]
13
+ gem.rubyforge_project = gem.name
14
+
15
+ gem.extra_rdoc_files = ["README.rdoc", "CHANGELOG", "CONTRIBUTORS.txt"]
16
+
17
+ gem.add_dependency "eventmachine", ">= 0.10.0"
18
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'rake/testtask'
27
+ Rake::TestTask.new(:test) do |test|
28
+ test.libs << 'lib' << 'test'
29
+ test.pattern = 'test/**/*_test.rb'
30
+ test.verbose = true
31
+ end
32
+
33
+ begin
34
+ require 'rcov/rcovtask'
35
+ Rcov::RcovTask.new do |test|
36
+ test.libs << 'test'
37
+ test.pattern = 'test/**/test_*.rb'
38
+ test.verbose = true
39
+ end
40
+ rescue LoadError
41
+ task :rcov do
42
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
43
+ end
44
+ end
45
+
46
+ task :test => :check_dependencies
47
+
48
+ task :default => :test
49
+
50
+ require 'rake/rdoctask'
51
+ Rake::RDocTask.new do |rdoc|
52
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
53
+
54
+ rdoc.rdoc_dir = 'rdoc'
55
+ rdoc.title = "ruby-smpp #{version}"
56
+ rdoc.rdoc_files.include('README*', "CHANGELOG", "CONTRIBUTORS.txt", "LICENSE")
57
+ rdoc.rdoc_files.include('lib/**/*.rb')
58
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.3.pre1
@@ -1,56 +1,51 @@
1
- #!/usr/bin/env ruby0
1
+ #!/usr/bin/env ruby
2
+
3
+ # Sample SMS gateway that can receive MOs (mobile originated messages) and
4
+ # DRs (delivery reports), and send MTs (mobile terminated messages).
5
+ # MTs are, in the name of simplicity, entered on the command line in the format
6
+ # <sender> <receiver> <message body>
7
+ # MOs and DRs will be dumped to standard out.
8
+
9
+ require 'rubygems'
10
+ require File.dirname(__FILE__) + '/../lib/smpp'
11
+
2
12
  LOGFILE = File.dirname(__FILE__) + "/sms_gateway.log"
3
13
  Smpp::Base.logger = Logger.new(LOGFILE)
4
14
 
5
- # the transceiver
6
- $tx = nil
7
-
8
15
  # We use EventMachine to receive keyboard input (which we send as MT messages).
9
16
  # A "real" gateway would probably get its MTs from a message queue instead.
10
17
  module KeyboardHandler
11
18
  include EventMachine::Protocols::LineText2
12
19
 
13
20
  def receive_line(data)
14
- puts "Sending MT: #{data}"
15
- from = '2210'
16
- to = '4790000000'
17
- msg_id = 123
18
- $tx.send_mt(msg_id, from, to, data)
19
-
20
-
21
- # if you want to send messages with custom options, uncomment below code, this configuration allows the sender ID to be alpha numeric
22
- # $tx.send_mt(123, "RubySmpp", to, "Testing RubySmpp as sender id",{
23
- # :source_addr_ton=> 5,
24
- # :service_type => 1,
25
- # :source_addr_ton => 5,
26
- # :source_addr_npi => 0 ,
27
- # :dest_addr_ton => 2,
28
- # :dest_addr_npi => 1,
29
- # :esm_class => 3 ,
30
- # :protocol_id => 0,
31
- # :priority_flag => 0,
32
- # :schedule_delivery_time => nil,
33
- # :validity_period => nil,
34
- # :registered_delivery=> 1,
35
- # :replace_if_present_flag => 0,
36
- # :data_coding => 0,
37
- # :sm_default_msg_id => 0
38
- # })
39
-
40
- # if you want to send message to multiple destinations , uncomment below code
41
- # $tx.send_multi_mt(123, from, ["919900000001","919900000002","919900000003"], "I am echoing that ruby-smpp is great")
21
+ sender, receiver, *body_parts = data.split
22
+ unless sender && receiver && body_parts.size > 0
23
+ puts "Syntax: <sender> <receiver> <message body>"
24
+ else
25
+ body = body_parts.join(' ')
26
+ puts "Sending MT from #{sender} to #{receiver}: #{body}"
27
+ SampleGateway.send_mt(sender, receiver, body)
28
+ end
42
29
  prompt
43
30
  end
44
31
 
45
32
  def prompt
46
- print "Enter MT body: "
33
+ print "MT: "
47
34
  $stdout.flush
48
35
  end
49
36
  end
50
37
 
51
38
  class SampleGateway
52
- include KeyboardHandler
53
39
 
40
+ # MT id counter.
41
+ @@mt_id = 0
42
+
43
+ # expose SMPP transceiver's send_mt method
44
+ def self.send_mt(*args)
45
+ @@mt_id += 1
46
+ @@tx.send_mt(@@mt_id, *args)
47
+ end
48
+
54
49
  def logger
55
50
  Smpp::Base.logger
56
51
  end
@@ -60,65 +55,46 @@ class SampleGateway
60
55
  # semantics to map SMSC message IDs to your own message IDs.
61
56
  pdr_storage = {}
62
57
 
63
- # The block invoked when we receive an MO message from the SMSC
64
- mo_proc = Proc.new do |sender, receiver, msg|
65
- begin
66
- # This is where you'd enqueue or store the MO message for further processing.
67
- logger.info "Received MO from <#{sender}> to <#{receiver}>: <#{msg}>"
68
- rescue Exception => ex
69
- logger.error "Exception processing MO: #{ex}"
70
- end
71
- end
72
-
73
- # Invoked on delivery reports
74
- dr_proc = Proc.new do |msg_reference, stat, dr_pdu|
75
- begin
76
- # The SMSC returns its own message reference. Look up (and delete) our stored objects
77
- # based on this reference.
78
- #
79
- # The short_message attribute contains details on the current delivery status of the
80
- # message.
81
- pending_message = pdr_storage.delete(msg_reference)
82
- logger.info "Received DR for #{pending_message}. Stat: #{stat} SM: #{dr_pdu.short_message}"
83
- rescue Exception => ex
84
- logger.error "Error processing DR: #{ex}"
85
- end
86
- end
87
-
88
58
  # Run EventMachine in loop so we can reconnect when the SMSC drops our connection.
89
- prompt
59
+ puts "Connecting to SMSC..."
90
60
  loop do
91
61
  EventMachine::run do
92
- $tx = EventMachine::connect(
93
- config[:host],
94
- config[:port],
95
- Smpp::Transceiver,
96
- config,
97
- self # self is delegate
62
+ @@tx = EventMachine::connect(
63
+ config[:host],
64
+ config[:port],
65
+ Smpp::Transceiver,
66
+ config,
67
+ self # delegate that will receive callbacks on MOs and DRs and other events
98
68
  )
99
-
69
+ print "MT: "
70
+ $stdout.flush
71
+
100
72
  # Start consuming MT messages (in this case, from the console)
101
73
  # Normally, you'd hook this up to a message queue such as Starling
102
74
  # or ActiveMQ via STOMP.
103
75
  EventMachine::open_keyboard(KeyboardHandler)
104
76
  end
105
- logger.warn "Event loop stopped. Restarting in 5 seconds.."
77
+ puts "Disconnected. Reconnecting in 5 seconds.."
106
78
  sleep 5
107
79
  end
80
+ end
81
+
82
+ # ruby-smpp delegate methods
108
83
 
84
+ def mo_received(transceiver, pdu)
85
+ logger.info "Delegate: mo_received: from #{pdu.source_addr} to #{pdu.destination_addr}: #{pdu.short_message}"
109
86
  end
110
- # Delegate methods that will receive callbacks on various events
111
87
 
112
- def mo_received(transceiver, source_addr, destination_addr, short_message)
113
- logger.info "Delegate: mo_received: from #{source_addr} to #{destination_addr}: #{short_message}"
88
+ def delivery_report_received(transceiver, pdu)
89
+ logger.info "Delegate: delivery_report_received: ref #{pdu.msg_reference} stat #{pdu.stat}"
114
90
  end
115
91
 
116
- def delivery_report_received(transceiver, msg_reference, stat, pdu)
117
- logger.info "Delegate: delivery_report_received: ref #{msg_reference} stat #{stat} pdu #{pdu}"
92
+ def message_accepted(transceiver, mt_message_id, pdu)
93
+ logger.info "Delegate: message_accepted: id #{mt_message_id} smsc ref id: #{pdu.message_id}"
118
94
  end
119
95
 
120
- def message_accepted(transceiver, mt_message_id, smsc_message_id)
121
- logger.info "Delegate: message_sent: id #{mt_message_id} smsc ref id: #{smsc_message_id}"
96
+ def message_rejected(transceiver, mt_message_id, pdu)
97
+ logger.info "Delegate: message_rejected: id #{mt_message_id} smsc ref id: #{pdu.message_id}"
122
98
  end
123
99
 
124
100
  def bound(transceiver)
@@ -129,21 +105,22 @@ class SampleGateway
129
105
  logger.info "Delegate: transceiver unbound"
130
106
  EventMachine::stop_event_loop
131
107
  end
108
+
132
109
  end
133
110
 
134
111
  # Start the Gateway
135
112
  begin
136
- puts "Starting SMS Gateway. Check the log at #{LOGFILE}"
113
+ puts "Starting SMS Gateway. Please check the log at #{LOGFILE}"
137
114
 
138
115
  # SMPP properties. These parameters work well with the Logica SMPP simulator.
139
116
  # Consult the SMPP spec or your mobile operator for the correct settings of
140
117
  # the other properties.
141
118
  config = {
142
- :host => 'localhost',
119
+ :host => '127.0.0.1',
143
120
  :port => 6000,
144
121
  :system_id => 'hugo',
145
122
  :password => 'ggoohu',
146
- :system_type => 'vma', # default given according to SMPP 3.4 Spec
123
+ :system_type => '', # default given according to SMPP 3.4 Spec
147
124
  :interface_version => 52,
148
125
  :source_ton => 0,
149
126
  :source_npi => 1,