[xmppd-dev] commit r1543 - in branches/RELEASE-1_6_1: . jabberd/base

mail at jabberd.org mail at jabberd.org
Tue Nov 25 23:55:44 CET 2008


Author: mawis
Date: Tue Nov 25 23:55:44 2008
New Revision: 1543

Log:
There had been a problem with dynamic routings (host/unhost) between jabberd processes if on process restarted: the other process might still route stanzas the other process registered for to this process, while this might not know how to handle it after a restart. Especially this caused loops after a s2s process restarted.
Dynamic routings are not removed when the peer disconnects.

Modified:
   branches/RELEASE-1_6_1/ChangeLog
   branches/RELEASE-1_6_1/jabberd/base/base_accept.cc

Modified: branches/RELEASE-1_6_1/ChangeLog
==============================================================================
--- branches/RELEASE-1_6_1/ChangeLog	Sun Nov 23 00:54:33 2008	(r1542)
+++ branches/RELEASE-1_6_1/ChangeLog	Tue Nov 25 23:55:44 2008	(r1543)
@@ -1,3 +1,8 @@
+2008-11-25  Matthias Wimmer  <m at tthias.eu>
+
+    * jabberd/base/base_accept.cc: improvement in failure recovery for dynamic
+    	routings
+
 2008-11-22  Matthias Wimmer  <m at tthias.eu>
 
     * jabberd/mio_tls.cc: method signatures for OpenPGP support have changed

Modified: branches/RELEASE-1_6_1/jabberd/base/base_accept.cc
==============================================================================
--- branches/RELEASE-1_6_1/jabberd/base/base_accept.cc	Sun Nov 23 00:54:33 2008	(r1542)
+++ branches/RELEASE-1_6_1/jabberd/base/base_accept.cc	Tue Nov 25 23:55:44 2008	(r1543)
@@ -58,7 +58,7 @@
     xdbcache offline;
     jid offjid;
     jqueue q;
-    /* dpacket dplast; */
+    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) {
@@ -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,6 +86,25 @@
     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) {
@@ -117,16 +128,8 @@
         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)
-                {
+		/* if we are supposed to be careful about what comes from this socket */
+                if (ai->restrict_var) {
                     jp = jpacket_new(x);
                     if(jp->type == JPACKET_UNKNOWN || jp->to == NULL || jp->from == NULL || deliver_hostcheck(jp->from->server) != ai->i)
                     {
@@ -136,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->server && std::string("-internal") == p->id->server && p->id->user) {
+		    // check for host at -internal
+		    if (std::string("host") == p->id->user && p->id->resource) {
+			ai->dynamic_routings->insert(p->id->resource);
+		    }
+
+		    // XXX might check for unhost as well
+		}
+
+                deliver(p, ai->i);
                 return;
             }
 
@@ -207,10 +223,6 @@
 		}
 	    }
 
-
-
-
-
             break;
 
         case MIO_ERROR:
@@ -220,10 +232,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:
@@ -231,10 +248,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;
@@ -348,6 +368,16 @@
     mio_write(inst->m, route_stanza, NULL, 0);
 }
 
+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) {
     char *secret = NULL;
     accept_instance inst;
@@ -392,6 +422,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) {


More information about the dev mailing list