Initial project snapshot
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
package mesh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ValidateProductionEnvelopeRouteConfig(local PeerIdentity, envelope ProductionEnvelope, routes []SyntheticRoute, now time.Time) error {
|
||||
if len(routes) == 0 {
|
||||
return nil
|
||||
}
|
||||
route, ok := productionRouteByID(routes, envelope.RouteID)
|
||||
if !ok {
|
||||
return ErrRouteNotFound
|
||||
}
|
||||
if route.ClusterID != envelope.ClusterID || route.ClusterID != local.ClusterID {
|
||||
return ErrClusterMismatch
|
||||
}
|
||||
if route.SourceNodeID != envelope.SourceNodeID || route.DestinationNodeID != envelope.DestinationNodeID {
|
||||
return ErrInvalidRoutePath
|
||||
}
|
||||
if route.ExpiresAt.IsZero() || !route.ExpiresAt.After(now.UTC()) || envelope.ExpiresAt.After(route.ExpiresAt) {
|
||||
return ErrRouteExpired
|
||||
}
|
||||
if !contains(route.AllowedChannels, ProductionChannelFabricControl) {
|
||||
return ErrUnauthorizedChannel
|
||||
}
|
||||
path := routePath(route)
|
||||
if len(path) < 2 || path[0] != route.SourceNodeID || path[len(path)-1] != route.DestinationNodeID {
|
||||
return ErrInvalidRoutePath
|
||||
}
|
||||
if len(envelope.RoutePath) > 0 && !sameNodePath(envelope.RoutePath, path) {
|
||||
return ErrInvalidRoutePath
|
||||
}
|
||||
if len(path) > 2 && len(envelope.RoutePath) == 0 {
|
||||
return ErrInvalidRoutePath
|
||||
}
|
||||
currentIndex := indexOf(path, local.NodeID)
|
||||
if currentIndex < 0 || envelope.CurrentHopNodeID != local.NodeID {
|
||||
return ErrNodeMismatch
|
||||
}
|
||||
expectedNextHop := local.NodeID
|
||||
if local.NodeID != envelope.DestinationNodeID {
|
||||
if currentIndex >= len(path)-1 {
|
||||
return ErrInvalidRoutePath
|
||||
}
|
||||
expectedNextHop = path[currentIndex+1]
|
||||
}
|
||||
if envelope.NextHopNodeID != expectedNextHop {
|
||||
return ErrInvalidRoutePath
|
||||
}
|
||||
if route.MaxTTL > 0 && envelope.TTL > route.MaxTTL {
|
||||
return fmt.Errorf("%w: ttl exceeds configured route max_ttl", ErrForwardEnvelopeInvalid)
|
||||
}
|
||||
if route.MaxHops > 0 && envelope.HopCount > route.MaxHops {
|
||||
return fmt.Errorf("%w: hop_count exceeds configured route max_hops", ErrForwardEnvelopeInvalid)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func productionRouteByID(routes []SyntheticRoute, routeID string) (SyntheticRoute, bool) {
|
||||
for _, route := range routes {
|
||||
if route.RouteID == routeID {
|
||||
return route, true
|
||||
}
|
||||
}
|
||||
return SyntheticRoute{}, false
|
||||
}
|
||||
|
||||
func sameNodePath(a []string, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := range a {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user