Skip to content
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# project files
Minecraft_fabric_1.21.1_source

# gradle

.gradle/
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '1.6-SNAPSHOT'
id 'fabric-loom' version '1.7-SNAPSHOT'
id 'maven-publish'
}

Expand Down
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.20.4
yarn_mappings=1.20.4+build.3
loader_version=0.15.10
minecraft_version=1.21.1
yarn_mappings=1.21.1+build.3
loader_version=0.17.3
# Mod Properties
mod_version=1.3
maven_group=ru.fiw.proxyserver
archives_base_name=ProxyServer
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.97.0+1.20.4
fabric_version=0.102.1+1.21.1
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
106 changes: 62 additions & 44 deletions src/main/java/ru/fiw/proxyserver/TestPing.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
import io.netty.handler.proxy.Socks4ProxyHandler;
import io.netty.handler.proxy.Socks5ProxyHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import net.minecraft.SharedConstants;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.DisconnectionInfo;
import net.minecraft.network.NetworkSide;
import net.minecraft.network.listener.ClientQueryPacketListener;
import net.minecraft.network.packet.c2s.handshake.ConnectionIntent;
import net.minecraft.network.packet.c2s.handshake.HandshakeC2SPacket;
import net.minecraft.network.packet.c2s.query.QueryPingC2SPacket;
import net.minecraft.network.packet.c2s.query.QueryRequestC2SPacket;
import net.minecraft.network.packet.s2c.query.PingResultS2CPacket;
Expand Down Expand Up @@ -42,19 +41,32 @@ public void run(String ip, int port, Proxy proxy) {

private void ping(String ip, int port) {
state = Text.translatable("ui.proxyserver.ping.pinging", ip).getString();
ClientConnection clientConnection;
try {
clientConnection = createTestClientConnection(InetAddress.getByName(ip), port);
pingDestination = createTestClientConnection(ip, port);
} catch (UnknownHostException e) {
state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantConnect").getString();
return;
} catch (Exception e) {
state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPing", ip).getString();
return;
}
pingDestination = clientConnection;
clientConnection.setPacketListener(new ClientQueryPacketListener() {
ClientConnection clientConnection = pingDestination;

ClientQueryPacketListener listener = new ClientQueryPacketListener() {
private boolean successful;
private boolean sentQuery;

@Override
public void onResponse(QueryResponseS2CPacket packet) {
if (this.sentQuery) {
clientConnection.disconnect(Text.translatable("multiplayer.status.unrequested"));
return;
}

this.sentQuery = true;
pingSentAt = Util.getMeasuringTimeMs();
clientConnection.send(new QueryPingC2SPacket(pingSentAt));
}

@Override
public void onPingResult(PingResultS2CPacket packet) {
Expand All @@ -65,59 +77,65 @@ public void onPingResult(PingResultS2CPacket packet) {
clientConnection.disconnect(Text.translatable("multiplayer.status.finished"));
}

public void onResponse(QueryResponseS2CPacket packet) {
pingSentAt = Util.getMeasuringTimeMs();
clientConnection.send(new QueryPingC2SPacket(pingSentAt));
}

public void onDisconnected(Text reason) {
@Override
public void onDisconnected(DisconnectionInfo info) {
pingDestination = null;
if (!this.successful) {
state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPingReason", ip, reason.getString()).getString();
state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPingReason", ip, info.reason().getString()).getString();
}
}

@Override
public boolean isConnectionOpen() {
return true;
return clientConnection.isOpen();
}

public ClientConnection getConnection() {
return clientConnection;
}
});
};

try {
clientConnection.send(new HandshakeC2SPacket(SharedConstants.getGameVersion().getProtocolVersion(), ip, port, ConnectionIntent.STATUS));
clientConnection.send(new QueryRequestC2SPacket());
clientConnection.connect(ip, port, listener);
clientConnection.send(QueryRequestC2SPacket.INSTANCE);
} catch (Throwable throwable) {
pingDestination = null;
state = Formatting.RED + Text.translatable("ui.proxyserver.err.cantPing", ip).getString();
clientConnection.disconnect(Text.translatable("multiplayer.status.cancelled"));
}
}

private ClientConnection createTestClientConnection(InetAddress address, int port) {
final ClientConnection clientConnection = new ClientConnection(NetworkSide.CLIENTBOUND);

(new Bootstrap()).group(ClientConnection.CLIENT_IO_GROUP.get()).handler(new ChannelInitializer<>() {
protected void initChannel(Channel channel) {
ClientConnection.setHandlers(channel);

try {
channel.config().setOption(ChannelOption.TCP_NODELAY, true);
} catch (ChannelException channelexception) {
}

ChannelPipeline channelpipeline = channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30));
ClientConnection.addHandlers(channelpipeline, NetworkSide.CLIENTBOUND, null);

if (proxy.type == Proxy.ProxyType.SOCKS5) {
channel.pipeline().addFirst(new Socks5ProxyHandler(new InetSocketAddress(proxy.getIp(), proxy.getPort()), proxy.username.isEmpty() ? null : proxy.username, proxy.password.isEmpty() ? null : proxy.password));
} else {
channel.pipeline().addFirst(new Socks4ProxyHandler(new InetSocketAddress(proxy.getIp(), proxy.getPort()), proxy.username.isEmpty() ? null : proxy.username));
}
}
}).channel(NioSocketChannel.class).connect(address, port).syncUninterruptibly();
return clientConnection;
private ClientConnection createTestClientConnection(String host, int port) throws UnknownHostException {
InetSocketAddress address = new InetSocketAddress(InetAddress.getByName(host), port);
ClientConnection connection = new ClientConnection(NetworkSide.CLIENTBOUND);

new Bootstrap()
.group((EventLoopGroup) ClientConnection.CLIENT_IO_GROUP.get())
.handler(new ChannelInitializer<>() {
@Override
protected void initChannel(Channel channel) {
try {
channel.config().setOption(ChannelOption.TCP_NODELAY, true);
} catch (ChannelException ignored) {
}

ChannelPipeline pipeline = channel.pipeline();

if (proxy.type == Proxy.ProxyType.SOCKS5) {
pipeline.addFirst(new Socks5ProxyHandler(new InetSocketAddress(proxy.getIp(), proxy.getPort()),
proxy.username.isEmpty() ? null : proxy.username,
proxy.password.isEmpty() ? null : proxy.password));
} else {
pipeline.addFirst(new Socks4ProxyHandler(new InetSocketAddress(proxy.getIp(), proxy.getPort()),
proxy.username.isEmpty() ? null : proxy.username));
}

pipeline.addLast("timeout", new ReadTimeoutHandler(30));
ClientConnection.addHandlers(pipeline, NetworkSide.CLIENTBOUND, false, null);
connection.addFlowControlHandler(pipeline);
}
})
.channel(NioSocketChannel.class)
.connect(address)
.syncUninterruptibly();

return connection;
}

public void pingPendingNetworks() {
Expand Down