cddl 0.8.1 → 0.8.12

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
- SHA1:
3
- metadata.gz: bc5efc3a37bc0a936d6e03eb4f7d689196758914
4
- data.tar.gz: 2ec4a61c192d6ec61ce94bbbcfa805693ef127fb
2
+ SHA256:
3
+ metadata.gz: 2ede21b4292e6f546745029c7a071eb1af1259366e676d90e19f400dfe089d7a
4
+ data.tar.gz: 57ed90f75d58941bd28c5afef7d5eb29eea5d5483a6a3b2c4fc65d49df0370aa
5
5
  SHA512:
6
- metadata.gz: e09a9a2e079f8eafa1c879ed3a2d5c30f5c507624dff1222f68bf54ee1e05b8d56e30060ee9e27da2124834158ec7f9d222fe61ebb92a251da1070fd0d966509
7
- data.tar.gz: 3f045307ce12737a799c238fb3eef169c9481b405d3f009af18aa6819ba12b86317e2473272685c244c278ea48f471b93c972411da7ba7610d8be3da1b36aab3
6
+ metadata.gz: 65de704e842bb6d48265e7024922edf0406d6cb521d2977b07db2926d396b8b2d6bdc103619d579b861cb53b8914b4383e25c2e610e86f7b4d88d89983a64dff
7
+ data.tar.gz: c0919845b3ee5bba3b2a5d77f9e182a4a9f1904f187843501abf29954d37033d62f1cfd50545865ba878c92583f26151f9024dc1093c0d4607442038b36008b0
data/bin/cddl CHANGED
@@ -7,13 +7,16 @@ require 'json'
7
7
 
8
8
  Encoding.default_external = "UTF-8" # wake up, smell the coffee
9
9
 
10
+ EX_USAGE = 64
11
+ EX_DATAERR = 65
12
+
10
13
  def usage
11
14
  warn "Usage:"
12
15
  warn "#$0 spec.cddl generate [n]"
13
16
  warn "#$0 spec.cddl json-generate [n]"
14
17
  warn "#$0 spec.cddl validate instance.cbor"
15
18
  warn "#$0 spec.cddl validate instance.json"
16
- exit 1
19
+ exit EX_USAGE
17
20
  end
18
21
 
19
22
  def read_arg(arg)
@@ -21,7 +24,7 @@ def read_arg(arg)
21
24
  STDIN.read
22
25
  else
23
26
  usage unless arg
24
- File.read(arg)
27
+ File.read(arg, mode: "rb")
25
28
  end
26
29
  end
27
30
 
@@ -86,10 +89,11 @@ begin
86
89
  # my_pp ann
87
90
  instance.cbor_add_annotations_from(ann) rescue nil
88
91
  my_diag(instance) if $annotate
92
+ exit 1 unless ann
89
93
  else
90
94
  usage
91
95
  end
92
96
  rescue CDDL::ParseError => e
93
97
  warn e.message
94
- exit 1
98
+ exit EX_DATAERR
95
99
  end
data/cddl.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.8.1'
3
+ s.version = '0.8.12'
4
4
  s.summary = "CDDL generator and validator."
5
5
  s.description = %{A parser, generator, and validator for CDDL}
6
6
  s.add_dependency('cbor-diag')
@@ -19,3 +19,4 @@ spec = Gem::Specification.new do |s|
19
19
  s.homepage = "http://github.com/cabo/cddl"
20
20
  s.license = 'MIT'
21
21
  end
22
+
data/data/cddl.abnf CHANGED
@@ -16,6 +16,7 @@ type1 = type2 [S (rangeop / annotator) S type2]
16
16
  / "#" "6" ["." uint] "(" S type S ")" ; note no space!
17
17
  / "#" DIGIT ["." uint] ; major/ai
18
18
  / "#" ; any
19
+ / "~" S typename [genericarg]
19
20
  / "{" S group S "}"
20
21
  / "[" S group S "]"
