psyced/world/net/psyc/routerparse.i

288 lines
6.9 KiB
OpenEdge ABL

// vim:foldmethod=marker:syntax=lpc:noexpandtab
// $Id: routerparse.i,v 1.15 2008/02/06 12:16:16 lynx Exp $
//
// THIS FILE IS FORK ONLY, thus currently not in use.
//
// TODO: both parsers need to croak on incoming _INTERNAL vars!!
#ifdef FORK // {{{
// MMP PARSER - parses the routing header of PSYC, also known as MMP.
//
// THIS IS THE INNOVATIVE RID'N'SAGE PARSER REWRITE
// they wanted to have it completely seperate from the original parse.i
// so *keep* it seperate in its own file, routerparse.i!
//
// unfortunately it handles context counters in a non-universal way.. TODO
// also it misses support for _trust
// this flag should enable forward-checks of dns resolutions..
// currently we don't have that, so this flag actually disables
// use of unprooven resolved hostnames and reduces everything to
// ip numbers.
//#define HOST_CHECKS
#ifndef PSYC_LIST_SIZE_LIMIT
# define PSYC_LIST_SIZE_LIMIT 404
#endif
// just the plain ip number of the remote host
// ^^ glatte lüge!
volatile string peerhost;
#if 0 //defined(PSYC_TCP) && __EFUN_DEFINED__(strrstr)
volatile string peerdomain;
#endif
// remote port number
volatile int peerport;
// unresolved-ip or ip:port
volatile string peeraddr;
// holds last ip we were connected to
volatile string peerip;
// how much can we trust the content of this packet?
volatile int ctrust;
volatile closure _deliver;
volatile object _psyced;
#define PSYCED (_psyced ? _deliver : (_psyced = DAEMON_PATH "psyc" -> load(), _deliver = symbol_function("deliver", _psyced)))
// current variables (":"), permanent variables ("=", "+", "-")
//
volatile mapping cvars = 0, pvars = ([ "_INTERNAL_origin" : ME ]), nvars = 0;
//
// a distinction between mmp and psyc-vars should be made
// current method and incoming buffer
volatile string buffer;
// cache of patched remote uniforms
volatile mapping patches = ([]);
// parsing helpers..
// MMP
volatile string lastvar, lastmod, checkpack, origin_unl;
volatile mixed lastvalue;
// list parsing helpers..
volatile array(mixed) list;
volatile mapping hash;
volatile int l = 0;
//volatile int pongtime; // TODO: FORK is missing the PONG
# ifndef PSYC_TCP
// resolved UNL of remote server (psyc://hostname or psyc://hostname:port)
volatile string netloc;
# define QUIT return 0;
# endif
// prototype definition for #'getdata
getdata(string a);
restart();
#ifdef __LDMUD__
# define SCANFIT (sscanf(a, "%1.1s%s%t%s", mod, vname, vvalue) || sscanf(a, "%1.1s%s", mod, vname))
#else
# define SCANFIT (sscanf(a, "%1s%s%*[ \t]%s", mod, vname, vvalue) || sscanf(a, "%1s%s", mod, vname))
#endif
#define SPLITVAL(val) \
unless (sscanf(val, "%s %s", val, vdata)) vdata = 0
// sollte es wirklich ein space sein? hmmm.. %t ist sowieso zu grob..
# ifndef PSYC_TCP
# define UDPRETURN(x) return x;
# define ERROR(m) UDPRETURN(0)
# else
# define UDPRETURN(x)
# define ERROR(m) { croak("_error_syntax_broken", "Failed in parsing " \
"[_modifier], closing connection.", \
([ "_modifier" : intp(m) \
? to_string(({m})) \
: to_string(m) ])); \
monitor_report("_error_syntax_broken", \
sprintf("MMP parsing failed. closing connection: %O", ME)); \
destruct(ME); \
}
# endif
# ifdef PSYC_TCP
void
# else
mixed
# endif
mmp_parse(string a) {
string mod, vname, vvalue;
P3(("MMP>> %O\n", a))
if (sizeof(a)) switch(a[0]) {
case '=':
case '+':
case '-':
# ifndef PSYC_TCP
// hier könnten wir jedenfalls nen error ausgeben
// udp und state ist keine gute kombination
# endif
case ':':
unless (2 <= sscanf(a, "%1.1s%s%t%s", mod, vname, vvalue)
|| 2 == sscanf(a, "%1.1s%s", mod, vname)) {
ERROR(a[0]);
}
if (vvalue == "") vvalue = 0;
P3(("G: %O %O %O\n", mod, vname, vvalue))
unless (vname) {
unless (lastvar && a[0] != '-' && lastmod
&& lastmod[0] == a[0]) ERROR(a[0]);
if (pointerp(lastvalue)) {
lastvalue += ({ vvalue });
} else {
lastvalue = ({ lastvalue, vvalue });
}
return;
}
break;
case '\t':
unless (lastvar) {
ERROR(a[0]);
}
if (pointerp(lastvalue))
lastvalue[<1] += "\n"+a[1..];
lastvalue += "\n"+a[1..];
return;
default:
ERROR(a[0]);
}
if (lastmod) switch(lastmod[0]) {
# ifdef PSYC_TCP
case '=':
unless (lastvalue) {
m_delete(pvars, lastvar);
break;
}
if (lastvar == "_understand_modules") {
gotiate(lastvalue);
} else if (lastvar == "_use_modules") {
negotiate(lastvalue);
}
pvars[lastvar] = lastvalue;
# endif
case ':':
if (lastvalue)
cvars[lastvar] = lastvalue;
else
m_add(nvars, lastvar);
break;
# ifdef PSYC_TCP
case '+':
_augment(pvars, lastvar, lastvalue);
if (lastvar == "_understand_modules") {
gotiate(lastvalue);
} else if (lastvar == "_use_modules") {
negotiate(lastvalue);
}
break;
case '-':
_diminish(pvars, lastvar, lastvalue);
break;
# endif
}
unless (sizeof(a)) {
# ifdef PSYC_TCP
next_input_to(#'getdata);
# endif
// TODO init cvars = copy(pvars)
cvars = (pvars + cvars) - nvars;
UDPRETURN(2)
} else if (a[0] == '.') {
# ifdef PSYC_TCP
next_input_to(#'mmp_parse);
# endif
restart();
UDPRETURN(1)
} else {
lastmod = mod;
lastvar = vname;
lastvalue = vvalue;
# ifdef PSYC_TCP
next_input_to(#'mmp_parse);
# endif
UDPRETURN(1)
}
# ifdef PSYC_TCP
if (timeoutPending) remove_call_out(#'quit);
# endif
}
getdata(string a) {
P4(("GETDATA: %O\n", a));
if (a != ".") {
if (buffer == "")
buffer = a;
else
buffer += "\n"+a;
# ifdef PSYC_TCP
next_input_to(#'getdata);
# endif
} else {
array(mixed) u;
string t = cvars["_context"] || cvars["_source"];
# ifdef PSYC_TCP
// let's do this before we deliver in case we run into
// a runtime error (but it's still better to fix it!)
next_input_to(#'mmp_parse);
# endif
if (!t || trustworthy > 5) {
funcall(PSYCED, 0, 0, ME, peeraddr, peerhost,
buffer, cvars);
} else unless (u = parse_uniform(t)) {
P1((">> parse_uniform %O %O\n", t, u))
croak("_error_invalid_uniform",
"Looks like a malformed URL to me.");
QUIT
} else dns_resolve(u[UHost], PSYCED, peerip, ME, peeraddr,
u[UHost], buffer, cvars);
restart();
}
return 1;
}
restart() {
// delete temporary variables for next msg
cvars = ([ "_INTERNAL_trust" : trustworthy ]);
nvars = m_allocate(0, 1);
lastvalue = lastvar = lastmod = 0;
// delete other stuff too
buffer = "";
ctrust = trustworthy;
return 1;
}
# ifdef PSYC_TCP
startParse(string a) {
if (a == ".") restart();
else {
croak("_error_syntax_initialization",
"The protocol begins with a dot on a line by itself.");
QUIT
}
next_input_to(#'mmp_parse);
}
# endif
// also overrides createUser in net/server.c
createUser(string nick) {
D2(D("creating " PSYC_PATH "user for "+ nick +"\n");)
return named_clone(PSYC_PATH "user", nick);
}
qOrigin() { return origin_unl; }
sOrigin(origin) { P3(("sOrigin(%O) (%O) in %O\n", origin, origin_unl, ME))
unless (origin_unl) origin_unl = origin; }
#endif /* FORK }}} */