mirror of
git://git.psyced.org/git/psyced
synced 2024-08-15 03:25:10 +00:00
276 lines
8.1 KiB
C
276 lines
8.1 KiB
C
// $Id: slave.c,v 1.64 2008/03/28 20:05:44 lynx Exp $ // vim:syntax=lpc
|
|
//
|
|
#define TIME_UPDATE_MINWAIT 33 // 33 seconds
|
|
|
|
#include <net.h>
|
|
#include <status.h>
|
|
|
|
virtual inherit NET_PATH "place/storic";
|
|
|
|
protected volatile string master, mastertrail;
|
|
protected volatile int members, servers;
|
|
private volatile int lastup;
|
|
|
|
histClear(a, b, source, vars) { if (b > 49) return ::histClear(a, b, source, vars); }
|
|
|
|
// the flag allows forced update and avoids call_out loops
|
|
#define UPDATE_NOW 0
|
|
#define UPDATE_SOON 1
|
|
#define UPDATE_REMINDER 2
|
|
|
|
qJunction() { return 0; }
|
|
|
|
update(flag) {
|
|
int t;
|
|
unless(master) return;
|
|
t = time() - lastup;
|
|
P2(("update(%O) - %O to go.\n", flag, TIME_UPDATE_MINWAIT - t))
|
|
|
|
if (flag == UPDATE_NOW || t > TIME_UPDATE_MINWAIT) {
|
|
lastup = time();
|
|
sendmsg(master, "_request_link", 0,
|
|
([ "_amount_members": to_string(size()) ]) );
|
|
} else if (flag == UPDATE_SOON)
|
|
call_out(#'update, TIME_UPDATE_MINWAIT+1-t, UPDATE_REMINDER);
|
|
}
|
|
|
|
void create() {
|
|
lastup = time(); // delay linkup by 7 seconds (see below)
|
|
::create();
|
|
}
|
|
|
|
#if 0
|
|
void reset(int again) {
|
|
if (again) update(UPDATE_SOON); // just in case..
|
|
else lastup = time(); // delay linkup by 7 seconds (see below)
|
|
return ::reset(again);
|
|
}
|
|
#endif
|
|
|
|
sIdentification(it) {
|
|
identification = it;
|
|
}
|
|
|
|
sMaster(link, modflag) {
|
|
unless (abbrev("psyc:", link))
|
|
link = "psyc://"+ link +"/"+ psycName();
|
|
mastertrail = master = lower_case(link); // lower_case UNI policy
|
|
identification = link;
|
|
set_context(ME, link);
|
|
// some kinda kludge until the psyc layer gives us the true UNI
|
|
// if (abbrev("psyc://ve.", master)) mastertrail = master[10..];
|
|
// P2(("mastertrail = %O\n", mastertrail))
|
|
//call_out(#'update, 7, UPDATE_NOW);
|
|
update(UPDATE_NOW);
|
|
}
|
|
|
|
mixed isValidRelay(mixed x) { return x == master || x == ME; }
|
|
|
|
msg(source, mc, data, vars) {
|
|
P2(("slave:msg(%O, %O, %O, %O)\n", source, mc, data, vars))
|
|
// if (vars["_context"]) return -1; // may not happen
|
|
// status update from master / identification
|
|
if (master && source == master ||
|
|
identification && source == identification) {
|
|
/* a message from our master / identification to us
|
|
* usually a status update or some other kind of control msg
|
|
* this control msg logic has moved around, but hasn't changed
|
|
*/
|
|
switch(mc) {
|
|
case "_notice_place_topic":
|
|
vSet("topic-user", vars["_nick"]);
|
|
// fall thru
|
|
case "_notice_place_topic_official":
|
|
vSet("topic", vars["_topic"]);
|
|
break;
|
|
case "_notice_place_topic_removed":
|
|
vSet("topic-user", vars["_nick"]);
|
|
break;
|
|
case "_notice_link_topic":
|
|
vSet("topic", vars["_topic"]);
|
|
// fall thru
|
|
case "_notice_link":
|
|
if (vars["_filter_presence"] &&
|
|
to_int(vars["_filter_presence"]) != 0)
|
|
vSet("_filter_presence", source);
|
|
else
|
|
vDel("_filter_presence");
|
|
//m_delete(vars, "_filter_presence");
|
|
break;
|
|
case "_notice_place_topic_removed_official":
|
|
vDel("topic");
|
|
break;
|
|
case "_error_necessary_link_place":
|
|
case "_error_rejected_message_membership":
|
|
// add protection from loops?
|
|
castmsg(ME, "_warning_place_link_lost",
|
|
"Master link [_master] has forgotten about us. Hold on.",
|
|
([ "_master" : master ]) );
|
|
// fall thru
|
|
case "_notice_unlink_restart":
|
|
case "_notice_unlink_restart_complete":
|
|
// update (UPDATE_NOW);
|
|
update (UPDATE_SOON);
|
|
return 1;
|
|
case "_notice_place_history_cleared":
|
|
::histClear(vars["_amount_messages"], 60, source, vars);
|
|
return 1;
|
|
case "_status_place_filter_presence":
|
|
if (vars["_filter_presence"] &&
|
|
to_int(vars["_filter_presence"]) != 0)
|
|
vSet("_filter_presence", source);
|
|
else
|
|
vDel("_filter_presence");
|
|
return 1;
|
|
}
|
|
|
|
if (abbrev("_notice_place_enter", mc)) {
|
|
// master notifies us that _source_relay was allowed
|
|
// to enter - kind of fake
|
|
string relay = vars["_source_relay"];
|
|
m_delete(vars, "_source_relay");
|
|
vars["_nick_place"] = MYNICK;
|
|
return ::msg(relay, mc, data, vars);
|
|
}
|
|
if (abbrev("_notice_place_leave", mc)) {
|
|
string relay = vars["_source_relay"];
|
|
m_delete(vars, "_source_relay");
|
|
vars["_nick_place"] = MYNICK;
|
|
return ::msg(relay, mc, data, vars);
|
|
}
|
|
return castmsg(source, mc, data, vars);
|
|
}
|
|
// someone is sending a message via us.
|
|
// we may send it to the master and if we dont return will pass
|
|
// it on to local msg()
|
|
// TODO: need to do some kind of checks if we want to forward
|
|
// sth for the sender
|
|
if ((!vars["_context"] // should not happen, but...
|
|
// things not to forward
|
|
&& !(abbrev("_request_leave", mc)
|
|
|| abbrev("_request_context_leave", mc))
|
|
// things we want to forward
|
|
||abbrev("_message", mc)
|
|
|| !v("_filter_presence") && (abbrev("_request_enter", mc)
|
|
|| abbrev("_request_context_enter", mc))
|
|
)
|
|
) { // source != master implied above
|
|
|
|
// we let upstream handle it
|
|
// TODO: we _must_ be linked to do this
|
|
// looks like a job for the notorious queue
|
|
//
|
|
// otherwise a slave may send an _request_enter to
|
|
// the master which is silent and should therefore
|
|
// drop the packet.
|
|
// and the user is left alone
|
|
// the master could catch such behaviour... but...
|
|
// complicates things and is more harmful than useful
|
|
//
|
|
// hrmpf. IMHO we should send it via master, if
|
|
// this does not work then debug it!
|
|
// hey, its lynX who told me to do that :)
|
|
#if 0
|
|
sendmsg(master, mc, data, vars + ([
|
|
"_location": query_ip_name(source),
|
|
"_source_relay": ME,
|
|
]), source);
|
|
#else
|
|
sendmsg(identification, mc, data, vars + ([
|
|
// what about peer scheme, host and -port
|
|
// ah, did just that in usercmd sayvars
|
|
"_location": objectp(source) ?
|
|
query_ip_name(source) : source,
|
|
"_source_relay": vars["_source_relay"] || source
|
|
]));
|
|
#endif
|
|
// if (abbrev("_message", mc)) return 1;
|
|
return 1;
|
|
#if 0 // wo war der Sinn von dem Code?
|
|
D3(else D(S("slave:msg from %O master %O, mastertrail %O\n",
|
|
source, master, mastertrail));)
|
|
if (source == master || (vars["_source"] == master &&
|
|
stringp(source) && trail(mastertrail, source))) {
|
|
string relay = vars["_source_relay"];
|
|
|
|
// if this were psyc 1.1, we wouldnt receive messages
|
|
// relayed, but have proper _context. i guess we want
|
|
// to implement both forms and maybe one day disallow
|
|
// one or the other on a per-room basis.
|
|
if (relay) {
|
|
// dieser teil war auskommentiert..
|
|
// was will mir das sagen? ich werde bugs auslösen?
|
|
// jopp
|
|
// vars["_source_relay"] = master;
|
|
// master could spoof local objects
|
|
// source = psyc_object(relay) || relay;
|
|
// geht das? hu?
|
|
vars["_source_relay"] = vars["_source"];
|
|
P2(("slave:msg(%O,%O,%O) relay=%O\n",
|
|
source, mc, data, relay))
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
// hm... can we simply do that?
|
|
return ::msg(source, mc, data, vars);
|
|
}
|
|
|
|
castmsg(source, mc, data, vars) {
|
|
P2(("slave:castmsg(%O, %O, %O, %O)\n",
|
|
source, mc, data, vars))
|
|
|
|
if (member(vars, "_amount_members")) {
|
|
members = to_int(vars["_amount_members"]);
|
|
m_delete(vars, "_amount_members");
|
|
}
|
|
if (member(vars, "_amount_servers")) {
|
|
servers = to_int(vars["_amount_servers"]);
|
|
m_delete(vars, "_amount_servers");
|
|
}
|
|
::castmsg(source, mc, data, vars);
|
|
}
|
|
|
|
enter(source,mc,data,vars) {
|
|
update (UPDATE_SOON);
|
|
return ::enter(source,mc,data,vars);
|
|
}
|
|
leave(source,mc,data,vars) {
|
|
update (UPDATE_SOON);
|
|
return ::leave(source,mc,data,vars);
|
|
}
|
|
|
|
memberInfo(person) {
|
|
unless (members && servers) return ::memberInfo(person);
|
|
unless (person) person = previous_object();
|
|
|
|
sendmsg(person, "_status_place_net_members_amount",
|
|
"[_nick_place] contains [_amount_members] people \
|
|
on [_amount_servers] servers.", ([
|
|
"_nick_place": MYNICK,
|
|
"_amount_members": members,
|
|
"_amount_servers": servers,
|
|
]) );
|
|
return 0;
|
|
}
|
|
|
|
showStatus(verbosity, al, source, mc, data, vars) {
|
|
if (members && master) {
|
|
sendmsg(source, "_status_place_link",
|
|
"Network link to [_link] active.",
|
|
([ "_link": master ]) );
|
|
}
|
|
return ::showStatus(verbosity, al, source, mc, data, vars);
|
|
}
|
|
|
|
qAllowExternal(source, mc) {
|
|
if (source == master) return 1;
|
|
}
|
|
|
|
reboot(reason, restart, pass) {
|
|
if (master) {
|
|
sendmsg(master, "_request_unlink");
|
|
master = 0;
|
|
}
|
|
return ::reboot(reason, restart, pass);
|
|
}
|