[xmppd-dev] commit r1564 - in trunk/jabberd14: . jabberd jabberd/base jabberd/lib jsm

mail at jabberd.org mail at jabberd.org
Tue Nov 10 02:02:45 CET 2009


Author: mawis
Date: Tue Nov 10 02:02:44 2009
New Revision: 1564

Log:
Porting the changes made in the release 1.6.x branch to trunk. Especially improved dynamic routing, mini-http server on XML sockets, and packet logging filters.
This does not yet contain the mod_dynamic jsm module

Modified:
   trunk/jabberd14/ChangeLog
   trunk/jabberd14/jabberd/base/base_accept.cc
   trunk/jabberd14/jabberd/base/base_connect.cc
   trunk/jabberd14/jabberd/config.cc
   trunk/jabberd14/jabberd/deliver.cc
   trunk/jabberd14/jabberd/jabberd.h
   trunk/jabberd14/jabberd/lib/jabberdlib.h
   trunk/jabberd14/jabberd/lib/jutil.cc
   trunk/jabberd14/jabberd/lib/str.cc
   trunk/jabberd14/jabberd/mio.cc
   trunk/jabberd14/jabberd/mio_tls.cc
   trunk/jabberd14/jabberd/mio_xml.cc
   trunk/jabberd14/jabberd/xdb.cc
   trunk/jabberd14/jsm/jsm.cc

Modified: trunk/jabberd14/ChangeLog
==============================================================================
--- trunk/jabberd14/ChangeLog	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/ChangeLog	Tue Nov 10 02:02:44 2009	(r1564)
@@ -1,3 +1,18 @@
+2009-11-10  Matthias Wimmer  <m at tthias.eu>
+    * jsm/jsm.cc: porting changes in 1.6.x branch to trunk
+    * jabberd/jabberd.h: same
+    * jabberd/mio_xml.cc: same
+    * jabberd/config.cc: same
+    * jabberd/mio_tls.cc: same
+    * jabberd/xdb.cc: same
+    * jabberd/lib/str.cc: same
+    * jabberd/lib/jabberdlib.h: same
+    * jabberd/lib/jutil.cc: same
+    * jabberd/mio.cc: same
+    * jabberd/base/base_connect.cc: same
+    * jabberd/base/base_accept.cc: same
+    * jabberd/deliver.cc: same
+
 2009-03-17  Matthias Wimmer  <m at tthias.eu>
 
     * jabberd/lib/jabberdlib.h: fixing includes (by Robin Redeker)

Modified: trunk/jabberd14/jabberd/base/base_accept.cc
==============================================================================
--- trunk/jabberd14/jabberd/base/base_accept.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/base/base_accept.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -38,11 +38,11 @@
 #define A_ERROR  -1
 #define A_READY   1
 
-typedef struct queue_struct {
+typedef struct jqueue_struct {
     int stamp;
     xmlnode x;
-    struct queue_struct *next;
-} *queue, _queue;
+    struct jqueue_struct *next;
+} *jqueue, _jqueue;
 
 typedef struct accept_instance_st {
     mio m;
@@ -57,15 +57,15 @@
     int restrict_var;
     xdbcache offline;
     jid offjid;
-    queue q;
-    /* dpacket dplast; */
+    jqueue q;
+    std::set<std::string>* dynamic_routings; /**< hostnames the peer has dynamically routed to him, need to unregister on connection close */
 } *accept_instance, _accept_instance;
 
 static void base_accept_queue(accept_instance ai, xmlnode x) {
-    queue q;
+    jqueue q;
     if(ai == NULL || x == NULL) return;
 
-    q = static_cast<queue>(pmalloco(xmlnode_pool(x),sizeof(_queue)));
+    q = static_cast<jqueue>(pmalloco(xmlnode_pool(x),sizeof(_jqueue)));
     q->stamp = time(NULL);
     q->x = x;
     q->next = ai->q;
@@ -78,15 +78,7 @@
 
     /* Insert the message into the write_queue if we don't have a MIO socket yet.. */
     if (ai->state == A_READY) {
-        /*
-         * TSBandit -- this doesn't work, since many components simply modify the node in-place
-        if(ai->dplast == p) // don't return packets that they sent us! circular reference!
-        {
-            deliver_fail(p,"Circular Refernce Detected");
-        }
-        else
-        */
-            mio_write(ai->m, p->x, NULL, 0);
+	mio_write(ai->m, p->x, NULL, 0);
         return r_DONE;
     }
 
@@ -94,12 +86,31 @@
     return r_DONE;
 }
 
+static void base_accept_unregister_dynamics(accept_instance ai) {
+    // sanity check
+    if (!ai)
+	return;
+
+    // unregister the dynamic routings
+    if (ai->dynamic_routings) {
+	for (std::set<std::string>::const_iterator p = ai->dynamic_routings->begin(); p != ai->dynamic_routings->end(); ++p) {
+	    log_notice(ai->i->id, "unregistering dynamic routing for '%s'", p->c_str());
+	    unregister_instance(ai->i, p->c_str());
+	}
+
+	delete ai->dynamic_routings;
+	ai->dynamic_routings = NULL;
+    }
+
+    // create new set for future dynamic routings
+    ai->dynamic_routings = new std::set<std::string>();
+}
 
 /* Handle incoming packets from the xstream associated with an MIO object */
 static void base_accept_process_xml(mio m, int state, void* arg, xmlnode x, char* unused1, int unused2) {
     accept_instance ai = (accept_instance)arg;
     xmlnode cur, off;
-    queue q, q2;
+    jqueue q, q2;
     jpacket jp;
     char const* pwdsent;
     xmppd::sha1 pwdcheck;
@@ -118,13 +129,6 @@
         case MIO_XML_NODE:
             /* If aio has been authenticated previously, go ahead and deliver the packet */
             if(ai->state == A_READY  && m == ai->m) {
-                /*
-                 * TSBandit -- this doesn't work.. since many components modify the node in-place
-                ai->dplast = dpacket_new(x);
-                deliver(ai->dplast, ai->i);
-                ai->dplast = NULL;
-                */
-
                 /* if we are supposed to be careful about what comes from this socket */
                 if(ai->restrict_var) {
                     jp = jpacket_new(x);
@@ -135,7 +139,20 @@
                     }
                 }
 
-                deliver(dpacket_new(x), ai->i);
+		// create a deliverable packet from the stanza we got
+		dpacket p = dpacket_new(x);
+
+		// check if this is a routing update we got
+		if (p && p->type == p_XDB && p->id && p->id->get_domain() == "-internal" && p->id->has_node()) {
+		    // check for host at -internal
+		    if (p->id->get_node() == "host" && p->id->has_resource()) {
+			ai->dynamic_routings->insert(p->id->get_resource());
+		    }
+
+		    // XXX might check for unhost as well
+		}
+
+                deliver(p, ai->i);
                 return;
             }
 
