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 +23 -0
- data/{NEWS.txt → CHANGELOG} +7 -2
- data/CONTRIBUTORS.txt +3 -1
- data/{License.txt → LICENSE} +0 -0
- data/{README.txt → README.rdoc} +33 -41
- data/Rakefile +58 -9
- data/VERSION +1 -0
- data/examples/sample_gateway.rb +55 -78
- data/examples/sample_smsc.rb +2 -3
- data/lib/smpp/base.rb +33 -0
- data/lib/smpp/pdu/base.rb +23 -5
- data/lib/smpp/pdu/deliver_sm.rb +39 -7
- data/lib/smpp/server.rb +5 -1
- data/lib/smpp/transceiver.rb +15 -8
- data/ruby-smpp.gemspec +66 -18
- data/test/smpp_test.rb +147 -30
- metadata +26 -37
- data/History.txt +0 -14
- data/Manifest.txt +0 -45
- data/config/hoe.rb +0 -70
- data/config/requirements.rb +0 -15
- data/lib/smpp/version.rb +0 -9
- data/script/console +0 -10
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/script/txt2html +0 -74
- data/setup.rb +0 -1585
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/test/test_helper.rb +0 -2
data/.gitignore
ADDED
data/{NEWS.txt → CHANGELOG}
RENAMED
@@ -1,4 +1,9 @@
|
|
1
|
-
=
|
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>
|
data/{License.txt → LICENSE}
RENAMED
File without changes
|
data/{README.txt → README.rdoc}
RENAMED
@@ -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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
require '
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
data/examples/sample_gateway.rb
CHANGED
@@ -1,56 +1,51 @@
|
|
1
|
-
#!/usr/bin/env
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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 "
|
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
|
-
|
59
|
+
puts "Connecting to SMSC..."
|
90
60
|
loop do
|
91
61
|
EventMachine::run do
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
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
|
113
|
-
logger.info "Delegate:
|
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
|
117
|
-
logger.info "Delegate:
|
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
|
121
|
-
logger.info "Delegate:
|
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.
|
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 => '
|
119
|
+
:host => '127.0.0.1',
|
143
120
|
:port => 6000,
|
144
121
|
:system_id => 'hugo',
|
145
122
|
:password => 'ggoohu',
|
146
|
-
:system_type => '
|
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,
|