diff --git a/src/mod/endpoints/mod_iax/Makefile.am b/src/mod/endpoints/mod_iax/Makefile.am deleted file mode 100644 index 728c1aa29c..0000000000 --- a/src/mod/endpoints/mod_iax/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -include $(top_srcdir)/build/modmake.rulesam -MODNAME=mod_iax - -mod_LTLIBRARIES = mod_iax.la -mod_iax_la_SOURCES = mod_iax.c iax2-parser.c iax.c md5.c jitterbuf.c iax-mutex.c -mod_iax_la_CFLAGS = $(AM_CFLAGS) -I. -DNEWJB -DLIBIAX -DDEBUG_SUPPORT -mod_iax_la_LIBADD = $(switch_builddir)/libfreeswitch.la -mod_iax_la_LDFLAGS = -avoid-version -module -no-undefined -shared diff --git a/src/mod/endpoints/mod_iax/answer.h b/src/mod/endpoints/mod_iax/answer.h deleted file mode 100644 index 2a034204cf..0000000000 --- a/src/mod/endpoints/mod_iax/answer.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Signed 16-bit audio data - * - * Source: answer.raw - * - * Copyright (C) 1999, Mark Spencer and Linux Support Services - * - * Distributed under the terms of the GNU General Public License - * - */ - -static signed short answer[] = { -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 0x19b7, 0x0245, 0xeee5, 0xb875, 0xd9a4, 0x6018, 0x660a, 0xc3c6, -0x8741, 0xff55, 0x4c2e, 0x2146, 0xfed2, 0xf079, 0xcbd4, 0xe561, 0x3c41, 0x3166, -0xd425, 0xdc59, 0x2748, 0x087d, 0xc72b, 0xfe3a, 0x4681, 0x14c6, 0xcf45, 0xdd38, -0xf8dd, 0x0a39, 0x3a5a, 0x32b9, 0xbfec, 0x957f, 0x15a3, 0x70f4, 0x1d95, 0xbfc4, -0xd367, 0xfda0, 0x0dc0, 0x29eb, 0x1fc2, 0xd684, 0xcab1, 0x19c7, 0x29ef, 0xe679, -0xe9d0, 0x2b82, 0x151a, 0xca9f, 0xdb68, 0x1f4a, 0x271c, 0x0e2a, 0xfb32, 0xd1b2, -0xc8ff, 0x2382, 0x6380, 0x0a52, 0xa118, 0xccbf, 0x2ddc, 0x33fd, 0x0964, 0xf2a4, -0xdd81, 0xe092, 0x1a00, 0x325c, 0xf5e3, 0xd6a1, 0x0b6c, 0x1c75, 0xe4f8, 0xe07c, -0x2082, 0x2b3e, 0xf445, 0xdaa9, 0xea13, 0xff3c, 0x245c, 0x35c1, 0xf308, 0xab53, -0xdf59, 0x4698, 0x3f3b, 0xe7f7, 0xca84, 0xed4d, 0x0c3f, 0x1e94, 0x1c2d, 0xf06f, -0xd4df, 0xff34, 0x23d8, 0x001e, 0xe3f1, 0x0b15, 0x2113, 0xf3fd, 0xd768, 0xf9a0, -0x1d31, 0x1c6e, 0x0797, 0xe3a0, 0xce6c, 0xfd7b, 0x422a, 0x2c4c, 0xd364, 0xbf42, -0x0278, 0x303e, 0x1c51, 0xf737, 0xe25a, 0xe75f, 0x0a8f, 0x22ab, 0x05f4, 0xe3f9, -0xf8c4, 0x1705, 0x0162, 0xe49f, 0xfb8b, 0x1e2b, 0x13ac, 0xf044, 0xe07b, 0xf01a, -0x1567, 0x2cbf, 0x0b75, 0xd01b, 0xd206, 0x1563, 0x38d7, 0x0f2e, 0xdb32, 0xdc30, -0x023b, 0x1e44, 0x16eb, 0xf5f7, 0xe425, 0xfa33, 0x14d5, 0x0968, 0xeff2, 0xf762, -0x1137, 0x0e59, 0xf13a, 0xe651, 0xff41, 0x1d60, 0x18fd, 0xf1e6, 0xd75f, 0xf097, -0x20ec, 0x27fa, 0xfba4, 0xd5b8, 0xe68e, 0x1657, 0x2518, 0x04f6, 0xe5a3, 0xe976, -0x0578, 0x18fa, 0x0a92, 0xec0a, 0xef2a, 0x111f, 0x12f4, 0xeec3, 0xe95e, 0x0d3a, -0x18fd, 0xff72, 0xeefc, 0xf114, 0xfaaa, 0x14ee, 0x21db, 0xf56e, 0xcb49, 0xf621, -0x3323, 0x1947, 0xe017, 0xe7e9, 0x0819, 0x0707, 0x084c, 0x0f57, 0xf152, 0xdf92, -0x104a, 0x28eb, 0xedcc, 0xd4ad, 0x1415, 0x296d, 0xed9a, 0xdf57, 0x0cc2, 0x0d95, -0xf7b5, 0x0deb, 0x0b34, 0xd713, 0xea08, 0x38d6, 0x216d, 0xc727, 0xdc32, 0x2cd2, -0x1822, 0xe2d5, 0xfeb3, 0x106c, 0xe6e5, 0xf81e, 0x2fe8, 0x01af, 0xc180, 0x037a, -0x42d8, 0xf88d, 0xc344, 0x0a4f, 0x2c4e, 0xf19d, 0xebeb, 0x162c, 0xf9e9, 0xde93, -0x1b56, 0x2c60, 0xd8aa, 0xce3e, 0x2a41, 0x2eeb, 0xdab1, 0xde32, 0x1c32, 0x0aba, -0xeabe, 0x1008, 0x136d, 0xda2f, 0xec3b, 0x31dd, 0x1130, 0xca79, 0xf5b8, 0x3423, -0x0274, 0xd27d, 0x035e, 0x1e68, 0xf641, 0xf904, 0x1691, 0xef7d, 0xd57a, 0x1c3b, -0x3c23, 0xe881, 0xc274, 0x0af5, 0x2962, 0xfa34, 0xf676, 0x0f71, 0xefcc, 0xe01f, -0x19e7, 0x276f, 0xe694, 0xe134, 0x1c3a, 0x0e8b, 0xd8e7, 0xfa81, 0x2f8b, 0x07c5, -0xd904, 0xf6fa, 0x0ca5, 0xf9a2, 0x0dc7, 0x2623, 0xec54, 0xbe23, 0x02b6, 0x4296, -0x10cd, 0xda61, 0xf11c, 0x0103, 0xf41c, 0x10b4, 0x2a03, 0xf63c, 0xce1a, 0xfdbd, -0x1fb4, 0xfc51, 0xf727, 0x1c8a, 0x04ff, 0xcf41, 0xec05, 0x2913, 0x1ce8, 0xf70c, -0xf744, 0xede8, 0xdd77, 0x0d99, 0x43f1, 0x119c, 0xc14f, 0xd60e, 0x17cb, 0x1e19, -0x0d4e, 0x0c95, 0xeed1, 0xcdf4, 0xf7a5, 0x331f, 0x1cd0, 0xeb17, 0xf082, 0xfb19, -0xe899, 0xfdeb, 0x323c, 0x2036, 0xdad3, 0xd134, 0xfd03, 0x1345, 0x1c10, 0x2239, -0xf656, 0xbc22, 0xdc3f, 0x3392, 0x3d59, 0xfd77, 0xdb4d, 0xe23f, 0xedbe, 0x0f7e, -0x35cc, 0x1947, 0xd5dc, 0xd1bf, 0x035d, 0x16fc, 0x1174, 0x1675, 0x0249, 0xd2d4, -0xd851, 0x184d, 0x32fe, 0x0f91, 0xee14, 0xe1e6, 0xdf9b, 0x016b, 0x3668, 0x2b2b, -0xe20c, 0xc554, 0xf257, 0x1c05, 0x1fc5, 0x14f0, 0xf891, 0xd41c, 0xdf83, 0x1865, -0x2de1, 0x0b16, 0xed58, 0xea0c, 0xea79, 0xfbd9, 0x22af, 0x2732, 0xf62f, 0xd389, -0xe7d9, 0x0b39, 0x1cdc, 0x1de3, 0x038a, 0xd809, 0xd5f7, 0x0b55, 0x305e, 0x1910, -0xf02e, 0xe089, 0xe7c7, 0x0195, 0x2265, 0x21da, 0xf743, 0xd8f2, 0xe978, 0x09a1, -0x190a, 0x17c5, 0x045a, 0xe46d, 0xdd06, 0xffb2, 0x2293, 0x1cfe, 0xfd4d, 0xe4f9, -0xe310, 0xfaf1, 0x1d22, 0x2376, 0x0113, 0xde3a, 0xe21b, 0x0204, 0x1ba1, 0x1bd6, -0x0333, 0xe563, 0xe104, 0xfd51, 0x1bc1, 0x1ccf, 0x0285, 0xe757, 0xe35e, 0xfaf2, -0x185d, 0x1d46, 0x06b7, 0xec13, 0xe108, 0xef6e, 0x121d, 0x2a17, 0x16a6, 0xe32c, -0xc9a9, 0xf070, 0x2f48, 0x3788, 0xfa4e, 0xc32a, 0xd9c2, 0x1fa1, 0x36fe, 0x07fa, -0xd9e4, 0xe577, 0x0e5e, 0x1755, 0xfb53, 0xed71, 0x0540, 0x19e0, 0x0301, 0xdc97, -0xe391, 0x1937, 0x367c, 0x0bc9, 0xca4c, 0xc96b, 0x105d, 0x461f, 0x2416, 0xd481, -0xbc97, 0xf8b7, 0x39af, 0x2ec9, 0xecc6, 0xcb50, 0xeee3, 0x1ffe, 0x1e8e, 0xf700, -0xe66a, 0xff58, 0x149f, 0x02e5, 0xe792, 0xf2d8, 0x1a4d, 0x225a, 0xf642, 0xce7f, -0xe6a6, 0x25e2, 0x38f5, 0x01d0, 0xc50f, 0xd243, 0x19bd, 0x3fc6, 0x14f0, 0xd2d7, -0xcdb6, 0x069a, 0x2ffe, 0x1847, 0xe6f8, 0xdf0a, 0x0337, 0x1a90, 0x067a, 0xeb5b, -0xf541, 0x143b, 0x14f2, 0xf092, 0xdc02, 0xfb91, 0x28a3, 0x2274, 0xeaa8, 0xc9e7, -0xef48, 0x2d01, 0x322e, 0xf6d2, 0xc7cb, 0xe13b, 0x1fda, 0x3217, 0x0458, 0xd690, -0xe2bf, 0x11c4, 0x21d5, 0x0291, 0xe5c8, 0xf3a9, 0x12ba, 0x11aa, 0xf22b, 0xe627, -0x03ec, 0x219a, 0x1036, 0xe2f2, 0xd93f, 0x059c, 0x2ed6, 0x1b75, 0xe227, 0xce55, -0xfb19, 0x2de0, 0x2477, 0xed08, 0xd148, 0xf307, 0x21d4, 0x2002, 0xf543, 0xdeac, -0xf7f9, 0x18a9, 0x11d6, 0xf0ef, 0xe8e4, 0x05ea, 0x1ba5, 0x0727, 0xe448, 0xe748, -0x100e, 0x265e, 0x07fc, 0xdbae, 0xde78, 0x0efa, 0x2ce0, 0x0f94, 0xddf1, 0xd9ea, -0x0797, 0x28f6, 0x12eb, 0xe60c, 0xdf46, 0x0469, 0x1fbb, 0x0ced, 0xe9f6, 0xe95f, -0x09fe, 0x1ab9, 0x02cb, 0xe5a4, 0xef2a, 0x1327, 0x1d7b, 0xfd07, 0xde3d, 0xed9c, -0x17e5, 0x22e7, 0xfe3a, 0xdb38, 0xe9b9, 0x161a, 0x2416, 0x0175, 0xde3d, 0xe9de, -0x1294, 0x1fc9, 0x00ea, 0xe2a7, 0xeee2, 0x1298, 0x1a7d, 0xfc1d, 0xe3bb, 0xf47a, -0x1642, 0x185e, 0xf727, 0xe1af, 0xf709, 0x19c3, 0x18e7, 0xf50d, 0xe010, 0xf75b, -0x1a9c, 0x18d8, 0xf4c5, 0xe0c9, 0xf865, 0x1a1c, 0x16d5, 0xf3a6, 0xe257, 0xfaf2, -0x1a44, 0x14d5, 0xf34f, 0xe4b6, 0xfc77, 0x17d5, 0x0ff8, 0xf133, 0xe8b7, 0x0344, -0x1a37, 0x0ad5, 0xe95e, 0xe61a, 0x08a5, 0x227e, 0x0e33, 0xe4a7, 0xdd70, 0x03b0, -0x25f4, 0x17b2, 0xec0a, 0xdb4e, 0xf898, 0x1ba3, 0x18f6, 0xf973, 0xe87f, 0xf77a, -0x0b93, 0x096c, 0xfb0e, 0xfb03, 0x0896, 0x0940, 0xf51d, 0xe904, 0xfdc7, 0x1dda, -0x1bf9, 0xf29b, 0xd37f, 0xea1b, 0x1f37, 0x3175, 0x07eb, 0xd3f7, 0xd46b, 0x077d, -0x2eeb, 0x1e67, 0xeeae, 0xd8c7, 0xef85, 0x1119, 0x18d3, 0x088e, 0xf953, 0xf5ad, -0xf556, 0xf63d, 0x0234, 0x167a, 0x19a1, 0xfbf9, 0xd873, 0xdd4b, 0x0f06, 0x3748, -0x21e6, 0xe181, 0xc032, 0xe79a, 0x2bec, 0x3e76, 0x0b1b, 0xce41, 0xcb23, 0xff96, -0x2d79, 0x26d1, 0xfcc7, 0xdf8a, 0xe525, 0xfd83, 0x10f1, 0x16d7, 0x0f50, 0xfaea, -0xe3f1, 0xe20f, 0x0158, 0x27d9, 0x2866, 0xf96f, 0xcb34, 0xd563, 0x11d6, 0x3d25, -0x2424, 0xe254, 0xc2c9, 0xe7cd, 0x248d, 0x34f5, 0x0c42, 0xdcd0, 0xd827, 0xfa65, -0x19eb, 0x1b50, 0x0721, 0xf396, 0xeb9c, 0xefde, 0x0016, 0x1594, 0x1cc1, 0x0658, -0xe22b, 0xd852, 0xfb3e, 0x2923, 0x2c78, 0xfc87, 0xcdb5, 0xd69c, 0x0e3c, 0x3527, -0x201f, 0xe993, 0xcf9e, 0xeb21, 0x183f, 0x25ea, 0x0c93, 0xed4d, 0xe5f9, 0xf548, -0x07fb, 0x117c, 0x0ff2, 0x0398, 0xf08c, 0xe628, 0xf489, 0x143b, 0x2419, 0x0ccf, -0xe2cc, 0xd5a6, 0xf861, 0x2615, 0x2a1b, 0xfeb4, 0xd543, 0xdc53, 0x09b4, 0x2901, -0x19ff, 0xf24a, 0xde86, 0xeec4, 0x0b7b, 0x1733, 0x0d0a, 0xfc24, 0xf1bb, 0xf110, -0xfa03, 0x0a0f, 0x15d4, 0x0e21, 0xf435, 0xe17e, 0xee90, 0x1225, 0x2527, 0x0efa, -0xe61f, 0xd916, 0xf7b8, 0x1f50, 0x2326, 0x0099, 0xe01e, 0xe473, 0x0491, 0x1b37, -0x1360, 0xfb17, 0xecd9, 0xf20d, 0x0051, 0x0aec, 0x0d4a, 0x073d, 0xfa5a, 0xeeb8, -0xf165, 0x0516, 0x17dc, 0x12da, 0xf71b, 0xe213, 0xed85, 0x0eef, 0x20c8, 0x0e09, -0xebcc, 0xe0d4, 0xf848, 0x1637, 0x19d6, 0x026b, 0xec09, 0xed00, 0xff9b, 0x0e5a, -0x0d6b, 0x026c, 0xf865, 0xf4da, 0xf888, 0x025a, 0x0cbb, 0x0d53, 0xff96, 0xeefa, -0xee80, 0x021c, 0x15d6, 0x126a, 0xf9c1, 0xe724, 0xf017, 0x0aa1, 0x18b6, 0x0b4e, -0xf2d7, 0xea91, 0xf957, 0x0cac, 0x1061, 0x03f4, 0xf6ad, 0xf476, 0xfbdf, 0x0489, -0x08b1, 0x06df, 0xffcf, 0xf766, 0xf537, 0xfddf, 0x0ad4, 0x0e15, 0x01da, 0xf205, -0xf0a0, 0x0082, 0x1066, 0x0e41, 0xfc71, 0xef1b, 0xf4ad, 0x05cd, 0x0f32, 0x07ed, -0xf9c8, 0xf401, 0xfa93, 0x04af, 0x088c, 0x04a7, 0xfe15, 0xf9f1, 0xfa64, 0xff1e, -0x0539, 0x078c, 0x02af, 0xfa1a, 0xf69d, 0xfd09, 0x075b, 0x0a3d, 0x01f2, 0xf761, -0xf642, 0xffa7, 0x08f3, 0x0830, 0xff05, 0xf7db, 0xf9bc, 0x0174, 0x068b, 0x04b2, -0xfeff, 0xfb39, 0xfc1a, 000000, 0x0371, 0x03d7, 0x00fe, 0xfd37, 0xfbe0, 0xfe78, -0x02af, 0x044a, 0x0180, 0xfd43, 0xfc00, 0xfed1, 0x02aa, 0x0346, 0x00dd, 0xfde0, -0xfbfe, 0x0114, 0x0987, 0x04bc, 0xf49d, 0xf23a, 0x06ab, 0x162e, 0x0544, 0xe76b, -0xea25, 0x1015, 0x2474, 0x0431, 0xd7d3, 0xe1ec, 0x1923, 0x2df5, 0x01cd, 0xd386, -0xe3d9, 0x1b9d, 0x2c62, 0xfeb8, 0xd31a, 0xe6ba, 0x1dbd, 0x2abb, 0xfbab, 0xd2ed, -0xe9ab, 0x1fa7, 0x28ef, 0xf8b3, 0xd2f5, 0xeca5, 0x2160, 0x26fd, 0xf5d7, 0xd334, -0xefa1, 0x22e5, 0x24ea, 0xf31b, 0xd3a9, 0xf29f, 0x2435, 0x22b6, 0xf07e, 0xd44e, -0xf59b, 0x2551, 0x2067, 0xee08, 0xd527, 0xf88e, 0x2639, 0x1e00, 0xebb6, 0xd62d, -0xfb77, 0x26eb, 0x1b85, 0xe98b, 0xd75f, 0xfe51, 0x276b, 0x18f9, 0xe78e, 0xd8b9, -0x011a, 0x27b6, 0x1660, 0xe5bb, 0xda3a, 0x03cc, 0x27cf, 0x13bd, 0xe415, 0xdbdf, -0x066a, 0x27b7, 0x1117, 0xe29e, 0xdda5, 0x08ec, 0x276e, 0x0e6d, 0xe154, 0xdf89, -0x0b52, 0x26f6, 0x0bc7, 0xe039, 0xe185, 0x0d96, 0x2653, 0x0924, 0xdf4e, 0xe399, -0x0fb9, 0x2584, 0x068b, 0xde93, 0xe5c0, 0x11b8, 0x248e, 0x03fd, 0xde08, 0xe7f8, -0x1390, 0x2372, 0x0180, 0xddaa, 0xea3c, 0x1544, 0x2231, 0xff12, 0xdd7a, 0xec89, -0x16cf, 0x20d0, 0xfcb9, 0xdd77, 0xeedb, 0x1831, 0x1f52, 0xfa77, 0xdd9f, 0xf132, -0x1969, 0x1db7, 0xf850, 0xddf1, 0xf385, 0x1a75, 0x1c06, 0xf645, 0xde6b, 0xf5d7, -0x1b5b, 0x1a3f, 0xf457, 0xdf0d, 0xf820, 0x1c13, 0x1867, 0xf288, 0xdfd2, 0xfa5f, -0x1ca1, 0x167f, 0xf0db, 0xe0ba, 0xfc92, 0x1d06, 0x148b, 0xef50, 0xe1c1, 0xfeb5, -0x1d43, 0x1290, 0xede9, 0xe2e6, 0x00c6, 0x1d58, 0x108e, 0xeca7, 0xe426, 0x02c4, -0x1d45, 0x0e8a, 0xeb8a, 0xe57f, 0x04a9, 0x1d0e, 0x0c87, 0xea92, 0xe6ec, 0x0677, -0x1cb2, 0x0a87, 0xe9be, 0xe86e, 0x082a, 0x1c34, 0x088b, 0xe912, 0xe9fe, 0x09c1, -0x1b95, 0x069c, 0xe88c, 0xeb9c, 0x0b3a, 0x1ad9, 0x04b6, 0xe82a, 0xed43, 0x0c96, -0x1a00, 0x02df, 0xe7eb, 0xeef3, 0x0dd0, 0x190d, 0x0116, 0xe7d0, 0xf0a8, 0x0eec, -0x1804, 0xff61, 0xe7d8, 0xf25d, 0x0fe6, 0x16e3, 0xfdc0, 0xe800, 0xf412, 0x10bf, -0x15b1, 0xfc36, 0xe848, 0xf5c5, 0x1176, 0x146e, 0xfac2, 0xe8ad, 0xf771, 0x120d, -0x1320, 0xf969, 0xe92e, 0xf913, 0x1282, 0x11c4, 0xf828, 0xe9cb, 0xfaac, 0x12d8, -0x1062, 0xf703, 0xea7e, 0xfc38, 0x130e, 0x0efa, 0xf5fb, 0xeb49, 0xfdb5, 0x1325, -0x0d8e, 0xf50e, 0xec26, 0xff20, 0x131e, 0x0c21, 0xf43f, 0xed15, 0x007a, 0x12fa, -0x0ab6, 0xf38d, 0xee15, 0x01be, 0x12bd, 0x094f, 0xf2f9, 0xef22, 0x02ef, 0x1265, -0x07f0, 0xf283, 0xf037, 0x0408, 0x11f6, 0x0699, 0xf226, 0xf156, 0x050a, 0x1170, -0x054b, 0xf1e8, 0xf27a, 0x05f4, 0x10d8, 0x040c, 0xf1c5, 0xf3a3, 0x06c2, 0x102c, -0x02da, 0xf1bc, 0xf4cc, 0x0779, 0x0f71, 0x01b7, 0xf1cc, 0xf5f5, 0x0815, 0x0ea7, -0x00a8, 0xf1f4, 0xf719, 0x0899, 0x0dd2, 0xffab, 0xf233, 0xf839, 0x0902, 0x0cf4, -0xfec0, 0xf288, 0xf950, 0x0952, 0x0c0e, 0xfdec, 0xf2ee, 0xfa5d, 0x0989, 0x0b23, -0xfd2d, 0xf368, 0xfb62, 0x09a7, 0x0a35, 0xfc85, 0xf3f1, 0xfc58, 0x09af, 0x0946, -0xfbf2, 0xf488, 0xfd3f, 0x09a1, 0x0859, 0xfb77, 0xf52c, 0xfe17, 0x097d, 0x076f, -0xfb14, 0xf5d8, 0xfede, 0x0945, 0x068a, 0xfac6, 0xf68d, 0xff93, 0x08fb, 0x05ad, -0xfa8e, 0xf747, 0x0034, 0x08a1, 0x04da, 0xfa6f, 0xf805, 0x00c2, 0x0836, 0x0410, -0xfa63, 0xf8c6, 0x013c, 0x07bf, 0x0354, 0xfa6c, 0xf985, 0x01a1, 0x073b, 0x02a4, -0xfa8a, 0xfa43, 0x01f1, 0x06af, 0x0204, 0xfab9, 0xfafc, 0x022c, 0x0619, 0x0175, -0xfafa, 0xfbae, 0x0252, 0x057f, 0x00f6, 0xfb4b, 0xfc5a, 0x0263, 0x04e0, 0x008b, -0xfbaa, 0xfcfa, 0x0262, 0x0440, 0x0032, 0xfc16, 0xfd90, 0x024b, 0x03a0, 0xffec, -0xfc8c, 0xfe19, 0x0225, 0x0301, 0xffb9, 0xfd0c, 0xfe93, 0x01ea, 0x0267, 0xff9c, -0xfd95, 0xfefe, 0x01a0, 0x01d3, 0xff90, 0xfe22, 0xff5a, 0x0147, 0x0145, 0xff99, -0xfeb3, 0xffa1, 0x00e0, 0x00c3, 0xffb6, 0xff46, 0xffd9, 0x006d, 0x004b, 0xffe5, -0xffda, 0xfffc, 000000, 0xfffe, 000000, 0xffff, 000000, 0xffff, 0xffff, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, -000000 }; diff --git a/src/mod/endpoints/mod_iax/frame.h b/src/mod/endpoints/mod_iax/frame.h deleted file mode 100644 index cd6e28f7ef..0000000000 --- a/src/mod/endpoints/mod_iax/frame.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * libiax: An implementation of the Inter-Asterisk eXchange protocol - * - * Asterisk internal frame definitions. - * - * Copyright (C) 1999, Mark Spencer - * - * Mark Spencer - * - * This program is free software, distributed under the terms of - * the GNU Lesser General Public License. Other components of - * Asterisk are distributed under The GNU General Public License - * only. - */ - -#ifndef _LIBIAX_FRAME_H -#define _LIBIAX_FRAME_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -/* Frame types */ -#define AST_FRAME_DTMF 1 /* A DTMF digit, subclass is the digit */ -#define AST_FRAME_VOICE 2 /* Voice data, subclass is AST_FORMAT_* */ -#define AST_FRAME_VIDEO 3 /* Video frame, maybe?? :) */ -#define AST_FRAME_CONTROL 4 /* A control frame, subclass is AST_CONTROL_* */ -#define AST_FRAME_NULL 5 /* An empty, useless frame */ -#define AST_FRAME_IAX 6 /* Inter Aterisk Exchange private frame type */ -#define AST_FRAME_TEXT 7 /* Text messages */ -#define AST_FRAME_IMAGE 8 /* Image Frames */ -#define AST_FRAME_HTML 9 /* HTML Frames */ -#define AST_FRAME_CNG 10 /* Comfort Noise frame (subclass is level of CNG in -dBov) */ - -/* HTML subclasses */ -#define AST_HTML_URL 1 /* Sending a URL */ -#define AST_HTML_DATA 2 /* Data frame */ -#define AST_HTML_BEGIN 4 /* Beginning frame */ -#define AST_HTML_END 8 /* End frame */ -#define AST_HTML_LDCOMPLETE 16 /* Load is complete */ -#define AST_HTML_NOSUPPORT 17 /* Peer is unable to support HTML */ -#define AST_HTML_LINKURL 18 /* Send URL and track */ -#define AST_HTML_UNLINK 19 /* Request no more linkage */ -#define AST_HTML_LINKREJECT 20 /* Reject LINKURL */ - -/* Data formats for capabilities and frames alike */ -/*! G.723.1 compression */ -#define AST_FORMAT_G723_1 (1 << 0) - /*! GSM compression */ -#define AST_FORMAT_GSM (1 << 1) - /*! Raw mu-law data (G.711) */ -#define AST_FORMAT_ULAW (1 << 2) - /*! Raw A-law data (G.711) */ -#define AST_FORMAT_ALAW (1 << 3) - /*! ADPCM (G.726, 32kbps) */ -#define AST_FORMAT_G726 (1 << 4) - /*! ADPCM (IMA) */ -#define AST_FORMAT_ADPCM (1 << 5) - /*! Raw 16-bit Signed Linear (8000 Hz) PCM */ -#define AST_FORMAT_SLINEAR (1 << 6) - /*! LPC10, 180 samples/frame */ -#define AST_FORMAT_LPC10 (1 << 7) - /*! G.729A audio */ -#define AST_FORMAT_G729A (1 << 8) - /*! SpeeX Free Compression */ -#define AST_FORMAT_SPEEX (1 << 9) - /*! iLBC Free Compression */ -#define AST_FORMAT_ILBC (1 << 10) - /*! Maximum audio format */ -#define AST_FORMAT_MAX_AUDIO (1 << 15) - /*! JPEG Images */ -#define AST_FORMAT_JPEG (1 << 16) - /*! PNG Images */ -#define AST_FORMAT_PNG (1 << 17) - /*! H.261 Video */ -#define AST_FORMAT_H261 (1 << 18) - /*! H.263 Video */ -#define AST_FORMAT_H263 (1 << 19) - /*! Max one */ -#define AST_FORMAT_MAX_VIDEO (1 << 24) - -/* Control frame types */ -#define AST_CONTROL_HANGUP 1 /* Other end has hungup */ -#define AST_CONTROL_RING 2 /* Local ring */ -#define AST_CONTROL_RINGING 3 /* Remote end is ringing */ -#define AST_CONTROL_ANSWER 4 /* Remote end has answered */ -#define AST_CONTROL_BUSY 5 /* Remote end is busy */ -#define AST_CONTROL_TAKEOFFHOOK 6 /* Make it go off hook */ -#define AST_CONTROL_OFFHOOK 7 /* Line is off hook */ -#define AST_CONTROL_CONGESTION 8 /* Congestion (circuits busy) */ -#define AST_CONTROL_FLASH 9 /* Flash hook */ -#define AST_CONTROL_WINK 10 /* Wink */ -#define AST_CONTROL_OPTION 11 /* Set an option */ - -#define AST_FRIENDLY_OFFSET 64 /* Reserved header space */ - -struct ast_frame { - /*! Kind of frame */ - int frametype; - /*! Subclass, frame dependent */ - int subclass; - /*! Length of data */ - int datalen; - /*! Number of 8khz samples in this frame */ - int samples; - /*! Was the data malloc'd? i.e. should we free it when we discard the f -rame? */ - int mallocd; - /*! How far into "data" the data really starts */ - int offset; - /*! Optional source of frame for debugging */ - char *src; - /*! Pointer to actual data */ - void *data; - /*! Next/Prev for linking stand alone frames */ - struct ast_frame *prev; - /*! Next/Prev for linking stand alone frames */ - struct ast_frame *next; - /* Unused except - if debugging is turned on, but left - in the struct - so that it can be turned on without - requiring a r -ecompile of the whole thing */ -}; - - - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - - -#endif diff --git a/src/mod/endpoints/mod_iax/iax-client.h b/src/mod/endpoints/mod_iax/iax-client.h deleted file mode 100644 index e2cce789eb..0000000000 --- a/src/mod/endpoints/mod_iax/iax-client.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Asterisk -- A telephony toolkit for Linux. - * - * Implementation of Inter-Asterisk eXchange - * - * Copyright (C) 1999, Mark Spencer - * - * Mark Spencer - * - * This program is free software, distributed under the terms of - * the GNU Lesser General Public License (LGPL) - */ - -#ifndef _ASTERISK_IAX_CLIENT_H -#define _ASTERISK_IAX_CLIENT_H - -#ifdef WIN32_TIME_GET_TIME -#include -#endif - -#if defined(_MSC_VER) -/* disable zero-sized array in struct/union warning */ -#pragma warning(disable:4200) -#endif - -#if !defined(LINUX) && !defined(__NetBSD__) -#define socklen_t int -#endif - -#include "frame.h" -#include "iax2.h" -#include "iax2-parser.h" - -#define MAXSTRLEN 80 - -#define IAX_AUTHMETHOD_PLAINTEXT IAX_AUTH_PLAINTEXT -#define IAX_AUTHMETHOD_MD5 IAX_AUTH_MD5 - -extern char iax_errstr[]; - -struct iax_session; - - -#define IAX_EVENT_CONNECT 0 /* Connect a new call */ -#define IAX_EVENT_ACCEPT 1 /* Accept a call */ -#define IAX_EVENT_HANGUP 2 /* Hang up a call */ -#define IAX_EVENT_REJECT 3 /* Rejected call */ -#define IAX_EVENT_VOICE 4 /* Voice Data */ -#define IAX_EVENT_DTMF 5 /* A DTMF Tone */ -#define IAX_EVENT_TIMEOUT 6 /* Connection timeout... session will be - a pointer to free()'d memory! */ -#define IAX_EVENT_LAGRQ 7 /* Lag request -- Internal use only */ -#define IAX_EVENT_LAGRP 8 /* Lag Measurement. See event.lag */ -#define IAX_EVENT_RINGA 9 /* Announce we/they are ringing */ -#define IAX_EVENT_PING 10 /* Ping -- internal use only */ -#define IAX_EVENT_PONG 11 /* Pong -- internal use only */ -#define IAX_EVENT_BUSY 12 /* Report a line busy */ -#define IAX_EVENT_ANSWER 13 /* Answer the line */ - -#define IAX_EVENT_IMAGE 14 /* Send/Receive an image */ -#define IAX_EVENT_AUTHRQ 15 /* Authentication request */ -#define IAX_EVENT_AUTHRP 16 /* Authentication reply */ - -#define IAX_EVENT_REGREQ 17 /* Registration request */ -#define IAX_EVENT_REGACK 18 /* Registration reply */ -#define IAX_EVENT_URL 19 /* URL received */ -#define IAX_EVENT_LDCOMPLETE 20 /* URL loading complete */ - -#define IAX_EVENT_TRANSFER 21 /* Transfer has taken place */ - -#define IAX_EVENT_DPREQ 22 /* Dialplan request */ -#define IAX_EVENT_DPREP 23 /* Dialplan reply */ -#define IAX_EVENT_DIAL 24 /* Dial on a TBD call */ - -#define IAX_EVENT_QUELCH 25 /* Quelch Audio */ -#define IAX_EVENT_UNQUELCH 26 /* Unquelch Audio */ - -#define IAX_EVENT_UNLINK 27 /* Unlink */ -#define IAX_EVENT_LINKREJECT 28 /* Link Rejection */ -#define IAX_EVENT_TEXT 29 /* Text Frame :-) */ -#define IAX_EVENT_REGREJ 30 /* Registration reply */ -#define IAX_EVENT_LINKURL 31 /* Unlink */ -#define IAX_EVENT_CNG 32 /* Comfort-noise (almost silence) */ -#define IAX_EVENT_POKE 33 - -/* moved from iax.c to support attended transfer */ -#define IAX_EVENT_REREQUEST 999 -#define IAX_EVENT_TXREPLY 1000 -#define IAX_EVENT_TXREJECT 1001 -#define IAX_EVENT_TXACCEPT 1002 -#define IAX_EVENT_TXREADY 1003 - -#define IAX_SCHEDULE_FUZZ 0 /* ms of fuzz to drop */ - -#ifdef WIN32 -#if defined(_MSC_VER) -typedef int (__stdcall *sendto_t)(SOCKET, const char *, int, int, const struct sockaddr *, int); -typedef int (__stdcall *recvfrom_t)(SOCKET, char *, int, int, struct sockaddr *, int *); -#else -typedef int PASCAL (*sendto_t)(SOCKET, const char *, int, int, const struct sockaddr *, int); -typedef int PASCAL (*recvfrom_t)(SOCKET, char *buf, int len, int flags, struct sockaddr *from, int *fromlen); -#endif -#else -typedef int (*sendto_t)(int, const void *, size_t, int, const struct sockaddr *, socklen_t); -typedef int (*recvfrom_t)(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); -#endif - -struct iax_event { - int etype; /* Type of event */ - int subclass; /* Subclass data (event specific) */ - time_in_ms_t ts; /* Timestamp */ - struct iax_session *session; /* Applicable session */ - int datalen; /* Length of raw data */ - struct iax_ies ies; /* IE's for IAX2 frames */ - unsigned char data[]; /* Raw data if applicable */ -}; - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* All functions return 0 on success and -1 on failure unless otherwise - specified */ - -/* Called to initialize IAX structures and sockets. Returns actual - portnumber (which it will try preferred portno first, but if not - take what it can get */ -extern int iax_init(char *ip, int preferredportno); - -extern int iax_shutdown(void); - -/* Get filedescriptor for IAX to use with select or gtk_input_add */ -extern int iax_get_fd(void); - -/* Find out how many milliseconds until the next scheduled event */ -extern time_in_ms_t iax_time_to_next_event(void); - -/* Generate a new IAX session */ -extern struct iax_session *iax_session_new(void); - -/* Return exactly one iax event (if there is one pending). If blocking is - non-zero, IAX will block until some event is received */ -extern struct iax_event *iax_get_event(int blocking); - - -extern int iax_auth_reply(struct iax_session *session, char *password, - char *challenge, int methods); - -/* Free an event */ -extern void iax_event_free(struct iax_event *event); - -struct sockaddr_in; - -/* Front ends for sending events */ -extern int iax_send_dtmf(struct iax_session *session, char digit); -extern int iax_send_voice(struct iax_session *session, int format, unsigned char *data, int datalen, int samples); -extern int iax_send_cng(struct iax_session *session, int level, unsigned char *data, int datalen); -extern int iax_send_image(struct iax_session *session, int format, unsigned char *data, int datalen); -extern int iax_send_url(struct iax_session *session, char *url, int link); -extern int iax_send_text(struct iax_session *session, char *text); -extern int iax_send_ping(struct iax_session *session); -extern int iax_load_complete(struct iax_session *session); -extern int iax_reject(struct iax_session *session, const char *reason); -int iax_reject_registration(struct iax_session *session, char *reason); -int iax_ack_registration(struct iax_session *session); -int iax_auth_registration(struct iax_session *session); -extern int iax_busy(struct iax_session *session); -extern int iax_congestion(struct iax_session *session); -extern int iax_hangup(struct iax_session *session, char *byemsg); -extern int iax_call(struct iax_session *session, const char *cidnum, const char *cidname, char *ich, char *lang, int wait, int format, int capability); -extern int iax_accept(struct iax_session *session, int format); -extern int iax_answer(struct iax_session *session); -extern int iax_sendurl(struct iax_session *session, char *url); -extern int iax_send_unlink(struct iax_session *session); -extern int iax_send_link_reject(struct iax_session *session); -extern int iax_ring_announce(struct iax_session *session); -extern struct sockaddr_in iax_get_peer_addr(struct iax_session *session); -extern int iax_register(struct iax_session *session, char *hostname, char *peer, char *secret, int refresh); -extern int iax_lag_request(struct iax_session *session); -extern int iax_dial(struct iax_session *session, char *number); /* Dial on a TBD call */ -extern int iax_dialplan_request(struct iax_session *session, char *number); /* Request dialplan status for number */ -extern int iax_quelch(struct iax_session *session); -extern int iax_unquelch(struct iax_session * session); -extern int iax_transfer(struct iax_session *session, char *number); -extern int iax_quelch_moh(struct iax_session *session, int MOH); - -extern void iax_destroy(struct iax_session * session); - -extern void iax_enable_debug(void); -extern void iax_disable_debug(void); - -/* For attended transfer, application create a new session, - * make a call on the new session. - * On answer of the new session, call iax_setup_transfer and wait for - * IAX_EVENT_TXREADY when both sides are completed succefully or - * IAX_EVENT_TXREJECT for either side. - * If there are music on hold the it will be stopped by this library. - */ -extern int iax_setup_transfer(struct iax_session *s0, struct iax_session *s1); - -struct iax_netstat { - time_in_ms_t jitter; - int losspct; - int losscnt; - int packets; - time_in_ms_t delay; - int dropped; - int ooo; -}; -/* fills in rtt, and an iax_netstat structure for each of local/remote directions of call */ -extern int iax_get_netstats(struct iax_session *s, time_in_ms_t *rtt, struct iax_netstat *local, struct iax_netstat *remote); - - -extern void iax_set_private(struct iax_session *s, void *pvt); -extern void *iax_get_private(struct iax_session *s); -extern void iax_set_sendto(struct iax_session *s, sendto_t sendto); - -/* to use application networking instead of internal, set call this instead of iax_init, - * and pass in sendto and recvfrom replacements. blocking reads may not be implemented */ -extern void iax_set_networking(sendto_t st, recvfrom_t rf); - -/* destroy an iax session */ -extern void iax_session_destroy(struct iax_session **session); - -/* Handle externally received frames */ -struct iax_event *iax_net_process(unsigned char *buf, int len, struct sockaddr_in *sin); -extern unsigned int iax_session_get_capability(struct iax_session *s); -extern char iax_pref_codec_add(struct iax_session *session, unsigned int format); -extern void iax_pref_codec_del(struct iax_session *session, unsigned int format); -extern int iax_pref_codec_get(struct iax_session *session, unsigned int *array, int len); - -/* Fine tune jitterbuffer */ -extern void iax_set_jb_target_extra( long value ); - -extern char *iax_get_peer_ip(struct iax_session *session); -extern char *iax_event_get_apparent_ip(struct iax_event *event); -extern void iax_set_samplerate(struct iax_session *session, unsigned short samplemask); - -#if defined(__cplusplus) -} -#endif - -#endif /* _ASTERISK_IAX_CLIENT_H */ diff --git a/src/mod/endpoints/mod_iax/iax-mutex.c b/src/mod/endpoints/mod_iax/iax-mutex.c deleted file mode 100644 index fb8c61fc39..0000000000 --- a/src/mod/endpoints/mod_iax/iax-mutex.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Simple Mutex abstraction - * Copyright(C) 2007 Michael Jerris - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so. - * - * This work is provided under this license on an "as is" basis, without warranty of any kind, - * either expressed or implied, including, without limitation, warranties that the covered code - * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire - * risk as to the quality and performance of the covered code is with you. Should any covered - * code prove defective in any respect, you (not the initial developer or any other contributor) - * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty - * constitutes an essential part of this license. No use of any covered code is authorized hereunder - * except under this disclaimer. - * - */ - -#define _XOPEN_SOURCE 600 -#include -#include "iax-mutex.h" - - -#ifdef WIN32 -#define _WIN32_WINNT 0x0400 -#include -struct mutex { - CRITICAL_SECTION mutex; -}; - -#else - -#include -struct mutex { - pthread_mutex_t mutex; -}; - -#endif - - -mutex_status_t iax_mutex_create(mutex_t **mutex) -{ - mutex_status_t status = MUTEX_FAILURE; -#ifndef WIN32 - pthread_mutexattr_t attr; -#endif - mutex_t *check = NULL; - - check = (mutex_t *) malloc(sizeof(**mutex)); - if (!check) - goto done; -#ifdef WIN32 - InitializeCriticalSection(&check->mutex); -#else - if (pthread_mutexattr_init(&attr)) - goto done; - - if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) - goto fail; - - if (pthread_mutex_init(&check->mutex, &attr)) - goto fail; - - goto success; - - fail: - pthread_mutexattr_destroy(&attr); - goto done; - - success: -#endif - *mutex = check; - status = MUTEX_SUCCESS; - - done: - return status; -} - -mutex_status_t iax_mutex_destroy(mutex_t *mutex) -{ -#ifdef WIN32 - DeleteCriticalSection(&mutex->mutex); -#else - if (pthread_mutex_destroy(&mutex->mutex)) - return MUTEX_FAILURE; -#endif - free(mutex); - return MUTEX_SUCCESS; -} - -mutex_status_t iax_mutex_lock(mutex_t *mutex) -{ -#ifdef WIN32 - EnterCriticalSection(&mutex->mutex); -#else - if (pthread_mutex_lock(&mutex->mutex)) - return MUTEX_FAILURE; -#endif - return MUTEX_SUCCESS; -} - -mutex_status_t iax_mutex_trylock(mutex_t *mutex) -{ -#ifdef WIN32 - if (!TryEnterCriticalSection(&mutex->mutex)) - return MUTEX_FAILURE; -#else - if (pthread_mutex_trylock(&mutex->mutex)) - return MUTEX_FAILURE; -#endif - return MUTEX_SUCCESS; -} - -mutex_status_t iax_mutex_unlock(mutex_t *mutex) -{ -#ifdef WIN32 - LeaveCriticalSection(&mutex->mutex); -#else - if (pthread_mutex_unlock(&mutex->mutex)) - return MUTEX_FAILURE; -#endif - return MUTEX_SUCCESS; -} diff --git a/src/mod/endpoints/mod_iax/iax-mutex.h b/src/mod/endpoints/mod_iax/iax-mutex.h deleted file mode 100644 index 3d8a5a2d74..0000000000 --- a/src/mod/endpoints/mod_iax/iax-mutex.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Simple Mutex abstraction - * Copyright(C) 2007 Michael Jerris - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so. - * - * This work is provided under this license on an "as is" basis, without warranty of any kind, - * either expressed or implied, including, without limitation, warranties that the covered code - * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire - * risk as to the quality and performance of the covered code is with you. Should any covered - * code prove defective in any respect, you (not the initial developer or any other contributor) - * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty - * constitutes an essential part of this license. No use of any covered code is authorized hereunder - * except under this disclaimer. - * - */ - - -#ifndef _SIMPLE_ABSTRACT_MUTEX_H -#define _SIMPLE_ABSTRACT_MUTEX_H - -typedef struct mutex mutex_t; - -typedef enum mutex_status { - MUTEX_SUCCESS, - MUTEX_FAILURE -} mutex_status_t; - -mutex_status_t iax_mutex_create(mutex_t **mutex); -mutex_status_t iax_mutex_destroy(mutex_t *mutex); -mutex_status_t iax_mutex_lock(mutex_t *mutex); -mutex_status_t iax_mutex_trylock(mutex_t *mutex); -mutex_status_t iax_mutex_unlock(mutex_t *mutex); - -#endif diff --git a/src/mod/endpoints/mod_iax/iax.c b/src/mod/endpoints/mod_iax/iax.c deleted file mode 100644 index 912913f175..0000000000 --- a/src/mod/endpoints/mod_iax/iax.c +++ /dev/null @@ -1,3235 +0,0 @@ - /* - * libiax: An implementation of Inter-Asterisk eXchange - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * Mark Spencer - * - * This program is free software, distributed under the terms of - * the GNU Lesser (Library) General Public License - */ - -#ifdef WIN32 -#undef __STRICT_ANSI__ //for strdup with ms - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define snprintf _snprintf - -#if defined(_MSC_VER) -#define close _close -#define inline __inline -#define strdup _strdup -#endif - -void gettimeofday(struct timeval *tv, void /*struct timezone */ *tz); -#include "winpoop.h" - -#else - -#define _BSD_SOURCE 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif - -#include "iax2.h" -#include "iax-client.h" -#include "md5.h" - -#ifdef NEWJB -#include "jitterbuf.h" -#endif -#include "iax-mutex.h" -/* - work around jitter-buffer shrinking in asterisk: - channels/chan_iax2.c:schedule_delivery() shrinks jitter buffer by 2. - this causes frames timestamped 1ms apart to ( sometimes ) be delivered - out of order, and results in garbled audio. our temporary fix is to increase - the minimum number of ( timestamped ) milliseconds between frames to 3 ( 2 + 1 ). -*/ -#define IAX_MIN_TIMESTAMP_INCREMENT 3 - -/* Define socket options for IAX2 sockets, based on platform - * availability of flags */ -#ifdef WIN32 -#define IAX_SOCKOPTS 0 -#else -#ifdef LINUX -#define IAX_SOCKOPTS MSG_DONTWAIT | MSG_NOSIGNAL -#else -#define IAX_SOCKOPTS MSG_DONTWAIT -#endif -#endif - - - -#ifdef SNOM_HACK -/* The snom phone seems to improperly execute memset in some cases */ -#include "../../snom_phonecore2/include/snom_memset.h" -#endif - -/* Voice TS Prediction causes libiax2 to clean up the timestamps on - * outgoing frames. It works best with either continuous voice, or - * callers who call iax_send_cng to indicate DTX for silence */ -#define USE_VOICE_TS_PREDICTION - -/* Define Voice Smoothing to try to make some judgements and adjust timestamps - on incoming packets to what they "ought to be" */ - -#define VOICE_SMOOTHING -#undef VOICE_SMOOTHING - -/* Define Drop Whole Frames to make IAX shrink its jitter buffer by dropping entire - frames rather than simply delivering them faster. Dropping encoded frames, - before they're decoded, usually leads to better results than dropping - decoded frames. */ - -#define DROP_WHOLE_FRAMES - -#define MIN_RETRY_TIME 10 -#define MAX_RETRY_TIME 4000 -#define MEMORY_SIZE 1000 - -#define TRANSFER_NONE 0 -#define TRANSFER_BEGIN 1 -#define TRANSFER_READY 2 -#define TRANSFER_REL 3 - -#ifndef NEWJB -/* No more than 4 seconds of jitter buffer */ -static int max_jitterbuffer = 4000; -/* No more than 50 extra milliseconds of jitterbuffer than needed */ -static int max_extra_jitterbuffer = 50; -/* To use or not to use the jitterbuffer */ -static int iax_use_jitterbuffer = 1; - -/* Dropcount (in per-MEMORY_SIZE) usually percent */ -static int iax_dropcount = 3; -#endif - -/* UDP Socket (file descriptor) */ -static int netfd = -1; - -/* Max timeouts */ -static int maxretries = 10; - -/* configurable jitterbuffer options */ -static long jb_target_extra = -1; - -static int do_shutdown = 0; - -/* external global networking replacements */ -static sendto_t iax_sendto = (sendto_t) sendto; -static recvfrom_t iax_recvfrom = (recvfrom_t) recvfrom; - -/* ping interval (seconds) */ -static int ping_time = 10; -static void send_ping(void *session); - -struct iax_session { - /* Private data */ - void *pvt; - /* session-local Sendto function */ - sendto_t sendto; - /* Is voice quelched (e.g. hold) */ - int quelch; - /* Codec Pref Order */ - char codec_order[32]; - /* Codec Pref Order Index */ - int codec_order_len; - /* Last received voice format */ - int voiceformat; - /* Last transmitted voice format */ - int svoiceformat; - /* Per session capability */ - int capability; - /* Last received timestamp */ - time_in_ms_t last_ts; - /* Last transmitted timestamp */ - time_in_ms_t lastsent; - /* Last transmitted voice timestamp */ - unsigned int lastvoicets; - /* Next predicted voice ts */ - time_in_ms_t nextpred; - /* True if the last voice we transmitted was not silence/CNG */ - int notsilenttx; - /* Our last measured ping time */ - time_in_ms_t pingtime; - /* Address of peer */ - struct sockaddr_in peeraddr; - /* Our call number */ - int callno; - /* Peer's call number */ - int peercallno; - /* Our next outgoing sequence number */ - unsigned char oseqno; - /* Next sequence number they have not yet acknowledged */ - unsigned char rseqno; - /* Our last received incoming sequence number */ - unsigned char iseqno; - /* Last acknowledged sequence number */ - unsigned char aseqno; - /* Peer supported formats */ - int peerformats; - /* Time value that we base our transmission on */ - time_in_ms_t offset; - /* Time value we base our delivery on */ - time_in_ms_t rxcore; - /* History of lags */ - int history[MEMORY_SIZE]; - /* Current base jitterbuffer */ - int jitterbuffer; - /* Informational jitter */ - int jitter; - /* Measured lag */ - int lag; - /* Current link state */ - int state; - /* Peer name */ - char peer[MAXSTRLEN]; - /* Default Context */ - char context[MAXSTRLEN]; - /* Caller ID if available */ - char callerid[MAXSTRLEN]; - /* DNID */ - char dnid[MAXSTRLEN]; - /* Requested Extension */ - char exten[MAXSTRLEN]; - /* Expected Username */ - char username[MAXSTRLEN]; - /* Expected Secret */ - char secret[MAXSTRLEN]; - /* permitted authentication methods */ - char methods[MAXSTRLEN]; - /* MD5 challenge */ - char challenge[12]; -#ifdef VOICE_SMOOTHING - unsigned int lastts; -#endif - /* Refresh if applicable */ - int refresh; - - /* ping scheduler id */ - int pingid; - - /* Transfer stuff */ - struct sockaddr_in transfer; - int transferring; - int transfercallno; - int transferid; - int transferpeer; /* for attended transfer */ - int transfer_moh; /* for music on hold while performing attended transfer */ - -#ifdef NEWJB - jitterbuf *jb; -#endif - struct iax_netstat remote_netstats; - - unsigned short samplemask; - /* For linking if there are multiple connections */ - struct iax_session *next; -}; - -char iax_errstr[256]; - -static void destroy_session(struct iax_session *session); - -#define IAXERROR snprintf(iax_errstr, sizeof(iax_errstr), - -#ifdef DEBUG_SUPPORT - -#ifdef DEBUG_DEFAULT -static int debug = 1; -#else -static int debug = 0; -#endif - -void iax_enable_debug(void) -{ - debug = 1; -} - -void iax_disable_debug(void) -{ - debug = 0; -} - -/* This is a little strange, but to debug you call DEBU(G "Hello World!\n"); */ -#ifdef WIN32 -#define G __FILE__, __LINE__, __FUNCTION__, -#else -#define G __FILE__, __LINE__, (const char *)__func__, -#endif - -#define DEBU __debug -static int __debug(char *file, int lineno, const char *func, char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - if (debug) { - fprintf(stderr, "%s line %d in %s: ", file, lineno, func); - vfprintf(stderr, fmt, args); - } - va_end(args); - return 0; -} - -#else /* No debug support */ - -#ifdef WIN32 -#define DEBU -#else -#define DEBU(...) (void)(0) -#endif -#define G -#endif - -typedef void (*sched_func) (void *); - -struct iax_sched { - /* These are scheduled things to be delivered */ - time_in_ms_t when; - /* If event is non-NULL then we're delivering an event */ - struct iax_event *event; - /* If frame is non-NULL then we're transmitting a frame */ - struct iax_frame *frame; - /* If func is non-NULL then we should call it */ - sched_func func; - /* and pass it this argument */ - void *arg; - /* Easy linking */ - struct iax_sched *next; -}; - -static mutex_t *sched_mutex = NULL; -static mutex_t *session_mutex = NULL; -static struct iax_sched *schedq = NULL; -static struct iax_session *sessions = NULL; -static int callnums = 1; -static int transfer_id = 1; /* for attended transfer */ -static int time_init = 0; - -static void init_time(void) -{ -#ifdef WIN32_TIME_GET_TIME - timeBeginPeriod(1); -#endif - time_init = 1; -} - -static void time_end(void) -{ -#ifdef WIN32_TIME_GET_TIME - timeEndPeriod(1); -#endif - time_init = 0; -} - -static time_in_ms_t current_time_in_ms(void) -{ -#ifdef WIN32_TIME_GET_TIME - return timeGetTime(); -#else - struct timeval tv; - gettimeofday(&tv, NULL); - return ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); -#endif -} - -void iax_set_private(struct iax_session *s, void *ptr) -{ - s->pvt = ptr; -} - -void *iax_get_private(struct iax_session *s) -{ - return s->pvt; -} - -void iax_set_sendto(struct iax_session *s, sendto_t ptr) -{ - s->sendto = ptr; -} - - -unsigned int iax_session_get_capability(struct iax_session *s) -{ - return s->capability; -} - - -static int inaddrcmp(struct sockaddr_in *sin1, struct sockaddr_in *sin2) -{ - return (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) || (sin1->sin_port != sin2->sin_port); -} - -static int iax_sched_add(struct iax_event *event, struct iax_frame *frame, sched_func func, void *arg, time_in_ms_t ms) -{ - - /* Schedule event to be delivered to the client - in ms milliseconds from now, or a reliable frame to be retransmitted */ - struct iax_sched *sched, *cur, *prev = NULL; - - if (!event && !frame && !func) { - DEBU(G "No event, no frame, no func? what are we scheduling?\n"); - return -1; - } - - - sched = (struct iax_sched *) malloc(sizeof(struct iax_sched)); - if (sched) { - memset(sched, 0, sizeof(struct iax_sched)); - sched->when = current_time_in_ms() + ms; - sched->event = event; - sched->frame = frame; - sched->func = func; - sched->arg = arg; - /* Put it in the list, in order */ - iax_mutex_lock(sched_mutex); - cur = schedq; - while (cur && cur->when <= sched->when) { - prev = cur; - cur = cur->next; - } - sched->next = cur; - if (prev) { - prev->next = sched; - } else { - schedq = sched; - } - iax_mutex_unlock(sched_mutex); - return 0; - } else { - DEBU(G "Out of memory!\n"); - return -1; - } -} - -static int iax_sched_del(struct iax_event *event, struct iax_frame *frame, sched_func func, void *arg, int all) -{ - struct iax_sched *cur, *tmp, *prev = NULL; - int ret = 0; - - iax_mutex_lock(sched_mutex); - cur = schedq; - while (cur) { - if (cur->event == event && cur->frame == frame && cur->func == func && cur->arg == arg) { - if (prev) - prev->next = cur->next; - else - schedq = cur->next; - tmp = cur; - cur = cur->next; - free(tmp); - if (!all) { - ret = -1; - goto done; - } - } else { - prev = cur; - cur = cur->next; - } - } - done: - iax_mutex_unlock(sched_mutex); - - return 0; - -} - - -time_in_ms_t iax_time_to_next_event(void) -{ - struct iax_sched *cur = NULL; - time_in_ms_t minimum = 999999999; - - iax_mutex_lock(sched_mutex); - cur = schedq; - - /* If there are no pending events, we don't need to timeout */ - if (!cur) { - iax_mutex_unlock(sched_mutex); - return -1; - } - while (cur) { - if (cur->when < minimum) { - minimum = cur->when; - } - cur = cur->next; - } - iax_mutex_unlock(sched_mutex); - - if (minimum <= 0) { - return -1; - } - - - - return minimum - current_time_in_ms(); -} - -struct iax_session *iax_session_new(void) -{ - struct iax_session *s; - s = (struct iax_session *) malloc(sizeof(struct iax_session)); - if (s) { - memset(s, 0, sizeof(struct iax_session)); - /* Initialize important fields */ - s->voiceformat = -1; - s->svoiceformat = -1; - /* Default pingtime to 30 ms */ - s->pingtime = 30; - /* XXX Not quite right -- make sure it's not in use, but that won't matter - unless you've had at least 65k calls. XXX */ - s->callno = callnums++; - if (callnums > 32767) - callnums = 1; - s->peercallno = 0; - s->transferpeer = 0; /* for attended transfer */ - - s->sendto = iax_sendto; - s->pingid = -1; -#ifdef NEWJB - s->jb = jb_new(); - { - jb_conf jbconf; - jbconf.max_jitterbuf = 0; - jbconf.resync_threshold = 1000; - jbconf.max_contig_interp = 0; - jbconf.target_extra = jb_target_extra; - jb_setconf(s->jb, &jbconf); - } -#endif - iax_mutex_lock(session_mutex); - s->next = sessions; - sessions = s; - iax_mutex_unlock(session_mutex); - } - return s; -} - -static int iax_session_valid(struct iax_session *session) -{ - /* Return -1 on a valid iax session pointer, 0 on a failure */ - struct iax_session *cur; - - iax_mutex_lock(session_mutex); - cur = sessions; - while (cur) { - if (session == cur) { - iax_mutex_unlock(session_mutex); - return -1; - } - cur = cur->next; - } - iax_mutex_unlock(session_mutex); - - return 0; -} - -int iax_get_netstats(struct iax_session *session, time_in_ms_t *rtt, struct iax_netstat *local, struct iax_netstat *remote) -{ - - if (!iax_session_valid(session)) - return -1; - - *rtt = session->pingtime; - - *remote = session->remote_netstats; - -#ifdef NEWJB - { - jb_info stats; - jb_getinfo(session->jb, &stats); - - local->jitter = stats.jitter; - /* XXX: should be short-term loss pct.. */ - if (stats.frames_in == 0) - stats.frames_in = 1; - local->losspct = stats.losspct / 1000; - local->losscnt = stats.frames_lost; - local->packets = stats.frames_in; - local->delay = stats.current - stats.min; - local->dropped = stats.frames_dropped; - local->ooo = stats.frames_ooo; - } -#endif - return 0; -} - -static time_in_ms_t calc_timestamp(struct iax_session *session, time_in_ms_t ts, struct ast_frame *f) -{ - time_in_ms_t ms; - time_in_ms_t time_in_ms; - int voice = 0; - int genuine = 0; - - if (f && f->frametype == AST_FRAME_VOICE) { - voice = 1; - } else if (!f || f->frametype == AST_FRAME_IAX) { - genuine = 1; - } - - /* If this is the first packet we're sending, get our - offset now. */ - if (!session->offset) { - session->offset = current_time_in_ms(); - } - /* If the timestamp is specified, just use their specified - timestamp no matter what. Usually this is done for - special cases. */ - if (ts) { - return ts; - } - /* Otherwise calculate the timestamp from the current time */ - time_in_ms = current_time_in_ms(); - - - /* Calculate the number of milliseconds since we sent the first packet */ - ms = time_in_ms - session->offset; - - if (ms < 0) { - ms = 0; - } - - if (voice) { -#ifdef USE_VOICE_TS_PREDICTION - - /* If we haven't most recently sent silence, and we're - * close in time, use predicted time */ - if (session->notsilenttx && iax_abs(ms - session->nextpred) <= 240) { - /* Adjust our txcore, keeping voice and non-voice - * synchronized */ - session->offset += (int) (ms - session->nextpred) / 10; - - if (!session->nextpred) { - session->nextpred = ms; - } - ms = session->nextpred; - } else { - /* in this case, just use the actual time, since - * we're either way off (shouldn't happen), or we're - * ending a silent period -- and seed the next predicted - * time. Also, round ms to the next multiple of - * frame size (so our silent periods are multiples - * of frame size too) */ - time_in_ms_t diff = ms % (f->samples / 8); - if (diff) - ms += f->samples / 8 - diff; - session->nextpred = ms; - } -#else - if (ms <= session->lastsent) - ms = session->lastsent + 3; -#endif - session->notsilenttx = 1; - } else { - /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) - if appropriate unless it's a genuine frame */ - if (genuine) { - if (ms <= session->lastsent) - ms = session->lastsent + 3; - } else if (iax_abs(ms - session->lastsent) <= 240) { - ms = session->lastsent + 3; - } - - } - - /* Record the last sent packet for future reference */ - /* unless an AST_FRAME_IAX */ - if (!genuine) - session->lastsent = ms; - -#ifdef USE_VOICE_TS_PREDICTION - /* set next predicted ts based on 8khz samples */ - if (voice) - session->nextpred = session->nextpred + f->samples / 8; -#endif - - return ms; -} - -#ifdef NEWJB -static unsigned char get_n_bits_at(unsigned char *data, int n, int bit) -{ - int byte = bit / 8; /* byte containing first bit */ - int rem = 8 - (bit % 8); /* remaining bits in first byte */ - unsigned char ret = 0; - - if (n <= 0 || n > 8) - return 0; - - if (rem < n) { - ret = (unsigned char) (data[byte] << (n - rem)); - ret |= (data[byte + 1] >> (8 - n + rem)); - } else { - ret = (unsigned char) (data[byte] >> (rem - n)); - } - - return (unsigned char) (ret & (0xff >> (8 - n))); -} - -static int speex_get_wb_sz_at(unsigned char *data, int len, int bit) -{ - static int SpeexWBSubModeSz[] = { - 0, 36, 112, 192, - 352, 0, 0, 0 - }; - int off = bit; - unsigned char c; - - /* skip up to two wideband frames */ - if (((len * 8 - off) >= 5) && get_n_bits_at(data, 1, off)) { - c = get_n_bits_at(data, 3, off + 1); - off += SpeexWBSubModeSz[c]; - - if (((len * 8 - off) >= 5) && get_n_bits_at(data, 1, off)) { - c = get_n_bits_at(data, 3, off + 1); - off += SpeexWBSubModeSz[c]; - - if (((len * 8 - off) >= 5) && get_n_bits_at(data, 1, off)) { - /* too many in a row */ - DEBU(G "\tCORRUPT too many wideband streams in a row\n"); - return -1; - } - } - - } - return off - bit; -} - -static int speex_get_samples(unsigned char *data, int len) -{ - static int SpeexSubModeSz[] = { - 0, 43, 119, 160, - 220, 300, 364, 492, - 79, 0, 0, 0, - 0, 0, 0, 0 - }; - static int SpeexInBandSz[] = { - 1, 1, 4, 4, - 4, 4, 4, 4, - 8, 8, 16, 16, - 32, 32, 64, 64 - }; - int bit = 0; - int cnt = 0; - int off = 0; - unsigned char c; - - DEBU(G "speex_get_samples(%d)\n", len); - while ((len * 8 - bit) >= 5) { - /* skip wideband frames */ - off = speex_get_wb_sz_at(data, len, bit); - if (off < 0) { - DEBU(G "\tERROR reading wideband frames\n"); - break; - } - bit += off; - - if ((len * 8 - bit) < 5) { - DEBU(G "\tERROR not enough bits left after wb\n"); - break; - } - - /* get control bits */ - c = get_n_bits_at(data, 5, bit); - DEBU(G "\tCONTROL: %d at %d\n", c, bit); - bit += 5; - - if (c == 15) { - DEBU(G "\tTERMINATOR\n"); - break; - } else if (c == 14) { - /* in-band signal; next 4 bits contain signal id */ - c = get_n_bits_at(data, 4, bit); - bit += 4; - DEBU(G "\tIN-BAND %d bits\n", SpeexInBandSz[c]); - bit += SpeexInBandSz[c]; - } else if (c == 13) { - /* user in-band; next 5 bits contain msg len */ - c = get_n_bits_at(data, 5, bit); - bit += 5; - DEBU(G "\tUSER-BAND %d bytes\n", c); - bit += c * 8; - } else if (c > 8) { - DEBU(G "\tUNKNOWN sub-mode %d\n", c); - break; - } else { - /* skip number bits for submode (less the 5 control bits) */ - DEBU(G "\tSUBMODE %d %d bits\n", c, SpeexSubModeSz[c]); - bit += SpeexSubModeSz[c] - 5; - - cnt += 160; /* new frame */ - } - } - DEBU(G "\tSAMPLES: %d\n", cnt); - return cnt; -} - -static inline int get_interp_len(int format) -{ - return (format == AST_FORMAT_ILBC) ? 30 : 20; -} - -static int get_sample_cnt(struct iax_event *e) -{ - int cnt = 0; - - /* - * In the case of zero length frames, do not return a cnt of 0 - */ - if (e->datalen == 0) { - return get_interp_len(e->subclass) * 8; - } - - switch (e->subclass) { - case AST_FORMAT_SPEEX: - cnt = speex_get_samples(e->data, e->datalen); - break; - case AST_FORMAT_G723_1: - cnt = 240; /* FIXME Not always the case */ - break; - case AST_FORMAT_ILBC: - cnt = 240 * (e->datalen / 50); - break; - case AST_FORMAT_GSM: - cnt = 160 * (e->datalen / 33); - break; - case AST_FORMAT_G729A: - cnt = 160 * (e->datalen / 20); - break; - case AST_FORMAT_SLINEAR: - cnt = e->datalen / 2; - break; - case AST_FORMAT_LPC10: - cnt = 22 * 8 + (((char *) (e->data))[7] & 0x1) * 8; - break; - case AST_FORMAT_ULAW: - case AST_FORMAT_ALAW: - cnt = e->datalen; - break; - case AST_FORMAT_ADPCM: - case AST_FORMAT_G726: - cnt = e->datalen * 2; - break; - default: - return 0; - } - return cnt; -} -#endif - -static int iax_xmit_frame(struct iax_frame *f) -{ - /* Send the frame raw */ -#ifdef DEBUG_SUPPORT - struct ast_iax2_full_hdr *h = (f->data); - if (ntohs(h->scallno) & IAX_FLAG_FULL) - iax_showframe(f, NULL, 0, f->transfer ? &(f->session->transfer) : &(f->session->peeraddr), f->datalen - sizeof(struct ast_iax2_full_hdr)); -#endif - - return f->session->sendto(netfd, (const char *) f->data, f->datalen, - IAX_SOCKOPTS, - f->transfer ? - (struct sockaddr *) &(f->session->transfer) : (struct sockaddr *) &(f->session->peeraddr), sizeof(f->session->peeraddr)); -} - -static int iax_reliable_xmit(struct iax_frame *f) -{ - struct iax_frame *fc; - struct ast_iax2_full_hdr *fh; - fh = (struct ast_iax2_full_hdr *) f->data; - if (!fh->type) { - DEBU(G "Asked to reliably transmit a non-packet. Crashing.\n"); - *((char *) 0) = 0; - } - fc = (struct iax_frame *) malloc(sizeof(struct iax_frame)); - if (fc) { - /* Make a copy of the frame */ - memcpy(fc, f, sizeof(struct iax_frame)); - /* And a copy of the data if applicable */ - if (!fc->data || !fc->datalen) { - IAXERROR "No frame data?"); - DEBU(G "No frame data?\n"); - return -1; - } else { - fc->data = (char *) malloc(fc->datalen); - if (!fc->data) { - DEBU(G "Out of memory\n"); - IAXERROR "Out of memory\n"); - return -1; - } - memcpy(fc->data, f->data, f->datalen); - iax_sched_add(NULL, fc, NULL, NULL, fc->retrytime); - return iax_xmit_frame(fc); - } - } else - return -1; -} - -void iax_set_networking(sendto_t st, recvfrom_t rf) { - - init_time(); - iax_sendto = st; - iax_recvfrom = rf; -} - -int __iax_shutdown(void) { - struct iax_sched *sp, *fp; - - /* Hangup Calls */ - if (sessions) { - struct iax_session *sp = NULL, *fp = NULL; - iax_mutex_lock(session_mutex); - for (sp = sessions; sp;) { - iax_hangup(sp, "System Shutdown"); - fp = sp; - sp = sp->next; - destroy_session(fp); - } - iax_mutex_unlock(session_mutex); - } - - /* Clear Scheduler */ - iax_mutex_lock(sched_mutex); - for (sp = schedq; sp;) { - fp = sp; - sp = sp->next; - free(fp); - } - iax_mutex_unlock(sched_mutex); - - if (netfd > -1) { - shutdown(netfd, 2); - close(netfd); - } - - time_end(); - - iax_mutex_destroy(sched_mutex); - iax_mutex_destroy(session_mutex); - - return 0; -} - -int iax_shutdown(void) { - return do_shutdown++; -} - -void iax_set_jb_target_extra(long value) { - /* store in jb_target_extra, a static global */ - jb_target_extra = value; -} - -int iax_init(char *ip, int preferredportno) { - int portno = preferredportno; - struct sockaddr_in sin; -#ifdef WIN32 - socklen_t sinlen; -#else - unsigned int sinlen; -#endif - int flags; - - init_time(); - - iax_mutex_create(&sched_mutex); - iax_mutex_create(&session_mutex); - - if (iax_recvfrom == (recvfrom_t) recvfrom) { - if (netfd > -1) { - /* Sokay, just don't do anything */ - DEBU(G "Already initialized."); - return 0; - } - netfd = (int) socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (netfd < 0) { - DEBU(G "Unable to allocate UDP socket\n"); - IAXERROR "Unable to allocate UDP socket\n"); - return -1; - } - - if (preferredportno == 0) - preferredportno = IAX_DEFAULT_PORTNO; - if (preferredportno < 0) - preferredportno = 0; - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = 0; - sin.sin_port = htons((short) preferredportno); - if (bind(netfd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { -#if defined(WIN32) || defined(_WIN32_WCE) - if (WSAGetLastError() == WSAEADDRINUSE) -#else - if (errno == EADDRINUSE) -#endif - { - /*the port is already in use, so bind to a free port chosen by the IP stack */ - DEBU(G "Unable to bind to preferred port - port is in use. Trying to bind to a free one"); - sin.sin_port = htons((short) 0); - if (bind(netfd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { - IAXERROR "Unable to bind UDP socket\n"); - return -1; - } - } else { - IAXERROR "Unable to bind UDP socket\n"); - return -1; - } - } - sinlen = sizeof(sin); - if (getsockname(netfd, (struct sockaddr *) &sin, &sinlen) < 0) { - close(netfd); - netfd = -1; - DEBU(G "Unable to figure out what I'm bound to."); - IAXERROR "Unable to determine bound port number."); - } -#ifdef WIN32 - flags = 1; - if (ioctlsocket(netfd, FIONBIO, (unsigned long *) &flags)) { - closesocket(netfd); - netfd = -1; - DEBU(G "Unable to set non-blocking mode."); - IAXERROR "Unable to set non-blocking mode."); - } -#else - if ((flags = fcntl(netfd, F_GETFL)) < 0) { - close(netfd); - netfd = -1; - DEBU(G "Unable to retrieve socket flags."); - IAXERROR "Unable to retrieve socket flags."); - } - if (fcntl(netfd, F_SETFL, flags | O_NONBLOCK) < 0) { - close(netfd); - netfd = -1; - DEBU(G "Unable to set non-blocking mode."); - IAXERROR "Unable to set non-blocking mode."); - } -#endif - portno = ntohs(sin.sin_port); - } - srand((unsigned int) time(NULL)); - callnums = rand() % 32767 + 1; - transfer_id = rand() % 32767 + 1; - DEBU(G "Started on port %d\n", portno); - return portno; -} - - - -static void convert_reply(char *out, unsigned char *in) { - int x; - for (x = 0; x < 16; x++) - out += sprintf(out, "%2.2x", (int) in[x]); -} - -static unsigned char compress_subclass(int subclass) { - int x; - int power = -1; - /* If it's 128 or smaller, just return it */ - if (subclass < IAX_FLAG_SC_LOG) - return (unsigned char) subclass; - /* Otherwise find its power */ - for (x = 0; x < IAX_MAX_SHIFT; x++) { - if (subclass & (1 << x)) { - if (power > -1) { - DEBU(G "Can't compress subclass %d\n", subclass); - return 0; - } else - power = x; - } - } - return (unsigned char) (power | IAX_FLAG_SC_LOG); -} - -static int iax_send(struct iax_session *pvt, struct ast_frame *f, time_in_ms_t ts, int seqno, int now, int transfer, int final) { - /* Queue a packet for delivery on a given private structure. Use "ts" for - timestamp, or calculate if ts is 0. Send immediately without retransmission - or delayed, with retransmission */ - struct ast_iax2_full_hdr *fh; - struct ast_iax2_mini_hdr *mh; - unsigned char buf[5120]; - struct iax_frame *fr; - int res; - int sendmini = 0; - time_in_ms_t lastsent; - time_in_ms_t fts; - - if (!pvt) { - IAXERROR "No private structure for packet?\n"); - return -1; - } - - /* this must come before the next call to calc_timestamp() since - calc_timestamp() will change lastsent to the returned value */ - lastsent = pvt->lastsent; - - /* Calculate actual timestamp */ - fts = calc_timestamp(pvt, ts, f); - - if (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) - /* High two bits are the same on timestamp, or sending on a trunk */ - && (f->frametype == AST_FRAME_VOICE) - /* is a voice frame */ - && (f->subclass == pvt->svoiceformat) - /* is the same type */ - ) { - /* Force immediate rather than delayed transmission */ - now = 1; - /* Mark that mini-style frame is appropriate */ - sendmini = 1; - } - /* Allocate an iax_frame */ - if (now) { - fr = (struct iax_frame *) buf; - } else - fr = iax_frame_new(DIRECTION_OUTGRESS, f->datalen); - if (!fr) { - IAXERROR "Out of memory\n"); - return -1; - } - /* Copy our prospective frame into our immediate or retransmitted wrapper */ - iax_frame_wrap(fr, f); - - fr->ts = fts; - if (!fr->ts) { - IAXERROR "timestamp is 0?\n"); - if (!now) - iax_frame_free(fr); - return -1; - } - - fr->callno = (unsigned short) pvt->callno; - fr->transfer = transfer; - fr->final = final; - fr->session = pvt; - if (!sendmini) { - /* We need a full frame */ - if (seqno > -1) - fr->oseqno = seqno; - else - fr->oseqno = pvt->oseqno++; - fr->iseqno = pvt->iseqno; - fh = (struct ast_iax2_full_hdr *) (((char *) fr->af.data) - sizeof(struct ast_iax2_full_hdr)); - fh->scallno = htons(fr->callno | IAX_FLAG_FULL); - fh->ts = htonl((long) (fr->ts)); - fh->oseqno = (unsigned char) fr->oseqno; - if (transfer) { - fh->iseqno = 0; - } else - fh->iseqno = (unsigned char) fr->iseqno; - /* Keep track of the last thing we've acknowledged */ - pvt->aseqno = (unsigned char) fr->iseqno; - fh->type = (char) (fr->af.frametype & 0xFF); - fh->csub = compress_subclass(fr->af.subclass); - if (transfer) { - fr->dcallno = (unsigned short) pvt->transfercallno; - } else - fr->dcallno = (unsigned short) pvt->peercallno; - fh->dcallno = htons(fr->dcallno); - fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr); - fr->data = fh; - fr->retries = maxretries; - /* Retry after 2x the ping time has passed */ - fr->retrytime = pvt->pingtime * 2; - if (fr->retrytime < MIN_RETRY_TIME) - fr->retrytime = MIN_RETRY_TIME; - if (fr->retrytime > MAX_RETRY_TIME) - fr->retrytime = MAX_RETRY_TIME; - /* Acks' don't get retried */ - if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK)) - fr->retries = -1; - if (f->frametype == AST_FRAME_VOICE) { - pvt->svoiceformat = f->subclass; - } - if (now) { - res = iax_xmit_frame(fr); - } else - res = iax_reliable_xmit(fr); - } else { - /* Mini-frames have no sequence number */ - fr->oseqno = -1; - fr->iseqno = -1; - /* Mini frame will do */ - mh = (struct ast_iax2_mini_hdr *) (((char *) fr->af.data) - sizeof(struct ast_iax2_mini_hdr)); - mh->callno = htons(fr->callno); - mh->ts = htons((short) (fr->ts & 0xFFFF)); - fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr); - fr->data = mh; - fr->retries = -1; - res = iax_xmit_frame(fr); - } - if (!now && fr != NULL) - iax_frame_free(fr); - return res; -} - -#if 0 -static int iax_predestroy(struct iax_session *pvt) { - if (!pvt) { - return -1; - } - if (!pvt->alreadygone) { - /* No more pings or lagrq's */ - if (pvt->pingid > -1) - ast_sched_del(sched, pvt->pingid); - if (pvt->lagid > -1) - ast_sched_del(sched, pvt->lagid); - if (pvt->autoid > -1) - ast_sched_del(sched, pvt->autoid); - if (pvt->initid > -1) - ast_sched_del(sched, pvt->initid); - pvt->pingid = -1; - pvt->lagid = -1; - pvt->autoid = -1; - pvt->initid = -1; - pvt->alreadygone = 1; - } - return 0; -} -#endif - -static int __send_command(struct iax_session *i, char type, int command, time_in_ms_t ts, unsigned char *data, int datalen, int seqno, - int now, int transfer, int final, int samples) { - struct ast_frame f; - f.frametype = type; - f.subclass = command; - f.datalen = datalen; - f.samples = samples; - f.mallocd = 0; - f.offset = 0; -#ifdef __GNUC__ - f.src = (char *) __FUNCTION__; -#else - f.src = (char *) __FILE__; -#endif - f.data = data; - return iax_send(i, &f, ts, seqno, now, transfer, final); -} - -static int send_command(struct iax_session *i, char type, int command, time_in_ms_t ts, unsigned char *data, int datalen, int seqno) { - return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0, 0); -} - -static int send_command_final(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen, int seqno) { -#if 0 - /* It is assumed that the callno has already been locked */ - iax_predestroy(i); -#endif - int r; - r = __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1, 0); - if (r >= 0) { - iax_mutex_lock(session_mutex); - destroy_session(i); - iax_mutex_unlock(session_mutex); - } - return r; -} - -static int send_command_immediate(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen, int seqno) { - return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0, 0); -} - -static int send_command_transfer(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen) { - return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0, 0); -} - -static int send_command_samples(struct iax_session *i, char type, int command, unsigned int ts, unsigned char *data, int datalen, int seqno, int samples) { - return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0, samples); -} - - -int iax_transfer(struct iax_session *session, char *number) { - static int res; //Return Code - struct iax_ie_data ied; //IE Data Structure (Stuff To Send) - - // Clear The Memory Used For IE Buffer - memset(&ied, 0, sizeof(ied)); - - // Copy The Transfer Destination Into The IE Structure - iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, (unsigned char *) number); - - // Send The Transfer Command - Asterisk Will Handle The Rest! - res = send_command(session, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1); - - // Return Success - return 0; -} - -static void stop_transfer(struct iax_session *session) { - struct iax_sched *sch; - - iax_mutex_lock(sched_mutex); - sch = schedq; - while (sch) { - if (sch->frame && (sch->frame->session == session)) - sch->frame->retries = -1; - sch = sch->next; - } - iax_mutex_unlock(sched_mutex); -} /* stop_transfer */ - -static void complete_transfer(struct iax_session *session, int peercallno, int xfr2peer, int preserveSeq) { - session->peercallno = peercallno; - /* Change from transfer to session now */ - if (xfr2peer) { - memcpy(&session->peeraddr, &session->transfer, sizeof(session->peeraddr)); - memset(&session->transfer, 0, sizeof(session->transfer)); - session->transferring = TRANSFER_NONE; - session->transferpeer = 0; - session->transfer_moh = 0; - /* Force retransmission of a real voice packet, and reset all timing */ - session->svoiceformat = -1; - session->voiceformat = 0; - } - session->rxcore = session->offset = 0; - memset(&session->history, 0, sizeof(session->history)); -#ifdef NEWJB - { /* Reset jitterbuffer */ - jb_frame frame; - while (jb_getall(session->jb, &frame) == JB_OK) - iax_event_free(frame.data); - - jb_reset(session->jb); - } -#endif - session->jitterbuffer = 0; - session->jitter = 0; - session->lag = 0; - - if (!preserveSeq) { - /* Reset sequence numbers */ - session->aseqno = 0; - session->oseqno = 0; - session->iseqno = 0; - } - - session->lastsent = 0; - session->last_ts = 0; - session->lastvoicets = 0; - session->pingtime = 30; - /* We have to dump anything we were going to (re)transmit now that we've been - transferred since they're all invalid and for the old host. */ - stop_transfer(session); -} /* complete_transfer */ - -int iax_setup_transfer(struct iax_session *org_session, struct iax_session *new_session) { - int res; - struct iax_ie_data ied0; - struct iax_ie_data ied1; - - struct iax_session *s0 = org_session; - struct iax_session *s1 = new_session; - - memset(&ied0, 0, sizeof(ied0)); - memset(&ied1, 0, sizeof(ied1)); - - /* reversed setup */ - iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &s1->peeraddr); - iax_ie_append_short(&ied0, IAX_IE_CALLNO, (unsigned short) s1->peercallno); - iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transfer_id); - - iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &s0->peeraddr); - iax_ie_append_short(&ied1, IAX_IE_CALLNO, (unsigned short) s0->peercallno); - iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transfer_id); - - s0->transfer = s1->peeraddr; - s1->transfer = s0->peeraddr; - - s0->transferid = transfer_id; - s1->transferid = transfer_id; - - s0->transfercallno = s0->peercallno; - s1->transfercallno = s1->peercallno; - - s0->transferring = TRANSFER_BEGIN; - s1->transferring = TRANSFER_BEGIN; - - s0->transferpeer = s1->callno; - s1->transferpeer = s0->callno; - - transfer_id++; - - if (transfer_id > 32767) - transfer_id = 1; - - res = send_command(s0, AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1); - if (res < 0) { - return -1; - } - - res = send_command(s1, AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1); - if (res < 0) { - return -1; - } - - return 0; -} - -static int iax_finish_transfer(struct iax_session *s, short new_peer) { - int res; - struct iax_ie_data ied; - - memset(&ied, 0, sizeof(ied)); - - iax_ie_append_short(&ied, IAX_IE_CALLNO, new_peer); - - res = send_command(s, AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied.buf, ied.pos, -1); - - complete_transfer(s, new_peer, 0, 1); - - return res; - -} - -static struct iax_session *iax_find_session2(short callno) { - struct iax_session *cur; - - iax_mutex_lock(session_mutex); - cur = sessions; - while (cur) { - if (callno == cur->callno && callno != 0) { - iax_mutex_unlock(session_mutex); - return cur; - } - cur = cur->next; - } - iax_mutex_unlock(session_mutex); - - return NULL; -} - -static int iax_handle_txready(struct iax_session *s) { - struct iax_session *s0, *s1; - short s0_org_peer, s1_org_peer; - - if (s->transfer_moh) { - s->transfer_moh = 0; - iax_unquelch(s); - } - - complete_transfer(s, s->peercallno, 0, 1); - - s->transferring = TRANSFER_REL; - - s0 = s; - s1 = iax_find_session2((short) s0->transferpeer); - - if (s1 != NULL && s1->callno == s0->transferpeer && s0->transferring == TRANSFER_REL && s1->transferring == TRANSFER_REL) { - - s0_org_peer = (short) s0->peercallno; - s1_org_peer = (short) s1->peercallno; - - iax_finish_transfer(s0, s1_org_peer); - iax_finish_transfer(s1, s0_org_peer); - return 1; - } - - return 0; -} - -static void iax_handle_txreject(struct iax_session *s) { - struct iax_session *s0, *s1; - - s0 = s; - s1 = iax_find_session2((short) s0->transferpeer); - if (s1 != NULL && s0->transferpeer == s1->callno && s1->transferring) { - if (s1->transfer_moh) { - s1->transfer_moh = 0; - send_command_immediate(s1, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 0, s1->iseqno); - } - } - if (s0->transfer_moh) { - s0->transfer_moh = 0; - send_command_immediate(s0, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 0, s0->iseqno); - } - - memset(&s->transfer, 0, sizeof(s->transfer)); - s->transferring = TRANSFER_NONE; - s->transferpeer = 0; - s->transfer_moh = 0; -} - -static void destroy_session(struct iax_session *session) { - struct iax_session *cur, *prev = NULL; - struct iax_sched *curs, *prevs = NULL, *nexts = NULL; - int loop_cnt = 0; - - iax_mutex_lock(sched_mutex); - curs = schedq; - while (curs) { - nexts = curs->next; - if (curs->frame && curs->frame->session == session) { - /* Just mark these frames as if they've been sent */ - curs->frame->retries = -1; - } else if (curs->event && curs->event->session == session) { - if (prevs) - prevs->next = nexts; - else - schedq = nexts; - if (curs->event) - iax_event_free(curs->event); - free(curs); - } else { - prevs = curs; - } - curs = nexts; - loop_cnt++; - } - iax_mutex_unlock(sched_mutex); - - - cur = sessions; - while (cur) { - if (cur == session) { - if (prev) - prev->next = session->next; - else - sessions = session->next; -#ifdef NEWJB - { - jb_frame frame; - while (jb_getall(session->jb, &frame) == JB_OK) - iax_event_free(frame.data); - - jb_destroy(session->jb); - } -#endif - free(session); - return; - } - prev = cur; - cur = cur->next; - } -} - -static int iax_send_lagrp(struct iax_session *session, time_in_ms_t ts); -static int iax_send_pong(struct iax_session *session, time_in_ms_t ts); - -static struct iax_event *handle_event(struct iax_event *event) { - /* We have a candidate event to be delievered. Be sure - the session still exists. */ - if (event) { - if (iax_session_valid(event->session)) { - /* Lag requests are never actually sent to the client, but - other than that are handled as normal packets */ - switch (event->etype) { - /* the user on the outside may need to look at the session so we will not free - it here anymore we will test for hangup event in iax_event_free and do it - there. - */ - case IAX_EVENT_REJECT: - case IAX_EVENT_HANGUP: - return event; - case IAX_EVENT_LAGRQ: - event->etype = IAX_EVENT_LAGRP; - iax_send_lagrp(event->session, event->ts); - iax_event_free(event); - break; - case IAX_EVENT_PING: - event->etype = IAX_EVENT_PONG; - iax_send_pong(event->session, event->ts); - iax_event_free(event); - break; - case IAX_EVENT_POKE: - event->etype = IAX_EVENT_PONG; - iax_send_pong(event->session, event->ts); - iax_destroy(event->session); - iax_event_free(event); - break; - default: - return event; - } - } else - iax_event_free(event); - } - return NULL; -} - -static int iax2_vnak(struct iax_session *session) { - return send_command_immediate(session, AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, session->iseqno); -} - -int iax_send_dtmf(struct iax_session *session, char digit) { - return send_command(session, AST_FRAME_DTMF, digit, 0, NULL, 0, -1); -} - -int iax_send_voice(struct iax_session *session, int format, unsigned char *data, int datalen, int samples) { - /* Send a (possibly compressed) voice frame */ - if (!session->quelch) - return send_command_samples(session, AST_FRAME_VOICE, format, 0, data, datalen, -1, samples); - return 0; -} - -int iax_send_cng(struct iax_session *session, int level, unsigned char *data, int datalen) { - session->notsilenttx = 0; - return send_command(session, AST_FRAME_CNG, level, 0, data, datalen, -1); -} - -int iax_send_image(struct iax_session *session, int format, unsigned char *data, int datalen) { - /* Send an image frame */ - return send_command(session, AST_FRAME_IMAGE, format, 0, data, datalen, -1); -} - -int iax_register(struct iax_session *session, char *server, char *peer, char *secret, int refresh) { - /* Send a registration request */ - char tmp[256]; - char *p; - int res; - int portno = IAX_DEFAULT_PORTNO; - struct iax_ie_data ied; - struct hostent *hp; - - tmp[255] = '\0'; - strncpy(tmp, server, sizeof(tmp) - 1); - p = strchr(tmp, ':'); - if (p) { - *p = '\0'; - portno = atoi(p + 1); - } - - memset(&ied, 0, sizeof(ied)); - if (secret) - strncpy(session->secret, secret, sizeof(session->secret) - 1); - else - strcpy(session->secret, ""); - - /* Connect first */ - hp = gethostbyname(tmp); - if (!hp) { - snprintf(iax_errstr, sizeof(iax_errstr), "Invalid hostname: %s", tmp); - return -1; - } - memcpy(&session->peeraddr.sin_addr, hp->h_addr, sizeof(session->peeraddr.sin_addr)); - session->peeraddr.sin_port = htons((unsigned short) portno); - session->peeraddr.sin_family = AF_INET; - strncpy(session->username, peer, sizeof(session->username) - 1); - session->refresh = refresh; - iax_ie_append_str(&ied, IAX_IE_USERNAME, (unsigned char *) peer); - iax_ie_append_short(&ied, IAX_IE_REFRESH, (unsigned short) refresh); - res = send_command(session, AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); - return res; -} - -int iax_reject_registration(struct iax_session *session, char *reason) { - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - iax_ie_append_str(&ied, IAX_IE_CAUSE, reason ? (unsigned char *) reason : (unsigned char *) "Unspecified"); - return send_command_final(session, AST_FRAME_IAX, IAX_COMMAND_REGREJ, 0, ied.buf, ied.pos, -1); -} - -int iax_ack_registration(struct iax_session *session) { - return send_command_final(session, AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, NULL, 0, -1); -} - -int iax_auth_registration(struct iax_session *session) { - return send_command_final(session, AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, NULL, 0, -1); -} - -int iax_reject(struct iax_session *session, const char *reason) { - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - iax_ie_append_str(&ied, IAX_IE_CAUSE, reason ? (unsigned char *) reason : (unsigned char *) "Unspecified"); - return send_command_final(session, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1); -} - -int iax_hangup(struct iax_session *session, char *byemsg) { - struct iax_ie_data ied; - iax_sched_del(NULL, NULL, send_ping, (void *) session, 1); - memset(&ied, 0, sizeof(ied)); - iax_ie_append_str(&ied, IAX_IE_CAUSE, byemsg ? (unsigned char *) byemsg : (unsigned char *) "Normal clearing"); - return send_command_final(session, AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); -} - -int iax_sendurl(struct iax_session *session, char *url) { - return send_command(session, AST_FRAME_HTML, AST_HTML_URL, 0, (unsigned char *) url, (int) strlen(url), -1); -} - -int iax_ring_announce(struct iax_session *session) { - return send_command(session, AST_FRAME_CONTROL, AST_CONTROL_RINGING, 0, NULL, 0, -1); -} - -int iax_lag_request(struct iax_session *session) { - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1); -} - -int iax_busy(struct iax_session *session) { - return send_command(session, AST_FRAME_CONTROL, AST_CONTROL_BUSY, 0, NULL, 0, -1); -} - -int iax_congestion(struct iax_session *session) { - return send_command(session, AST_FRAME_CONTROL, AST_CONTROL_CONGESTION, 0, NULL, 0, -1); -} - - -int iax_accept(struct iax_session *session, int format) { - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - iax_ie_append_int(&ied, IAX_IE_FORMAT, format); - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied.buf, ied.pos, -1); -} - -int iax_answer(struct iax_session *session) { - return send_command(session, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); -} - -int iax_load_complete(struct iax_session *session) { - return send_command(session, AST_FRAME_HTML, AST_HTML_LDCOMPLETE, 0, NULL, 0, -1); -} - -int iax_send_url(struct iax_session *session, char *url, int link) { - return send_command(session, AST_FRAME_HTML, link ? AST_HTML_LINKURL : AST_HTML_URL, 0, (unsigned char *) url, (int) strlen(url), -1); -} - -int iax_send_text(struct iax_session *session, char *text) { - return send_command(session, AST_FRAME_TEXT, 0, 0, (unsigned char *) text, (int) strlen(text) + 1, -1); -} - -int iax_send_unlink(struct iax_session *session) { - return send_command(session, AST_FRAME_HTML, AST_HTML_UNLINK, 0, NULL, 0, -1); -} - -int iax_send_link_reject(struct iax_session *session) { - return send_command(session, AST_FRAME_HTML, AST_HTML_LINKREJECT, 0, NULL, 0, -1); -} - -static int iax_send_pong(struct iax_session *session, time_in_ms_t ts) { - struct iax_ie_data ied; - - memset(&ied, 0, sizeof(ied)); -#ifdef NEWJB - { - jb_info stats; - jb_getinfo(session->jb, &stats); - - iax_ie_append_int(&ied, IAX_IE_RR_JITTER, (int) stats.jitter); - /* XXX: should be short-term loss pct.. */ - if (stats.frames_in == 0) - stats.frames_in = 1; - iax_ie_append_int(&ied, IAX_IE_RR_LOSS, ((0xff & (stats.losspct / 1000)) << 24 | (stats.frames_lost & 0x00ffffff))); - iax_ie_append_int(&ied, IAX_IE_RR_PKTS, stats.frames_in); - iax_ie_append_short(&ied, IAX_IE_RR_DELAY, (unsigned short) (stats.current - stats.min)); - iax_ie_append_int(&ied, IAX_IE_RR_DROPPED, stats.frames_dropped); - iax_ie_append_int(&ied, IAX_IE_RR_OOO, stats.frames_ooo); - } -#else - iax_ie_append_int(&ied, IAX_IE_RR_JITTER, session->jitter); - /* don't know, don't send! iax_ie_append_int(&ied,IAX_IE_RR_LOSS, 0); */ - /* don't know, don't send! iax_ie_append_int(&ied,IAX_IE_RR_PKTS, stats.frames_in); */ - /* don't know, don't send! iax_ie_append_short(&ied,IAX_IE_RR_DELAY, stats.current - stats.min); */ -#endif - - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_PONG, ts, ied.buf, ied.pos, -1); -} - -/* external API; deprecated since we send pings ourselves now (finally) */ -int iax_send_ping(struct iax_session *session) { - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); -} - -/* scheduled ping sender; sends ping, then reschedules */ -static void send_ping(void *s) { - struct iax_session *session = (struct iax_session *) s; - - /* important, eh? */ - if (!iax_session_valid(session)) - return; - - send_command(session, AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); - session->pingid = iax_sched_add(NULL, NULL, send_ping, (void *) session, ping_time * 1000); - return; -} - -static int iax_send_lagrp(struct iax_session *session, time_in_ms_t ts) { - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_LAGRP, ts, NULL, 0, -1); -} - -static int iax_send_txcnt(struct iax_session *session) { - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - iax_ie_append_int(&ied, IAX_IE_TRANSFERID, session->transferid); - return send_command_transfer(session, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos); -} - -static int iax_send_txrej(struct iax_session *session) { - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - iax_ie_append_int(&ied, IAX_IE_TRANSFERID, session->transferid); - return send_command_transfer(session, AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, ied.buf, ied.pos); -} - -static int iax_send_txaccept(struct iax_session *session) { - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - iax_ie_append_int(&ied, IAX_IE_TRANSFERID, session->transferid); - return send_command_transfer(session, AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, ied.buf, ied.pos); -} - -static int iax_send_txready(struct iax_session *session) { - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - /* see asterisk chan_iax2.c */ - iax_ie_append_short(&ied, IAX_IE_CALLNO, (unsigned short) session->callno); - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied.buf, ied.pos, -1); -} - -int iax_auth_reply(struct iax_session *session, char *password, char *challenge, int methods) { - char reply[16]; - struct MD5Context md5; - char realreply[256]; - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - if ((methods & IAX_AUTH_MD5) && challenge) { - MD5Init(&md5); - MD5Update(&md5, (const unsigned char *) challenge, (unsigned int) strlen(challenge)); - MD5Update(&md5, (const unsigned char *) password, (unsigned int) strlen(password)); - MD5Final((unsigned char *) reply, &md5); - memset(realreply, 0, sizeof(realreply)); - convert_reply(realreply, (unsigned char *) reply); - iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, (unsigned char *) realreply); - } else { - iax_ie_append_str(&ied, IAX_IE_PASSWORD, (unsigned char *) password); - } - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1); -} - -static int iax_regauth_reply(struct iax_session *session, char *password, char *challenge, int methods) { - char reply[16]; - struct MD5Context md5; - char realreply[256]; - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - iax_ie_append_str(&ied, IAX_IE_USERNAME, (unsigned char *) session->username); - iax_ie_append_short(&ied, IAX_IE_REFRESH, (unsigned short) session->refresh); - if ((methods & IAX_AUTHMETHOD_MD5) && challenge) { - MD5Init(&md5); - MD5Update(&md5, (const unsigned char *) challenge, (unsigned int) strlen(challenge)); - MD5Update(&md5, (const unsigned char *) password, (unsigned int) strlen(password)); - MD5Final((unsigned char *) reply, &md5); - memset(realreply, 0, sizeof(realreply)); - convert_reply(realreply, (unsigned char *) reply); - iax_ie_append_str(&ied, IAX_IE_MD5_RESULT, (unsigned char *) realreply); - } else { - iax_ie_append_str(&ied, IAX_IE_PASSWORD, (unsigned char *) password); - } - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); -} - - -int iax_dial(struct iax_session *session, char *number) { - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, (unsigned char *) number); - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_DIAL, 0, ied.buf, ied.pos, -1); -} - -int iax_quelch(struct iax_session *session) { - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_QUELCH, 0, NULL, 0, -1); -} - -int iax_unquelch(struct iax_session *session) { - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_UNQUELCH, 0, NULL, 0, -1); -} - -int iax_dialplan_request(struct iax_session *session, char *number) { - struct iax_ie_data ied; - memset(&ied, 0, sizeof(ied)); - iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, (unsigned char *) number); - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1); -} - -static inline int which_bit(unsigned int i) { - unsigned char x; - for (x = 0; x < 32; x++) { - if ((unsigned) (1 << x) == i) { - return x + 1; - } - } - return 0; -} - -char iax_pref_codec_add(struct iax_session *session, unsigned int format) { - int diff = (int) 'A'; - session->codec_order[session->codec_order_len++] = (char) ((which_bit(format)) + diff); - session->codec_order[session->codec_order_len] = '\0'; - return session->codec_order[session->codec_order_len - 1]; -} - - -void iax_pref_codec_del(struct iax_session *session, unsigned int format) { - int diff = (int) 'A'; - size_t x; - char old[32]; - char remove = (char) (which_bit(format) + diff); - - strncpy(old, session->codec_order, sizeof(old)); - session->codec_order_len = 0; - - for (x = 0; x < strlen(old); x++) { - if (old[x] != remove) { - session->codec_order[session->codec_order_len++] = old[x]; - } - } - session->codec_order[session->codec_order_len] = '\0'; -} - -int iax_pref_codec_get(struct iax_session *session, unsigned int *array, int len) { - int diff = (int) 'A'; - int x; - - for (x = 0; x < session->codec_order_len && x < len; x++) { - array[x] = (1 << (session->codec_order[x] - diff - 1)); - } - - return x; -} - -void iax_set_samplerate(struct iax_session *session, unsigned short samplemask) { - session->samplemask = samplemask; -} - - -int iax_call(struct iax_session *session, const char *cidnum, const char *cidname, char *ich, char *lang, int wait, int formats, int capabilities) { - char tmp[256] = ""; - char *part1, *part2; - int res; - int portno; - char *username, *hostname, *secret, *context, *exten, *dnid; - struct iax_ie_data ied; - struct hostent *hp; - /* We start by parsing up the temporary variable which is of the form of: - [user@]peer[:portno][/exten[@context]] */ - if (!ich) { - IAXERROR "Invalid IAX Call Handle\n"); - DEBU(G "Invalid IAX Call Handle\n"); - return -1; - } - memset(&ied, 0, sizeof(ied)); - strncpy(tmp, ich, sizeof(tmp) - 1); - - iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); - if (session->samplemask) { - iax_ie_append_short(&ied, IAX_IE_SAMPLINGRATE, session->samplemask); - } - if (cidnum) - iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, (unsigned char *) cidnum); - if (cidname) - iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, (unsigned char *) cidname); - - if (session->codec_order_len) { - iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, (unsigned char *) session->codec_order); - } - - session->capability = capabilities; - session->pingid = iax_sched_add(NULL, NULL, send_ping, (void *) session, 2 * 1000); - - /* XXX We should have a preferred format XXX */ - iax_ie_append_int(&ied, IAX_IE_FORMAT, formats); - iax_ie_append_int(&ied, IAX_IE_CAPABILITY, capabilities); - if (lang) - iax_ie_append_str(&ied, IAX_IE_LANGUAGE, (unsigned char *) lang); - - /* Part 1 is [user[:password]@]peer[:port] */ - part1 = strtok(tmp, "/"); - - /* Part 2 is exten[@context] if it is anything all */ - part2 = strtok(NULL, "/"); - - if (strchr(part1, '@')) { - username = strtok(part1, "@"); - hostname = strtok(NULL, "@"); - } else { - username = NULL; - hostname = part1; - } - - if (username && strchr(username, ':')) { - username = strtok(username, ":"); - secret = strtok(NULL, ":"); - } else - secret = NULL; - - if (username) - strncpy(session->username, username, sizeof(session->username) - 1); - - if (secret) - strncpy(session->secret, secret, sizeof(session->secret) - 1); - - if (strchr(hostname, ':')) { - strtok(hostname, ":"); - portno = atoi(strtok(NULL, ":")); - } else { - portno = IAX_DEFAULT_PORTNO; - } - if (part2) { - exten = strtok(part2, "@"); - dnid = exten; - context = strtok(NULL, "@"); - } else { - exten = NULL; - dnid = NULL; - context = NULL; - } - if (username) - iax_ie_append_str(&ied, IAX_IE_USERNAME, (unsigned char *) username); - if (exten && strlen(exten)) - iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, (unsigned char *) exten); - if (dnid && strlen(dnid)) - iax_ie_append_str(&ied, IAX_IE_DNID, (unsigned char *) dnid); - if (context && strlen(context)) - iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, (unsigned char *) context); - - /* Setup host connection */ - hp = gethostbyname(hostname); - if (!hp) { - snprintf(iax_errstr, sizeof(iax_errstr), "Invalid hostname: %s", hostname); - return -1; - } - memcpy(&session->peeraddr.sin_addr, hp->h_addr, sizeof(session->peeraddr.sin_addr)); - session->peeraddr.sin_port = htons((unsigned short) portno); - session->peeraddr.sin_family = AF_INET; - res = send_command(session, AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); - if (res < 0) - return res; - if (wait) { - DEBU(G "Waiting not yet implemented\n"); - return -1; - } - return res; -} - -static time_in_ms_t calc_rxstamp(struct iax_session *session) { - time_in_ms_t time_in_ms; - - time_in_ms = current_time_in_ms(); - - if (!session->rxcore) { - session->rxcore = time_in_ms; - } - - return time_in_ms - session->rxcore; -} - -#ifdef notdef_cruft -static int match(struct sockaddr_in *sin, short callno, short dcallno, struct iax_session *cur) { - if ((cur->peeraddr.sin_addr.s_addr == sin->sin_addr.s_addr) && (cur->peeraddr.sin_port == sin->sin_port)) { - /* This is the main host */ - if ((cur->peercallno == callno) || ((dcallno == cur->callno) && !cur->peercallno)) { - /* That's us. Be sure we keep track of the peer call number */ - cur->peercallno = callno; - return 1; - } - } - if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { - /* We're transferring */ - if (dcallno == cur->callno) - return 1; - } - return 0; -} -#endif - -/* splitted match into 2 passes otherwise causing problem of matching - up the wrong session using the dcallno and the peercallno because - during a transfer (2 IAX channels on the same client/system) the - same peercallno (from two different asterisks) exist in more than - one session. - */ -static int forward_match(struct sockaddr_in *sin, short callno, short dcallno, struct iax_session *cur) { - if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { - /* We're transferring */ - if (dcallno == cur->callno) { - return 1; - } - } - - if ((cur->peeraddr.sin_addr.s_addr == sin->sin_addr.s_addr) && (cur->peeraddr.sin_port == sin->sin_port)) { - if (dcallno == cur->callno && dcallno != 0) { - /* That's us. Be sure we keep track of the peer call number */ - if (cur->peercallno == 0) { - cur->peercallno = callno; - } - return 1; - } - } - - return 0; -} - -static int reverse_match(struct sockaddr_in *sin, short callno, struct iax_session *cur) { - if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { - /* We're transferring */ - if (callno == cur->peercallno) { - return 1; - } - } - if ((cur->peeraddr.sin_addr.s_addr == sin->sin_addr.s_addr) && (cur->peeraddr.sin_port == sin->sin_port)) { - if (callno == cur->peercallno) { - return 1; - } - } - - return 0; -} - -static struct iax_session *iax_find_session(struct sockaddr_in *sin, short callno, short dcallno, int makenew) { - struct iax_session *cur; - - iax_mutex_lock(session_mutex); - cur = sessions; - while (cur) { - if (forward_match(sin, callno, dcallno, cur)) { - iax_mutex_unlock(session_mutex); - return cur; - } - cur = cur->next; - } - - cur = sessions; - while (cur) { - if (reverse_match(sin, callno, cur)) { - iax_mutex_unlock(session_mutex); - return cur; - } - cur = cur->next; - } - - iax_mutex_unlock(session_mutex); - - if (makenew && !dcallno) { - cur = iax_session_new(); - cur->peercallno = callno; - cur->peeraddr.sin_addr.s_addr = sin->sin_addr.s_addr; - cur->peeraddr.sin_port = sin->sin_port; - cur->peeraddr.sin_family = AF_INET; - cur->pingid = iax_sched_add(NULL, NULL, send_ping, (void *) cur, 2 * 1000); - DEBU(G "Making new session, peer callno %d, our callno %d\n", callno, cur->callno); - } else { - DEBU(G "No session, peer = %d, us = %d\n", callno, dcallno); - } - - return cur; -} - -#ifdef EXTREME_DEBUG -static int display_time(int ms) { - static int oldms = -1; - if (oldms < 0) { - DEBU(G "First measure\n"); - oldms = ms; - return 0; - } - DEBU(G "Time from last frame is %d ms\n", ms - oldms); - oldms = ms; - return 0; -} -#endif - -#define FUDGE 1 - -#ifdef NEWJB -/* From chan_iax2/steve davies: need to get permission from steve or digium, I guess */ -static time_in_ms_t unwrap_timestamp(time_in_ms_t ts, time_in_ms_t last) { - time_in_ms_t x; - - if ((ts & 0xFFFF0000) == (last & 0xFFFF0000)) { - x = ts - last; - if (x < -50000) { - /* Sudden big jump backwards in timestamp: - What likely happened here is that miniframe timestamp has circled but we haven't - gotten the update from the main packet. We'll just pretend that we did, and - update the timestamp appropriately. */ - ts = ((last & 0xFFFF0000) + 0x10000) | (ts & 0xFFFF); - DEBU(G "schedule_delivery: pushed forward timestamp\n"); - } - if (x > 50000) { - /* Sudden apparent big jump forwards in timestamp: - What's likely happened is this is an old miniframe belonging to the previous - top-16-bit timestamp that has turned up out of order. - Adjust the timestamp appropriately. */ - ts = ((last & 0xFFFF0000) - 0x10000) | (ts & 0xFFFF); - DEBU(G "schedule_delivery: pushed back timestamp\n"); - } - } - return ts; -} -#endif - - -static struct iax_event *schedule_delivery(struct iax_event *e, time_in_ms_t ts, int updatehistory) { - /* - * This is the core of the IAX jitterbuffer delivery mechanism: - * Dynamically adjust the jitterbuffer and decide how time_in_ms_t to wait - * before delivering the packet. - */ -#ifndef NEWJB - int ms, x; - int drops[MEMORY_SIZE]; - int min, max = 0, maxone = 0, y, z, match; -#endif - -#ifdef EXTREME_DEBUG - DEBU(G "[%p] We are at %d, packet is for %d\n", e->session, calc_rxstamp(e->session), ts); -#endif - -#ifdef VOICE_SMOOTHING - if (e->etype == IAX_EVENT_VOICE) { - /* Smooth voices if we know enough about the format */ - switch (e->event.voice.format) { - case AST_FORMAT_GSM: - /* GSM frames are 20 ms long, although there could be periods of - silence. If the time is < 50 ms, assume it ought to be 20 ms */ - if (ts - e->session->lastts < 50) - ts = e->session->lastts + 20; -#ifdef EXTREME_DEBUG - display_time(ts); -#endif - break; - default: - /* Can't do anything */ - } - e->session->lastts = ts; - } -#endif - -#ifdef NEWJB - { - int type = JB_TYPE_CONTROL; - int len = 0; - - if (e->etype == IAX_EVENT_VOICE) { - type = JB_TYPE_VOICE; - len = get_sample_cnt(e) / 8; - } else if (e->etype == IAX_EVENT_CNG) { - type = JB_TYPE_SILENCE; - } - - /* unwrap timestamp */ - ts = unwrap_timestamp(ts, e->session->last_ts); - - /* move forward last_ts if it's greater. We do this _after_ unwrapping, because - * asterisk _still_ has cases where it doesn't send full frames when it ought to */ - if (ts > e->session->last_ts) { - e->session->last_ts = ts; - } - - - /* insert into jitterbuffer */ - /* TODO: Perhaps we could act immediately if it's not droppable and late */ - if (jb_put(e->session->jb, e, type, len, ts, calc_rxstamp(e->session)) == JB_DROP) { - iax_event_free(e); - } - - } -#else - - /* How many ms from now should this packet be delivered? (remember - this can be a negative number, too */ - ms = (int) (calc_rxstamp(e->session) - ts); - - /* - Drop voice frame if timestamp is way off - if ((e->etype == IAX_EVENT_VOICE) && ((ms > 65536) || (ms < -65536))) { - DEBU(G "Dropping a voice packet with odd ts (ts = %d; ms = %d)\n", ts, ms); - free(e); - return NULL; - } - */ - - /* Adjust if voice frame timestamp is off by a step */ - if (ms > 32768) { - /* What likely happened here is that our counter has circled but we haven't - gotten the update from the main packet. We'll just pretend that we did, and - update the timestamp appropriately. */ - ms -= 65536; - } - if (ms < -32768) { - /* We got this packet out of order. Lets add 65536 to it to bring it into our new - time frame */ - ms += 65536; - } -#if 0 - printf("rxstamp is %d, timestamp is %d, ms is %d\n", calc_rxstamp(e->session), ts, ms); -#endif - /* Rotate history queue. Leading 0's are irrelevant. */ - if (updatehistory) { - for (x = 0; x < MEMORY_SIZE - 1; x++) - e->session->history[x] = e->session->history[x + 1]; - - /* Add new entry for this time */ - e->session->history[x] = ms; - } - - /* We have to find the maximum and minimum time delay we've had to deliver. */ - min = e->session->history[0]; - for (z = 0; z < iax_dropcount + 1; z++) { - /* We drop the top iax_dropcount entries. iax_dropcount represents - a tradeoff between quality of voice and latency. 3% drop seems to - be unnoticable to the client and can significantly improve latency. - We add one more to our droplist, but that's the one we actually use, - and don't drop. */ - max = -99999999; - for (x = 0; x < MEMORY_SIZE; x++) { - if (max < e->session->history[x]) { - /* New candidate value. Make sure we haven't dropped it. */ - match = 0; - for (y = 0; !match && (y < z); y++) - match |= (drops[y] == x); - /* If there is no match, this is our new maximum */ - if (!match) { - max = e->session->history[x]; - maxone = x; - } - } - if (!z) { - /* First pass, calcualte our minimum, too */ - if (min > e->session->history[x]) - min = e->session->history[x]; - } - } - drops[z] = maxone; - } - /* Again, just for reference. The "jitter buffer" is the max. The difference - is the perceived jitter correction. */ - e->session->jitter = max - min; - - /* If the jitter buffer is substantially too large, shrink it, slowly enough - that the client won't notice ;-) . */ - if (max < e->session->jitterbuffer - max_extra_jitterbuffer) { -#ifdef EXTREME_DEBUG - DEBU(G "Shrinking jitterbuffer (target = %d, current = %d...\n", max, e->session->jitterbuffer); -#endif - e->session->jitterbuffer -= 1; - } - - /* Keep the jitter buffer from becoming unreasonably large */ - if (max > min + max_jitterbuffer) { - DEBU(G "Constraining jitter buffer (min = %d, max = %d)...\n", min, max); - max = min + max_jitterbuffer; - } - - /* If the jitter buffer is too small, we immediately grow our buffer to - accomodate */ - if (max > e->session->jitterbuffer) - e->session->jitterbuffer = max; - - /* Start with our jitter buffer delay, and subtract the lateness (or earliness). - Remember these times are all relative to the first packet, so their absolute - values are really irrelevant. */ - ms = e->session->jitterbuffer - ms - IAX_SCHEDULE_FUZZ; - - /* If the jitterbuffer is disabled, always deliver immediately */ - if (!iax_use_jitterbuffer) - ms = 0; - - if (ms < 1) { -#ifdef EXTREME_DEBUG - DEBU(G "Calculated delay is only %d\n", ms); -#endif - if ((ms > -4) || (e->etype != IAX_EVENT_VOICE)) { - /* Return the event immediately if it's it's less than 3 milliseconds - too late, or if it's not voice (believe me, you don't want to - just drop a hangup frame because it's late, or a ping, or some such. - That kinda ruins retransmissions too ;-) */ - /* Queue for immediate delivery */ - iax_sched_add(e, NULL, NULL, NULL, 0); - return NULL; - //return e; - } - DEBU(G "(not so) Silently dropping a packet (ms = %d)\n", ms); - /* Silently discard this as if it were to be delivered */ - free(e); - return NULL; - } - /* We need this to be delivered in the future, so we use our scheduler */ - iax_sched_add(e, NULL, NULL, NULL, ms); -#ifdef EXTREME_DEBUG - DEBU(G "Delivering packet in %d ms\n", ms); -#endif -#endif /* NEWJB */ - return NULL; - -} - -static int uncompress_subclass(unsigned char csub) { - /* If the SC_LOG flag is set, return 2^csub otherwise csub */ - if (csub & IAX_FLAG_SC_LOG) - return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT); - else - return csub; -} - -static inline char *extract(char *src, char *string) { - /* Extract and duplicate what we need from a string */ - char *s, *t; - s = strstr(src, string); - if (s) { - s += strlen(string); - s = strdup(s); - /* End at ; */ - t = strchr(s, ';'); - if (t) { - *t = '\0'; - } - } - return s; - -} - -static struct iax_event *iax_header_to_event(struct iax_session *session, struct ast_iax2_full_hdr *fh, int datalen, struct sockaddr_in *sin) { - struct iax_event *e; - struct iax_sched *sch; - unsigned int ts; - int subclass = uncompress_subclass(fh->csub); - time_in_ms_t nowts; - int updatehistory = 1; - ts = ntohl(fh->ts); - /* don't run last_ts backwards; i.e. for retransmits and the like */ - if (ts > session->last_ts && - (fh->type == AST_FRAME_IAX && subclass != IAX_COMMAND_ACK && subclass != IAX_COMMAND_PONG && subclass != IAX_COMMAND_LAGRP)) { - session->last_ts = ts; - } - -#ifdef DEBUG_SUPPORT - iax_showframe(NULL, fh, 1, sin, datalen); -#endif - - /* Get things going with it, timestamp wise, if we - haven't already. */ - - /* Handle implicit ACKing unless this is an INVAL, and only if this is - from the real peer, not the transfer peer */ - if (!inaddrcmp(sin, &session->peeraddr) && (((subclass != IAX_COMMAND_INVAL)) || (fh->type != AST_FRAME_IAX))) { - unsigned char x; - /* XXX This code is not very efficient. Surely there is a better way which still - properly handles boundary conditions? XXX */ - /* First we have to qualify that the ACKed value is within our window */ - for (x = session->rseqno; x != session->oseqno; x++) - if (fh->iseqno == x) - break; - if ((x != session->oseqno) || (session->oseqno == fh->iseqno)) { - /* The acknowledgement is within our window. Time to acknowledge everything - that it says to */ - for (x = session->rseqno; x != fh->iseqno; x++) { - /* Ack the packet with the given timestamp */ - DEBU(G "Cancelling transmission of packet %d\n", x); - iax_mutex_lock(sched_mutex); - sch = schedq; - while (sch) { - if (sch->frame && (sch->frame->session == session) && (sch->frame->oseqno == x)) - sch->frame->retries = -1; - sch = sch->next; - } - iax_mutex_unlock(sched_mutex); - } - /* Note how much we've received acknowledgement for */ - session->rseqno = fh->iseqno; - } else - DEBU(G "Received iseqno %d not within window %d->%d\n", fh->iseqno, session->rseqno, session->oseqno); - } - - /* Check where we are */ - if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (fh->type != AST_FRAME_VOICE)) - updatehistory = 0; - if ((session->iseqno != fh->oseqno) && - (session->iseqno || - ((subclass != IAX_COMMAND_TXREADY) && - (subclass != IAX_COMMAND_TXREL) && (subclass != IAX_COMMAND_TXCNT) && (subclass != IAX_COMMAND_TXACC)) || (fh->type != AST_FRAME_IAX))) { - if (((subclass != IAX_COMMAND_ACK) && - (subclass != IAX_COMMAND_INVAL) && - (subclass != IAX_COMMAND_TXREADY) && - (subclass != IAX_COMMAND_TXREL) && - (subclass != IAX_COMMAND_TXCNT) && (subclass != IAX_COMMAND_TXACC) && (subclass != IAX_COMMAND_VNAK)) || (fh->type != AST_FRAME_IAX)) { - /* If it's not an ACK packet, it's out of order. */ - DEBU(G "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", - session->iseqno, fh->oseqno, fh->type, subclass); - if (session->iseqno > fh->oseqno) { - /* If we've already seen it, ack it XXX There's a border condition here XXX */ - if ((fh->type != AST_FRAME_IAX) || ((subclass != IAX_COMMAND_ACK) && (subclass != IAX_COMMAND_INVAL))) { - DEBU(G "Acking anyway\n"); - /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if - we have anything to send, we'll retransmit and get an ACK back anyway XXX */ - send_command_immediate(session, AST_FRAME_IAX, IAX_COMMAND_ACK, ts, NULL, 0, fh->iseqno); - } - } else { - /* Send a VNAK requesting retransmission */ - iax2_vnak(session); - } - return NULL; - } - } else { - /* Increment unless it's an ACK or VNAK */ - if (((subclass != IAX_COMMAND_ACK) && - (subclass != IAX_COMMAND_INVAL) && - (subclass != IAX_COMMAND_TXCNT) && (subclass != IAX_COMMAND_TXACC) && (subclass != IAX_COMMAND_VNAK)) || (fh->type != AST_FRAME_IAX)) - session->iseqno++; - } - - e = (struct iax_event *) malloc(sizeof(struct iax_event) + datalen + 1); - - if (e) { - memset(e, 0, sizeof(struct iax_event) + datalen); - /* Set etype to some unknown value so do not inavertently - sending IAX_EVENT_CONNECT event, which is 0 to application. - */ - e->etype = -1; - e->session = session; - switch (fh->type) { - case AST_FRAME_DTMF: - e->etype = IAX_EVENT_DTMF; - e->subclass = subclass; - /* - We want the DTMF event deliver immediately so all I/O can be - terminate quickly in an IVR system. - e = schedule_delivery(e, ts, updatehistory); */ - break; - case AST_FRAME_VOICE: - e->etype = IAX_EVENT_VOICE; - e->subclass = subclass; - session->voiceformat = subclass; - if (datalen) { - memcpy(e->data, fh->iedata, datalen); - e->datalen = datalen; - } - e = schedule_delivery(e, ts, updatehistory); - break; - case AST_FRAME_CNG: - e->etype = IAX_EVENT_CNG; - e->subclass = subclass; - if (datalen) { - memcpy(e->data, fh->iedata, datalen); - e->datalen = datalen; - } - e = schedule_delivery(e, ts, updatehistory); - break; - case AST_FRAME_IAX: - /* Parse IE's */ - if (datalen) { - memcpy(e->data, fh->iedata, datalen); - e->datalen = datalen; - } - if (iax_parse_ies(&e->ies, e->data, e->datalen)) { - IAXERROR "Unable to parse IE's"); - free(e); - e = NULL; - break; - } - switch (subclass) { - case IAX_COMMAND_NEW: - /* This is a new, incoming call */ - /* save the capability for validation */ - session->capability = e->ies.capability; - if (e->ies.codec_prefs) { - strncpy(session->codec_order, e->ies.codec_prefs, sizeof(session->codec_order)); - session->codec_order_len = (int) strlen(session->codec_order); - } - e->etype = IAX_EVENT_CONNECT; - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_AUTHREQ: - /* This is a request for a call */ - e->etype = IAX_EVENT_AUTHRQ; - if (strlen(session->username) && !strcmp(e->ies.username, session->username) && strlen(session->secret)) { - /* Hey, we already know this one */ - iax_auth_reply(session, session->secret, e->ies.challenge, e->ies.authmethods); - free(e); - e = NULL; - break; - } - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_HANGUP: - e->etype = IAX_EVENT_HANGUP; - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_INVAL: - e->etype = IAX_EVENT_HANGUP; - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_REJECT: - e->etype = IAX_EVENT_REJECT; - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_ACK: - free(e); - e = NULL; - break; - case IAX_COMMAND_LAGRQ: - /* Pass this atime_in_ms_t for later handling */ - e->etype = IAX_EVENT_LAGRQ; - e->ts = ts; - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_POKE: - e->etype = IAX_EVENT_POKE; - e->ts = ts; - break; - case IAX_COMMAND_PING: - /* PINGS and PONGS don't get scheduled; */ - e->etype = IAX_EVENT_PING; - e->ts = ts; - break; - case IAX_COMMAND_PONG: - e->etype = IAX_EVENT_PONG; - /* track weighted average of ping time */ - session->pingtime = ((2 * session->pingtime) + (calc_timestamp(session, 0, NULL) - ts)) / 3; - session->remote_netstats.jitter = e->ies.rr_jitter; - session->remote_netstats.losspct = e->ies.rr_loss >> 24;; - session->remote_netstats.losscnt = e->ies.rr_loss & 0xffffff; - session->remote_netstats.packets = e->ies.rr_pkts; - session->remote_netstats.delay = e->ies.rr_delay; - session->remote_netstats.dropped = e->ies.rr_dropped; - session->remote_netstats.ooo = e->ies.rr_ooo; - break; - case IAX_COMMAND_ACCEPT: - if (e->ies.format & session->capability) { - e->etype = IAX_EVENT_ACCEPT; - } else { - struct iax_ie_data ied; - /* Although this should not happen, we added this to make sure - the negotiation protocol is enforced. - For lack of event to notify the application we use the defined - REJECT event. - */ - memset(&ied, 0, sizeof(ied)); - iax_ie_append_str(&ied, IAX_IE_CAUSE, (unsigned char *) "Unable to negotiate codec"); - send_command_final(session, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1); - e->etype = IAX_EVENT_REJECT; - } - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_REGREQ: - e->etype = IAX_EVENT_REGREQ; - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_REGREL: - e->etype = IAX_EVENT_REGREQ; - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_REGACK: - e->etype = IAX_EVENT_REGACK; - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_REGAUTH: - iax_regauth_reply(session, session->secret, e->ies.challenge, e->ies.authmethods); - free(e); - e = NULL; - break; - case IAX_COMMAND_REGREJ: - e->etype = IAX_EVENT_REGREJ; - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_LAGRP: - e->etype = IAX_EVENT_LAGRP; - nowts = calc_timestamp(session, 0, NULL); - e->ts = nowts - ts; - e->subclass = session->jitter; - /* Can't call schedule_delivery since timestamp is non-normal */ - break;; - case IAX_COMMAND_TXREQ: - /* added check for defensive programming - * - in case the asterisk server - * or another client does not send the - * apparent transfer address - */ - if (e->ies.apparent_addr != NULL) { - /* so a full voice frame is sent on the - next voice output */ - session->svoiceformat = -1; - session->transfer = *e->ies.apparent_addr; - session->transfer.sin_family = AF_INET; - session->transfercallno = e->ies.callno; - session->transferring = TRANSFER_BEGIN; - session->transferid = e->ies.transferid; - iax_send_txcnt(session); - } - free(e); - e = NULL; - break; - case IAX_COMMAND_DPREP: - /* Received dialplan reply */ - e->etype = IAX_EVENT_DPREP; - /* Return immediately, makes no sense to schedule */ - break; - case IAX_COMMAND_TXCNT: - if (session->transferring) { - session->transfer = *sin; - iax_send_txaccept(session); - } - free(e); - e = NULL; - break; - case IAX_COMMAND_TXACC: - if (session->transferring) { - stop_transfer(session); - session->transferring = TRANSFER_READY; - iax_send_txready(session); - } - free(e); - e = NULL; - break; - case IAX_COMMAND_TXREL: - /* Release the transfer */ - send_command_immediate(session, AST_FRAME_IAX, IAX_COMMAND_ACK, fh->ts, NULL, 0, fh->iseqno); - if (session->transferring) { - complete_transfer(session, e->ies.callno, 1, 0); - } else { - complete_transfer(session, session->peercallno, 0, 1); - } - e->etype = IAX_EVENT_TRANSFER; - /* notify that asterisk no longer sitting between peers */ - e = schedule_delivery(e, ts, updatehistory); - break; - case IAX_COMMAND_QUELCH: - e->etype = IAX_EVENT_QUELCH; - session->quelch = 1; - break; - case IAX_COMMAND_UNQUELCH: - e->etype = IAX_EVENT_UNQUELCH; - session->quelch = 0; - break; - case IAX_COMMAND_TXREJ: - e->etype = IAX_EVENT_TXREJECT; - iax_handle_txreject(session); - break; - - case IAX_COMMAND_TXREADY: - send_command_immediate(session, AST_FRAME_IAX, IAX_COMMAND_ACK, ts, NULL, 0, fh->iseqno); - if (iax_handle_txready(session)) { - e->etype = IAX_EVENT_TXREADY; - } else { - free(e); - e = NULL; - } - break; - default: - DEBU(G "Don't know what to do with IAX command %d\n", subclass); - free(e); - e = NULL; - } - break; - case AST_FRAME_CONTROL: - switch (subclass) { - case AST_CONTROL_ANSWER: - e->etype = IAX_EVENT_ANSWER; - e = schedule_delivery(e, ts, updatehistory); - break; - case AST_CONTROL_CONGESTION: - case AST_CONTROL_BUSY: - e->etype = IAX_EVENT_BUSY; - e = schedule_delivery(e, ts, updatehistory); - break; - case AST_CONTROL_RINGING: - e->etype = IAX_EVENT_RINGA; - e = schedule_delivery(e, ts, updatehistory); - break; - default: - DEBU(G "Don't know what to do with AST control %d\n", subclass); - free(e); - return NULL; - } - break; - case AST_FRAME_IMAGE: - e->etype = IAX_EVENT_IMAGE; - e->subclass = subclass; - if (datalen) { - memcpy(e->data, fh->iedata, datalen); - } - e = schedule_delivery(e, ts, updatehistory); - break; - - case AST_FRAME_TEXT: - e->etype = IAX_EVENT_TEXT; - if (datalen) { - memcpy(e->data, fh->iedata, datalen); - } - e = schedule_delivery(e, ts, updatehistory); - break; - - case AST_FRAME_HTML: - switch (fh->csub) { - case AST_HTML_LINKURL: - e->etype = IAX_EVENT_LINKURL; - /* Fall through */ - case AST_HTML_URL: - if (e->etype == -1) - e->etype = IAX_EVENT_URL; - e->subclass = fh->csub; - e->datalen = datalen; - if (datalen) { - memcpy(e->data, fh->iedata, datalen); - } - e = schedule_delivery(e, ts, updatehistory); - break; - case AST_HTML_LDCOMPLETE: - e->etype = IAX_EVENT_LDCOMPLETE; - e = schedule_delivery(e, ts, updatehistory); - break; - case AST_HTML_UNLINK: - e->etype = IAX_EVENT_UNLINK; - e = schedule_delivery(e, ts, updatehistory); - break; - case AST_HTML_LINKREJECT: - e->etype = IAX_EVENT_LINKREJECT; - e = schedule_delivery(e, ts, updatehistory); - break; - default: - DEBU(G "Don't know how to handle HTML type %d frames\n", fh->csub); - free(e); - return NULL; - } - break; - default: - DEBU(G "Don't know what to do with frame type %d\n", fh->type); - free(e); - return NULL; - } - } else - DEBU(G "Out of memory\n"); - - /* Already ack'd iax frames */ - if (session->aseqno != session->iseqno) { - send_command_immediate(session, AST_FRAME_IAX, IAX_COMMAND_ACK, ts, NULL, 0, fh->iseqno); - } - return e; -} - -static struct iax_event *iax_miniheader_to_event(struct iax_session *session, struct ast_iax2_mini_hdr *mh, int datalen) { - struct iax_event *e; - time_in_ms_t ts; - int updatehistory = 1; - e = (struct iax_event *) malloc(sizeof(struct iax_event) + datalen); - if (e) { - if (session->voiceformat > 0) { - e->etype = IAX_EVENT_VOICE; - e->session = session; - e->subclass = session->voiceformat; - e->datalen = datalen; - if (datalen) { -#ifdef EXTREME_DEBUG - DEBU(G "%d bytes of voice\n", datalen); -#endif - memcpy(e->data, mh->data, datalen); - } - ts = (session->last_ts & 0xFFFF0000) | ntohs(mh->ts); - return schedule_delivery(e, ts, updatehistory); - } else { - DEBU(G "No last format received on session %d\n", session->callno); - free(e); - e = NULL; - } - } else - DEBU(G "Out of memory\n"); - return e; -} - -void iax_destroy(struct iax_session *session) { - iax_mutex_lock(session_mutex); - destroy_session(session); - iax_mutex_unlock(session_mutex); -} - -static struct iax_event *iax_net_read(void) { - unsigned char buf[65536]; - int res; -#ifndef __Linux__ - socklen_t sinlen; -#else - unsigned int sinlen; -#endif - struct sockaddr_in sin; - - sinlen = sizeof(sin); - res = iax_recvfrom(netfd, (char *) buf, sizeof(buf), 0, (struct sockaddr *) &sin, &sinlen); - - if (res < 0) { -#ifdef WIN32 - if (WSAGetLastError() != WSAEWOULDBLOCK) { - DEBU(G "Error on read: %d\n", WSAGetLastError()); - IAXERROR "Read error on network socket: %s", strerror(errno)); - } -#else - if (errno != EAGAIN) { - DEBU(G "Error on read: %s\n", strerror(errno)); - IAXERROR "Read error on network socket: %s", strerror(errno)); - } -#endif - return NULL; - } - return iax_net_process(buf, res, &sin); -} - -static struct iax_session *iax_txcnt_session(struct ast_iax2_full_hdr *fh, int datalen, struct sockaddr_in *sin, short callno, short dcallno) { - int subclass = uncompress_subclass(fh->csub); - unsigned char buf[65536]; /* allocated on stack with same size as iax_net_read() */ - struct iax_ies ies; - struct iax_session *cur; - - if ((fh->type != AST_FRAME_IAX) || (subclass != IAX_COMMAND_TXCNT) || (!datalen)) { - return NULL; /* special handling for TXCNT only */ - } - memcpy(buf, fh->iedata, datalen); /* prepare local buf for iax_parse_ies() */ - - if (iax_parse_ies(&ies, buf, datalen)) { - return NULL; /* Unable to parse IE's */ - } - if (!ies.transferid) { - return NULL; /* TXCNT without proper IAX_IE_TRANSFERID */ - } - iax_mutex_lock(session_mutex); - for (cur = sessions; cur; cur = cur->next) { - if ((cur->transferring) && (cur->transferid == (int) ies.transferid) && (cur->callno == dcallno) && (cur->transfercallno == callno)) { - /* We're transferring --- - * skip address/port checking which would fail while remote peer behind symmetric NAT - * verify transferid instead - */ - cur->transfer.sin_addr.s_addr = sin->sin_addr.s_addr; /* setup for further handling */ - cur->transfer.sin_port = sin->sin_port; - break; - } - } - iax_mutex_unlock(session_mutex); - return cur; -} - -struct iax_event *iax_net_process(unsigned char *buf, int len, struct sockaddr_in *sin) { - struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *) buf; - struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *) buf; - struct iax_session *session; - - if (ntohs(fh->scallno) & IAX_FLAG_FULL) { - int subclass = uncompress_subclass(fh->csub); - int makenew = 0; - - /* Full size header */ - if (len < sizeof(struct ast_iax2_full_hdr)) { - DEBU(G "Short header received from %s\n", inet_ntoa(sin->sin_addr)); - IAXERROR "Short header received from %s\n", inet_ntoa(sin->sin_addr)); - return NULL; - } - /* Only allow it to make new sessions on types where that makes sense */ - if ((fh->type == AST_FRAME_IAX) && ((subclass == IAX_COMMAND_NEW) || - (subclass == IAX_COMMAND_POKE) || (subclass == IAX_COMMAND_REGREL) || (subclass == IAX_COMMAND_REGREQ))) { - makenew = 1; - } - - /* We have a full header, process appropriately */ - session = iax_find_session(sin, ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, makenew); - if (!session) - session = - iax_txcnt_session(fh, len - sizeof(struct ast_iax2_full_hdr), sin, ntohs(fh->scallno) & ~IAX_FLAG_FULL, - ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS); - if (session) - return iax_header_to_event(session, fh, len - sizeof(struct ast_iax2_full_hdr), sin); - /* if we get here, the frame was invalid for some reason, we should probably send IAX_COMMAND_INVAL (as long as the subclass was not already IAX_COMMAND_INVAL) */ - DEBU(G "No session?\n"); - return NULL; - } else { - if (len < sizeof(struct ast_iax2_mini_hdr)) { - DEBU(G "Short header received from %s\n", inet_ntoa(sin->sin_addr)); - IAXERROR "Short header received from %s\n", inet_ntoa(sin->sin_addr)); - return NULL; - } - /* Miniature, voice frame */ - session = iax_find_session(sin, ntohs(fh->scallno), 0, 0); - if (session) - return iax_miniheader_to_event(session, mh, len - sizeof(struct ast_iax2_mini_hdr)); - DEBU(G "No session?\n"); - return NULL; - } -} - -static struct iax_sched *iax_get_sched(time_in_ms_t time_in_ms) { - struct iax_sched *cur, *prev = NULL; - iax_mutex_lock(sched_mutex); - cur = schedq; - /* Check the event schedule first. */ - while (cur) { - if (time_in_ms > cur->when) { - /* Take it out of the event queue */ - if (prev) { - prev->next = cur->next; - } else { - schedq = cur->next; - } - iax_mutex_unlock(sched_mutex); - return cur; - } - cur = cur->next; - } - iax_mutex_unlock(sched_mutex); - return NULL; -} - -struct iax_event *iax_get_event(int blocking) { - struct iax_event *event; - struct iax_frame *frame; - time_in_ms_t time_in_ms; - struct iax_sched *cur; - - if (do_shutdown) { - __iax_shutdown(); - do_shutdown = 0; - return NULL; - } - time_in_ms = current_time_in_ms(); - while ((cur = iax_get_sched(time_in_ms))) { - - event = cur->event; - frame = cur->frame; - if (event) { - - /* See if this is an event we need to handle */ - event = handle_event(event); - if (event) { - free(cur); - return event; - } - } else if (frame) { - /* It's a frame, transmit it and schedule a retry */ - if (frame->retries < 0) { - /* It's been acked. No need to send it. Destroy the old - frame. If final, destroy the session. */ - if (frame->final) { - iax_mutex_lock(session_mutex); - destroy_session(frame->session); - iax_mutex_unlock(session_mutex); - } - if (frame->data) - free(frame->data); - free(frame); - } else if (frame->retries == 0) { - if (frame->transfer) { - /* Send a transfer reject since we weren't able to connect */ - iax_send_txrej(frame->session); - if (frame->data) - free(frame->data); - free(frame); - free(cur); - break; - } else { - /* We haven't been able to get an ACK on this packet. If a - final frame, destroy the session, otherwise, pass up timeout */ - if (frame->final) { - iax_mutex_lock(session_mutex); - destroy_session(frame->session); - iax_mutex_unlock(session_mutex); - if (frame->data) - free(frame->data); - free(frame); - } else { - event = (struct iax_event *) malloc(sizeof(struct iax_event)); - if (event) { - event->etype = IAX_EVENT_TIMEOUT; - event->session = frame->session; - if (frame->data) - free(frame->data); - free(frame); - free(cur); - return handle_event(event); - } - } - } - } else { - struct ast_iax2_full_hdr *fh; - /* Decrement remaining retries */ - frame->retries--; - /* Multiply next retry time by 4, not above MAX_RETRY_TIME though */ - frame->retrytime *= 4; - /* Keep under 1000 ms if this is a transfer packet */ - if (!frame->transfer) { - if (frame->retrytime > MAX_RETRY_TIME) - frame->retrytime = MAX_RETRY_TIME; - } else if (frame->retrytime > 1000) - frame->retrytime = 1000; - fh = (struct ast_iax2_full_hdr *) (frame->data); - fh->dcallno = htons(IAX_FLAG_RETRANS | frame->dcallno); - iax_xmit_frame(frame); - /* Schedule another retransmission */ - DEBU(G "Scheduling retransmission %d\n", frame->retries); - iax_sched_add(NULL, frame, NULL, NULL, frame->retrytime); - } - } else if (cur->func) { - cur->func(cur->arg); - } - free(cur); - } - -#ifdef NEWJB - /* get jitterbuffer-scheduled events */ - { - struct iax_session *cur; - jb_frame frame; - iax_mutex_lock(session_mutex); - for (cur = sessions; cur; cur = cur->next) { - int ret; - time_in_ms_t now; - time_in_ms_t next; - - now = time_in_ms - cur->rxcore; - if (now > (next = jb_next(cur->jb))) { - ret = jb_get(cur->jb, &frame, now, get_interp_len(cur->voiceformat)); - switch (ret) { - case JB_OK: - // if (frame.type == JB_TYPE_VOICE && next + 20 != jb_next(cur->jb)) fprintf(stderr, "NEXT %ld is not %ld+20!\n", jb_next(cur->jb), next); - event = frame.data; - event = handle_event(event); - if (event) { - iax_mutex_unlock(session_mutex); - return event; - } - break; - case JB_INTERP: - // if (next + 20 != jb_next(cur->jb)) fprintf(stderr, "NEXT %ld is not %ld+20!\n", jb_next(cur->jb), next); - /* create an interpolation frame */ - //fprintf(stderr, "Making Interpolation frame\n"); - event = (struct iax_event *) malloc(sizeof(struct iax_event)); - if (event) { - event->etype = IAX_EVENT_VOICE; - event->subclass = cur->voiceformat; - event->ts = now; /* XXX: ??? applications probably ignore this anyway */ - event->session = cur; - event->datalen = 0; - event = handle_event(event); - if (event) { - iax_mutex_unlock(session_mutex); - return event; - } - } - break; - case JB_DROP: - // if (next != jb_next(cur->jb)) fprintf(stderr, "NEXT %ld is not next %ld!\n", jb_next(cur->jb), next); - iax_event_free(frame.data); - break; - case JB_NOFRAME: - case JB_EMPTY: - /* do nothing */ - break; - default: - /* shouldn't happen */ - break; - } - } - } - iax_mutex_unlock(session_mutex); - } - -#endif - /* Now look for networking events */ - if (blocking) { - /* Block until there is data if desired */ - fd_set fds; - time_in_ms_t nextEventTime; - - FD_ZERO(&fds); - FD_SET(netfd, &fds); - - nextEventTime = iax_time_to_next_event(); - if (nextEventTime < 0 && blocking > 1) { - nextEventTime = blocking; - } - if (nextEventTime < 0) - select(netfd + 1, &fds, NULL, NULL, NULL); - else { - struct timeval nextEvent; - - nextEvent.tv_sec = (long) (nextEventTime / 1000); - nextEvent.tv_usec = (long) ((nextEventTime % 1000) * 1000); - - select(netfd + 1, &fds, NULL, NULL, &nextEvent); - } - - } - event = iax_net_read(); - - return handle_event(event); -} - -struct sockaddr_in iax_get_peer_addr(struct iax_session *session) { - return session->peeraddr; -} - -char *iax_get_peer_ip(struct iax_session *session) { - return inet_ntoa(session->peeraddr.sin_addr); -} - -char *iax_event_get_apparent_ip(struct iax_event *event) { - return inet_ntoa(event->ies.apparent_addr->sin_addr); -} - -void iax_session_destroy(struct iax_session **session) { - iax_mutex_lock(session_mutex); - destroy_session(*session); - *session = NULL; - iax_mutex_unlock(session_mutex); -} - -void iax_event_free(struct iax_event *event) { - /* - We gave the user a chance to play with the session now we need to destroy it - if you are not calling this function on every event you read you are now going - to leak sessions as well as events! - */ - switch (event->etype) { - case IAX_EVENT_REJECT: - case IAX_EVENT_HANGUP: - /* Destroy this session -- it's no longer valid */ - if (event->session) { /* maybe the user did it already */ - iax_mutex_lock(session_mutex); - destroy_session(event->session); - iax_mutex_unlock(session_mutex); - } - break; - } - free(event); -} - -int iax_get_fd(void) { - /* Return our network file descriptor. The client can select on this (probably with other - things, or can add it to a network add sort of gtk_input_add for example */ - return netfd; -} - -int iax_quelch_moh(struct iax_session *session, int MOH) { - - struct iax_ie_data ied; //IE Data Structure (Stuff To Send) - memset(&ied, 0, sizeof(ied)); - - // You can't quelch the quelched - if (session->quelch == 1) - return -1; - - if (MOH) { - iax_ie_append(&ied, IAX_IE_MUSICONHOLD); - session->transfer_moh = 1; - } - - return send_command(session, AST_FRAME_IAX, IAX_COMMAND_QUELCH, 0, ied.buf, ied.pos, -1); -} diff --git a/src/mod/endpoints/mod_iax/iax.h b/src/mod/endpoints/mod_iax/iax.h deleted file mode 100644 index 10a676cd4a..0000000000 --- a/src/mod/endpoints/mod_iax/iax.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * libIAX - * - * Implementation of Inter-IAXerisk eXchange - * - * Copyright (C) 1999, Mark Spencer - * - * Mark Spencer - * - * This program is free software, distributed under the terms of - * the GNU Lesser (Library) General Public License - */ - -#ifndef _IAX_H -#define _IAX_H - -/* Max version of IAX protocol we support */ -#define IAX_PROTO_VERSION 1 - -#define IAX_MAX_CALLS 32768 - -#define IAX_FLAG_FULL 0x8000 - -#define IAX_FLAG_SC_LOG 0x80 - -#define IAX_MAX_SHIFT 0x1F - -/* Maximum size of an IAX frame (max size of UDP frame) */ -#define IAX_MAX_BUF_SIZE 65536 - -/* Subclass for IAX_FRAME_IAX */ -#define IAX_COMMAND_NEW 1 -#define IAX_COMMAND_PING 2 -#define IAX_COMMAND_PONG 3 -#define IAX_COMMAND_ACK 4 -#define IAX_COMMAND_HANGUP 5 -#define IAX_COMMAND_REJECT 6 -#define IAX_COMMAND_ACCEPT 7 -#define IAX_COMMAND_AUTHREQ 8 -#define IAX_COMMAND_AUTHREP 9 -#define IAX_COMMAND_INVAL 10 -#define IAX_COMMAND_LAGRQ 11 -#define IAX_COMMAND_LAGRP 12 -#define IAX_COMMAND_REGREQ 13 /* Registration request */ -#define IAX_COMMAND_REGAUTH 14 /* Registration authentication required */ -#define IAX_COMMAND_REGACK 15 /* Registration accepted */ -#define IAX_COMMAND_REGREJ 16 /* Registration rejected */ -#define IAX_COMMAND_REGREL 17 /* Force release of registration */ -#define IAX_COMMAND_VNAK 18 /* If we receive voice before valid first voice frame, send this */ -#define IAX_COMMAND_DPREQ 19 /* Request status of a dialplan entry */ -#define IAX_COMMAND_DPREP 20 /* Request status of a dialplan entry */ -#define IAX_COMMAND_DIAL 21 /* Request a dial on channel brought up TBD */ -#define IAX_COMMAND_TXREQ 22 /* Transfer Request */ -#define IAX_COMMAND_TXCNT 23 /* Transfer Connect */ -#define IAX_COMMAND_TXACC 24 /* Transfer Accepted */ -#define IAX_COMMAND_TXREADY 25 /* Transfer ready */ -#define IAX_COMMAND_TXREL 26 /* Transfer release */ -#define IAX_COMMAND_TXREJ 27 /* Transfer reject */ -#define IAX_COMMAND_QUELCH 28 /* Stop audio/video transmission */ -#define IAX_COMMAND_UNQUELCH 29 /* Resume audio/video transmission */ - -#define IAX_DEFAULT_REG_EXPIRE 60 - -#define IAX_DEFAULT_PORTNO 5036 - -/* Full frames are always delivered reliably */ -struct iax_full_hdr { - short callno; /* Source call number -- high bit must be 1 */ - short dcallno; /* Destination call number */ - unsigned int ts; /* 32-bit timestamp in milliseconds */ - unsigned short seqno; /* Packet number */ - char type; /* Frame type */ - unsigned char csub; /* Compressed subclass */ - char data[]; -}; - -/* Mini header is used only for voice frames -- delivered unreliably */ -struct iax_mini_hdr { - short callno; /* Source call number -- high bit must be 0 */ - unsigned short ts; /* 16-bit Timestamp (high 16 bits from last IAX_full_hdr) */ - /* Frametype implicitly VOICE_FRAME */ - /* subclass implicit from last IAX_full_hdr */ - char data[]; -}; - -#endif diff --git a/src/mod/endpoints/mod_iax/iax2-parser.c b/src/mod/endpoints/mod_iax/iax2-parser.c deleted file mode 100644 index df2f82a64c..0000000000 --- a/src/mod/endpoints/mod_iax/iax2-parser.c +++ /dev/null @@ -1,872 +0,0 @@ -/* - * Asterisk -- A telephony toolkit for Linux. - * - * Implementation of Inter-Asterisk eXchange - * - * Copyright (C) 2003-2004, Digium - * - * Mark Spencer - * - * This program is free software, distributed under the terms of - * the GNU Lesser (Library) General Public License - */ - -#ifdef WIN32 -#include -#define snprintf _snprintf -#else -#include -#include -#include -#include -#endif - -#ifndef _MSC_VER -#include -#endif - -#include -#include -#include - -#include "frame.h" -#include "iax2.h" -#include "iax2-parser.h" - -static int frame_count = 0; -static int iframes = 0; -static int oframes = 0; - -#ifdef ALIGN32 -static unsigned int get_uint32(unsigned char *p) -{ - return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; -} - -static unsigned short get_uint16(unsigned char *p) -{ - return (p[0] << 8) | p[1]; -} - -#else -#define get_uint32(p) (*((unsigned int *)(p))) -#define get_uint16(p) (*((unsigned short *)(p))) -#endif - - -static void internaloutput(const char *str) -{ - printf("%s", str); -} - -static void internalerror(const char *str) -{ - fprintf(stderr, "WARNING: %s", str); -} - -static void (*outputf) (const char *str) = internaloutput; -static void (*errorf) (const char *str) = internalerror; - -static void dump_addr(char *output, int maxlen, void *value, int len) -{ - struct sockaddr_in sin; - if (len == sizeof(sin)) { - memcpy(&sin, value, len); - snprintf(output, maxlen, "IPV4 %s:%d", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); - } else { - snprintf(output, maxlen, "Invalid Address"); - } -} - -static void dump_string(char *output, int maxlen, void *value, int len) -{ - maxlen--; - if (maxlen > len) - maxlen = len; - strncpy(output, value, maxlen); - output[maxlen] = '\0'; -} - -static void dump_int(char *output, int maxlen, void *value, int len) -{ - if (len == (int) sizeof(unsigned int)) - snprintf(output, maxlen, "%lu", (unsigned long) ntohl(get_uint32(value))); - else - snprintf(output, maxlen, "Invalid INT"); -} - -static void dump_short(char *output, int maxlen, void *value, int len) -{ - if (len == (int) sizeof(unsigned short)) - snprintf(output, maxlen, "%d", ntohs(get_uint16(value))); - else - snprintf(output, maxlen, "Invalid SHORT"); -} - -static void dump_byte(char *output, int maxlen, void *value, int len) -{ - if (len == (int) sizeof(unsigned char)) - snprintf(output, maxlen, "%d", *((unsigned char *) value)); - else - snprintf(output, maxlen, "Invalid BYTE"); -} - -#if 0 -static void dump_ipaddr(char *output, int maxlen, void *value, int len) -{ - struct sockaddr_in sin; - if (len == (int) sizeof(unsigned int)) { - memcpy(&sin.sin_addr, value, len); - snprintf(output, maxlen, "%s", inet_ntoa(sin.sin_addr)); - } else - snprintf(output, maxlen, "Invalid IPADDR"); -} - -static void dump_prov_flags(char *output, int maxlen, void *value, int len) -{ - if (len == (int) sizeof(unsigned int)) - snprintf(output, maxlen, "%lu (%s)", (unsigned long) ntohl(get_uint32(value)), "PROVISION_PARSING_NOT_IMPLEMENTED"); - else - snprintf(output, maxlen, "Invalid INT"); -} -#endif - -static void dump_samprate(char *output, int maxlen, void *value, int len) -{ - char tmp[256] = ""; - int sr; - if (len == (int) sizeof(unsigned short)) { - sr = ntohs(*((unsigned short *) value)); - if (sr & IAX_RATE_8KHZ) - strcat(tmp, ",8khz"); - if (sr & IAX_RATE_11KHZ) - strcat(tmp, ",11.025khz"); - if (sr & IAX_RATE_16KHZ) - strcat(tmp, ",16khz"); - if (sr & IAX_RATE_32KHZ) - strcat(tmp, ",32khz"); - if (sr & IAX_RATE_22KHZ) - strcat(tmp, ",22.05khz"); - if (sr & IAX_RATE_44KHZ) - strcat(tmp, ",44.1khz"); - if (sr & IAX_RATE_48KHZ) - strcat(tmp, ",48khz"); - if (strlen(tmp)) - strncpy(output, &tmp[1], maxlen - 1); - else - strncpy(output, "None specified!\n", maxlen - 1); - } else - snprintf(output, maxlen, "Invalid SHORT"); - -} - -static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len); -static void dump_prov(char *output, int maxlen, void *value, int len) -{ - dump_prov_ies(output, maxlen, value, len); -} - -static struct iax2_ie { - int ie; - char *name; - void (*dump) (char *output, int maxlen, void *value, int len); -} ies[] = { - { - IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string}, { - IAX_IE_CALLING_NUMBER, "CALLING NUMBER", dump_string}, { - IAX_IE_CALLING_ANI, "ANI", dump_string}, { - IAX_IE_CALLING_NAME, "CALLING NAME", dump_string}, { - IAX_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string}, { - IAX_IE_USERNAME, "USERNAME", dump_string}, { - IAX_IE_PASSWORD, "PASSWORD", dump_string}, { - IAX_IE_CAPABILITY, "CAPABILITY", dump_int}, { - IAX_IE_FORMAT, "FORMAT", dump_int}, { - IAX_IE_LANGUAGE, "LANGUAGE", dump_string}, { - IAX_IE_CODEC_PREFS, "CODEC_PREFS", dump_string}, { - IAX_IE_VERSION, "VERSION", dump_short}, { - IAX_IE_ADSICPE, "ADSICPE", dump_short}, { - IAX_IE_DNID, "DNID", dump_string}, { - IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_short}, { - IAX_IE_CHALLENGE, "CHALLENGE", dump_string}, { - IAX_IE_MD5_RESULT, "MD5 RESULT", dump_string}, { - IAX_IE_RSA_RESULT, "RSA RESULT", dump_string}, { - IAX_IE_APPARENT_ADDR, "APPARENT ADDRESS", dump_addr}, { - IAX_IE_REFRESH, "REFRESH", dump_short}, { - IAX_IE_DPSTATUS, "DIALPLAN STATUS", dump_short}, { - IAX_IE_CALLNO, "CALL NUMBER", dump_short}, { - IAX_IE_CAUSE, "CAUSE", dump_string}, { - IAX_IE_IAX_UNKNOWN, "UNKNOWN IAX CMD", dump_byte}, { - IAX_IE_MSGCOUNT, "MESSAGE COUNT", dump_short}, { - IAX_IE_AUTOANSWER, "AUTO ANSWER REQ"}, { - IAX_IE_TRANSFERID, "TRANSFER ID", dump_int}, { - IAX_IE_RDNIS, "REFERRING DNIS", dump_string}, { - IAX_IE_PROVISIONING, "PROVISIONING", dump_prov}, { - IAX_IE_AESPROVISIONING, "AES PROVISIONG"}, { - IAX_IE_DATETIME, "DATE TIME", dump_int}, { - IAX_IE_DEVICETYPE, "DEVICE TYPE", dump_string}, { - IAX_IE_SERVICEIDENT, "SERVICE IDENT", dump_string}, { - IAX_IE_FIRMWAREVER, "FIRMWARE VER", dump_short}, { - IAX_IE_FWBLOCKDESC, "FW BLOCK DESC", dump_int}, { - IAX_IE_FWBLOCKDATA, "FW BLOCK DATA"}, { - IAX_IE_PROVVER, "PROVISIONG VER", dump_int}, { - IAX_IE_CALLINGPRES, "CALLING PRESNTN", dump_byte}, { - IAX_IE_CALLINGTON, "CALLING TYPEOFNUM", dump_byte}, { - IAX_IE_CALLINGTNS, "CALLING TRANSITNET", dump_short}, { - IAX_IE_SAMPLINGRATE, "SAMPLINGRATE", dump_samprate}, { - IAX_IE_RR_JITTER, "RR_JITTER", dump_int}, { - IAX_IE_RR_LOSS, "RR_LOSS", dump_int}, { - IAX_IE_RR_PKTS, "RR_PKTS", dump_int}, { - IAX_IE_RR_DELAY, "RR_DELAY", dump_short}, { - IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int}, { -IAX_IE_RR_OOO, "RR_OOO", dump_int},}; - -const char *iax_ie2str(int ie) -{ - int x; - for (x = 0; x < (int) sizeof(ies) / (int) sizeof(ies[0]); x++) { - if (ies[x].ie == ie) - return ies[x].name; - } - return "Unknown IE"; -} - - -static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len) -{ - int ielen; - int ie; - int found; - char tmp[256]; - if (len < 2) - return; - strcpy(output, "\n"); - maxlen -= (int) strlen(output); - output += strlen(output); - while (len > 2) { - ie = iedata[0]; - ielen = iedata[1]; - if (ielen + 2 > len) { - snprintf(tmp, (int) sizeof(tmp), "Total Prov IE length of %d bytes exceeds remaining prov frame length of %d bytes\n", ielen + 2, len); - strncpy(output, tmp, maxlen - 1); - maxlen -= (int) strlen(output); - output += strlen(output); - return; - } - found = 0; - if (!found) { - snprintf(tmp, (int) sizeof(tmp), " Unknown Prov IE %03d : Present\n", ie); - strncpy(output, tmp, maxlen - 1); - maxlen -= (int) strlen(output); - output += strlen(output); - } - iedata += (2 + ielen); - len -= (2 + ielen); - } -} - -static void dump_ies(unsigned char *iedata, int len) -{ - int ielen; - int ie; - int x; - int found; - char interp[1024]; - char tmp[1024]; - if (len < 2) - return; - while (len > 2) { - ie = iedata[0]; - ielen = iedata[1]; - if (ielen + 2 > len) { - snprintf(tmp, (int) sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len); - outputf(tmp); - return; - } - found = 0; - for (x = 0; x < (int) sizeof(ies) / (int) sizeof(ies[0]); x++) { - if (ies[x].ie == ie) { - if (ies[x].dump) { - ies[x].dump(interp, (int) sizeof(interp), iedata + 2, ielen); - snprintf(tmp, (int) sizeof(tmp), " %-15.15s : %s\n", ies[x].name, interp); - outputf(tmp); - } else { - if (ielen) - snprintf(interp, (int) sizeof(interp), "%d bytes", ielen); - else - strcpy(interp, "Present"); - snprintf(tmp, (int) sizeof(tmp), " %-15.15s : %s\n", ies[x].name, interp); - outputf(tmp); - } - found++; - } - } - if (!found) { - snprintf(tmp, (int) sizeof(tmp), " Unknown IE %03d : Present\n", ie); - outputf(tmp); - } - iedata += (2 + ielen); - len -= (2 + ielen); - } - outputf("\n"); -} - -void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen) -{ - const char *frames[] = { - "(0?)", - "DTMF ", - "VOICE ", - "VIDEO ", - "CONTROL", - "NULL ", - "IAX ", - "TEXT ", - "IMAGE " - }; - const char *iaxs[] = { - "(0?)", - "NEW ", - "PING ", - "PONG ", - "ACK ", - "HANGUP ", - "REJECT ", - "ACCEPT ", - "AUTHREQ", - "AUTHREP", - "INVAL ", - "LAGRQ ", - "LAGRP ", - "REGREQ ", - "REGAUTH", - "REGACK ", - "REGREJ ", - "REGREL ", - "VNAK ", - "DPREQ ", - "DPREP ", - "DIAL ", - "TXREQ ", - "TXCNT ", - "TXACC ", - "TXREADY", - "TXREL ", - "TXREJ ", - "QUELCH ", - "UNQULCH", - "POKE", - "PAGE", - "MWI", - "UNSUPPORTED", - "TRANSFER", - "PROVISION", - "FWDOWNLD", - "FWDATA" - }; - - - const char *cmds[] = { - "(0?)", - "HANGUP ", - "RING ", - "RINGING", - "ANSWER ", - "BUSY ", - "TKOFFHK", - "OFFHOOK", - "CONGSTN", - "FLASH ", - "WINK ", - "OPTION ", - "RDKEY ", - "RDUNKEY", - "PROGRES", - "PROCDNG", - "HOLD ", - "UNHOLD ", - "VIDUPDT", - "T38 ", - "SRCUPDT", - "TXFER ", - "CNLINE ", - "REDIR ", - }; - - struct ast_iax2_full_hdr *fh; - char retries[20]; - char class2[20]; - char subclass2[20]; - const char *class; - const char *subclass; - char tmp[256]; - - if (f) { - fh = f->data; - snprintf(retries, (int) sizeof(retries), "%03d", f->retries); - } else { - fh = fhi; - if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) - strcpy(retries, "Yes"); - else - strcpy(retries, " No"); - } - if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) { - /* Don't mess with mini-frames */ - return; - } - if (fh->type > ((int) sizeof(frames) / (int) sizeof(char *)) - 1) { - snprintf(class2, (int) sizeof(class2), "(%d?)", fh->type); - class = class2; - } else { - class = frames[(int) fh->type]; - } - if (fh->type == AST_FRAME_DTMF) { - sprintf(subclass2, "%c", fh->csub); - subclass = subclass2; - } else if (fh->type == AST_FRAME_IAX) { - if (fh->csub >= (int) sizeof(iaxs) / (int) sizeof(iaxs[0])) { - snprintf(subclass2, (int) sizeof(subclass2), "(%d?)", fh->csub); - subclass = subclass2; - } else { - subclass = iaxs[(int) fh->csub]; - } - } else if (fh->type == AST_FRAME_CONTROL) { - if (fh->csub > (int) sizeof(cmds) / (int) sizeof(char *)) { - snprintf(subclass2, (int) sizeof(subclass2), "(%d?)", fh->csub); - subclass = subclass2; - } else { - subclass = cmds[(int) fh->csub]; - } - } else { - snprintf(subclass2, (int) sizeof(subclass2), "%d", fh->csub); - subclass = subclass2; - } - - snprintf(tmp, (int) sizeof(tmp), - "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n", - (rx ? "Rx" : "Tx"), retries, fh->oseqno, fh->iseqno, class, subclass); - outputf(tmp); - snprintf(tmp, (int) sizeof(tmp), - " Timestamp: %05lums SCall: %5.5d DCall: %5.5d [%s:%d]\n", - (unsigned long) ntohl(fh->ts), - ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); - outputf(tmp); - if (fh->type == AST_FRAME_IAX) - dump_ies(fh->iedata, datalen); -} - -int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen) -{ - char tmp[256]; - if (datalen > ((int) sizeof(ied->buf) - ied->pos)) { - 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); - errorf(tmp); - return -1; - } - ied->buf[ied->pos++] = ie; - ied->buf[ied->pos++] = (unsigned char) datalen; - memcpy(ied->buf + ied->pos, data, datalen); - ied->pos += datalen; - return 0; -} - -int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, struct sockaddr_in *sin) -{ - return iax_ie_append_raw(ied, ie, sin, (int) sizeof(struct sockaddr_in)); -} - -int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value) -{ - unsigned int newval; - newval = htonl(value); - return iax_ie_append_raw(ied, ie, &newval, (int) sizeof(newval)); -} - -int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value) -{ - unsigned short newval; - newval = htons(value); - return iax_ie_append_raw(ied, ie, &newval, (int) sizeof(newval)); -} - -int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const unsigned char *str) -{ - return iax_ie_append_raw(ied, ie, str, (int) strlen((char *) str)); -} - -int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat) -{ - return iax_ie_append_raw(ied, ie, &dat, 1); -} - -int iax_ie_append(struct iax_ie_data *ied, unsigned char ie) -{ - return iax_ie_append_raw(ied, ie, NULL, 0); -} - -void iax_set_output(void (*func) (const char *)) -{ - outputf = func; -} - -void iax_set_error(void (*func) (const char *)) -{ - errorf = func; -} - -int iax_parse_ies(struct iax_ies *my_ies, unsigned char *data, int datalen) -{ - /* Parse data into information elements */ - int len; - int ie; - char tmp[256]; - memset(my_ies, 0, (int) sizeof(struct iax_ies)); - my_ies->msgcount = -1; - my_ies->firmwarever = -1; - my_ies->calling_ton = -1; - my_ies->calling_tns = -1; - my_ies->calling_pres = -1; - my_ies->samprate = IAX_RATE_8KHZ; - while (datalen >= 2) { - ie = data[0]; - len = data[1]; - if (len > datalen - 2) { - errorf("Information element length exceeds message size\n"); - return -1; - } - switch (ie) { - case IAX_IE_CALLED_NUMBER: - my_ies->called_number = (char *) data + 2; - break; - case IAX_IE_CALLING_NUMBER: - my_ies->calling_number = (char *) data + 2; - break; - case IAX_IE_CALLING_ANI: - my_ies->calling_ani = (char *) data + 2; - break; - case IAX_IE_CALLING_NAME: - my_ies->calling_name = (char *) data + 2; - break; - case IAX_IE_CALLED_CONTEXT: - my_ies->called_context = (char *) data + 2; - break; - case IAX_IE_USERNAME: - my_ies->username = (char *) data + 2; - break; - case IAX_IE_PASSWORD: - my_ies->password = (char *) data + 2; - break; - case IAX_IE_CAPABILITY: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else - my_ies->capability = ntohl(get_uint32(data + 2)); - break; - case IAX_IE_FORMAT: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else - my_ies->format = ntohl(get_uint32(data + 2)); - break; - case IAX_IE_LANGUAGE: - my_ies->language = (char *) data + 2; - break; - case IAX_IE_CODEC_PREFS: - my_ies->codec_prefs = (char *) data + 2; - break; - case IAX_IE_VERSION: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->version = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_ADSICPE: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->adsicpe = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_SAMPLINGRATE: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->samprate = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_DNID: - my_ies->dnid = (char *) data + 2; - break; - case IAX_IE_RDNIS: - my_ies->rdnis = (char *) data + 2; - break; - case IAX_IE_AUTHMETHODS: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->authmethods = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_CHALLENGE: - my_ies->challenge = (char *) data + 2; - break; - case IAX_IE_MD5_RESULT: - my_ies->md5_result = (char *) data + 2; - break; - case IAX_IE_RSA_RESULT: - my_ies->rsa_result = (char *) data + 2; - break; - case IAX_IE_APPARENT_ADDR: - my_ies->apparent_addr = ((struct sockaddr_in *) (data + 2)); - break; - case IAX_IE_REFRESH: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting refresh to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->refresh = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_DPSTATUS: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting dpstatus to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->dpstatus = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_CALLNO: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting callno to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->callno = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_CAUSE: - my_ies->cause = (char *) data + 2; - break; - case IAX_IE_CAUSECODE: - if (len != 1) { - snprintf(tmp, (int) sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len); - errorf(tmp); - } else { - my_ies->causecode = data[2]; - } - break; - case IAX_IE_IAX_UNKNOWN: - if (len == 1) - my_ies->iax_unknown = data[2]; - else { - snprintf(tmp, (int) sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len); - errorf(tmp); - } - break; - case IAX_IE_MSGCOUNT: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->msgcount = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_AUTOANSWER: - my_ies->autoanswer = 1; - break; - case IAX_IE_MUSICONHOLD: - my_ies->musiconhold = 1; - break; - case IAX_IE_TRANSFERID: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else - my_ies->transferid = ntohl(get_uint32(data + 2)); - break; - case IAX_IE_DATETIME: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else - my_ies->datetime = ntohl(get_uint32(data + 2)); - break; - case IAX_IE_FIRMWAREVER: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->firmwarever = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_DEVICETYPE: - my_ies->devicetype = (char *) data + 2; - break; - case IAX_IE_SERVICEIDENT: - my_ies->serviceident = (char *) data + 2; - break; - case IAX_IE_FWBLOCKDESC: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else - my_ies->fwdesc = ntohl(get_uint32(data + 2)); - break; - case IAX_IE_FWBLOCKDATA: - my_ies->fwdata = data + 2; - my_ies->fwdatalen = (unsigned char) len; - break; - case IAX_IE_PROVVER: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else { - my_ies->provverpres = 1; - my_ies->provver = ntohl(get_uint32(data + 2)); - } - break; - case IAX_IE_CALLINGPRES: - if (len == 1) - my_ies->calling_pres = data[2]; - else { - snprintf(tmp, (int) sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len); - errorf(tmp); - } - break; - case IAX_IE_CALLINGTON: - if (len == 1) - my_ies->calling_ton = data[2]; - else { - snprintf(tmp, (int) sizeof(tmp), "Expected single byte callington, but was %d long\n", len); - errorf(tmp); - } - break; - case IAX_IE_CALLINGTNS: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else - my_ies->calling_tns = ntohs(get_uint16(data + 2)); - break; - case IAX_IE_RR_JITTER: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else { - my_ies->rr_jitter = ntohl(get_uint32(data + 2)); - } - break; - case IAX_IE_RR_LOSS: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else { - my_ies->rr_loss = ntohl(get_uint32(data + 2)); - } - break; - case IAX_IE_RR_PKTS: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else { - my_ies->rr_pkts = ntohl(get_uint32(data + 2)); - } - break; - case IAX_IE_RR_DELAY: - if (len != (int) sizeof(unsigned short)) { - snprintf(tmp, (int) sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int) sizeof(unsigned short), len); - errorf(tmp); - } else { - my_ies->rr_delay = ntohs(get_uint16(data + 2)); - } - break; - case IAX_IE_RR_DROPPED: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else { - my_ies->rr_dropped = ntohl(get_uint32(data + 2)); - } - break; - case IAX_IE_RR_OOO: - if (len != (int) sizeof(unsigned int)) { - snprintf(tmp, (int) sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int) sizeof(unsigned int), len); - errorf(tmp); - } else { - my_ies->rr_ooo = ntohl(get_uint32(data + 2)); - } - break; - default: - snprintf(tmp, (int) sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len); - outputf(tmp); - } - /* Overwrite information element with 0, to null terminate previous portion */ - data[0] = 0; - datalen -= (len + 2); - data += (len + 2); - } - /* Null-terminate last field */ - *data = '\0'; - if (datalen) { - errorf("Invalid information element contents, strange boundary\n"); - return -1; - } - return 0; -} - -void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f) -{ - fr->af.frametype = f->frametype; - fr->af.subclass = f->subclass; - fr->af.mallocd = 0; /* Our frame is static relative to the container */ - fr->af.datalen = f->datalen; - fr->af.samples = f->samples; - fr->af.offset = AST_FRIENDLY_OFFSET; - fr->af.src = f->src; - fr->af.data = fr->afdata; - if (fr->af.datalen) - memcpy(fr->af.data, f->data, fr->af.datalen); -} - -struct iax_frame *iax_frame_new(int direction, int datalen) -{ - struct iax_frame *fr; - fr = malloc((int) sizeof(struct iax_frame) + datalen); - if (fr) { - fr->direction = direction; - fr->retrans = -1; - frame_count++; - if (fr->direction == DIRECTION_INGRESS) - iframes++; - else - oframes++; - } - return fr; -} - -void iax_frame_free(struct iax_frame *fr) -{ - /* Note: does not remove from scheduler! */ - if (fr->direction == DIRECTION_INGRESS) - iframes--; - else if (fr->direction == DIRECTION_OUTGRESS) - oframes--; - else { - errorf("Attempt to double free frame detected\n"); - return; - } - fr->direction = 0; - free(fr); - frame_count--; -} - -int iax_get_frames(void) -{ - return frame_count; -} -int iax_get_iframes(void) -{ - return iframes; -} -int iax_get_oframes(void) -{ - return oframes; -} diff --git a/src/mod/endpoints/mod_iax/iax2-parser.h b/src/mod/endpoints/mod_iax/iax2-parser.h deleted file mode 100644 index 25b863de00..0000000000 --- a/src/mod/endpoints/mod_iax/iax2-parser.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Asterisk -- A telephony toolkit for Linux. - * - * Implementation of Inter-Asterisk eXchange - * - * Copyright (C) 2003, Digium - * - * Mark Spencer - * - * This program is free software, distributed under the terms of - * the GNU Lesser (Library) General Public License - */ - -#ifndef _IAX2_PARSER_H -#define _IAX2_PARSER_H - -struct iax_ies { - char *called_number; - char *calling_number; - char *calling_ani; - char *calling_name; - int calling_ton; - int calling_tns; - int calling_pres; - char *called_context; - char *username; - char *password; - unsigned int capability; - unsigned int format; - char *codec_prefs; - char *language; - int version; - unsigned short adsicpe; - char *dnid; - char *rdnis; - unsigned int authmethods; - char *challenge; - char *md5_result; - char *rsa_result; - struct sockaddr_in *apparent_addr; - unsigned short refresh; - unsigned short dpstatus; - unsigned short callno; - char *cause; - unsigned char causecode; - unsigned char iax_unknown; - int msgcount; - int autoanswer; - int musiconhold; - unsigned int transferid; - unsigned int datetime; - char *devicetype; - char *serviceident; - int firmwarever; - unsigned int fwdesc; - unsigned char *fwdata; - unsigned char fwdatalen; - unsigned int provver; - unsigned short samprate; - unsigned int provverpres; - unsigned int rr_jitter; - unsigned int rr_loss; - unsigned int rr_pkts; - unsigned short rr_delay; - unsigned int rr_dropped; - unsigned int rr_ooo; -}; - -#define DIRECTION_INGRESS 1 -#define DIRECTION_OUTGRESS 2 - -struct iax_frame { -#ifdef LIBIAX - struct iax_session *session; - struct iax_event *event; -#endif - - /* /Our/ call number */ - unsigned short callno; - /* /Their/ call number */ - unsigned short dcallno; - /* Start of raw frame (outgoing only) */ - void *data; - /* Length of frame (outgoing only) */ - int datalen; - /* How many retries so far? */ - int retries; - /* Outgoing relative timestamp (ms) */ - time_in_ms_t ts; - /* How long to wait before retrying */ - time_in_ms_t retrytime; - /* Are we received out of order? */ - int outoforder; - /* Have we been sent at all yet? */ - int sentyet; - /* Outgoing Packet sequence number */ - int oseqno; - /* Next expected incoming packet sequence number */ - int iseqno; - /* Non-zero if should be sent to transfer peer */ - int transfer; - /* Non-zero if this is the final message */ - int final; - /* Ingress or outgres */ - int direction; - /* Retransmission ID */ - int retrans; - /* Easy linking */ - struct iax_frame *next; - struct iax_frame *prev; - /* Actual, isolated frame header */ - struct ast_frame af; - unsigned char unused[AST_FRIENDLY_OFFSET]; - unsigned char afdata[]; /* Data for frame */ -}; - -struct iax_ie_data { - unsigned char buf[1024]; - int pos; -}; - -/* Choose a different function for output */ -extern void iax_set_output(void (*output)(const char *data)); -/* Choose a different function for errors */ -extern void iax_set_error(void (*output)(const char *data)); -extern void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen); - -extern const char *iax_ie2str(int ie); - -extern int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen); -extern int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, struct sockaddr_in *sin); -extern int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value); -extern int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value); -extern int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const unsigned char *str); -extern int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat); -extern int iax_ie_append(struct iax_ie_data *ied, unsigned char ie); -extern int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen); - -extern int iax_get_frames(void); -extern int iax_get_iframes(void); -extern int iax_get_oframes(void); -extern void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f); -extern struct iax_frame *iax_frame_new(int direction, int datalen); -extern void iax_frame_free(struct iax_frame *fr); -#endif diff --git a/src/mod/endpoints/mod_iax/iax2.h b/src/mod/endpoints/mod_iax/iax2.h deleted file mode 100644 index 96719a80ae..0000000000 --- a/src/mod/endpoints/mod_iax/iax2.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Asterisk -- A telephony toolkit for Linux. - * - * Implementation of Inter-Asterisk eXchange - * - * Copyright (C) 2003, Digium - * - * Mark Spencer - * - * This program is free software, distributed under the terms of - * the GNU Lesser (Library) General Public License - */ - -#ifndef _IAX2_H -#define _IAX2_H - -typedef long long time_in_ms_t; -#define iax_abs(x) ((x) >= 0 ? (x) : -(x)) - -/* Max version of IAX protocol we support */ -#define IAX_PROTO_VERSION 2 - -#define IAX_MAX_CALLS 32768 - -#define IAX_FLAG_FULL 0x8000 - -#define IAX_FLAG_RETRANS 0x8000 - -#define IAX_FLAG_SC_LOG 0x80 - -#define IAX_MAX_SHIFT 0x1F - -#define IAX_WINDOW 64 - -/* Subclass for AST_FRAME_IAX */ -#define IAX_COMMAND_NEW 1 -#define IAX_COMMAND_PING 2 -#define IAX_COMMAND_PONG 3 -#define IAX_COMMAND_ACK 4 -#define IAX_COMMAND_HANGUP 5 -#define IAX_COMMAND_REJECT 6 -#define IAX_COMMAND_ACCEPT 7 -#define IAX_COMMAND_AUTHREQ 8 -#define IAX_COMMAND_AUTHREP 9 -#define IAX_COMMAND_INVAL 10 -#define IAX_COMMAND_LAGRQ 11 -#define IAX_COMMAND_LAGRP 12 -#define IAX_COMMAND_REGREQ 13 /* Registration request */ -#define IAX_COMMAND_REGAUTH 14 /* Registration authentication required */ -#define IAX_COMMAND_REGACK 15 /* Registration accepted */ -#define IAX_COMMAND_REGREJ 16 /* Registration rejected */ -#define IAX_COMMAND_REGREL 17 /* Force release of registration */ -#define IAX_COMMAND_VNAK 18 /* If we receive voice before valid first voice frame, send this */ -#define IAX_COMMAND_DPREQ 19 /* Request status of a dialplan entry */ -#define IAX_COMMAND_DPREP 20 /* Request status of a dialplan entry */ -#define IAX_COMMAND_DIAL 21 /* Request a dial on channel brought up TBD */ -#define IAX_COMMAND_TXREQ 22 /* Transfer Request */ -#define IAX_COMMAND_TXCNT 23 /* Transfer Connect */ -#define IAX_COMMAND_TXACC 24 /* Transfer Accepted */ -#define IAX_COMMAND_TXREADY 25 /* Transfer ready */ -#define IAX_COMMAND_TXREL 26 /* Transfer release */ -#define IAX_COMMAND_TXREJ 27 /* Transfer reject */ -#define IAX_COMMAND_QUELCH 28 /* Stop audio/video transmission */ -#define IAX_COMMAND_UNQUELCH 29 /* Resume audio/video transmission */ -#define IAX_COMMAND_POKE 30 /* Like ping, but does not require an open connection */ -#define IAX_COMMAND_PAGE 31 /* Paging description */ -#define IAX_COMMAND_MWI 32 /* Stand-alone message waiting indicator */ -#define IAX_COMMAND_UNSUPPORT 33 /* Unsupported message received */ -#define IAX_COMMAND_TRANSFER 34 /* Request remote transfer */ -#define IAX_COMMAND_PROVISION 35 /* Provision device */ -#define IAX_COMMAND_FWDOWNL 36 /* Download firmware */ -#define IAX_COMMAND_FWDATA 37 /* Firmware Data */ - -#define IAX_DEFAULT_REG_EXPIRE 60 /* By default require re-registration once per minute */ - -#define IAX_LINGER_TIMEOUT 10 /* How long to wait before closing bridged call */ - -#define IAX_DEFAULT_PORTNO 4569 - -/* IAX Information elements */ -#define IAX_IE_CALLED_NUMBER 1 /* Number/extension being called - string */ -#define IAX_IE_CALLING_NUMBER 2 /* Calling number - string */ -#define IAX_IE_CALLING_ANI 3 /* Calling number ANI for billing - string */ -#define IAX_IE_CALLING_NAME 4 /* Name of caller - string */ -#define IAX_IE_CALLED_CONTEXT 5 /* Context for number - string */ -#define IAX_IE_USERNAME 6 /* Username (peer or user) for authentication - string */ -#define IAX_IE_PASSWORD 7 /* Password for authentication - string */ -#define IAX_IE_CAPABILITY 8 /* Actual codec capability - unsigned int */ -#define IAX_IE_FORMAT 9 /* Desired codec format - unsigned int */ -#define IAX_IE_LANGUAGE 10 /* Desired language - string */ -#define IAX_IE_VERSION 11 /* Protocol version - short */ -#define IAX_IE_ADSICPE 12 /* CPE ADSI capability - short */ -#define IAX_IE_DNID 13 /* Originally dialed DNID - string */ -#define IAX_IE_AUTHMETHODS 14 /* Authentication method(s) - short */ -#define IAX_IE_CHALLENGE 15 /* Challenge data for MD5/RSA - string */ -#define IAX_IE_MD5_RESULT 16 /* MD5 challenge result - string */ -#define IAX_IE_RSA_RESULT 17 /* RSA challenge result - string */ -#define IAX_IE_APPARENT_ADDR 18 /* Apparent address of peer - struct sockaddr_in */ -#define IAX_IE_REFRESH 19 /* When to refresh registration - short */ -#define IAX_IE_DPSTATUS 20 /* Dialplan status - short */ -#define IAX_IE_CALLNO 21 /* Call number of peer - short */ -#define IAX_IE_CAUSE 22 /* Cause - string */ -#define IAX_IE_IAX_UNKNOWN 23 /* Unknown IAX command - byte */ -#define IAX_IE_MSGCOUNT 24 /* How many messages waiting - short */ -#define IAX_IE_AUTOANSWER 25 /* Request auto-answering -- none */ -#define IAX_IE_MUSICONHOLD 26 /* Request musiconhold with QUELCH -- none or string */ -#define IAX_IE_TRANSFERID 27 /* Transfer Request Identifier -- int */ -#define IAX_IE_RDNIS 28 /* Referring DNIS -- string */ -#define IAX_IE_PROVISIONING 29 /* Provisioning info */ -#define IAX_IE_AESPROVISIONING 30 /* AES Provisioning info */ -#define IAX_IE_DATETIME 31 /* Date/Time */ -#define IAX_IE_DEVICETYPE 32 /* Device Type -- string */ -#define IAX_IE_SERVICEIDENT 33 /* Service Identifier -- string */ -#define IAX_IE_FIRMWAREVER 34 /* Firmware revision -- u16 */ -#define IAX_IE_FWBLOCKDESC 35 /* Firmware block description -- u32 */ -#define IAX_IE_FWBLOCKDATA 36 /* Firmware block of data -- raw */ -#define IAX_IE_PROVVER 37 /* Provisioning Version (u32) */ -#define IAX_IE_CALLINGPRES 38 /* Calling presentation (u8) */ -#define IAX_IE_CALLINGTON 39 /* Calling type of number (u8) */ -#define IAX_IE_CALLINGTNS 40 /* Calling transit network select (u16) */ -#define IAX_IE_SAMPLINGRATE 41 /* Supported sampling rates (u16) */ -#define IAX_IE_CAUSECODE 42 /* Hangup cause (u8) */ -#define IAX_IE_ENCRYPTION 43 /* Encryption format (u16) */ -#define IAX_IE_ENCKEY 44 /* Encryption key (raw) */ -#define IAX_IE_CODEC_PREFS 45 /* Codec Negotiation */ - -#define IAX_IE_RR_JITTER 46 /* Received jitter (as in RFC1889) u32 */ -#define IAX_IE_RR_LOSS 47 /* Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889 */ -#define IAX_IE_RR_PKTS 48 /* Received frames (total frames received) u32 */ -#define IAX_IE_RR_DELAY 49 /* Max playout delay for received frames (in ms) u16 */ -#define IAX_IE_RR_DROPPED 50 /* Dropped frames (presumably by jitterbuf) u32 */ -#define IAX_IE_RR_OOO 51 /* Frames received Out of Order u32 */ - - - -#define IAX_AUTH_PLAINTEXT (1 << 0) -#define IAX_AUTH_MD5 (1 << 1) -#define IAX_AUTH_RSA (1 << 2) - -#define IAX_META_TRUNK 1 /* Trunk meta-message */ -#define IAX_META_VIDEO 2 /* Video frame */ - -#define IAX_RATE_8KHZ (1 << 0) /* 8khz sampling (default if absent) */ -#define IAX_RATE_11KHZ (1 << 1) /* 11.025khz sampling */ -#define IAX_RATE_16KHZ (1 << 2) /* 16khz sampling */ -#define IAX_RATE_22KHZ (1 << 3) /* 22.05khz sampling */ -#define IAX_RATE_44KHZ (1 << 4) /* 44.1khz sampling */ -#define IAX_RATE_48KHZ (1 << 5) /* 48khz sampling */ -#define IAX_RATE_32KHZ (1 << 6) /* 32khz sampling */ - -#define IAX_DPSTATUS_EXISTS (1 << 0) -#define IAX_DPSTATUS_CANEXIST (1 << 1) -#define IAX_DPSTATUS_NONEXISTANT (1 << 2) -#define IAX_DPSTATUS_IGNOREPAT (1 << 14) -#define IAX_DPSTATUS_MATCHMORE (1 << 15) - -#if defined __GNUC__ -#define __PACKED __attribute__ ((__packed__)) -#else -#if defined (_MSC_VER) -#pragma pack(push,1) -#define __PACKED -#else -#pragma pack(1) -#define __PACKED -#endif -#endif - -/* Full frames are always delivered reliably */ -struct ast_iax2_full_hdr { - unsigned short scallno; /* Source call number -- high bit must be 1 */ - unsigned short dcallno; /* Destination call number -- high bit is 1 if retransmission */ - unsigned int ts; /* 32-bit timestamp in milliseconds (from 1st transmission) */ - unsigned char oseqno; /* Packet number (outgoing) */ - unsigned char iseqno; /* Packet number (next incoming expected) */ - char type; /* Frame type */ - unsigned char csub; /* Compressed subclass */ - unsigned char iedata[]; -} __PACKED; - -/* Mini header is used only for voice frames -- delivered unreliably */ -struct ast_iax2_mini_hdr { - unsigned short callno; /* Source call number -- high bit must be 0, rest must be non-zero */ - unsigned short ts; /* 16-bit Timestamp (high 16 bits from last ast_iax2_full_hdr) */ - /* Frametype implicitly VOICE_FRAME */ - /* subclass implicit from last ast_iax2_full_hdr */ - unsigned char data[]; -} __PACKED; - -struct ast_iax2_meta_hdr { - unsigned short zeros; /* Zeros field -- must be zero */ - unsigned char metacmd; /* Meta command */ - unsigned char cmddata; /* Command Data */ - unsigned char data[]; -} __PACKED; - -struct ast_iax2_video_hdr { - unsigned short zeros; /* Zeros field -- must be zero */ - unsigned short callno; /* Video call number */ - unsigned short ts; /* Timestamp and mark if present */ - unsigned char data[]; -} __PACKED; - -struct ast_iax2_meta_trunk_hdr { - unsigned int ts; /* 32-bit timestamp for all messages */ - unsigned char data[]; -} __PACKED; - -struct ast_iax2_meta_trunk_entry { - unsigned short callno; /* Call number */ - unsigned short len; /* Length of data for this callno */ -} __PACKED; - -#define IAX_FIRMWARE_MAGIC 0x69617879 - -struct ast_iax2_firmware_header { - unsigned int magic; /* Magic number */ - unsigned short version; /* Software version */ - unsigned char devname[16]; /* Device */ - unsigned int datalen; /* Data length of file beyond header */ - unsigned char chksum[16]; /* Checksum of all data */ - unsigned char data[]; -} __PACKED; - - -#ifdef _MSC_VER -#pragma pack(pop) -#else -#ifndef __GNUC__ -#pragma pack() -#endif -#endif - -#undef __PACKED - -#endif diff --git a/src/mod/endpoints/mod_iax/jitterbuf.c b/src/mod/endpoints/mod_iax/jitterbuf.c deleted file mode 100644 index 06defca911..0000000000 --- a/src/mod/endpoints/mod_iax/jitterbuf.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * jitterbuf: an application-independent jitterbuffer - * - * Copyrights: - * Copyright (C) 2004-2005, Horizon Wimba, Inc. - * - * Contributors: - * Steve Kann - * - * This program is free software, distributed under the terms of - * the GNU Lesser (Library) General Public License - * - * Copyright on this file is disclaimed to Digium for inclusion in Asterisk - */ - -#include "iax2.h" -#include -#include -#include -#include - -#include "jitterbuf.h" - -/* define these here, just for ancient compiler systems */ -#define JB_LONGMAX 2147483647L -#define JB_LONGMIN (-JB_LONGMAX - 1L) - -/* MS VC can't do __VA_ARGS__ */ -#if (defined(WIN32) || defined(_WIN32_WCE)) && defined(_MSC_VER) -#define jb_warn if (warnf) warnf -#define jb_err if (errf) errf -#define jb_dbg if (dbgf) dbgf - -#ifdef DEEP_DEBUG -#define jb_dbg2 if (dbgf) dbgf -#else -#define jb_dbg2 if (0) dbgf -#endif - -#else - -#define jb_warn(...) (warnf ? warnf(__VA_ARGS__) : (void)0) -#define jb_err(...) (errf ? errf(__VA_ARGS__) : (void)0) -#define jb_dbg(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0) - -#ifdef DEEP_DEBUG -#define jb_dbg2(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0) -#else -#define jb_dbg2(...) ((void)0) -#endif - -#endif - -static jb_output_function_t warnf, errf, dbgf; - -void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg) -{ - errf = err; - warnf = warn; - dbgf = dbg; -} - -static void increment_losspct(jitterbuf * jb) -{ - jb->info.losspct = (100000 + 499 * jb->info.losspct) / 500; -} - -static void decrement_losspct(jitterbuf * jb) -{ - jb->info.losspct = (499 * jb->info.losspct) / 500; -} - -void jb_reset(jitterbuf * jb) -{ - /* only save settings */ - jb_conf s = jb->info.conf; - memset(jb, 0, sizeof(*jb)); - jb->info.conf = s; - - /* initialize length, using the configured value */ - jb->info.current = jb->info.target = jb->info.conf.target_extra; - jb->info.silence_begin_ts = -1; -} - -jitterbuf *jb_new() -{ - jitterbuf *jb = (jitterbuf *) malloc(sizeof(*jb)); - - if (!jb) - return NULL; - - jb->info.conf.target_extra = JB_TARGET_EXTRA; - - jb_reset(jb); - - return jb; -} - -void jb_destroy(jitterbuf * jb) -{ - jb_frame *frame; - - /* free all the frames on the "free list" */ - frame = jb->free; - while (frame != NULL) { - jb_frame *next = frame->next; - free(frame); - frame = next; - } - - /* free ourselves! */ - free(jb); -} - - - -#if 0 -static int longcmp(const void *a, const void *b) -{ - return *(long *) a - *(long *) b; -} -#endif - -/* simple history manipulation */ -/* maybe later we can make the history buckets variable size, or something? */ -/* drop parameter determines whether we will drop outliers to minimize - * delay */ -static int history_put(jitterbuf * jb, time_in_ms_t ts, time_in_ms_t now) -{ - time_in_ms_t delay = now - (ts - jb->info.resync_offset); - time_in_ms_t threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold; - time_in_ms_t kicked; - - /* don't add special/negative times to history */ - if (ts <= 0) - return 0; - - /* check for drastic change in delay */ - if (jb->info.conf.resync_threshold != -1) { - if (iax_abs(delay - jb->info.last_delay) > threshold) { - jb->info.cnt_delay_discont++; - if (jb->info.cnt_delay_discont > 3) { - /* resync the jitterbuffer */ - jb->info.cnt_delay_discont = 0; - jb->hist_ptr = 0; - jb->hist_maxbuf_valid = 0; - - jb_warn("Resyncing the jb. last_delay %ld, this delay %ld, threshold %ld, new offset %ld\n", jb->info.last_delay, delay, threshold, - ts - now); - jb->info.resync_offset = ts - now; - jb->info.last_delay = delay = 0; /* after resync, frame is right on time */ - } else { - return -1; - } - } else { - jb->info.last_delay = delay; - jb->info.cnt_delay_discont = 0; - } - } - - kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ]; - - jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay; - - /* optimization; the max/min buffers don't need to be recalculated, - * if this packet's entry doesn't change them. This happens if this - * packet is not involved, _and_ any packet that got kicked out of - * the history is also not involved. We do a number of comparisons, - * but it's probably still worthwhile, because it will usually - * succeed, and should be a lot faster than going through all 500 - * packets in history */ - if (!jb->hist_maxbuf_valid) - return 0; - - /* don't do this until we've filled history - * (reduces some edge cases below) */ - if (jb->hist_ptr < JB_HISTORY_SZ) - goto invalidate; - - /* if the new delay would go into min */ - if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ - 1]) - goto invalidate; - - /* or max.. */ - if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ - 1]) - goto invalidate; - - /* or the kicked delay would be in min */ - if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ - 1]) - goto invalidate; - - if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ - 1]) - goto invalidate; - - /* if we got here, we don't need to invalidate, 'cause this delay didn't - * affect things */ - return 0; - /* end optimization */ - - - invalidate: - jb->hist_maxbuf_valid = 0; - return 0; -} - -static void history_calc_maxbuf(jitterbuf * jb) -{ - int i, j; - - if (jb->hist_ptr == 0) - return; - - - /* initialize maxbuf/minbuf to the latest value */ - for (i = 0; i < JB_HISTORY_MAXBUF_SZ; i++) { - /* - * jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ]; - * jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ]; - */ - jb->hist_maxbuf[i] = JB_LONGMIN; - jb->hist_minbuf[i] = JB_LONGMAX; - } - - /* use insertion sort to populate maxbuf */ - /* we want it to be the top "n" values, in order */ - - /* start at the beginning, or JB_HISTORY_SZ frames ago */ - i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0; - - for (; i < jb->hist_ptr; i++) { - time_in_ms_t toins = jb->history[i % JB_HISTORY_SZ]; - - /* if the maxbuf should get this */ - if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ - 1]) { - - /* insertion-sort it into the maxbuf */ - for (j = 0; j < JB_HISTORY_MAXBUF_SZ; j++) { - /* found where it fits */ - if (toins > jb->hist_maxbuf[j]) { - /* move over */ - memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0])); - /* insert */ - jb->hist_maxbuf[j] = toins; - - break; - } - } - } - - /* if the minbuf should get this */ - if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ - 1]) { - - /* insertion-sort it into the maxbuf */ - for (j = 0; j < JB_HISTORY_MAXBUF_SZ; j++) { - /* found where it fits */ - if (toins < jb->hist_minbuf[j]) { - /* move over */ - memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0])); - /* insert */ - jb->hist_minbuf[j] = toins; - - break; - } - } - } -#if 0 - int k; - fprintf(stderr, "toins = %ld\n", toins); - fprintf(stderr, "maxbuf ="); - for (k = 0; k < JB_HISTORY_MAXBUF_SZ; k++) - fprintf(stderr, "%ld ", jb->hist_maxbuf[k]); - fprintf(stderr, "\nminbuf ="); - for (k = 0; k < JB_HISTORY_MAXBUF_SZ; k++) - fprintf(stderr, "%ld ", jb->hist_minbuf[k]); - fprintf(stderr, "\n"); -#endif - } - - jb->hist_maxbuf_valid = 1; -} - -static void history_get(jitterbuf * jb) -{ - time_in_ms_t max, min, jitter; - int index; - int count; - - if (!jb->hist_maxbuf_valid) - history_calc_maxbuf(jb); - - /* count is how many items in history we're examining */ - count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ; - - /* index is the "n"ths highest/lowest that we'll look for */ - index = count * JB_HISTORY_DROPPCT / 100; - - /* sanity checks for index */ - if (index > (JB_HISTORY_MAXBUF_SZ - 1)) - index = JB_HISTORY_MAXBUF_SZ - 1; - - - if (index < 0) { - jb->info.min = 0; - jb->info.jitter = 0; - return; - } - - max = jb->hist_maxbuf[index]; - min = jb->hist_minbuf[index]; - - jitter = max - min; - - /* these debug stmts compare the difference between looking at the absolute jitter, and the - * values we get by throwing away the outliers */ - /* - fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", index, min, max, jitter); - fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", 0, jb->hist_minbuf[0], jb->hist_maxbuf[0], jb->hist_maxbuf[0]-jb->hist_minbuf[0]); - */ - - jb->info.min = min; - jb->info.jitter = jitter; -} - -/* returns 1 if frame was inserted into head of queue, 0 otherwise */ -static int queue_put(jitterbuf * jb, void *data, const enum jb_frame_type type, long ms, time_in_ms_t ts) -{ - jb_frame *frame = jb->free; - jb_frame *p; - int head = 0; - time_in_ms_t resync_ts = ts - jb->info.resync_offset; - - if (frame) { - jb->free = frame->next; - } else { - frame = (jb_frame *) malloc(sizeof(*frame)); - if (!frame) { - jb_err("cannot allocate frame\n"); - return 0; - } - } - - jb->info.frames_cur++; - - frame->data = data; - frame->ts = resync_ts; - frame->ms = ms; - frame->type = type; - - /* - * frames are a circular list, jb-frames points to to the lowest ts, - * jb->frames->prev points to the highest ts - */ - - if (!jb->frames) { /* queue is empty */ - jb->frames = frame; - frame->next = frame; - frame->prev = frame; - head = 1; - } else if (resync_ts < jb->frames->ts) { - frame->next = jb->frames; - frame->prev = jb->frames->prev; - - frame->next->prev = frame; - frame->prev->next = frame; - - /* frame is out of order */ - jb->info.frames_ooo++; - - jb->frames = frame; - head = 1; - } else { - p = jb->frames; - - /* frame is out of order */ - if (resync_ts < p->prev->ts) - jb->info.frames_ooo++; - - while (resync_ts < p->prev->ts && p->prev != jb->frames) - p = p->prev; - - frame->next = p; - frame->prev = p->prev; - - frame->next->prev = frame; - frame->prev->next = frame; - } - return head; -} - -static time_in_ms_t queue_next(jitterbuf * jb) -{ - if (jb->frames) - return jb->frames->ts; - else - return -1; -} - -static time_in_ms_t queue_last(jitterbuf * jb) -{ - if (jb->frames) - return jb->frames->prev->ts; - else - return -1; -} - -static jb_frame *_queue_get(jitterbuf * jb, time_in_ms_t ts, int all) -{ - jb_frame *frame; - frame = jb->frames; - - if (!frame) - return NULL; - - /*jb_warn("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts); */ - - if (all || ts >= frame->ts) { - /* remove this frame */ - frame->prev->next = frame->next; - frame->next->prev = frame->prev; - - if (frame->next == frame) - jb->frames = NULL; - else - jb->frames = frame->next; - - - /* insert onto "free" single-linked list */ - frame->next = jb->free; - jb->free = frame; - - jb->info.frames_cur--; - - /* we return the frame pointer, even though it's on free list, - * but caller must copy data */ - return frame; - } - - return NULL; -} - -static jb_frame *queue_get(jitterbuf * jb, time_in_ms_t ts) -{ - return _queue_get(jb, ts, 0); -} - -static jb_frame *queue_getall(jitterbuf * jb) -{ - return _queue_get(jb, 0, 1); -} - -#if 0 -/* some diagnostics */ -static void jb_dbginfo(jitterbuf * jb) -{ - if (dbgf == NULL) - return; - - jb_dbg("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n", - jb->info.frames_in, jb->info.frames_out, jb->info.frames_late, jb->info.frames_lost, jb->info.frames_dropped, jb->info.frames_cur); - - jb_dbg("jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n", - jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min, - jb->info.frames_cur ? (jb->info.current - jb->info.min) / jb->info.frames_cur : -8); - if (jb->info.frames_in > 0) - jb_dbg("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n", - jb->info.frames_lost * 100 / (jb->info.frames_in + jb->info.frames_lost), jb->info.frames_late * 100 / jb->info.frames_in); - jb_dbg("jb info: queue %d -> %d. last_ts %d (queue len: %d) last_ms %d\n", - queue_next(jb), queue_last(jb), jb->info.next_voice_ts, queue_last(jb) - queue_next(jb), jb->info.last_voice_ms); -} -#endif - -#ifdef DEEP_DEBUG -static void jb_chkqueue(jitterbuf * jb) -{ - int i = 0; - jb_frame *p = jb->frames; - - if (!p) { - return; - } - - do { - if (p->next == NULL) { - jb_err("Queue is BROKEN at item [%d]", i); - } - i++; - p = p->next; - } while (p->next != jb->frames); -} - -static void jb_dbgqueue(jitterbuf * jb) -{ - int i = 0; - jb_frame *p = jb->frames; - - jb_dbg("queue: "); - - if (!p) { - jb_dbg("EMPTY\n"); - return; - } - - do { - jb_dbg("[%d]=%ld ", i++, p->ts); - p = p->next; - } while (p->next != jb->frames); - - jb_dbg("\n"); -} -#endif - -enum jb_return_code jb_put(jitterbuf * jb, void *data, const enum jb_frame_type type, long ms, time_in_ms_t ts, time_in_ms_t now) -{ - jb->info.frames_in++; - - if (type == JB_TYPE_VOICE) { - /* presently, I'm only adding VOICE frames to history and drift - * calculations; mostly because with the IAX integrations, I'm - * sending retransmitted control frames with their awkward - * timestamps through - */ - if (history_put(jb, ts, now)) - return JB_DROP; - } - - /* if put into head of queue, caller needs to reschedule */ - if (queue_put(jb, data, type, ms, ts)) { - return JB_SCHED; - } - - return JB_OK; -} - - -static enum jb_return_code _jb_get(jitterbuf * jb, jb_frame * frameout, time_in_ms_t now, long interpl) -{ - jb_frame *frame; - time_in_ms_t diff; - - /*if ((now - jb_next(jb)) > 2 * jb->info.last_voice_ms) jb_warn("SCHED: %ld", (now - jb_next(jb))); */ - /* get jitter info */ - history_get(jb); - - - /* target */ - jb->info.target = jb->info.jitter + jb->info.min + jb->info.conf.target_extra; - - /* if a hard clamp was requested, use it */ - if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) { - jb_dbg("clamping target from %d to %d\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf); - jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf; - } - - diff = jb->info.target - jb->info.current; - - /* jb_warn("diff = %d lms=%d last = %d now = %d\n", diff, */ - /* jb->info.last_voice_ms, jb->info.last_adjustment, now); */ - - /* let's work on non-silent case first */ - if (!jb->info.silence_begin_ts) { - /* we want to grow */ - if ((diff > 0) && - /* we haven't grown in the delay length */ - (((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) || - /* we need to grow more than the "length" we have left */ - (diff > queue_last(jb) - queue_next(jb)))) { - /* grow by interp frame length */ - jb->info.current += interpl; - jb->info.next_voice_ts += interpl; - jb->info.last_voice_ms = interpl; - jb->info.last_adjustment = now; - jb->info.cnt_contig_interp++; - /* assume silence instead of continuing to interpolate */ - if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) { - jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current; - } - jb_dbg("G"); - return JB_INTERP; - } - - frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current); - - /* not a voice frame; just return it. */ - if (frame && frame->type != JB_TYPE_VOICE) { - /* track start of silence */ - if (frame->type == JB_TYPE_SILENCE) { - jb->info.silence_begin_ts = frame->ts; - jb->info.cnt_contig_interp = 0; - } - - *frameout = *frame; - jb->info.frames_out++; - jb_dbg("o"); - return JB_OK; - } - - /* voice frame is later than expected */ - if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) { - if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) { - /* either we interpolated past this frame in the last jb_get */ - /* or the frame is still in order, but came a little too quick */ - *frameout = *frame; - /* reset expectation for next frame */ - jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms; - jb->info.frames_out++; - decrement_losspct(jb); - jb->info.cnt_contig_interp = 0; - jb_dbg("v"); - return JB_OK; - } else { - /* voice frame is late */ - *frameout = *frame; - jb->info.frames_out++; - decrement_losspct(jb); - jb->info.frames_late++; - jb->info.frames_lost--; - jb_dbg("l"); - /*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb)); - jb_warninfo(jb); */ - return JB_DROP; - } - } - - /* keep track of frame sizes, to allow for variable sized-frames */ - if (frame && frame->ms > 0) { - jb->info.last_voice_ms = frame->ms; - } - - /* we want to shrink; shrink at 1 frame / 500ms */ - /* unless we don't have a frame, then shrink 1 frame */ - /* every 80ms (though perhaps we can shrink even faster */ - /* in this case) */ - if (diff < -jb->info.conf.target_extra && ((!frame && jb->info.last_adjustment + 80 < now) || (jb->info.last_adjustment + 500 < now))) { - - jb->info.last_adjustment = now; - jb->info.cnt_contig_interp = 0; - - if (frame) { - *frameout = *frame; - /* shrink by frame size we're throwing out */ - jb->info.current -= frame->ms; - jb->info.frames_out++; - decrement_losspct(jb); - jb->info.frames_dropped++; - jb_dbg("s"); - return JB_DROP; - } else { - /* shrink by last_voice_ms */ - jb->info.current -= jb->info.last_voice_ms; - jb->info.frames_lost++; - increment_losspct(jb); - jb_dbg("S"); - return JB_NOFRAME; - } - } - - /* lost frame */ - if (!frame) { - /* this is a bit of a hack for now, but if we're close to - * target, and we find a missing frame, it makes sense to - * grow, because the frame might just be a bit late; - * otherwise, we presently get into a pattern where we return - * INTERP for the lost frame, then it shows up next, and we - * throw it away because it's late */ - /* I've recently only been able to replicate this using - * iaxclient talking to app_echo on asterisk. In this case, - * my outgoing packets go through asterisk's (old) - * jitterbuffer, and then might get an unusual increasing delay - * there if it decides to grow?? */ - /* Update: that might have been a different bug, that has been fixed.. - * But, this still seemed like a good idea, except that it ended up making a single actual - * lost frame get interpolated two or more times, when there was "room" to grow, so it might - * be a bit of a bad idea overall */ - /*if (diff > -1 * jb->info.last_voice_ms) { - jb->info.current += jb->info.last_voice_ms; - jb->info.last_adjustment = now; - jb_warn("g"); - return JB_INTERP; - } */ - jb->info.frames_lost++; - increment_losspct(jb); - jb->info.next_voice_ts += interpl; - jb->info.last_voice_ms = interpl; - jb->info.cnt_contig_interp++; - /* assume silence instead of continuing to interpolate */ - if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) { - jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current; - } - jb_dbg("L"); - return JB_INTERP; - } - - /* normal case; return the frame, increment stuff */ - *frameout = *frame; - jb->info.next_voice_ts += frame->ms; - jb->info.frames_out++; - jb->info.cnt_contig_interp = 0; - decrement_losspct(jb); - jb_dbg("v"); - return JB_OK; - } else { - /* TODO: after we get the non-silent case down, we'll make the - * silent case -- basically, we'll just grow and shrink faster - * here, plus handle next_voice_ts a bit differently */ - - /* to disable silent special case altogether, just uncomment this: */ - /* jb->info.silence_begin_ts = 0; */ - - /* shrink interpl len every 10ms during silence */ - if (diff < -jb->info.conf.target_extra && jb->info.last_adjustment + 10 <= now) { - jb->info.current -= interpl; - jb->info.last_adjustment = now; - } - - frame = queue_get(jb, now - jb->info.current); - if (!frame) { - return JB_NOFRAME; - } else if (frame->type != JB_TYPE_VOICE) { - /* normal case; in silent mode, got a non-voice frame */ - *frameout = *frame; - jb->info.frames_out++; - return JB_OK; - } - if (frame->ts < jb->info.silence_begin_ts) { - /* voice frame is late */ - *frameout = *frame; - jb->info.frames_out++; - decrement_losspct(jb); - jb->info.frames_late++; - jb->info.frames_lost--; - jb_dbg("l"); - /*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb)); - jb_warninfo(jb); */ - return JB_DROP; - } else { - /* voice frame */ - /* try setting current to target right away here */ - jb->info.current = jb->info.target; - jb->info.silence_begin_ts = 0; - jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms; - jb->info.last_voice_ms = frame->ms; - jb->info.frames_out++; - decrement_losspct(jb); - *frameout = *frame; - jb_dbg("V"); - return JB_OK; - } - } -} - -time_in_ms_t jb_next(jitterbuf * jb) -{ - if (jb->info.silence_begin_ts) { - if (jb->frames) { - time_in_ms_t next = queue_next(jb); - history_get(jb); - /* shrink during silence */ - if (jb->info.target - jb->info.current < -jb->info.conf.target_extra) - return jb->info.last_adjustment + 10; - return next + jb->info.target; - } else - return JB_LONGMAX; - } else { - return jb->info.next_voice_ts; - } -} - -enum jb_return_code jb_get(jitterbuf * jb, jb_frame * frameout, time_in_ms_t now, long interpl) -{ - enum jb_return_code ret = _jb_get(jb, frameout, now, interpl); -#if 0 - static int lastts = 0; - int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0; - jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists); - if (thists && thists < lastts) - jb_warn("XXXX timestamp roll-back!!!\n"); - lastts = thists; -#endif - return ret; -} - -enum jb_return_code jb_getall(jitterbuf * jb, jb_frame * frameout) -{ - jb_frame *frame; - frame = queue_getall(jb); - - if (!frame) { - return JB_NOFRAME; - } - - *frameout = *frame; - return JB_OK; -} - - -enum jb_return_code jb_getinfo(jitterbuf * jb, jb_info * stats) -{ - history_get(jb); - - *stats = jb->info; - - return JB_OK; -} - -enum jb_return_code jb_setconf(jitterbuf * jb, jb_conf * conf) -{ - /* take selected settings from the struct */ - - jb->info.conf.max_jitterbuf = conf->max_jitterbuf; - jb->info.conf.resync_threshold = conf->resync_threshold; - jb->info.conf.max_contig_interp = conf->max_contig_interp; - - /* -1 indicates use of the default JB_TARGET_EXTRA value */ - jb->info.conf.target_extra = (conf->target_extra == -1) - ? JB_TARGET_EXTRA : conf->target_extra; - - /* update these to match new target_extra setting */ - jb->info.current = jb->info.conf.target_extra; - jb->info.target = jb->info.conf.target_extra; - - return JB_OK; -} diff --git a/src/mod/endpoints/mod_iax/jitterbuf.h b/src/mod/endpoints/mod_iax/jitterbuf.h deleted file mode 100644 index 60331b25e3..0000000000 --- a/src/mod/endpoints/mod_iax/jitterbuf.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * jitterbuf: an application-independent jitterbuffer - * - * Copyrights: - * Copyright (C) 2004-2005, Horizon Wimba, Inc. - * - * Contributors: - * Steve Kann - * - * This program is free software, distributed under the terms of - * the GNU Lesser (Library) General Public License - * - * Copyright on this file is disclaimed to Digium for inclusion in Asterisk - */ - -#ifndef _JITTERBUF_H_ -#define _JITTERBUF_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* configuration constants */ - /* Number of historical timestamps to use in calculating jitter and drift */ -#define JB_HISTORY_SZ 500 - /* what percentage of timestamps should we drop from the history when we examine it; - * this might eventually be something made configurable */ -#define JB_HISTORY_DROPPCT 3 - /* the maximum droppct we can handle (say it was configurable). */ -#define JB_HISTORY_DROPPCT_MAX 4 - /* the size of the buffer we use to keep the top and botton timestamps for dropping */ -#define JB_HISTORY_MAXBUF_SZ JB_HISTORY_SZ * JB_HISTORY_DROPPCT_MAX / 100 - /* amount of additional jitterbuffer adjustment */ -#define JB_TARGET_EXTRA 40 - /* ms between growing and shrinking; may not be honored if jitterbuffer runs out of space */ -#define JB_ADJUST_DELAY 40 - -enum jb_return_code { - /* return codes */ - JB_OK, /* 0 */ - JB_EMPTY, /* 1 */ - JB_NOFRAME, /* 2 */ - JB_INTERP, /* 3 */ - JB_DROP, /* 4 */ - JB_SCHED /* 5 */ -}; - -enum jb_frame_type { -/* frame types */ - JB_TYPE_CONTROL, /* 0 */ - JB_TYPE_VOICE, /* 1 */ - JB_TYPE_VIDEO, /* 2 - reserved */ - JB_TYPE_SILENCE /* 3 */ -}; - -typedef struct jb_conf { - /* settings */ - long max_jitterbuf; /* defines a hard clamp to use in setting the jitter buffer delay */ - long resync_threshold; /* the jb will resync when delay increases to (2 * jitter) + this param */ - long max_contig_interp; /* the max interp frames to return in a row */ - long target_extra; /* amount of additional jitterbuffer adjustment, overrides JB_TARGET_EXTRA */ -} jb_conf; - -typedef struct jb_info { - jb_conf conf; - - /* statistics */ - long frames_in; /* number of frames input to the jitterbuffer.*/ - long frames_out; /* number of frames output from the jitterbuffer.*/ - long frames_late; /* number of frames which were too late, and dropped.*/ - long frames_lost; /* number of missing frames.*/ - long frames_dropped; /* number of frames dropped (shrinkage) */ - long frames_ooo; /* number of frames received out-of-order */ - long frames_cur; /* number of frames presently in jb, awaiting delivery.*/ - time_in_ms_t jitter; /* jitter measured within current history interval*/ - time_in_ms_t min; /* minimum lateness within current history interval */ - time_in_ms_t current; /* the present jitterbuffer adjustment */ - time_in_ms_t target; /* the target jitterbuffer adjustment */ - long losspct; /* recent lost frame percentage (* 1000) */ - time_in_ms_t next_voice_ts; /* the ts of the next frame to be read from the jb - in receiver's time */ - long last_voice_ms; /* the duration of the last voice frame */ - time_in_ms_t silence_begin_ts; /* the time of the last CNG frame, when in silence */ - time_in_ms_t last_adjustment; /* the time of the last adjustment */ - time_in_ms_t last_delay; /* the last now added to history */ - long cnt_delay_discont; /* the count of discontinuous delays */ - time_in_ms_t resync_offset; /* the amount to offset ts to support resyncs */ - long cnt_contig_interp; /* the number of contiguous interp frames returned */ -} jb_info; - -typedef struct jb_frame { - void *data; /* the frame data */ - time_in_ms_t ts; /* the relative delivery time expected */ - long ms; /* the time covered by this frame, in sec/8000 */ - enum jb_frame_type type; /* the type of frame */ - struct jb_frame *next, *prev; -} jb_frame; - -typedef struct jitterbuf { - jb_info info; - - /* history */ - time_in_ms_t history[JB_HISTORY_SZ]; /* history */ - int hist_ptr; /* points to index in history for next entry */ - time_in_ms_t hist_maxbuf[JB_HISTORY_MAXBUF_SZ]; /* a sorted buffer of the max delays (highest first) */ - time_in_ms_t hist_minbuf[JB_HISTORY_MAXBUF_SZ]; /* a sorted buffer of the min delays (lowest first) */ - int hist_maxbuf_valid; /* are the "maxbuf"/minbuf valid? */ - - jb_frame *frames; /* queued frames */ - jb_frame *free; /* free frames (avoid malloc?) */ -} jitterbuf; - - -/* new jitterbuf */ -jitterbuf * jb_new(void); - -/* destroy jitterbuf */ -void jb_destroy(jitterbuf *jb); - -/* reset jitterbuf */ -/* NOTE: The jitterbuffer should be empty before you call this, otherwise - * you will leak queued frames, and some internal structures */ -void jb_reset(jitterbuf *jb); - -/* queue a frame data=frame data, timings (in ms): ms=length of frame (for voice), ts=ts (sender's time) - * now=now (in receiver's time) return value is one of - * JB_OK: Frame added. Last call to jb_next() still valid - * JB_DROP: Drop this frame immediately - * JB_SCHED: Frame added. Call jb_next() to get a new time for the next frame - */ -enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, time_in_ms_t ts, time_in_ms_t now); - -/* get a frame for time now (receiver's time) return value is one of - * JB_OK: You've got frame! - * JB_DROP: Here's an audio frame you should just drop. Ask me again for this time.. - * JB_NOFRAME: There's no frame scheduled for this time. - * JB_INTERP: Please interpolate an interpl-length frame for this time (either we need to grow, or there was a lost frame) - * JB_EMPTY: The jb is empty. - */ -enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frame, time_in_ms_t now, long interpl); - -/* unconditionally get frames from jitterbuf until empty */ -enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout); - -/* when is the next frame due out, in receiver's time (0=EMPTY) - * This value may change as frames are added (esp non-audio frames) */ -time_in_ms_t jb_next(jitterbuf *jb); - -/* get jitterbuf info: only "statistics" may be valid */ -enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats); - -/* set jitterbuf conf */ -enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf); - -typedef void (*jb_output_function_t)(const char *fmt, ...); -extern void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg); - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/src/mod/endpoints/mod_iax/md5.c b/src/mod/endpoints/mod_iax/md5.c deleted file mode 100644 index 9f8505ace6..0000000000 --- a/src/mod/endpoints/mod_iax/md5.c +++ /dev/null @@ -1,296 +0,0 @@ -/* MD5 checksum routines used for authentication. Not covered by GPL, but - in the public domain as per the copyright below */ - -#ifdef FREEBSD -# include -#elif defined(LINUX) -# include -# include -# include -#elif defined(SOLARIS) - /* each solaris is different -- this won't work on 2.6 or 2.7 */ -# include /* Defines either _LITTLE_ENDIAN or _BIG_ENDIAN */ -# define __BIG_ENDIAN 4321 -# define __LITTLE_ENDIAN 1234 -# define BIG_ENDIAN 4321 -# define LITTLE_ENDIAN 1234 -# ifdef _LITTLE_ENDIAN -# define __BYTE_ORDER __LITTLE_ENDIAN -# define BYTE_ORDER LITTLE_ENDIAN -# else -# define __BYTE_ORDER __BIG_ENDIAN -# define BYTE_ORDER BIG_ENDIAN -# endif -#endif - -#ifdef _MSC_VER -#ifndef __LITTLE_ENDIAN -#define __LITTLE_ENDIAN 1234 -#endif -#ifndef __BIG_ENDIAN -#define __BIG_ENDIAN 4321 -#endif -#ifndef __BYTE_ORDER -#define __BYTE_ORDER __LITTLE_ENDIAN -#endif -#endif - -#if __BYTE_ORDER == __BIG_ENDIAN || BYTE_ORDER == BIG_ENDIAN -# define HIGHFIRST 1 -#elif __BYTE_ORDER == __LITTLE_ENDIAN || BYTE_ORDER == LITLE_ENDIAN -# undef HIGHFIRST -#else -# error "Please fix " -#endif - -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ -#include /* for memcpy() */ -#include "md5.h" - -#ifndef HIGHFIRST -#define byteReverse(buf, len) /* Nothing */ -#else -void byteReverse(unsigned char *buf, unsigned longs); - -#ifndef ASM_MD5 -/* - * Note: this code is harmless on little-endian machines. - */ -void byteReverse(unsigned char *buf, unsigned longs) -{ - uint32 t; - do { - t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); - *(uint32 *) buf = t; - buf += 4; - } while (--longs); -} -#endif -#endif - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - uint32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Final(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((uint32 *) ctx->in)[14] = ctx->bits[0]; - ((uint32 *) ctx->in)[15] = ctx->bits[1]; - - MD5Transform(ctx->buf, (uint32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -#ifndef ASM_MD5 - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -void MD5Transform(uint32 buf[4], uint32 const in[16]) -{ - register uint32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#endif diff --git a/src/mod/endpoints/mod_iax/md5.h b/src/mod/endpoints/mod_iax/md5.h deleted file mode 100644 index 69e0071fc5..0000000000 --- a/src/mod/endpoints/mod_iax/md5.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef MD5_H -#define MD5_H - -#if defined(__alpha) || defined(__x86_64) -typedef unsigned int uint32; -#else -typedef unsigned long uint32; -#endif - -struct MD5Context { - uint32 buf[4]; - uint32 bits[2]; - unsigned char in[64]; -}; - -void MD5Init(struct MD5Context *context); -void MD5Update(struct MD5Context *context, unsigned char const *buf, - unsigned len); -void MD5Final(unsigned char digest[16], struct MD5Context *context); -void MD5Transform(uint32 buf[4], uint32 const in[16]); - -/* - * This is needed to make RSAREF happy on some MS-DOS compilers. - */ -typedef struct MD5Context MD5_CTX; - -#endif /* !MD5_H */ diff --git a/src/mod/endpoints/mod_iax/mod_iax.2008.vcproj b/src/mod/endpoints/mod_iax/mod_iax.2008.vcproj deleted file mode 100644 index 6d8fb032df..0000000000 --- a/src/mod/endpoints/mod_iax/mod_iax.2008.vcproj +++ /dev/null @@ -1,321 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mod/endpoints/mod_iax/mod_iax.c b/src/mod/endpoints/mod_iax/mod_iax.c deleted file mode 100644 index 054ce2586c..0000000000 --- a/src/mod/endpoints/mod_iax/mod_iax.c +++ /dev/null @@ -1,1234 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2009, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Anthony Minessale II - * - * - * mod_iax.c -- IAX2 Endpoint Module - * - */ -#include - -SWITCH_MODULE_LOAD_FUNCTION(mod_iax_load); -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_iax_shutdown); -SWITCH_MODULE_RUNTIME_FUNCTION(mod_iax_runtime); -SWITCH_MODULE_DEFINITION(mod_iax, mod_iax_load, mod_iax_shutdown, mod_iax_runtime); - -#include -#include -#include -#ifdef WIN32 -#include -#endif - -switch_endpoint_interface_t *iax_endpoint_interface; -static switch_memory_pool_t *module_pool = NULL; -static int running = 1; - - -typedef enum { - TFLAG_IO = (1 << 0), - TFLAG_INBOUND = (1 << 1), - TFLAG_OUTBOUND = (1 << 2), - TFLAG_DTMF = (1 << 3), - TFLAG_VOICE = (1 << 4), - TFLAG_HANGUP = (1 << 5), - TFLAG_LINEAR = (1 << 6), - TFLAG_CODEC = (1 << 7), - TFLAG_BREAK = (1 << 8) -} TFLAGS; - -typedef enum { - GFLAG_MY_CODEC_PREFS = (1 << 0) -} GFLAGS; - -static struct { - int debug; - char *ip; - int port; - char *dialplan; - char *codec_string; - char *codec_order[SWITCH_MAX_CODECS]; - int codec_order_last; - char *codec_rates_string; - char *codec_rates[SWITCH_MAX_CODECS]; - int codec_rates_last; - unsigned int flags; - int fd; - int calls; - switch_mutex_t *mutex; - int media_timeout; -} globals; - -struct private_object { - unsigned int flags; - switch_codec_t read_codec; - switch_codec_t write_codec; - switch_frame_t *read_frame; - switch_frame_t cng_frame; - unsigned char cng_databuf[10]; - switch_core_session_t *session; - struct iax_session *iax_session; - switch_caller_profile_t *caller_profile; - unsigned int codec; - unsigned int codecs; - unsigned short samprate; - switch_mutex_t *mutex; - switch_mutex_t *flag_mutex; - int cng_count; - switch_timer_t timer; - switch_queue_t *frame_queue; - int media_timeout; - //switch_thread_cond_t *cond; -}; - -typedef struct private_object private_t; - - -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ip, globals.ip); - - -static char *IAXNAMES[] = { "IAX_EVENT_CONNECT", "IAX_EVENT_ACCEPT", "IAX_EVENT_HANGUP", "IAX_EVENT_REJECT", "IAX_EVENT_VOICE", - "IAX_EVENT_DTMF", "IAX_EVENT_TIMEOUT", "IAX_EVENT_LAGRQ", "IAX_EVENT_LAGRP", "IAX_EVENT_RINGA", - "IAX_EVENT_PING", "IAX_EVENT_PONG", "IAX_EVENT_BUSY", "IAX_EVENT_ANSWER", "IAX_EVENT_IMAGE", - "IAX_EVENT_AUTHRQ", "IAX_EVENT_AUTHRP", "IAX_EVENT_REGREQ", "IAX_EVENT_REGACK", - "IAX_EVENT_URL", "IAX_EVENT_LDCOMPLETE", "IAX_EVENT_TRANSFER", "IAX_EVENT_DPREQ", - "IAX_EVENT_DPREP", "IAX_EVENT_DIAL", "IAX_EVENT_QUELCH", "IAX_EVENT_UNQUELCH", - "IAX_EVENT_UNLINK", "IAX_EVENT_LINKREJECT", "IAX_EVENT_TEXT", "IAX_EVENT_REGREJ", - "IAX_EVENT_LINKURL", "IAX_EVENT_CNG", "IAX_EVENT_REREQUEST", "IAX_EVENT_TXREPLY", - "IAX_EVENT_TXREJECT", "IAX_EVENT_TXACCEPT", "IAX_EVENT_TXREADY" -}; - - -struct ast_iana { - const unsigned int ast; - const int iana; - char *name; -}; - -//999 means it's wrong nad i dont know the real one -static struct ast_iana AST_IANA[] = { {AST_FORMAT_G723_1, 4, "g723.1"}, -{AST_FORMAT_GSM, 3, "gsm"}, -{AST_FORMAT_ULAW, 0, "ulaw"}, -{AST_FORMAT_ALAW, 8, "alaw"}, -{AST_FORMAT_G726, 999, "g726"}, -{AST_FORMAT_ADPCM, 999, "adpcm"}, -{AST_FORMAT_SLINEAR, 10, "slinear"}, -{AST_FORMAT_LPC10, 7, "lpc10"}, -{AST_FORMAT_G729A, 18, "g729"}, -{AST_FORMAT_SPEEX, 97, "speex"}, -{AST_FORMAT_SPEEX, 98, "speex"}, -{AST_FORMAT_ILBC, 102, "ilbc"}, -{AST_FORMAT_MAX_AUDIO, 999, ""}, -{AST_FORMAT_JPEG, 999, ""}, -{AST_FORMAT_PNG, 999, ""}, -{AST_FORMAT_H261, 999, ""}, -{AST_FORMAT_H263, 999, ""}, -{AST_FORMAT_MAX_VIDEO, 999, ""}, -{0, 0} -}; - -static char *ast2str(int ast) -{ - int x; - for (x = 0; x < 19; x++) { - if ((1 << x) == ast) { - return AST_IANA[x].name; - } - } - return ""; -} - -static unsigned int iana2ast(int iana) -{ - int x = 0; - unsigned int ast = 0; - - for (x = 0; AST_IANA[x].ast; x++) { - if (AST_IANA[x].iana == iana) { - ast = AST_IANA[x].ast; - break; - } - } - - return ast; -} - -static unsigned short iax_build_codec_rates(void) -{ - int x; - unsigned short samples = 0; - - for (x = 0; x < globals.codec_rates_last; x++) { - int rate = atoi(globals.codec_rates[x]); - switch (rate) { - case 8: - samples |= IAX_RATE_8KHZ; - break; - case 16: - samples |= IAX_RATE_16KHZ; - break; - case 22: - samples |= IAX_RATE_22KHZ; - break; - case 32: - samples |= IAX_RATE_32KHZ; - break; - case 44: - samples |= IAX_RATE_44KHZ; - break; - case 48: - samples |= IAX_RATE_48KHZ; - break; - default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "I don't know rate %d\n", rate); - break; - } - } - return samples; -} - -typedef enum { - IAX_SET = 1, - IAX_QUERY = 2 -} iax_io_t; - -static switch_status_t iax_set_codec(private_t *tech_pvt, struct iax_session *iax_session, - unsigned int *format, unsigned int *cababilities, unsigned short *samprate, iax_io_t io) -{ - char *dname = NULL; - switch_channel_t *channel; - const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS]; - int num_codecs = 0; - unsigned int local_cap = 0, mixed_cap = 0, chosen = 0, leading = 0; - int x, srate = 8000; - uint32_t interval = 0; - const switch_codec_implementation_t *read_impl; - - if (globals.codec_string) { - num_codecs = switch_loadable_module_get_codecs_sorted(codecs, SWITCH_MAX_CODECS, globals.codec_order, globals.codec_order_last); - } else { - num_codecs = switch_loadable_module_get_codecs(codecs, SWITCH_MAX_CODECS); - } - - if (num_codecs <= 0) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "NO codecs?\n"); - return SWITCH_STATUS_GENERR; - } - - for (x = 0; x < num_codecs; x++) { - static const switch_codec_implementation_t *imp; - for (imp = codecs[x]; imp; imp = imp->next) { - unsigned int codec = iana2ast(imp->ianacode); - if (io == IAX_QUERY && !(codec & local_cap)) { - iax_pref_codec_add(iax_session, codec); - } - local_cap |= codec; - } - } - - switch_assert(codecs[0]); - - if (io == IAX_SET) { - mixed_cap = (local_cap & *cababilities); - } else { - mixed_cap = local_cap; - } - - leading = iana2ast(codecs[0]->ianacode); - interval = codecs[0]->microseconds_per_packet / 1000; - if (io == IAX_QUERY) { - chosen = leading; - *format = chosen; - *cababilities = local_cap; - if (globals.codec_rates_last) { - *samprate = iax_build_codec_rates(); - tech_pvt->samprate = *samprate; - } - return SWITCH_STATUS_SUCCESS; - } else if (switch_test_flag(&globals, GFLAG_MY_CODEC_PREFS) && (leading & mixed_cap)) { - chosen = leading; - dname = codecs[0]->iananame; - } else { - unsigned int prefs[32]; - int len = 0; - - if (!switch_test_flag(&globals, GFLAG_MY_CODEC_PREFS)) { - len = iax_pref_codec_get(iax_session, prefs, sizeof(prefs)); - } - - if (len) { /*they sent us a pref and we don't want to be codec master */ - char pref_str[256] = "("; - - for (x = 0; x < len; x++) { - strncat(pref_str, ast2str(prefs[x]), sizeof(pref_str) - 1); - strncat(pref_str, x == len - 1 ? ")" : ",", sizeof(pref_str) - 1); - } - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_INFO, "Codec Prefs Detected: %s\n", pref_str); - - for (x = 0; x < len; x++) { - if ((prefs[x] & mixed_cap)) { - int z; - chosen = prefs[x]; - for (z = 0; z < num_codecs; z++) { - static const switch_codec_implementation_t *imp; - for (imp = codecs[z]; imp; imp = imp->next) { - if (prefs[x] == iana2ast(imp->ianacode)) { - dname = imp->iananame; - interval = imp->microseconds_per_packet / 1000; - break; - } - } - } - break; - } - } - } else { - if (*format & mixed_cap) { /* is the one we asked for here? */ - chosen = *format; - for (x = 0; x < num_codecs; x++) { - static const switch_codec_implementation_t *imp; - for (imp = codecs[x]; imp; imp = imp->next) { - unsigned int cap = iana2ast(imp->ianacode); - if (cap == chosen) { - dname = imp->iananame; - interval = imp->microseconds_per_packet / 1000; - break; - } - } - } - } else { /* c'mon there has to be SOMETHING... */ - for (x = 0; x < num_codecs; x++) { - static const switch_codec_implementation_t *imp; - for (imp = codecs[x]; imp; imp = imp->next) { - unsigned int cap = iana2ast(imp->ianacode); - if (cap & mixed_cap) { - chosen = cap; - dname = imp->iananame; - interval = imp->microseconds_per_packet / 1000; - break; - } - } - } - } - } - } - - if (!dname && !chosen) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "NO codecs?\n"); - return SWITCH_STATUS_GENERR; - } - - channel = switch_core_session_get_channel(tech_pvt->session); - - if (tech_pvt->samprate || *samprate) { - unsigned short samples = iax_build_codec_rates(); - unsigned short mixed = ((tech_pvt->samprate ? tech_pvt->samprate : *samprate) & samples); - - srate = 8000; - - if (mixed & IAX_RATE_16KHZ) { - srate = 16000; - } - if (mixed & IAX_RATE_22KHZ) { - srate = 22050; - } - if (mixed & IAX_RATE_32KHZ) { - srate = 32000; - } - if (mixed & IAX_RATE_44KHZ) { - srate = 44000; - } - if (mixed & IAX_RATE_48KHZ) { - srate = 48000; - } - } - - if (!strcasecmp(dname, "l16")) { - switch_set_flag_locked(tech_pvt, TFLAG_LINEAR); - } - if (switch_core_codec_init(&tech_pvt->read_codec, - dname, - NULL, - srate, - interval, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n"); - return SWITCH_STATUS_GENERR; - } else { - if (switch_core_codec_init(&tech_pvt->write_codec, - dname, - NULL, - srate, - interval, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n"); - switch_core_codec_destroy(&tech_pvt->read_codec); - return SWITCH_STATUS_GENERR; - } else { - int ms; - int rate; - ms = tech_pvt->write_codec.implementation->microseconds_per_packet / 1000; - rate = tech_pvt->write_codec.implementation->samples_per_second; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_INFO, "Activate Codec %s/%d %d ms\n", dname, rate, ms); - switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec); - switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec); - switch_set_flag_locked(tech_pvt, TFLAG_CODEC); - } - tech_pvt->codec = chosen; - tech_pvt->codecs = local_cap; - } - - read_impl = tech_pvt->read_codec.implementation; - - switch_core_timer_init(&tech_pvt->timer, "soft", - read_impl->microseconds_per_packet / 1000, - read_impl->samples_per_packet, - switch_core_session_get_pool(tech_pvt->session)); - - tech_pvt->media_timeout = (read_impl->samples_per_second * globals.media_timeout) / read_impl->samples_per_packet; - - - if (io == IAX_QUERY) { - *format = tech_pvt->codec; - *cababilities = local_cap; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_init(switch_core_session_t *session); -static switch_status_t channel_on_hangup(switch_core_session_t *session); -static switch_status_t channel_on_destroy(switch_core_session_t *session); -static switch_status_t channel_on_routing(switch_core_session_t *session); -static switch_status_t channel_on_exchange_media(switch_core_session_t *session); -static switch_status_t channel_on_soft_execute(switch_core_session_t *session); -static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, - switch_caller_profile_t *outbound_profile, - switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause); -static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); -static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); -static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); - - -static void iax_err_cb(const char *s) -{ - switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, "IAX ERR: %s", s); -} - -static void iax_out_cb(const char *s) -{ - if (globals.debug > 1) { - switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "IAX INFO: %s", s); - } -} - -static void tech_init(private_t *tech_pvt, switch_core_session_t *session) -{ - tech_pvt->cng_frame.data = tech_pvt->cng_databuf; - tech_pvt->cng_frame.buflen = sizeof(tech_pvt->cng_databuf); - switch_set_flag((&tech_pvt->cng_frame), SFF_CNG); - tech_pvt->cng_frame.datalen = 2; - switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); - switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); - switch_queue_create(&tech_pvt->frame_queue, 50000, switch_core_session_get_pool(session)); - switch_core_session_set_private(session, tech_pvt); - tech_pvt->session = session; -} - -/* - State methods they get called when the state changes to the specific state - returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next - so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it. -*/ -static switch_status_t channel_on_init(switch_core_session_t *session) -{ - private_t *tech_pvt = switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - - iax_set_private(tech_pvt->iax_session, tech_pvt); - - switch_set_flag_locked(tech_pvt, TFLAG_IO); - - /* Move channel's state machine to ROUTING */ - switch_channel_set_state(switch_core_session_get_channel(session), CS_ROUTING); - switch_mutex_lock(globals.mutex); - globals.calls++; - switch_mutex_unlock(globals.mutex); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_routing(switch_core_session_t *session) -{ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(switch_core_session_get_channel(session))); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_execute(switch_core_session_t *session) -{ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(switch_core_session_get_channel(session))); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_destroy(switch_core_session_t *session) -{ - private_t *tech_pvt = switch_core_session_get_private(session); - void *pop; - - if (tech_pvt) { - if (switch_core_codec_ready(&tech_pvt->read_codec)) { - switch_core_codec_destroy(&tech_pvt->read_codec); - } - - if (!switch_core_codec_ready(&tech_pvt->write_codec)) { - switch_core_codec_destroy(&tech_pvt->write_codec); - } - - while (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { - switch_frame_t *frame = (switch_frame_t *) pop; - switch_frame_free(&frame); - } - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_hangup(switch_core_session_t *session) -{ - private_t *tech_pvt = switch_core_session_get_private(session); - - switch_assert(tech_pvt != NULL); - - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); - switch_clear_flag_locked(tech_pvt, TFLAG_CODEC); - - switch_mutex_lock(globals.mutex); - if (tech_pvt->iax_session) { - if (!switch_test_flag(tech_pvt, TFLAG_HANGUP)) { - iax_hangup(tech_pvt->iax_session, "Hangup"); - switch_set_flag_locked(tech_pvt, TFLAG_HANGUP); - } - iax_session_destroy(&tech_pvt->iax_session); - } - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(switch_core_session_get_channel(session))); - globals.calls--; - if (globals.calls < 0) { - globals.calls = 0; - } - switch_mutex_unlock(globals.mutex); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig) -{ - private_t *tech_pvt = switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - - switch (sig) { - case SWITCH_SIG_KILL: - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); - switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_NORMAL_CLEARING); - break; - case SWITCH_SIG_BREAK: - switch_set_flag_locked(tech_pvt, TFLAG_BREAK); - break; - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_exchange_media(switch_core_session_t *session) -{ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n"); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_on_soft_execute(switch_core_session_t *session) -{ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n"); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) -{ - private_t *tech_pvt = switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - if (tech_pvt->iax_session) { - switch_mutex_lock(globals.mutex); - iax_send_dtmf(tech_pvt->iax_session, dtmf->digit); - switch_mutex_unlock(globals.mutex); - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) -{ - private_t *tech_pvt = switch_core_session_get_private(session); - switch_byte_t *data; - void *pop; - - switch_assert(tech_pvt != NULL); - *frame = NULL; - - while (switch_test_flag(tech_pvt, TFLAG_IO)) { - - if (!switch_test_flag(tech_pvt, TFLAG_CODEC)) { - switch_cond_next(); - continue; - } - if (switch_test_flag(tech_pvt, TFLAG_BREAK)) { - switch_clear_flag(tech_pvt, TFLAG_BREAK); - goto cng; - } - - if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - return SWITCH_STATUS_FALSE; - } - - if (!switch_queue_size(tech_pvt->frame_queue)) { - switch_core_timer_next(&tech_pvt->timer); - } - - if (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { - if (tech_pvt->read_frame) { - switch_frame_free(&tech_pvt->read_frame); - } - - tech_pvt->read_frame = (switch_frame_t *) pop; - tech_pvt->read_frame->codec = &tech_pvt->read_codec; - *frame = tech_pvt->read_frame; - -#if SWITCH_BYTE_ORDER == __BIG_ENDIAN - if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { - switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2); - } -#endif - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); - tech_pvt->cng_count = tech_pvt->media_timeout; - return SWITCH_STATUS_SUCCESS; - } else { - if (tech_pvt->cng_count && --tech_pvt->cng_count == 0) { - break; - } - goto cng; - } - - - } - - return SWITCH_STATUS_FALSE; - - cng: - data = (switch_byte_t *) tech_pvt->cng_frame.data; - data[0] = 65; - data[1] = 0; - tech_pvt->cng_frame.datalen = 2; - tech_pvt->cng_frame.flags = SFF_CNG; - *frame = &tech_pvt->cng_frame; - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) -{ - private_t *tech_pvt = switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - - if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - return SWITCH_STATUS_FALSE; - } -#if SWITCH_BYTE_ORDER == __BIG_ENDIAN - if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { - switch_swap_linear(frame->data, (int) frame->datalen / 2); - } -#endif - iax_send_voice(tech_pvt->iax_session, tech_pvt->codec, frame->data, (int) frame->datalen, tech_pvt->write_codec.implementation->samples_per_packet); - - return SWITCH_STATUS_SUCCESS; - -} - -static switch_status_t channel_answer_channel(switch_core_session_t *session) -{ - private_t *tech_pvt = switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - - if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) { - switch_mutex_lock(globals.mutex); - iax_answer(tech_pvt->iax_session); - switch_mutex_unlock(globals.mutex); - } - return SWITCH_STATUS_SUCCESS; -} - - -static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) -{ - private_t *tech_pvt = (private_t *) switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - - switch (msg->message_id) { - case SWITCH_MESSAGE_INDICATE_RESPOND: - { - if (tech_pvt->iax_session) { - switch_mutex_lock(globals.mutex); - iax_reject(tech_pvt->iax_session, msg->string_arg ? msg->string_arg : "Call Rejected"); - switch_set_flag(tech_pvt, TFLAG_HANGUP); - switch_mutex_unlock(globals.mutex); - } - } - break; - case SWITCH_MESSAGE_INDICATE_ANSWER: - { - channel_answer_channel(session); - } - break; - - case SWITCH_MESSAGE_INDICATE_BRIDGE: - case SWITCH_MESSAGE_INDICATE_UNBRIDGE: - case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC: - { - void *pop; - - while (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { - switch_frame_t *frame = (switch_frame_t *) pop; - switch_frame_free(&frame); - } - } - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines - that allocate memory or you will have 1 channel with memory allocated from another channel's pool! -*/ -static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, - switch_caller_profile_t *outbound_profile, - switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) -{ - if ((*new_session = switch_core_session_request(iax_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) { - private_t *tech_pvt; - switch_channel_t *channel; - switch_caller_profile_t *caller_profile; - unsigned int req = 0, cap = 0; - unsigned short samprate = 0; - - switch_core_session_add_stream(*new_session, NULL); - if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) { - channel = switch_core_session_get_channel(*new_session); - tech_init(tech_pvt, *new_session); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); - switch_core_session_destroy(new_session); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } - - if (outbound_profile) { - char name[128]; - - switch_snprintf(name, sizeof(name), "IAX/%s-%04x", outbound_profile->destination_number, rand() & 0xffff); - switch_channel_set_name(channel, name); - - caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); - switch_channel_set_caller_profile(channel, caller_profile); - tech_pvt->caller_profile = caller_profile; - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Doh! no caller profile\n"); - switch_core_session_destroy(new_session); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } - - switch_mutex_lock(globals.mutex); - tech_pvt->iax_session = iax_session_new(); - switch_mutex_unlock(globals.mutex); - - if (!tech_pvt->iax_session) { - switch_core_session_destroy(new_session); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } - - if (iax_set_codec(tech_pvt, tech_pvt->iax_session, &req, &cap, &samprate, IAX_QUERY) != SWITCH_STATUS_SUCCESS) { - switch_core_session_destroy(new_session); - return SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL; - } - - if (samprate) { - iax_set_samplerate(tech_pvt->iax_session, samprate); - } - - iax_call(tech_pvt->iax_session, - caller_profile->caller_id_number, caller_profile->caller_id_name, caller_profile->destination_number, NULL, 0, req, cap); - - switch_channel_set_flag(channel, CF_OUTBOUND); - switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND); - switch_channel_set_state(channel, CS_INIT); - return SWITCH_CAUSE_SUCCESS; - } - - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; -} - -static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event) -{ - struct private_object *tech_pvt = switch_core_session_get_private(session); - char *body = switch_event_get_body(event); - - switch_assert(tech_pvt != NULL); - - if (!body) { - body = ""; - } - - iax_send_text(tech_pvt->iax_session, body); - - return SWITCH_STATUS_SUCCESS; -} - - -switch_state_handler_table_t iax_state_handlers = { - /*.on_init */ channel_on_init, - /*.on_routing */ channel_on_routing, - /*.on_execute */ channel_on_execute, - /*.on_hangup */ channel_on_hangup, - /*.on_exchange_media */ channel_on_exchange_media, - /*.on_soft_execute */ channel_on_soft_execute, - /*.on_consume_media*/ NULL, - /*.on_hibernate*/ NULL, - /*.on_reset*/ NULL, - /*.on_park*/ NULL, - /*.on_reporting*/ NULL, - /*.on_destroy*/ channel_on_destroy -}; - -switch_io_routines_t iax_io_routines = { - /*.outgoing_channel */ channel_outgoing_channel, - /*.read_frame */ channel_read_frame, - /*.write_frame */ channel_write_frame, - /*.kill_channel */ channel_kill_channel, - /*.send_dtmf */ channel_send_dtmf, - /*.receive_message */ channel_receive_message, - /*.receive_event */ channel_receive_event -}; - -SWITCH_MODULE_LOAD_FUNCTION(mod_iax_load) -{ - memset(&globals, 0, sizeof(globals)); - - module_pool = pool; - - *module_interface = switch_loadable_module_create_module_interface(pool, modname); - iax_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); - iax_endpoint_interface->interface_name = "iax"; - iax_endpoint_interface->io_routines = &iax_io_routines; - iax_endpoint_interface->state_handler = &iax_state_handlers; - - /* indicate that the module should continue to be loaded */ - return SWITCH_STATUS_SUCCESS; -} - -#define PHONE_FREED 0 -#define PHONE_CALLACCEPTED 1 -#define PHONE_RINGING 2 -#define PHONE_ANSWERED 3 -#define PHONE_CONNECTED 4 - -static switch_status_t load_config(void) -{ - char *cf = "iax.conf"; - switch_xml_t cfg, xml, settings, param; - - memset(&globals, 0, sizeof(globals)); - switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool); - if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); - return SWITCH_STATUS_TERM; - } - - globals.media_timeout = 300; - - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (!strcmp(var, "debug")) { - globals.debug = atoi(val); - } else if (!strcmp(var, "port")) { - globals.port = atoi(val); - } else if (!strcmp(var, "ip")) { - set_global_ip(val); - } else if (!strcmp(var, "codec-master")) { - if (!strcasecmp(val, "us")) { - switch_set_flag(&globals, GFLAG_MY_CODEC_PREFS); - } - } else if (!strcmp(var, "media-timeout")) { - int mt = atoi(val); - if (mt > 0) { - globals.media_timeout = mt; - } - } else if (!strcmp(var, "dialplan")) { - set_global_dialplan(val); - } else if (!strcmp(var, "codec-prefs")) { - set_global_codec_string(val); - globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS); - } else if (!strcmp(var, "codec-rates")) { - set_global_codec_rates_string(val); - globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS); - } - } - } - - if (!globals.dialplan) { - set_global_dialplan("default"); - } - - if (!globals.port) { - globals.port = 4569; - } - - switch_xml_free(xml); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t tech_media(private_t *tech_pvt, struct iax_event *iaxevent) -{ - unsigned int cap = iax_session_get_capability(iaxevent->session); - unsigned int format = iaxevent->ies.format; - switch_status_t status = SWITCH_STATUS_SUCCESS; - - if (!switch_test_flag(tech_pvt, TFLAG_CODEC) && - (status = iax_set_codec(tech_pvt, iaxevent->session, &format, &cap, &iaxevent->ies.samprate, IAX_SET)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Codec Error %u %u\n", iaxevent->ies.format, iaxevent->ies.capability); - } - - return status; -} - -SWITCH_MODULE_RUNTIME_FUNCTION(mod_iax_runtime) -{ - struct iax_event *iaxevent = NULL; - switch_event_t *s_event; - if (load_config() != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_TERM; - } - - if (globals.debug > 1) { - iax_enable_debug(); - } - if (iax_init(globals.ip, globals.port) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Binding Port!\n"); - return SWITCH_STATUS_TERM; - } - - iax_set_error(iax_err_cb); - iax_set_output(iax_out_cb); - globals.fd = iax_get_fd(); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IAX Ready Port %d\n", globals.port); - - if (switch_event_create(&s_event, SWITCH_EVENT_PUBLISH) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "service", "_iax2._udp"); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", globals.port); - switch_event_fire(&s_event); - } - - for (;;) { - if (running == -1) { - break; - } - - /* Wait for an event. */ - if ((iaxevent = iax_get_event(0)) == NULL) { - int waitlen = 0; - - if (globals.calls == 0) { - waitlen = 10000; - } else if (globals.calls < 10) { - waitlen = 1000; - } else { - waitlen = 500; - } - - switch_yield(waitlen); - continue; - } else { - private_t *tech_pvt = NULL; - switch_channel_t *channel = NULL; - - if ((tech_pvt = iax_get_private(iaxevent->session))) { - channel = switch_core_session_get_channel(tech_pvt->session); - } - - if (globals.debug && iaxevent->etype != IAX_EVENT_VOICE) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Event %d [%s]!\n", iaxevent->etype, IAXNAMES[iaxevent->etype]); - } - - switch_mutex_lock(globals.mutex); - switch (iaxevent->etype) { - case IAX_EVENT_REGACK: - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Registration completed successfully.\n"); - //if (iaxevent->ies.refresh) - //refresh = iaxevent->ies.refresh; - break; - case IAX_EVENT_REGREJ: - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Registration failed.\n"); - break; - case IAX_EVENT_REGREQ: - /* what is the right way to handle this? */ - iax_reject_registration(iaxevent->session, NULL); - break; - case IAX_EVENT_TIMEOUT: - break; - case IAX_EVENT_ACCEPT: - if (channel && !switch_channel_test_flag(channel, CF_ANSWERED)) { - if (tech_media(tech_pvt, iaxevent) == SWITCH_STATUS_SUCCESS) { - switch_channel_mark_pre_answered(channel); - } else { - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - } - } - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Call accepted.\n"); - break; - case IAX_EVENT_RINGA: - if (channel) { - switch_channel_mark_ring_ready(channel); - } - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Ringing heard.\n"); - break; - case IAX_EVENT_PONG: - // informative only - break; - case IAX_EVENT_ANSWER: - // the other side answered our call - if (channel) { - if (tech_media(tech_pvt, iaxevent) == SWITCH_STATUS_SUCCESS) { - if (switch_channel_test_flag(channel, CF_ANSWERED)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "Multiple Answer %s?\n", switch_channel_get_name(channel)); - - } else { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Answer %s\n", switch_channel_get_name(channel)); - switch_channel_mark_answered(channel); - } - } else { - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - } - } - break; - case IAX_EVENT_CONNECT: - // incoming call detected - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, - "Incoming call connected %s, %s, %s %u/%u\n", - iaxevent->ies.called_number, - iaxevent->ies.calling_number, iaxevent->ies.calling_name, iaxevent->ies.format, iaxevent->ies.capability); - - if (iaxevent) { - switch_core_session_t *session; - - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "New Inbound Channel %s!\n", iaxevent->ies.calling_name); - if ((session = switch_core_session_request(iax_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL)) != 0) { - switch_core_session_add_stream(session, NULL); - if ((tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t))) != 0) { - channel = switch_core_session_get_channel(session); - tech_init(tech_pvt, session); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); - switch_core_session_destroy(&session); - break; - } - - if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), - iaxevent->ies.username, - globals.dialplan, - iaxevent->ies.calling_name, - iaxevent->ies.calling_number, - iax_get_peer_ip(iaxevent->session), - iaxevent->ies.calling_ani, - NULL, - NULL, - modname, - iaxevent->ies.called_context, iaxevent->ies.called_number)) != 0) { - char name[128]; - switch_snprintf(name, sizeof(name), "IAX/%s-%04x", tech_pvt->caller_profile->destination_number, rand() & 0xffff); - switch_channel_set_name(channel, name); - switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); - } - - if (iax_set_codec(tech_pvt, iaxevent->session, - &iaxevent->ies.format, &iaxevent->ies.capability, &iaxevent->ies.samprate, IAX_SET) != SWITCH_STATUS_SUCCESS) { - iax_reject(iaxevent->session, "Codec Error!"); - switch_core_session_destroy(&session); - } else { - tech_pvt->iax_session = iaxevent->session; - tech_pvt->session = session; - iax_accept(tech_pvt->iax_session, tech_pvt->codec); - iax_ring_announce(tech_pvt->iax_session); - switch_channel_set_state(channel, CS_INIT); - if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error spawning thread\n"); - switch_core_session_destroy(&session); - } - } - } - } - break; - case IAX_EVENT_REJECT: - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Rejected call.\n"); - case IAX_EVENT_BUSY: - case IAX_EVENT_HANGUP: - if (channel) { - switch_mutex_lock(globals.mutex); - switch_mutex_lock(tech_pvt->flag_mutex); - switch_clear_flag(tech_pvt, TFLAG_IO); - switch_clear_flag(tech_pvt, TFLAG_VOICE); - switch_mutex_unlock(tech_pvt->flag_mutex); - - - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Hangup %s\n", switch_channel_get_name(channel)); - switch_set_flag_locked(tech_pvt, TFLAG_HANGUP); - switch_channel_hangup(channel, iaxevent->etype == IAX_EVENT_HANGUP ? SWITCH_CAUSE_NORMAL_CLEARING : SWITCH_CAUSE_FACILITY_REJECTED); - iaxevent->session = NULL; - switch_mutex_unlock(globals.mutex); - } - break; - case IAX_EVENT_CNG: - // pseudo-silence - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "sending silence\n"); - break; - case IAX_EVENT_VOICE: - if (tech_pvt && iaxevent->datalen) { - if (channel && switch_channel_up(channel)) { - int bytes = 0, frames = 1; - switch_frame_t *frame = NULL; - - if (!switch_test_flag(tech_pvt, TFLAG_CODEC) || !tech_pvt->read_codec.implementation || - !switch_core_codec_ready(&tech_pvt->read_codec)) { - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - break; - } - - if (tech_pvt->read_codec.implementation->encoded_bytes_per_packet) { - bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_packet; - frames = (int) (iaxevent->datalen / bytes); - } - - switch_frame_alloc(&frame, iaxevent->datalen); - - memcpy(frame->data, iaxevent->data, iaxevent->datalen); - frame->datalen = iaxevent->datalen; - switch_queue_push(tech_pvt->frame_queue, frame); - frame = NULL; - - /* wake up the i/o thread */ - switch_set_flag_locked(tech_pvt, TFLAG_VOICE); - } - } - break; - case IAX_EVENT_TRANSFER: - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Call transfer occurred.\n"); - break; - case IAX_EVENT_DTMF: - if (channel) { - switch_dtmf_t dtmf = { (char) iaxevent->subclass, switch_core_default_dtmf_duration(0) }; - if (globals.debug) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_INFO, "%c DTMF %s\n", dtmf.digit, switch_channel_get_name(channel)); - } - switch_mutex_lock(tech_pvt->flag_mutex); - switch_channel_queue_dtmf(channel, &dtmf); - switch_set_flag(tech_pvt, TFLAG_DTMF); - switch_mutex_unlock(tech_pvt->flag_mutex); - } - - break; - default: - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Don't know what to do with IAX event %d.\n", iaxevent->etype); - break; - } - iax_event_free(iaxevent); - switch_mutex_unlock(globals.mutex); - } - } - - running = 0; - - return SWITCH_STATUS_TERM; -} - - -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_iax_shutdown) -{ - int x = 0; - - running = -1; - - if (globals.fd) { - /* Die Mutha $%#$@% Die Mutha $#%#$^ Die */ - shutdown(globals.fd, 2); - } - iax_shutdown(); - - while (running) { - if (x++ > 100) { - break; - } - switch_yield(20000); - } - - switch_safe_free(globals.dialplan); - switch_safe_free(globals.codec_string); - switch_safe_free(globals.codec_rates_string); - switch_safe_free(globals.ip); - - return SWITCH_STATUS_SUCCESS; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: - */ diff --git a/src/mod/endpoints/mod_iax/mod_iax.vcproj b/src/mod/endpoints/mod_iax/mod_iax.vcproj deleted file mode 100644 index 7314c8bf29..0000000000 --- a/src/mod/endpoints/mod_iax/mod_iax.vcproj +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mod/endpoints/mod_iax/winpoop.h b/src/mod/endpoints/mod_iax/winpoop.h deleted file mode 100644 index 8cd9a83c1f..0000000000 --- a/src/mod/endpoints/mod_iax/winpoop.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Functions Windows doesn't have... but should - * Copyright(C) 2001, Linux Support Services, Inc. - * - * Distributed under GNU LGPL. - * - * These are NOT fully compliant with BSD 4.3 and are not - * threadsafe. - * - */ - -#ifndef _winpoop_h -#define _winpoop_h - -#if defined(_MSC_VER) -#define INLINE __inline -#else -#define INLINE inline -#endif - -#include - -void gettimeofday(struct timeval *tv, void /*struct timezone*/ *tz); - -static INLINE int inet_aton(char *cp, struct in_addr *inp) -{ - int a1, a2, a3, a4; - unsigned int saddr; - if (sscanf(cp, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) != 4) - return 0; - a1 &= 0xff; - a2 &= 0xff; - a3 &= 0xff; - a4 &= 0xff; - saddr = (a1 << 24) | (a2 << 16) | (a3 << 8) | a4; - inp->s_addr = htonl(saddr); - return 1; -} - -#endif