rumid 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e1efccfe98577add2b171f4ebcec3e2cf24f6c95
4
+ data.tar.gz: 0b307b0dab72435318c1a26015250efb51d12507
5
+ SHA512:
6
+ metadata.gz: 64c0ec1eb478e5fcae6821323e86117b7845aeb8aace9c6eb490ffdaa80e1e621bd2ea2083750ff9b5c740b4cdb7729f726867a77b44d557db862c62e8f078cb
7
+ data.tar.gz: bbd454a5f9649ae771c6f3e1936fa73d2ce4ed4984dfaa191ad1b92f905ca5ba388bb986904a0ec19b0aba25f4c104880ea23b730ddd08c90dbfecfa8ab02617
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
@@ -0,0 +1,2 @@
1
+ --protected
2
+ --private
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in rumid.gemspec
6
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Dmitry Rubinstein
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.
@@ -0,0 +1,40 @@
1
+ # Rumid
2
+
3
+ Use this gem to create uniprotocol TCP server. You can implement any protocol - for example modbus, using this gem.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rumid'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rumid
18
+
19
+ ## Usage
20
+
21
+ To run server you should implement `Request`, `Server`, and then start the server.
22
+
23
+ ## Documentation
24
+
25
+ Buld docs by running
26
+
27
+ $ yardoc
28
+
29
+ Start yard server by executing
30
+
31
+ $ yard server
32
+
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it ( https://github.com/[my-github-username]/rumid/fork )
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create a new Pull Request
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+
13
+ require 'rake'
14
+ require 'rspec/core'
15
+ require 'rspec/core/rake_task'
16
+ RSpec::Core::RakeTask.new(:spec) do |spec|
17
+ spec.pattern = FileList['spec/**/*_spec.rb']
18
+ #begin
19
+ # require 'serialport'
20
+ #rescue LoadError => e
21
+ # spec.pattern.exclude("spec/rtu_client_spec.rb", "spec/rtu_server_spec.rb")
22
+ #end
23
+ end
24
+
25
+ task :default => :spec
26
+
27
+ task :pry do
28
+ sh "bundle exec pry -r .lib/rumid.rb"
29
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rumid/version'
4
+
5
+ require 'timeout'
6
+ require 'rumid/io'
7
+
8
+ require 'rumid/errors'
9
+
10
+ require 'gserver'
11
+ require 'rumid/server'
12
+ require 'rumid/request'
13
+
14
+ require 'rumid/tcp_server'
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ module Rumid
4
+ # Module represents errors occuring during protocol serving
5
+ module Errors
6
+
7
+ # Standart time-out error to fire on packet end
8
+ class EndPacketError < StandardError;end
9
+
10
+ # Standart error, representing that request is not valid for this protocol
11
+ class NotValidRequestError < StandardError;end
12
+
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ # Extending of standart IO class
4
+ class IO
5
+ include Timeout
6
+
7
+
8
+ # Reads the next "packet" from I/O stream. Packets are separated by time delay.
9
+ # @param time [Integer] time delay between packets in seconds.
10
+ # @example
11
+ # server.print "Foo"
12
+ # sleep 0.1
13
+ # server.print "Bar"
14
+ # sleep 0.1
15
+ # server.print "Foo"
16
+ # client.gett(0.1) #=> "Foo"
17
+ # client.gett(0.2) #=> "BarFoo"
18
+ # @return [String] recieved packet string
19
+ def gett(time)
20
+ raw = getc
21
+ loop {
22
+ begin
23
+ timeout(time){raw << getc}
24
+ rescue Timeout::Error
25
+ break
26
+ end
27
+ }
28
+ raw
29
+ end
30
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+
3
+ module Rumid
4
+
5
+ # Abstract class, representing Request. Should be extended to specify protocol.
6
+ # @abstract
7
+ # @example
8
+ # class Foo < Request
9
+ # read_wire do |io|
10
+ # io.readline
11
+ # end
12
+ #
13
+ # format_request do |raw|
14
+ # {route: raw[1], data: raw[2]}
15
+ # end
16
+ #
17
+ # validate_request do |raw|
18
+ # raw[4] != raw[5]
19
+ # end
20
+ #
21
+ # validate_request do |raw|
22
+ # raw[1]+raw[2] != raw[3]
23
+ # end
24
+ # end
25
+ class Request
26
+ include Errors
27
+ # Raw data from IO getter block
28
+ # @note Proc requires [IO]
29
+ @@wire_handler = nil
30
+ # Raw data to request hash parser.
31
+ # @note Proc requires [String] raw data
32
+ @@wire_parser = nil
33
+ # [Array(Proc)] validation procs array
34
+ # @note Proc requires [String] raw data
35
+ @@request_validators = []
36
+
37
+ # Initalize raw data from IO getter
38
+ # @param block [Proc] representing raw data from IO getter
39
+ # @note block requires requires [IO]
40
+ def self.read_wire(&block)
41
+ @@wire_handler = block
42
+ end
43
+
44
+ # Initialize raw data to request hash parser
45
+ # @param block [Proc] representing raw data to request hash parser
46
+ # @note block requires requires [String] raw data
47
+ def self.format_request(&block)
48
+ @@wire_parser = block
49
+ end
50
+
51
+ # Method gets only valid requests
52
+ # @param io [IO] representing raw data to request hash parser
53
+ # @note Typicaly you should not call this method
54
+ def get_request(io)
55
+ raw = @@wire_handler.call(io)
56
+ throw NotValidRequestError if @@request_validators.all?{|block| block.call(raw)}
57
+ @@wire_parser.call(raw)
58
+ end
59
+
60
+ # Initialize new request validator
61
+ # @param block [Proc] represent request validator
62
+ # @note Proc requires [Stirng] raw data
63
+ # @note Proc returns [Boolean] request validness
64
+ def self.validate_request(&block)
65
+ @@request_validators << block
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,118 @@
1
+ # encoding: utf-8
2
+
3
+ module Rumid
4
+
5
+ # Abstract class, representing Server. Should be extended to specify protocol.
6
+ # @abstract
7
+ # @example
8
+ # class Foo < Server
9
+ # handle_request_with(BarRequest)
10
+ #
11
+ # wrap_response do |response|
12
+ # "Responce is: #{responce[:route]}|#{responce[:data]}"
13
+ # end
14
+ #
15
+ # route "foo" do |request|
16
+ # {route: "foo", data: 1}
17
+ # end
18
+ #
19
+ # route "bar" do |request|
20
+ # {route: "bar", data: 2}
21
+ # end
22
+ # end
23
+ class Server
24
+ include Errors
25
+
26
+ # @!constant routes [{String=>Proc}] representing routes strings and procs to handle requests
27
+ # @see Server.route
28
+ @@routes = {}
29
+
30
+ # @!constant request_handler [Request] klass, backed to handle this protocol requests
31
+ # @see Rumid::Request
32
+ @@request_handler = nil
33
+
34
+ def initialize
35
+ @responsed = false
36
+ end
37
+
38
+
39
+ # Main server function. Do all work from getting raw request to sending raw response
40
+ # @note Typicaly you should not call this method
41
+ # @param io [IO] I/O stream for getting requests and sending responces
42
+ def serve(io)
43
+ @io = io
44
+ request_hash = get_request
45
+ route_handle(request_hash)
46
+ end
47
+
48
+ # @return [Hash] hash with Keys - routes, Values - Procs for handling requests
49
+ def self.show_routes
50
+ @@routes
51
+ end
52
+
53
+ private
54
+
55
+ # Method reading data from I/O stream
56
+ # @note Typicaly you should not call this method
57
+ def get_request
58
+ raise NotImplementedError, "Request handler is not initialized." if @@request_handler.nil?
59
+ @@request_handler.get_request(@io)
60
+ end
61
+
62
+ # Method which sends request direct roated handler
63
+ # @note Typicaly you should not call this method
64
+ # @param request_hash [{Symbol=>Proc}] request hash
65
+ def route_handle(request_hash)
66
+ @@routes.each do |route,method|
67
+ return response_with(@@response_wrapper.call(method.call(request_hash))) unless (route =~ request_hash[:route]).nil?
68
+ end
69
+ warn "This request doesn't match any route."
70
+ end
71
+
72
+
73
+ # Initialising new route
74
+ # @param route [String] representing route string
75
+ # @param block [Proc] representing route handler
76
+ # @example
77
+ # route "foo" do |request|
78
+ # {route: "foo", data: 1}
79
+ # end
80
+ # @note Proc requires [{Symbol=>String}] request hash
81
+ # @note Proc returns [{Symbol=>String}] response hash
82
+ def self.route(route, &block)
83
+ @@routes[Regexp.new(route)] = block
84
+ end
85
+
86
+ # Initializing how to pack responces to send back by protocol
87
+ # @param block [Proc] representing respose wrapper
88
+ # @example
89
+ # wrap_response do |response|
90
+ # "Responce is: #{responce[:route]}|#{responce[:data]}"
91
+ # end
92
+ # @note Proc requires [{Symbol=>String}] response hash
93
+ # @note Proc returns [String] raw packet
94
+ def self.wrap_response(&block)
95
+ @@response_wrapper = block
96
+ end
97
+
98
+ # Initializing [Request] class to handle requests
99
+ # @param request_handler_class [Class] klass representing Request specified by protocol
100
+ # @example
101
+ # handle_request_with FooRequest
102
+ # @note request_handler_class extends [Request]
103
+ def self.handle_request_with(request_handler_class)
104
+ @@request_handler = request_handler_class.new
105
+ end
106
+
107
+ # Method sending response. Checks response uniquness
108
+ # @param response [String] response raw string
109
+ def response_with(response)
110
+ if @responsed == true then
111
+ warn "Trying to response with:\n #{response}\nfor already responsed request!"
112
+ return
113
+ end
114
+ @io.write(response)
115
+ @responsed = true
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+
3
+ module Rumid
4
+ #Extended GServer, baked to work with Rumid::Server servers
5
+ class TcpServer < GServer
6
+ # @param port [Integer] port to be listened by the server
7
+ # @param protocol_server [Rumid::Server] klass the extended Server class
8
+ def initialize(port, protocol_server, *args)
9
+ super(port, *args)
10
+ @protocol_server = protocol_server
11
+ end
12
+
13
+
14
+ # Overriden Gserver#serve function.
15
+ # @note Typicaly you should not call this method
16
+ # @param session [IO] I/O stream from TCP connection
17
+ def serve(session)
18
+ loop{
19
+ begin
20
+ @protocol_server.new.serve(session)
21
+ rescue Rumid::Errors::NotValidRequestError
22
+ log "Error in validation occured!"
23
+ end
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module Rumid
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rumid/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "rumid"
9
+ spec.version = Rumid::VERSION
10
+ spec.authors = ["Dmitry Rubinstein"]
11
+ spec.email = ["rubinsteindb@gmail.com"]
12
+ spec.summary = %q{Uniprotocol TCP server.}
13
+ spec.description = %q{Gem for creating servers with any protocol over TCP.}
14
+ spec.homepage = "https://github.com/Virviil/rumid"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.6"
23
+ spec.add_development_dependency 'rake', '~> 0'
24
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rumid
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dmitry Rubinstein
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Gem for creating servers with any protocol over TCP.
42
+ email:
43
+ - rubinsteindb@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".yardopts"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - lib/rumid.rb
55
+ - lib/rumid/errors.rb
56
+ - lib/rumid/io.rb
57
+ - lib/rumid/request.rb
58
+ - lib/rumid/server.rb
59
+ - lib/rumid/tcp_server.rb
60
+ - lib/rumid/version.rb
61
+ - rumid.gemspec
62
+ homepage: https://github.com/Virviil/rumid
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.2.2
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: Uniprotocol TCP server.
86
+ test_files: []
87
+ has_rdoc: