Simplifications, bugfixes and TCP once again
This commit is contained in:
@@ -2,7 +2,9 @@ package li.cil.oc2.api.inet;
|
||||
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface LayerParameters {
|
||||
Tag getSavedState();
|
||||
Optional<Tag> getSavedState();
|
||||
InternetManager getInternetManager();
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import li.cil.oc2.api.inet.layer.LinkLocalLayer;
|
||||
public interface InternetProvider {
|
||||
|
||||
/**
|
||||
* This method should provide and implementation of {@link LinkLocalLayer} interface and not fail.
|
||||
* This method should provide an implementation of {@link LinkLocalLayer} interface.
|
||||
* It will be called once for each loaded internet card.
|
||||
*
|
||||
* @return an implementation of {@link LinkLocalLayer} interface
|
||||
|
||||
@@ -28,6 +28,7 @@ public final class Constants {
|
||||
public static final String MOD_TAG_NAME = API.MOD_ID;
|
||||
public static final String ITEMS_TAG_NAME = "items";
|
||||
public static final String ENERGY_TAG_NAME = "energy";
|
||||
public static final String INTERNET_ADAPTER_TAG_NAME = "InternetAdapter";
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import li.cil.oc2.common.inet.InternetManagerImpl;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.EndTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -34,7 +33,6 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
|
||||
|
||||
private InternetConnection internetConnection;
|
||||
|
||||
private static final String STATE_TAG = "internet_adapter";
|
||||
private Tag internetState;
|
||||
|
||||
private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.gatewayEnergyStorage);
|
||||
@@ -43,18 +41,14 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
|
||||
super(BlockEntities.INTERNET_GATEWAY.get(), pos, state);
|
||||
inboundQueue = new ArrayDeque<>();
|
||||
outboundQueue = new ArrayDeque<>();
|
||||
internetState = EndTag.INSTANCE;
|
||||
internetState = null;
|
||||
setNeedsLevelUnloadEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(CompoundTag tag) {
|
||||
super.load(tag);
|
||||
if (tag.contains(STATE_TAG)) {
|
||||
internetState = tag.get(STATE_TAG);
|
||||
} else {
|
||||
internetState = EndTag.INSTANCE;
|
||||
}
|
||||
internetState = tag.get(Constants.INTERNET_ADAPTER_TAG_NAME);
|
||||
energy.deserializeNBT(tag.getCompound(Constants.ENERGY_TAG_NAME));
|
||||
}
|
||||
|
||||
@@ -62,7 +56,8 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
|
||||
public void saveAdditional(CompoundTag tag) {
|
||||
super.saveAdditional(tag);
|
||||
if (internetConnection != null) {
|
||||
internetConnection.saveAdapterState().ifPresent(adapterState -> tag.put(STATE_TAG, adapterState));
|
||||
internetConnection.saveAdapterState()
|
||||
.ifPresent(adapterState -> tag.put(Constants.INTERNET_ADAPTER_TAG_NAME, adapterState));
|
||||
}
|
||||
tag.put(Constants.ENERGY_TAG_NAME, energy.serializeNBT());
|
||||
LOGGER.info("State saved");
|
||||
@@ -70,7 +65,8 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
|
||||
|
||||
@Override
|
||||
protected void loadServer() {
|
||||
InternetManagerImpl.getInstance().ifPresent(internetManager -> internetConnection = internetManager.connect(this, internetState));
|
||||
InternetManagerImpl.getInstance()
|
||||
.ifPresent(internetManager -> internetConnection = internetManager.connect(this, internetState));
|
||||
if (internetConnection != null) {
|
||||
LOGGER.info("Connected to the internet");
|
||||
} else {
|
||||
@@ -103,7 +99,7 @@ public class InternetGateWayBlockEntity extends ModBlockEntity implements Networ
|
||||
}
|
||||
return hasEnough;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendEthernetFrame(byte[] frame) {
|
||||
LOGGER.info("Got inbound packet");
|
||||
|
||||
@@ -3,6 +3,7 @@ package li.cil.oc2.common.bus.device.vm.item;
|
||||
import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult;
|
||||
import li.cil.oc2.api.bus.device.vm.context.VMContext;
|
||||
import li.cil.oc2.api.capabilities.NetworkInterface;
|
||||
import li.cil.oc2.common.Constants;
|
||||
import li.cil.oc2.common.inet.InternetAdapter;
|
||||
import li.cil.oc2.common.inet.InternetConnection;
|
||||
import li.cil.oc2.common.inet.InternetManagerImpl;
|
||||
@@ -15,13 +16,12 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class InternetCardDevice extends AbstractNetworkInterfaceDevice {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private static final String ADAPTER_SUBTAG = "InternetAdapter";
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private InternetConnection internetConnection = null;
|
||||
@@ -37,11 +37,9 @@ public final class InternetCardDevice extends AbstractNetworkInterfaceDevice {
|
||||
private void openInternetAccess() {
|
||||
LOGGER.debug("Connect internet card");
|
||||
closeInternetAccess();
|
||||
final Tag savedState = internetAdapterState;
|
||||
assert savedState != null;
|
||||
final InternetAdapter internetAdapter = new InternetAdapterImpl(getNetworkInterface());
|
||||
InternetManagerImpl.getInstance()
|
||||
.ifPresent(internetManager -> internetConnection = internetManager.connect(internetAdapter, savedState));
|
||||
.ifPresent(internetManager -> internetConnection = internetManager.connect(internetAdapter, internetAdapterState));
|
||||
}
|
||||
|
||||
private void closeInternetAccess() {
|
||||
@@ -57,7 +55,7 @@ public final class InternetCardDevice extends AbstractNetworkInterfaceDevice {
|
||||
@Override
|
||||
public void deserializeNBT(final CompoundTag tag) {
|
||||
super.deserializeNBT(tag);
|
||||
internetAdapterState = Objects.requireNonNullElse(tag.get(ADAPTER_SUBTAG), EndTag.INSTANCE);
|
||||
internetAdapterState = tag.get(Constants.INTERNET_ADAPTER_TAG_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +64,11 @@ public final class InternetCardDevice extends AbstractNetworkInterfaceDevice {
|
||||
final InternetConnection internetConnection = this.internetConnection;
|
||||
if (internetConnection != null) {
|
||||
internetConnection.saveAdapterState()
|
||||
.ifPresent(adapterState -> tag.put(ADAPTER_SUBTAG, adapterState));
|
||||
.ifPresent(adapterState -> {
|
||||
tag.put(Constants.INTERNET_ADAPTER_TAG_NAME, adapterState);
|
||||
// TODO: not sure, if this is meaningful
|
||||
internetAdapterState = adapterState;
|
||||
});
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
@@ -53,25 +53,26 @@ public final class DefaultLinkLocalLayer implements LinkLocalLayer {
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
public DefaultLinkLocalLayer(final LayerParameters layerParameters, final NetworkLayer networkLayer) {
|
||||
final Tag tag = layerParameters.getSavedState();
|
||||
if (tag instanceof CompoundTag layerState) {
|
||||
final String ipAddressString = layerState.getString(IPv4_ADDRESS_TAG);
|
||||
if (!ipAddressString.isEmpty()) {
|
||||
try {
|
||||
myIpV4Address = InetUtils.parseIpv4Address(ipAddressString);
|
||||
} catch (final AddressParseException exception) {
|
||||
LOGGER.error("Failed to parse internet adapter IPv4 address", exception);
|
||||
layerParameters.getSavedState().ifPresent(tag -> {
|
||||
if (tag instanceof CompoundTag layerState) {
|
||||
final String ipAddressString = layerState.getString(IPv4_ADDRESS_TAG);
|
||||
if (!ipAddressString.isEmpty()) {
|
||||
try {
|
||||
myIpV4Address = InetUtils.parseIpv4Address(ipAddressString);
|
||||
} catch (final AddressParseException exception) {
|
||||
LOGGER.error("Failed to parse internet adapter IPv4 address", exception);
|
||||
}
|
||||
}
|
||||
final String macAddressString = layerState.getString(MAC_ADDRESS_TAG);
|
||||
if (!macAddressString.isEmpty()) {
|
||||
try {
|
||||
myMacAddress = InetUtils.parseMacAddress(macAddressString);
|
||||
} catch (final AddressParseException exception) {
|
||||
LOGGER.error("Failed to parse internet adapter MAC address from NBT", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
final String macAddressString = layerState.getString(MAC_ADDRESS_TAG);
|
||||
if (!macAddressString.isEmpty()) {
|
||||
try {
|
||||
myMacAddress = InetUtils.parseMacAddress(macAddressString);
|
||||
} catch (final AddressParseException exception) {
|
||||
LOGGER.error("Failed to parse internet adapter MAC address from NBT", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this.networkLayer = networkLayer;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,11 @@ import java.net.InetAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class DefaultSessionLayer implements SessionLayer {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
@@ -59,14 +61,7 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
return;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
final Session session = readySessions.getToRead().poll();
|
||||
if (session == null) {
|
||||
break;
|
||||
}
|
||||
if (session.isClosed()) {
|
||||
continue;
|
||||
}
|
||||
final boolean somethingRead = processQueue(readySessions.getToRead(), session -> {
|
||||
if (session instanceof DatagramSession datagramSession) {
|
||||
LOGGER.info("Datagram received");
|
||||
final DatagramChannel channel = getChannel(datagramSession);
|
||||
@@ -75,18 +70,47 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
assert datagram != null;
|
||||
final SocketAddress address = channel.receive(datagram);
|
||||
if (address == null) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (Config.useSynchronisedNAT && !address.equals(datagramSession.getDestination())) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
datagram.flip();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Trying to read datagram socket", e);
|
||||
return true;
|
||||
} catch (final IOException exception) {
|
||||
LOGGER.error("Trying to read datagram socket", exception);
|
||||
}
|
||||
LOGGER.info("Datagram received");
|
||||
} else if (session instanceof StreamSession streamSession) {
|
||||
LOGGER.info("Stream received");
|
||||
final SocketChannel channel = getChannel(streamSession);
|
||||
try {
|
||||
final ByteBuffer stream = receiver.receive(streamSession);
|
||||
assert stream != null;
|
||||
final int read = channel.read(stream);
|
||||
if (read != 0) {
|
||||
// some data still remaining in socket, read it later
|
||||
readySessions.getToRead().add(streamSession);
|
||||
}
|
||||
return true;
|
||||
} catch (final IOException exception) {
|
||||
LOGGER.error("Trying to read stream socket", exception);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (somethingRead) {
|
||||
return;
|
||||
}
|
||||
|
||||
processQueue(readySessions.getToConnect(), session -> {
|
||||
if (session instanceof StreamSession streamSession) {
|
||||
receiver.receive(streamSession);
|
||||
streamSession.connect();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,7 +144,7 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
LOGGER.info("Send datagram");
|
||||
final DatagramChannel channel = getChannel(datagramSession);
|
||||
assert data != null;
|
||||
int sent = channel.send(data, session.getDestination());
|
||||
channel.send(data, session.getDestination());
|
||||
break;
|
||||
}
|
||||
case EXPIRED: {
|
||||
@@ -161,6 +185,21 @@ public final class DefaultSessionLayer implements SessionLayer {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean processQueue(final Queue<Session> queue, final Function<Session, Boolean> action) {
|
||||
while (true) {
|
||||
final Session session = queue.poll();
|
||||
if (session == null) {
|
||||
return false;
|
||||
}
|
||||
if (session.isClosed()) {
|
||||
continue;
|
||||
}
|
||||
if (action.apply(session)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void closeSession(final Session session) {
|
||||
try {
|
||||
getChannel(session).close();
|
||||
|
||||
@@ -3,14 +3,13 @@ package li.cil.oc2.common.inet;
|
||||
import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.layer.LinkLocalLayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.EndTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class InetUtils {
|
||||
@@ -42,16 +41,16 @@ public final class InetUtils {
|
||||
}
|
||||
|
||||
public static short transportRfc1071Checksum(
|
||||
final ByteBuffer buffer,
|
||||
final int srcIpAddress,
|
||||
final int dstIpAddress,
|
||||
final byte protocol
|
||||
final ByteBuffer buffer,
|
||||
final int srcIpAddress,
|
||||
final int dstIpAddress,
|
||||
final byte protocol
|
||||
) {
|
||||
final int size = buffer.remaining();
|
||||
final int checksumPart = bufferChecksum(buffer, size);
|
||||
final int checksum = checksumPart + Byte.toUnsignedInt(protocol) + size +
|
||||
(srcIpAddress >>> 16) + (srcIpAddress & 0xFFFF) +
|
||||
(dstIpAddress >>> 16) + (dstIpAddress & 0xFFFF);
|
||||
(srcIpAddress >>> 16) + (srcIpAddress & 0xFFFF) +
|
||||
(dstIpAddress >>> 16) + (dstIpAddress & 0xFFFF);
|
||||
return finishChecksum(checksum);
|
||||
}
|
||||
|
||||
@@ -66,10 +65,10 @@ public final class InetUtils {
|
||||
|
||||
public static InetAddress toJavaInetAddress(final int ipAddress) {
|
||||
final byte[] bytes = new byte[]{
|
||||
(byte) (ipAddress >>> 24),
|
||||
(byte) (ipAddress >>> 16),
|
||||
(byte) (ipAddress >>> 8),
|
||||
(byte) (ipAddress)
|
||||
(byte) (ipAddress >>> 24),
|
||||
(byte) (ipAddress >>> 16),
|
||||
(byte) (ipAddress >>> 8),
|
||||
(byte) (ipAddress)
|
||||
};
|
||||
return getInetAddressByBytes(bytes);
|
||||
}
|
||||
@@ -124,7 +123,7 @@ public final class InetUtils {
|
||||
byteToHex(builder, (byte) prefix);
|
||||
for (int i = 3; i >= 0; --i) {
|
||||
builder.append(':');
|
||||
byteToHex(builder, (byte) (address >>> (8*i)));
|
||||
byteToHex(builder, (byte) (address >>> (8 * i)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +159,7 @@ public final class InetUtils {
|
||||
public static int javaInetAddressToIpAddress(final Inet4Address address) {
|
||||
final byte[] bytes = address.getAddress();
|
||||
return (Byte.toUnsignedInt(bytes[0]) << 24) | (Byte.toUnsignedInt(bytes[1]) << 16)
|
||||
| (Byte.toUnsignedInt(bytes[2]) << 8) | Byte.toUnsignedInt(bytes[3]);
|
||||
| (Byte.toUnsignedInt(bytes[2]) << 8) | Byte.toUnsignedInt(bytes[3]);
|
||||
}
|
||||
|
||||
public static int indexOf(final CharSequence string, final char character, final int start) {
|
||||
@@ -222,7 +221,7 @@ public final class InetUtils {
|
||||
final short prefix = (short) (first << 8 | parseMacAddressByte(string, 3));
|
||||
int address = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
final int pos = i*3 + 5;
|
||||
final int pos = i * 3 + 5;
|
||||
if (string.charAt(pos) != ':') {
|
||||
throw illegalDelimiter(string, pos);
|
||||
}
|
||||
@@ -282,13 +281,10 @@ public final class InetUtils {
|
||||
}
|
||||
|
||||
public static LayerParameters nextLayerParameters(final LayerParameters layerParameters, final String layerName) {
|
||||
final Tag currentLayerState = layerParameters.getSavedState();
|
||||
final Tag nextLayerState;
|
||||
if (currentLayerState instanceof CompoundTag tag) {
|
||||
nextLayerState = Objects.requireNonNullElse(tag.get(layerName), EndTag.INSTANCE);
|
||||
} else {
|
||||
nextLayerState = EndTag.INSTANCE;
|
||||
}
|
||||
final Optional<Tag> nextLayerState = layerParameters.getSavedState()
|
||||
.flatMap(currentLayerState -> (currentLayerState instanceof CompoundTag tag) ?
|
||||
Optional.ofNullable(tag.get(layerName)) :
|
||||
Optional.empty());
|
||||
return new LayerParametersImpl(nextLayerState, layerParameters.getInternetManager());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +69,8 @@ public final class InternetManagerImpl implements InternetManager {
|
||||
return task;
|
||||
}
|
||||
|
||||
public InternetConnection connect(final InternetAdapter internetAdapter, final Tag savedState) {
|
||||
final LayerParameters layerParameters = new LayerParametersImpl(savedState, this);
|
||||
public InternetConnection connect(final InternetAdapter internetAdapter, @Nullable final Tag savedState) {
|
||||
final LayerParameters layerParameters = new LayerParametersImpl(Optional.ofNullable(savedState), this);
|
||||
final InternetConnectionImpl internetConnection =
|
||||
new InternetConnectionImpl(internetAdapter, internetProvider.provideInternet(layerParameters));
|
||||
connections.add(internetConnection);
|
||||
@@ -116,7 +116,10 @@ public final class InternetManagerImpl implements InternetManager {
|
||||
final List<InternetConnectionImpl> connectionsToProcess
|
||||
) {
|
||||
runTasks();
|
||||
connectionsToStop.forEach(InternetConnectionImpl::stop);
|
||||
connectionsToStop.forEach(connection -> {
|
||||
LOGGER.debug("Revoked internet access");
|
||||
connection.ethernet.onStop();
|
||||
});
|
||||
connectionsToProcess.forEach(InternetConnectionImpl::process);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,5 +4,7 @@ import li.cil.oc2.api.inet.LayerParameters;
|
||||
import li.cil.oc2.api.inet.InternetManager;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
public record LayerParametersImpl(Tag getSavedState, InternetManager getInternetManager) implements LayerParameters {
|
||||
import java.util.Optional;
|
||||
|
||||
public record LayerParametersImpl(Optional<Tag> getSavedState, InternetManager getInternetManager) implements LayerParameters {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user