Skip to content

Commit

Permalink
Added unit test for NetAddr MacAddress class + some code refactor & c…
Browse files Browse the repository at this point in the history
…leanup
  • Loading branch information
ccie18643 committed Sep 1, 2024
1 parent 6f52416 commit c74ae4d
Show file tree
Hide file tree
Showing 6 changed files with 746 additions and 41 deletions.
4 changes: 2 additions & 2 deletions pytcp/lib/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class PacketIntegrityError(PacketValidationError):
Exception raised when integrity check fails.
"""

def __init__(self, message: str):
def __init__(self, /, message: str):
super().__init__("[INTEGRITY ERROR]" + message)


Expand All @@ -62,5 +62,5 @@ class PacketSanityError(PacketValidationError):
Exception raised when sanity check fails.
"""

def __init__(self, message: str):
def __init__(self, /, message: str):
super().__init__("[SANITY ERROR]" + message)
120 changes: 103 additions & 17 deletions pytcp/lib/net_addr/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,53 +35,139 @@

from __future__ import annotations

from typing import Any

class NetAddrError(Exception): ...

class NetAddrError(Exception):
"""
Base class for all NetAddr exceptions.
"""

class IpAddressFormatError(NetAddrError): ...

class IpAddressFormatError(NetAddrError):
"""
Base class for all IP address format exceptions.
"""

class IpMaskFormatError(NetAddrError): ...

class IpMaskFormatError(NetAddrError):
"""
Base class for all IP mask format exceptions.
"""

class IpNetworkFormatError(NetAddrError): ...

class IpNetworkFormatError(NetAddrError):
"""
Base class for all IP network format exceptions.
"""

class IpHostFormatError(NetAddrError): ...

class IpHostFormatError(NetAddrError):
"""
Base class for all IP host format exceptions.
"""

class IpHostGatewayError(NetAddrError): ...

class IpHostGatewayError(NetAddrError):
"""
Base class for all IP host gateway exceptions.
"""

class Ip4AddressFormatError(IpAddressFormatError): ...

class Ip4AddressFormatError(IpAddressFormatError):
"""
Exception raised when IPv4 address format is invalid.
"""

class Ip4MaskFormatError(IpMaskFormatError): ...
def __init__(self, /, message: Any):
super().__init__(f"The IPv4 address format is invalid: {message!r}")


class Ip4NetworkFormatError(IpNetworkFormatError): ...
class Ip4MaskFormatError(IpMaskFormatError):
"""
Exception raised when IPv4 mask format is invalid.
"""

def __init__(self, /, message: Any):
super().__init__(f"The IPv4 mask format is invalid: {message!r}")

class Ip4HostFormatError(IpHostFormatError): ...

class Ip4NetworkFormatError(IpNetworkFormatError):
"""
Exception raised when IPv4 network format is invalid.
"""

class Ip4HostGatewayError(IpHostGatewayError): ...
def __init__(self, /, message: Any):
super().__init__(f"The IPv4 network format is invalid: {message!r}")


class Ip6AddressFormatError(IpAddressFormatError): ...
class Ip4HostFormatError(IpHostFormatError):
"""
Exception raised when IPv4 host format is invalid.
"""

def __init__(self, /, message: Any):
super().__init__(f"The IPv4 host format is invalid: {message!r}")

class Ip6MaskFormatError(IpMaskFormatError): ...

class Ip4HostGatewayError(IpHostGatewayError):
"""
Exception raised when IPv4 host gateway is invalid.
"""

class Ip6NetworkFormatError(IpNetworkFormatError): ...
def __init__(self, /, message: Any):
super().__init__(f"The IPv4 host gateway is invalid: {message!r}")


class Ip6HostFormatError(IpHostFormatError): ...
class Ip6AddressFormatError(IpAddressFormatError):
"""
Exception raised when IPv6 address format is invalid.
"""

def __init__(self, /, message: Any):
super().__init__(f"The IPv6 address format is invalid: {message!r}")

class Ip6HostGatewayError(IpHostGatewayError): ...

class Ip6MaskFormatError(IpMaskFormatError):
"""
Exception raised when IPv6 mask format is invalid.
"""

class MacAddressFormatError(Exception): ...
def __init__(self, /, message: Any):
super().__init__(f"The IPv6 mask format is invalid: {message!r}")


