257 lines
6.2 KiB
Java
257 lines
6.2 KiB
Java
package com.comphenix.protocol.injector.netty.channel;
|
|
|
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
|
import io.netty.buffer.ByteBufAllocator;
|
|
import io.netty.channel.Channel;
|
|
import io.netty.channel.ChannelConfig;
|
|
import io.netty.channel.ChannelFuture;
|
|
import io.netty.channel.ChannelMetadata;
|
|
import io.netty.channel.ChannelPipeline;
|
|
import io.netty.channel.ChannelProgressivePromise;
|
|
import io.netty.channel.ChannelPromise;
|
|
import io.netty.channel.EventLoop;
|
|
import io.netty.util.Attribute;
|
|
import io.netty.util.AttributeKey;
|
|
import java.net.SocketAddress;
|
|
import java.util.function.Consumer;
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
/**
|
|
* A netty channel which has all methods delegated to another given channel except for the event loop which is proxied
|
|
* separately. This class can not extend from AbstractChannel as the {@code newUnsafe()} method is protected and can
|
|
* therefore not be called in the delegate channel.
|
|
*/
|
|
final class NettyChannelProxy implements Channel {
|
|
|
|
private final Channel delegate;
|
|
private final EventLoop eventLoop;
|
|
private final NettyChannelInjector injector;
|
|
|
|
public NettyChannelProxy(Channel delegate, EventLoop eventLoop, NettyChannelInjector injector) {
|
|
this.delegate = delegate;
|
|
this.eventLoop = eventLoop;
|
|
this.injector = injector;
|
|
}
|
|
|
|
@Override
|
|
public EventLoop eventLoop() {
|
|
return this.eventLoop;
|
|
}
|
|
|
|
@Override
|
|
public Channel parent() {
|
|
return this.delegate.parent();
|
|
}
|
|
|
|
@Override
|
|
public ChannelConfig config() {
|
|
return this.delegate.config();
|
|
}
|
|
|
|
@Override
|
|
public boolean isOpen() {
|
|
return this.delegate.isOpen();
|
|
}
|
|
|
|
@Override
|
|
public boolean isRegistered() {
|
|
return this.delegate.isRegistered();
|
|
}
|
|
|
|
@Override
|
|
public boolean isActive() {
|
|
return this.delegate.isActive();
|
|
}
|
|
|
|
@Override
|
|
public ChannelMetadata metadata() {
|
|
return this.delegate.metadata();
|
|
}
|
|
|
|
@Override
|
|
public SocketAddress localAddress() {
|
|
return this.delegate.localAddress();
|
|
}
|
|
|
|
@Override
|
|
public SocketAddress remoteAddress() {
|
|
return this.delegate.remoteAddress();
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture closeFuture() {
|
|
return this.delegate.closeFuture();
|
|
}
|
|
|
|
@Override
|
|
public boolean isWritable() {
|
|
return this.delegate.isWritable();
|
|
}
|
|
|
|
@Override
|
|
public Unsafe unsafe() {
|
|
return this.delegate.unsafe();
|
|
}
|
|
|
|
@Override
|
|
public ChannelPipeline pipeline() {
|
|
return this.delegate.pipeline();
|
|
}
|
|
|
|
@Override
|
|
public ByteBufAllocator alloc() {
|
|
return this.delegate.alloc();
|
|
}
|
|
|
|
@Override
|
|
public ChannelPromise newPromise() {
|
|
return this.delegate.newPromise();
|
|
}
|
|
|
|
@Override
|
|
public ChannelProgressivePromise newProgressivePromise() {
|
|
return this.delegate.newProgressivePromise();
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture newSucceededFuture() {
|
|
return this.delegate.newSucceededFuture();
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture newFailedFuture(Throwable cause) {
|
|
return this.delegate.newFailedFuture(cause);
|
|
}
|
|
|
|
@Override
|
|
public ChannelPromise voidPromise() {
|
|
return this.delegate.voidPromise();
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture bind(SocketAddress localAddress) {
|
|
return this.delegate.bind(localAddress);
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture connect(SocketAddress remoteAddress) {
|
|
return this.delegate.connect(remoteAddress);
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
|
|
return this.delegate.connect(remoteAddress, localAddress);
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture disconnect() {
|
|
return this.delegate.disconnect();
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture close() {
|
|
return this.delegate.close();
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture deregister() {
|
|
return this.delegate.deregister();
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
|
|
return this.delegate.bind(localAddress, promise);
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {
|
|
return this.delegate.connect(remoteAddress, promise);
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress,
|
|
ChannelPromise promise) {
|
|
return this.delegate.connect(remoteAddress, localAddress, promise);
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture disconnect(ChannelPromise promise) {
|
|
return this.delegate.disconnect(promise);
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture close(ChannelPromise promise) {
|
|
return this.delegate.close(promise);
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture deregister(ChannelPromise promise) {
|
|
return this.delegate.deregister(promise);
|
|
}
|
|
|
|
@Override
|
|
public Channel read() {
|
|
return this.delegate.read();
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture write(Object msg) {
|
|
return this.write(msg, this.newPromise());
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture write(Object msg, ChannelPromise promise) {
|
|
// only need to do our special handling if we are in the event loop
|
|
if (this.isPacketEventCallNeeded(msg)) {
|
|
this.processPacketOutbound(msg, packet -> this.delegate.write(packet, promise));
|
|
return promise;
|
|
} else {
|
|
// no special handling needed, just write the packet
|
|
return this.delegate.write(msg, promise);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Channel flush() {
|
|
return this.delegate.flush();
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
|
|
// only need to do our special handling if we are in the event loop
|
|
if (this.isPacketEventCallNeeded(msg)) {
|
|
this.processPacketOutbound(msg, packet -> this.delegate.writeAndFlush(packet, promise));
|
|
return promise;
|
|
} else {
|
|
// no special handling needed, just write the packet
|
|
return this.delegate.writeAndFlush(msg, promise);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public ChannelFuture writeAndFlush(Object msg) {
|
|
return this.writeAndFlush(msg, this.newPromise());
|
|
}
|
|
|
|
@Override
|
|
public <T> Attribute<T> attr(AttributeKey<T> key) {
|
|
return this.delegate.attr(key);
|
|
}
|
|
|
|
@Override
|
|
public int compareTo(@NotNull Channel o) {
|
|
return this.delegate.compareTo(o);
|
|
}
|
|
|
|
private boolean isPacketEventCallNeeded(Object msg) {
|
|
return MinecraftReflection.isPacketClass(msg) && !this.injector.wasProcessedBefore(msg);
|
|
}
|
|
|
|
private void processPacketOutbound(Object packet, Consumer<Object> delegateActionHandler) {
|
|
Runnable action = this.injector.processOutbound(() -> delegateActionHandler.accept(packet), false);
|
|
if (action != null) {
|
|
action.run();
|
|
}
|
|
}
|
|
}
|