jabberd2  2.3.3
mod_disco.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 
30 #define ACTIVE_SESSIONS_NAME "Active sessions"
31 
33 typedef struct service_st *service_t;
34 struct service_st {
36 
37  char name[257];
38 
39  char category[257];
40  char type[257];
41 
43 };
44 
46 typedef struct disco_st *disco_t;
47 struct disco_st {
49  const char *category;
50  const char *type;
51  const char *name;
52 
54  int agents;
55 
59 
62 
67 };
68 
69 /* union for xhash_iter_get to comply with strict-alias rules for gcc3 */
70 union xhashv
71 {
72  void **val;
73  service_t *svc_val;
75  const char **char_val;
76 };
77 
79 static void _disco_unify_walker(const char *key, int keylen, void *val, void *arg) {
80  service_t svc = (service_t) val;
81  xht dest = (xht) arg;
82 
83  /* if its already there, skip this one */
84  if(xhash_get(dest, jid_full(svc->jid)) != NULL)
85  return;
86 
87  log_debug(ZONE, "unify: %s", jid_full(svc->jid));
88 
89  xhash_put(dest, jid_full(svc->jid), (void *) svc);
90 }
91 
93 static void _disco_unify_lists(disco_t d) {
94  log_debug(ZONE, "unifying lists");
95 
96  if(d->un != NULL)
97  xhash_free(d->un);
98 
99  d->un = xhash_new(101);
100 
101  /* dynamic overrieds static */
102  xhash_walk(d->dyn, _disco_unify_walker, (void *) d->un);
103  xhash_walk(d->stat, _disco_unify_walker, (void *) d->un);
104 }
105 
107 static pkt_t _disco_items_result(module_t mod, disco_t d) {
108  pkt_t pkt;
109  int ns;
110  service_t svc;
111  union xhashv xhv;
112 
113  pkt = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);
114  ns = nad_add_namespace(pkt->nad, uri_DISCO_ITEMS, NULL);
115  nad_append_elem(pkt->nad, ns, "query", 2);
116 
117  if(xhash_iter_first(d->un))
118  do {
119  xhv.svc_val = &svc;
120  xhash_iter_get(d->un, NULL, NULL, xhv.val);
121 
122  nad_append_elem(pkt->nad, ns, "item", 3);
123  nad_append_attr(pkt->nad, -1, "jid", jid_full(svc->jid));
124 
125  if(svc->name[0] != '\0')
126  nad_append_attr(pkt->nad, -1, "name", svc->name);
127  } while(xhash_iter_next(d->un));
128 
129  return pkt;
130 }
131 
133 static pkt_t _disco_info_result(module_t mod, disco_t d) {
134  pkt_t pkt;
135  int el, ns;
136  const char *key;
137  int keylen;
138 
139  pkt = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);
140  ns = nad_add_namespace(pkt->nad, uri_DISCO_INFO, NULL);
141  nad_append_elem(pkt->nad, ns, "query", 2);
142 
143  /* identity */
144  nad_append_elem(pkt->nad, ns, "identity", 3);
145  nad_append_attr(pkt->nad, -1, "category", d->category);
146  nad_append_attr(pkt->nad, -1, "type", d->type);
147  nad_append_attr(pkt->nad, -1, "name", d->name);
148 
149  /* fill in our features */
150  if(xhash_iter_first(mod->mm->sm->features))
151  do {
152  xhash_iter_get(mod->mm->sm->features, &key, &keylen, NULL);
153 
154  el = nad_append_elem(pkt->nad, ns, "feature", 3);
155  nad_set_attr(pkt->nad, el, -1, "var", (char *) key, keylen);
156  } while(xhash_iter_next(mod->mm->sm->features));
157 
158  /* put it throuhg disco_extend chain to add
159  * XEP-0128 Service Discovery Extensions */
160  mm_disco_extend(mod->mm, pkt);
161 
162  return pkt;
163 }
164 
166 static pkt_t _disco_agents_result(module_t mod, disco_t d) {
167  pkt_t pkt;
168  int ns;
169  const char *key;
170  int keylen;
171  service_t svc;
172  union xhashv xhv;
173 
174  pkt = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);
175  ns = nad_add_namespace(pkt->nad, uri_AGENTS, NULL);
176  nad_append_elem(pkt->nad, ns, "query", 2);
177 
178  /* fill in the items */
179  if(xhash_iter_first(d->un))
180  do {
181  xhv.svc_val = &svc;
182  xhash_iter_get(d->un, &key, &keylen, xhv.val);
183 
184  nad_append_elem(pkt->nad, ns, "agent", 3);
185  nad_append_attr(pkt->nad, -1, "jid", jid_full(svc->jid));
186 
187  if(svc->name[0] != '\0') {
188  nad_append_elem(pkt->nad, ns, "name", 4);
189  nad_append_cdata(pkt->nad, svc->name, strlen(svc->name), 5);
190  }
191 
192  nad_append_elem(pkt->nad, ns, "service", 4);
193  nad_append_cdata(pkt->nad, svc->type, strlen(svc->type), 5);
194 
195  /* map features to the old agent flags */
196  if(xhash_get(svc->features, uri_REGISTER) != NULL)
197  nad_append_elem(pkt->nad, ns, "register", 4);
198  if(xhash_get(svc->features, uri_SEARCH) != NULL)
199  nad_append_elem(pkt->nad, ns, "search", 4);
200  if(xhash_get(svc->features, uri_GATEWAY) != NULL)
201  nad_append_elem(pkt->nad, ns, "transport", 4);
202 
203  /* conference gets special treatment */
204  if(strcmp(svc->category, "conference") == 0)
205  nad_append_elem(pkt->nad, ns, "groupchat", 4);
206  } while(xhash_iter_next(d->un));
207 
208  return pkt;
209 }
210 
212 static void _disco_generate_packets(module_t mod, disco_t d) {
213  log_debug(ZONE, "regenerating packets");
214 
215  if(d->disco_items_result != NULL)
218 
219  if(d->disco_info_result != NULL)
222 
223  if(d->agents) {
224  if(d->agents_result != NULL)
226  d->agents_result = _disco_agents_result(mod, d);
227  }
228 
229 }
230 
233 {
234  module_t mod = mi->mod;
235  disco_t d = (disco_t) mod->private;
236  int ns, qelem, elem, attr;
237  service_t svc;
238 
239  /* it has to come from the service itself - don't want any old user messing with the table */
240  if(pkt->from->node[0] != '\0' || pkt->from->resource[0] != '\0')
241  {
242  log_debug(ZONE, "disco response from %s, not allowed", jid_full(pkt->from));
243  return -stanza_err_NOT_ALLOWED;
244  }
245 
246  ns = nad_find_scoped_namespace(pkt->nad, uri_DISCO_INFO, NULL);
247  qelem = nad_find_elem(pkt->nad, 1, ns, "query", 1);
248 
249  elem = nad_find_elem(pkt->nad, qelem, ns, "identity", 1);
250  if(elem < 0)
251  return -stanza_err_BAD_REQUEST;
252 
253  /* we don't want to list other im servers on the router */
254  if(nad_find_attr(pkt->nad, elem, -1, "category", "server") >= 0
255  && nad_find_attr(pkt->nad, elem, -1, "type", "im") >= 0) {
256  pkt_free(pkt);
257  return mod_HANDLED;
258  }
259 
260  /* see if we already have this service */
261  svc = xhash_get(d->dyn, jid_full(pkt->from));
262  if(svc == NULL)
263  {
264  /* make a new one */
265  svc = (service_t) calloc(1, sizeof(struct service_st));
266 
267  svc->jid = jid_dup(pkt->from);
268 
269  svc->features = xhash_new(11);
270 
271  /* link it in */
272  xhash_put(d->dyn, jid_full(svc->jid), (void *) svc);
273 
274  /* unify */
276  }
277 
278  /* fill in the name */
279  attr = nad_find_attr(pkt->nad, elem, -1, "name", NULL);
280  if(attr < 0)
281  svc->name[0] = '\0';
282  else
283  snprintf(svc->name, 257, "%.*s", NAD_AVAL_L(pkt->nad, attr), NAD_AVAL(pkt->nad, attr));
284 
285  /* category and type */
286  attr = nad_find_attr(pkt->nad, elem, -1, "category", NULL);
287  if(attr >= 0)
288  snprintf(svc->category, 257, "%.*s", NAD_AVAL_L(pkt->nad, attr), NAD_AVAL(pkt->nad, attr));
289  else
290  strcpy(svc->category, "unknown");
291 
292  attr = nad_find_attr(pkt->nad, elem, -1, "type", NULL);
293  if(attr >= 0)
294  snprintf(svc->type, 257, "%.*s", NAD_AVAL_L(pkt->nad, attr), NAD_AVAL(pkt->nad, attr));
295  else
296  strcpy(svc->type, "unknown");
297 
298  /* features */
299  elem = nad_find_elem(pkt->nad, qelem, -1, "feature", 1);
300  while(elem >= 0)
301  {
302  attr = nad_find_attr(pkt->nad, elem, -1, "var", NULL);
303  if(attr < 0)
304  {
305  elem = nad_find_elem(pkt->nad, elem, -1, "feature", 0);
306  continue;
307  }
308 
309  xhash_put(svc->features, pstrdupx(xhash_pool(svc->features), NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr)), (void *) 1);
310 
311  elem = nad_find_elem(pkt->nad, elem, -1, "feature", 0);
312  }
313 
314  /* regenerate packets */
315  _disco_generate_packets(mod, d);
316 
317  pkt_free(pkt);
318 
319  return mod_HANDLED;
320 }
321 
324 {
325  /* it has to have no to address or self bare jid */
326  if(pkt->to != NULL && strcmp(jid_user(sess->jid), jid_full(pkt->to)))
327  {
328  return mod_PASS;
329  }
330 
331  /* identity */
332  nad_append_elem(pkt->nad, -1, "identity", 3);
333  nad_append_attr(pkt->nad, -1, "category", "account");
334  nad_append_attr(pkt->nad, -1, "type", "registered");
335 
336  /* tell them */
337  nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);
338  pkt_sess(pkt_tofrom(pkt), sess);
339 
340  return mod_HANDLED;
341 }
342 
344 static void _disco_sessions_result(module_t mod, disco_t d, pkt_t pkt) {
345  int ns;
346  sess_t sess;
347  union xhashv xhv;
348 
349  ns = nad_add_namespace(pkt->nad, uri_DISCO_ITEMS, NULL);
350  nad_append_elem(pkt->nad, ns, "query", 2);
351  nad_append_attr(pkt->nad, -1, "node", "sessions");
352 
353  if(xhash_iter_first(mod->mm->sm->sessions))
354  do {
355  xhv.sess_val = &sess;
356  xhash_iter_get(mod->mm->sm->sessions, NULL, NULL, xhv.val);
357 
358  nad_append_elem(pkt->nad, ns, "item", 3);
359  nad_append_attr(pkt->nad, -1, "jid", jid_full(sess->jid));
360  nad_append_attr(pkt->nad, -1, "name", "Active session");
361  } while(xhash_iter_next(mod->mm->sm->sessions));
362 }
363 
366  module_t mod = mi->mod;
367  disco_t d = (disco_t) mod->private;
368  pkt_t result;
369  int node, ns;
370 
371  /* disco info results go to a seperate function */
372  if(pkt->type == pkt_IQ_RESULT && pkt->ns == ns_DISCO_INFO)
373  return _disco_pkt_sm_populate(mi, pkt);
374 
375  /* check whether the requested domain is serviced here */
376  if(xhash_get(mod->mm->sm->hosts, pkt->to->domain) == NULL)
378 
379  /* we want disco or agents gets */
380  if(pkt->type != pkt_IQ || !(pkt->ns == ns_DISCO_INFO || pkt->ns == ns_DISCO_ITEMS || pkt->ns == ns_AGENTS))
381  return mod_PASS;
382 
383  /* generate the caches if we haven't yet */
384  if(d->disco_info_result == NULL)
385  _disco_generate_packets(mod, d);
386 
387  node = nad_find_attr(pkt->nad, 2, -1, "node", NULL);
388 
389  /* they want to know about us */
390  if(pkt->ns == ns_DISCO_INFO) {
391  /* respond with cached disco info packet if no node given */
392  if(node < 0) {
393  result = pkt_dup(d->disco_info_result, jid_full(pkt->from), jid_full(pkt->to));
394 
395  node = nad_find_attr(pkt->nad, 2, -1, "node", NULL);
396  if(node >= 0) {
397  nad_set_attr(result->nad, 2, -1, "node", NAD_AVAL(pkt->nad, node), NAD_AVAL_L(pkt->nad, node));
398  }
399 
400  pkt_id(pkt, result);
401  pkt_free(pkt);
402 
403  /* off it goes */
404  pkt_router(result);
405 
406  return mod_HANDLED;
407  }
408  else if(NAD_AVAL_L(pkt->nad, node) == 8 && strncmp("sessions", NAD_AVAL(pkt->nad, node), 8) == 0) {
409  /* priviliged op, make sure they're allowed */
410  if(!aci_check(mod->mm->sm->acls, "disco", pkt->from))
411  return -stanza_err_ITEM_NOT_FOUND; /* we never advertised it, so we can pretend its not here */
412 
413  result = pkt_create(mod->mm->sm, "iq", "result", jid_full(pkt->from), jid_full(pkt->to));
414  pkt_id(pkt, result);
415  pkt_free(pkt);
416 
417  ns = nad_add_namespace(result->nad, uri_DISCO_INFO, NULL);
418  nad_append_elem(result->nad, ns, "query", 2);
419  nad_append_elem(result->nad, ns, "identity", 3);
420  nad_append_attr(result->nad, -1, "category", "hierarchy");
421  nad_append_attr(result->nad, -1, "type", "branch");
422  nad_append_attr(result->nad, -1, "name", ACTIVE_SESSIONS_NAME);
423  nad_append_elem(result->nad, -1, "feature", 3);
424  nad_append_attr(result->nad, -1, "var", uri_DISCO_INFO);
425  nad_append_elem(result->nad, -1, "feature", 3);
426  nad_append_attr(result->nad, -1, "var", uri_DISCO_ITEMS);
427 
428  /* off it goes */
429  pkt_router(result);
430 
431  return mod_HANDLED;
432  }
433  else
435  }
436 
437  /* handle agents */
438  if(pkt->ns == ns_AGENTS) {
439  /* make sure we're supporting compat */
440  if(!d->agents)
441  return -stanza_err_NOT_ALLOWED;
442 
443  result = pkt_dup(d->agents_result, jid_full(pkt->from), jid_full(pkt->to));
444  pkt_id(pkt, result);
445  pkt_free(pkt);
446 
447  /* off it goes */
448  pkt_router(result);
449 
450  return mod_HANDLED;
451  }
452 
453  /* they want to know who we know about */
454  if(node < 0) {
455  /* no node, so toplevel services */
456  result = pkt_dup(d->disco_items_result, jid_full(pkt->from), jid_full(pkt->to));
457  pkt_id(pkt, result);
458  pkt_free(pkt);
459 
460  /* if they have privs, then show them any administrative things they can disco to */
461  if(aci_check(mod->mm->sm->acls, "disco", result->to)) {
462  nad_append_elem(result->nad, NAD_ENS(result->nad, 2), "item", 3);
463  nad_append_attr(result->nad, -1, "jid", jid_full(result->from));
464  nad_append_attr(result->nad, -1, "node", "sessions");
465  nad_append_attr(result->nad, -1, "name", ACTIVE_SESSIONS_NAME);
466  }
467 
468  pkt_router(result);
469 
470  return mod_HANDLED;
471  }
472 
473  /* active sessions */
474  if(NAD_AVAL_L(pkt->nad, node) == 8 && strncmp("sessions", NAD_AVAL(pkt->nad, node), 8) == 0) {
475  /* priviliged op, make sure they're allowed */
476  if(!aci_check(mod->mm->sm->acls, "disco", pkt->from))
477  return -stanza_err_ITEM_NOT_FOUND; /* we never advertised it, so we can pretend its not here */
478 
479  result = pkt_create(mod->mm->sm, "iq", "result", jid_full(pkt->from), jid_full(pkt->to));
480  pkt_id(pkt, result);
481  pkt_free(pkt);
482 
483  _disco_sessions_result(mod, d, result);
484 
485  /* off it goes */
486  pkt_router(result);
487 
488  return mod_HANDLED;
489  }
490 
491  /* I dunno what they're asking for */
493 }
494 
497  module_t mod = mi->mod;
498  disco_t d = (disco_t) mod->private;
499  pkt_t result;
500 
501  /* disco info requests go to a seperate function */
502  if(pkt->type == pkt_IQ && pkt->ns == ns_DISCO_INFO)
503  return _disco_in_sess_result(mi, sess, pkt);
504 
505  /* we want agents gets */
506  if(pkt->type != pkt_IQ || pkt->ns != ns_AGENTS || pkt->to != NULL)
507  return mod_PASS;
508 
509  /* fail if its not enabled */
510  if(!d->agents)
511  return -stanza_err_NOT_ALLOWED;
512 
513  /* generate the caches if we haven't yet */
514  if(d->disco_info_result == NULL)
515  _disco_generate_packets(mod, d);
516 
517  /* pre-canned response */
518  result = pkt_dup(d->agents_result, NULL, NULL);
519  pkt_id(pkt, result);
520  pkt_free(pkt);
521 
522  /* off it goes */
523  pkt_sess(result, sess);
524 
525  return mod_HANDLED;
526 }
527 
530 {
531  module_t mod = mi->mod;
532  disco_t d = (disco_t) mod->private;
533  service_t svc;
534  pkt_t request;
535  int ns;
536 
537  /* we want advertisements with a from address */
538  if(pkt->from == NULL || !(pkt->rtype & route_ADV))
539  return mod_PASS;
540 
541  /* component online */
542  if(pkt->rtype == route_ADV)
543  {
544  log_debug(ZONE, "presence from component %s, issuing discovery request", jid_full(pkt->from));
545 
546  /* new disco get packet */
547  request = pkt_create(mod->mm->sm, "iq", "get", jid_full(pkt->from), mod->mm->sm->id);
548  pkt_id_new(request);
549  ns = nad_add_namespace(request->nad, uri_DISCO_INFO, NULL);
550  nad_append_elem(request->nad, ns, "query", 2);
551 
552  pkt_router(request);
553 
554  /* done with this */
555  pkt_free(pkt);
556 
557  return mod_HANDLED;
558  }
559 
560  /* it went away. find it and remove it */
561  svc = xhash_get(d->dyn, jid_full(pkt->from));
562  if(svc != NULL)
563  {
564  log_debug(ZONE, "dropping entry for %s", jid_full(pkt->from));
565 
566  xhash_zap(d->dyn, jid_full(pkt->from));
567 
568  jid_free(svc->jid);
569  xhash_free(svc->features);
570  free(svc);
571 
572  /* unify */
574  _disco_generate_packets(mod, d);
575  }
576 
577  /* done */
578  pkt_free(pkt);
579 
580  return mod_HANDLED;
581 }
582 
583 static void _disco_free_walker(const char *key, int keylen, void *val, void *arg) {
584  service_t svc = (service_t) val;
585 
586  jid_free(svc->jid);
587  xhash_free(svc->features);
588  free(svc);
589 }
590 
591 static void _disco_free(module_t mod) {
592  disco_t d = (disco_t) mod->private;
593 
595  xhash_walk(d->dyn, _disco_free_walker, NULL);
596 
597  xhash_free(d->stat);
598  xhash_free(d->dyn);
599  xhash_free(d->un);
600 
601  if(d->disco_info_result != NULL) pkt_free(d->disco_info_result);
603  if(d->agents_result != NULL) pkt_free(d->agents_result);
604 
605  free(d);
606 }
607 
608 DLLEXPORT int module_init(mod_instance_t mi, const char *arg)
609 {
610  module_t mod = mi->mod;
611  disco_t d;
612  nad_t nad;
613  int items, item, jid, name, category, type, ns;
614  service_t svc;
615 
616  if(mod->init) return 0;
617 
618  log_debug(ZONE, "disco module init");
619 
620  d = (disco_t) calloc(1, sizeof(struct disco_st));
621 
622  /* new hashes to store the lists in */
623  d->dyn = xhash_new(51);
624  d->stat = xhash_new(51);
625 
626  /* identity */
627  d->category = config_get_one(mod->mm->sm->config, "discovery.identity.category", 0);
628  if(d->category == NULL) d->category = "server";
629  d->type = config_get_one(mod->mm->sm->config, "discovery.identity.type", 0);
630  if(d->type == NULL) d->type = "im";
631  d->name = config_get_one(mod->mm->sm->config, "discovery.identity.name", 0);
632  if(d->name == NULL) d->name = "Jabber IM server";
633 
634  /* agents compatibility */
635  d->agents = config_get(mod->mm->sm->config, "discovery.agents") != NULL;
636 
637  if(d->agents)
638  log_debug(ZONE, "agents compat enabled");
639 
640  /* our data */
641  mod->private = (void *) d;
642 
643  /* our handlers */
644  mod->pkt_sm = _disco_pkt_sm;
645  mod->in_sess = _disco_in_sess;
647  mod->free = _disco_free;
648 
649  nad = mod->mm->sm->config->nad;
650 
651  /* we support a number of things */
654  if(d->agents)
656 
657  /* populate the static list from the config file */
658  if((items = nad_find_elem(nad, 0, -1, "discovery", 1)) < 0 || (items = nad_find_elem(nad, items, -1, "items", 1)) < 0)
659  return 0;
660 
661  item = nad_find_elem(nad, items, -1, "item", 1);
662  while(item >= 0)
663  {
664  /* jid is required */
665  jid = nad_find_attr(nad, item, -1, "jid", NULL);
666  if(jid < 0)
667  {
668  item = nad_find_elem(nad, item, -1, "item", 0);
669  continue;
670  }
671 
672  /* new service */
673  svc = (service_t) calloc(1, sizeof(struct service_st));
674 
675  svc->features = xhash_new(13);
676 
677  svc->jid = jid_new(NAD_AVAL(nad, jid), NAD_AVAL_L(nad, jid));
678 
679  /* link it in */
680  xhash_put(d->stat, jid_full(svc->jid), (void *) svc);
681 
682  /* copy the name */
683  name = nad_find_attr(nad, item, -1, "name", NULL);
684  if(name >= 0)
685  snprintf(svc->name, 257, "%.*s", NAD_AVAL_L(nad, name), NAD_AVAL(nad, name));
686 
687  /* category and type */
688  category = nad_find_attr(nad, item, -1, "category", NULL);
689  if(category >= 0)
690  snprintf(svc->category, 257, "%.*s", NAD_AVAL_L(nad, category), NAD_AVAL(nad, category));
691  else
692  strcpy(svc->category, "unknown");
693 
694  type = nad_find_attr(nad, item, -1, "type", NULL);
695  if(type >= 0)
696  snprintf(svc->type, 257, "%.*s", NAD_AVAL_L(nad, type), NAD_AVAL(nad, type));
697  else
698  strcpy(svc->type, "unknown");
699 
700  /* namespaces */
701  ns = nad_find_elem(nad, item, -1, "ns", 1);
702  while(ns >= 0)
703  {
704  if(NAD_CDATA_L(nad, ns) > 0)
705  xhash_put(svc->features, pstrdupx(xhash_pool(svc->features), NAD_CDATA(nad, ns), NAD_CDATA_L(nad, ns)), (void *) 1);
706 
707  ns = nad_find_elem(nad, ns, -1, "ns", 0);
708  }
709 
710  item = nad_find_elem(nad, item, -1, "item", 0);
711 
712  log_debug(ZONE, "added %s to static list", jid_full(svc->jid));
713  }
714 
715  /* generate the initial union list */
717 
718  /* we don't generate the packets here, because the router conn isn't up yet, and so we don't have a nad cache */
719 
720  return 0;
721 }
#define ACTIVE_SESSIONS_NAME
Definition: mod_disco.c:30
struct xht_struct * xht
pkt_type_t type
packet type
Definition: sm.h:138
jid_t jid
session jid (user@host/res)
Definition: sm.h:257
Definition: nad.h:93
int nad_append_attr(nad_t nad, int ns, const char *name, const char *val)
attach new attr to the last elem
Definition: nad.c:701
data structures and prototypes for the session manager
#define ns_DISCO_INFO
Definition: sm.h:81
xht stat
Definition: mod_disco.c:58
static void _disco_sessions_result(module_t mod, disco_t d, pkt_t pkt)
build a disco items result, active sessions
Definition: mod_disco.c:344
#define NAD_CDATA_L(N, E)
Definition: nad.h:186
const char * id
component id
Definition: sm.h:168
#define ns_DISCO_ITEMS
Definition: sm.h:80
void xhash_free(xht h)
Definition: xhash.c:241
const char * jid_user(jid_t jid)
expand and return the user
Definition: jid.c:339
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:347
service_t * svc_val
Definition: mod_disco.c:73
pkt_t agents_result
Definition: mod_disco.c:66
jid_t jid_new(const char *id, int len)
make a new jid
Definition: jid.c:81
pkt_t pkt_tofrom(pkt_t pkt)
swap a packet's to and from attributes
Definition: pkt.c:57
single instance of a module in a chain
Definition: sm.h:445
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
void nad_append_cdata(nad_t nad, const char *cdata, int len, int depth)
append new cdata to the last elem
Definition: nad.c:709
config_t config
config context
Definition: sm.h:197
int init
number of times the module intialiser has been called
Definition: sm.h:415
xht hosts
vHosts map
Definition: sm.h:223
int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
bring a new namespace into scope
Definition: nad.c:734
pkt_t pkt_dup(pkt_t pkt, const char *to, const char *from)
duplicate pkt, replacing addresses
Definition: pkt.c:84
info/query (result)
Definition: sm.h:108
const char * category
identity
Definition: mod_disco.c:49
void pkt_id_new(pkt_t pkt)
create an id value for new iq packets
Definition: pkt.c:364
void mm_disco_extend(mm_t mm, pkt_t pkt)
disco extend
Definition: mm.c:778
int agents
compatibility
Definition: mod_disco.c:54
char * resource
Definition: jid.h:46
static mod_ret_t _disco_pkt_sm(mod_instance_t mi, pkt_t pkt)
catch responses and populate the table; respond to requests
Definition: mod_disco.c:365
int nad_append_elem(nad_t nad, int ns, const char *name, int depth)
create a new elem on the list
Definition: nad.c:667
int xhash_iter_next(xht h)
Definition: xhash.c:320
static mod_ret_t _disco_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt)
legacy support for agents requests from sessions
Definition: mod_disco.c:496
xht sessions
pointers to all connected sessions (key is random sm id)
Definition: sm.h:190
mm_t mm
module manager
Definition: sm.h:403
static pkt_t _disco_items_result(module_t mod, disco_t d)
build a disco items result, known services
Definition: mod_disco.c:107
static void _disco_free_walker(const char *key, int keylen, void *val, void *arg)
Definition: mod_disco.c:583
const char * name
Definition: mod_disco.c:51
#define DLLEXPORT
Definition: c2s.h:47
void nad_set_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen)
create, update, or zap any matching attr on this elem
Definition: nad.c:375
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
struct disco_st * disco_t
all the current disco data
Definition: mod_disco.c:46
mod_ret_t(* pkt_router)(mod_instance_t mi, pkt_t pkt)
pkt-router handler
Definition: sm.h:431
nad_t nad
Definition: util.h:203
module_t mod
module that this is an instance of
Definition: sm.h:448
jid_t from
packet addressing (not used for routing)
Definition: sm.h:140
void * private
module private data
Definition: sm.h:417
void ** val
Definition: c2s.h:384
packet summary data wrapper
Definition: sm.h:129
char * pstrdupx(pool_t p, const char *src, int len)
use given size
Definition: pool.c:205
nad_t nad
nad of the entire packet
Definition: sm.h:146
void jid_free(jid_t jid)
free a jid
Definition: jid.c:286
int aci_check(xht aci, const char *type, const char *name)
see if a username is in an acl
Definition: aci.c:93
advertisement (available)
Definition: sm.h:123
static mod_ret_t _disco_pkt_sm_populate(mod_instance_t mi, pkt_t pkt)
catch responses and populate the table
Definition: mod_disco.c:232
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
sess_t * sess_val
Definition: c2s.h:386
#define uri_AGENTS
Definition: uri.h:63
#define stanza_err_BAD_REQUEST
Definition: util.h:367
char * domain
Definition: jid.h:45
xht features
Definition: mod_disco.c:42
jid_t jid
Definition: mod_disco.c:35
Definition: jid.h:42
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
Definition: xhash.c:374
#define uri_REGISTER
Definition: uri.h:61
#define NAD_AVAL_L(N, A)
Definition: nad.h:190
void pkt_id(pkt_t src, pkt_t dest)
convenience - copy the packet id from src to dest
Definition: pkt.c:353
void pkt_router(pkt_t pkt)
Definition: pkt.c:379
void xhash_zap(xht h, const char *key)
Definition: xhash.c:235
void pkt_free(pkt_t pkt)
Definition: pkt.c:315
#define log_debug(...)
Definition: log.h:65
pkt_t disco_items_result
Definition: mod_disco.c:65
#define stanza_err_NOT_ALLOWED
Definition: util.h:376
void feature_register(sm_t sm, const char *feature)
register a feature
Definition: feature.c:37
info/query (get)
Definition: sm.h:106
#define NAD_AVAL(N, A)
Definition: nad.h:189
#define uri_SEARCH
Definition: uri.h:76
xht dyn
the lists
Definition: mod_disco.c:57
#define uri_GATEWAY
Definition: uri.h:71
packet was unhandled, should be passed to the next module
Definition: sm.h:339
int ns
iq sub-namespace
Definition: sm.h:142
#define stanza_err_ITEM_NOT_FOUND
Definition: util.h:373
config_elem_t config_get(config_t c, const char *key)
get the config element for this key
Definition: config.c:271
packet was handled (and freed)
Definition: sm.h:338
static mod_ret_t _disco_pkt_router(mod_instance_t mi, pkt_t pkt)
update the table for component changes
Definition: mod_disco.c:529
There is one instance of this struct per user who is logged in to this c2s instance.
Definition: c2s.h:74
static mod_ret_t _disco_in_sess_result(mod_instance_t mi, sess_t sess, pkt_t pkt)
respond to user quering its JID
Definition: mod_disco.c:323
static void _disco_unify_walker(const char *key, int keylen, void *val, void *arg)
put val into arg
Definition: mod_disco.c:79
int xhash_iter_first(xht h)
iteration
Definition: xhash.c:311
struct service_st * service_t
holder for a single service
Definition: mod_disco.c:33
void xhash_walk(xht h, xhash_walker w, void *arg)
Definition: xhash.c:268
static void _disco_generate_packets(module_t mod, disco_t d)
generate cached result packets
Definition: mod_disco.c:212
static pkt_t _disco_info_result(module_t mod, disco_t d)
build a disco info result
Definition: mod_disco.c:133
mod_ret_t(* pkt_sm)(mod_instance_t mi, pkt_t pkt)
pkt-sm handler
Definition: sm.h:428
pkt_t disco_info_result
cached result packets
Definition: mod_disco.c:64
const char ** char_val
Definition: c2s.h:385
jid_t to
Definition: sm.h:140
static void _disco_free(module_t mod)
Definition: mod_disco.c:591
pool_t xhash_pool(xht h)
get our pool
Definition: xhash.c:305
#define NAD_CDATA(N, E)
Definition: nad.h:185
jid_t jid_dup(jid_t jid)
duplicate a jid
Definition: jid.c:373
char category[257]
Definition: mod_disco.c:39
void * xhash_get(xht h, const char *key)
Definition: xhash.c:184
xht acls
access control lists (key is list name, value is jid_t list)
Definition: sm.h:214
#define ZONE
Definition: mio_impl.h:76
session packet handling
Definition: c2s.h:382
xht un
unified list
Definition: mod_disco.c:61
static pkt_t _disco_agents_result(module_t mod, disco_t d)
build an agents result
Definition: mod_disco.c:166
const char * config_get_one(config_t c, const char *key, int num)
get config value n for this key
Definition: config.c:277
char name[257]
Definition: mod_disco.c:37
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
#define uri_DISCO_INFO
Definition: uri.h:80
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
#define uri_DISCO_ITEMS
Definition: uri.h:79
static void _disco_unify_lists(disco_t d)
unify the contents of dyn and stat
Definition: mod_disco.c:93
pkt_t pkt_create(sm_t sm, const char *elem, const char *type, const char *to, const char *from)
Definition: pkt.c:328
mod_ret_t
module return values
Definition: sm.h:337
const char * type
Definition: mod_disco.c:50
#define ns_AGENTS
Definition: sm.h:72
void pkt_sess(pkt_t pkt, sess_t sess)
Definition: pkt.c:459
char type[257]
Definition: mod_disco.c:40
char * node
Definition: jid.h:44
DLLEXPORT int module_init(mod_instance_t mi, const char *arg)
Definition: mod_disco.c:608
#define NAD_ENS(N, E)
Definition: nad.h:196
int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix)
find a namespace in scope
Definition: nad.c:290
route_type_t rtype
type of enclosing route
Definition: sm.h:136
xht features
feature index (key is feature string
Definition: sm.h:195