Skip to content

Commit abbecfe

Browse files
authored
Added option to disable UPnP port forwarding (SubnauticaNitrox#1547)
* Added option to disable UPnP port forwarding
1 parent d3670ea commit abbecfe

19 files changed

+215
-72
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.Threading;
2+
3+
namespace NitroxModel.DataStructures
4+
{
5+
public sealed class AtomicBool
6+
{
7+
private int backingValue;
8+
9+
public bool Value
10+
{
11+
get => Interlocked.CompareExchange(ref backingValue, 1, 1) == 1;
12+
set
13+
{
14+
if (value)
15+
{
16+
Interlocked.CompareExchange(ref backingValue, 1, 0);
17+
}
18+
else
19+
{
20+
Interlocked.CompareExchange(ref backingValue, 0, 1);
21+
}
22+
}
23+
}
24+
25+
public static implicit operator bool(AtomicBool b)
26+
{
27+
return b.Value;
28+
}
29+
30+
/// <summary>
31+
/// Sets the bool to true if it's false.
32+
/// </summary>
33+
/// <returns>Returns true if the bool was just set to true and wasn't already true.</returns>
34+
public bool GetAndSet()
35+
{
36+
return Interlocked.CompareExchange(ref backingValue, 1, 0) == 0;
37+
}
38+
}
39+
}

NitroxModel/NitroxModel.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<Compile Include="Core\IAutoFacRegistrar.cs" />
4848
<Compile Include="Core\NitroxEnvironment.cs" />
4949
<Compile Include="Core\NitroxServiceLocator.cs" />
50+
<Compile Include="DataStructures\AtomicBool.cs" />
5051
<Compile Include="DataStructures\GameLogic\PlantableItemData.cs" />
5152
<Compile Include="DataStructures\GameLogic\DamageTakenData.cs" />
5253
<Compile Include="DataStructures\GameLogic\Entities\Metadata\PrecursorDoorwayMetadata.cs" />

NitroxServer/Communication/NetworkingLayer/LiteNetLib/LiteNetLibConnection.cs renamed to NitroxServer/Communication/LiteNetLib/LiteNetLibConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using NitroxModel.Networking;
66
using NitroxModel.Packets;
77

8-
namespace NitroxServer.Communication.NetworkingLayer.LiteNetLib
8+
namespace NitroxServer.Communication.LiteNetLib
99
{
1010
public class LiteNetLibConnection : NitroxConnection
1111
{

NitroxServer/Communication/NetworkingLayer/LiteNetLib/LiteNetLibServer.cs renamed to NitroxServer/Communication/LiteNetLib/LiteNetLibServer.cs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@
66
using NitroxServer.GameLogic.Entities;
77
using NitroxServer.Serialization;
88

9-
namespace NitroxServer.Communication.NetworkingLayer.LiteNetLib
9+
namespace NitroxServer.Communication.LiteNetLib
1010
{
1111
public class LiteNetLibServer : NitroxServer
1212
{
13-
private readonly NetManager server;
1413
private readonly EventBasedNetListener listener;
1514
private readonly NetPacketProcessor netPacketProcessor = new();
15+
private readonly NetManager server;
1616

1717
public LiteNetLibServer(PacketHandler packetHandler, PlayerManager playerManager, EntitySimulation entitySimulation, ServerConfig serverConfig) : base(packetHandler, playerManager, entitySimulation, serverConfig)
1818
{
1919
netPacketProcessor.SubscribeReusable<WrapperPacket, NetPeer>(OnPacketReceived);
2020
listener = new EventBasedNetListener();
2121
server = new NetManager(listener);
2222
}
23+
2324
public override bool Start()
2425
{
2526
listener.PeerConnectedEvent += PeerConnected;
@@ -32,25 +33,41 @@ public override bool Start()
3233
server.UpdateTime = 15;
3334
server.UnsyncedEvents = true;
3435
#if DEBUG
35-
server.DisconnectTimeout = 300000; //Disables Timeout (for 5 min) for debug purpose (like if you jump though the server code)
36+
server.DisconnectTimeout = 300000; //Disables Timeout (for 5 min) for debug purpose (like if you jump though the server code)
3637
#endif
38+
3739
if (!server.Start(portNumber))
3840
{
3941
return false;
4042
}
41-
42-
SetupUPNP();
43-
44-
isStopped = false;
43+
44+
#if RELEASE
45+
if (useUpnpPortForwarding)
46+
{
47+
BeginPortForward(portNumber);
48+
}
49+
#endif
50+
4551
return true;
4652
}
4753

4854
public override void Stop()
4955
{
50-
isStopped = true;
5156
server.Stop();
5257
}
5358

59+
public void OnConnectionRequest(ConnectionRequest request)
60+
{
61+
if (server.PeersCount < maxConnections)
62+
{
63+
request.AcceptIfKey("nitrox");
64+
}
65+
else
66+
{
67+
request.Reject();
68+
}
69+
}
70+
5471
private void PeerConnected(NetPeer peer)
5572
{
5673
LiteNetLibConnection connection = new(peer);
@@ -77,18 +94,6 @@ private void OnPacketReceived(WrapperPacket wrapperPacket, NetPeer peer)
7794
ProcessIncomingData(connection, packet);
7895
}
7996

80-
public void OnConnectionRequest(ConnectionRequest request)
81-
{
82-
if (server.PeersCount < maxConn)
83-
{
84-
request.AcceptIfKey("nitrox");
85-
}
86-
else
87-
{
88-
request.Reject();
89-
}
90-
}
91-
9297
private NitroxConnection GetConnection(int remoteIdentifier)
9398
{
9499
NitroxConnection connection;

NitroxServer/Communication/NetworkingLayer/NitroxConnection.cs renamed to NitroxServer/Communication/NitroxConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using NitroxModel.Packets;
33
using NitroxModel.Packets.Processors.Abstract;
44

5-
namespace NitroxServer.Communication.NetworkingLayer
5+
namespace NitroxServer.Communication
66
{
77
public interface NitroxConnection : IProcessorContext
88
{

NitroxServer/Communication/NetworkingLayer/NitroxServer.cs renamed to NitroxServer/Communication/NitroxServer.cs

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22
using System.Collections.Generic;
3-
using Mono.Nat;
43
using NitroxModel.DataStructures;
54
using NitroxModel.Logger;
65
using NitroxModel.Packets;
@@ -9,12 +8,13 @@
98
using NitroxServer.GameLogic.Entities;
109
using NitroxServer.Serialization;
1110

12-
namespace NitroxServer.Communication.NetworkingLayer
11+
namespace NitroxServer.Communication
1312
{
1413
public abstract class NitroxServer
1514
{
16-
protected bool isStopped = true;
17-
protected int portNumber, maxConn;
15+
protected readonly int portNumber;
16+
protected readonly int maxConnections;
17+
protected readonly bool useUpnpPortForwarding;
1818

1919
protected readonly PacketHandler packetHandler;
2020
protected readonly EntitySimulation entitySimulation;
@@ -28,7 +28,8 @@ public NitroxServer(PacketHandler packetHandler, PlayerManager playerManager, En
2828
this.entitySimulation = entitySimulation;
2929

3030
portNumber = serverConfig.ServerPort;
31-
maxConn = serverConfig.MaxConnections;
31+
maxConnections = serverConfig.MaxConnections;
32+
useUpnpPortForwarding = serverConfig.AutoPortForward;
3233
}
3334

3435
public abstract bool Start();
@@ -56,44 +57,30 @@ protected void ClientDisconnected(NitroxConnection connection)
5657
}
5758
}
5859

59-
protected void ProcessIncomingData(NitroxConnection connection, Packet packet)
60+
protected void BeginPortForward(int port)
6061
{
61-
try
62-
{
63-
packetHandler.Process(packet, connection);
64-
}
65-
catch (Exception ex)
62+
PortForward.TryOpenPortAsync(port, TimeSpan.FromSeconds(20)).ContinueWith(task =>
6663
{
67-
Log.Error(ex, $"Exception while processing packet: {packet}");
68-
}
69-
}
70-
71-
protected void SetupUPNP()
72-
{
73-
NatUtility.DeviceFound += DeviceFound;
74-
NatUtility.StartDiscovery();
64+
if (task.Result)
65+
{
66+
Log.Info($"Server port {port} UDP has been automatically opened on your router (expires in 1 day)");
67+
}
68+
else
69+
{
70+
Log.Warn(PortForward.GetError(port) ?? $"Failed to port forward {port} UDP through UPnP");
71+
}
72+
}).ConfigureAwait(false);
7573
}
7674

77-
private async void DeviceFound(object sender, DeviceEventArgs args)
75+
protected void ProcessIncomingData(NitroxConnection connection, Packet packet)
7876
{
7977
try
8078
{
81-
INatDevice device = args.Device;
82-
await device.CreatePortMapAsync(new Mapping(Protocol.Udp, portNumber, portNumber, (int)TimeSpan.FromDays(1).TotalSeconds, "Nitrox Server - Subnautica"));
83-
Log.Info($"Server port ({portNumber}) has been automatically opened on your router");
79+
packetHandler.Process(packet, connection);
8480
}
85-
catch (MappingException ex)
81+
catch (Exception ex)
8682
{
87-
switch (ex.ErrorCode)
88-
{
89-
case ErrorCode.ConflictInMappingEntry:
90-
Log.Warn($"Automatic port forwarding failed (Is it already open ?)");
91-
break;
92-
default:
93-
Log.Warn($"Automatic port forwarding failed, please manually port forward");
94-
break;
95-
96-
}
83+
Log.Error(ex, $"Exception while processing packet: {packet}");
9784
}
9885
}
9986
}

NitroxServer/Communication/Packets/PacketHandler.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using NitroxServer.GameLogic;
88
using NitroxModel.Core;
99
using NitroxModel.DataStructures.Util;
10-
using NitroxServer.Communication.NetworkingLayer;
1110

1211
namespace NitroxServer.Communication.Packets
1312
{

NitroxServer/Communication/Packets/Processors/Abstract/UnauthenticatedPacketProcessor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using NitroxModel.Packets;
22
using NitroxModel.Packets.Processors.Abstract;
3-
using NitroxServer.Communication.NetworkingLayer;
43

54
namespace NitroxServer.Communication.Packets.Processors.Abstract
65
{

NitroxServer/Communication/Packets/Processors/MultiplayerSessionPolicyRequestProcessor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using NitroxModel.Logger;
22
using NitroxModel.Packets;
33
using NitroxModel.Server;
4-
using NitroxServer.Communication.NetworkingLayer;
54
using NitroxServer.Communication.Packets.Processors.Abstract;
65
using NitroxServer.Serialization;
76

NitroxServer/Communication/Packets/Processors/MultiplayerSessionReservationRequestProcessor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using NitroxModel.Logger;
22
using NitroxModel.MultiplayerSession;
33
using NitroxModel.Packets;
4-
using NitroxServer.Communication.NetworkingLayer;
54
using NitroxServer.Communication.Packets.Processors.Abstract;
65
using NitroxServer.GameLogic;
76

0 commit comments

Comments
 (0)