|
@@ -70,6 +70,67 @@ func TestSetRemoteTraffic_AttributesOriginNodeGuid(t *testing.T) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// A cloned node reports its OWN inbound with its own (duplicated) panelGuid as
|
|
|
|
|
+// the origin. That must be remapped to the node-unique key, not stored verbatim
|
|
|
|
|
+// — otherwise origin_node_guid keeps the shared GUID while online is keyed by
|
|
|
|
|
+// the node-unique key, and the inbound page reads an empty bucket (shows
|
|
|
|
|
+// offline). A genuinely forwarded sub-node GUID is still kept across the hop.
|
|
|
|
|
+func TestSetRemoteTraffic_RemapsClonedNodeOwnGuidOrigin(t *testing.T) {
|
|
|
|
|
+ setupConflictDB(t)
|
|
|
|
|
+ db := database.GetDB()
|
|
|
|
|
+
|
|
|
|
|
+ // Two nodes share one panelGuid (cloned servers).
|
|
|
|
|
+ for _, n := range []*model.Node{
|
|
|
|
|
+ {Id: 1, Name: "a", Address: "10.0.0.1", Port: 2053, ApiToken: "t", Guid: "dup"},
|
|
|
|
|
+ {Id: 2, Name: "b", Address: "10.0.0.2", Port: 2053, ApiToken: "t", Guid: "dup"},
|
|
|
|
|
+ } {
|
|
|
|
|
+ if err := db.Create(n).Error; err != nil {
|
|
|
|
|
+ t.Fatalf("create node %s: %v", n.Name, err)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ snap := &runtime.TrafficSnapshot{
|
|
|
|
|
+ Inbounds: []*model.Inbound{
|
|
|
|
|
+ { // node 1's OWN inbound, reporting its own (shared) panelGuid as origin
|
|
|
|
|
+ Tag: "own-443-tcp",
|
|
|
|
|
+ Enable: true,
|
|
|
|
|
+ Port: 443,
|
|
|
|
|
+ Protocol: model.VLESS,
|
|
|
|
|
+ Settings: `{"clients":[]}`,
|
|
|
|
|
+ OriginNodeGuid: "dup",
|
|
|
|
|
+ },
|
|
|
|
|
+ { // forwarded from a sub-node with a distinct guid — kept across the hop
|
|
|
|
|
+ Tag: "fwd-8443-tcp",
|
|
|
|
|
+ Enable: true,
|
|
|
|
|
+ Port: 8443,
|
|
|
|
|
+ Protocol: model.VLESS,
|
|
|
|
|
+ Settings: `{"clients":[]}`,
|
|
|
|
|
+ OriginNodeGuid: "child-guid",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ svc := InboundService{}
|
|
|
|
|
+ if _, err := svc.setRemoteTrafficLocked(1, snap, false); err != nil {
|
|
|
|
|
+ t.Fatalf("setRemoteTrafficLocked: %v", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ origin := func(tag string) string {
|
|
|
|
|
+ var ib model.Inbound
|
|
|
|
|
+ if err := db.Where("tag = ?", tag).First(&ib).Error; err != nil {
|
|
|
|
|
+ t.Fatalf("load inbound %q: %v", tag, err)
|
|
|
|
|
+ }
|
|
|
|
|
+ return ib.OriginNodeGuid
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if og := origin("own-443-tcp"); og != "node:1" {
|
|
|
|
|
+ t.Fatalf("cloned node's own inbound origin = %q, want node:1 (remapped from shared GUID)", og)
|
|
|
|
|
+ }
|
|
|
|
|
+ if og := origin("fwd-8443-tcp"); og != "child-guid" {
|
|
|
|
|
+ t.Fatalf("forwarded inbound origin = %q, want child-guid (kept across the hop)", og)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func TestSetRemoteTraffic_PreservesLocalShareAddressStrategy(t *testing.T) {
|
|
func TestSetRemoteTraffic_PreservesLocalShareAddressStrategy(t *testing.T) {
|
|
|
setupConflictDB(t)
|
|
setupConflictDB(t)
|
|
|
db := database.GetDB()
|
|
db := database.GetDB()
|