Some simplifications
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.layer.NetworkLayer;
|
||||
import li.cil.oc2.common.inet.InetUtils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
@@ -123,14 +124,11 @@ public final class TransportMessage {
|
||||
* @return IPv4 source address
|
||||
*/
|
||||
public InetAddress getSrcAddress() {
|
||||
switch (networkProtocolNumber) {
|
||||
case NetworkLayer.PROTOCOL_IPv4:
|
||||
return InetUtils.toJavaInetAddress(getSrcIpv4Address());
|
||||
case NetworkLayer.PROTOCOL_IPv6:
|
||||
return InetUtils.toJavaInetAddress(srcIpAddressMost, srcIpAddressLeast);
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return switch (networkProtocolNumber) {
|
||||
case NetworkLayer.PROTOCOL_IPv4 -> InetUtils.toJavaInetAddress(getSrcIpv4Address());
|
||||
case NetworkLayer.PROTOCOL_IPv6 -> InetUtils.toJavaInetAddress(srcIpAddressMost, srcIpAddressLeast);
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,14 +137,11 @@ public final class TransportMessage {
|
||||
* @return IPv4 destination address
|
||||
*/
|
||||
public InetAddress getDstAddress() {
|
||||
switch (networkProtocolNumber) {
|
||||
case NetworkLayer.PROTOCOL_IPv4:
|
||||
return InetUtils.toJavaInetAddress(getDstIpv4Address());
|
||||
case NetworkLayer.PROTOCOL_IPv6:
|
||||
return InetUtils.toJavaInetAddress(dstIpAddressMost, dstIpAddressLeast);
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return switch (networkProtocolNumber) {
|
||||
case NetworkLayer.PROTOCOL_IPv4 -> InetUtils.toJavaInetAddress(getDstIpv4Address());
|
||||
case NetworkLayer.PROTOCOL_IPv6 -> InetUtils.toJavaInetAddress(dstIpAddressMost, dstIpAddressLeast);
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.layer;
|
||||
|
||||
import li.cil.oc2.api.inet.InternetDeviceLifecycle;
|
||||
import li.cil.oc2.api.inet.provider.NetworkLayerInternetProvider;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.layer;
|
||||
|
||||
import li.cil.oc2.api.inet.InternetDeviceLifecycle;
|
||||
import li.cil.oc2.api.inet.provider.TransportLayerInternetProvider;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.layer;
|
||||
|
||||
import li.cil.oc2.api.inet.InternetDeviceLifecycle;
|
||||
import li.cil.oc2.api.inet.session.Session;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -10,6 +13,8 @@ public interface SessionLayer extends InternetDeviceLifecycle {
|
||||
|
||||
String LAYER_NAME = "Session";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
default void receiveSession(final Receiver receiver) {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.layer;
|
||||
|
||||
import li.cil.oc2.api.inet.InternetDeviceLifecycle;
|
||||
import li.cil.oc2.api.inet.TransportMessage;
|
||||
import li.cil.oc2.api.inet.provider.SessionLayerInternetProvider;
|
||||
|
||||
/**
|
||||
* Transport TCP/IP layer interface.
|
||||
@@ -47,7 +51,7 @@ public interface TransportLayer extends InternetDeviceLifecycle {
|
||||
* {@link TransportLayer#PROTOCOL_NONE}, if no new data has arrived
|
||||
*/
|
||||
default byte receiveTransportMessage(final TransportMessage message) {
|
||||
return 0;
|
||||
return PROTOCOL_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,7 @@
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package li.cil.oc2.api.inet.layer;
|
||||
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
@@ -1,4 +1,7 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.provider;
|
||||
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.layer.LinkLocalLayer;
|
||||
|
||||
/**
|
||||
* Internet access provider for oc2:internet-card item.
|
||||
@@ -1,11 +1,9 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.provider;
|
||||
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.layer.LinkLocalLayer;
|
||||
import li.cil.oc2.api.inet.layer.NetworkLayer;
|
||||
import li.cil.oc2.common.inet.*;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.EndTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An {@link InternetProvider} partial implementation that expects an {@link LinkLocalLayer} implementation from
|
||||
@@ -1,11 +1,13 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.provider;
|
||||
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.layer.LinkLocalLayer;
|
||||
import li.cil.oc2.api.inet.layer.NetworkLayer;
|
||||
import li.cil.oc2.api.inet.layer.TransportLayer;
|
||||
import li.cil.oc2.common.inet.DefaultLinkLocalLayer;
|
||||
import li.cil.oc2.common.inet.DefaultNetworkLayer;
|
||||
import li.cil.oc2.common.inet.InetUtils;
|
||||
import li.cil.oc2.common.inet.NullLayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
/**
|
||||
* An {@link InternetProvider} partial implementation that expects an {@link NetworkLayer} implementation from
|
||||
@@ -1,5 +1,8 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.provider;
|
||||
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.layer.SessionLayer;
|
||||
import li.cil.oc2.api.inet.layer.TransportLayer;
|
||||
import li.cil.oc2.common.inet.DefaultSessionLayer;
|
||||
import li.cil.oc2.common.inet.DefaultTransportLayer;
|
||||
import li.cil.oc2.common.inet.InetUtils;
|
||||
@@ -1,5 +1,9 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.provider;
|
||||
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.layer.NetworkLayer;
|
||||
import li.cil.oc2.api.inet.layer.SessionLayer;
|
||||
import li.cil.oc2.api.inet.layer.TransportLayer;
|
||||
import li.cil.oc2.common.inet.DefaultNetworkLayer;
|
||||
import li.cil.oc2.common.inet.DefaultTransportLayer;
|
||||
import li.cil.oc2.common.inet.InetUtils;
|
||||
@@ -0,0 +1,7 @@
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package li.cil.oc2.api.inet.provider;
|
||||
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
@@ -1,4 +1,4 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.session;
|
||||
|
||||
public interface DatagramSession extends Session {
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.session;
|
||||
|
||||
public interface EchoSession extends Session {
|
||||
int getSequenceNumber();
|
||||
@@ -1,4 +1,4 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.session;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -17,6 +17,13 @@ public interface Session {
|
||||
|
||||
InetSocketAddress getDestination();
|
||||
|
||||
default boolean isClosed() {
|
||||
return switch (getState()) {
|
||||
case FINISH, REJECT, EXPIRED -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
enum States {
|
||||
NEW, ESTABLISHED, FINISH, REJECT, EXPIRED
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package li.cil.oc2.api.inet;
|
||||
package li.cil.oc2.api.inet.session;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.DatagramSession;
|
||||
import li.cil.oc2.api.inet.session.DatagramSession;
|
||||
|
||||
public final class DatagramSessionImpl extends SessionBase implements DatagramSession {
|
||||
private final DatagramSessionDiscriminator discriminator;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.SessionLayer;
|
||||
import li.cil.oc2.api.inet.SessionLayerInternetProvider;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import li.cil.oc2.api.inet.layer.SessionLayer;
|
||||
import li.cil.oc2.api.inet.provider.SessionLayerInternetProvider;
|
||||
|
||||
public final class DefaultInternetProvider extends SessionLayerInternetProvider {
|
||||
public static final DefaultInternetProvider INSTANCE = new DefaultInternetProvider();
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.LinkLocalLayer;
|
||||
import li.cil.oc2.api.inet.NetworkLayer;
|
||||
import li.cil.oc2.api.inet.layer.LinkLocalLayer;
|
||||
import li.cil.oc2.api.inet.layer.NetworkLayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.EndTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.*;
|
||||
import li.cil.oc2.api.inet.layer.NetworkLayer;
|
||||
import li.cil.oc2.api.inet.layer.TransportLayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.*;
|
||||
import li.cil.oc2.api.inet.layer.SessionLayer;
|
||||
import li.cil.oc2.api.inet.session.DatagramSession;
|
||||
import li.cil.oc2.api.inet.session.EchoSession;
|
||||
import li.cil.oc2.api.inet.session.Session;
|
||||
import li.cil.oc2.api.inet.session.StreamSession;
|
||||
import li.cil.oc2.common.Config;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -11,8 +16,6 @@ import java.net.InetAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -23,7 +26,7 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private static final Executor executor = Executors
|
||||
.newSingleThreadExecutor(runnable -> new Thread(runnable, "internet/blocking-session"));
|
||||
.newSingleThreadExecutor(runnable -> new Thread(runnable, "internet/blocking-session"));
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -31,8 +34,8 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private final Set<Session> readySessions = new HashSet<>();
|
||||
private final Set<SelectionKey> ownedKeys = new HashSet<>();
|
||||
private final ReadySessions readySessions = new ReadySessions();
|
||||
|
||||
private final SocketManager socketManager;
|
||||
|
||||
public DefaultSessionLayer(final LayerParameters layerParameters) {
|
||||
@@ -42,14 +45,6 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
for (var key : ownedKeys) {
|
||||
try {
|
||||
key.channel().close();
|
||||
} catch (final IOException exception) {
|
||||
LOGGER.error("Exception on stopping channel", exception);
|
||||
}
|
||||
}
|
||||
ownedKeys.clear();
|
||||
socketManager.detach();
|
||||
}
|
||||
|
||||
@@ -64,32 +59,34 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Session session : readySessions) {
|
||||
while (true) {
|
||||
final Session session = readySessions.getToRead().poll();
|
||||
if (session == null) {
|
||||
break;
|
||||
}
|
||||
if (session.isClosed()) {
|
||||
continue;
|
||||
}
|
||||
if (session instanceof DatagramSession datagramSession) {
|
||||
final SelectionKey selectionKey = (SelectionKey) datagramSession.getUserdata();
|
||||
assert selectionKey != null;
|
||||
if (selectionKey.isReadable()) {
|
||||
LOGGER.info("Datagram received");
|
||||
final DatagramChannel channel = (DatagramChannel) selectionKey.channel();
|
||||
try {
|
||||
final ByteBuffer datagram = receiver.receive(datagramSession);
|
||||
assert datagram != null;
|
||||
final SocketAddress address = channel.receive(datagram);
|
||||
if (address == null) {
|
||||
continue;
|
||||
}
|
||||
if (Config.useSynchronisedNAT && !address.equals(datagramSession.getDestination())) {
|
||||
continue;
|
||||
}
|
||||
datagram.flip();
|
||||
LOGGER.info("Datagram received");
|
||||
final DatagramChannel channel = getChannel(datagramSession);
|
||||
try {
|
||||
final ByteBuffer datagram = receiver.receive(datagramSession);
|
||||
assert datagram != null;
|
||||
final SocketAddress address = channel.receive(datagram);
|
||||
if (address == null) {
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Trying to read datagram socket", e);
|
||||
}
|
||||
if (Config.useSynchronisedNAT && !address.equals(datagramSession.getDestination())) {
|
||||
return;
|
||||
}
|
||||
datagram.flip();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Trying to read datagram socket", e);
|
||||
}
|
||||
LOGGER.info("Datagram received");
|
||||
}
|
||||
}
|
||||
readySessions.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,22 +110,17 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
try {
|
||||
switch (session.getState()) {
|
||||
case NEW: {
|
||||
final DatagramChannel channel = DatagramChannel.open();
|
||||
channel.configureBlocking(false);
|
||||
final SelectionKey key = socketManager.createDatagramChannel(datagramSession, readySessions);
|
||||
datagramSession.setUserdata(key);
|
||||
ownedKeys.add(key);
|
||||
final DatagramChannel channel =
|
||||
socketManager.createDatagramChannel(datagramSession, readySessions);
|
||||
datagramSession.setUserdata(channel);
|
||||
LOGGER.info("Open datagram socket {}", session.getDestination());
|
||||
/* Fallthrough */
|
||||
}
|
||||
case ESTABLISHED: {
|
||||
final SelectionKey key = (SelectionKey) session.getUserdata();
|
||||
assert key != null;
|
||||
if (key.isWritable()) {
|
||||
final DatagramChannel channel = (DatagramChannel) key.channel();
|
||||
assert data != null;
|
||||
channel.send(data, session.getDestination());
|
||||
}
|
||||
LOGGER.info("Send datagram");
|
||||
final DatagramChannel channel = getChannel(datagramSession);
|
||||
assert data != null;
|
||||
int sent = channel.send(data, session.getDestination());
|
||||
break;
|
||||
}
|
||||
case EXPIRED: {
|
||||
@@ -141,34 +133,22 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
LOGGER.error("Datagram session failure", e);
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
/* else if (session instanceof StreamSession) {
|
||||
} else if (session instanceof StreamSession streamSession) {
|
||||
try {
|
||||
switch (session.getState()) {
|
||||
case NEW -> {
|
||||
final SocketChannel channel = SocketChannel.open();
|
||||
channel.configureBlocking(false);
|
||||
final SelectionKey key =
|
||||
register(channel, session, SelectionKey.OP_READ | SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT);
|
||||
session.setUserdata(key);
|
||||
streamKeys.add(key);
|
||||
final SocketChannel channel = socketManager.createStreamChannel(streamSession, readySessions);
|
||||
session.setUserdata(channel);
|
||||
channel.connect(session.getDestination());
|
||||
LOGGER.info("Open stream socket {}", session.getDestination());
|
||||
}
|
||||
case ESTABLISHED -> {
|
||||
final SelectionKey key = (SelectionKey) session.getUserdata();
|
||||
assert key != null;
|
||||
if (key.isWritable()) {
|
||||
final SocketChannel channel = (SocketChannel) key.channel();
|
||||
assert data != null;
|
||||
channel.write(data);
|
||||
}
|
||||
final SocketChannel channel = getChannel(streamSession);
|
||||
assert data != null;
|
||||
channel.write(data);
|
||||
}
|
||||
case FINISH, EXPIRED -> {
|
||||
final SelectionKey key = (SelectionKey) session.getUserdata();
|
||||
assert key != null;
|
||||
key.channel().close();
|
||||
streamKeys.remove(key);
|
||||
closeSession(session);
|
||||
LOGGER.info("Close stream socket {}", session.getDestination());
|
||||
}
|
||||
}
|
||||
@@ -176,25 +156,37 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
LOGGER.error("Stream session failure", e);
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
*/
|
||||
else {
|
||||
} else {
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void closeSession(final Session session) {
|
||||
try {
|
||||
readySessions.remove(session);
|
||||
final SelectionKey selectionKey = (SelectionKey) session.getUserdata();
|
||||
assert selectionKey != null;
|
||||
selectionKey.channel().close();
|
||||
ownedKeys.remove(selectionKey);
|
||||
getChannel(session).close();
|
||||
} catch (final IOException exception) {
|
||||
LOGGER.error("Error on closing channel", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private Object getExistingUserdata(final Session session) {
|
||||
final Object channel = session.getUserdata();
|
||||
assert channel != null;
|
||||
return channel;
|
||||
}
|
||||
|
||||
private SocketChannel getChannel(final StreamSession session) {
|
||||
return (SocketChannel) getExistingUserdata(session);
|
||||
}
|
||||
|
||||
private DatagramChannel getChannel(final DatagramSession session) {
|
||||
return (DatagramChannel) getExistingUserdata(session);
|
||||
}
|
||||
|
||||
private SelectableChannel getChannel(final Session session) {
|
||||
return (SelectableChannel) getExistingUserdata(session);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private static final class EchoResponse {
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.*;
|
||||
import li.cil.oc2.api.inet.layer.SessionLayer;
|
||||
import li.cil.oc2.api.inet.layer.TransportLayer;
|
||||
import li.cil.oc2.api.inet.session.DatagramSession;
|
||||
import li.cil.oc2.api.inet.session.EchoSession;
|
||||
import li.cil.oc2.api.inet.session.Session;
|
||||
import li.cil.oc2.api.inet.session.StreamSession;
|
||||
import li.cil.oc2.common.Config;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
@@ -16,9 +22,10 @@ import java.util.function.Function;
|
||||
|
||||
public final class DefaultTransportLayer implements TransportLayer {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final byte ICMP_TYPE_ECHO_REPLY = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
private static final byte ICMP_TYPE_ECHO_REPLY = 0;
|
||||
private static final byte ICMP_TYPE_ECHO_REQUEST = 8;
|
||||
private static final byte ICMP_TYPE_ECHO_UNREACHABLE = 3;
|
||||
private static final byte ICMP_CODE_ECHO_UNREACHABLE_PORT = 3;
|
||||
@@ -169,7 +176,7 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
final int limit = data.limit();
|
||||
data.putShort(discriminator.getDstPort());
|
||||
data.putShort(discriminator.getSrcPort());
|
||||
boolean recv = stream.onReceive(data);
|
||||
final boolean recv = stream.onReceive(data);
|
||||
if (!recv) {
|
||||
data.position(position);
|
||||
data.limit(limit);
|
||||
@@ -235,10 +242,8 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
if (session instanceof EchoSession) {
|
||||
final EchoSessionImpl echoSession = (EchoSessionImpl) session;
|
||||
switch (session.getState()) {
|
||||
case FINISH:
|
||||
closeSession(session);
|
||||
break;
|
||||
case ESTABLISHED: {
|
||||
case FINISH -> closeSession(session);
|
||||
case ESTABLISHED -> {
|
||||
final EchoSessionDiscriminator discriminator = echoSession.getDiscriminator();
|
||||
final ByteBuffer buffer = receiver.getBuffer();
|
||||
final int position = buffer.position();
|
||||
@@ -248,16 +253,13 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
message.updateIpv4(discriminator.getDstIpAddress(), discriminator.getSrcIpAddress());
|
||||
return PROTOCOL_ICMP;
|
||||
}
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
default -> throw new IllegalStateException();
|
||||
}
|
||||
} else if (session instanceof DatagramSession) {
|
||||
final DatagramSessionImpl datagramSession = (DatagramSessionImpl) session;
|
||||
switch (session.getState()) {
|
||||
case FINISH:
|
||||
closeSession(session);
|
||||
break;
|
||||
case ESTABLISHED: {
|
||||
case FINISH -> closeSession(session);
|
||||
case ESTABLISHED -> {
|
||||
final DatagramSessionDiscriminator discriminator = datagramSession.getDiscriminator();
|
||||
final ByteBuffer buffer = receiver.getBuffer();
|
||||
final int position = buffer.position();
|
||||
@@ -266,18 +268,17 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
buffer.putShort(position + 4, (short) buffer.remaining());
|
||||
buffer.putShort(position + 6, (short) 0);
|
||||
short checksum = InetUtils.transportRfc1071Checksum(
|
||||
buffer,
|
||||
discriminator.getDstIpAddress(),
|
||||
discriminator.getSrcIpAddress(),
|
||||
PROTOCOL_UDP
|
||||
buffer,
|
||||
discriminator.getDstIpAddress(),
|
||||
discriminator.getSrcIpAddress(),
|
||||
PROTOCOL_UDP
|
||||
);
|
||||
buffer.putShort(position + 6, checksum);
|
||||
buffer.position(position);
|
||||
message.updateIpv4(discriminator.getDstIpAddress(), discriminator.getSrcIpAddress());
|
||||
return PROTOCOL_UDP;
|
||||
}
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
default -> throw new IllegalStateException();
|
||||
}
|
||||
} else if (session instanceof StreamSession) {
|
||||
final StreamSessionImpl streamSession = (StreamSessionImpl) session;
|
||||
@@ -301,6 +302,11 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
for (final SessionBase session : sessions.values()) {
|
||||
session.setState(Session.States.FINISH);
|
||||
sessionLayer.sendSession(session, null);
|
||||
closeSession(session);
|
||||
}
|
||||
sessionLayer.onStop();
|
||||
}
|
||||
|
||||
@@ -314,7 +320,7 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
final ByteBuffer data = message.getData();
|
||||
|
||||
switch (protocol) {
|
||||
case PROTOCOL_ICMP: {
|
||||
case PROTOCOL_ICMP -> {
|
||||
if (data.remaining() < ICMP_HEADER_SIZE) {
|
||||
return;
|
||||
}
|
||||
@@ -330,9 +336,9 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
final short identity = data.getShort();
|
||||
final short sequence = data.getShort();
|
||||
final EchoSessionDiscriminator discriminator =
|
||||
new EchoSessionDiscriminator(srcIpAddress, dstIpAddress, identity);
|
||||
new EchoSessionDiscriminator(srcIpAddress, dstIpAddress, identity);
|
||||
final EchoSessionImpl session =
|
||||
getOrCreateSession(discriminator, it -> new EchoSessionImpl(dstIpAddress, PORT_ECHO, it));
|
||||
getOrCreateSession(discriminator, it -> new EchoSessionImpl(dstIpAddress, PORT_ECHO, it));
|
||||
if (session == null) {
|
||||
reject(data, srcIpAddress);
|
||||
} else {
|
||||
@@ -342,9 +348,8 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
sessionSendFinish(session, data, srcIpAddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROTOCOL_UDP: {
|
||||
case PROTOCOL_UDP -> {
|
||||
if (data.remaining() < UDP_HEADER_SIZE) {
|
||||
return;
|
||||
}
|
||||
@@ -360,18 +365,17 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
data.limit(data.position() + datagramLength - UDP_HEADER_SIZE);
|
||||
|
||||
final DatagramSessionDiscriminator discriminator =
|
||||
new DatagramSessionDiscriminator(srcIpAddress, srcPort, dstIpAddress, dstPort);
|
||||
new DatagramSessionDiscriminator(srcIpAddress, srcPort, dstIpAddress, dstPort);
|
||||
final DatagramSessionImpl session =
|
||||
getOrCreateSession(discriminator, it -> new DatagramSessionImpl(dstIpAddress, dstPort, it));
|
||||
getOrCreateSession(discriminator, it -> new DatagramSessionImpl(dstIpAddress, dstPort, it));
|
||||
if (session == null) {
|
||||
reject(data, srcIpAddress);
|
||||
} else {
|
||||
sessionLayer.sendSession(session, data);
|
||||
sessionSendFinish(session, data, srcIpAddress);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROTOCOL_TCP: {
|
||||
case PROTOCOL_TCP -> {
|
||||
if (data.remaining() < MIN_TCP_HEADER_SIZE) {
|
||||
return;
|
||||
}
|
||||
@@ -380,15 +384,15 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
final short dstPort = data.getShort();
|
||||
|
||||
final StreamSessionDiscriminator discriminator =
|
||||
new StreamSessionDiscriminator(srcIpAddress, srcPort, dstIpAddress, dstPort);
|
||||
new StreamSessionDiscriminator(srcIpAddress, srcPort, dstIpAddress, dstPort);
|
||||
final StreamSessionImpl session =
|
||||
getOrCreateSession(discriminator, it -> new StreamSessionImpl(dstIpAddress, dstPort, it));
|
||||
getOrCreateSession(discriminator, it -> new StreamSessionImpl(dstIpAddress, dstPort, it));
|
||||
if (session == null) {
|
||||
reject(data, srcIpAddress);
|
||||
} else {
|
||||
if (session.onSend(data)) {
|
||||
if (session.getState() == Session.States.NEW)
|
||||
sessionLayer.sendSession(session, data);
|
||||
sessionLayer.sendSession(session, data);
|
||||
final Session.States state = session.getState();
|
||||
if (state == Session.States.REJECT || state == Session.States.FINISH) {
|
||||
rejectedStream = session;
|
||||
@@ -397,7 +401,6 @@ public final class DefaultTransportLayer implements TransportLayer {
|
||||
closeSession(session);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.EchoSession;
|
||||
import li.cil.oc2.api.inet.session.EchoSession;
|
||||
|
||||
public final class EchoSessionImpl extends SessionBase implements EchoSession {
|
||||
private final EchoSessionDiscriminator discriminator;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.LinkLocalLayer;
|
||||
import li.cil.oc2.api.inet.layer.LinkLocalLayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.EndTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
@@ -2,10 +2,9 @@ package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.InternetManager;
|
||||
import li.cil.oc2.api.inet.InternetProvider;
|
||||
import li.cil.oc2.api.inet.LinkLocalLayer;
|
||||
import li.cil.oc2.api.inet.provider.InternetProvider;
|
||||
import li.cil.oc2.api.inet.layer.LinkLocalLayer;
|
||||
import li.cil.oc2.common.Config;
|
||||
import net.minecraft.nbt.EndTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
@@ -15,7 +14,6 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -23,7 +21,6 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class InternetManagerImpl implements InternetManager {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.LinkLocalLayer;
|
||||
import li.cil.oc2.api.inet.NetworkLayer;
|
||||
import li.cil.oc2.api.inet.SessionLayer;
|
||||
import li.cil.oc2.api.inet.TransportLayer;
|
||||
import li.cil.oc2.api.inet.layer.LinkLocalLayer;
|
||||
import li.cil.oc2.api.inet.layer.NetworkLayer;
|
||||
import li.cil.oc2.api.inet.layer.SessionLayer;
|
||||
import li.cil.oc2.api.inet.layer.TransportLayer;
|
||||
|
||||
public final class NullLayer implements LinkLocalLayer, NetworkLayer, TransportLayer, SessionLayer {
|
||||
public static final NullLayer INSTANCE = new NullLayer();
|
||||
|
||||
24
src/main/java/li/cil/oc2/common/inet/ReadySessions.java
Normal file
24
src/main/java/li/cil/oc2/common/inet/ReadySessions.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.session.Session;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
|
||||
public final class ReadySessions {
|
||||
private final Queue<Session> toRead = new ArrayDeque<>();
|
||||
private final Queue<Session> toWrite = new ArrayDeque<>();
|
||||
private final Queue<Session> toConnect = new ArrayDeque<>();
|
||||
|
||||
public Queue<Session> getToRead() {
|
||||
return toRead;
|
||||
}
|
||||
|
||||
public Queue<Session> getToWrite() {
|
||||
return toWrite;
|
||||
}
|
||||
|
||||
public Queue<Session> getToConnect() {
|
||||
return toConnect;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.Session;
|
||||
import li.cil.oc2.api.inet.session.Session;
|
||||
import li.cil.oc2.common.Config;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -30,14 +30,9 @@ public abstract class SessionBase implements Session {
|
||||
@Override
|
||||
public void close() {
|
||||
switch (state) {
|
||||
case NEW:
|
||||
state = States.REJECT;
|
||||
return;
|
||||
case ESTABLISHED:
|
||||
state = States.FINISH;
|
||||
return;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
case NEW -> state = States.REJECT;
|
||||
case ESTABLISHED -> state = States.FINISH;
|
||||
default -> throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.Session;
|
||||
import li.cil.oc2.api.inet.session.Session;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.DatagramSession;
|
||||
import li.cil.oc2.api.inet.session.DatagramSession;
|
||||
import li.cil.oc2.api.inet.InternetManager;
|
||||
import li.cil.oc2.api.inet.Session;
|
||||
import org.apache.commons.logging.Log;
|
||||
import li.cil.oc2.api.inet.session.Session;
|
||||
import li.cil.oc2.api.inet.session.StreamSession;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.io.IOException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Set;
|
||||
|
||||
public final class SocketManager {
|
||||
@@ -35,7 +36,17 @@ public final class SocketManager {
|
||||
try {
|
||||
selector.selectNow(selectionKey -> {
|
||||
final ChannelAttachment attachment = (ChannelAttachment) selectionKey.attachment();
|
||||
attachment.ready.add(attachment.session);
|
||||
final Session session = attachment.session;
|
||||
final ReadySessions readySessions = attachment.readySessions;
|
||||
if (selectionKey.isReadable()) {
|
||||
readySessions.getToRead().add(session);
|
||||
}
|
||||
if (selectionKey.isWritable()) {
|
||||
readySessions.getToWrite().add(session);
|
||||
}
|
||||
if (selectionKey.isConnectable()) {
|
||||
readySessions.getToConnect().add(session);
|
||||
}
|
||||
});
|
||||
} catch (final IOException exception) {
|
||||
LOGGER.error("Exception while selecting", exception);
|
||||
@@ -52,14 +63,27 @@ public final class SocketManager {
|
||||
LOGGER.info("Started socket manager");
|
||||
}
|
||||
|
||||
private record ChannelAttachment(Session session, Set<Session> ready) {
|
||||
private record ChannelAttachment(Session session, ReadySessions readySessions) {
|
||||
}
|
||||
|
||||
public SelectionKey createDatagramChannel(final DatagramSession session, final Set<Session> ready) throws IOException {
|
||||
public DatagramChannel createDatagramChannel(final DatagramSession session,
|
||||
final ReadySessions readySessions) throws IOException {
|
||||
final DatagramChannel datagramChannel = DatagramChannel.open();
|
||||
datagramChannel.configureBlocking(false);
|
||||
final ChannelAttachment attachment = new ChannelAttachment(session, ready);
|
||||
return datagramChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, attachment);
|
||||
final ChannelAttachment attachment = new ChannelAttachment(session, readySessions);
|
||||
final int ops = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
|
||||
datagramChannel.register(selector, ops, attachment);
|
||||
return datagramChannel;
|
||||
}
|
||||
|
||||
public SocketChannel createStreamChannel(final StreamSession session,
|
||||
final ReadySessions readySessions) throws IOException {
|
||||
final SocketChannel socketChannel = SocketChannel.open();
|
||||
socketChannel.configureBlocking(false);
|
||||
final ChannelAttachment attachment = new ChannelAttachment(session, readySessions);
|
||||
final int ops = SelectionKey.OP_READ | SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT;
|
||||
socketChannel.register(selector, ops, attachment);
|
||||
return socketChannel;
|
||||
}
|
||||
|
||||
private void shutdown() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package li.cil.oc2.common.inet;
|
||||
|
||||
import li.cil.oc2.api.inet.StreamSession;
|
||||
import li.cil.oc2.api.inet.session.StreamSession;
|
||||
import li.cil.oc2.common.Config;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -174,17 +174,11 @@ public class StreamSessionImpl extends SessionBase implements StreamSession {
|
||||
}
|
||||
|
||||
public boolean onSend(final ByteBuffer data) {
|
||||
switch (getState()) {
|
||||
case NEW:
|
||||
return newConnection(data);
|
||||
case ESTABLISHED:
|
||||
case FINISH:
|
||||
return onPacket(data);
|
||||
case REJECT:
|
||||
case EXPIRED:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return false;
|
||||
return switch (getState()) {
|
||||
case NEW -> newConnection(data);
|
||||
case ESTABLISHED, FINISH -> onPacket(data);
|
||||
case REJECT, EXPIRED -> throw new IllegalStateException();
|
||||
};
|
||||
}
|
||||
|
||||
public boolean onReceive(final ByteBuffer data) {
|
||||
|
||||
Reference in New Issue
Block a user