Skip to content
This repository has been archived by the owner on Apr 2, 2020. It is now read-only.

Commit

Permalink
Merge pull request #32 from booster-proj/issue/31
Browse files Browse the repository at this point in the history
Issue/31
  • Loading branch information
dmorn authored Feb 1, 2019
2 parents 682f734 + e44697e commit c134bf9
Show file tree
Hide file tree
Showing 6 changed files with 326 additions and 87 deletions.
4 changes: 2 additions & 2 deletions remote/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ func makePoliciesHandler(s *store.SourceStore) http.HandlerFunc {

func makePoliciesDelHandler(s *store.SourceStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
err := s.DelPolicy(mux.Vars(r)["id"])
id := mux.Vars(r)["id"]
err := s.DelPolicy(id)
if err != nil {
writeError(w, err, http.StatusNotFound)
return
Expand Down Expand Up @@ -160,7 +161,6 @@ func makePoliciesAvoidHandler(s *store.SourceStore) http.HandlerFunc {
return
}


p := store.NewAvoidPolicy(payload.Issuer, payload.SourceID, payload.Target)
p.Reason = payload.Reason
handlePolicy(s, p, w, r)
Expand Down
2 changes: 1 addition & 1 deletion source/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (i *Interface) SetMetricsExporter(exp MetricsExporter) {

// ID implements the core.Source interface.
func (i *Interface) ID() string {
return i.ifi.HardwareAddr.String()
return i.ifi.Name
}

// DialContext dials a connection of type `network` to `address`. If an error is
Expand Down
123 changes: 92 additions & 31 deletions store/policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,48 @@
package store

import (
"context"
"fmt"
"net"
"time"
)

type HostResolver interface {
// Returns all ip addresses associated with `host`
LookupHost(ctx context.Context, host string) (addrs []string, err error)
// Returns at least an host associated with `addr`
LookupAddr(ctx context.Context, addr string) (hosts []string, err error)
}

var Resolver HostResolver = &net.Resolver{}

// Policy codes, different for each `Policy` created.
const (
PolicyCodeBlock int = iota + 1
PolicyCodeReserve
PolicyCodeStick
PolicyCodeAvoid
)

type basePolicy struct {
Name string `json:"id"`

// Reason explains why this policy exists.
Reason string `json:"reason"`

// Issuer tells where this policy comes from.
Issuer string `json:"issuer"`

// Code is the code of the policy, usefull when the policy
// is delivered to another context.
Code int `json:"code"`

// Desc describes how the policy acts.
Desc string `json:"description"`

// Addrs is the list of address address that the
// policy takes into consideration.
Addrs []string `json:"addresses"`
}

func (p basePolicy) ID() string {
Expand All @@ -54,16 +75,16 @@ type GenPolicy struct {

// AcceptFunc is used as implementation
// of Accept.
AcceptFunc func(id, target string) bool `json:"-"`
AcceptFunc func(id, address string) bool `json:"-"`
}

func (p *GenPolicy) ID() string {
return p.Name
}

// Accept implements Policy.
func (p *GenPolicy) Accept(id, target string) bool {
return p.AcceptFunc(id, target)
func (p *GenPolicy) Accept(id, address string) bool {
return p.AcceptFunc(id, address)
}

// BlockPolicy blocks `SourceID`.
Expand All @@ -86,79 +107,96 @@ func NewBlockPolicy(issuer, sourceID string) *BlockPolicy {
}

// Accept implements Policy.
func (p *BlockPolicy) Accept(id, target string) bool {
func (p *BlockPolicy) Accept(id, address string) bool {
return id != p.SourceID
}

// ReservedPolicy is a Policy implementation. It is used to reserve a source
// for a specific connection target. Note that this does not mean that the
// others sources may not receive a connection to target, it just means that
// `SourceID` will not accept any other connection exept the ones that go to
// `Target`.
// to be used only for connections to a defined address, and those connections
// will not be assigned to any other source.
type ReservedPolicy struct {
basePolicy
SourceID string `json:"reserved_source_id"`
Target string `json:"target"`
Address string `json:"address"`
}

func NewReservedPolicy(issuer, sourceID, target string) *ReservedPolicy {
func NewReservedPolicy(issuer, sourceID, address string) *ReservedPolicy {
address = TrimPort(address)
return &ReservedPolicy{
basePolicy: basePolicy{
Name: fmt.Sprintf("reserve_%s_for_%s", sourceID, target),
Name: fmt.Sprintf("reserve_%s_for_%s", sourceID, address),
Issuer: issuer,
Code: PolicyCodeReserve,
Desc: fmt.Sprintf("source %v will only be used for connections to %s", sourceID, target),
Desc: fmt.Sprintf("source %v will only be used for connections to %s", sourceID, address),
Addrs: LookupAddress(address),
},
SourceID: sourceID,
Target: target,
Address: address,
}
}

// Accept implements Policy.
func (p *ReservedPolicy) Accept(id, target string) bool {
if id == p.SourceID {
return target == p.Target
func (p *ReservedPolicy) Accept(id, address string) bool {
isIn := false
for _, v := range p.Addrs {
if address == v {
isIn = true
break
}
}
return true
if isIn {
return id == p.SourceID
}

return id != p.SourceID
}

// AvoidPolicy is a Policy implementation. It is used to avoid giving
// connection to `Target` to `SourceID`.
// connection to `Address` to `SourceID`.
type AvoidPolicy struct {
basePolicy
SourceID string `json:"avoid_source_id"`
Target string `json:"target"`
Address string `json:"address"`
}

func NewAvoidPolicy(issuer, sourceID, target string) *AvoidPolicy {
func NewAvoidPolicy(issuer, sourceID, address string) *AvoidPolicy {
address = TrimPort(address)
return &AvoidPolicy{
basePolicy: basePolicy{
Name: fmt.Sprintf("avoid_%s_for_%s", sourceID, target),
Name: fmt.Sprintf("avoid_%s_for_%s", sourceID, address),
Issuer: issuer,
Code: PolicyCodeReserve,
Desc: fmt.Sprintf("source %v will not be used for connections to %s", sourceID, target),
Code: PolicyCodeAvoid,
Desc: fmt.Sprintf("source %v will not be used for connections to %s", sourceID, address),
Addrs: LookupAddress(address),
},
SourceID: sourceID,
Target: target,
Address: address,
}
}

// Accept implements Policy.
func (p *AvoidPolicy) Accept(id, target string) bool {
if target == p.Target {
func (p *AvoidPolicy) Accept(id, address string) bool {
isIn := false
for _, v := range p.Addrs {
if address == v {
isIn = true
break
}
}
if isIn {
return id != p.SourceID
}
return true
}

// HistoryQueryFunc describes the function that is used to query the bind
// history of an entity. It is called passing the connection target in question,
// history of an entity. It is called passing the connection address in question,
// and it returns the source identifier that is associated to it and true,
// otherwise false if none is found.
type HistoryQueryFunc func(string) (string, bool)

// StickyPolicy is a Policy implementation. It is used to make connections to
// some target be always bound with the same source.
// some address be always bound with the same source.
type StickyPolicy struct {
basePolicy
BindHistory HistoryQueryFunc `json:"-"`
Expand All @@ -170,17 +208,40 @@ func NewStickyPolicy(issuer string, f HistoryQueryFunc) *StickyPolicy {
Name: "stick",
Issuer: issuer,
Code: PolicyCodeStick,
Desc: "once a source receives a connection to a target, the following connections to the same target will be assigned to the same source",
Desc: "once a source receives a connection to a address, the following connections to the same address will be assigned to the same source",
},
BindHistory: f,
}
}

// Accept implements Policy.
func (p *StickyPolicy) Accept(id, target string) bool {
if hid, ok := p.BindHistory(target); ok {
func (p *StickyPolicy) Accept(id, address string) bool {
if hid, ok := p.BindHistory(address); ok {
return id == hid
}

return true
}

// TrimPort removes port information from `address`.
func TrimPort(address string) string {
host, _, err := net.SplitHostPort(address)
if err == nil {
return host
}
return address
}

// LookupAddress finds the addresses associated with `address`. If it
// is not able to lookup, it just returns `address` wrapped into a list.
func LookupAddress(address string) []string {
address = TrimPort(address)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

names, err := Resolver.LookupHost(ctx, address)
if err != nil {
return []string{address}
}
return names
}
Loading

0 comments on commit c134bf9

Please sign in to comment.