class Ip6NetworkFormatError(IpNetworkFormatError):
"""
Exception raised when IPv6 network format is invalid.
"""

def __init__(self, /, message: Any):
super().__init__(f"The IPv6 network format is invalid: {message!r}")


class Ip6HostFormatError(IpHostFormatError):
"""
Exception raised when IPv6 host format is invalid.
"""

def __init__(self, /, message: Any):
super().__init__(f"The IPv6 host format is invalid: {message!r}")


class Ip6HostGatewayError(IpHostGatewayError):
"""
Exception raised when IPv6 host gateway is invalid.
"""

def __init__(self, /, message: Any):
super().__init__(f"The IPv6 host gateway is invalid: {message!r}")


class MacAddressFormatError(Exception):
"""
Exception raised when MAC address format is invalid.
"""

def __init__(self, /, message: Any):
super().__init__(f"The MAC address format is invalid: {message!r}")
37 changes: 20 additions & 17 deletions pytcp/lib/net_addr/mac_address.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@ class MacAddress:

def __init__(
self,
/,
address: (
MacAddress | str | bytes | bytearray | memoryview | int | None
) = None,
) -> None:
"""
Class constructor.
Create a new MAC address object.
"""

self._address: int
Expand All @@ -63,7 +64,7 @@ def __init__(
return

if isinstance(address, int):
if address in range(0xFFFF_FFFF_FFFF + 1):
if 0 <= address <= 0xFFFF_FFFF_FFFF:
self._address = address
return

Expand Down Expand Up @@ -94,21 +95,21 @@ def __init__(

def __str__(self) -> str:
"""
The '__str__()' dunder.
Get the MAC address log string.
"""

return ":".join([f"{_:0>2x}" for _ in bytes(self)])

def __repr__(self) -> str:
"""
The '__repr__()' dunder.
Get the MAC address string representation.
"""

return f"MacAddress('{str(self)}')"
return f"{self.__class__.__name__}('{str(self)}')"

def __bytes__(self) -> bytes:
"""
The '__bytes__() dunder.
Get the MAC address as bytes.
"""

return struct.pack(
Expand All @@ -120,77 +121,79 @@ def __bytes__(self) -> bytes:

def __int__(self) -> int:
"""
The '__int__()' dunder.
Get the MAC address as int.
"""

return self._address

def __eq__(self, other: object) -> bool:
"""
The '__eq__()' dunder.
Compare MAC address with another object.
"""

return repr(self) == repr(other)

def __hash__(self) -> int:
"""
The '__hash__' dunder.
Get the MAC address hash.
"""

return self._address

@property
def is_unspecified(self) -> bool:
"""
Check if address is unspecified.
Check if MAC address is unspecified.
"""

return self._address == 0x0000_0000_0000

@property
def is_unicast(self) -> bool:
"""
Check if address is unicast.
Check if MAC address is unicast.
"""

return (self._address & 0x0100_0000_0000) == 0x0000_0000_0000

@property
def is_multicast(self) -> bool:
"""
Check if address is multicast.
Check if MAC address is multicast.
"""

return (self._address & 0x0100_0000_0000) == 0x0100_0000_0000
return (
(self._address & 0x0100_0000_0000) == 0x0100_0000_0000
) and not self.is_broadcast

@property
def is_multicast_ip4(self) -> bool:
"""
Check if address is a MAC for IPv4 multicast.
Check if MAC address is a IPv4 multicast MAC.
"""

return (self._address & 0xFFFF_FF00_0000) == 0x0100_5E00_0000

@property
def is_multicast_ip6(self) -> bool:
"""
Check if address is a MAC for IPv6 multicast.
Check if MAC address is a MAC for IPv6 multicast MAC.
"""

return (self._address & 0xFFFF_0000_0000) == 0x3333_0000_0000

@property
def is_multicast_ip6_solicited_node(self) -> bool:
"""
Check if address is a MAC for IPv6 solicited node multicast.
Check if address is IPv6 solicited node multicast MAC.
"""

return (self._address & 0xFFFF_FF00_0000) == 0x3333_FF00_0000

@property
def is_broadcast(self) -> bool:
"""
Check if address is a broadcast MAC.
Check if MAC address is a broadcast.
"""

return self._address == 0xFFFF_FFFF_FFFF
Loading

0 comments on commit c74ae4d

Please sign in to comment.