21
22
  / "&" S "(" S group S ")"
@@ -49,8 +50,10 @@ occur = [uint] "*" [uint]
49
50
  / "+"
50
51
  / "?"
51
52
 
52
- uint = ["0x" / "0b"] "0"
53
- / ["0x" / "0b"] DIGIT1 *DIGIT
53
+ uint = DIGIT1 *DIGIT
54
+ / "0x" 1*HEXDIG
55
+ / "0b" 1*BINDIG
56
+ / "0"
54
57
 
55
58
  value = number
56
59
  / text
@@ -77,6 +80,9 @@ ALPHA = %x41-5A / %x61-7A
77
80
  EALPHA = %x41-5A / %x61-7A / "@" / "_" / "$"
78
81
  DIGIT = %x30-39
79
82
  DIGIT1 = %x31-39
83
+ HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
84
+ BINDIG = %x30-31
85
+
80
86
  S = *WS
81
87
  WS = SP / NL
82
88
  SP = %x20
data/lib/cddl.rb CHANGED
@@ -4,6 +4,7 @@ require 'pathname'
4
4
  require 'cbor-pure' unless defined?(CBOR::Tagged)
5
5
  require 'regexp-examples'
6
6
  require 'colorize'
7
+ require 'base64'
7
8
 
8
9
  module CDDL
9
10
 
@@ -14,7 +15,7 @@ module CDDL
14
15
 
15
16
  MANY = Float::INFINITY
16
17
 
17
- MAX_RECURSE = 32 # XXX
18
+ MAX_RECURSE = 128 # XXX
18
19
 
19
20
  class ParseError < ArgumentError; end
20
21
 
@@ -319,7 +320,8 @@ module CDDL
319
320
  end
320
321
  when :member
321
322
  st = where[1]
322
- en = [where[2], [st, 4].max].min # truncate to 4 unless must be more
323
+ fudge = 4 * (1 - (@recursion / MAX_RECURSE.to_f))**3 # get less generate-happy with more recursion
324
+ en = [where[2], [st, fudge].max].min # truncate to fudge unless must be more
323
325
  st += rand(en + 1 - st) if en != st
324
326
  kr = where[3]
325
327
  vr = where[4]
@@ -327,8 +329,12 @@ module CDDL
327
329
  unless kr
328
330
  case vr[0]
329
331
  when :grpent
330
- fail "grpent in map #{vr.inspect}" unless vr.size == 2
331
- g = Array.new(st) { generate1(vr[1], true) }.flatten(1)
332
+ # fail "grpent in map #{vr.inspect}" unless vr.size == 2
333
+ g = Array.new(st) {
334
+ vr[1..-1].map{ |vrx|
335
+ generate1(vrx, true)
336
+ }.flatten(1)
337
+ }.flatten(1)
332
338
  # warn "GGG #{g.inspect}"
333
339
  return g
334
340
  when :grpchoice
@@ -348,7 +354,7 @@ module CDDL
348
354
  fail BackTrack.new("Need #{where[1]}..#{where[2]} of these: #{[kr, vr].inspect}") unless where[1] == 0
349
355
  []
350
356
  end
351
- when :text, :int, :float
357
+ when :text, :int, :float, :bytes
352
358
  where[1]
353
359
  when :range
354
360
  rand(where[1])
@@ -390,15 +396,19 @@ module CDDL
390
396
  case where[1]
391
397
  when :size
392
398
  should_be_int = generate1(control)
393
- unless (target == [:prim, 2] || target == [:prim, 0]) && Integer === should_be_int && should_be_int >= 0
399
+ unless (Array === target && target[0] == :prim && [0, 2, 3].include?(target[1])) && Integer === should_be_int && should_be_int >= 0
394
400
  fail "Don't know yet how to generate #{where}"
395
401
  end
396
402
  s = Random.new.bytes(should_be_int)
397
- if target == [:prim, 0]
403
+ case target[1]
404
+ when 0
398
405
  # silently restrict to what we can put into a uint
