zhuhaow/NEKit

View on GitHub
src/Utils/Checksum.swift

Summary

Maintainability
A
1 hr
Test Coverage
import Foundation

open class Checksum {

    public static func computeChecksum(_ data: Data, from start: Int = 0, to end: Int? = nil, withPseudoHeaderChecksum initChecksum: UInt32 = 0) -> UInt16 {
        return toChecksum(computeChecksumUnfold(data, from: start, to: end, withPseudoHeaderChecksum: initChecksum))
    }

    public static func validateChecksum(_ payload: Data, from start: Int = 0, to end: Int? = nil) -> Bool {
        let cs = computeChecksumUnfold(payload, from: start, to: end)
        return toChecksum(cs) == 0
    }

    public static func computeChecksumUnfold(_ data: Data, from start: Int = 0, to end: Int? = nil, withPseudoHeaderChecksum initChecksum: UInt32 = 0) -> UInt32 {
        let scanner = BinaryDataScanner(data: data, littleEndian: true)
        scanner.skip(to: start)
        var result: UInt32 = initChecksum
        var end = end
        if end == nil {
            end = data.count
        }
        while scanner.position + 2 <= end! {
            let value = scanner.read16()!
            result += UInt32(value)
        }

        if scanner.position != end {
            // data is of odd size
            // Intel and ARM are both litten endian
            // so just add it
            let value = scanner.readByte()!
            result += UInt32(value)
        }
        return result
    }

    public static func toChecksum(_ checksum: UInt32) -> UInt16 {
        var result = checksum
        while (result) >> 16 != 0 {
            result = result >> 16 + result & 0xFFFF
        }
        return ~UInt16(result)
    }
}