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