399
406
  s[0...8].bytes.inject(0) {|a, b| a << 8 | b }
400
- else
407
+ when 2
401
408
  s
409
+ when 3
410
+ Base64.urlsafe_encode64(s)[0...should_be_int]
411
+ # XXX generate word a la w = gen_word
402
412
  end
403
413
  when :bits
404
414
  set_of_bits = Array.new(10) { generate1(control) } # XXX: ten?
@@ -429,6 +439,8 @@ module CDDL
429
439
  $default_warned = true
430
440
  end
431
441
  generate1(target, inmap)
442
+ when :feature
443
+ generate1(target, inmap)
432
444
  when :eq
433
445
  content = generate1(control)
434
446
  if validate1(content, where)
@@ -517,7 +529,7 @@ module CDDL
517
529
  end
518
530
  end
519
531
 
520
- VALUE_TYPE = {text: String, int: Integer, float: Float}
532
+ VALUE_TYPE = {text: String, bytes: String, int: Integer, float: Float}
521
533
  SIMPLE_VALUE = {
522
534
  [:prim, 7, 20] => [true, false, :bool],
523
535
  [:prim, 7, 21] => [true, true, :bool],
@@ -525,7 +537,7 @@ module CDDL
525
537
  [:prim, 7, 23] => [true, :undefined, :undefined],
526
538
  }
527
539
 
528
- def extract_value(t)
540
+ def extract_value(t) # []
529
541
  if vt = VALUE_TYPE[t[0]]
530
542
  [true, t[1], vt]
531
543
  elsif v = SIMPLE_VALUE[t]
@@ -541,11 +553,17 @@ module CDDL
541
553
 
542
554
  def validate(d, warn=true)
543
555
  @recursion = 0
556
+ $features = Hash.new {|h, k| h[k] = {}}
544
557
  result = validate1a(d, rules)
545
- unless result
546
- if warn
558
+ if warn
559
+ if result
560
+ if $features != {}
561
+ warn "** Features potentially used: #{$features.map {|k, v| "#{k}: #{v.keys}"}.join(", ")}"
562
+ end
563
+ else
547
564
  warn "CDDL validation failure (#{result.inspect} for #{d.inspect}):"
548
565
  PP::pp(validate_diag, STDERR)
566
+ puts(validate_diag.cbor_diagnostic)
549
567
  end
550
568
  end
551
569
  result
@@ -660,7 +678,7 @@ module CDDL
660
678
  # this is mostly quadratic; let's do the linear thing if possible
661
679
  simple, simpleval = extract_value(k)
662
680
  if simple
663
- # puts "SIMPLE: #{d_check.inspect} #{simpleval}"
681
+ puts "SIMPLE: #{d_check.inspect} #{simpleval}" if ENV["CDDL_TRACE"]
664
682
  # add occurrence check; check that val is present in the first place
665
683
  actual = d.fetch(simpleval, :not_found)
666
684
  if actual == :not_found
@@ -672,7 +690,7 @@ module CDDL
672
690
  end
673
691
  end
674
692
  else
675
- # puts "COMPLEX: #{k.inspect} #{simple.inspect} #{simpleval.inspect}"
693
+ puts "COMPLEX: #{k.inspect} #{simple.inspect} #{simpleval.inspect}" if ENV["CDDL_TRACE"]
676
694
  keys = d_check.keys
677
695
  ta, keys = keys.partition{ |key| validate1(key, k)}
678
696
  # XXX check ta.size against s/e
@@ -735,9 +753,12 @@ module CDDL
735
753
  idx, ann = validate_forward(d, 0, where)
736
754
  ann if validate_result(idx == d.size) { "#{validate_diag.inspect} -- cannot complete (#{idx}, #{d.size}) array #{d} for #{where}" }
737
755
  end
738
- when :text, :int, :float
756
+ when :int, :float
739
757
  _, v = extract_value(where)
