Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/p/daemon/iplookup.c b/p/daemon/iplookup.c
new file mode 100644
index 0000000..7608d8f
--- /dev/null
+++ b/p/daemon/iplookup.c
@@ -0,0 +1,225 @@
+/*
+ * Mudlibseite des iplookup systems, mit dem aus numerischen IP Adressen
+ * der Hostname und der Ort, an dem sich der Rechner befinden berechnet wird.
+ * Ergebnisse werden gecachet.
+ *
+ * (c)2010 rumata @ morgengrauen
+ */
+
+#pragma strict_types,save_types
+#pragma no_clone,no_shadow
+
+// Format der ipmap:
+// Key: numerische ip als string (ohne fuehrende nullen)
+// Data:
+// [ip,0] Hostname, der vom externen Server geliefert wurde.
+// [ip,1] Locationinformation, die vom externen Server kommt.
+// dieser sollte den Ort, oder falls es nicht besser geht, das Land
+// im Klartext liefern.
+// [ip,2] Zeitstempel, bei dessen erreichen der Wert geloescht werden
+// soll.
+// [ip,3] Status der Anfrage
+
+private mapping ipmap;
+#define IPMAP_HOST 0
+#define IPMAP_CITY 1
+#define IPMAP_EXPIRE 2
+#define IPMAP_STATUS 3
+
+// externer server, der der lokationdaten berechnet
+#define IPLOOKUP_HOST "127.0.0.1"
+#define IPLOOKUP_PORT 8711
+#define IPLOOKUP_SAVE "/p/daemon/save/iplookup"
+
+// moegliche statuswerte (platz zum zaehlen der anfragen gelassen)
+#define STATUS_QUERYING 1
+#define STATUS_AUTHORITATIVE 128
+
+// so lange werden die daten im cache gehalten
+#define CACHE_TIME 86400 /* 1 day */
+
+// Ab dieser Groesse betrache ich den cache als "gross genug",
+// um einen cache update in etappen zu rechtfertigen.
+#define LARGE_CACHE_LIMIT 2000
+
+// so lange sind wir bereit auf die antwort einer anfrage beim server zu warten
+#define QUERY_TIME 60 /* 1 min */
+
+#include <config.h>
+#if MUDNAME == "MorgenGrauen"
+#define LOG(x) log_file("rumata/iplookup.log",strftime("%Y-%m-%d %H:%M:%S: ")+(x)+"\n")
+#else
+#define LOG(x)
+#endif
+
+// PROTOTYPES
+
+public void create();
+public void reset();
+static int active_entry( string key, mixed* data );
+static void expire_cache_small();
+static void expire_cache_large( string* keys );
+public void update( string udp_reply );
+
+// IMPLEMENTATION
+
+public void create() {
+ seteuid(getuid());
+ restore_object( IPLOOKUP_SAVE );
+
+ if( !mappingp(ipmap) || widthof(ipmap)!=4 ) {
+ ipmap = m_allocate( 0, 4 );
+ LOG("restore failed, creating new ipmap");
+ } else {
+ LOG(sprintf("created (%d entries)",sizeof(ipmap)));
+ }
+}
+
+public void reset() {
+ if( sizeof(ipmap) < LARGE_CACHE_LIMIT ) {
+ expire_cache_small();
+ } else {
+ LOG(sprintf("reset %d ->",sizeof(ipmap)));
+ expire_cache_large( m_indices(ipmap) );
+ }
+ set_next_reset(10800);
+}
+
+static int active_entry( string key, mixed* data ) {
+ return time() < data[IPMAP_EXPIRE];
+}
+
+// Den cache auf einfache weise aufraeumen.
+static void expire_cache_small() {
+ int s = sizeof(ipmap);
+ ipmap = filter( ipmap, #'active_entry );
+ save_object( IPLOOKUP_SAVE );
+ LOG(sprintf("reset (%d -> %d)",s,sizeof(ipmap)));
+}
+
+// Kompliziertere routine, die den cache etappenweise abarbeitet.
+static void expire_cache_large( string* keys ) {
+ if( !pointerp(keys) ) return;
+ int next=0;
+ foreach( string key: keys ) {
+ if( get_eval_cost() < 100000 ) break;
+ if( ipmap[key,IPMAP_EXPIRE] < time() ) {
+ m_delete( ipmap, key );
+ }
+ next++;
+ }
+ LOG(sprintf("checking %d of %d",next,sizeof(keys)));
+ if( next<sizeof(keys) ) {
+ call_out( #'expire_cache_large, 6, keys[next..] );
+ } else {
+ save_object( IPLOOKUP_SAVE );
+ LOG(sprintf("reset -> %d (done)",sizeof(ipmap)));
+ }
+}
+
+#define SEARCHING "<auf der Suche...>"
+
+/* Erzeugt einen temporaeren Eintrag, der fuer eine Suche steht.
+ * Wenn die Antwort kommt, wird der Eintrag mit den entgueltigen
+ * Daten ueberschrieben.
+ */
+static void make_request( string ipnum ) {
+ send_udp( IPLOOKUP_HOST, IPLOOKUP_PORT, ipnum );
+ ipmap += ([ ipnum : ipnum ; SEARCHING ;
+ time()+QUERY_TIME ; STATUS_QUERYING
+ ]);
+}
+
+/* Liefert zu einer gegebenen ipnum den Ort.
+ * diese Funktion wird von simul_efun aufgerufen.
+ * @param ipnum eine numerische ip-adresse oder ein interactive
+ * @return den Ort (oder das Land) in dem sich die ip-adresse
+ * laut externem Server befindet.
+ */
+public string country( mixed ipnum ) {
+ string host,city;
+ int expire,state;
+
+ if( objectp(ipnum) ) {
+ ipnum = query_ip_number(ipnum);
+ }
+ if( !stringp(ipnum) ) {
+ return "<undefined>";
+ }
+ if( !m_contains( &host, &city, &expire, &state, ipmap, ipnum ) ) {
+ make_request( ipnum );
+ return SEARCHING;
+ }
+
+ return city;
+}
+
+/* Liefert zu einer gegebenen ipnum den Hostnamen.
+ * diese Funktion wird von simul_efun aufgerufen.
+ * @param ipnum eine numerische ip-adresse oder ein interactive
+ * @return den Hostnamen der zu der angegebenen ip-adresse gehoert.
+ * wenn der hostname nicht bekannt ist, wird die ipadresse zurueckgegeben.
+ */
+public string host( mixed ipnum ) {
+ string host,city;
+ int expire,state;
+
+ if( objectp(ipnum) ) {
+ ipnum = query_ip_number(ipnum);
+ }
+ if( !stringp(ipnum) ) {
+ return "<undefined>";
+ }
+ if( !m_contains( &host, &city, &expire, &state, ipmap, ipnum ) ) {
+ make_request( ipnum );
+ return ipnum;
+ }
+
+ return host;
+}
+
+/* wird vom master aufgerufen, wenn eine antwort vom externen
+ * iplookup dienst eintrudelt.
+ */
+public void update( string udp_reply ) {
+ string* reply;
+ if( previous_object()!=master() ) return;
+ reply = explode(udp_reply,"\n");
+ if( sizeof(reply)<4 ) return;
+
+ if( reply[3] == "<unknown>" ) reply[3] = reply[1];
+ if( reply[2] == "<unknown>" ) reply[2] = "irgendwoher";
+ ipmap += ([ reply[1] : reply[3] ; reply[2] ; time()+CACHE_TIME ;
+ STATUS_AUTHORITATIVE ]);
+ //save_object( IPLOOKUP_SAVE );
+}
+
+int remove(int silent) {
+ save_object( IPLOOKUP_SAVE );
+ destruct(this_object());
+ return 1;
+}
+
+// DEBUGGING CODE
+
+#if 0
+public void dump( string key, mixed* data ) {
+ printf( "%s: %s (%s) s=%d bis %d\n", key, data[0], data[1],
+ data[3], data[2] );
+}
+
+public void load(string s) {
+ restore_object(s);
+ if( !mappingp(ipmap) || widthof(ipmap)!=4 ) {
+ ipmap = m_allocate( 0, 4 );
+ LOG("restore failed, creating new ipmap");
+ } else {
+ LOG(sprintf("created (%d entries)",sizeof(ipmap)));
+ }
+}
+
+public void debug() {
+ map( ipmap, #'dump );
+ printf( "= %d Eintraege\n", sizeof(ipmap) );
+}
+#endif