jabberd2  2.3.3
mm.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #include "sm.h"
22 
23 #ifdef _WIN32
24 # define LIBRARY_DIR "."
25 # include <windows.h>
26 #else
27 # include <dlfcn.h>
28 #endif /* _WIN32 */
29 
37 /* these functions implement a multiplexor to get calls to the correct module
38  * for the given type */
39 
40 /* Notes on dynamic modules (cedricv@) :
41  Modules are searched by name mod_[modulename].so or mod_[modulename].dll
42  depending platform.
43  You have to set <path>[full_path]</path> within <modules> in sm.xml config,
44  else it will only search in LD_LIBRARY_PATH or c:\windows\system32
45  */
46 
48  mm_t mm;
49  int celem, melem, attr, *nlist = NULL;
50  char id[13], name[32], mod_fullpath[PATH_MAX], arg[1024];
51  const char *modules_path;
52  mod_chain_t chain = (mod_chain_t) NULL;
53  mod_instance_t **list = NULL, mi;
54  module_t mod;
55 
56  mm = (mm_t) calloc(1, sizeof(struct mm_st));
57 
58  mm->sm = sm;
59  mm->modules = xhash_new(101);
60 
61  if((celem = nad_find_elem(sm->config->nad, 0, -1, "modules", 1)) < 0)
62  return mm;
63 
64  modules_path = config_get_one(sm->config, "modules.path", 0);
65  if (modules_path != NULL)
66  log_write(sm->log, LOG_NOTICE, "modules search path: %s", modules_path);
67  else
68  log_write(sm->log, LOG_NOTICE, "modules search path undefined, using default: "LIBRARY_DIR);
69 
70  celem = nad_find_elem(sm->config->nad, celem, -1, "chain", 1);
71  while(celem >= 0) {
72  if((attr = nad_find_attr(sm->config->nad, celem, -1, "id", NULL)) < 0) {
73  celem = nad_find_elem(sm->config->nad, celem, -1, "chain", 0);
74  continue;
75  }
76 
77  snprintf(id, 13, "%.*s", NAD_AVAL_L(sm->config->nad, attr), NAD_AVAL(sm->config->nad, attr));
78  id[12] = '\0';
79 
80  log_debug(ZONE, "processing config for chain '%s'", id);
81 
82  list = NULL;
83  if(strcmp(id, "sess-start") == 0) {
84  chain = chain_SESS_START;
85  list = &mm->sess_start;
86  nlist = &mm->nsess_start;
87  }
88  else if(strcmp(id, "sess-end") == 0) {
89  chain = chain_SESS_END;
90  list = &mm->sess_end;
91  nlist = &mm->nsess_end;
92  }
93  else if(strcmp(id, "in-sess") == 0) {
94  chain = chain_IN_SESS;
95  list = &mm->in_sess;
96  nlist = &mm->nin_sess;
97  }
98  else if(strcmp(id, "in-router") == 0) {
99  chain = chain_IN_ROUTER;
100  list = &mm->in_router;
101  nlist = &mm->nin_router;
102  }
103  else if(strcmp(id, "out-sess") == 0) {
104  chain = chain_OUT_SESS;
105  list = &mm->out_sess;
106  nlist = &mm->nout_sess;
107  }
108  else if(strcmp(id, "out-router") == 0) {
109  chain = chain_OUT_ROUTER;
110  list = &mm->out_router;
111  nlist = &mm->nout_router;
112  }
113  else if(strcmp(id, "pkt-sm") == 0) {
114  chain = chain_PKT_SM;
115  list = &mm->pkt_sm;
116  nlist = &mm->npkt_sm;
117  }
118  else if(strcmp(id, "pkt-user") == 0) {
119  chain = chain_PKT_USER;
120  list = &mm->pkt_user;
121  nlist = &mm->npkt_user;
122  }
123  else if(strcmp(id, "pkt-router") == 0) {
124  chain = chain_PKT_ROUTER;
125  list = &mm->pkt_router;
126  nlist = &mm->npkt_router;
127  }
128  else if(strcmp(id, "user-load") == 0) {
129  chain = chain_USER_LOAD;
130  list = &mm->user_load;
131  nlist = &mm->nuser_load;
132  }
133  else if(strcmp(id, "user-unload") == 0) {
134  chain = chain_USER_UNLOAD;
135  list = &mm->user_unload;
136  nlist = &mm->nuser_unload;
137  }
138  else if(strcmp(id, "user-create") == 0) {
139  chain = chain_USER_CREATE;
140  list = &mm->user_create;
141  nlist = &mm->nuser_create;
142  }
143  else if(strcmp(id, "user-delete") == 0) {
144  chain = chain_USER_DELETE;
145  list = &mm->user_delete;
146  nlist = &mm->nuser_delete;
147  }
148  else if(strcmp(id, "disco-extend") == 0) {
149  chain = chain_DISCO_EXTEND;
150  list = &mm->disco_extend;
151  nlist = &mm->ndisco_extend;
152  }
153 
154  if(list == NULL) {
155  log_write(sm->log, LOG_ERR, "unknown chain type '%s'", id);
156 
157  celem = nad_find_elem(sm->config->nad, celem, -1, "chain", 0);
158  continue;
159  }
160 
161  melem = nad_find_elem(sm->config->nad, celem, -1, "module", 1);
162  while(melem >= 0) {
163  if(NAD_CDATA_L(sm->config->nad, melem) <= 0) {
164  melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
165  continue;
166  }
167 
168  arg[0] = '\0';
169  attr = nad_find_attr(sm->config->nad, melem, -1, "arg", NULL);
170  if(attr >= 0) {
171  snprintf(arg, 1024, "%.*s", NAD_AVAL_L(sm->config->nad, attr), NAD_AVAL(sm->config->nad, attr));
172  log_debug(ZONE, "module arg: %s", arg);
173  }
174 
175  snprintf(name, 32, "%.*s", NAD_CDATA_L(sm->config->nad, melem), NAD_CDATA(sm->config->nad, melem));
176 
177  mod = xhash_get(mm->modules, name);
178  if(mod == NULL) {
179  mod = (module_t) calloc(1, sizeof(struct module_st));
180 
181  mod->mm = mm;
182  mod->index = mm->nindex;
183  mod->name = strdup(name);
184  #ifndef _WIN32
185  if (modules_path != NULL)
186  snprintf(mod_fullpath, PATH_MAX, "%s/mod_%s.so", modules_path, name);
187  else
188  snprintf(mod_fullpath, PATH_MAX, "%s/mod_%s.so", LIBRARY_DIR, name);
189  mod->handle = dlopen(mod_fullpath, RTLD_LAZY);
190  if (mod->handle != NULL)
191  mod->module_init_fn = dlsym(mod->handle, "module_init");
192  #else
193  if (modules_path != NULL)
194  snprintf(mod_fullpath, PATH_MAX, "%s\\mod_%s.dll", modules_path, name);
195  else
196  snprintf(mod_fullpath, PATH_MAX, "mod_%s.dll", name);
197  mod->handle = (void*) LoadLibrary(mod_fullpath);
198  if (mod->handle != NULL)
199  mod->module_init_fn = (int (*)(mod_instance_t))GetProcAddress((HMODULE) mod->handle, "module_init");
200  #endif
201 
202  if (mod->handle != NULL && mod->module_init_fn != NULL) {
203  log_debug(ZONE, "preloaded module '%s' to chain '%s' (not added yet)", name, id);
204  xhash_put(mm->modules, mod->name, (void *) mod);
205  mm->nindex++;
206  } else {
207  #ifndef _WIN32
208  log_write(sm->log, LOG_ERR, "failed loading module '%s' to chain '%s' (%s)", name, id, dlerror());
209  if (mod->handle != NULL)
210  dlclose(mod->handle);
211  #else
212  log_write(sm->log, LOG_ERR, "failed loading module '%s' to chain '%s' (errcode: %x)", name, id, GetLastError());
213  if (mod->handle != NULL)
214  FreeLibrary((HMODULE) mod->handle);
215  #endif
216 
217  melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
218  continue;
219  }
220  }
221 
222  mi = (mod_instance_t) calloc(1, sizeof(struct mod_instance_st));
223 
224  mi->sm = sm;
225  mi->mod = mod;
226  mi->chain = chain;
227  mi->arg = (arg[0] == '\0') ? NULL : strdup(arg);
228  mi->seq = mod->init;
229 
230  if(mod->module_init_fn(mi) != 0) {
231  log_write(sm->log, LOG_ERR, "init for module '%s' (seq %d) failed", name, mi->seq);
232  free(mi);
233 
234  if(mod->init == 0) {
235  xhash_zap(mm->modules, mod->name);
236 
237  #ifndef _WIN32
238  if (mod->handle != NULL)
239  dlclose(mod->handle);
240  #else
241  if (mod->handle != NULL)
242  FreeLibrary((HMODULE) mod->handle);
243  #endif
244 
245  free((void*)mod->name);
246  free(mod);
247 
248  mm->nindex--;
249 
250  melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
251  continue;
252  }
253  }
254 
255  mod->init++;
256 
257  *list = (mod_instance_t *) realloc(*list, sizeof(mod_instance_t) * (*nlist + 1));
258  (*list)[*nlist] = mi;
259 
260  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);
261 
262  (*nlist)++;
263 
264  melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
265  }
266 
267  celem = nad_find_elem(sm->config->nad, celem, -1, "chain", 0);
268  }
269 
270  return mm;
271 }
272 
273 static void _mm_reaper(const char *module, int modulelen, void *val, void *arg) {
274  module_t mod = (module_t) val;
275 
276  if(mod->free != NULL)
277  (mod->free)(mod);
278 
279  #ifndef _WIN32
280  if (mod->handle != NULL)
281  dlclose(mod->handle);
282  #else
283  if (mod->handle != NULL)
284  FreeLibrary((HMODULE) mod->handle);
285  #endif
286 
287  free((void*)mod->name);
288  free(mod);
289 }
290 
291 void mm_free(mm_t mm) {
292  int i, j, *nlist = NULL;
293  mod_instance_t **list = NULL, mi;
294 
295  /* close down modules */
296  xhash_walk(mm->modules, _mm_reaper, NULL);
297 
298  /* free instances */
299  for(i = 0; i < 13; i++) {
300  switch(i) {
301  case 0:
302  list = &mm->sess_start;
303  nlist = &mm->nsess_start;
304  break;
305  case 1:
306  list = &mm->sess_end;
307  nlist = &mm->nsess_end;
308  break;
309  case 2:
310  list = &mm->in_sess;
311  nlist = &mm->nin_sess;
312  break;
313  case 3:
314  list = &mm->in_router;
315  nlist = &mm->nin_router;
316  break;
317  case 4:
318  list = &mm->out_sess;
319  nlist = &mm->nout_sess;
320  break;
321  case 5:
322  list = &mm->out_router;
323  nlist = &mm->nout_router;
324  break;
325  case 6:
326  list = &mm->pkt_sm;
327  nlist = &mm->npkt_sm;
328  break;
329  case 7:
330  list = &mm->pkt_user;
331  nlist = &mm->npkt_user;
332  break;
333  case 8:
334  list = &mm->pkt_router;
335  nlist = &mm->npkt_router;
336  break;
337  case 9:
338  list = &mm->user_load;
339  nlist = &mm->nuser_load;
340  break;
341  case 10:
342  list = &mm->user_create;
343  nlist = &mm->nuser_create;
344  break;
345  case 11:
346  list = &mm->user_delete;
347  nlist = &mm->nuser_delete;
348  break;
349  case 12:
350  list = &mm->disco_extend;
351  nlist = &mm->ndisco_extend;
352  break;
353  }
354 
355  for(j = 0; j < *nlist; j++) {
356  mi = (*list)[j];
357  if(mi->arg != NULL)
358  free((void*)mi->arg);
359  free(mi);
360  }
361  }
362 
363  /* free lists */
364  free(mm->sess_start);
365  free(mm->sess_end);
366  free(mm->in_sess);
367  free(mm->in_router);
368  free(mm->out_sess);
369  free(mm->out_router);
370  free(mm->pkt_sm);
371  free(mm->pkt_user);
372  free(mm->pkt_router);
373  free(mm->user_load);
374  free(mm->user_create);
375  free(mm->user_delete);
376  free(mm->disco_extend);
377 
378  xhash_free(mm->modules);
379 
380  free(mm);
381 }
382 
384 int mm_sess_start(mm_t mm, sess_t sess) {
385  int n, ret = 0;
386  mod_instance_t mi;
387 
388  log_debug(ZONE, "dispatching sess-start chain");
389 
390  ret = 0;
391  for(n = 0; n < mm->nsess_start; n++) {
392  mi = mm->sess_start[n];
393  if(mi == NULL) {
394  log_debug(ZONE, "module at index %d is not loaded yet", n);
395  continue;
396  }
397  if(mi->mod->sess_start == NULL) {
398  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
399  continue;
400  }
401 
402  log_debug(ZONE, "calling module %s", mi->mod->name);
403 
404  ret = (mi->mod->sess_start)(mi, sess);
405  if(ret != 0)
406  break;
407  }
408 
409  log_debug(ZONE, "sess-start chain returning %d", ret);
410 
411  return ret;
412 }
413 
415 void mm_sess_end(mm_t mm, sess_t sess) {
416  int n;
417  mod_instance_t mi;
418 
419  log_debug(ZONE, "dispatching sess-end chain");
420 
421  for(n = 0; n < mm->nsess_end; n++) {
422  mi = mm->sess_end[n];
423  if(mi == NULL) {
424  log_debug(ZONE, "module at index %d is not loaded yet", n);
425  continue;
426  }
427  if(mi->mod->sess_end == NULL) {
428  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
429  continue;
430  }
431 
432  log_debug(ZONE, "calling module %s", mi->mod->name);
433 
434  (mi->mod->sess_end)(mi, sess);
435  }
436 
437  log_debug(ZONE, "sess-end chain returning");
438 }
439 
442  int n;
443  mod_instance_t mi;
444  mod_ret_t ret = mod_PASS;
445 
446  log_debug(ZONE, "dispatching in-sess chain");
447 
448  ret = mod_PASS;
449  for(n = 0; n < mm->nin_sess; n++) {
450  mi = mm->in_sess[n];
451  if(mi == NULL) {
452  log_debug(ZONE, "module at index %d is not loaded yet", n);
453  continue;
454  }
455  if(mi->mod->in_sess == NULL) {
456  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
457  continue;
458  }
459 
460  log_debug(ZONE, "calling module %s", mi->mod->name);
461 
462  ret = (mi->mod->in_sess)(mi, sess, pkt);
463  if(ret != mod_PASS)
464  break;
465  }
466 
467  log_debug(ZONE, "in-sess chain returning %d", ret);
468 
469  return ret;
470 }
471 
474  int n;
475  mod_instance_t mi;
476  mod_ret_t ret = mod_PASS;
477 
478  log_debug(ZONE, "dispatching in-router chain");
479 
480  if (mm != NULL && pkt != NULL )
481  for(n = 0; n < mm->nin_router; n++) {
482  mi = mm->in_router[n];
483  if(mi == NULL) {
484  log_debug(ZONE, "module at index %d is not loaded yet", n);
485  continue;
486  }
487  if(mi->mod == NULL || mi->mod->in_router == NULL) {
488  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
489  continue;
490  }
491 
492  log_debug(ZONE, "calling module %s", mi->mod->name);
493 
494  ret = (mi->mod->in_router)(mi, pkt);
495  if(ret != mod_PASS)
496  break;
497  }
498 
499  log_debug(ZONE, "in-router chain returning %d", ret);
500 
501  return ret;
502 }
503 
506  int n;
507  mod_instance_t mi;
508  mod_ret_t ret = mod_PASS;
509 
510  log_debug(ZONE, "dispatching out-sess chain");
511 
512  for(n = 0; n < mm->nout_sess; n++) {
513  mi = mm->out_sess[n];
514  if(mi == NULL) {
515  log_debug(ZONE, "module at index %d is not loaded yet", n);
516  continue;
517  }
518  if(mi->mod->out_sess == NULL) {
519  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
520  continue;
521  }
522 
523  log_debug(ZONE, "calling module %s", mi->mod->name);
524 
525  ret = (mi->mod->out_sess)(mi, sess, pkt);
526  if(ret != mod_PASS)
527  break;
528  }
529 
530  log_debug(ZONE, "out-sess chain returning %d", ret);
531 
532  return ret;
533 }
534 
537  int n;
538  mod_instance_t mi;
539  mod_ret_t ret = mod_PASS;
540 
541  log_debug(ZONE, "dispatching out-router chain");
542 
543  for(n = 0; n < mm->nout_router; n++) {
544  mi = mm->out_router[n];
545  if(mi == NULL) {
546  log_debug(ZONE, "module at index %d is not loaded yet", n);
547  continue;
548  }
549  if(mi->mod->out_router == NULL) {
550  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
551  continue;
552  }
553 
554  log_debug(ZONE, "calling module %s", mi->mod->name);
555 
556  ret = (mi->mod->out_router)(mi, pkt);
557  if(ret != mod_PASS)
558  break;
559  }
560 
561  log_debug(ZONE, "out-router chain returning %d", ret);
562 
563  return ret;
564 }
565 
568  int n, ret = 0;
569  mod_instance_t mi;
570 
571  log_debug(ZONE, "dispatching pkt-sm chain");
572 
573  for(n = 0; n < mm->npkt_sm; n++) {
574  mi = mm->pkt_sm[n];
575  if(mi == NULL) {
576  log_debug(ZONE, "module at index %d is not loaded yet", n);
577  continue;
578  }
579  if(mi->mod->pkt_sm == NULL) {
580  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
581  continue;
582  }
583 
584  log_debug(ZONE, "calling module %s", mi->mod->name);
585 
586  ret = (mi->mod->pkt_sm)(mi, pkt);
587  if(ret != mod_PASS)
588  break;
589  }
590 
591  log_debug(ZONE, "pkt-sm chain returning %d", ret);
592 
593  return ret;
594 }
595 
598  int n;
599  mod_instance_t mi;
600  mod_ret_t ret = mod_PASS;
601 
602  log_debug(ZONE, "dispatching pkt-user chain");
603 
604  for(n = 0; n < mm->npkt_user; n++) {
605  mi = mm->pkt_user[n];
606  if(mi == NULL) {
607  log_debug(ZONE, "module at index %d is not loaded yet", n);
608  continue;
609  }
610  if(mi->mod->pkt_user == NULL) {
611  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
612  continue;
613  }
614 
615  log_debug(ZONE, "calling module %s", mi->mod->name);
616 
617  ret = (mi->mod->pkt_user)(mi, user, pkt);
618  if(ret != mod_PASS)
619  break;
620  }
621 
622  log_debug(ZONE, "pkt-user chain returning %d", ret);
623 
624  return ret;
625 }
626 
629  int n;
630  mod_instance_t mi;
631  mod_ret_t ret = mod_PASS;
632 
633  log_debug(ZONE, "dispatching pkt-router chain");
634 
635  for(n = 0; n < mm->npkt_router; n++) {
636  mi = mm->pkt_router[n];
637  if(mi == NULL) {
638  log_debug(ZONE, "module at index %d is not loaded yet", n);
639  continue;
640  }
641  if(mi->mod->pkt_router == NULL) {
642  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
643  continue;
644  }
645 
646  log_debug(ZONE, "calling module %s", mi->mod->name);
647 
648  ret = (mi->mod->pkt_router)(mi, pkt);
649  if(ret != mod_PASS)
650  break;
651  }
652 
653  log_debug(ZONE, "pkt-router chain returning %d", ret);
654 
655  return ret;
656 }
657 
659 int mm_user_load(mm_t mm, user_t user) {
660  int n;
661  mod_instance_t mi;
662  int ret = 0;
663 
664  log_debug(ZONE, "dispatching user-load chain");
665 
666  for(n = 0; n < mm->nuser_load; n++) {
667  mi = mm->user_load[n];
668  if(mi == NULL) {
669  log_debug(ZONE, "module at index %d is not loaded yet", n);
670  continue;
671  }
672  if(mi->mod->user_load == NULL) {
673  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
674  continue;
675  }
676 
677  log_debug(ZONE, "calling module %s", mi->mod->name);
678 
679  ret = (mi->mod->user_load)(mi, user);
680  if(ret != 0)
681  break;
682  }
683 
684  log_debug(ZONE, "user-load chain returning %d", ret);
685 
686  return ret;
687 }
688 
690 int mm_user_unload(mm_t mm, user_t user) {
691  int n;
692  mod_instance_t mi;
693  int ret = 0;
694 
695  log_debug(ZONE, "dispatching user-unload chain");
696 
697  for(n = 0; n < mm->nuser_unload; n++) {
698  mi = mm->user_unload[n];
699  if(mi == NULL) {
700  log_debug(ZONE, "module at index %d is not loaded yet", n);
701  continue;
702  }
703  if(mi->mod->user_unload == NULL) {
704  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
705  continue;
706  }
707 
708  log_debug(ZONE, "calling module %s", mi->mod->name);
709 
710  ret = (mi->mod->user_unload)(mi, user);
711  if(ret != 0)
712  break;
713  }
714 
715  log_debug(ZONE, "user-unload chain returning %d", ret);
716 
717  return ret;
718 }
719 
721 int mm_user_create(mm_t mm, jid_t jid) {
722  int n;
723  mod_instance_t mi;
724  int ret = 0;
725 
726  log_debug(ZONE, "dispatching user-create chain");
727 
728  for(n = 0; n < mm->nuser_create; n++) {
729  mi = mm->user_create[n];
730  if(mi == NULL) {
731  log_debug(ZONE, "module at index %d is not loaded yet", n);
732  continue;
733  }
734  if(mi->mod->user_create == NULL) {
735  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
736  continue;
737  }
738 
739  log_debug(ZONE, "calling module %s", mi->mod->name);
740 
741  ret = (mi->mod->user_create)(mi, jid);
742  if(ret != 0)
743  break;
744  }
745 
746  log_debug(ZONE, "user-create chain returning %d", ret);
747 
748  return ret;
749 }
750 
752 void mm_user_delete(mm_t mm, jid_t jid) {
753  int n;
754  mod_instance_t mi;
755 
756  log_debug(ZONE, "dispatching user-delete chain");
757 
758  for(n = 0; n < mm->nuser_delete; n++) {
759  mi = mm->user_delete[n];
760  if(mi == NULL) {
761  log_debug(ZONE, "module at index %d is not loaded yet", n);
762  continue;
763  }
764  if(mi->mod->user_delete == NULL) {
765  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
766  continue;
767  }
768 
769  log_debug(ZONE, "calling module %s", mi->mod->name);
770 
771  (mi->mod->user_delete)(mi, jid);
772  }
773 
774  log_debug(ZONE, "user-delete chain returning");
775 }
776 
778 void mm_disco_extend(mm_t mm, pkt_t pkt) {
779  int n;
780  mod_instance_t mi;
781 
782  log_debug(ZONE, "dispatching disco-extend chain");
783 
784  for(n = 0; n < mm->ndisco_extend; n++) {
785  mi = mm->disco_extend[n];
786  if(mi == NULL) {
787  log_debug(ZONE, "module at index %d is not loaded yet", n);
788  continue;
789  }
790  if(mi->mod->disco_extend == NULL) {
791  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
792  continue;
793  }
794 
795  log_debug(ZONE, "calling module %s", mi->mod->name);
796 
797  (mi->mod->disco_extend)(mi, pkt);
798  }
799 
800  log_debug(ZONE, "disco-extend chain returning");
801 }
int(* module_init_fn)(mod_instance_t)
module init function
Definition: sm.h:413
static sm_t sm
Definition: main.c:33
mod_instance_t * pkt_user
pkt-user chain
Definition: sm.h:386
user deletion, delete saved per-user data
Definition: sm.h:355
struct mm_st * mm_t
Definition: sm.h:63
mod_instance_t * sess_end
sess-end chain
Definition: sm.h:374
data structures and prototypes for the session manager
int nindex
counter for module instance sequence (!!! should be local to mm_new)
Definition: sm.h:369
#define NAD_CDATA_L(N, E)
Definition: nad.h:186
mod_instance_t * pkt_sm
pkt-sm chain
Definition: sm.h:384
void xhash_free(xht h)
Definition: xhash.c:241
int mm_user_load(mm_t mm, user_t user)
load user data
Definition: mm.c:659
mod_ret_t(* out_router)(mod_instance_t mi, pkt_t pkt)
out-router handler
Definition: sm.h:426
disco request, extend sm disco::info
Definition: sm.h:357
single instance of a module in a chain
Definition: sm.h:445
log_t log
log context
Definition: sm.h:199
packet for the sm itself
Definition: sm.h:350
void mm_sess_end(mm_t mm, sess_t sess)
session ending
Definition: mm.c:415
int nad_find_elem(nad_t nad, int elem, int ns, const char *name, int depth)
locate the next elem at a given depth with an optional matching name
Definition: nad.c:204
int nuser_unload
Definition: sm.h:398
config_t config
config context
Definition: sm.h:197
int init
number of times the module intialiser has been called
Definition: sm.h:415
void log_write(log_t log, int level, const char *msgfmt,...)
Definition: log.c:104
mod_ret_t mm_out_sess(mm_t mm, sess_t sess, pkt_t pkt)
packets to active session
Definition: mm.c:505
void(* sess_end)(mod_instance_t mi, sess_t sess)
sess-end handler
Definition: sm.h:420
mod_chain_t
module chain types
Definition: sm.h:343
user loaded, load per-user data
Definition: sm.h:353
mod_instance_t * in_sess
in-sess chain
Definition: sm.h:376
mod_ret_t(* out_sess)(mod_instance_t mi, sess_t sess, pkt_t pkt)
out-sess handler
Definition: sm.h:425
int nsess_end
Definition: sm.h:374
user creation, generate and save per-user data
Definition: sm.h:354
mod_ret_t mm_pkt_sm(mm_t mm, pkt_t pkt)
packets for sm
Definition: mm.c:567
mod_ret_t(* in_router)(mod_instance_t mi, pkt_t pkt)
in-router handler
Definition: sm.h:423
session start, load per-session data
Definition: sm.h:344
void mm_disco_extend(mm_t mm, pkt_t pkt)
disco extend
Definition: mm.c:778
mod_ret_t mm_pkt_user(mm_t mm, user_t user, pkt_t pkt)
packets for user
Definition: mm.c:597
mm_t mm_new(sm_t sm)
allocate a module manager instance, and loads the modules
Definition: mm.c:47
int index
module index.
Definition: sm.h:407
mm_t mm
module manager
Definition: sm.h:403
int npkt_sm
Definition: sm.h:384
xht modules
pointers to module data (key is module name)
Definition: sm.h:367
int ndisco_extend
Definition: sm.h:396
#define PATH_MAX
Definition: util.h:69
void mm_user_delete(mm_t mm, jid_t jid)
delete user
Definition: mm.c:752
int npkt_user
Definition: sm.h:386
sm_t sm
sm context
Definition: sm.h:365
mod_ret_t(* in_sess)(mod_instance_t mi, sess_t sess, pkt_t pkt)
in-sess handler
Definition: sm.h:422
mod_ret_t(* pkt_router)(mod_instance_t mi, pkt_t pkt)
pkt-router handler
Definition: sm.h:431
void * handle
module handle
Definition: sm.h:411
int nuser_delete
Definition: sm.h:394
packet for a user
Definition: sm.h:351
int nuser_load
Definition: sm.h:390
nad_t nad
Definition: util.h:203
mod_ret_t mm_in_router(mm_t mm, pkt_t pkt)
packets from router
Definition: mm.c:473
module_t mod
module that this is an instance of
Definition: sm.h:448
mod_instance_t * out_router
out-router chain
Definition: sm.h:382
packet summary data wrapper
Definition: sm.h:129
int npkt_router
Definition: sm.h:388
mod_ret_t mm_pkt_router(mm_t mm, pkt_t pkt)
packets from the router
Definition: mm.c:628
packet from the router
Definition: sm.h:347
session manager global context
Definition: sm.h:167
mod_instance_t * in_router
in-router chain
Definition: sm.h:378
packet from an active session
Definition: sm.h:346
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
mod_instance_t * user_unload
user-unload chain
Definition: sm.h:398
Definition: jid.h:42
int nout_router
Definition: sm.h:382
int nsess_start
Definition: sm.h:372
void mm_free(mm_t mm)
free a mm instance
Definition: mm.c:291
int nuser_create
Definition: sm.h:392
mod_ret_t mm_out_router(mm_t mm, pkt_t pkt)
packets to router
Definition: mm.c:536
#define NAD_AVAL_L(N, A)
Definition: nad.h:190
mod_ret_t(* pkt_user)(mod_instance_t mi, user_t user, pkt_t pkt)
pkt-user handler
Definition: sm.h:429
void xhash_zap(xht h, const char *key)
Definition: xhash.c:235
#define log_debug(...)
Definition: log.h:65
int nout_sess
Definition: sm.h:380
int mm_sess_start(mm_t mm, sess_t sess)
session starting
Definition: mm.c:384
#define NAD_AVAL(N, A)
Definition: nad.h:189
packet was unhandled, should be passed to the next module
Definition: sm.h:339
int mm_user_create(mm_t mm, jid_t jid)
create user
Definition: mm.c:721
mod_instance_t * disco_extend
disco-extend chain
Definition: sm.h:396
mod_ret_t mm_in_sess(mm_t mm, sess_t sess, pkt_t pkt)
packets from active session
Definition: mm.c:441
mod_instance_t * sess_start
sess-start chain
Definition: sm.h:372
There is one instance of this struct per user who is logged in to this c2s instance.
Definition: c2s.h:74
int nin_router
Definition: sm.h:378
int(* user_load)(mod_instance_t mi, user_t user)
user-load handler
Definition: sm.h:433
void xhash_walk(xht h, xhash_walker w, void *arg)
Definition: xhash.c:268
module manager data
Definition: sm.h:364
void(* user_delete)(mod_instance_t mi, jid_t jid)
user-delete handler
Definition: sm.h:437
mod_ret_t(* pkt_sm)(mod_instance_t mi, pkt_t pkt)
pkt-sm handler
Definition: sm.h:428
static void _mm_reaper(const char *module, int modulelen, void *val, void *arg)
Definition: mm.c:273
mod_instance_t * pkt_router
pkt-router chain
Definition: sm.h:388
session ended, save & free per-session data
Definition: sm.h:345
mod_instance_t * user_delete
user-delete chain
Definition: sm.h:394
int(* user_unload)(mod_instance_t mi, user_t user)
user-load handler
Definition: sm.h:434
#define NAD_CDATA(N, E)
Definition: nad.h:185
user is about to be unloaded
Definition: sm.h:356
void * xhash_get(xht h, const char *key)
Definition: xhash.c:184
void(* disco_extend)(mod_instance_t mi, pkt_t pkt)
disco-extend handler
Definition: sm.h:439
mod_instance_t * out_sess
out-sess chain
Definition: sm.h:380
const char * name
name of module
Definition: sm.h:405
#define ZONE
Definition: mio_impl.h:76
int(* sess_start)(mod_instance_t mi, sess_t sess)
sess-start handler
Definition: sm.h:419
const char * config_get_one(config_t c, const char *key, int num)
get config value n for this key
Definition: config.c:277
void(* free)(module_t mod)
called when module is freed
Definition: sm.h:441
xht xhash_new(int prime)
Definition: xhash.c:96
data for a single module
Definition: sm.h:402
int nad_find_attr(nad_t nad, int elem, int ns, const char *name, const char *val)
get a matching attr on this elem, both name and optional val
Definition: nad.c:235
int nin_sess
Definition: sm.h:376
packet to a router
Definition: sm.h:349
packet from the router (special purpose)
Definition: sm.h:352
packet to an active session
Definition: sm.h:348
int mm_user_unload(mm_t mm, user_t user)
user data is about to be unloaded
Definition: mm.c:690
mod_ret_t
module return values
Definition: sm.h:337
struct mod_instance_st * mod_instance_t
Definition: sm.h:361
mod_instance_t * user_load
user-load chain
Definition: sm.h:390
int(* user_create)(mod_instance_t mi, jid_t jid)
user-create handler
Definition: sm.h:436
mod_instance_t * user_create
user-create chain
Definition: sm.h:392
struct module_st * module_t
Definition: sm.h:360
data for a single user
Definition: sm.h:233