ramp 0.1.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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/lib/ramp/command.rb +192 -0
- data/lib/ramp/fields.rb +54 -0
- data/lib/ramp/version.rb +3 -0
- data/lib/ramp.rb +120 -0
- data/ramp.gemspec +17 -0
- metadata +56 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Sameer Rahmani
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Ramp
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ramp'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ramp
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/ramp/command.rb
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
# RAMP - AMP protocol client implementation in Ruby
|
3
|
+
# Copyright (C) 2012 Yellowen
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 2 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License along
|
16
|
+
# with this program; if not, write to the Free Software Foundation, Inc.,
|
17
|
+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
18
|
+
# -----------------------------------------------------------------------------
|
19
|
+
|
20
|
+
module Ramp
|
21
|
+
|
22
|
+
class Command
|
23
|
+
|
24
|
+
# EignClass -------------------------------------
|
25
|
+
class << self
|
26
|
+
|
27
|
+
attr_accessor :arguments_hash, :responses_hash, :command_name
|
28
|
+
|
29
|
+
def arguments args
|
30
|
+
@arguments_hash = args
|
31
|
+
end
|
32
|
+
|
33
|
+
def responses args
|
34
|
+
@responses_hash = args
|
35
|
+
end
|
36
|
+
|
37
|
+
def command name
|
38
|
+
@command_name = name
|
39
|
+
end
|
40
|
+
|
41
|
+
def loads(data)
|
42
|
+
# Construct a hash from given data and return it
|
43
|
+
buffer = data.to_s.bytes.to_a
|
44
|
+
pos = 0
|
45
|
+
result = {}
|
46
|
+
|
47
|
+
while 1 do
|
48
|
+
|
49
|
+
# Parse the next key length
|
50
|
+
key_length = 0
|
51
|
+
buffer[pos..pos + 1].each {|x| key_length += x}
|
52
|
+
|
53
|
+
if key_length > 255
|
54
|
+
raise TypeError, "malform packet."
|
55
|
+
end
|
56
|
+
|
57
|
+
if key_length == 0
|
58
|
+
# key length of 0 means end of package.
|
59
|
+
break
|
60
|
+
end
|
61
|
+
|
62
|
+
pos += 2
|
63
|
+
# Read the key
|
64
|
+
key = buffer[pos..pos + key_length - 1].pack("c*")
|
65
|
+
|
66
|
+
# Parse next value length
|
67
|
+
pos += key_length
|
68
|
+
value_length = 0
|
69
|
+
buffer[pos..pos + 1].each {|x| value_length += x}
|
70
|
+
|
71
|
+
# Read the value
|
72
|
+
pos += 2
|
73
|
+
value = buffer[pos..pos + value_length - 1].pack("c*")
|
74
|
+
pos += value_length
|
75
|
+
result[key.to_sym] = value
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
result
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Public -------------------------------------
|
84
|
+
|
85
|
+
# A Class variable (static attribute) to hold the asks sequences
|
86
|
+
@@ask_seqs = []
|
87
|
+
|
88
|
+
attr_reader :values
|
89
|
+
|
90
|
+
def initialize (args)
|
91
|
+
# Initialize an object with provided values for fields defined in
|
92
|
+
# @arguments using argument class method
|
93
|
+
@values = {}
|
94
|
+
@buffer = []
|
95
|
+
|
96
|
+
@_args = args
|
97
|
+
|
98
|
+
kwargs = Hash[args.map{|k, v|[k.to_sym, v]}]
|
99
|
+
if kwargs.include? :_ask or kwargs.include? :_command
|
100
|
+
raise ArgumentError, "':_ask' and ':_command' should not be in arguments"
|
101
|
+
end
|
102
|
+
|
103
|
+
kwargs.each do |key, value|
|
104
|
+
|
105
|
+
# Check for key validation
|
106
|
+
if not self.class.arguments_hash.include? key
|
107
|
+
raise ArgumentError, "'#{key}' is not defined in '#{self.class}'."
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
# Construct the values ivar
|
112
|
+
@values[key.to_sym] = self.class.arguments_hash[key.to_sym].new value
|
113
|
+
end
|
114
|
+
|
115
|
+
# Build a AMP packet data from kwargs hash for more information about
|
116
|
+
# amp protocol structure take a look at:
|
117
|
+
# http://www.amp-protocol.net
|
118
|
+
|
119
|
+
@values[:_command] = self.class.command_name
|
120
|
+
|
121
|
+
while 1 do
|
122
|
+
# TODO: is it safe in logic ?
|
123
|
+
ask = rand(999999)
|
124
|
+
if not @@ask_seqs.include? ask
|
125
|
+
@@ask_seqs << ask
|
126
|
+
break
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
@values[:_ask] = ask
|
131
|
+
# Generate the packet data and store it into @buffer
|
132
|
+
generate_packet
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
def to_s
|
138
|
+
|
139
|
+
@buffer.pack("c*")
|
140
|
+
end
|
141
|
+
|
142
|
+
def to_a
|
143
|
+
@buffer
|
144
|
+
end
|
145
|
+
|
146
|
+
def ask
|
147
|
+
@values[:_ask]
|
148
|
+
end
|
149
|
+
|
150
|
+
def dup
|
151
|
+
self.class.new @_args
|
152
|
+
end
|
153
|
+
|
154
|
+
def callback (*)
|
155
|
+
# Each subclass may override this method to have a callback
|
156
|
+
# when any answer recieved.
|
157
|
+
nil
|
158
|
+
end
|
159
|
+
|
160
|
+
# Exceptions ------------------------------------------------
|
161
|
+
class KeyLenError < StandardError
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
# Private definations ---------------------------------------
|
166
|
+
def split_bytes (hex)
|
167
|
+
hex.each_char.each_slice(2).map {|x| x.join}
|
168
|
+
end
|
169
|
+
|
170
|
+
def generate_packet()
|
171
|
+
@values.each do |key, value|
|
172
|
+
|
173
|
+
if key.length > 255
|
174
|
+
raise KeyLenError, "AMP keys should have 255 byte max kength"
|
175
|
+
end
|
176
|
+
|
177
|
+
[0, key.to_s.bytes.to_a.length].each {|x| @buffer << x}
|
178
|
+
key.to_s.bytes.to_a.each {|x| @buffer << x}
|
179
|
+
|
180
|
+
value_lenght = split_bytes "%04x" % value.to_s.bytes.to_a.length.to_s(16)
|
181
|
+
@buffer << value_lenght[0].to_i
|
182
|
+
@buffer << value_lenght[1].to_i
|
183
|
+
|
184
|
+
|
185
|
+
value.to_s.bytes.to_a.each {|x| @buffer << x}
|
186
|
+
end
|
187
|
+
|
188
|
+
[0x00, 0x00].each {|x| @buffer << x}
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
end
|
data/lib/ramp/fields.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
# RAMP - AMP protocol client implementation in Ruby
|
3
|
+
# Copyright (C) 2012 Yellowen
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 2 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License along
|
16
|
+
# with this program; if not, write to the Free Software Foundation, Inc.,
|
17
|
+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
18
|
+
# -----------------------------------------------------------------------------
|
19
|
+
|
20
|
+
module Ramp
|
21
|
+
module Fields
|
22
|
+
|
23
|
+
class StringField < String
|
24
|
+
|
25
|
+
def self.to_o data
|
26
|
+
String.new data
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
class IntegerField < Integer
|
32
|
+
|
33
|
+
def self.to_o data
|
34
|
+
Integer.new data
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
class JsonField < Hash
|
40
|
+
|
41
|
+
require 'json'
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
JSON.dump(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.to_o data
|
48
|
+
JSON.load(data)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
data/lib/ramp/version.rb
ADDED
data/lib/ramp.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
# RAMP - AMP protocol client implementation in Ruby
|
3
|
+
# Copyright (C) 2012 Yellowen
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 2 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License along
|
16
|
+
# with this program; if not, write to the Free Software Foundation, Inc.,
|
17
|
+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
18
|
+
# -----------------------------------------------------------------------------
|
19
|
+
require 'socket'
|
20
|
+
|
21
|
+
require "ramp/version"
|
22
|
+
require "ramp/command.rb"
|
23
|
+
require "ramp/fields.rb"
|
24
|
+
|
25
|
+
|
26
|
+
module Ramp
|
27
|
+
# Ramp module
|
28
|
+
|
29
|
+
class AmpClient
|
30
|
+
# AmpClient class is responsble for establishing a connection to a AMPserver
|
31
|
+
|
32
|
+
@@sent_packets = Hash.new
|
33
|
+
|
34
|
+
def initialize (host, port, kwargs={secure: false,
|
35
|
+
ssl_key: nil,
|
36
|
+
ssl_cert:nil,
|
37
|
+
async: false})
|
38
|
+
|
39
|
+
@async = kwargs[:async]
|
40
|
+
@secure = kwargs[:secure]
|
41
|
+
@ssl_key = kwargs[:ssl_key]
|
42
|
+
@ssl_cert = kwargs[:ssl_cert]
|
43
|
+
|
44
|
+
@host = host
|
45
|
+
@port = port
|
46
|
+
|
47
|
+
make_connection
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
def call_remote(command, kwargs)
|
52
|
+
|
53
|
+
# Create a new command instance
|
54
|
+
obj = command.new kwargs
|
55
|
+
|
56
|
+
# Add the curretn command instance to the sent hash
|
57
|
+
@@sent_packets[obj.ask] = obj
|
58
|
+
|
59
|
+
if @async
|
60
|
+
t = Thread.new {
|
61
|
+
transfer obj.to_s
|
62
|
+
}
|
63
|
+
t.abort_on_exception = true
|
64
|
+
t.run
|
65
|
+
else
|
66
|
+
transfer obj.to_s
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
# Private members -----------------------------------
|
72
|
+
private
|
73
|
+
|
74
|
+
def make_connection
|
75
|
+
|
76
|
+
begin
|
77
|
+
socket = TCPSocket.new @host, @port
|
78
|
+
rescue Errno::ECONNREFUSED
|
79
|
+
abort("Connection Refused")
|
80
|
+
end
|
81
|
+
|
82
|
+
if @secure
|
83
|
+
ctx = OpenSSL::SSL::SSLContext.new()
|
84
|
+
ctx.cert = OpenSSL::X509::Certificate.new(File.open(@ssl_cert))
|
85
|
+
ctx.key = OpenSSL::PKey::RSA.new(File.open(@ssl_key))
|
86
|
+
ctx.ssl_version = :SSLv23
|
87
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
88
|
+
ssl_socket.sync_close = true
|
89
|
+
ssl_socket.connect
|
90
|
+
@socket = ssl_socket
|
91
|
+
return
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
@socket = socket
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
def transfer data
|
100
|
+
# send the encoded data across the net
|
101
|
+
@socket.syswrite(data)
|
102
|
+
# TODO: Should i specify a recieving limitation ?
|
103
|
+
rawdata = @socket.recv(1024)
|
104
|
+
data = Command::loads(rawdata)
|
105
|
+
|
106
|
+
if data.include? :_answer
|
107
|
+
if @@sent_packets.keys.include? data
|
108
|
+
@@sent_packets[data[:_answer]].callback(data)
|
109
|
+
end
|
110
|
+
elsif data.include? :_error
|
111
|
+
# Generate an exception from _error_code and rise it
|
112
|
+
exception = Object.const_set(data[:_error_code], Class.new(StandardError))
|
113
|
+
raise exception, data[:_error_description]
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
data/ramp.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/ramp/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Sameer Rahmani"]
|
6
|
+
gem.email = ["lxsameer@gnu.org"]
|
7
|
+
gem.description = %q{AMP protocol implementation in Ruby. For more information about AMP protocol take a look at http://amp-protocol.net/}
|
8
|
+
gem.summary = %q{AMP protocol implementation in Ruby}
|
9
|
+
gem.homepage = "http://ramp.yellowen.com/"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "ramp"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Ramp::VERSION
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ramp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sameer Rahmani
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-08 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: AMP protocol implementation in Ruby. For more information about AMP protocol
|
15
|
+
take a look at http://amp-protocol.net/
|
16
|
+
email:
|
17
|
+
- lxsameer@gnu.org
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- lib/ramp.rb
|
28
|
+
- lib/ramp/command.rb
|
29
|
+
- lib/ramp/fields.rb
|
30
|
+
- lib/ramp/version.rb
|
31
|
+
- ramp.gemspec
|
32
|
+
homepage: http://ramp.yellowen.com/
|
33
|
+
licenses: []
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.8.24
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: AMP protocol implementation in Ruby
|
56
|
+
test_files: []
|