/
CDC-1.1/
parent $network_root
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_root buffer `[]
var $network_root ip ""
var $network_root hostname ""
var $network_root port 0
var $network_root socket 0
var $network_root active 0
var $root inited 1
var $connection daemon 0
var $connection interface 0
var $connection receive_internal 0
var $connection timeout 0

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

method init_inbound_connection
    (> .perms(caller(), $root) <);
    daemon = 0;
    interface = 0;
.

method uninit_inbound_connection
    (> .perms(caller(), $root) <);
    daemon = 0;
    interface = 0;
.

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() <);
    (| daemon.connection_ending() |);
    (> .destroy() <);
.

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

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

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

method disconnect
    (> pass() <);
    daemon.connection_ending();
.

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();
    interface.new_connection(.address());
.