| < draft-devault-bare-05.txt | draft-devault-bare-06.txt > | |||
|---|---|---|---|---|
| Internet Engineering Task Force D. DeVault | Internet Engineering Task Force D. DeVault | |||
| Internet-Draft SourceHut | Internet-Draft SourceHut | |||
| Intended status: Informational 29 April 2022 | Intended status: Informational 2 May 2022 | |||
| Expires: 31 October 2022 | Expires: 3 November 2022 | |||
| Binary Application Record Encoding (BARE) | Binary Application Record Encoding (BARE) | |||
| draft-devault-bare-05 | draft-devault-bare-06 | |||
| Abstract | Abstract | |||
| The Binary Application Record Encoding (BARE) is a data format used | The Binary Application Record Encoding (BARE) is a data format used | |||
| to represent application records for storage or transmission between | to represent application records for storage or transmission between | |||
| programs. BARE messages are concise and have a well-defined schema, | programs. BARE messages are concise and have a well-defined schema, | |||
| and implementations may be simple and broadly compatible. A schema | and implementations may be simple and broadly compatible. A schema | |||
| language is also provided to express message schemas out-of-band. | language is also provided to express message schemas out-of-band. | |||
| Comments | Comments | |||
| skipping to change at page 1, line 39 ¶ | skipping to change at page 1, line 39 ¶ | |||
| Internet-Drafts are working documents of the Internet Engineering | Internet-Drafts are working documents of the Internet Engineering | |||
| Task Force (IETF). Note that other groups may also distribute | Task Force (IETF). Note that other groups may also distribute | |||
| working documents as Internet-Drafts. The list of current Internet- | working documents as Internet-Drafts. The list of current Internet- | |||
| Drafts is at https://datatracker.ietf.org/drafts/current/. | Drafts is at https://datatracker.ietf.org/drafts/current/. | |||
| Internet-Drafts are draft documents valid for a maximum of six months | Internet-Drafts are draft documents valid for a maximum of six months | |||
| and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
| time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
| material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
| This Internet-Draft will expire on 31 October 2022. | This Internet-Draft will expire on 3 November 2022. | |||
| Copyright Notice | Copyright Notice | |||
| Copyright (c) 2022 IETF Trust and the persons identified as the | Copyright (c) 2022 IETF Trust and the persons identified as the | |||
| document authors. All rights reserved. | document authors. All rights reserved. | |||
| This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
| Provisions Relating to IETF Documents (https://trustee.ietf.org/ | Provisions Relating to IETF Documents (https://trustee.ietf.org/ | |||
| license-info) in effect on the date of publication of this document. | license-info) in effect on the date of publication of this document. | |||
| Please review these documents carefully, as they describe your rights | Please review these documents carefully, as they describe your rights | |||
| skipping to change at page 2, line 33 ¶ | skipping to change at page 2, line 33 ¶ | |||
| 3.2. ABNF Grammar . . . . . . . . . . . . . . . . . . . . . . 9 | 3.2. ABNF Grammar . . . . . . . . . . . . . . . . . . . . . . 9 | |||
| 3.3. Semantic Elements . . . . . . . . . . . . . . . . . . . . 11 | 3.3. Semantic Elements . . . . . . . . . . . . . . . . . . . . 11 | |||
| 4. Application Considerations . . . . . . . . . . . . . . . . . 11 | 4. Application Considerations . . . . . . . . . . . . . . . . . 11 | |||
| 5. Future Considerations . . . . . . . . . . . . . . . . . . . . 12 | 5. Future Considerations . . . . . . . . . . . . . . . . . . . . 12 | |||
| 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 12 | 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 12 | |||
| 7. Security Considerations . . . . . . . . . . . . . . . . . . . 12 | 7. Security Considerations . . . . . . . . . . . . . . . . . . . 12 | |||
| 8. Normative References . . . . . . . . . . . . . . . . . . . . 12 | 8. Normative References . . . . . . . . . . . . . . . . . . . . 12 | |||
| Appendix A. Example Values . . . . . . . . . . . . . . . . . . . 13 | Appendix A. Example Values . . . . . . . . . . . . . . . . . . . 13 | |||
| Appendix B. Example Company . . . . . . . . . . . . . . . . . . 15 | Appendix B. Example Company . . . . . . . . . . . . . . . . . . 15 | |||
| B.1. Message Schema . . . . . . . . . . . . . . . . . . . . . 16 | B.1. Message Schema . . . . . . . . . . . . . . . . . . . . . 16 | |||
| B.2. Encoded Messages . . . . . . . . . . . . . . . . . . . . 18 | B.2. Encoded Messages . . . . . . . . . . . . . . . . . . . . 17 | |||
| Appendix C. Complex data . . . . . . . . . . . . . . . . . . . . 19 | Appendix C. Complex Data . . . . . . . . . . . . . . . . . . . . 18 | |||
| C.1. Simple hierarchical data . . . . . . . . . . . . . . . . 19 | C.1. Simple Hierarchical Data . . . . . . . . . . . . . . . . 18 | |||
| C.2. JSON schema . . . . . . . . . . . . . . . . . . . . . . . 19 | C.2. JSON Schema . . . . . . . . . . . . . . . . . . . . . . . 19 | |||
| C.3. Graph . . . . . . . . . . . . . . . . . . . . . . . . . . 20 | C.3. Graph . . . . . . . . . . . . . . . . . . . . . . . . . . 19 | |||
| Appendix D. Design Decisions . . . . . . . . . . . . . . . . . . 20 | Appendix D. Design Decisions . . . . . . . . . . . . . . . . . . 20 | |||
| Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 21 | Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 21 | |||
| 1. Introduction | 1. Introduction | |||
| The purpose of the BARE message encoding, like hundreds of others, is | The purpose of the BARE message encoding, like hundreds of others, is | |||
| to encode application messages. The goals of such encodings vary | to encode application messages. The goals of such encodings vary | |||
| (leading to their proliferation); BARE's goals are the following: | (leading to their proliferation); BARE's goals are the following: | |||
| * Concise messages | * Concise messages | |||
| skipping to change at page 4, line 31 ¶ | skipping to change at page 4, line 31 ¶ | |||
| exchange BARE messages. The type names used here are provided for | exchange BARE messages. The type names used here are provided for | |||
| this informative purpose, but are more rigourously specified by the | this informative purpose, but are more rigourously specified by the | |||
| schema language specification in Section 3. | schema language specification in Section 3. | |||
| 2.1. Primitive Types | 2.1. Primitive Types | |||
| Primitive types represent exactly one value. | Primitive types represent exactly one value. | |||
| uint | uint | |||
| A variable-length unsigned integer encoded using the Unsigned | A variable-length unsigned integer encoded using the Unsigned | |||
| Little Endian Base 128 (ULEB128). Each octet of the encoded | Little Endian Base 128 (ULEB128). Every octet of the encoded | |||
| value has the most-significant bit set, except for the last | value has the most-significant bit set, except for the last | |||
| octet. The remaining bits are the zero-extended integer | octet. The remaining bits are the zero-extended integer | |||
| value in 7-bit groups, the least-significant group first. | value in 7-bit groups, the least-significant group first. | |||
| The encoder MUST encode uint using the minimum necessary | The encoder MUST encode uint using the minimum necessary | |||
| number of octets, and the decoder SHOULD raise an error if it | number of octets, and the decoder SHOULD raise an error if it | |||
| encounters the opposite. | encounters the opposite. | |||
| The maximum precision of such a number is 64-bits. The | The maximum precision of such a number is 64-bits. The | |||
| maximum length of an encoded uint is therefore 10 octets. | maximum length of an encoded uint is therefore 10 octets. | |||
| skipping to change at page 6, line 17 ¶ | skipping to change at page 6, line 17 ¶ | |||
| if it encounters such a value. | if it encounters such a value. | |||
| data | data | |||
| Arbitrary data of a variable length. The length (in octets) | Arbitrary data of a variable length. The length (in octets) | |||
| is encoded first as a uint, followed by the data itself | is encoded first as a uint, followed by the data itself | |||
| encoded literally. | encoded literally. | |||
| data[length] | data[length] | |||
| Arbitrary data of a fixed "length", e.g. data[16]. The | Arbitrary data of a fixed "length", e.g. data[16]. The | |||
| length (in octets) is not encoded into the message. The data | length (in octets) is not encoded into the message. The data | |||
| is encoded literally in the message, and MUST NOT be longer | is encoded literally in the message. | |||
| than 18,446,744,073,709,551,615 octets (the maximum value of | ||||
| a u64). | ||||
| void | void | |||
| A type with zero length. It is not encoded into BARE | A type with zero length. It is not encoded into BARE | |||
| messages. | messages. | |||
| enum | enum | |||
| An unsigned integer value from a set of named values agreed | An unsigned integer value from a set of named values agreed | |||
| upon in advance, encoded with the uint type. | upon in advance, encoded with the uint type. | |||
| An enum whose uint value is not a member of the values agreed | An enum whose uint value is not a member of the values agreed | |||
| skipping to change at page 7, line 34 ¶ | skipping to change at page 7, line 34 ¶ | |||
| with the number of key/value pairs encoded as a uint, | with the number of key/value pairs encoded as a uint, | |||
| followed by the encoded key/value pairs concatenated. Each | followed by the encoded key/value pairs concatenated. Each | |||
| key/value pair is encoded as the encoded key concatenated | key/value pair is encoded as the encoded key concatenated | |||
| with the encoded value. | with the encoded value. | |||
| A message with repeated keys is considered invalid, and the | A message with repeated keys is considered invalid, and the | |||
| decoder SHOULD raise an error if it encounters such a value. | decoder SHOULD raise an error if it encounters such a value. | |||
| union | union | |||
| A tagged union whose value may be one of any type from a set | A tagged union whose value may be one of any type from a set | |||
| of types agreed upon in advance. Each type in the set is | of types agreed upon in advance. Every type in the set is | |||
| assigned a numeric identifier. The value is encoded as the | assigned a numeric identifier. The value is encoded as the | |||
| selected type's identifier represented with the uint | selected type's identifier represented with the uint | |||
| encoding, followed by the encoded value of that type. | encoding, followed by the encoded value of that type. | |||
| A union with a tag value that does not have a corresponding | A union with a tag value that does not have a corresponding | |||
| type assigned is considered invalid, and the decoder SHOULD | type assigned is considered invalid, and the decoder SHOULD | |||
| raise an error if it encounters such a value. | raise an error if it encounters such a value. | |||
| struct | struct | |||
| A set of values of arbitrary types concatenated in an order | A set of values of arbitrary types concatenated in an order | |||
| skipping to change at page 8, line 24 ¶ | skipping to change at page 8, line 24 ¶ | |||
| The following invariants are specified: | The following invariants are specified: | |||
| * Any type that is ultimately a void type (either directly or via a | * Any type that is ultimately a void type (either directly or via a | |||
| user-defined type) MUST NOT be used as an optional type, list | user-defined type) MUST NOT be used as an optional type, list | |||
| value, map key, map value, or struct field type. Void types may | value, map key, map value, or struct field type. Void types may | |||
| only be used as members of the set of types in a tagged union. | only be used as members of the set of types in a tagged union. | |||
| * Enums MUST have at least one named value, and each named value of | * Enums MUST have at least one named value, and each named value of | |||
| an enum MUST be unique. | an enum MUST be unique. | |||
| * The lengths of fixed-length list and fixed-length data types MUST | * The lengths of fixed-length data and fixed-length list types MUST | |||
| be at least one. | be at least one and MUST NOT be longer than | |||
| 18,446,744,073,709,551,615 octets (the maximum value of a u64). | ||||
| * Any map key type (directly or via a user-defined type) MUST be of | * Any map key type (directly or via a user-defined type) MUST be of | |||
| a primitive type that is not f32, f64, data, data[length], or | a primitive type that is not f32, f64, data, data[length], or | |||
| void. | void. | |||
| * Unions MUST have at least one type, and each type of a union MUST | * Unions MUST have at least one type, and each type of a union MUST | |||
| be unique. | be unique. | |||
| * Structs MUST have at least one field, and each field of a struct | * Structs MUST have at least one field, and each field of a struct | |||
| MUST have a unique name. | MUST have a unique name. | |||
| skipping to change at page 11, line 14 ¶ | skipping to change at page 11, line 14 ¶ | |||
| 3.3. Semantic Elements | 3.3. Semantic Elements | |||
| The names of fields and user-defined types are informational: they | The names of fields and user-defined types are informational: they | |||
| are not represented in BARE messages. They may be used by code | are not represented in BARE messages. They may be used by code | |||
| generation tools to inform the generation of field and type names in | generation tools to inform the generation of field and type names in | |||
| the native programming environment. | the native programming environment. | |||
| Enum values are also informational. Values without an integer token | Enum values are also informational. Values without an integer token | |||
| are assigned automatically in the order that they appear, starting | are assigned automatically in the order that they appear, starting | |||
| from zero and incrementing for each subsequent unassigned value. If | from zero and incrementing by one for each subsequent unassigned | |||
| a value is explicitly specified, automatic assignment continues from | value. If a value is explicitly specified, automatic assignment | |||
| that value plus one for subsequent enum values. | continues from that value plus one for subsequent enum values. | |||
| Union type members are assigned a tag in the order that they appear, | Union type members are assigned a tag in the order that they appear, | |||
| starting from zero and incrementing for each subsequent type. If a | starting from zero and incrementing by one for each subsequent type. | |||
| tag value is explicitly specified, automatic assignment continues | If a tag value is explicitly specified, automatic assignment | |||
| from that value plus one for subsequent values. | continues from that value plus one for subsequent values. | |||
| 4. Application Considerations | 4. Application Considerations | |||
| Message authors who wish to design a schema that is backwards- and | Message authors who wish to design a schema that is backwards- and | |||
| forwards-compatible with future messages are encouraged to use union | forwards-compatible with future messages are encouraged to use union | |||
| types for this purpose. New types may be appended to the members of | types for this purpose. New types may be appended to the members of | |||
| a union type while retaining backwards compatibility with older | a union type while retaining backwards compatibility with older | |||
| message types. The choice to do this must be made from the first | message types. The choice to do this must be made from the first | |||
| message version -- moving a struct into a union _does not_ produce a | message version -- moving a struct into a union _does not_ produce a | |||
| backwards-compatible message. | backwards-compatible message. | |||
| skipping to change at page 15, line 41 ¶ | skipping to change at page 15, line 41 ¶ | |||
| union {int | uint = 255 | str} | union {int | uint = 255 | str} | |||
| 0 00 00 | 0 00 00 | |||
| 1 00 02 | 1 00 02 | |||
| 1 FF 01 01 | 1 FF 01 01 | |||
| -1 00 01 | -1 00 01 | |||
| 255 00 FE 03 | 255 00 FE 03 | |||
| 255 FF 01 FF 01 | 255 FF 01 FF 01 | |||
| -255 00 FD 03 | -255 00 FD 03 | |||
| "BARE" 80 02 04 42 41 52 45 | "BARE" 80 02 04 42 41 52 45 | |||
| struct {foo : uint bar : int buzz : str} | struct {foo: uint bar: int buzz: str} | |||
| foo => 255 | foo => 255 | |||
| bar => -255 | bar => -255 | |||
| buzz => "BARE" | buzz => "BARE" | |||
| FF 01 FD 03 04 42 41 52 45 | FF 01 FD 03 04 42 41 52 45 | |||
| Appendix B. Example Company | Appendix B. Example Company | |||
| An example company that uses BARE to encode data about customers and | An example company that uses BARE to encode data about customers and | |||
| employees. | employees. | |||
| skipping to change at page 17, line 18 ¶ | skipping to change at page 16, line 23 ¶ | |||
| type Department enum { | type Department enum { | |||
| ACCOUNTING | ACCOUNTING | |||
| ADMINISTRATION | ADMINISTRATION | |||
| CUSTOMER_SERVICE | CUSTOMER_SERVICE | |||
| DEVELOPMENT | DEVELOPMENT | |||
| # Reserved for the CEO | # Reserved for the CEO | |||
| JSMITH = 99 | JSMITH = 99 | |||
| } | } | |||
| type Address struct { | type Address list<str>[4] # street, city, state, country | |||
| address: list<str>[4] | ||||
| city: str | ||||
| state: str | ||||
| country: str | ||||
| } | ||||
| type Customer struct { | type Customer struct { | |||
| name: str | name: str | |||
| email: str | email: str | |||
| address: Address | address: Address | |||
| orders: list<struct { | orders: list<struct { | |||
| orderId: i64 | orderId: i64 | |||
| quantity: i32 | quantity: i32 | |||
| }> | }> | |||
| metadata: map<str><data> | metadata: map<str><data> | |||
| skipping to change at page 18, line 31 ¶ | skipping to change at page 17, line 31 ¶ | |||
| Encoded BARE message: | Encoded BARE message: | |||
| 00 0b 4a 61 6d 65 73 20 53 6d 69 74 68 12 6a 73 | 00 0b 4a 61 6d 65 73 20 53 6d 69 74 68 12 6a 73 | |||
| 6d 69 74 68 40 65 78 61 6d 70 6c 65 2e 6f 72 67 | 6d 69 74 68 40 65 78 61 6d 70 6c 65 2e 6f 72 67 | |||
| 0b 31 32 33 20 4d 61 69 6e 20 53 74 0c 50 68 69 | 0b 31 32 33 20 4d 61 69 6e 20 53 74 0c 50 68 69 | |||
| 6c 61 64 65 6c 70 68 69 61 02 50 41 0d 55 6e 69 | 6c 61 64 65 6c 70 68 69 61 02 50 41 0d 55 6e 69 | |||
| 74 65 64 20 53 74 61 74 65 73 01 b2 41 de fc 00 | 74 65 64 20 53 74 61 74 65 73 01 b2 41 de fc 00 | |||
| 00 00 00 05 00 00 00 00 | 00 00 00 05 00 00 00 00 | |||
| Encoded BARE message, but characters of strings are decoded: | ||||
| 00 0b J a m e s S m i t h 12 j s | ||||
| m i t h @ e x a m p l e . o r g | ||||
| 0b 1 2 3 M a i n S t 0c P h i | ||||
| l a d e l p h i a 02 P A 0d U n i | ||||
| t e d S t a t e s 01 b2 41 de fc 00 | ||||
| 00 00 00 05 00 00 00 00 | ||||
| A "Person" value of type "Employee" with the following values: | A "Person" value of type "Employee" with the following values: | |||
| name Tiffany Doe | name Tiffany Doe | |||
| email tiffanyd@acme.corp | email tiffanyd@acme.corp | |||
| address 123 Main St; Philadelphia; PA; United States | address 123 Main St; Philadelphia; PA; United States | |||
| department ADMINISTRATION | department ADMINISTRATION | |||
| skipping to change at page 18, line 44 ¶ | skipping to change at page 18, line 4 ¶ | |||
| email tiffanyd@acme.corp | email tiffanyd@acme.corp | |||
| address 123 Main St; Philadelphia; PA; United States | address 123 Main St; Philadelphia; PA; United States | |||
| department ADMINISTRATION | department ADMINISTRATION | |||
| hireDate 2020-06-21T21:18:05Z | hireDate 2020-06-21T21:18:05Z | |||
| publicKey (unset) | publicKey (unset) | |||
| metadata (unset) | metadata (unset) | |||
| Encoded BARE message: | Encoded BARE message: | |||
| 01 0b 54 69 66 66 61 6e 79 20 44 6f 65 12 74 69 | 01 0b 54 69 66 66 61 6e 79 20 44 6f 65 12 74 69 | |||
| 66 66 61 6e 79 64 40 61 63 6d 65 2e 63 6f 72 70 | 66 66 61 6e 79 64 40 61 63 6d 65 2e 63 6f 72 70 | |||
| 0b 31 32 33 20 4d 61 69 6e 20 53 74 0c 50 68 69 | 0b 31 32 33 20 4d 61 69 6e 20 53 74 0c 50 68 69 | |||
| 6c 61 64 65 6c 70 68 69 61 02 50 41 0d 55 6e 69 | 6c 61 64 65 6c 70 68 69 61 02 50 41 0d 55 6e 69 | |||
| 74 65 64 20 53 74 61 74 65 73 01 14 32 30 32 30 | 74 65 64 20 53 74 61 74 65 73 01 14 32 30 32 30 | |||
| 2d 30 36 2d 32 31 54 32 31 3a 31 38 3a 30 35 5a | 2d 30 36 2d 32 31 54 32 31 3a 31 38 3a 30 35 5a | |||
| 00 00 | 00 00 | |||
| Encoded BARE message, but characters of strings are decoded: | ||||
| 01 0b T i f f a n y D o e 12 t i | ||||
| f f a n y d @ a c m e . c o r p | ||||
| 0b 1 2 3 M a i n S t 0c P h i | ||||
| l a d e l p h i a 02 P A 0d U n i | ||||
| t e d S t a t e s 01 14 2 0 2 0 | ||||
| - 0 6 - 2 1 T 2 1 : 1 8 : 0 5 Z | ||||
| 00 00 | ||||
| A "Person" value of type "TerminatedEmployee". | A "Person" value of type "TerminatedEmployee". | |||
| Encoded BARE message: | Encoded BARE message: | |||
| 02 | 02 | |||
| Appendix C. Complex data | Appendix C. Complex Data | |||
| BARE schema examples for complex data structures. | BARE schema examples for complex data structures. | |||
| C.1. Simple hierarchical data | C.1. Simple Hierarchical Data | |||
| Recursive data types are forbidden in BARE. The following examples | Recursive data types are forbidden in BARE. The following examples | |||
| show how linked list and binary tree, widely used recursive data | show how linked list and binary tree, widely used recursive data | |||
| types, can be encoded in BARE message. | types, can be encoded in BARE messages. | |||
| As BARE supports variable-length lists, encoding of linked list is | As BARE supports variable-length lists, encoding of linked list is | |||
| straightforward. | straightforward. | |||
| type Element struct { | type Element struct { | |||
| str: what | str: what | |||
| } | } | |||
| type LinkedList list<Element> | type LinkedList list<Element> | |||
| A binary tree can be encoded to BARE's variable-length list with 2x + | A binary tree can be encoded to BARE's variable-length list with 2x + | |||
| 1 and 2x + 2 indexing. | 1 and 2x + 2 indexing. | |||
| type Node optional<struct { | type Node optional<struct { | |||
| str: what | str: what | |||
| }> | }> | |||
| type BinaryTree list<Node> | type BinaryTree list<Node> | |||
| C.2. JSON schema | C.2. JSON Schema | |||
| Sometimes it is needed to deal with generic format of data. When the | Sometimes it is needed to deal with generic format of data. When the | |||
| use-case for recursive types is encountered, each element to encode | use-case for recursive types is encountered, each element to encode | |||
| needs to be identified. | needs to be identified. | |||
| type ElementId uint | type ElementId uint | |||
| type False void | type False void | |||
| type True void | type True void | |||
| type Null void | type Null void | |||
| skipping to change at page 21, line 42 ¶ | skipping to change at page 21, line 17 ¶ | |||
| *Namespaces or imports are not used* | *Namespaces or imports are not used* | |||
| It would increase complexity. BARE schema language is simple. | It would increase complexity. BARE schema language is simple. | |||
| *There is no bitmap type* | *There is no bitmap type* | |||
| Use data[length] instead. | Use data[length] instead. | |||
| *There is no date/time type* | *There is no date/time type* | |||
| Use u64 for timestamp or str. | Use u64 for timestamp or str. | |||
| *There is no ordered map type* | ||||
| Ordered maps are not widely supported in programming environments. | ||||
| Users that want to use ordered maps can use a list of pairs: | ||||
| list<struct { | ||||
| key: KeyType | ||||
| val: ValType | ||||
| }> | ||||
| Author's Address | Author's Address | |||
| Drew DeVault | Drew DeVault | |||
| SourceHut | SourceHut | |||
| 454 E. Girard Ave #2R | 454 E. Girard Ave #2R | |||
| Philadelphia, PA 19125 | Philadelphia, PA 19125 | |||
| United States of America | United States of America | |||
| Phone: +1 719 213 5473 | Phone: +1 719 213 5473 | |||
| Email: sir@cmpwn.com | Email: sir@cmpwn.com | |||
| URI: https://sourcehut.org/ | URI: https://sourcehut.org/ | |||
| End of changes. 21 change blocks. | ||||
| 35 lines changed or deleted | 55 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||