/
ColdCore-3.0a9.02/
ColdCore-3.0a9.02/src/
new object $dns: $network;

var $dmi_data descriptions = #[];
var $dns async = 0;
var $dns connection = 0;
var $dns dnshost = ["127.0.0.1", 1153];
var $dns started = 0;
var $dns starting = 0;
var $dns valid_host_regexp = "^([-a-z0-9]+\.)+(gov|edu|com|org|int|mil|net|nato|arpa|[a-z][a-z])$";
var $dns valid_ip_regexp = "([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)";
var $root created_on = 867779129;
var $root flags = ['variables, 'methods, 'code, 'core];
var $root inited = 1;
var $root managed = [$dns];
var $root manager = $dns;
var $root trusted_by = [$outbound_connection];

public method .connection_going_away() {
    arg host, port;
    
    if (sender() != connection)
        return;
    started = 0;
    if (!starting)
        .restart();
};

public method .connection_starting() {
    arg host, port;
    
};

public method .core_dns() {
    async = 0;
    connection = 0;
    starting = 0;
    started = 0;
};

public method .hostname() {
    arg ip;
    var c, line, result;
    
    if (!ip)
        return pass();
    if (!match_regexp(ip, valid_ip_regexp))
        throw(~invip, "Invalid IP Address: " + ip);
    if (!async)
        return pass(ip);
    if (!valid(connection)) {
        if (!(.restart()))
            return pass(ip);
    }
    connection = connection.write((task_id() + ":N:") + ip);
    result = $scheduler.suspend(this());
    if ((type(result) != 'list) || (listlen(result) != 2))
        return "";
    switch (result[1]) {
        case "N":
            throw(~address, result[2]);
        case "F":
            throw(~failed, result[2]);
        case "G":
            return result[2];
        default:
            $sys.log("DNS ERROR: Invalid result: " + (result.join(":")));
    }
};

public method .ip() {
    arg hostname;
    var c, line, result;
    
    if (!hostname)
        return pass();
    if ((hostname != "localhost") && (!match_regexp(hostname, valid_host_regexp)))
        throw(~address, ("Invalid Internet Address: \"" + hostname) + "\"");
    if (!async)
        return pass(hostname);
    if (!valid(connection)) {
        if (!(.restart()))
            return pass(hostname);
    }
    connection = connection.write((task_id() + ":R:") + hostname);
    result = $scheduler.suspend(this());
    if ((type(result) != 'list) || (listlen(result) != 2))
        return "";
    switch (result[1]) {
        case "N":
            throw(~address, result[2]);
        case "F":
            throw(~failed, result[2]);
        case "G":
            return result[2];
        default:
            $sys.log("DNS ERROR: Invalid result: " + (result.join(":")));
    }
};

public method .parse_line() {
    arg line;
    var m, task, code, info;
    
    (> .perms(caller(), $connection) <);
    if ((m = regexp(line, "^([0-9]+):([a-z]):(.*)$"))) {
        [task, code, info] = m;
        task = toint(task);
        catch any {
            $scheduler.resume(task, [code, info]);
        } with {
            $sys.log("DNS ERROR: ");
            $sys.log($parse_lib.traceback(traceback()));
        }
    } else {
        $sys.log("DNS ERROR: Invalid Result from server: " + line);
    }
};

public method .restart() {
    if (starting || (!started))
        return 0;
    connection = 0;
    catch any {
        (> .startup_dns() <);
        $sys.log("** Restarting async DNS lookups at " + (dnshost.join(":")));
    } with {
        $sys.log("** Unable to restart async DNS lookups because:");
        $sys.log("** => " + ((traceback()[1])[2]));
    }
    return valid(connection);
};

public method .shutdown() {
    arg @args;
    var c;
    
    (sender() != this()) && (> .perms(caller(), 'system) <);
    c = connection;
    connection = 0;
    (| c.close() |);
    started = 0;
};

public method .startup(): forked  {
    arg @args;
    
    (> .perms(sender(), 'system) <);
    .shutdown();
    if (!async)
        return;
    catch any {
        (> .startup_dns() <);
        $sys.log("** Starting async DNS lookups at " + (dnshost.join(":")));
    } with {
        $sys.log("** Unable to startup async DNS lookups because:");
        $sys.log("** => " + ((traceback()[1])[2]));
    }
};

protected method .startup_dns() {
    var id, tmp, x;
    
    if (starting)
        return;
    started = 0;
    starting = 1;
    if (connection)
        (| connection.close() |);
    id = tosym("dns_connection");
    while ((| lookup(id) |))
        id = tosym("dns_connection_" + ++x);
    connection = $outbound_connection.new_with(id);
    if ((| connection.open_connection(@dnshost) |)) {
        starting = 0;
        started = 1;
        return;
    }
    
    // try to exec() it, then startup again
    (| $sys.startup_dnsserv() |);
    $scheduler.sleep(1);
    catch any {
        connection.open_connection(@dnshost);
        starting = 0;
    } with {
        (| connection.close() |);
        connection = 0;
        starting = 0;
        if (error() == ~refused)
            throw(~refused, "Unable to open connection to " + (dnshost.join(":")));
        else
            rethrow(error());
    }
    started = 1;
};

public method .valid_host_regexp() {
    return valid_host_regexp;
};

public method .valid_hostname() {
    arg host;
    
    return match_regexp(host, valid_host_regexp) ? 1 : 0;
};

public method .valid_ip() {
    arg ip;
    
    return match_regexp(ip, valid_ip_regexp) ? 1 : 0;
};

public method .valid_ip_regexp() {
    return valid_ip_regexp;
};