740
758
  [] if d == v
759
+ when :text, :bytes
760
+ _, v = extract_value(where)
761
+ [] if d == v && ((d.encoding == Encoding::BINARY) == (v.encoding == Encoding::BINARY))
741
762
  when :range
742
763
  [] if where[2] === d && where[1].include?(d)
743
764
  when :anno
@@ -783,6 +804,10 @@ module CDDL
783
804
  $default_warned = true
784
805
  end
785
806
  ann
807
+ when :feature
808
+ ok, v, vt = extract_value(control)
809
+ $features[v][d] = true
810
+ ann
786
811
  when :lt, :le, :gt, :ge, :eq, :ne
787
812
  op = OPERATORS[where[1]]
788
813
  ok, v, _vt = extract_value(control)
@@ -831,6 +856,14 @@ module CDDL
831
856
  when 3
832
857
  String === d && d.encoding != Encoding::BINARY # cheat
833
858
  when 6
859
+ if Integer === d
860
+ t = 2 # assuming only 2/3 match an Integer
861
+ if d < 0
862
+ d = ~d
863
+ t = 3
864
+ end
865
+ d = CBOR::Tagged.new(t, d == 0 ? "".b : d.digits(256).reverse!.pack("C*"))
866
+ end
834
867
  CBOR::Tagged === d && d.tag == where[2] && validate1a(d.data, where[3])
835
868
  when 7
836
869
  t, v = extract_value(where)
@@ -942,14 +975,34 @@ module CDDL
942
975
  def value(n)
943
976
  # cheat:
944
977
  # warn n
945
- val = eval(n.to_s)
946
- # warn val
947
- [case val
948
- when Integer; :int
949
- when Numeric; :float
950
- when String; :text
951
- else fail "huh? value #{val.inspect}"
952
- end, val]
978
+ s = n.to_s
979
+ if s[-1] == "'"
980
+ parts = s.split("'", 3)
981
+ if parts[2] != "" || parts[1] =~ /\\/
982
+ warn "*** Can't handle backslashes in #{s.inspect} yet"
983
+ end
984
+ [:bytes,
985
+ case parts[0]
986
+ when ""
987
+ parts[1].b
988
+ when "h"
989
+ parts[1].gsub(/\s/, "").chars.each_slice(2).map{ |x| Integer(x.join, 16).chr("BINARY") }.join.b
990
+ when "b64"
991
+ Base64.urlsafe_decode64(parts[1])
992
+ else
993
+ warn "*** Can't handle byte string type #{parts[0].inspect} yet"
994
+ end
995
+ ]
996
+ else
997
+ val = eval(n.to_s)
998
+ # warn val
999
+ case val
1000
+ when Integer; [:int, val]
1001
+ when Numeric; [:float, val]
1002
+ when String; [:text, val.force_encoding(Encoding::UTF_8)]
1003
+ else fail "huh? value #{val.inspect}"
1004
+ end
1005
+ end
953
1006
  end
954
1007
 
955
1008
  def workaround1(n)
@@ -988,7 +1041,7 @@ module CDDL
988
1041
  fail [n, n.children, mk, mk.children].inspect
989
1042
  end
990
1043
  name = bw.to_s
991
- [[:member, *occ, [:text, name], type(nt)]]
1044
+ [[:member, *occ, [:text, name.force_encoding(Encoding::UTF_8)], type(nt)]]
992
1045
  end
993
1046
  else
994
1047
  t = if nbw = nt.bareword
@@ -1000,8 +1053,8 @@ module CDDL
1000
1053
  else
1001
1054
  type(nt, true) # type can actually be a group here!
1002
1055
  end
1003
- # pp ["t is", t]
1004
- if t[0] == :grpent && (@insides.last != :array || occ == [1, 1])
1056
+ pp ["t is", t] if ENV["CDDL_TRACE"]
1057
+ if t[0] == :grpent && (occ == [1, 1])
1005
1058
  # go through the members here and multiply the occs
