mirror of
git://git.psyced.org/git/psyced
synced 2024-08-15 03:25:10 +00:00
let the past begone in cvs land. welcome to igit igit!
This commit is contained in:
commit
4e601cf1c7
509 changed files with 77963 additions and 0 deletions
431
world/net/psyc/library.i
Normal file
431
world/net/psyc/library.i
Normal file
|
@ -0,0 +1,431 @@
|
|||
// vim:foldmethod=marker:syntax=lpc:noexpandtab
|
||||
// $Id: library.i,v 1.170 2008/03/29 20:05:32 lynx Exp $
|
||||
|
||||
#include <psyc.h>
|
||||
// #include "../base64.i"
|
||||
#define QUIT destruct(ME); return 1;
|
||||
|
||||
#if SYSTEM_CHARSET != "UTF-8"
|
||||
# echo "FIXME: PSYC will be not be rendered in UTF-8."
|
||||
#endif
|
||||
|
||||
volatile mapping obj2unl = ([]);
|
||||
volatile mapping unl2obj = ([]);
|
||||
// global location to identification resolver
|
||||
volatile mapping unl2uni = ([]);
|
||||
|
||||
varargs void register_location(mixed unl, vamixed uni, vaint unsafe) {
|
||||
PROTECT("REGISTER_LOCATION")
|
||||
if (uni) {
|
||||
if (unsafe && unl2uni[unl]) {
|
||||
P1(("register_location denied: %O says it is %O, but that is already registered for %O\n", uni, unl, unl2uni[unl]))
|
||||
return;
|
||||
}
|
||||
unl2uni[unl] = uni;
|
||||
}
|
||||
else m_delete(unl2uni, unl);
|
||||
}
|
||||
|
||||
/** finds the _identification for a network source. if it cannot find
|
||||
** the information in the cache, and a second argument is given with
|
||||
** the _identification claimed by the source, that _identification
|
||||
** will be asked for confirmation via PSYC. the result will obviously
|
||||
** be available only at a later time. there is no callback function
|
||||
** to this purpose. this function will ONLY return an identification
|
||||
** when it is effectively different from the provided source.
|
||||
** when a source is its own identification, this returns to avoid
|
||||
** any extra processing. maybe one day we will return 1 if that's
|
||||
** useful in any way, but you can check source == givenUNI yourself.
|
||||
** the reason why the variable is called givenUNI and not identification
|
||||
** is because a client may very well claim to be someone and actually not
|
||||
** be that person. we are not sure about identification before the
|
||||
** _request_authentication has returned.
|
||||
*/
|
||||
// this code is used intensely in FORK mode, whereas in !FORK,
|
||||
// since entity.c, the givenUNI is never passed, thus inactive.
|
||||
// unl2uni is only being used for local users' clients, not remotes
|
||||
//
|
||||
varargs mixed lookup_identification(mixed source, vamixed givenUNI) {
|
||||
PROTECT("LOOKUP_IDENTIFICATION")
|
||||
P2(("lookup_identification %O (%O) in %O\n", source, givenUNI, unl2uni))
|
||||
if (member(unl2uni, source)) return unl2uni[source];
|
||||
// ask a remote uni, but don't wait to complete
|
||||
if (givenUNI && source) {
|
||||
unl2uni[source] = 0; // ensures that we don't get here twice
|
||||
// now and in future always return 0 to avoid extra
|
||||
// processing of
|
||||
if (givenUNI == source) return 0;
|
||||
P1(("%O sending _request_authentication to %O for %O\n",
|
||||
ME, givenUNI, source))
|
||||
#ifndef __PIKE__ // TPD
|
||||
sendmsg(givenUNI, "_request_authentication", 0,
|
||||
([ "_location" : source ]));
|
||||
#endif
|
||||
}
|
||||
// we could look again ;)
|
||||
//if (unl2uni[source]) return unl2uni[source];
|
||||
return 0;
|
||||
}
|
||||
|
||||
varargs string psyc_name(mixed source, vastring localpart) {
|
||||
string s;
|
||||
|
||||
if (s = obj2unl[source]) return s;
|
||||
#if DEBUG > 0
|
||||
if (stringp(source))
|
||||
raise_error("psyc_name called for string "+ source+ "\n");
|
||||
#else
|
||||
if (stringp(source)) return source;
|
||||
#endif
|
||||
#ifdef PARANOID
|
||||
unless (objectp(source)) return 0;
|
||||
#endif
|
||||
unless (s = localpart) {
|
||||
if (s = source->psycName()) {
|
||||
if (abbrev("mailto:", s)) {
|
||||
unl2obj[s] = source;
|
||||
return obj2unl[source] = s;
|
||||
}
|
||||
} else s = file_name(source);
|
||||
}
|
||||
//
|
||||
// since this is an outgoing UNL and we do not do
|
||||
// virtual psyc hosting we should be
|
||||
// allowed to leave out the myUNL here.
|
||||
// since we need to recognize ourselves in _context messages
|
||||
// even if our _source has been repatched, we need to know
|
||||
// all our "canonical" names. so this isn't even enough.
|
||||
// we probably need to our canonical hostname: myUNLCN.
|
||||
//
|
||||
#ifndef __HOST_IP_NUMBER__
|
||||
// if (myUNLIP)
|
||||
#endif
|
||||
// unl2obj[myUNLIP +"/"+ s] = source;
|
||||
// why store it with an ip? nobody uses that anyway!?
|
||||
// is it being used anywhere in the parser? naaah.
|
||||
s = myUNL + s;
|
||||
unl2obj[s] = source;
|
||||
return obj2unl[source] = s;
|
||||
}
|
||||
|
||||
object psyc_object(string uniform) {
|
||||
P3(("psyc_object(%O) in %O\n", uniform, unl2obj))
|
||||
return unl2obj[uniform];
|
||||
}
|
||||
|
||||
#ifndef FORK
|
||||
object find_psyc_object(array(mixed) u) {
|
||||
string t, r, svc, user;
|
||||
object o;
|
||||
|
||||
user = u[UUser];
|
||||
r = u[UResource];
|
||||
if (r && strlen(r)) {
|
||||
#if __EFUN_DEFINED__(trim)
|
||||
# include <sys/strings.h>
|
||||
r = trim(r, TRIM_RIGHT, '/');
|
||||
#else
|
||||
while (char_from_end(r, 1) == '/') r = slice_from_end(r, 0, 2);
|
||||
#endif
|
||||
if (strlen(r)) switch(r[0]) {
|
||||
case '^':
|
||||
case '~':
|
||||
if (user) {
|
||||
// croak("_error_invalid_uniform_user_duplicate",
|
||||
// "Two users in uniform not allowed here.");
|
||||
// QUIT
|
||||
return 0; // TODO!
|
||||
}
|
||||
user = r[1..];
|
||||
break;
|
||||
case '$':
|
||||
// target wird auf serv/args gesetzt
|
||||
// weiss noch nicht ob das gut ist
|
||||
t = r[1..];
|
||||
unless (sscanf(t, "%s/%s", svc, r))
|
||||
svc = t;
|
||||
//P3(("find_service: %O for %O(%O)\n", o, svc, r))
|
||||
if (o = find_service(lower_case(svc)))
|
||||
break;
|
||||
// unless (user) {
|
||||
// croak("_failure_unavailable_service",
|
||||
// "No service '[_service]' available here.", ([ "_service" : svc ]) );
|
||||
// return restart();
|
||||
// }
|
||||
return 0; // TODO!
|
||||
#ifndef __PIKE__
|
||||
case '@':
|
||||
// t[0..0] = PLACE_PATH;
|
||||
r = PLACE_PATH + lower_case(r[1..]);
|
||||
if (o = find_object(r)) break;
|
||||
// should check for legal name instead
|
||||
// of catch. TODO
|
||||
catch(o = r -> load());
|
||||
if (objectp(o)) break;
|
||||
// fall thru
|
||||
#endif
|
||||
default:
|
||||
o = find_object(r);
|
||||
D2( if(!o)
|
||||
D("OBJECT NOT FOUND: "+ r +"\n"); )
|
||||
}
|
||||
}
|
||||
else unless (user) {
|
||||
//return 0; // return SERVER_UNI !?
|
||||
return find_target_handler("/");
|
||||
}
|
||||
if (!objectp(o) && user) {
|
||||
// psyc/parse used to do this here
|
||||
o = summon_person(user); //, PSYC_PATH "user");
|
||||
P2(("%O summoning %O: %O\n", ME, user, o))
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
#ifndef __PIKE__
|
||||
// library transmits udp packets itself
|
||||
#include "edit.i"
|
||||
#endif
|
||||
|
||||
// target is lowercased already
|
||||
int psyc_sendmsg(mixed target, string mc, mixed data, mapping vars,
|
||||
int showingLog, mixed source, array(mixed) u) {
|
||||
string sname, host, buf, room;
|
||||
int port, usesrv = 1;
|
||||
object o;
|
||||
mixed t;
|
||||
|
||||
unless (u[UHost]) {
|
||||
#ifndef __PIKE__ // TPD
|
||||
sendmsg(source, "_failure_unsupported_notation_location",
|
||||
"PSYC server-independent uniform network "
|
||||
"identificators not implemented yet.", 0, 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#if DEBUG > 0
|
||||
unless (stringp(mc)) {
|
||||
P0(("psyc_sendmsg got mc == %O from %O.\n"
|
||||
"probably a mistake when converting a walk_mapping.\n",
|
||||
mc, previous_object()))
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
sname = objectp(source) ? psyc_name(source) : sname;
|
||||
// host = lower_case(u[UHostPort]);
|
||||
// unless (u[URoot]) u[URoot] = "psyc://"+host;
|
||||
|
||||
// TODO: vars should be enforced system-wide
|
||||
unless (mappingp(vars)) vars = ([ ]);
|
||||
#ifndef FORK
|
||||
// seid ihr euch wirklich sicher, dass ihr diese zeile entfernen wollt?
|
||||
vars["_target"] = target;
|
||||
// <lynX> this could help protect against sources who destruct while
|
||||
// the message is in the queue. is it being used or is it okay to do
|
||||
// this operation at enqueing time? in fact the templates who use it
|
||||
// get it from psyctext() which resolves _source as source.. so this
|
||||
// here should not be necessary.. then again we just calculated it
|
||||
// so we don't want it to be calculated again later.. so we should
|
||||
// rather adapt the other spots where it's used rather than here..
|
||||
// after all it's mostly speed improvements.. no big thing.. TODO
|
||||
vars["_source"] = sname;
|
||||
#endif
|
||||
unless (port = u[UPort]) port = u[UTransport] == "s" ?
|
||||
PSYCS_SERVICE : PSYC_SERVICE;
|
||||
else {
|
||||
usesrv = 0;
|
||||
if (port < 0) {
|
||||
P2(("Minusport in %O or %O, _failure to %O || %O\n",
|
||||
target, u[UHost], vars["_context"], source))
|
||||
#ifndef __PIKE__ // TPD
|
||||
sendmsg(vars["_context"] || source,
|
||||
"_failure_network_connect_invalid_port",
|
||||
"No connectable port known for [_source_relay].",
|
||||
([ "_source_relay" : target || u[UHost] ]), ME);
|
||||
// ME shouldn't be necessary! TODO
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
host = lower_case(u[UHost]);
|
||||
if (query_udp_port() == port && is_localhost(host)) {
|
||||
o = find_psyc_object(u);
|
||||
// cache the resulting object for the url
|
||||
if (o) {
|
||||
// currently find_psyc_object returns 0 for the
|
||||
// local root, thus register_target messes up next. ouch.
|
||||
P1(("psyc_sendmsg registering target %O for %O found through %O\n",
|
||||
target, o, u))
|
||||
register_target(target, o);
|
||||
}
|
||||
#ifndef __PIKE__ // TPD
|
||||
return sendmsg(o, mc, data, vars, source);
|
||||
#endif
|
||||
// or deliver directly?
|
||||
}
|
||||
// since the local URoot is in targets and pointing to net/root
|
||||
// we have to get here *after* making sure we are not addressing
|
||||
// a local entity.
|
||||
P3(("looking for %O(%O) in %O..\n", target, u[UHostPort], targets))
|
||||
// if (member(targets, t2 = u[URoot])) {
|
||||
// t = targets[t2];
|
||||
// if (t) {
|
||||
if (t = targets[u[URoot]]) {
|
||||
P2(("%O to be delivered on %O's circuit\n",
|
||||
target, query_ip_name(t) || t ))
|
||||
register_target(target, t);
|
||||
// was delivermsg(
|
||||
return t->msg(sname, mc, data, vars, 0, target);
|
||||
// no more cleansing of targets mapping.. see also net/library.i
|
||||
// } else {
|
||||
// P1(("PSYC/TCP target %O gone!\n", t2))
|
||||
// m_delete( targets, t2 );
|
||||
// }
|
||||
}
|
||||
#ifndef __PIKE__
|
||||
// okay so we have no existing connection..
|
||||
// current rule of thumb to decide whether to open up a tcp
|
||||
// also all localhost traffic should be handled by udp TODO
|
||||
#ifdef _flag_enable_routing_UDP
|
||||
if (u[UTransport] == "c" ||
|
||||
# ifdef _flag_enable_routing_TLS
|
||||
u[UTransport] == "s" ||
|
||||
# endif
|
||||
(!u[UTransport] && !abbrev("_notice", mc)))
|
||||
#else
|
||||
if (!u[UTransport] || u[UTransport] == "c"
|
||||
# ifdef _flag_enable_routing_TLS
|
||||
|| u[UTransport] == "s"
|
||||
# endif
|
||||
)
|
||||
#endif
|
||||
{
|
||||
dns_resolve(host, (:
|
||||
object o;
|
||||
string hopo = $2;
|
||||
string psychopo;
|
||||
string psycippo = "psyc://"+ $1 +"/";
|
||||
|
||||
// if ($3 && $3 != PSYC_SERVICE) {
|
||||
if ($9) {
|
||||
hopo += ":"+$9;
|
||||
psycippo += ":"+$9;
|
||||
}
|
||||
// hope it is correct to have a trailing slash here
|
||||
psychopo = "psyc://"+ hopo +"/";
|
||||
unless (o = find_target_handler(psycippo)) {
|
||||
// we use psyc:host:port as an object name
|
||||
// we can change that if it is confusing
|
||||
#ifdef QUEUE_WITH_SCHEME
|
||||
// this makes it look for psyc:host:port as its queue
|
||||
o = ("psyc:"+hopo) -> circuit($2, $3, u[UTransport],
|
||||
usesrv && "psyc", 0, systemQ, psychopo);
|
||||
#else
|
||||
// this makes it look for host:port as its queue
|
||||
o = ("psyc:"+hopo) -> circuit($2, $3, u[UTransport],
|
||||
usesrv && "psyc", hopo, systemQ, psychopo);
|
||||
#endif
|
||||
// SRV tag "psyc" is actively being checked, but
|
||||
// don't rely on it.. just use it as a fallback if
|
||||
// nothing else is possible, but some clients may
|
||||
// no longer be able to connect to you...
|
||||
}
|
||||
register_target($4, o);
|
||||
register_target(psychopo, o);
|
||||
register_target(psycippo, o);
|
||||
P2(("delivering %O(%O) over %O\n", hopo, $1, o))
|
||||
P3(("targets = %O\n", targets))
|
||||
// psyc/circuit.c will register psyc://IP:PORT at logon()
|
||||
// the last thing missing is a way to register all CNAMEs
|
||||
return o->msg($5, $6, $7, $8, 0, $4);
|
||||
// ip=1 2 3 4 5 6 7 8 9
|
||||
:),
|
||||
#ifdef FORK
|
||||
host, port, target, source, mc, data, vars, u[UPort]
|
||||
#else
|
||||
host, port, target, sname, mc, data, vars, u[UPort]
|
||||
#endif
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
#ifdef _flag_enable_routing_UDP
|
||||
if (u[UTransport] && u[UTransport] != "d")
|
||||
#endif
|
||||
{
|
||||
P1(("Invalid transport %O in %O, _failure to %O || %O\n",
|
||||
u[UTransport], target, vars["_context"], source))
|
||||
sendmsg(vars["_context"] || source,
|
||||
"_failure_network_connect_invalid_transport",
|
||||
"Unknown transport type '[_transport]' for [_source_relay].",
|
||||
([ "_source_relay" : target || u[UHost],
|
||||
"_transport": u[UTransport] ]), ME);
|
||||
// ME shouldn't be necessary! TODO
|
||||
return 0;
|
||||
}
|
||||
#ifdef _flag_enable_routing_UDP
|
||||
// fall thru to UDP
|
||||
# if DEBUG > 1
|
||||
if (port) {
|
||||
D(S("UDP[%s:%d] <= %O: %s\n", host, port, source, mc));
|
||||
} else {
|
||||
D(S("UDP[%s] <= %O: %s\n", host, source, mc));
|
||||
}
|
||||
# endif
|
||||
#ifndef NEW_RENDER
|
||||
// this produced wrong _length. please discontinue.
|
||||
if (stringp(data) && strlen(data))
|
||||
// why do we take guesses at data here? uncool!
|
||||
data="\n"+data+ (data[strlen(data)-1] == '\n' ?
|
||||
S_GLYPH_PACKET_DELIMITER "\n" :
|
||||
"\n" S_GLYPH_PACKET_DELIMITER "\n");
|
||||
else data="\n" S_GLYPH_PACKET_DELIMITER "\n"; // TODO? look up textdb.
|
||||
|
||||
// look! MMP-conformant support of the _context variable!
|
||||
if (room = vars["_context"]) {
|
||||
// this may have to change into a full psyc: URL
|
||||
if (objectp(room)) room = psyc_name(room);
|
||||
buf = S_GLYPH_PACKET_DELIMITER "\n"
|
||||
# ifdef PRE_SPEC
|
||||
":_source\t"+ sname +"\n"
|
||||
# else
|
||||
":_source_relay\t"+ sname +"\n"
|
||||
# endif
|
||||
+ ":_context\t"+ room +"\n";
|
||||
} else
|
||||
buf = S_GLYPH_PACKET_DELIMITER "\n"
|
||||
":_source\t"+ sname +"\n"
|
||||
":_target\t"+ target +"\n";
|
||||
buf += psyc_render(source, mc, data, vars, showingLog, target);
|
||||
#else
|
||||
buf = psyc_render(source, mc, data, vars, showingLog, target);
|
||||
#endif /* NEW_RENDER */
|
||||
|
||||
if (is_localhost(host)) return send_udp(host, port, buf);
|
||||
PT(("dns_resolve + send_udp %O:%O packet:\n%s", host,port,buf))
|
||||
dns_resolve(host, (: if (stringp($1))
|
||||
send_udp($1, $2, $3);
|
||||
else
|
||||
// if your driver complains about vars being
|
||||
// undefined at this point, you are probably
|
||||
// running an ldmud 3.2 which is not compatible
|
||||
// with psyced. pick a newer major version pls
|
||||
sendmsg(vars["_context"] || source,
|
||||
"_failure_network_send_resolve",
|
||||
"[_source_host] for [_source_relay] does not resolve.",
|
||||
([ "_source_host" : host,
|
||||
"_source_relay" : target||host ]), ME);
|
||||
return; :), port, buf);
|
||||
return 1;
|
||||
#endif /* _flag_enable_routing_UDP */
|
||||
#endif // PIKE
|
||||
}
|
||||
#endif
|
||||
|
||||
/* this breaks /connect ...
|
||||
object createUser(string nick) {
|
||||
PT(("creating " PSYC_PATH "user for "+ nick +"\n"))
|
||||
return named_clone(PSYC_PATH "user", nick);
|
||||
}
|
||||
*/
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue