knot-ruby 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 102f6dc54dc3b034d4b71e890c921cdd3067ef32999cf92e829b56e6cf661266
4
- data.tar.gz: 847a1e73410dd0dbe17793c7c2819e22879dfbe47f728ec0625e02b88dcb7c2a
3
+ metadata.gz: 955cc51d2b5bc2c9057fbac7501aa4cd4ddae6a41769a414d9f3dad99da233ec
4
+ data.tar.gz: 7e63b760071edf2236e09e2148a447d6f3a6ea11ddef129fc98e6160ea43217e
5
5
  SHA512:
6
- metadata.gz: e87bfff66910c223c3046dbc0ea63929d7c60d62434e06f1dccac5f2bca3ffc8b9e0652b32c1f4137ff6912cca50f26855dd989a64ec8f2a1c2f741f34307637
7
- data.tar.gz: bcd68e1fa196ec799970697180b2dd375c6816da752c721dab9b0bf4bb82405d5909f090f5f10185713ee4c28166af0a64f103ff926ede60a519fc41a13a2e6a
6
+ metadata.gz: 9c8056ca3f3f7f2b97eb2dbc57047f2d6222a76e2b1d1794a07b016037cb976e6c9d6510e236f26aeb6d9182d98a82ee27f141f5e7bd291ec2d0992847829b6f
7
+ data.tar.gz: 8f85e0815f1e6bbcc39c357be9ee3d3922201f9fa58aafa576e6d69db1dd8a2d18601d547db2299621fe2bd223745a91987fc6b8a986634e1ec63dd94b8c7811
@@ -127,37 +127,39 @@ class Knot::Conf
127
127
  self.commit
128
128
  end
129
129
 
130
- def parse_item k
131
- case k
130
+ def parse_item kv
131
+ case kv
132
132
  when Hash
133
- case k.keys.sort
134
- when %w[section], %w[id section], %w[item section], %w[id item section]
135
- k
133
+ r = {}
134
+ kv.each {|k,v| r[k.to_s.to_sym] = v }
135
+ case r.keys.sort
136
+ when %i[section], %i[id section], %i[item section], %i[id item section]
137
+ r
136
138
  else
137
- raise ArgumentError, "Invalid Item-format"
139
+ raise ArgumentError, "Invalid Item-format: #{k}"
138
140
  end
139
141
 
140
142
  when Array
141
- case k.length
142
- when 1 then {section: k[0]}
143
- when 2 then {section: k[0], item: k[1]}
144
- when 3 then {section: k[0], id: k[1], item: k[2]}
145
- else raise ArgumentError, "Invalid Item-format"
143
+ case kv.length
144
+ when 1 then {section: kv[0]}
145
+ when 2 then {section: kv[0], item: kv[1]}
146
+ when 3 then {section: kv[0], id: kv[1], item: kv[2]}
147
+ else raise ArgumentError, "Invalid Item-format: #{kv}"
146
148
  end
147
149
 
148
150
  when /\A
149
- (?<section> [a-z0-9_-]+ )
150
- (?: \[ (?<id> [a-z0-9_.-]+) \] )?
151
- (?: \. (?<item>[a-z0-9_-]+) )?
151
+ (?<section> [a-z0-9_-]+ )
152
+ (?: \[ (?<id> [a-z0-9_.-]+) \] )?
153
+ (?: \. (?<item>[a-z0-9_-]+) )?
152
154
  \z/xi
153
155
 
154
- $~.named_captures.delete_if {|_,v| v.nil? }
156
+ $~.named_captures.delete_if {|_,v| v.nil? }
155
157
 
156
158
  when nil
157
159
  {}
158
160
 
159
161
  else
160
- raise ArgumentError, "Invalid Item-format"
162
+ raise ArgumentError, "Invalid Item-format: #{kv}"
161
163
  end
162
164
  end
163
165
 
data/lib/knot/protocol.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'iounpack'
2
- require 'stringio'
2
+ require 'pathname'
3
+ require 'socket'
4
+ require 'logger'
3
5
  require_relative 'errors'
4
6
 
5
7
  module Knot
@@ -53,7 +55,7 @@ module Knot::Protocol::Type
53
55
  end
54
56
 
55
57
  #class Knot::KnotC
56
- # attr_accessor :debug, :binary
58
+ # attr_accessor :binary
57
59
  #
58
60
  # def initialize path = nil, binary: nil
59
61
  # @path = path
@@ -72,44 +74,100 @@ end
72
74
  # end
73
75
  #end
74
76
 