@@ -218,10 +235,15 @@
 
             ai->state = A_ERROR;
 
+	    log_notice(ai->i->id, "Connection to peer had an error");
+
             /* clean up any tirds */
             while ((cur = mio_cleanup(m)) != NULL)
                 deliver_fail(dpacket_new(cur), N_("External Server Error"));
 
+	    // unregister dynamic routings to peer
+	    base_accept_unregister_dynamics(ai);
+
             return;
 
         case MIO_CLOSED:
@@ -229,10 +251,13 @@
             if (m != ai->m)
                 return;
 
-            log_debug2(ZONE, LOGT_IO, "closing accepted socket");
+	    log_notice(ai->i->id, "Connection to peer has been closed");
             ai->m = NULL;
             ai->state = A_ERROR;
 
+	    // unregister dynamic routings to peer
+	    base_accept_unregister_dynamics(ai);
+
             return;
         default:
             return;
@@ -275,7 +300,7 @@
 /* check the packet queue for stale packets */
 static result base_accept_beat(void *arg) {
     accept_instance ai = (accept_instance)arg;
-    queue bouncer, lastgood, cur, next;
+    jqueue bouncer, lastgood, cur, next;
     int now = time(NULL);
 
     cur = ai->q;
@@ -310,6 +335,16 @@
     return r_DONE;
 }
 
+static void base_accept_send_routingupdate(accept_instance inst, char const* destination, int is_register) {
+    xmlnode route_stanza = xmlnode_new_tag_ns("xdb", NULL, NS_SERVER);
+    xmlnode_put_attrib_ns(route_stanza, "ns", NULL, NULL, "");
+    xmlnode_put_attrib_ns(route_stanza, "from", NULL, NULL, inst->i->id);
+    jid magic_jid = jid_new(xmlnode_pool(route_stanza), is_register ? "host at -internal" : "unhost at -internal");
+    jid_set(magic_jid, destination, JID_RESOURCE);
+    xmlnode_put_attrib_ns(route_stanza, "to", NULL, NULL, jid_full(magic_jid));
+    mio_write(inst->m, route_stanza, NULL, 0);
+}
+
 /**
  * callback that gets notified if a new host is routed by this jabberd instance
  *
@@ -321,29 +356,37 @@
 static void base_accept_routingupdate(instance i, char const* destination, int is_register, void *arg) {
     accept_instance inst = static_cast<accept_instance>(arg);
     // sanity check
-    if (!inst)
+    if (!inst || !destination)
 	return;
 
     // we only care for routingupdates if we are configured to be the uplink
     if (!deliver_is_uplink(inst->i))
 	return;
 
-    // and we have to have an established connection
-    if (!inst->m || inst->state != A_READY)
+    // we do not forward default routings
+    if (std::string("*") == destination)
 	return;
 
     // do not route back updates if both sides feel being an uplink
     if (inst->i == i)
 	return;
 
+    // and we have to have an established connection
+    if (!inst->m || inst->state != A_READY)
+	return;
+
     log_debug2(ZONE, LOGT_DYNAMIC, "base_accept is uplink and has to forward %s", is_register ? "host-command" : "unhost-command");
-    xmlnode route_stanza = xmlnode_new_tag_ns("xdb", NULL, NS_SERVER);
-    xmlnode_put_attrib_ns(route_stanza, "ns", NULL, NULL, "");
-    xmlnode_put_attrib_ns(route_stanza, "from", NULL, NULL, inst->i->id);
-    jid magic_jid = jid_new(xmlnode_pool(route_stanza), is_register ? "host at -internal" : "unhost at -internal");
-    jid_set(magic_jid, destination, JID_RESOURCE);
-    xmlnode_put_attrib_ns(route_stanza, "to", NULL, NULL, jid_full(magic_jid));
-    mio_write(inst->m, route_stanza, NULL, 0);
+    base_accept_send_routingupdate(inst, destination, is_register);
+}
+
+static void _base_accept_freeing_instance(void* arg) {
+    accept_instance inst = static_cast<accept_instance>(arg);
+
+    if (!inst)
+	return;
+
+    if (inst->dynamic_routings)
+	delete inst->dynamic_routings;
 }
 
 static result base_accept_config(instance id, xmlnode x, void *arg) {
@@ -385,6 +428,8 @@
     inst->ip          = ip;
     inst->port        = port;
     inst->timeout     = timeout;
+    inst->dynamic_routings = new std::set<std::string>();
+    pool_cleanup(id->p, _base_accept_freeing_instance, static_cast<void*>(inst));
     if (restrict_var)
         inst->restrict_var = 1;
     if (offline) {

Modified: trunk/jabberd14/jabberd/base/base_connect.cc
==============================================================================
--- trunk/jabberd14/jabberd/base/base_connect.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/base/base_connect.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -247,13 +247,17 @@
 static void base_connect_routingupdate(instance i, char const* destination, int is_register, void *arg) {
     conn_info	ci = static_cast<conn_info>(arg);
     // sanity check
-    if (!ci)
+    if (!ci || !destination)
 	return;
 
     // we only care for the routingupdates if we are configured to be the uplink
     if (!deliver_is_uplink(ci->inst))
 	return;
 
+    // we do not forward default routings
+    if (std::string("*") == destination)
+	return;
+
     // do not route updates for hosts we (un)registered ourself
     if (ci->inst == i)
 	return;

Modified: trunk/jabberd14/jabberd/config.cc
==============================================================================
--- trunk/jabberd14/jabberd/config.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/config.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -363,6 +363,9 @@
 	}
     }
 
+    // update the filter settings in the XML router
+    deliver_config_filter(greymatter__);
+
     return 0;
 }
 
@@ -386,7 +389,7 @@
  * @param f the handler function that should be registered
  * @param arg argument, that should be passed to the handler function
  */
