forked from CloudburstMC/ProxyPass
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Still some bugs to iron for instance being able to rejoin properly.
- Loading branch information
0 parents
commit 1aee6de
Showing
12 changed files
with
925 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
## Address proxy will bind to. | ||
proxy: | ||
host: 0.0.0.0 | ||
port: 19122 | ||
## Destination server which the client will connect to. | ||
## You are only able to join offline mode servers | ||
destination: | ||
host: 127.0.0.1 | ||
port: 19132 | ||
## Pass packet buffers through to minimize processing (Disable to test protocol library for bugs) | ||
pass-through: true | ||
## Log packets for each session | ||
log-packets: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns="http://maven.apache.org/POM/4.0.0" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>com.nukkitx</groupId> | ||
<artifactId>proxypass</artifactId> | ||
<version>1.0.0-SNAPSHOT</version> | ||
<name>ProxyPass</name> | ||
|
||
<repositories> | ||
<repository> | ||
<id>nukkitx-repo</id> | ||
<url>https://repo.nukkitx.com/snapshot</url> | ||
</repository> | ||
</repositories> | ||
|
||
<properties> | ||
<maven.compiler.source>1.8</maven.compiler.source> | ||
<maven.compiler.target>1.8</maven.compiler.target> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
<maven.build.timestamp.format>HHmm-ddMMyyyy</maven.build.timestamp.format> | ||
<jackson.version>2.9.6</jackson.version> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.projectlombok</groupId> | ||
<artifactId>lombok</artifactId> | ||
<version>1.16.18</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.nukkitx.network</groupId> | ||
<artifactId>raknet</artifactId> | ||
<version>1.2.3-SNAPSHOT</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.code.findbugs</groupId> | ||
<artifactId>jsr305</artifactId> | ||
<version>1.3.9</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.nukkitx.protocol</groupId> | ||
<artifactId>bedrock-v291</artifactId> | ||
<version>1.0.0-SNAPSHOT</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-databind</artifactId> | ||
<version>${jackson.version}</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.dataformat</groupId> | ||
<artifactId>jackson-dataformat-yaml</artifactId> | ||
<version>${jackson.version}</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.nukkitx</groupId> | ||
<artifactId>common</artifactId> | ||
<version>1.0.1-SNAPSHOT</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.fusesource.jansi</groupId> | ||
<artifactId>jansi</artifactId> | ||
<version>1.17.1</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.jline</groupId> | ||
<artifactId>jline-reader</artifactId> | ||
<version>3.7.0</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.nimbusds</groupId> | ||
<artifactId>nimbus-jose-jwt</artifactId> | ||
<version>4.41.2</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<configuration> | ||
<archive> | ||
<manifestEntries> | ||
<addClasspath>true</addClasspath> | ||
<classpathPrefix>lib/</classpathPrefix> | ||
<Main-Class>com.nukkitx.proxypass.ProxyPass</Main-Class> | ||
</manifestEntries> | ||
</archive> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-shade-plugin</artifactId> | ||
<dependencies> | ||
<dependency> | ||
<groupId>com.github.edwgiz</groupId> | ||
<artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId> | ||
<version>2.8.1</version> | ||
</dependency> | ||
</dependencies> | ||
<executions> | ||
<execution> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>shade</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
<configuration> | ||
<transformers> | ||
<transformer | ||
implementation="com.github.edwgiz.mavenShadePlugin.log4j2CacheTransformer.PluginsCacheFileTransformer"> | ||
</transformer> | ||
</transformers> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.nukkitx.proxypass; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.Getter; | ||
import lombok.ToString; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.BufferedWriter; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.net.InetSocketAddress; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.StandardOpenOption; | ||
|
||
@Getter | ||
@ToString | ||
public class Configuration { | ||
|
||
private Address proxy; | ||
private Address destination; | ||
|
||
@JsonProperty("pass-through") | ||
private boolean passingThrough = true; | ||
@JsonProperty("log-packets") | ||
private boolean loggingPackets = false; | ||
|
||
public static Configuration load(Path path) throws IOException { | ||
try (BufferedReader reader = Files.newBufferedReader(path)) { | ||
return ProxyPass.YAML_MAPPER.readValue(reader, Configuration.class); | ||
} | ||
} | ||
|
||
public static Configuration load(InputStream stream) throws IOException { | ||
return ProxyPass.YAML_MAPPER.readValue(stream, Configuration.class); | ||
} | ||
|
||
public static void save(Path path, Configuration configuration) throws IOException { | ||
try (BufferedWriter writer = Files.newBufferedWriter(path, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) { | ||
ProxyPass.YAML_MAPPER.writerWithDefaultPrettyPrinter().writeValue(writer, configuration); | ||
} | ||
} | ||
|
||
@Getter | ||
@ToString | ||
public static class Address { | ||
private String host; | ||
private int port; | ||
|
||
InetSocketAddress getAddress() { | ||
return new InetSocketAddress(host, port); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package com.nukkitx.proxypass; | ||
|
||
import com.fasterxml.jackson.databind.DeserializationFeature; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; | ||
import com.nukkitx.network.raknet.RakNetClient; | ||
import com.nukkitx.network.raknet.RakNetServer; | ||
import com.nukkitx.protocol.bedrock.session.BedrockSession; | ||
import com.nukkitx.protocol.bedrock.v291.Bedrock_v291; | ||
import com.nukkitx.protocol.bedrock.wrapper.WrappedPacket; | ||
import com.nukkitx.proxypass.network.NukkitSessionManager; | ||
import com.nukkitx.proxypass.network.ProxyRakNetEventListener; | ||
import com.nukkitx.proxypass.network.bedrock.session.DownstreamPacketHandler; | ||
import com.nukkitx.proxypass.network.bedrock.session.ProxyPlayerSession; | ||
import com.nukkitx.proxypass.network.bedrock.session.UpstreamPacketHandler; | ||
import lombok.Getter; | ||
import lombok.extern.log4j.Log4j2; | ||
|
||
import java.io.IOException; | ||
import java.net.InetSocketAddress; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.nio.file.StandardCopyOption; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
import java.util.concurrent.locks.Lock; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
@Log4j2 | ||
@Getter | ||
public class ProxyPass { | ||
public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); | ||
public static final YAMLMapper YAML_MAPPER = (YAMLMapper) new YAMLMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); | ||
public static final String MINECRAFT_VERSION; | ||
public static final int PROTOCOL_VERSION = 291; | ||
|
||
static { | ||
String minecraftVersion; | ||
|
||
Package mainPackage = ProxyPass.class.getPackage(); | ||
try { | ||
minecraftVersion = mainPackage.getImplementationVersion().split("-")[0]; | ||
} catch (NullPointerException e) { | ||
minecraftVersion = "0.0.0"; | ||
} | ||
MINECRAFT_VERSION = minecraftVersion; | ||
} | ||
|
||
private final AtomicBoolean running = new AtomicBoolean(true); | ||
private NukkitSessionManager sessionManager = new NukkitSessionManager(); | ||
private RakNetServer<BedrockSession<ProxyPlayerSession>> rakNetServer; | ||
private RakNetClient<BedrockSession<ProxyPlayerSession>> rakNetClient; | ||
private InetSocketAddress targetAddress; | ||
private InetSocketAddress proxyAddress; | ||
private Configuration configuration; | ||
private Path loggingDir; | ||
|
||
public static void main(String[] args) { | ||
ProxyPass proxy = new ProxyPass(); | ||
try { | ||
proxy.boot(); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public void boot() throws IOException { | ||
log.info("Loading configuration..."); | ||
Path configPath = Paths.get(".").resolve("config.yml"); | ||
if (Files.notExists(configPath) || !Files.isRegularFile(configPath)) { | ||
Files.copy(ProxyPass.class.getClassLoader().getResourceAsStream("config.yml"), configPath, StandardCopyOption.REPLACE_EXISTING); | ||
} | ||
|
||
configuration = Configuration.load(configPath); | ||
|
||
proxyAddress = configuration.getProxy().getAddress(); | ||
targetAddress = configuration.getDestination().getAddress(); | ||
|
||
loggingDir = Paths.get(".").resolve("packet-logs/").toAbsolutePath(); | ||
Files.createDirectories(loggingDir); | ||
|
||
log.info("Loading server..."); | ||
rakNetServer = RakNetServer.<BedrockSession<ProxyPlayerSession>>builder() | ||
.eventListener(new ProxyRakNetEventListener()) | ||
.address(proxyAddress) | ||
.packet(WrappedPacket::new, 0xfe) | ||
.sessionManager(sessionManager) | ||
.sessionFactory(rakNetSession -> { | ||
BedrockSession<ProxyPlayerSession> session = new BedrockSession<>(rakNetSession); | ||
session.setHandler(new UpstreamPacketHandler(session, this)); | ||
return session; | ||
}) | ||
.build(); | ||
if (rakNetServer.bind()) { | ||
log.info("RakNet server started on {}", proxyAddress); | ||
} else { | ||
log.fatal("RakNet server was not able to bind to {}", proxyAddress); | ||
} | ||
rakNetClient = new RakNetClient.Builder<BedrockSession<ProxyPlayerSession>>() | ||
.packet(WrappedPacket::new, 0xfe) | ||
.sessionFactory(rakNetSession -> { | ||
BedrockSession<ProxyPlayerSession> session = new BedrockSession<>(rakNetSession, Bedrock_v291.V291_CODEC); | ||
session.setHandler(new DownstreamPacketHandler(session, this)); | ||
return session; | ||
}) | ||
.sessionManager(sessionManager) | ||
.build(); | ||
log.info("RakNet client ready for connections to {}", targetAddress); | ||
loop(); | ||
} | ||
|
||
public void loop() { | ||
Lock lock = new ReentrantLock(); | ||
|
||
while (running.get()) { | ||
lock.lock(); | ||
try { | ||
lock.newCondition().await(50, TimeUnit.MILLISECONDS); | ||
} catch (InterruptedException e) { | ||
//Ignore | ||
} | ||
lock.unlock(); | ||
} | ||
} | ||
|
||
public void shutdown() { | ||
running.compareAndSet(false, true); | ||
rakNetClient.close(); | ||
rakNetServer.close(); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
src/main/java/com/nukkitx/proxypass/network/NukkitSessionManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.nukkitx.proxypass.network; | ||
|
||
import com.flowpowered.math.GenericMath; | ||
import com.nukkitx.network.SessionManager; | ||
import com.nukkitx.protocol.bedrock.session.BedrockSession; | ||
import com.nukkitx.proxypass.network.bedrock.session.ProxyPlayerSession; | ||
import lombok.extern.log4j.Log4j2; | ||
|
||
import java.util.concurrent.ThreadPoolExecutor; | ||
|
||
@Log4j2 | ||
public class NukkitSessionManager extends SessionManager<BedrockSession<ProxyPlayerSession>> { | ||
private static final int SESSIONS_PER_THREAD = 50; | ||
|
||
/*public NukkitSessionManager() { | ||
super(Executors.newSingleThreadScheduledExecutor()); | ||
ScheduledExecutorService service = (ScheduledExecutorService) executor; | ||
service.scheduleAtFixedRate(this::onTick, 50, 50, TimeUnit.MILLISECONDS); | ||
}*/ | ||
|
||
@Override | ||
protected void onAddSession(BedrockSession<ProxyPlayerSession> session) { | ||
adjustPoolSize(); | ||
} | ||
|
||
@Override | ||
protected void onRemoveSession(BedrockSession<ProxyPlayerSession> session) { | ||
adjustPoolSize(); | ||
} | ||
|
||
private void adjustPoolSize() { | ||
if (executor instanceof ThreadPoolExecutor) { | ||
ThreadPoolExecutor sessionTicker = (ThreadPoolExecutor) executor; | ||
int threads = GenericMath.clamp(sessions.size() / SESSIONS_PER_THREAD, 1, Runtime.getRuntime().availableProcessors()); | ||
if (sessionTicker.getMaximumPoolSize() != threads) { | ||
sessionTicker.setMaximumPoolSize(threads); | ||
} | ||
} | ||
} | ||
|
||
public void onTick() { | ||
for (BedrockSession session : sessions.values()) { | ||
executor.execute(session::onTick); | ||
} | ||
} | ||
} |
Oops, something went wrong.