ccnx.xsd is the xml schema that describes what the xml rendition of ccn data (including Interest messages) should look like.
ccnx.dtd is a dtd that should describe the same, in a less strongly-typed fashion.
tagname.csvdict contains the mapping between the DTAG values used in the binary encoding and the element names used in the XML representation.
Below we will use a less formal abstract syntax to indicate how the pieces fit together.
Interest ::= Name
MinSuffixComponents?
MaxSuffixComponents?
PublisherPublicKeyDigest?
Exclude?
ChildSelector?
AnswerOriginKind?
Scope?
Nonce?
The hierarchical Name is the only required element in an Interest message.
The remaining elements fall into several categories:
-
those that further qualify the ContentObjects that may match the Interest MinSuffixComponents, MaxSuffixComponents, PublisherPublicKeyDigest, Exclude)
-
those that limit where the answer might come from (AnswerOriginKind, Scope)
-
those that advise the selection of what to send when there are multiple ContentObjects that match (ChildSelector)
-
duplicate suppression (Nonce)
See the Example for encodings of a minimal Interest
Message.
The Name element in an interest is synonymous with the term prefix.
The Name of every piece of content includes as its final component a derived digest that serves to make the entire name unique. This may occur in an Interest Name as an ordinary Component (the last). However, this final component is never included explicitly in the ContentObject as it appears on the wire.
MinSuffixComponents ::= nonNegativeInteger
MaxSuffixComponents ::= nonNegativeInteger
A client may need to say that the Name in the interest is either the full name including the digest, or the full name except for the digest, or that the content it is seeking has a known range of legitimate component counts. To encode this there are two parameters, named MinSuffixComponents and MaxSuffixComponents, that specify these limits. These refer to the number of name components beyond those in the prefix, and counting the implicit digest, that may occur in the matching ContentObject. The default for MinSuffixComponents is 0 and for MaxSuffixComponents is effectively infinite. Often only one of these will be needed to get the desired effect.
PublisherPublicKeyDigest ::= BLOB
If the PublisherPublicKeyDigest element is present in the Interest, the associated value (a SHA-256 digest) must be equal to the value of the PublisherPublicKeyDigest of the ContentObject for there to be a match.
(The Interest schema admits some other possibilities, but only this form of publisher selection is currently implemented.)
Exclude ::= (Any | Bloom)? ( Component (Any | Bloom)? )*
Any ::= (empty)
Bloom ::= BLOB
The Exclude element embodies a description of name components that should not appear as a continuation of the Name prefix in the response to the interest.
The Components in the exclusion list must occur in strictly increasing order according to the canonical CCNx ordering. Call the pieces in the exclude list B[0], C[1], B[1], C[2], B[2], … C[m], B[m]. (Here the B[i] are the Bloom elements and the C[i] are the Component elements. The omission of a Bloom element is equivalent to a bloom filter that describes the empty set.) Furthermore, take C[0] as negative infinity and C[m+1] as infinity. Then a component C is a member of the exclusion set iff C = C[k] for some k in [1..m] or if C[k] < C < C[k+1] for some k in [0..m] and C matches B[k].
A client could choose to simply enumerate the elements of the exclusion set if that is sufficiently compact (using no Bloom filters at all). At the other extreme, it could simply supply a single Bloom filter to describe the exclusion set.
A seed value is used for the hash functions of the bloom filters. By using different seeds on different expressions of its interests, an application may minimize the impact of the false positives inherent with bloom filters.
The Bloom's BLOB is of length 8 + ceiling(n/8) bytes, where n is the number of bits in the bloom filter. We restrict n to be a power of two or zero. The first 8 bytes of the BLOB contains a header:
unsigned char lg_bits; /* 13 maximum (8 kilobits), 3 minimum (one byte) */
unsigned char n_hash; /* number of hash functions to employ */
unsigned char method; /* allow for various hashing algorithms */
unsigned char reserved; /* must be 0 for now */
unsigned char seed[4]; /* can seed hashes differently */
and the remaining bytes hold the bits of the bloom filter. The bits in the filter itself are packed little-endian by byte. Note that a Bloom filter with 0 hash functions is one way to match everything, and a filter with all ones is another. But these are not very compact, so the All element is provided as a better way to encode this common case.
TODO - The the calculation of the hash functions must also be specified. At present, referring to the c code is the best option; it should be quite easy to port to other languages.
ChildSelector ::= nonNegativeInteger
Often a given interest will match more than one ContentObject within a given content store. The ChildSelector provides a way of expressing a preference for which of these should be returned. If the (low order bit of) the value is 0, the leftmost child is preferred. If 1, the rightmost child is preferred. Here leftmost and rightmost refer to the least and greatest components according to the canonical CCNx ordering. This ordering is only done at the level of the name hierarchy one past the name prefix.
AnswerOriginKind ::= nonNegativeInteger
AnswerOriginKind encodes several bitfields that alter the usual response to interest. There is a do-not-answer-from-content-store bit, which also implies a passive bit. There will eventually need to be some security aspects to this, limiting it by scope and/or by interest signing, but we are choosing to ignore these for now. There is also utility in the passive bit alone - it means do not generate any newly-signed content in response to this interest.
Wire representation: the AnswerOriginKind element holds a nonNegativeInteger with bitmasks having the following interpretation:
-
1 = Answer from existing content store
-
2 = Answers may be generated
-
4 = Answer may be "stale"
-
16 = Mark as stale in content store (must have Scope 0) Status: hack
-
The default is 3, giving normal behavior. The two low-order bits in combination mean:
0 = do-not-answer-from-content-store
1 = passive
2 is disallowed
3 = normal
Scope ::= nonNegativeInteger
This limits where the Interest may propagate. Scope 0 prevents propagation beyond the local ccnd (even to other applications on the same host). Scope 1 limits propagation to the originating host. Other values are not currently defined, and will cause the Interest message to be dropped.
The Nonce carries a randomly-genenerated bytestring that is used to detect and discard duplicate Interest messages. Applications generally do not need to generate or check the Nonce. Note that the Nonce is not the only basis for detecting and discarding duplicate Interest messages that arrive at a node, but can be used to improve the efficiency of the detection.
Here is an example of an Interest containing a name prefix with 2
components.
In XML, the Interest Message is:
<Interest>
<Name>
<Component ccnbencoding="base64Binary">UEFSQw==</Component>
<Component ccnbencoding="base64Binary">AAEC</Component>
</Name>
</Interest>
<Interest>
<Name>
<Component ccnbencoding="text">PARC</Component>
<Component ccnbencoding="base64Binary">AAEC</Component>
</Name>
</Interest>
00000000 01 d2 f2 fa a5 50 41 52 43 00 fa 9d 00 01 02 00 |.....PARC.......|
00000010 00 00 |..|
This is the form that actually appears on the wire.