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