jabberd2  2.2.16
sm/mm.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
00004  *                    Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00021 #include "sm.h"
00022 
00023 #ifdef _WIN32
00024 # define LIBRARY_DIR "."
00025 # include <windows.h>
00026 #else
00027 # include <dlfcn.h>
00028 #endif /* _WIN32 */
00029 
00037 /* these functions implement a multiplexor to get calls to the correct module
00038  * for the given type */
00039 
00040 /* Notes on dynamic modules (cedricv@) :
00041    Modules are searched by name mod_[modulename].so or mod_[modulename].dll
00042    depending platform.
00043    You have to set <path>[full_path]</path> within <modules> in sm.xml config,
00044    else it will only search in LD_LIBRARY_PATH or c:\windows\system32
00045  */
00046 
00047 mm_t mm_new(sm_t sm) {
00048     mm_t mm;
00049     int celem, melem, attr, *nlist = NULL;
00050     char id[13], name[32], mod_fullpath[PATH_MAX], arg[1024], *modules_path;
00051     mod_chain_t chain = (mod_chain_t) NULL;
00052     mod_instance_t **list = NULL, mi;
00053     module_t mod;
00054 
00055     mm = (mm_t) calloc(1, sizeof(struct mm_st));
00056 
00057     mm->sm = sm;
00058     mm->modules = xhash_new(101);
00059 
00060     if((celem = nad_find_elem(sm->config->nad, 0, -1, "modules", 1)) < 0)
00061         return mm;
00062 
00063     modules_path = config_get_one(sm->config, "modules.path", 0);
00064     if (modules_path != NULL)
00065         log_write(sm->log, LOG_NOTICE, "modules search path: %s", modules_path);
00066     else
00067         log_write(sm->log, LOG_NOTICE, "modules search path undefined, using deafult: "LIBRARY_DIR);
00068 
00069     celem = nad_find_elem(sm->config->nad, celem, -1, "chain", 1);
00070     while(celem >= 0) {
00071         if((attr = nad_find_attr(sm->config->nad, celem, -1, "id", NULL)) < 0) {
00072             celem = nad_find_elem(sm->config->nad, celem, -1, "chain", 0);
00073             continue;
00074         }
00075 
00076         snprintf(id, 13, "%.*s", NAD_AVAL_L(sm->config->nad, attr), NAD_AVAL(sm->config->nad, attr));
00077         id[12] = '\0';
00078 
00079         log_debug(ZONE, "processing config for chain '%s'", id);
00080 
00081         list = NULL;
00082         if(strcmp(id, "sess-start") == 0) {
00083             chain = chain_SESS_START;
00084             list = &mm->sess_start;
00085             nlist = &mm->nsess_start;
00086         }
00087         else if(strcmp(id, "sess-end") == 0) {
00088             chain = chain_SESS_END;
00089             list = &mm->sess_end;
00090             nlist = &mm->nsess_end;
00091         }
00092         else if(strcmp(id, "in-sess") == 0) {
00093             chain = chain_IN_SESS;
00094             list = &mm->in_sess;
00095             nlist = &mm->nin_sess;
00096         }
00097         else if(strcmp(id, "in-router") == 0) {
00098             chain = chain_IN_ROUTER;
00099             list = &mm->in_router;
00100             nlist = &mm->nin_router;
00101         }
00102         else if(strcmp(id, "out-sess") == 0) {
00103             chain = chain_OUT_SESS;
00104             list = &mm->out_sess;
00105             nlist = &mm->nout_sess;
00106         }
00107         else if(strcmp(id, "out-router") == 0) {
00108             chain = chain_OUT_ROUTER;
00109             list = &mm->out_router;
00110             nlist = &mm->nout_router;
00111         }
00112         else if(strcmp(id, "pkt-sm") == 0) {
00113             chain = chain_PKT_SM;
00114             list = &mm->pkt_sm;
00115             nlist = &mm->npkt_sm;
00116         }
00117         else if(strcmp(id, "pkt-user") == 0) {
00118             chain = chain_PKT_USER;
00119             list = &mm->pkt_user;
00120             nlist = &mm->npkt_user;
00121         }
00122         else if(strcmp(id, "pkt-router") == 0) {
00123             chain = chain_PKT_ROUTER;
00124             list = &mm->pkt_router;
00125             nlist = &mm->npkt_router;
00126         }
00127         else if(strcmp(id, "user-load") == 0) {
00128             chain = chain_USER_LOAD;
00129             list = &mm->user_load;
00130             nlist = &mm->nuser_load;
00131         }
00132         else if(strcmp(id, "user-unload") == 0) {
00133             chain = chain_USER_UNLOAD;
00134             list = &mm->user_unload;
00135             nlist = &mm->nuser_unload;
00136         }
00137         else if(strcmp(id, "user-create") == 0) {
00138             chain = chain_USER_CREATE;
00139             list = &mm->user_create;
00140             nlist = &mm->nuser_create;
00141         }
00142         else if(strcmp(id, "user-delete") == 0) {
00143             chain = chain_USER_DELETE;
00144             list = &mm->user_delete;
00145             nlist = &mm->nuser_delete;
00146         }
00147         else if(strcmp(id, "disco-extend") == 0) {
00148             chain = chain_DISCO_EXTEND;
00149             list = &mm->disco_extend;
00150             nlist = &mm->ndisco_extend;
00151         }
00152 
00153         if(list == NULL) {
00154             log_write(sm->log, LOG_ERR, "unknown chain type '%s'", id);
00155 
00156             celem = nad_find_elem(sm->config->nad, celem, -1, "chain", 0);
00157             continue;
00158         }
00159 
00160         melem = nad_find_elem(sm->config->nad, celem, -1, "module", 1);
00161         while(melem >= 0) {
00162             if(NAD_CDATA_L(sm->config->nad, melem) <= 0) {
00163                 melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
00164                 continue;
00165             }
00166 
00167             arg[0] = '\0';
00168             attr = nad_find_attr(sm->config->nad, melem, -1, "arg", NULL);
00169             if(attr >= 0) {
00170                 snprintf(arg, 1024, "%.*s", NAD_AVAL_L(sm->config->nad, attr), NAD_AVAL(sm->config->nad, attr));
00171                 log_debug(ZONE, "module arg: %s", arg);
00172             }
00173 
00174             snprintf(name, 32, "%.*s", NAD_CDATA_L(sm->config->nad, melem), NAD_CDATA(sm->config->nad, melem));
00175 
00176             mod = xhash_get(mm->modules, name);
00177             if(mod == NULL) {
00178                 mod = (module_t) calloc(1, sizeof(struct module_st));
00179 
00180                 mod->mm = mm;
00181                 mod->index = mm->nindex;
00182                 mod->name = strdup(name);
00183                 #ifndef _WIN32
00184                   if (modules_path != NULL)
00185                       snprintf(mod_fullpath, PATH_MAX, "%s/mod_%s.so", modules_path, name);
00186                   else
00187                       snprintf(mod_fullpath, PATH_MAX, "%s/mod_%s.so", LIBRARY_DIR, name);
00188                   mod->handle = dlopen(mod_fullpath, RTLD_LAZY);
00189                   if (mod->handle != NULL)
00190                       mod->module_init_fn = dlsym(mod->handle, "module_init");
00191                 #else
00192                   if (modules_path != NULL)
00193                       snprintf(mod_fullpath, PATH_MAX, "%s\\mod_%s.dll", modules_path, name);
00194                   else
00195                       snprintf(mod_fullpath, PATH_MAX, "mod_%s.dll", name);
00196                   mod->handle = (void*) LoadLibrary(mod_fullpath);
00197                   if (mod->handle != NULL)
00198                       mod->module_init_fn = (int (*)(mod_instance_t))GetProcAddress((HMODULE) mod->handle, "module_init");
00199                 #endif
00200 
00201                 if (mod->handle != NULL && mod->module_init_fn != NULL) {
00202                     log_debug(ZONE, "preloaded module '%s' to chain '%s' (not added yet)", name, id);
00203                         xhash_put(mm->modules, mod->name, (void *) mod);
00204                         mm->nindex++;
00205                 } else {
00206                     #ifndef _WIN32
00207                       log_write(sm->log, LOG_ERR, "failed loading module '%s' to chain '%s' (%s)", name, id, dlerror());
00208                       if (mod->handle != NULL)
00209                           dlclose(mod->handle);
00210                     #else
00211                       log_write(sm->log, LOG_ERR, "failed loading module '%s' to chain '%s' (errcode: %x)", name, id, GetLastError());
00212                       if (mod->handle != NULL)
00213                           FreeLibrary((HMODULE) mod->handle);
00214                     #endif
00215 
00216                     melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
00217                     continue;
00218                 }
00219             }
00220 
00221             mi = (mod_instance_t) calloc(1, sizeof(struct mod_instance_st));
00222 
00223             mi->sm = sm;
00224             mi->mod = mod;
00225             mi->chain = chain;
00226             mi->arg = (arg[0] == '\0') ? NULL : strdup(arg);
00227             mi->seq = mod->init;
00228 
00229             if(mod->module_init_fn(mi) != 0) {
00230                 log_write(sm->log, LOG_ERR, "init for module '%s' (seq %d) failed", name, mi->seq);
00231                 free(mi);
00232 
00233                 if(mod->init == 0) {
00234                     xhash_zap(mm->modules, mod->name);
00235 
00236                     #ifndef _WIN32
00237                       if (mod->handle != NULL)
00238                           dlclose(mod->handle);
00239                     #else
00240                       if (mod->handle != NULL)
00241                           FreeLibrary((HMODULE) mod->handle);
00242                     #endif
00243 
00244                     free(mod->name);
00245                     free(mod);
00246 
00247                     mm->nindex--;
00248 
00249                     melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
00250                     continue;
00251                 }
00252             }
00253 
00254             mod->init++;
00255 
00256             *list = (mod_instance_t *) realloc(*list, sizeof(mod_instance_t) * (*nlist + 1));
00257             (*list)[*nlist] = mi;
00258 
00259             log_write(sm->log, LOG_NOTICE, "module '%s' added to chain '%s' (order %d index %d seq %d)", mod->name, id, *nlist, mod->index, mi->seq);
00260 
00261             (*nlist)++;
00262 
00263             melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
00264         }
00265 
00266         celem = nad_find_elem(sm->config->nad, celem, -1, "chain", 0);
00267     }
00268 
00269     return mm;
00270 }
00271 
00272 static void _mm_reaper(const char *module, int modulelen, void *val, void *arg) {
00273     module_t mod = (module_t) val;
00274 
00275     if(mod->free != NULL)
00276         (mod->free)(mod);
00277 
00278     #ifndef _WIN32
00279         if (mod->handle != NULL)
00280             dlclose(mod->handle);
00281     #else
00282         if (mod->handle != NULL)
00283             FreeLibrary((HMODULE) mod->handle);
00284     #endif
00285 
00286     free(mod->name);
00287     free(mod);
00288 }
00289 
00290 void mm_free(mm_t mm) {
00291     int i, j, *nlist = NULL;
00292     mod_instance_t **list = NULL, mi;
00293 
00294     /* close down modules */
00295     xhash_walk(mm->modules, _mm_reaper, NULL);
00296 
00297     /* free instances */
00298     for(i = 0; i < 13; i++) {
00299         switch(i) {
00300             case 0:
00301                 list = &mm->sess_start;
00302                 nlist = &mm->nsess_start;
00303                 break;
00304             case 1:
00305                 list = &mm->sess_end;
00306                 nlist = &mm->nsess_end;
00307                 break;
00308             case 2:
00309                 list = &mm->in_sess;
00310                 nlist = &mm->nin_sess;
00311                 break;
00312             case 3:
00313                 list = &mm->in_router;
00314                 nlist = &mm->nin_router;
00315                 break;
00316             case 4:
00317                 list = &mm->out_sess;
00318                 nlist = &mm->nout_sess;
00319                 break;
00320             case 5:
00321                 list = &mm->out_router;
00322                 nlist = &mm->nout_router;
00323                 break;
00324             case 6:
00325                 list = &mm->pkt_sm;
00326                 nlist = &mm->npkt_sm;
00327                 break;
00328             case 7:
00329                 list = &mm->pkt_user;
00330                 nlist = &mm->npkt_user;
00331                 break;
00332             case 8:
00333                 list = &mm->pkt_router;
00334                 nlist = &mm->npkt_router;
00335                 break;
00336             case 9:
00337                 list = &mm->user_load;
00338                 nlist = &mm->nuser_load;
00339                 break;
00340             case 10:
00341                 list = &mm->user_create;
00342                 nlist = &mm->nuser_create;
00343                 break;
00344             case 11:
00345                 list = &mm->user_delete;
00346                 nlist = &mm->nuser_delete;
00347                 break;
00348             case 12:
00349                 list = &mm->disco_extend;
00350                 nlist = &mm->ndisco_extend;
00351                 break;
00352         }
00353 
00354         for(j = 0; j < *nlist; j++) {
00355             mi = (*list)[j];
00356             if(mi->arg != NULL)
00357                 free(mi->arg);
00358             free(mi);
00359         }
00360     }
00361 
00362     /* free lists */
00363     free(mm->sess_start);
00364     free(mm->sess_end);
00365     free(mm->in_sess);
00366     free(mm->in_router);
00367     free(mm->out_sess);
00368     free(mm->out_router);
00369     free(mm->pkt_sm);
00370     free(mm->pkt_user);
00371     free(mm->pkt_router);
00372     free(mm->user_load);
00373     free(mm->user_create);
00374     free(mm->user_delete);
00375     free(mm->disco_extend);
00376 
00377     xhash_free(mm->modules);
00378 
00379     free(mm);
00380 }
00381 
00383 int mm_sess_start(mm_t mm, sess_t sess) {
00384     int n, ret = 0;
00385     mod_instance_t mi;
00386 
00387     log_debug(ZONE, "dispatching sess-start chain");
00388 
00389     ret = 0;
00390     for(n = 0; n < mm->nsess_start; n++) {
00391         mi = mm->sess_start[n];
00392         if(mi == NULL) {
00393             log_debug(ZONE, "module at index %d is not loaded yet", n);
00394             continue;
00395         }
00396         if(mi->mod->sess_start == NULL) {
00397             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00398             continue;
00399         }
00400 
00401         log_debug(ZONE, "calling module %s", mi->mod->name);
00402 
00403         ret = (mi->mod->sess_start)(mi, sess);
00404         if(ret != 0)
00405             break;
00406     }
00407 
00408     log_debug(ZONE, "sess-start chain returning %d", ret);
00409 
00410     return ret;
00411 }
00412 
00414 void mm_sess_end(mm_t mm, sess_t sess) {
00415     int n;
00416     mod_instance_t mi;
00417 
00418     log_debug(ZONE, "dispatching sess-end chain");
00419 
00420     for(n = 0; n < mm->nsess_end; n++) {
00421         mi = mm->sess_end[n];
00422         if(mi == NULL) {
00423             log_debug(ZONE, "module at index %d is not loaded yet", n);
00424             continue;
00425         }
00426         if(mi->mod->sess_end == NULL) {
00427             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00428             continue;
00429         }
00430 
00431         log_debug(ZONE, "calling module %s", mi->mod->name);
00432 
00433         (mi->mod->sess_end)(mi, sess);
00434     }
00435 
00436     log_debug(ZONE, "sess-end chain returning");
00437 }
00438 
00440 mod_ret_t mm_in_sess(mm_t mm, sess_t sess, pkt_t pkt) {
00441     int n;
00442     mod_instance_t mi;
00443     mod_ret_t ret = mod_PASS;
00444 
00445     log_debug(ZONE, "dispatching in-sess chain");
00446 
00447     ret = mod_PASS;
00448     for(n = 0; n < mm->nin_sess; n++) {
00449         mi = mm->in_sess[n];
00450         if(mi == NULL) {
00451             log_debug(ZONE, "module at index %d is not loaded yet", n);
00452             continue;
00453         }
00454         if(mi->mod->in_sess == NULL) {
00455             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00456             continue;
00457         }
00458 
00459         log_debug(ZONE, "calling module %s", mi->mod->name);
00460 
00461         ret = (mi->mod->in_sess)(mi, sess, pkt);
00462         if(ret != mod_PASS)
00463             break;
00464     }
00465 
00466     log_debug(ZONE, "in-sess chain returning %d", ret);
00467 
00468     return ret;
00469 }
00470 
00472 mod_ret_t mm_in_router(mm_t mm, pkt_t pkt) {
00473     int n;
00474     mod_instance_t mi;
00475     mod_ret_t ret = mod_PASS;
00476 
00477     log_debug(ZONE, "dispatching in-router chain");
00478 
00479     if (mm != NULL && pkt != NULL )
00480     for(n = 0; n < mm->nin_router; n++) {
00481         mi = mm->in_router[n];
00482         if(mi == NULL) {
00483             log_debug(ZONE, "module at index %d is not loaded yet", n);
00484             continue;
00485         }
00486         if(mi->mod == NULL || mi->mod->in_router == NULL) {
00487             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00488             continue;
00489         }
00490 
00491         log_debug(ZONE, "calling module %s", mi->mod->name);
00492 
00493         ret = (mi->mod->in_router)(mi, pkt);
00494         if(ret != mod_PASS)
00495             break;
00496     }
00497 
00498     log_debug(ZONE, "in-router chain returning %d", ret);
00499 
00500     return ret;
00501 }
00502 
00504 mod_ret_t mm_out_sess(mm_t mm, sess_t sess, pkt_t pkt) {
00505     int n;
00506     mod_instance_t mi;
00507     mod_ret_t ret = mod_PASS;
00508 
00509     log_debug(ZONE, "dispatching out-sess chain");
00510 
00511     for(n = 0; n < mm->nout_sess; n++) {
00512         mi = mm->out_sess[n];
00513         if(mi == NULL) {
00514             log_debug(ZONE, "module at index %d is not loaded yet", n);
00515             continue;
00516         }
00517         if(mi->mod->out_sess == NULL) {
00518             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00519             continue;
00520         }
00521 
00522         log_debug(ZONE, "calling module %s", mi->mod->name);
00523 
00524         ret = (mi->mod->out_sess)(mi, sess, pkt);
00525         if(ret != mod_PASS)
00526             break;
00527     }
00528 
00529     log_debug(ZONE, "out-sess chain returning %d", ret);
00530 
00531     return ret;
00532 }
00533 
00535 mod_ret_t mm_out_router(mm_t mm, pkt_t pkt) {
00536     int n;
00537     mod_instance_t mi;
00538     mod_ret_t ret = mod_PASS;
00539 
00540     log_debug(ZONE, "dispatching out-router chain");
00541 
00542     for(n = 0; n < mm->nout_router; n++) {
00543         mi = mm->out_router[n];
00544         if(mi == NULL) {
00545             log_debug(ZONE, "module at index %d is not loaded yet", n);
00546             continue;
00547         }
00548         if(mi->mod->out_router == NULL) {
00549             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00550             continue;
00551         }
00552 
00553         log_debug(ZONE, "calling module %s", mi->mod->name);
00554 
00555         ret = (mi->mod->out_router)(mi, pkt);
00556         if(ret != mod_PASS)
00557             break;
00558     }
00559 
00560     log_debug(ZONE, "out-router chain returning %d", ret);
00561 
00562     return ret;
00563 }
00564 
00566 mod_ret_t mm_pkt_sm(mm_t mm, pkt_t pkt) {
00567     int n, ret = 0;
00568     mod_instance_t mi;
00569 
00570     log_debug(ZONE, "dispatching pkt-sm chain");
00571 
00572     for(n = 0; n < mm->npkt_sm; n++) {
00573         mi = mm->pkt_sm[n];
00574         if(mi == NULL) {
00575             log_debug(ZONE, "module at index %d is not loaded yet", n);
00576             continue;
00577         }
00578         if(mi->mod->pkt_sm == NULL) {
00579             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00580             continue;
00581         }
00582 
00583         log_debug(ZONE, "calling module %s", mi->mod->name);
00584 
00585         ret = (mi->mod->pkt_sm)(mi, pkt);
00586         if(ret != mod_PASS)
00587             break;
00588     }
00589 
00590     log_debug(ZONE, "pkt-sm chain returning %d", ret);
00591 
00592     return ret;
00593 }
00594 
00596 mod_ret_t mm_pkt_user(mm_t mm, user_t user, pkt_t pkt) {
00597     int n;
00598     mod_instance_t mi;
00599     mod_ret_t ret = mod_PASS;
00600 
00601     log_debug(ZONE, "dispatching pkt-user chain");
00602 
00603     for(n = 0; n < mm->npkt_user; n++) {
00604         mi = mm->pkt_user[n];
00605         if(mi == NULL) {
00606             log_debug(ZONE, "module at index %d is not loaded yet", n);
00607             continue;
00608         }
00609         if(mi->mod->pkt_user == NULL) {
00610             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00611             continue;
00612         }
00613 
00614         log_debug(ZONE, "calling module %s", mi->mod->name);
00615 
00616         ret = (mi->mod->pkt_user)(mi, user, pkt);
00617         if(ret != mod_PASS)
00618             break;
00619     }
00620 
00621     log_debug(ZONE, "pkt-user chain returning %d", ret);
00622 
00623     return ret;
00624 }
00625 
00627 mod_ret_t mm_pkt_router(mm_t mm, pkt_t pkt) {
00628     int n;
00629     mod_instance_t mi;
00630     mod_ret_t ret = mod_PASS;
00631 
00632     log_debug(ZONE, "dispatching pkt-router chain");
00633 
00634     for(n = 0; n < mm->npkt_router; n++) {
00635         mi = mm->pkt_router[n];
00636         if(mi == NULL) {
00637             log_debug(ZONE, "module at index %d is not loaded yet", n);
00638             continue;
00639         }
00640         if(mi->mod->pkt_router == NULL) {
00641             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00642             continue;
00643         }
00644 
00645         log_debug(ZONE, "calling module %s", mi->mod->name);
00646 
00647         ret = (mi->mod->pkt_router)(mi, pkt);
00648         if(ret != mod_PASS)
00649             break;
00650     }
00651 
00652     log_debug(ZONE, "pkt-router chain returning %d", ret);
00653 
00654     return ret;
00655 }
00656 
00658 int mm_user_load(mm_t mm, user_t user) {
00659     int n;
00660     mod_instance_t mi;
00661     int ret = 0;
00662 
00663     log_debug(ZONE, "dispatching user-load chain");
00664 
00665     for(n = 0; n < mm->nuser_load; n++) {
00666         mi = mm->user_load[n];
00667         if(mi == NULL) {
00668             log_debug(ZONE, "module at index %d is not loaded yet", n);
00669             continue;
00670         }
00671         if(mi->mod->user_load == NULL) {
00672             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00673             continue;
00674         }
00675 
00676         log_debug(ZONE, "calling module %s", mi->mod->name);
00677 
00678         ret = (mi->mod->user_load)(mi, user);
00679         if(ret != 0)
00680             break;
00681     }
00682 
00683     log_debug(ZONE, "user-load chain returning %d", ret);
00684 
00685     return ret;
00686 }
00687 
00689 int mm_user_unload(mm_t mm, user_t user) {
00690     int n;
00691     mod_instance_t mi;
00692     int ret = 0;
00693 
00694     log_debug(ZONE, "dispatching user-unload chain");
00695 
00696     for(n = 0; n < mm->nuser_unload; n++) {
00697         mi = mm->user_unload[n];
00698         if(mi == NULL) {
00699             log_debug(ZONE, "module at index %d is not loaded yet", n);
00700             continue;
00701         }
00702         if(mi->mod->user_unload == NULL) {
00703             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00704             continue;
00705         }
00706 
00707         log_debug(ZONE, "calling module %s", mi->mod->name);
00708 
00709         ret = (mi->mod->user_unload)(mi, user);
00710         if(ret != 0)
00711             break;
00712     }
00713 
00714     log_debug(ZONE, "user-unload chain returning %d", ret);
00715 
00716     return ret;
00717 }
00718 
00720 int mm_user_create(mm_t mm, jid_t jid) {
00721     int n;
00722     mod_instance_t mi;
00723     int ret = 0;
00724 
00725     log_debug(ZONE, "dispatching user-create chain");
00726 
00727     for(n = 0; n < mm->nuser_create; n++) {
00728         mi = mm->user_create[n];
00729         if(mi == NULL) {
00730             log_debug(ZONE, "module at index %d is not loaded yet", n);
00731             continue;
00732         }
00733         if(mi->mod->user_create == NULL) {
00734             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00735             continue;
00736         }
00737 
00738         log_debug(ZONE, "calling module %s", mi->mod->name);
00739 
00740         ret = (mi->mod->user_create)(mi, jid);
00741         if(ret != 0)
00742             break;
00743     }
00744 
00745     log_debug(ZONE, "user-create chain returning %d", ret);
00746 
00747     return ret;
00748 }
00749 
00751 void mm_user_delete(mm_t mm, jid_t jid) {
00752     int n;
00753     mod_instance_t mi;
00754 
00755     log_debug(ZONE, "dispatching user-delete chain");
00756 
00757     for(n = 0; n < mm->nuser_delete; n++) {
00758         mi = mm->user_delete[n];
00759         if(mi == NULL) {
00760             log_debug(ZONE, "module at index %d is not loaded yet", n);
00761             continue;
00762         }
00763         if(mi->mod->user_delete == NULL) {
00764             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00765             continue;
00766         }
00767 
00768         log_debug(ZONE, "calling module %s", mi->mod->name);
00769 
00770         (mi->mod->user_delete)(mi, jid);
00771     }
00772 
00773     log_debug(ZONE, "user-delete chain returning");
00774 }
00775 
00777 void mm_disco_extend(mm_t mm, pkt_t pkt) {
00778     int n;
00779     mod_instance_t mi;
00780 
00781     log_debug(ZONE, "dispatching disco-extend chain");
00782 
00783     for(n = 0; n < mm->ndisco_extend; n++) {
00784         mi = mm->disco_extend[n];
00785         if(mi == NULL) {
00786             log_debug(ZONE, "module at index %d is not loaded yet", n);
00787             continue;
00788         }
00789         if(mi->mod->disco_extend == NULL) {
00790             log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
00791             continue;
00792         }
00793 
00794         log_debug(ZONE, "calling module %s", mi->mod->name);
00795 
00796         (mi->mod->disco_extend)(mi, pkt);
00797     }
00798 
00799     log_debug(ZONE, "disco-extend chain returning");
00800 }