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/services/ArpService.lvt
namespace Livt.Net
/**
* Owns a checked ARP response graph and keeps it immutable until explicit release.
* Borrows request storage and an admission strategy. The successful response is
* independent of RX; all request views close before TryHandle returns.
*/
component ArpService<S: IPacketData, A: IFrameAcceptance> : IResponseService
{
// Borrowed source, policy and shared parsers; the response graph is owned.
source: S
acceptance: A
ethernet: EthernetFrameParser<S>
response: ArpResponder<S>
// Endpoint configuration and publication state, owned by this service.
localMac: byte[6]
localIp: byte[4]
ready: bool
/**
* Borrows source, policy and shared parsers; creates an unpublished response.
* Parsers must bind this source in the same clock/reset domain. Serialize
* all parser users and close their descendants before handling a request.
*/
new(source: S, ethernet: EthernetFrameParser<S>, acceptance: A, localMac: byte[6], localIp: byte[4])
{
this.source = source
this.acceptance = acceptance
this.localMac = localMac
this.localIp = localIp
this.ethernet = ethernet
this.response = new ArpResponder<S>(ethernet)
}
/**
* Prepares one supported local request; Busy preserves all previous bytes.
* Rejected/failed requests close their views and leave no published response.
*/
override fn TryHandle() ServiceResult
{
if (this.ready) {
return ServiceResult.Busy
}
if (!this.source.IsReady()) {
return ServiceResult.NotReady
}
this.ethernet.TryParse()
if (!this.ethernet.IsReady()) {
this.ethernet.Invalidate()
return ServiceResult.Invalid
}
if (this.ethernet.GetEtherType() != IEthernetPayload.ETHER_TYPE_ARP) {
this.ethernet.Invalidate()
return ServiceResult.Ignored
}
var peer = this.ethernet.GetSourceMac()
if (!this.acceptance.Accept(peer, IEthernetPayload.ETHER_TYPE_ARP)) {
this.ethernet.Invalidate()
return ServiceResult.Ignored
}
var result = this.response.TryPrepareParsed(this.localMac, this.localIp)
if (result != PacketDataResult.Success) {
this.response.Invalidate()
return ServiceResult.Ignored
}
this.ready = true
return ServiceResult.Prepared
}
/**
* Drops the response only after the caller has ended all response borrows.
*/
override fn TryReleaseResponse() PacketDataResult
{
if (!this.ready) {
return PacketDataResult.Invalid
}
this.ready = false
this.response.Invalidate()
return PacketDataResult.Success
}
/**
* Reports this service's publication, not mere internal preparation progress.
*/
override fn IsReady() bool
{
return this.ready
}
/**
* Returns complete padded frame bytes, or zero before publication.
*/
override fn GetAvailableLength() int
{
if (!this.ready) {
return 0
}
return this.response.GetAvailableLength()
}
/**
* Reads a published response byte; output is data only on Success.
*/
override fn TryRead(index: int, value: out byte) PacketDataResult
{
value = 0x00
if (!this.ready) {
return PacketDataResult.NotReady
}
return this.response.TryRead(index, value)
}
}