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

View File

@ -474,9 +474,11 @@ int disconnected(string remaining) {
#endif #endif
// wow.. a sincerely expected disconnect! // wow.. a sincerely expected disconnect!
if (flags & TCP_PENDING_DISCONNECT) return 1; 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", monitor_report("_failure_network_circuit_disconnect",
object_name(ME) +" · lost PSYC circuit"); object_name(ME) +" · lost PSYC circuit");
#else
P1(("%O disconnected unexpectedly\n", ME))
#endif #endif
return 0; // unexpected 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 // keep a list of objects to ->disconnected() when the driver tells us
volatile array(object) disconnect_notifies; 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) unless(disconnect_notifies)
disconnect_notifies = ({ }); disconnect_notifies = ({ });
disconnect_notifies += ({ user }); disconnect_notifies += ({ user });
@ -54,11 +55,10 @@ protected quit() { QUIT }
// self-destruct when the TCP link gets lost // self-destruct when the TCP link gets lost
disconnected(remaining) { disconnected(remaining) {
P2(( "%O got disconnected.\n", ME))
// emulate disconnected() for net/psyc/user // emulate disconnected() for net/psyc/user
if (disconnect_notifies) { if (disconnect_notifies) foreach (object t : disconnect_notifies) {
foreach (object t : disconnect_notifies) P3(( "%O disconnecting %O\n", ME, t))
if (t) t->disconnected(); if (t) t->link_disconnected();
} }
::disconnected(remaining); ::disconnected(remaining);
QUIT // returns unexpected.. TODO 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 // $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 "common.h"
#include <net.h> #include <net.h>
@ -12,14 +13,19 @@ logon() {
#ifdef NO_EXTERNAL_LOGINS #ifdef NO_EXTERNAL_LOGINS
return destruct(ME); return destruct(ME);
#endif #endif
#if 0
// psyc users dont have their own socket, so the driver // psyc users dont have their own socket, so the driver
// does not call disconnected() for them - this enables the // does not call disconnected() for them - this enables the
// psyc socket to do that // 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. // connection that is creating us, died while we got here.
// rare, but does indeed happen sometimes. // rare, but does indeed happen sometimes.
else return destruct(ME); else return destruct(ME);
// i presume the else case is better handled by disconnected() --lynX
#endif
// no lang support here either // no lang support here either
vSet("scheme", "psyc"); vSet("scheme", "psyc");
return ::logon(); return ::logon();
@ -27,10 +33,10 @@ logon() {
// errors only, it says // errors only, it says
pr(mc, fmt, a,b,c,d,e,f,g,h) { pr(mc, fmt, a,b,c,d,e,f,g,h) {
#if 1 //def PRO_PATH #if 1 //ndef DEVELOPMENT
if (abbrev("_message",mc)) return; //if (abbrev("_message",mc)) return;
if (v("location")) foreach (string location : v("locations")[0])
sendmsg(v("location"), mc+"_print", sprintf(fmt, a,b,c,d,e,f,g,h) ); sendmsg(location, mc+"_print", sprintf(fmt, a,b,c,d,e,f,g,h) );
#else #else
// checkVar() still calls pr() .... grmlblmblm TODO // checkVar() still calls pr() .... grmlblmblm TODO
raise_error("pr() called\n"); raise_error("pr() called\n");

View File

@ -183,9 +183,14 @@ int disconnected(string remaining) {
#endif #endif
// wow.. a sincerely expected disconnect! // wow.. a sincerely expected disconnect!
if (flags & TCP_PENDING_DISCONNECT) return 1; if (flags & TCP_PENDING_DISCONNECT) return 1;
#ifdef _flag_enable_report_failure_network_circuit_disconnect
monitor_report("_failure_network_circuit_disconnect", monitor_report("_failure_network_circuit_disconnect",
object_name(ME) +" · lost PSYC circuit"); 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 // 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 // keep a list of objects to ->disconnected() when the driver tells us
volatile array(object) disconnect_notifies; volatile array(object) disconnect_notifies;
void do_notify_on_disconnect(object user) { void register_link(object user) {
unless(disconnect_notifies) unless(disconnect_notifies)
disconnect_notifies = ({ }); disconnect_notifies = ({ });
disconnect_notifies += ({ user }); disconnect_notifies += ({ user });
@ -54,7 +54,7 @@ disconnected(remaining) {
// emulate disconnect() for net/psyc/user // emulate disconnect() for net/psyc/user
if (disconnect_notifies) { if (disconnect_notifies) {
foreach (object t : disconnect_notifies) foreach (object t : disconnect_notifies)
if (t) t->disconnected(); if (t) t->link_disconnected();
} }
rc = ::disconnected(remaining); rc = ::disconnected(remaining);
destruct(ME); destruct(ME);

View File

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