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

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

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

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

method reset_connection
    // reset parameters to their default values
    (> .perms(caller(), $network) <);
    close_connection();
    buffer = `[];
    line_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.open_connection(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 = $sys.hostname(ip);
    }
.

method disconnect
    arg [args];
    
    if (sender() != 0)
        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, index;
    
    // called by the server with an incoming buffer
    if (sender())
        throw(~perm, "Sender and caller are not the server");
    lines = buffer_to_strings(buffer_append(buffer, incoming));
    index = listlen(lines);
    buffer = lines[index];
    lines = delete(lines, index);
    line_buffer = [@line_buffer, @lines];
    while (line_buffer) {
        line = line_buffer[1];
        line_buffer = delete(line_buffer, 1);
        (| .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_port
    arg port, receiver;
    
    // bind to a port
    (> .perms(sender(), 'this) <);
    (> $sys.bind_port(port, receiver) <);
.

method unbind_port
    arg port;
    
    // unbind from a port
    (> .perms(sender(), 'this) <);
    (> $sys.unbind_port(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;
.