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.ARPQueryFrame
import net.shadowfacts.phycon.frame.ARPResponseFrame import net.shadowfacts.phycon.frame.ARPResponseFrame
import net.shadowfacts.phycon.frame.BasePacketFrame import net.shadowfacts.phycon.frame.BasePacketFrame
import net.shadowfacts.phycon.frame.NetworkSplitFrame
import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.NetworkUtil import net.shadowfacts.phycon.util.NetworkUtil
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ -75,6 +76,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
when (frame) { when (frame) {
is ARPQueryFrame -> handleARPQuery(frame) is ARPQueryFrame -> handleARPQuery(frame)
is ARPResponseFrame -> handleARPResponse(frame) is ARPResponseFrame -> handleARPResponse(frame)
is NetworkSplitFrame -> handleNetworkSplit()
is PacketFrame -> { is PacketFrame -> {
if (frame.packet.destination.isBroadcast || frame.packet.destination == ipAddress) { if (frame.packet.destination.isBroadcast || frame.packet.destination == ipAddress) {
doHandlePacket(frame.packet) doHandlePacket(frame.packet)
@ -107,6 +109,11 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
packetQueue.removeAll(toRemove) packetQueue.removeAll(toRemove)
} }
protected open fun handleNetworkSplit() {
arpTable.clear()
cachedDestination = null
}
override fun sendPacket(packet: Packet) { override fun sendPacket(packet: Packet) {
if (packet.destination.isBroadcast) { if (packet.destination.isBroadcast) {
send(BasePacketFrame(packet, macAddress, MACAddress.BROADCAST)) send(BasePacketFrame(packet, macAddress, MACAddress.BROADCAST))
@ -140,6 +147,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
override fun cableDisconnected() { override fun cableDisconnected() {
cachedDestination = null cachedDestination = null
handleNetworkSplit()
} }
open fun tick() { 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.fabricmc.fabric.api.`object`.builder.v1.block.FabricBlockSettings
import net.minecraft.block.* import net.minecraft.block.*
import net.minecraft.block.entity.BlockEntity
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemPlacementContext import net.minecraft.item.ItemPlacementContext
import net.minecraft.item.ItemStack
import net.minecraft.state.StateManager import net.minecraft.state.StateManager
import net.minecraft.state.property.EnumProperty import net.minecraft.state.property.EnumProperty
import net.minecraft.util.ActionResult import net.minecraft.util.ActionResult
@ -200,11 +202,13 @@ class CableBlock(
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) { override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
super.onBreak(world, pos, state, player) super.onBreak(world, pos, state, player)
if (!world.isClient) { if (!world.isClient) {
// notify devices on either end that the connection was broken (i.e., unset the cached receivers) world.server?.execute {
val connectedSides = getNetworkConnectedSides(state, world, pos) // notify devices on either end that the connection was broken (i.e., unset the cached receivers)
for (side in connectedSides) { val connectedSides = getNetworkConnectedSides(state, world, pos)
val dest = NetworkUtil.findConnectedInterface(world, pos, side) for (side in connectedSides) {
dest?.cableDisconnected() 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.IPAddress
import net.shadowfacts.phycon.api.util.MACAddress import net.shadowfacts.phycon.api.util.MACAddress
import net.shadowfacts.phycon.frame.BasePacketFrame import net.shadowfacts.phycon.frame.BasePacketFrame
import net.shadowfacts.phycon.frame.NetworkSplitFrame
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.packet.ItemStackPacket import net.shadowfacts.phycon.packet.ItemStackPacket
import net.shadowfacts.phycon.util.NetworkUtil 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) PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) forwarding {} to side {}", this, fromItf.side, fromItf.macAddress, frame, dir)
interfaceForSide(dir).send(frame) interfaceForSide(dir).send(frame)
} else { } else {
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) flooding {}", this, fromItf.side, fromItf.macAddress, frame)
flood(frame, fromItf) 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) { for (itf in interfaces) {
if (source == itf) continue if (source == itf) continue
itf.send(frame) 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() { fun tick() {
packetsHandledThisTick = 0 packetsHandledThisTick = 0
@ -164,7 +175,7 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
} }
override fun cableDisconnected() { 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.api.util.IPAddress
import net.shadowfacts.phycon.block.DeviceBlockEntity import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.block.FaceDeviceBlock import net.shadowfacts.phycon.block.FaceDeviceBlock
import net.shadowfacts.phycon.frame.NetworkSplitFrame
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.ClientConfigurableDevice import net.shadowfacts.phycon.util.ClientConfigurableDevice
import java.lang.ref.WeakReference
/** /**
* @author shadowfacts * @author shadowfacts
@ -50,17 +52,21 @@ class P2PReceiverBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntit
var clientObserver: (() -> Unit)? = null var clientObserver: (() -> Unit)? = null
private var isFirstTick = true private var isFirstTick = true
// todo: need some way of removing this when there's no network path to the p2p interface private var targetInventory: WeakReference<Storage<ItemVariant>>? = null
private var targetInventory: Storage<ItemVariant>? = null
override fun handle(packet: Packet) { override fun handle(packet: Packet) {
when (packet) { when (packet) {
is PongPacket -> if (packet.source == target) status = Status.OK 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 is DeviceRemovedPacket -> if (packet.source == target) targetInventory = null
} }
} }
override fun handleNetworkSplit() {
super.handleNetworkSplit()
targetInventory = null
}
override fun tick() { override fun tick() {
super.tick() super.tick()
@ -74,10 +80,10 @@ class P2PReceiverBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntit
if (target == null) { if (target == null) {
return null return null
} }
if (targetInventory == null) { if (targetInventory?.get() == null) {
sendPacket(RequestInventoryPacket(RequestInventoryPacket.Kind.SIDED, ipAddress, target!!)) sendPacket(RequestInventoryPacket(RequestInventoryPacket.Kind.SIDED, ipAddress, target!!))
} }
return targetInventory return targetInventory?.get()
} }
private fun updateStatus() { 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.api.util.IPAddress
import net.shadowfacts.phycon.block.DeviceBlockEntity import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.component.* import net.shadowfacts.phycon.component.*
import net.shadowfacts.phycon.frame.NetworkSplitFrame
import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.NetworkUtil import net.shadowfacts.phycon.util.NetworkUtil
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ -69,6 +70,11 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockP
return null return null
} }
override fun handleNetworkSplit() {
super.handleNetworkSplit()
inventoryCache.clear()
}
override fun handle(packet: Packet) { override fun handle(packet: Packet) {
when (packet) { when (packet) {
is ReadGroupedInventoryPacket -> handleReadInventory(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)