/
CDC-1.2b/
CDC-1.2b/src/
parent $network
object $connection

var $root dbref 'connection
var $root child_index 0
var $root fertile 1
var $root manager $connection
var $root owned [$connection]
var $root owners [$connection]
var $root writable []
var $root readable ['parameters, 'methods, 'code]
var $network buffer `[]
var $network ip ""
var $network hostname ""
var $network port 0
var $network socket 0
var $network active 0
var $root inited 1
var $connection daemon 0
var $connection interface 0
var $connection receive_internal 0
var $connection timeout 0
var $connection read_lines []
var $connection started_at 0

method receive
    arg line, status;
    
    (> .perms(sender(), this(), @$sys.system(), daemon) <);
    if ((status != 'external) && (!receive_internal))
        return;
    if (read_lines) {
        read_lines = read_lines.parse(line);
        line = .rehash_read_status();
        if ((!line) && (line != ""))
            return;
    }
    if ((interface.parse_line(line)) == 'disconnect)
        .close();
.

method initialize_connection
    arg interface_parent, seconds;
    var addr;
    
    (> .perms(sender()) <);
    
    // spawn this now, if they want to connect to a permanent interface
    // the spawned one can do that (such as a user object)
    addr = .address();
    daemon = sender();
    interface = interface_parent.spawn();
    .add_writer(interface);
    interface.new_connection(addr);
    interface.set_manager(interface);
    timeout = seconds;
    .set_active(1);
.

method set_interface_object
    arg obj;
    
    // called by an interface object to change interfaces.
    (> .perms(sender(), 'this) <);
    interface = obj;
.

method close
    (> pass() <);
    (> .destroy() <);
.

method init_connection
    (> .perms(caller(), $root) <);
    timeout = -1;
    daemon = 0;
    interface = 0;
.

method uninit_connection
    (> .perms(caller(), $root) <);
    daemon.connection_ending();
    timeout = -1;
    daemon = 0;
    (| interface.connection_going_away(.address(), .port()) |);
.

method connect
    arg [args];
    
    (> pass(@args) <);
    daemon.connection_starting();
    interface.connection_starting();
    started_at = time();
    if (timeout >= 0)
        (| $scheduler.add_task(timeout, 'timeout) |);
.

method timeout
    (> .perms(sender(), 'this) <);
    if (interface.timeout()) {
        .send(("Timeout (" + tostr(timeout)) + ").");
        .close();
    }
.

method address
    var addr;
    
    // return hostname or ip
    if (!('parameters in (.is_readable_by(sender()))))
        throw(~perm, "Sender does not have permission to get parameters.");
    addr = .hostname();
    if (!addr)
        addr = .ip();
    return addr;
.

method change_interface_object
    arg obj;
    var old_interface;
    
    // called by an interface object to change interfaces.
    (> .perms(sender(), interface) <);
    old_interface = interface;
    interface = obj;
    old_interface.connection_going_away(.address(), .port());
    interface.new_connection(.address(), .port());
    .del_writer(old_interface);
    .add_writer(interface);
.

method tell
    arg foo;
    
    (> .send(foo) <);
.

method rehash_read_status
    (> .perms(sender(), 'this) <);
    switch (read_lines.status()) {
        case 'abort:
            .abort_reading();
        case 'not_done:
            // do nothing
        case 'done:
            .finish_reading();
        case 'pass_command:
            return read_lines.command();
    }
    return 0;
.

method start_reading
    arg count;
    
    (> .perms(sender()) <);
    read_lines = $read_parser.new(task_id(), count);
    return $sys.suspend();
.

method finish_reading
    var task_id, lines;
    
    (> .perms(sender()) <);
    task_id = read_lines.task_id();
    lines = read_lines.lines();
    read_lines = 0;
    $sys.resume(task_id, lines);
.

method abort_reading
    (> .perms(sender()) <);
    read_lines = read_lines.add('lines, 'aborted);
    .finish_reading();
.

method is_reading
    return read_lines ? 1 | 0;
.

method started_at
    if (!('parameters in (.is_readable_by(sender()))))
        throw(~perm, "Sender does not have permission to get parameters.");
    return started_at;
.