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/checksum/InternetChecksum.lvt

namespace Livt.Net

/**
 * Computes the RFC 1071 one's-complement word sum over a byte stream.
 *
 * Keep the unfolded sum within a non-negative int (at most 2147483647).
 * Feed bytes in network (big-endian) order using AddByte(). Odd-length data
 * is treated as if padded with a trailing zero byte.
 *
 * GetWordSum() returns the unfolded accumulated sum, compatible with the
 * payloadWordSum parameter of TcpChecksum.CalculatePayloadChecksum.
 *
 * GetChecksum() returns the final RFC 1071 checksum value (folded and
 * one's-complemented) ready to be written into an IPv4, ICMP, TCP, or UDP
 * header field. Use NetworkOrder.HighByte() and NetworkOrder.LowByte() to extract the two bytes.
 */
component InternetChecksum
{
	// Unfolded word sum and the optional unmatched high octet.
	sum: int
	pendingByte: byte
	hasPendingByte: bool

	/**
	 * Starts with an empty, zero-valued sum and no pending high byte.
	 */
	new()
	{
	}

	/**
	 * Clears the accumulated sum and resets the byte-pairing state.
	 */
	public fn Reset()
	{
		this.sum = 0
		this.pendingByte = 0x00
		this.hasPendingByte = false
	}

	/**
	 * Accumulates one byte into the running word sum.
	 * Bytes are paired in network order: the first byte of each pair is the
	 * high byte of the 16-bit word, the second is the low byte.
	 */
	public fn AddByte(b: byte)
	{
		if (this.hasPendingByte == false) {
			this.pendingByte = b
			this.hasPendingByte = true
			return
		}

		this.sum = this.sum + NetworkOrder.Word(this.pendingByte, b)
		this.pendingByte = 0x00
		this.hasPendingByte = false
	}

	/**
	 * Returns the accumulated unfolded one's-complement word sum.
	 * Odd-length streams are treated as if padded with a trailing zero byte.
	 * Compatible with TcpChecksum.CalculatePayloadChecksum(payloadWordSum).
	 */
	public fn GetWordSum() int
	{
		if (this.hasPendingByte == true) {
			return this.sum + NetworkOrder.Word(this.pendingByte, 0x00)
		}

		return this.sum
	}

	/**
	 * Returns the final RFC 1071 checksum (folded and one's-complemented).
	 * Use NetworkOrder.HighByte() and NetworkOrder.LowByte() to extract the two header bytes.
	 */
	public fn GetChecksum() int
	{
		var s: int = this.GetWordSum()
		return ChecksumArithmetic.Finish(s)
	}
}