<commit_before>import Foundation
import CocoaLumberjackSwift

public enum IPVersion: UInt8 {
    case iPv4 = 4, iPv6 = 6
}

public enum TransportProtocol: UInt8 {
    case icmp = 1, tcp = 6, udp = 17
}

/// The class to process and build IP packet.
///
/// - note: Only IPv4 is supported as of now.
open class IPPacket {
    /**
     Get the version of the IP Packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The version of the packet. Returns `nil` if failed to parse the packet.
     */
    open static func peekIPVersion(_ data: Data) -> IPVersion? {
        guard data.count >= 20 else {
            return nil
        }

        let version = (data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count).pointee >> 4
        return IPVersion(rawValue: version)
    }

    /**
     Get the protocol of the IP Packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The protocol of the packet. Returns `nil` if failed to parse the packet.
     */
    open static func peekProtocol(_ data: Data) -> TransportProtocol? {
        guard data.count >= 20 else {
            return nil
        }

        return TransportProtocol(rawValue: (data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count).advanced(by: 9).pointee)
    }

    /**
     Get the source IP address of the IP packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The source IP address of the packet. Returns `nil` if failed to parse the packet.
     */
    open static func peekSourceAddress(_ data: Data) -> IPv4Address? {
        guard data.count >= 20 else {
            return nil
        }

        return IPv4Address(fromBytesInNetworkOrder: (data as NSData).bytes.advanced(by: 12))
    }

    /**
     Get the destination IP address of the IP packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The destination IP address of the packet. Returns `nil` if failed to parse the packet.
     */
    open static func peekDestinationAddress(_ data: Data) -> IPv4Address? {
        guard data.count >= 20 else {
            return nil
        }

        return IPv4Address(fromBytesInNetworkOrder: (data as NSData).bytes.advanced(by: 16))
    }

    /**
     Get the source port of the IP packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The source IP address of the packet. Returns `nil` if failed to parse the packet.

     - note: Only TCP and UDP packet has port field.
     */
    open static func peekSourcePort(_ data: Data) -> Port? {
        guard let proto = peekProtocol(data) else {
            return nil
        }

        guard proto == .tcp || proto == .udp else {
            return nil
        }

        let headerLength = Int((data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count).pointee & 0x0F * 4)

        // Make sure there are bytes for source and destination bytes.
        guard data.count > headerLength + 4 else {
            return nil
        }

        return Port(bytesInNetworkOrder: (data as NSData).bytes.advanced(by: headerLength))
    }

    /**
     Get the destination port of the IP packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The destination IP address of the packet. Returns `nil` if failed to parse the packet.

     - note: Only TCP and UDP packet has port field.
     */
    open static func peekDestinationPort(_ data: Data) -> Port? {
        guard let proto = peekProtocol(data) else {
            return nil
        }

        guard proto == .tcp || proto == .udp else {
            return nil
        }

        let headerLength = Int((data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count).pointee & 0x0F * 4)

        // Make sure there are bytes for source and destination bytes.
        guard data.count > headerLength + 4 else {
            return nil
        }

        return Port(bytesInNetworkOrder: (data as NSData).bytes.advanced(by: headerLength + 2))
    }

    /// The version of the current IP packet.
    open var version: IPVersion = .iPv4

    /// The length of the IP packet header.
    open var headerLength: UInt8 = 20

    /// This contains the DSCP and ECN of the IP packet.
    ///
    /// - note: Since we can not send custom IP packet out with NetworkExtension, this is useless and simply ignored.
    open var tos: UInt8 = 0

    /// This should be the length of the datagram.
    /// This value is not read from header since NEPacketTunnelFlow has already taken care of it for us.
    open var totalLength: UInt16 {
        get {
            return UInt16(packetData.count)
        }
    }

    /// Identification of the current packet.
    ///
    /// - note: Since we do not support fragment, this is ignored and always will be zero.
    /// - note: Theoratically, this should be a sequentially increasing number. It probably will be implemented.
    var identification: UInt16 = 0

    /// Offset of the current packet.
    ///
    /// - note: Since we do not support fragment, this is ignored and always will be zero.
    var offset: UInt16 = 0

    /// TTL of the packet.
    var TTL: UInt8 = 64

