lpmoo-1.2/etc/
lpmoo-1.2/mudlib/
lpmoo-1.2/mudlib/etc/
lpmoo-1.2/mudlib/include/
lpmoo-1.2/mudlib/include/moo/
lpmoo-1.2/mudlib/lpc/
lpmoo-1.2/mudlib/std/auto/
lpmoo-1.2/mudlib/std/bfuns/
/*
 * 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();
}