Hunter0x7c7
2022-08-11 a82f9cb69f63aaeba40c024960deda7d75b9fece
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package command
 
import (
    "strings"
 
    "github.com/v2fly/v2ray-core/v5/common/net"
    "github.com/v2fly/v2ray-core/v5/features/routing"
)
 
// routingContext is an wrapper of protobuf RoutingContext as implementation of routing.Context and routing.Route.
type routingContext struct {
    *RoutingContext
}
 
func (c routingContext) GetSourceIPs() []net.IP {
    return mapBytesToIPs(c.RoutingContext.GetSourceIPs())
}
 
func (c routingContext) GetSourcePort() net.Port {
    return net.Port(c.RoutingContext.GetSourcePort())
}
 
func (c routingContext) GetTargetIPs() []net.IP {
    return mapBytesToIPs(c.RoutingContext.GetTargetIPs())
}
 
func (c routingContext) GetTargetPort() net.Port {
    return net.Port(c.RoutingContext.GetTargetPort())
}
 
// GetSkipDNSResolve is a mock implementation here to match the interface,
// SkipDNSResolve is set from dns module, no use if coming from a protobuf object?
// TODO: please confirm @Vigilans
func (c routingContext) GetSkipDNSResolve() bool {
    return false
}
 
// AsRoutingContext converts a protobuf RoutingContext into an implementation of routing.Context.
func AsRoutingContext(r *RoutingContext) routing.Context {
    return routingContext{r}
}
 
// AsRoutingRoute converts a protobuf RoutingContext into an implementation of routing.Route.
func AsRoutingRoute(r *RoutingContext) routing.Route {
    return routingContext{r}
}
 
var fieldMap = map[string]func(*RoutingContext, routing.Route){
    "inbound":        func(s *RoutingContext, r routing.Route) { s.InboundTag = r.GetInboundTag() },
    "network":        func(s *RoutingContext, r routing.Route) { s.Network = r.GetNetwork() },
    "ip_source":      func(s *RoutingContext, r routing.Route) { s.SourceIPs = mapIPsToBytes(r.GetSourceIPs()) },
    "ip_target":      func(s *RoutingContext, r routing.Route) { s.TargetIPs = mapIPsToBytes(r.GetTargetIPs()) },
    "port_source":    func(s *RoutingContext, r routing.Route) { s.SourcePort = uint32(r.GetSourcePort()) },
    "port_target":    func(s *RoutingContext, r routing.Route) { s.TargetPort = uint32(r.GetTargetPort()) },
    "domain":         func(s *RoutingContext, r routing.Route) { s.TargetDomain = r.GetTargetDomain() },
    "protocol":       func(s *RoutingContext, r routing.Route) { s.Protocol = r.GetProtocol() },
    "user":           func(s *RoutingContext, r routing.Route) { s.User = r.GetUser() },
    "attributes":     func(s *RoutingContext, r routing.Route) { s.Attributes = r.GetAttributes() },
    "outbound_group": func(s *RoutingContext, r routing.Route) { s.OutboundGroupTags = r.GetOutboundGroupTags() },
    "outbound":       func(s *RoutingContext, r routing.Route) { s.OutboundTag = r.GetOutboundTag() },
}
 
// AsProtobufMessage takes selectors of fields and returns a function to convert routing.Route to protobuf RoutingContext.
func AsProtobufMessage(fieldSelectors []string) func(routing.Route) *RoutingContext {
    initializers := []func(*RoutingContext, routing.Route){}
    for field, init := range fieldMap {
        if len(fieldSelectors) == 0 { // If selectors not set, retrieve all fields
            initializers = append(initializers, init)
            continue
        }
        for _, selector := range fieldSelectors {
            if strings.HasPrefix(field, selector) {
                initializers = append(initializers, init)
                break
            }
        }
    }
    return func(ctx routing.Route) *RoutingContext {
        message := new(RoutingContext)
        for _, init := range initializers {
            init(message, ctx)
        }
        return message
    }
}
 
func mapBytesToIPs(bytes [][]byte) []net.IP {
    var ips []net.IP
    for _, rawIP := range bytes {
        ips = append(ips, net.IP(rawIP))
    }
    return ips
}
 
func mapIPsToBytes(ips []net.IP) [][]byte {
    var bytes [][]byte
    for _, ip := range ips {
        bytes = append(bytes, []byte(ip))
    }
    return bytes
}