📄 deliver.c
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL"). You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/. * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights * * Portions created by or assigned to Jabber.com, Inc. are * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. * * Acknowledgements * * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. * * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above. If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL. If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL. * * * --------------------------------------------------------------------------*//* WARNING: the comments in here are random ramblings across the timespan this file has lived, don't rely on them for anything except entertainment (and if this entertains you, heh, you need to get out more :)<jer mode="pondering">ok, the whole <xdb/> <log/> <service/> and id="" and <host/> have gotten us this far, barely, but it needs some rethought.there seem to be four types of conversations, xdb, log, route, and normal packetseach type can be sub-divided based on different criteria, such as hostname, namespace, log type, etc.to do this right, base modules need to be able to assert their own logic within the delivery processand we need to do it efficientlyand logically, so the administrator is able to understand where the packets are flowingupon startup, like normal configuration directive callbacks, base modules can register a filter config callback with an arg per-type (xdb/log/service)configuration calls each one of those, which use the arg to identify the instance that they are withinthis one is special, jabberd tracks which instances each callback is associated with based on during configuration, jabberd tracks which base modules were calledso during the configuration process, each base module registers a callback PER-INSTANCE that it's configured infirst, break down byfirst step with a packet to be delivered is identify the instance it belongs tofilter_hostfilter_nsfilter_logtypeit's an & operation, host & ns must have to matchfirst get type (xdb/log/svc)then find which filters for the list of instancesthen ask each filter to return a sub-setafter all the filters, deliver to the final instance(s)what if we make <route/> addressing seperate, and only use the id="" for it?we need to add a <drain> ... <drain> which matches any undelivered packet, and can send to another jabberd via accept/exec/stdout/etc</jer><jer mode="pretty sure">id="" is only required on servicesHT host_normHT host_xdbHT host_logHT nsilist log_notice, log_alert, log_warningto deliver the dpacket, first check the right host hashtable and get a listsecond, if it's xdb or log, check the ns HT or log type listfind intersection of listsif a host, ns, or type is used in any instance, it must be used in ALL of that type, or configuration error!if intersection has multiple results, fail, or none, find uplink or faildeliver() deliver_norm if(host_norm != NULL) ilista = host_norm(host) deliver_xdb if(host_xdb != NULL) ilista = host_xdb(host) if(ns != NULL) ilistb = ns(namespace) i = intersect(ilista, ilistb) if result multiple, return NULL if result single, return if result NULL, return uplink deliver_instance(i) deliver_log host_log, if logtype_flag switch on type</jer> */#include "jabberd.h"extern pool jabberd__runtime;int deliver__flag=0;pth_msgport_t deliver__mp=NULL;typedef struct deliver_mp_st{ pth_message_t head; instance i; dpacket p;} _deliver_msg,*deliver_msg;typedef struct ilist_struct{ instance i; struct ilist_struct *next;} *ilist, _ilist;ilist ilist_add(ilist il, instance i){ ilist cur, ilnew; for(cur = il; cur != NULL; cur = cur->next) if(cur->i == i) return cur; ilnew = pmalloco(i->p, sizeof(_ilist)); ilnew->i = i; ilnew->next = il; return ilnew;}ilist ilist_rem(ilist il, instance i){ ilist cur; if(il == NULL) return NULL; if(il->i == i) return il->next; for(cur = il; cur->next != NULL; cur = cur->next) if(cur->next->i == i) { cur->next = cur->next->next; return il; } return il;}/* XXX handle removing things from the list too, yuck *//* set up our global delivery logic tracking vars */xht deliver__hnorm = NULL; /* hosts for normal packets, important and most frequently used one */xht deliver__hxdb = NULL; /* host filters for xdb requests */xht deliver__hlog = NULL; /* host filters for logging */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 */ilist deliver__all = NULL; /* all instances */instance deliver__uplink = NULL; /* uplink instance, only one *//* utility to find the right hashtable based on type */xht deliver_hashtable(ptype type){ switch(type) { case p_LOG: return deliver__hlog; case p_XDB: return deliver__hxdb; default: return deliver__hnorm; }}/* utility to find the right ilist in the hashtable */ilist deliver_hashmatch(xht ht, char *key){ ilist l; l = xhash_get(ht, key); if(l == NULL) { l = xhash_get(ht, "*"); } return l;}/* find and return the instance intersecting both lists, or react intelligently */instance deliver_intersect(ilist a, ilist b){ ilist cur = NULL, cur2; instance i = NULL; if(a == NULL) cur = b; if(b == NULL) cur = a; if(cur != NULL) /* we've only got one list */ { if(cur->next != NULL) return NULL; /* multiple results is a failure */ else return cur->i; } for(cur = a; cur != NULL; cur = cur->next) { for(cur2 = b; cur2 != NULL; cur2 = cur2->next) { if(cur->i == cur2->i) /* yay, intersection! */ { if(i != NULL) return NULL; /* multiple results is a failure */ i = cur->i; } } } if(i == NULL) /* no match, use uplink */ return deliver__uplink; return i;}/* special case handler for xdb calls @-internal */void deliver_internal(dpacket p, instance i){ xmlnode x; char *ns = xmlnode_get_attrib(p->x, "ns"); log_debug2(ZONE, LOGT_DELIVER, "@-internal processing %s",xmlnode2str(p->x)); if(j_strcmp(p->id->user,"config") == 0) { /* config@-internal means it's a special xdb request to get data from the config file */ for(x = xmlnode_get_firstchild(i->x); x != NULL; x = xmlnode_get_nextsibling(x)) { if(j_strcmp(xmlnode_get_attrib(x,"xmlns"),ns) != 0) continue; /* insert results */ xmlnode_insert_tag_node(p->x, x); } /* reformat packet as a reply */ xmlnode_put_attrib(p->x,"type","result"); jutil_tofrom(p->x); p->type = p_NORM; /* deliver back to the sending instance */ deliver_instance(i, p); return; } if(j_strcmp(p->id->user,"host") == 0) { /* dynamic register_instance crap */ register_instance(i,p->id->resource); return; } if(j_strcmp(p->id->user,"unhost") == 0) { /* dynamic register_instance crap */ unregister_instance(i,p->id->resource); return; }}/* register this instance as a possible recipient of packets to this host */void register_instance(instance i, char *host){ ilist l; xht ht; log_debug2(ZONE, LOGT_REGISTER, "Registering %s with instance %s", host, i->id); /* fail, since ns is required on every XDB instance if it's used on any one */ if(i->type == p_XDB && deliver__ns != NULL && xmlnode_get_tag(i->x, "ns") == NULL) { fprintf(stderr, "Configuration Error! If <ns> is used in any xdb section, it must be used in all sections for correct packet routing."); exit(1); } /* fail, since logtype is required on every LOG instance if it's used on any one */ if(i->type == p_LOG && deliver__logtype != NULL && xmlnode_get_tag(i->x, "logtype") == NULL) { fprintf(stderr, "Configuration Error! If <logtype> is used in any log section, it must be used in all sections for correct packet routing."); exit(1); } ht = deliver_hashtable(i->type); l = xhash_get(ht, host); l = ilist_add(l, i); xhash_put(ht, pstrdup(i->p,host), (void *)l);}void unregister_instance(instance i, char *host){ ilist l; xht ht; log_debug2(ZONE, LOGT_REGISTER, "Unregistering %s with instance %s",host,i->id); ht = deliver_hashtable(i->type); l = xhash_get(ht, host); l = ilist_rem(l, i); if(l == NULL) xhash_zap(ht, host); else xhash_put(ht, pstrdup(i->p,host), (void *)l);}result deliver_config_host(instance i, xmlnode x, void *arg){ char *host; int c; if(i == NULL) return r_PASS; host = xmlnode_get_data(x); if(host == NULL) { register_instance(i, "*"); return r_DONE; } for(c = 0; host[c] != '\0'; c++) if(isspace((int)host[c])) { xmlnode_put_attrib(x,"error","The host tag contains illegal whitespace."); return r_ERR; } register_instance(i, host); return r_DONE;}result deliver_config_ns(instance i, xmlnode x, void *arg){ ilist l; char *ns, star[] = "*"; if(i == NULL) return r_PASS; if(i->type != p_XDB) return r_ERR; ns = xmlnode_get_data(x); if(ns == NULL) ns = pstrdup(xmlnode_pool(x),star); log_debug2(ZONE, LOGT_INIT|LOGT_STORAGE|LOGT_REGISTER, "Registering namespace %s with instance %s",ns,i->id); if(deliver__ns == NULL) deliver__ns = xhash_new(401); l = xhash_get(deliver__ns, ns); l = ilist_add(l, i); xhash_put(deliver__ns, ns, (void *)l); return r_DONE;}result deliver_config_logtype(instance i, xmlnode x, void *arg){ ilist l; char *type, star[] = "*"; if(i == NULL) return r_PASS; if(i->type != p_LOG) return r_ERR; type = xmlnode_get_data(x); if(type == NULL) type = pstrdup(xmlnode_pool(x),star); log_debug2(ZONE, LOGT_REGISTER, "Registering logtype %s with instance %s",type,i->id); if(deliver__logtype == NULL) deliver__logtype = xhash_new(401); l = xhash_get(deliver__logtype, type); l = ilist_add(l, i); xhash_put(deliver__logtype, type, (void *)l); return r_DONE;}result deliver_config_uplink(instance i, xmlnode x, void *arg){ if(i == NULL) return r_PASS; if(deliver__uplink != NULL) return r_ERR; deliver__uplink = i; return r_DONE;}/* NULL that sukkah! */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -