/
CDC-1.1/
parent $misc
object $network_root

var $root dbref 'network_root
var $root child_index 4
var $root fertile 0
var $root manager $network_root
var $root owned [$network_root]
var $root owners [$network_root]
var $root writable []
var $root readable ['parameters, 'methods, 'code]
var $root inited 1
var $network_root buffer `[]
var $network_root ip ""
var $network_root hostname ""
var $network_root socket 0
var $network_root port 0
var $network_root active 0

method init_network_root
    (> .perms(caller(), $root) <);
    (> .reset_connection() <);
.

method uninit_network_root
    (> .perms(caller(), $root) <);
    (> .reset_connection() <);
.

method reset_connection
    // reset parameters to their default values
    (> .perms(caller(), $network_root) <);
    disconnect();
    buffer = `[];
    ip = "";
    hostname = "";
    port = 0;
    socket = 0;
    active = 0;
.

method failed
    arg socket;
    
    // called by the server when unable to make a connection.
    if ((sender() != 0) || (sender() != this()))
        throw(~perm, "Sender is not the server");
    .receive("CONNECTION FAILED; socket: " + tostr(socket), 'connection_failed);
    
    // we weren't ever connected, but this will reset us.
    (| .close() |);
.

method open
    arg addr, port;
    
    // open a connection to <addr> on <port>
    (> .perms(sender()) <);
    if (active)
        throw(~engaged, (.namef('ref)) + " is currently engaged.");
    
    // reset for good measure
    (> .reset_connection() <);
    
    // set the active bit.
    .set_active(1);
    
    // set the ip or addr, if children want they can redefine .set_*
    // to check for hostname() or whatever.
    if (toint(addr))
        .set_ip(addr);
    else
        .set_hostname(addr);
    .set_port(port);
    
    // try to open it
    (> $sys.connect(addr, port, this()) <);
.

method close
    // close the connection
    (> .perms(sender()) <);
    (> .reset_connection() <);
    .receive("Connection Closed.", 'connection_closed);
.

method connect
    arg [args];
    
    // called by the server when a successful connection is made
    if (sender() != 0)
        throw(~perm, "Sender is not the server");
    .receive("CONNECTION ESTABLISHED; " + ($data.unparse(args)), 'connection_established);
    
    // This is ugly, will be fixed when networking is fixed in the driver
    if (type(args[1]) == 'integer) {
        socket = args[1];
    } else {
        ip = args[1];
        socket = args[2];
        hostname = hostname(ip);
    }
.

method disconnect
    arg [args];
    
    if ((sender() != 0) || (sender() != this()))
        throw(~perm, "Sender is not the server");
    (> .close() <);
.

method receive
    arg line, status;
    
    // receive a string, called by .parse()
.

method parse
    arg incoming;
    var lines, line;
    
    // called by the server with an incoming buffer
    if (sender() != 0)
        throw(~perm, "Sender and caller are not the server");
    lines = buffer_to_strings(buffer_append(buffer, incoming));
    buffer = lines[listlen(lines)];
    lines = sublist(lines, 1, listlen(lines) - 1);
    for line in (lines)
        .receive(line, 'external);
.

method send
    arg what;
    var line;
    
    // send off a string or list of strings.  Calls .echo()
    if (type(what) == 'list) {
        for line in (what)
            .send(line);
    } else {
        .echo(what, 'string);
    }
.

method echo
    arg what, type;
    
    // send off a string or buffer
    (> .perms(sender()) <);
    switch (type) {
        case 'string:
            (> echo(buffer_from_strings([what])) <);
        case 'buffer:
            (> echo(what) <);
    }
.

method bind
    arg port, receiver;
    
    // bind to a port
    (> .perms(sender(), 'this) <);
    (> $sys.bind(port, receiver) <);
.

method unbind
    arg port;
    
    // unbind from a port
    (> .perms(sender(), 'this) <);
    (> $sys.unbind(port) <);
.

method ip
    (> .perms(sender(), 'trusts) <);
    return ip;
.

method hostname
    (> .perms(sender(), 'trusts) <);
    return hostname;
.

method port
    (> .perms(sender(), 'trusts) <);
    return port;
.

method socket
    (> .perms(sender(), 'trusts) <);
    return socket;
.

method active
    (> .perms(sender(), 'trusts) <);
    return active;
.

method set_ip
    arg str;
    
    (> .perms(sender(), 'this) <);
    ip = str;
.

method set_hostname
    arg str;
    
    (> .perms(sender(), 'this) <);
    hostname = str;
.

method set_port
    arg int;
    
    (> .perms(sender(), 'this) <);
    port = int;
.

method set_socket
    arg int;
    
    (> .perms(sender(), 'this) <);
    socket = int;
.

method set_active
    arg bit;
    
    (> .perms(sender(), 'this) <);
    active = bit;
.