jabberd2  2.6.1
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  free(mod->name);
217  free(mod);
218  mod = NULL;
219 
220  melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
221  continue;
222  }
223  }
224 
225  mi = (mod_instance_t) calloc(1, sizeof(struct mod_instance_st));
226 
227  mi->sm = sm;
228  mi->mod = mod;
229  mi->chain = chain;
230  mi->arg = (arg[0] == '\0') ? NULL : strdup(arg);
231  mi->seq = mod->init;
232 
233  if(mod->module_init_fn(mi) != 0) {
234  log_write(sm->log, LOG_ERR, "init for module '%s' (seq %d) failed", name, mi->seq);
235  free(mi);
236 
237  if(mod->init == 0) {
238  xhash_zap(mm->modules, mod->name);
239 
240  #ifndef _WIN32
241  if (mod->handle != NULL)
242  dlclose(mod->handle);
243  #else
244  if (mod->handle != NULL)
245  FreeLibrary((HMODULE) mod->handle);
246  #endif
247 
248  free((void*)mod->name);
249  free(mod);
250 
251  mm->nindex--;
252 
253  melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
254  }
255  continue;
256  }
257 
258  mod->init++;
259 
260  *list = (mod_instance_t *) realloc(*list, sizeof(mod_instance_t) * (*nlist + 1));
261  (*list)[*nlist] = mi;
262 
263  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);
264 
265  (*nlist)++;
266 
267  melem = nad_find_elem(sm->config->nad, melem, -1, "module", 0);
268  }
269 
270  celem = nad_find_elem(sm->config->nad, celem, -1, "chain", 0);
271  }
272 
273  return mm;
274 }
275 
276 static void _mm_reaper(const char *module, int modulelen, void *val, void *arg) {
277  module_t mod = (module_t) val;
278 
279  if(mod->free != NULL)
280  (mod->free)(mod);
281 
282  #ifndef _WIN32
283  if (mod->handle != NULL)
284  dlclose(mod->handle);
285  #else
286  if (mod->handle != NULL)
287  FreeLibrary((HMODULE) mod->handle);
288  #endif
289 
290  free((void*)mod->name);
291  free(mod);
292 }
293 
294 void mm_free(mm_t mm) {
295  int i, j, *nlist = NULL;
296  mod_instance_t **list = NULL, mi;
297 
298  /* close down modules */
299  xhash_walk(mm->modules, _mm_reaper, NULL);
300 
301  /* free instances */
302  for(i = 0; i < 13; i++) {
303  switch(i) {
304  case 0:
305  list = &mm->sess_start;
306  nlist = &mm->nsess_start;
307  break;
308  case 1:
309  list = &mm->sess_end;
310  nlist = &mm->nsess_end;
311  break;
312  case 2:
313  list = &mm->in_sess;
314  nlist = &mm->nin_sess;
315  break;
316  case 3:
317  list = &mm->in_router;
318  nlist = &mm->nin_router;
319  break;
320  case 4:
321  list = &mm->out_sess;
322  nlist = &mm->nout_sess;
323  break;
324  case 5:
325  list = &mm->out_router;
326  nlist = &mm->nout_router;
327  break;
328  case 6:
329  list = &mm->pkt_sm;
330  nlist = &mm->npkt_sm;
331  break;
332  case 7:
333  list = &mm->pkt_user;
334  nlist = &mm->npkt_user;
335  break;
336  case 8:
337  list = &mm->pkt_router;
338  nlist = &mm->npkt_router;
339  break;
340  case 9:
341  list = &mm->user_load;
342  nlist = &mm->nuser_load;
343  break;
344  case 10:
345  list = &mm->user_create;
346  nlist = &mm->nuser_create;
347  break;
348  case 11:
349  list = &mm->user_delete;
350  nlist = &mm->nuser_delete;
351  break;
352  case 12:
353  list = &mm->disco_extend;
354  nlist = &mm->ndisco_extend;
355  break;
356  }
357 
358  for(j = 0; j < *nlist; j++) {
359  mi = (*list)[j];
360  if(mi->arg != NULL)
361  free((void*)mi->arg);
362  free(mi);
363  }
364  }
365 
366  /* free lists */
367  free(mm->sess_start);
368  free(mm->sess_end);
369  free(mm->in_sess);
370  free(mm->in_router);
371  free(mm->out_sess);
372  free(mm->out_router);
373  free(mm->pkt_sm);
374  free(mm->pkt_user);
375  free(mm->pkt_router);
376  free(mm->user_load);
377  free(mm->user_create);
378  free(mm->user_delete);
379  free(mm->disco_extend);
380 
381  xhash_free(mm->modules);
382 
383  free(mm);
384 }
385 
387 int mm_sess_start(mm_t mm, sess_t sess) {
388  int n, ret = 0;
389  mod_instance_t mi;
390 
391  log_debug(ZONE, "dispatching sess-start chain");
392 
393  ret = 0;
394  for(n = 0; n < mm->nsess_start; n++) {
395  mi = mm->sess_start[n];
396  if(mi == NULL) {
397  log_debug(ZONE, "module at index %d is not loaded yet", n);
398  continue;
399  }
400  if(mi->mod->sess_start == NULL) {
401  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
402  continue;
403  }
404 
405  log_debug(ZONE, "calling module %s", mi->mod->name);
406 
407  ret = (mi->mod->sess_start)(mi, sess);
408  if(ret != 0)
409  break;
410  }
411 
412  log_debug(ZONE, "sess-start chain returning %d", ret);
413 
414  return ret;
415 }
416 
418 void mm_sess_end(mm_t mm, sess_t sess) {
419  int n;
420  mod_instance_t mi;
421 
422  log_debug(ZONE, "dispatching sess-end chain");
423 
424  for(n = 0; n < mm->nsess_end; n++) {
425  mi = mm->sess_end[n];
426  if(mi == NULL) {
427  log_debug(ZONE, "module at index %d is not loaded yet", n);
428  continue;
429  }
430  if(mi->mod->sess_end == NULL) {
431  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
432  continue;
433  }
434 
435  log_debug(ZONE, "calling module %s", mi->mod->name);
436 
437  (mi->mod->sess_end)(mi, sess);
438  }
439 
440  log_debug(ZONE, "sess-end chain returning");
441 }
442 
445  int n;
446  mod_instance_t mi;
447  mod_ret_t ret = mod_PASS;
448 
449  log_debug(ZONE, "dispatching in-sess chain");
450 
451  ret = mod_PASS;
452  for(n = 0; n < mm->nin_sess; n++) {
453  mi = mm->in_sess[n];
454  if(mi == NULL) {
455  log_debug(ZONE, "module at index %d is not loaded yet", n);
456  continue;
457  }
458  if(mi->mod->in_sess == NULL) {
459  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
460  continue;
461  }
462 
463  log_debug(ZONE, "calling module %s", mi->mod->name);
464 
465  ret = (mi->mod->in_sess)(mi, sess, pkt);
466  if(ret != mod_PASS)
467  break;
468  }
469 
470  log_debug(ZONE, "in-sess chain returning %d", ret);
471 
472  return ret;
473 }
474 
477  int n;
478  mod_instance_t mi;
479  mod_ret_t ret = mod_PASS;
480 
481  log_debug(ZONE, "dispatching in-router chain");
482 
483  if (mm != NULL && pkt != NULL )
484  for(n = 0; n < mm->nin_router; n++) {
485  mi = mm->in_router[n];
486  if(mi == NULL) {
487  log_debug(ZONE, "module at index %d is not loaded yet", n);
488  continue;
489  }
490  if(mi->mod == NULL || mi->mod->in_router == NULL) {
491  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
492  continue;
493  }
494 
495  log_debug(ZONE, "calling module %s", mi->mod->name);
496 
497  ret = (mi->mod->in_router)(mi, pkt);
498  if(ret != mod_PASS)
499  break;
500  }
501 
502  log_debug(ZONE, "in-router chain returning %d", ret);
503 
504  return ret;
505 }
506 
509  int n;
510  mod_instance_t mi;
511  mod_ret_t ret = mod_PASS;
512 
513  log_debug(ZONE, "dispatching out-sess chain");
514 
515  for(n = 0; n < mm->nout_sess; n++) {
516  mi = mm->out_sess[n];
517  if(mi == NULL) {
518  log_debug(ZONE, "module at index %d is not loaded yet", n);
519  continue;
520  }
521  if(mi->mod->out_sess == NULL) {
522  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
523  continue;
524  }
525 
526  log_debug(ZONE, "calling module %s", mi->mod->name);
527 
528  ret = (mi->mod->out_sess)(mi, sess, pkt);
529  if(ret != mod_PASS)
530  break;
531  }
532 
533  log_debug(ZONE, "out-sess chain returning %d", ret);
534 
535  return ret;
536 }
537 
540  int n;
541  mod_instance_t mi;
542  mod_ret_t ret = mod_PASS;
543 
544  log_debug(ZONE, "dispatching out-router chain");
545 
546  for(n = 0; n < mm->nout_router; n++) {
547  mi = mm->out_router[n];
548  if(mi == NULL) {
549  log_debug(ZONE, "module at index %d is not loaded yet", n);
550  continue;
551  }
552  if(mi->mod->out_router == NULL) {
553  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
554  continue;
555  }
556 
557  log_debug(ZONE, "calling module %s", mi->mod->name);
558 
559  ret = (mi->mod->out_router)(mi, pkt);
560  if(ret != mod_PASS)
561  break;
562  }
563 
564  log_debug(ZONE, "out-router chain returning %d", ret);
565 
566  return ret;
567 }
568 
571  int n, ret = 0;
572  mod_instance_t mi;
573 
574  log_debug(ZONE, "dispatching pkt-sm chain");
575 
576  for(n = 0; n < mm->npkt_sm; n++) {
577  mi = mm->pkt_sm[n];
578  if(mi == NULL) {
579  log_debug(ZONE, "module at index %d is not loaded yet", n);
580  continue;
581  }
582  if(mi->mod->pkt_sm == NULL) {
583  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
584  continue;
585  }
586 
587  log_debug(ZONE, "calling module %s", mi->mod->name);
588 
589  ret = (mi->mod->pkt_sm)(mi, pkt);
590  if(ret != mod_PASS)
591  break;
592  }
593 
594  log_debug(ZONE, "pkt-sm chain returning %d", ret);
595 
596  return ret;
597 }
598 
601  int n;
602  mod_instance_t mi;
603  mod_ret_t ret = mod_PASS;
604 
605  log_debug(ZONE, "dispatching pkt-user chain");
606 
607  for(n = 0; n < mm->npkt_user; n++) {
608  mi = mm->pkt_user[n];
609  if(mi == NULL) {
610  log_debug(ZONE, "module at index %d is not loaded yet", n);
611  continue;
612  }
613  if(mi->mod->pkt_user == NULL) {
614  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
615  continue;
616  }
617 
618  log_debug(ZONE, "calling module %s", mi->mod->name);
619 
620  ret = (mi->mod->pkt_user)(mi, user, pkt);
621  if(ret != mod_PASS)
622  break;
623  }
624 
625  log_debug(ZONE, "pkt-user chain returning %d", ret);
626 
627  return ret;
628 }
629 
632  int n;
633  mod_instance_t mi;
634  mod_ret_t ret = mod_PASS;
635 
636  log_debug(ZONE, "dispatching pkt-router chain");
637 
638  for(n = 0; n < mm->npkt_router; n++) {
639  mi = mm->pkt_router[n];
640  if(mi == NULL) {
641  log_debug(ZONE, "module at index %d is not loaded yet", n);
642  continue;
643  }
644  if(mi->mod->pkt_router == NULL) {
645  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
646  continue;
647  }
648 
649  log_debug(ZONE, "calling module %s", mi->mod->name);
650 
651  ret = (mi->mod->pkt_router)(mi, pkt);
652  if(ret != mod_PASS)
653  break;
654  }
655 
656  log_debug(ZONE, "pkt-router chain returning %d", ret);
657 
658  return ret;
659 }
660 
662 int mm_user_load(mm_t mm, user_t user) {
663  int n;
664  mod_instance_t mi;
665  int ret = 0;
666 
667  log_debug(ZONE, "dispatching user-load chain");
668 
669  for(n = 0; n < mm->nuser_load; n++) {
670  mi = mm->user_load[n];
671  if(mi == NULL) {
672  log_debug(ZONE, "module at index %d is not loaded yet", n);
673  continue;
674  }
675  if(mi->mod->user_load == NULL) {
676  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
677  continue;
678  }
679 
680  log_debug(ZONE, "calling module %s", mi->mod->name);
681 
682  ret = (mi->mod->user_load)(mi, user);
683  if(ret != 0)
684  break;
685  }
686 
687  log_debug(ZONE, "user-load chain returning %d", ret);
688 
689  return ret;
690 }
691 
693 int mm_user_unload(mm_t mm, user_t user) {
694  int n;
695  mod_instance_t mi;
696  int ret = 0;
697 
698  log_debug(ZONE, "dispatching user-unload chain");
699 
700  for(n = 0; n < mm->nuser_unload; n++) {
701  mi = mm->user_unload[n];
702  if(mi == NULL) {
703  log_debug(ZONE, "module at index %d is not loaded yet", n);
704  continue;
705  }
706  if(mi->mod->user_unload == NULL) {
707  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
708  continue;
709  }
710 
711  log_debug(ZONE, "calling module %s", mi->mod->name);
712 
713  ret = (mi->mod->user_unload)(mi, user);
714  if(ret != 0)
715  break;
716  }
717 
718  log_debug(ZONE, "user-unload chain returning %d", ret);
719 
720  return ret;
721 }
722 
724 int mm_user_create(mm_t mm, jid_t jid) {
725  int n;
726  mod_instance_t mi;
727  int ret = 0;
728 
729  log_debug(ZONE, "dispatching user-create chain");
730 
731  for(n = 0; n < mm->nuser_create; n++) {
732  mi = mm->user_create[n];
733  if(mi == NULL) {
734  log_debug(ZONE, "module at index %d is not loaded yet", n);
735  continue;
736  }
737  if(mi->mod->user_create == NULL) {
738  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
739  continue;
740  }
741 
742  log_debug(ZONE, "calling module %s", mi->mod->name);
743 
744  ret = (mi->mod->user_create)(mi, jid);
745  if(ret != 0)
746  break;
747  }
748 
749  log_debug(ZONE, "user-create chain returning %d", ret);
750 
751  return ret;
752 }
753 
755 void mm_user_delete(mm_t mm, jid_t jid) {
756  int n;
757  mod_instance_t mi;
758 
759  log_debug(ZONE, "dispatching user-delete chain");
760 
761  for(n = 0; n < mm->nuser_delete; n++) {
762  mi = mm->user_delete[n];
763  if(mi == NULL) {
764  log_debug(ZONE, "module at index %d is not loaded yet", n);
765  continue;
766  }
767  if(mi->mod->user_delete == NULL) {
768  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
769  continue;
770  }
771 
772  log_debug(ZONE, "calling module %s", mi->mod->name);
773 
774  (mi->mod->user_delete)(mi, jid);
775  }
776 
777  log_debug(ZONE, "user-delete chain returning");
778 }
779 
781 void mm_disco_extend(mm_t mm, pkt_t pkt) {
782  int n;
783  mod_instance_t mi;
784 
785  log_debug(ZONE, "dispatching disco-extend chain");
786 
787  for(n = 0; n < mm->ndisco_extend; n++) {
788  mi = mm->disco_extend[n];
789  if(mi == NULL) {
790  log_debug(ZONE, "module at index %d is not loaded yet", n);
791  continue;
792  }
793  if(mi->mod->disco_extend == NULL) {
794  log_debug(ZONE, "module %s has no handler for this chain", mi->mod->name);
795  continue;
796  }
797 
798  log_debug(ZONE, "calling module %s", mi->mod->name);
799 
800  (mi->mod->disco_extend)(mi, pkt);
801  }
802 
803  log_debug(ZONE, "disco-extend chain returning");
804 }
int(* module_init_fn)(mod_instance_t)
module init function
Definition: sm.h:414
static sm_t sm
Definition: main.c:33
mod_instance_t * pkt_user
pkt-user chain
Definition: sm.h:387
user deletion, delete saved per-user data
Definition: sm.h:356
struct mm_st * mm_t
Definition: sm.h:63
mod_instance_t * sess_end
sess-end chain
Definition: sm.h:375
data structures and prototypes for the session manager
int nindex
counter for module instance sequence (!!! should be local to mm_new)
Definition: sm.h:370
#define NAD_CDATA_L(N, E)
Definition: nad.h:186
mod_instance_t * pkt_sm
pkt-sm chain
Definition: sm.h:385
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:662
mod_ret_t(* out_router)(mod_instance_t mi, pkt_t pkt)
out-router handler
Definition: sm.h:427
disco request, extend sm disco::info
Definition: sm.h:358
int nad_find_attr(nad_t nad, unsigned 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:237
single instance of a module in a chain
Definition: sm.h:446
log_t log
log context
Definition: sm.h:200
packet for the sm itself
Definition: sm.h:351
void mm_sess_end(mm_t mm, sess_t sess)
session ending
Definition: mm.c:418
int nuser_unload
Definition: sm.h:399
config_t config
config context
Definition: sm.h:198
int init
number of times the module intialiser has been called
Definition: sm.h:416
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:508
void(* sess_end)(mod_instance_t mi, sess_t sess)
sess-end handler
Definition: sm.h:421
mod_chain_t
module chain types
Definition: sm.h:344
user loaded, load per-user data
Definition: sm.h:354
mod_instance_t * in_sess
in-sess chain
Definition: sm.h:377
mod_ret_t(* out_sess)(mod_instance_t mi, sess_t sess, pkt_t pkt)
out-sess handler
Definition: sm.h:426
int nsess_end
Definition: sm.h:375
user creation, generate and save per-user data
Definition: sm.h:355
mod_ret_t mm_pkt_sm(mm_t mm, pkt_t pkt)
packets for sm
Definition: mm.c:570
mod_ret_t(* in_router)(mod_instance_t mi, pkt_t pkt)
in-router handler
Definition: sm.h:424
session start, load per-session data
Definition: sm.h:345
void mm_disco_extend(mm_t mm, pkt_t pkt)
disco extend
Definition: mm.c:781
mod_ret_t mm_pkt_user(mm_t mm, user_t user, pkt_t pkt)
packets for user
Definition: mm.c:600
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:408
mm_t mm
module manager
Definition: sm.h:404
int npkt_sm
Definition: sm.h:385
xht modules
pointers to module data (key is module name)
Definition: sm.h:368
int ndisco_extend
Definition: sm.h:397
#define PATH_MAX
Definition: util.h:69
void mm_user_delete(mm_t mm, jid_t jid)
delete user
Definition: mm.c:755
int npkt_user
Definition: sm.h:387
sm_t sm
sm context
Definition: sm.h:366
mod_ret_t(* in_sess)(mod_instance_t mi, sess_t sess, pkt_t pkt)
in-sess handler
Definition: sm.h:423
mod_ret_t(* pkt_router)(mod_instance_t mi, pkt_t pkt)
pkt-router handler
Definition: sm.h:432
void * handle
module handle
Definition: sm.h:412
int nuser_delete
Definition: sm.h:395
packet for a user
Definition: sm.h:352
int nuser_load
Definition: sm.h:391
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:476
module_t mod
module that this is an instance of
Definition: sm.h:449
mod_instance_t * out_router
out-router chain
Definition: sm.h:383
packet summary data wrapper
Definition: sm.h:129
int npkt_router
Definition: sm.h:389
mod_ret_t mm_pkt_router(mm_t mm, pkt_t pkt)
packets from the router
Definition: mm.c:631
packet from the router
Definition: sm.h:348
session manager global context
Definition: sm.h:167
mod_instance_t * in_router
in-router chain
Definition: sm.h:379
packet from an active session
Definition: sm.h:347
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:399
Definition: jid.h:42
int nout_router
Definition: sm.h:383
int nsess_start
Definition: sm.h:373
void mm_free(mm_t mm)
free a mm instance
Definition: mm.c:294
int nuser_create
Definition: sm.h:393
mod_ret_t mm_out_router(mm_t mm, pkt_t pkt)
packets to router
Definition: mm.c:539
#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:430
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:381
int mm_sess_start(mm_t mm, sess_t sess)
session starting
Definition: mm.c:387
#define NAD_AVAL(N, A)
Definition: nad.h:189
packet was unhandled, should be passed to the next module
Definition: sm.h:340
int mm_user_create(mm_t mm, jid_t jid)
create user
Definition: mm.c:724
mod_instance_t * disco_extend
disco-extend chain
Definition: sm.h:397
mod_ret_t mm_in_sess(mm_t mm, sess_t sess, pkt_t pkt)
packets from active session
Definition: mm.c:444
mod_instance_t * sess_start
sess-start chain
Definition: sm.h:373
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:379
int(* user_load)(mod_instance_t mi, user_t user)
user-load handler
Definition: sm.h:434
int nad_find_elem(nad_t nad, unsigned 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:206
void xhash_walk(xht h, xhash_walker w, void *arg)
Definition: xhash.c:268
module manager data
Definition: sm.h:365
void(* user_delete)(mod_instance_t mi, jid_t jid)
user-delete handler
Definition: sm.h:438
mod_ret_t(* pkt_sm)(mod_instance_t mi, pkt_t pkt)
pkt-sm handler
Definition: sm.h:429
static void _mm_reaper(const char *module, int modulelen, void *val, void *arg)
Definition: mm.c:276
mod_instance_t * pkt_router
pkt-router chain
Definition: sm.h:389
session ended, save & free per-session data
Definition: sm.h:346
mod_instance_t * user_delete
user-delete chain
Definition: sm.h:395
int(* user_unload)(mod_instance_t mi, user_t user)
user-load handler
Definition: sm.h:435
#define NAD_CDATA(N, E)
Definition: nad.h:185
user is about to be unloaded
Definition: sm.h:357
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:440
mod_instance_t * out_sess
out-sess chain
Definition: sm.h:381
const char * name
name of module
Definition: sm.h:406
#define ZONE
Definition: mio_impl.h:76
int(* sess_start)(mod_instance_t mi, sess_t sess)
sess-start handler
Definition: sm.h:420
const char * config_get_one(config_t c, const char *key, int num)
get config value n for this key
Definition: config.c:278
void(* free)(module_t mod)
called when module is freed
Definition: sm.h:442
xht xhash_new(int prime)
Definition: xhash.c:96
data for a single module
Definition: sm.h:403
int nin_sess
Definition: sm.h:377
packet to a router
Definition: sm.h:350
packet from the router (special purpose)
Definition: sm.h:353
packet to an active session
Definition: sm.h:349
int mm_user_unload(mm_t mm, user_t user)
user data is about to be unloaded
Definition: mm.c:693
mod_ret_t
module return values
Definition: sm.h:338
struct mod_instance_st * mod_instance_t
Definition: sm.h:362
mod_instance_t * user_load
user-load chain
Definition: sm.h:391
int(* user_create)(mod_instance_t mi, jid_t jid)
user-create handler
Definition: sm.h:437
mod_instance_t * user_create
user-create chain
Definition: sm.h:393
struct module_st * module_t
Definition: sm.h:361
data for a single user
Definition: sm.h:234