- Add UPnP support to Forge game server

- Fix closing of server
- Fix server (Netty) log configuration
This commit is contained in:
elcnesh
2015-04-10 13:39:53 +00:00
parent edbebf27c0
commit a859902c20
4 changed files with 81 additions and 5 deletions

1
.gitattributes vendored
View File

@@ -17819,6 +17819,7 @@ forge-gui/src/main/java/forge/util/XmlUtil.java -text
forge-gui/src/main/java/forge/util/gui/SGuiChoose.java -text forge-gui/src/main/java/forge/util/gui/SGuiChoose.java -text
forge-gui/src/main/java/forge/util/gui/SOptionPane.java -text forge-gui/src/main/java/forge/util/gui/SOptionPane.java -text
forge-gui/src/main/java/forge/util/package-info.java -text forge-gui/src/main/java/forge/util/package-info.java -text
forge-gui/src/main/resources/log4jConfig.config -text
forge-gui/src/main/resources/proxy-template.ftl -text forge-gui/src/main/resources/proxy-template.ftl -text
forge-gui/src/site/apt/index.apt -text forge-gui/src/site/apt/index.apt -text
forge-gui/tools/PerSetTracking.py svneol=native#text/x-python forge-gui/tools/PerSetTracking.py svneol=native#text/x-python

View File

@@ -10,6 +10,16 @@
<artifactId>forge-gui</artifactId> <artifactId>forge-gui</artifactId>
<name>Forge Gui</name> <name>Forge Gui</name>
<repositories>
<repository>
<id>4thline-repo</id>
<url>http://4thline.org/m2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>forge</groupId> <groupId>forge</groupId>
@@ -51,6 +61,16 @@
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
<version>4.0.25.Final</version> <version>4.0.25.Final</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.fourthline.cling</groupId>
<artifactId>cling-support</artifactId>
<version>2.0.1</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -21,6 +21,7 @@ import forge.net.game.NetEvent;
import forge.net.game.ReplyEvent; import forge.net.game.ReplyEvent;
import forge.net.game.UpdateLobbyPlayerEvent; import forge.net.game.UpdateLobbyPlayerEvent;
import forge.net.game.server.RemoteClient; import forge.net.game.server.RemoteClient;
import forge.properties.ForgeConstants;
import forge.util.ITriggerEvent; import forge.util.ITriggerEvent;
import io.netty.bootstrap.ServerBootstrap; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel; import io.netty.channel.Channel;
@@ -40,11 +41,19 @@ import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler; import io.netty.handler.logging.LoggingHandler;
import java.io.Serializable; import java.io.Serializable;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.log4j.PropertyConfigurator;
import org.fourthline.cling.UpnpService;
import org.fourthline.cling.UpnpServiceImpl;
import org.fourthline.cling.support.igd.PortMappingListener;
import org.fourthline.cling.support.model.PortMapping;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@@ -55,15 +64,29 @@ public final class FServerManager {
private boolean isHosting = false; private boolean isHosting = false;
private final EventLoopGroup bossGroup = new NioEventLoopGroup(1); private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
private final EventLoopGroup workerGroup = new NioEventLoopGroup(); private final EventLoopGroup workerGroup = new NioEventLoopGroup();
private UpnpService upnpService = null;
private final Map<Channel, RemoteClient> clients = Maps.newTreeMap(); private final Map<Channel, RemoteClient> clients = Maps.newTreeMap();
private ServerGameLobby localLobby; private ServerGameLobby localLobby;
private ILobbyListener lobbyListener; private ILobbyListener lobbyListener;
private final Thread shutdownHook = new Thread(new Runnable() {
@Override public final void run() {
if (isHosting()) {
stopServer(false);
}
}
});
private FServerManager() { private FServerManager() {
} }
/**
* Get the singleton instance of {@link FServerManager}.
*
* @return the singleton FServerManager.
*/
public static FServerManager getInstance() { public static FServerManager getInstance() {
if (instance == null) { if (instance == null) {
PropertyConfigurator.configure(ForgeConstants.ASSETS_DIR + "/src/main/resources/log4jConfig.config");
instance = new FServerManager(); instance = new FServerManager();
} }
return instance; return instance;
@@ -103,6 +126,8 @@ public final class FServerManager {
} }
}).start(); }).start();
mapNatPort(port);
Runtime.getRuntime().addShutdownHook(shutdownHook);
isHosting = true; isHosting = true;
} catch (final InterruptedException e) { } catch (final InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
@@ -110,8 +135,18 @@ public final class FServerManager {
} }
public void stopServer() { public void stopServer() {
stopServer(true);
}
private void stopServer(final boolean removeShutdownHook) {
bossGroup.shutdownGracefully(); bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully(); workerGroup.shutdownGracefully();
if (upnpService != null) {
upnpService.shutdown();
upnpService = null;
}
if (removeShutdownHook) {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
}
isHosting = false; isHosting = false;
} }
@@ -167,10 +202,21 @@ public final class FServerManager {
return null; return null;
} }
@Override private void mapNatPort(final int port) {
protected void finalize() throws Throwable { final String localAddress;
super.finalize(); try {
stopServer(); localAddress = Inet4Address.getLocalHost().getHostAddress();
} catch (final UnknownHostException e) {
throw new RuntimeException(e);
}
final PortMapping portMapping = new PortMapping(port, localAddress, PortMapping.Protocol.TCP, "Forge");
if (upnpService != null) {
// Safeguard shutdown call, to prevent lingering port mappings
upnpService.shutdown();
}
upnpService = new UpnpServiceImpl(new PortMappingListener(portMapping));
upnpService.getControlPoint().search();
} }
private class MessageHandler extends ChannelInboundHandlerAdapter { private class MessageHandler extends ChannelInboundHandlerAdapter {

View File

@@ -0,0 +1,9 @@
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=ALL, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n