75
- module Knot::Protocol::Idx
76
- Idx = [
77
- :command, # 10, :CMD, # Control command name.
78
- :flags, # 11, :FLAGS, # Control command flags.
79
- :error, # 12, :ERROR, # Error message.
80
- :section, # 13, :SECTION, # Configuration section name.
81
- :item, # 14, :ITEM, # Configuration item name.
82
- :id, # 15, :ID, # Congiguration item identifier.
83
- :zone, # 16, :ZONE, # Zone name.
84
- :owner, # 17, :OWNER, # Zone record owner
85
- :ttl, # 18, :TTL, # Zone record TTL.
86
- :type, # 19, :TYPE, # Zone record type name.
87
- :data, # 1a, :DATA, # Configuration item/zone record data.
88
- :filter, # 1b, :FILTER, # An option or a filter for output data processing.
89
- ]
90
- Name = {}
91
- Code = {}
92
- Idx.each_with_index do |v, i|
93
- Code[0x10+i] = v
94
- Name[v] = i
77
+ class Knot::Protocol::Code
78
+ include Comparable
79
+ attr_reader :name, :code, :cname, :description
80
+
81
+ def initialize name, code, cname, description
82
+ raise ArgumentError, "Expecting Symbol for #{self.class.name} instead of: #{name.inspect}" unless Symbol === name
83
+ raise ArgumentError, "Expecting Integer for #{self.class.name} instead of: #{code.inspect}" unless Integer === code
84
+ @name, @code, @cname, @description = name, code, cname, description
85
+ freeze
86
+ end
87
+
88
+ def === x
89
+ case x
90
+ when self.class then @id == x.id
91
+ when Symbol then @name == x
92
+ when String then @name == x.to_sym
93
+ when Integer then @code == x
94
+ else nil
95
+ end
95
96
  end
96
- def self.[] k
97
+
98
+ def <=>( x) @id <=> x.id end
99
+ def to_s() @name.to_s end
100
+ def to_sym() @name end
101
+ def to_i() @code end
102
+ end
103
+
104
+ module Knot::Protocol::Codes
105
+ include Enumerable
106
+ def [] k
97
107
  case k
98
108
  when Symbol
99
- Name[k] or raise Knot::Errors::EINVAL, "Unknown Idx: #{k}"
109
+ self::Name[k] or raise Knot::Errors::EINVAL, "Unknown Codes: #{k}"
100
110
  when Integer
101
- Idx[k] or raise Knot::Errors::EINVAL, "Unknown Idx: #{k}"
111
+ self::Code[k] or raise Knot::Errors::EINVAL, "Unknown Codes: #{k}"
102
112
  else
103
- raise ArgumentError, "Unknown Idx-Type: #{k}"
113
+ raise ArgumentError, "Unknown Codes-Type: #{k}"
104
114
  end
105
115
  end
116
+
117
+ def each &exe
118
+ block_given? ? self::Codes.each( &exe) : self::Codes.to_enum( :each)
119
+ end
120
+ end
121
+
122
+ module Knot::Protocol::Idx
123
+ extend Knot::Protocol::Codes
124
+
125
+ Codes = [
126
+ Knot::Protocol::Code.new( :command, 0x10, :CMD, 'Control command name.'),
127
+ Knot::Protocol::Code.new( :flags, 0x11, :FLAGS, 'Control command flags.'),
128
+ Knot::Protocol::Code.new( :error, 0x12, :ERROR, 'Error message.'),
129
+ Knot::Protocol::Code.new( :section, 0x13, :SECTION, 'Configuration section name.'),
130
+ Knot::Protocol::Code.new( :item, 0x14, :ITEM, 'Configuration item name.'),
131
+ Knot::Protocol::Code.new( :id, 0x15, :ID, 'Congiguration item identifier.'),
132
+ Knot::Protocol::Code.new( :zone, 0x16, :ZONE, 'Zone name.'),
133
+ Knot::Protocol::Code.new( :owner, 0x17, :OWNER, 'Zone record owner'),
134
+ Knot::Protocol::Code.new( :ttl, 0x18, :TTL, 'Zone record TTL.'),
135
+ Knot::Protocol::Code.new( :type, 0x19, :TYPE, 'Zone record type name.'),
136
+ Knot::Protocol::Code.new( :data, 0x1a, :DATA, 'Configuration item/zone record data.'),
137
+ Knot::Protocol::Code.new( :filter, 0x1b, :FILTER, 'An option or a filter for output data processing.'),
138
+ ]
139
+ Name = {}
140
+ Code = {}
141
+
142
+ Codes.each do |id|
143
+ Code[id.to_i] = id
144
+ Name[id.to_sym] = id
145
+ end
146
+ end
147
+
148
+ module Knot::Protocol::Types
149
+ extend Knot::Protocol::Codes
150
+
151
+ Codes = [
152
+ Knot::Protocol::Code.new( :end, 0x00, :END, 'Type END.'),
153
+ Knot::Protocol::Code.new( :data, 0x01, :DATA, 'Type DATA.'),
154
+ Knot::Protocol::Code.new( :extra, 0x02, :EXTRA, 'Type EXTRA.'),
155
+ Knot::Protocol::Code.new( :block, 0x03, :BLOCK, 'Type BLOCK.'),
156
+ ]
157
+
158
+ Name = {}
159
+ Code = {}
160
+
161
+ Codes.each do |id|
162
+ Code[id.to_i] = id
163
+ Name[id.to_sym] = id
164
+ end
106
165
  end
107
166
 
108
167
  class Knot::Protocol
109
- attr_reader :sock, :conf, :zones
110
- attr_accessor :debug
168
+ attr_reader :sock, :conf, :zones, :logger
111
169
 
