Fix P2P receiver not invalidating target on netsplit

This commit is contained in:
Shadowfacts 2023-03-13 11:21:53 -04:00
parent 33614e0dc6
commit 73de26387a
6 changed files with 56 additions and 13 deletions

View File

@ -19,6 +19,7 @@ import net.shadowfacts.phycon.api.util.MACAddress
import net.shadowfacts.phycon.frame.ARPQueryFrame
import net.shadowfacts.phycon.frame.ARPResponseFrame
import net.shadowfacts.phycon.frame.BasePacketFrame
import net.shadowfacts.phycon.frame.NetworkSplitFrame
import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.NetworkUtil
import java.lang.ref.WeakReference
@ -75,6 +76,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
when (frame) {
is ARPQueryFrame -> handleARPQuery(frame)
is ARPResponseFrame -> handleARPResponse(frame)
is NetworkSplitFrame -> handleNetworkSplit()
is PacketFrame -> {
if (frame.packet.destination.isBroadcast || frame.packet.destination == ipAddress) {
doHandlePacket(frame.packet)
@ -107,6 +109,11 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
packetQueue.removeAll(toRemove)
}
protected open fun handleNetworkSplit() {
arpTable.clear()
cachedDestination = null
}
override fun sendPacket(packet: Packet) {
if (packet.destination.isBroadcast) {
send(BasePacketFrame(packet, macAddress, MACAddress.BROADCAST))
@ -140,6 +147,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
override fun cableDisconnected() {
cachedDestination = null
handleNetworkSplit()
}
open fun tick() {

View File

@ -2,8 +2,10 @@ package net.shadowfacts.phycon.block.cable
import net.fabricmc.fabric.api.`object`.builder.v1.block.FabricBlockSettings
import net.minecraft.block.*
import net.minecraft.block.entity.BlockEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemPlacementContext
import net.minecraft.item.ItemStack
import net.minecraft.state.StateManager
import net.minecraft.state.property.EnumProperty
import net.minecraft.util.ActionResult
@ -200,11 +202,13 @@ class CableBlock(
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
super.onBreak(world, pos, state, player)
if (!world.isClient) {
// notify devices on either end that the connection was broken (i.e., unset the cached receivers)
val connectedSides = getNetworkConnectedSides(state, world, pos)
for (side in connectedSides) {
val dest = NetworkUtil.findConnectedInterface(world, pos, side)
dest?.cableDisconnected()
world.server?.execute {
// notify devices on either end that the connection was broken (i.e., unset the cached receivers)
val connectedSides = getNetworkConnectedSides(state, world, pos)
for (side in connectedSides) {
val dest = NetworkUtil.findConnectedInterface(world, pos, side)
dest?.cableDisconnected()
}
}
}
}

View File

@ -17,6 +17,7 @@ import net.shadowfacts.phycon.api.frame.PacketFrame
import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.api.util.MACAddress
import net.shadowfacts.phycon.frame.BasePacketFrame
import net.shadowfacts.phycon.frame.NetworkSplitFrame
import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.packet.ItemStackPacket
import net.shadowfacts.phycon.util.NetworkUtil
@ -66,12 +67,12 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) forwarding {} to side {}", this, fromItf.side, fromItf.macAddress, frame, dir)
interfaceForSide(dir).send(frame)
} else {
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) flooding {}", this, fromItf.side, fromItf.macAddress, frame)
flood(frame, fromItf)
}
}
private fun flood(frame: EthernetFrame, source: Interface) {
private fun flood(frame: EthernetFrame, source: SwitchInterface) {
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) flooding {}", this, source.side, source.macAddress, frame)
for (itf in interfaces) {
if (source == itf) continue
itf.send(frame)
@ -86,6 +87,16 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
}
}
private fun cableDisconnected(itf: SwitchInterface) {
macTable.entries.filter {
it.value == itf.side
}.forEach {
macTable.remove(it.key)
}
destinationCache[itf.side.ordinal] = null
flood(NetworkSplitFrame(itf.macAddress), itf)
}
fun tick() {
packetsHandledThisTick = 0
@ -164,7 +175,7 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
}
override fun cableDisconnected() {
switch.get()?.destinationCache?.set(side.ordinal, null)
switch.get()?.cableDisconnected(this)
}
}

View File

@ -12,9 +12,11 @@ import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.block.FaceDeviceBlock
import net.shadowfacts.phycon.frame.NetworkSplitFrame
import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.ClientConfigurableDevice
import java.lang.ref.WeakReference
/**
* @author shadowfacts
@ -50,17 +52,21 @@ class P2PReceiverBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntit
var clientObserver: (() -> Unit)? = null
private var isFirstTick = true
// todo: need some way of removing this when there's no network path to the p2p interface
private var targetInventory: Storage<ItemVariant>? = null
private var targetInventory: WeakReference<Storage<ItemVariant>>? = null
override fun handle(packet: Packet) {
when (packet) {
is PongPacket -> if (packet.source == target) status = Status.OK
is ReadItemStoragePacket -> targetInventory = packet.inventory
is ReadItemStoragePacket -> targetInventory = WeakReference(packet.inventory)
is DeviceRemovedPacket -> if (packet.source == target) targetInventory = null
}
}
override fun handleNetworkSplit() {
super.handleNetworkSplit()
targetInventory = null
}
override fun tick() {
super.tick()
@ -74,10 +80,10 @@ class P2PReceiverBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntit
if (target == null) {
return null
}
if (targetInventory == null) {
if (targetInventory?.get() == null) {
sendPacket(RequestInventoryPacket(RequestInventoryPacket.Kind.SIDED, ipAddress, target!!))
}
return targetInventory
return targetInventory?.get()
}
private fun updateStatus() {

View File

@ -18,6 +18,7 @@ import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.component.*
import net.shadowfacts.phycon.frame.NetworkSplitFrame
import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.NetworkUtil
import java.lang.ref.WeakReference
@ -69,6 +70,11 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockP
return null
}
override fun handleNetworkSplit() {
super.handleNetworkSplit()
inventoryCache.clear()
}
override fun handle(packet: Packet) {
when (packet) {
is ReadGroupedInventoryPacket -> handleReadInventory(packet)

View File

@ -0,0 +1,8 @@
package net.shadowfacts.phycon.frame
import net.shadowfacts.phycon.api.util.MACAddress
/**
* @author shadowfacts
*/
class NetworkSplitFrame(source: MACAddress): BaseFrame(source, MACAddress.BROADCAST)