1006
1059
  t1 = t[1..-1].flatten(1)
1007
1060
  if t1[0] == :recurse_grpent
@@ -1116,7 +1169,7 @@ module CDDL
1116
1169
  end
1117
1170
  when :recurse_grpent # XXX we don't have the entry yet
1118
1171
  when :member
1119
- fail "map entry without member key given: #{member}" unless member[3] || member[4][0] == :grpent || member[4][0] == :grpchoice
1172
+ fail "map entry #{member.inspect} without member key given: #{member}" unless member[3] || member[4][0] == :grpent || member[4][0] == :grpchoice
1120
1173
  else
1121
1174
  fail ["type1 member", member].inspect unless member[0] == :member
1122
1175
  end
@@ -1126,7 +1179,7 @@ module CDDL
1126
1179
  BRACE = {"{" => :map, "[" => :array}
1127
1180
  RANGE_EXCLUDE_END = {".." => false, "..." => true}
1128
1181
  SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp, :cbor, :cborseq, :within, :and,
1129
- :default, :lt, :le, :gt, :ge, :eq, :ne]
1182
+ :default, :lt, :le, :gt, :ge, :eq, :ne, :feature]
1130
1183
 
1131
1184
  def type1(n, canbegroup = false)
1132
1185
  # puts "NVALUE #{n.value.inspect}"
@@ -1188,6 +1241,26 @@ module CDDL
1188
1241
  v
1189
1242
  }
1190
1243
  ]
1244
+ when /\A~/
1245
+ if tn = n.typename
1246
+ s = type_recall(tn.to_s, false, n.genericarg).flatten(1)
1247
+ else
1248
+ fail "No typename in unwrap #{n}"
1249
+ end
1250
+ if s[0] != :type1
1251
+ fail [:UNWRAPs0, s].inspect
1252
+ end
1253
+ case s[1]
1254
+ when :map, :array
1255
+ [:grpent, s[2..-1]]
1256
+ when :prim
1257
+ if s[2] != 6
1258
+ fail [:UNWRAPs2, s].inspect
1259
+ end
1260
+ s[4] # check :type1?
1261
+ else
1262
+ fail [:UNWRAPs1, s].inspect
1263
+ end
1191
1264
  else
1192
1265
  "unimplemented #{n}"
1193
1266
  end
data/test/test-cddl.rb CHANGED
@@ -59,9 +59,9 @@ class TestABNF < Test::Unit::TestCase
59
59
 
60
60
  def test_generate_hex_bin
61
61
  parser = CDDL::Parser.new <<HERE
62
- test = [0x4711, 0b1011001110001111000]
62
+ test = [0x4711, 0xabcDEF, 0b1011001110001111000]
63
63
  HERE
64
- assert_equal [0x4711, 0b1011001110001111000], parser.generate
64
+ assert_equal [0x4711, 0xabcDEF, 0b1011001110001111000], parser.generate
65
65
  end
66
66
 
67
67
  def test_generate_le
@@ -171,6 +171,57 @@ HERE
171
171
  assert parser.validate_for_test(true)
172
172
  end
173
173
 
