unlink detection rewrite - please test this

This commit is contained in:
psyc://psyced.org/~lynX 2011-01-19 22:19:34 +01:00
parent 6b8e138eb4
commit b4867481f4
7 changed files with 70 additions and 36 deletions

View File

@ -525,6 +525,15 @@ static linkSet(service, location, source) {
v("locations")[service] = ([ location ]);
}
register_location(location, ME);
// let me know if you lose the connection to my link!
object circuit = find_target_handler(location);
if (objectp(circuit)) {
P3(("linkSet: registering disc notify for %O from %O.\n",
location, circuit))
circuit -> register_link(ME);
}
// probably should go to the user instead
else P1(("Warning for %O: Location %O will ghost.\n", MYNICK, location))
if (service) sendmsg(source, "_notice_link_service", 0,
([ "_service" : service,
"_location" : location,
@ -551,22 +560,24 @@ static linkSet(service, location, source) {
}
P2(("locations after linkSet: %O\n", v("locations")))
}
static linkDel(service, source, variant) {
linkDel(service, source, variant) {
P3(("linkDel(%O, %O, %O) called in %O!\n", service, source, variant, ME))
string mc = "_notice_unlink";
service = service || 0;
unless (member(v("locations"), service)) {
P3(("linkDel(%O, %O) called in %O: no such candidate!\n",
P4(("linkDel(%O, %O) called in %O: no such candidate!\n",
service, source, ME));
return 0;
}
int n = 0;
foreach(string candidate : v("locations")[service]) {
P4(("linkDel(%O, %O) in %O: unlinking %O ? handler = %O\n",
service, source, ME, candidate, find_target_handler(candidate)));
if ((objectp(source) && find_target_handler(candidate) != source) ||
(source && !objectp(source) && candidate != source)) continue;
P2(("linkDel(%O, %O) called in %O: unlinking %O.\n",
P2(("linkDel(%O, %O) in %O: unlinking %O.\n",
service, source, ME, candidate));
// sLocation?
register_location(candidate, 0);
@ -1049,7 +1060,6 @@ case "_set_password":
if (checkPassword(vars["_password"], vars["_method"], nonce, vars))
#endif
{
string scheme;
mixed *u;
// TODO? add support for integer _service means multiple
@ -1084,8 +1094,11 @@ case "_set_password":
return display;
}
#endif
scheme = v("scheme");
#if 1
#if 0
// no new link should throw out interactives or other links!
// this must be from the days when we had no disconnect notification
// so it would remove ghosts of itself..
// his should be unnecessary by now! --lynX 2011
// <el> in other cases this is done by
// morph. this may not be the very best
// solution, but until person/user is rewritten
@ -1108,13 +1121,13 @@ case "_set_password":
// allows two psyc clients to be logged in
// concurrently and is very suspicious
if (query_once_interactive(ME)
|| (scheme && scheme != "psyc")) {
|| (v("scheme") && v("scheme") != "psyc")) {
// temporary fix for initially created psyc
// users. (they dont have a scheme)
object o;
save();
if (interactive(ME)) {
linkDel();
// linkDel(); doesn't make sense here
remove_interactive(ME);
}
o = named_clone(PSYC_PATH "user", MYNICK);
@ -1172,7 +1185,7 @@ case "_set_password":
// language support for clients..
// done in w() instead.
vars["_INTERNAL_origin"]->sTextPath(v("layout"),
v("language"), scheme);
v("language"), v("scheme"));
#endif
// yeah right..
//unless (interactive()) vSet("host", source);
@ -2637,13 +2650,14 @@ quit(immediate, variant) {
int rc;
P3(("person:QUIT(%O,%O) in %O\n", immediate,variant, ME))
// keeping services running while logging out should be possible.. but
// we currently don't do that -- now we do
linkDel(0, previous_object());
#if 0
#if 1
// keeping services running while logging out should be possible..
// will this unlink all main clients? should it?
linkDel(0); // 0, previous_object()); <- this can be ME and will fail
#else
if (sizeof(v("locations"))) { // this should only trigger at first pass
linkCleanUp();
#if 1 //def PARANOID
# if 1 //def PARANOID
if (sizeof(v("locations"))) {
P1(("%O * Hey, linkCleanUp left us with %O\n",
ME, v("locations")))
@ -2651,7 +2665,7 @@ quit(immediate, variant) {
// breaks when we do
vSet("locations", ([]));
}
#endif
# endif
}
#endif
if (immediate == 1 || (immediate && find_call_out(#'quit) != -1)) { //'

View File

@ -474,9 +474,11 @@ int disconnected(string remaining) {
#endif
// wow.. a sincerely expected disconnect!
if (flags & TCP_PENDING_DISCONNECT) return 1;
#ifndef _flag_disable_report_failure_network_circuit_disconnect
#ifdef _flag_enable_report_failure_network_circuit_disconnect
monitor_report("_failure_network_circuit_disconnect",
object_name(ME) +" · lost PSYC circuit");
#else
P1(("%O disconnected unexpectedly\n", ME))
#endif
return 0; // unexpected
}

View File

@ -19,7 +19,8 @@ inherit PSYC_PATH "circuit";
// keep a list of objects to ->disconnected() when the driver tells us
volatile array(object) disconnect_notifies;
void do_notify_on_disconnect(object user) {
void register_link(object user) {
P4(("disconnect_notifies for %O in %O\n", user, ME))
unless(disconnect_notifies)
disconnect_notifies = ({ });
disconnect_notifies += ({ user });
@ -54,11 +55,10 @@ protected quit() { QUIT }
// self-destruct when the TCP link gets lost
disconnected(remaining) {
P2(( "%O got disconnected.\n", ME))
// emulate disconnected() for net/psyc/user
if (disconnect_notifies) {
foreach (object t : disconnect_notifies)
if (t) t->disconnected();
if (disconnect_notifies) foreach (object t : disconnect_notifies) {
P3(( "%O disconnecting %O\n", ME, t))
if (t) t->link_disconnected();
}
::disconnected(remaining);
QUIT // returns unexpected.. TODO

View File

@ -1,6 +1,7 @@
// $Id: user.c,v 1.15 2008/12/09 19:27:32 lynx Exp $ // vim:syntax=lpc
//
// handler for PSYC clients
// should be a dummy user object since all user objects
// must be able to handle PSYC clients
#include "common.h"
#include <net.h>
@ -12,14 +13,19 @@ logon() {
#ifdef NO_EXTERNAL_LOGINS
return destruct(ME);
#endif
#if 0
// psyc users dont have their own socket, so the driver
// does not call disconnected() for them - this enables the
// psyc socket to do that
if (this_interactive()) this_interactive()->do_notify_on_disconnect(ME);
// basically a good idea, but the wrong place to do this. since we
// want to be notified about any of n possible psyc clients we need
// to do this in linkSet(). --lynX
if (this_interactive()) this_interactive()->register_link(ME);
// connection that is creating us, died while we got here.
// rare, but does indeed happen sometimes.
else return destruct(ME);
// i presume the else case is better handled by disconnected() --lynX
#endif
// no lang support here either
vSet("scheme", "psyc");
return ::logon();
@ -27,10 +33,10 @@ logon() {
// errors only, it says
pr(mc, fmt, a,b,c,d,e,f,g,h) {
#if 1 //def PRO_PATH
if (abbrev("_message",mc)) return;
if (v("location"))
sendmsg(v("location"), mc+"_print", sprintf(fmt, a,b,c,d,e,f,g,h) );
#if 1 //ndef DEVELOPMENT
//if (abbrev("_message",mc)) return;
foreach (string location : v("locations")[0])
sendmsg(location, mc+"_print", sprintf(fmt, a,b,c,d,e,f,g,h) );
#else
// checkVar() still calls pr() .... grmlblmblm TODO
raise_error("pr() called\n");

View File

@ -183,9 +183,14 @@ int disconnected(string remaining) {
#endif
// wow.. a sincerely expected disconnect!
if (flags & TCP_PENDING_DISCONNECT) return 1;
#ifdef _flag_enable_report_failure_network_circuit_disconnect
monitor_report("_failure_network_circuit_disconnect",
object_name(ME) +" · lost PSYC circuit");
return 0; // unexpected
#else
P1(("%O disconnected unexpectedly\n", ME))
#endif
return 0; // unexpected
}
// respond to the first empty packet

View File

@ -15,7 +15,7 @@ inherit NET_PATH "spyc/circuit";
// keep a list of objects to ->disconnected() when the driver tells us
volatile array(object) disconnect_notifies;
void do_notify_on_disconnect(object user) {
void register_link(object user) {
unless(disconnect_notifies)
disconnect_notifies = ({ });
disconnect_notifies += ({ user });
@ -54,7 +54,7 @@ disconnected(remaining) {
// emulate disconnect() for net/psyc/user
if (disconnect_notifies) {
foreach (object t : disconnect_notifies)
if (t) t->disconnected();
if (t) t->link_disconnected();
}
rc = ::disconnected(remaining);
destruct(ME);

View File

@ -1760,16 +1760,23 @@ quit(immediate, variant) {
return ::quit(immediate, variant);
}
link_disconnected() {
P3(("link_disconnected in %O from %O\nlocations: %O\n", ME, previous_object(), v("locations")))
linkDel(0, previous_object());
// if there are any catch-all connections left don't quit,
// just delete link
if (member(v("locations"), 0) && sizeof(v("locations")[0])) return;
// unless we have a legacy client, let's get outta here
unless (interactive(ME)) disconnected();
}
// driver calls us here to tell us we lost the connection
// if you don't like this default behaviour, override it
//
// we also call this manually from _request_unlink_disconnect
disconnected(remainder) {
P2(("disconnected(%O) called in %O\nlocations: %O\n", remainder, ME, v("locations")))
// if there are any catch-all connections left don't quit, just delete link
if (member(v("locations"), 0) && sizeof(v("locations")[0]) > 1)
return linkDel(0, previous_object());
P2(("disconnected(%O) in %O from %O\n",
remainder, ME, previous_object()))
// user did not detach his client properly. we'll make a wild guess
// at how many messages he may have missed - enough to make the user
// check the lastlog if that's not enough.