Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-17 05:20:14 +01:00
Cherry-pick full Unix domain socket support from b00389029f
Closes #991. We can't properly support this without an API break, so let's just do it in 5.0.0.
Dieser Commit ist enthalten in:
Ursprung
02ed711573
Commit
771dfa8d0e
@ -9,22 +9,22 @@ package com.velocitypowered.api.event.proxy;
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.velocitypowered.api.network.ListenerType;
|
import com.velocitypowered.api.network.ListenerType;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event is fired by the proxy after a listener starts accepting connections.
|
* This event is fired by the proxy after a listener starts accepting connections.
|
||||||
*/
|
*/
|
||||||
public final class ListenerBoundEvent {
|
public final class ListenerBoundEvent {
|
||||||
|
|
||||||
private final InetSocketAddress address;
|
private final SocketAddress address;
|
||||||
private final ListenerType listenerType;
|
private final ListenerType listenerType;
|
||||||
|
|
||||||
public ListenerBoundEvent(InetSocketAddress address, ListenerType listenerType) {
|
public ListenerBoundEvent(SocketAddress address, ListenerType listenerType) {
|
||||||
this.address = Preconditions.checkNotNull(address, "address");
|
this.address = Preconditions.checkNotNull(address, "address");
|
||||||
this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType");
|
this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType");
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetSocketAddress getAddress() {
|
public SocketAddress getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,22 +9,22 @@ package com.velocitypowered.api.event.proxy;
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.velocitypowered.api.network.ListenerType;
|
import com.velocitypowered.api.network.ListenerType;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event is fired by the proxy before the proxy stops accepting connections.
|
* This event is fired by the proxy before the proxy stops accepting connections.
|
||||||
*/
|
*/
|
||||||
public final class ListenerCloseEvent {
|
public final class ListenerCloseEvent {
|
||||||
|
|
||||||
private final InetSocketAddress address;
|
private final SocketAddress address;
|
||||||
private final ListenerType listenerType;
|
private final ListenerType listenerType;
|
||||||
|
|
||||||
public ListenerCloseEvent(InetSocketAddress address, ListenerType listenerType) {
|
public ListenerCloseEvent(SocketAddress address, ListenerType listenerType) {
|
||||||
this.address = Preconditions.checkNotNull(address, "address");
|
this.address = Preconditions.checkNotNull(address, "address");
|
||||||
this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType");
|
this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType");
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetSocketAddress getAddress() {
|
public SocketAddress getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ package com.velocitypowered.api.proxy;
|
|||||||
|
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,11 +18,11 @@ import java.util.Optional;
|
|||||||
public interface InboundConnection {
|
public interface InboundConnection {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the player's IP address.
|
* Returns the player's remote address.
|
||||||
*
|
*
|
||||||
* @return the player's IP
|
* @return the player's remote address
|
||||||
*/
|
*/
|
||||||
InetSocketAddress getRemoteAddress();
|
SocketAddress getRemoteAddress();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hostname that the user entered into the client, if applicable.
|
* Returns the hostname that the user entered into the client, if applicable.
|
||||||
|
@ -31,7 +31,6 @@ import net.kyori.adventure.text.Component;
|
|||||||
import net.kyori.adventure.text.event.HoverEvent;
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
import net.kyori.adventure.text.event.HoverEventSource;
|
import net.kyori.adventure.text.event.HoverEventSource;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,7 +18,7 @@ import com.velocitypowered.api.proxy.server.RegisteredServer;
|
|||||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||||
import com.velocitypowered.api.scheduler.Scheduler;
|
import com.velocitypowered.api.scheduler.Scheduler;
|
||||||
import com.velocitypowered.api.util.ProxyVersion;
|
import com.velocitypowered.api.util.ProxyVersion;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -179,7 +179,7 @@ public interface ProxyServer extends Audience {
|
|||||||
*
|
*
|
||||||
* @return the address the proxy is bound to
|
* @return the address the proxy is bound to
|
||||||
*/
|
*/
|
||||||
InetSocketAddress getBoundAddress();
|
SocketAddress getBoundAddress();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link ProxyConfig} instance.
|
* Gets the {@link ProxyConfig} instance.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
package com.velocitypowered.api.proxy.server;
|
package com.velocitypowered.api.proxy.server;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||||||
public final class ServerInfo implements Comparable<ServerInfo> {
|
public final class ServerInfo implements Comparable<ServerInfo> {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final InetSocketAddress address;
|
private final SocketAddress address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new ServerInfo object.
|
* Creates a new ServerInfo object.
|
||||||
@ -27,7 +27,7 @@ public final class ServerInfo implements Comparable<ServerInfo> {
|
|||||||
* @param name the name for the server
|
* @param name the name for the server
|
||||||
* @param address the address of the server to connect to
|
* @param address the address of the server to connect to
|
||||||
*/
|
*/
|
||||||
public ServerInfo(String name, InetSocketAddress address) {
|
public ServerInfo(String name, SocketAddress address) {
|
||||||
this.name = Preconditions.checkNotNull(name, "name");
|
this.name = Preconditions.checkNotNull(name, "name");
|
||||||
this.address = Preconditions.checkNotNull(address, "address");
|
this.address = Preconditions.checkNotNull(address, "address");
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ public final class ServerInfo implements Comparable<ServerInfo> {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final InetSocketAddress getAddress() {
|
public final SocketAddress getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ import io.netty.channel.EventLoopGroup;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
@ -231,16 +232,18 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
// init console permissions after plugins are loaded
|
// init console permissions after plugins are loaded
|
||||||
console.setupPermissions();
|
console.setupPermissions();
|
||||||
|
|
||||||
|
final SocketAddress bindAddr = configuration.getBind();
|
||||||
final Integer port = this.options.getPort();
|
final Integer port = this.options.getPort();
|
||||||
if (port != null) {
|
if (port != null && bindAddr instanceof InetSocketAddress) {
|
||||||
logger.debug("Overriding bind port to {} from command line option", port);
|
logger.debug("Overriding bind port to {} from command line option", port);
|
||||||
this.cm.bind(new InetSocketAddress(configuration.getBind().getHostString(), port));
|
this.cm.bind(new InetSocketAddress(((InetSocketAddress) bindAddr).getHostString(), port));
|
||||||
} else {
|
} else {
|
||||||
this.cm.bind(configuration.getBind());
|
this.cm.bind(configuration.getBind());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configuration.isQueryEnabled()) {
|
if (configuration.isQueryEnabled() && bindAddr instanceof InetSocketAddress) {
|
||||||
this.cm.queryBind(configuration.getBind().getHostString(), configuration.getQueryPort());
|
this.cm.queryBind(((InetSocketAddress) bindAddr).getHostString(),
|
||||||
|
configuration.getQueryPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
Metrics.VelocityMetrics.startMetrics(this, configuration.getMetrics());
|
Metrics.VelocityMetrics.startMetrics(this, configuration.getMetrics());
|
||||||
@ -362,8 +365,8 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
logger.info("Loaded {} plugins", pluginManager.getPlugins().size());
|
logger.info("Loaded {} plugins", pluginManager.getPlugins().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bootstrap createBootstrap(@Nullable EventLoopGroup group) {
|
public Bootstrap createBootstrap(@Nullable EventLoopGroup group, SocketAddress target) {
|
||||||
return this.cm.createWorker(group);
|
return this.cm.createWorker(group, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelInitializer<Channel> getBackendChannelInitializer() {
|
public ChannelInitializer<Channel> getBackendChannelInitializer() {
|
||||||
@ -443,7 +446,9 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we have a new bind address, bind to it
|
// If we have a new bind address, bind to it
|
||||||
if (!configuration.getBind().equals(newConfiguration.getBind())) {
|
SocketAddress oldBind = configuration.getBind();
|
||||||
|
SocketAddress newBind = newConfiguration.getBind();
|
||||||
|
if (!configuration.getBind().equals(newBind)) {
|
||||||
this.cm.bind(newConfiguration.getBind());
|
this.cm.bind(newConfiguration.getBind());
|
||||||
this.cm.close(configuration.getBind());
|
this.cm.close(configuration.getBind());
|
||||||
}
|
}
|
||||||
@ -451,12 +456,13 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
boolean queryPortChanged = newConfiguration.getQueryPort() != configuration.getQueryPort();
|
boolean queryPortChanged = newConfiguration.getQueryPort() != configuration.getQueryPort();
|
||||||
boolean queryAlreadyEnabled = configuration.isQueryEnabled();
|
boolean queryAlreadyEnabled = configuration.isQueryEnabled();
|
||||||
boolean queryEnabled = newConfiguration.isQueryEnabled();
|
boolean queryEnabled = newConfiguration.isQueryEnabled();
|
||||||
if ((!queryEnabled && queryAlreadyEnabled) || queryPortChanged) {
|
if (oldBind instanceof InetSocketAddress
|
||||||
|
&& ((!queryEnabled && queryAlreadyEnabled) || queryPortChanged)) {
|
||||||
this.cm.close(new InetSocketAddress(
|
this.cm.close(new InetSocketAddress(
|
||||||
configuration.getBind().getHostString(), configuration.getQueryPort()));
|
((InetSocketAddress) oldBind).getHostString(), configuration.getQueryPort()));
|
||||||
}
|
}
|
||||||
if (queryEnabled && queryPortChanged) {
|
if (queryEnabled && queryPortChanged && configuration.getBind() instanceof InetSocketAddress) {
|
||||||
this.cm.queryBind(newConfiguration.getBind().getHostString(),
|
this.cm.queryBind(((InetSocketAddress) newConfiguration.getBind()).getHostString(),
|
||||||
newConfiguration.getQueryPort());
|
newConfiguration.getQueryPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,7 +724,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InetSocketAddress getBoundAddress() {
|
public SocketAddress getBoundAddress() {
|
||||||
if (configuration == null) {
|
if (configuration == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"No configuration"); // even though you'll never get the chance... heh, heh
|
"No configuration"); // even though you'll never get the chance... heh, heh
|
||||||
|
@ -32,7 +32,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -247,7 +247,7 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetSocketAddress getBind() {
|
public SocketAddress getBind() {
|
||||||
return AddressUtil.parseAndResolveAddress(bind);
|
return AddressUtil.parseAndResolveAddress(bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,9 @@ import com.velocitypowered.proxy.server.VelocityRegisteredServer;
|
|||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.channel.unix.DomainSocketAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
@ -94,8 +97,16 @@ public class BungeeCordMessageResponder {
|
|||||||
ByteBuf buf = Unpooled.buffer();
|
ByteBuf buf = Unpooled.buffer();
|
||||||
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
out.writeUTF("IP");
|
out.writeUTF("IP");
|
||||||
out.writeUTF(player.getRemoteAddress().getHostString());
|
|
||||||
out.writeInt(player.getRemoteAddress().getPort());
|
SocketAddress address = player.getRemoteAddress();
|
||||||
|
if (address instanceof InetSocketAddress) {
|
||||||
|
InetSocketAddress serverInetAddr = (InetSocketAddress) address;
|
||||||
|
out.writeUTF(serverInetAddr.getHostString());
|
||||||
|
out.writeInt(serverInetAddr.getPort());
|
||||||
|
} else {
|
||||||
|
out.writeUTF("unix://" + ((DomainSocketAddress) address).path());
|
||||||
|
out.writeInt(0);
|
||||||
|
}
|
||||||
sendResponseOnConnection(buf);
|
sendResponseOnConnection(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,8 +245,15 @@ public class BungeeCordMessageResponder {
|
|||||||
|
|
||||||
out.writeUTF("IPOther");
|
out.writeUTF("IPOther");
|
||||||
out.writeUTF(player.getUsername());
|
out.writeUTF(player.getUsername());
|
||||||
out.writeUTF(player.getRemoteAddress().getHostString());
|
SocketAddress address = player.getRemoteAddress();
|
||||||
out.writeInt(player.getRemoteAddress().getPort());
|
if (address instanceof InetSocketAddress) {
|
||||||
|
InetSocketAddress serverInetAddr = (InetSocketAddress) address;
|
||||||
|
out.writeUTF(serverInetAddr.getHostString());
|
||||||
|
out.writeInt(serverInetAddr.getPort());
|
||||||
|
} else {
|
||||||
|
out.writeUTF("unix://" + ((DomainSocketAddress) address).path());
|
||||||
|
out.writeInt(0);
|
||||||
|
}
|
||||||
|
|
||||||
sendResponseOnConnection(buf);
|
sendResponseOnConnection(buf);
|
||||||
});
|
});
|
||||||
@ -248,8 +266,15 @@ public class BungeeCordMessageResponder {
|
|||||||
|
|
||||||
out.writeUTF("ServerIP");
|
out.writeUTF("ServerIP");
|
||||||
out.writeUTF(info.getServerInfo().getName());
|
out.writeUTF(info.getServerInfo().getName());
|
||||||
out.writeUTF(info.getServerInfo().getAddress().getHostString());
|
SocketAddress address = info.getServerInfo().getAddress();
|
||||||
out.writeShort(info.getServerInfo().getAddress().getPort());
|
if (address instanceof InetSocketAddress) {
|
||||||
|
InetSocketAddress serverInetAddr = (InetSocketAddress) address;
|
||||||
|
out.writeUTF(serverInetAddr.getHostString());
|
||||||
|
out.writeShort(serverInetAddr.getPort());
|
||||||
|
} else {
|
||||||
|
out.writeUTF("unix://" + ((DomainSocketAddress) address).path());
|
||||||
|
out.writeShort(0);
|
||||||
|
}
|
||||||
|
|
||||||
sendResponseOnConnection(buf);
|
sendResponseOnConnection(buf);
|
||||||
});
|
});
|
||||||
|
@ -45,6 +45,8 @@ import com.velocitypowered.proxy.server.VelocityRegisteredServer;
|
|||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -98,9 +100,10 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
CompletableFuture<Impl> result = new CompletableFuture<>();
|
CompletableFuture<Impl> result = new CompletableFuture<>();
|
||||||
// Note: we use the event loop for the connection the player is on. This reduces context
|
// Note: we use the event loop for the connection the player is on. This reduces context
|
||||||
// switches.
|
// switches.
|
||||||
server.createBootstrap(proxyPlayer.getConnection().eventLoop())
|
SocketAddress destinationAddress = registeredServer.getServerInfo().getAddress();
|
||||||
|
server.createBootstrap(proxyPlayer.getConnection().eventLoop(), destinationAddress)
|
||||||
.handler(server.getBackendChannelInitializer())
|
.handler(server.getBackendChannelInitializer())
|
||||||
.connect(registeredServer.getServerInfo().getAddress())
|
.connect(destinationAddress)
|
||||||
.addListener((ChannelFutureListener) future -> {
|
.addListener((ChannelFutureListener) future -> {
|
||||||
if (future.isSuccess()) {
|
if (future.isSuccess()) {
|
||||||
connection = new MinecraftConnection(future.channel(), server);
|
connection = new MinecraftConnection(future.channel(), server);
|
||||||
@ -124,23 +127,37 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
}
|
}
|
||||||
|
|
||||||
String getPlayerRemoteAddressAsString() {
|
String getPlayerRemoteAddressAsString() {
|
||||||
final String addr = proxyPlayer.getRemoteAddress().getAddress().getHostAddress();
|
final SocketAddress address = proxyPlayer.getRemoteAddress();
|
||||||
int ipv6ScopeIdx = addr.indexOf('%');
|
if (!(address instanceof InetSocketAddress)) {
|
||||||
if (ipv6ScopeIdx == -1) {
|
return address.toString();
|
||||||
return addr;
|
|
||||||
} else {
|
|
||||||
return addr.substring(0, ipv6ScopeIdx);
|
|
||||||
}
|
}
|
||||||
|
final String host = ((InetSocketAddress) address).getAddress().getHostAddress();
|
||||||
|
int ipv6ScopeIdx = host.indexOf('%');
|
||||||
|
if (ipv6ScopeIdx == -1) {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
return host.substring(0, ipv6ScopeIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getHandshakeRemoteAddress() {
|
||||||
|
return proxyPlayer.getVirtualHost()
|
||||||
|
.map(InetSocketAddress::getHostString)
|
||||||
|
.or(() -> Optional.of(registeredServer.getServerInfo().getAddress())
|
||||||
|
.filter(addr -> addr instanceof InetSocketAddress)
|
||||||
|
.map(addr -> ((InetSocketAddress) addr).getHostString()))
|
||||||
|
.orElse("");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createLegacyForwardingAddress(UnaryOperator<List<Property>> propertiesTransform) {
|
private String createLegacyForwardingAddress(UnaryOperator<List<Property>> propertiesTransform) {
|
||||||
// BungeeCord IP forwarding is simply a special injection after the "address" in the handshake,
|
// BungeeCord IP forwarding is simply a special injection after the "address" in the handshake,
|
||||||
// separated by \0 (the null byte). In order, you send the original host, the player's IP, their
|
// separated by \0 (the null byte). In order, you send the original host, the player's IP, their
|
||||||
// UUID (undashed), and if you are in online-mode, their login properties (from Mojang).
|
// UUID (undashed), and if you are in online-mode, their login properties (from Mojang).
|
||||||
|
SocketAddress playerRemoteAddress = proxyPlayer.getRemoteAddress();
|
||||||
|
if (!(playerRemoteAddress instanceof InetSocketAddress)) {
|
||||||
|
return getHandshakeRemoteAddress();
|
||||||
|
}
|
||||||
StringBuilder data = new StringBuilder()
|
StringBuilder data = new StringBuilder()
|
||||||
.append(proxyPlayer.getVirtualHost()
|
.append(getHandshakeRemoteAddress())
|
||||||
.orElseGet(() -> registeredServer.getServerInfo().getAddress())
|
|
||||||
.getHostString())
|
|
||||||
.append('\0')
|
.append('\0')
|
||||||
.append(getPlayerRemoteAddressAsString())
|
.append(getPlayerRemoteAddressAsString())
|
||||||
.append('\0')
|
.append('\0')
|
||||||
@ -171,10 +188,6 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
|
|
||||||
// Initiate the handshake.
|
// Initiate the handshake.
|
||||||
ProtocolVersion protocolVersion = proxyPlayer.getConnection().getProtocolVersion();
|
ProtocolVersion protocolVersion = proxyPlayer.getConnection().getProtocolVersion();
|
||||||
String playerVhost = proxyPlayer.getVirtualHost()
|
|
||||||
.orElseGet(() -> registeredServer.getServerInfo().getAddress())
|
|
||||||
.getHostString();
|
|
||||||
|
|
||||||
Handshake handshake = new Handshake();
|
Handshake handshake = new Handshake();
|
||||||
handshake.setNextStatus(StateRegistry.LOGIN_ID);
|
handshake.setNextStatus(StateRegistry.LOGIN_ID);
|
||||||
handshake.setProtocolVersion(protocolVersion);
|
handshake.setProtocolVersion(protocolVersion);
|
||||||
@ -184,12 +197,15 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
byte[] secret = server.getConfiguration().getForwardingSecret();
|
byte[] secret = server.getConfiguration().getForwardingSecret();
|
||||||
handshake.setServerAddress(createBungeeGuardForwardingAddress(secret));
|
handshake.setServerAddress(createBungeeGuardForwardingAddress(secret));
|
||||||
} else if (proxyPlayer.getConnection().getType() == ConnectionTypes.LEGACY_FORGE) {
|
} else if (proxyPlayer.getConnection().getType() == ConnectionTypes.LEGACY_FORGE) {
|
||||||
handshake.setServerAddress(playerVhost + HANDSHAKE_HOSTNAME_TOKEN);
|
handshake.setServerAddress(getHandshakeRemoteAddress() + HANDSHAKE_HOSTNAME_TOKEN);
|
||||||
} else {
|
} else {
|
||||||
handshake.setServerAddress(playerVhost);
|
handshake.setServerAddress(getHandshakeRemoteAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
handshake.setPort(registeredServer.getServerInfo().getAddress().getPort());
|
SocketAddress destinationAddr = registeredServer.getServerInfo().getAddress();
|
||||||
|
if (destinationAddr instanceof InetSocketAddress) {
|
||||||
|
handshake.setPort(((InetSocketAddress) destinationAddr).getPort());
|
||||||
|
}
|
||||||
mc.delayedWrite(handshake);
|
mc.delayedWrite(handshake);
|
||||||
|
|
||||||
mc.setProtocolVersion(protocolVersion);
|
mc.setProtocolVersion(protocolVersion);
|
||||||
|
@ -81,6 +81,7 @@ import com.velocitypowered.proxy.util.collect.CappedSet;
|
|||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -304,8 +305,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InetSocketAddress getRemoteAddress() {
|
public SocketAddress getRemoteAddress() {
|
||||||
return (InetSocketAddress) connection.getRemoteAddress();
|
return connection.getRemoteAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -38,6 +38,7 @@ import io.netty.channel.WriteBufferWaterMark;
|
|||||||
import io.netty.channel.epoll.EpollChannelOption;
|
import io.netty.channel.epoll.EpollChannelOption;
|
||||||
import io.netty.util.concurrent.GlobalEventExecutor;
|
import io.netty.util.concurrent.GlobalEventExecutor;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@ -57,7 +58,7 @@ public final class ConnectionManager {
|
|||||||
private static final WriteBufferWaterMark SERVER_WRITE_MARK = new WriteBufferWaterMark(1 << 20,
|
private static final WriteBufferWaterMark SERVER_WRITE_MARK = new WriteBufferWaterMark(1 << 20,
|
||||||
1 << 21);
|
1 << 21);
|
||||||
private static final Logger LOGGER = LogManager.getLogger(ConnectionManager.class);
|
private static final Logger LOGGER = LogManager.getLogger(ConnectionManager.class);
|
||||||
private final Map<InetSocketAddress, Endpoint> endpoints = new HashMap<>();
|
private final Map<SocketAddress, Endpoint> endpoints = new HashMap<>();
|
||||||
private final TransportType transportType;
|
private final TransportType transportType;
|
||||||
private final EventLoopGroup bossGroup;
|
private final EventLoopGroup bossGroup;
|
||||||
private final EventLoopGroup workerGroup;
|
private final EventLoopGroup workerGroup;
|
||||||
@ -113,18 +114,20 @@ public final class ConnectionManager {
|
|||||||
*
|
*
|
||||||
* @param address the address to bind to
|
* @param address the address to bind to
|
||||||
*/
|
*/
|
||||||
public void bind(final InetSocketAddress address) {
|
public void bind(final SocketAddress address) {
|
||||||
final ServerBootstrap bootstrap = new ServerBootstrap()
|
final ServerBootstrap bootstrap = new ServerBootstrap()
|
||||||
.channelFactory(this.transportType.serverSocketChannelFactory)
|
.channelFactory(this.transportType.getServerChannelFactory(address))
|
||||||
.group(this.bossGroup, this.workerGroup)
|
.group(this.bossGroup, this.workerGroup)
|
||||||
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, SERVER_WRITE_MARK)
|
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, SERVER_WRITE_MARK)
|
||||||
.childHandler(this.serverChannelInitializer.get())
|
.childHandler(this.serverChannelInitializer.get())
|
||||||
.childOption(ChannelOption.TCP_NODELAY, true)
|
|
||||||
.childOption(ChannelOption.IP_TOS, 0x18)
|
|
||||||
.localAddress(address);
|
.localAddress(address);
|
||||||
|
|
||||||
if (transportType == TransportType.EPOLL && server.getConfiguration().useTcpFastOpen()) {
|
if (address instanceof InetSocketAddress) {
|
||||||
bootstrap.option(EpollChannelOption.TCP_FASTOPEN, 3);
|
bootstrap.childOption(ChannelOption.TCP_NODELAY, true)
|
||||||
|
.childOption(ChannelOption.IP_TOS, 0x18);
|
||||||
|
if (transportType == TransportType.EPOLL && server.getConfiguration().useTcpFastOpen()) {
|
||||||
|
bootstrap.option(EpollChannelOption.TCP_FASTOPEN, 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrap.bind()
|
bootstrap.bind()
|
||||||
@ -173,14 +176,15 @@ public final class ConnectionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a TCP {@link Bootstrap} using Velocity's event loops.
|
* Creates a {@link Bootstrap} using Velocity's event loops.
|
||||||
*
|
*
|
||||||
* @param group the event loop group to use. Use {@code null} for the default worker group.
|
* @param group the event loop group to use. Use {@code null} for the default worker group.
|
||||||
|
* @param target the address the client will connect to
|
||||||
* @return a new {@link Bootstrap}
|
* @return a new {@link Bootstrap}
|
||||||
*/
|
*/
|
||||||
public Bootstrap createWorker(@Nullable EventLoopGroup group) {
|
public Bootstrap createWorker(@Nullable EventLoopGroup group, SocketAddress target) {
|
||||||
Bootstrap bootstrap = new Bootstrap()
|
Bootstrap bootstrap = new Bootstrap()
|
||||||
.channelFactory(this.transportType.socketChannelFactory)
|
.channelFactory(this.transportType.getClientChannelFactory(target))
|
||||||
.option(ChannelOption.TCP_NODELAY, true)
|
.option(ChannelOption.TCP_NODELAY, true)
|
||||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,
|
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,
|
||||||
this.server.getConfiguration().getConnectTimeout())
|
this.server.getConfiguration().getConnectTimeout())
|
||||||
@ -197,7 +201,7 @@ public final class ConnectionManager {
|
|||||||
*
|
*
|
||||||
* @param oldBind the endpoint to close
|
* @param oldBind the endpoint to close
|
||||||
*/
|
*/
|
||||||
public void close(InetSocketAddress oldBind) {
|
public void close(SocketAddress oldBind) {
|
||||||
Endpoint endpoint = endpoints.remove(oldBind);
|
Endpoint endpoint = endpoints.remove(oldBind);
|
||||||
|
|
||||||
// Fire proxy close event to notify plugins of socket close. We block since plugins
|
// Fire proxy close event to notify plugins of socket close. We block since plugins
|
||||||
@ -215,8 +219,8 @@ public final class ConnectionManager {
|
|||||||
* Closes all endpoints.
|
* Closes all endpoints.
|
||||||
*/
|
*/
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
for (final Map.Entry<InetSocketAddress, Endpoint> entry : this.endpoints.entrySet()) {
|
for (final Map.Entry<SocketAddress, Endpoint> entry : this.endpoints.entrySet()) {
|
||||||
final InetSocketAddress address = entry.getKey();
|
final SocketAddress address = entry.getKey();
|
||||||
final Endpoint endpoint = entry.getValue();
|
final Endpoint endpoint = entry.getValue();
|
||||||
|
|
||||||
// Fire proxy close event to notify plugins of socket close. We block since plugins
|
// Fire proxy close event to notify plugins of socket close. We block since plugins
|
||||||
|
@ -18,11 +18,15 @@
|
|||||||
package com.velocitypowered.proxy.network;
|
package com.velocitypowered.proxy.network;
|
||||||
|
|
||||||
import com.velocitypowered.proxy.util.concurrent.VelocityNettyThreadFactory;
|
import com.velocitypowered.proxy.util.concurrent.VelocityNettyThreadFactory;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFactory;
|
import io.netty.channel.ChannelFactory;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.ServerChannel;
|
||||||
import io.netty.channel.epoll.Epoll;
|
import io.netty.channel.epoll.Epoll;
|
||||||
import io.netty.channel.epoll.EpollDatagramChannel;
|
import io.netty.channel.epoll.EpollDatagramChannel;
|
||||||
|
import io.netty.channel.epoll.EpollDomainSocketChannel;
|
||||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||||
|
import io.netty.channel.epoll.EpollServerDomainSocketChannel;
|
||||||
import io.netty.channel.epoll.EpollServerSocketChannel;
|
import io.netty.channel.epoll.EpollServerSocketChannel;
|
||||||
import io.netty.channel.epoll.EpollSocketChannel;
|
import io.netty.channel.epoll.EpollSocketChannel;
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
@ -32,6 +36,10 @@ import io.netty.channel.socket.SocketChannel;
|
|||||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
import io.netty.channel.unix.DomainSocketAddress;
|
||||||
|
import io.netty.channel.unix.DomainSocketChannel;
|
||||||
|
import io.netty.channel.unix.ServerDomainSocketChannel;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
@ -42,27 +50,37 @@ public enum TransportType {
|
|||||||
NIO("NIO", NioServerSocketChannel::new,
|
NIO("NIO", NioServerSocketChannel::new,
|
||||||
NioSocketChannel::new,
|
NioSocketChannel::new,
|
||||||
NioDatagramChannel::new,
|
NioDatagramChannel::new,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
(name, type) -> new NioEventLoopGroup(0, createThreadFactory(name, type))),
|
(name, type) -> new NioEventLoopGroup(0, createThreadFactory(name, type))),
|
||||||
EPOLL("epoll", EpollServerSocketChannel::new,
|
EPOLL("epoll", EpollServerSocketChannel::new,
|
||||||
EpollSocketChannel::new,
|
EpollSocketChannel::new,
|
||||||
EpollDatagramChannel::new,
|
EpollDatagramChannel::new,
|
||||||
|
EpollServerDomainSocketChannel::new,
|
||||||
|
EpollDomainSocketChannel::new,
|
||||||
(name, type) -> new EpollEventLoopGroup(0, createThreadFactory(name, type)));
|
(name, type) -> new EpollEventLoopGroup(0, createThreadFactory(name, type)));
|
||||||
|
|
||||||
final String name;
|
final String name;
|
||||||
final ChannelFactory<? extends ServerSocketChannel> serverSocketChannelFactory;
|
final ChannelFactory<? extends ServerSocketChannel> serverSocketChannelFactory;
|
||||||
final ChannelFactory<? extends SocketChannel> socketChannelFactory;
|
final ChannelFactory<? extends SocketChannel> socketChannelFactory;
|
||||||
final ChannelFactory<? extends DatagramChannel> datagramChannelFactory;
|
final ChannelFactory<? extends DatagramChannel> datagramChannelFactory;
|
||||||
|
final ChannelFactory<? extends ServerDomainSocketChannel> domainServerSocketChannelFactory;
|
||||||
|
final ChannelFactory<? extends DomainSocketChannel> domainSocketChannelFactory;
|
||||||
final BiFunction<String, Type, EventLoopGroup> eventLoopGroupFactory;
|
final BiFunction<String, Type, EventLoopGroup> eventLoopGroupFactory;
|
||||||
|
|
||||||
TransportType(final String name,
|
TransportType(final String name,
|
||||||
final ChannelFactory<? extends ServerSocketChannel> serverSocketChannelFactory,
|
final ChannelFactory<? extends ServerSocketChannel> serverSocketChannelFactory,
|
||||||
final ChannelFactory<? extends SocketChannel> socketChannelFactory,
|
final ChannelFactory<? extends SocketChannel> socketChannelFactory,
|
||||||
final ChannelFactory<? extends DatagramChannel> datagramChannelFactory,
|
final ChannelFactory<? extends DatagramChannel> datagramChannelFactory,
|
||||||
|
final ChannelFactory<? extends ServerDomainSocketChannel> domainServerSocketChannelFactory,
|
||||||
|
final ChannelFactory<? extends DomainSocketChannel> domainSocketChannelFactory,
|
||||||
final BiFunction<String, Type, EventLoopGroup> eventLoopGroupFactory) {
|
final BiFunction<String, Type, EventLoopGroup> eventLoopGroupFactory) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.serverSocketChannelFactory = serverSocketChannelFactory;
|
this.serverSocketChannelFactory = serverSocketChannelFactory;
|
||||||
this.socketChannelFactory = socketChannelFactory;
|
this.socketChannelFactory = socketChannelFactory;
|
||||||
this.datagramChannelFactory = datagramChannelFactory;
|
this.datagramChannelFactory = datagramChannelFactory;
|
||||||
|
this.domainServerSocketChannelFactory = domainServerSocketChannelFactory;
|
||||||
|
this.domainSocketChannelFactory = domainSocketChannelFactory;
|
||||||
this.eventLoopGroupFactory = eventLoopGroupFactory;
|
this.eventLoopGroupFactory = eventLoopGroupFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +89,40 @@ public enum TransportType {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the channel factory to use to listen on the specified socket address.
|
||||||
|
*
|
||||||
|
* @param address the address we want to listen on
|
||||||
|
* @return the channel factory
|
||||||
|
*/
|
||||||
|
public ChannelFactory<? extends ServerChannel> getServerChannelFactory(SocketAddress address) {
|
||||||
|
if (address instanceof DomainSocketAddress) {
|
||||||
|
if (this.domainServerSocketChannelFactory == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Domain sockets are not available for non-Linux platforms");
|
||||||
|
}
|
||||||
|
return this.domainServerSocketChannelFactory;
|
||||||
|
}
|
||||||
|
return this.serverSocketChannelFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the channel factory to use to connect on the specified socket address.
|
||||||
|
*
|
||||||
|
* @param address the address we want to connect to
|
||||||
|
* @return the channel factory
|
||||||
|
*/
|
||||||
|
public ChannelFactory<? extends Channel> getClientChannelFactory(SocketAddress address) {
|
||||||
|
if (address instanceof DomainSocketAddress) {
|
||||||
|
if (this.domainSocketChannelFactory == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Domain sockets are not available for non-Linux platforms");
|
||||||
|
}
|
||||||
|
return this.domainSocketChannelFactory;
|
||||||
|
}
|
||||||
|
return this.socketChannelFactory;
|
||||||
|
}
|
||||||
|
|
||||||
public EventLoopGroup createEventLoopGroup(final Type type) {
|
public EventLoopGroup createEventLoopGroup(final Type type) {
|
||||||
return this.eventLoopGroupFactory.apply(this.name, type);
|
return this.eventLoopGroupFactory.apply(this.name, type);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import io.netty.channel.socket.DatagramPacket;
|
import io.netty.channel.socket.DatagramPacket;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -92,8 +93,8 @@ public class GameSpyQueryHandler extends SimpleChannelInboundHandler<DatagramPac
|
|||||||
.map(server.getConfiguration().getQueryMap())
|
.map(server.getConfiguration().getQueryMap())
|
||||||
.currentPlayers(server.getPlayerCount())
|
.currentPlayers(server.getPlayerCount())
|
||||||
.maxPlayers(server.getConfiguration().getShowMaxPlayers())
|
.maxPlayers(server.getConfiguration().getShowMaxPlayers())
|
||||||
.proxyPort(server.getConfiguration().getBind().getPort())
|
.proxyPort(((InetSocketAddress) server.getConfiguration().getBind()).getPort())
|
||||||
.proxyHost(server.getConfiguration().getBind().getHostString())
|
.proxyHost(((InetSocketAddress) server.getConfiguration().getBind()).getHostString())
|
||||||
.players(server.getAllPlayers().stream().map(Player::getUsername)
|
.players(server.getAllPlayers().stream().map(Player::getUsername)
|
||||||
.collect(Collectors.toList()))
|
.collect(Collectors.toList()))
|
||||||
.proxyVersion("Velocity")
|
.proxyVersion("Velocity")
|
||||||
|
@ -29,6 +29,8 @@ import com.velocitypowered.proxy.protocol.packet.StatusRequest;
|
|||||||
import com.velocitypowered.proxy.protocol.packet.StatusResponse;
|
import com.velocitypowered.proxy.protocol.packet.StatusResponse;
|
||||||
import io.netty.channel.EventLoop;
|
import io.netty.channel.EventLoop;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,8 +57,16 @@ public class PingSessionHandler implements MinecraftSessionHandler {
|
|||||||
public void activated() {
|
public void activated() {
|
||||||
Handshake handshake = new Handshake();
|
Handshake handshake = new Handshake();
|
||||||
handshake.setNextStatus(StateRegistry.STATUS_ID);
|
handshake.setNextStatus(StateRegistry.STATUS_ID);
|
||||||
handshake.setServerAddress(server.getServerInfo().getAddress().getHostString());
|
|
||||||
handshake.setPort(server.getServerInfo().getAddress().getPort());
|
SocketAddress address = server.getServerInfo().getAddress();
|
||||||
|
if (address instanceof InetSocketAddress) {
|
||||||
|
InetSocketAddress socketAddr = (InetSocketAddress) address;
|
||||||
|
handshake.setServerAddress(socketAddr.getHostString());
|
||||||
|
handshake.setPort(socketAddr.getPort());
|
||||||
|
} else {
|
||||||
|
// Just fake it
|
||||||
|
handshake.setServerAddress("127.0.0.1");
|
||||||
|
}
|
||||||
handshake.setProtocolVersion(version);
|
handshake.setProtocolVersion(version);
|
||||||
connection.delayedWrite(handshake);
|
connection.delayedWrite(handshake);
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ public class VelocityRegisteredServer implements RegisteredServer, ForwardingAud
|
|||||||
throw new IllegalStateException("No Velocity proxy instance available");
|
throw new IllegalStateException("No Velocity proxy instance available");
|
||||||
}
|
}
|
||||||
CompletableFuture<ServerPing> pingFuture = new CompletableFuture<>();
|
CompletableFuture<ServerPing> pingFuture = new CompletableFuture<>();
|
||||||
server.createBootstrap(loop)
|
server.createBootstrap(loop, serverInfo.getAddress())
|
||||||
.handler(new ChannelInitializer<Channel>() {
|
.handler(new ChannelInitializer<Channel>() {
|
||||||
@Override
|
@Override
|
||||||
protected void initChannel(Channel ch) throws Exception {
|
protected void initChannel(Channel ch) throws Exception {
|
||||||
|
@ -19,8 +19,11 @@ package com.velocitypowered.proxy.util;
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.net.InetAddresses;
|
import com.google.common.net.InetAddresses;
|
||||||
|
import io.netty.channel.epoll.Epoll;
|
||||||
|
import io.netty.channel.unix.DomainSocketAddress;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,14 +38,16 @@ public final class AddressUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to parse an IP address of the form {@code 127.0.0.1:25565}. The returned
|
* Attempts to parse a socket address of the form {@code 127.0.0.1:25565}. The returned
|
||||||
* {@link InetSocketAddress} is not resolved.
|
* {@link SocketAddress} is not resolved if it is a {@link InetSocketAddress}.
|
||||||
*
|
*
|
||||||
* @param ip the IP to parse
|
* @param ip the IP to parse
|
||||||
* @return the parsed address
|
* @return the parsed address
|
||||||
*/
|
*/
|
||||||
public static InetSocketAddress parseAddress(String ip) {
|
public static SocketAddress parseAddress(String ip) {
|
||||||
Preconditions.checkNotNull(ip, "ip");
|
if (ip.startsWith("unix://") && Epoll.isAvailable()) {
|
||||||
|
return new DomainSocketAddress(ip.substring("unix://".length()));
|
||||||
|
}
|
||||||
URI uri = URI.create("tcp://" + ip);
|
URI uri = URI.create("tcp://" + ip);
|
||||||
if (uri.getHost() == null) {
|
if (uri.getHost() == null) {
|
||||||
throw new IllegalStateException("Invalid hostname/IP " + ip);
|
throw new IllegalStateException("Invalid hostname/IP " + ip);
|
||||||
@ -58,13 +63,16 @@ public final class AddressUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to parse an IP address of the form {@code 127.0.0.1:25565}. The returned
|
* Attempts to parse a socket address of the form {@code 127.0.0.1:25565}. The returned
|
||||||
* {@link InetSocketAddress} is resolved.
|
* {@link SocketAddress} is resolved if it is a {@link InetSocketAddress}.
|
||||||
*
|
*
|
||||||
* @param ip the IP to parse
|
* @param ip the IP to parse
|
||||||
* @return the parsed address
|
* @return the parsed address
|
||||||
*/
|
*/
|
||||||
public static InetSocketAddress parseAndResolveAddress(String ip) {
|
public static SocketAddress parseAndResolveAddress(String ip) {
|
||||||
|
if (ip.startsWith("unix://") && Epoll.isAvailable()) {
|
||||||
|
return new DomainSocketAddress(ip.substring("unix://".length()));
|
||||||
|
}
|
||||||
Preconditions.checkNotNull(ip, "ip");
|
Preconditions.checkNotNull(ip, "ip");
|
||||||
URI uri = URI.create("tcp://" + ip);
|
URI uri = URI.create("tcp://" + ip);
|
||||||
if (uri.getHost() == null) {
|
if (uri.getHost() == null) {
|
||||||
|
@ -38,6 +38,7 @@ import java.net.Inet4Address;
|
|||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -196,14 +197,19 @@ public enum InformationUtils {
|
|||||||
public static JsonObject collectServerInfo(RegisteredServer server) {
|
public static JsonObject collectServerInfo(RegisteredServer server) {
|
||||||
JsonObject info = new JsonObject();
|
JsonObject info = new JsonObject();
|
||||||
info.addProperty("currentPlayers", server.getPlayersConnected().size());
|
info.addProperty("currentPlayers", server.getPlayersConnected().size());
|
||||||
InetSocketAddress iaddr = server.getServerInfo().getAddress();
|
SocketAddress addr = server.getServerInfo().getAddress();
|
||||||
if (iaddr.isUnresolved()) {
|
if (addr instanceof InetSocketAddress) {
|
||||||
// Greetings form Netty 4aa10db9
|
InetSocketAddress iaddr = (InetSocketAddress) addr;
|
||||||
info.addProperty("host", iaddr.getHostString());
|
if (iaddr.isUnresolved()) {
|
||||||
|
// Greetings form Netty 4aa10db9
|
||||||
|
info.addProperty("host", iaddr.getHostString());
|
||||||
|
} else {
|
||||||
|
info.addProperty("host", anonymizeInetAddress(iaddr.getAddress()));
|
||||||
|
}
|
||||||
|
info.addProperty("port", iaddr.getPort());
|
||||||
} else {
|
} else {
|
||||||
info.addProperty("host", anonymizeInetAddress(iaddr.getAddress()));
|
info.addProperty("bind", addr.toString());
|
||||||
}
|
}
|
||||||
info.addProperty("port", iaddr.getPort());
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren