/*
* NAME: outbound.c
* DESCRIPTION: connection object specialized for outbound connections
*/
inherit "/obj/binary";
# include <moo/verb.h>
private int tcp_port; /* TCP port of remote connection */
private int flags; /* special outbound flags */
# define F_OPENED 0x01 /* onc() succeeded? */
/*
* NAME: boot()
* DESCRIPTION: lose the connection without any feedback
*/
varargs
void boot(string message)
{
::boot();
}
/*
* NAME: seed_onc()
* DESCRIPTION: prepare to be connected to a remote host via onc()
*/
void seed_onc(JS_PROTO, mixed *jumpstack, string host, int port)
{
susp_data = ({ JS_DATA(bjump), jumpstack });
tcp_port = port;
call_out("connect1", 0, host);
}
/*
* NAME: unseed()
* DESCRIPTION: the suspended read()/onc() task was killed
*/
void unseed(void)
{
::unseed();
if (! (flags & F_OPENED))
boot();
}
/*
* NAME: do_onc()
* DESCRIPTION: return from open_network_connection()
*/
static
void do_onc(MOOVAL res)
{
mixed *stack, *info, *js;
stack = susp_data[0];
info = susp_data[1];
js = susp_data[4];
susp_data = 0;
global->task_started(info[I_TASKID]);
PUSH(res);
call_other(js[1], js[2], js[3]...);
}
/*
* NAME: connect2()
* DESCRIPTION: initiate connection to resolved IP address
*/
static
void connect2(string ip, int port)
{
if (catch(DRIVER->connect(this_object(), ip, port, "tcp")))
{
call_out("destruct", 1);
do_onc(ERR(E_INVARG));
}
}
/*
* NAME: connect1()
* DESCRIPTION: resolve hostname, call connect2()
*/
static
void connect1(string host)
{
string ip;
switch (ip = DNS->get_addr(host, "resolved_name"))
{
case 0:
/* nameserver not available */
do_onc(ERR(E_QUOTA));
return;
case "":
/* nameserver is looking up */
return;
default:
/* nameserver had IP in cache */
connect2(ip, tcp_port);
return;
}
}
/*
* NAME: resolved_name()
* DESCRIPTION: nameserver returned a resolved name
*/
void resolved_name(string ip)
{
if (ip == 0)
do_onc(ERR(E_INVARG));
else
connect2(ip, tcp_port);
}
/*
* NAME: get_connection_name()
* DESCRIPTION: return a descriptive string for this connection
*/
string get_connection_name(void)
{
return (string) pfd + " to " +
((ip_name && strlen(ip_name)) ? ip_name : ip_number) +
", port " + (string) tcp_port;
}
/*
* NAME: open()
* DESCRIPTION: called by DGD when the connection is established
*/
static
void open(void)
{
init("CONNECT");
flags |= F_OPENED;
do_onc(OBJ(player_id));
}
/*
* NAME: cancel_susp()
* DESCRIPTION: rid susp_data (connection closed)
*/
static
void cancel_susp(void)
{
if (susp_data && ! (flags & F_OPENED))
call_out("do_onc", 0, ERR(E_INVARG));
else
::cancel_susp();
}