112
- def initialize path_or_sock = nil
170
+ def initialize path_or_sock = nil, logger: nil
113
171
  case path_or_sock
114
172
  when String, Pathname
115
173
  @sock = UNIXSocket.new path_or_sock.to_s
@@ -118,24 +176,32 @@ class Knot::Protocol
118
176
  when nil
119
177
  @sock = UNIXSocket.new '/run/knot/knot.sock'
120
178
  end
121
- @debug = false
179
+ @logger = logger || Logger.new(STDERR)
122
180
  @conf = Knot::Conf.new self
123
181
  @zones = Hash.new {|h, zone| h[zone] = Knot::Zone.new zone, self }
124
182
  end
125
183
 
126
184
  def snd sock: nil, **data
127
185
  rsock = sock || @sock
128
- s = ''
129
- sock = StringIO.new s
130
- sock.write [1].pack( 'c')
186
+ #s = ''.b
187
+ #sock = StringIO.new s
188
+ #sock.write [1].pack( 'c')
131
189
  data[:flags] ||= ''
132
- Idx::Idx.each_with_index do |n, i|
133
- v = data[n]&.to_s
134
- sock.write [0x10+i, v.size, v].pack( 'c na*') if v
190
+ ds =
191
+ Idx.
192
+ select {|n| data[n.to_sym] }.
193
+ map {|n| v = data[n.to_sym].to_s.b; [n.to_i, v.size, v ] }
194
+ s = [Types[:data].to_i, ds, Types[:block].to_i].flatten.pack( "c #{'c na*'*ds.length} c").b
195
+ #Idx.each do |n|
196
+ # v = data[n.to_sym]&.to_s&.b
197
+ # sock.write [n.to_i, v.size, v].pack( 'c na*') if v
198
+ #end
199
+ #sock.write [3].pack( 'c')
200
+ #sock.flush
201
+ if 0 >= @logger.sev_threshold
202
+ @logger.debug "send data #{data.inspect}"
203
+ @logger.debug "send raw #{s.inspect}"
135
204
  end
136
- sock.write [3].pack( 'c')
137
- sock.flush
138
- STDERR.puts( {data: data, _: s}.inspect) if @debug
139
205
  rsock.write s
140
206
  rsock.flush
141
207
  end
@@ -144,45 +210,48 @@ class Knot::Protocol
144
210
  attr_reader :str
145
211
 
146
212
  def initialize sock, str = nil
147
- @str, @sock = str || '', sock
213
+ @str, @sock = str || ''.b, sock
148
214
  end
149
215
 
150
216
  def unpack pattern
151
- IOUnpack.new(pattern).unpack self
217
+ IOUnpack.new( pattern).unpack self
152
218
  end
153
219
 
154
220
  def unpack1 pattern
155
- IOUnpack.new(pattern).unpack1 self
221
+ IOUnpack.new( pattern).unpack1 self
156
222
  end
157
223
 
158
224
  def read n
159
225
  s = @sock.read n
160
- @str.insert -1, s
161
- s
226
+ @str.insert -1, s unless s.nil?
227
+ s || ''
162
228
  end
163
229
  end
164
230
 
165
231
  def rcv sock: nil
166
232
  ret, r = [], nil
167
233
  sock = sock || @sock
168
- sock = RecordIO.new sock if @debug
234
+ sock = RecordIO.new sock if 0 >= @logger.sev_threshold
169
235
  loop do
170
236
  t = sock.unpack1 'c'
171
237
  case t
172
- when 0, 3
238
+ when Knot::Protocol::Types[:end], Knot::Protocol::Types[:block]
173
239
  return ret
174
- when 1, 2
240
+ when Knot::Protocol::Types[:data], Knot::Protocol::Types[:extra]
175
241
  type = t
176
242
  ret.push( r = {})
177
243
  else
178
244
  raise Knot::Errors::EINVAL, "Missing Type before: #{t}" if ret.empty?
179
- i = Idx::Idx[t - 0x10] or raise Knot::Errors::EINVAL, "Unknown index: #{t-0x10}"
245
+ i = Idx[t] or raise Knot::Errors::EINVAL, "Unknown index: #{t}"
180
246
  l = sock.unpack1 'n'
181
- r[i] = sock.read( l)
247
+ r[i.to_sym] = sock.read( l)
182
248
  end
183
249
  end
184
250
  ensure
185
- STDERR.puts( {rcvd: ret, read: sock.str}.inspect) if @debug
251
+ if RecordIO === sock
252
+ @logger.debug "rcvd raw #{sock.str.inspect}"
253
+ @logger.debug "rcvd data #{ret.inspect}"
254
+ end
186
255
  ret
187
256
  end
188
257
 
data/lib/knot/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Knot
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knot-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Knauf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-28 00:00:00.000000000 Z
11
+ date: 2022-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: iounpack
@@ -64,8 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
64
  - !ruby/object:Gem::Version
65
65
  version: '0'
66
66
  requirements: []
67
- rubyforge_project:
68
- rubygems_version: 2.7.6.2
67
+ rubygems_version: 3.2.5
69
68
  signing_key:
70
69
  specification_version: 4
71
70
  summary: Provides interface to knot-server.