-void register_config(pool p, char *node, cfhandler f, void *arg) {
+void register_config(pool p, char const* node, cfhandler f, void *arg) {
     cfg newg;
 
     /* create and setup */

Modified: trunk/jabberd14/jabberd/deliver.cc
==============================================================================
--- trunk/jabberd14/jabberd/deliver.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/deliver.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -129,10 +129,16 @@
 </jer> */
 
 #include "jabberd.h"
+#include <set>
+
+extern xmlnode greymatter__;
 
 int deliver__flag=0;	/**< 0 = pause delivery on startup and queue for later delivery, 1 = normal operation, -1 = shutdown: no delivery, no queueing */
 pth_msgport_t deliver__mp=NULL;	/**< message port, that contains all queued messages for later delivery while ::deliver__flag = 0 */
 
+xht filter_namespaces = NULL; /**< namespaces using in dump filters of the router */
+std::list<Glib::ustring> filter_expressions; /**< xpath expressions used for logging routed packets */
+
 /**
  * queue item for the list of queued messages for later delivery, used while ::deliver__flag = 0
  */
@@ -150,6 +156,56 @@
 } *ilist, _ilist;
 
 /**
+ * initializes or updates the dump filters of the router
+ *
+ * @param greymatter the parsed configuration file
+ */
+void deliver_config_filter(xmlnode greymatter) {
+    // remove existing expressions
+    filter_expressions.erase(filter_expressions.begin(), filter_expressions.end());
+
+    // create a new hash for the prefixes, free old one if there is already one
+    xht old_filter_namespaces = filter_namespaces;
+    filter_namespaces = xhash_new(17);
+    if (old_filter_namespaces) {
+	xhash_free(old_filter_namespaces);
+	old_filter_namespaces = NULL;
+    }
+
+    // read prefixes from configuration
+    xht namespaces = xhash_new(11);
+    pool p = pool_new();
+    xhash_put(namespaces, "", const_cast<char*>(NS_JABBERD_CONFIGFILE));
+    xmlnode_vector prefix_list = xmlnode_get_tags(greymatter, "global/router/namespace", namespaces);
+    for (xmlnode_vector::const_iterator cur = prefix_list.begin(); cur != prefix_list.end(); ++cur) {
+	char const* prefix = xmlnode_get_attrib_ns(*cur, "prefix", NULL);
+	char const* ns_iri = xmlnode_get_data(*cur);
+
+	if (prefix && ns_iri) {
+	    log_debug2(ZONE, LOGT_DELIVER, "adding namespace prefix: %s=%s", prefix, ns_iri);
+	    xhash_put(filter_namespaces, prefix, pstrdup(greymatter->p, ns_iri));
+	}
+    }
+
+    // read expressions from configuration
+    xmlnode_vector expression_list = xmlnode_get_tags(greymatter, "global/router/dump", namespaces);
+    for (xmlnode_vector::const_iterator cur = expression_list.begin(); cur != expression_list.end(); ++cur) {
+	char const* expression = xmlnode_get_data(*cur);
+
+	if (expression) {
+	    log_debug2(ZONE, LOGT_DELIVER, "adding filter expression: %s", expression);
+	    filter_expressions.push_back(expression);
+	}
+    }
+
+    // free temp memory
+    xhash_free(namespaces);
+    namespaces = NULL;
+    pool_free(p);
+    p = NULL;
+}
+
+/**
  * add an ::instance to the list of all instances
  *
  * @param il the existing list
@@ -203,6 +259,8 @@
 xht deliver__ns = NULL; /**< namespace filters for xdb */
 xht deliver__logtype = NULL; /**< log types, fixed set, but it's easier (wussier) to just be consistent and use a hashtable */
 
+std::set<Glib::ustring> null_sources; /**< source addresses that get null-routes */
+
 /* ilist deliver__all = NULL; / all instances - not used anymore!? */
 instance deliver__uplink = NULL; /**< uplink instance, only one */
 
@@ -352,6 +410,9 @@
     return i;
 }
 
+// forward reference
+static void deliver_instance(instance i, dpacket p);
+
 /**
  * special case handler for xdb calls @-internal
  *
@@ -669,6 +730,24 @@
     ilist a, b;
 
     if(deliver__flag == 1 && p == NULL && i == NULL) {
+	// server is up, get the null sources
+	xht namespaces = xhash_new(3);
+	xhash_put(namespaces, "", const_cast<char*>(NS_JABBERD_CONFIGFILE));
+	xhash_put(namespaces, "router", const_cast<char*>(NS_JABBERD_CONFIGFILE_ROUTER));
+	pool temp_pool = pool_new();
+	xmlnode_vector null_sources_e = xmlnode_get_tags(greymatter__, "global/router:router/router:routing/router:null-source", namespaces);
+	for (xmlnode_vector::const_iterator null_source = null_sources_e.begin(); null_source != null_sources_e.end(); ++null_source) {
+	    jid null_jid = jid_new(temp_pool, xmlnode_get_data(*null_source));
+	    log_debug2(ZONE, LOGT_CONFIG, "null route for %s", jid_full(null_jid));
+	    if (null_jid) {
+		null_sources.insert(Glib::ustring(jid_full(null_jid)));
+	    }
+	}
+	xhash_free(namespaces);
+	namespaces = NULL;
+	pool_free(temp_pool);
+	temp_pool = NULL;
+
 	/* send notifies for already configured routings */
 	xhash_walk(deliver_hashtable(p_LOG), _deliver_notify_walker, NULL);
 	xhash_walk(deliver_hashtable(p_XDB), _deliver_notify_walker, NULL);
