cimd 0.0.1
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.
- data/.travis.yml +5 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +42 -0
- data/Guardfile +35 -0
- data/README.md +49 -0
- data/Rakefile +2 -0
- data/bin/cimd_cli.rb +70 -0
- data/cimd.gemspec +29 -0
- data/lib/cimd.rb +4 -0
- data/lib/cimd/version.rb +5 -0
- data/lib/cimd_constants.rb +91 -0
- data/lib/cimd_loop.rb +173 -0
- data/lib/cimd_messages.rb +56 -0
- data/lib/cimd_structures.rb +237 -0
- data/spec/lib/cimd_spec.rb +158 -0
- metadata +174 -0
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
cimd (0.0.1)
|
5
|
+
eventmachine (>= 0.12)
|
6
|
+
thor
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
diff-lcs (1.1.3)
|
12
|
+
eventmachine (0.12.10)
|
13
|
+
ffi (1.0.11)
|
14
|
+
guard (1.3.2)
|
15
|
+
listen (>= 0.4.2)
|
16
|
+
thor (>= 0.14.6)
|
17
|
+
guard-rspec (1.2.1)
|
18
|
+
guard (>= 1.1)
|
19
|
+
listen (0.5.0)
|
20
|
+
rake (0.9.2.2)
|
21
|
+
rb-inotify (0.8.8)
|
22
|
+
ffi (>= 0.5.0)
|
23
|
+
rspec (2.6.0)
|
24
|
+
rspec-core (~> 2.6.0)
|
25
|
+
rspec-expectations (~> 2.6.0)
|
26
|
+
rspec-mocks (~> 2.6.0)
|
27
|
+
rspec-core (2.6.4)
|
28
|
+
rspec-expectations (2.6.0)
|
29
|
+
diff-lcs (~> 1.1.2)
|
30
|
+
rspec-mocks (2.6.0)
|
31
|
+
thor (0.16.0)
|
32
|
+
|
33
|
+
PLATFORMS
|
34
|
+
ruby
|
35
|
+
|
36
|
+
DEPENDENCIES
|
37
|
+
cimd!
|
38
|
+
guard (>= 1.3)
|
39
|
+
guard-rspec (>= 1.2)
|
40
|
+
rake
|
41
|
+
rb-inotify (>= 0.8.8)
|
42
|
+
rspec
|
data/Guardfile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
#guard 'coffeescript', :input => 'app/assets/javascripts'
|
5
|
+
|
6
|
+
#guard 'livereload' do
|
7
|
+
#watch(%r{app/views/.+\.(erb|haml|slim)})
|
8
|
+
#watch(%r{app/helpers/.+\.rb})
|
9
|
+
#watch(%r{public/.+\.(css|js|html)})
|
10
|
+
#watch(%r{config/locales/.+\.yml})
|
11
|
+
## Rails Assets Pipeline
|
12
|
+
#watch(%r{(app|vendor)/assets/\w+/(.+\.(css|js|html)).*}) { |m| "/assets/#{m[2]}" }
|
13
|
+
#end
|
14
|
+
|
15
|
+
guard 'rspec', :version => 2 do
|
16
|
+
watch(%r{^spec/lib/.+_spec\.rb$})
|
17
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/cimd_spec.rb" }
|
18
|
+
#watch('spec/spec_helper.rb') { "spec" }
|
19
|
+
|
20
|
+
## Rails example
|
21
|
+
#watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
22
|
+
#watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
23
|
+
#watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
24
|
+
#watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
25
|
+
#watch('config/routes.rb') { "spec/routing" }
|
26
|
+
#watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
27
|
+
|
28
|
+
## Capybara request specs
|
29
|
+
#watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
30
|
+
|
31
|
+
## Turnip features and steps
|
32
|
+
#watch(%r{^spec/acceptance/(.+)\.feature$})
|
33
|
+
#watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
34
|
+
end
|
35
|
+
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
[](https://gemnasium.com/musashimm/cimd)
|
2
|
+
[](http://travis-ci.org/musashimm/cimd)
|
3
|
+
[](https://codeclimate.com/github/musashimm/cimd)
|
4
|
+
|
5
|
+
CIMD
|
6
|
+
======
|
7
|
+
|
8
|
+
Overview
|
9
|
+
--------
|
10
|
+
|
11
|
+
Classes and binaries to handle SMS Cimd protocol.
|
12
|
+
|
13
|
+
Usage
|
14
|
+
-----
|
15
|
+
|
16
|
+
### cimd_cli.rb receivesms ###
|
17
|
+
`cimd_cli.rb receivesms` receives smses endlessly. If You want to stop reciving just press ^C.
|
18
|
+
|
19
|
+
cimd_cli.rb receivesms --msisdn=MSISDN --password=PASSWORD --server=SERVER --user-identity=USER_IDENTITY
|
20
|
+
|
21
|
+
Options:
|
22
|
+
--server=SERVER # Address of SMSC server (can be DNS name)
|
23
|
+
[--port=PORT] # Port number for CIMD protocol
|
24
|
+
# Default: 9971
|
25
|
+
--user-identity=USER_IDENTITY # Username of CIMD account
|
26
|
+
--password=PASSWORD # Password for CIMD account USERNAME
|
27
|
+
[--message=MESSAGE] # Message to be send
|
28
|
+
# Default: SMS test message
|
29
|
+
--msisdn=MSISDN # MSISDN number to be send
|
30
|
+
[--alpha-orig-address=ALPHA_ORIG_ADDRESS] # Identity of sender
|
31
|
+
# Default: Sms Service
|
32
|
+
### cimd_cli.rb sendsms ###
|
33
|
+
`cimd_cli.rb sendsms` sends text SMS to MSISDN number
|
34
|
+
|
35
|
+
cimd_cli.rb sendsms --msisdn=MSISDN --password=PASSWORD --server=SERVER --user-identity=USER_IDENTITY
|
36
|
+
|
37
|
+
Options:
|
38
|
+
--server=SERVER # Address of SMSC server (can be DNS name)
|
39
|
+
[--port=PORT] # Port number for CIMD protocol
|
40
|
+
# Default: 9971
|
41
|
+
--user-identity=USER_IDENTITY # Username of CIMD account
|
42
|
+
--password=PASSWORD # Password for CIMD account USERNAME
|
43
|
+
[--message=MESSAGE] # Message to be send
|
44
|
+
# Default: SMS test message
|
45
|
+
--msisdn=MSISDN # MSISDN number to be send
|
46
|
+
[--alpha-orig-address=ALPHA_ORIG_ADDRESS] # Identity of sender
|
47
|
+
# Default: Sms Service
|
48
|
+
|
49
|
+
|
data/Rakefile
ADDED
data/bin/cimd_cli.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'eventmachine'
|
5
|
+
require 'cimd'
|
6
|
+
require 'thor'
|
7
|
+
|
8
|
+
module CIMD
|
9
|
+
|
10
|
+
def self.start_eventmachine(conn,messages,options)
|
11
|
+
EventMachine.run do
|
12
|
+
Signal.trap("INT") { CIMD::Loop.logout_request }
|
13
|
+
Signal.trap("TERM") { CIMD::Loop.logout_request }
|
14
|
+
EventMachine.connect conn.server, conn.port, CIMD::Loop do |c|
|
15
|
+
c.messages = messages
|
16
|
+
c.conn = conn
|
17
|
+
c.options = options
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class MyCLI < Thor
|
23
|
+
|
24
|
+
desc "sendsms", "Sends text SMS to MSISDN number"
|
25
|
+
option :server, :required => true,:desc => "Address of SMSC server (can be DNS name)"
|
26
|
+
option :port, :desc => "Port number for CIMD protocol",:default => 9971
|
27
|
+
option :user_identity, :required => true,:desc => "Username of CIMD account"
|
28
|
+
option :password, :required => true,:desc => "Password for CIMD account USERNAME"
|
29
|
+
option :message, :desc => "Message to be send",:default=>"SMS test message"
|
30
|
+
option :msisdn, :required => true,:desc => "MSISDN number to be send"
|
31
|
+
option :alpha_orig_address, :desc => "Identity of sender",:default => "Sms Service"
|
32
|
+
def sendsms()
|
33
|
+
puts "Sending sms message: #{options[:message]} to #{options[:msisdn]}"
|
34
|
+
conn = CIMD::Connection.new(options[:server],options[:port],options[:user_identity],options[:password],options[:alpha_orig_address],1,60)
|
35
|
+
messages = EM::Queue.new
|
36
|
+
messages.push(CIMD::login_message(conn))
|
37
|
+
messages.push(CIMD::submit_text_message(conn,options[:msisdn],options[:message]))
|
38
|
+
messages.push(CIMD::logout_message)
|
39
|
+
CIMD::start_eventmachine(conn,messages,{})
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "receivesms", "Receives smses and sends echo"
|
43
|
+
long_desc <<-LONGDESC
|
44
|
+
`cimd_cli.rb receivesms` receives smses endlessly. If You want to stop
|
45
|
+
reciving just press ^C.
|
46
|
+
LONGDESC
|
47
|
+
option :server, :required => true,:desc => "Address of SMSC server (can be DNS name)"
|
48
|
+
option :port, :desc => "Port number for CIMD protocol",:default => 9971
|
49
|
+
option :user_identity, :required => true,:desc => "Username of CIMD account"
|
50
|
+
option :password, :required => true,:desc => "Password for CIMD account USERNAME"
|
51
|
+
option :message, :desc => "Message to be send",:default=>"SMS test message"
|
52
|
+
option :msisdn, :required => true,:desc => "MSISDN number to be send"
|
53
|
+
option :alpha_orig_address, :desc => "Identity of sender",:default => "Sms Service"
|
54
|
+
def receivesms()
|
55
|
+
puts "Start receiving"
|
56
|
+
conn = CIMD::Connection.new(options[:server],options[:port],options[:user_identity],options[:password],options[:alpha_orig_address],1,60)
|
57
|
+
messages = EM::Queue.new
|
58
|
+
messages.push(CIMD::login_message(conn))
|
59
|
+
CIMD::start_eventmachine(conn,messages,{})
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
CIMD::MyCLI.start(ARGV)
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
|
data/cimd.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "cimd/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "cimd"
|
7
|
+
s.version = CIMD::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Wojciech Todryk"]
|
10
|
+
s.email = ["wojciech@todryk.pl"]
|
11
|
+
s.homepage = "http://todryk.pl/cimd"
|
12
|
+
s.summary = %q{Utils for CIMD protocol}
|
13
|
+
s.description = %q{Utils for CIMD protocol}
|
14
|
+
|
15
|
+
s.rubyforge_project = "cimd"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.add_dependency "eventmachine", [">= 0.12"]
|
22
|
+
s.add_dependency "thor", [">= 0"]
|
23
|
+
s.add_development_dependency "rspec", [">= 0"]
|
24
|
+
s.add_development_dependency "rake", [">= 0"]
|
25
|
+
s.add_development_dependency "guard", [">= 1.3"]
|
26
|
+
s.add_development_dependency "guard-rspec", [">= 1.2"]
|
27
|
+
s.add_development_dependency "rb-inotify", [">= 0.8.8"]
|
28
|
+
|
29
|
+
end
|
data/lib/cimd.rb
ADDED
data/lib/cimd/version.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
module CIMD
|
2
|
+
|
3
|
+
STX = 0x02
|
4
|
+
ETX = 0x03
|
5
|
+
TAB = "\t"
|
6
|
+
CC = 0xFF
|
7
|
+
PARAM_SEP = ":"
|
8
|
+
|
9
|
+
# OP - OPERATION CODES
|
10
|
+
OP_LOGIN = 1
|
11
|
+
OP_LOGOUT = 2
|
12
|
+
OP_SUBMIT= 3
|
13
|
+
OP_ENQUIRE_MESSAGE_STATUS = 4
|
14
|
+
OP_DELIVERY_REQUEST = 5
|
15
|
+
OP_CANCEL_MESSAGE = 6
|
16
|
+
OP_SET = 8
|
17
|
+
OP_GET = 9
|
18
|
+
OP_DELIVERY_MESSAGE = 20
|
19
|
+
OP_DELIVERY_STATUS_REPORT = 23
|
20
|
+
OP_ALIVE = 40
|
21
|
+
OP_LOGIN_RESPONSE = 51
|
22
|
+
OP_LOGOUT_RESPONSE = 52
|
23
|
+
OP_SUBMIT_RESPONSE = 53
|
24
|
+
OP_ENQUIRE_MESSAGE_STATUS_RESPONSE = 54
|
25
|
+
OP_DELIVERY_REQUEST_RESPONSE = 55
|
26
|
+
OP_CANCEL_MESSAGE_RESPONSE = 56
|
27
|
+
OP_SET_RESPONSE = 58
|
28
|
+
OP_GET_RESPONSE = 59
|
29
|
+
OP_DELIVERY_MESSAGE_RESPONSE = 70
|
30
|
+
OP_DELIVERY_STATUS_REPORT_RESPONSE = 73
|
31
|
+
OP_ALIVE_RESPONSE = 90
|
32
|
+
OP_GENERAL_ERROR_RESPONSE = 98
|
33
|
+
OP_NACK = 99
|
34
|
+
|
35
|
+
def self.opcode_description(op_code)
|
36
|
+
descs = {
|
37
|
+
OP_LOGIN => "OP_LOGIN",
|
38
|
+
OP_LOGOUT => "OP_LOGOUT",
|
39
|
+
OP_SUBMIT=> "OP_SUBMIT",
|
40
|
+
OP_ENQUIRE_MESSAGE_STATUS => "OP_ENQUIRE_MESSAGE_STATUS",
|
41
|
+
OP_DELIVERY_REQUEST => "OP_DELIVERY_REQUEST",
|
42
|
+
OP_CANCEL_MESSAGE => "OP_CANCEL_MESSAGE",
|
43
|
+
OP_SET => "OP_SET",
|
44
|
+
OP_GET => "OP_GET",
|
45
|
+
OP_DELIVERY_MESSAGE => "OP_DELIVERY_MESSAGE",
|
46
|
+
OP_DELIVERY_STATUS_REPORT => "OP_DELIVERY_STATUS_REPORT",
|
47
|
+
OP_ALIVE => "OP_ALIVE",
|
48
|
+
OP_LOGIN_RESPONSE => "OP_LOGIN_RESPONSE",
|
49
|
+
OP_LOGOUT_RESPONSE => "OP_LOGOUT_RESPONSE",
|
50
|
+
OP_SUBMIT_RESPONSE => "OP_SUBMIT_RESPONSE",
|
51
|
+
OP_ENQUIRE_MESSAGE_STATUS_RESPONSE => "OP_ENQUIRE_MESSAGE_STATUS_RESPONSE",
|
52
|
+
OP_DELIVERY_REQUEST_RESPONSE => "OP_DELIVERY_REQUEST_RESPONSE",
|
53
|
+
OP_CANCEL_MESSAGE_RESPONSE => "OP_CANCEL_MESSAGE_RESPONSE",
|
54
|
+
OP_SET_RESPONSE => "OP_SET_RESPONSE",
|
55
|
+
OP_GET_RESPONSE => "OP_GET_RESPONSE",
|
56
|
+
OP_DELIVERY_MESSAGE_RESPONSE => "OP_DELIVERY_MESSAGE_RESPONSE",
|
57
|
+
OP_DELIVERY_STATUS_REPORT_RESPONSE => "OP_DELIVERY_STATUS_REPORT_RESPONSE",
|
58
|
+
OP_ALIVE_RESPONSE => "OP_ALIVE_RESPONSE",
|
59
|
+
OP_GENERAL_ERROR_RESPONSE => "OP_GENERAL_ERROR_RESPONSE",
|
60
|
+
OP_NACK => "",
|
61
|
+
}
|
62
|
+
return descs.has_key?(op_code) ? "(#{descs[op_code]})" : "(UNKNOWN)"
|
63
|
+
end
|
64
|
+
|
65
|
+
# P - PARAMETER
|
66
|
+
P_USER_IDENTITY = 10
|
67
|
+
P_PASSWORD = 11
|
68
|
+
P_SUBADDR = 12
|
69
|
+
P_WINDOW_SIZE = 19
|
70
|
+
P_DESTINATION_ADDRESS = 21
|
71
|
+
P_ORIGINATOR_ADDRESS = 23
|
72
|
+
P_ALPHA_ORIG_ADDRESS = 27
|
73
|
+
P_DATA_CODING_SCHEME = 30
|
74
|
+
P_USER_DATA_HEADER = 32
|
75
|
+
P_USER_DATA = 33
|
76
|
+
P_USER_DATA_BINARY = 34
|
77
|
+
P_PROTOCOL_IDENTIFIER = 52
|
78
|
+
P_SERVICE_CENTRE_TIME_STAMP = 60
|
79
|
+
P_ERROR_CODE = 900
|
80
|
+
P_ERROR_TEXT = 901
|
81
|
+
|
82
|
+
DEFAULT_WINDOW_SIZE = 1
|
83
|
+
DEFAULT_KEEP_ALIVE = 60
|
84
|
+
|
85
|
+
ALPHABET_DEFAULT = 0
|
86
|
+
ALPHABET_8BIT = 1
|
87
|
+
ALPHABET_UCS2 = 2
|
88
|
+
ALPHABET_RESERVED = 3
|
89
|
+
|
90
|
+
ALPHABET_BINARY = 8
|
91
|
+
end
|
data/lib/cimd_loop.rb
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'rubygems'
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'cimd'
|
5
|
+
|
6
|
+
module CIMD
|
7
|
+
|
8
|
+
class Loop < EventMachine::Connection
|
9
|
+
|
10
|
+
@@logout_request = false
|
11
|
+
|
12
|
+
STATE=[:not_connected,:connected,:banner_received,:ready_to_send,:suspend]
|
13
|
+
MAX_NO_ACTIVITY_TIME = 180
|
14
|
+
attr_accessor :state
|
15
|
+
attr_accessor :messages
|
16
|
+
attr_accessor :conn
|
17
|
+
attr_accessor :keep_alive_counter
|
18
|
+
attr_accessor :no_activity_counter
|
19
|
+
attr_accessor :options
|
20
|
+
attr_accessor :logfile
|
21
|
+
attr_accessor :debug
|
22
|
+
|
23
|
+
def to_log(message)
|
24
|
+
#puts @debug
|
25
|
+
#puts @logfile
|
26
|
+
puts "#{Time.now.strftime("%Y-%m-%d/%H:%M:%S")} #{message}"
|
27
|
+
#puts message if @debug
|
28
|
+
#@logfile.puts message if @logfile
|
29
|
+
$stdout.flush
|
30
|
+
end
|
31
|
+
|
32
|
+
def change_state(new_state)
|
33
|
+
if @state != new_state
|
34
|
+
to_log("#### Transition: #{@state.to_s} ==> #{new_state.to_s} (no_act:#{ Time.now.tv_sec - @no_activity_counter}, keep:#{Time.now.tv_sec - @keep_alive_counter}, queue:#{@messages.size})")
|
35
|
+
@state = new_state
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.logout_request
|
40
|
+
@@logout_request = true
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize
|
44
|
+
@state = :not_connected
|
45
|
+
@debug = false
|
46
|
+
@log = nil
|
47
|
+
@keep_alive_counter = Time.now.tv_sec
|
48
|
+
@no_activity_counter = Time.now.tv_sec
|
49
|
+
#@debug = true if @options[:debug]
|
50
|
+
#begin
|
51
|
+
# @log = File.new("ss", "w") if options[:logfile]
|
52
|
+
#rescue Exception => e
|
53
|
+
# puts e.to_s
|
54
|
+
# exit
|
55
|
+
#end
|
56
|
+
end
|
57
|
+
|
58
|
+
def post_init
|
59
|
+
|
60
|
+
@timer = EM.add_periodic_timer(1) do
|
61
|
+
|
62
|
+
if @@logout_request == true
|
63
|
+
change_state(:logout_request)
|
64
|
+
@@logout_request = false
|
65
|
+
end
|
66
|
+
|
67
|
+
change_state(:alive) if Time.now.tv_sec - @keep_alive_counter > @conn.keep_alive
|
68
|
+
change_state(:no_activity) if Time.now.tv_sec - @no_activity_counter > MAX_NO_ACTIVITY_TIME
|
69
|
+
|
70
|
+
#puts "No act:#{ Time.now.tv_sec - @no_activity_counter} Keep:#{Time.now.tv_sec - @keep_alive_counter} Queue: #{@messages.size}"
|
71
|
+
case @state
|
72
|
+
when :banner_received
|
73
|
+
change_state(:login_request)
|
74
|
+
@messages.pop{ |message| sending_message(message)}
|
75
|
+
when :login_sucessfull
|
76
|
+
change_state(:ready_to_send)
|
77
|
+
when :ready_to_send
|
78
|
+
change_state(:suspend)
|
79
|
+
@messages.pop{ |message| sending_message(message)}
|
80
|
+
when :no_activity,:logout_done
|
81
|
+
close_connection
|
82
|
+
when :alive
|
83
|
+
change_state(:suspend)
|
84
|
+
to_log("<<<< #{CIMD::alive_message}")
|
85
|
+
sending_message(CIMD::alive_message)
|
86
|
+
when :logout_request
|
87
|
+
@messages = EM::Queue.new
|
88
|
+
to_log("<<<< #{CIMD::logout_message}")
|
89
|
+
messages.push(CIMD::logout_message);
|
90
|
+
change_state(:ready_to_send)
|
91
|
+
when :suspend
|
92
|
+
#puts "Suspend"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end # post_init
|
97
|
+
|
98
|
+
def sending_message(message)
|
99
|
+
message.packet_number = @conn.packet_number!
|
100
|
+
to_log("<<<< #{message.to_s}")
|
101
|
+
send_data message.to_binary
|
102
|
+
@keep_alive_counter = Time.now.tv_sec
|
103
|
+
end
|
104
|
+
|
105
|
+
def sending_response_message(message)
|
106
|
+
m = CIMD::only_response_message(message)
|
107
|
+
to_log("<<<< #{m.to_s}")
|
108
|
+
send_data m.to_binary
|
109
|
+
end
|
110
|
+
|
111
|
+
def connection_completed
|
112
|
+
change_state(:connected)
|
113
|
+
end
|
114
|
+
|
115
|
+
def receive_data(data)
|
116
|
+
#puts "Received plain data: #{data}"
|
117
|
+
|
118
|
+
case data
|
119
|
+
when /CIMD2-A/
|
120
|
+
change_state(:banner_received)
|
121
|
+
else
|
122
|
+
|
123
|
+
(@buffer ||= BufferedTokenizer.new("\003")).extract(data).each do |line|
|
124
|
+
message = Message.parse(line)
|
125
|
+
|
126
|
+
to_log(">>>> #{message.to_s}")
|
127
|
+
# sprawdzic checsum
|
128
|
+
if message.is_binary?
|
129
|
+
message.parse_binary_data
|
130
|
+
to_log("**** Decoded binary: #{message.to_s}")
|
131
|
+
end
|
132
|
+
@no_activity_counter = Time.now.tv_sec
|
133
|
+
|
134
|
+
case message.operation_code
|
135
|
+
when CIMD::OP_LOGIN_RESPONSE
|
136
|
+
if message.has_error?
|
137
|
+
to_log("!!!! Error: #{message.error}")
|
138
|
+
close_connection
|
139
|
+
else
|
140
|
+
change_state(:login_sucessfull)
|
141
|
+
end
|
142
|
+
when CIMD::OP_SUBMIT_RESPONSE
|
143
|
+
if message.has_error?
|
144
|
+
to_log("!!!! Error: #{message.error}")
|
145
|
+
end
|
146
|
+
change_state(:ready_to_send)
|
147
|
+
when CIMD::OP_DELIVERY_STATUS_REPORT
|
148
|
+
sending_response_message(message)
|
149
|
+
when CIMD::OP_DELIVERY_MESSAGE
|
150
|
+
sending_response_message(message)
|
151
|
+
messages.push(CIMD::submit_text_message(@conn,message.parameter_value(CIMD::P_ORIGINATOR_ADDRESS),message.parameter_value(CIMD::P_USER_DATA)))
|
152
|
+
when CIMD::OP_LOGOUT_RESPONSE
|
153
|
+
change_state(:logout_done)
|
154
|
+
when CIMD::OP_ALIVE_RESPONSE
|
155
|
+
when CIMD::OP_GENERAL_ERROR_RESPONSE
|
156
|
+
to_log("!!!! Error: #{message.error}")
|
157
|
+
close_connection
|
158
|
+
else
|
159
|
+
to_log("???? Unknown message type: #{data}")
|
160
|
+
end # case message.operation_code
|
161
|
+
end
|
162
|
+
end # case data
|
163
|
+
end # receive_data
|
164
|
+
|
165
|
+
def unbind
|
166
|
+
@logfile.close unless @logfile.nil?
|
167
|
+
change_state(:not_connected)
|
168
|
+
EventMachine.stop_event_loop
|
169
|
+
end
|
170
|
+
|
171
|
+
end # class Loop
|
172
|
+
|
173
|
+
end # module CIMD
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module CIMD
|
2
|
+
|
3
|
+
def self.login_message(connection)
|
4
|
+
m = Message.new(OP_LOGIN)
|
5
|
+
p_login = Parameter.new(P_USER_IDENTITY,connection.user_identity)
|
6
|
+
p_password = Parameter.new(P_PASSWORD,connection.password)
|
7
|
+
m.add(p_login)
|
8
|
+
m.add(p_password)
|
9
|
+
return m
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.logout_message
|
13
|
+
m = Message.new(OP_LOGOUT)
|
14
|
+
return m
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.submit_text_message(connection,msisdn,text)
|
18
|
+
m = Message.new(OP_SUBMIT)
|
19
|
+
p_msisdn = Parameter.new(P_DESTINATION_ADDRESS,msisdn)
|
20
|
+
p_text = Parameter.new(P_USER_DATA,text)
|
21
|
+
m.add(p_msisdn)
|
22
|
+
m.add(p_text)
|
23
|
+
unless connection.alpha_orig_address.nil?
|
24
|
+
p_orig = Parameter.new(P_ALPHA_ORIG_ADDRESS,connection.alpha_orig_address)
|
25
|
+
m.add(p_orig)
|
26
|
+
end
|
27
|
+
return m
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.submit_binary_message(connection,msisdn,binary_text)
|
31
|
+
m = Message.new(OP_SUBMIT)
|
32
|
+
p_msisdn = Parameter.new(P_DESTINATION_ADDRESS,msisdn)
|
33
|
+
p_text = Parameter.new(P_USER_DATA_BINARY,binary_text)
|
34
|
+
p_dcs = Parameter.new(P_DATA_CODING_SCHEME,ALPHABET_BINARY)
|
35
|
+
m.add(p_msisdn)
|
36
|
+
m.add(p_text)
|
37
|
+
m.add(p_dcs)
|
38
|
+
unless connection.alpha_orig_address.nil?
|
39
|
+
p_orig = Parameter.new(P_ALPHA_ORIG_ADDRESS,connection.alpha_orig_address)
|
40
|
+
m.add(p_orig)
|
41
|
+
end
|
42
|
+
return m
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.only_response_message(message)
|
46
|
+
m = Message.new(message.operation_code + 50)
|
47
|
+
m.packet_number = message.packet_number
|
48
|
+
return m
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.alive_message
|
52
|
+
m = Message.new(OP_ALIVE)
|
53
|
+
return m
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
module CIMD
|
2
|
+
|
3
|
+
class Connection
|
4
|
+
|
5
|
+
attr_accessor :server
|
6
|
+
attr_accessor :port
|
7
|
+
attr_accessor :user_identity
|
8
|
+
attr_accessor :password
|
9
|
+
attr_accessor :keep_alive
|
10
|
+
attr_accessor :packet_number
|
11
|
+
attr_accessor :window_size
|
12
|
+
attr_accessor :alpha_orig_address
|
13
|
+
|
14
|
+
def initialize(server,port,user_identity,password,alpha_orig_address,window_size,keep_alive)
|
15
|
+
@server = server
|
16
|
+
@port = port
|
17
|
+
@user_identity = user_identity
|
18
|
+
@password = password
|
19
|
+
@keep_alive = keep_alive
|
20
|
+
@packet_number = 1
|
21
|
+
@alpha_orig_address = alpha_orig_address
|
22
|
+
@window_size = window_size
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
return sprintf "\n\n*** Connection object:\nServer: %s\n,Port: %s\n,User identity: %s\nPassword: %s\nKeep Alive: %3d\nAlpha Orig Address: %s\n Packet number: %d\n\n",@server,@port,@user_identity,@password,@keep_alive,@alpha_orig_address,@packet_number
|
27
|
+
end
|
28
|
+
|
29
|
+
def packet_number?
|
30
|
+
return @packet_number
|
31
|
+
end
|
32
|
+
|
33
|
+
def packet_number!
|
34
|
+
f = @packet_number
|
35
|
+
(@packet_number += 2) > 255 ? @packet_number = 1 : @packet_number
|
36
|
+
return f
|
37
|
+
end
|
38
|
+
|
39
|
+
end #connection
|
40
|
+
|
41
|
+
class Parameter
|
42
|
+
|
43
|
+
attr_accessor :code
|
44
|
+
attr_accessor :value
|
45
|
+
|
46
|
+
def initialize(code,value)
|
47
|
+
@code = code
|
48
|
+
@value = value
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
return sprintf "%03d:%s",@code,@value
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.parse(data)
|
56
|
+
fields = data.split(":")
|
57
|
+
p = Parameter.new((fields[0]).to_i,fields[1])
|
58
|
+
return p
|
59
|
+
end
|
60
|
+
|
61
|
+
end #parameter
|
62
|
+
|
63
|
+
class Dcs
|
64
|
+
|
65
|
+
attr_accessor :value
|
66
|
+
|
67
|
+
def initialize(value)
|
68
|
+
@value = value
|
69
|
+
end
|
70
|
+
|
71
|
+
def set_value(value)
|
72
|
+
@value = value.to_i
|
73
|
+
end
|
74
|
+
|
75
|
+
def coding_group
|
76
|
+
return @value & 0xF0
|
77
|
+
end
|
78
|
+
|
79
|
+
def has_coding_group_zero?
|
80
|
+
(@value & 0b11000000).zero?
|
81
|
+
end
|
82
|
+
|
83
|
+
def has_default_alphabet?
|
84
|
+
value.zero?
|
85
|
+
end
|
86
|
+
|
87
|
+
def alphabet
|
88
|
+
if has_coding_group_zero?
|
89
|
+
return (@value & 0b00001100) >> 2
|
90
|
+
else
|
91
|
+
return 0
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def alphabet_set_UCS2
|
96
|
+
value = 8
|
97
|
+
end
|
98
|
+
|
99
|
+
end #dcs
|
100
|
+
|
101
|
+
class Message
|
102
|
+
|
103
|
+
attr_accessor :operation_code
|
104
|
+
attr_accessor :parameters
|
105
|
+
attr_accessor :packet_number
|
106
|
+
attr_accessor :checksum
|
107
|
+
attr_accessor :dcs
|
108
|
+
|
109
|
+
def initialize(operation_code)
|
110
|
+
@operation_code = operation_code
|
111
|
+
@packet_number = 1
|
112
|
+
@parameters = Array.new
|
113
|
+
@checksum = 0
|
114
|
+
@dcs = Dcs.new(0)
|
115
|
+
end
|
116
|
+
|
117
|
+
def alphabet
|
118
|
+
@dcs.alphabet
|
119
|
+
end
|
120
|
+
|
121
|
+
def has_alphabet_ucs2?
|
122
|
+
@dcs.alphabet == ALPHABET_UCS2
|
123
|
+
end
|
124
|
+
|
125
|
+
def has_error?
|
126
|
+
return has_parameter?(P_ERROR_CODE) ? true : false
|
127
|
+
end
|
128
|
+
|
129
|
+
def error
|
130
|
+
return has_error? ? "(#{parameter_value(CIMD::P_ERROR_CODE)}) #{parameter_value(CIMD::P_ERROR_TEXT)}" : nil
|
131
|
+
end
|
132
|
+
|
133
|
+
def calc_checksum
|
134
|
+
checksum = 0
|
135
|
+
s = String.new
|
136
|
+
s << STX
|
137
|
+
s << (sprintf "%02d:%03d",@operation_code,@packet_number)
|
138
|
+
s << TAB
|
139
|
+
@parameters.each do |p|
|
140
|
+
s << p.to_s
|
141
|
+
s << TAB
|
142
|
+
end
|
143
|
+
|
144
|
+
s.each_byte do |b|
|
145
|
+
checksum += b
|
146
|
+
checksum &= 0xFF
|
147
|
+
end
|
148
|
+
return checksum
|
149
|
+
end
|
150
|
+
|
151
|
+
def add(parameter)
|
152
|
+
@parameters.push(parameter)
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_s
|
156
|
+
s = sprintf "<STX>%02d:%03d<TAB>",@operation_code,@packet_number
|
157
|
+
#add(Parameter.new(P_DATA_CODING_SCHEME,@dcs.value)) @operation_code == OP_SUBMIT
|
158
|
+
@parameters.each do |p|
|
159
|
+
s << p.to_s
|
160
|
+
s << "<TAB>"
|
161
|
+
end
|
162
|
+
s << (sprintf "%02x",@checksum).upcase
|
163
|
+
s << "<ETX> "
|
164
|
+
s << CIMD::opcode_description(@operation_code)
|
165
|
+
return s
|
166
|
+
end
|
167
|
+
|
168
|
+
def to_binary
|
169
|
+
s = String.new
|
170
|
+
s << STX
|
171
|
+
s << (sprintf "%02d:%03d",@operation_code,@packet_number)
|
172
|
+
s << TAB
|
173
|
+
#add(Parameter.new(P_DATA_CODING_SCHEME,@dcs.value)) if @operation_code == OP_SUBMIT
|
174
|
+
@parameters.each do |p|
|
175
|
+
s << p.to_s
|
176
|
+
s << TAB
|
177
|
+
end
|
178
|
+
s << (sprintf "%02x",calc_checksum)
|
179
|
+
s << ETX
|
180
|
+
return s
|
181
|
+
end
|
182
|
+
|
183
|
+
def is_binary?
|
184
|
+
has_parameter?(P_USER_DATA_BINARY)
|
185
|
+
end
|
186
|
+
|
187
|
+
def self.parse(data)
|
188
|
+
data.slice!(0)
|
189
|
+
fields = data.split(TAB)
|
190
|
+
header = fields[0].split(PARAM_SEP)
|
191
|
+
operation_code = header[0].to_i
|
192
|
+
m = Message.new(operation_code)
|
193
|
+
m.packet_number = header[1].to_i
|
194
|
+
fields.delete_at(0)
|
195
|
+
m.checksum = (fields.delete_at(fields.size - 1)).hex.to_i
|
196
|
+
fields.each do |p|
|
197
|
+
m.parameters << Parameter.parse(p)
|
198
|
+
end
|
199
|
+
m.dcs.set_value(m.parameter_value(P_DATA_CODING_SCHEME)) if m.has_parameter?(P_DATA_CODING_SCHEME)
|
200
|
+
return m
|
201
|
+
end
|
202
|
+
|
203
|
+
def parse_binary_data
|
204
|
+
if has_alphabet_ucs2? and @operation_code == OP_DELIVERY_MESSAGE
|
205
|
+
data = parameter_value(P_USER_DATA_BINARY)
|
206
|
+
i = 0
|
207
|
+
s = ""
|
208
|
+
while i < data.length do
|
209
|
+
s << data[i,2].hex
|
210
|
+
i += 2
|
211
|
+
end
|
212
|
+
p = Parameter.new(P_USER_DATA,Iconv.iconv("UTF-8", "UCS-2BE",s).first)
|
213
|
+
add(p)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def has_parameter?(code)
|
218
|
+
@parameters.each do |p|
|
219
|
+
return true if p.code == code
|
220
|
+
end
|
221
|
+
return false
|
222
|
+
end
|
223
|
+
|
224
|
+
def parameter_value(code)
|
225
|
+
@parameters.each do |p|
|
226
|
+
return p.value if p.code == code
|
227
|
+
end
|
228
|
+
return nil
|
229
|
+
end
|
230
|
+
|
231
|
+
end # message
|
232
|
+
|
233
|
+
end # CIMD
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'cimd'
|
2
|
+
require 'iconv'
|
3
|
+
|
4
|
+
describe CIMD do
|
5
|
+
|
6
|
+
it "has constants" do
|
7
|
+
CIMD::OP_LOGIN.should == 1
|
8
|
+
CIMD::OP_LOGOUT.should == 2
|
9
|
+
CIMD::OP_SUBMIT.should == 3
|
10
|
+
CIMD::ALPHABET_BINARY.should == 8
|
11
|
+
end
|
12
|
+
|
13
|
+
context CIMD::Connection do
|
14
|
+
|
15
|
+
let(:cn) { CIMD::Connection.new('server',1234,'user1','password1',nil,1,120) }
|
16
|
+
let(:c) { CIMD::Connection.new('server',1234,'user1','password1','alpha',1,120) }
|
17
|
+
|
18
|
+
it "returns connection object with nil alpha orig number" do
|
19
|
+
cn.user_identity.should eq('user1')
|
20
|
+
cn.password.should eq('password1')
|
21
|
+
cn.server.should eq('server')
|
22
|
+
cn.port.should eq(1234)
|
23
|
+
cn.alpha_orig_address.should be_nil
|
24
|
+
cn.window_size.should eq(1)
|
25
|
+
cn.keep_alive.should eq(120)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns connection object with not nil alpha orig number" do
|
29
|
+
c.user_identity.should eq('user1')
|
30
|
+
c.password.should eq('password1')
|
31
|
+
c.alpha_orig_address.should eq('alpha')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "returns first packet number" do
|
35
|
+
c.packet_number?.should eq(1)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns 10th packet number" do
|
39
|
+
10.times { c.packet_number! }
|
40
|
+
c.packet_number?.should eq(21)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns 130th packet number" do
|
44
|
+
130.times { c.packet_number! }
|
45
|
+
c.packet_number?.should eq(5)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "opcode description" do
|
49
|
+
CIMD::opcode_description("as").should eq("(UNKNOWN)")
|
50
|
+
CIMD::opcode_description(CIMD::OP_LOGIN).should eq("(OP_LOGIN)")
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end # context CIMD::Connection
|
55
|
+
|
56
|
+
context CIMD::Message do
|
57
|
+
|
58
|
+
let(:cn) { CIMD::Connection.new('server',1234,'user1','password1',nil,1,120) }
|
59
|
+
let(:c) { CIMD::Connection.new('server',1234,'user1','password1','alpha',1,120) }
|
60
|
+
let(:lm) { CIMD::login_message(cn) }
|
61
|
+
let(:lo) { CIMD::logout_message }
|
62
|
+
let(:submitn) { CIMD::submit_text_message(cn,'1234567789','textn') }
|
63
|
+
let(:submit) {CIMD::submit_text_message(c,'1234567789','text') }
|
64
|
+
|
65
|
+
it "returns login message" do
|
66
|
+
lm.has_parameter?(CIMD::P_USER_IDENTITY).should be_true
|
67
|
+
lm.has_parameter?(CIMD::P_PASSWORD).should be_true
|
68
|
+
lm.parameter_value(CIMD::P_USER_IDENTITY).should eq('user1')
|
69
|
+
lm.parameter_value(CIMD::P_PASSWORD).should eq('password1')
|
70
|
+
lm.has_parameter?(CIMD::P_DESTINATION_ADDRESS).should be_false
|
71
|
+
lm.parameter_value(CIMD::P_DESTINATION_ADDRESS).should be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns logout message" do
|
75
|
+
lo.parameters.size.should eq(0)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "to_s" do
|
79
|
+
submit.to_s.should eq("<STX>03:001<TAB>021:1234567789<TAB>033:text<TAB>027:alpha<TAB>00<ETX> (OP_SUBMIT)")
|
80
|
+
submitn.to_s.should eq("<STX>03:001<TAB>021:1234567789<TAB>033:textn<TAB>00<ETX> (OP_SUBMIT)")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "submit message with no alpha" do
|
84
|
+
#puts submitn
|
85
|
+
submitn.parameters.size.should eq(2)
|
86
|
+
submitn.has_parameter?(CIMD::P_ALPHA_ORIG_ADDRESS).should be_false
|
87
|
+
end
|
88
|
+
|
89
|
+
it "submit message with alpha" do
|
90
|
+
#puts submit
|
91
|
+
submit.parameters.size.should eq(3)
|
92
|
+
submit.has_parameter?(CIMD::P_ALPHA_ORIG_ADDRESS).should be_true
|
93
|
+
submit.parameter_value(CIMD::P_ALPHA_ORIG_ADDRESS).should eq('alpha')
|
94
|
+
end
|
95
|
+
|
96
|
+
it "return confirmation frame" do
|
97
|
+
submit.packet_number = 5
|
98
|
+
m = CIMD::only_response_message(submit)
|
99
|
+
m.packet_number.should eq(submit.packet_number)
|
100
|
+
m.operation_code.should eq(submit.operation_code+50)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "inserts packet number to message" do
|
104
|
+
10.times { c.packet_number! }
|
105
|
+
submit.packet_number = c.packet_number!
|
106
|
+
submit.packet_number.should eq(21)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "calculates checksum test" do
|
110
|
+
m = CIMD::Message.new(CIMD::OP_GENERAL_ERROR_RESPONSE)
|
111
|
+
m.packet_number = 1
|
112
|
+
m.add(CIMD::Parameter.new(CIMD::P_ERROR_CODE,'2'))
|
113
|
+
m.add(CIMD::Parameter.new(CIMD::P_ERROR_TEXT,'Syntax error'))
|
114
|
+
sprintf("%02x",m.calc_checksum).upcase.should eq('03')
|
115
|
+
end
|
116
|
+
|
117
|
+
it "parses message" do
|
118
|
+
s = ""
|
119
|
+
s << CIMD::STX
|
120
|
+
s << (sprintf("%02d:%03d\t",1,23))
|
121
|
+
s << (sprintf("%03d:%s\t",11,'admin1'))
|
122
|
+
s << (sprintf("%03d:%s\t",10,'jan'))
|
123
|
+
s << "57"
|
124
|
+
s << CIMD::ETX
|
125
|
+
m = CIMD::Message.parse(s)
|
126
|
+
m.operation_code.should eq(1)
|
127
|
+
m.packet_number.should eq(23)
|
128
|
+
m.parameter_value(CIMD::P_USER_IDENTITY).should eq('jan')
|
129
|
+
m.parameter_value(CIMD::P_PASSWORD).should eq('admin1')
|
130
|
+
sprintf("%02x",m.calc_checksum).upcase.should eq('57')
|
131
|
+
end
|
132
|
+
|
133
|
+
it "parses binary message" do
|
134
|
+
s ="\00220:000\t021:48661001723\t023:48601130651\t060:120210100902\t034:0044006600760067006700720067006200760142006400660076007600660105\t052:0\t030:8\t1A\003"
|
135
|
+
m = CIMD::Message.parse(s)
|
136
|
+
sprintf("%02x",m.calc_checksum).upcase.should eq('1A')
|
137
|
+
m.is_binary?.should be_true
|
138
|
+
m.dcs.coding_group.should be_zero
|
139
|
+
m.dcs.has_coding_group_zero?.should be_true
|
140
|
+
m.alphabet.should eq(2)
|
141
|
+
m.has_alphabet_ucs2?.should be_true
|
142
|
+
m.parse_binary_data
|
143
|
+
m.parameter_value(CIMD::P_USER_DATA).should match(/^D/)
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
#context CIMD::Loop do
|
149
|
+
#let(:loop) { CIMD::Loop.new({}) }
|
150
|
+
|
151
|
+
#it ("create new loop instance") do
|
152
|
+
#puts loop
|
153
|
+
#end
|
154
|
+
|
155
|
+
#end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cimd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Wojciech Todryk
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: eventmachine
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.12'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.12'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: thor
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: guard
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '1.3'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1.3'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: guard-rspec
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '1.2'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '1.2'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rb-inotify
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.8.8
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.8.8
|
126
|
+
description: Utils for CIMD protocol
|
127
|
+
email:
|
128
|
+
- wojciech@todryk.pl
|
129
|
+
executables:
|
130
|
+
- cimd_cli.rb
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- .travis.yml
|
135
|
+
- Gemfile
|
136
|
+
- Gemfile.lock
|
137
|
+
- Guardfile
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- bin/cimd_cli.rb
|
141
|
+
- cimd.gemspec
|
142
|
+
- lib/cimd.rb
|
143
|
+
- lib/cimd/version.rb
|
144
|
+
- lib/cimd_constants.rb
|
145
|
+
- lib/cimd_loop.rb
|
146
|
+
- lib/cimd_messages.rb
|
147
|
+
- lib/cimd_structures.rb
|
148
|
+
- spec/lib/cimd_spec.rb
|
149
|
+
homepage: http://todryk.pl/cimd
|
150
|
+
licenses: []
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
none: false
|
157
|
+
requirements:
|
158
|
+
- - ! '>='
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
none: false
|
163
|
+
requirements:
|
164
|
+
- - ! '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
requirements: []
|
168
|
+
rubyforge_project: cimd
|
169
|
+
rubygems_version: 1.8.24
|
170
|
+
signing_key:
|
171
|
+
specification_version: 3
|
172
|
+
summary: Utils for CIMD protocol
|
173
|
+
test_files:
|
174
|
+
- spec/lib/cimd_spec.rb
|