knot-ruby 0.2.0 → 0.3.0

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.
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.