Skip to content

Commit 68d9dfb

Browse files
authored
Merge branch 'Corona-Studio:main' into main
2 parents 623ec57 + 50988ab commit 68d9dfb

File tree

8 files changed

+123
-41
lines changed

8 files changed

+123
-41
lines changed

ConnectX.Client/Client.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,11 @@ private async Task ResetRoomState(CancellationToken ct = default)
8888
_isInGroup = false;
8989

9090
// Clear and reset all manager
91-
await _zeroTierNodeLinkHolder.LeaveNetworkAsync(ct);
91+
if (OperatingSystem.IsWindows())
92+
{
93+
await _zeroTierNodeLinkHolder.LeaveNetworkAsync(ct);
94+
}
95+
9296
_router.RemoveAllPeers();
9397
_roomInfoManager.ClearRoomInfo();
9498
_partnerManager.RemoveAllPartners();
@@ -135,7 +139,8 @@ private void OnGroupUserStateChanged(MessageContext<GroupUserStateChanged> ctx)
135139
if (groupInfo == null)
136140
return (null, GroupCreationStatus.Other, "Failed to acquire group info");
137141

138-
if (message is JoinGroup or CreateGroup)
142+
if (OperatingSystem.IsWindows() &&
143+
message is JoinGroup or CreateGroup)
139144
{
140145
if (createResult.Status != GroupCreationStatus.Succeeded)
141146
return (null, createResult.Status, createResult.ErrorMessage);
@@ -162,17 +167,20 @@ private void OnGroupUserStateChanged(MessageContext<GroupUserStateChanged> ctx)
162167

163168
if (result is not { Status: GroupCreationStatus.Succeeded })
164169
return (null, result?.Status ?? GroupCreationStatus.Other, "Failed to update room member network info");
165-
166-
_isInGroup = true;
167170
}
168171

172+
_isInGroup = true;
169173
return (groupInfo, GroupCreationStatus.Succeeded, null);
170174
}
171175

172176
public async Task<(GroupInfo? Info, GroupCreationStatus Status, string? Error)> CreateGroupAsync(CreateGroup createGroup, CancellationToken ct)
173177
{
174-
if (!_serverLinkHolder.IsConnected) return (null, GroupCreationStatus.Other, "Not connected to the server");
175-
if (!_serverLinkHolder.IsSignedIn) return (null, GroupCreationStatus.Other, "Not signed in");
178+
if (!_serverLinkHolder.IsConnected)
179+
return (null, GroupCreationStatus.Other, "Not connected to the server");
180+
if (!_serverLinkHolder.IsSignedIn)
181+
return (null, GroupCreationStatus.Other, "Not signed in");
182+
if (!OperatingSystem.IsWindows() && !createGroup.UseRelayServer)
183+
return (null, GroupCreationStatus.Other, "Only Windows platform supports direct connection");
176184

177185
return await PerformOpAndGetRoomInfoAsync(createGroup, ct);
178186
}
@@ -183,6 +191,8 @@ private void OnGroupUserStateChanged(MessageContext<GroupUserStateChanged> ctx)
183191
return (null, GroupCreationStatus.Other, "Not connected to the server");
184192
if (!_serverLinkHolder.IsSignedIn)
185193
return (null, GroupCreationStatus.Other, "Not signed in");
194+
if (!OperatingSystem.IsWindows() && !joinGroup.UseRelayServer)
195+
return (null, GroupCreationStatus.Other, "Only Windows platform supports direct connection");
186196

187197
return await PerformOpAndGetRoomInfoAsync(joinGroup, ct);
188198
}

ConnectX.Client/Managers/RoomInfoManager.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
5454
continue;
5555
}
5656

57-
await TaskHelper.WaitUntilAsync(zeroTierNodeLinkHolder.IsNodeOnline, stoppingToken);
58-
await TaskHelper.WaitUntilAsync(zeroTierNodeLinkHolder.IsNetworkReady, stoppingToken);
57+
if (OperatingSystem.IsWindows())
58+
{
59+
await TaskHelper.WaitUntilAsync(zeroTierNodeLinkHolder.IsNodeOnline, stoppingToken);
60+
await TaskHelper.WaitUntilAsync(zeroTierNodeLinkHolder.IsNetworkReady, stoppingToken);
61+
}
5962