174
+ def test_validate_bignum
175
+ parser = CDDL::Parser.new <<HERE
176
+ test = bigint
177
+ HERE
178
+ assert parser.validate_for_test(2**4711)
179
+ assert parser.validate_for_test(-2**815)
180
+ assert parser.validate_for_test(1)
181
+ assert parser.validate_for_test(0)
182
+ assert parser.validate_for_test(-11)
183
+ end
184
+
185
+ def test_aaaaaaaa_invalidate_bignum
186
+ parser = CDDL::Parser.new <<HERE
187
+ test = bignint
188
+ HERE
189
+ refute parser.validate_for_test(2**4711, false)
190
+ assert parser.validate_for_test(-2**815)
191
+ refute parser.validate_for_test(1, false)
192
+ refute parser.validate_for_test(0, false)
193
+ assert parser.validate_for_test(-11)
194
+ end
195
+
196
+
197
+ def test_aaaaaaaa_validate_bignum0b
198
+ parser = CDDL::Parser.new <<HERE
199
+ test = #6.2("")
200
+ HERE
201
+ refute parser.validate_for_test(1, false)
202
+ refute parser.validate_for_test(0, false)
203
+ end
204
+
205
+
206
+ def test_aaaaaaaa_validate_bignum0
207
+ parser = CDDL::Parser.new <<HERE
208
+ test = #6.2(h'')
209
+ HERE
210
+ assert parser.validate_for_test(0)
211
+ refute parser.validate_for_test(1, false)
212
+ end
213
+
214
+
215
+ def test_aaaaaaaa_validate_bignum1
216
+ parser = CDDL::Parser.new <<HERE
217
+ test = #6.2(h'01')
218
+ HERE
219
+ assert parser.validate_for_test(1)
220
+ refute parser.validate_for_test(0, false)
221
+ refute parser.validate_for_test(2, false)
222
+ end
223
+
224
+
174
225
  def test_validate_a
175
226
  parser = CDDL::Parser.new <<HERE
176
227
  test = [* one: 1]
@@ -202,6 +253,54 @@ HERE
202
253
  assert parser.validate_for_test({"one" => 1, "two" => 1}, false)
203
254
  end
204
255
 