    /// Source IP address.<commit_msg>Fix warning for explicit getter<commit_after>import Foundation
import CocoaLumberjackSwift

public enum IPVersion: UInt8 {
    case iPv4 = 4, iPv6 = 6
}

public enum TransportProtocol: UInt8 {
    case icmp = 1, tcp = 6, udp = 17
}

/// The class to process and build IP packet.
///
/// - note: Only IPv4 is supported as of now.
open class IPPacket {
    /**
     Get the version of the IP Packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The version of the packet. Returns `nil` if failed to parse the packet.
     */
    open static func peekIPVersion(_ data: Data) -> IPVersion? {
        guard data.count >= 20 else {
            return nil
        }

        let version = (data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count).pointee >> 4
        return IPVersion(rawValue: version)
    }

    /**
     Get the protocol of the IP Packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The protocol of the packet. Returns `nil` if failed to parse the packet.
     */
    open static func peekProtocol(_ data: Data) -> TransportProtocol? {
        guard data.count >= 20 else {
            return nil
        }

        return TransportProtocol(rawValue: (data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count).advanced(by: 9).pointee)
    }

    /**
     Get the source IP address of the IP packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The source IP address of the packet. Returns `nil` if failed to parse the packet.
     */
    open static func peekSourceAddress(_ data: Data) -> IPv4Address? {
        guard data.count >= 20 else {
            return nil
        }

        return IPv4Address(fromBytesInNetworkOrder: (data as NSData).bytes.advanced(by: 12))
    }

    /**
     Get the destination IP address of the IP packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The destination IP address of the packet. Returns `nil` if failed to parse the packet.
     */
    open static func peekDestinationAddress(_ data: Data) -> IPv4Address? {
        guard data.count >= 20 else {
            return nil
        }

        return IPv4Address(fromBytesInNetworkOrder: (data as NSData).bytes.advanced(by: 16))
    }

    /**
     Get the source port of the IP packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The source IP address of the packet. Returns `nil` if failed to parse the packet.

     - note: Only TCP and UDP packet has port field.
     */
    open static func peekSourcePort(_ data: Data) -> Port? {
        guard let proto = peekProtocol(data) else {
            return nil
        }

        guard proto == .tcp || proto == .udp else {
            return nil
        }

        let headerLength = Int((data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count).pointee & 0x0F * 4)

        // Make sure there are bytes for source and destination bytes.
        guard data.count > headerLength + 4 else {
            return nil
        }

        return Port(bytesInNetworkOrder: (data as NSData).bytes.advanced(by: headerLength))
    }

    /**
     Get the destination port of the IP packet without parsing the whole packet.

     - parameter data: The data containing the whole IP packet.

     - returns: The destination IP address of the packet. Returns `nil` if failed to parse the packet.

     - note: Only TCP and UDP packet has port field.
     */
    open static func peekDestinationPort(_ data: Data) -> Port? {
        guard let proto = peekProtocol(data) else {
            return nil
        }

        guard proto == .tcp || proto == .udp else {
            return nil
        }

        let headerLength = Int((data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count).pointee & 0x0F * 4)

        // Make sure there are bytes for source and destination bytes.
        guard data.count > headerLength + 4 else {
            return nil
        }

        return Port(bytesInNetworkOrder: (data as NSData).bytes.advanced(by: headerLength + 2))
    }

    /// The version of the current IP packet.
    open var version: IPVersion = .iPv4

    /// The length of the IP packet header.
    open var headerLength: UInt8 = 20

    /// This contains the DSCP and ECN of the IP packet.
    ///
    /// - note: Since we can not send custom IP packet out with NetworkExtension, this is useless and simply ignored.
    open var tos: UInt8 = 0

    /// This should be the length of the datagram.
    /// This value is not read from header since NEPacketTunnelFlow has already taken care of it for us.
    open var totalLength: UInt16 {
            return UInt16(packetData.count)
    }

    /// Identification of the current packet.
    ///
    /// - note: Since we do not support fragment, this is ignored and always will be zero.
    /// - note: Theoratically, this should be a sequentially increasing number. It probably will be implemented.
    var identification: UInt16 = 0

    /// Offset of the current packet.
    ///
    /// - note: Since we do not support fragment, this is ignored and always will be zero.
    var offset: UInt16 = 0

    /// TTL of the packet.
    var TTL: UInt8 = 64

    /// Source IP address.
{'fraction_non_alphanumeric': 0.08164383561643836, 'fraction_numerical': 0.011141552511415525, 'mean_word_length': 2.226576311137301, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5879794', 'n_tokens_mistral': 3092, 'n_tokens_neox': 2877, 'n_words': 1288}