/* * 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(); }