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/NetworkService.lvt

namespace Livt.Net

/**
 * Common ARP/ICMP endpoint with owned handlers, admission policy and selection.
 * Construct over a receiver/provider and bind the transmitter to this response
 * source. TryHandle snapshots requests, so RX can be released immediately after
 * it returns. Keep responses until TX completion, then TryReleaseResponse.
 * Custom policies/handlers compose through ArpService, IcmpEchoService and ServiceChain.
 */
component NetworkService<S: IPacketData, CAPACITY: int = 128> : IResponseService
{
	// Owned default strategy, response graphs and priority chain.
	acceptance: AcceptAllFrames
	arp: ArpService<S, AcceptAllFrames>
	icmp: IcmpEchoService<S, AcceptAllFrames, CAPACITY>
	services: ServiceChain<ArpService<S, AcceptAllFrames>, IcmpEchoService<S, AcceptAllFrames, CAPACITY>>
	classification: FrameClassification<S>
	localIp: byte[4]

	/**
	 * Borrows the source and its Ethernet/IPv4 parser pair; owns service responses.
	 * The parsers must bind the same source and clock/reset domain. Serialize
	 * all users and invalidate external descendants before TryHandle/ClearDiagnostics.
	 */
	new(source: S, ethernet: EthernetFrameParser<S>, ipv4: Ipv4PacketParser<EthernetFrameParser<S>>, localMac: byte[6], localIp: byte[4])
	{
		this.localIp = localIp
		this.acceptance = new AcceptAllFrames()
		this.arp = new ArpService<S, AcceptAllFrames>(source, ethernet, this.acceptance, localMac, localIp)
		this.icmp = new IcmpEchoService<S, AcceptAllFrames, CAPACITY>(source, ethernet, ipv4, this.acceptance, localMac, localIp)
		this.services = new ServiceChain<ArpService<S, AcceptAllFrames>, IcmpEchoService<S, AcceptAllFrames, CAPACITY>>(this.arp, this.icmp)
		this.classification = new FrameClassification<S>(ethernet, ipv4)
	}

	/**
	 * Handles ARP before ICMP. Busy retains both response and diagnostics unchanged.
	 */
	override fn TryHandle() ServiceResult
	{
		if (this.services.IsReady()) {
			return ServiceResult.Busy
		}

		this.classification.Inspect(this.localIp)
		return this.services.TryHandle()
	}

	/**
	 * Releases the selected graph only after all response borrows have ended.
	 */
	override fn TryReleaseResponse() PacketDataResult
	{
		return this.services.TryReleaseResponse()
	}

	/**
	 * Clears diagnostics at the next request boundary; no active response may remain.
	 */
	public fn ClearDiagnostics()
	{
		if (!this.services.IsReady()) {
			this.classification.Clear()
		}
	}

	/**
	 * Returns ARP/ICMP for a selected response, or Unknown if no response is published.
	 */
	public fn GetResponseProtocol() NetworkProtocol
	{
		var selected = this.services.GetSelection()

		if (selected == ServiceSelection.First) {
			return NetworkProtocol.Arp
		}

		if (selected == ServiceSelection.Second) {
			return NetworkProtocol.Icmp
		}

		return NetworkProtocol.Unknown
	}

	/**
	 * Returns decoded protocol metadata independently of response selection.
	 */
	public fn GetRequestProtocol() NetworkProtocol
	{
		return this.classification.GetProtocol()
	}

	/**
	 * Reports supported IPv4 metadata addressed to this endpoint.
	 */
	public fn IsRequestForLocalIp() bool
	{
		return this.classification.IsForLocalIp()
	}

	/**
	 * Reports the selected response publication.
	 */
	override fn IsReady() bool
	{
		return this.services.IsReady()
	}

	/**
	 * Returns complete padded frame length, or zero when no response is ready.
	 */
	override fn GetAvailableLength() int
	{
		return this.services.GetAvailableLength()
	}

	/**
	 * Reads the selected graph without an additional payload copy.
	 */
	override fn TryRead(index: int, value: out byte) PacketDataResult
	{
		return this.services.TryRead(index, value)
	}
}