Added read signal, and modified policies to use non-pointer receivers

gql_cataclysm
noah metz 2023-07-28 11:21:18 -06:00
parent b3de3144cc
commit fc69bc3d0d
8 changed files with 132 additions and 25 deletions

@ -785,6 +785,14 @@ type GQLExt struct {
SubscribeListeners []chan Signal
}
func (ext *GQLExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*GQLExt)interface{}{
"listen": func(ext *GQLExt) interface{} {
return ext.Listen
},
})
}
func (ext *GQLExt) NewSubscriptionChannel(buffer int) chan Signal {
ext.SubscribeLock.Lock()
defer ext.SubscribeLock.Unlock()

@ -91,7 +91,7 @@ func NewSimpleListener(ctx *Context, buffer int) (*Node, *ListenerExt) {
SimpleListenerNodeType,
nil,
listener_extension,
NewACLExt(&policy),
NewACLExt(policy),
NewLockableExt())
return listener, listener_extension

@ -19,6 +19,17 @@ func NewListenerExt(buffer int) *ListenerExt {
}
}
func (ext *ListenerExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*ListenerExt)interface{}{
"buffer": func(ext *ListenerExt) interface{} {
return ext.Buffer
},
"chan": func(ext *ListenerExt) interface{} {
return ext.Chan
},
})
}
// Simple load function, unmarshal the buffer int from json
func LoadListenerExt(ctx *Context, data []byte) (Extension, error) {
var j int
@ -66,6 +77,23 @@ type LockableExtJSON struct {
Dependencies map[string]string `json:"dependencies"`
}
func (ext *LockableExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*LockableExt)interface{}{
"owner": func(ext *LockableExt) interface{} {
return ext.Owner
},
"pending_owner": func(ext *LockableExt) interface{} {
return ext.PendingOwner
},
"requirements": func(ext *LockableExt) interface{} {
return ext.Requirements
},
"dependencies": func(ext *LockableExt) interface{} {
return ext.Dependencies
},
})
}
func LoadLockableExt(ctx *Context, data []byte) (Extension, error) {
var j LockableExtJSON
err := json.Unmarshal(data, &j)

@ -26,13 +26,13 @@ func TestLink(t *testing.T) {
l1_listener := NewListenerExt(10)
l1 := NewNode(ctx, RandID(), TestLockableType, nil,
l1_listener,
NewACLExt(&link_policy),
NewACLExt(link_policy),
NewLockableExt(),
)
l2_listener := NewListenerExt(10)
l2 := NewNode(ctx, RandID(), TestLockableType, nil,
l2_listener,
NewACLExt(&link_policy),
NewACLExt(link_policy),
NewLockableExt(),
)
@ -57,7 +57,7 @@ func TestLock(t *testing.T) {
listener := NewListenerExt(10)
l := NewNode(ctx, RandID(), TestLockableType, nil,
listener,
NewACLExt(&lock_policy, &link_policy),
NewACLExt(lock_policy, link_policy),
NewLockableExt(),
)
return l, listener

@ -72,6 +72,7 @@ type Serializable[I comparable] interface {
// Extensions are data attached to nodes that process signals
type Extension interface {
Serializable[ExtType]
Field(string)interface{}
Process(context *Context, source NodeID, node *Node, signal Signal)
}
@ -142,6 +143,27 @@ type Msg struct {
Signal Signal
}
func ReadNodeFields(ctx *Context, self *Node, princ NodeID, reqs map[ExtType][]string)map[ExtType]map[string]interface{} {
exts := map[ExtType]map[string]interface{}{}
for ext_type, field_reqs := range(reqs) {
fields := map[string]interface{}{}
for _, req := range(field_reqs) {
err := Allowed(ctx, princ, MakeAction(ReadSignalType, ext_type, req), self)
if err != nil {
fields[req] = err
} else {
ext, exists := self.Extensions[ext_type]
if exists == false {
fields[req] = fmt.Errorf("%s does not have %s extension", self.ID, ext_type)
} else {
fields[req] = ext.Field(req)
}
}
}
}
return exts
}
// Main Loop for Threads, starts a write context, so cannot be called from a write or read context
func nodeLoop(ctx *Context, node *Node) error {
started := node.Active.CompareAndSwap(false, true)
@ -171,7 +193,16 @@ func nodeLoop(ctx *Context, node *Node) error {
if signal.Type() == StopSignalType {
node.Process(ctx, node.ID, NewStatusSignal("stopped", node.ID))
break
} else if signal.Type() == ReadSignalType {
read_signal, ok := signal.(ReadSignal)
if ok == false {
ctx.Log.Logf("signal", "READ_SIGNAL: bad cast %+v", signal)
} else {
fields := ReadNodeFields(ctx, node, source, read_signal.Extensions)
ctx.Log.Logf("test", "READ_RESULT: %+v", fields)
}
}
node.Process(ctx, source, signal)
}

@ -22,11 +22,11 @@ type Policy interface {
Merge(Policy) Policy
}
func (policy *AllNodesPolicy) Allows(principal_id NodeID, action Action, node *Node) error {
func (policy AllNodesPolicy) Allows(principal_id NodeID, action Action, node *Node) error {
return policy.Actions.Allows(action)
}
func (policy *PerNodePolicy) Allows(principal_id NodeID, action Action, node *Node) error {
func (policy PerNodePolicy) Allows(principal_id NodeID, action Action, node *Node) error {
for id, actions := range(policy.NodeActions) {
if id != principal_id {
continue
@ -36,7 +36,7 @@ func (policy *PerNodePolicy) Allows(principal_id NodeID, action Action, node *No
return fmt.Errorf("%s is not in per node policy of %s", principal_id, node.ID)
}
func (policy *RequirementOfPolicy) Allows(principal_id NodeID, action Action, node *Node) error {
func (policy RequirementOfPolicy) Allows(principal_id NodeID, action Action, node *Node) error {
lockable_ext, err := GetExt[*LockableExt](node)
if err != nil {
return err
@ -54,7 +54,7 @@ func (policy *RequirementOfPolicy) Allows(principal_id NodeID, action Action, no
type RequirementOfPolicy struct {
AllNodesPolicy
}
func (policy *RequirementOfPolicy) Type() PolicyType {
func (policy RequirementOfPolicy) Type() PolicyType {
return RequirementOfPolicyType
}
@ -83,20 +83,20 @@ func MergeNodeActions(modified NodeActions, read NodeActions) {
}
}
func (policy *PerNodePolicy) Merge(p Policy) Policy {
other := p.(*PerNodePolicy)
func (policy PerNodePolicy) Merge(p Policy) Policy {
other := p.(PerNodePolicy)
MergeNodeActions(policy.NodeActions, other.NodeActions)
return policy
}
func (policy *AllNodesPolicy) Merge(p Policy) Policy {
other := p.(*AllNodesPolicy)
func (policy AllNodesPolicy) Merge(p Policy) Policy {
other := p.(AllNodesPolicy)
policy.Actions = MergeActions(policy.Actions, other.Actions)
return policy
}
func (policy *RequirementOfPolicy) Merge(p Policy) Policy {
other := p.(*RequirementOfPolicy)
func (policy RequirementOfPolicy) Merge(p Policy) Policy {
other := p.(RequirementOfPolicy)
policy.Actions = MergeActions(policy.Actions, other.Actions)
return policy
}
@ -190,11 +190,11 @@ type PerNodePolicy struct {
NodeActions NodeActions `json:"node_actions"`
}
func (policy *PerNodePolicy) Type() PolicyType {
func (policy PerNodePolicy) Type() PolicyType {
return PerNodePolicyType
}
func (policy *PerNodePolicy) Serialize() ([]byte, error) {
func (policy PerNodePolicy) Serialize() ([]byte, error) {
return json.MarshalIndent(policy, "", " ")
}
@ -212,11 +212,11 @@ type AllNodesPolicy struct {
Actions Actions
}
func (policy *AllNodesPolicy) Type() PolicyType {
func (policy AllNodesPolicy) Type() PolicyType {
return AllNodesPolicyType
}
func (policy *AllNodesPolicy) Serialize() ([]byte, error) {
func (policy AllNodesPolicy) Serialize() ([]byte, error) {
return json.MarshalIndent(policy, "", " ")
}
@ -288,6 +288,14 @@ func (ext *ACLExt) Serialize() ([]byte, error) {
func (ext *ACLExt) Process(ctx *Context, princ_id NodeID, node *Node, signal Signal) {
}
func (ext *ACLExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*ACLExt)interface{}{
"policies": func(ext *ACLExt) interface{} {
return ext.Policies
},
})
}
func NewACLExt(policies ...Policy) *ACLExt {
policy_map := map[PolicyType]Policy{}
for _, policy := range(policies) {

@ -9,6 +9,7 @@ const (
StatusSignalType = SignalType("STATUS")
LinkSignalType = SignalType("LINK")
LockSignalType = SignalType("LOCK")
ReadSignalType = SignalType("READ")
)
type SignalDirection int
@ -144,14 +145,14 @@ func (signal StateSignal) Permission() Action {
return MakeAction(signal.Type(), signal.State)
}
type StartChildSignal struct {
IDSignal
Action string `json:"action"`
type ReadSignal struct {
BaseSignal
Extensions map[ExtType][]string `json:"extensions"`
}
func NewStartChildSignal(child_id NodeID, action string) StartChildSignal {
return StartChildSignal{
IDSignal: NewIDSignal("start_child", Direct, child_id),
Action: action,
func NewReadSignal(exts map[ExtType][]string) ReadSignal {
return ReadSignal{
BaseSignal: NewDirectSignal(ReadSignalType),
Extensions: exts,
}
}

@ -14,6 +14,29 @@ type ECDHExt struct {
Shared []byte
}
func ResolveFields[T Extension](t T, name string, field_funcs map[string]func(T)interface{})interface{} {
var zero T
field_func, ok := field_funcs[name]
if ok == false {
return fmt.Errorf("%s is not a field of %s", name, zero.Type())
}
return field_func(t)
}
func (ext *ECDHExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*ECDHExt)interface{}{
"granted": func(ext *ECDHExt) interface{} {
return ext.Granted
},
"pubkey": func(ext *ECDHExt) interface{} {
return ext.Pubkey
},
"shared": func(ext *ECDHExt) interface{} {
return ext.Shared
},
})
}
type ECDHExtJSON struct {
Granted time.Time `json:"granted"`
Pubkey []byte `json:"pubkey"`
@ -88,6 +111,14 @@ func (ext *GroupExt) Serialize() ([]byte, error) {
}, "", " ")
}
func (ext *GroupExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*GroupExt)interface{}{
"members": func(ext *GroupExt) interface{} {
return ext.Members
},
})
}
func NewGroupExt(members map[NodeID]string) *GroupExt {
if members == nil {
members = map[NodeID]string{}