package delivery import ( "encoding/json" "fmt" "git.novox.be/novox/mesh-sdk/go/catalogue" ) // A node's record is what the machine observes of itself (issue 1126, ADR 0555 ยง3), written by its own agent in its // own have key, `.node` of the node-engine's have bucket (HaveNode.Record), whenever an observed fact changes and // only when the value differs. The key's change is the event its readers hear: every node and the parts that compose // watch it. Where a module runs, and every fact a person decides of the node (its endpoint, site, hub, address on the // private network, public domain, accounts, the tunnel found at adoption), are the catalogue's placement // (placement.go). Nothing in it is secret: its keys are public halves. // RecordTunnel is a tunnel found on a node when it was adopted, as compose.Tunnel holds it: public keys and addresses // only. After the node took it over the tunnel is no longer there to observe, so it is kept as what was decided at // adoption, in the node's placement (NodeDecided.Tunnel). type RecordTunnel struct { Interface string `json:"interface"` Unit string `json:"unit,omitempty"` Config string `json:"config,omitempty"` Port int `json:"port,omitempty"` MTU int `json:"mtu,omitempty"` Address string `json:"address,omitempty"` Range string `json:"range,omitempty"` PublicKey string `json:"public-key,omitempty"` Peers []RecordTunnelPeer `json:"peers,omitempty"` } // RecordTunnelPeer is one peer of a found tunnel. type RecordTunnelPeer struct { PublicKey string `json:"public-key"` Address string `json:"address,omitempty"` } // NodeRecord is one node's record: what the machine observes of itself (issue 1126, ADR 0555: what a person decides // lives in the catalogue's placement file, Placement.Decided; what the machine observes lives here). TunnelKey is the // public key of its private-network tunnel; Certificate the one the mesh issued for its internal name, public, as the // node holds it. The tunnel found at adoption and the names given to its peers are decisions kept in the placement; // whether the hub took its found tunnel over, and which node enrolled under a carried peer's key, are read from both. type NodeRecord struct { V int `json:"v"` Node string `json:"node"` TunnelKey string `json:"tunnel-key,omitempty"` Capabilities []string `json:"capabilities,omitempty"` SealingKey string `json:"sealing-key,omitempty"` ServingKey string `json:"serving-key,omitempty"` Certificate string `json:"certificate,omitempty"` OutwardLinks []string `json:"outward-links,omitempty"` Networks []catalogue.AttachedNetwork `json:"networks,omitempty"` NetworksSaid bool `json:"networks-said,omitempty"` Contract int `json:"contract,omitempty"` // Authority is the mesh's own certificate as this machine holds it (public): the one its declaration last wrote where // a module asked for it. A node composing its own composes a certificate with it (compose.Input.Authority). Authority string `json:"authority,omitempty"` } func (r NodeRecord) check() error { if err := checkName("node", r.Node); err != nil { return err } for _, c := range r.Capabilities { if c == "" { return fmt.Errorf("delivery: the record of %s names an empty capability", r.Node) } } return nil } // EncodeNodeRecord is r as JSON at Version; it refuses what DecodeNodeRecord refuses. func EncodeNodeRecord(r NodeRecord) ([]byte, error) { if err := r.check(); err != nil { return nil, err } r.V = Version return json.Marshal(r) } // DecodeNodeRecord reads a node record; it refuses an unknown version (ErrUnknownVersion), a node that is not a name, and // an empty capability. func DecodeNodeRecord(data []byte) (NodeRecord, error) { var r NodeRecord if err := decode(data, &r); err != nil { return NodeRecord{}, err } if err := r.check(); err != nil { return NodeRecord{}, err } return r, nil } // SameNodeRecord says whether two records are the same value, so the agent writes only when they differ. func SameNodeRecord(a, b NodeRecord) bool { a.V, b.V = 0, 0 return jsonEqual(a, b) }