Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 90 additions & 34 deletions src/presentation/runners/common/runtime_address_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,26 @@ import (
"net/netip"
clientConfiguration "tungo/infrastructure/PAL/configuration/client"
serverConfiguration "tungo/infrastructure/PAL/configuration/server"
"tungo/infrastructure/settings"
)

type RuntimeAddressPair struct {
IPv4 netip.Addr
IPv6 netip.Addr
}

func (p RuntimeAddressPair) IsValid() bool {
return p.IPv4.IsValid() || p.IPv6.IsValid()
}

type RuntimeProtocolAddress struct {
Protocol settings.Protocol
ServerAddress RuntimeAddressPair
TunnelAddress RuntimeAddressPair
}

type RuntimeAddressInfo struct {
ServerIPv4 netip.Addr
ServerIPv6 netip.Addr
TunnelIPv4 netip.Addr
TunnelIPv6 netip.Addr
ProtocolAddresses []RuntimeProtocolAddress
}

func RuntimeAddressInfoFromClientConfiguration(conf clientConfiguration.Configuration) RuntimeAddressInfo {
Expand All @@ -19,43 +32,86 @@ func RuntimeAddressInfoFromClientConfiguration(conf clientConfiguration.Configur
if err != nil {
return info
}
if serverIPv4, ok := activeSettings.Server.IPv4(); ok {
info.ServerIPv4 = serverIPv4
}
if serverIPv6, ok := activeSettings.Server.IPv6(); ok {
info.ServerIPv6 = serverIPv6
}
if activeSettings.IPv4.IsValid() {
info.TunnelIPv4 = activeSettings.IPv4
}
if activeSettings.IPv6.IsValid() {
info.TunnelIPv6 = activeSettings.IPv6
if protocolAddress, ok := newRuntimeProtocolAddress(
protocolOrFallback(activeSettings.Protocol, conf.Protocol),
runtimeAddressPairFromHost(activeSettings.Server),
runtimeAddressPairFromAddrs(activeSettings.IPv4, activeSettings.IPv6),
); ok {
info.ProtocolAddresses = append(info.ProtocolAddresses, protocolAddress)
}
return info
}

func RuntimeAddressInfoFromServerConfiguration(conf serverConfiguration.Configuration) RuntimeAddressInfo {
info := RuntimeAddressInfo{}
for _, s := range conf.EnabledSettings() {
if !info.ServerIPv4.IsValid() {
if serverIPv4, ok := s.Server.IPv4(); ok {
info.ServerIPv4 = serverIPv4
}
}
if !info.ServerIPv6.IsValid() {
if serverIPv6, ok := s.Server.IPv6(); ok {
info.ServerIPv6 = serverIPv6
}
}
if !info.TunnelIPv4.IsValid() && s.IPv4.IsValid() {
info.TunnelIPv4 = s.IPv4
}
if !info.TunnelIPv6.IsValid() && s.IPv6.IsValid() {
info.TunnelIPv6 = s.IPv6
}
if info.ServerIPv4.IsValid() && info.ServerIPv6.IsValid() && info.TunnelIPv4.IsValid() && info.TunnelIPv6.IsValid() {
break
for _, enabledSetting := range enabledProtocolSettings(conf) {
s := enabledSetting.settings
if protocolAddress, ok := newRuntimeProtocolAddress(
protocolOrFallback(s.Protocol, enabledSetting.protocol),
runtimeAddressPairFromHost(s.Server),
runtimeAddressPairFromAddrs(s.IPv4, s.IPv6),
); ok {
info.ProtocolAddresses = append(info.ProtocolAddresses, protocolAddress)
}
}
return info
}

type protocolSettings struct {
protocol settings.Protocol
settings settings.Settings
}

func enabledProtocolSettings(conf serverConfiguration.Configuration) []protocolSettings {
result := make([]protocolSettings, 0, 3)
if conf.EnableTCP {
result = append(result, protocolSettings{protocol: settings.TCP, settings: conf.TCPSettings})
}
if conf.EnableUDP {
result = append(result, protocolSettings{protocol: settings.UDP, settings: conf.UDPSettings})
}
if conf.EnableWS {
result = append(result, protocolSettings{protocol: settings.WS, settings: conf.WSSettings})
}
return result
}

func runtimeAddressPairFromHost(host settings.Host) RuntimeAddressPair {
var pair RuntimeAddressPair
if ipv4, ok := host.IPv4(); ok {
pair.IPv4 = ipv4
}
if ipv6, ok := host.IPv6(); ok {
pair.IPv6 = ipv6
}
return pair
}

func runtimeAddressPairFromAddrs(ipv4, ipv6 netip.Addr) RuntimeAddressPair {
return RuntimeAddressPair{
IPv4: ipv4,
IPv6: ipv6,
}
}

func newRuntimeProtocolAddress(
protocol settings.Protocol,
serverAddress RuntimeAddressPair,
tunnelAddress RuntimeAddressPair,
) (RuntimeProtocolAddress, bool) {
if !serverAddress.IsValid() && !tunnelAddress.IsValid() {
return RuntimeProtocolAddress{}, false
}
return RuntimeProtocolAddress{
Protocol: protocol,
ServerAddress: serverAddress,
TunnelAddress: tunnelAddress,
}, true
}

func protocolOrFallback(protocol, fallback settings.Protocol) settings.Protocol {
if protocol == settings.UNKNOWN {
return fallback
}
return protocol
}
133 changes: 115 additions & 18 deletions src/presentation/runners/common/runtime_address_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,23 @@ func TestRuntimeAddressInfoFromClientConfiguration(t *testing.T) {
}

got := RuntimeAddressInfoFromClientConfiguration(cfg)
if got.ServerIPv4 != netip.MustParseAddr("198.51.100.10") {
t.Fatalf("ServerIPv4: got %v", got.ServerIPv4)
if len(got.ProtocolAddresses) != 1 {
t.Fatalf("expected one protocol address entry, got %d", len(got.ProtocolAddresses))
}
if got.ServerIPv6 != netip.MustParseAddr("2001:db8::10") {
t.Fatalf("ServerIPv6: got %v", got.ServerIPv6)
if got.ProtocolAddresses[0].Protocol != settings.TCP {
t.Fatalf("ProtocolAddresses[0].Protocol: got %v", got.ProtocolAddresses[0].Protocol)
}
if got.TunnelIPv4 != netip.MustParseAddr("10.0.0.2") {
t.Fatalf("TunnelIPv4: got %v", got.TunnelIPv4)
if got.ProtocolAddresses[0].ServerAddress.IPv4 != netip.MustParseAddr("198.51.100.10") {
t.Fatalf("ProtocolAddresses[0].ServerAddress.IPv4: got %v", got.ProtocolAddresses[0].ServerAddress.IPv4)
}
if got.TunnelIPv6 != netip.MustParseAddr("fd00::2") {
t.Fatalf("TunnelIPv6: got %v", got.TunnelIPv6)
if got.ProtocolAddresses[0].ServerAddress.IPv6 != netip.MustParseAddr("2001:db8::10") {
t.Fatalf("ProtocolAddresses[0].ServerAddress.IPv6: got %v", got.ProtocolAddresses[0].ServerAddress.IPv6)
}
if got.ProtocolAddresses[0].TunnelAddress.IPv4 != netip.MustParseAddr("10.0.0.2") {
t.Fatalf("ProtocolAddresses[0].TunnelAddress.IPv4: got %v", got.ProtocolAddresses[0].TunnelAddress.IPv4)
}
if got.ProtocolAddresses[0].TunnelAddress.IPv6 != netip.MustParseAddr("fd00::2") {
t.Fatalf("ProtocolAddresses[0].TunnelAddress.IPv6: got %v", got.ProtocolAddresses[0].TunnelAddress.IPv6)
}
}

Expand All @@ -52,17 +58,66 @@ func TestRuntimeAddressInfoFromServerConfiguration(t *testing.T) {
}

got := RuntimeAddressInfoFromServerConfiguration(cfg)
if got.ServerIPv4 != netip.MustParseAddr("203.0.113.10") {
t.Fatalf("ServerIPv4: got %v", got.ServerIPv4)
if len(got.ProtocolAddresses) != 1 {
t.Fatalf("expected one protocol address entry, got %d", len(got.ProtocolAddresses))
}
if got.ProtocolAddresses[0].Protocol != settings.UDP {
t.Fatalf("ProtocolAddresses[0].Protocol: got %v", got.ProtocolAddresses[0].Protocol)
}
if got.ProtocolAddresses[0].ServerAddress.IPv4 != netip.MustParseAddr("203.0.113.10") {
t.Fatalf("ProtocolAddresses[0].ServerAddress.IPv4: got %v", got.ProtocolAddresses[0].ServerAddress.IPv4)
}
if got.ServerIPv6 != netip.MustParseAddr("2001:db8::20") {
t.Fatalf("ServerIPv6: got %v", got.ServerIPv6)
if got.ProtocolAddresses[0].ServerAddress.IPv6 != netip.MustParseAddr("2001:db8::20") {
t.Fatalf("ProtocolAddresses[0].ServerAddress.IPv6: got %v", got.ProtocolAddresses[0].ServerAddress.IPv6)
}
if got.TunnelIPv4 != netip.MustParseAddr("10.1.0.1") {
t.Fatalf("TunnelIPv4: got %v", got.TunnelIPv4)
if got.ProtocolAddresses[0].TunnelAddress.IPv4 != netip.MustParseAddr("10.1.0.1") {
t.Fatalf("ProtocolAddresses[0].TunnelAddress.IPv4: got %v", got.ProtocolAddresses[0].TunnelAddress.IPv4)
}
if got.TunnelIPv6 != netip.MustParseAddr("fd01::1") {
t.Fatalf("TunnelIPv6: got %v", got.TunnelIPv6)
if got.ProtocolAddresses[0].TunnelAddress.IPv6 != netip.MustParseAddr("fd01::1") {
t.Fatalf("ProtocolAddresses[0].TunnelAddress.IPv6: got %v", got.ProtocolAddresses[0].TunnelAddress.IPv6)
}
}

func TestRuntimeAddressInfoFromServerConfiguration_CollectsAllEnabledProtocolAddresses(t *testing.T) {
cfg := serverConfiguration.Configuration{
EnableTCP: true,
EnableUDP: true,
EnableWS: true,
TCPSettings: settings.Settings{
Protocol: settings.TCP,
Addressing: settings.Addressing{
IPv4: netip.MustParseAddr("10.0.0.1"),
IPv6: netip.MustParseAddr("fd00::1"),
},
},
UDPSettings: settings.Settings{
Protocol: settings.UDP,
Addressing: settings.Addressing{
IPv4: netip.MustParseAddr("10.0.1.1"),
IPv6: netip.MustParseAddr("fd00::2"),
},
},
WSSettings: settings.Settings{
Protocol: settings.WS,
Addressing: settings.Addressing{
IPv4: netip.MustParseAddr("10.0.2.1"),
IPv6: netip.MustParseAddr("fd00::3"),
},
},
}

got := RuntimeAddressInfoFromServerConfiguration(cfg)
if len(got.ProtocolAddresses) != 3 {
t.Fatalf("expected three protocol address entries, got %d", len(got.ProtocolAddresses))
}
if got.ProtocolAddresses[0].Protocol != settings.TCP || got.ProtocolAddresses[0].TunnelAddress.IPv4 != netip.MustParseAddr("10.0.0.1") || got.ProtocolAddresses[0].TunnelAddress.IPv6 != netip.MustParseAddr("fd00::1") {
t.Fatalf("unexpected TCP protocol address entry: %+v", got.ProtocolAddresses[0])
}
if got.ProtocolAddresses[1].Protocol != settings.UDP || got.ProtocolAddresses[1].TunnelAddress.IPv4 != netip.MustParseAddr("10.0.1.1") || got.ProtocolAddresses[1].TunnelAddress.IPv6 != netip.MustParseAddr("fd00::2") {
t.Fatalf("unexpected UDP protocol address entry: %+v", got.ProtocolAddresses[1])
}
if got.ProtocolAddresses[2].Protocol != settings.WS || got.ProtocolAddresses[2].TunnelAddress.IPv4 != netip.MustParseAddr("10.0.2.1") || got.ProtocolAddresses[2].TunnelAddress.IPv6 != netip.MustParseAddr("fd00::3") {
t.Fatalf("unexpected WS protocol address entry: %+v", got.ProtocolAddresses[2])
}
}

Expand All @@ -72,7 +127,49 @@ func TestRuntimeAddressInfoFromClientConfiguration_ActiveSettingsErrorReturnsZer
}

got := RuntimeAddressInfoFromClientConfiguration(cfg)
if got.ServerIPv4.IsValid() || got.ServerIPv6.IsValid() || got.TunnelIPv4.IsValid() || got.TunnelIPv6.IsValid() {
t.Fatalf("expected zero info when active settings resolution fails, got %+v", got)
if len(got.ProtocolAddresses) != 0 {
t.Fatalf("expected no protocol address entries when active settings resolution fails, got %d", len(got.ProtocolAddresses))
}
}

func TestRuntimeAddressInfoFromServerConfiguration_PreservesPerProtocolServerAddresses(t *testing.T) {
cfg := serverConfiguration.Configuration{
EnableTCP: true,
EnableUDP: true,
TCPSettings: settings.Settings{
Protocol: settings.TCP,
Addressing: settings.Addressing{
Server: settings.Host{}.WithIPv4(netip.MustParseAddr("198.51.100.10")),
IPv4: netip.MustParseAddr("10.0.0.1"),
},
},
UDPSettings: settings.Settings{
Protocol: settings.UDP,
Addressing: settings.Addressing{
Server: settings.Host{}.WithIPv6(netip.MustParseAddr("2001:db8::20")),
IPv4: netip.MustParseAddr("10.0.1.1"),
},
},
}

got := RuntimeAddressInfoFromServerConfiguration(cfg)
if len(got.ProtocolAddresses) != 2 {
t.Fatalf("expected two protocol address entries, got %d", len(got.ProtocolAddresses))
}
if got.ProtocolAddresses[0].ServerAddress.IPv4 != netip.MustParseAddr("198.51.100.10") || got.ProtocolAddresses[0].ServerAddress.IPv6.IsValid() {
t.Fatalf("unexpected TCP server address: %+v", got.ProtocolAddresses[0].ServerAddress)
}
if got.ProtocolAddresses[1].ServerAddress.IPv6 != netip.MustParseAddr("2001:db8::20") || got.ProtocolAddresses[1].ServerAddress.IPv4.IsValid() {
t.Fatalf("unexpected UDP server address: %+v", got.ProtocolAddresses[1].ServerAddress)
}
}

func TestNewRuntimeProtocolAddress_InvalidAddressesReturnFalse(t *testing.T) {
got, ok := newRuntimeProtocolAddress(settings.TCP, RuntimeAddressPair{}, RuntimeAddressPair{})
if ok {
t.Fatal("expected invalid address pairs to be rejected")
}
if got != (RuntimeProtocolAddress{}) {
t.Fatalf("expected zero protocol address on invalid input, got %+v", got)
}
}
Loading
Loading