[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