Documentation ¶
Index ¶
- func AddEventListener[T any](node NTNode, propName PropKey, callback T) error
- func PropertySet[T any](ptr *T, propName PropKey, value any) error
- type BaseNode
- func (n *BaseNode) Apply(matching enc.Matching) enc.Name
- func (n *BaseNode) At(path enc.NamePattern) NTNode
- func (n *BaseNode) AttachedPrefix() enc.Name
- func (n *BaseNode) Child(edge enc.ComponentPattern) NTNode
- func (n *BaseNode) Children() []NTNode
- func (n *BaseNode) ConstructName(matching enc.Matching, ret enc.Name) error
- func (n *BaseNode) Depth() uint
- func (n *BaseNode) Engine() ndn.Engine
- func (n *BaseNode) Get(propName PropKey) any
- func (n *BaseNode) Init(parent NTNode, edge enc.ComponentPattern)
- func (n *BaseNode) Match(name enc.Name) (NTNode, enc.Matching)
- func (n *BaseNode) NodeTrait() NTNode
- func (n *BaseNode) OnAttach(path enc.NamePattern, engine ndn.Engine) error
- func (n *BaseNode) OnDetach()
- func (n *BaseNode) OnInterest(interest ndn.Interest, rawInterest enc.Wire, sigCovered enc.Wire, ...)
- func (n *BaseNode) Parent() NTNode
- func (n *BaseNode) PutNode(path enc.NamePattern, node NTNode) error
- func (n *BaseNode) Set(propName PropKey, value any) error
- func (n *BaseNode) SetAttachedPrefix(prefix enc.Name) error
- func (n *BaseNode) UpEdge() enc.ComponentPattern
- type Context
- type CtxKey
- type Event
- type ExpressPoint
- func (n *ExpressPoint) Get(propName PropKey) any
- func (n *ExpressPoint) Init(parent NTNode, edge enc.ComponentPattern)
- func (n *ExpressPoint) Need(matching enc.Matching, name enc.Name, appParam enc.Wire, context Context) chan NeedResult
- func (n *ExpressPoint) OnInterest(interest ndn.Interest, rawInterest enc.Wire, sigCovered enc.Wire, ...)
- func (n *ExpressPoint) SearchCache(matching enc.Matching, name enc.Name, canBePrefix bool, mustBeFresh bool, ...) enc.Wire
- func (n *ExpressPoint) Set(propName PropKey, value any) error
- type LeafNode
- type NTNode
- type NTPolicy
- type NeedResult
- type NodeGetSignerEvent
- type NodeOnAttachEvent
- type NodeOnDetachEvent
- type NodeOnIntEvent
- type NodeSaveStorageEvent
- type NodeSearchStorageEvent
- type NodeValidateEvent
- type PropKey
- type Tree
- func (t *Tree) At(path enc.NamePattern) NTNode
- func (t *Tree) Attach(prefix enc.Name, engine ndn.Engine) error
- func (t *Tree) Detach()
- func (t *Tree) Match(name enc.Name) (NTNode, enc.Matching)
- func (t *Tree) PutNode(path enc.NamePattern, node NTNode) error
- func (t *Tree) RLock()
- func (t *Tree) RUnlock()
- type ValidRes
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddEventListener ¶
AddEventListener add `callback` to the event `propKey` of `node`
Types ¶
type BaseNode ¶
type BaseNode struct { // Self is the pointer pointing to Self. // Note: This is needed since golang does not have true OO. // For example, if NodeA inherits BaseNode and calls a BaseNode function, // then the BaseNode function has to access NodeA via this Self pointer. Self NTNode // Chd holds all children. // Since a schema tree typically only has <10 branches, an array should not hurt performance. // Change when there found evidences showing this is the bottleneck. Chd []NTNode // Log is the logger Log *log.Entry // contains filtered or unexported fields }
BaseNode is the base class of NTSchema nodes. TODO: Inheritance from BaseNode is really a bad model of this thing but I cannot come up with a better one in limited time. If possible, a mixin programming model may be better. TODO: (updated) a better choice may be separate the tree node (that handles Child, Parent, etc.) and the polymorphic functional part (than handles Get, Set, Events, etc.) For WASM use in the future, we may need a list of properties. Also, add ENV for Init.
func (*BaseNode) Apply ¶
Apply a (variable) matching and obtain the corresponding NDN name For example, apply {"id":[]byte{"aa"}} to a node at /ndn/<id> will get /ndn/aa
func (*BaseNode) At ¶
func (n *BaseNode) At(path enc.NamePattern) NTNode
At gets a node/subtree at a given pattern path. The path does not include the attached prefix.
func (*BaseNode) AttachedPrefix ¶
AttachedPrefix of the root node. Must be nil for all other nodes and before Attach.
func (*BaseNode) Child ¶
func (n *BaseNode) Child(edge enc.ComponentPattern) NTNode
Child of given edge
func (*BaseNode) ConstructName ¶
ConstructName is the aux function used by Apply
func (*BaseNode) Depth ¶
Depth of the node in the tree. It includes the attached prefix, so the root node may have a positive depth For example, if the root is attached at prefix /ndn, then the child of path /<id> from the root will have a depth=2.
func (*BaseNode) Init ¶
func (n *BaseNode) Init(parent NTNode, edge enc.ComponentPattern)
Init the node
func (*BaseNode) Match ¶
Match an NDN name to a (variable) matching For example, /ndn/aa may match to a node at /ndn/<id> with matching <id> = "aa"
func (*BaseNode) OnAttach ¶
OnAttach is called when the node is attached to an engine BaseNode will call the event set by policy
func (*BaseNode) OnDetach ¶
func (n *BaseNode) OnDetach()
OnDetach is called when the node is detached from an engine BaseNode will call the event set by policy
func (*BaseNode) OnInterest ¶
func (n *BaseNode) OnInterest( interest ndn.Interest, rawInterest enc.Wire, sigCovered enc.Wire, reply ndn.ReplyFunc, deadline time.Time, matching enc.Matching, )
OnInterest is the function called when an Interest comes. A base node shouldn't receive any Interest, so drops it.
func (*BaseNode) PutNode ¶
func (n *BaseNode) PutNode(path enc.NamePattern, node NTNode) error
PutNode sets a node/subtree at a given pattern path. The path does not include the attached prefix.
func (*BaseNode) SetAttachedPrefix ¶
SetAttachedPrefix sets the attached prefix of the root node.
func (*BaseNode) UpEdge ¶
func (n *BaseNode) UpEdge() enc.ComponentPattern
UpEdge is the edge value from its parent to itself
type Context ¶
Context contains extra info that may be useful to an event, but not worthy to be an argument. It can also be used to pass information between chained event callbacks.
type CtxKey ¶
type CtxKey uint64
CtxKey is the type of keys of the context.
const ( // The following keys are used to grab extra information of the incoming packet. [TYPE] CkDeadline CtxKey = 1 // Deadline is now + InterestLifetime. [time.Time] CkRawPacket CtxKey = 2 // The raw Interest or Data wire. [enc.Wire] CkSigCovered CtxKey = 3 // The wire covered by the signature. [enc.Wire] CkName CtxKey = 4 // The name of the packet. [enc.Name] CkInterest CtxKey = 5 // The Interest packet. [ndn.Interest] CkData CtxKey = 6 // The Data packet. [ndn.Data] CkContent CtxKey = 7 // The content of the data packet or AppParam of Interest. [enc.Wire] CkNackReason CtxKey = 8 // The NackReason. Only valid when the InterestResult is NACK. [uint64] CkLastValidResult CtxKey = 10 // The result returned by the prev validator in the callback chain. [ValidRes] CkEngine CtxKey = 20 // The engine the current node is attached to. [ndn.Engine] // The following keys are used to overwrite nodes' properties once // Not valid for incoming Interest or Data packets. CkCanBePrefix CtxKey = 101 // [bool] CkMustBeFresh CtxKey = 102 // [bool] CkForwardingHint CtxKey = 103 // [[]enc.Name] CkNonce CtxKey = 104 // [time.Duration] CkLifetime CtxKey = 105 // [uint64] CkHopLimit CtxKey = 106 // [uint] CkSupressInt CtxKey = 107 // If true, only local storage is searched. No Interest will be expressed. [bool] CkContentType CtxKey = 201 // [ndn.ContentType] CkFreshness CtxKey = 202 // [time.Duration] CkFinalBlockID CtxKey = 203 // [enc.Component] // The validity period of a data in the storage produced by this node, // i.e. how long the local storage will serve it. // Should be larger than FreshnessPeriod. Not affected data fetched remotely. CkValidDuration CtxKey = 205 // [time.Duration] )
type Event ¶
type Event[T comparable] struct { // contains filtered or unexported fields }
Event is a chain of callback functions for an event. The execution order is supposed to be the addition order. Note: to implement `comparable`, you need to use pointer type, like *func()
func NewEvent ¶
func NewEvent[T comparable]() *Event[T]
NewEvent creates an event. Note that T should be *func.
func (*Event[T]) Add ¶
func (e *Event[T]) Add(callback T)
Add a callback. Note that callback should be a *func.
type ExpressPoint ¶
type ExpressPoint struct { BaseNode // contains filtered or unexported fields }
ExpressPoint is an expressing point where an Interest is supposed to be expressed. For example, for an RDR protocol w/ metadata name being /prefix/<filename>/32=metadata/<v=version>, The node at "/prefix/<filename>/32=metadata" is an ExpressPoint, as the consumer will express an Interest of this name with CanBePrefix. The node at "/prefix/<filename>/32=metadata/<v=version>" is a LeafNode.
func (*ExpressPoint) Get ¶
func (n *ExpressPoint) Get(propName PropKey) any
Get a property or callback event
func (*ExpressPoint) Init ¶
func (n *ExpressPoint) Init(parent NTNode, edge enc.ComponentPattern)
func (*ExpressPoint) Need ¶
func (n *ExpressPoint) Need( matching enc.Matching, name enc.Name, appParam enc.Wire, context Context, ) chan NeedResult
Need is the function to obtain the corresponding Data. May express an Interest if the Data is not stored. Name is constructed from matching if nil. If given, name must agree with matching. TODO: 1. Need we make it non-blocking and return future/channel? 2. Need we use a different type than ndn.InterestResult? 3. Need we use []byte instead of enc.Wire, given that the performance is not a big consideration here?
func (*ExpressPoint) OnInterest ¶
func (n *ExpressPoint) OnInterest( interest ndn.Interest, rawInterest enc.Wire, sigCovered enc.Wire, reply ndn.ReplyFunc, deadline time.Time, matching enc.Matching, )
OnInterest is the function called when an Interest comes.
func (*ExpressPoint) SearchCache ¶
type LeafNode ¶
type LeafNode struct { ExpressPoint // contains filtered or unexported fields }
LeafNode is a leaf of the NTSchema tree, a point where Data packets can be named.
func (*LeafNode) Provide ¶
func (n *LeafNode) Provide( matching enc.Matching, name enc.Name, content enc.Wire, context Context, ) enc.Wire
Provide a Data packet with given name and content. Name is constructed from matching if nil. If given, name must agree with matching. TODO: make sure code handles when context or matching is nil.
type NTNode ¶
type NTNode interface { // NodeTrait is the type trait of NTNode NodeTrait() NTNode // Child of given edge Child(edge enc.ComponentPattern) NTNode // Children include all children of a node Children() []NTNode // Parent of this node Parent() NTNode // UpEdge is the edge value from its parent to itself UpEdge() enc.ComponentPattern // Depth of the node in the tree. // It includes the attached prefix, so the root node may have a positive depth Depth() uint // Match an NDN name to a (variable) matching // TODO: do people like the current matching or a simpler version that makes everything into []byte? Match(name enc.Name) (NTNode, enc.Matching) // Apply a (variable) matching and obtain the corresponding NDN name Apply(matching enc.Matching) enc.Name // Get a property or callback event // TODO: reflection may be better than manual implementation? Get(propName PropKey) any // Set a property // Please use Get to set callback event. // To avoid annoying type cast, consider use AddEventListener to help. Set(propName PropKey, value any) error // ConstructName is the aux function used by Apply ConstructName(matching enc.Matching, ret enc.Name) error // OnInterest is the callback function when there is an incoming Interest. OnInterest(interest ndn.Interest, rawInterest enc.Wire, sigCovered enc.Wire, reply ndn.ReplyFunc, deadline time.Time, matching enc.Matching) // OnAttach is called when the node is attached to an engine OnAttach(path enc.NamePattern, engine ndn.Engine) error // OnDetach is called when the node is detached from an engine OnDetach() // At gets a node/subtree at a given pattern path. The path does not include the attached prefix. At(path enc.NamePattern) NTNode // PutNode puts a node/subtree at a given pattern path. The path does not include the attached prefix. // The path must not be put with an existing node. // The node will be initialized after PutNode. // Note: the correct sig of this func should be Put[T NTNode](path), but golang provents this. PutNode(path enc.NamePattern, node NTNode) error // Init initializes a node with a specified parent and edge // This is the first part where one can modify the properties of the node. // It acts as the constructor, so the properties set here are the default values, and will be // overwriten by the policies' apply(). Init(parent NTNode, edge enc.ComponentPattern) // AttachedPrefix returns the attached prefix if this node is the root of a schema tree. // Return nil otherwise. AttachedPrefix() enc.Name // SetAttachedPrefix set the attached prefix if the node is the root of a schema tree. SetAttachedPrefix(enc.Name) error }
NTNode represents a node (subtree) of NTSchema. See comments for NTPolicy below for more details TODO: See also BaseNode for TODO points
type NTPolicy ¶
type NTPolicy interface { // PolicyTrait is the type trait of NTPolicy PolicyTrait() NTPolicy // Apply the policy at a node (subtree). May modify the children of the given node. // The execution order is node.Init() -> policy.Apply() -> onAttach() // So the properties set here will overwrite Init()'s default values, // but be overwriten by onAttach(). Apply(node NTNode) error }
NTPolicy represents a policy, which is a modifier that sets properties and registers events during the initialization of a schema tree. The execution order is: construct the tree -> apply policies & env setup -> attach to engine (see Tree) Though policies are also considered as static knowledge (at compile time), they may be configured differently on different nodes. For example, an storage may access different folders for different instances. TODO: Design for this configuration under different environments. For example, the path to a storage, the name of the self-key, etc are knowledge specific to one instance, and thus dynamically configured. Currently I don't have an idea on the best way to separate the "statically shared part" (NTTree and the nodes) and the "dynamically configure part". (#ENV)
type NeedResult ¶
type NeedResult struct { Status ndn.InterestResult Content enc.Wire }
func (NeedResult) Get ¶
func (r NeedResult) Get() (ndn.InterestResult, enc.Wire)
type NodeGetSignerEvent ¶
NodeGetSignerEvent is the event triggered when the node needs a signer for an Interest or a Data. When there are multiple callbacks, the first non-nil signer returned is taken. Args: name matching, full name, context Context: (user defined fields only)
type NodeOnAttachEvent ¶
type NodeOnAttachEvent = func(enc.NamePattern, ndn.Engine) error
NodeOnAttachEvent is the event triggered when attaching to an engine. This is called after the tree is built and policies are attached, so the properties modified here will overwrite the properties set before. Args: the path to this node, the engine to attach Return: a non-nil error to abort attaching. Nil when it can continue.
type NodeOnDetachEvent ¶
NodeOnDetachEvent is the event triggered when detaching from the engine.
type NodeOnIntEvent ¶
NodeOnIntEvent is the event triggered when an Interest is received. Only used by ExpressingPoint and LeafNode. Args: name matching, app params, reply, context Return: whether to abort processing (ignore events after the current one) Context: CkInterest, CkDeadline, CkRawPacket, CkSigCovered, CkName, CkEngine, CkContent(=AppParam)
type NodeSaveStorageEvent ¶
NodeSaveStorageEvent is the event triggered when the node stores the Data into the storage. Args: name matching, full name, raw data packet, validity time (See CkValidDuration), context Context: CkData, CkRawPacket, CkSigCovered, CkName, CkEngine, CkContent
type NodeSearchStorageEvent ¶
NodeSearchStorageEvent is the event triggered when the node searches the storage for data. Used by ExpressingPoint and LeafNode. Args: name matching, full name, can be prefix, must be fresh, context Return: the raw wire of Data packet. Nil if not existing Context: CkInterest, CkDeadline, CkRawPacket, CkSigCovered, CkName, CkEngine, CkContent(=AppParam)
type NodeValidateEvent ¶
NodeValidateEvent is the event triggered when the node needs to validate an Interest or a Data Used by ExpressingPoint and LeafNode. Args: name matching, full name, signature, covered part, context Return: the result of current validation process Context: CkInterest/CkData, CkName, CkDeadline, CkRawPacket, CkSigCovered, CkEngine, CkContent(=Content/AppParam) CkLastValidResult (the VrResult given by the last callback in the chain)
type PropKey ¶
type PropKey string
PropKey is the type of properties of a node. A property of a node gives the default setting of some procedure as well as event callbacks. We design in this way to support DSL and WASM in future.
const ( // The event called when the node is attached to an engine. [NodeOnAttachEvent] PropOnAttach PropKey = "OnAttach" // The event called when the node is detached from an engine. [NodeOnDetachEvent] PropOnDetach PropKey = "OnDetach" // The event called when an ExpressingPoint or LeafNode receives an Interest. [NodeOnIntEvent] PropOnInterest PropKey = "OnInterest" // The event called when an ExpressingPoint or LeafNode verifies the signature of an Interest. [NodeValidateEvent] PropOnValidateInt PropKey = "OnValidateInt" // The event called when an ExpressingPoint or LeafNode verifies the signature of a Data. [NodeValidateEvent] PropOnValidateData PropKey = "OnValidateData" // The event called when an ExpressingPoint or LeafNode searches the storage on Need(). [NodeSearchStorageEvent] PropOnSearchStorage PropKey = "OnSearchStorage" // The event called to get a signer for an Interest PropOnGetIntSigner PropKey = "OnGetIntSigner" // The event called to get a signer for a Data PropOnGetDataSigner PropKey = "OnGetDataSigner" // The event called when an ExpressingPoint or LeafNode saves a packet into the storage. // The packet may be produced locally or fetched from the network. // TODO: Add a sign to distinguish them. // [NodeSaveStorageEvent] PropOnSaveStorage PropKey = "OnSaveStorage" // Default CanBePrefix for outgoing Interest. [bool] PropCanBePrefix PropKey = "CanBePrefix" // Default MustBeFresh for outgoing Interest. [bool] PropMustBeFresh PropKey = "MustBeFresh" // Default Lifetime for outgoing Interest. [time.Duration] PropLifetime PropKey = "Lifetime" // If true, only local storage is searched. No Interest will be expressed. // Note: may be overwritten by the Context. // [bool] PropSuppressInt PropKey = "SupressInt" // Default ContentType for produced Data. [ndn.ContentType] PropContentType PropKey = "ContentType" // Default FreshnessPeriod for produced Data. [time.Duration] PropFreshness PropKey = "Freshness" // See CkValidDuration. [time.Duration] PropValidDuration PropKey = "ValidDuration" )
type Tree ¶
Tree represents an NTSchema tree. It is supposed to be a static knowledge and shared by all parties in the system at compile time. The execution order: construct the tree -> apply policies & env setup -> attach to engine
func (*Tree) At ¶
func (t *Tree) At(path enc.NamePattern) NTNode
At the path return the node. Path does not include the attached prefix.
type ValidRes ¶
type ValidRes = int
ValidRes is the result of data/interest signature validation, given by one validator. When there are multiple validators chained, a packet is valid when there is at least one VrPass and no VrFail.
const ( VrFail ValidRes = -2 // An immediate failure. Abort the validation. VrTimeout ValidRes = -1 // Timeout. Abort the validation. VrSilence ValidRes = 0 // The current validator cannot give any result. VrPass ValidRes = 1 // The current validator approves the packet. VrBypass ValidRes = 2 // An immediate success. Bypasses the rest validators that are not executed yet. VrCachedData ValidRes = 3 // The data is obtained from a local cache, and the signature is checked before. )