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/icmp/IcmpEchoReply.lvt
namespace Livt.Net
/**
* Prepared echo reply borrowing a published payload provider. Only header
* metadata is stored here. Invalidate ancestors before replacing the payload;
* keep the provider stable until every prepared response/TX borrow has ended.
*/
component IcmpEchoReply<P: IPacketData> : IPacketData, IIpv4Payload
{
// Borrowed echo data; must remain stable until emission finishes.
payload: P
// Prepared echo header metadata and bounded data length.
identifier: logic[16]
sequence: logic[16]
checksum: logic[16]
dataLength: logic[16]
ready: bool
// Owned accumulator used only while preparing the checksum.
calculator: InternetChecksum
/**
* Borrows the fixed payload and owns a checksum calculator; starts unprepared.
*/
new(payload: P)
{
this.payload = payload;
calculator = new InternetChecksum()
}
/**
* Discards prepared metadata without changing the payload. Finish all dependent
* reads and transmit borrows before invalidating.
*/
public fn Invalidate()
{
ready = false;
dataLength = 0
}
/**
* Failure invalidates the previous reply. Compute checksum once, before reads.
*/
public fn TryPrepare(identifier: byte[2], sequence: byte[2]) PacketDataResult
{
this.Invalidate()
if (!payload.IsReady()) {
return PacketDataResult.NotReady
}
var size = payload.GetAvailableLength()
if (size < 0 || size > 65507) {
return PacketDataResult.Invalid
}
this.identifier = NetworkOrder.Word(identifier[0], identifier[1]) as logic[16]
this.sequence = NetworkOrder.Word(sequence[0], sequence[1]) as logic[16]
calculator.Reset()
// Reply type, code and checksum are all zero during calculation.
calculator.AddByte(identifier[0])
calculator.AddByte(identifier[1])
calculator.AddByte(sequence[0])
calculator.AddByte(sequence[1])
for (var i = 0; i < size; i++) {
var value: byte = 0x00
var result = payload.TryRead(i, value)
if (result != PacketDataResult.Success) {
return result
}
calculator.AddByte(value)
}
checksum = calculator.GetChecksum() as logic[16]
dataLength = size as logic[16]
ready = true
return PacketDataResult.Success
}
/**
* Reports prepared metadata; the owner must still keep all borrowed payloads stable.
*/
override fn IsReady() bool
{
return ready
}
/**
* Returns the IPv4 protocol number identifying this payload, independent of readiness.
*/
override fn GetProtocol() int
{
return IIpv4Payload.PROTOCOL_ICMP as int
}
/**
* Returns the prepared packet length in bytes, or zero while unprepared.
*/
override fn GetAvailableLength() int
{
if (!ready) {
return 0
}
return 8 + ((dataLength as uint) as int)
}
/**
* Reads a packet-relative byte; returns NotReady while unprepared and Invalid
* outside the prepared length. Delegated payload errors propagate; the output
* is data only on Success. Keep the prepared graph stable throughout the call.
* Bytes 0..1: reply type/code; 2..3: checksum; 4..5: identifier;
* 6..7: sequence; bytes 8 onward delegate to the echo payload.
*/
override fn TryRead(index: int, value: out byte) PacketDataResult
{
value = 0x00
if (!ready) {
return PacketDataResult.NotReady
}
if (index < 0 || index >= 8 + ((dataLength as uint) as int)) {
return PacketDataResult.Invalid
}
if (index < 8) {
value = this.IcmpHeaderByte(index, identifier, sequence, checksum)
return PacketDataResult.Success
}
return payload.TryRead(index - 8, value)
}
/** Pure byte selection; no additional scheduled transaction. */
inline fn IcmpHeaderByte[](index: int, snapshotidentifier: logic[16], snapshotsequence: logic[16], snapshotchecksum: logic[16]) byte
{
if (index == 2) { return (snapshotchecksum >> 8) as byte }
if (index == 3) { return snapshotchecksum as byte }
if (index == 4) { return (snapshotidentifier >> 8) as byte }
if (index == 5) { return snapshotidentifier as byte }
if (index == 6) { return (snapshotsequence >> 8) as byte }
if (index == 7) { return snapshotsequence as byte }
return 0x00
}
}