6063
if (needToRefreshRoomInfo)
6164
{
@@ -74,9 +77,10 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
7477
continue;
7578
}
7679

77-
if (self.NetworkIpAddresses == null ||
80+
if ((self.NetworkIpAddresses == null ||
7881
self.NetworkIpAddresses.Length == 0 ||
79-
string.IsNullOrEmpty(self.NetworkNodeId))
82+
string.IsNullOrEmpty(self.NetworkNodeId)) &&
83+
OperatingSystem.IsWindows())
8084
{
8185
needToRefreshRoomInfo = true;
8286

@@ -122,6 +126,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
122126
if (user.UserId == serverLinkHolder.UserId)
123127
continue;
124128

129+
if (user.RelayServerAddress != null)
130+
{
131+
_possiblePeers.Add(user.UserId);
132+
possibleUsers.Add(user);
133+
continue;
134+
}
135+
125136
if (user.NetworkIpAddresses == null ||
126137
user.NetworkIpAddresses.Length == 0)
127138
{

ConnectX.Client/Proxy/FakeServerMultiCaster.cs

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,27 @@ public FakeServerMultiCaster(
4747
}
4848

4949
public event Action<string, int>? OnListenedLanServer;
50+
51+
private static IPAddress GetLocalIpAddress()
52+
{
53+
var networkInterfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
54+
.Where(ni => ni.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up
55+
&& ni.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback);
56+
57+
foreach (var ni in networkInterfaces)
58+
{
59+
var ipProps = ni.GetIPProperties();
60+
foreach (var addr in ipProps.UnicastAddresses)
61+
{
62+
if (addr.Address.AddressFamily == AddressFamily.InterNetwork)
63+
{
64+
return addr.Address;
65+
}
66+
}
67+
}
68+
69+
throw new Exception("No network adapters with an IPv4 address in the system!");
70+
}
5071

5172
private void OnReceiveMcMulticastMessage(McMulticastMessage message, PacketContext context)
5273
{
@@ -59,19 +80,39 @@ private void OnReceiveMcMulticastMessage(McMulticastMessage message, PacketConte
5980
return;
6081
}
6182

62-
var multicastSocket = new Socket(SocketType.Dgram, ProtocolType.Udp);
63-
var multicastOption = new MulticastOption(MulticastAddress, IPAddress.Any);
83+
Socket? socket = null;
84+
85+
if (OperatingSystem.IsWindows())
86+
{
87+
socket = new Socket(SocketType.Dgram, ProtocolType.Udp);
88+
89+
var multicastOption = new MulticastOption(MulticastAddress, IPAddress.Any);
90+
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOption);
91+
}
92+
93+
if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
94+
{
95+
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
96+
97+
var localIp = GetLocalIpAddress();
98+
99+
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, localIp.GetAddressBytes());
100+
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
101+
socket.Bind(new IPEndPoint(localIp, 0));
102+
}
103+
104+
ArgumentNullException.ThrowIfNull(socket);
64105

65-
multicastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOption);
106+
using var multicastSocket = socket;
66107

67-
//传递给客户端的是另一个端口,并非源端口。客户端连接此端口通过P2P.NET和源端口通信
68108
var mess = $"[MOTD]{message.Name}[/MOTD][AD]{proxy.LocalMappingPort}[/AD]";
69109
var buf = Encoding.Default.GetBytes(mess);
70110

71111
multicastSocket.SendTo(buf, MulticastIpe);
72112
_logger.LogMulticastMessageToClient(proxy.LocalMappingPort, message.Name);
73113
}
74114