@@ -688,6 +767,15 @@
     if (p == NULL)
 	 return;
 
+    // log-dump the packet?
+    if (p->type != p_LOG && filter_namespaces) {
+	for (std::list<Glib::ustring>::const_iterator cur = filter_expressions.begin(); cur != filter_expressions.end(); ++cur) {
+	    if (!xmlnode_get_tags(p->x, cur->c_str(), filter_namespaces).empty()) {
+		log_notice(NULL, "on router %s: %s", cur->c_str(), xmlnode_serialize_string(p->x, xmppd::ns_decl_list(), 0));
+	    }
+	}
+    }
+
     /* catch the @-internal xdb crap */
     if (p->type == p_XDB && *(p->host) == '-') {
         deliver_internal(p, i);
@@ -707,6 +795,23 @@
         return;
     }
 
+    // filter the packets we do not want to route (drop them instead)
+    if (p->from_jid) {
+	std::ostringstream filter_jid;
+	if (p->from_jid->has_node()) {
+	    filter_jid << p->from_jid->get_node() << '@';
+	}
+
+	filter_jid << p->from_jid->get_domain();
+
+	// is this address a null source?
+	if (null_sources.find(filter_jid.str()) != null_sources.end()) {
+	    log_notice(p->host, "Dropping packet because of configured source address. from='%s' to='%s'", jid_full(p->from_jid), jid_full(p->to_jid));
+	    pool_free(p->p);
+	    return;
+	}
+    }
+
     log_debug2(ZONE, LOGT_DELIVER, "DELIVER %d:%s %s", p->type, p->host, xmlnode_serialize_string(p->x, xmppd::ns_decl_list(), 0));
 
     b = NULL;
@@ -896,6 +1001,7 @@
 		    xmlnode_put_attrib_ns(sc, "msg", "err", NS_JABBERD_ERRMSG, err);
 
 		    jutil_tofrom(p->x);
+		    log_notice(p->host, "ended packet is: %s", xmlnode_serialize_string(p->x, xmppd::ns_decl_list(), 0));
 		    deliver(dpacket_new(p->x), NULL);
 
 		    break;
@@ -943,18 +1049,79 @@
     }
 }
 
+static void deliver_log_routing_table_walker(xht hash, char const* key, void* value, void* arg) {
+    log_notice(NULL, "  entry: %s", key);
+
+    for (ilist il = static_cast<ilist>(value); il; il = il->next) {
+	log_notice(NULL, "    routing: %s", il->i ? il->i->id : "<NULL>");
+    }
+}
+
+static void deliver_log_routing_table(int type) {
+    switch (type) {
+	case p_XDB:
+	    log_notice(NULL, ">>> Routing-Table for XDB packets:");
+	    xhash_walk(deliver__hxdb, deliver_log_routing_table_walker, NULL);
+	    log_notice(NULL, ">>> Routing-Table for NS:");
+	    xhash_walk(deliver__ns, deliver_log_routing_table_walker, NULL);
+	    break;
+	case p_LOG:
+	    log_notice(NULL, ">>> Route-Table for Log packets:");
+	    xhash_walk(deliver__hlog, deliver_log_routing_table_walker, NULL);
+	    log_notice(NULL, ">>> Routing-Table for Logtype:");
+	    xhash_walk(deliver__logtype, deliver_log_routing_table_walker, NULL);
+	    break;
+	default:
+	    log_notice(NULL, ">>> Routing-Table for normal packets:");
+	    xhash_walk(deliver__hnorm, deliver_log_routing_table_walker, NULL);
+    }
+}
+
 /**
  * actually perform the delivery to an instance
  *
  * @param i the instance to deliver to
  * @param p the packet that gets delivered (packet gets consumed)
  */
