Asterisk - The Open Source Telephony Project  18.5.0
parser.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  * Mark Spencer <[email protected]>
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  * \brief Implementation of Inter-Asterisk eXchange Protocol, v 2
22  *
23  * \author Mark Spencer <[email protected]>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 
36 #include "asterisk/frame.h"
37 #include "asterisk/utils.h"
38 #include "asterisk/unaligned.h"
39 #include "asterisk/config.h"
40 #include "asterisk/lock.h"
41 #include "asterisk/threadstorage.h"
42 #include "asterisk/netsock2.h"
43 #include "asterisk/format_cache.h"
45 
46 #include "include/iax2.h"
47 #include "include/parser.h"
48 #include "include/provision.h"
49 #include "include/codec_pref.h"
50 
51 static int frames = 0;
52 static int iframes = 0;
53 static int oframes = 0;
54 
55 #if (defined(LOW_MEMORY) || defined(MALLOC_DEBUG)) && !defined(NO_FRAME_CACHE)
56 #define NO_FRAME_CACHE
57 #endif
58 
59 #if !defined(NO_FRAME_CACHE)
60 static void frame_cache_cleanup(void *data);
61 
62 /*! \brief A per-thread cache of iax_frame structures */
64 
65 /*! \brief This is just so iax_frames, a list head struct for holding a list of
66  * iax_frame structures, is defined. */
68 
69 struct iax_frames {
71  size_t size;
72 };
73 
74 #define FRAME_CACHE_MAX_SIZE 20
75 #endif
76 
77 static void internaloutput(const char *str)
78 {
79  fputs(str, stdout);
80 }
81 
82 static void internalerror(const char *str)
83 {
84  fprintf(stderr, "WARNING: %s", str);
85 }
86 
87 static void (*outputf)(const char *str) = internaloutput;
88 static void (*errorf)(const char *str) = internalerror;
89 
90 static void dump_addr(char *output, int maxlen, void *value, int len)
91 {
92  struct ast_sockaddr addr;
93 
94  if (len == (int)sizeof(struct sockaddr_in)) {
95  addr.ss.ss_family = AF_INET;
96  } else if (len == (int) sizeof(struct sockaddr_in6)) {
97  addr.ss.ss_family = AF_INET6;
98  } else {
99  ast_copy_string(output, "Invalid Address", maxlen);
100  return;
101  }
102 
103  memcpy(&addr, value, len);
104  addr.len = len;
105 
106  snprintf(output, maxlen, "%s %s",
107  ast_sockaddr_is_ipv4(&addr) || ast_sockaddr_is_ipv4_mapped(&addr) ? "IPV4" : "IPV6",
108  ast_sockaddr_stringify(&addr));
109 }
110 
111 static void dump_string_hex(char *output, int maxlen, void *value, int len)
112 {
113  int i = 0;
114 
115  while (len-- && (i + 1) * 4 < maxlen) {
116  sprintf(output + (4 * i), "\\x%02hhx", *((unsigned char *)value + i));
117  i++;
118  }
119 }
120 
121 static void dump_string(char *output, int maxlen, void *value, int len)
122 {
123  maxlen--;
124  if (maxlen > len)
125  maxlen = len;
126  strncpy(output, value, maxlen);
127  output[maxlen] = '\0';
128 }
129 
130 static void dump_prefs(char *output, int maxlen, void *value, int len)
131 {
132  struct iax2_codec_pref pref;
133  int total_len = 0;
134 
135  maxlen--;
136  total_len = maxlen;
137 
138  if (maxlen > len)
139  maxlen = len;
140 
141  strncpy(output, value, maxlen);
142  output[maxlen] = '\0';
143 
144  iax2_codec_pref_convert(&pref, output, total_len, 0);
145  memset(output,0,total_len);
146  iax2_codec_pref_string(&pref, output, total_len);
147 }
148 
149 static void dump_int(char *output, int maxlen, void *value, int len)
150 {
151  if (len == (int)sizeof(unsigned int))
152  snprintf(output, maxlen, "%lu", (unsigned long)ntohl(get_unaligned_uint32(value)));
153  else
154  ast_copy_string(output, "Invalid INT", maxlen);
155 }
156 
157 static void dump_short(char *output, int maxlen, void *value, int len)
158 {
159  if (len == (int)sizeof(unsigned short))
160  snprintf(output, maxlen, "%d", ntohs(get_unaligned_uint16(value)));
161  else
162  ast_copy_string(output, "Invalid SHORT", maxlen);
163 }
164 
165 static void dump_byte(char *output, int maxlen, void *value, int len)
166 {
167  if (len == (int)sizeof(unsigned char))
168  snprintf(output, maxlen, "%d", *((unsigned char *)value));
169  else
170  ast_copy_string(output, "Invalid BYTE", maxlen);
171 }
172 
173 static void dump_datetime(char *output, int maxlen, void *value, int len)
174 {
175  struct ast_tm tm;
176  unsigned long val = (unsigned long) ntohl(get_unaligned_uint32(value));
177  if (len == (int)sizeof(unsigned int)) {
178  tm.tm_sec = (val & 0x1f) << 1;
179  tm.tm_min = (val >> 5) & 0x3f;
180  tm.tm_hour = (val >> 11) & 0x1f;
181  tm.tm_mday = (val >> 16) & 0x1f;
182  tm.tm_mon = ((val >> 21) & 0x0f) - 1;
183  tm.tm_year = ((val >> 25) & 0x7f) + 100;
184  ast_strftime(output, maxlen, "%Y-%m-%d %T", &tm);
185  } else
186  ast_copy_string(output, "Invalid DATETIME format!", maxlen);
187 }
188 
189 static void dump_ipaddr(char *output, int maxlen, void *value, int len)
190 {
191  struct ast_sockaddr addr;
192  char *str_addr;
193 
194  if (len == (int)sizeof(struct sockaddr_in)) {
195  addr.ss.ss_family = AF_INET;
196  } else if (len == (int)sizeof(struct sockaddr_in6)) {
197  addr.ss.ss_family = AF_INET6;
198  } else {
199  ast_copy_string(output, "Invalid IPADDR", maxlen);
200  return;
201  }
202 
203  memcpy(&addr, value, len);
204  addr.len = len;
205 
206  str_addr = ast_sockaddr_stringify(&addr);
207  ast_copy_string(output, str_addr, maxlen);
208 }
209 
210 
211 static void dump_prov_flags(char *output, int maxlen, void *value, int len)
212 {
213  char buf[256] = "";
214  if (len == (int)sizeof(unsigned int))
215  snprintf(output, maxlen, "%lu (%s)", (unsigned long)ntohl(get_unaligned_uint32(value)),
216  iax_provflags2str(buf, sizeof(buf), ntohl(get_unaligned_uint32(value))));
217  else
218  ast_copy_string(output, "Invalid INT", maxlen);
219 }
220 
221 static void dump_samprate(char *output, int maxlen, void *value, int len)
222 {
223  char tmp[256]="";
224  int sr;
225  if (len == (int)sizeof(unsigned short)) {
226  sr = ntohs(*((unsigned short *)value));
227  if (sr & IAX_RATE_8KHZ)
228  strcat(tmp, ",8khz");
229  if (sr & IAX_RATE_11KHZ)
230  strcat(tmp, ",11.025khz");
231  if (sr & IAX_RATE_16KHZ)
232  strcat(tmp, ",16khz");
233  if (sr & IAX_RATE_22KHZ)
234  strcat(tmp, ",22.05khz");
235  if (sr & IAX_RATE_44KHZ)
236  strcat(tmp, ",44.1khz");
237  if (sr & IAX_RATE_48KHZ)
238  strcat(tmp, ",48khz");
239  if (strlen(tmp))
240  ast_copy_string(output, &tmp[1], maxlen);
241  else
242  ast_copy_string(output, "None Specified!\n", maxlen);
243  } else
244  ast_copy_string(output, "Invalid SHORT", maxlen);
245 
246 }
247 
248 static void dump_versioned_codec(char *output, int maxlen, void *value, int len)
249 {
250  char *version = (char *) value;
251  if (version[0] == 0) {
252  if (len == (int) (sizeof(iax2_format) + sizeof(char))) {
253  iax2_format codec = ntohll(get_unaligned_uint64(value + 1));
254  ast_copy_string(output, iax2_getformatname(codec), maxlen);
255  } else {
256  ast_copy_string(output, "Invalid length!", maxlen);
257  }
258  } else {
259  ast_copy_string(output, "Unknown version!", maxlen);
260  }
261 }
262 
263 static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len);
264 static void dump_prov(char *output, int maxlen, void *value, int len)
265 {
266  dump_prov_ies(output, maxlen, value, len);
267 }
268 
269 struct iax2_ie {
270  int ie;
271  char *name;
272  void (*dump)(char *output, int maxlen, void *value, int len);
273 };
274 static struct iax2_ie infoelts[] = {
275  { IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
276  { IAX_IE_CALLING_NUMBER, "CALLING NUMBER", dump_string },
277  { IAX_IE_CALLING_ANI, "ANI", dump_string },
278  { IAX_IE_CALLING_NAME, "CALLING NAME", dump_string },
279  { IAX_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
280  { IAX_IE_USERNAME, "USERNAME", dump_string },
281  { IAX_IE_PASSWORD, "PASSWORD", dump_string },
282  { IAX_IE_CAPABILITY, "CAPABILITY", dump_int },
283  { IAX_IE_CAPABILITY2, "CAPABILITY2", dump_versioned_codec },
284  { IAX_IE_FORMAT, "FORMAT", dump_int },
285  { IAX_IE_FORMAT2, "FORMAT2", dump_versioned_codec },
286  { IAX_IE_LANGUAGE, "LANGUAGE", dump_string },
287  { IAX_IE_VERSION, "VERSION", dump_short },
288  { IAX_IE_ADSICPE, "ADSICPE", dump_short },
289  { IAX_IE_DNID, "DNID", dump_string },
290  { IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_short },
291  { IAX_IE_CHALLENGE, "CHALLENGE", dump_string_hex },
292  { IAX_IE_MD5_RESULT, "MD5 RESULT", dump_string },
293  { IAX_IE_RSA_RESULT, "RSA RESULT", dump_string },
294  { IAX_IE_APPARENT_ADDR, "APPARENT ADDRESS", dump_addr },
295  { IAX_IE_REFRESH, "REFRESH", dump_short },
296  { IAX_IE_DPSTATUS, "DIALPLAN STATUS", dump_short },
297  { IAX_IE_CALLNO, "CALL NUMBER", dump_short },
298  { IAX_IE_CAUSE, "CAUSE", dump_string },
299  { IAX_IE_IAX_UNKNOWN, "UNKNOWN IAX CMD", dump_byte },
300  { IAX_IE_MSGCOUNT, "MESSAGE COUNT", dump_short },
301  { IAX_IE_AUTOANSWER, "AUTO ANSWER REQ" },
302  { IAX_IE_TRANSFERID, "TRANSFER ID", dump_int },
303  { IAX_IE_RDNIS, "REFERRING DNIS", dump_string },
304  { IAX_IE_PROVISIONING, "PROVISIONING", dump_prov },
305  { IAX_IE_AESPROVISIONING, "AES PROVISIONG" },
306  { IAX_IE_DATETIME, "DATE TIME", dump_datetime },
307  { IAX_IE_DEVICETYPE, "DEVICE TYPE", dump_string },
308  { IAX_IE_SERVICEIDENT, "SERVICE IDENT", dump_string },
309  { IAX_IE_FIRMWAREVER, "FIRMWARE VER", dump_short },
310  { IAX_IE_FWBLOCKDESC, "FW BLOCK DESC", dump_int },
311  { IAX_IE_FWBLOCKDATA, "FW BLOCK DATA" },
312  { IAX_IE_PROVVER, "PROVISIONG VER", dump_int },
313  { IAX_IE_CALLINGPRES, "CALLING PRESNTN", dump_byte },
314  { IAX_IE_CALLINGTON, "CALLING TYPEOFNUM", dump_byte },
315  { IAX_IE_CALLINGTNS, "CALLING TRANSITNET", dump_short },
316  { IAX_IE_SAMPLINGRATE, "SAMPLINGRATE", dump_samprate },
317  { IAX_IE_CAUSECODE, "CAUSE CODE", dump_byte },
318  { IAX_IE_ENCRYPTION, "ENCRYPTION", dump_short },
319  { IAX_IE_ENCKEY, "ENCRYPTION KEY" },
320  { IAX_IE_CODEC_PREFS, "CODEC_PREFS", dump_prefs },
321  { IAX_IE_RR_JITTER, "RR_JITTER", dump_int },
322  { IAX_IE_RR_LOSS, "RR_LOSS", dump_int },
323  { IAX_IE_RR_PKTS, "RR_PKTS", dump_int },
324  { IAX_IE_RR_DELAY, "RR_DELAY", dump_short },
325  { IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int },
326  { IAX_IE_RR_OOO, "RR_OUTOFORDER", dump_int },
327  { IAX_IE_VARIABLE, "VARIABLE", dump_string },
328  { IAX_IE_OSPTOKEN, "OSPTOKEN" },
329  { IAX_IE_CALLTOKEN, "CALLTOKEN" },
330 };
331 
332 static const struct iax2_ie prov_ies[] = {
333  { PROV_IE_USEDHCP, "USEDHCP" },
334  { PROV_IE_IPADDR, "IPADDR", dump_ipaddr },
335  { PROV_IE_SUBNET, "SUBNET", dump_ipaddr },
336  { PROV_IE_GATEWAY, "GATEWAY", dump_ipaddr },
337  { PROV_IE_PORTNO, "BINDPORT", dump_short },
338  { PROV_IE_USER, "USERNAME", dump_string },
339  { PROV_IE_PASS, "PASSWORD", dump_string },
340  { PROV_IE_LANG, "LANGUAGE", dump_string },
341  { PROV_IE_TOS, "TYPEOFSERVICE", dump_byte },
342  { PROV_IE_FLAGS, "FLAGS", dump_prov_flags },
343  { PROV_IE_FORMAT, "FORMAT", dump_int },
344  { PROV_IE_AESKEY, "AESKEY" },
345  { PROV_IE_SERVERIP, "SERVERIP", dump_ipaddr },
346  { PROV_IE_SERVERPORT, "SERVERPORT", dump_short },
347  { PROV_IE_NEWAESKEY, "NEWAESKEY" },
348  { PROV_IE_PROVVER, "PROV VERSION", dump_int },
349  { PROV_IE_ALTSERVER, "ALTSERVERIP", dump_ipaddr },
350 };
351 
352 const char *iax_ie2str(int ie)
353 {
354  int x;
355  for (x = 0; x < ARRAY_LEN(infoelts); x++) {
356  if (infoelts[x].ie == ie)
357  return infoelts[x].name;
358  }
359  return "Unknown IE";
360 }
361 
362 
363 static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
364 {
365  int ielen;
366  int ie;
367  int x;
368  int found;
369  char interp[80];
370  char tmp[256];
371  if (len < 2)
372  return;
373  strcpy(output, "\n");
374  maxlen -= strlen(output); output += strlen(output);
375  while(len > 2) {
376  ie = iedata[0];
377  ielen = iedata[1];
378  if (ielen + 2> len) {
379  snprintf(tmp, (int)sizeof(tmp), "Total Prov IE length of %d bytes exceeds remaining prov frame length of %d bytes\n", ielen + 2, len);
380  ast_copy_string(output, tmp, maxlen);
381  maxlen -= strlen(output);
382  output += strlen(output);
383  return;
384  }
385  found = 0;
386  for (x=0;x<(int)sizeof(prov_ies) / (int)sizeof(prov_ies[0]); x++) {
387  if (prov_ies[x].ie == ie) {
388  if (prov_ies[x].dump) {
389  prov_ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
390  snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", prov_ies[x].name, interp);
391  ast_copy_string(output, tmp, maxlen);
392  maxlen -= strlen(output); output += strlen(output);
393  } else {
394  if (ielen)
395  snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
396  else
397  strcpy(interp, "Present");
398  snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", prov_ies[x].name, interp);
399  ast_copy_string(output, tmp, maxlen);
400  maxlen -= strlen(output); output += strlen(output);
401  }
402  found++;
403  }
404  }
405  if (!found) {
406  snprintf(tmp, (int)sizeof(tmp), " Unknown Prov IE %03d : Present\n", ie);
407  ast_copy_string(output, tmp, maxlen);
408  maxlen -= strlen(output); output += strlen(output);
409  }
410  iedata += (2 + ielen);
411  len -= (2 + ielen);
412  }
413 }
414 
415 static void dump_ies(unsigned char *iedata, int len)
416 {
417  int ielen;
418  int ie;
419  int x;
420  int found;
421  char interp[1024];
422  char tmp[1046];
423 
424  if (len < 2)
425  return;
426  while(len > 2) {
427  ie = iedata[0];
428  ielen = iedata[1];
429  if (ielen + 2> len) {
430  snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
431  outputf(tmp);
432  return;
433  }
434  found = 0;
435  for (x = 0; x < ARRAY_LEN(infoelts); x++) {
436  if (infoelts[x].ie == ie) {
437  if (infoelts[x].dump) {
438  infoelts[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
439  snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", infoelts[x].name, interp);
440  outputf(tmp);
441  } else {
442  if (ielen)
443  snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
444  else
445  strcpy(interp, "Present");
446  snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", infoelts[x].name, interp);
447  outputf(tmp);
448  }
449  found++;
450  }
451  }
452  if (!found) {
453  snprintf(tmp, (int)sizeof(tmp), " Unknown IE %03d : Present\n", ie);
454  outputf(tmp);
455  }
456  iedata += (2 + ielen);
457  len -= (2 + ielen);
458  }
459  outputf("\n");
460 }
461 
462 void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len)
463 {
464  const char *cmd = "Unknown";
465 
466  /* if an error occurs here during compile, that means a new iax frame subclass
467  * has been added to the iax_frame_subclass enum. Add the new subclass to the
468  * switch case and make sure to update it with a new string representation. */
469  switch (subclass) {
470  case IAX_COMMAND_NEW:
471  cmd = "NEW ";
472  break;
473  case IAX_COMMAND_PING:
474  cmd = "PING ";
475  break;
476  case IAX_COMMAND_PONG:
477  cmd = "PONG ";
478  break;
479  case IAX_COMMAND_ACK:
480  cmd = "ACK ";
481  break;
482  case IAX_COMMAND_HANGUP:
483  cmd = "HANGUP ";
484  break;
485  case IAX_COMMAND_REJECT:
486  cmd = "REJECT ";
487  break;
488  case IAX_COMMAND_ACCEPT:
489  cmd = "ACCEPT ";
490  break;
491  case IAX_COMMAND_AUTHREQ:
492  cmd = "AUTHREQ";
493  break;
494  case IAX_COMMAND_AUTHREP:
495  cmd = "AUTHREP";
496  break;
497  case IAX_COMMAND_INVAL:
498  cmd = "INVAL ";
499  break;
500  case IAX_COMMAND_LAGRQ:
501  cmd = "LAGRQ ";
502  break;
503  case IAX_COMMAND_LAGRP:
504  cmd = "LAGRP ";
505  break;
506  case IAX_COMMAND_REGREQ:
507  cmd = "REGREQ ";
508  break;
509  case IAX_COMMAND_REGAUTH:
510  cmd = "REGAUTH";
511  break;
512  case IAX_COMMAND_REGACK:
513  cmd = "REGACK ";
514  break;
515  case IAX_COMMAND_REGREJ:
516  cmd = "REGREJ ";
517  break;
518  case IAX_COMMAND_REGREL:
519  cmd = "REGREL ";
520  break;
521  case IAX_COMMAND_VNAK:
522  cmd = "VNAK ";
523  break;
524  case IAX_COMMAND_DPREQ:
525  cmd = "DPREQ ";
526  break;
527  case IAX_COMMAND_DPREP:
528  cmd = "DPREP ";
529  break;
530  case IAX_COMMAND_DIAL:
531  cmd = "DIAL ";
532  break;
533  case IAX_COMMAND_TXREQ:
534  cmd = "TXREQ ";
535  break;
536  case IAX_COMMAND_TXCNT:
537  cmd = "TXCNT ";
538  break;
539  case IAX_COMMAND_TXACC:
540  cmd = "TXACC ";
541  break;
542  case IAX_COMMAND_TXREADY:
543  cmd = "TXREADY";
544  break;
545  case IAX_COMMAND_TXREL:
546  cmd = "TXREL ";
547  break;
548  case IAX_COMMAND_TXREJ:
549  cmd = "TXREJ ";
550  break;
551  case IAX_COMMAND_QUELCH:
552  cmd = "QUELCH ";
553  break;
555  cmd = "UNQULCH";
556  break;
557  case IAX_COMMAND_POKE:
558  cmd = "POKE ";
559  break;
560  case IAX_COMMAND_PAGE:
561  cmd = "PAGE ";
562  break;
563  case IAX_COMMAND_MWI:
564  cmd = "MWI ";
565  break;
567  cmd = "UNSPRTD";
568  break;
570  cmd = "TRANSFR";
571  break;
573  cmd = "PROVISN";
574  break;
575  case IAX_COMMAND_FWDOWNL:
576  cmd = "FWDWNLD";
577  break;
578  case IAX_COMMAND_FWDATA:
579  cmd = "FWDATA ";
580  break;
581  case IAX_COMMAND_TXMEDIA:
582  cmd = "TXMEDIA";
583  break;
584  case IAX_COMMAND_RTKEY:
585  cmd = "RTKEY ";
586  break;
588  cmd = "CTOKEN ";
589  break;
590  }
591  ast_copy_string(str, cmd, len);
592 }
593 
594 void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct ast_sockaddr *addr, int datalen)
595 {
596  const char *framelist[] = {
597  "(0?)",
598  "DTMF_E ",
599  "VOICE ",
600  "VIDEO ",
601  "CONTROL",
602  "NULL ",
603  "IAX ",
604  "TEXT ",
605  "IMAGE ",
606  "HTML ",
607  "CNG ",
608  "MODEM ",
609  "DTMF_B ",
610  };
611  const char *cmds[] = {
612  "(0?)",
613  "HANGUP ",
614  "RING ",
615  "RINGING",
616  "ANSWER ",
617  "BUSY ",
618  "TKOFFHK",
619  "OFFHOOK",
620  "CONGSTN",
621  "FLASH ",
622  "WINK ",
623  "OPTION ",
624  "RDKEY ",
625  "RDUNKEY",
626  "PROGRES",
627  "PROCDNG",
628  "HOLD ",
629  "UNHOLD ",
630  "VIDUPDT",
631  "T38 ",
632  "SRCUPDT",
633  "TXFER ",
634  "CNLINE ",
635  "REDIR ",
636  "T38PARM",
637  "CC ERR!",/* This must never go across an IAX link. */
638  "SRCCHG ",
639  "READACT",
640  "AOC ",
641  "ENDOFQ ",
642  "INCOMPL",
643  "MCID ",
644  "UPDRTPP",
645  "PCAUSEC",
646  };
647  struct ast_iax2_full_hdr *fh;
648  char retries[20];
649  char class2[20];
650  char subclass2[20];
651  const char *class;
652  const char *subclass;
653  char *dir;
654  char tmp[512];
655 
656  switch(rx) {
657  case 0:
658  dir = "Tx";
659  break;
660  case 2:
661  dir = "TE";
662  break;
663  case 3:
664  dir = "RD";
665  break;
666  default:
667  dir = "Rx";
668  break;
669  }
670  if (f) {
671  fh = f->data;
672  snprintf(retries, sizeof(retries), "%03d", f->retries);
673  } else {
674  fh = fhi;
675  if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
676  strcpy(retries, "Yes");
677  else
678  strcpy(retries, " No");
679  }
680  if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
681  /* Don't mess with mini-frames */
682  return;
683  }
684  if (fh->type >= ARRAY_LEN(framelist)) {
685  snprintf(class2, sizeof(class2), "(%d?)", fh->type);
686  class = class2;
687  } else {
688  class = framelist[(int)fh->type];
689  }
690  if (fh->type == AST_FRAME_DTMF_BEGIN || fh->type == AST_FRAME_DTMF_END) {
691  sprintf(subclass2, "%c", fh->csub);
692  subclass = subclass2;
693  } else if (fh->type == AST_FRAME_IAX) {
694  iax_frame_subclass2str((int)fh->csub, subclass2, sizeof(subclass2));
695  subclass = subclass2;
696  } else if (fh->type == AST_FRAME_CONTROL) {
697  if (fh->csub >= ARRAY_LEN(cmds)) {
698  snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
699  subclass = subclass2;
700  } else {
701  subclass = cmds[(int)fh->csub];
702  }
703  } else {
704  snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
705  subclass = subclass2;
706  }
707 
708  snprintf(tmp, sizeof(tmp),
709  "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
710  dir,
711  retries, fh->oseqno, fh->iseqno, class, subclass);
712  outputf(tmp);
713  snprintf(tmp, sizeof(tmp), " Timestamp: %05lums SCall: %5.5d DCall: %5.5d %s\n",
714  (unsigned long)ntohl(fh->ts),
715  ntohs(fh->scallno) & ~IAX_FLAG_FULL,
716  ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
717  ast_sockaddr_stringify(addr));
718 
719  outputf(tmp);
720  if (fh->type == AST_FRAME_IAX)
721  dump_ies(fh->iedata, datalen);
722 
723 }
724 
725 int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
726 {
727  char tmp[256];
728  if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
729  snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", iax_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
730  errorf(tmp);
731  return -1;
732  }
733  ied->buf[ied->pos++] = ie;
734  ied->buf[ied->pos++] = datalen;
735  memcpy(ied->buf + ied->pos, data, datalen);
736  ied->pos += datalen;
737  return 0;
738 }
739 
740 int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct ast_sockaddr *addr)
741 {
742  return iax_ie_append_raw(ied, ie, addr, addr->len);
743 }
744 
745 int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
746 {
747  struct _local {
748  unsigned char version;
749  uint64_t value;
750  } __attribute__((packed)) newval = { version, };
751  put_unaligned_uint64(&newval.value, htonll(value));
752  return iax_ie_append_raw(ied, ie, &newval, (int) sizeof(newval));
753 }
754 
755 int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
756 {
757  unsigned int newval;
758  newval = htonl(value);
759  return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
760 }
761 
762 int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
763 {
764  unsigned short newval;
765  newval = htons(value);
766  return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
767 }
768 
769 int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str)
770 {
771  return iax_ie_append_raw(ied, ie, str, strlen(str));
772 }
773 
774 int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
775 {
776  return iax_ie_append_raw(ied, ie, &dat, 1);
777 }
778 
779 int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
780 {
781  return iax_ie_append_raw(ied, ie, NULL, 0);
782 }
783 
784 void iax_set_output(void (*func)(const char *))
785 {
786  outputf = func;
787 }
788 
789 void iax_set_error(void (*func)(const char *))
790 {
791  errorf = func;
792 }
793 
794 int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
795 {
796  /* Parse data into information elements */
797  int len;
798  int ie;
799  char tmp[256], *tmp2;
800  struct ast_variable *var, *var2, *prev;
801  unsigned int count;
802  memset(ies, 0, (int)sizeof(struct iax_ies));
803  ies->msgcount = -1;
804  ies->firmwarever = -1;
805  ies->calling_ton = -1;
806  ies->calling_tns = -1;
807  ies->calling_pres = -1;
808  ies->samprate = IAX_RATE_8KHZ;
809  while(datalen >= 2) {
810  ie = data[0];
811  len = data[1];
812  if (len > datalen - 2) {
813  errorf("Information element length exceeds message size\n");
814  return -1;
815  }
816  switch(ie) {
818  ies->called_number = (char *)data + 2;
819  break;
821  ies->calling_number = (char *)data + 2;
822  break;
823  case IAX_IE_CALLING_ANI:
824  ies->calling_ani = (char *)data + 2;
825  break;
826  case IAX_IE_CALLING_NAME:
827  ies->calling_name = (char *)data + 2;
828  break;
830  ies->called_context = (char *)data + 2;
831  break;
832  case IAX_IE_USERNAME:
833  ies->username = (char *)data + 2;
834  break;
835  case IAX_IE_PASSWORD:
836  ies->password = (char *)data + 2;
837  break;
838  case IAX_IE_CODEC_PREFS:
839  ies->codec_prefs = (char *)data + 2;
840  break;
841  case IAX_IE_CAPABILITY:
842  if (len != (int)sizeof(unsigned int)) {
843  snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
844  errorf(tmp);
845  } else if (ies->capability == 0) { /* Don't overwrite capability2, if specified */
846  ies->capability = ntohl(get_unaligned_uint32(data + 2));
847  }
848  break;
849  case IAX_IE_CAPABILITY2:
850  {
851  int version = data[2];
852  if (version == 0) {
853  if (len != (int)sizeof(char) + sizeof(iax2_format)) {
854  snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len);
855  errorf(tmp);
856  } else {
858  }
859  } /* else unknown version */
860  }
861  break;
862  case IAX_IE_FORMAT:
863  if (len != (int)sizeof(unsigned int)) {
864  snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
865  errorf(tmp);
866  } else if (ies->format == 0) { /* Don't overwrite format2, if specified */
867  ies->format = ntohl(get_unaligned_uint32(data + 2));
868  }
869  break;
870  case IAX_IE_FORMAT2:
871  {
872  int version = data[2];
873  if (version == 0) {
874  if (len != (int)sizeof(char) + sizeof(iax2_format)) {
875  snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int) (sizeof(iax2_format) + sizeof(char)), len);
876  errorf(tmp);
877  } else {
878  ies->format = (iax2_format) ntohll(get_unaligned_uint64(data + 3));
879  }
880  } /* else unknown version */
881  }
882  break;
883  case IAX_IE_LANGUAGE:
884  ies->language = (char *)data + 2;
885  break;
886  case IAX_IE_VERSION:
887  if (len != (int)sizeof(unsigned short)) {
888  snprintf(tmp, (int)sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
889  errorf(tmp);
890  } else
891  ies->version = ntohs(get_unaligned_uint16(data + 2));
892  break;
893  case IAX_IE_ADSICPE:
894  if (len != (int)sizeof(unsigned short)) {
895  snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
896  errorf(tmp);
897  } else
898  ies->adsicpe = ntohs(get_unaligned_uint16(data + 2));
899  break;
900  case IAX_IE_SAMPLINGRATE:
901  if (len != (int)sizeof(unsigned short)) {
902  snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
903  errorf(tmp);
904  } else
905  ies->samprate = ntohs(get_unaligned_uint16(data + 2));
906  break;
907  case IAX_IE_DNID:
908  ies->dnid = (char *)data + 2;
909  break;
910  case IAX_IE_RDNIS:
911  ies->rdnis = (char *)data + 2;
912  break;
913  case IAX_IE_AUTHMETHODS:
914  if (len != (int)sizeof(unsigned short)) {
915  snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
916  errorf(tmp);
917  } else
918  ies->authmethods = ntohs(get_unaligned_uint16(data + 2));
919  break;
920  case IAX_IE_ENCRYPTION:
921  if (len != (int)sizeof(unsigned short)) {
922  snprintf(tmp, (int)sizeof(tmp), "Expecting encryption to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
923  errorf(tmp);
924  } else
925  ies->encmethods = ntohs(get_unaligned_uint16(data + 2));
926  break;
927  case IAX_IE_CHALLENGE:
928  ies->challenge = (char *)data + 2;
929  break;
930  case IAX_IE_MD5_RESULT:
931  ies->md5_result = (char *)data + 2;
932  break;
933  case IAX_IE_RSA_RESULT:
934  ies->rsa_result = (char *)data + 2;
935  break;
937  memcpy(&ies->apparent_addr , (struct ast_sockaddr *) (data + 2), len);
938  ies->apparent_addr.len = len;
939  break;
940  case IAX_IE_REFRESH:
941  if (len != (int)sizeof(unsigned short)) {
942  snprintf(tmp, (int)sizeof(tmp), "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
943  errorf(tmp);
944  } else
945  ies->refresh = ntohs(get_unaligned_uint16(data + 2));
946  break;
947  case IAX_IE_DPSTATUS:
948  if (len != (int)sizeof(unsigned short)) {
949  snprintf(tmp, (int)sizeof(tmp), "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
950  errorf(tmp);
951  } else
952  ies->dpstatus = ntohs(get_unaligned_uint16(data + 2));
953  break;
954  case IAX_IE_CALLNO:
955  if (len != (int)sizeof(unsigned short)) {
956  snprintf(tmp, (int)sizeof(tmp), "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
957  errorf(tmp);
958  } else
959  ies->callno = ntohs(get_unaligned_uint16(data + 2));
960  break;
961  case IAX_IE_CAUSE:
962  ies->cause = (char *)data + 2;
963  break;
964  case IAX_IE_CAUSECODE:
965  if (len != 1) {
966  snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
967  errorf(tmp);
968  } else {
969  ies->causecode = data[2];
970  }
971  break;
972  case IAX_IE_IAX_UNKNOWN:
973  if (len == 1)
974  ies->iax_unknown = data[2];
975  else {
976  snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
977  errorf(tmp);
978  }
979  break;
980  case IAX_IE_MSGCOUNT:
981  if (len != (int)sizeof(unsigned short)) {
982  snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
983  errorf(tmp);
984  } else
985  ies->msgcount = ntohs(get_unaligned_uint16(data + 2));
986  break;
987  case IAX_IE_AUTOANSWER:
988  ies->autoanswer = 1;
989  break;
990  case IAX_IE_MUSICONHOLD:
991  ies->musiconhold = 1;
992  break;
993  case IAX_IE_TRANSFERID:
994  if (len != (int)sizeof(unsigned int)) {
995  snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
996  errorf(tmp);
997  } else
998  ies->transferid = ntohl(get_unaligned_uint32(data + 2));
999  break;
1000  case IAX_IE_DATETIME:
1001  if (len != (int)sizeof(unsigned int)) {
1002  snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1003  errorf(tmp);
1004  } else
1005  ies->datetime = ntohl(get_unaligned_uint32(data + 2));
1006  break;
1007  case IAX_IE_FIRMWAREVER:
1008  if (len != (int)sizeof(unsigned short)) {
1009  snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1010  errorf(tmp);
1011  } else
1012  ies->firmwarever = ntohs(get_unaligned_uint16(data + 2));
1013  break;
1014  case IAX_IE_DEVICETYPE:
1015  ies->devicetype = (char *)data + 2;
1016  break;
1017  case IAX_IE_SERVICEIDENT:
1018  ies->serviceident = (char *)data + 2;
1019  break;
1020  case IAX_IE_FWBLOCKDESC:
1021  if (len != (int)sizeof(unsigned int)) {
1022  snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1023  errorf(tmp);
1024  } else
1025  ies->fwdesc = ntohl(get_unaligned_uint32(data + 2));
1026  break;
1027  case IAX_IE_FWBLOCKDATA:
1028  ies->fwdata = data + 2;
1029  ies->fwdatalen = len;
1030  break;
1031  case IAX_IE_ENCKEY:
1032  ies->enckey = data + 2;
1033  ies->enckeylen = len;
1034  break;
1035  case IAX_IE_PROVVER:
1036  if (len != (int)sizeof(unsigned int)) {
1037  snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1038  errorf(tmp);
1039  } else {
1040  ies->provverpres = 1;
1041  ies->provver = ntohl(get_unaligned_uint32(data + 2));
1042  }
1043  break;
1044  case IAX_IE_CALLINGPRES:
1045  if (len == 1)
1046  ies->calling_pres = data[2];
1047  else {
1048  snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
1049  errorf(tmp);
1050  }
1051  break;
1052  case IAX_IE_CALLINGTON:
1053  if (len == 1)
1054  ies->calling_ton = data[2];
1055  else {
1056  snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
1057  errorf(tmp);
1058  }
1059  break;
1060  case IAX_IE_CALLINGTNS:
1061  if (len != (int)sizeof(unsigned short)) {
1062  snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1063  errorf(tmp);
1064  } else
1065  ies->calling_tns = ntohs(get_unaligned_uint16(data + 2));
1066  break;
1067  case IAX_IE_RR_JITTER:
1068  if (len != (int)sizeof(unsigned int)) {
1069  snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1070  errorf(tmp);
1071  } else {
1072  ies->rr_jitter = ntohl(get_unaligned_uint32(data + 2));
1073  }
1074  break;
1075  case IAX_IE_RR_LOSS:
1076  if (len != (int)sizeof(unsigned int)) {
1077  snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1078  errorf(tmp);
1079  } else {
1080  ies->rr_loss = ntohl(get_unaligned_uint32(data + 2));
1081  }
1082  break;
1083  case IAX_IE_RR_PKTS:
1084  if (len != (int)sizeof(unsigned int)) {
1085  snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1086  errorf(tmp);
1087  } else {
1088  ies->rr_pkts = ntohl(get_unaligned_uint32(data + 2));
1089  }
1090  break;
1091  case IAX_IE_RR_DELAY:
1092  if (len != (int)sizeof(unsigned short)) {
1093  snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
1094  errorf(tmp);
1095  } else {
1096  ies->rr_delay = ntohs(get_unaligned_uint16(data + 2));
1097  }
1098  break;
1099  case IAX_IE_RR_DROPPED:
1100  if (len != (int)sizeof(unsigned int)) {
1101  snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1102  errorf(tmp);
1103  } else {
1104  ies->rr_dropped = ntohl(get_unaligned_uint32(data + 2));
1105  }
1106  break;
1107  case IAX_IE_RR_OOO:
1108  if (len != (int)sizeof(unsigned int)) {
1109  snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
1110  errorf(tmp);
1111  } else {
1112  ies->rr_ooo = ntohl(get_unaligned_uint32(data + 2));
1113  }
1114  break;
1115  case IAX_IE_VARIABLE:
1116  ast_copy_string(tmp, (char *)data + 2, len + 1);
1117  tmp2 = strchr(tmp, '=');
1118  if (tmp2)
1119  *tmp2++ = '\0';
1120  else
1121  tmp2 = "";
1122  {
1123  struct ast_str *str = ast_str_create(16);
1124  /* Existing variable or new variable? */
1125  for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
1126  if (strcmp(tmp, var2->name) == 0) {
1127  ast_str_set(&str, 0, "%s%s", var2->value, tmp2);
1128  var = ast_variable_new(tmp, ast_str_buffer(str), var2->file);
1129  var->next = var2->next;
1130  if (prev) {
1131  prev->next = var;
1132  } else {
1133  ies->vars = var;
1134  }
1135  snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
1136  outputf(tmp);
1137  ast_free(var2);
1138  break;
1139  }
1140  }
1141  ast_free(str);
1142  }
1143 
1144  if (!var2) {
1145  var = ast_variable_new(tmp, tmp2, "");
1146  snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
1147  outputf(tmp);
1148  var->next = ies->vars;
1149  ies->vars = var;
1150  }
1151  break;
1152  case IAX_IE_OSPTOKEN:
1153  if ((count = data[2]) < IAX_MAX_OSPBLOCK_NUM) {
1154  ies->osptokenblock[count] = (char *)data + 2 + 1;
1155  ies->ospblocklength[count] = len - 1;
1156  } else {
1157  snprintf(tmp, (int)sizeof(tmp), "Expected OSP token block index to be 0~%d but was %u\n", IAX_MAX_OSPBLOCK_NUM - 1, count);
1158  errorf(tmp);
1159  }
1160  break;
1161  case IAX_IE_CALLTOKEN:
1162  if (len) {
1163  ies->calltokendata = (unsigned char *) data + 2;
1164  }
1165  ies->calltoken = 1;
1166  break;
1167  default:
1168  snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
1169  outputf(tmp);
1170  }
1171  /* Overwrite information element with 0, to null terminate previous portion */
1172  data[0] = 0;
1173  datalen -= (len + 2);
1174  data += (len + 2);
1175  }
1176  /* Null-terminate last field */
1177  *data = '\0';
1178  if (datalen) {
1179  errorf("Invalid information element contents, strange boundary\n");
1180  return -1;
1181  }
1182  return 0;
1183 }
1184 
1185 void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
1186 {
1187  fr->af.frametype = f->frametype;
1188  fr->af.subclass.format = f->subclass.format;
1189  fr->af.subclass.integer = f->subclass.integer;
1190  fr->af.mallocd = 0; /* Our frame is static relative to the container */
1191  fr->af.datalen = f->datalen;
1192  fr->af.samples = f->samples;
1194  fr->af.src = f->src;
1195  fr->af.delivery.tv_sec = 0;
1196  fr->af.delivery.tv_usec = 0;
1197  fr->af.data.ptr = fr->afdata;
1198  fr->af.len = f->len;
1199  if (fr->af.datalen) {
1200  size_t copy_len = fr->af.datalen;
1201  if (copy_len > fr->afdatalen) {
1202  ast_log(LOG_ERROR, "Losing frame data because destination buffer size '%d' bytes not big enough for '%d' bytes in the frame\n",
1203  (int) fr->afdatalen, (int) fr->af.datalen);
1204  copy_len = fr->afdatalen;
1205  }
1206 #if __BYTE_ORDER == __LITTLE_ENDIAN
1207  /* We need to byte-swap slinear samples from network byte order */
1208  if ((fr->af.frametype == AST_FRAME_VOICE) &&
1210  /* 2 bytes / sample for SLINEAR */
1211  ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2);
1212  } else
1213 #endif
1214  memcpy(fr->af.data.ptr, f->data.ptr, copy_len);
1215  }
1216 }
1217 
1218 struct iax_frame *iax_frame_new(int direction, int datalen, unsigned int cacheable)
1219 {
1220  struct iax_frame *fr;
1221 
1222 #if !defined(NO_FRAME_CACHE)
1223  if (cacheable) {
1224  struct iax_frames *iax_frames;
1225  struct iax_frame *smallest;
1226 
1227  /* Attempt to get a frame from this thread's cache */
1228  if ((iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
1229  smallest = AST_LIST_FIRST(&iax_frames->list);
1230  AST_LIST_TRAVERSE_SAFE_BEGIN(&iax_frames->list, fr, list) {
1231  if (fr->afdatalen >= datalen) {
1232  size_t afdatalen = fr->afdatalen;
1234  iax_frames->size--;
1235  memset(fr, 0, sizeof(*fr));
1236  fr->afdatalen = afdatalen;
1237  break;
1238  } else if (smallest->afdatalen > fr->afdatalen) {
1239  smallest = fr;
1240  }
1241  }
1243  if (!fr) {
1244  if (iax_frames->size >= FRAME_CACHE_MAX_SIZE && smallest) {
1245  /* Make useless cache into something more useful */
1246  AST_LIST_REMOVE(&iax_frames->list, smallest, list);
1247  iax_frames->size--;
1248  ast_free(smallest);
1249  }
1250  if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1251  return NULL;
1252  }
1253  fr->afdatalen = datalen;
1254  }
1255  } else {
1256  if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1257  return NULL;
1258  }
1259  fr->afdatalen = datalen;
1260  }
1261  fr->cacheable = 1;
1262  } else
1263 #endif
1264  {
1265  if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
1266  return NULL;
1267  }
1268  fr->afdatalen = datalen;
1269  }
1270 
1271 
1272  fr->direction = direction;
1273  fr->retrans = -1;
1274 
1275  if (fr->direction == DIRECTION_INGRESS)
1277  else
1279 
1281 
1282  return fr;
1283 }
1284 
1285 void iax_frame_free(struct iax_frame *fr)
1286 {
1287 #if !defined(NO_FRAME_CACHE)
1288  struct iax_frames *iax_frames = NULL;
1289 #endif
1290 
1291  /* Note: does not remove from scheduler! */
1292  if (fr->direction == DIRECTION_INGRESS)
1294  else if (fr->direction == DIRECTION_OUTGRESS)
1296  else {
1297  errorf("Attempt to double free frame detected\n");
1298  return;
1299  }
1301 
1302 #if !defined(NO_FRAME_CACHE)
1303  if (!fr->cacheable
1305  || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
1306  ast_free(fr);
1307  return;
1308  }
1309 
1310  if (iax_frames->size < FRAME_CACHE_MAX_SIZE) {
1311  fr->direction = 0;
1312  /* Pseudo-sort: keep smaller frames at the top of the list. This should
1313  * increase the chance that we pick the smallest applicable frame for use. */
1314  if (AST_LIST_FIRST(&iax_frames->list) && AST_LIST_FIRST(&iax_frames->list)->afdatalen < fr->afdatalen) {
1315  AST_LIST_INSERT_TAIL(&iax_frames->list, fr, list);
1316  } else {
1317  AST_LIST_INSERT_HEAD(&iax_frames->list, fr, list);
1318  }
1319  iax_frames->size++;
1320  return;
1321  }
1322 #endif
1323  ast_free(fr);
1324 }
1325 
1326 #if !defined(NO_FRAME_CACHE)
1327 static void frame_cache_cleanup(void *data)
1328 {
1329  struct iax_frames *framelist = data;
1330  struct iax_frame *current;
1331 
1332  while ((current = AST_LIST_REMOVE_HEAD(&framelist->list, list)))
1333  ast_free(current);
1334 
1335  ast_free(framelist);
1336 }
1337 #endif
1338 
1339 int iax_get_frames(void) { return frames; }
1340 int iax_get_iframes(void) { return iframes; }
1341 int iax_get_oframes(void) { return oframes; }
struct ast_variable * next
struct ast_frame af
Definition: parser.h:141
struct sockaddr_storage ss
Definition: netsock2.h:98
#define PROV_IE_FLAGS
Definition: provision.h:32
static void(* outputf)(const char *str)
Definition: parser.c:87
unsigned int fwdesc
Definition: parser.h:66
#define IAX_IE_IAX_UNKNOWN
Definition: iax2.h:153
static void dump_int(char *output, int maxlen, void *value, int len)
Definition: parser.c:149
static void dump_byte(char *output, int maxlen, void *value, int len)
Definition: parser.c:165
#define IAX_RATE_22KHZ
Definition: iax2.h:211
static void frame_cache_cleanup(void *data)
Definition: parser.c:1327
#define IAX_IE_CAPABILITY2
Definition: iax2.h:187
static struct ast_threadstorage frame_cache
Definition: parser.c:63
unsigned char csub
Definition: iax2.h:235
int calling_tns
Definition: parser.h:33
Asterisk locking-related definitions:
#define IAX_IE_CALLINGTNS
Definition: iax2.h:170
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
Definition: parser.c:779
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * serviceident
Definition: parser.h:64
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
#define IAX_IE_PROVVER
Definition: iax2.h:167
char * rsa_result
Definition: parser.h:50
This is just so iax_frames, a list head struct for holding a list of iax_frame structures, is defined.
Definition: parser.c:67
int iax_get_oframes(void)
Definition: parser.c:1341
char * md5_result
Definition: parser.h:49
#define IAX_RATE_44KHZ
Definition: iax2.h:212
Definition: ast_expr2.c:325
static int iframes
Definition: parser.c:52
static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
Definition: parser.c:363
unsigned short scallno
Definition: iax2.h:229
size_t afdatalen
Definition: parser.h:143
#define PROV_IE_USEDHCP
Definition: provision.h:21
static const struct iax2_ie prov_ies[]
Definition: parser.c:332
iax_frame_subclass
Definition: iax2.h:51
const char * iax_ie2str(int ie)
Definition: parser.c:352
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
unsigned int transferid
Definition: parser.h:61
#define PROV_IE_NEWAESKEY
Definition: provision.h:37
static void dump_samprate(char *output, int maxlen, void *value, int len)
Definition: parser.c:221
static void dump_prefs(char *output, int maxlen, void *value, int len)
Definition: parser.c:130
#define IAX_IE_VARIABLE
Definition: iax2.h:183
#define IAX_IE_RR_LOSS
Definition: iax2.h:178
struct iax_frame * iax_frame_new(int direction, int datalen, unsigned int cacheable)
Definition: parser.c:1218
const char * iax2_getformatname(iax2_format format)
iax2 wrapper function for ast_getformatname
Definition: chan_iax2.c:1903
unsigned char * fwdata
Definition: parser.h:67
#define IAX_IE_DATETIME
Definition: iax2.h:161
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
char * username
Definition: parser.h:36
unsigned char oseqno
Definition: iax2.h:232
unsigned int rr_dropped
Definition: parser.h:78
int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
Definition: parser.c:755
int calling_ton
Definition: parser.h:32
void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
Definition: parser.c:1185
static int tmp()
Definition: bt_open.c:389
socklen_t len
Definition: netsock2.h:99
static void dump_ies(unsigned char *iedata, int len)
Definition: parser.c:415
#define IAX_IE_CALLNO
Definition: iax2.h:151
#define IAX_RATE_48KHZ
Definition: iax2.h:213
Structure for variables, used for configurations and for channel variables.
iax2_format format
Definition: parser.h:39
void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len)
Definition: parser.c:462
#define IAX_IE_MD5_RESULT
Definition: iax2.h:146
static int oframes
Definition: parser.c:53
unsigned char * enckey
Definition: parser.h:69
#define var
Definition: ast_expr2f.c:614
#define IAX_IE_FIRMWAREVER
Definition: iax2.h:164
int firmwarever
Definition: parser.h:65
void ast_swapcopy_samples(void *dst, const void *src, int samples)
Definition: main/frame.c:396
unsigned char afdata[0]
Definition: parser.h:145
#define IAX_IE_RR_DELAY
Definition: iax2.h:180
#define IAX_IE_AUTOANSWER
Definition: iax2.h:155
static struct iax2_ie infoelts[]
Definition: parser.c:274
int iax_get_frames(void)
Definition: parser.c:1339
#define IAX_IE_SAMPLINGRATE
Definition: iax2.h:171
#define PROV_IE_USER
Definition: provision.h:26
unsigned int rr_loss
Definition: parser.h:75
unsigned int datetime
Definition: parser.h:62
Definition: parser.h:27
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
#define IAX_IE_CHALLENGE
Definition: iax2.h:145
unsigned int provver
Definition: parser.h:71
unsigned short dpstatus
Definition: parser.h:53
Definitions to aid in the use of thread local storage.
#define FRAME_CACHE_MAX_SIZE
Definition: parser.c:74
unsigned char fwdatalen
Definition: parser.h:68
int value
Definition: syslog.c:37
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855
#define IAX_IE_DPSTATUS
Definition: iax2.h:150
char * devicetype
Definition: parser.h:63
static void(* errorf)(const char *str)
Definition: parser.c:88
#define PROV_IE_SUBNET
Definition: provision.h:23
#define IAX_IE_LANGUAGE
Definition: iax2.h:140
char * calling_number
Definition: parser.h:29
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
Socket address structure.
Definition: netsock2.h:97
int tm_year
Definition: localtime.h:41
#define IAX_IE_RR_JITTER
Definition: iax2.h:177
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define IAX_IE_CALLING_NUMBER
Definition: iax2.h:132
int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
Definition: parser.c:774
Implementation of the IAX2 protocol.
struct ast_frame_subclass subclass
#define IAX_IE_CALLING_ANI
Definition: iax2.h:133
static void dump_string_hex(char *output, int maxlen, void *value, int len)
Definition: parser.c:111
Utility functions.
static void dump_ipaddr(char *output, int maxlen, void *value, int len)
Definition: parser.c:189
static void dump_addr(char *output, int maxlen, void *value, int len)
Definition: parser.c:90
unsigned char type
Definition: iax2.h:234
#define IAX_IE_DEVICETYPE
Definition: iax2.h:162
#define IAX_IE_ENCRYPTION
Definition: iax2.h:173
#define IAX_IE_ENCKEY
Definition: iax2.h:174
int msgcount
Definition: parser.h:58
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
unsigned short dcallno
Definition: iax2.h:230
Configuration File Parser.
char * called_context
Definition: parser.h:35
char * codec_prefs
Definition: parser.h:40
int iax_get_iframes(void)
Definition: parser.c:1340
char * challenge
Definition: parser.h:48
#define ast_log
Definition: astobj2.c:42
Handle unaligned data access.
int ie
Definition: parser.c:270
#define IAX_MAX_OSPBLOCK_NUM
Definition: iax2.h:191
unsigned int encmethods
Definition: parser.h:47
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct ast_sockaddr *addr)
Definition: parser.c:740
unsigned short callno
Definition: parser.h:54
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
int provverpres
Definition: parser.h:73
unsigned char * calltokendata
Definition: parser.h:84
#define IAX_IE_FORMAT2
Definition: iax2.h:188
unsigned char causecode
Definition: parser.h:56
static void dump_short(char *output, int maxlen, void *value, int len)
Definition: parser.c:157
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
const char * src
#define DIRECTION_OUTGRESS
Definition: parser.h:88
#define ast_opt_cache_media_frames
Definition: options.h:121
unsigned int cacheable
Definition: parser.h:123
#define DIRECTION_INGRESS
Definition: parser.h:87
#define IAX_IE_CAUSECODE
Definition: iax2.h:172
unsigned int rr_jitter
Definition: parser.h:74
#define IAX_IE_VERSION
Definition: iax2.h:141
#define PROV_IE_IPADDR
Definition: provision.h:22
static int frames
Definition: parser.c:51
unsigned char iax_unknown
Definition: parser.h:57
uint64_t htonll(uint64_t host64)
Definition: strcompat.c:390
#define PROV_IE_FORMAT
Definition: provision.h:33
char * osptokenblock[IAX_MAX_OSPBLOCK_NUM]
Definition: parser.h:81
#define IAX_IE_SERVICEIDENT
Definition: iax2.h:163
int tm_mon
Definition: localtime.h:40
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
Asterisk internal frame definitions.
void(* dump)(char *output, int maxlen, void *value, int len)
Definition: parser.c:272
#define IAX_IE_CALLING_NAME
Definition: iax2.h:134
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
Definition: parser.c:725
size_t size
Definition: parser.c:71
#define IAX_IE_PROVISIONING
Definition: iax2.h:159
#define IAX_IE_AESPROVISIONING
Definition: iax2.h:160
int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
Definition: parser.c:745
#define PROV_IE_SERVERPORT
Definition: provision.h:36
unsigned short adsicpe
Definition: parser.h:43
#define ast_variable_new(name, value, filename)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
int tm_mday
Definition: localtime.h:39
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
#define IAX_IE_DNID
Definition: iax2.h:143
static unsigned int get_unaligned_uint32(const void *p)
Definition: unaligned.h:38
Network socket handling.
int version
Definition: parser.h:42
static unsigned short get_unaligned_uint16(const void *p)
Definition: unaligned.h:44
unsigned int direction
Definition: parser.h:121
char * iax_provflags2str(char *buf, int buflen, unsigned int flags)
Definition: provision.c:90
#define IAX_IE_CALLTOKEN
Definition: iax2.h:185
unsigned int rr_ooo
Definition: parser.h:79
static void internalerror(const char *str)
Definition: parser.c:82
#define IAX_IE_CALLED_NUMBER
Definition: iax2.h:131
int pos
Definition: parser.h:150
IAX2 Provisioning protocol.
#define PROV_IE_AESKEY
Definition: provision.h:34
#define IAX_IE_ADSICPE
Definition: iax2.h:142
static void dump_versioned_codec(char *output, int maxlen, void *value, int len)
Definition: parser.c:248
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static void dump_prov_flags(char *output, int maxlen, void *value, int len)
Definition: parser.c:211
Implementation of Inter-Asterisk eXchange, version 2 iax2-parser::c iax2-parser.h chan_iax2...
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static void dump_prov(char *output, int maxlen, void *value, int len)
Definition: parser.c:264
Media Format Bitfield Compatibility API.
void * data
Definition: parser.h:103
int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size)
Dump audio codec preference list into a string.
Definition: codec_pref.c:178
int calling_pres
Definition: parser.h:34
#define IAX_IE_AUTHMETHODS
Definition: iax2.h:144
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * language
Definition: parser.h:41
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define IAX_IE_PASSWORD
Definition: iax2.h:137
char * rdnis
Definition: parser.h:45
void iax_frame_free(struct iax_frame *fr)
Definition: parser.c:1285
#define IAX_IE_MSGCOUNT
Definition: iax2.h:154
void iax_set_error(void(*func)(const char *))
Definition: parser.c:789
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define IAX_IE_FWBLOCKDESC
Definition: iax2.h:165
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
char * calling_name
Definition: parser.h:31
uint64_t ntohll(uint64_t net64)
Definition: strcompat.c:364
int retries
Definition: parser.h:107
static const char name[]
Definition: cdr_mysql.c:74
unsigned int authmethods
Definition: parser.h:46
#define IAX_IE_RR_OOO
Definition: iax2.h:182
#define ast_free(a)
Definition: astmm.h:182
int datalen
Definition: parser.h:105
unsigned char calltoken
Definition: parser.h:83
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static void put_unaligned_uint64(void *p, uint64_t datum)
Definition: unaligned.h:51
unsigned char iedata[0]
Definition: iax2.h:236
int autoanswer
Definition: parser.h:59
#define PROV_IE_PORTNO
Definition: provision.h:25
unsigned char iseqno
Definition: iax2.h:233
#define IAX_IE_CODEC_PREFS
Definition: iax2.h:175
char * called_number
Definition: parser.h:28
static void dump_datetime(char *output, int maxlen, void *value, int len)
Definition: parser.c:173
int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr)
Determine if this is an IPv4-mapped IPv6 address.
Definition: netsock2.c:507
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
int tm_hour
Definition: localtime.h:38
int retrans
Definition: parser.h:129
unsigned char buf[1024]
Definition: parser.h:149
#define IAX_IE_OSPTOKEN
Definition: iax2.h:184
unsigned char enckeylen
Definition: parser.h:70
struct timeval delivery
unsigned short rr_delay
Definition: parser.h:77
int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
Definition: parser.c:794
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
#define IAX_IE_CALLINGTON
Definition: iax2.h:169
int tm_sec
Definition: localtime.h:36
#define IAX_IE_REFRESH
Definition: iax2.h:149
struct ast_variable * vars
Definition: parser.h:80
#define IAX_IE_CALLINGPRES
Definition: iax2.h:168
#define PROV_IE_SERVERIP
Definition: provision.h:35
#define IAX_IE_RDNIS
Definition: iax2.h:158
int musiconhold
Definition: parser.h:60
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define IAX_IE_USERNAME
Definition: iax2.h:136
int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str)
Definition: parser.c:769
#define IAX_IE_RR_DROPPED
Definition: iax2.h:181
#define PROV_IE_GATEWAY
Definition: provision.h:24
struct ast_sockaddr apparent_addr
Definition: parser.h:51
unsigned int rr_pkts
Definition: parser.h:76
#define IAX_IE_MUSICONHOLD
Definition: iax2.h:156
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
#define IAX_IE_RR_PKTS
Definition: iax2.h:179
Data structure associated with a single frame of data.
#define IAX_FLAG_FULL
Definition: iax2.h:40
#define IAX_IE_CAUSE
Definition: iax2.h:152
#define IAX_IE_RSA_RESULT
Definition: iax2.h:147
unsigned int ospblocklength[IAX_MAX_OSPBLOCK_NUM]
Definition: parser.h:82
#define PROV_IE_ALTSERVER
Definition: provision.h:39
char * password
Definition: parser.h:37
char * name
Definition: parser.c:271
#define IAX_IE_FWBLOCKDATA
Definition: iax2.h:166
char * calling_ani
Definition: parser.h:30
#define IAX_IE_CALLED_CONTEXT
Definition: iax2.h:135
int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
Definition: parser.c:762
#define IAX_RATE_16KHZ
Definition: iax2.h:210
union ast_frame::@263 data
void iax_set_output(void(*func)(const char *))
Definition: parser.c:784
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
enum ast_frame_type frametype
#define IAX_IE_APPARENT_ADDR
Definition: iax2.h:148
struct iax_frame_list list
Definition: parser.c:70
iax2_format capability
Definition: parser.h:38
Media Format Bitfield Compatibility API.
#define PROV_IE_TOS
Definition: provision.h:31
struct ast_format * format
unsigned short refresh
Definition: parser.h:52
#define IAX_IE_TRANSFERID
Definition: iax2.h:157
char * cause
Definition: parser.h:55
#define IAX_IE_FORMAT
Definition: iax2.h:139
direction
void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right)
Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string...
Definition: codec_pref.c:44
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define IAX_FLAG_RETRANS
Definition: iax2.h:42
#define IAX_RATE_11KHZ
Definition: iax2.h:209
#define PROV_IE_PASS
Definition: provision.h:27
static void internaloutput(const char *str)
Definition: parser.c:77
void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct ast_sockaddr *addr, int datalen)
Definition: parser.c:594
static void dump_string(char *output, int maxlen, void *value, int len)
Definition: parser.c:121
#define IAX_IE_CAPABILITY
Definition: iax2.h:138
#define IAX_RATE_8KHZ
Definition: iax2.h:208
static uint64_t get_unaligned_uint64(const void *p)
Definition: unaligned.h:32
int tm_min
Definition: localtime.h:37
#define PROV_IE_LANG
Definition: provision.h:30
char * dnid
Definition: parser.h:44
int64_t iax2_format
Definition: iax2.h:222
unsigned short samprate
Definition: parser.h:72
Media Format Cache API.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
unsigned int ts
Definition: iax2.h:231
#define PROV_IE_PROVVER
Definition: provision.h:38