115+
75116
private void ListenedLanServer(string serverName, ushort port)
76117
{
77118
_logger.LogLanServerIsListened(serverName, port);
@@ -120,37 +161,50 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
120161
{
121162
if (_roomInfoManager.CurrentGroupInfo == null)
122163
{
123-
// We are not in a room, so we don't need to listen to multicast
124164
await Task.Delay(3000, stoppingToken);
125165
continue;
126166
}
127167

128-
using var multicastSocket = new Socket(SocketType.Dgram, ProtocolType.Udp);
129-
var multicastOption = new MulticastOption(MulticastAddress, IPAddress.Any);
130-
131-
multicastSocket.SetSocketOption(
132-
SocketOptionLevel.IP,
133-
SocketOptionName.AddMembership,
134-
multicastOption);
168+
using var multicastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
135169

136-
multicastSocket.SetSocketOption(
137-
SocketOptionLevel.Socket,
138-
SocketOptionName.ReuseAddress,
139-
true);
170+
// Allow multiple sockets to bind to same address (important for Linux/macOS)
171+
multicastSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
140172

173+
// Bind to ANY address but the multicast port
141174
multicastSocket.Bind(new IPEndPoint(IPAddress.Any, MulticastPort));
142-
143-
var receiveFromResult = await multicastSocket.ReceiveFromAsync(buffer, MulticastIpe);
144-
var message = Encoding.UTF8.GetString(buffer, 0, receiveFromResult.ReceivedBytes);
145-
var serverName = message["[MOTD]".Length..message.IndexOf("[/MOTD]", StringComparison.Ordinal)];
146-
var portStart = message.IndexOf("[AD]", StringComparison.Ordinal) + 4;
147-
var portEnd = message.IndexOf("[/AD]", StringComparison.Ordinal);
148-
var port = ushort.Parse(message[portStart..portEnd]);
149175

150-
if (!serverName.StartsWith($"[{Prefix}]")) //如果[ConnectX]开头,则是自己发出的,忽略
151-
ListenedLanServer(serverName, port);
176+
// Join multicast group
177+
var multicastOption = new MulticastOption(MulticastAddress, IPAddress.Any);
178+
multicastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOption);
152179

153-
multicastSocket.Close();
180+
try
181+
{
182+
var receiveFromResult = await multicastSocket.ReceiveFromAsync(buffer, SocketFlags.None,
183+
new IPEndPoint(IPAddress.Any, 0), stoppingToken);
184+
var message = Encoding.UTF8.GetString(buffer, 0, receiveFromResult.ReceivedBytes);
185+
186+
var serverName = message["[MOTD]".Length..message.IndexOf("[/MOTD]", StringComparison.Ordinal)];
187+
var portStart = message.IndexOf("[AD]", StringComparison.Ordinal) + 4;
188+
var portEnd = message.IndexOf("[/AD]", StringComparison.Ordinal);
189+
var port = ushort.Parse(message[portStart..portEnd]);
190+
191+
if (!serverName.StartsWith($"[{Prefix}]"))
192+
{
193+
ListenedLanServer(serverName, port);
194+
}
195+
}
196+
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.Interrupted)
197+
{
198+
// Expected during shutdown
199+
}
200+
catch (Exception ex)
201+
{
202+
_logger.LogError(ex, "Error receiving multicast message");
203+
}
204+
finally
205+
{
206+
multicastSocket.Close();
207+
}
154208

155209
await Task.Delay(3000, stoppingToken);
156210
}

ConnectX.ClientConsole/ConnectX.ClientConsole.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
2323
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
2424
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
25-
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
25+
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
2626
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
2727
</ItemGroup>
2828

ConnectX.MessageRegister.SourceGenerator/ConnectX.MessageRegister.SourceGenerator.csproj

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,17 @@
77
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
88
</PropertyGroup>
99

10+
<PropertyGroup>
11+
<!-- Ensure the source generator can be loaded on any architecture -->
12+
<PlatformTarget>AnyCPU</PlatformTarget>
13+
</PropertyGroup>
14+
1015
<ItemGroup>
1116
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" PrivateAssets="all" />
12-
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" />
17+
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
18+
<PrivateAssets>all</PrivateAssets>
19+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
20+
</PackageReference>
1321
</ItemGroup>
1422

1523
</Project>

ConnectX.Relay/ConnectX.Relay.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
2525
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
2626
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
27-
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
27+
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
2828
</ItemGroup>
2929

3030
<ItemGroup>

ConnectX.Server/ConnectX.Server.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
3232
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
3333
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
34-
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
34+
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
3535
</ItemGroup>
3636

3737
<ItemGroup>

ConnectX.Server/Managers/GroupManager.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Collections.Concurrent;
2-
using System.Diagnostics;
32
using System.Diagnostics.CodeAnalysis;
43
using System.Net;
54
using ConnectX.Server.Interfaces;

0 commit comments

Comments
 (0)