# Copyright 2026 SigmaSRC, Inc. All Rights Reserved.

import re
import socket
import logging

logger = logging.getLogger("protocol.hostcache")

def cache_host(host, options):
    """Magic caching of the Sigma Server host name lookup.

    This function tries to look up the host using the Python API
    to the resolver library, socket.gethostbyname().  If this
    succeeds, the cache is refreshed if necessary.  If this fails,
    the cached value is used, if necessary.

    The mapping is caced in $AVDATA/hostcache.txt; this should
    contain a single line of the form <hostname>=<address>.  The
    cached <address> is only used if <hostname> matches the host
    argument.

    """
    if re.match(r"\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\Z", host):
        return host
    chost = caddr = None
    cachefn = options.datapath("hostcache.txt")
    try:
        f = open(cachefn)
    except IOError:
        pass
    else:
        try:
            for line in f:
                m = re.match(r"^([^=\s]+)=([^\s]+)$", line)
                if m is not None:
                    chost, caddr = m.group(1, 2)
                    break
        finally:
            f.close()
    try:
        addr = socket.gethostbyname(host)
    except socket.error as err:
        logger.warn("Lookup for hostname %s failed: %s", host, err)
        if host == chost and caddr != None:
            logger.info("Using cached address %s", caddr)
            return caddr
        return host # Let the error happen again later
    logger.debug("Host %s = %s", host, addr)
    if (host, addr) != (chost, caddr):
        try:
            f = open(cachefn, "w")
        except IOError as err:
            logger.error("Can't write %s: %s", cachefn, err)
        else:
            logger.info("Updating %s with %s=%s", cachefn, host, addr)
            try:
                f.write("%s=%s\n" % (host, addr))
            finally:
                f.close()
    return addr