256
+ def test_validate_a_nontrivial_group_map
257
+ parser = CDDL::Parser.new <<HERE
258
+ test = {* (text => 1, text => 2)}
259
+ HERE
260
+ assert parser.validate_for_test({})
261
+ assert parser.validate_for_test({"one" => 2, "two" => 1})
262
+ assert parser.validate_for_test({"one" => 1, "two" => 2})
263
+ refute parser.validate_for_test({"one" => 1}, false)
264
+ assert parser.validate_for_test({"one" => 1, "two" => 2, "uno" => 1, "due" => 2})
265
+ end
266
+
267
+
268
+ def test_murray
269
+ parser = CDDL::Parser.new <<HERE
270
+ a = {
271
+ b
272
+ }
273
+
274
+ b = (
275
+ (x: int // y: int), z: int
276
+ )
277
+ HERE
278
+ assert parser.validate_for_test({})
279
+ assert parser.validate_for_test({"x" => 2, "z" => 1})
280
+ assert parser.validate_for_test({"y" => 1, "z" => 2})
281
+ refute parser.validate_for_test({"z" => 1}, false)
282
+ assert parser.validate_for_test({"one" => 1, "two" => 2, "uno" => 1, "due" => 2})
283
+ end
284
+
285
+
286
+ def test_murray_workaround
287
+ parser = CDDL::Parser.new <<HERE
288
+ a = {
289
+ b
290
+ }
291
+
292
+ b = ( z: int
293
+ (x: int // y: int)
294
+ )
295
+ HERE
296
+ assert parser.validate_for_test({})
297
+ assert parser.validate_for_test({"x" => 2, "z" => 1})
298
+ assert parser.validate_for_test({"y" => 1, "z" => 2})
299
+ refute parser.validate_for_test({"z" => 1}, false)
300
+ assert parser.validate_for_test({"one" => 1, "two" => 2, "uno" => 1, "due" => 2})
301
+ end
302
+
303
+
205
304
  def test_validate_a_string
206
305
  parser = CDDL::Parser.new <<HERE
207
306
  test = [* one: "one"]
@@ -0,0 +1,14 @@
1
+ coap-problem-details = {
2
+ type => uint,
3
+ ? title => text,
4
+ ? response-code => bstr .size 1,
5
+ ? detail => text,
6
+ ? instance => uri,
7
+ * $$coap-problem-details-extension,
8
+ }
9
+
10
+ type = 0
11
+ title = 1
12
+ response-code = 2
13
+ detail = 3
14
+ instance = 4
@@ -0,0 +1 @@
1
+ abignum = unsigned
@@ -0,0 +1,2 @@
1
+ b = [ a ]
2
+ a = uint
@@ -0,0 +1 @@
1
+ badaddr = text .regexp "[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]"
@@ -0,0 +1,136 @@
1
+ start = bundle
2
+
3
+ dtn-time = uint
4
+
5
+ creation-timestamp = [dtn-time, sequence: uint]
6
+
7
+ eid-generic = [uri-code, SSP: any]
8
+
9
+ uri-code = uint
10
+
11
+ eid = eid-choice .within eid-generic
12
+
13
+ eid-choice /= [dtn-code, SSP: (text / 0)]
14
+
15
+ dtn-code = 1 ; TBD
16
+
17
+ eid-choice /= [ipn-code, SSP: [nodenum: uint, servicenum: uint]]
18
+
19
+ ipn-code = 2 ; TBD
20
+
21
+ bundle-control-flags = uint .bits bundleflagbits
22
+
23
+ bundleflagbits = &(
24
+
25
+ reserved: 15
26
+
27
+ reserved: 14
28
+
29
+ reserved: 13
30
+
31
+ bundle-deletion-status-reports-are-requested: 12
32
+
33
+ bundle-delivery-status-reports-are-requested: 11
34
+
35
+ bundle-forwarding-status-reports-are-requested: 10
36
+
37
+ reserved: 9
38
+
39
+ bundle-reception-status-reports-are-requested: 8
40
+
41
+ bundle-contains-a-Manifest-block: 7
42
+
43
+ status-time-is-requested-in-all-status-reports: 6
44
+
45
+ user-application-acknowledgement-is-requested: 5
46
+
47
+ reserved: 4
48
+
49
+ reserved: 3
50
+
51
+ bundle-must-not-be-fragmented: 2
52
+
53
+ payload-is-an-administrative-record: 1
54
+
55
+ bundle-is-a-fragment: 0
56
+
57
+ )
58
+
59
+ crc = bytes
60
+
61
+ block-control-flags = uint .bits blockflagbits
62
+
63
+ blockflagbits = &(
64
+
65
+ reserved: 7
66
+
67
+ reserved: 6
68
+
69
+ reserved: 5
70
+
71
+ reserved: 4
72
+
73
+ bundle-must-be-deleted-if-block-cannot-be-processed: 3
74
+
75
+ status-report-must-be-transmitted-if-block-cannot-be-processed: 2
76
+
77
+ block-must-be-removed-from-bundle-if-it-cannot-be-processed: 1
78
+
79
+ block-must-be-replicated-in-every-fragment: 0
80
+
81
+ )
82
+
83
+ bundle = [primary-block, *extension-block, payload-block]
84
+
85
+ primary-block = [
86
+
87
+ version: 7,
88
+
89
+ bundle-control-flags,
90
+
91
+ crc-type: uint,
92
+
93
+ destination: eid,
94
+
95
+ source-node: eid,
96
+
97
+ report-to: eid,
98
+
99
+ creation-timestamp,
100
+
101
+ lifetime: uint,
102
+
103
+ ? fragment-offset: uint,
104
+
105
+ ? total-application-data-length: uint,
106
+
107
+ ? crc,
108
+
109
+ ]
110
+
111
+ canonical-block = [
112
+
113
+ block-type-code: uint,
114
+
115
+ canonical-block-common,
116
+
117
+ ? crc
118
+
119
+ ]
120
+
121
+ canonical-block-common = (
122
+
123
+ block-number: uint,
124
+
125
+ block-control-flags,
126
+
127
+ crc-type: uint,
128
+
129
+ block-type-specific-data: bytes
130
+
131
+ )
132
+
133
+
134
+ payload-block = ([block-type-code: 1, canonical-block-common, ?crc]) .within canonical-block
135
+
136
+ extension-block = ([block-type-code: (uint .ne 1), canonical-block-common, ?crc]) .within canonical-block