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
34
world/net/d/bounce.c
Normal file
34
world/net/d/bounce.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
// $Id: bounce.c,v 1.6 2005/03/14 13:30:46 lynx Exp $ // vim:syntax=lpc
|
||||
//
|
||||
// currently specific to the IRC implementation: recognize when a
|
||||
// person has several clients kicking each other out automatically.
|
||||
// yes, IRC client coders do implement things like these.
|
||||
//
|
||||
#include <net.h>
|
||||
|
||||
volatile mapping bounces = ([ ]);
|
||||
|
||||
#ifndef MAX_BOUNCES
|
||||
# define MAX_BOUNCES 3
|
||||
#endif
|
||||
#ifndef BOUNCE_INTERVAL
|
||||
# define BOUNCE_INTERVAL 60
|
||||
#endif
|
||||
|
||||
reset() {
|
||||
foreach (string nick : bounces) {
|
||||
unless (bounces[nick]) m_delete(bounces, nick);
|
||||
}
|
||||
}
|
||||
|
||||
checkBounce(nick) {
|
||||
string n = lower_case(nick);
|
||||
if (bounces[n] < (MAX_BOUNCES + 2)) {
|
||||
bounces[n]++;
|
||||
call_out(lambda(({}),
|
||||
({ #'--,
|
||||
({ #'[, bounces, n })
|
||||
})), BOUNCE_INTERVAL);
|
||||
}
|
||||
return (bounces[lower_case(nick)] > MAX_BOUNCES);
|
||||
}
|
16
world/net/d/echo.c
Normal file
16
world/net/d/echo.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
// $Id: echo.c,v 1.2 2005/03/14 10:23:26 lynx Exp $ // vim:syntax=lpc
|
||||
//
|
||||
// just a test daemon.. load it if you want urls of $echo type to work
|
||||
// you can (currently) also use /msg echo:whatever locally
|
||||
// put it into init.ls
|
||||
|
||||
create() {
|
||||
register_service("echo");
|
||||
}
|
||||
|
||||
msg(source, mc, data, mapping vars) {
|
||||
P1(("%O echoing for %O", ME, source))
|
||||
sendmsg(source, "_notice_echo"+mc,
|
||||
"Thanks for the "+data, vars);
|
||||
}
|
||||
|
270
world/net/d/gameserv.c
Normal file
270
world/net/d/gameserv.c
Normal file
|
@ -0,0 +1,270 @@
|
|||
// $Id: gameserv.c,v 1.12 2007/09/18 08:37:57 lynx Exp $ // vim:syntax=lpc
|
||||
//
|
||||
// game server gateway or something. quite amazing.
|
||||
// serves also as demonstration on how to use the udp library.
|
||||
//
|
||||
#include <net.h>
|
||||
|
||||
#if defined(__ERQ_MAX_SEND__) && !defined(MUD)
|
||||
|
||||
#include <closures.h>
|
||||
|
||||
inherit NET_PATH "udp";
|
||||
|
||||
#define P_PING 0
|
||||
#define P_FRAGS 1
|
||||
#define P_NAME 2
|
||||
#define P_DEATHS 3
|
||||
#define P_TEAM 4
|
||||
|
||||
protected mapping servers, alias, ut, ut_player, q3, bf_player;
|
||||
|
||||
void create() {
|
||||
servers = ([ ]);
|
||||
alias = ([ ]);
|
||||
q3 = ([ "hostname" : "_name", "mapname" : "_map", "clients" : "_players", "sv_maxclients" : "_maxplayers" ]);
|
||||
ut = ([ "hostname" : "_name", "mapname" : "_map", "numplayers" : "_players", "maxplayers" : "_maxplayers" ]);
|
||||
ut_player = ([ "player" : P_NAME, "frags" : P_FRAGS, "ping " : P_PING ]);
|
||||
bf_player = ([ "player" : P_NAME, "score" : P_FRAGS, ]);
|
||||
}
|
||||
|
||||
/*
|
||||
GSERV: player_11 => -'-=||=<Dr.ArAgOrN
|
||||
GSERV: frags_11 => 56
|
||||
GSERV: ping_11 => 69
|
||||
GSERV: team_11 => 1
|
||||
GSERV: mesh_11 => Male Soldier
|
||||
GSERV: skin_11 => SoldierSkins.Gard
|
||||
GSERV: face_11 => SoldierSkins.Wraith
|
||||
*/
|
||||
|
||||
public string list_servers() {
|
||||
reset();
|
||||
string message = "SERVERS:\n";
|
||||
foreach(string key : m_indices(servers)) {
|
||||
// message += " "+key+"\t"+servers[key]+"\n";
|
||||
message += sprintf("%s\t%s\n",to_string(key),servers[key]["_name"]);
|
||||
}
|
||||
message += "\nALIASES:\n";
|
||||
foreach(string key : m_indices(alias)) {
|
||||
// message += " "+key+"\t"+alias[key]+"\n";
|
||||
message += sprintf("%s\t%s\n",key,alias[key]);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private closure gen_callback(string id,string type) {
|
||||
return lambda(({ 'flag, 'data, 'l_port, 'ip, 'r_port }),
|
||||
({ CL_IF, ({ #'==, 'flag, 1 }),
|
||||
({ symbol_function("parse_"+type, ME), id, 'data, 'l_port,'ip, 'r_port }),
|
||||
({ #'return })
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
parse_bf(string id, string data, int l_port, int ip, int r_port) {
|
||||
D2(D(data);)
|
||||
}
|
||||
|
||||
parse_q3a(string id, string data, int l_port, int ip, int r_port) {
|
||||
array(string) temp;
|
||||
int size;
|
||||
temp = explode(data, "\n");
|
||||
string * info = explode(temp[1], "\\");
|
||||
size = sizeof(info);
|
||||
for(int i = 1; i < size; i = i + 2) {
|
||||
servers[id][(q3[info[i]] || info[i])] = info[i+1];
|
||||
D2(D("GSERV: "+info[i]+" => "+info[i+1]+"\n");)
|
||||
}
|
||||
if(temp[0] == "ÿÿÿÿstatusResponse") {
|
||||
int ping, frags;
|
||||
string name;
|
||||
foreach(string player : temp[2..]) {
|
||||
if(sscanf(player,"%U %U \"%s\"",frags,ping,name) == 3) {
|
||||
name = regreplace(name,"\\^[0-9]","",1);
|
||||
D2(D("PLAYER: "+frags+"\t"+ping+"\t"+name+"\n");)
|
||||
servers[id]["p"] += ({ ({ frags,ping,name }) });
|
||||
}
|
||||
}
|
||||
}
|
||||
if(servers[id]["_name"])
|
||||
alias[servers[id]["_name"]] = id;
|
||||
if(servers[id]["sv_privateClients"])
|
||||
servers[id]["_maxplayers"] = to_int(servers[id]["_maxplayers"]) - to_int(servers[id]["sv_privateClients"]);
|
||||
servers[id]["time"] = time();
|
||||
return 1;
|
||||
}
|
||||
|
||||
parse_ut(string id, string data, int l_port, int ip, int r_port) {
|
||||
array(string) temp;
|
||||
int size,num;
|
||||
string key, value;
|
||||
temp = explode(data, "\\")[1..];
|
||||
size = sizeof(temp);
|
||||
if(temp[size - 2] != "final") {
|
||||
closure cb = gen_callback(id,"ut");
|
||||
ticket(cb,l_port,ip,r_port);
|
||||
}
|
||||
for(int i = 0; i < size - 2; i = i + 2) {
|
||||
if(sscanf(temp[i],"%s_%U",key,num) == 2 && ut_player[key]) {
|
||||
if(sizeof(servers[id]["p"]) - 1 < num) servers[id]["p"][num] = allocate(10);
|
||||
servers[id]["p"][num][ut_player[key]] = temp[i+1];
|
||||
} else {
|
||||
servers[id][(ut[temp[i]] || temp[i])] = temp[i+1];
|
||||
D2(D("GSERV: "+temp[i]+" => "+temp[i+1]+"\n");)
|
||||
}
|
||||
}
|
||||
if(servers[id]["_name"])
|
||||
alias[servers[id]["_name"]] = id;
|
||||
servers[id]["time"] = time();
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void del_server(string id) {
|
||||
m_delete(servers, id);
|
||||
foreach(string key : m_indices(alias)) {
|
||||
if(alias[key] == id)
|
||||
m_delete(alias, key);
|
||||
}
|
||||
}
|
||||
|
||||
public mapping info(string id) {
|
||||
if(servers[id] || servers[alias[id]]) {
|
||||
D2(D("wuuusch!\n");)
|
||||
return servers[id] || servers[alias[id]];
|
||||
}
|
||||
return ([]);
|
||||
}
|
||||
|
||||
public mapping* players(string id) {
|
||||
if(pointerp(servers[id]["p"]))
|
||||
return servers[id]["p"];
|
||||
return ({ });
|
||||
}
|
||||
|
||||
public int update_server(string id) {
|
||||
closure cb;
|
||||
switch(lower_case(servers[id]["_type"])) {
|
||||
case "q1":
|
||||
case "quake1":
|
||||
cb = gen_callback(id,"q1");
|
||||
|
||||
break;
|
||||
case "qw":
|
||||
case "quakew":
|
||||
case "quakeworld":
|
||||
cb = gen_callback(id,"qw");
|
||||
|
||||
break;
|
||||
case "q2":
|
||||
case "quake2":
|
||||
cb = gen_callback(id,"q2");
|
||||
|
||||
break;
|
||||
case "q3":
|
||||
case "q3a":
|
||||
case "quake3":
|
||||
case "quake3arena":
|
||||
cb = gen_callback(id,"q3a");
|
||||
ticket(cb,"q3a", servers[id]["_host"], servers[id]["_port"]);
|
||||
ticket(cb,"q3a", servers[id]["_host"], servers[id]["_port"]);
|
||||
send("q3a", servers[id]["_host"], servers[id]["_port"],
|
||||
to_string(({ 255,255,255,255 })) + "getinfo");
|
||||
send("q3a", servers[id]["_host"], servers[id]["_port"],
|
||||
to_string(({ 255,255,255,255 })) + "getstatus");
|
||||
break;
|
||||
case "unreal":
|
||||
cb = gen_callback(id,"ut");
|
||||
ticket(cb,"u", servers[id]["_host"], servers[id]["_port"]);
|
||||
send("u", servers[id]["_host"], servers[id]["_port"], "\\status\\");
|
||||
break;
|
||||
case "ut":
|
||||
case "unrealtournament":
|
||||
cb = gen_callback(id,"ut");
|
||||
ticket(cb,"ut", servers[id]["_host"], servers[id]["_port"] + 1);
|
||||
send("ut", servers[id]["_host"], servers[id]["_port"] + 1, "\\status\\");
|
||||
break;
|
||||
case "ut2003":
|
||||
case "unrealtournament2003":
|
||||
cb = gen_callback(id,"ut2003");
|
||||
ticket(cb,"ut2003", servers[id]["_host"], servers[id]["_port"] + 1);
|
||||
send("ut2003", servers[id]["_host"], servers[id]["_port"] + 1, "x" + to_string(({ 0,0,0,0 })));
|
||||
break;
|
||||
case "bf":
|
||||
case "bf1942":
|
||||
cb = gen_callback(id,"bf");
|
||||
ticket(cb,"bf", servers[id]["_host"], servers[id]["_port"] + 8433);
|
||||
send("bf", servers[id]["_host"], servers[id]["_port"] + 8433, "\\status\\");
|
||||
break;
|
||||
default:
|
||||
del_server(id);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public varargs int add_server(string type, string r_host, int r_port, string name) {
|
||||
string id;
|
||||
reset();
|
||||
id = to_string(r_host + ":" + r_port);
|
||||
if(name) alias[name] = id;
|
||||
if(servers[id]) {
|
||||
return update_server(id);
|
||||
}
|
||||
servers[id] = ([
|
||||
"_type" : type,
|
||||
"_host" : r_host,
|
||||
"_port" : r_port,
|
||||
"time" : time(),
|
||||
"p" : ({ }),
|
||||
]);
|
||||
return update_server(id);
|
||||
/* cb = lambda(({ 'flag, 'data, 'l_port, 'ip, 'r_port }),
|
||||
({ CL_IF, ({ #'==, 'flag, 1 }),
|
||||
({ symbol_function("parseGS", ME), id, 'data, 'l_port,'ip, 'r_port }),
|
||||
({ #'return })
|
||||
})
|
||||
); */
|
||||
}
|
||||
|
||||
load() {
|
||||
reset();
|
||||
register_scheme("gameserv");
|
||||
return ME;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
public varargs int add_server(string type, string r_host, int r_port, string name) {
|
||||
D2(D("You need an erq to use d/gameserv.c\n");)
|
||||
return 0;
|
||||
}
|
||||
|
||||
public string list_servers() {
|
||||
D2(D("You need an erq to use d/gameserv.c\n");)
|
||||
return "";
|
||||
}
|
||||
public void del_server(string id) {
|
||||
D2(D("You need an erq to use d/gameserv.c\n");)
|
||||
}
|
||||
public mapping info(string id) {
|
||||
D2(D("You need an erq to use d/gameserv.c\n");)
|
||||
return ([ ]);
|
||||
}
|
||||
public mapping* players(string id) {
|
||||
D2(D("You need an erq to use d/gameserv.c\n");)
|
||||
return ([ ]);
|
||||
}
|
||||
public int update_server(string id) {
|
||||
D2(D("You need an erq to use d/gameserv.c\n");)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
msg(source, mc, data, mapping vars, showingLog, target) {
|
||||
D2(D("GAMESPY-D: HERE I AM!\n");)
|
||||
}
|
||||
|
177
world/net/d/hosts.c
Normal file
177
world/net/d/hosts.c
Normal file
|
@ -0,0 +1,177 @@
|
|||
// $Id: hosts.c,v 1.27 2008/03/11 13:42:25 lynx Exp $ // vim:syntax=lpc
|
||||
//
|
||||
// keeper of list of offensive hosts
|
||||
|
||||
#include <net.h>
|
||||
#include CONFIG_PATH "hosts.h"
|
||||
|
||||
#ifdef legal_host
|
||||
# undef legal_host
|
||||
#endif
|
||||
|
||||
#ifndef DISABLED_HOSTS
|
||||
# define DISABLED_HOSTS
|
||||
#endif
|
||||
#ifndef ENABLED_HOSTS
|
||||
# define ENABLED_HOSTS
|
||||
#endif
|
||||
|
||||
#ifdef PSYC_ENABLED_HOSTS
|
||||
# define PSYC_TRUSTWORTHY_HOSTS PSYC_ENABLED_HOSTS
|
||||
# define PSYC_PRIVATE
|
||||
#endif
|
||||
|
||||
#define DATA_FILE DATA_PATH "hosts"
|
||||
|
||||
#define I_HOST 0
|
||||
#define I_REASON 1
|
||||
#define I_NEXT 2
|
||||
|
||||
array(string) disabled_hosts = ({ DISABLED_HOSTS });
|
||||
mixed *disabled_list;
|
||||
volatile array(string) enabled_hosts = ({ ENABLED_HOSTS });
|
||||
volatile int loaded = 0;
|
||||
|
||||
#ifdef PSYC_TRUSTWORTHY_HOSTS
|
||||
volatile array(string) psyc_trustworthy_hosts = ({ PSYC_TRUSTWORTHY_HOSTS });
|
||||
#endif
|
||||
|
||||
create() { load(); }
|
||||
|
||||
load() {
|
||||
// P1(("disabled_hosts is %O\n", disabled_hosts))
|
||||
unless (loaded) {
|
||||
loaded++;
|
||||
restore_object(DATA_FILE);
|
||||
unless (disabled_list) {
|
||||
mixed *cur = disabled_list = allocate(3);
|
||||
|
||||
foreach (string host : disabled_hosts) {
|
||||
cur = cur[I_NEXT] = allocate(3);
|
||||
cur[I_HOST] = host;
|
||||
// easier to read. no info where there is no info.
|
||||
cur[I_REASON] = ""; // "Old block, no reason given.";
|
||||
}
|
||||
disabled_hosts = 0;
|
||||
}
|
||||
}
|
||||
return ME;
|
||||
}
|
||||
|
||||
legal_host(host, port, scheme, udp) {
|
||||
int i, k, l;
|
||||
mixed *cur = disabled_list;
|
||||
|
||||
if (udp) udp = 3; // UDP is spoofable, see net/psyc/udp.c
|
||||
l = strlen(host);
|
||||
P3(("legal_host(%O,%O,%O,%O) called\n", host, port, scheme, udp))
|
||||
#ifdef PSYC_TRUSTWORTHY_HOSTS
|
||||
if (scheme == "psyc") {
|
||||
for (i=sizeof(psyc_trustworthy_hosts)-1; i>=0; i--) {
|
||||
k = strlen(psyc_trustworthy_hosts[i]) - 1;
|
||||
P3(("trustworthy_host(%O): %O,%O,%O,%O,%O\n",
|
||||
host, i, k, l, psyc_trustworthy_hosts[i], host[0..k]))
|
||||
if (k < l && host[0..k] == psyc_trustworthy_hosts[i])
|
||||
return 9 - udp;
|
||||
}
|
||||
# ifdef PSYC_PRIVATE
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
while (cur = cur[I_NEXT]) {
|
||||
k = strlen(cur[I_HOST]) - 1;
|
||||
P3(("disabled_host(%O): %O,%O,%O,%O,%O\n",
|
||||
host, cur, k, l, cur[I_HOST], host[0..k]))
|
||||
#if 1
|
||||
// #define DIABLED_HOSTS "" blocks everyone.. imho this is not
|
||||
// expected behaviour
|
||||
if (k != -1 && k < l && host[0..k] == cur[I_HOST]) return 0;
|
||||
#else // ungetestet.. wäre aber genauer
|
||||
if (k < l && host[0..k] == cur[I_HOST]) {
|
||||
if (host == cur[I_HOST]) return 0;
|
||||
if (host[k] == '.') return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (enabled_hosts && sizeof(enabled_hosts)) {
|
||||
for (i=sizeof(enabled_hosts)-1; i>=0; i--) {
|
||||
k = strlen(enabled_hosts[i]) - 1;
|
||||
P4(("enabled_host(%O): %O,%O,%O,%O,%O\n",
|
||||
host, i, k, l, enabled_hosts[i], host[0..k]))
|
||||
if (k != -1 && k < l && host[0..k] == enabled_hosts[i])
|
||||
return 7 - udp;
|
||||
}
|
||||
// why should activated ENABLED_HOSTS exclude everyone else??
|
||||
//
|
||||
// return 0;
|
||||
}
|
||||
return 5 - udp;
|
||||
}
|
||||
|
||||
list() {
|
||||
mapping show = ([ ]);
|
||||
mixed *cur = disabled_list;
|
||||
|
||||
if (enabled_hosts && sizeof(enabled_hosts)) {
|
||||
previous_object()->pr("_list_hosts_enabled_amount", // _tab
|
||||
"Access permitted from %d IP nets\n", sizeof(enabled_hosts));
|
||||
previous_object()->pr("_list_hosts_enabled", // _tab
|
||||
"Enabled IP nets: %O\n", enabled_hosts);
|
||||
}
|
||||
/*
|
||||
int i;
|
||||
string l;
|
||||
|
||||
for (i=sizeof(disabled_hosts)-1; i>=0; i--) {
|
||||
if (l) l += ", \""+ disabled_hosts[i] +"\"";
|
||||
else l = "\""+ disabled_hosts[i] +"\"";
|
||||
}
|
||||
unless (l) l = "none.";
|
||||
*/
|
||||
while (cur = cur[I_NEXT])
|
||||
show[cur[I_HOST]] = cur[I_REASON];
|
||||
previous_object()->pr("_list_hosts_disabled", // _tab
|
||||
"Blocked IP nets: %O\n", show);
|
||||
// "Blocked IP nets: %-*#s\n", implode(disabled_hosts, "\n")
|
||||
#ifdef PSYC_TRUSTWORTHY_HOSTS
|
||||
previous_object()->pr("_list_hosts_trustworthy_psyc", // _tab
|
||||
"PSYC-trustworthy nets: %O\n", psyc_trustworthy_hosts);
|
||||
#endif
|
||||
}
|
||||
|
||||
modify(match, reason) {
|
||||
int i;
|
||||
mixed *pre, *cur = disabled_list;
|
||||
|
||||
//for (i=sizeof(disabled_hosts)-1; i>=0; i--) {
|
||||
while ((pre = cur) && cur = cur[I_NEXT]) {
|
||||
if (cur[I_HOST] == match) {
|
||||
pre[I_NEXT] = cur[I_NEXT];
|
||||
|
||||
#ifdef SAVE_FORMAT
|
||||
save_object(DATA_FILE, SAVE_FORMAT);
|
||||
#else
|
||||
save_object(DATA_FILE);
|
||||
#endif
|
||||
log_file("BLOCK", "[%s] %O unblocked by %O\n",
|
||||
ctime(), match, previous_object());
|
||||
monitor_report("_notice_block_off",
|
||||
match+" unblocked by "+
|
||||
object_name(previous_object()));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
unless (reason) return -2;
|
||||
disabled_list[I_NEXT] = ({ match, reason, disabled_list[I_NEXT] });
|
||||
#ifdef SAVE_FORMAT
|
||||
save_object(DATA_FILE, SAVE_FORMAT);
|
||||
#else
|
||||
save_object(DATA_FILE);
|
||||
#endif
|
||||
log_file("BLOCK", "[%s] %O blocked by %O\n",
|
||||
ctime(), match, previous_object());
|
||||
monitor_report("_notice_block_on",
|
||||
match+" blocked by "+object_name(previous_object()));
|
||||
return 1;
|
||||
}
|
32
world/net/d/mysql.c
Normal file
32
world/net/d/mysql.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <net.h>
|
||||
|
||||
/*
|
||||
* from ldmud's concepts/mysql:
|
||||
* As mySQL "limits" the number of connections to 100 and as every
|
||||
* connection to the mySQL-server takes time, you should use
|
||||
* database serverobjects in your MUD which constantly keep the
|
||||
* connection to the mySQL-server.
|
||||
*
|
||||
* hence we use this instead of letting each object have it's own connection
|
||||
*/
|
||||
|
||||
volatile int handle;
|
||||
|
||||
create() {
|
||||
#if defined(STORAGE_MYSQL)
|
||||
handle = db_connect(STORAGE_MYSQL_DATABASE, STORAGE_MYSQL_USER, STORAGE_MYSQL_PASSWORD);
|
||||
#endif
|
||||
}
|
||||
|
||||
mixed query(string q, varargs mixed args) {
|
||||
// TODO: it might be wise to db_conv_string on each arg to
|
||||
// avoid sql injections
|
||||
int res;
|
||||
mixed row;
|
||||
mixed *data = ({ });
|
||||
res = db_exec(handle, sprintf(q, args...));
|
||||
unless(res) return ({ });
|
||||
while(row = db_fetch(handle))
|
||||
data += ({ row });
|
||||
return data;
|
||||
}
|
23
world/net/d/pgsql.c
Normal file
23
world/net/d/pgsql.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include <net.h>
|
||||
|
||||
/*
|
||||
* using one database connection is sufficient
|
||||
*
|
||||
* WARNING
|
||||
* ONLY USE THIS IF YOUR DRIVER HAS THE SYNC PG PACKAGE
|
||||
* (otherwise you dont have the pg_connect_sync and pg_query_sync efuns ;-)
|
||||
*/
|
||||
|
||||
create() {
|
||||
int ret;
|
||||
#if defined(STORAGE_PGSQL)
|
||||
ret = pg_connect_sync(STORAGE_PGSQL_CONNECT);
|
||||
PT(("ret %d\n", ret))
|
||||
#endif
|
||||
}
|
||||
|
||||
mixed query(string q, varargs mixed args) {
|
||||
// TODO: it might be wise to db_conv_string on each arg to
|
||||
// avoid sql injections
|
||||
return pg_query_sync(sprintf(q, args...));
|
||||
}
|
700
world/net/d/psyc.c
Normal file
700
world/net/d/psyc.c
Normal file
|
@ -0,0 +1,700 @@
|
|||
// vim:foldmethod=marker:syntax=lpc:noexpandtab
|
||||
|
||||
// this whole file is a mistake... and not in use...
|
||||
|
||||
#ifdef FORK // {{{
|
||||
|
||||
#include <net.h>
|
||||
#include <url.h>
|
||||
#include <services.h>
|
||||
|
||||
inherit NET_PATH "state";
|
||||
inherit NET_PATH "queue2";
|
||||
|
||||
#include "../psyc/edit.i"
|
||||
|
||||
string psycName() { return ""; }
|
||||
|
||||
varargs mixed find_psyc_object(string t, object connection, array(mixed) u) {
|
||||
string r, svc, user;
|
||||
object o;
|
||||
|
||||
PT((">> t: %O\n", t))
|
||||
|
||||
unless (strlen(t) && u = (u || parse_uniform(t))) return 0;
|
||||
|
||||
//unless (u[UScheme] && u[UScheme] == "psyc") {
|
||||
unless (u[UScheme] && strlen(u[UScheme])) {
|
||||
if (connection)
|
||||
connection -> w("_failure_unsupported_target_relative",
|
||||
"No support for relative targets yet.");
|
||||
return 0;
|
||||
//QUIT
|
||||
}
|
||||
unless (u[UHost] && strlen(u[UHost])) {
|
||||
if (connection)
|
||||
connection -> w("_failure_unsupported_notation_location",
|
||||
"No support for fancy UNLs yet.");
|
||||
return 0;
|
||||
//QUIT
|
||||
}
|
||||
// TODO: croak if host:port isnt us?
|
||||
// or implement proxy service?
|
||||
// do any checking for gateway schemes?
|
||||
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 (r[<1] == '/') r = r[..<2];
|
||||
#endif
|
||||
if (strlen(r)) switch(r[0]) {
|
||||
case '^':
|
||||
case '~':
|
||||
if (user) {
|
||||
if (connection)
|
||||
connection -> w("_error_invalid_uniform_user_duplicate",
|
||||
"Two users in uniform not allowed here.");
|
||||
// QUIT
|
||||
return 0;
|
||||
}
|
||||
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) {
|
||||
if (connection)
|
||||
connection -> w("_failure_unavailable_service",
|
||||
"No service '[_service]' available here.", ([ "_service" : svc ]) );
|
||||
return 0;
|
||||
}
|
||||
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());
|
||||
// fall thru
|
||||
default:
|
||||
o = find_object(r);
|
||||
D2( if(!o)
|
||||
D("OBJECT NOT FOUND: "+ r +"\n"); )
|
||||
}
|
||||
else unless (user) return 0;
|
||||
if (user && !objectp(o)) {
|
||||
o = summon_person(user);
|
||||
// o = find_person(user);
|
||||
// unless(o) o = createUser(user);
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
// new psyc-parser to fit the needs ot the new api. operates on _one_ string
|
||||
// containing _one_ paket (everything after the mc is considered the data)
|
||||
//
|
||||
// returns the mc, psyc-data remains in the buffer.
|
||||
#define ERROR(x) { monitor_report("_error_broken_syntax", x+((connection) ? sprintf(" from %O.", connection) : ".")); return 0; }
|
||||
//#define ERROR(x) { monitor_report("_error_broken_syntax", x); return 0; }
|
||||
|
||||
static string spsyc_parse(string buf, mapping vars, int iscontext, string source,
|
||||
object connection, object o) {
|
||||
string mod, var, val, mc, line, lastmod, lastvar;
|
||||
mixed lastval;
|
||||
int a = 0, b;
|
||||
|
||||
while (a < strlen(buf) && !mc && ((b = strstr(buf, "\n", a)) != -1
|
||||
|| b = strlen(buf))) {
|
||||
|
||||
val = "";
|
||||
line = buf[a..b-1];
|
||||
switch(buf[a]) {
|
||||
case ':':
|
||||
case '=':
|
||||
case '+':
|
||||
case '-':
|
||||
unless (sscanf(line, "%1.1s%s%t%s", mod, var, val)
|
||||
|| sscanf(line, "%1.1s%s", mod, var)) {
|
||||
if (connection)
|
||||
connection -> w("_error_broken_syntax",
|
||||
"You are in league with Ratzinger,\
|
||||
the evil lord or broken psyc.");
|
||||
// <lynX> runtime error erzeugen!?? wie kommt ihr darauf
|
||||
// das sei eine gute idee? damit man nen grund hat große
|
||||
// teure catches zu machen? ich will in meinen logs nur
|
||||
// runtime fehler von bugs - ist schon schlimm genug das
|
||||
// schrottige http-zugriffe sowas auslösen, aber logs
|
||||
// voller fehler von buggy psyc implementationen, nein!
|
||||
// man sagt der gegenseite dass was faul ist, killt evtl
|
||||
// die verbindung falls der fehler nicht recoverbar ist,
|
||||
// reported oder loggt das problem, aber dann is gut!
|
||||
ERROR(S("PSYC parsing failed in '%s'", line))
|
||||
}
|
||||
unless (sizeof(var)) {
|
||||
if (mod == "-") {
|
||||
if (connection)
|
||||
connection -> w("_error_broken_syntax",
|
||||
"Diminishing of lists is not supported.");
|
||||
ERROR("PSYC parsing failed (Invalid list diminish)")
|
||||
} else unless (lastvar) {
|
||||
if (connection)
|
||||
connection -> w("_error_broken_syntax",
|
||||
"Wrong list continuation.");
|
||||
ERROR("PSYC parsing failed (Invalid list continuation)")
|
||||
} else unless (lastmod == mod) {
|
||||
if (connection)
|
||||
connection -> w("_error_broken_syntax",
|
||||
"Inconsistent list continuation. Do not mix modifiers.");
|
||||
ERROR("PSYC parsing failed (Invalid list continuation)")
|
||||
}
|
||||
|
||||
if (pointerp(lastval)) {
|
||||
lastval += ({ val });
|
||||
} else {
|
||||
lastval = ({ lastval, val });
|
||||
}
|
||||
a = b+1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
case '\t':
|
||||
unless (lastvar) {
|
||||
if (connection)
|
||||
connection -> w("_error_broken_syntax",
|
||||
"Continuation without variable.");
|
||||
ERROR("PSYC parsing failed (Invalid variable continuation)")
|
||||
}
|
||||
if (pointerp(lastval))
|
||||
lastval[<1] += "\n"+line[1..];
|
||||
else lastval += "\n"+line[1..];
|
||||
a = b+1;
|
||||
continue;
|
||||
case '_':
|
||||
int i;
|
||||
for (i = b - a - 1; i>=0; i--) {
|
||||
unless (line[i] == '_' ||
|
||||
(line[i] >= 'a' && line[i] <= 'z') ||
|
||||
(line[i] >= '0' && line[i] <= '9') ||
|
||||
(line[i] >= 'A' && line[i] <= 'Z')) {
|
||||
if (connection)
|
||||
connection -> w("_error_illegal_method",
|
||||
"[_method] is not a valid method name.",
|
||||
([ "_method" : line ]));
|
||||
ERROR("PSYC parsing failed (Invalid method '"
|
||||
+ line +"')\n")
|
||||
}
|
||||
}
|
||||
mc = line;
|
||||
switch(mc) {
|
||||
case "_conversation": // we will soon have to decide its
|
||||
case "_converse": // final name...
|
||||
case "_talk":
|
||||
mc = "_message";
|
||||
break;
|
||||
default:
|
||||
if (abbrev("_conversation", mc)) {
|
||||
mc[..12] = "_message";
|
||||
} else if (abbrev("_converse", mc)) {
|
||||
mc[..8] = "_message";
|
||||
} else if (abbrev("_talk", mc)) {
|
||||
mc[..4] = "_message";
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (connection)
|
||||
connection -> w("_error_broken_syntax",
|
||||
"Unsupported modifier '[_modifier]'",
|
||||
([ "_modifier" : line[0] ]));
|
||||
ERROR("PSYC parsing failed (Unknown modifier '"
|
||||
+ line[0] + "')")
|
||||
}
|
||||
if (lastmod) switch(lastmod[0]) {
|
||||
case '=':
|
||||
if (o)
|
||||
o -> Assign(source, lastvar, lastval, iscontext);
|
||||
case ':':
|
||||
vars[lastvar] = lastval;
|
||||
break;
|
||||
case '+':
|
||||
if (o)
|
||||
o -> Augment(source, lastvar, lastval, iscontext);
|
||||
break;
|
||||
case '-':
|
||||
if (o)
|
||||
o -> Diminish(source, lastvar, lastval, iscontext);
|
||||
break;
|
||||
}
|
||||
|
||||
lastmod = mod;
|
||||
lastvar = var;
|
||||
lastval = val;
|
||||
a = b+1;
|
||||
}
|
||||
unless (mc) {
|
||||
// malformed psyc-packet in buf. get on it!
|
||||
if (connection)
|
||||
connection -> w("_error_broken_syntax",
|
||||
"Received packet without method.");
|
||||
ERROR("PSYC parsing failed (Method missing)")
|
||||
}
|
||||
|
||||
if (strlen(buf) == b) { // no data. packet ends with mc
|
||||
buf = "";
|
||||
} else {
|
||||
// still data in buf. buf[b] is the last \n before the psyc-data
|
||||
buf = buf[b+1..];
|
||||
}
|
||||
|
||||
return mc;
|
||||
}
|
||||
|
||||
// not exactly beautiful to have it here, but still more efficient than
|
||||
// having hordes of if (psycd) checks..
|
||||
int deliver(mixed ip, string peerip, object connection, string peeraddr,
|
||||
string host, string data, mapping mvars) {
|
||||
string psycaddr;
|
||||
PT(("deliver(%O, %O, %O, %O)\n", ip, host, data, mvars))
|
||||
mixed o, target = mvars["_target"];
|
||||
int trustworthy = (member(mvars, "_INTERNAL_trust"))
|
||||
? to_int(mvars["_INTERNAL_trust"])
|
||||
: 0;
|
||||
|
||||
|
||||
|
||||
if (ip == -1) {
|
||||
monitor_report("_error_something_because_somebody_was_once_again_too_lazy_to_look_up_a_method_which_most_likely_already_exists_in_library_dns_c", S("%O could not resolve %O.",
|
||||
ME, host));
|
||||
|
||||
if (objectp(connection))
|
||||
connection->w("_error_invalid_host", "Could not resolve [_host].",
|
||||
([ "_host": host ]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ip && ip != peerip) {
|
||||
monitor_report("_warning_rejected_relay_incoming",
|
||||
"Dropped a packet from "+ peerip +
|
||||
" trying to relay for "+ host);
|
||||
P0(("Dropped a packet from "+ peerip +
|
||||
" trying to relay for "+ host +"\n"+
|
||||
" in parse:deliver(%O, %O, %O, %O)\n",
|
||||
ip, host, data, mvars))
|
||||
if (connection)
|
||||
connection->w("_error_rejected_relay_incoming",
|
||||
"You are not allowed to relay for [_host].",
|
||||
([ "_host": host ]));
|
||||
return 1;
|
||||
} else if (psycaddr = mvars["_context"] || mvars["_source"]) {
|
||||
// schmorp??
|
||||
if (connection)
|
||||
// is psycaddr already lc?
|
||||
register_target(lower_case(psycaddr), connection);
|
||||
} else psycaddr = "psyc://"+peeraddr;
|
||||
|
||||
if (member(mvars, "_source_identification")) {
|
||||
mixed t = lookup_identification(psycaddr,
|
||||
mvars["_source_identification"]);
|
||||
unless (t) {
|
||||
// the i: is a safety measure in case of a supergau
|
||||
// that mvars["_source_identification"] could somehow resemble
|
||||
// some other queue in the system.. not convinced..
|
||||
// see also two more occurences in this file.
|
||||
//
|
||||
string n = "i:"+mvars["_source_identification"]+psycaddr;
|
||||
unless (qExists(n)) qInit(n, 100, 5);
|
||||
enqueue(n, ({ ip, peerip, connection, peeraddr, host, data,
|
||||
mvars }));
|
||||
return 0;
|
||||
} else if (t == mvars["_source_identification"]) {
|
||||
// TODO: increase trustworthy ness
|
||||
mvars["_source_technical"] = psycaddr;
|
||||
mvars["_source"] = mvars["_source_identification"];
|
||||
m_delete(mvars, "_source_identification");
|
||||
} else {
|
||||
PT(("someone (%O) claims an identification (%O) though he is "
|
||||
"already"
|
||||
" registered as someone else. Will we allow multiple"
|
||||
" identifications per unl? Should - in theory - be possible"
|
||||
" and okay. dropping this message.\n",
|
||||
psycaddr, mvars["_source_identification"]))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
string state, err, mc;
|
||||
mixed source, t;
|
||||
mixed *u;
|
||||
int iscontext = 0; // if we are in context-state
|
||||
mapping psycvars = ([ "_INTERNAL_origin" : connection ]);
|
||||
|
||||
// this is our new context-routing without target.
|
||||
// 1 _source
|
||||
// 2 _target
|
||||
// 4 _context
|
||||
switch(
|
||||
(member(mvars, "_source") ? 1 : 0) |
|
||||
(member(mvars, "_target") ? 2 : 0) |
|
||||
(member(mvars, "_context") ? 4 : 0)
|
||||
) {
|
||||
case 5:
|
||||
# if DEBUG > 0
|
||||
PT(("Received both context(%s) and source(%s) from %O\n",
|
||||
mvars["_context"], mvars["_source"], psycaddr))
|
||||
# endif
|
||||
case 4:
|
||||
t = mvars["_context"];
|
||||
state = t;
|
||||
iscontext = 1;
|
||||
o = find_context(t);
|
||||
unless (o) {
|
||||
// no one is interested / online
|
||||
// is this an abuse or a feature?
|
||||
// fippo: feature, context may be 0
|
||||
// if no one who is normally listening is online
|
||||
PT(("Dropped messages from %s because there was no\
|
||||
context slave for %s.\n",
|
||||
psycaddr, mvars["_context"]))
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 6: // this is unicast from context to target in the context's
|
||||
// state
|
||||
state = mvars["_context"];
|
||||
iscontext = 1;
|
||||
case 3:
|
||||
// "Link to [_source] established.. uses this
|
||||
// and place/slave too (although improperly)
|
||||
//m_delete(mvars, "_source");
|
||||
unless (iscontext) {
|
||||
source = lower_case(mvars["_source"]);
|
||||
state = source;
|
||||
}
|
||||
case 2:
|
||||
t = mvars["_target"];
|
||||
// this is a message from the rootobj but since its target is
|
||||
// not our rootmsg we need to offer some kind of source.
|
||||
// TODO: Why not use ME here ??
|
||||
unless (source)
|
||||
source = psycaddr;
|
||||
if (trustworthy > 7) {
|
||||
P2(("%O relaying permitted for %O to %O via %O\n",
|
||||
ME, source, t, o))
|
||||
// We should do mmp-routing here.. but find out before if
|
||||
// there is any connections registered for that target/host
|
||||
}
|
||||
u = parse_uniform(t);
|
||||
if (u && (u[UResource] == "" || !u[UResource])) {
|
||||
// rootMSG. that parse_uniform makes me quite unhappy.
|
||||
// we may check the string t only for the existance of a
|
||||
// resource since we allready know that it is a valid url.
|
||||
// TODO
|
||||
} else unless (o = psyc_object(t) || find_psyc_object(t)) {
|
||||
PT(("Found no recipent for %O. Dropping message.\n", t))
|
||||
return 1;
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
// this is a message to our rootmsg from someone
|
||||
source = lower_case(mvars["_source"]);
|
||||
break;
|
||||
case 0:
|
||||
// going to our rootmsg from hell
|
||||
source = psycaddr;
|
||||
break;
|
||||
default:
|
||||
PT(("Unimplemented routing-scheme (_source, _target and _context are all present)\n"))
|
||||
return 1;
|
||||
}
|
||||
// can this safely move into one of the ifs above? TODO
|
||||
if (t = mvars["_source_relay"]) {
|
||||
if (t = psyc_object(t)) {
|
||||
P2(("local _source_relay %O from %O, cont %O\n",
|
||||
t, source, mvars["_context"]))
|
||||
mvars["_source_relay"] = t;
|
||||
}
|
||||
}
|
||||
|
||||
unless (mc = spsyc_parse(&data, psycvars, iscontext, state,
|
||||
connection, o)) {
|
||||
if (connection)
|
||||
destruct(connection);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# ifdef PSYC_TCP
|
||||
P2(("TCP[%s] => %O: %s\n", peeraddr, o || t, mc))
|
||||
# else
|
||||
PT(("UDP[%s] => %O: %s\n", peeraddr, o || t, mc))
|
||||
# endif
|
||||
|
||||
# ifndef GOOD_IDEA
|
||||
// why do we parse for auth mcs here if we already do it
|
||||
// in common::rootMsg? if this should be here instead,
|
||||
// you can make these checks a bit more efficient if
|
||||
// you first ensure that the target of this message is
|
||||
// the server root. it's also nicer to the users that
|
||||
// you're not looking at their messages here.. ;)
|
||||
//
|
||||
if (mc == "_error_invalid_authentication") {
|
||||
string n;
|
||||
unless (member(mvars, "_source") &&
|
||||
member(psycvars, "_location")) {
|
||||
PT(("got _error_invalid_authentication without proper"
|
||||
"vars.\n"))
|
||||
return 0;
|
||||
|
||||
}
|
||||
n = "i:"+mvars["_source"]+psycvars["_location"];
|
||||
unless (qExists(n)) {
|
||||
PT(("got _error_invalid_authentication for something we "
|
||||
"never requested.\n"))
|
||||
return 0;
|
||||
}
|
||||
sendmsg(psycvars["_location"], "_error_invalid_source_identification",
|
||||
"Your identification [_location] seems to be bogus. "
|
||||
"Du kommst hier ned rein!\n",
|
||||
([ "_location" : mvars["_source"]]));
|
||||
qDel(n);
|
||||
return 1;
|
||||
} else if (mc == "_notice_authentication") {
|
||||
string n;
|
||||
unless (member(mvars, "_source") &&
|
||||
member(psycvars, "_location")) {
|
||||
PT(("got _notice_authentication without proper"
|
||||
"vars.\n"))
|
||||
return 0;
|
||||
}
|
||||
n = "i:"+mvars["_source"]+psycvars["_location"];
|
||||
unless (qExists(n)) {
|
||||
PT(("got _notice_authentication for something we "
|
||||
"never requested.\n"))
|
||||
return 0;
|
||||
}
|
||||
register_location(psycvars["_location"], mvars["_source"]);
|
||||
while (qSize(n))
|
||||
apply(#'deliver, shift(n));
|
||||
return 1;
|
||||
}
|
||||
# endif
|
||||
|
||||
// we could put these mmp-vars into cvars only to avoid this loop
|
||||
foreach (string key : mvars) {
|
||||
if (mergeRoutingVar(key))
|
||||
psycvars[key] = mvars[key];
|
||||
}
|
||||
PT(("deliver ending with target: %O and mc: %O\n", o, mc))
|
||||
|
||||
if (objectp(o))
|
||||
o -> msg(source, mc, (data == "" ? 0 : data), psycvars, 0,
|
||||
source);
|
||||
else if (connection) {
|
||||
// per-connection "server root" which actually handles
|
||||
// connection feature negotiation
|
||||
connection -> rootMsg(source, mc, data == "" ? 0 : data,
|
||||
psycvars, source);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* wrong order of arguments.. elsaga: how did this ever work!?
|
||||
int msg(mixed target, string mc, mixed data, mapping vars,
|
||||
mixed source, mixed target2) {
|
||||
*/
|
||||
int msg(mixed source, string mc, mixed data, mapping vars,
|
||||
mixed showingLog, mixed target) {
|
||||
string sname;
|
||||
int port;
|
||||
string user, host, obj;
|
||||
string buf, room;
|
||||
object o;
|
||||
mixed t;
|
||||
array(mixed) u = parse_uniform(target);
|
||||
|
||||
unless (u[UHost]) {
|
||||
sendmsg(source, "_failure_unsupported_notation_location",
|
||||
"PSYC server-independent uniform network "
|
||||
"identificators not implemented yet.", 0, 0);
|
||||
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 = psyc_name(source);
|
||||
// host = lower_case(u[UHostPort]);
|
||||
// unless (u[URoot]) u[URoot] = "psyc://"+host;
|
||||
|
||||
// TODO: no need for vars
|
||||
unless (mappingp(vars)) vars = ([ ]);
|
||||
P3(("looking for %O(%O) in %O..\n", target, u[UHostPort], targets))
|
||||
// if (member(targets, t2 = u[URoot])) {
|
||||
// t = targets[t2];
|
||||
// if (t) {
|
||||
unless (port = u[UPort]) port = PSYC_SERVICE;
|
||||
else if (port < 0) {
|
||||
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
|
||||
return 0;
|
||||
}
|
||||
host = lower_case(u[UHost]);
|
||||
user = u[UUser];
|
||||
obj = u[UResource];
|
||||
// was: obj = u[UResource];
|
||||
// but probably caused the erratic rootMsg() events
|
||||
//obj = u[UUser] ? "~" + u[UUser] : u[UResource];
|
||||
//
|
||||
// if (host == SERVER_HOST) host = "127.0.0.1";
|
||||
#if 1
|
||||
//
|
||||
// at this point i should be able to recognize targets which are my own!
|
||||
// net/gateway/aim would use that.. TODO
|
||||
//
|
||||
// see also legal_domain and legal_host
|
||||
if (query_udp_port() == port && (host == "127.0.0.1"
|
||||
|| host == "127.1"
|
||||
#ifdef __HOST_IP_NUMBER__
|
||||
|| host == __HOST_IP_NUMBER__
|
||||
#else
|
||||
|| host == myIP
|
||||
#endif
|
||||
// || host == SERVER_HOST
|
||||
// || lower_case(host) == myLowerCaseHost
|
||||
|| host == my_lower_case_host() || host == "localhost")) {
|
||||
if (stringp(obj)) {
|
||||
if (obj[<1] == '/') obj = obj[..<2];
|
||||
if (strlen(obj)) switch(obj[0]) {
|
||||
case '^':
|
||||
case '~':
|
||||
unless(user) user = obj[1..];
|
||||
break;
|
||||
case '$':
|
||||
// no services available yet
|
||||
// but here's the support for them
|
||||
obj[0..0] = "/service/";
|
||||
break;
|
||||
case '@':
|
||||
// t[0..0] = PLACE_PATH;
|
||||
obj = PLACE_PATH + lower_case(obj[1..]);
|
||||
if (o = find_object(obj)) break;
|
||||
// should check for legal name instead
|
||||
// of catch. TODO
|
||||
catch(obj -> load());
|
||||
// fall thru
|
||||
default:
|
||||
o = find_object(obj);
|
||||
D2( if(!o) D(S("OBJECT NOT FOUND: %O\n", t)); )
|
||||
} else unless(user) {
|
||||
// rootMsg(source, mc,
|
||||
// buffer == "" ? 0 : buffer, cvars);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// user@ is ignored if /@ or /~ is given..
|
||||
if (user && !objectp(o)) {
|
||||
o = summon_person(user); //, PSYC_PATH "user");
|
||||
//o = find_person(user);
|
||||
//unless(o) o = createUser(user);
|
||||
}
|
||||
// cache the resulting object for the url
|
||||
register_target(lower_case(target), o);
|
||||
return sendmsg(o, mc, data, vars, source);
|
||||
// or deliver directly?
|
||||
}
|
||||
#endif
|
||||
// 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
|
||||
unless (u[UTransport] == "d" || abbrev("_notice", mc)) {
|
||||
#endif
|
||||
dns_resolve(host, (:
|
||||
object o;
|
||||
string addr = $1;
|
||||
string hopo = $2;
|
||||
string psycaddr = "psyc://"+ addr;
|
||||
|
||||
// if ($3 && $3 != PSYC_SERVICE) {
|
||||
if ($9) {
|
||||
hopo += ":"+$9;
|
||||
addr += ":"+$9;
|
||||
}
|
||||
unless (o = find_target_handler(psycaddr)) {
|
||||
o = ("psyc:"+hopo) -> circuit($2, $3, 0, "psyc", 0,
|
||||
system_queue());
|
||||
}
|
||||
register_target($4, o);
|
||||
register_target("psyc://"+hopo, o);
|
||||
register_target(psycaddr, o);
|
||||
P2(("delivering %O(%O) over %O\n", hopo, $1, o))
|
||||
// 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
|
||||
:),
|
||||
host, port, target, sname, mc, data, vars, u[UPort]
|
||||
);
|
||||
return 1;
|
||||
#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
|
||||
if (objectp(source)) buf = make_psyc(mc, data, vars, source);
|
||||
else buf = make_psyc(mc, data, vars);
|
||||
buf = make_mmp(buf, vars);
|
||||
|
||||
if (host == "localhost") return send_udp(host, port, buf);
|
||||
P3(("send_udp %O:%O packet:\n%O", host,port,buf))
|
||||
dns_resolve(host, (: if ($2 < 0) {
|
||||
send_udp($1, $2, $3);
|
||||
}
|
||||
return; :), port, buf);
|
||||
return 1;
|
||||
#endif /* _flag_enable_routing_UDP */
|
||||
}
|
||||
|
||||
object load() {
|
||||
return ME;
|
||||
}
|
||||
|
||||
int outstate() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
mapping state() {
|
||||
return ([]);
|
||||
}
|
||||
|
||||
void create() {
|
||||
qCreate();
|
||||
}
|
||||
|
||||
#endif // }}}
|
25
world/net/d/sqlite.c
Normal file
25
world/net/d/sqlite.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include <net.h>
|
||||
|
||||
#ifdef STORAGE_SQLITE
|
||||
# ifndef SQLITE_DB_PERSON
|
||||
# define SQLITE_DB_PERSON DATA_PATH "person-sqlite"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TODO: actually, this may need be a wrapper, as every object is only allowed
|
||||
* a single sqlite db
|
||||
*/
|
||||
|
||||
|
||||
create() {
|
||||
#if defined(STORAGE_SQLITE)
|
||||
sl_open(SQLITE_DB_PERSON);
|
||||
#endif
|
||||
}
|
||||
|
||||
mixed query(string q, varargs mixed args) {
|
||||
// TODO: it might be wise to db_conv_string on each arg to
|
||||
// avoid sql injections
|
||||
return sl_exec(sprintf(q, args...));
|
||||
}
|
481
world/net/d/udp.c
Normal file
481
world/net/d/udp.c
Normal file
|
@ -0,0 +1,481 @@
|
|||
// $Id: udp.c,v 1.15 2008/03/29 20:05:32 lynx Exp $ // vim:syntax=lpc
|
||||
//
|
||||
// interface to the erq (external request daemon) to handle
|
||||
// multi-protocol UDP, since the driver only has one port
|
||||
// which we use for native PSYC. okay fippo also uses it for SIP,
|
||||
// but i'm not sure if that's going to stay that way.
|
||||
|
||||
#include <net.h>
|
||||
#ifdef __ERQ_MAX_SEND__
|
||||
|
||||
#include <erq.h>
|
||||
#include <errno.h>
|
||||
#include <closures.h>
|
||||
|
||||
//#include NET_PATH "queue.c"
|
||||
inherit NET_PATH "queue";
|
||||
|
||||
|
||||
volatile private mapping udp_ports, alias;
|
||||
#endif
|
||||
|
||||
// port || alias -> data
|
||||
// port -> alias
|
||||
public varargs int ticket(closure callback, int localport, string remotehost, int remoteport);
|
||||
public int send(int localport, string host, int remoteport, string data);
|
||||
private void sendUDP(int localport);
|
||||
public varargs mixed listenPort(int port, mixed param, varargs mixed * args);
|
||||
public int closePort(mixed port);
|
||||
void process_erq(int port, string type, int * response_data, int len);
|
||||
public void getRPort(int port);
|
||||
public varargs mixed listPorts(int m);
|
||||
private void reset();
|
||||
|
||||
#ifdef __ERQ_MAX_SEND__
|
||||
|
||||
#define TICKETS_MAX 100 // maximum size of the tickets array
|
||||
#define TICKETS_PRE 50 // size to allocate
|
||||
#define QUEUE_MAX 100
|
||||
#define QUEUE_PRE 50
|
||||
|
||||
// sockets states
|
||||
#define S_WAITING -1
|
||||
#define S_ERROR 0
|
||||
#define S_OK 1
|
||||
#define S_BLOCKED 2
|
||||
#define S_SENDING 3
|
||||
#define S_CLOSED 4
|
||||
|
||||
// send-queue packet-array
|
||||
#define P_LOCALPORT 0
|
||||
#define P_REMOTEHOST 1
|
||||
#define P_REMOTEPORT 2
|
||||
#define P_DATA 3
|
||||
|
||||
// socket-array
|
||||
#define STATE 0
|
||||
#define TICKET 1
|
||||
#define CALLBACK 2
|
||||
#define PORT 3
|
||||
|
||||
//load() { return ME; }
|
||||
/*
|
||||
public void reset(int a) {
|
||||
if(!mappingp(udp_ports)) udp_ports = ([ ]);
|
||||
if(!mappingp(alias)) alias = ([ ]);
|
||||
::reset(a);
|
||||
}
|
||||
*/
|
||||
public varargs mixed listPorts(int m) {
|
||||
string message, port;
|
||||
mapping states;
|
||||
reset();
|
||||
states = ([ -1 : "S_WAITING", 0 : "S_ERROR", 1 : "S_OK",
|
||||
2 : "S_BLOCKED", 3 : "S_SENDING", 4 : "S_CLOSED" ]);
|
||||
if (m) {
|
||||
mixed value, ports;
|
||||
|
||||
ports = ([ ]);
|
||||
foreach (port, value : udp_ports) {
|
||||
ports += ([ port : ([ "_port" : port,
|
||||
"_state" : states[value[STATE]],
|
||||
"_callback" : to_string(value[CALLBACK])
|
||||
]) ]);
|
||||
}
|
||||
return ports;
|
||||
}
|
||||
|
||||
message = "===================\n\tPORT\tSTATE\tCALLBACK\n";
|
||||
foreach(port : m_indices(udp_ports)) {
|
||||
message += "\t"+port+"\t"+states[udp_ports[port][STATE]]+"\t"
|
||||
+to_string(udp_ports[port][CALLBACK])+"\n";
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public varargs int ticket(closure callback, mixed localport, string remotehost, int remoteport) {
|
||||
mixed key;
|
||||
|
||||
reset();
|
||||
unless(udp_ports[to_string(localport)]) {
|
||||
if(!alias[to_string(localport)]) {
|
||||
if(stringp(localport)) {
|
||||
unless (listenPort(0,localport,callback))
|
||||
return 0;
|
||||
} else {
|
||||
unless (listenPort(localport,callback))
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
localport = alias[to_string(localport)];
|
||||
}
|
||||
}
|
||||
localport = to_string(localport);
|
||||
if(remotehost && sscanf(remotehost,"%~D.%~D.%~D.%~D") != 4) {
|
||||
closure c = lambda(
|
||||
({ 'name }),
|
||||
({
|
||||
CL_IF, 'name,
|
||||
({ (#'funcall), #'ticket,
|
||||
callback, localport, 'name,
|
||||
remoteport
|
||||
})
|
||||
}));
|
||||
dns_resolve(remotehost, c);
|
||||
return 1;
|
||||
}
|
||||
if(remoteport) {
|
||||
key = localport + ":" + remotehost + ":" + remoteport;
|
||||
} else if(remotehost) {
|
||||
key = localport + ":" + remotehost;
|
||||
} else {
|
||||
key = localport;
|
||||
}
|
||||
unless(qExists( key )) {
|
||||
qInit(key, TICKETS_MAX, TICKETS_PRE);
|
||||
}
|
||||
enqueue(key, callback);
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int send(mixed localport, string remotehost, int remoteport, string data) {
|
||||
|
||||
unless(udp_ports[to_string(localport)]) {
|
||||
if(!alias[to_string(localport)]) {
|
||||
if(stringp(localport)) {
|
||||
unless (listenPort(0,localport))
|
||||
return 0;
|
||||
} else {
|
||||
unless (listenPort(localport))
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
localport = alias[to_string(localport)];
|
||||
}
|
||||
}
|
||||
localport = to_string(localport);
|
||||
if(remotehost && sscanf(remotehost,"%~D.%~D.%~D.%~D") != 4) {
|
||||
closure c = lambda(
|
||||
({ 'name }),
|
||||
({
|
||||
CL_IF, 'name,
|
||||
({ (#'funcall), #'send,
|
||||
localport, 'name,
|
||||
remoteport, data
|
||||
})
|
||||
}) );
|
||||
dns_resolve(remotehost, c);
|
||||
return 1;
|
||||
}
|
||||
if(udp_ports[localport][STATE] != S_BLOCKED) {
|
||||
if(!enqueue(":" + localport,({
|
||||
localport,remotehost,remoteport,
|
||||
to_array(data)[0..strlen(data)-1],
|
||||
}) )) return 0;
|
||||
sendUDP(localport);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void sendUDP(mixed localport) {
|
||||
string packet;
|
||||
mixed data;
|
||||
int * ip;
|
||||
unless(udp_ports[localport]) return 0;
|
||||
switch(udp_ports[localport][STATE]) {
|
||||
case S_OK:
|
||||
if(!qSize( ":" + localport ))
|
||||
return;
|
||||
data = shift( ":" + localport );
|
||||
ip = map(explode(data[P_REMOTEHOST],"."),#'to_int);
|
||||
packet = udp_ports[localport][TICKET]
|
||||
+ ip[0..3]
|
||||
+ ({ data[P_REMOTEPORT] / 256, data[P_REMOTEPORT] & 255 })
|
||||
+ data[P_DATA];
|
||||
unless (send_erq(ERQ_SEND, packet,
|
||||
lambda(({ 'data, 'len }),
|
||||
({
|
||||
#'process_erq, localport,
|
||||
ERQ_SEND, 'data, 'len
|
||||
})
|
||||
))) {
|
||||
P0(("%O failed to ERQ_SEND!\n", ME))
|
||||
}
|
||||
udp_ports[localport][STATE] = S_SENDING;
|
||||
D2(D("============\nOutgoing UDP-packet on port "+localport
|
||||
+"\nto: "+data[P_REMOTEHOST]
|
||||
+":"+data[P_REMOTEPORT]+"\n============\n");)
|
||||
return;
|
||||
case S_ERROR:
|
||||
|
||||
return;
|
||||
case S_WAITING:
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void getRPort(int port) {
|
||||
// first we will try to bind port 3645
|
||||
// if that fails ++ until it works fine ,)
|
||||
// then we will send a packet over the new
|
||||
// unknown port which is still represented by udp_ports[0]
|
||||
// to our new port 3645+n. Tada! we know our former unknown
|
||||
// port. Then we just change 0 to x.
|
||||
//
|
||||
// and everything put into one large lambda.. .]
|
||||
// -el
|
||||
|
||||
if (send_erq(ERQ_OPEN_UDP,({ port/256, port&255 }),
|
||||
lambda(({ 'data, 'len }),
|
||||
({ (#',),
|
||||
({ (#'=),'data,({ (#'map),'data,#'&,255 }) }),
|
||||
({ #'switch, ({ CL_INDEX, 'data, 0 }),
|
||||
({ ERQ_OK }),
|
||||
({ (#',),
|
||||
({ #'send,0,"127.0.0.1",port,"PORT" }),
|
||||
({ (#'=), ({ CL_INDEX, ({ CL_INDEX, udp_ports, port }), TICKET }), ({ CL_L_RANGE, 'data, 1 }) }),
|
||||
({ (#'=), ({ CL_INDEX, ({ CL_INDEX, udp_ports, port }), STATE }), S_OK }),
|
||||
}),
|
||||
(#'break),
|
||||
({ ERQ_E_UNKNOWN }),
|
||||
({ CL_IF, ({ #'==,({ CL_INDEX, 'data, 1}), 98 }),
|
||||
({ #'getRPort, port+1 }),
|
||||
({ (#'return),0 }),
|
||||
}),
|
||||
(#'break),
|
||||
({ ERQ_STDOUT }),
|
||||
({ (#',),
|
||||
({ (#'=),'r_host,({ (#'sprintf),"%d.%d.%d.%d", ({ CL_INDEX, 'data, 1 }), ({ CL_INDEX, 'data, 2 }), ({ CL_INDEX, 'data, 3 }), ({ CL_INDEX, 'data, 4 }) }) }),
|
||||
({ CL_IF, ({ #'&&, ({ #'==,'r_host,"127.0.0.1" }),({ #'==,({ (#'to_string),({ CL_RANGE,'data,7,11 }) }),"PORT" }), }),
|
||||
({ (#',),
|
||||
({ (#'=),'l_port, ({ (#'+), ({ CL_INDEX,'data,6 }),({ (#'*),256,({ CL_INDEX,'data,5 }) }) }) }),
|
||||
({ #'qRename,":0", ({ (#'+),":",'l_port }) }),
|
||||
({ (#'=), ({ CL_INDEX, udp_ports, 'l_port }), ({ CL_INDEX, udp_ports, to_string(0) }) }),
|
||||
({ (#'m_delete), udp_ports, to_string(0) }),
|
||||
({ #'closePort, port}),
|
||||
({ (#'=), 'callback, ({ CL_INDEX, ({ CL_INDEX, udp_ports, 'l_port }), CALLBACK }) }),
|
||||
({ #'closePort, 'l_port }),
|
||||
({ #'listenPort, 'l_port, 'callback }),
|
||||
({ (#'funcall), 'callback, 0, 'l_port }),
|
||||
}),
|
||||
({ (#'return),0 })
|
||||
}),
|
||||
}),
|
||||
(#'break),
|
||||
})
|
||||
}))))
|
||||
{
|
||||
qInit(":" + port, QUEUE_MAX, QUEUE_PRE);
|
||||
udp_ports += ([ port : ({ S_WAITING,0,lambda(({ 'data, 'len }), ({ #'process_erq, port, ERQ_OPEN_UDP, 'data, 'len }) )}) ]);
|
||||
} else {
|
||||
P0(("%O failed to ERQ_OPEN_UDP!\n", ME))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* switch(data[0]) {
|
||||
* case ERQ_OK:
|
||||
* send data to that port over unknown port which is still
|
||||
* represented by udp_ports[0] callback must be the 0 to x changer!
|
||||
* break;
|
||||
* case ERQ_E_UNKNOW:
|
||||
* if(data[1] == 98) { // 98 == Adress allready in use
|
||||
* bind port+1
|
||||
* recall myself
|
||||
* }
|
||||
* break;
|
||||
* case ERQ_STDOUT:
|
||||
* extract port and make the movement!
|
||||
* break;
|
||||
* }
|
||||
*/
|
||||
}
|
||||
|
||||
public varargs mixed listenPort(int port, mixed param, varargs mixed * args) {
|
||||
unless (mappingp(udp_ports))
|
||||
reset();
|
||||
if(qExists(":" + port) && udp_ports[to_string(port)]) return 0;
|
||||
if(!port && !param) return 0;
|
||||
// doesnt make any sence to bind to a
|
||||
// random port without getting to know
|
||||
// which it is.
|
||||
mixed id;
|
||||
closure callback;
|
||||
if(!port && stringp(param)) {
|
||||
while (udp_ports[param]) {
|
||||
param = to_string(({ random(150)+1,random(150)+1 }));
|
||||
}
|
||||
id = param;
|
||||
if(sizeof(args) && closurep(args[0])) callback = args[0];
|
||||
} else {
|
||||
id = to_string(port);
|
||||
}
|
||||
if(closurep(param)) callback = param;
|
||||
|
||||
D2(D("============\nlistenPort("+(port || id)
|
||||
+") called!\n============\n");)
|
||||
closure c = lambda(
|
||||
({ 'data, 'len }),
|
||||
({
|
||||
#'process_erq, id,
|
||||
ERQ_OPEN_UDP, 'data, 'len
|
||||
})
|
||||
);
|
||||
if (send_erq(ERQ_OPEN_UDP,({ port/256, port&255 }),c)) {
|
||||
qInit(":" + id, QUEUE_MAX, QUEUE_PRE);
|
||||
udp_ports += ([ id : ({ S_WAITING,0,callback || 0 }) ]);
|
||||
if(stringp(param)) return id;
|
||||
return 1;
|
||||
} else {
|
||||
P0(("%O failed to ERQ_OPEN_UDP!\n", ME))
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int closePort(mixed port) {
|
||||
port = to_string(port);
|
||||
if(!udp_ports[port] && (!alias[port] && !udp_ports[alias[port]])) return 0;
|
||||
D2(D("============\nclosePort("+port+") called!\n============\n");)
|
||||
send_erq(ERQ_KILL,
|
||||
(udp_ports[port][TICKET] || udp_ports[alias[port]][TICKET])
|
||||
+ ({0,0,0,0}),
|
||||
lambda(({ 'data, 'len }),
|
||||
({ #'process_erq, port,
|
||||
ERQ_KILL, 'data, 'len })
|
||||
));
|
||||
udp_ports -= ([ port ]);
|
||||
udp_ports -= ([ alias[port] ]);
|
||||
alias -= ([ port ]);
|
||||
qDel(":" + port);
|
||||
}
|
||||
|
||||
void process_erq(mixed port, string type, int * response_data, int len) {
|
||||
response_data = map(response_data,#'&,255);
|
||||
port = to_string(port);
|
||||
int remoteport;
|
||||
string remotehost;
|
||||
mixed callback;
|
||||
|
||||
switch (response_data[0]) {
|
||||
// BIND and SEND
|
||||
case ERQ_OK: // port bound || package sent !
|
||||
switch (type) {
|
||||
case ERQ_OPEN_UDP:
|
||||
D2(D("============\nPORT \""+port+"\" bound for ticket: \""+to_string(response_data[1..])+"\"\n============\n");)
|
||||
udp_ports[port][TICKET] = response_data[1..];
|
||||
udp_ports[port][STATE] = S_OK;
|
||||
if(port == "0" && udp_ports[port][CALLBACK]) {
|
||||
// no alias, cb
|
||||
getRPort(3654);
|
||||
} else {
|
||||
sendUDP( port );
|
||||
}
|
||||
break;
|
||||
case ERQ_SEND:
|
||||
udp_ports[port][STATE] = S_OK;
|
||||
sendUDP( port );
|
||||
break;
|
||||
case ERQ_KILL:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
case ERQ_E_UNKNOWN: // unknown error while binding || sending
|
||||
switch(response_data[1]) {
|
||||
case EADDRINUSE:
|
||||
D2(D("Port "+port+" allready in use by someone else!\n");)
|
||||
default:
|
||||
D2(D("Unknown error while Binding or Sending!"
|
||||
+to_string(response_data[1..])+"\n");)
|
||||
}
|
||||
return;
|
||||
// BIND
|
||||
case ERQ_E_NSLOTS:// The max number of child processes is exhausted.
|
||||
udp_ports -= ([ port ]);
|
||||
return;
|
||||
case ERQ_E_ARGLENGTH: // The port number given does not consist of two bytes
|
||||
return;
|
||||
// SEND
|
||||
case ERQ_E_TICKET: // ticket invalid!
|
||||
if(!unshift(":" + port )) {
|
||||
D2(D("PANIC! Mysteriously a UDP-packet got lost in the"
|
||||
"queue!\n");)
|
||||
}
|
||||
if(!to_int(port) || to_string(to_int(port)) != port) {
|
||||
listenPort(0, port );
|
||||
} else {
|
||||
listenPort( to_int(port), udp_ports[port][CALLBACK] || 0);
|
||||
}
|
||||
udp_ports -= ([ port ]);
|
||||
return;
|
||||
case ERQ_E_INCOMPLETE: // only a part of the message has been sent
|
||||
return;
|
||||
case ERQ_E_WOULDBLOCK: // erq allready has a packet in the queue..
|
||||
if(!unshift( port )) {
|
||||
D2(D("You are too fast, young Jedi!\n");)
|
||||
}
|
||||
return;
|
||||
case ERQ_E_PIPE: // pipe error. <info>
|
||||
|
||||
return;
|
||||
// INCOMING UDP
|
||||
case ERQ_STDOUT: // incoming data on udp-port
|
||||
remotehost = sprintf("%d.%d.%d.%d", response_data[1],
|
||||
response_data[2], response_data[3],
|
||||
response_data[4]);
|
||||
remoteport = response_data[5] * 256 + response_data[6];
|
||||
|
||||
string key = qSize(port + ":" + remotehost + ":" + remoteport,
|
||||
port + ":" + remotehost,
|
||||
port);
|
||||
if(key) {
|
||||
callback = shift( key );
|
||||
} else {
|
||||
callback = udp_ports[port][CALLBACK];
|
||||
}
|
||||
D2(D("============\nIncoming UDP-packet:\n from: "+port + ":"
|
||||
+ remotehost + ":" + remoteport +"\nticket: \""+ key
|
||||
+ "\" callback: "+to_string(callback)+"\n============\n");)
|
||||
if(closurep(callback))
|
||||
funcall(callback,1,to_string(response_data[7..]), port,
|
||||
remotehost, remoteport);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void create() {
|
||||
alias = ([ ]);
|
||||
udp_ports = ([ ]);
|
||||
}
|
||||
|
||||
load() { return ME; }
|
||||
|
||||
#else
|
||||
public varargs int ticket(closure callback, int localport, string remotehost, int remoteport) {
|
||||
D2(D("You need an erq to use d/udp.c\n");)
|
||||
return 0;
|
||||
}
|
||||
public int send(int localport, string host, int remoteport, string data) {
|
||||
D2(D("You need an erq to use d/udp.c\n");)
|
||||
return 0;
|
||||
}
|
||||
public varargs mixed listenPort(int port, mixed param) {
|
||||
D2(D("You need an erq to use d/udp.c\n");)
|
||||
return 0;
|
||||
}
|
||||
public void getRPort(int port) {
|
||||
D2(D("You need an erq to use d/udp.c\n");)
|
||||
}
|
||||
public varargs mixed listPorts(int m) {
|
||||
D2(D("You need an erq to use d/udp.c\n");)
|
||||
if (m)
|
||||
return ([ ]);
|
||||
return "";
|
||||
}
|
||||
load() {
|
||||
return ME;
|
||||
}
|
||||
#endif
|
||||
|
||||
void reset() { }
|
Loading…
Add table
Add a link
Reference in a new issue