Some simplifications

This commit is contained in:
ktlo
2022-04-05 23:13:21 +03:00
committed by logan
parent 47699d936d
commit db5fb40243
31 changed files with 258 additions and 189 deletions

View File

@@ -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();
};
}
/**

View File

@@ -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;

View File

@@ -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;

View File

@@ -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) {
}

View File

@@ -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;
}
/**

View File

@@ -0,0 +1,7 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
package li.cil.oc2.api.inet.layer;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -0,0 +1,7 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
package li.cil.oc2.api.inet.provider;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -1,4 +1,4 @@
package li.cil.oc2.api.inet;
package li.cil.oc2.api.inet.session;
public interface DatagramSession extends Session {
}

View File

@@ -1,4 +1,4 @@
package li.cil.oc2.api.inet;
package li.cil.oc2.api.inet.session;
public interface EchoSession extends Session {
int getSequenceNumber();

View File

@@ -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
}

View File

@@ -1,4 +1,4 @@
package li.cil.oc2.api.inet;
package li.cil.oc2.api.inet.session;
import java.nio.ByteBuffer;

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();

View File

@@ -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();

View 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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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) {