[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 <status/> element, NULL for no <status/> 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