Livt packages

Livt.Net

Version 1.4.1

Ethernet, IPv4, TCP, UDP, ARP, TFTP, and Telnet networking components for Livt hardware.

Published files (163)

src/arp/ArpReply.lvt

namespace Livt.Net

/**
 * Prepared Ethernet/IPv4 ARP reply payload, excluding the Ethernet header.
 */
component ArpReply : IPacketData, IEthernetPayload
{
	const PREFIX: byte[8] = [0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02]

	// Owned sender/target address snapshot, readable only while prepared.
	address0: logic[16]
	address1: logic[16]
	address2: logic[16]
	address3: logic[16]
	address4: logic[16]
	address5: logic[16]
	address6: logic[16]
	address7: logic[16]
	address8: logic[16]
	address9: logic[16]
	ready: bool

	/**
	 * Discards the prepared address snapshot after all dependent reads have finished.
	 */
	public fn Invalidate()
	{
		ready = false
	}

	/**
	 * Snapshot the local and peer addresses from a validated ARP request.
	 */
	public fn TryPrepare(sourceMac: byte[6], sourceIp: byte[4], targetMac: byte[6], targetIp: byte[4]) PacketDataResult
	{
		ready = false

		address0 = NetworkOrder.Word(sourceMac[0], sourceMac[1]) as logic[16]
		address1 = NetworkOrder.Word(sourceMac[2], sourceMac[3]) as logic[16]
		address2 = NetworkOrder.Word(sourceMac[4], sourceMac[5]) as logic[16]
		address3 = NetworkOrder.Word(sourceIp[0], sourceIp[1]) as logic[16]
		address4 = NetworkOrder.Word(sourceIp[2], sourceIp[3]) as logic[16]
		address5 = NetworkOrder.Word(targetMac[0], targetMac[1]) as logic[16]
		address6 = NetworkOrder.Word(targetMac[2], targetMac[3]) as logic[16]
		address7 = NetworkOrder.Word(targetMac[4], targetMac[5]) as logic[16]
		address8 = NetworkOrder.Word(targetIp[0], targetIp[1]) as logic[16]
		address9 = NetworkOrder.Word(targetIp[2], targetIp[3]) as logic[16]

		ready = true
		return PacketDataResult.Success
	}

	/**
	 * Returns the Ethernet II EtherType identifying this payload, independent of readiness.
	 */
	override fn GetEtherType() int
	{
		return IEthernetPayload.ETHER_TYPE_ARP
	}

	/**
	 * Reports prepared metadata; the owner must still keep all borrowed payloads stable.
	 */
	override fn IsReady() bool
	{
		return ready
	}

	/**
	 * Returns the prepared packet length in bytes, or zero while unprepared.
	 */
	override fn GetAvailableLength() int
	{
		if (!ready) {
			return 0
		}

		return 28
	}

	/**
	 * Reads bytes 0..7 from the fixed ARP prefix and 8..27 from the address snapshot.
	 * Returns NotReady before preparation and Invalid outside 0..27; failures leave zero.
	 */
	override fn TryRead(index: int, value: out byte) PacketDataResult
	{
		value = 0x00

		if (!ready) {
			return PacketDataResult.NotReady
		}

		if (index < 0 || index >= 28) {
			return PacketDataResult.Invalid
		}

		if (index < 8) {
			value = PREFIX[index];
			return PacketDataResult.Success
		}

		value = this.ArpHeaderByte(index, address0, address1, address2, address3, address4, address5, address6, address7, address8, address9)
		return PacketDataResult.Success
	}

	/** Pure byte selection; no additional scheduled transaction. */
	inline fn ArpHeaderByte[](index: int, snapshotaddress0: logic[16], snapshotaddress1: logic[16], snapshotaddress2: logic[16], snapshotaddress3: logic[16], snapshotaddress4: logic[16], snapshotaddress5: logic[16], snapshotaddress6: logic[16], snapshotaddress7: logic[16], snapshotaddress8: logic[16], snapshotaddress9: logic[16]) byte
	{
		if (index == 8) { return (snapshotaddress0 >> 8) as byte }
		if (index == 9) { return snapshotaddress0 as byte }
		if (index == 10) { return (snapshotaddress1 >> 8) as byte }
		if (index == 11) { return snapshotaddress1 as byte }
		if (index == 12) { return (snapshotaddress2 >> 8) as byte }
		if (index == 13) { return snapshotaddress2 as byte }
		if (index == 14) { return (snapshotaddress3 >> 8) as byte }
		if (index == 15) { return snapshotaddress3 as byte }
		if (index == 16) { return (snapshotaddress4 >> 8) as byte }
		if (index == 17) { return snapshotaddress4 as byte }
		if (index == 18) { return (snapshotaddress5 >> 8) as byte }
		if (index == 19) { return snapshotaddress5 as byte }
		if (index == 20) { return (snapshotaddress6 >> 8) as byte }
		if (index == 21) { return snapshotaddress6 as byte }
		if (index == 22) { return (snapshotaddress7 >> 8) as byte }
		if (index == 23) { return snapshotaddress7 as byte }
		if (index == 24) { return (snapshotaddress8 >> 8) as byte }
		if (index == 25) { return snapshotaddress8 as byte }
		if (index == 26) { return (snapshotaddress9 >> 8) as byte }
		if (index == 27) { return snapshotaddress9 as byte }
		return 0x00
	}
}