-void deliver_instance(instance i, dpacket p) {
+static void deliver_instance(instance i, dpacket p) {
     handel h, hlast;
     result r;
     dpacket pig = NULL;
 
     if (i == NULL) {
+	log_warn(NULL, "********** CANNOT DELIVER A DPACKET **********");
+	if (p) {
+	    log_warn(NULL, "p->host = %s", p->host);
+	    log_warn(NULL, "p->id = %s", jid_full(p->id));
+	    log_warn(NULL, "p->from_jid = %s", jid_full(p->from_jid));
+	    log_warn(NULL, "p->to_jid = %s", jid_full(p->to_jid));
+	    log_warn(NULL, "p->type = %s", p->type == p_NONE ? "p_NONE" : p->type == p_NORM ? "p_NORM" : p->type == p_XDB ? "p_XDB" : p->type == p_LOG ? "p_LOG" : p->type == p_ROUTE ? "p_ROUTE" : "???");
+	    log_warn(NULL, "p->p = %x", p->p);
+	    log_warn(NULL, "p->x = %s", xmlnode_serialize_string(p->x, xmppd::ns_decl_list(), 0));
+
+	    ilist a = deliver_hashmatch(deliver_hashtable(p->type), p->host);
+	    log_warn(NULL, "A list on routing calculation is:");
+	    for (ilist cur = a; cur; cur = cur->next) {
+		log_warn(NULL, "  i=%x, id=%s", cur->i, cur->i->id);
+	    }
+	    ilist b = NULL;
+	    if (p->type == p_XDB)
+		b = deliver_hashmatch(deliver__ns, xmlnode_get_attrib_ns(p->x, "ns", NULL));
+	    else if (p->type == p_LOG)
+		b = deliver_hashmatch(deliver__logtype, xmlnode_get_attrib_ns(p->x, "type", NULL));
+	    if (b) {
+		log_warn(NULL, "B list on routing calculation is:");
+		for (ilist cur = b; cur; cur = cur->next) {
+		    log_warn(NULL, "  i=%x, id=%s", cur->i, cur->i->id);
+		}
+	    } else {
+		log_warn(NULL, "B list is non-existant");
+	    }
+	} else {
+	    log_warn(NULL, "p == NULL");
+	}
+	deliver_log_routing_table(p ? p->type : p_NONE);
+
         deliver_fail(p, N_("Unable to deliver, destination unknown"));
         return;
     }
@@ -1064,11 +1231,15 @@
     if(p->type == p_XDB && (str = xmlnode_get_attrib_ns(p->x, "type", NULL)) != NULL && (*str == 'r' || *str == 'e' )) /* check full name? */
         p->type = p_NORM;
 
+    // add the to and from jid
+    p->to_jid = jid_new(p->p, xmlnode_get_attrib_ns(x, "to", NULL));
+    p->from_jid = jid_new(p->p, xmlnode_get_attrib_ns(x, "from", NULL));
+
     /* determine who to route it to, overriding the default to="" attrib only for logs where we use from */
     if(p->type == p_LOG)
-        p->id = jid_new(p->p, xmlnode_get_attrib_ns(x, "from", NULL));
+        p->id = p->from_jid;
     else
-        p->id = jid_new(p->p, xmlnode_get_attrib_ns(x, "to", NULL));
+        p->id = p->to_jid;
 
     if(p->id == NULL) {
         log_warn(NULL,"Packet Delivery Failed, invalid packet, dropping %s",xmlnode_serialize_string(x, xmppd::ns_decl_list(), 0));

Modified: trunk/jabberd14/jabberd/jabberd.h
==============================================================================
--- trunk/jabberd14/jabberd/jabberd.h	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/jabberd.h	Tue Nov 10 02:02:44 2009	(r1564)
@@ -147,6 +147,8 @@
 {
     char *host;
     jid id;
+    jid from_jid;
+    jid to_jid;
     ptype type;
     pool p;
     xmlnode x;
@@ -195,7 +197,7 @@
 typedef result (*beathandler)(void *arg);
 
 /*** public functions for base modules ***/
-void register_config(pool p, char *node, cfhandler f, void *arg); /* register a function to handle that node in the config file */
+void register_config(pool p, char const* node, cfhandler f, void *arg); /* register a function to handle that node in the config file */
 void register_beat(int freq, beathandler f, void *arg); /* register the function to be called from the heartbeat, freq is how often, <= 0 is ignored */
 typedef void(*shutdown_func)(void*arg);
 void register_shutdown(shutdown_func f,void *arg); /* register to be notified when the server is shutting down */
@@ -209,10 +211,11 @@
 dpacket dpacket_copy(dpacket p); /* copy a packet (and it's flags) */
 void deliver(dpacket p, instance i); /* deliver packet from sending instance */
 void deliver_fail(dpacket p, const char *err); /* bounce a packet intelligently */
-void deliver_instance(instance i, dpacket p); /* deliver packet TO the instance, if the result != r_DONE, you have to handle the packet! */
+// void deliver_instance(instance i, dpacket p); /* deliver packet TO the instance, if the result != r_DONE, you have to handle the packet! */
 bool deliver_is_delivered_to(Glib::ustring const& host, _instance const* i); /* util that returns the instance handling this hostname for normal packets */
 bool deliver_is_uplink(instance i); // checks if an instance is configured to be the uplink
 std::set<Glib::ustring> deliver_routed_hosts(ptype type, instance i);
+void deliver_config_filter(xmlnode greymatter);
 
 /*** global logging/signal symbols ***/
 #define LOGT_LEGACY 1
@@ -284,7 +287,7 @@
 
 xdbcache xdb_cache(instance i); /**< create a new xdb cache for this instance */
 xmlnode xdb_get(xdbcache xc,  jid owner, const char *ns); /**< blocks until namespace is retrieved, returns xmlnode or NULL if failed */
-int xdb_act(xdbcache xc, jid owner, const char *ns, char *act, char *match, xmlnode data); /**< sends new xml action, returns non-zero if failure */
+int xdb_act(xdbcache xc, jid owner, const char *ns, char *act, char const* match, xmlnode data); /**< sends new xml action, returns non-zero if failure */
 int xdb_act_path(xdbcache xc, jid owner, const char *ns, char const *act, char const* matchpath, xht namespaces, xmlnode data); /**< sends new xml action, returns non-zero if failure */
 int xdb_set(xdbcache xc, jid owner, const char *ns, xmlnode data); /**< sends new xml to replace old, returns non-zero if failure */
 
@@ -413,7 +416,10 @@
     int zzz_active;	/**< if set to something else then 1, there has been sent a signal already, that is not yet processed */
     struct karma *k;	/**< default karma */
     int rate_t, rate_p; /**< default rate, if any */
-    char *bounce_uri;	/**< where to bounce HTTP requests to */
+    char const* bounce_uri;	/**< where to bounce HTTP requests to */
+    char const* webserver_path;	/**< location where small HTTP requests are handled from */
+    char const* flash_policy;	/**< location of the flash policy file */
+
 } _ios,*ios;
 
 /* MIO SOCKET HANDLERS */
@@ -530,6 +536,9 @@
 #define mio_ip(m) (m ? m->peer_ip : NULL)
 #define mio_connect_errmsg(m) (m->connect_errmsg)
 
+// where to bounce a HTTP GET request to if not otherwise configured
+#define HTTP_BOUNCE_URI "http://jabberd.org/get-bounce"
+
 /*-----------------
  * Access controll 
  *-----------------*/

Modified: trunk/jabberd14/jabberd/lib/jabberdlib.h
==============================================================================
--- trunk/jabberd14/jabberd/lib/jabberdlib.h	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/lib/jabberdlib.h	Tue Nov 10 02:02:44 2009	(r1564)
@@ -356,7 +356,7 @@
 }
 
 #define ZONE zonestr(__FILE__,__LINE__)
-char *zonestr(char *file, int line);
+char *zonestr(char const* file, int line);
 
 /* --------------------------------------------------------- */
 /*                                                           */
@@ -1294,20 +1294,22 @@
 
 #define NS_JABBERD_CONFIGFILE "http://jabberd.org/ns/configfile" /**< namespace of the root element in the config file */
 #define NS_JABBERD_CONFIGFILE_REPLACE "http://jabberd.org/ns/configfile/replace" /**< namespace of replace and include commands */
+#define NS_JABBERD_CONFIGFILE_ROUTER "http://xmppd.org/ns/configfile/router" /**< namespace for global router configuration */
 #define NS_JABBERD_CONFIG_XDBFILE "jabber:config:xdb_file" /**< namespace of xdb_file component configuration */
 #define NS_JABBERD_CONFIG_DIALBACK "jabber:config:dialback" /**< namespace of dialback component configuration */
 #define NS_JABBERD_CONFIG_DNSRV "jabber:config:dnsrv" /**< namespace of the dnsrv component configuration */
 #define NS_JABBERD_CONFIG_JSM "jabber:config:jsm" /**< namespace of the jsm component configuration */
 #define NS_JABBERD_CONFIG_PTHCSOCK "jabber:config:pth-csock" /**< namespace of the pthsock_client component configuration */
 #define NS_JABBERD_CONFIG_XDBSQL "jabber:config:xdb_sql" /**< namepace of the xdb_sql component configuration */
+#define NS_JABBERD_CONFIG_DYNAMICHOST "http://xmppd.org/ns/dynamichost" /**< namespace of the dynamic configuration of additional hosts for components */
 
 /* --------------------------------------------------------- */
 /*                                                           */
 /* JUtil functions                                           */
 /*                                                           */
 /* --------------------------------------------------------- */
-xmlnode jutil_presnew(int type, char *to, const char *status); /* Create a skeleton presence packet */
-xmlnode jutil_iqnew(int type, char *ns);		 /* Create a skeleton iq packet */
+xmlnode jutil_presnew(int type, char const* to, const char *status); /* Create a skeleton presence packet */
+xmlnode jutil_iqnew(int type, char const* ns);		 /* Create a skeleton iq packet */
 xmlnode jutil_msgnew(char const* type, char const* to, char const* subj, char const* body);
 							 /* Create a skeleton message packet */
 int     jutil_priority(xmlnode x);			 /* Determine priority of this packet */
@@ -1318,7 +1320,7 @@
 void    jutil_error(xmlnode x, terror E);		 /* Append an <error> node to x */
 void    jutil_error_xmpp(xmlnode x, xterror E);		 /* Append an <error> node to x using XMPP syntax */
 void	jutil_error_map(terror old, xterror *mapped);	 /* map an old terror structure to a new xterror structure */
-void    jutil_delay(xmlnode msg, char *reason);		 /* Append a delay packet to msg */
+void    jutil_delay(xmlnode msg, char const* reason);		 /* Append a delay packet to msg */
 char*   jutil_regkey(char *key, char *seed);		 /* pass a seed to generate a key, pass the key again to validate (returns it) */
 
 /* --------------------------------------------------------- */

Modified: trunk/jabberd14/jabberd/lib/jutil.cc
==============================================================================
--- trunk/jabberd14/jabberd/lib/jutil.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/lib/jutil.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -43,7 +43,7 @@
  * @param status optional status (CDATA for the &lt;status/&gt; element, NULL for no &lt;status/&gt; element)
  * @return the xmlnode containing the created presence stanza
  */
-xmlnode jutil_presnew(int type, char *to, const char *status) {
+xmlnode jutil_presnew(int type, char const* to, char const* status) {
     xmlnode pres;
 
     pres = xmlnode_new_tag_ns("presence", NULL, NS_SERVER);

Modified: trunk/jabberd14/jabberd/lib/str.cc
==============================================================================
--- trunk/jabberd14/jabberd/lib/str.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/lib/str.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -326,7 +326,7 @@
     return temp;
 }
 
-char *zonestr(char *file, int line)
+char *zonestr(char const* file, int line)
 {
     static char buff[64];
     int i;

Modified: trunk/jabberd14/jabberd/mio.cc
==============================================================================
--- trunk/jabberd14/jabberd/mio.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/mio.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -1109,8 +1109,10 @@
         pth_yield(NULL);
     }
 
-    /* where to bounce HTTP requests to */
+    // HTTP configuration
     mio__data->bounce_uri = pstrdup(mio__data->p, xmlnode_get_data(xmlnode_get_list_item(xmlnode_get_tags(io, "bounce", namespaces), 0)));
+    mio__data->webserver_path = pstrdup(mio__data->p, xmlnode_get_data(xmlnode_get_list_item(xmlnode_get_tags(io, "mini-webserver", namespaces), 0)));
+    mio__data->flash_policy = pstrdup(mio__data->p, xmlnode_get_data(xmlnode_get_list_item(xmlnode_get_tags(io, "flash-policy", namespaces), 0)));
 
     if (karma != NULL) {
         mio__data->k->val	  = j_atoi(xmlnode_get_data(xmlnode_get_list_item(xmlnode_get_tags(karma, "init", namespaces), 0)), KARMA_INIT);

Modified: trunk/jabberd14/jabberd/mio_tls.cc
==============================================================================
--- trunk/jabberd14/jabberd/mio_tls.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/mio_tls.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -596,7 +596,7 @@
 	    continue;
 	}
 
-	/*
+#ifdef HAS_NEW_GNUTLS
 	// load an OpenPGP key
 	if (j_strcmp(xmlnode_get_localname(cur), "openpgp") == 0) {
 	    char const *const pubfile = xmlnode_get_data(cur);
@@ -640,7 +640,7 @@
 
 	    continue;
 	}
-	*/
+#endif
 
 	// setup protocols to use
 	if (j_strcmp(xmlnode_get_localname(cur), "protocols") == 0) {

Modified: trunk/jabberd14/jabberd/mio_xml.cc
==============================================================================
--- trunk/jabberd14/jabberd/mio_xml.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/mio_xml.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -39,6 +39,8 @@
  */
 
 #include <jabberd.h>
+#include <fstream>
+#include <libgen.h>
 
 /* defined in mio.c */
 extern ios mio__data;
@@ -328,21 +330,170 @@
     /* init the parser if this is the first read call */
     if (m->parser == NULL) {
         _mio_xstream_init(m);
+
         /* XXX pretty big hack here, if the initial read contained a nul, assume nul-packet-terminating format stream */
-        if((nul = strchr(buf,'\0')) != NULL && (nul - buf) < bufsz)
-        {
+        if((nul = strchr(buf,'\0')) != NULL && (nul - buf) < bufsz) {
             m->type = type_NUL;
             nul[-2] = ' '; /* assume it's .../>0 and make the stream open again */
         }
-        /* XXX another big hack/experiment, for bypassing dumb proxies */
-        if(*buf == 'P')
-            m->type = type_HTTP;
-
-	/* Bounce HTTP-GET-Requests to the configured host */
-	if(*buf == 'G' && mio__data->bounce_uri != NULL) {
-	    mio_write(m, NULL, "HTTP/1.1 301 Moved permanently\r\nServer: " PACKAGE " " VERSION "\r\nConnection: close\r\nLocation: ", -1);
-	    mio_write(m, NULL, mio__data->bounce_uri, -1);
-	    mio_write(m, NULL, "\r\n\r\n", -1);
+
+	// Check for HTTP requests, extract first line for that reason
+	std::string buffer_data(buf, bufsz);
+	std::istringstream buffer_stream(buffer_data);
+	std::string first_line;
+	std::getline(buffer_stream, first_line);
+
+	// PUT/POST requests are a legacy hack to bypass some HTTP proxies
+	// Note: Most HTTP proxies do not forward these PUT/POST requests
+	// of Jabber. Using proxy CONNECT with a jabberd listening on port
+	// 443 seems to work better.
+	if (first_line.substr(0, 1) == "P") {
+	    m->type = type_HTTP;
+	}
+
+	// GET requests: first check if we do serve our own file, else we might
+	// have been configured to forward the request to some URI.
+	if (first_line.substr(0, 4) == "GET ") {
+	    // extract path and protocol
+	    std::istringstream first_line_stream(first_line.substr(4));
+	    std::string request_path;
+	    std::string request_protocol;
+	    first_line_stream >> request_path >> request_protocol;
+	    log_debug2(ZONE, LOGT_IO, "handling HTTP-GET path=%s, protocol=%s", request_path.c_str(), request_protocol.c_str());
+
+	    // internal mini webserver enabled?
+	    if (mio__data->webserver_path) {
+		char request_path_copy[1024] = "";
+		snprintf(request_path_copy, sizeof(request_path_copy), "%s", request_path.c_str());
+		request_path_copy[sizeof(request_path_copy)-1] = 0; // make sure the string is terminated
+		std::string request_basename = ::basename(request_path_copy);
+		if (request_basename == "/" || request_basename == "") {
+		    request_basename = "index.html";
+		}
+		log_debug2(ZONE, LOGT_IO, "GET request processing for file %s", request_basename.c_str());
+
+		// check that the file is not a directory
+		std::string filename = std::string(mio__data->webserver_path) + "/" + request_basename;
+		struct stat stat_buf;
+		int stat_ret = ::stat(filename.c_str(), &stat_buf);
+		if (stat_ret == 0 && S_ISREG(stat_buf.st_mode)) {
+		    // try to open file
+		    std::ifstream file (filename.c_str(), std::ifstream::binary);
+		    if (file.is_open()) {
+			// get the file size
+			file.seekg(0, std::ios::end);
+			std::streampos file_size = file.tellg();
+			file.seekg(0, std::ios::beg);
+
+			if (file_size >= 1024*1024) {
+			    log_error(NULL, "mini-webserver tried to return %s (size: %i B) which is bigger than 1 MiB. Not able to handle that big files", filename.c_str(), static_cast<int>(file_size));
+
+			    std::string message ("Request entity too large\r\n");
+
+			    std::ostringstream http_result;
+			    http_result << (request_protocol == "" || request_protocol == "HTTP/1.0" ? "HTTP/1.0" : "HTTP/1.1") << " 413 Request entity too large\r\n";
+			    http_result << "Server: " PACKAGE " " VERSION "\r\n";
+			    http_result << "Connection: close\r\n";
+			    http_result << "Content-Length: " << message.length() << "\r\n";
+			    http_result << "Content-Type: text/plain; charset=utf-8\r\n";
+			    http_result << "\r\n";
+			    http_result << message;
+
+			    mio_write(m, NULL, http_result.str().c_str(), http_result.str().length());
+			    mio_close(m);
+			} else {
+			    if (file_size >= 1024*100) {
+				log_warn(NULL, "Warning: mini-webserver is returning %s (size: %i B). You should not use jabberd to handle big files!", filename.c_str(), static_cast<int>(file_size));
+			    }
+
+			    char* result_buffer = new char[file_size];
+
+			    file.read(result_buffer, file_size);
+
+			    std::ostringstream http_result;
+			    http_result << (request_protocol == "" || request_protocol == "HTTP/1.0" ? "HTTP/1.0" : "HTTP/1.1") << " 200 OK\r\n";
+			    http_result << "Server: " PACKAGE " " VERSION "\r\n";
+			    http_result << "Connection: close\r\n";
+			    http_result << "Content-Length: " << file_size << "\r\n";
+			    http_result << "Content-Type: text/html\r\n";
+			    http_result << "\r\n";
+			    http_result << std::string(result_buffer, file_size);
+
+			    delete[] result_buffer;
+
+			    mio_write(m, NULL, http_result.str().c_str(), http_result.str().length());
+			    mio_close(m);
+			}
+
+			// close the file
+			file.close();
+
+			// we handle the request
+			return;
+		    }
+		}
+	    }
+
+	    // no document returned, send a bounce
+	    std::ostringstream http_result;
+	    http_result << (request_protocol == "" || request_protocol == "HTTP/1.0" ? "HTTP/1.0" : "HTTP/1.1") << " 301 Moved permanently\r\n";
+	    http_result << "Server: " PACKAGE " " VERSION "\r\n";
+	    http_result << "Connection: close\r\n";
+	    // bounce to a configured host?
+	    if (mio__data->bounce_uri) {
+		http_result << "Location: " << mio__data->bounce_uri << "\r\n";
+	    } else {
+		http_result << "Location: " HTTP_BOUNCE_URI "\r\n";
+	    }
+	    http_result << "\r\n";
+
+	    mio_write(m, NULL, http_result.str().c_str(), http_result.str().length());
+	    mio_close(m);
+
+	    // we handled the request now
+	    return;
+	}
+
+	// check for Flash policy requests
+	if (first_line.substr(0, 20) == "<policy-file-request") {
+	    // reset type to type_NORMAL, else mio will add a "/>" to the data that is sent back
+	    m->type = type_NORMAL;
+
+	    // is there a configured flash policy?
+	    if (mio__data->flash_policy) {
+		struct stat stat_buf;
+		int stat_ret = ::stat(mio__data->flash_policy, &stat_buf);
+		if (stat_ret == 0 && S_ISREG(stat_buf.st_mode)) {
+		    // try to open file
+		    std::ifstream file(mio__data->flash_policy, std::ifstream::binary);
+		    if (file.is_open()) {
+			// get the file size
+			file.seekg(0, std::ios::end);
+			std::streampos file_size = file.tellg();
+			file.seekg(0, std::ios::beg);
+
+			if (file_size < 1024*1024) {
+			    char* result_buffer = new char[file_size];
+			    file.read(result_buffer, file_size);
+			    std::string result_string(result_buffer, file_size);
+			    mio_write(m, NULL, result_string.c_str(), result_string.length()+1);
+			    delete[] result_buffer;
+
+			    mio_close(m);
+			    file.close();
+			    return;
+			}
+
+			log_warn(NULL, "Flash policy file is too big for being returned to the flash client.");
+			file.close();
+		    }
+		}
+	    }
+
+	    // no configured flash policy, or policy too big. Send default
+	    std::string default_policy("<?xml version='1.0'?>\n<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\n<cross-domain-policy/>\n");
+	    log_notice(NULL, "Received Flash policy-file-request, but non is configured. Returning (empty) default policy.");
+	    mio_write(m, NULL, default_policy.c_str(), default_policy.length()+1); // length()+1 because we want to send the NULL byte as well
 	    mio_close(m);
 	    return;
 	}

Modified: trunk/jabberd14/jabberd/xdb.cc
==============================================================================
--- trunk/jabberd14/jabberd/xdb.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jabberd/xdb.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -332,11 +332,11 @@
     return 0;
 }
 
-int xdb_act(xdbcache xc, jid owner, const char *ns, char *act, char *match, xmlnode data) {
+int xdb_act(xdbcache xc, jid owner, char const* ns, char const* act, char const* match, xmlnode data) {
     return _xdb_act(xc, owner, ns, act, match, NULL, NULL, data);
 }
 
-int xdb_act_path(xdbcache xc, jid owner, const char *ns, char const* act, char const* matchpath, xht namespaces, xmlnode data) {
+int xdb_act_path(xdbcache xc, jid owner, char const* ns, char const* act, char const* matchpath, xht namespaces, xmlnode data) {
     return _xdb_act(xc, owner, ns, act, NULL, matchpath, namespaces, data);
 }
 

Modified: trunk/jabberd14/jsm/jsm.cc
==============================================================================
--- trunk/jabberd14/jsm/jsm.cc	Sun Nov  1 03:09:09 2009	(r1563)
+++ trunk/jabberd14/jsm/jsm.cc	Tue Nov 10 02:02:44 2009	(r1564)
@@ -201,6 +201,7 @@
     xhash_put(si->std_namespace_prefixes, "jabberd", const_cast<char*>(NS_JABBERD_WRAPPER));
     xhash_put(si->std_namespace_prefixes, "cmd", const_cast<char*>(NS_COMMAND));
     xhash_put(si->std_namespace_prefixes, "data", const_cast<char*>(NS_DATA));
+    xhash_put(si->std_namespace_prefixes, "dhost", const_cast<char*>(NS_JABBERD_CONFIG_DYNAMICHOST));
     si->xc = xdb_cache(i); /* getting xdb_* handle and fetching config */
     config = js_config(si, NULL, NULL);
     si->hosts = xhash_new(j_atoi(xmlnode_get_data(xmlnode_get_list_item(xmlnode_get_tags(config, "jsm:maxhosts", si->std_namespace_prefixes), 0)), HOSTS_PRIME));


More information about the dev mailing list