# Path: dyndnsc/detector/base.py
# LOG = logging.getLogger(__name__)
# class IPDetector(Subject, DynamicCliMixin):
#     def __init__(self, *args, **kwargs):
#     def can_detect_offline(self):
#     def af(self):
#     def get_old_value(self):
#     def set_old_value(self, value):
#     def get_current_value(self, default=None):
#     def set_current_value(self, value):
#     def has_changed(self):
#     def configuration_key_prefix():
# 
# Path: dyndnsc/common/detect_ip.py
# def detect_ip(kind):
#     """
#     Detect IP address.
# 
#     kind can be:
#         IPV4 - returns IPv4 address
#         IPV6_ANY - returns any IPv6 address (no preference)
#         IPV6_PUBLIC - returns public IPv6 address
#         IPV6_TMP - returns temporary IPV6 address (privacy extensions)
# 
#     This function either returns an IP address (str) or
#     raises a GetIpException.
#     """
#     if kind not in (IPV4, IPV6_PUBLIC, IPV6_TMP, IPV6_ANY):
#         raise ValueError("invalid kind specified")
# 
#     # We create an UDP socket and connect it to a public host.
#     # We query the OS to know what our address is.
#     # No packet will really be sent since we are using UDP.
#     af = socket.AF_INET if kind == IPV4 else socket.AF_INET6
#     s = socket.socket(af, socket.SOCK_DGRAM)
#     try:
#         if kind in [IPV6_PUBLIC, IPV6_TMP, ]:
#             # caller wants some specific kind of IPv6 address (not IPV6_ANY)
#             try:
#                 if kind == IPV6_PUBLIC:
#                     preference = socket.IPV6_PREFER_SRC_PUBLIC
#                 elif kind == IPV6_TMP:
#                     preference = socket.IPV6_PREFER_SRC_TMP
#                 s.setsockopt(socket.IPPROTO_IPV6,
#                              socket.IPV6_ADDR_PREFERENCES, preference)
#             except socket.error as e:
#                 if e.errno == errno.ENOPROTOOPT:
#                     raise GetIpException("Kernel doesn't support IPv6 address preference")
#                 else:
#                     raise GetIpException("Unable to set IPv6 address preference: %s" % e)
# 
#         try:
#             outside_ip = OUTSIDE_IPV4 if kind == IPV4 else OUTSIDE_IPV6
#             s.connect((outside_ip, 9))
#         except (socket.error, socket.gaierror) as e:
#             raise GetIpException(str(e))
# 
#         ip = s.getsockname()[0]
#     finally:
#         s.close()
#     return ip
# 
# IPV4 = "ipv4"
# 
# IPV6_PUBLIC = "ipv6_public"
# 
# class GetIpException(Exception):
#     """Generic base class for all exceptions raised here."""


import logging
from .base import IPDetector, AF_INET6
from ..common.detect_ip import detect_ip, IPV4, IPV6_PUBLIC, GetIpException



LOG = logging.getLogger(__name__)


class IPDetector_Socket(IPDetector):
    """Detect IPs used by the system to communicate with outside world."""

    configuration_key = "socket"

    def __init__(self, family=None, *args, **kwargs):
        """
        Initialize.

        :param family: IP address family (default: INET, possible: INET6)
        """
        super(IPDetector_Socket, self).__init__(*args, family=family, **kwargs)

    def can_detect_offline(self):
        """Return False, this detector works offline."""
        # unsure about this. detector does not really transmit data to outside,
        # but unsure if it gives the wanted IPs if system is offline
        return False

    def detect(self):
        """Detect the IP address."""
        if self.opts_family == AF_INET6:
            kind = IPV6_PUBLIC
        else:  # 'INET':

# Path: dyndnsc/detector/base.py
# LOG = logging.getLogger(__name__)
# class IPDetector(Subject, DynamicCliMixin):
#     def __init__(self, *args, **kwargs):
#     def can_detect_offline(self):
#     def af(self):
#     def get_old_value(self):
#     def set_old_value(self, value):
#     def get_current_value(self, default=None):
#     def set_current_value(self, value):
#     def has_changed(self):
#     def configuration_key_prefix():
# 
# Path: dyndnsc/common/detect_ip.py
# def detect_ip(kind):
#     """
#     Detect IP address.
# 
#     kind can be:
#         IPV4 - returns IPv4 address
#         IPV6_ANY - returns any IPv6 address (no preference)
#         IPV6_PUBLIC - returns public IPv6 address
#         IPV6_TMP - returns temporary IPV6 address (privacy extensions)
# 
#     This function either returns an IP address (str) or
#     raises a GetIpException.
#     """
#     if kind not in (IPV4, IPV6_PUBLIC, IPV6_TMP, IPV6_ANY):
#         raise ValueError("invalid kind specified")
# 
#     # We create an UDP socket and connect it to a public host.
#     # We query the OS to know what our address is.
#     # No packet will really be sent since we are using UDP.
#     af = socket.AF_INET if kind == IPV4 else socket.AF_INET6
#     s = socket.socket(af, socket.SOCK_DGRAM)
#     try:
#         if kind in [IPV6_PUBLIC, IPV6_TMP, ]:
#             # caller wants some specific kind of IPv6 address (not IPV6_ANY)
#             try:
#                 if kind == IPV6_PUBLIC:
#                     preference = socket.IPV6_PREFER_SRC_PUBLIC
#                 elif kind == IPV6_TMP:
#                     preference = socket.IPV6_PREFER_SRC_TMP
#                 s.setsockopt(socket.IPPROTO_IPV6,
#                              socket.IPV6_ADDR_PREFERENCES, preference)
#             except socket.error as e:
#                 if e.errno == errno.ENOPROTOOPT:
#                     raise GetIpException("Kernel doesn't support IPv6 address preference")
#                 else:
#                     raise GetIpException("Unable to set IPv6 address preference: %s" % e)
# 
#         try:
#             outside_ip = OUTSIDE_IPV4 if kind == IPV4 else OUTSIDE_IPV6
#             s.connect((outside_ip, 9))
#         except (socket.error, socket.gaierror) as e:
#             raise GetIpException(str(e))
# 
#         ip = s.getsockname()[0]
#     finally:
#         s.close()
#     return ip
# 
# IPV4 = "ipv4"
# 
# IPV6_PUBLIC = "ipv6_public"
# 
# class GetIpException(Exception):
#     """Generic base class for all exceptions raised here."""


# Path: dyndnsc/detector/socket_ip.py
import logging
from .base import IPDetector, AF_INET6
from ..common.detect_ip import detect_ip, IPV4, IPV6_PUBLIC, GetIpException




LOG = logging.getLogger(__name__)


class IPDetector_Socket(IPDetector):
    """Detect IPs used by the system to communicate with outside world."""

    configuration_key = "socket"

    def __init__(self, family=None, *args, **kwargs):
        """
        Initialize.

        :param family: IP address family (default: INET, possible: INET6)
        """
        super(IPDetector_Socket, self).__init__(*args, family=family, **kwargs)

    def can_detect_offline(self):
        """Return False, this detector works offline."""
        # unsure about this. detector does not really transmit data to outside,
        # but unsure if it gives the wanted IPs if system is offline
        return False

    def detect(self):
        """Detect the IP address."""
        if self.opts_family == AF_INET6:
            kind = IPV6_PUBLIC
        else:  # 'INET':

            kind = IPV4