Wed Jan 8 2020 09:49:44

Asterisk developer's documentation


chan_jingle.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Matt O'Gorman <mogorman@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \author Matt O'Gorman <mogorman@digium.com>
22  *
23  * \brief Jingle Channel Driver
24  *
25  * \extref Iksemel http://iksemel.jabberstudio.org/
26  *
27  * \ingroup channel_drivers
28  */
29 
30 /*** MODULEINFO
31  <depend>iksemel</depend>
32  <depend>res_jabber</depend>
33  <use>openssl</use>
34  <support_level>extended</support_level>
35  ***/
36 
37 #include "asterisk.h"
38 
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
40 
41 #include <sys/socket.h>
42 #include <fcntl.h>
43 #include <netdb.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #include <sys/signal.h>
47 #include <iksemel.h>
48 #include <pthread.h>
49 
50 #include "asterisk/lock.h"
51 #include "asterisk/channel.h"
52 #include "asterisk/config.h"
53 #include "asterisk/module.h"
54 #include "asterisk/pbx.h"
55 #include "asterisk/sched.h"
56 #include "asterisk/io.h"
57 #include "asterisk/rtp_engine.h"
58 #include "asterisk/acl.h"
59 #include "asterisk/callerid.h"
60 #include "asterisk/file.h"
61 #include "asterisk/cli.h"
62 #include "asterisk/app.h"
63 #include "asterisk/musiconhold.h"
64 #include "asterisk/manager.h"
65 #include "asterisk/stringfields.h"
66 #include "asterisk/utils.h"
67 #include "asterisk/causes.h"
68 #include "asterisk/astobj.h"
69 #include "asterisk/abstract_jb.h"
70 #include "asterisk/jabber.h"
71 #include "asterisk/jingle.h"
72 
73 #define JINGLE_CONFIG "jingle.conf"
74 
75 /*! Global jitterbuffer configuration - by default, jb is disabled */
76 static struct ast_jb_conf default_jbconf =
77 {
78  .flags = 0,
79  .max_size = -1,
80  .resync_threshold = -1,
81  .impl = "",
82  .target_extra = -1,
83 };
84 static struct ast_jb_conf global_jbconf;
85 
89 };
90 
96 };
97 
98 struct jingle_pvt {
99  ast_mutex_t lock; /*!< Channel private lock */
100  time_t laststun;
101  struct jingle *parent; /*!< Parent client */
102  char sid[100];
104  char ring[10]; /*!< Message ID of ring */
105  iksrule *ringrule; /*!< Rule for matching RING request */
106  int initiator; /*!< If we're the initiator */
112  char cid_num[80]; /*!< Caller ID num */
113  char cid_name[80]; /*!< Caller ID name */
114  char exten[80]; /*!< Called extension */
115  struct ast_channel *owner; /*!< Master Channel */
116  char audio_content_name[100]; /*!< name attribute of content tag */
117  struct ast_rtp_instance *rtp; /*!< RTP audio session */
118  char video_content_name[100]; /*!< name attribute of content tag */
119  struct ast_rtp_instance *vrtp; /*!< RTP video session */
120  format_t jointcapability; /*!< Supported capability at both ends (codecs ) */
122  struct jingle_pvt *next; /* Next entity */
123 };
124 
126  unsigned int component; /*!< ex. : 1 for RTP, 2 for RTCP */
127  unsigned int foundation; /*!< Function of IP, protocol, type */
128  unsigned int generation;
129  char ip[16];
130  unsigned int network;
131  unsigned int port;
132  unsigned int priority;
134  char password[100];
136  char ufrag[100];
137  unsigned int preference;
139 };
140 
141 struct jingle {
144  struct aji_buddy *buddy;
145  struct jingle_pvt *p;
147  int amaflags; /*!< AMA Flags */
148  char user[100];
149  char context[100];
150  char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
152  ast_group_t callgroup; /*!< Call group */
153  ast_group_t pickupgroup; /*!< Pickup group */
154  int callingpres; /*!< Calling presentation */
156  char language[MAX_LANGUAGE]; /*!< Default language for prompts */
157  char musicclass[MAX_MUSICCLASS]; /*!< Music on Hold class */
158  char parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */
159 };
160 
163 };
164 
165 static const char desc[] = "Jingle Channel";
166 static const char channel_type[] = "Jingle";
167 
169 
170 AST_MUTEX_DEFINE_STATIC(jinglelock); /*!< Protect the interface list (of jingle_pvt's) */
171 
172 /* Forward declarations */
173 static struct ast_channel *jingle_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
174 static int jingle_sendtext(struct ast_channel *ast, const char *text);
175 static int jingle_digit_begin(struct ast_channel *ast, char digit);
176 static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
177 static int jingle_call(struct ast_channel *ast, char *dest, int timeout);
178 static int jingle_hangup(struct ast_channel *ast);
179 static int jingle_answer(struct ast_channel *ast);
180 static int jingle_newcall(struct jingle *client, ikspak *pak);
181 static struct ast_frame *jingle_read(struct ast_channel *ast);
182 static int jingle_write(struct ast_channel *ast, struct ast_frame *f);
183 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
184 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
185 static int jingle_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
186 static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid);
187 static char *jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
188 static char *jingle_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
189 
190 /*! \brief PBX interface structure for channel registration */
191 static const struct ast_channel_tech jingle_tech = {
192  .type = "Jingle",
193  .description = "Jingle Channel Driver",
194  .capabilities = AST_FORMAT_AUDIO_MASK,
195  .requester = jingle_request,
196  .send_text = jingle_sendtext,
197  .send_digit_begin = jingle_digit_begin,
198  .send_digit_end = jingle_digit_end,
199  .bridge = ast_rtp_instance_bridge,
200  .call = jingle_call,
201  .hangup = jingle_hangup,
202  .answer = jingle_answer,
203  .read = jingle_read,
204  .write = jingle_write,
205  .exception = jingle_read,
206  .indicate = jingle_indicate,
207  .fixup = jingle_fixup,
208  .send_html = jingle_sendhtml,
210 };
211 
212 static struct sockaddr_in bindaddr = { 0, }; /*!< The address we bind to */
213 
214 static struct sched_context *sched; /*!< The scheduling context */
215 static struct io_context *io; /*!< The IO context */
216 static struct in_addr __ourip;
217 
218 static struct ast_cli_entry jingle_cli[] = {
219  AST_CLI_DEFINE(jingle_do_reload, "Reload Jingle configuration"),
220  AST_CLI_DEFINE(jingle_show_channels, "Show Jingle channels"),
221 };
222 
223 
224 static char externip[16];
225 
227 
228 static void jingle_member_destroy(struct jingle *obj)
229 {
230  ast_free(obj);
231 }
232 
233 static struct jingle *find_jingle(char *name, char *connection)
234 {
235  struct jingle *jingle = NULL;
236 
237  jingle = ASTOBJ_CONTAINER_FIND(&jingle_list, name);
238  if (!jingle && strchr(name, '@'))
239  jingle = ASTOBJ_CONTAINER_FIND_FULL(&jingle_list, name, user,,, strcasecmp);
240 
241  if (!jingle) {
242  /* guest call */
244  ASTOBJ_RDLOCK(iterator);
245  if (!strcasecmp(iterator->name, "guest")) {
246  jingle = iterator;
247  }
248  ASTOBJ_UNLOCK(iterator);
249 
250  if (jingle)
251  break;
252  });
253 
254  }
255  return jingle;
256 }
257 
258 
259 static void add_codec_to_answer(const struct jingle_pvt *p, int codec, iks *dcodecs)
260 {
261  char *format = ast_getformatname(codec);
262 
263  if (!strcasecmp("ulaw", format)) {
264  iks *payload_eg711u, *payload_pcmu;
265  payload_pcmu = iks_new("payload-type");
266  iks_insert_attrib(payload_pcmu, "id", "0");
267  iks_insert_attrib(payload_pcmu, "name", "PCMU");
268  payload_eg711u = iks_new("payload-type");
269  iks_insert_attrib(payload_eg711u, "id", "100");
270  iks_insert_attrib(payload_eg711u, "name", "EG711U");
271  iks_insert_node(dcodecs, payload_pcmu);
272  iks_insert_node(dcodecs, payload_eg711u);
273  }
274  if (!strcasecmp("alaw", format)) {
275  iks *payload_eg711a;
276  iks *payload_pcma = iks_new("payload-type");
277  iks_insert_attrib(payload_pcma, "id", "8");
278  iks_insert_attrib(payload_pcma, "name", "PCMA");
279  payload_eg711a = iks_new("payload-type");
280  iks_insert_attrib(payload_eg711a, "id", "101");
281  iks_insert_attrib(payload_eg711a, "name", "EG711A");
282  iks_insert_node(dcodecs, payload_pcma);
283  iks_insert_node(dcodecs, payload_eg711a);
284  }
285  if (!strcasecmp("ilbc", format)) {
286  iks *payload_ilbc = iks_new("payload-type");
287  iks_insert_attrib(payload_ilbc, "id", "97");
288  iks_insert_attrib(payload_ilbc, "name", "iLBC");
289  iks_insert_node(dcodecs, payload_ilbc);
290  }
291  if (!strcasecmp("g723", format)) {
292  iks *payload_g723 = iks_new("payload-type");
293  iks_insert_attrib(payload_g723, "id", "4");
294  iks_insert_attrib(payload_g723, "name", "G723");
295  iks_insert_node(dcodecs, payload_g723);
296  }
297 }
298 
299 static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p)
300 {
301  struct jingle_pvt *tmp = client->p;
302  struct aji_client *c = client->connection;
303  iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn;
304  int x;
305  format_t pref_codec = 0;
306  int alreadysent = 0;
307 
308  if (p->initiator)
309  return 1;
310 
311  iq = iks_new("iq");
312  jingle = iks_new(JINGLE_NODE);
313  dcodecs = iks_new("description");
314  if (iq && jingle && dcodecs) {
315  iks_insert_attrib(dcodecs, "xmlns", JINGLE_AUDIO_RTP_NS);
316 
317  for (x = 0; x < 64; x++) {
318  if (!(pref_codec = ast_codec_pref_index(&client->prefs, x)))
319  break;
320  if (!(client->capability & pref_codec))
321  continue;
322  if (alreadysent & pref_codec)
323  continue;
324  add_codec_to_answer(p, pref_codec, dcodecs);
325  alreadysent |= pref_codec;
326  }
327  payload_red = iks_new("payload-type");
328  iks_insert_attrib(payload_red, "id", "117");
329  iks_insert_attrib(payload_red, "name", "red");
330  payload_audio = iks_new("payload-type");
331  iks_insert_attrib(payload_audio, "id", "106");
332  iks_insert_attrib(payload_audio, "name", "audio/telephone-event");
333  payload_cn = iks_new("payload-type");
334  iks_insert_attrib(payload_cn, "id", "13");
335  iks_insert_attrib(payload_cn, "name", "CN");
336 
337 
338  iks_insert_attrib(iq, "type", "set");
339  iks_insert_attrib(iq, "to", (p->them) ? p->them : client->user);
340  iks_insert_attrib(iq, "id", client->connection->mid);
342 
343  iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
344  iks_insert_attrib(jingle, "action", JINGLE_ACCEPT);
345  iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
346  iks_insert_attrib(jingle, JINGLE_SID, tmp->sid);
347  iks_insert_node(iq, jingle);
348  iks_insert_node(jingle, dcodecs);
349  iks_insert_node(dcodecs, payload_red);
350  iks_insert_node(dcodecs, payload_audio);
351  iks_insert_node(dcodecs, payload_cn);
352 
353  ast_aji_send(c, iq);
354 
355  iks_delete(payload_red);
356  iks_delete(payload_audio);
357  iks_delete(payload_cn);
358  iks_delete(dcodecs);
359  iks_delete(jingle);
360  iks_delete(iq);
361  }
362  return 1;
363 }
364 
365 static int jingle_ringing_ack(void *data, ikspak *pak)
366 {
367  struct jingle_pvt *p = data;
368 
369  if (p->ringrule)
370  iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
371  p->ringrule = NULL;
372  if (p->owner)
374  return IKS_FILTER_EAT;
375 }
376 
377 static int jingle_answer(struct ast_channel *ast)
378 {
379  struct jingle_pvt *p = ast->tech_pvt;
380  struct jingle *client = p->parent;
381  int res = 0;
382 
383  ast_debug(1, "Answer!\n");
384  ast_mutex_lock(&p->lock);
385  jingle_accept_call(client, p);
386  ast_mutex_unlock(&p->lock);
387  return res;
388 }
389 
390 static enum ast_rtp_glue_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
391 {
392  struct jingle_pvt *p = chan->tech_pvt;
394 
395  if (!p)
396  return res;
397 
398  ast_mutex_lock(&p->lock);
399  if (p->rtp) {
400  ao2_ref(p->rtp, +1);
401  *instance = p->rtp;
403  }
404  ast_mutex_unlock(&p->lock);
405 
406  return res;
407 }
408 
410 {
411  struct jingle_pvt *p = chan->tech_pvt;
412  return p->peercapability;
413 }
414 
415 static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, format_t codecs, int nat_active)
416 {
417  struct jingle_pvt *p;
418 
419  p = chan->tech_pvt;
420  if (!p)
421  return -1;
422  ast_mutex_lock(&p->lock);
423 
424 /* if (rtp)
425  ast_rtp_get_peer(rtp, &p->redirip);
426  else
427  memset(&p->redirip, 0, sizeof(p->redirip));
428  p->redircodecs = codecs; */
429 
430  /* Reset lastrtprx timer */
431  ast_mutex_unlock(&p->lock);
432  return 0;
433 }
434 
435 static struct ast_rtp_glue jingle_rtp_glue = {
436  .type = "Jingle",
437  .get_rtp_info = jingle_get_rtp_peer,
438  .get_codec = jingle_get_codec,
439  .update_peer = jingle_set_rtp_peer,
440 };
441 
442 static int jingle_response(struct jingle *client, ikspak *pak, const char *reasonstr, const char *reasonstr2)
443 {
444  iks *response = NULL, *error = NULL, *reason = NULL;
445  int res = -1;
446 
447  response = iks_new("iq");
448  if (response) {
449  iks_insert_attrib(response, "type", "result");
450  iks_insert_attrib(response, "from", client->connection->jid->full);
451  iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
452  iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
453  if (reasonstr) {
454  error = iks_new("error");
455  if (error) {
456  iks_insert_attrib(error, "type", "cancel");
457  reason = iks_new(reasonstr);
458  if (reason)
459  iks_insert_node(error, reason);
460  iks_insert_node(response, error);
461  }
462  }
463  ast_aji_send(client->connection, response);
464  res = 0;
465  }
466 
467  iks_delete(reason);
468  iks_delete(error);
469  iks_delete(response);
470 
471  return res;
472 }
473 
474 static int jingle_is_answered(struct jingle *client, ikspak *pak)
475 {
476  struct jingle_pvt *tmp;
477 
478  ast_debug(1, "The client is %s\n", client->name);
479  /* Make sure our new call doesn't exist yet */
480  for (tmp = client->p; tmp; tmp = tmp->next) {
481  if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
482  break;
483  }
484 
485  if (tmp) {
486  if (tmp->owner)
488  } else
489  ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
490  jingle_response(client, pak, NULL, NULL);
491  return 1;
492 }
493 
494 static int jingle_handle_dtmf(struct jingle *client, ikspak *pak)
495 {
496  struct jingle_pvt *tmp;
497  iks *dtmfnode = NULL, *dtmfchild = NULL;
498  char *dtmf;
499  /* Make sure our new call doesn't exist yet */
500  for (tmp = client->p; tmp; tmp = tmp->next) {
501  if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
502  break;
503  }
504 
505  if (tmp) {
506  if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) {
507  jingle_response(client,pak,
508  "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
509  "unsupported-dtmf-method xmlns='http://www.xmpp.org/extensions/xep-0181.html#ns-errors'");
510  return -1;
511  }
512  if ((dtmfnode = iks_find(pak->x, "dtmf"))) {
513  if((dtmf = iks_find_attrib(dtmfnode, "code"))) {
514  if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) {
515  struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
516  f.subclass.integer = dtmf[0];
517  ast_queue_frame(tmp->owner, &f);
518  ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
519  } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) {
520  struct ast_frame f = {AST_FRAME_DTMF_END, };
521  f.subclass.integer = dtmf[0];
522  ast_queue_frame(tmp->owner, &f);
523  ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
524  } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */
525  struct ast_frame f = {AST_FRAME_DTMF, };
526  f.subclass.integer = dtmf[0];
527  ast_queue_frame(tmp->owner, &f);
528  ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
529  }
530  }
531  } else if ((dtmfnode = iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "session-info"))) {
532  if((dtmfchild = iks_find(dtmfnode, "dtmf"))) {
533  if((dtmf = iks_find_attrib(dtmfchild, "code"))) {
534  if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) {
535  struct ast_frame f = {AST_FRAME_DTMF_END, };
536  f.subclass.integer = dtmf[0];
537  ast_queue_frame(tmp->owner, &f);
538  ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
539  } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) {
540  struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
541  f.subclass.integer = dtmf[0];
542  ast_queue_frame(tmp->owner, &f);
543  ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
544  }
545  }
546  }
547  }
548  jingle_response(client, pak, NULL, NULL);
549  return 1;
550  } else
551  ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
552 
553  jingle_response(client, pak, NULL, NULL);
554  return 1;
555 }
556 
557 
558 static int jingle_hangup_farend(struct jingle *client, ikspak *pak)
559 {
560  struct jingle_pvt *tmp;
561 
562  ast_debug(1, "The client is %s\n", client->name);
563  /* Make sure our new call doesn't exist yet */
564  for (tmp = client->p; tmp; tmp = tmp->next) {
565  if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
566  break;
567  }
568 
569  if (tmp) {
570  tmp->alreadygone = 1;
571  if (tmp->owner)
572  ast_queue_hangup(tmp->owner);
573  } else
574  ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
575  jingle_response(client, pak, NULL, NULL);
576  return 1;
577 }
578 
579 static int jingle_create_candidates(struct jingle *client, struct jingle_pvt *p, char *sid, char *from)
580 {
581  struct jingle_candidate *tmp;
582  struct aji_client *c = client->connection;
583  struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
584  struct sockaddr_in sin = { 0, };
585  struct ast_sockaddr sin_tmp;
586  struct ast_sockaddr us_tmp;
587  struct ast_sockaddr bindaddr_tmp;
588  struct in_addr us;
589  struct in_addr externaddr;
590  iks *iq, *jingle, *content, *transport, *candidate;
591  char component[16], foundation[16], generation[16], network[16], pass[16], port[7], priority[16], user[16];
592 
593 
594  iq = iks_new("iq");
595  jingle = iks_new(JINGLE_NODE);
596  content = iks_new("content");
597  transport = iks_new("transport");
598  candidate = iks_new("candidate");
599  if (!iq || !jingle || !content || !transport || !candidate) {
600  ast_log(LOG_ERROR, "Memory allocation error\n");
601  goto safeout;
602  }
603  ours1 = ast_calloc(1, sizeof(*ours1));
604  ours2 = ast_calloc(1, sizeof(*ours2));
605  if (!ours1 || !ours2)
606  goto safeout;
607 
608  iks_insert_node(iq, jingle);
609  iks_insert_node(jingle, content);
610  iks_insert_node(content, transport);
611  iks_insert_node(transport, candidate);
612 
613  for (; p; p = p->next) {
614  if (!strcasecmp(p->sid, sid))
615  break;
616  }
617 
618  if (!p) {
619  ast_log(LOG_NOTICE, "No matching jingle session - SID %s!\n", sid);
620  goto safeout;
621  }
622 
624  ast_sockaddr_to_sin(&sin_tmp, &sin);
625  ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
626  ast_find_ourip(&us_tmp, &bindaddr_tmp, AF_INET);
627  us.s_addr = htonl(ast_sockaddr_ipv4(&us_tmp));
628 
629  /* Setup our first jingle candidate */
630  ours1->component = 1;
631  ours1->foundation = (unsigned int)bindaddr.sin_addr.s_addr | AJI_CONNECT_HOST | AJI_PROTOCOL_UDP;
632  ours1->generation = 0;
633  ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip));
634  ours1->network = 0;
635  ours1->port = ntohs(sin.sin_port);
636  ours1->priority = 1678246398;
637  ours1->protocol = AJI_PROTOCOL_UDP;
638  snprintf(pass, sizeof(pass), "%08lx%08lx", (unsigned long)ast_random(), (unsigned long)ast_random());
639  ast_copy_string(ours1->password, pass, sizeof(ours1->password));
640  ours1->type = AJI_CONNECT_HOST;
641  snprintf(user, sizeof(user), "%08lx%08lx", (unsigned long)ast_random(), (unsigned long)ast_random());
642  ast_copy_string(ours1->ufrag, user, sizeof(ours1->ufrag));
643  p->ourcandidates = ours1;
644 
645  if (!ast_strlen_zero(externip)) {
646  /* XXX We should really stun for this one not just go with externip XXX */
647  if (inet_aton(externip, &externaddr))
648  ast_log(LOG_WARNING, "Invalid extern IP : %s\n", externip);
649 
650  ours2->component = 1;
651  ours2->foundation = (unsigned int)externaddr.s_addr | AJI_CONNECT_PRFLX | AJI_PROTOCOL_UDP;
652  ours2->generation = 0;
653  ast_copy_string(ours2->ip, externip, sizeof(ours2->ip));
654  ours2->network = 0;
655  ours2->port = ntohs(sin.sin_port);
656  ours2->priority = 1678246397;
657  ours2->protocol = AJI_PROTOCOL_UDP;
658  snprintf(pass, sizeof(pass), "%08lx%08lx", (unsigned long)ast_random(), (unsigned long)ast_random());
659  ast_copy_string(ours2->password, pass, sizeof(ours2->password));
660  ours2->type = AJI_CONNECT_PRFLX;
661 
662  snprintf(user, sizeof(user), "%08lx%08lx", (unsigned long)ast_random(), (unsigned long)ast_random());
663  ast_copy_string(ours2->ufrag, user, sizeof(ours2->ufrag));
664  ours1->next = ours2;
665  ours2 = NULL;
666  }
667  ours1 = NULL;
668 
669  for (tmp = p->ourcandidates; tmp; tmp = tmp->next) {
670  snprintf(component, sizeof(component), "%u", tmp->component);
671  snprintf(foundation, sizeof(foundation), "%u", tmp->foundation);
672  snprintf(generation, sizeof(generation), "%u", tmp->generation);
673  snprintf(network, sizeof(network), "%u", tmp->network);
674  snprintf(port, sizeof(port), "%u", tmp->port);
675  snprintf(priority, sizeof(priority), "%u", tmp->priority);
676 
677  iks_insert_attrib(iq, "from", c->jid->full);
678  iks_insert_attrib(iq, "to", from);
679  iks_insert_attrib(iq, "type", "set");
680  iks_insert_attrib(iq, "id", c->mid);
682  iks_insert_attrib(jingle, "action", JINGLE_NEGOTIATE);
683  iks_insert_attrib(jingle, JINGLE_SID, sid);
684  iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from);
685  iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
686  iks_insert_attrib(content, "creator", p->initiator ? "initiator" : "responder");
687  iks_insert_attrib(content, "name", "asterisk-audio-content");
688  iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
689  iks_insert_attrib(candidate, "component", component);
690  iks_insert_attrib(candidate, "foundation", foundation);
691  iks_insert_attrib(candidate, "generation", generation);
692  iks_insert_attrib(candidate, "ip", tmp->ip);
693  iks_insert_attrib(candidate, "network", network);
694  iks_insert_attrib(candidate, "port", port);
695  iks_insert_attrib(candidate, "priority", priority);
696  switch (tmp->protocol) {
697  case AJI_PROTOCOL_UDP:
698  iks_insert_attrib(candidate, "protocol", "udp");
699  break;
700  case AJI_PROTOCOL_SSLTCP:
701  iks_insert_attrib(candidate, "protocol", "ssltcp");
702  break;
703  }
704  iks_insert_attrib(candidate, "pwd", tmp->password);
705  switch (tmp->type) {
706  case AJI_CONNECT_HOST:
707  iks_insert_attrib(candidate, "type", "host");
708  break;
709  case AJI_CONNECT_PRFLX:
710  iks_insert_attrib(candidate, "type", "prflx");
711  break;
712  case AJI_CONNECT_RELAY:
713  iks_insert_attrib(candidate, "type", "relay");
714  break;
715  case AJI_CONNECT_SRFLX:
716  iks_insert_attrib(candidate, "type", "srflx");
717  break;
718  }
719  iks_insert_attrib(candidate, "ufrag", tmp->ufrag);
720 
721  ast_aji_send(c, iq);
722  }
723  p->laststun = 0;
724 
725 safeout:
726  if (ours1)
727  ast_free(ours1);
728  if (ours2)
729  ast_free(ours2);
730  iks_delete(iq);
731  iks_delete(jingle);
732  iks_delete(content);
733  iks_delete(transport);
734  iks_delete(candidate);
735 
736  return 1;
737 }
738 
739 static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid)
740 {
741  struct jingle_pvt *tmp = NULL;
742  struct aji_resource *resources = NULL;
743  struct aji_buddy *buddy = NULL;
744  char idroster[200];
745  struct ast_sockaddr bindaddr_tmp;
746 
747  ast_debug(1, "The client is %s for alloc\n", client->name);
748  if (!sid && !strchr(from, '/')) { /* I started call! */
749  if (!strcasecmp(client->name, "guest")) {
750  buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from);
751  if (buddy) {
752  resources = buddy->resources;
753  }
754  } else if (client->buddy)
755  resources = client->buddy->resources;
756  while (resources) {
757  if (resources->cap->jingle) {
758  break;
759  }
760  resources = resources->next;
761  }
762  if (resources)
763  snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource);
764  else {
765  ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n");
766  if (buddy) {
768  }
769  return NULL;
770  }
771  if (buddy) {
773  }
774  }
775  if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
776  return NULL;
777  }
778 
779  memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs));
780 
781  if (sid) {
782  ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
783  ast_copy_string(tmp->them, from, sizeof(tmp->them));
784  } else {
785  snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", (unsigned long)ast_random(), (unsigned long)ast_random());
786  ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
787  tmp->initiator = 1;
788  }
789  ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
790  tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
791  tmp->parent = client;
792  if (!tmp->rtp) {
793  ast_log(LOG_WARNING, "Out of RTP sessions?\n");
794  ast_free(tmp);
795  return NULL;
796  }
797  ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
798  ast_mutex_init(&tmp->lock);
800  tmp->next = client->p;
801  client->p = tmp;
803  return tmp;
804 }
805 
806 /*! \brief Start new jingle channel */
807 static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *i, int state, const char *title, const char *linkedid)
808 {
809  struct ast_channel *tmp;
810  int fmt;
811  int what;
812  const char *str;
813 
814  if (title)
815  str = title;
816  else
817  str = i->them;
818  tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", linkedid, 0, "Jingle/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff));
819  if (!tmp) {
820  ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
821  return NULL;
822  }
823  tmp->tech = &jingle_tech;
824 
825  /* Select our native format based on codec preference until we receive
826  something from another device to the contrary. */
827  if (i->jointcapability)
828  what = i->jointcapability;
829  else if (i->capability)
830  what = i->capability;
831  else
832  what = global_capability;
833 
834  /* Set Frame packetization */
835  if (i->rtp)
837 
839  fmt = ast_best_codec(tmp->nativeformats);
840 
841  if (i->rtp) {
844  }
845  if (i->vrtp) {
848  }
849  if (state == AST_STATE_RING)
850  tmp->rings = 1;
852  tmp->writeformat = fmt;
853  tmp->rawwriteformat = fmt;
854  tmp->readformat = fmt;
855  tmp->rawreadformat = fmt;
856  tmp->tech_pvt = i;
857 
858  tmp->callgroup = client->callgroup;
859  tmp->pickupgroup = client->pickupgroup;
860  tmp->caller.id.name.presentation = client->callingpres;
861  tmp->caller.id.number.presentation = client->callingpres;
862  if (!ast_strlen_zero(client->accountcode))
864  if (client->amaflags)
865  tmp->amaflags = client->amaflags;
866  if (!ast_strlen_zero(client->language))
867  ast_string_field_set(tmp, language, client->language);
868  if (!ast_strlen_zero(client->musicclass))
870  i->owner = tmp;
871  ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
872  ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
873  /* Don't use ast_set_callerid() here because it will
874  * generate an unnecessary NewCallerID event */
875  if (!ast_strlen_zero(i->cid_num)) {
876  tmp->caller.ani.number.valid = 1;
877  tmp->caller.ani.number.str = ast_strdup(i->cid_num);
878  }
879  if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) {
880  tmp->dialed.number.str = ast_strdup(i->exten);
881  }
882  tmp->priority = 1;
883  if (i->rtp)
885  if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
886  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
888  ast_hangup(tmp);
889  tmp = NULL;
890  }
891 
892  return tmp;
893 }
894 
895 static int jingle_action(struct jingle *client, struct jingle_pvt *p, const char *action)
896 {
897  iks *iq, *jingle = NULL;
898  int res = -1;
899 
900  iq = iks_new("iq");
901  jingle = iks_new("jingle");
902 
903  if (iq) {
904  iks_insert_attrib(iq, "type", "set");
905  iks_insert_attrib(iq, "from", client->connection->jid->full);
906  iks_insert_attrib(iq, "to", p->them);
907  iks_insert_attrib(iq, "id", client->connection->mid);
909  if (jingle) {
910  iks_insert_attrib(jingle, "action", action);
911  iks_insert_attrib(jingle, JINGLE_SID, p->sid);
912  iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
913  iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
914 
915  iks_insert_node(iq, jingle);
916 
917  ast_aji_send(client->connection, iq);
918  res = 0;
919  }
920  }
921 
922  iks_delete(jingle);
923  iks_delete(iq);
924 
925  return res;
926 }
927 
928 static void jingle_free_candidates(struct jingle_candidate *candidate)
929 {
930  struct jingle_candidate *last;
931  while (candidate) {
932  last = candidate;
933  candidate = candidate->next;
934  ast_free(last);
935  }
936 }
937 
938 static void jingle_free_pvt(struct jingle *client, struct jingle_pvt *p)
939 {
940  struct jingle_pvt *cur, *prev = NULL;
941  cur = client->p;
942  while (cur) {
943  if (cur == p) {
944  if (prev)
945  prev->next = p->next;
946  else
947  client->p = p->next;
948  break;
949  }
950  prev = cur;
951  cur = cur->next;
952  }
953  if (p->ringrule)
954  iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
955  if (p->owner)
956  ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
957  if (p->rtp)
959  if (p->vrtp)
962  ast_free(p);
963 }
964 
965 
966 static int jingle_newcall(struct jingle *client, ikspak *pak)
967 {
968  struct jingle_pvt *p, *tmp = client->p;
969  struct ast_channel *chan;
970  int res;
971  iks *codec, *content, *description;
972  char *from = NULL;
973 
974  /* Make sure our new call doesn't exist yet */
975  from = iks_find_attrib(pak->x,"to");
976  if(!from)
977  from = client->connection->jid->full;
978 
979  while (tmp) {
980  if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
981  ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
982  jingle_response(client, pak, "out-of-order", NULL);
983  return -1;
984  }
985  tmp = tmp->next;
986  }
987 
988  if (!strcasecmp(client->name, "guest")){
989  /* the guest account is not tied to any configured XMPP client,
990  let's set it now */
991  if (client->connection) {
993  }
994  client->connection = ast_aji_get_client(from);
995  if (!client->connection) {
996  ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from);
997  return -1;
998  }
999  }
1000 
1001  p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID));
1002  if (!p) {
1003  ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n");
1004  return -1;
1005  }
1006  chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user, NULL);
1007  if (!chan) {
1008  jingle_free_pvt(client, p);
1009  return -1;
1010  }
1011  ast_mutex_lock(&p->lock);
1012  ast_copy_string(p->them, pak->from->full, sizeof(p->them));
1013  if (iks_find_attrib(pak->query, JINGLE_SID)) {
1014  ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID),
1015  sizeof(p->sid));
1016  }
1017 
1018  /* content points to the first <content/> tag */
1019  content = iks_child(iks_child(pak->x));
1020  while (content) {
1021  description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS);
1022  if (description) {
1023  /* audio content found */
1024  codec = iks_child(iks_child(content));
1025  ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name));
1026 
1027  while (codec) {
1028  ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
1029  ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
1030  codec = iks_next(codec);
1031  }
1032  }
1033 
1034  description = NULL;
1035  codec = NULL;
1036 
1037  description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS);
1038  if (description) {
1039  /* video content found */
1040  codec = iks_child(iks_child(content));
1041  ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name));
1042 
1043  while (codec) {
1044  ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
1045  ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
1046  codec = iks_next(codec);
1047  }
1048  }
1049 
1050  content = iks_next(content);
1051  }
1052 
1053  ast_mutex_unlock(&p->lock);
1055  res = ast_pbx_start(chan);
1056 
1057  switch (res) {
1058  case AST_PBX_FAILED:
1059  ast_log(LOG_WARNING, "Failed to start PBX :(\n");
1060  jingle_response(client, pak, "service-unavailable", NULL);
1061  break;
1062  case AST_PBX_CALL_LIMIT:
1063  ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
1064  jingle_response(client, pak, "service-unavailable", NULL);
1065  break;
1066  case AST_PBX_SUCCESS:
1067  jingle_response(client, pak, NULL, NULL);
1068  jingle_create_candidates(client, p,
1069  iks_find_attrib(pak->query, JINGLE_SID),
1070  iks_find_attrib(pak->x, "from"));
1071  /* nothing to do */
1072  break;
1073  }
1074 
1075  return 1;
1076 }
1077 
1078 static int jingle_update_stun(struct jingle *client, struct jingle_pvt *p)
1079 {
1080  struct jingle_candidate *tmp;
1081  struct hostent *hp;
1082  struct ast_hostent ahp;
1083  struct sockaddr_in sin;
1084  struct ast_sockaddr sin_tmp;
1085 
1086  if (time(NULL) == p->laststun)
1087  return 0;
1088 
1089  tmp = p->theircandidates;
1090  p->laststun = time(NULL);
1091  while (tmp) {
1092  char username[256];
1093  hp = ast_gethostbyname(tmp->ip, &ahp);
1094  sin.sin_family = AF_INET;
1095  memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
1096  sin.sin_port = htons(tmp->port);
1097  snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
1098 
1099  ast_sockaddr_from_sin(&sin_tmp, &sin);
1100  ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username);
1101  tmp = tmp->next;
1102  }
1103  return 1;
1104 }
1105 
1106 static int jingle_add_candidate(struct jingle *client, ikspak *pak)
1107 {
1108  struct jingle_pvt *p = NULL, *tmp = NULL;
1109  struct aji_client *c = client->connection;
1110  struct jingle_candidate *newcandidate = NULL;
1111  iks *traversenodes = NULL, *receipt = NULL;
1112 
1113  for (tmp = client->p; tmp; tmp = tmp->next) {
1114  if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
1115  p = tmp;
1116  break;
1117  }
1118  }
1119 
1120  if (!p)
1121  return -1;
1122 
1123  traversenodes = pak->query;
1124  while(traversenodes) {
1125  if(!strcasecmp(iks_name(traversenodes), "jingle")) {
1126  traversenodes = iks_child(traversenodes);
1127  continue;
1128  }
1129  if(!strcasecmp(iks_name(traversenodes), "content")) {
1130  traversenodes = iks_child(traversenodes);
1131  continue;
1132  }
1133  if(!strcasecmp(iks_name(traversenodes), "transport")) {
1134  traversenodes = iks_child(traversenodes);
1135  continue;
1136  }
1137 
1138  if(!strcasecmp(iks_name(traversenodes), "candidate")) {
1139  newcandidate = ast_calloc(1, sizeof(*newcandidate));
1140  if (!newcandidate)
1141  return 0;
1142  ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip));
1143  newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
1144  ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password));
1145  if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
1146  newcandidate->protocol = AJI_PROTOCOL_UDP;
1147  else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
1148  newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
1149 
1150  if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "host"))
1151  newcandidate->type = AJI_CONNECT_HOST;
1152  else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "prflx"))
1153  newcandidate->type = AJI_CONNECT_PRFLX;
1154  else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
1155  newcandidate->type = AJI_CONNECT_RELAY;
1156  else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "srflx"))
1157  newcandidate->type = AJI_CONNECT_SRFLX;
1158 
1159  newcandidate->network = atoi(iks_find_attrib(traversenodes, "network"));
1160  newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
1161  newcandidate->next = NULL;
1162 
1163  newcandidate->next = p->theircandidates;
1164  p->theircandidates = newcandidate;
1165  p->laststun = 0;
1166  jingle_update_stun(p->parent, p);
1167  newcandidate = NULL;
1168  }
1169  traversenodes = iks_next(traversenodes);
1170  }
1171 
1172  receipt = iks_new("iq");
1173  iks_insert_attrib(receipt, "type", "result");
1174  iks_insert_attrib(receipt, "from", c->jid->full);
1175  iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
1176  iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
1177  ast_aji_send(c, receipt);
1178 
1179  iks_delete(receipt);
1180 
1181  return 1;
1182 }
1183 
1184 static struct ast_frame *jingle_rtp_read(struct ast_channel *ast, struct jingle_pvt *p)
1185 {
1186  struct ast_frame *f;
1187 
1188  if (!p->rtp)
1189  return &ast_null_frame;
1190  f = ast_rtp_instance_read(p->rtp, 0);
1191  jingle_update_stun(p->parent, p);
1192  if (p->owner) {
1193  /* We already hold the channel lock */
1194  if (f->frametype == AST_FRAME_VOICE) {
1196  ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec));
1197  p->owner->nativeformats =
1201  }
1202 /* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
1203  f = ast_dsp_process(p->owner, p->vad, f);
1204  if (f && (f->frametype == AST_FRAME_DTMF))
1205  ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.codec);
1206  } */
1207  }
1208  }
1209  return f;
1210 }
1211 
1212 static struct ast_frame *jingle_read(struct ast_channel *ast)
1213 {
1214  struct ast_frame *fr;
1215  struct jingle_pvt *p = ast->tech_pvt;
1216 
1217  ast_mutex_lock(&p->lock);
1218  fr = jingle_rtp_read(ast, p);
1219  ast_mutex_unlock(&p->lock);
1220  return fr;
1221 }
1222 
1223 /*! \brief Send frame to media channel (rtp) */
1224 static int jingle_write(struct ast_channel *ast, struct ast_frame *frame)
1225 {
1226  struct jingle_pvt *p = ast->tech_pvt;
1227  int res = 0;
1228  char buf[256];
1229 
1230  switch (frame->frametype) {
1231  case AST_FRAME_VOICE:
1232  if (!(frame->subclass.codec & ast->nativeformats)) {
1234  "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
1236  ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
1239  return 0;
1240  }
1241  if (p) {
1242  ast_mutex_lock(&p->lock);
1243  if (p->rtp) {
1244  res = ast_rtp_instance_write(p->rtp, frame);
1245  }
1246  ast_mutex_unlock(&p->lock);
1247  }
1248  break;
1249  case AST_FRAME_VIDEO:
1250  if (p) {
1251  ast_mutex_lock(&p->lock);
1252  if (p->vrtp) {
1253  res = ast_rtp_instance_write(p->vrtp, frame);
1254  }
1255  ast_mutex_unlock(&p->lock);
1256  }
1257  break;
1258  case AST_FRAME_IMAGE:
1259  return 0;
1260  break;
1261  default:
1262  ast_log(LOG_WARNING, "Can't send %u type frames with Jingle write\n",
1263  frame->frametype);
1264  return 0;
1265  }
1266 
1267  return res;
1268 }
1269 
1270 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1271 {
1272  struct jingle_pvt *p = newchan->tech_pvt;
1273  ast_mutex_lock(&p->lock);
1274 
1275  if ((p->owner != oldchan)) {
1276  ast_mutex_unlock(&p->lock);
1277  return -1;
1278  }
1279  if (p->owner == oldchan)
1280  p->owner = newchan;
1281  ast_mutex_unlock(&p->lock);
1282  return 0;
1283 }
1284 
1285 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
1286 {
1287  int res = 0;
1288 
1289  switch (condition) {
1290  case AST_CONTROL_HOLD:
1291  ast_moh_start(ast, data, NULL);
1292  break;
1293  case AST_CONTROL_UNHOLD:
1294  ast_moh_stop(ast);
1295  break;
1296  default:
1297  ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
1298  res = -1;
1299  }
1300 
1301  return res;
1302 }
1303 
1304 static int jingle_sendtext(struct ast_channel *chan, const char *text)
1305 {
1306  int res = 0;
1307  struct aji_client *client = NULL;
1308  struct jingle_pvt *p = chan->tech_pvt;
1309 
1310 
1311  if (!p->parent) {
1312  ast_log(LOG_ERROR, "Parent channel not found\n");
1313  return -1;
1314  }
1315  if (!p->parent->connection) {
1316  ast_log(LOG_ERROR, "XMPP client not found\n");
1317  return -1;
1318  }
1319  client = p->parent->connection;
1320  res = ast_aji_send_chat(client, p->them, text);
1321  return res;
1322 }
1323 
1324 static int jingle_digit(struct ast_channel *ast, char digit, unsigned int duration)
1325 {
1326  struct jingle_pvt *p = ast->tech_pvt;
1327  struct jingle *client = p->parent;
1328  iks *iq, *jingle, *dtmf;
1329  char buffer[2] = {digit, '\0'};
1330  iq = iks_new("iq");
1331  jingle = iks_new("jingle");
1332  dtmf = iks_new("dtmf");
1333  if(!iq || !jingle || !dtmf) {
1334  iks_delete(iq);
1335  iks_delete(jingle);
1336  iks_delete(dtmf);
1337  ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
1338  return -1;
1339  }
1340 
1341  iks_insert_attrib(iq, "type", "set");
1342  iks_insert_attrib(iq, "to", p->them);
1343  iks_insert_attrib(iq, "from", client->connection->jid->full);
1344  iks_insert_attrib(iq, "id", client->connection->mid);
1346  iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1347  iks_insert_attrib(jingle, "action", "session-info");
1348  iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
1349  iks_insert_attrib(jingle, "sid", p->sid);
1350  iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS);
1351  iks_insert_attrib(dtmf, "code", buffer);
1352  iks_insert_node(iq, jingle);
1353  iks_insert_node(jingle, dtmf);
1354 
1355  ast_mutex_lock(&p->lock);
1356  if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
1357  iks_insert_attrib(dtmf, "action", "button-down");
1358  } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
1359  iks_insert_attrib(dtmf, "action", "button-up");
1360  }
1361  ast_aji_send(client->connection, iq);
1362 
1363  iks_delete(iq);
1364  iks_delete(jingle);
1365  iks_delete(dtmf);
1366  ast_mutex_unlock(&p->lock);
1367  return 0;
1368 }
1369 
1370 static int jingle_digit_begin(struct ast_channel *chan, char digit)
1371 {
1372  return jingle_digit(chan, digit, 0);
1373 }
1374 
1375 static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
1376 {
1377  return jingle_digit(ast, digit, duration);
1378 }
1379 
1380 static int jingle_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
1381 {
1382  ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
1383 
1384  return -1;
1385 }
1387 {
1388  struct jingle *aux = NULL;
1389  struct aji_client *client = NULL;
1390  iks *iq, *jingle, *content, *description, *transport;
1391  iks *payload_eg711u, *payload_pcmu;
1392 
1393  aux = p->parent;
1394  client = aux->connection;
1395  iq = iks_new("iq");
1396  jingle = iks_new(JINGLE_NODE);
1397  content = iks_new("content");
1398  description = iks_new("description");
1399  transport = iks_new("transport");
1400  payload_pcmu = iks_new("payload-type");
1401  payload_eg711u = iks_new("payload-type");
1402 
1403  ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name));
1404 
1405  iks_insert_attrib(iq, "type", "set");
1406  iks_insert_attrib(iq, "to", p->them);
1407  iks_insert_attrib(iq, "from", client->jid->full);
1408  iks_insert_attrib(iq, "id", client->mid);
1409  ast_aji_increment_mid(client->mid);
1410  iks_insert_attrib(jingle, "action", JINGLE_INITIATE);
1411  iks_insert_attrib(jingle, JINGLE_SID, p->sid);
1412  iks_insert_attrib(jingle, "initiator", client->jid->full);
1413  iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1414 
1415  /* For now, we only send one audio based content */
1416  iks_insert_attrib(content, "creator", "initiator");
1417  iks_insert_attrib(content, "name", p->audio_content_name);
1418  iks_insert_attrib(content, "profile", "RTP/AVP");
1419  iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS);
1420  iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
1421  iks_insert_attrib(payload_pcmu, "id", "0");
1422  iks_insert_attrib(payload_pcmu, "name", "PCMU");
1423  iks_insert_attrib(payload_eg711u, "id", "100");
1424  iks_insert_attrib(payload_eg711u, "name", "EG711U");
1425  iks_insert_node(description, payload_pcmu);
1426  iks_insert_node(description, payload_eg711u);
1427  iks_insert_node(content, description);
1428  iks_insert_node(content, transport);
1429  iks_insert_node(jingle, content);
1430  iks_insert_node(iq, jingle);
1431 
1432  ast_aji_send(client, iq);
1433 
1434  iks_delete(iq);
1435  iks_delete(jingle);
1436  iks_delete(content);
1437  iks_delete(description);
1438  iks_delete(transport);
1439  iks_delete(payload_eg711u);
1440  iks_delete(payload_pcmu);
1441  return 0;
1442 }
1443 
1444 /* Not in use right now.
1445 static int jingle_auto_congest(void *nothing)
1446 {
1447  struct jingle_pvt *p = nothing;
1448 
1449  ast_mutex_lock(&p->lock);
1450  if (p->owner) {
1451  if (!ast_channel_trylock(p->owner)) {
1452  ast_log(LOG_NOTICE, "Auto-congesting %s\n", p->owner->name);
1453  ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
1454  ast_channel_unlock(p->owner);
1455  }
1456  }
1457  ast_mutex_unlock(&p->lock);
1458  return 0;
1459 }
1460 */
1461 
1462 /*! \brief Initiate new call, part of PBX interface
1463  * dest is the dial string */
1464 static int jingle_call(struct ast_channel *ast, char *dest, int timeout)
1465 {
1466  struct jingle_pvt *p = ast->tech_pvt;
1467 
1468  if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1469  ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name);
1470  return -1;
1471  }
1472 
1474  p->jointcapability = p->capability;
1475  if (!p->ringrule) {
1476  ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
1477  p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p,
1478  IKS_RULE_ID, p->ring, IKS_RULE_DONE);
1479  } else
1480  ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
1481 
1483  jingle_create_candidates(p->parent, p, p->sid, p->them);
1484 
1485  return 0;
1486 }
1487 
1488 /*! \brief Hangup a call through the jingle proxy channel */
1489 static int jingle_hangup(struct ast_channel *ast)
1490 {
1491  struct jingle_pvt *p = ast->tech_pvt;
1492  struct jingle *client;
1493 
1494  ast_mutex_lock(&p->lock);
1495  client = p->parent;
1496  p->owner = NULL;
1497  ast->tech_pvt = NULL;
1498  if (!p->alreadygone)
1499  jingle_action(client, p, JINGLE_TERMINATE);
1500  ast_mutex_unlock(&p->lock);
1501 
1502  jingle_free_pvt(client, p);
1503 
1504  return 0;
1505 }
1506 
1507 /*! \brief Part of PBX interface */
1508 static struct ast_channel *jingle_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
1509 {
1510  struct jingle_pvt *p = NULL;
1511  struct jingle *client = NULL;
1512  char *sender = NULL, *to = NULL, *s = NULL;
1513  struct ast_channel *chan = NULL;
1514 
1515  if (data) {
1516  s = ast_strdupa(data);
1517  sender = strsep(&s, "/");
1518  if (sender && (sender[0] != '\0')) {
1519  to = strsep(&s, "/");
1520  }
1521  if (!to) {
1522  ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", (char*) data);
1523  return NULL;
1524  }
1525  }
1526 
1527  client = find_jingle(to, sender);
1528  if (!client) {
1529  ast_log(LOG_WARNING, "Could not find recipient.\n");
1530  return NULL;
1531  }
1532  if (!strcasecmp(client->name, "guest")){
1533  /* the guest account is not tied to any configured XMPP client,
1534  let's set it now */
1535  if (client->connection) {
1537  }
1538  client->connection = ast_aji_get_client(sender);
1539  if (!client->connection) {
1540  ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
1541  return NULL;
1542  }
1543  }
1544 
1545  ASTOBJ_WRLOCK(client);
1546  p = jingle_alloc(client, to, NULL);
1547  if (p)
1548  chan = jingle_new(client, p, AST_STATE_DOWN, to, requestor ? requestor->linkedid : NULL);
1549  ASTOBJ_UNLOCK(client);
1550 
1551  return chan;
1552 }
1553 
1554 /*! \brief CLI command "jingle show channels" */
1555 static char *jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1556 {
1557 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n"
1558  struct jingle_pvt *p;
1559  struct ast_channel *chan;
1560  int numchans = 0;
1561  char them[AJI_MAX_JIDLEN];
1562  char *jid = NULL;
1563  char *resource = NULL;
1564 
1565  switch (cmd) {
1566  case CLI_INIT:
1567  e->command = "jingle show channels";
1568  e->usage =
1569  "Usage: jingle show channels\n"
1570  " Shows current state of the Jingle channels.\n";
1571  return NULL;
1572  case CLI_GENERATE:
1573  return NULL;
1574  }
1575 
1576  if (a->argc != 3)
1577  return CLI_SHOWUSAGE;
1578 
1580  ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
1582  ASTOBJ_WRLOCK(iterator);
1583  p = iterator->p;
1584  while(p) {
1585  chan = p->owner;
1586  ast_copy_string(them, p->them, sizeof(them));
1587  jid = them;
1588  resource = strchr(them, '/');
1589  if (!resource)
1590  resource = "None";
1591  else {
1592  *resource = '\0';
1593  resource ++;
1594  }
1595  if (chan)
1596  ast_cli(a->fd, FORMAT,
1597  chan->name,
1598  jid,
1599  resource,
1602  );
1603  else
1604  ast_log(LOG_WARNING, "No available channel\n");
1605  numchans ++;
1606  p = p->next;
1607  }
1608  ASTOBJ_UNLOCK(iterator);
1609  });
1610 
1612 
1613  ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : "");
1614  return CLI_SUCCESS;
1615 #undef FORMAT
1616 }
1617 
1618 /*! \brief CLI command "jingle reload" */
1619 static char *jingle_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1620 {
1621  switch (cmd) {
1622  case CLI_INIT:
1623  e->command = "jingle reload";
1624  e->usage =
1625  "Usage: jingle reload\n"
1626  " Reload jingle channel driver.\n";
1627  return NULL;
1628  case CLI_GENERATE:
1629  return NULL;
1630  }
1631 
1632  return CLI_SUCCESS;
1633 }
1634 
1635 static int jingle_parser(void *data, ikspak *pak)
1636 {
1637  struct jingle *client = ASTOBJ_REF((struct jingle *) data);
1638  ast_log(LOG_NOTICE, "Filter matched\n");
1639 
1640  if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) {
1641  /* New call */
1642  jingle_newcall(client, pak);
1643  } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) {
1644  ast_debug(3, "About to add candidate!\n");
1645  jingle_add_candidate(client, pak);
1646  ast_debug(3, "Candidate Added!\n");
1647  } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) {
1648  jingle_is_answered(client, pak);
1649  } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) {
1650  jingle_handle_dtmf(client, pak);
1651  } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) {
1652  jingle_hangup_farend(client, pak);
1653  } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) {
1654  jingle_hangup_farend(client, pak);
1655  }
1657  return IKS_FILTER_EAT;
1658 }
1659 /* Not using this anymore probably take out soon
1660 static struct jingle_candidate *jingle_create_candidate(char *args)
1661 {
1662  char *name, *type, *preference, *protocol;
1663  struct jingle_candidate *res;
1664  res = ast_calloc(1, sizeof(*res));
1665  if (args)
1666  name = args;
1667  if ((args = strchr(args, ','))) {
1668  *args = '\0';
1669  args++;
1670  preference = args;
1671  }
1672  if ((args = strchr(args, ','))) {
1673  *args = '\0';
1674  args++;
1675  protocol = args;
1676  }
1677  if ((args = strchr(args, ','))) {
1678  *args = '\0';
1679  args++;
1680  type = args;
1681  }
1682  if (name)
1683  ast_copy_string(res->name, name, sizeof(res->name));
1684  if (preference) {
1685  res->preference = atof(preference);
1686  }
1687  if (protocol) {
1688  if (!strcasecmp("udp", protocol))
1689  res->protocol = AJI_PROTOCOL_UDP;
1690  if (!strcasecmp("ssltcp", protocol))
1691  res->protocol = AJI_PROTOCOL_SSLTCP;
1692  }
1693  if (type) {
1694  if (!strcasecmp("host", type))
1695  res->type = AJI_CONNECT_HOST;
1696  if (!strcasecmp("prflx", type))
1697  res->type = AJI_CONNECT_PRFLX;
1698  if (!strcasecmp("relay", type))
1699  res->type = AJI_CONNECT_RELAY;
1700  if (!strcasecmp("srflx", type))
1701  res->type = AJI_CONNECT_SRFLX;
1702  }
1703 
1704  return res;
1705 }
1706 */
1707 
1708 static int jingle_create_member(char *label, struct ast_variable *var, int allowguest,
1709  struct ast_codec_pref prefs, char *context,
1710  struct jingle *member)
1711 {
1712  struct aji_client *client;
1713 
1714  if (!member)
1715  ast_log(LOG_WARNING, "Out of memory.\n");
1716 
1717  ast_copy_string(member->name, label, sizeof(member->name));
1718  ast_copy_string(member->user, label, sizeof(member->user));
1719  ast_copy_string(member->context, context, sizeof(member->context));
1720  member->allowguest = allowguest;
1721  member->prefs = prefs;
1722  while (var) {
1723 #if 0
1724  struct jingle_candidate *candidate = NULL;
1725 #endif
1726  if (!strcasecmp(var->name, "username"))
1727  ast_copy_string(member->user, var->value, sizeof(member->user));
1728  else if (!strcasecmp(var->name, "disallow"))
1729  ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0);
1730  else if (!strcasecmp(var->name, "allow"))
1731  ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
1732  else if (!strcasecmp(var->name, "context"))
1733  ast_copy_string(member->context, var->value, sizeof(member->context));
1734 #if 0
1735  else if (!strcasecmp(var->name, "candidate")) {
1736  candidate = jingle_create_candidate(var->value);
1737  if (candidate) {
1738  candidate->next = member->ourcandidates;
1739  member->ourcandidates = candidate;
1740  }
1741  }
1742 #endif
1743  else if (!strcasecmp(var->name, "connection")) {
1744  if ((client = ast_aji_get_client(var->value))) {
1745  member->connection = client;
1746  iks_filter_add_rule(client->f, jingle_parser, member,
1747  IKS_RULE_TYPE, IKS_PAK_IQ,
1748  IKS_RULE_FROM_PARTIAL, member->user,
1749  IKS_RULE_NS, JINGLE_NS,
1750  IKS_RULE_DONE);
1751  } else {
1752  ast_log(LOG_ERROR, "connection referenced not found!\n");
1753  return 0;
1754  }
1755  }
1756  var = var->next;
1757  }
1758  if (member->connection && member->user)
1759  member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
1760  else {
1761  ast_log(LOG_ERROR, "No Connection or Username!\n");
1762  }
1763  return 1;
1764 }
1765 
1766 static int jingle_load_config(void)
1767 {
1768  char *cat = NULL;
1769  struct ast_config *cfg = NULL;
1770  char context[100];
1771  int allowguest = 1;
1772  struct ast_variable *var;
1773  struct jingle *member;
1774  struct hostent *hp;
1775  struct ast_hostent ahp;
1776  struct ast_codec_pref prefs;
1777  struct aji_client_container *clients;
1778  struct jingle_candidate *global_candidates = NULL;
1779  struct ast_flags config_flags = { 0 };
1780 
1781  cfg = ast_config_load(JINGLE_CONFIG, config_flags);
1782  if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
1783  return 0;
1784  }
1785 
1786  /* Copy the default jb config over global_jbconf */
1787  memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
1788 
1789  cat = ast_category_browse(cfg, NULL);
1790  for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
1791  /* handle jb conf */
1792  if (!ast_jb_read_conf(&global_jbconf, var->name, var->value))
1793  continue;
1794 
1795  if (!strcasecmp(var->name, "allowguest"))
1796  allowguest =
1797  (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0;
1798  else if (!strcasecmp(var->name, "disallow"))
1799  ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0);
1800  else if (!strcasecmp(var->name, "allow"))
1801  ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1);
1802  else if (!strcasecmp(var->name, "context"))
1803  ast_copy_string(context, var->value, sizeof(context));
1804  else if (!strcasecmp(var->name, "externip"))
1805  ast_copy_string(externip, var->value, sizeof(externip));
1806  else if (!strcasecmp(var->name, "bindaddr")) {
1807  if (!(hp = ast_gethostbyname(var->value, &ahp))) {
1808  ast_log(LOG_WARNING, "Invalid address: %s\n", var->value);
1809  } else {
1810  memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
1811  }
1812  }
1813 /* Idea to allow for custom candidates */
1814 /*
1815  else if (!strcasecmp(var->name, "candidate")) {
1816  candidate = jingle_create_candidate(var->value);
1817  if (candidate) {
1818  candidate->next = global_candidates;
1819  global_candidates = candidate;
1820  }
1821  }
1822 */
1823  }
1824  while (cat) {
1825  if (strcasecmp(cat, "general")) {
1826  var = ast_variable_browse(cfg, cat);
1827  member = ast_calloc(1, sizeof(*member));
1828  ASTOBJ_INIT(member);
1829  ASTOBJ_WRLOCK(member);
1830  if (!strcasecmp(cat, "guest")) {
1831  ast_copy_string(member->name, "guest", sizeof(member->name));
1832  ast_copy_string(member->user, "guest", sizeof(member->user));
1833  ast_copy_string(member->context, context, sizeof(member->context));
1834  member->allowguest = allowguest;
1835  member->prefs = prefs;
1836  while (var) {
1837  if (!strcasecmp(var->name, "disallow"))
1838  ast_parse_allow_disallow(&member->prefs, &member->capability,
1839  var->value, 0);
1840  else if (!strcasecmp(var->name, "allow"))
1841  ast_parse_allow_disallow(&member->prefs, &member->capability,
1842  var->value, 1);
1843  else if (!strcasecmp(var->name, "context"))
1844  ast_copy_string(member->context, var->value,
1845  sizeof(member->context));
1846  else if (!strcasecmp(var->name, "parkinglot"))
1847  ast_copy_string(member->parkinglot, var->value,
1848  sizeof(member->parkinglot));
1849 /* Idea to allow for custom candidates */
1850 /*
1851  else if (!strcasecmp(var->name, "candidate")) {
1852  candidate = jingle_create_candidate(var->value);
1853  if (candidate) {
1854  candidate->next = member->ourcandidates;
1855  member->ourcandidates = candidate;
1856  }
1857  }
1858 */
1859  var = var->next;
1860  }
1861  ASTOBJ_UNLOCK(member);
1862  clients = ast_aji_get_clients();
1863  if (clients) {
1864  ASTOBJ_CONTAINER_TRAVERSE(clients, 1, {
1865  ASTOBJ_WRLOCK(iterator);
1866  ASTOBJ_WRLOCK(member);
1867  if (member->connection) {
1869  }
1870  member->connection = NULL;
1871  iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE);
1872  iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE);
1873  ASTOBJ_UNLOCK(member);
1874  ASTOBJ_UNLOCK(iterator);
1875  });
1877  } else {
1878  ASTOBJ_UNLOCK(member);
1880  }
1881  } else {
1882  ASTOBJ_UNLOCK(member);
1883  if (jingle_create_member(cat, var, allowguest, prefs, context, member))
1886  }
1887  }
1888  cat = ast_category_browse(cfg, cat);
1889  }
1890  ast_config_destroy(cfg);
1891  jingle_free_candidates(global_candidates);
1892  return 1;
1893 }
1894 
1895 /*! \brief Load module into PBX, register channel */
1896 static int load_module(void)
1897 {
1898  struct ast_sockaddr ourip_tmp;
1899  struct ast_sockaddr bindaddr_tmp;
1900 
1901  char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
1902  free(jabber_loaded);
1903  if (!jabber_loaded) {
1904  /* Dependency module has a different name, if embedded */
1905  jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
1906  free(jabber_loaded);
1907  if (!jabber_loaded) {
1908  ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n");
1909  return AST_MODULE_LOAD_DECLINE;
1910  }
1911  }
1912 
1914  if (!jingle_load_config()) {
1915  ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG);
1916  return AST_MODULE_LOAD_DECLINE;
1917  }
1918 
1919  sched = sched_context_create();
1920  if (!sched) {
1921  ast_log(LOG_WARNING, "Unable to create schedule context\n");
1922  }
1923 
1924  io = io_context_create();
1925  if (!io) {
1926  ast_log(LOG_WARNING, "Unable to create I/O context\n");
1927  }
1928 
1929  bindaddr.sin_family = AF_INET;
1930  ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
1931  if (ast_find_ourip(&ourip_tmp, &bindaddr_tmp, AF_INET)) {
1932  ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
1933  return 0;
1934  }
1935  __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp));
1936 
1937  ast_rtp_glue_register(&jingle_rtp_glue);
1938  ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
1939  /* Make sure we can register our channel type */
1940  if (ast_channel_register(&jingle_tech)) {
1941  ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
1942  return -1;
1943  }
1944  return 0;
1945 }
1946 
1947 /*! \brief Reload module */
1948 static int reload(void)
1949 {
1950  return 0;
1951 }
1952 
1953 /*! \brief Unload the jingle channel from Asterisk */
1954 static int unload_module(void)
1955 {
1956  struct jingle_pvt *privates = NULL;
1957  ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
1958  /* First, take us out of the channel loop */
1959  ast_channel_unregister(&jingle_tech);
1960  ast_rtp_glue_unregister(&jingle_rtp_glue);
1961 
1962  if (!ast_mutex_lock(&jinglelock)) {
1963  /* Hangup all interfaces if they have an owner */
1965  ASTOBJ_WRLOCK(iterator);
1966  privates = iterator->p;
1967  while(privates) {
1968  if (privates->owner)
1970  privates = privates->next;
1971  }
1972  iterator->p = NULL;
1973  ASTOBJ_UNLOCK(iterator);
1974  });
1976  } else {
1977  ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1978  return -1;
1979  }
1982  return 0;
1983 }
1984 
1985 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Jingle Channel Driver",
1986  .load = load_module,
1987  .unload = unload_module,
1988  .reload = reload,
1989  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
1990  );
Jingle definitions for chan_jingle.
struct jingle_pvt * p
Definition: chan_jingle.c:145
void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs)
Set codec packetization preferences.
Definition: rtp_engine.c:727
static char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:155
static struct ast_channel_tech jingle_tech
PBX interface structure for channel registration.
Definition: chan_jingle.c:191
static int unload_module(void)
Unload the jingle channel from Asterisk.
Definition: chan_jingle.c:1954
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1569
unsigned long long ast_group_t
Definition: channel.h:175
static char pass[512]
union ast_frame_subclass subclass
Definition: frame.h:146
enum jingle_connect_type type
Definition: chan_jingle.c:135
unsigned int preference
Definition: chan_jingle.c:137
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
int alreadygone
Definition: chan_jingle.c:107
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:383
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:227
Main Channel structure associated with a channel.
Definition: channel.h:742
static char externip[16]
Definition: chan_jingle.c:224
Music on hold handling.
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
const char *const type
Definition: channel.h:508
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
int rings
Definition: channel.h:840
static int jingle_answer(struct ast_channel *ast)
Definition: chan_jingle.c:377
static struct jingle_pvt * jingle_alloc(struct jingle *client, const char *from, const char *sid)
Definition: chan_jingle.c:739
static int jingle_ringing_ack(void *data, ikspak *pak)
Definition: chan_jingle.c:365
void ast_aji_buddy_destroy(struct aji_buddy *obj)
Definition: res_jabber.c:432
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * str
Subscriber phone number (Malloced)
Definition: channel.h:336
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
Definition: channel.c:1601
struct ast_frame ast_null_frame
Definition: frame.c:131
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct jingle_candidate * next
Definition: chan_jingle.c:138
char * strsep(char **str, const char *delims)
int priority
Definition: channel.h:841
ast_group_t callgroup
Definition: chan_jingle.c:152
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:245
static struct in_addr __ourip
Definition: chan_jingle.c:216
#define ast_strdup(a)
Definition: astmm.h:109
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
static int jingle_transmit_invite(struct jingle_pvt *p)
Definition: chan_jingle.c:1386
format_t writeformat
Definition: channel.h:854
unsigned int generation
Definition: chan_jingle.c:128
char musicclass[MAX_MUSICCLASS]
Definition: chan_jingle.c:157
int ast_aji_send(struct aji_client *client, iks *x)
Wraps raw sending.
Definition: res_jabber.c:1439
int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
Find our IP address.
Definition: acl.c:744
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static enum ast_rtp_glue_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
Definition: chan_jingle.c:390
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
static int jingle_add_candidate(struct jingle *client, ikspak *pak)
Definition: chan_jingle.c:1106
#define MAX_MUSICCLASS
Definition: channel.h:139
static struct ast_jb_conf global_jbconf
Definition: chan_jingle.c:84
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:938
void * tech_pvt
Definition: channel.h:744
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
static struct ast_frame * jingle_read(struct ast_channel *ast)
Definition: chan_jingle.c:1212
static void jingle_free_candidates(struct jingle_candidate *candidate)
Definition: chan_jingle.c:928
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:483
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
static int jingle_digit_begin(struct ast_channel *ast, char digit)
Definition: chan_jingle.c:1370
format_t capability
Definition: chan_jingle.c:108
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:577
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
char parkinglot[AST_MAX_CONTEXT]
Definition: chan_jingle.c:158
#define AST_FRAME_DTMF
Definition: frame.h:128
struct jingle_candidate * theircandidates
Definition: chan_jingle.c:110
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
char audio_content_name[100]
Definition: chan_jingle.c:116
#define var
Definition: ast_expr2f.c:606
format_t jointcapability
Definition: chan_jingle.c:120
static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, format_t codecs, int nat_active)
Definition: chan_jingle.c:415
#define AST_MAX_ACCOUNT_CODE
Definition: cdr.h:73
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:374
format_t rawwriteformat
Definition: channel.h:856
#define ast_rtp_glue_register(glue)
Definition: rtp_engine.h:476
format_t ast_codec_pref_index(struct ast_codec_pref *pref, int index)
Codec located at a particular place in the preference index.
Definition: frame.c:1061
char ring[10]
Definition: chan_jingle.c:104
static int jingle_update_stun(struct jingle *client, struct jingle_pvt *p)
Definition: chan_jingle.c:1078
struct jingle_pvt * next
Definition: chan_jingle.c:122
Definition: cli.h:146
unsigned int network
Definition: chan_jingle.c:130
struct jingle * parent
Definition: chan_jingle.c:101
static int jingle_parser(void *data, ikspak *pak)
Definition: chan_jingle.c:1635
static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: chan_jingle.c:1270
Configuration File Parser.
uint32_t ast_sockaddr_ipv4(const struct ast_sockaddr *addr)
Get an IPv4 address of an ast_sockaddr.
Definition: netsock2.c:394
static int jingle_call(struct ast_channel *ast, char *dest, int timeout)
Initiate new call, part of PBX interface dest is the dial string.
Definition: chan_jingle.c:1464
int allowguest
Definition: chan_jingle.c:155
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
Definition: channel.c:1062
static int jingle_write(struct ast_channel *ast, struct ast_frame *f)
Send frame to media channel (rtp)
Definition: chan_jingle.c:1224
#define ASTOBJ_WRLOCK(object)
Lock an ASTOBJ for writing.
Definition: astobj.h:104
#define JINGLE_NODE
Definition: jingle.h:37
#define ast_mutex_lock(a)
Definition: lock.h:155
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:907
static int jingle_load_config(void)
Definition: chan_jingle.c:1766
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
char * text
Definition: app_queue.c:1091
format_t nativeformats
Definition: channel.h:852
const char * str
Definition: app_jack.c:144
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
format_t capability
Definition: chan_jingle.c:151
format_t codec
Definition: frame.h:137
const char * data
Definition: channel.h:755
static int load_module(void)
Load module into PBX, register channel.
Definition: chan_jingle.c:1896
I/O Management (derived from Cheops-NG)
Common implementation-independent jitterbuffer stuff.
ast_group_t pickupgroup
Definition: chan_jingle.c:153
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
static int jingle_create_candidates(struct jingle *client, struct jingle_pvt *p, char *sid, char *from)
Definition: chan_jingle.c:579
#define JINGLE_VIDEO_RTP_NS
Definition: jingle.h:42
const ast_string_field linkedid
Definition: channel.h:787
AJI - The Asterisk Jabber Interface.
enum ast_channel_adsicpe adsicpe
Definition: channel.h:844
char sid[100]
Definition: chan_jingle.c:102
format_t rawreadformat
Definition: channel.h:855
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
static struct jingle_container jingle_list
Definition: chan_jingle.c:226
Socket address structure.
Definition: netsock2.h:63
ast_group_t pickupgroup
Definition: channel.h:819
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
const char * type
Definition: rtp_engine.h:395
struct ast_channel * owner
Definition: chan_jingle.c:115
struct ast_codec_pref prefs
Definition: chan_jingle.c:146
ast_group_t callgroup
Definition: channel.h:818
#define JINGLE_AUDIO_RTP_NS
Definition: jingle.h:41
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
char password[100]
Definition: chan_jingle.c:134
struct ast_frame dtmff
Definition: channel.h:816
#define MAX_LANGUAGE
Definition: channel.h:138
int ast_aji_send_chat(struct aji_client *client, const char *address, const char *message)
sends messages.
Definition: res_jabber.c:2582
#define JINGLE_ICE_UDP_NS
Definition: jingle.h:43
String fields in structures.
Utility functions.
static const char channel_type[]
Definition: chan_jingle.c:166
#define ASTOBJ_COMPONENTS(type)
Add ASTOBJ components to a struct (with locking support).
Definition: astobj.h:173
void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
Request that the underlying RTP engine send a STUN BIND request.
Definition: rtp_engine.c:1749
#define ASTOBJ_CONTAINER_INIT(container)
Initialize a container.
Definition: astobj.h:752
#define JINGLE_NS
Definition: jingle.h:40
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
Definition: chan_jingle.c:1285
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
char resource[AJI_MAX_RESJIDLEN]
Definition: jabber.h:119
static void jingle_member_destroy(struct jingle *obj)
Definition: chan_jingle.c:228
format_t peercapability
Definition: chan_jingle.c:121
ast_mutex_t lock
Definition: chan_jingle.c:99
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const char * value
Definition: config.h:79
char language[MAX_LANGUAGE]
Definition: chan_jingle.c:156
char name[80]
Definition: chan_jingle.c:142
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:377
General Asterisk PBX channel definitions.
struct ast_party_dialed::@155 number
Dialed/Called number.
struct aji_buddy_container buddies
Definition: jabber.h:184
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:642
static int jingle_response(struct jingle *client, ikspak *pak, const char *reasonstr, const char *reasonstr2)
Definition: chan_jingle.c:442
const int fd
Definition: cli.h:153
#define AST_FORMAT_ALAW
Definition: frame.h:248
ASTOBJ_CONTAINER_COMPONENTS(struct jingle)
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
char context[100]
Definition: chan_jingle.c:149
char cid_num[80]
Definition: chan_jingle.c:112
char * ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
Match modules names for the Asterisk cli.
Definition: loader.c:626
static format_t jingle_get_codec(struct ast_channel *chan)
Definition: chan_jingle.c:409
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct sla_ringing_trunk * last
Definition: app_meetme.c:965
Access Control of various sorts.
iksrule * ringrule
Definition: chan_jingle.c:105
Global IO variables are now in a struct in order to be made threadsafe.
Definition: io.c:66
int datalen
Definition: frame.h:148
Scheduler Routines (derived from cheops)
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
#define ao2_ref(o, delta)
Definition: astobj2.h:472
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
long int ast_random(void)
Definition: utils.c:1640
#define ASTOBJ_INIT(object)
Initialize an object.
Definition: astobj.h:264
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
const char * name
Definition: config.h:77
char them[AJI_MAX_JIDLEN]
Definition: chan_jingle.c:103
static int jingle_hangup_farend(struct jingle *client, ikspak *pak)
Definition: chan_jingle.c:558
static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_jingle.c:1375
#define AST_FORMAT_H263
Definition: frame.h:283
enum jingle_protocol protocol
Definition: chan_jingle.c:133
#define FORMAT
static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p)
Definition: chan_jingle.c:299
struct aji_resource * next
Definition: jabber.h:123
ast_rtp_glue_result
Definition: rtp_engine.h:125
static int jingle_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
Definition: chan_jingle.c:1380
int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options)
Record payload information that was seen in an a=rtpmap: SDP line.
Definition: rtp_engine.c:597
static struct ast_frame * jingle_rtp_read(struct ast_channel *ast, struct jingle_pvt *p)
Definition: chan_jingle.c:1184
Structure to describe a channel &quot;technology&quot;, ie a channel driver See for examples: ...
Definition: channel.h:507
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1558
char video_content_name[100]
Definition: chan_jingle.c:118
static struct sched_context * sched
Definition: chan_gtalk.c:227
#define ASTOBJ_UNREF(object, destructor)
Decrement the reference count on an object.
Definition: astobj.h:218
struct ast_rtp_instance * vrtp
Definition: chan_jingle.c:119
struct ast_party_dialed dialed
Dialed/Called information.
Definition: channel.h:797
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
struct aji_buddy * buddy
Definition: chan_jingle.c:144
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define ASTOBJ_CONTAINER_DESTROY(container)
Destroy a container.
Definition: astobj.h:765
#define LOG_ERROR
Definition: logger.h:155
#define ASTOBJ_CONTAINER_DESTROYALL(container, destructor)
Empty a container.
Definition: astobj.h:453
A set of macros implementing objects and containers. Macros are used for maximum performance, to support multiple inheritance, and to be easily integrated into existing structures without additional malloc calls, etc.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
#define JINGLE_TERMINATE
Definition: jingle.h:64
static void add_codec_to_answer(const struct jingle_pvt *p, int codec, iks *dcodecs)
Definition: chan_jingle.c:259
static struct ast_rtp_glue jingle_rtp_glue
Definition: chan_jingle.c:435
int64_t format_t
Definition: frame_defs.h:32
static char * jingle_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command &quot;jingle reload&quot;.
Definition: chan_jingle.c:1619
#define free(a)
Definition: astmm.h:94
#define ASTOBJ_CONTAINER_LINK(container, newobj)
Add an object to a container.
Definition: astobj.h:776
#define JINGLE_SID
Definition: jingle.h:52
static const char desc[]
Definition: chan_jingle.c:165
#define CLI_SHOWUSAGE
Definition: cli.h:44
static int reload(void)
Reload module.
Definition: chan_jingle.c:1948
static int jingle_create_member(char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct jingle *member)
Definition: chan_jingle.c:1708
static struct ast_codec_pref prefs
Definition: chan_iax2.c:258
int amaflags
Definition: chan_jingle.c:147
#define AST_FORMAT_ULAW
Definition: frame.h:246
iksid * jid
Definition: jabber.h:160
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct io_context * io
Definition: chan_jingle.c:215
#define AJI_MAX_JIDLEN
Definition: jabber.h:73
format_t ast_codec_choose(struct ast_codec_pref *pref, format_t formats, int find_best)
Select the best audio format according to preference list from supplied options. If &quot;find_best&quot; is no...
Definition: frame.c:1249
#define ASTOBJ_CONTAINER_TRAVERSE(container, continue, eval)
Iterate through the objects in a container.
Definition: astobj.h:376
#define LOG_NOTICE
Definition: logger.h:133
static struct ast_jb_conf default_jbconf
Definition: chan_jingle.c:76
static int jingle_handle_dtmf(struct jingle *client, ikspak *pak)
Definition: chan_jingle.c:494
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_jingle.c:150
jingle_connect_type
Definition: chan_jingle.c:91
jingle_protocol
Definition: chan_jingle.c:86
#define JINGLE_ACCEPT
Definition: jingle.h:57
char exten[80]
Definition: chan_jingle.c:114
struct aji_client * ast_aji_get_client(const char *name)
grab a aji_client structure by label name or JID. Bumps the refcount. (without the resource string) ...
Definition: res_jabber.c:4575
#define AST_FORMAT_VIDEO_MASK
Definition: frame.h:290
struct ast_codec_pref prefs
Definition: chan_jingle.c:109
static const char name[]
#define AST_MAX_CONTEXT
Definition: channel.h:136
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
#define ASTOBJ_UNLOCK(object)
Unlock a locked object.
Definition: astobj.h:109
#define JINGLE_INITIATE
Definition: jingle.h:55
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
#define ASTOBJ_CONTAINER_FIND(container, namestr)
Find an object in a container.
Definition: astobj.h:401
#define AST_FORMAT_AUDIO_MASK
Definition: frame.h:274
int allowguest
Definition: jabber.h:177
unsigned int priority
Definition: chan_jingle.c:132
static struct ast_format f[]
Definition: format_g726.c:181
#define JINGLE_CONFIG
Definition: chan_jingle.c:73
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
Definition: rtp_engine.c:786
static int jingle_action(struct jingle *client, struct jingle_pvt *p, const char *action)
Definition: chan_jingle.c:895
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:308
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:58
static format_t global_capability
Definition: chan_jingle.c:168
static const char type[]
Definition: chan_nbs.c:57
structure to hold users read from users.conf
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:430
Structure used to handle boolean flags.
Definition: utils.h:200
static struct aji_client_container clients
Definition: res_jabber.c:392
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:301
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2631
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:616
const char * usage
Definition: cli.h:171
static int jingle_hangup(struct ast_channel *ast)
Hangup a call through the jingle proxy channel.
Definition: chan_jingle.c:1489
struct ast_rtp_instance * rtp
Definition: chan_jingle.c:117
static struct sockaddr_in bindaddr
Definition: chan_gtalk.c:225
void ast_aji_client_destroy(struct aji_client *obj)
Definition: res_jabber.c:410
struct aji_version * cap
Definition: jabber.h:121
#define CLI_SUCCESS
Definition: cli.h:43
void * jingle
Definition: jabber.h:186
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
Definition: utils.c:195
struct sched_context * sched_context_create(void)
New schedule context.
Definition: sched.c:246
Channels have this property if they can create jitter; i.e. most VoIP channels.
Definition: channel.h:888
static int jingle_is_answered(struct jingle *client, ikspak *pak)
Definition: chan_jingle.c:474
Standard Command Line Interface.
#define ASTOBJ_RDLOCK(object)
Lock an ASTOBJ for reading.
Definition: astobj.h:100
format_t readformat
Definition: channel.h:853
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static struct jingle * find_jingle(char *name, char *connection)
Definition: chan_jingle.c:233
#define JINGLE_DTMF_NS
Definition: jingle.h:44
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static ast_mutex_t jinglelock
Definition: chan_jingle.c:170
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
char cid_name[80]
Definition: chan_jingle.c:113
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Definition: rtp_engine.c:266
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct jingle_candidate * ourcandidates
Definition: chan_jingle.c:111
static int jingle_sendtext(struct ast_channel *ast, const char *text)
Definition: chan_jingle.c:1304
char * ast_getformatname_multiple(char *buf, size_t size, format_t format)
Get the names of a set of formats.
Definition: frame.c:591
unsigned int component
Definition: chan_jingle.c:126
Data structure associated with a single frame of data.
Definition: frame.h:142
int hangupcause
Definition: channel.h:849
#define ASTOBJ_CONTAINER_FIND_FULL(container, data, field, hashfunc, hashoffset, comparefunc)
Find an object in a container.
Definition: astobj.h:428
Internal Asterisk hangup causes.
static struct ast_channel * jingle_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
Part of PBX interface.
Definition: chan_jingle.c:1508
int timeout
Definition: jabber.h:178
static struct ast_cli_entry jingle_cli[]
Definition: chan_jingle.c:218
#define JINGLE_INFO
Definition: jingle.h:63
struct aji_client * connection
Definition: chan_jingle.c:143
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
Definition: channel.h:883
static int jingle_newcall(struct jingle *client, ikspak *pak)
Definition: chan_jingle.c:966
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:629
enum ast_frame_type frametype
Definition: frame.h:144
static void jingle_free_pvt(struct jingle *client, struct jingle_pvt *p)
Definition: chan_jingle.c:938
struct ast_variable * next
Definition: config.h:82
#define ast_mutex_init(pmutex)
Definition: lock.h:152
int callingpres
Definition: chan_jingle.c:154
#define JINGLE_NEGOTIATE
Definition: jingle.h:60
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
time_t laststun
Definition: chan_jingle.c:100
static struct ast_channel * jingle_new(struct jingle *client, struct jingle_pvt *i, int state, const char *title, const char *linkedid)
Start new jingle channel.
Definition: chan_jingle.c:807
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Pluggable RTP Architecture.
#define ASTOBJ_REF(object)
Increment an object reference count.
Definition: astobj.h:201
Asterisk module definitions.
static struct hostent * hp
Definition: chan_skinny.c:1048
int amaflags
Definition: channel.h:843
char ufrag[100]
Definition: chan_jingle.c:136
unsigned int foundation
Definition: chan_jingle.c:127
static snd_pcm_format_t format
Definition: chan_alsa.c:93
union ast_frame::@172 data
struct ast_channel_tech * tech
Definition: channel.h:743
static int jingle_digit(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_jingle.c:1324
#define AST_FORMAT_GSM
Definition: frame.h:244
char mid[6]
Definition: jabber.h:159
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct aji_resource * resources
Definition: jabber.h:137
unsigned int port
Definition: chan_jingle.c:131
General jitterbuffer configuration.
Definition: abstract_jb.h:55
char user[100]
Definition: chan_jingle.c:148
void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
Record payload information that was seen in an m= SDP line.
Definition: rtp_engine.c:532
int inet_aton(const char *cp, struct in_addr *pin)
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
iksfilter * f
Definition: jabber.h:162
int jingle
Definition: jabber.h:106
Structure for mutex and tracking information.
Definition: lock.h:121
static char * jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command &quot;jingle show channels&quot;.
Definition: chan_jingle.c:1555
void ast_aji_increment_mid(char *mid)
increments the mid field for messages and other events.
Definition: res_jabber.c:2790
int ast_parse_allow_disallow(struct ast_codec_pref *pref, format_t *mask, const char *list, int allowing)
Parse an &quot;allow&quot; or &quot;deny&quot; line in a channel or device configuration and update the capabilities mask...
Definition: frame.c:1272
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:379
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define ast_mutex_unlock(a)
Definition: lock.h:156
enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
Bridge two channels that use RTP instances.
Definition: rtp_engine.c:1274
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
struct aji_client_container * ast_aji_get_clients(void)
Definition: res_jabber.c:4597
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...
Definition: io.c:76