git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@417 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2006-01-20 00:41:30 +00:00
parent 42383b1f15
commit 1e04eb13b5
25 changed files with 3123 additions and 3130 deletions

View File

@ -64,16 +64,16 @@ static void *audio_bridge_thread(switch_thread *thread, void *obj)
chan_a = switch_core_session_get_channel(session_a); chan_a = switch_core_session_get_channel(session_a);
chan_b = switch_core_session_get_channel(session_b); chan_b = switch_core_session_get_channel(session_b);
while(data->running > 0) { while (data->running > 0) {
switch_channel_state b_state = switch_channel_get_state(chan_b); switch_channel_state b_state = switch_channel_get_state(chan_b);
switch (b_state) { switch (b_state) {
case CS_HANGUP: case CS_HANGUP:
data->running = -1; data->running = -1;
continue; continue;
break; break;
default: default:
break; break;
} }
if (switch_channel_has_dtmf(chan_a)) { if (switch_channel_has_dtmf(chan_a)) {
@ -82,7 +82,8 @@ default:
switch_core_session_send_dtmf(session_b, dtmf); switch_core_session_send_dtmf(session_b, dtmf);
} }
if (switch_core_session_read_frame(session_a, &read_frame, -1, stream_id) == SWITCH_STATUS_SUCCESS && read_frame->datalen) { if (switch_core_session_read_frame(session_a, &read_frame, -1, stream_id) == SWITCH_STATUS_SUCCESS
&& read_frame->datalen) {
if (switch_core_session_write_frame(session_b, read_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) { if (switch_core_session_write_frame(session_b, read_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "write: Bad Frame.... Bubye!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "write: Bad Frame.... Bubye!\n");
data->running = -1; data->running = -1;
@ -115,7 +116,8 @@ static switch_status audio_bridge_on_hangup(switch_core_session *session)
other_channel = switch_core_session_get_channel(other_session); other_channel = switch_core_session_get_channel(other_session);
assert(other_channel != NULL); assert(other_channel != NULL);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "CUSTOM HANGUP %s kill %s\n", switch_channel_get_name(channel), switch_channel_get_name(other_channel)); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "CUSTOM HANGUP %s kill %s\n", switch_channel_get_name(channel),
switch_channel_get_name(other_channel));
switch_core_session_kill_channel(other_session, SWITCH_SIG_KILL); switch_core_session_kill_channel(other_session, SWITCH_SIG_KILL);
switch_core_session_kill_channel(session, SWITCH_SIG_KILL); switch_core_session_kill_channel(session, SWITCH_SIG_KILL);
@ -143,21 +145,21 @@ static switch_status audio_bridge_on_ring(switch_core_session *session)
} }
static const switch_event_handler_table audio_bridge_peer_event_handlers = { static const switch_event_handler_table audio_bridge_peer_event_handlers = {
/*.on_init*/ NULL, /*.on_init */ NULL,
/*.on_ring*/ audio_bridge_on_ring, /*.on_ring */ audio_bridge_on_ring,
/*.on_execute*/ NULL, /*.on_execute */ NULL,
/*.on_hangup*/ audio_bridge_on_hangup, /*.on_hangup */ audio_bridge_on_hangup,
/*.on_loopback*/ NULL, /*.on_loopback */ NULL,
/*.on_transmit*/ NULL /*.on_transmit */ NULL
}; };
static const switch_event_handler_table audio_bridge_caller_event_handlers = { static const switch_event_handler_table audio_bridge_caller_event_handlers = {
/*.on_init*/ NULL, /*.on_init */ NULL,
/*.on_ring*/ NULL, /*.on_ring */ NULL,
/*.on_execute*/ NULL, /*.on_execute */ NULL,
/*.on_hangup*/ audio_bridge_on_hangup, /*.on_hangup */ audio_bridge_on_hangup,
/*.on_loopback*/ NULL, /*.on_loopback */ NULL,
/*.on_transmit*/ NULL /*.on_transmit */ NULL
}; };
static void audio_bridge_function(switch_core_session *session, char *data) static void audio_bridge_function(switch_core_session *session, char *data)
@ -165,8 +167,8 @@ static void audio_bridge_function(switch_core_session *session, char *data)
switch_channel *caller_channel, *peer_channel; switch_channel *caller_channel, *peer_channel;
switch_core_session *peer_session; switch_core_session *peer_session;
switch_caller_profile *caller_profile, *caller_caller_profile; switch_caller_profile *caller_profile, *caller_caller_profile;
char chan_type[128]= {'\0'}, *chan_data; char chan_type[128] = { '\0' }, *chan_data;
int timelimit = 60; /* probably a useful option to pass in when there's time */ int timelimit = 60; /* probably a useful option to pass in when there's time */
caller_channel = switch_core_session_get_channel(session); caller_channel = switch_core_session_get_channel(session);
assert(caller_channel != NULL); assert(caller_channel != NULL);
@ -180,17 +182,15 @@ static void audio_bridge_function(switch_core_session *session, char *data)
caller_caller_profile = switch_channel_get_caller_profile(caller_channel); caller_caller_profile = switch_channel_get_caller_profile(caller_channel);
caller_profile = switch_caller_profile_new(session, caller_profile = switch_caller_profile_new(session,
caller_caller_profile->dialplan, caller_caller_profile->dialplan,
caller_caller_profile->caller_id_name, caller_caller_profile->caller_id_name,
caller_caller_profile->caller_id_number, caller_caller_profile->caller_id_number,
caller_caller_profile->network_addr, caller_caller_profile->network_addr, NULL, NULL, chan_data);
NULL,
NULL,
chan_data);
if (switch_core_session_outgoing_channel(session, chan_type, caller_profile, &peer_session) != SWITCH_STATUS_SUCCESS) { if (switch_core_session_outgoing_channel(session, chan_type, caller_profile, &peer_session) !=
SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "DOH!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "DOH!\n");
switch_channel_hangup(caller_channel); switch_channel_hangup(caller_channel);
return; return;
@ -219,7 +219,7 @@ static void audio_bridge_function(switch_core_session *session, char *data)
switch_channel_set_event_handlers(peer_channel, &audio_bridge_peer_event_handlers); switch_channel_set_event_handlers(peer_channel, &audio_bridge_peer_event_handlers);
switch_core_session_thread_launch(peer_session); switch_core_session_thread_launch(peer_session);
for(;;) { for (;;) {
int state = switch_channel_get_state(peer_channel); int state = switch_channel_get_state(peer_channel);
if (state > CS_RING) { if (state > CS_RING) {
break; break;
@ -228,11 +228,10 @@ static void audio_bridge_function(switch_core_session *session, char *data)
} }
time(&start); time(&start);
while(switch_channel_get_state(caller_channel) == CS_EXECUTE && while (switch_channel_get_state(caller_channel) == CS_EXECUTE &&
switch_channel_get_state(peer_channel) == CS_TRANSMIT && switch_channel_get_state(peer_channel) == CS_TRANSMIT &&
!switch_channel_test_flag(peer_channel, CF_ANSWERED) && !switch_channel_test_flag(peer_channel, CF_ANSWERED) && ((time(NULL) - start) < timelimit)) {
((time(NULL) - start) < timelimit)) { switch_yield(20000);
switch_yield(20000);
} }
if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) { if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) {
@ -259,21 +258,22 @@ static void audio_bridge_function(switch_core_session *session, char *data)
static const switch_application_interface bridge_application_interface = { static const switch_application_interface bridge_application_interface = {
/*.interface_name*/ "bridge", /*.interface_name */ "bridge",
/*.application_function*/ audio_bridge_function /*.application_function */ audio_bridge_function
}; };
static const switch_loadable_module_interface mod_bridgecall_module_interface = { static const switch_loadable_module_interface mod_bridgecall_module_interface = {
/*.module_name = */ modname, /*.module_name = */ modname,
/*.endpoint_interface = */ NULL, /*.endpoint_interface = */ NULL,
/*.timer_interface = */ NULL, /*.timer_interface = */ NULL,
/*.dialplan_interface = */ NULL, /*.dialplan_interface = */ NULL,
/*.codec_interface = */ NULL, /*.codec_interface = */ NULL,
/*.application_interface*/ &bridge_application_interface /*.application_interface */ &bridge_application_interface
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &mod_bridgecall_module_interface; *interface = &mod_bridgecall_module_interface;

View File

@ -59,11 +59,11 @@ void playback_function(switch_core_session *session, char *data)
assert(channel != NULL); assert(channel != NULL);
if (switch_core_file_open(&fh, if (switch_core_file_open(&fh,
data, data,
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel); switch_channel_hangup(channel);
return; return;
} }
switch_channel_answer(channel); switch_channel_answer(channel);
@ -81,17 +81,17 @@ void playback_function(switch_core_session *session, char *data)
codec_name = "L16"; codec_name = "L16";
if (switch_core_codec_init(&codec, if (switch_core_codec_init(&codec,
codec_name, codec_name,
fh.samplerate, fh.samplerate,
interval, interval,
fh.channels, fh.channels,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, NULL, pool) == SWITCH_STATUS_SUCCESS) {
pool) == SWITCH_STATUS_SUCCESS) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Raw Codec Activated\n");
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Raw Codec Activated\n"); write_frame.codec = &codec;
write_frame.codec = &codec;
} else { } else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Raw Codec Activation Failed %s@%dhz %d channels %dms\n", codec_name, fh.samplerate, fh.channels, interval); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Raw Codec Activation Failed %s@%dhz %d channels %dms\n",
codec_name, fh.samplerate, fh.channels, interval);
switch_core_file_close(&fh); switch_core_file_close(&fh);
switch_channel_hangup(channel); switch_channel_hangup(channel);
return; return;
@ -108,11 +108,11 @@ void playback_function(switch_core_session *session, char *data)
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "setup timer success %d bytes per %d ms!\n", len, interval); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "setup timer success %d bytes per %d ms!\n", len, interval);
/* start a thread to absorb incoming audio */ /* start a thread to absorb incoming audio */
for(stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) { for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
switch_core_service_session(session, &thread_session, stream_id); switch_core_service_session(session, &thread_session, stream_id);
} }
ilen = samples; ilen = samples;
while(switch_channel_get_state(channel) == CS_EXECUTE) { while (switch_channel_get_state(channel) == CS_EXECUTE) {
int done = 0; int done = 0;
if (switch_channel_has_dtmf(channel)) { if (switch_channel_has_dtmf(channel)) {
@ -139,12 +139,12 @@ void playback_function(switch_core_session *session, char *data)
} }
write_frame.datalen = ilen * 2; write_frame.datalen = ilen * 2;
write_frame.samples = (int)ilen; write_frame.samples = (int) ilen;
#ifdef SWAP_LINEAR #ifdef SWAP_LINEAR
switch_swap_linear(write_frame.data, (int)write_frame.datalen / 2); switch_swap_linear(write_frame.data, (int) write_frame.datalen / 2);
#endif #endif
for(stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) { for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) { if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Bad Write\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Bad Write\n");
done = 1; done = 1;
@ -178,20 +178,21 @@ void playback_function(switch_core_session *session, char *data)
} }
static const switch_application_interface playback_application_interface = { static const switch_application_interface playback_application_interface = {
/*.interface_name*/ "playback", /*.interface_name */ "playback",
/*.application_function*/ playback_function /*.application_function */ playback_function
}; };
static const switch_loadable_module_interface mod_playback_module_interface = { static const switch_loadable_module_interface mod_playback_module_interface = {
/*.module_name = */ modname, /*.module_name = */ modname,
/*.endpoint_interface = */ NULL, /*.endpoint_interface = */ NULL,
/*.timer_interface = */ NULL, /*.timer_interface = */ NULL,
/*.dialplan_interface = */ NULL, /*.dialplan_interface = */ NULL,
/*.codec_interface = */ NULL, /*.codec_interface = */ NULL,
/*.application_interface*/ &playback_application_interface /*.application_interface */ &playback_application_interface
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &mod_playback_module_interface; *interface = &mod_playback_module_interface;
@ -207,7 +208,3 @@ if it returns anything but SWITCH_STATUS_TERM it will be called again automaticl
//switch_status switch_module_runtime(void) //switch_status switch_module_runtime(void)

View File

@ -34,15 +34,16 @@
static const char modname[] = "mod_skel"; static const char modname[] = "mod_skel";
static switch_loadable_module_interface skel_module_interface = { static switch_loadable_module_interface skel_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ NULL, /*.endpoint_interface */ NULL,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
switch_status switch_module_load(switch_loadable_module_interface **interface, char *filename) { switch_status switch_module_load(switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &skel_module_interface; *interface = &skel_module_interface;
@ -51,4 +52,3 @@ switch_status switch_module_load(switch_loadable_module_interface **interface, c
/* indicate that the module should continue to be loaded */ /* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -47,70 +47,71 @@
*/ */
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ #define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
#define QUANT_MASK (0xf) /* Quantization field mask. */ #define QUANT_MASK (0xf) /* Quantization field mask. */
#define NSEGS (8) /* Number of A-law segments. */ #define NSEGS (8) /* Number of A-law segments. */
#define SEG_SHIFT (4) /* Left shift for segment number. */ #define SEG_SHIFT (4) /* Left shift for segment number. */
#define SEG_MASK (0x70) /* Segment field mask. */ #define SEG_MASK (0x70) /* Segment field mask. */
static short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF, static short seg_aend[8] = { 0x1F, 0x3F, 0x7F, 0xFF,
0x1FF, 0x3FF, 0x7FF, 0xFFF}; 0x1FF, 0x3FF, 0x7FF, 0xFFF
static short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, };
0x3FF, 0x7FF, 0xFFF, 0x1FFF}; static short seg_uend[8] = { 0x3F, 0x7F, 0xFF, 0x1FF,
0x3FF, 0x7FF, 0xFFF, 0x1FFF
};
/* copy from CCITT G.711 specifications */ /* copy from CCITT G.711 specifications */
unsigned char _u2a[128] = { /* u- to A-law conversions */ unsigned char _u2a[128] = { /* u- to A-law conversions */
1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 2, 2, 3, 3, 4, 4,
5, 5, 6, 6, 7, 7, 8, 8, 5, 5, 6, 6, 7, 7, 8, 8,
9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 29, 31, 33, 34, 35, 36, 25, 27, 29, 31, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 37, 38, 39, 40, 41, 42, 43, 44,
46, 48, 49, 50, 51, 52, 53, 54, 46, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 55, 56, 57, 58, 59, 60, 61, 62,
64, 65, 66, 67, 68, 69, 70, 71, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 72, 73, 74, 75, 76, 77, 78, 79,
/* corrected: /* corrected:
81, 82, 83, 84, 85, 86, 87, 88, 81, 82, 83, 84, 85, 86, 87, 88,
should be: */ should be: */
80, 82, 83, 84, 85, 86, 87, 88, 80, 82, 83, 84, 85, 86, 87, 88,
89, 90, 91, 92, 93, 94, 95, 96, 89, 90, 91, 92, 93, 94, 95, 96,
97, 98, 99, 100, 101, 102, 103, 104, 97, 98, 99, 100, 101, 102, 103, 104,
105, 106, 107, 108, 109, 110, 111, 112, 105, 106, 107, 108, 109, 110, 111, 112,
113, 114, 115, 116, 117, 118, 119, 120, 113, 114, 115, 116, 117, 118, 119, 120,
121, 122, 123, 124, 125, 126, 127, 128}; 121, 122, 123, 124, 125, 126, 127, 128
};
unsigned char _a2u[128] = { /* A- to u-law conversions */ unsigned char _a2u[128] = { /* A- to u-law conversions */
1, 3, 5, 7, 9, 11, 13, 15, 1, 3, 5, 7, 9, 11, 13, 15,
16, 17, 18, 19, 20, 21, 22, 23, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 24, 25, 26, 27, 28, 29, 30, 31,
32, 32, 33, 33, 34, 34, 35, 35, 32, 32, 33, 33, 34, 34, 35, 35,
36, 37, 38, 39, 40, 41, 42, 43, 36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 48, 49, 49, 44, 45, 46, 47, 48, 48, 49, 49,
50, 51, 52, 53, 54, 55, 56, 57, 50, 51, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 64, 58, 59, 60, 61, 62, 63, 64, 64,
65, 66, 67, 68, 69, 70, 71, 72, 65, 66, 67, 68, 69, 70, 71, 72,
/* corrected: /* corrected:
73, 74, 75, 76, 77, 78, 79, 79, 73, 74, 75, 76, 77, 78, 79, 79,
should be: */ should be: */
73, 74, 75, 76, 77, 78, 79, 80, 73, 74, 75, 76, 77, 78, 79, 80,
80, 81, 82, 83, 84, 85, 86, 87, 80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103, 96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111, 104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127}; 120, 121, 122, 123, 124, 125, 126, 127
};
static short search( static short search(short val, short *table, short size)
short val,
short *table,
short size)
{ {
short i; short i;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
if (val <= *table++) if (val <= *table++)
return (i); return (i);
} }
return (size); return (size);
} }
/* /*
@ -132,66 +133,63 @@ static short search(
* For further information see John C. Bellamy's Digital Telephony, 1982, * For further information see John C. Bellamy's Digital Telephony, 1982,
* John Wiley & Sons, pps 98-111 and 472-476. * John Wiley & Sons, pps 98-111 and 472-476.
*/ */
unsigned char unsigned char linear2alaw(short pcm_val)
linear2alaw(short pcm_val) /* 2's complement (16-bit range) */ { /* 2's complement (16-bit range) */
{ short mask;
short mask; short seg;
short seg; unsigned char aval;
unsigned char aval;
pcm_val = pcm_val >> 3; pcm_val = pcm_val >> 3;
if (pcm_val >= 0) { if (pcm_val >= 0) {
mask = 0xD5; /* sign (7th) bit = 1 */ mask = 0xD5; /* sign (7th) bit = 1 */
} else { } else {
mask = 0x55; /* sign bit = 0 */ mask = 0x55; /* sign bit = 0 */
pcm_val = -pcm_val - 1; pcm_val = -pcm_val - 1;
} }
/* Convert the scaled magnitude to segment number. */ /* Convert the scaled magnitude to segment number. */
seg = search(pcm_val, seg_aend, 8); seg = search(pcm_val, seg_aend, 8);
/* Combine the sign, segment, and quantization bits. */ /* Combine the sign, segment, and quantization bits. */
if (seg >= 8) /* out of range, return maximum value. */ if (seg >= 8) /* out of range, return maximum value. */
return (unsigned char) (0x7F ^ mask); return (unsigned char) (0x7F ^ mask);
else { else {
aval = (unsigned char) seg << SEG_SHIFT; aval = (unsigned char) seg << SEG_SHIFT;
if (seg < 2) if (seg < 2)
aval |= (pcm_val >> 1) & QUANT_MASK; aval |= (pcm_val >> 1) & QUANT_MASK;
else else
aval |= (pcm_val >> seg) & QUANT_MASK; aval |= (pcm_val >> seg) & QUANT_MASK;
return (aval ^ mask); return (aval ^ mask);
} }
} }
/* /*
* alaw2linear() - Convert an A-law value to 16-bit linear PCM * alaw2linear() - Convert an A-law value to 16-bit linear PCM
* *
*/ */
short short alaw2linear(unsigned char a_val)
alaw2linear(
unsigned char a_val)
{ {
short t; short t;
short seg; short seg;
a_val ^= 0x55; a_val ^= 0x55;
t = (a_val & QUANT_MASK) << 4; t = (a_val & QUANT_MASK) << 4;
seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; seg = ((unsigned) a_val & SEG_MASK) >> SEG_SHIFT;
switch (seg) { switch (seg) {
case 0: case 0:
t += 8; t += 8;
break; break;
case 1: case 1:
t += 0x108; t += 0x108;
break; break;
default: default:
t += 0x108; t += 0x108;
t <<= seg - 1; t <<= seg - 1;
} }
return ((a_val & SIGN_BIT) ? t : -t); return ((a_val & SIGN_BIT) ? t : -t);
} }
#define BIAS (0x84) /* Bias for linear code. */ #define BIAS (0x84) /* Bias for linear code. */
@ -226,38 +224,37 @@ alaw2linear(
* For further information see John C. Bellamy's Digital Telephony, 1982, * For further information see John C. Bellamy's Digital Telephony, 1982,
* John Wiley & Sons, pps 98-111 and 472-476. * John Wiley & Sons, pps 98-111 and 472-476.
*/ */
unsigned char unsigned char linear2ulaw(short pcm_val)
linear2ulaw( { /* 2's complement (16-bit range) */
short pcm_val) /* 2's complement (16-bit range) */ short mask;
{ short seg;
short mask; unsigned char uval;
short seg;
unsigned char uval;
/* Get the sign and the magnitude of the value. */ /* Get the sign and the magnitude of the value. */
pcm_val = pcm_val >> 2; pcm_val = pcm_val >> 2;
if (pcm_val < 0) { if (pcm_val < 0) {
pcm_val = -pcm_val; pcm_val = -pcm_val;
mask = 0x7F; mask = 0x7F;
} else { } else {
mask = 0xFF; mask = 0xFF;
} }
if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ if (pcm_val > CLIP)
pcm_val += (BIAS >> 2); pcm_val = CLIP; /* clip the magnitude */
pcm_val += (BIAS >> 2);
/* Convert the scaled magnitude to segment number. */ /* Convert the scaled magnitude to segment number. */
seg = search(pcm_val, seg_uend, 8); seg = search(pcm_val, seg_uend, 8);
/* /*
* Combine the sign, segment, quantization bits; * Combine the sign, segment, quantization bits;
* and complement the code word. * and complement the code word.
*/ */
if (seg >= 8) /* out of range, return maximum value. */ if (seg >= 8) /* out of range, return maximum value. */
return (unsigned char) (0x7F ^ mask); return (unsigned char) (0x7F ^ mask);
else { else {
uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
return (uval ^ mask); return (uval ^ mask);
} }
} }
@ -270,43 +267,35 @@ linear2ulaw(
* Note that this function expects to be passed the complement of the * Note that this function expects to be passed the complement of the
* original code word. This is in keeping with ISDN conventions. * original code word. This is in keeping with ISDN conventions.
*/ */
short short ulaw2linear(unsigned char u_val)
ulaw2linear(
unsigned char u_val)
{ {
short t; short t;
/* Complement to obtain normal u-law value. */ /* Complement to obtain normal u-law value. */
u_val = ~u_val; u_val = ~u_val;
/* /*
* Extract and bias the quantization bits. Then * Extract and bias the quantization bits. Then
* shift up by the segment number and subtract out the bias. * shift up by the segment number and subtract out the bias.
*/ */
t = ((u_val & QUANT_MASK) << 3) + BIAS; t = ((u_val & QUANT_MASK) << 3) + BIAS;
t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; t <<= ((unsigned) u_val & SEG_MASK) >> SEG_SHIFT;
return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
} }
/* A-law to u-law conversion */ /* A-law to u-law conversion */
unsigned char unsigned char alaw2ulaw(unsigned char aval)
alaw2ulaw(
unsigned char aval)
{ {
aval &= 0xff; aval &= 0xff;
return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : (0x7F ^ _a2u[aval ^ 0x55]));
(0x7F ^ _a2u[aval ^ 0x55]));
} }
/* u-law to A-law conversion */ /* u-law to A-law conversion */
unsigned char unsigned char ulaw2alaw(unsigned char uval)
ulaw2alaw(
unsigned char uval)
{ {
uval &= 0xff; uval &= 0xff;
return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
(0x55 ^ (_u2a[0x7F ^ uval] - 1)));
} }
/* ---------- end of g711.c ----------------------------------------------------- */ /* ---------- end of g711.c ----------------------------------------------------- */

View File

@ -36,7 +36,8 @@
static const char modname[] = "mod_g711codec"; static const char modname[] = "mod_g711codec";
static switch_status switch_g711u_init(switch_codec *codec, switch_codec_flag flags, const struct switch_codec_settings *codec_settings) static switch_status switch_g711u_init(switch_codec *codec, switch_codec_flag flags,
const struct switch_codec_settings *codec_settings)
{ {
int encoding, decoding; int encoding, decoding;
@ -57,9 +58,7 @@ static switch_status switch_g711u_encode(switch_codec *codec,
size_t decoded_data_len, size_t decoded_data_len,
int decoded_rate, int decoded_rate,
void *encoded_data, void *encoded_data,
size_t *encoded_data_len, size_t *encoded_data_len, int *encoded_rate, unsigned int *flag)
int *encoded_rate,
unsigned int *flag)
{ {
short *dbuf; short *dbuf;
unsigned char *ebuf; unsigned char *ebuf;
@ -83,9 +82,7 @@ static switch_status switch_g711u_decode(switch_codec *codec,
size_t encoded_data_len, size_t encoded_data_len,
int encoded_rate, int encoded_rate,
void *decoded_data, void *decoded_data,
size_t *decoded_data_len, size_t *decoded_data_len, int *decoded_rate, unsigned int *flag)
int *decoded_rate,
unsigned int *flag)
{ {
short *dbuf; short *dbuf;
unsigned char *ebuf; unsigned char *ebuf;
@ -114,7 +111,8 @@ static switch_status switch_g711u_destroy(switch_codec *codec)
} }
static switch_status switch_g711a_init(switch_codec *codec, switch_codec_flag flags, const struct switch_codec_settings *codec_settings) static switch_status switch_g711a_init(switch_codec *codec, switch_codec_flag flags,
const struct switch_codec_settings *codec_settings)
{ {
int encoding, decoding; int encoding, decoding;
@ -135,9 +133,7 @@ static switch_status switch_g711a_encode(switch_codec *codec,
size_t decoded_data_len, size_t decoded_data_len,
int decoded_rate, int decoded_rate,
void *encoded_data, void *encoded_data,
size_t *encoded_data_len, size_t *encoded_data_len, int *encoded_rate, unsigned int *flag)
int *encoded_rate,
unsigned int *flag)
{ {
short *dbuf; short *dbuf;
unsigned char *ebuf; unsigned char *ebuf;
@ -161,9 +157,7 @@ static switch_status switch_g711a_decode(switch_codec *codec,
size_t encoded_data_len, size_t encoded_data_len,
int encoded_rate, int encoded_rate,
void *decoded_data, void *decoded_data,
size_t *decoded_data_len, size_t *decoded_data_len, int *decoded_rate, unsigned int *flag)
int *decoded_rate,
unsigned int *flag)
{ {
short *dbuf; short *dbuf;
unsigned char *ebuf; unsigned char *ebuf;
@ -195,126 +189,122 @@ static switch_status switch_g711a_destroy(switch_codec *codec)
static const switch_codec_implementation g711u_8k_60ms_implementation = { static const switch_codec_implementation g711u_8k_60ms_implementation = {
/*.samples_per_second*/ 8000, /*.samples_per_second */ 8000,
/*.bits_per_second*/ 19200, /*.bits_per_second */ 19200,
/*.microseconds_per_frame*/ 60000, /*.microseconds_per_frame */ 60000,
/*.samples_per_frame*/ 480, /*.samples_per_frame */ 480,
/*.bytes_per_frame*/ 960, /*.bytes_per_frame */ 960,
/*.encoded_bytes_per_frame*/ 480, /*.encoded_bytes_per_frame */ 480,
/*.number_of_channels*/ 1, /*.number_of_channels */ 1,
/*.pref_frames_per_packet*/ 1, /*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.init*/ switch_g711u_init, /*.init */ switch_g711u_init,
/*.encode*/ switch_g711u_encode, /*.encode */ switch_g711u_encode,
/*.decode*/ switch_g711u_decode, /*.decode */ switch_g711u_decode,
/*.destroy*/ switch_g711u_destroy /*.destroy */ switch_g711u_destroy
}; };
static const switch_codec_implementation g711u_8k_30ms_implementation = { static const switch_codec_implementation g711u_8k_30ms_implementation = {
/*.samples_per_second*/ 8000, /*.samples_per_second */ 8000,
/*.bits_per_second*/ 96000, /*.bits_per_second */ 96000,
/*.microseconds_per_frame*/ 30000, /*.microseconds_per_frame */ 30000,
/*.samples_per_frame*/ 240, /*.samples_per_frame */ 240,
/*.bytes_per_frame*/ 480, /*.bytes_per_frame */ 480,
/*.encoded_bytes_per_frame*/ 240, /*.encoded_bytes_per_frame */ 240,
/*.number_of_channels*/ 1, /*.number_of_channels */ 1,
/*.pref_frames_per_packet*/ 1, /*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.init*/ switch_g711u_init, /*.init */ switch_g711u_init,
/*.encode*/ switch_g711u_encode, /*.encode */ switch_g711u_encode,
/*.decode*/ switch_g711u_decode, /*.decode */ switch_g711u_decode,
/*.destroy*/ switch_g711u_destroy, /*.destroy */ switch_g711u_destroy,
/*.next*/ &g711u_8k_60ms_implementation /*.next */ &g711u_8k_60ms_implementation
}; };
static const switch_codec_implementation g711u_16k_implementation = { static const switch_codec_implementation g711u_16k_implementation = {
/*.samples_per_second*/ 16000, /*.samples_per_second */ 16000,
/*.bits_per_second*/ 128000, /*.bits_per_second */ 128000,
/*.microseconds_per_frame*/ 20000, /*.microseconds_per_frame */ 20000,
/*.samples_per_frame*/ 320, /*.samples_per_frame */ 320,
/*.bytes_per_frame*/ 640, /*.bytes_per_frame */ 640,
/*.encoded_bytes_per_frame*/ 320, /*.encoded_bytes_per_frame */ 320,
/*.number_of_channels*/ 1, /*.number_of_channels */ 1,
/*.pref_frames_per_packet*/ 1, /*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.init*/ switch_g711u_init, /*.init */ switch_g711u_init,
/*.encode*/ switch_g711u_encode, /*.encode */ switch_g711u_encode,
/*.decode*/ switch_g711u_decode, /*.decode */ switch_g711u_decode,
/*.destroy*/ switch_g711u_destroy, /*.destroy */ switch_g711u_destroy,
}; };
static const switch_codec_implementation g711u_8k_implementation = { static const switch_codec_implementation g711u_8k_implementation = {
/*.samples_per_second*/ 8000, /*.samples_per_second */ 8000,
/*.bits_per_second*/ 64000, /*.bits_per_second */ 64000,
/*.microseconds_per_frame*/ 20000, /*.microseconds_per_frame */ 20000,
/*.samples_per_frame*/ 160, /*.samples_per_frame */ 160,
/*.bytes_per_frame*/ 320, /*.bytes_per_frame */ 320,
/*.encoded_bytes_per_frame*/ 160, /*.encoded_bytes_per_frame */ 160,
/*.number_of_channels*/ 1, /*.number_of_channels */ 1,
/*.pref_frames_per_packet*/ 1, /*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.init*/ switch_g711u_init, /*.init */ switch_g711u_init,
/*.encode*/ switch_g711u_encode, /*.encode */ switch_g711u_encode,
/*.decode*/ switch_g711u_decode, /*.decode */ switch_g711u_decode,
/*.destroy*/ switch_g711u_destroy, /*.destroy */ switch_g711u_destroy,
/*.next*/ &g711u_16k_implementation /*.next */ &g711u_16k_implementation
}; };
static const switch_codec_implementation g711a_8k_implementation = { static const switch_codec_implementation g711a_8k_implementation = {
/*.samples_per_second*/ 8000, /*.samples_per_second */ 8000,
/*.bits_per_second*/ 64000, /*.bits_per_second */ 64000,
/*.microseconds_per_frame*/ 20000, /*.microseconds_per_frame */ 20000,
/*.samples_per_frame*/ 160, /*.samples_per_frame */ 160,
/*.bytes_per_frame*/ 320, /*.bytes_per_frame */ 320,
/*.encoded_bytes_per_frame*/ 160, /*.encoded_bytes_per_frame */ 160,
/*.number_of_channels*/ 1, /*.number_of_channels */ 1,
/*.pref_frames_per_packet*/ 1, /*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.init*/ switch_g711a_init, /*.init */ switch_g711a_init,
/*.encode*/ switch_g711a_encode, /*.encode */ switch_g711a_encode,
/*.decode*/ switch_g711a_decode, /*.decode */ switch_g711a_decode,
/*.destroy*/ switch_g711a_destroy /*.destroy */ switch_g711a_destroy
}; };
static const switch_codec_interface g711a_codec_interface = { static const switch_codec_interface g711a_codec_interface = {
/*.interface_name*/ "g711 alaw", /*.interface_name */ "g711 alaw",
/*.codec_type*/ SWITCH_CODEC_TYPE_AUDIO, /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode*/ 8, /*.ianacode */ 8,
/*.iananame*/ "PCMA", /*.iananame */ "PCMA",
/*.implementations*/ &g711a_8k_implementation /*.implementations */ &g711a_8k_implementation
}; };
static const switch_codec_interface g711u_codec_interface = { static const switch_codec_interface g711u_codec_interface = {
/*.interface_name*/ "g711 ulaw", /*.interface_name */ "g711 ulaw",
/*.codec_type*/ SWITCH_CODEC_TYPE_AUDIO, /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode*/ 0, /*.ianacode */ 0,
/*.iananame*/ "PCMU", /*.iananame */ "PCMU",
/*.implementations*/ &g711u_8k_implementation, /*.implementations */ &g711u_8k_implementation,
/*.next*/ &g711a_codec_interface /*.next */ &g711a_codec_interface
}; };
static switch_loadable_module_interface g711_module_interface = { static switch_loadable_module_interface g711_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ NULL, /*.endpoint_interface */ NULL,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ &g711u_codec_interface, /*.codec_interface */ &g711u_codec_interface,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &g711_module_interface; *interface = &g711_module_interface;
/* indicate that the module should continue to be loaded */ /* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -31,173 +31,139 @@
*/ */
#include "switch.h" #include "switch.h"
#include "g729.h" #include "g729.h"
static const char modname[] = "mod_codec_g729";
static const char modname[] = "mod_codec_g729"; struct g729_context {
struct dec_state decoder_object;
struct g729_context { struct cod_state encoder_object;
struct dec_state decoder_object; };
struct cod_state encoder_object; static switch_status switch_g729_init(switch_codec *codec, switch_codec_flag flags,
}; const struct switch_codec_settings *codec_settings)
static switch_status switch_g729_init(switch_codec *codec, switch_codec_flag flags, const struct switch_codec_settings *codec_settings)
{ {
struct g729_context *context = NULL; struct g729_context *context = NULL;
int encoding, decoding; int encoding, decoding;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE); if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(struct g729_context))))) {
return SWITCH_STATUS_FALSE;
if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(struct g729_context))))) { } else {
return SWITCH_STATUS_FALSE; if (encoding) {
} else { g729_init_coder(&context->encoder_object, 0);
if (encoding) { }
g729_init_coder(&context->encoder_object, 0); if (decoding) {
} g729_init_decoder(&context->decoder_object);
if (decoding) { }
g729_init_decoder(&context->decoder_object); codec->private = context;
} return SWITCH_STATUS_SUCCESS;
}
codec->private = context; }
static switch_status switch_g729_destroy(switch_codec *codec)
return SWITCH_STATUS_SUCCESS;
}
}
static switch_status switch_g729_destroy(switch_codec *codec)
{ {
codec->private = NULL; codec->private = NULL;
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status switch_g729_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data,
size_t decoded_data_len, int decoded_rate, void *encoded_data,
static switch_status switch_g729_encode(switch_codec *codec, size_t *encoded_data_len, int *encoded_rate, unsigned int *flag)
switch_codec *other_codec,
void *decoded_data,
size_t decoded_data_len,
int decoded_rate,
void *encoded_data,
size_t *encoded_data_len,
int *encoded_rate,
unsigned int *flag)
{ {
struct g729_context *context = codec->private; struct g729_context *context = codec->private;
int cbret = 0; int cbret = 0;
if (!context) {
if (!context) { return SWITCH_STATUS_FALSE;
return SWITCH_STATUS_FALSE; }
} if (decoded_data_len % 160 == 0) {
if (decoded_data_len % 160 == 0) { unsigned int new_len = 0;
unsigned int new_len = 0; INT16 * ddp = decoded_data;
INT16 *ddp = decoded_data; char *edp = encoded_data;
char *edp = encoded_data; int x;
int x; int loops = (int) decoded_data_len / 160;
int loops = (int) decoded_data_len / 160; for (x = 0; x < loops && new_len < *encoded_data_len; x++) {
g729_coder(&context->encoder_object, ddp, edp, &cbret);
for(x = 0; x < loops && new_len < *encoded_data_len; x++) { edp += 10;
g729_coder(&context->encoder_object, ddp, edp, &cbret); ddp += 80;
edp += 10; new_len += 10;
ddp += 80; }
new_len += 10; if (new_len <= *encoded_data_len) {
} *encoded_data_len = new_len;
if( new_len <= *encoded_data_len ) { } else {
*encoded_data_len = new_len; switch_console_printf(SWITCH_CHANNEL_CONSOLE, "buffer overflow!!! %u >= %u\n", new_len, *encoded_data_len);
} else { return SWITCH_STATUS_FALSE;
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "buffer overflow!!! %u >= %u\n", new_len, *encoded_data_len); }
return SWITCH_STATUS_FALSE; }
} return SWITCH_STATUS_SUCCESS;
} }
return SWITCH_STATUS_SUCCESS; static switch_status switch_g729_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data,
} size_t encoded_data_len, int encoded_rate, void *decoded_data,
size_t *decoded_data_len, int *decoded_rate, unsigned int *flag)
static switch_status switch_g729_decode(switch_codec *codec,
switch_codec *other_codec,
void *encoded_data,
size_t encoded_data_len,
int encoded_rate,
void *decoded_data,
size_t *decoded_data_len,
int *decoded_rate,
unsigned int *flag)
{ {
struct g729_context *context = codec->private; struct g729_context *context = codec->private;
if (!context) {
return SWITCH_STATUS_FALSE;
}
if (encoded_data_len % 10 == 0) {
int loops = (int) encoded_data_len / 10;
char *edp = encoded_data;
short *ddp = decoded_data;
int x;
unsigned int new_len = 0;
for (x = 0; x < loops && new_len < *decoded_data_len; x++) {
g729_decoder(&context->decoder_object, ddp, edp, 10);
ddp += 80;
edp += 10;
new_len += 160;
}
if (new_len <= *decoded_data_len) {
*decoded_data_len = new_len;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "buffer overflow!!!\n");
return SWITCH_STATUS_FALSE;
}
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "yo this frame is an odd size [%d]\n", encoded_data_len);
}
return SWITCH_STATUS_SUCCESS;
}
if (!context) {
return SWITCH_STATUS_FALSE;
}
if (encoded_data_len % 10 == 0) {
int loops = (int) encoded_data_len / 10;
char *edp = encoded_data;
short *ddp = decoded_data;
int x;
unsigned int new_len = 0;
for(x = 0; x < loops && new_len < *decoded_data_len; x++) {
g729_decoder(&context->decoder_object, ddp, edp, 10);
ddp += 80;
edp += 10;
new_len += 160;
}
if (new_len <= *decoded_data_len) {
*decoded_data_len = new_len;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "buffer overflow!!!\n");
return SWITCH_STATUS_FALSE;
}
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "yo this frame is an odd size [%d]\n", encoded_data_len);
}
return SWITCH_STATUS_SUCCESS;
}
/* Registration */ /* Registration */
static const switch_codec_implementation g729_8k_implementation = {
static const switch_codec_implementation g729_8k_implementation = { /*.samples_per_second */ 8000,
/*.samples_per_second*/ 8000, /*.bits_per_second */ 64000,
/*.bits_per_second*/ 64000, /*.microseconds_per_frame */ 20000,
/*.microseconds_per_frame*/ 20000, /*.samples_per_frame */ 160,
/*.samples_per_frame*/ 160, /*.bytes_per_frame */ 320,
/*.bytes_per_frame*/ 320, /*.encoded_bytes_per_frame */ 20,
/*.encoded_bytes_per_frame*/ 20, /*.number_of_channels */ 1,
/*.number_of_channels*/ 1, /*.pref_frames_per_packet */ 1,
/*.pref_frames_per_packet*/ 1, /*.max_frames_per_packet */ 24,
/*.max_frames_per_packet*/ 24, /*.init */ switch_g729_init,
/*.init*/ switch_g729_init, /*.encode */ switch_g729_encode,
/*.encode*/ switch_g729_encode, /*.decode */ switch_g729_decode,
/*.decode*/ switch_g729_decode, /*.destroy */ switch_g729_destroy,
/*.destroy*/ switch_g729_destroy,
}; };
static const switch_codec_interface g729_codec_interface = {
static const switch_codec_interface g729_codec_interface = { /*.interface_name */ "g729",
/*.interface_name*/ "g729", /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.codec_type*/ SWITCH_CODEC_TYPE_AUDIO, /*.ianacode */ 18,
/*.ianacode*/ 18, /*.iananame */ "G729",
/*.iananame*/ "G729", /*.implementations */ &g729_8k_implementation,
/*.implementations*/ &g729_8k_implementation,
}; };
static switch_loadable_module_interface g729_module_interface = {
static switch_loadable_module_interface g729_module_interface = { /*.module_name */ modname,
/*.module_name*/ modname, /*.endpoint_interface */ NULL,
/*.endpoint_interface*/ NULL, /*.timer_interface */ NULL,
/*.timer_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.codec_interface */ &g729_codec_interface,
/*.codec_interface*/ &g729_codec_interface, /*.application_interface */ NULL
/*.application_interface*/ NULL
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface,
char *filename)
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { {
/* connect my internal structure to the blank pointer passed to me */
*interface = &g729_module_interface; /* connect my internal structure to the blank pointer passed to me */
*interface = &g729_module_interface;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; /* indicate that the module should continue to be loaded */
} return SWITCH_STATUS_SUCCESS;
}

View File

@ -31,177 +31,145 @@
*/ */
#include "switch.h" #include "switch.h"
#include "gsm.h" #include "gsm.h"
static const char modname[] = "mod_codec_gsm";
static const char modname[] = "mod_codec_gsm"; struct gsm_context {
gsm encoder;
struct gsm_context { gsm decoder;
gsm encoder; };
gsm decoder; static switch_status switch_gsm_init(switch_codec *codec, switch_codec_flag flags,
}; const struct switch_codec_settings *codec_settings)
static switch_status switch_gsm_init(switch_codec *codec, switch_codec_flag flags, const struct switch_codec_settings *codec_settings)
{ {
struct gsm_context *context; struct gsm_context *context;
int encoding, decoding; int encoding, decoding;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE); if (!(encoding || decoding)) {
return SWITCH_STATUS_FALSE;
if (!(encoding || decoding)) { } else {
return SWITCH_STATUS_FALSE; context = switch_core_alloc(codec->memory_pool, sizeof(*context));
} else { if (encoding)
context = switch_core_alloc(codec->memory_pool, sizeof(*context)); context->encoder = gsm_create();
if (encoding) context->encoder = gsm_create(); if (decoding)
if (decoding) context->decoder = gsm_create(); context->decoder = gsm_create();
} }
codec->private = context;
codec->private = context; return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_SUCCESS; static switch_status switch_gsm_destroy(switch_codec *codec)
}
static switch_status switch_gsm_destroy(switch_codec *codec)
{ {
struct gsm_context *context = codec->private; struct gsm_context *context = codec->private;
int encoding = (codec->flags & SWITCH_CODEC_FLAG_ENCODE); int encoding = (codec->flags & SWITCH_CODEC_FLAG_ENCODE);
int decoding = (codec->flags & SWITCH_CODEC_FLAG_DECODE); int decoding = (codec->flags & SWITCH_CODEC_FLAG_DECODE);
if (encoding)
if (encoding) gsm_destroy(context->encoder); gsm_destroy(context->encoder);
if (decoding) gsm_destroy(context->decoder); if (decoding)
gsm_destroy(context->decoder);
codec->private = NULL; codec->private = NULL;
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status switch_gsm_encode(switch_codec *codec, switch_codec *other_codec, void *decoded_data,
size_t decoded_data_len, int decoded_rate, void *encoded_data,
static switch_status switch_gsm_encode(switch_codec *codec, size_t *encoded_data_len, int *encoded_rate, unsigned int *flag)
switch_codec *other_codec,
void *decoded_data,
size_t decoded_data_len,
int decoded_rate,
void *encoded_data,
size_t *encoded_data_len,
int *encoded_rate,
unsigned int *flag)
{ {
struct gsm_context *context = codec->private; struct gsm_context *context = codec->private;
int cbret = 0; int cbret = 0;
if (!context) {
if (!context) { return SWITCH_STATUS_FALSE;
return SWITCH_STATUS_FALSE; }
} if (decoded_data_len % 320 == 0) {
if (decoded_data_len % 320 == 0) { unsigned int new_len = 0;
unsigned int new_len = 0; gsm_signal * ddp = decoded_data;
gsm_signal *ddp = decoded_data; gsm_byte * edp = encoded_data;
gsm_byte *edp = encoded_data; int x;
int x; int loops = (int) decoded_data_len / 320;
int loops = (int) decoded_data_len / 320; for (x = 0; x < loops && new_len < *encoded_data_len; x++) {
for(x = 0; x < loops && new_len < *encoded_data_len; x++) { gsm_encode(context->encoder, ddp, edp);
gsm_encode(context->encoder, ddp, edp); edp += 33;
edp += 33; ddp += 160;
ddp += 160; new_len += 33;
new_len += 33; }
} if (new_len <= *encoded_data_len) {
if( new_len <= *encoded_data_len ) { *encoded_data_len = new_len;
*encoded_data_len = new_len; } else {
} else { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "buffer overflow!!! %u >= %u\n", new_len, *encoded_data_len);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "buffer overflow!!! %u >= %u\n", new_len, *encoded_data_len); return SWITCH_STATUS_FALSE;
return SWITCH_STATUS_FALSE; }
} }
} return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_SUCCESS; static switch_status switch_gsm_decode(switch_codec *codec, switch_codec *other_codec, void *encoded_data,
} size_t encoded_data_len, int encoded_rate, void *decoded_data,
size_t *decoded_data_len, int *decoded_rate, unsigned int *flag)
static switch_status switch_gsm_decode(switch_codec *codec,
switch_codec *other_codec,
void *encoded_data,
size_t encoded_data_len,
int encoded_rate,
void *decoded_data,
size_t *decoded_data_len,
int *decoded_rate,
unsigned int *flag)
{ {
struct gsm_context *context = codec->private; struct gsm_context *context = codec->private;
if (!context) {
return SWITCH_STATUS_FALSE;
}
if (encoded_data_len % 33 == 0) {
int loops = (int) encoded_data_len / 33;
gsm_byte * edp = encoded_data;
gsm_signal * ddp = decoded_data;
int x;
unsigned int new_len = 0;
for (x = 0; x < loops && new_len < *decoded_data_len; x++) {
gsm_decode(context->decoder, edp, ddp);
ddp += 160;
edp += 33;
new_len += 320;
}
if (new_len <= *decoded_data_len) {
*decoded_data_len = new_len;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "buffer overflow!!!\n");
return SWITCH_STATUS_FALSE;
}
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "yo this frame is an odd size [%d]\n", encoded_data_len);
}
return SWITCH_STATUS_SUCCESS;
}
if (!context) {
return SWITCH_STATUS_FALSE;
}
if (encoded_data_len % 33 == 0) {
int loops = (int) encoded_data_len / 33;
gsm_byte *edp = encoded_data;
gsm_signal *ddp = decoded_data;
int x;
unsigned int new_len = 0;
for(x = 0; x < loops && new_len < *decoded_data_len; x++) {
gsm_decode(context->decoder, edp, ddp);
ddp += 160;
edp += 33;
new_len += 320;
}
if (new_len <= *decoded_data_len) {
*decoded_data_len = new_len;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "buffer overflow!!!\n");
return SWITCH_STATUS_FALSE;
}
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "yo this frame is an odd size [%d]\n", encoded_data_len);
}
return SWITCH_STATUS_SUCCESS;
}
/* Registration */ /* Registration */
static const switch_codec_implementation gsm_8k_implementation = {
static const switch_codec_implementation gsm_8k_implementation = { /*.samples_per_second */ 8000,
/*.samples_per_second*/ 8000, /*.bits_per_second */ 13200,
/*.bits_per_second*/ 13200, /*.microseconds_per_frame */ 20000,
/*.microseconds_per_frame*/ 20000, /*.samples_per_frame */ 160,
/*.samples_per_frame*/ 160, /*.bytes_per_frame */ 320,
/*.bytes_per_frame*/ 320, /*.encoded_bytes_per_frame */ 33,
/*.encoded_bytes_per_frame*/ 33, /*.number_of_channels */ 1,
/*.number_of_channels*/ 1, /*.pref_frames_per_packet */ 1,
/*.pref_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.init */ switch_gsm_init,
/*.init*/ switch_gsm_init, /*.encode */ switch_gsm_encode,
/*.encode*/ switch_gsm_encode, /*.decode */ switch_gsm_decode,
/*.decode*/ switch_gsm_decode, /*.destroy */ switch_gsm_destroy,
/*.destroy*/ switch_gsm_destroy,
}; };
static const switch_codec_interface gsm_codec_interface = {
static const switch_codec_interface gsm_codec_interface = { /*.interface_name */ "gsm",
/*.interface_name*/ "gsm", /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.codec_type*/ SWITCH_CODEC_TYPE_AUDIO, /*.ianacode */ 3,
/*.ianacode*/ 3, /*.iananame */ "gsm",
/*.iananame*/ "gsm", /*.implementations */ &gsm_8k_implementation,
/*.implementations*/ &gsm_8k_implementation,
}; };
static switch_loadable_module_interface gsm_module_interface = {
static switch_loadable_module_interface gsm_module_interface = { /*.module_name */ modname,
/*.module_name*/ modname, /*.endpoint_interface */ NULL,
/*.endpoint_interface*/ NULL, /*.timer_interface */ NULL,
/*.timer_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.codec_interface */ &gsm_codec_interface,
/*.codec_interface*/ &gsm_codec_interface, /*.application_interface */ NULL
/*.application_interface*/ NULL
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface,
char *filename)
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { {
/* connect my internal structure to the blank pointer passed to me */
*interface = &gsm_module_interface; /* connect my internal structure to the blank pointer passed to me */
*interface = &gsm_module_interface;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; /* indicate that the module should continue to be loaded */
} return SWITCH_STATUS_SUCCESS;
}

View File

@ -35,7 +35,8 @@
static const char modname[] = "mod_rawaudio"; static const char modname[] = "mod_rawaudio";
static switch_status switch_raw_init(switch_codec *codec, switch_codec_flag flags, const struct switch_codec_settings *codec_settings) static switch_status switch_raw_init(switch_codec *codec, switch_codec_flag flags,
const struct switch_codec_settings *codec_settings)
{ {
int encoding, decoding; int encoding, decoding;
struct raw_context *context = NULL; struct raw_context *context = NULL;
@ -51,17 +52,15 @@ static switch_status switch_raw_init(switch_codec *codec, switch_codec_flag flag
} }
static switch_status switch_raw_encode(switch_codec *codec, static switch_status switch_raw_encode(switch_codec *codec,
switch_codec *other_codec, switch_codec *other_codec,
void *decoded_data, void *decoded_data,
size_t decoded_data_len, size_t decoded_data_len,
int decoded_rate, int decoded_rate,
void *encoded_data, void *encoded_data,
size_t *encoded_data_len, size_t *encoded_data_len, int *encoded_rate, unsigned int *flag)
int *encoded_rate,
unsigned int *flag)
{ {
/* NOOP indicates that the audio in is already the same as the audio out, so no conversion was necessary.*/ /* NOOP indicates that the audio in is already the same as the audio out, so no conversion was necessary. */
if (codec->implementation->samples_per_second != other_codec->implementation->samples_per_second) { if (codec->implementation->samples_per_second != other_codec->implementation->samples_per_second) {
memcpy(encoded_data, decoded_data, decoded_data_len); memcpy(encoded_data, decoded_data, decoded_data_len);
*encoded_data_len = decoded_data_len; *encoded_data_len = decoded_data_len;
@ -71,14 +70,12 @@ static switch_status switch_raw_encode(switch_codec *codec,
} }
static switch_status switch_raw_decode(switch_codec *codec, static switch_status switch_raw_decode(switch_codec *codec,
switch_codec *other_codec, switch_codec *other_codec,
void *encoded_data, void *encoded_data,
size_t encoded_data_len, size_t encoded_data_len,
int encoded_rate, int encoded_rate,
void *decoded_data, void *decoded_data,
size_t *decoded_data_len, size_t *decoded_data_len, int *decoded_rate, unsigned int *flag)
int *decoded_rate,
unsigned int *flag)
{ {
if (codec->implementation->samples_per_second != other_codec->implementation->samples_per_second) { if (codec->implementation->samples_per_second != other_codec->implementation->samples_per_second) {
memcpy(decoded_data, encoded_data, encoded_data_len); memcpy(decoded_data, encoded_data, encoded_data_len);
@ -96,7 +93,7 @@ static switch_status switch_raw_destroy(switch_codec *codec)
} }
static const switch_codec_implementation raw_32k_implementation = { static const switch_codec_implementation raw_32k_implementation = {
/*.samples_per_second = */ 32000, /*.samples_per_second = */ 32000,
/*.bits_per_second = */ 512000, /*.bits_per_second = */ 512000,
/*.microseconds_per_frame = */ 20000, /*.microseconds_per_frame = */ 20000,
/*.samples_per_frame = */ 640, /*.samples_per_frame = */ 640,
@ -164,52 +161,48 @@ static const switch_codec_implementation raw_8k_implementation = {
static const switch_codec_implementation raw_8k_30ms_implementation = { static const switch_codec_implementation raw_8k_30ms_implementation = {
/*.samples_per_second*/ 8000, /*.samples_per_second */ 8000,
/*.bits_per_second*/ 128000, /*.bits_per_second */ 128000,
/*.microseconds_per_frame*/ 30000, /*.microseconds_per_frame */ 30000,
/*.samples_per_frame*/ 240, /*.samples_per_frame */ 240,
/*.bytes_per_frame*/ 480, /*.bytes_per_frame */ 480,
/*.encoded_bytes_per_frame*/ 480, /*.encoded_bytes_per_frame */ 480,
/*.number_of_channels*/ 1, /*.number_of_channels */ 1,
/*.pref_frames_per_packet*/ 1, /*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.init*/ switch_raw_init, /*.init */ switch_raw_init,
/*.encode*/ switch_raw_encode, /*.encode */ switch_raw_encode,
/*.decode*/ switch_raw_decode, /*.decode */ switch_raw_decode,
/*.destroy*/ switch_raw_destroy, /*.destroy */ switch_raw_destroy,
/*.next*/ &raw_8k_implementation /*.next */ &raw_8k_implementation
}; };
static const switch_codec_interface raw_codec_interface = { static const switch_codec_interface raw_codec_interface = {
/*.interface_name*/ "raw signed linear (16 bit)", /*.interface_name */ "raw signed linear (16 bit)",
/*.codec_type*/ SWITCH_CODEC_TYPE_AUDIO, /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode*/ 10, /*.ianacode */ 10,
/*.iananame*/ "L16", /*.iananame */ "L16",
/*.implementations*/ &raw_8k_30ms_implementation /*.implementations */ &raw_8k_30ms_implementation
}; };
static switch_loadable_module_interface raw_module_interface = { static switch_loadable_module_interface raw_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ NULL, /*.endpoint_interface */ NULL,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ &raw_codec_interface, /*.codec_interface */ &raw_codec_interface,
/*.application_interface*/ NULL, /*.application_interface */ NULL,
/*.api_interface*/ NULL, /*.api_interface */ NULL,
///*.file_interface*/ &raw_file_interface ///*.file_interface*/ &raw_file_interface
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &raw_module_interface; *interface = &raw_module_interface;
/* indicate that the module should continue to be loaded */ /* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -36,22 +36,22 @@
static const char modname[] = "mod_speexcodec"; static const char modname[] = "mod_speexcodec";
const struct switch_codec_settings default_codec_settings = { const struct switch_codec_settings default_codec_settings = {
/*.quality*/ 5, /*.quality */ 5,
/*.complexity*/ 5, /*.complexity */ 5,
/*.enhancement*/ 1, /*.enhancement */ 1,
/*.vad*/ 0, /*.vad */ 0,
/*.vbr*/ 0, /*.vbr */ 0,
/*.vbr_quality*/ 4, /*.vbr_quality */ 4,
/*.abr*/ 0, /*.abr */ 0,
/*.dtx*/ 0, /*.dtx */ 0,
/*.preproc*/ 0, /*.preproc */ 0,
/*.pp_vad*/ 0, /*.pp_vad */ 0,
/*.pp_agc*/ 0, /*.pp_agc */ 0,
/*.pp_agc_level*/ 8000, /*.pp_agc_level */ 8000,
/*.pp_denoise*/ 0, /*.pp_denoise */ 0,
/*.pp_dereverb*/ 0, /*.pp_dereverb */ 0,
/*.pp_dereverb_decay*/ 0.4f, /*.pp_dereverb_decay */ 0.4f,
/*.pp_dereverb_level*/ 0.3f, /*.pp_dereverb_level */ 0.3f,
}; };
struct speex_context { struct speex_context {
@ -72,7 +72,8 @@ struct speex_context {
int decoder_mode; int decoder_mode;
}; };
static switch_status switch_speex_init(switch_codec *codec, switch_codec_flag flags, const struct switch_codec_settings *codec_settings) static switch_status switch_speex_init(switch_codec *codec, switch_codec_flag flags,
const struct switch_codec_settings *codec_settings)
{ {
struct speex_context *context = NULL; struct speex_context *context = NULL;
int encoding, decoding; int encoding, decoding;
@ -110,14 +111,17 @@ static switch_status switch_speex_init(switch_codec *codec, switch_codec_flag fl
speex_encoder_ctl(context->encoder_state, SPEEX_GET_FRAME_SIZE, &context->encoder_frame_size); speex_encoder_ctl(context->encoder_state, SPEEX_GET_FRAME_SIZE, &context->encoder_frame_size);
speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &codec->codec_settings.complexity); speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &codec->codec_settings.complexity);
if (codec->codec_settings.preproc) { if (codec->codec_settings.preproc) {
context->pp = speex_preprocess_state_init(context->encoder_frame_size, codec->implementation->samples_per_second); context->pp =
speex_preprocess_state_init(context->encoder_frame_size, codec->implementation->samples_per_second);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &codec->codec_settings.pp_vad); speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &codec->codec_settings.pp_vad);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC, &codec->codec_settings.pp_agc); speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC, &codec->codec_settings.pp_agc);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &codec->codec_settings.pp_agc_level); speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &codec->codec_settings.pp_agc_level);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &codec->codec_settings.pp_denoise); speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &codec->codec_settings.pp_denoise);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB, &codec->codec_settings.pp_dereverb); speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB, &codec->codec_settings.pp_dereverb);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &codec->codec_settings.pp_dereverb_decay); speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY,
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &codec->codec_settings.pp_dereverb_level); &codec->codec_settings.pp_dereverb_decay);
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL,
&codec->codec_settings.pp_dereverb_level);
} }
if (!codec->codec_settings.abr && !codec->codec_settings.vbr) { if (!codec->codec_settings.abr && !codec->codec_settings.vbr) {
@ -154,14 +158,12 @@ static switch_status switch_speex_init(switch_codec *codec, switch_codec_flag fl
} }
static switch_status switch_speex_encode(switch_codec *codec, static switch_status switch_speex_encode(switch_codec *codec,
switch_codec *other_codec, switch_codec *other_codec,
void *decoded_data, void *decoded_data,
size_t decoded_data_len, size_t decoded_data_len,
int decoded_rate, int decoded_rate,
void *encoded_data, void *encoded_data,
size_t *encoded_data_len, size_t *encoded_data_len, int *encoded_rate, unsigned int *flag)
int *encoded_rate,
unsigned int *flag)
{ {
struct speex_context *context = codec->private; struct speex_context *context = codec->private;
short *buf; short *buf;
@ -178,7 +180,8 @@ static switch_status switch_speex_encode(switch_codec *codec,
} }
if (is_speech) { if (is_speech) {
is_speech = speex_encode_int(context->encoder_state, buf, &context->encoder_bits) || ! context->codec->codec_settings.dtx; is_speech = speex_encode_int(context->encoder_state, buf, &context->encoder_bits)
|| !context->codec->codec_settings.dtx;
} else { } else {
speex_bits_pack(&context->encoder_bits, 0, 5); speex_bits_pack(&context->encoder_bits, 0, 5);
} }
@ -202,7 +205,7 @@ static switch_status switch_speex_encode(switch_codec *codec,
speex_bits_pack(&context->encoder_bits, 15, 5); speex_bits_pack(&context->encoder_bits, 15, 5);
*encoded_data_len = speex_bits_write(&context->encoder_bits, (char *)encoded_data, context->encoder_frame_size); *encoded_data_len = speex_bits_write(&context->encoder_bits, (char *) encoded_data, context->encoder_frame_size);
speex_bits_reset(&context->encoder_bits); speex_bits_reset(&context->encoder_bits);
@ -210,14 +213,12 @@ static switch_status switch_speex_encode(switch_codec *codec,
} }
static switch_status switch_speex_decode(switch_codec *codec, static switch_status switch_speex_decode(switch_codec *codec,
switch_codec *other_codec, switch_codec *other_codec,
void *encoded_data, void *encoded_data,
size_t encoded_data_len, size_t encoded_data_len,
int encoded_rate, int encoded_rate,
void *decoded_data, void *decoded_data,
size_t *decoded_data_len, size_t *decoded_data_len, int *decoded_rate, unsigned int *flag)
int *decoded_rate,
unsigned int *flag)
{ {
struct speex_context *context = codec->private; struct speex_context *context = codec->private;
short *buf; short *buf;
@ -230,7 +231,7 @@ static switch_status switch_speex_decode(switch_codec *codec,
if (*flag & SWITCH_CODEC_FLAG_SILENCE) { if (*flag & SWITCH_CODEC_FLAG_SILENCE) {
speex_decode_int(context->decoder_state, NULL, buf); speex_decode_int(context->decoder_state, NULL, buf);
} else { } else {
speex_bits_read_from(&context->decoder_bits, (char *)encoded_data, (int)*decoded_data_len); speex_bits_read_from(&context->decoder_bits, (char *) encoded_data, (int) *decoded_data_len);
speex_decode_int(context->decoder_state, &context->decoder_bits, buf); speex_decode_int(context->decoder_state, &context->decoder_bits, buf);
} }
@ -267,73 +268,74 @@ static switch_status switch_speex_destroy(switch_codec *codec)
/* Registration */ /* Registration */
static const switch_codec_implementation speex_32k_implementation = { static const switch_codec_implementation speex_32k_implementation = {
/*.samples_per_second*/ 32000, /*.samples_per_second */ 32000,
/*.bits_per_second*/ 512000, /*.bits_per_second */ 512000,
/*.nanoseconds_per_frame*/ 20000, /*.nanoseconds_per_frame */ 20000,
/*.samples_per_frame*/ 640, /*.samples_per_frame */ 640,
/*.bytes_per_frame*/ 1280, /*.bytes_per_frame */ 1280,
/*.encoded_bytes_per_frame*/ 1280, /*.encoded_bytes_per_frame */ 1280,
/*.number_of_channels*/ 1, /*.number_of_channels */ 1,
/*.pref_frames_per_packet*/ 1, /*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.init*/ switch_speex_init, /*.init */ switch_speex_init,
/*.encode*/ switch_speex_encode, /*.encode */ switch_speex_encode,
/*.decode*/ switch_speex_decode, /*.decode */ switch_speex_decode,
/*.destroy*/ switch_speex_destroy /*.destroy */ switch_speex_destroy
}; };
static const switch_codec_implementation speex_16k_implementation = { static const switch_codec_implementation speex_16k_implementation = {
/*.samples_per_second*/ 16000, /*.samples_per_second */ 16000,
/*.bits_per_second*/ 256000, /*.bits_per_second */ 256000,
/*.nanoseconds_per_frame*/ 20000, /*.nanoseconds_per_frame */ 20000,
/*.samples_per_frame*/ 320, /*.samples_per_frame */ 320,
/*.bytes_per_frame*/ 640, /*.bytes_per_frame */ 640,
/*.encoded_bytes_per_frame*/ 640, /*.encoded_bytes_per_frame */ 640,
/*.number_of_channels*/ 1, /*.number_of_channels */ 1,
/*.pref_frames_per_packet*/ 1, /*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.init*/ switch_speex_init, /*.init */ switch_speex_init,
/*.encode*/ switch_speex_encode, /*.encode */ switch_speex_encode,
/*.decode*/ switch_speex_decode, /*.decode */ switch_speex_decode,
/*.destroy*/ switch_speex_destroy, /*.destroy */ switch_speex_destroy,
/*.next*/ &speex_32k_implementation /*.next */ &speex_32k_implementation
}; };
static const switch_codec_implementation speex_8k_implementation = { static const switch_codec_implementation speex_8k_implementation = {
/*.samples_per_second*/ 8000, /*.samples_per_second */ 8000,
/*.bits_per_second*/ 128000, /*.bits_per_second */ 128000,
/*.nanoseconds_per_frame*/ 20000, /*.nanoseconds_per_frame */ 20000,
/*.samples_per_frame*/ 160, /*.samples_per_frame */ 160,
/*.bytes_per_frame*/ 320, /*.bytes_per_frame */ 320,
/*.encoded_bytes_per_frame*/ 320, /*.encoded_bytes_per_frame */ 320,
/*.number_of_channels*/ 1, /*.number_of_channels */ 1,
/*.pref_frames_per_packet*/ 1, /*.pref_frames_per_packet */ 1,
/*.max_frames_per_packet*/ 1, /*.max_frames_per_packet */ 1,
/*.init*/ switch_speex_init, /*.init */ switch_speex_init,
/*.encode*/ switch_speex_encode, /*.encode */ switch_speex_encode,
/*.decode*/ switch_speex_decode, /*.decode */ switch_speex_decode,
/*.destroy*/ switch_speex_destroy, /*.destroy */ switch_speex_destroy,
/*.next*/ &speex_16k_implementation /*.next */ &speex_16k_implementation
}; };
static const switch_codec_interface speex_codec_interface = { static const switch_codec_interface speex_codec_interface = {
/*.interface_name*/ "speex", /*.interface_name */ "speex",
/*.codec_type*/ SWITCH_CODEC_TYPE_AUDIO, /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode*/ 98, /*.ianacode */ 98,
/*.iananame*/ "speex", /*.iananame */ "speex",
/*.implementations*/ &speex_8k_implementation /*.implementations */ &speex_8k_implementation
}; };
static switch_loadable_module_interface speex_module_interface = { static switch_loadable_module_interface speex_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ NULL, /*.endpoint_interface */ NULL,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ &speex_codec_interface, /*.codec_interface */ &speex_codec_interface,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &speex_module_interface; *interface = &speex_module_interface;

View File

@ -52,7 +52,8 @@ switch_caller_extension *demo_dialplan_hunt(switch_core_session *session)
caller_profile = switch_channel_get_caller_profile(channel); caller_profile = switch_channel_get_caller_profile(channel);
//switch_channel_set_variable(channel, "pleasework", "yay"); //switch_channel_set_variable(channel, "pleasework", "yay");
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hello %s You Dialed %s!\n", caller_profile->caller_id_name, caller_profile->destination_number); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hello %s You Dialed %s!\n", caller_profile->caller_id_name,
caller_profile->destination_number);
if (!switch_config_open_file(&cfg, cf)) { if (!switch_config_open_file(&cfg, cf)) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "open of %s failed\n", cf); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "open of %s failed\n", cf);
@ -76,7 +77,10 @@ switch_caller_extension *demo_dialplan_hunt(switch_core_session *session)
continue; continue;
} }
if (!extension) { if (!extension) {
if (!(extension = switch_caller_extension_new(session, caller_profile->destination_number, caller_profile->destination_number))) { if (!
(extension =
switch_caller_extension_new(session, caller_profile->destination_number,
caller_profile->destination_number))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "memory error!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "memory error!\n");
break; break;
} }
@ -100,9 +104,9 @@ switch_caller_extension *demo_dialplan_hunt(switch_core_session *session)
static const switch_dialplan_interface demo_dialplan_interface = { static const switch_dialplan_interface demo_dialplan_interface = {
/*.interface_name =*/ "demo", /*.interface_name = */ "demo",
/*.hunt_function = */ demo_dialplan_hunt /*.hunt_function = */ demo_dialplan_hunt
/*.next = NULL */ /*.next = NULL */
}; };
static const switch_loadable_module_interface demo_dialplan_module_interface = { static const switch_loadable_module_interface demo_dialplan_module_interface = {
@ -111,10 +115,11 @@ static const switch_loadable_module_interface demo_dialplan_module_interface = {
/*.timer_interface = */ NULL, /*.timer_interface = */ NULL,
/*.dialplan_interface = */ &demo_dialplan_interface, /*.dialplan_interface = */ &demo_dialplan_interface,
/*.codec_interface = */ NULL, /*.codec_interface = */ NULL,
/*.application_interface =*/ NULL /*.application_interface = */ NULL
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &demo_dialplan_module_interface; *interface = &demo_dialplan_module_interface;

View File

@ -60,7 +60,8 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session)
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
caller_profile = switch_channel_get_caller_profile(channel); caller_profile = switch_channel_get_caller_profile(channel);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Processing %s->%s!\n", caller_profile->caller_id_name, caller_profile->destination_number); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Processing %s->%s!\n", caller_profile->caller_id_name,
caller_profile->destination_number);
if (!switch_config_open_file(&cfg, cf)) { if (!switch_config_open_file(&cfg, cf)) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "open of %s failed\n", cf); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "open of %s failed\n", cf);
@ -69,7 +70,7 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session)
} }
while (switch_config_next_pair(&cfg, &var, &val)) { while (switch_config_next_pair(&cfg, &var, &val)) {
if (cfg.catno != catno) { /* new category */ if (cfg.catno != catno) { /* new category */
catno = cfg.catno; catno = cfg.catno;
exten_name = cfg.category; exten_name = cfg.category;
cleanre(); cleanre();
@ -81,12 +82,11 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session)
int erroffset = 0; int erroffset = 0;
cleanre(); cleanre();
re = pcre_compile( re = pcre_compile(val, /* the pattern */
val, /* the pattern */ 0, /* default options */
0, /* default options */ &error, /* for error message */
&error, /* for error message */ &erroffset, /* for error offset */
&erroffset, /* for error offset */ NULL); /* use default character tables */
NULL); /* use default character tables */
if (error) { if (error) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "COMPILE ERROR: %d [%s]\n", erroffset, error); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "COMPILE ERROR: %d [%s]\n", erroffset, error);
cleanre(); cleanre();
@ -94,31 +94,31 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session)
return NULL; return NULL;
} }
match_count = pcre_exec( match_count = pcre_exec(re, /* result of pcre_compile() */
re, /* result of pcre_compile() */ NULL, /* we didn't study the pattern */
NULL, /* we didn't study the pattern */ caller_profile->destination_number, /* the subject string */
caller_profile->destination_number, /* the subject string */ strlen(caller_profile->destination_number), /* the length of the subject string */
strlen(caller_profile->destination_number), /* the length of the subject string */ 0, /* start at offset 0 in the subject */
0, /* start at offset 0 in the subject */ 0, /* default options */
0, /* default options */ ovector, /* vector of integers for substring information */
ovector, /* vector of integers for substring information */ sizeof(ovector) / sizeof(ovector[0])); /* number of elements (NOT size in bytes) */
sizeof(ovector) / sizeof(ovector[0])); /* number of elements (NOT size in bytes) */
} else if (match_count > 0 && !strcasecmp(var, "match")) { } else if (match_count > 0 && !strcasecmp(var, "match")) {
if (!re) { if (!re) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "ERROR: match without regex in %s line %d\n", cfg.path, cfg.lineno); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "ERROR: match without regex in %s line %d\n", cfg.path,
cfg.lineno);
continue; continue;
} else { } else {
char newval[1024] = ""; char newval[1024] = "";
char index[10] = ""; char index[10] = "";
char replace[128] = ""; char replace[128] = "";
int x, y=0, z=0, num = 0; int x, y = 0, z = 0, num = 0;
char *data; char *data;
for (x = 0; x < sizeof(newval) && x < strlen(val);) { for (x = 0; x < sizeof(newval) && x < strlen(val);) {
if (val[x] == '$') { if (val[x] == '$') {
x++; x++;
while(val[x] > 47 && val[x] < 58) { while (val[x] > 47 && val[x] < 58) {
index[z++] = val[x]; index[z++] = val[x];
x++; x++;
} }
@ -126,9 +126,11 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session)
z = 0; z = 0;
num = atoi(index); num = atoi(index);
if (pcre_copy_substring(caller_profile->destination_number, ovector, match_count, num, replace, sizeof(replace)) > 0) { if (pcre_copy_substring
(caller_profile->destination_number, ovector, match_count, num, replace,
sizeof(replace)) > 0) {
int r; int r;
for(r = 0; r < strlen(replace); r++) { for (r = 0; r < strlen(replace); r++) {
newval[y++] = replace[r]; newval[y++] = replace[r];
} }
} }
@ -152,7 +154,9 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session)
if (!extension) { if (!extension) {
if (!(extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number))) { if (!
(extension =
switch_caller_extension_new(session, exten_name, caller_profile->destination_number))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "memory error!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "memory error!\n");
break; break;
} }
@ -177,9 +181,9 @@ switch_caller_extension *dialplan_hunt(switch_core_session *session)
static const switch_dialplan_interface dialplan_interface = { static const switch_dialplan_interface dialplan_interface = {
/*.interface_name =*/ "pcre", /*.interface_name = */ "pcre",
/*.hunt_function = */ dialplan_hunt /*.hunt_function = */ dialplan_hunt
/*.next = NULL */ /*.next = NULL */
}; };
static const switch_loadable_module_interface dialplan_module_interface = { static const switch_loadable_module_interface dialplan_module_interface = {
@ -188,10 +192,11 @@ static const switch_loadable_module_interface dialplan_module_interface = {
/*.timer_interface = */ NULL, /*.timer_interface = */ NULL,
/*.dialplan_interface = */ &dialplan_interface, /*.dialplan_interface = */ &dialplan_interface,
/*.codec_interface = */ NULL, /*.codec_interface = */ NULL,
/*.application_interface =*/ NULL /*.application_interface = */ NULL
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &dialplan_module_interface; *interface = &dialplan_module_interface;

View File

@ -144,11 +144,14 @@ static switch_status exosip_on_init(switch_core_session *session);
static switch_status exosip_on_hangup(switch_core_session *session); static switch_status exosip_on_hangup(switch_core_session *session);
static switch_status exosip_on_loopback(switch_core_session *session); static switch_status exosip_on_loopback(switch_core_session *session);
static switch_status exosip_on_transmit(switch_core_session *session); static switch_status exosip_on_transmit(switch_core_session *session);
static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session); static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id); switch_core_session **new_session);
static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id); static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id);
static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id);
static int config_exosip(int reload); static int config_exosip(int reload);
static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **drate, char **dpayload); static switch_status parse_sdp_media(sdp_media_t * media, char **dname, char **drate, char **dpayload);
static switch_status exosip_kill_channel(switch_core_session *session, int sig); static switch_status exosip_kill_channel(switch_core_session *session, int sig);
static void activate_rtp(struct private_object *tech_pvt); static void activate_rtp(struct private_object *tech_pvt);
static void deactivate_rtp(struct private_object *tech_pvt); static void deactivate_rtp(struct private_object *tech_pvt);
@ -190,16 +193,16 @@ static int sdp_add_codec(struct osip_rfc3264 *cnf, int codec_type, int payload,
} }
switch (codec_type) { switch (codec_type) {
case SWITCH_CODEC_TYPE_AUDIO: case SWITCH_CODEC_TYPE_AUDIO:
med->m_media = osip_strdup("audio"); med->m_media = osip_strdup("audio");
osip_rfc3264_add_audio_media(cnf, med, -1); osip_rfc3264_add_audio_media(cnf, med, -1);
break; break;
case SWITCH_CODEC_TYPE_VIDEO: case SWITCH_CODEC_TYPE_VIDEO:
med->m_media = osip_strdup("video"); med->m_media = osip_strdup("video");
osip_rfc3264_add_video_media(cnf, med, -1); osip_rfc3264_add_video_media(cnf, med, -1);
break; break;
default: default:
break; break;
} }
return 0; return 0;
} }
@ -232,7 +235,7 @@ static switch_status exosip_on_init(switch_core_session *session)
char *dest_uri; char *dest_uri;
switch_codec_interface *codecs[SWITCH_MAX_CODECS]; switch_codec_interface *codecs[SWITCH_MAX_CODECS];
int num_codecs = 0; int num_codecs = 0;
/* do SIP Goodies...*/ /* do SIP Goodies... */
/* Generate callerid URI */ /* Generate callerid URI */
eXosip_guess_localip(AF_INET, localip, 128); eXosip_guess_localip(AF_INET, localip, 128);
@ -245,14 +248,17 @@ static switch_status exosip_on_init(switch_core_session *session)
/* Initialize SDP */ /* Initialize SDP */
sdp_message_init(&tech_pvt->local_sdp); sdp_message_init(&tech_pvt->local_sdp);
sdp_message_v_version_set(tech_pvt->local_sdp, "0"); sdp_message_v_version_set(tech_pvt->local_sdp, "0");
sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4", tech_pvt->local_sdp_audio_ip); sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4",
tech_pvt->local_sdp_audio_ip);
sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call"); sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call");
sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL); sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL);
sdp_message_t_time_descr_add(tech_pvt->local_sdp, "0", "0"); sdp_message_t_time_descr_add(tech_pvt->local_sdp, "0", "0");
snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port); snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port);
sdp_message_m_media_add(tech_pvt->local_sdp, "audio", port, NULL, "RTP/AVP"); sdp_message_m_media_add(tech_pvt->local_sdp, "audio", port, NULL, "RTP/AVP");
/* Add in every codec we support on this outbound call */ /* Add in every codec we support on this outbound call */
if ((num_codecs = switch_loadable_module_get_codecs(switch_core_session_get_pool(session), codecs, sizeof(codecs)/sizeof(codecs[0]))) > 0) { if ((num_codecs =
switch_loadable_module_get_codecs(switch_core_session_get_pool(session), codecs,
sizeof(codecs) / sizeof(codecs[0]))) > 0) {
int i; int i;
static const switch_codec_implementation *imp; static const switch_codec_implementation *imp;
for (i = 0; i < num_codecs; i++) { for (i = 0; i < num_codecs; i++) {
@ -260,12 +266,14 @@ static switch_status exosip_on_init(switch_core_session *session)
snprintf(tmp, sizeof(tmp), "%i", codecs[i]->ianacode); snprintf(tmp, sizeof(tmp), "%i", codecs[i]->ianacode);
sdp_message_m_payload_add(tech_pvt->local_sdp, 0, osip_strdup(tmp)); sdp_message_m_payload_add(tech_pvt->local_sdp, 0, osip_strdup(tmp));
for (imp = codecs[i]->implementations ; imp ; imp = imp->next) { for (imp = codecs[i]->implementations; imp; imp = imp->next) {
/* Add to SDP config */ /* Add to SDP config */
sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame, imp->samples_per_second, x++); sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame,
imp->samples_per_second, x++);
/* Add to SDP message */ /* Add to SDP message */
snprintf(tmp, sizeof(tmp), "%i %s/%i", codecs[i]->ianacode, codecs[i]->iananame, imp->samples_per_second); snprintf(tmp, sizeof(tmp), "%i %s/%i", codecs[i]->ianacode, codecs[i]->iananame,
imp->samples_per_second);
sdp_message_a_attribute_add(tech_pvt->local_sdp, 0, "rtpmap", osip_strdup(tmp)); sdp_message_a_attribute_add(tech_pvt->local_sdp, 0, "rtpmap", osip_strdup(tmp));
memset(tmp, 0, sizeof(tmp)); memset(tmp, 0, sizeof(tmp));
} }
@ -273,7 +281,9 @@ static switch_status exosip_on_init(switch_core_session *session)
} }
/* Setup our INVITE */ /* Setup our INVITE */
eXosip_lock(); eXosip_lock();
if (!(dest_uri = (char *) switch_core_session_alloc(session, strlen(tech_pvt->caller_profile->destination_number) + 10))) { if (!
(dest_uri =
(char *) switch_core_session_alloc(session, strlen(tech_pvt->caller_profile->destination_number) + 10))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "AIEEEE!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "AIEEEE!\n");
assert(dest_uri != NULL); assert(dest_uri != NULL);
} }
@ -346,7 +356,8 @@ static switch_status exosip_on_hangup(switch_core_session *session)
switch_core_codec_destroy(&tech_pvt->write_codec); switch_core_codec_destroy(&tech_pvt->write_codec);
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "EXOSIP HANGUP %s %d/%d=%d\n", switch_channel_get_name(channel), tech_pvt->cid, tech_pvt->did, i); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "EXOSIP HANGUP %s %d/%d=%d\n", switch_channel_get_name(channel),
tech_pvt->cid, tech_pvt->did, i);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -362,14 +373,16 @@ static switch_status exosip_on_transmit(switch_core_session *session)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session) static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
switch_core_session **new_session)
{ {
if ((*new_session = switch_core_session_request(&exosip_endpoint_interface, NULL))) { if ((*new_session = switch_core_session_request(&exosip_endpoint_interface, NULL))) {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel; switch_channel *channel;
switch_core_session_add_stream(*new_session, NULL); switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) { if ((tech_pvt =
(struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt)); memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(*new_session); channel = switch_core_session_get_channel(*new_session);
switch_core_session_set_private(*new_session, tech_pvt); switch_core_session_set_private(*new_session, tech_pvt);
@ -412,7 +425,7 @@ static void deactivate_rtp(struct private_object *tech_pvt)
if (tech_pvt->rtp_session) { if (tech_pvt->rtp_session) {
switch_mutex_lock(tech_pvt->rtp_lock); switch_mutex_lock(tech_pvt->rtp_lock);
while(loops < 10 && (switch_test_flag(tech_pvt, TFLAG_READING) || switch_test_flag(tech_pvt, TFLAG_WRITING))) { while (loops < 10 && (switch_test_flag(tech_pvt, TFLAG_READING) || switch_test_flag(tech_pvt, TFLAG_WRITING))) {
switch_yield(10000); switch_yield(10000);
loops++; loops++;
} }
@ -454,25 +467,20 @@ static void activate_rtp(struct private_object *tech_pvt)
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activating RTP %s:%d->%s:%d codec: %d ms: %d\n", switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activating RTP %s:%d->%s:%d codec: %d ms: %d\n",
tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_audio_ip,
tech_pvt->local_sdp_audio_port, tech_pvt->local_sdp_audio_port,
tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip,
tech_pvt->remote_sdp_audio_port, tech_pvt->remote_sdp_audio_port, tech_pvt->read_codec.codec_interface->ianacode, ms);
tech_pvt->read_codec.codec_interface->ianacode,
ms
);
tech_pvt->rtp_session = jrtp4c_new( tech_pvt->rtp_session = jrtp4c_new(tech_pvt->local_sdp_audio_ip,
tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_audio_port,
tech_pvt->local_sdp_audio_port, tech_pvt->remote_sdp_audio_ip,
tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port,
tech_pvt->remote_sdp_audio_port, tech_pvt->read_codec.codec_interface->ianacode,
tech_pvt->read_codec.codec_interface->ianacode, tech_pvt->read_codec.implementation->samples_per_second, &err);
tech_pvt->read_codec.implementation->samples_per_second,
&err);
if (tech_pvt->rtp_session) { if (tech_pvt->rtp_session) {
tech_pvt->ssrc = jrtp4c_get_ssrc(tech_pvt->rtp_session); tech_pvt->ssrc = jrtp4c_get_ssrc(tech_pvt->rtp_session);
@ -521,10 +529,11 @@ static switch_status exosip_answer_channel(switch_core_session *session)
} }
static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id) static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
size_t bytes = 0, samples = 0, frames=0, ms=0; size_t bytes = 0, samples = 0, frames = 0, ms = 0;
switch_channel *channel = NULL; switch_channel *channel = NULL;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
@ -553,18 +562,18 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
assert(tech_pvt->rtp_session != NULL); assert(tech_pvt->rtp_session != NULL);
tech_pvt->read_frame.datalen = 0; tech_pvt->read_frame.datalen = 0;
while(!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO) && tech_pvt->read_frame.datalen == 0) { while (!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO)
tech_pvt->read_frame.datalen = jrtp4c_read(tech_pvt->rtp_session, && tech_pvt->read_frame.datalen == 0) {
tech_pvt->read_frame.data, tech_pvt->read_frame.datalen =
sizeof(tech_pvt->read_buf)); jrtp4c_read(tech_pvt->rtp_session, tech_pvt->read_frame.data, sizeof(tech_pvt->read_buf));
if (tech_pvt->read_frame.datalen > 0) { if (tech_pvt->read_frame.datalen > 0) {
bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame; bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
frames = (tech_pvt->read_frame.datalen / bytes); frames = (tech_pvt->read_frame.datalen / bytes);
samples = frames * tech_pvt->read_codec.implementation->samples_per_frame; samples = frames * tech_pvt->read_codec.implementation->samples_per_frame;
ms = frames * tech_pvt->read_codec.implementation->microseconds_per_frame; ms = frames * tech_pvt->read_codec.implementation->microseconds_per_frame;
tech_pvt->timestamp_recv += (int32_t)samples; tech_pvt->timestamp_recv += (int32_t) samples;
tech_pvt->read_frame.samples = (int)samples; tech_pvt->read_frame.samples = (int) samples;
break; break;
} }
@ -598,12 +607,13 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
} }
static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id) static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel = NULL; switch_channel *channel = NULL;
switch_status status = SWITCH_STATUS_SUCCESS; switch_status status = SWITCH_STATUS_SUCCESS;
int bytes=0, samples=0, ms=0, frames=0; int bytes = 0, samples = 0, ms = 0, frames = 0;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
assert(channel != NULL); assert(channel != NULL);
@ -629,7 +639,7 @@ static switch_status exosip_write_frame(switch_core_session *session, switch_fra
if (switch_test_flag(tech_pvt, TFLAG_USING_CODEC)) { if (switch_test_flag(tech_pvt, TFLAG_USING_CODEC)) {
bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame; bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
frames = ((int)frame->datalen / bytes); frames = ((int) frame->datalen / bytes);
samples = frames * tech_pvt->read_codec.implementation->samples_per_frame; samples = frames * tech_pvt->read_codec.implementation->samples_per_frame;
ms = frames * tech_pvt->read_codec.implementation->microseconds_per_frame / 1000; ms = frames * tech_pvt->read_codec.implementation->microseconds_per_frame / 1000;
} else { } else {
@ -640,8 +650,8 @@ static switch_status exosip_write_frame(switch_core_session *session, switch_fra
//printf("%s %s->%s send %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip, frame->datalen, samples, frames, ms, tech_pvt->timestamp_send); //printf("%s %s->%s send %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip, frame->datalen, samples, frames, ms, tech_pvt->timestamp_send);
jrtp4c_write(tech_pvt->rtp_session, frame->data, (int)frame->datalen, samples); jrtp4c_write(tech_pvt->rtp_session, frame->data, (int) frame->datalen, samples);
tech_pvt->timestamp_send += (int)samples; tech_pvt->timestamp_send += (int) samples;
switch_clear_flag(tech_pvt, TFLAG_WRITING); switch_clear_flag(tech_pvt, TFLAG_WRITING);
//switch_mutex_unlock(tech_pvt->rtp_lock); //switch_mutex_unlock(tech_pvt->rtp_lock);
@ -700,39 +710,39 @@ static switch_status exosip_waitfor_write(switch_core_session *session, int ms,
} }
static const switch_io_routines exosip_io_routines = { static const switch_io_routines exosip_io_routines = {
/*.outgoing_channel*/ exosip_outgoing_channel, /*.outgoing_channel */ exosip_outgoing_channel,
/*.answer_channel*/ exosip_answer_channel, /*.answer_channel */ exosip_answer_channel,
/*.read_frame*/ exosip_read_frame, /*.read_frame */ exosip_read_frame,
/*.write_frame*/ exosip_write_frame, /*.write_frame */ exosip_write_frame,
/*.kill_channel*/ exosip_kill_channel, /*.kill_channel */ exosip_kill_channel,
/*.waitfor_read*/ exosip_waitfor_read, /*.waitfor_read */ exosip_waitfor_read,
/*.waitfor_read*/ exosip_waitfor_write /*.waitfor_read */ exosip_waitfor_write
}; };
static const switch_event_handler_table exosip_event_handlers = { static const switch_event_handler_table exosip_event_handlers = {
/*.on_init*/ exosip_on_init, /*.on_init */ exosip_on_init,
/*.on_ring*/ exosip_on_ring, /*.on_ring */ exosip_on_ring,
/*.on_execute*/ exosip_on_execute, /*.on_execute */ exosip_on_execute,
/*.on_hangup*/ exosip_on_hangup, /*.on_hangup */ exosip_on_hangup,
/*.on_loopback*/ exosip_on_loopback, /*.on_loopback */ exosip_on_loopback,
/*.on_transmit*/ exosip_on_transmit /*.on_transmit */ exosip_on_transmit
}; };
static const switch_endpoint_interface exosip_endpoint_interface = { static const switch_endpoint_interface exosip_endpoint_interface = {
/*.interface_name*/ "exosip", /*.interface_name */ "exosip",
/*.io_routines*/ &exosip_io_routines, /*.io_routines */ &exosip_io_routines,
/*.event_handlers*/ &exosip_event_handlers, /*.event_handlers */ &exosip_event_handlers,
/*.private*/ NULL, /*.private */ NULL,
/*.next*/ NULL /*.next */ NULL
}; };
static const switch_loadable_module_interface exosip_module_interface = { static const switch_loadable_module_interface exosip_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ &exosip_endpoint_interface, /*.endpoint_interface */ &exosip_endpoint_interface,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
#if 1 #if 1
@ -740,14 +750,15 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
{ {
if (globals.running) { if (globals.running) {
globals.running = -1; globals.running = -1;
while(globals.running) { while (globals.running) {
switch_yield(100000); switch_yield(100000);
} }
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
#endif #endif
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
/* NOTE: **interface is **_interface because the common lib redefines interface to struct in some situations */ /* NOTE: **interface is **_interface because the common lib redefines interface to struct in some situations */
if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) { if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
@ -762,7 +773,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status exosip_create_call(eXosip_event_t *event) static switch_status exosip_create_call(eXosip_event_t * event)
{ {
switch_core_session *session; switch_core_session *session;
sdp_message_t *remote_sdp = NULL; sdp_message_t *remote_sdp = NULL;
@ -794,14 +805,12 @@ static switch_status exosip_create_call(eXosip_event_t *event)
} }
if ((tech_pvt->caller_profile = switch_caller_profile_new(session, if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan, globals.dialplan,
event->request->from->displayname, event->request->from->displayname,
event->request->from->url->username, event->request->from->url->username,
event->request->from->url->host, event->request->from->url->host,
NULL, NULL, NULL, event->request->req_uri->username))) {
NULL, switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
event->request->req_uri->username))) {
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
} }
switch_set_flag(tech_pvt, TFLAG_INBOUND); switch_set_flag(tech_pvt, TFLAG_INBOUND);
@ -824,14 +833,17 @@ static switch_status exosip_create_call(eXosip_event_t *event)
osip_rfc3264_init(&tech_pvt->sdp_config); osip_rfc3264_init(&tech_pvt->sdp_config);
/* Add in what codecs we support locally */ /* Add in what codecs we support locally */
if ((num_codecs = switch_loadable_module_get_codecs(switch_core_session_get_pool(session), codecs, sizeof(codecs)/sizeof(codecs[0]))) > 0) { if ((num_codecs =
switch_loadable_module_get_codecs(switch_core_session_get_pool(session), codecs,
sizeof(codecs) / sizeof(codecs[0]))) > 0) {
int i; int i;
static const switch_codec_implementation *imp; static const switch_codec_implementation *imp;
for (i = 0; i < num_codecs; i++) { for (i = 0; i < num_codecs; i++) {
int x = 0; int x = 0;
for (imp = codecs[i]->implementations ; imp ; imp = imp->next) { for (imp = codecs[i]->implementations; imp; imp = imp->next) {
sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame, imp->samples_per_second, x++); sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame,
imp->samples_per_second, x++);
} }
} }
} }
@ -840,17 +852,18 @@ static switch_status exosip_create_call(eXosip_event_t *event)
sdp_message_parse(tech_pvt->local_sdp, local_sdp_str); sdp_message_parse(tech_pvt->local_sdp, local_sdp_str);
sdp_message_to_str(remote_sdp, &remote_sdp_str); sdp_message_to_str(remote_sdp, &remote_sdp_str);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "LOCAL SDP:\n%s\nREMOTE SDP:\n%s", local_sdp_str,remote_sdp_str); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "LOCAL SDP:\n%s\nREMOTE SDP:\n%s", local_sdp_str, remote_sdp_str);
mline = 0; mline = 0;
while (0==osip_rfc3264_match(tech_pvt->sdp_config, remote_sdp, audio_tab, video_tab, t38_tab, app_tab, mline)) { while (0 == osip_rfc3264_match(tech_pvt->sdp_config, remote_sdp, audio_tab, video_tab, t38_tab, app_tab, mline)) {
if (audio_tab[0] == NULL && video_tab[0] == NULL && t38_tab[0] == NULL && app_tab[0] == NULL) { if (audio_tab[0] == NULL && video_tab[0] == NULL && t38_tab[0] == NULL && app_tab[0] == NULL) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Got no compatible codecs!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Got no compatible codecs!\n");
break; break;
} }
for (pos=0; audio_tab[pos]!=NULL; pos++) { for (pos = 0; audio_tab[pos] != NULL; pos++) {
osip_rfc3264_complete_answer(tech_pvt->sdp_config, remote_sdp, tech_pvt->local_sdp, audio_tab[pos], mline); osip_rfc3264_complete_answer(tech_pvt->sdp_config, remote_sdp, tech_pvt->local_sdp, audio_tab[pos],
mline);
if (parse_sdp_media(audio_tab[pos], &dname, &drate, &dpayload) == SWITCH_STATUS_SUCCESS) { if (parse_sdp_media(audio_tab[pos], &dname, &drate, &dpayload) == SWITCH_STATUS_SUCCESS) {
tech_pvt->payload_num = atoi(dpayload); tech_pvt->payload_num = atoi(dpayload);
break; break;
@ -859,7 +872,8 @@ static switch_status exosip_create_call(eXosip_event_t *event)
mline++; mline++;
} }
free(remote_sdp_str); free(remote_sdp_str);
sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4", tech_pvt->local_sdp_audio_ip); sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4",
tech_pvt->local_sdp_audio_ip);
sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call"); sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call");
sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL); sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL);
snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port); snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port);
@ -887,34 +901,33 @@ static switch_status exosip_create_call(eXosip_event_t *event)
int rate = atoi(drate); int rate = atoi(drate);
if (switch_core_codec_init(&tech_pvt->read_codec, if (switch_core_codec_init(&tech_pvt->read_codec,
dname, dname,
rate, rate,
globals.codec_ms, globals.codec_ms,
1, 1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel);
return SWITCH_STATUS_FALSE;
} else {
if (switch_core_codec_init(&tech_pvt->write_codec,
dname,
rate,
globals.codec_ms,
1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} else {
if (switch_core_codec_init(&tech_pvt->write_codec,
dname,
rate,
globals.codec_ms,
1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel);
return SWITCH_STATUS_FALSE;
} else { } else {
int ms; int ms;
tech_pvt->read_frame.rate = rate; tech_pvt->read_frame.rate = rate;
switch_set_flag(tech_pvt, TFLAG_USING_CODEC); switch_set_flag(tech_pvt, TFLAG_USING_CODEC);
ms = tech_pvt->write_codec.implementation->microseconds_per_frame / 1000; ms = tech_pvt->write_codec.implementation->microseconds_per_frame / 1000;
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Inbound Codec %s/%d %d ms\n", dname, rate, ms); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Inbound Codec %s/%d %d ms\n", dname, rate,
ms);
tech_pvt->read_frame.codec = &tech_pvt->read_codec; tech_pvt->read_frame.codec = &tech_pvt->read_codec;
switch_core_session_set_read_codec(session, &tech_pvt->read_codec); switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
switch_core_session_set_write_codec(session, &tech_pvt->write_codec); switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
@ -939,13 +952,14 @@ static switch_status exosip_create_call(eXosip_event_t *event)
} }
static void destroy_call_by_event(eXosip_event_t *event) static void destroy_call_by_event(eXosip_event_t * event)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel = NULL; switch_channel *channel = NULL;
if (!(tech_pvt = get_pvt_by_call_id(event->cid))) { if (!(tech_pvt = get_pvt_by_call_id(event->cid))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Um in case you are interested, Can't find the pvt [%d]!\n", event->cid); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Um in case you are interested, Can't find the pvt [%d]!\n",
event->cid);
return; return;
} }
@ -958,7 +972,7 @@ static void destroy_call_by_event(eXosip_event_t *event)
} }
static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **drate, char **dpayload) static switch_status parse_sdp_media(sdp_media_t * media, char **dname, char **drate, char **dpayload)
{ {
int pos = 0; int pos = 0;
sdp_attribute_t *attr = NULL; sdp_attribute_t *attr = NULL;
@ -966,7 +980,7 @@ static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **dr
switch_status status = SWITCH_STATUS_GENERR; switch_status status = SWITCH_STATUS_GENERR;
while (osip_list_eol(media->a_attributes, pos) == 0) { while (osip_list_eol(media->a_attributes, pos) == 0) {
attr = (sdp_attribute_t *)osip_list_get(media->a_attributes, pos); attr = (sdp_attribute_t *) osip_list_get(media->a_attributes, pos);
if (attr != NULL && strcasecmp(attr->a_att_field, "rtpmap") == 0) { if (attr != NULL && strcasecmp(attr->a_att_field, "rtpmap") == 0) {
payload = attr->a_att_value; payload = attr->a_att_value;
if ((name = strchr(payload, ' '))) { if ((name = strchr(payload, ' '))) {
@ -987,7 +1001,8 @@ static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **dr
*dname = strdup("L16"); *dname = strdup("L16");
*drate = strdup("8000"); *drate = strdup("8000");
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Found negotiated codec Payload: %s Name: %s Rate: %s\n", *dpayload, *dname, *drate); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Found negotiated codec Payload: %s Name: %s Rate: %s\n",
*dpayload, *dname, *drate);
break; break;
} }
attr = NULL; attr = NULL;
@ -997,7 +1012,7 @@ static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **dr
return status; return status;
} }
static void handle_answer(eXosip_event_t *event) static void handle_answer(eXosip_event_t * event)
{ {
osip_message_t *ack = NULL; osip_message_t *ack = NULL;
sdp_message_t *remote_sdp = NULL; sdp_message_t *remote_sdp = NULL;
@ -1052,28 +1067,27 @@ static void handle_answer(eXosip_event_t *event)
if (switch_core_codec_init(&tech_pvt->read_codec, if (switch_core_codec_init(&tech_pvt->read_codec,
dname, dname,
rate, rate,
globals.codec_ms, globals.codec_ms,
1, 1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel);
return;
} else {
if (switch_core_codec_init(&tech_pvt->write_codec,
dname,
rate,
globals.codec_ms,
1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL,
switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return; return;
} else {
if (switch_core_codec_init(&tech_pvt->write_codec,
dname,
rate,
globals.codec_ms,
1,
SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE,
NULL,
switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel);
return;
} else { } else {
int ms; int ms;
tech_pvt->read_frame.rate = rate; tech_pvt->read_frame.rate = rate;
@ -1107,133 +1121,119 @@ static void handle_answer(eXosip_event_t *event)
} }
} }
static void log_event(eXosip_event_t *je) static void log_event(eXosip_event_t * je)
{ {
char buf[100]; char buf[100];
buf[0] = '\0'; buf[0] = '\0';
if (je->type == EXOSIP_CALL_NOANSWER) { if (je->type == EXOSIP_CALL_NOANSWER) {
snprintf (buf, 99, "<- (%i %i) No answer", je->cid, je->did); snprintf(buf, 99, "<- (%i %i) No answer", je->cid, je->did);
} else if (je->type == EXOSIP_CALL_CLOSED) { } else if (je->type == EXOSIP_CALL_CLOSED) {
snprintf (buf, 99, "<- (%i %i) Call Closed", je->cid, je->did); snprintf(buf, 99, "<- (%i %i) Call Closed", je->cid, je->did);
} else if (je->type == EXOSIP_CALL_RELEASED) { } else if (je->type == EXOSIP_CALL_RELEASED) {
snprintf (buf, 99, "<- (%i %i) Call released", je->cid, je->did); snprintf(buf, 99, "<- (%i %i) Call released", je->cid, je->did);
} else if (je->type == EXOSIP_MESSAGE_NEW } else if (je->type == EXOSIP_MESSAGE_NEW && je->request != NULL && MSG_IS_MESSAGE(je->request)) {
&& je->request!=NULL && MSG_IS_MESSAGE(je->request)) { char *tmp = NULL;
char *tmp = NULL;
if (je->request != NULL) { if (je->request != NULL) {
osip_body_t *body; osip_body_t *body;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
osip_message_get_body (je->request, 0, &body); osip_message_get_body(je->request, 0, &body);
if (body != NULL && body->body != NULL) { if (body != NULL && body->body != NULL) {
snprintf (buf, 99, "<- (%i) from: %s TEXT: %s", snprintf(buf, 99, "<- (%i) from: %s TEXT: %s", je->tid, tmp, body->body);
je->tid, tmp, body->body);
}
osip_free (tmp);
} else {
snprintf (buf, 99, "<- (%i) New event for unknown request?", je->tid);
} }
osip_free(tmp);
} else {
snprintf(buf, 99, "<- (%i) New event for unknown request?", je->tid);
}
} else if (je->type == EXOSIP_MESSAGE_NEW) { } else if (je->type == EXOSIP_MESSAGE_NEW) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i) %s from: %s", snprintf(buf, 99, "<- (%i) %s from: %s", je->tid, je->request->sip_method, tmp);
je->tid, je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->type == EXOSIP_MESSAGE_PROCEEDING } else if (je->type == EXOSIP_MESSAGE_PROCEEDING
|| je->type == EXOSIP_MESSAGE_ANSWERED || je->type == EXOSIP_MESSAGE_ANSWERED
|| je->type == EXOSIP_MESSAGE_REDIRECTED || je->type == EXOSIP_MESSAGE_REDIRECTED
|| je->type == EXOSIP_MESSAGE_REQUESTFAILURE || je->type == EXOSIP_MESSAGE_REQUESTFAILURE
|| je->type == EXOSIP_MESSAGE_SERVERFAILURE || je->type == EXOSIP_MESSAGE_SERVERFAILURE || je->type == EXOSIP_MESSAGE_GLOBALFAILURE) {
|| je->type == EXOSIP_MESSAGE_GLOBALFAILURE) { if (je->response != NULL && je->request != NULL) {
if (je->response != NULL && je->request != NULL) { char *tmp = NULL;
char *tmp = NULL;
osip_to_to_str (je->request->to, &tmp); osip_to_to_str(je->request->to, &tmp);
snprintf (buf, 99, "<- (%i) [%i %s for %s] to: %s", snprintf(buf, 99, "<- (%i) [%i %s for %s] to: %s",
je->tid, je->response->status_code, je->tid, je->response->status_code, je->response->reason_phrase, je->request->sip_method, tmp);
je->response->reason_phrase, je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp); } else if (je->request != NULL) {
} else if (je->request != NULL) { snprintf(buf, 99, "<- (%i) Error for %s request", je->tid, je->request->sip_method);
snprintf (buf, 99, "<- (%i) Error for %s request", } else {
je->tid, je->request->sip_method); snprintf(buf, 99, "<- (%i) Error for unknown request", je->tid);
} else { }
snprintf (buf, 99, "<- (%i) Error for unknown request", je->tid);
}
} else if (je->response == NULL && je->request != NULL && je->cid > 0) { } else if (je->response == NULL && je->request != NULL && je->cid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i %i) %s from: %s", snprintf(buf, 99, "<- (%i %i) %s from: %s", je->cid, je->did, je->request->cseq->method, tmp);
je->cid, je->did, je->request->cseq->method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL && je->cid > 0) { } else if (je->response != NULL && je->cid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_to_to_str (je->request->to, &tmp); osip_to_to_str(je->request->to, &tmp);
snprintf (buf, 99, "<- (%i %i) [%i %s] for %s to: %s", snprintf(buf, 99, "<- (%i %i) [%i %s] for %s to: %s",
je->cid, je->did, je->response->status_code, je->cid, je->did, je->response->status_code,
je->response->reason_phrase, je->request->sip_method, tmp); je->response->reason_phrase, je->request->sip_method, tmp);
osip_free (tmp); osip_free(tmp);
} else if (je->response == NULL && je->request != NULL && je->rid > 0) { } else if (je->response == NULL && je->request != NULL && je->rid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i) %s from: %s", snprintf(buf, 99, "<- (%i) %s from: %s", je->rid, je->request->cseq->method, tmp);
je->rid, je->request->cseq->method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL && je->rid > 0) { } else if (je->response != NULL && je->rid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i) [%i %s] from: %s", snprintf(buf, 99, "<- (%i) [%i %s] from: %s",
je->rid, je->response->status_code, je->rid, je->response->status_code, je->response->reason_phrase, tmp);
je->response->reason_phrase, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response == NULL && je->request != NULL && je->sid > 0) { } else if (je->response == NULL && je->request != NULL && je->sid > 0) {
char *tmp = NULL; char *tmp = NULL;
char *stat = NULL; char *stat = NULL;
osip_header_t *sub_state; osip_header_t *sub_state;
osip_message_header_get_byname (je->request, "subscription-state", osip_message_header_get_byname(je->request, "subscription-state", 0, &sub_state);
0, &sub_state);
if (sub_state != NULL && sub_state->hvalue != NULL) if (sub_state != NULL && sub_state->hvalue != NULL)
stat = sub_state->hvalue; stat = sub_state->hvalue;
osip_uri_to_str (je->request->from->url, &tmp); osip_uri_to_str(je->request->from->url, &tmp);
snprintf (buf, 99, "<- (%i) [%s] %s from: %s", snprintf(buf, 99, "<- (%i) [%s] %s from: %s", je->sid, stat, je->request->cseq->method, tmp);
je->sid, stat, je->request->cseq->method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL && je->sid > 0) { } else if (je->response != NULL && je->sid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_uri_to_str (je->request->to->url, &tmp); osip_uri_to_str(je->request->to->url, &tmp);
snprintf (buf, 99, "<- (%i) [%i %s] from: %s", snprintf(buf, 99, "<- (%i) [%i %s] from: %s",
je->sid, je->response->status_code, je->sid, je->response->status_code, je->response->reason_phrase, tmp);
je->response->reason_phrase, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response == NULL && je->request != NULL) { } else if (je->response == NULL && je->request != NULL) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) %s from: %s", snprintf(buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) %s from: %s",
je->cid, je->did, je->sid, je->nid, je->cid, je->did, je->sid, je->nid, je->request->sip_method, tmp);
je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL) { } else if (je->response != NULL) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) [%i %s] for %s from: %s", snprintf(buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) [%i %s] for %s from: %s",
je->cid, je->did, je->sid, je->nid, je->cid, je->did, je->sid, je->nid,
je->response->status_code, je->response->reason_phrase, je->response->status_code, je->response->reason_phrase, je->request->sip_method, tmp);
je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else { } else {
snprintf (buf, 99, "<- (c=%i|d=%i|s=%i|n=%i|t=%i) %s", snprintf(buf, 99, "<- (c=%i|d=%i|s=%i|n=%i|t=%i) %s",
je->cid, je->did, je->sid, je->nid, je->tid, je->textinfo); je->cid, je->did, je->sid, je->nid, je->tid, je->textinfo);
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\n%s\n", buf); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\n%s\n", buf);
/* Print it out */ /* Print it out */
@ -1307,88 +1307,88 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
config_exosip(0); config_exosip(0);
if (eXosip_init ()) { if (eXosip_init()) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_init initialization failed!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_init initialization failed!\n");
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }
if (eXosip_listen_addr (IPPROTO_UDP, NULL, globals.port, AF_INET, 0)) { if (eXosip_listen_addr(IPPROTO_UDP, NULL, globals.port, AF_INET, 0)) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_listen_addr failed!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_listen_addr failed!\n");
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }
globals.running = 1; globals.running = 1;
while (globals.running > 0) { while (globals.running > 0) {
if (!(event = eXosip_event_wait(0,100))) { if (!(event = eXosip_event_wait(0, 100))) {
switch_yield(1000); switch_yield(1000);
continue; continue;
} }
eXosip_lock(); eXosip_lock();
eXosip_automatic_action (); eXosip_automatic_action();
eXosip_unlock(); eXosip_unlock();
log_event(event); log_event(event);
switch(event->type) { switch (event->type) {
case EXOSIP_CALL_INVITE: case EXOSIP_CALL_INVITE:
exosip_create_call(event); exosip_create_call(event);
break; break;
case EXOSIP_CALL_REINVITE: case EXOSIP_CALL_REINVITE:
/* See what the reinvite is about - on hold or whatever */ /* See what the reinvite is about - on hold or whatever */
//handle_reinvite(event); //handle_reinvite(event);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Got a reinvite.\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Got a reinvite.\n");
break; break;
case EXOSIP_CALL_MESSAGE_NEW: case EXOSIP_CALL_MESSAGE_NEW:
if (event->request != NULL && MSG_IS_REFER(event->request)) { if (event->request != NULL && MSG_IS_REFER(event->request)) {
//handle_call_transfer(event); //handle_call_transfer(event);
} }
break; break;
case EXOSIP_CALL_ACK: case EXOSIP_CALL_ACK:
/* If audio is not flowing and this has SDP - fire it up! */ /* If audio is not flowing and this has SDP - fire it up! */
break; break;
case EXOSIP_CALL_ANSWERED: case EXOSIP_CALL_ANSWERED:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "The call was answered.\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "The call was answered.\n");
handle_answer(event); handle_answer(event);
break; break;
case EXOSIP_CALL_PROCEEDING: case EXOSIP_CALL_PROCEEDING:
/* This is like a 100 Trying... yeah */ /* This is like a 100 Trying... yeah */
break; break;
case EXOSIP_CALL_RINGING: case EXOSIP_CALL_RINGING:
//handle_ringing(event); //handle_ringing(event);
break; break;
case EXOSIP_CALL_REDIRECTED: case EXOSIP_CALL_REDIRECTED:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Call was redirect\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Call was redirect\n");
break; break;
case EXOSIP_CALL_CLOSED: case EXOSIP_CALL_CLOSED:
destroy_call_by_event(event); destroy_call_by_event(event);
break; break;
case EXOSIP_CALL_RELEASED: case EXOSIP_CALL_RELEASED:
destroy_call_by_event(event); destroy_call_by_event(event);
break; break;
case EXOSIP_CALL_NOANSWER: case EXOSIP_CALL_NOANSWER:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "The call was not answered.\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "The call was not answered.\n");
destroy_call_by_event(event); destroy_call_by_event(event);
break; break;
case EXOSIP_CALL_REQUESTFAILURE: case EXOSIP_CALL_REQUESTFAILURE:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Request failure\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Request failure\n");
destroy_call_by_event(event); destroy_call_by_event(event);
break; break;
case EXOSIP_CALL_SERVERFAILURE: case EXOSIP_CALL_SERVERFAILURE:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Server failure\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Server failure\n");
destroy_call_by_event(event); destroy_call_by_event(event);
break; break;
case EXOSIP_CALL_GLOBALFAILURE: case EXOSIP_CALL_GLOBALFAILURE:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Global failure\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Global failure\n");
destroy_call_by_event(event); destroy_call_by_event(event);
break; break;
/* Registration related stuff */ /* Registration related stuff */
case EXOSIP_REGISTRATION_NEW: case EXOSIP_REGISTRATION_NEW:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Received registration attempt\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Received registration attempt\n");
break; break;
default: default:
/* Unknown event... casually absorb it for now */ /* Unknown event... casually absorb it for now */
break; break;
} }
//switch_console_printf(SWITCH_CHANNEL_CONSOLE, "There was an event (%d) [%s]\n", event->type, event->textinfo); //switch_console_printf(SWITCH_CHANNEL_CONSOLE, "There was an event (%d) [%s]\n", event->type, event->textinfo);
@ -1399,8 +1399,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
eXosip_quit(); eXosip_quit();
globals.running = 0; globals.running = 0;
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Monitor Thread Exiting\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Monitor Thread Exiting\n");
//switch_sleep(2000000); //switch_sleep(2000000);
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }

View File

@ -145,11 +145,14 @@ static switch_status exosip_on_init(switch_core_session *session);
static switch_status exosip_on_hangup(switch_core_session *session); static switch_status exosip_on_hangup(switch_core_session *session);
static switch_status exosip_on_loopback(switch_core_session *session); static switch_status exosip_on_loopback(switch_core_session *session);
static switch_status exosip_on_transmit(switch_core_session *session); static switch_status exosip_on_transmit(switch_core_session *session);
static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session); static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags); switch_core_session **new_session);
static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags); static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags);
static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags);
static int config_exosip(int reload); static int config_exosip(int reload);
static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **drate, char **dpayload); static switch_status parse_sdp_media(sdp_media_t * media, char **dname, char **drate, char **dpayload);
static switch_status exosip_kill_channel(switch_core_session *session, int sig); static switch_status exosip_kill_channel(switch_core_session *session, int sig);
static void activate_rtp(struct private_object *tech_pvt); static void activate_rtp(struct private_object *tech_pvt);
static void deactivate_rtp(struct private_object *tech_pvt); static void deactivate_rtp(struct private_object *tech_pvt);
@ -202,7 +205,7 @@ static int sdp_add_codec(struct osip_rfc3264 *cnf, int codec_type, int payload,
default: default:
break; break;
} }
return 0; return 0;
} }
@ -232,7 +235,7 @@ static switch_status exosip_on_init(switch_core_session *session)
char *dest_uri; char *dest_uri;
switch_codec_interface *codecs[512]; switch_codec_interface *codecs[512];
int num_codecs = 0; int num_codecs = 0;
/* do SIP Goodies...*/ /* do SIP Goodies... */
/* Generate callerid URI */ /* Generate callerid URI */
eXosip_guess_localip(AF_INET, localip, 128); eXosip_guess_localip(AF_INET, localip, 128);
@ -245,14 +248,17 @@ static switch_status exosip_on_init(switch_core_session *session)
/* Initialize SDP */ /* Initialize SDP */
sdp_message_init(&tech_pvt->local_sdp); sdp_message_init(&tech_pvt->local_sdp);
sdp_message_v_version_set(tech_pvt->local_sdp, "0"); sdp_message_v_version_set(tech_pvt->local_sdp, "0");
sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4", tech_pvt->local_sdp_audio_ip); sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4",
tech_pvt->local_sdp_audio_ip);
sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call"); sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call");
sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL); sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL);
sdp_message_t_time_descr_add(tech_pvt->local_sdp, "0", "0"); sdp_message_t_time_descr_add(tech_pvt->local_sdp, "0", "0");
snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port); snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port);
sdp_message_m_media_add(tech_pvt->local_sdp, "audio", port, NULL, "RTP/AVP"); sdp_message_m_media_add(tech_pvt->local_sdp, "audio", port, NULL, "RTP/AVP");
/* Add in every codec we support on this outbound call */ /* Add in every codec we support on this outbound call */
if ((num_codecs = loadable_module_get_codecs(switch_core_session_get_pool(session), codecs, sizeof(codecs)/sizeof(codecs[0]))) > 0) { if ((num_codecs =
loadable_module_get_codecs(switch_core_session_get_pool(session), codecs,
sizeof(codecs) / sizeof(codecs[0]))) > 0) {
int i; int i;
static const switch_codec_implementation *imp; static const switch_codec_implementation *imp;
for (i = 0; i < num_codecs; i++) { for (i = 0; i < num_codecs; i++) {
@ -260,12 +266,14 @@ static switch_status exosip_on_init(switch_core_session *session)
snprintf(tmp, sizeof(tmp), "%i", codecs[i]->ianacode); snprintf(tmp, sizeof(tmp), "%i", codecs[i]->ianacode);
sdp_message_m_payload_add(tech_pvt->local_sdp, 0, osip_strdup(tmp)); sdp_message_m_payload_add(tech_pvt->local_sdp, 0, osip_strdup(tmp));
for (imp = codecs[i]->implementations ; imp ; imp = imp->next) { for (imp = codecs[i]->implementations; imp; imp = imp->next) {
/* Add to SDP config */ /* Add to SDP config */
sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame, imp->samples_per_second, x++); sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame,
imp->samples_per_second, x++);
/* Add to SDP message */ /* Add to SDP message */
snprintf(tmp, sizeof(tmp), "%i %s/%i", codecs[i]->ianacode, codecs[i]->iananame, imp->samples_per_second); snprintf(tmp, sizeof(tmp), "%i %s/%i", codecs[i]->ianacode, codecs[i]->iananame,
imp->samples_per_second);
sdp_message_a_attribute_add(tech_pvt->local_sdp, 0, "rtpmap", osip_strdup(tmp)); sdp_message_a_attribute_add(tech_pvt->local_sdp, 0, "rtpmap", osip_strdup(tmp));
memset(tmp, 0, sizeof(tmp)); memset(tmp, 0, sizeof(tmp));
} }
@ -273,7 +281,9 @@ static switch_status exosip_on_init(switch_core_session *session)
} }
/* Setup our INVITE */ /* Setup our INVITE */
eXosip_lock(); eXosip_lock();
if (!(dest_uri = (char *) switch_core_session_alloc(session, strlen(tech_pvt->caller_profile->destination_number) + 10))) { if (!
(dest_uri =
(char *) switch_core_session_alloc(session, strlen(tech_pvt->caller_profile->destination_number) + 10))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "AIEEEE!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "AIEEEE!\n");
assert(dest_uri != NULL); assert(dest_uri != NULL);
} }
@ -346,7 +356,8 @@ static switch_status exosip_on_hangup(switch_core_session *session)
switch_core_codec_destroy(&tech_pvt->write_codec); switch_core_codec_destroy(&tech_pvt->write_codec);
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "EXOSIP HANGUP %s %d/%d=%d\n", switch_channel_get_name(channel), tech_pvt->cid, tech_pvt->did, i); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "EXOSIP HANGUP %s %d/%d=%d\n", switch_channel_get_name(channel),
tech_pvt->cid, tech_pvt->did, i);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -362,7 +373,8 @@ static switch_status exosip_on_transmit(switch_core_session *session)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session) static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
switch_core_session **new_session)
{ {
if ((*new_session = switch_core_session_request(&exosip_endpoint_interface, NULL))) { if ((*new_session = switch_core_session_request(&exosip_endpoint_interface, NULL))) {
struct private_object *tech_pvt; struct private_object *tech_pvt;
@ -370,7 +382,8 @@ static switch_status exosip_outgoing_channel(switch_core_session *session, switc
switch_caller_profile *caller_profile, *originator_caller_profile = NULL; switch_caller_profile *caller_profile, *originator_caller_profile = NULL;
switch_core_session_add_stream(*new_session, NULL); switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) { if ((tech_pvt =
(struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt)); memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(*new_session); channel = switch_core_session_get_channel(*new_session);
switch_core_session_set_private(*new_session, tech_pvt); switch_core_session_set_private(*new_session, tech_pvt);
@ -421,7 +434,7 @@ static void deactivate_rtp(struct private_object *tech_pvt)
if (tech_pvt->rtp_session) { if (tech_pvt->rtp_session) {
//switch_mutex_lock(tech_pvt->rtp_lock); //switch_mutex_lock(tech_pvt->rtp_lock);
while(loops < 10 && (switch_test_flag(tech_pvt, TFLAG_READING) || switch_test_flag(tech_pvt, TFLAG_WRITING))) { while (loops < 10 && (switch_test_flag(tech_pvt, TFLAG_READING) || switch_test_flag(tech_pvt, TFLAG_WRITING))) {
switch_yield(10000); switch_yield(10000);
loops++; loops++;
} }
@ -457,22 +470,16 @@ static void activate_rtp(struct private_object *tech_pvt)
tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_audio_ip,
tech_pvt->local_sdp_audio_port, tech_pvt->local_sdp_audio_port,
tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip,
tech_pvt->remote_sdp_audio_port, tech_pvt->remote_sdp_audio_port, tech_pvt->read_codec.codec_interface->ianacode, ms);
tech_pvt->read_codec.codec_interface->ianacode,
ms
);
tech_pvt->rtp_session = ccrtp4c_new( tech_pvt->rtp_session = ccrtp4c_new(tech_pvt->local_sdp_audio_ip,
tech_pvt->local_sdp_audio_ip,
tech_pvt->local_sdp_audio_port, tech_pvt->local_sdp_audio_port,
tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip,
tech_pvt->remote_sdp_audio_port, tech_pvt->remote_sdp_audio_port,
tech_pvt->read_codec.codec_interface->ianacode, tech_pvt->read_codec.codec_interface->ianacode, ms, ms * 15);
ms,
ms * 15);
if (tech_pvt->rtp_session) { if (tech_pvt->rtp_session) {
tech_pvt->ssrc = ccrtp4c_get_ssrc(tech_pvt->rtp_session); tech_pvt->ssrc = ccrtp4c_get_ssrc(tech_pvt->rtp_session);
@ -517,10 +524,11 @@ static switch_status exosip_answer_channel(switch_core_session *session)
} }
static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags) static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags)
{ {
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
size_t bytes = 0, samples = 0, frames=0, ms=0; size_t bytes = 0, samples = 0, frames = 0, ms = 0;
switch_channel *channel = NULL; switch_channel *channel = NULL;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
@ -547,11 +555,10 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
assert(tech_pvt->rtp_session != NULL); assert(tech_pvt->rtp_session != NULL);
tech_pvt->read_frame.datalen = 0; tech_pvt->read_frame.datalen = 0;
while(!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO) && tech_pvt->read_frame.datalen == 0) { while (!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO)
&& tech_pvt->read_frame.datalen == 0) {
if ((tech_pvt->read_frame.datalen = if ((tech_pvt->read_frame.datalen =
ccrtp4c_read(tech_pvt->rtp_session, ccrtp4c_read(tech_pvt->rtp_session, tech_pvt->read_frame.data, sizeof(tech_pvt->read_buf),
tech_pvt->read_frame.data,
sizeof(tech_pvt->read_buf),
&tech_pvt->timestamp_recv))) { &tech_pvt->timestamp_recv))) {
bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame; bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
frames = (tech_pvt->read_frame.datalen / bytes); frames = (tech_pvt->read_frame.datalen / bytes);
@ -587,12 +594,13 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
} }
static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags) static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel = NULL; switch_channel *channel = NULL;
switch_status status = SWITCH_STATUS_SUCCESS; switch_status status = SWITCH_STATUS_SUCCESS;
int bytes=0, samples=0, ms=0, frames=0; int bytes = 0, samples = 0, ms = 0, frames = 0;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
assert(channel != NULL); assert(channel != NULL);
@ -628,7 +636,7 @@ static switch_status exosip_write_frame(switch_core_session *session, switch_fra
//printf("%s %s->%s send %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip, frame->datalen, samples, frames, ms, tech_pvt->timestamp_send); //printf("%s %s->%s send %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip, frame->datalen, samples, frames, ms, tech_pvt->timestamp_send);
tech_pvt->timestamp_send += (int)samples; tech_pvt->timestamp_send += (int) samples;
ccrtp4c_write(tech_pvt->rtp_session, frame->data, frame->datalen, &tech_pvt->timestamp_send); ccrtp4c_write(tech_pvt->rtp_session, frame->data, frame->datalen, &tech_pvt->timestamp_send);
@ -691,39 +699,39 @@ static switch_status exosip_waitfor_write(switch_core_session *session, int ms)
} }
static const switch_io_routines exosip_io_routines = { static const switch_io_routines exosip_io_routines = {
/*.outgoing_channel*/ exosip_outgoing_channel, /*.outgoing_channel */ exosip_outgoing_channel,
/*.answer_channel*/ exosip_answer_channel, /*.answer_channel */ exosip_answer_channel,
/*.read_frame*/ exosip_read_frame, /*.read_frame */ exosip_read_frame,
/*.write_frame*/ exosip_write_frame, /*.write_frame */ exosip_write_frame,
/*.kill_channel*/ exosip_kill_channel, /*.kill_channel */ exosip_kill_channel,
/*.waitfor_read*/ exosip_waitfor_read, /*.waitfor_read */ exosip_waitfor_read,
/*.waitfor_read*/ exosip_waitfor_write /*.waitfor_read */ exosip_waitfor_write
}; };
static const switch_event_handler_table exosip_event_handlers = { static const switch_event_handler_table exosip_event_handlers = {
/*.on_init*/ exosip_on_init, /*.on_init */ exosip_on_init,
/*.on_ring*/ exosip_on_ring, /*.on_ring */ exosip_on_ring,
/*.on_execute*/ exosip_on_execute, /*.on_execute */ exosip_on_execute,
/*.on_hangup*/ exosip_on_hangup, /*.on_hangup */ exosip_on_hangup,
/*.on_loopback*/ exosip_on_loopback, /*.on_loopback */ exosip_on_loopback,
/*.on_transmit*/ exosip_on_transmit /*.on_transmit */ exosip_on_transmit
}; };
static const switch_endpoint_interface exosip_endpoint_interface = { static const switch_endpoint_interface exosip_endpoint_interface = {
/*.interface_name*/ "exosip", /*.interface_name */ "exosip",
/*.io_routines*/ &exosip_io_routines, /*.io_routines */ &exosip_io_routines,
/*.event_handlers*/ &exosip_event_handlers, /*.event_handlers */ &exosip_event_handlers,
/*.private*/ NULL, /*.private */ NULL,
/*.next*/ NULL /*.next */ NULL
}; };
static const switch_loadable_module_interface exosip_module_interface = { static const switch_loadable_module_interface exosip_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ &exosip_endpoint_interface, /*.endpoint_interface */ &exosip_endpoint_interface,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
@ -731,7 +739,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
{ {
if (globals.running) { if (globals.running) {
globals.running = -1; globals.running = -1;
while(globals.running) { while (globals.running) {
switch_yield(1000); switch_yield(1000);
} }
} }
@ -739,7 +747,8 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
/* NOTE: **interface is **_interface because the common lib redefines interface to struct in some situations */ /* NOTE: **interface is **_interface because the common lib redefines interface to struct in some situations */
if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) { if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
@ -754,7 +763,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status exosip_create_call(eXosip_event_t *event) static switch_status exosip_create_call(eXosip_event_t * event)
{ {
switch_core_session *session; switch_core_session *session;
sdp_message_t *remote_sdp = NULL; sdp_message_t *remote_sdp = NULL;
@ -786,12 +795,11 @@ static switch_status exosip_create_call(eXosip_event_t *event)
} }
if ((tech_pvt->caller_profile = switch_caller_profile_new(session, if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan, globals.dialplan,
event->request->from->displayname, event->request->from->displayname,
event->request->from->url->username, event->request->from->url->username,
event->request->from->url->username, event->request->from->url->username,
NULL, NULL, event->request->req_uri->username))) {
event->request->req_uri->username))) {
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
} }
@ -815,14 +823,17 @@ static switch_status exosip_create_call(eXosip_event_t *event)
osip_rfc3264_init(&tech_pvt->sdp_config); osip_rfc3264_init(&tech_pvt->sdp_config);
/* Add in what codecs we support locally */ /* Add in what codecs we support locally */
if ((num_codecs = loadable_module_get_codecs(switch_core_session_get_pool(session), codecs, sizeof(codecs)/sizeof(codecs[0]))) > 0) { if ((num_codecs =
loadable_module_get_codecs(switch_core_session_get_pool(session), codecs,
sizeof(codecs) / sizeof(codecs[0]))) > 0) {
int i; int i;
static const switch_codec_implementation *imp; static const switch_codec_implementation *imp;
for (i = 0; i < num_codecs; i++) { for (i = 0; i < num_codecs; i++) {
int x = 0; int x = 0;
for (imp = codecs[i]->implementations ; imp ; imp = imp->next) { for (imp = codecs[i]->implementations; imp; imp = imp->next) {
sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame, imp->samples_per_second, x++); sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame,
imp->samples_per_second, x++);
} }
} }
} }
@ -831,17 +842,18 @@ static switch_status exosip_create_call(eXosip_event_t *event)
sdp_message_parse(tech_pvt->local_sdp, local_sdp_str); sdp_message_parse(tech_pvt->local_sdp, local_sdp_str);
sdp_message_to_str(remote_sdp, &remote_sdp_str); sdp_message_to_str(remote_sdp, &remote_sdp_str);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "LOCAL SDP:\n%s\nREMOTE SDP:\n%s", local_sdp_str,remote_sdp_str); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "LOCAL SDP:\n%s\nREMOTE SDP:\n%s", local_sdp_str, remote_sdp_str);
mline = 0; mline = 0;
while (0==osip_rfc3264_match(tech_pvt->sdp_config, remote_sdp, audio_tab, video_tab, t38_tab, app_tab, mline)) { while (0 == osip_rfc3264_match(tech_pvt->sdp_config, remote_sdp, audio_tab, video_tab, t38_tab, app_tab, mline)) {
if (audio_tab[0] == NULL && video_tab[0] == NULL && t38_tab[0] == NULL && app_tab[0] == NULL) { if (audio_tab[0] == NULL && video_tab[0] == NULL && t38_tab[0] == NULL && app_tab[0] == NULL) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Got no compatible codecs!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Got no compatible codecs!\n");
break; break;
} }
for (pos=0; audio_tab[pos]!=NULL; pos++) { for (pos = 0; audio_tab[pos] != NULL; pos++) {
osip_rfc3264_complete_answer(tech_pvt->sdp_config, remote_sdp, tech_pvt->local_sdp, audio_tab[pos], mline); osip_rfc3264_complete_answer(tech_pvt->sdp_config, remote_sdp, tech_pvt->local_sdp, audio_tab[pos],
mline);
if (parse_sdp_media(audio_tab[pos], &dname, &drate, &dpayload) == SWITCH_STATUS_SUCCESS) { if (parse_sdp_media(audio_tab[pos], &dname, &drate, &dpayload) == SWITCH_STATUS_SUCCESS) {
tech_pvt->payload_num = atoi(dpayload); tech_pvt->payload_num = atoi(dpayload);
break; break;
@ -850,7 +862,8 @@ static switch_status exosip_create_call(eXosip_event_t *event)
mline++; mline++;
} }
free(remote_sdp_str); free(remote_sdp_str);
sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4", tech_pvt->local_sdp_audio_ip); sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4",
tech_pvt->local_sdp_audio_ip);
sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call"); sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call");
sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL); sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL);
snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port); snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port);
@ -878,21 +891,21 @@ static switch_status exosip_create_call(eXosip_event_t *event)
int rate = atoi(drate); int rate = atoi(drate);
if (switch_core_codec_init(&tech_pvt->read_codec, if (switch_core_codec_init(&tech_pvt->read_codec,
dname, dname,
rate, rate,
globals.codec_ms, globals.codec_ms,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) { NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} else { } else {
if (switch_core_codec_init(&tech_pvt->write_codec, if (switch_core_codec_init(&tech_pvt->write_codec,
dname, dname,
rate, rate,
globals.codec_ms, globals.codec_ms,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) { NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
@ -900,7 +913,8 @@ static switch_status exosip_create_call(eXosip_event_t *event)
int ms; int ms;
switch_set_flag(tech_pvt, TFLAG_USING_CODEC); switch_set_flag(tech_pvt, TFLAG_USING_CODEC);
ms = tech_pvt->write_codec.implementation->nanoseconds_per_frame / 1000; ms = tech_pvt->write_codec.implementation->nanoseconds_per_frame / 1000;
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Inbound Codec %s/%d %d ms\n", dname, rate, ms); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Inbound Codec %s/%d %d ms\n", dname, rate,
ms);
tech_pvt->read_frame.codec = &tech_pvt->read_codec; tech_pvt->read_frame.codec = &tech_pvt->read_codec;
switch_core_session_set_read_codec(session, &tech_pvt->read_codec); switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
switch_core_session_set_write_codec(session, &tech_pvt->write_codec); switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
@ -920,13 +934,14 @@ static switch_status exosip_create_call(eXosip_event_t *event)
} }
static void destroy_call_by_event(eXosip_event_t *event) static void destroy_call_by_event(eXosip_event_t * event)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel = NULL; switch_channel *channel = NULL;
if (!(tech_pvt = get_pvt_by_call_id(event->cid))) { if (!(tech_pvt = get_pvt_by_call_id(event->cid))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Um in case you are interested, Can't find the pvt [%d]!\n", event->cid); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Um in case you are interested, Can't find the pvt [%d]!\n",
event->cid);
return; return;
} }
@ -939,7 +954,7 @@ static void destroy_call_by_event(eXosip_event_t *event)
} }
static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **drate, char **dpayload) static switch_status parse_sdp_media(sdp_media_t * media, char **dname, char **drate, char **dpayload)
{ {
int pos = 0; int pos = 0;
sdp_attribute_t *attr = NULL; sdp_attribute_t *attr = NULL;
@ -947,7 +962,7 @@ static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **dr
switch_status status = SWITCH_STATUS_GENERR; switch_status status = SWITCH_STATUS_GENERR;
while (osip_list_eol(media->a_attributes, pos) == 0) { while (osip_list_eol(media->a_attributes, pos) == 0) {
attr = (sdp_attribute_t *)osip_list_get(media->a_attributes, pos); attr = (sdp_attribute_t *) osip_list_get(media->a_attributes, pos);
if (attr != NULL && strcasecmp(attr->a_att_field, "rtpmap") == 0) { if (attr != NULL && strcasecmp(attr->a_att_field, "rtpmap") == 0) {
payload = attr->a_att_value; payload = attr->a_att_value;
if ((name = strchr(payload, ' '))) { if ((name = strchr(payload, ' '))) {
@ -968,7 +983,8 @@ static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **dr
*dname = strdup("L16"); *dname = strdup("L16");
*drate = strdup("8000"); *drate = strdup("8000");
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Found negotiated codec Payload: %s Name: %s Rate: %s\n", *dpayload, *dname, *drate); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Found negotiated codec Payload: %s Name: %s Rate: %s\n",
*dpayload, *dname, *drate);
break; break;
} }
attr = NULL; attr = NULL;
@ -978,7 +994,7 @@ static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **dr
return status; return status;
} }
static void handle_answer(eXosip_event_t *event) static void handle_answer(eXosip_event_t * event)
{ {
osip_message_t *ack = NULL; osip_message_t *ack = NULL;
sdp_message_t *remote_sdp = NULL; sdp_message_t *remote_sdp = NULL;
@ -1032,12 +1048,16 @@ static void handle_answer(eXosip_event_t *event)
int rate = atoi(drate); int rate = atoi(drate);
if (switch_core_codec_init(&tech_pvt->read_codec, dname, rate, globals.codec_ms, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) { if (switch_core_codec_init
(&tech_pvt->read_codec, dname, rate, globals.codec_ms, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return; return;
} else { } else {
if (switch_core_codec_init(&tech_pvt->write_codec, dname, rate, globals.codec_ms, SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) { if (switch_core_codec_init
(&tech_pvt->write_codec, dname, rate, globals.codec_ms,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return; return;
@ -1072,133 +1092,119 @@ static void handle_answer(eXosip_event_t *event)
} }
static void log_event(eXosip_event_t *je) static void log_event(eXosip_event_t * je)
{ {
char buf[100]; char buf[100];
buf[0] = '\0'; buf[0] = '\0';
if (je->type == EXOSIP_CALL_NOANSWER) { if (je->type == EXOSIP_CALL_NOANSWER) {
snprintf (buf, 99, "<- (%i %i) No answer", je->cid, je->did); snprintf(buf, 99, "<- (%i %i) No answer", je->cid, je->did);
} else if (je->type == EXOSIP_CALL_CLOSED) { } else if (je->type == EXOSIP_CALL_CLOSED) {
snprintf (buf, 99, "<- (%i %i) Call Closed", je->cid, je->did); snprintf(buf, 99, "<- (%i %i) Call Closed", je->cid, je->did);
} else if (je->type == EXOSIP_CALL_RELEASED) { } else if (je->type == EXOSIP_CALL_RELEASED) {
snprintf (buf, 99, "<- (%i %i) Call released", je->cid, je->did); snprintf(buf, 99, "<- (%i %i) Call released", je->cid, je->did);
} else if (je->type == EXOSIP_MESSAGE_NEW } else if (je->type == EXOSIP_MESSAGE_NEW && je->request != NULL && MSG_IS_MESSAGE(je->request)) {
&& je->request!=NULL && MSG_IS_MESSAGE(je->request)) {
char *tmp = NULL; char *tmp = NULL;
if (je->request != NULL) { if (je->request != NULL) {
osip_body_t *body; osip_body_t *body;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
osip_message_get_body (je->request, 0, &body); osip_message_get_body(je->request, 0, &body);
if (body != NULL && body->body != NULL) { if (body != NULL && body->body != NULL) {
snprintf (buf, 99, "<- (%i) from: %s TEXT: %s", snprintf(buf, 99, "<- (%i) from: %s TEXT: %s", je->tid, tmp, body->body);
je->tid, tmp, body->body);
} }
osip_free (tmp); osip_free(tmp);
} else { } else {
snprintf (buf, 99, "<- (%i) New event for unknown request?", je->tid); snprintf(buf, 99, "<- (%i) New event for unknown request?", je->tid);
} }
} else if (je->type == EXOSIP_MESSAGE_NEW) { } else if (je->type == EXOSIP_MESSAGE_NEW) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i) %s from: %s", snprintf(buf, 99, "<- (%i) %s from: %s", je->tid, je->request->sip_method, tmp);
je->tid, je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->type == EXOSIP_MESSAGE_PROCEEDING } else if (je->type == EXOSIP_MESSAGE_PROCEEDING
|| je->type == EXOSIP_MESSAGE_ANSWERED || je->type == EXOSIP_MESSAGE_ANSWERED
|| je->type == EXOSIP_MESSAGE_REDIRECTED || je->type == EXOSIP_MESSAGE_REDIRECTED
|| je->type == EXOSIP_MESSAGE_REQUESTFAILURE || je->type == EXOSIP_MESSAGE_REQUESTFAILURE
|| je->type == EXOSIP_MESSAGE_SERVERFAILURE || je->type == EXOSIP_MESSAGE_SERVERFAILURE || je->type == EXOSIP_MESSAGE_GLOBALFAILURE) {
|| je->type == EXOSIP_MESSAGE_GLOBALFAILURE) {
if (je->response != NULL && je->request != NULL) { if (je->response != NULL && je->request != NULL) {
char *tmp = NULL; char *tmp = NULL;
osip_to_to_str (je->request->to, &tmp); osip_to_to_str(je->request->to, &tmp);
snprintf (buf, 99, "<- (%i) [%i %s for %s] to: %s", snprintf(buf, 99, "<- (%i) [%i %s for %s] to: %s",
je->tid, je->response->status_code, je->tid, je->response->status_code, je->response->reason_phrase, je->request->sip_method, tmp);
je->response->reason_phrase, je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->request != NULL) { } else if (je->request != NULL) {
snprintf (buf, 99, "<- (%i) Error for %s request", snprintf(buf, 99, "<- (%i) Error for %s request", je->tid, je->request->sip_method);
je->tid, je->request->sip_method);
} else { } else {
snprintf (buf, 99, "<- (%i) Error for unknown request", je->tid); snprintf(buf, 99, "<- (%i) Error for unknown request", je->tid);
} }
} else if (je->response == NULL && je->request != NULL && je->cid > 0) { } else if (je->response == NULL && je->request != NULL && je->cid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i %i) %s from: %s", snprintf(buf, 99, "<- (%i %i) %s from: %s", je->cid, je->did, je->request->cseq->method, tmp);
je->cid, je->did, je->request->cseq->method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL && je->cid > 0) { } else if (je->response != NULL && je->cid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_to_to_str (je->request->to, &tmp); osip_to_to_str(je->request->to, &tmp);
snprintf (buf, 99, "<- (%i %i) [%i %s] for %s to: %s", snprintf(buf, 99, "<- (%i %i) [%i %s] for %s to: %s",
je->cid, je->did, je->response->status_code, je->cid, je->did, je->response->status_code,
je->response->reason_phrase, je->request->sip_method, tmp); je->response->reason_phrase, je->request->sip_method, tmp);
osip_free (tmp); osip_free(tmp);
} else if (je->response == NULL && je->request != NULL && je->rid > 0) { } else if (je->response == NULL && je->request != NULL && je->rid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i) %s from: %s", snprintf(buf, 99, "<- (%i) %s from: %s", je->rid, je->request->cseq->method, tmp);
je->rid, je->request->cseq->method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL && je->rid > 0) { } else if (je->response != NULL && je->rid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i) [%i %s] from: %s", snprintf(buf, 99, "<- (%i) [%i %s] from: %s",
je->rid, je->response->status_code, je->rid, je->response->status_code, je->response->reason_phrase, tmp);
je->response->reason_phrase, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response == NULL && je->request != NULL && je->sid > 0) { } else if (je->response == NULL && je->request != NULL && je->sid > 0) {
char *tmp = NULL; char *tmp = NULL;
char *stat = NULL; char *stat = NULL;
osip_header_t *sub_state; osip_header_t *sub_state;
osip_message_header_get_byname (je->request, "subscription-state", osip_message_header_get_byname(je->request, "subscription-state", 0, &sub_state);
0, &sub_state);
if (sub_state != NULL && sub_state->hvalue != NULL) if (sub_state != NULL && sub_state->hvalue != NULL)
stat = sub_state->hvalue; stat = sub_state->hvalue;
osip_uri_to_str (je->request->from->url, &tmp); osip_uri_to_str(je->request->from->url, &tmp);
snprintf (buf, 99, "<- (%i) [%s] %s from: %s", snprintf(buf, 99, "<- (%i) [%s] %s from: %s", je->sid, stat, je->request->cseq->method, tmp);
je->sid, stat, je->request->cseq->method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL && je->sid > 0) { } else if (je->response != NULL && je->sid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_uri_to_str (je->request->to->url, &tmp); osip_uri_to_str(je->request->to->url, &tmp);
snprintf (buf, 99, "<- (%i) [%i %s] from: %s", snprintf(buf, 99, "<- (%i) [%i %s] from: %s",
je->sid, je->response->status_code, je->sid, je->response->status_code, je->response->reason_phrase, tmp);
je->response->reason_phrase, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response == NULL && je->request != NULL) { } else if (je->response == NULL && je->request != NULL) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) %s from: %s", snprintf(buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) %s from: %s",
je->cid, je->did, je->sid, je->nid, je->cid, je->did, je->sid, je->nid, je->request->sip_method, tmp);
je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL) { } else if (je->response != NULL) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) [%i %s] for %s from: %s", snprintf(buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) [%i %s] for %s from: %s",
je->cid, je->did, je->sid, je->nid, je->cid, je->did, je->sid, je->nid,
je->response->status_code, je->response->reason_phrase, je->response->status_code, je->response->reason_phrase, je->request->sip_method, tmp);
je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else { } else {
snprintf (buf, 99, "<- (c=%i|d=%i|s=%i|n=%i|t=%i) %s", snprintf(buf, 99, "<- (c=%i|d=%i|s=%i|n=%i|t=%i) %s",
je->cid, je->did, je->sid, je->nid, je->tid, je->textinfo); je->cid, je->did, je->sid, je->nid, je->tid, je->textinfo);
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\n%s\n", buf); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\n%s\n", buf);
/* Print it out */ /* Print it out */
@ -1212,18 +1218,18 @@ static void *monitor_thread_run(void)
globals.running = 1; globals.running = 1;
while (globals.running > 0) { while (globals.running > 0) {
if (!(event = eXosip_event_wait(0,100))) { if (!(event = eXosip_event_wait(0, 100))) {
switch_yield(100); switch_yield(100);
continue; continue;
} }
eXosip_lock(); eXosip_lock();
eXosip_automatic_action (); eXosip_automatic_action();
eXosip_unlock(); eXosip_unlock();
log_event(event); log_event(event);
switch(event->type) { switch (event->type) {
case EXOSIP_CALL_INVITE: case EXOSIP_CALL_INVITE:
exosip_create_call(event); exosip_create_call(event);
break; break;
@ -1344,11 +1350,11 @@ static int config_exosip(int reload)
set_global_dialplan("default"); set_global_dialplan("default");
} }
if (eXosip_init ()) { if (eXosip_init()) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_init initialization failed!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_init initialization failed!\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
if (eXosip_listen_addr (IPPROTO_UDP, NULL, globals.port, AF_INET, 0)) { if (eXosip_listen_addr(IPPROTO_UDP, NULL, globals.port, AF_INET, 0)) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_listen_addr failed!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_listen_addr failed!\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
@ -1371,4 +1377,3 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
config_exosip(0); config_exosip(0);
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }

View File

@ -116,7 +116,7 @@ struct private_object {
int32_t timestamp_send; int32_t timestamp_send;
int32_t timestamp_recv; int32_t timestamp_recv;
int payload_num; int payload_num;
struct rtp *rtp_session; struct rtp *rtp_session;
struct osip_rfc3264 *sdp_config; struct osip_rfc3264 *sdp_config;
sdp_message_t *remote_sdp; sdp_message_t *remote_sdp;
sdp_message_t *local_sdp; sdp_message_t *local_sdp;
@ -160,11 +160,14 @@ static switch_status exosip_on_init(switch_core_session *session);
static switch_status exosip_on_hangup(switch_core_session *session); static switch_status exosip_on_hangup(switch_core_session *session);
static switch_status exosip_on_loopback(switch_core_session *session); static switch_status exosip_on_loopback(switch_core_session *session);
static switch_status exosip_on_transmit(switch_core_session *session); static switch_status exosip_on_transmit(switch_core_session *session);
static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session); static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags); switch_core_session **new_session);
static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags); static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags);
static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags);
static int config_exosip(int reload); static int config_exosip(int reload);
static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **drate, char **dpayload); static switch_status parse_sdp_media(sdp_media_t * media, char **dname, char **drate, char **dpayload);
static switch_status exosip_kill_channel(switch_core_session *session, int sig); static switch_status exosip_kill_channel(switch_core_session *session, int sig);
static void activate_rtp(struct private_object *tech_pvt); static void activate_rtp(struct private_object *tech_pvt);
static void deactivate_rtp(struct private_object *tech_pvt); static void deactivate_rtp(struct private_object *tech_pvt);
@ -217,7 +220,7 @@ static int sdp_add_codec(struct osip_rfc3264 *cnf, int codec_type, int payload,
default: default:
break; break;
} }
return 0; return 0;
} }
@ -247,7 +250,7 @@ static switch_status exosip_on_init(switch_core_session *session)
char *dest_uri; char *dest_uri;
switch_codec_interface *codecs[512]; switch_codec_interface *codecs[512];
int num_codecs = 0; int num_codecs = 0;
/* do SIP Goodies...*/ /* do SIP Goodies... */
/* Generate callerid URI */ /* Generate callerid URI */
eXosip_guess_localip(AF_INET, localip, 128); eXosip_guess_localip(AF_INET, localip, 128);
@ -260,14 +263,17 @@ static switch_status exosip_on_init(switch_core_session *session)
/* Initialize SDP */ /* Initialize SDP */
sdp_message_init(&tech_pvt->local_sdp); sdp_message_init(&tech_pvt->local_sdp);
sdp_message_v_version_set(tech_pvt->local_sdp, "0"); sdp_message_v_version_set(tech_pvt->local_sdp, "0");
sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4", tech_pvt->local_sdp_audio_ip); sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4",
tech_pvt->local_sdp_audio_ip);
sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call"); sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call");
sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL); sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL);
sdp_message_t_time_descr_add(tech_pvt->local_sdp, "0", "0"); sdp_message_t_time_descr_add(tech_pvt->local_sdp, "0", "0");
snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port); snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port);
sdp_message_m_media_add(tech_pvt->local_sdp, "audio", port, NULL, "RTP/AVP"); sdp_message_m_media_add(tech_pvt->local_sdp, "audio", port, NULL, "RTP/AVP");
/* Add in every codec we support on this outbound call */ /* Add in every codec we support on this outbound call */
if ((num_codecs = loadable_module_get_codecs(switch_core_session_get_pool(session), codecs, sizeof(codecs)/sizeof(codecs[0]))) > 0) { if ((num_codecs =
loadable_module_get_codecs(switch_core_session_get_pool(session), codecs,
sizeof(codecs) / sizeof(codecs[0]))) > 0) {
int i; int i;
static const switch_codec_implementation *imp; static const switch_codec_implementation *imp;
for (i = 0; i < num_codecs; i++) { for (i = 0; i < num_codecs; i++) {
@ -275,12 +281,14 @@ static switch_status exosip_on_init(switch_core_session *session)
snprintf(tmp, sizeof(tmp), "%i", codecs[i]->ianacode); snprintf(tmp, sizeof(tmp), "%i", codecs[i]->ianacode);
sdp_message_m_payload_add(tech_pvt->local_sdp, 0, osip_strdup(tmp)); sdp_message_m_payload_add(tech_pvt->local_sdp, 0, osip_strdup(tmp));
for (imp = codecs[i]->implementations ; imp ; imp = imp->next) { for (imp = codecs[i]->implementations; imp; imp = imp->next) {
/* Add to SDP config */ /* Add to SDP config */
sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame, imp->samples_per_second, x++); sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame,
imp->samples_per_second, x++);
/* Add to SDP message */ /* Add to SDP message */
snprintf(tmp, sizeof(tmp), "%i %s/%i", codecs[i]->ianacode, codecs[i]->iananame, imp->samples_per_second); snprintf(tmp, sizeof(tmp), "%i %s/%i", codecs[i]->ianacode, codecs[i]->iananame,
imp->samples_per_second);
sdp_message_a_attribute_add(tech_pvt->local_sdp, 0, "rtpmap", osip_strdup(tmp)); sdp_message_a_attribute_add(tech_pvt->local_sdp, 0, "rtpmap", osip_strdup(tmp));
memset(tmp, 0, sizeof(tmp)); memset(tmp, 0, sizeof(tmp));
} }
@ -288,7 +296,9 @@ static switch_status exosip_on_init(switch_core_session *session)
} }
/* Setup our INVITE */ /* Setup our INVITE */
eXosip_lock(); eXosip_lock();
if (!(dest_uri = (char *) switch_core_session_alloc(session, strlen(tech_pvt->caller_profile->destination_number) + 10))) { if (!
(dest_uri =
(char *) switch_core_session_alloc(session, strlen(tech_pvt->caller_profile->destination_number) + 10))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "AIEEEE!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "AIEEEE!\n");
assert(dest_uri != NULL); assert(dest_uri != NULL);
} }
@ -362,7 +372,8 @@ static switch_status exosip_on_hangup(switch_core_session *session)
switch_core_codec_destroy(&tech_pvt->write_codec); switch_core_codec_destroy(&tech_pvt->write_codec);
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "EXOSIP HANGUP %s %d/%d=%d\n", switch_channel_get_name(channel), tech_pvt->cid, tech_pvt->did, i); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "EXOSIP HANGUP %s %d/%d=%d\n", switch_channel_get_name(channel),
tech_pvt->cid, tech_pvt->did, i);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -378,7 +389,8 @@ static switch_status exosip_on_transmit(switch_core_session *session)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session) static switch_status exosip_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
switch_core_session **new_session)
{ {
if ((*new_session = switch_core_session_request(&exosip_endpoint_interface, NULL))) { if ((*new_session = switch_core_session_request(&exosip_endpoint_interface, NULL))) {
struct private_object *tech_pvt; struct private_object *tech_pvt;
@ -386,7 +398,8 @@ static switch_status exosip_outgoing_channel(switch_core_session *session, switc
switch_caller_profile *caller_profile, *originator_caller_profile = NULL; switch_caller_profile *caller_profile, *originator_caller_profile = NULL;
switch_core_session_add_stream(*new_session, NULL); switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) { if ((tech_pvt =
(struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt)); memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(*new_session); channel = switch_core_session_get_channel(*new_session);
switch_core_session_set_private(*new_session, tech_pvt); switch_core_session_set_private(*new_session, tech_pvt);
@ -447,30 +460,29 @@ static const char *event_names[] = {
}; };
#endif #endif
static void rtp_event_handler(struct rtp *session, rtp_event *event) static void rtp_event_handler(struct rtp *session, rtp_event * event)
{ {
rtp_packet *packet; rtp_packet *packet;
struct private_object *tech_pvt = (struct private_object *) rtp_get_userdata(session); struct private_object *tech_pvt = (struct private_object *) rtp_get_userdata(session);
if (!session) { if (!session) {
return; return;
} }
//switch_console_printf(SWITCH_CHANNEL_CONSOLE, "RTP EVENT (%s)\n", event_names[event->type]);
//switch_console_printf(SWITCH_CHANNEL_CONSOLE, "RTP EVENT (%s)\n", event_names[event->type]); switch (event->type) {
switch(event->type) {
case RX_RTP: case RX_RTP:
if((packet = (rtp_packet *) event->data)) { if ((packet = (rtp_packet *) event->data)) {
if (packet->data_len < 10000) { if (packet->data_len < 10000) {
memcpy(tech_pvt->read_buf, packet->data, packet->data_len); memcpy(tech_pvt->read_buf, packet->data, packet->data_len);
tech_pvt->read_frame.datalen = packet->data_len; tech_pvt->read_frame.datalen = packet->data_len;
} else { } else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WTF PACKET LEN %d\n", packet->data_len); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WTF PACKET LEN %d\n", packet->data_len);
} }
free(packet); /* xfree() is mandatory to release RTP packet data */ free(packet); /* xfree() is mandatory to release RTP packet data */
} }
break; break;
case RR_TIMEOUT: case RR_TIMEOUT:
case RX_BYE: case RX_BYE:
switch_set_flag(tech_pvt, TFLAG_BYE); switch_set_flag(tech_pvt, TFLAG_BYE);
@ -485,7 +497,7 @@ static void deactivate_rtp(struct private_object *tech_pvt)
if (tech_pvt->rtp_session) { if (tech_pvt->rtp_session) {
//switch_mutex_lock(tech_pvt->rtp_lock); //switch_mutex_lock(tech_pvt->rtp_lock);
while(loops < 10 && (switch_test_flag(tech_pvt, TFLAG_READING) || switch_test_flag(tech_pvt, TFLAG_WRITING))) { while (loops < 10 && (switch_test_flag(tech_pvt, TFLAG_READING) || switch_test_flag(tech_pvt, TFLAG_WRITING))) {
switch_yield(10000); switch_yield(10000);
loops++; loops++;
} }
@ -507,9 +519,8 @@ static void activate_rtp(struct private_object *tech_pvt)
assert(channel != NULL); assert(channel != NULL);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activating RTP %d->%s:%d\n", switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activating RTP %d->%s:%d\n",
tech_pvt->local_sdp_audio_port, tech_pvt->local_sdp_audio_port,
tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
tech_pvt->remote_sdp_audio_port);
//switch_mutex_lock(tech_pvt->rtp_lock); //switch_mutex_lock(tech_pvt->rtp_lock);
@ -521,13 +532,13 @@ static void activate_rtp(struct private_object *tech_pvt)
bw *= 8; bw *= 8;
} }
tech_pvt->rtp_session = rtp_init(tech_pvt->remote_sdp_audio_ip, /* Host/Group IP address */ tech_pvt->rtp_session = rtp_init(tech_pvt->remote_sdp_audio_ip, /* Host/Group IP address */
tech_pvt->local_sdp_audio_port, /* receive port */ tech_pvt->local_sdp_audio_port, /* receive port */
tech_pvt->remote_sdp_audio_port, /* transmit port */ tech_pvt->remote_sdp_audio_port, /* transmit port */
ms * 2, /* time-to-live */ ms * 2, /* time-to-live */
bw, /* B/W estimate */ bw, /* B/W estimate */
rtp_event_handler, /* RTP event callback */ rtp_event_handler, /* RTP event callback */
(void *) tech_pvt); /* App. specific data */ (void *) tech_pvt); /* App. specific data */
if (tech_pvt->rtp_session) { if (tech_pvt->rtp_session) {
@ -576,12 +587,13 @@ static switch_status exosip_answer_channel(switch_core_session *session)
} }
static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags) static switch_status exosip_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags)
{ {
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
size_t bytes = 0, samples = 0, frames, ms, x; size_t bytes = 0, samples = 0, frames, ms, x;
switch_channel *channel = NULL; switch_channel *channel = NULL;
int ns=0; int ns = 0;
struct timeval tv; struct timeval tv;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
@ -616,9 +628,9 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
//switch_mutex_lock(tech_pvt->rtp_lock); //switch_mutex_lock(tech_pvt->rtp_lock);
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = ns; tv.tv_usec = ns;
while(switch_test_flag(tech_pvt, TFLAG_IO) && !switch_test_flag(tech_pvt, TFLAG_BYE)) { while (switch_test_flag(tech_pvt, TFLAG_IO) && !switch_test_flag(tech_pvt, TFLAG_BYE)) {
x = rtp_recv(tech_pvt->rtp_session, &tv, tech_pvt->timestamp_recv); x = rtp_recv(tech_pvt->rtp_session, &tv, tech_pvt->timestamp_recv);
if(x < 0) { if (x < 0) {
break; break;
} }
if (tech_pvt->read_frame.datalen) { if (tech_pvt->read_frame.datalen) {
@ -629,7 +641,7 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
break; break;
} }
} }
tech_pvt->timestamp_recv += (int)samples; tech_pvt->timestamp_recv += (int) samples;
//printf("%s\trecv %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->read_frame.datalen, samples, frames, ms, tech_pvt->timestamp_recv); //printf("%s\trecv %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->read_frame.datalen, samples, frames, ms, tech_pvt->timestamp_recv);
//switch_mutex_unlock(tech_pvt->rtp_lock); //switch_mutex_unlock(tech_pvt->rtp_lock);
@ -651,7 +663,8 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
} }
static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags) static switch_status exosip_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel = NULL; switch_channel *channel = NULL;
@ -688,16 +701,14 @@ static switch_status exosip_write_frame(switch_core_session *session, switch_fra
} else { } else {
assert(0); assert(0);
} }
tech_pvt->timestamp_send += (int)samples; tech_pvt->timestamp_send += (int) samples;
//printf("%s %s->%s send %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip, frame->datalen, samples, frames, ms, tech_pvt->timestamp_recv); //printf("%s %s->%s send %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip, frame->datalen, samples, frames, ms, tech_pvt->timestamp_recv);
rtp_send_ctrl(tech_pvt->rtp_session, tech_pvt->timestamp_send, NULL); rtp_send_ctrl(tech_pvt->rtp_session, tech_pvt->timestamp_send, NULL);
x = rtp_send_data(tech_pvt->rtp_session, tech_pvt->timestamp_send, tech_pvt->payload_num, x = rtp_send_data(tech_pvt->rtp_session, tech_pvt->timestamp_send, tech_pvt->payload_num,
0, 0, 0, 0, 0, 0, (char *) frame->data, (int) frame->datalen, 0, 0, 0);
(char *)frame->data, (int)frame->datalen,
0, 0, 0);
switch_clear_flag(tech_pvt, TFLAG_WRITING); switch_clear_flag(tech_pvt, TFLAG_WRITING);
@ -758,39 +769,39 @@ static switch_status exosip_waitfor_write(switch_core_session *session, int ms)
} }
static const switch_io_routines exosip_io_routines = { static const switch_io_routines exosip_io_routines = {
/*.outgoing_channel*/ exosip_outgoing_channel, /*.outgoing_channel */ exosip_outgoing_channel,
/*.answer_channel*/ exosip_answer_channel, /*.answer_channel */ exosip_answer_channel,
/*.read_frame*/ exosip_read_frame, /*.read_frame */ exosip_read_frame,
/*.write_frame*/ exosip_write_frame, /*.write_frame */ exosip_write_frame,
/*.kill_channel*/ exosip_kill_channel, /*.kill_channel */ exosip_kill_channel,
/*.waitfor_read*/ exosip_waitfor_read, /*.waitfor_read */ exosip_waitfor_read,
/*.waitfor_read*/ exosip_waitfor_write /*.waitfor_read */ exosip_waitfor_write
}; };
static const switch_event_handler_table exosip_event_handlers = { static const switch_event_handler_table exosip_event_handlers = {
/*.on_init*/ exosip_on_init, /*.on_init */ exosip_on_init,
/*.on_ring*/ exosip_on_ring, /*.on_ring */ exosip_on_ring,
/*.on_execute*/ exosip_on_execute, /*.on_execute */ exosip_on_execute,
/*.on_hangup*/ exosip_on_hangup, /*.on_hangup */ exosip_on_hangup,
/*.on_loopback*/ exosip_on_loopback, /*.on_loopback */ exosip_on_loopback,
/*.on_transmit*/ exosip_on_transmit /*.on_transmit */ exosip_on_transmit
}; };
static const switch_endpoint_interface exosip_endpoint_interface = { static const switch_endpoint_interface exosip_endpoint_interface = {
/*.interface_name*/ "exosip", /*.interface_name */ "exosip",
/*.io_routines*/ &exosip_io_routines, /*.io_routines */ &exosip_io_routines,
/*.event_handlers*/ &exosip_event_handlers, /*.event_handlers */ &exosip_event_handlers,
/*.private*/ NULL, /*.private */ NULL,
/*.next*/ NULL /*.next */ NULL
}; };
static const switch_loadable_module_interface exosip_module_interface = { static const switch_loadable_module_interface exosip_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ &exosip_endpoint_interface, /*.endpoint_interface */ &exosip_endpoint_interface,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
@ -798,7 +809,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
{ {
if (globals.running) { if (globals.running) {
globals.running = -1; globals.running = -1;
while(globals.running) { while (globals.running) {
switch_yield(1000); switch_yield(1000);
} }
} }
@ -806,7 +817,9 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **_interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **_interface,
char *filename)
{
/* NOTE: **interface is **_interface because the common lib redefines interface to struct in some situations */ /* NOTE: **interface is **_interface because the common lib redefines interface to struct in some situations */
if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) { if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
@ -821,7 +834,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status exosip_create_call(eXosip_event_t *event) static switch_status exosip_create_call(eXosip_event_t * event)
{ {
switch_core_session *session; switch_core_session *session;
sdp_message_t *remote_sdp = NULL; sdp_message_t *remote_sdp = NULL;
@ -853,12 +866,11 @@ static switch_status exosip_create_call(eXosip_event_t *event)
} }
if ((tech_pvt->caller_profile = switch_caller_profile_new(session, if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan, globals.dialplan,
event->request->from->displayname, event->request->from->displayname,
event->request->from->url->username, event->request->from->url->username,
event->request->from->url->username, event->request->from->url->username,
NULL, NULL, event->request->req_uri->username))) {
event->request->req_uri->username))) {
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
} }
@ -882,14 +894,17 @@ static switch_status exosip_create_call(eXosip_event_t *event)
osip_rfc3264_init(&tech_pvt->sdp_config); osip_rfc3264_init(&tech_pvt->sdp_config);
/* Add in what codecs we support locally */ /* Add in what codecs we support locally */
if ((num_codecs = loadable_module_get_codecs(switch_core_session_get_pool(session), codecs, sizeof(codecs)/sizeof(codecs[0]))) > 0) { if ((num_codecs =
loadable_module_get_codecs(switch_core_session_get_pool(session), codecs,
sizeof(codecs) / sizeof(codecs[0]))) > 0) {
int i; int i;
static const switch_codec_implementation *imp; static const switch_codec_implementation *imp;
for (i = 0; i < num_codecs; i++) { for (i = 0; i < num_codecs; i++) {
int x = 0; int x = 0;
for (imp = codecs[i]->implementations ; imp ; imp = imp->next) { for (imp = codecs[i]->implementations; imp; imp = imp->next) {
sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame, imp->samples_per_second, x++); sdp_add_codec(tech_pvt->sdp_config, codecs[i]->codec_type, codecs[i]->ianacode, codecs[i]->iananame,
imp->samples_per_second, x++);
} }
} }
} }
@ -898,17 +913,18 @@ static switch_status exosip_create_call(eXosip_event_t *event)
sdp_message_parse(tech_pvt->local_sdp, local_sdp_str); sdp_message_parse(tech_pvt->local_sdp, local_sdp_str);
sdp_message_to_str(remote_sdp, &remote_sdp_str); sdp_message_to_str(remote_sdp, &remote_sdp_str);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "LOCAL SDP:\n%s\nREMOTE SDP:\n%s", local_sdp_str,remote_sdp_str); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "LOCAL SDP:\n%s\nREMOTE SDP:\n%s", local_sdp_str, remote_sdp_str);
mline = 0; mline = 0;
while (0==osip_rfc3264_match(tech_pvt->sdp_config, remote_sdp, audio_tab, video_tab, t38_tab, app_tab, mline)) { while (0 == osip_rfc3264_match(tech_pvt->sdp_config, remote_sdp, audio_tab, video_tab, t38_tab, app_tab, mline)) {
if (audio_tab[0] == NULL && video_tab[0] == NULL && t38_tab[0] == NULL && app_tab[0] == NULL) { if (audio_tab[0] == NULL && video_tab[0] == NULL && t38_tab[0] == NULL && app_tab[0] == NULL) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Got no compatible codecs!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Got no compatible codecs!\n");
break; break;
} }
for (pos=0; audio_tab[pos]!=NULL; pos++) { for (pos = 0; audio_tab[pos] != NULL; pos++) {
osip_rfc3264_complete_answer(tech_pvt->sdp_config, remote_sdp, tech_pvt->local_sdp, audio_tab[pos], mline); osip_rfc3264_complete_answer(tech_pvt->sdp_config, remote_sdp, tech_pvt->local_sdp, audio_tab[pos],
mline);
if (parse_sdp_media(audio_tab[pos], &dname, &drate, &dpayload) == SWITCH_STATUS_SUCCESS) { if (parse_sdp_media(audio_tab[pos], &dname, &drate, &dpayload) == SWITCH_STATUS_SUCCESS) {
tech_pvt->payload_num = atoi(dpayload); tech_pvt->payload_num = atoi(dpayload);
break; break;
@ -917,7 +933,8 @@ static switch_status exosip_create_call(eXosip_event_t *event)
mline++; mline++;
} }
free(remote_sdp_str); free(remote_sdp_str);
sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4", tech_pvt->local_sdp_audio_ip); sdp_message_o_origin_set(tech_pvt->local_sdp, "OpenSWITCH2", "0", "0", "IN", "IP4",
tech_pvt->local_sdp_audio_ip);
sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call"); sdp_message_s_name_set(tech_pvt->local_sdp, "SIP Call");
sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL); sdp_message_c_connection_add(tech_pvt->local_sdp, -1, "IN", "IP4", tech_pvt->local_sdp_audio_ip, NULL, NULL);
snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port); snprintf(port, sizeof(port), "%i", tech_pvt->local_sdp_audio_port);
@ -945,21 +962,21 @@ static switch_status exosip_create_call(eXosip_event_t *event)
int rate = atoi(drate); int rate = atoi(drate);
if (switch_core_codec_init(&tech_pvt->read_codec, if (switch_core_codec_init(&tech_pvt->read_codec,
dname, dname,
rate, rate,
globals.codec_ms, globals.codec_ms,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) { NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} else { } else {
if (switch_core_codec_init(&tech_pvt->write_codec, if (switch_core_codec_init(&tech_pvt->write_codec,
dname, dname,
rate, rate,
globals.codec_ms, globals.codec_ms,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) { NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
@ -967,7 +984,8 @@ static switch_status exosip_create_call(eXosip_event_t *event)
int ms; int ms;
switch_set_flag(tech_pvt, TFLAG_USING_CODEC); switch_set_flag(tech_pvt, TFLAG_USING_CODEC);
ms = tech_pvt->write_codec.implementation->nanoseconds_per_frame / 1000; ms = tech_pvt->write_codec.implementation->nanoseconds_per_frame / 1000;
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Inbound Codec %s/%d %d ms\n", dname, rate, ms); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Activate Inbound Codec %s/%d %d ms\n", dname, rate,
ms);
tech_pvt->read_frame.codec = &tech_pvt->read_codec; tech_pvt->read_frame.codec = &tech_pvt->read_codec;
switch_core_session_set_read_codec(session, &tech_pvt->read_codec); switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
switch_core_session_set_write_codec(session, &tech_pvt->write_codec); switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
@ -987,13 +1005,14 @@ static switch_status exosip_create_call(eXosip_event_t *event)
} }
static void destroy_call_by_event(eXosip_event_t *event) static void destroy_call_by_event(eXosip_event_t * event)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel = NULL; switch_channel *channel = NULL;
if (!(tech_pvt = get_pvt_by_call_id(event->cid))) { if (!(tech_pvt = get_pvt_by_call_id(event->cid))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Um in case you are interested, Can't find the pvt [%d]!\n", event->cid); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Um in case you are interested, Can't find the pvt [%d]!\n",
event->cid);
return; return;
} }
@ -1006,7 +1025,7 @@ static void destroy_call_by_event(eXosip_event_t *event)
} }
static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **drate, char **dpayload) static switch_status parse_sdp_media(sdp_media_t * media, char **dname, char **drate, char **dpayload)
{ {
int pos = 0; int pos = 0;
sdp_attribute_t *attr = NULL; sdp_attribute_t *attr = NULL;
@ -1014,7 +1033,7 @@ static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **dr
switch_status status = SWITCH_STATUS_GENERR; switch_status status = SWITCH_STATUS_GENERR;
while (osip_list_eol(media->a_attributes, pos) == 0) { while (osip_list_eol(media->a_attributes, pos) == 0) {
attr = (sdp_attribute_t *)osip_list_get(media->a_attributes, pos); attr = (sdp_attribute_t *) osip_list_get(media->a_attributes, pos);
if (attr != NULL && strcasecmp(attr->a_att_field, "rtpmap") == 0) { if (attr != NULL && strcasecmp(attr->a_att_field, "rtpmap") == 0) {
payload = attr->a_att_value; payload = attr->a_att_value;
if ((name = strchr(payload, ' '))) { if ((name = strchr(payload, ' '))) {
@ -1035,7 +1054,8 @@ static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **dr
*dname = strdup("L16"); *dname = strdup("L16");
*drate = strdup("8000"); *drate = strdup("8000");
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Found negotiated codec Payload: %s Name: %s Rate: %s\n", *dpayload, *dname, *drate); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Found negotiated codec Payload: %s Name: %s Rate: %s\n",
*dpayload, *dname, *drate);
break; break;
} }
attr = NULL; attr = NULL;
@ -1045,7 +1065,7 @@ static switch_status parse_sdp_media(sdp_media_t *media, char **dname, char **dr
return status; return status;
} }
static void handle_answer(eXosip_event_t *event) static void handle_answer(eXosip_event_t * event)
{ {
osip_message_t *ack = NULL; osip_message_t *ack = NULL;
sdp_message_t *remote_sdp = NULL; sdp_message_t *remote_sdp = NULL;
@ -1099,12 +1119,16 @@ static void handle_answer(eXosip_event_t *event)
int rate = atoi(drate); int rate = atoi(drate);
if (switch_core_codec_init(&tech_pvt->read_codec, dname, rate, globals.codec_ms, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) { if (switch_core_codec_init
(&tech_pvt->read_codec, dname, rate, globals.codec_ms, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return; return;
} else { } else {
if (switch_core_codec_init(&tech_pvt->write_codec, dname, rate, globals.codec_ms, SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) { if (switch_core_codec_init
(&tech_pvt->write_codec, dname, rate, globals.codec_ms,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_channel_hangup(channel); switch_channel_hangup(channel);
return; return;
@ -1137,133 +1161,119 @@ static void handle_answer(eXosip_event_t *event)
} }
static void log_event(eXosip_event_t *je) static void log_event(eXosip_event_t * je)
{ {
char buf[100]; char buf[100];
buf[0] = '\0'; buf[0] = '\0';
if (je->type == EXOSIP_CALL_NOANSWER) { if (je->type == EXOSIP_CALL_NOANSWER) {
snprintf (buf, 99, "<- (%i %i) No answer", je->cid, je->did); snprintf(buf, 99, "<- (%i %i) No answer", je->cid, je->did);
} else if (je->type == EXOSIP_CALL_CLOSED) { } else if (je->type == EXOSIP_CALL_CLOSED) {
snprintf (buf, 99, "<- (%i %i) Call Closed", je->cid, je->did); snprintf(buf, 99, "<- (%i %i) Call Closed", je->cid, je->did);
} else if (je->type == EXOSIP_CALL_RELEASED) { } else if (je->type == EXOSIP_CALL_RELEASED) {
snprintf (buf, 99, "<- (%i %i) Call released", je->cid, je->did); snprintf(buf, 99, "<- (%i %i) Call released", je->cid, je->did);
} else if (je->type == EXOSIP_MESSAGE_NEW } else if (je->type == EXOSIP_MESSAGE_NEW && je->request != NULL && MSG_IS_MESSAGE(je->request)) {
&& je->request!=NULL && MSG_IS_MESSAGE(je->request)) {
char *tmp = NULL; char *tmp = NULL;
if (je->request != NULL) { if (je->request != NULL) {
osip_body_t *body; osip_body_t *body;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
osip_message_get_body (je->request, 0, &body); osip_message_get_body(je->request, 0, &body);
if (body != NULL && body->body != NULL) { if (body != NULL && body->body != NULL) {
snprintf (buf, 99, "<- (%i) from: %s TEXT: %s", snprintf(buf, 99, "<- (%i) from: %s TEXT: %s", je->tid, tmp, body->body);
je->tid, tmp, body->body);
} }
osip_free (tmp); osip_free(tmp);
} else { } else {
snprintf (buf, 99, "<- (%i) New event for unknown request?", je->tid); snprintf(buf, 99, "<- (%i) New event for unknown request?", je->tid);
} }
} else if (je->type == EXOSIP_MESSAGE_NEW) { } else if (je->type == EXOSIP_MESSAGE_NEW) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i) %s from: %s", snprintf(buf, 99, "<- (%i) %s from: %s", je->tid, je->request->sip_method, tmp);
je->tid, je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->type == EXOSIP_MESSAGE_PROCEEDING } else if (je->type == EXOSIP_MESSAGE_PROCEEDING
|| je->type == EXOSIP_MESSAGE_ANSWERED || je->type == EXOSIP_MESSAGE_ANSWERED
|| je->type == EXOSIP_MESSAGE_REDIRECTED || je->type == EXOSIP_MESSAGE_REDIRECTED
|| je->type == EXOSIP_MESSAGE_REQUESTFAILURE || je->type == EXOSIP_MESSAGE_REQUESTFAILURE
|| je->type == EXOSIP_MESSAGE_SERVERFAILURE || je->type == EXOSIP_MESSAGE_SERVERFAILURE || je->type == EXOSIP_MESSAGE_GLOBALFAILURE) {
|| je->type == EXOSIP_MESSAGE_GLOBALFAILURE) {
if (je->response != NULL && je->request != NULL) { if (je->response != NULL && je->request != NULL) {
char *tmp = NULL; char *tmp = NULL;
osip_to_to_str (je->request->to, &tmp); osip_to_to_str(je->request->to, &tmp);
snprintf (buf, 99, "<- (%i) [%i %s for %s] to: %s", snprintf(buf, 99, "<- (%i) [%i %s for %s] to: %s",
je->tid, je->response->status_code, je->tid, je->response->status_code, je->response->reason_phrase, je->request->sip_method, tmp);
je->response->reason_phrase, je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->request != NULL) { } else if (je->request != NULL) {
snprintf (buf, 99, "<- (%i) Error for %s request", snprintf(buf, 99, "<- (%i) Error for %s request", je->tid, je->request->sip_method);
je->tid, je->request->sip_method);
} else { } else {
snprintf (buf, 99, "<- (%i) Error for unknown request", je->tid); snprintf(buf, 99, "<- (%i) Error for unknown request", je->tid);
} }
} else if (je->response == NULL && je->request != NULL && je->cid > 0) { } else if (je->response == NULL && je->request != NULL && je->cid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i %i) %s from: %s", snprintf(buf, 99, "<- (%i %i) %s from: %s", je->cid, je->did, je->request->cseq->method, tmp);
je->cid, je->did, je->request->cseq->method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL && je->cid > 0) { } else if (je->response != NULL && je->cid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_to_to_str (je->request->to, &tmp); osip_to_to_str(je->request->to, &tmp);
snprintf (buf, 99, "<- (%i %i) [%i %s] for %s to: %s", snprintf(buf, 99, "<- (%i %i) [%i %s] for %s to: %s",
je->cid, je->did, je->response->status_code, je->cid, je->did, je->response->status_code,
je->response->reason_phrase, je->request->sip_method, tmp); je->response->reason_phrase, je->request->sip_method, tmp);
osip_free (tmp); osip_free(tmp);
} else if (je->response == NULL && je->request != NULL && je->rid > 0) { } else if (je->response == NULL && je->request != NULL && je->rid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i) %s from: %s", snprintf(buf, 99, "<- (%i) %s from: %s", je->rid, je->request->cseq->method, tmp);
je->rid, je->request->cseq->method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL && je->rid > 0) { } else if (je->response != NULL && je->rid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (%i) [%i %s] from: %s", snprintf(buf, 99, "<- (%i) [%i %s] from: %s",
je->rid, je->response->status_code, je->rid, je->response->status_code, je->response->reason_phrase, tmp);
je->response->reason_phrase, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response == NULL && je->request != NULL && je->sid > 0) { } else if (je->response == NULL && je->request != NULL && je->sid > 0) {
char *tmp = NULL; char *tmp = NULL;
char *stat = NULL; char *stat = NULL;
osip_header_t *sub_state; osip_header_t *sub_state;
osip_message_header_get_byname (je->request, "subscription-state", osip_message_header_get_byname(je->request, "subscription-state", 0, &sub_state);
0, &sub_state);
if (sub_state != NULL && sub_state->hvalue != NULL) if (sub_state != NULL && sub_state->hvalue != NULL)
stat = sub_state->hvalue; stat = sub_state->hvalue;
osip_uri_to_str (je->request->from->url, &tmp); osip_uri_to_str(je->request->from->url, &tmp);
snprintf (buf, 99, "<- (%i) [%s] %s from: %s", snprintf(buf, 99, "<- (%i) [%s] %s from: %s", je->sid, stat, je->request->cseq->method, tmp);
je->sid, stat, je->request->cseq->method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL && je->sid > 0) { } else if (je->response != NULL && je->sid > 0) {
char *tmp = NULL; char *tmp = NULL;
osip_uri_to_str (je->request->to->url, &tmp); osip_uri_to_str(je->request->to->url, &tmp);
snprintf (buf, 99, "<- (%i) [%i %s] from: %s", snprintf(buf, 99, "<- (%i) [%i %s] from: %s",
je->sid, je->response->status_code, je->sid, je->response->status_code, je->response->reason_phrase, tmp);
je->response->reason_phrase, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response == NULL && je->request != NULL) { } else if (je->response == NULL && je->request != NULL) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) %s from: %s", snprintf(buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) %s from: %s",
je->cid, je->did, je->sid, je->nid, je->cid, je->did, je->sid, je->nid, je->request->sip_method, tmp);
je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else if (je->response != NULL) { } else if (je->response != NULL) {
char *tmp = NULL; char *tmp = NULL;
osip_from_to_str (je->request->from, &tmp); osip_from_to_str(je->request->from, &tmp);
snprintf (buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) [%i %s] for %s from: %s", snprintf(buf, 99, "<- (c=%i|d=%i|s=%i|n=%i) [%i %s] for %s from: %s",
je->cid, je->did, je->sid, je->nid, je->cid, je->did, je->sid, je->nid,
je->response->status_code, je->response->reason_phrase, je->response->status_code, je->response->reason_phrase, je->request->sip_method, tmp);
je->request->sip_method, tmp); osip_free(tmp);
osip_free (tmp);
} else { } else {
snprintf (buf, 99, "<- (c=%i|d=%i|s=%i|n=%i|t=%i) %s", snprintf(buf, 99, "<- (c=%i|d=%i|s=%i|n=%i|t=%i) %s",
je->cid, je->did, je->sid, je->nid, je->tid, je->textinfo); je->cid, je->did, je->sid, je->nid, je->tid, je->textinfo);
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\n%s\n", buf); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\n%s\n", buf);
/* Print it out */ /* Print it out */
@ -1277,18 +1287,18 @@ static void *monitor_thread_run(void)
globals.running = 1; globals.running = 1;
while (globals.running > 0) { while (globals.running > 0) {
if (!(event = eXosip_event_wait(0,100))) { if (!(event = eXosip_event_wait(0, 100))) {
switch_yield(100); switch_yield(100);
continue; continue;
} }
eXosip_lock(); eXosip_lock();
eXosip_automatic_action (); eXosip_automatic_action();
eXosip_unlock(); eXosip_unlock();
log_event(event); log_event(event);
switch(event->type) { switch (event->type) {
case EXOSIP_CALL_INVITE: case EXOSIP_CALL_INVITE:
exosip_create_call(event); exosip_create_call(event);
break; break;
@ -1409,11 +1419,11 @@ static int config_exosip(int reload)
set_global_dialplan("default"); set_global_dialplan("default");
} }
if (eXosip_init ()) { if (eXosip_init()) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_init initialization failed!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_init initialization failed!\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
if (eXosip_listen_addr (IPPROTO_UDP, NULL, globals.port, AF_INET, 0)) { if (eXosip_listen_addr(IPPROTO_UDP, NULL, globals.port, AF_INET, 0)) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_listen_addr failed!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "eXosip_listen_addr failed!\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
@ -1436,4 +1446,3 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
config_exosip(0); config_exosip(0);
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }

View File

@ -92,19 +92,21 @@ struct private_object {
}; };
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) 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_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_codec_rates_string, globals.codec_rates_string)
static char *IAXNAMES[] = {"IAX_EVENT_CONNECT","IAX_EVENT_ACCEPT","IAX_EVENT_HANGUP","IAX_EVENT_REJECT","IAX_EVENT_VOICE", static char *IAXNAMES[] =
"IAX_EVENT_DTMF","IAX_EVENT_TIMEOUT","IAX_EVENT_LAGRQ","IAX_EVENT_LAGRP","IAX_EVENT_RINGA", { "IAX_EVENT_CONNECT", "IAX_EVENT_ACCEPT", "IAX_EVENT_HANGUP", "IAX_EVENT_REJECT", "IAX_EVENT_VOICE",
"IAX_EVENT_PING","IAX_EVENT_PONG","IAX_EVENT_BUSY","IAX_EVENT_ANSWER","IAX_EVENT_IMAGE", "IAX_EVENT_DTMF", "IAX_EVENT_TIMEOUT", "IAX_EVENT_LAGRQ", "IAX_EVENT_LAGRP", "IAX_EVENT_RINGA",
"IAX_EVENT_AUTHRQ","IAX_EVENT_AUTHRP","IAX_EVENT_REGREQ","IAX_EVENT_REGACK", "IAX_EVENT_PING", "IAX_EVENT_PONG", "IAX_EVENT_BUSY", "IAX_EVENT_ANSWER", "IAX_EVENT_IMAGE",
"IAX_EVENT_URL","IAX_EVENT_LDCOMPLETE","IAX_EVENT_TRANSFER","IAX_EVENT_DPREQ", "IAX_EVENT_AUTHRQ", "IAX_EVENT_AUTHRP", "IAX_EVENT_REGREQ", "IAX_EVENT_REGACK",
"IAX_EVENT_DPREP","IAX_EVENT_DIAL","IAX_EVENT_QUELCH","IAX_EVENT_UNQUELCH", "IAX_EVENT_URL", "IAX_EVENT_LDCOMPLETE", "IAX_EVENT_TRANSFER", "IAX_EVENT_DPREQ",
"IAX_EVENT_UNLINK","IAX_EVENT_LINKREJECT","IAX_EVENT_TEXT","IAX_EVENT_REGREJ", "IAX_EVENT_DPREP", "IAX_EVENT_DIAL", "IAX_EVENT_QUELCH", "IAX_EVENT_UNQUELCH",
"IAX_EVENT_LINKURL","IAX_EVENT_CNG","IAX_EVENT_REREQUEST","IAX_EVENT_TXREPLY", "IAX_EVENT_UNLINK", "IAX_EVENT_LINKREJECT", "IAX_EVENT_TEXT", "IAX_EVENT_REGREJ",
"IAX_EVENT_TXREJECT","IAX_EVENT_TXACCEPT","IAX_EVENT_TXREADY"}; "IAX_EVENT_LINKURL", "IAX_EVENT_CNG", "IAX_EVENT_REREQUEST", "IAX_EVENT_TXREPLY",
"IAX_EVENT_TXREJECT", "IAX_EVENT_TXACCEPT", "IAX_EVENT_TXREADY"
};
struct ast_iana { struct ast_iana {
@ -114,31 +116,30 @@ struct ast_iana {
}; };
//999 means it's wrong nad i dont know the real one //999 means it's wrong nad i dont know the real one
static struct ast_iana AST_IANA[] = static struct ast_iana AST_IANA[] = { {AST_FORMAT_G723_1, 4, "g723.1"},
{{AST_FORMAT_G723_1, 4, "g723.1"}, {AST_FORMAT_GSM, 3, "gsm"},
{AST_FORMAT_GSM, 3, "gsm"}, {AST_FORMAT_ULAW, 0, "ulaw"},
{AST_FORMAT_ULAW, 0, "ulaw"}, {AST_FORMAT_ALAW, 8, "alaw"},
{AST_FORMAT_ALAW, 8, "alaw"}, {AST_FORMAT_G726, 999, "g726"},
{AST_FORMAT_G726, 999, "g726"}, {AST_FORMAT_ADPCM, 999, "adpcm"},
{AST_FORMAT_ADPCM, 999, "adpcm"}, {AST_FORMAT_SLINEAR, 10, "slinear"},
{AST_FORMAT_SLINEAR, 10, "slinear"}, {AST_FORMAT_LPC10, 7, "lpc10"},
{AST_FORMAT_LPC10, 7, "lpc10"}, {AST_FORMAT_G729A, 18, "g729"},
{AST_FORMAT_G729A, 18, "g729"}, {AST_FORMAT_SPEEX, 98, "speex"},
{AST_FORMAT_SPEEX, 98, "speex"}, {AST_FORMAT_ILBC, 999, "ilbc"},
{AST_FORMAT_ILBC, 999, "ilbc"}, {AST_FORMAT_MAX_AUDIO, 999, ""},
{AST_FORMAT_MAX_AUDIO, 999, ""}, {AST_FORMAT_JPEG, 999, ""},
{AST_FORMAT_JPEG, 999, ""}, {AST_FORMAT_PNG, 999, ""},
{AST_FORMAT_PNG, 999, ""}, {AST_FORMAT_H261, 999, ""},
{AST_FORMAT_H261, 999, ""}, {AST_FORMAT_H263, 999, ""},
{AST_FORMAT_H263, 999, ""}, {AST_FORMAT_MAX_VIDEO, 999, ""},
{AST_FORMAT_MAX_VIDEO, 999, ""}, {0, 0}
{0,0} };
};
static char *ast2str(unsigned int ast) static char *ast2str(unsigned int ast)
{ {
int x; int x;
for(x = 0; x < 32; x++) { for (x = 0; x < 32; x++) {
if ((1 << x) == ast) { if ((1 << x) == ast) {
return AST_IANA[x].name; return AST_IANA[x].name;
} }
@ -151,7 +152,7 @@ static unsigned int iana2ast(int iana)
int x = 0; int x = 0;
unsigned int ast = 0; unsigned int ast = 0;
for(x = 0; AST_IANA[x].ast; x++) { for (x = 0; AST_IANA[x].ast; x++) {
if (AST_IANA[x].iana == iana) { if (AST_IANA[x].iana == iana) {
ast = AST_IANA[x].ast; ast = AST_IANA[x].ast;
break; break;
@ -200,7 +201,9 @@ typedef enum {
IAX_QUERY = 2 IAX_QUERY = 2
} iax_io_t; } iax_io_t;
static switch_status iax_set_codec(struct private_object *tech_pvt, struct iax_session *iax_session, unsigned int *format, unsigned int *cababilities, unsigned short *samprate, iax_io_t io) static switch_status iax_set_codec(struct private_object *tech_pvt, struct iax_session *iax_session,
unsigned int *format, unsigned int *cababilities, unsigned short *samprate,
iax_io_t io)
{ {
char *dname = NULL; char *dname = NULL;
//int rate = 8000; //int rate = 8000;
@ -213,14 +216,18 @@ static switch_status iax_set_codec(struct private_object *tech_pvt, struct iax_s
if (globals.codec_string) { if (globals.codec_string) {
if (!(num_codecs = switch_loadable_module_get_codecs_sorted(switch_core_session_get_pool(tech_pvt->session), if (!(num_codecs = switch_loadable_module_get_codecs_sorted(switch_core_session_get_pool(tech_pvt->session),
codecs, codecs,
SWITCH_MAX_CODECS, SWITCH_MAX_CODECS,
globals.codec_order, globals.codec_order,
globals.codec_order_last)) > 0) { globals.codec_order_last)) > 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "NO codecs?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "NO codecs?\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
} else if (!(num_codecs = switch_loadable_module_get_codecs(switch_core_session_get_pool(tech_pvt->session), codecs, SWITCH_MAX_CODECS)) > 0) { } else
if (!
(num_codecs =
switch_loadable_module_get_codecs(switch_core_session_get_pool(tech_pvt->session), codecs,
SWITCH_MAX_CODECS)) > 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "NO codecs?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "NO codecs?\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
@ -260,7 +267,7 @@ static switch_status iax_set_codec(struct private_object *tech_pvt, struct iax_s
len = iax_pref_codec_get(iax_session, prefs, sizeof(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*/ if (len) { /*they sent us a pref and we don't want to be codec master */
char pref_str[256] = "("; char pref_str[256] = "(";
for (x = 0; x < len; x++) { for (x = 0; x < len; x++) {
@ -283,7 +290,7 @@ static switch_status iax_set_codec(struct private_object *tech_pvt, struct iax_s
} }
} }
} else { } else {
if (*format & mixed_cap) { /* is the one we asked for here? */ if (*format & mixed_cap) { /* is the one we asked for here? */
chosen = *format; chosen = *format;
for (x = 0; x < num_codecs; x++) { for (x = 0; x < num_codecs; x++) {
unsigned int cap = iana2ast(codecs[x]->ianacode); unsigned int cap = iana2ast(codecs[x]->ianacode);
@ -291,7 +298,7 @@ static switch_status iax_set_codec(struct private_object *tech_pvt, struct iax_s
dname = codecs[x]->iananame; dname = codecs[x]->iananame;
} }
} }
} else { /* c'mon there has to be SOMETHING...*/ } else { /* c'mon there has to be SOMETHING... */
for (x = 0; x < num_codecs; x++) { for (x = 0; x < num_codecs; x++) {
unsigned int cap = iana2ast(codecs[x]->ianacode); unsigned int cap = iana2ast(codecs[x]->ianacode);
if (cap & mixed_cap) { if (cap & mixed_cap) {
@ -344,9 +351,8 @@ static switch_status iax_set_codec(struct private_object *tech_pvt, struct iax_s
srate, srate,
0, 0,
1, 1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} else { } else {
@ -355,9 +361,8 @@ static switch_status iax_set_codec(struct private_object *tech_pvt, struct iax_s
srate, srate,
0, 0,
1, 1,
SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_core_codec_destroy(&tech_pvt->read_codec); switch_core_codec_destroy(&tech_pvt->read_codec);
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
@ -392,9 +397,12 @@ static switch_status channel_on_hangup(switch_core_session *session);
static switch_status channel_on_ring(switch_core_session *session); static switch_status channel_on_ring(switch_core_session *session);
static switch_status channel_on_loopback(switch_core_session *session); static switch_status channel_on_loopback(switch_core_session *session);
static switch_status channel_on_transmit(switch_core_session *session); static switch_status channel_on_transmit(switch_core_session *session);
static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session); static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id); switch_core_session **new_session);
static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id); static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id);
static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id);
static switch_status channel_kill_channel(switch_core_session *session, int sig); static switch_status channel_kill_channel(switch_core_session *session, int sig);
@ -551,7 +559,8 @@ static switch_status channel_on_transmit(switch_core_session *session)
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines /* 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! that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
*/ */
static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session) static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
switch_core_session **new_session)
{ {
if ((*new_session = switch_core_session_request(&channel_endpoint_interface, NULL))) { if ((*new_session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
struct private_object *tech_pvt; struct private_object *tech_pvt;
@ -561,7 +570,8 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit
unsigned short samprate = 0; unsigned short samprate = 0;
switch_core_session_add_stream(*new_session, NULL); switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) { if ((tech_pvt =
(struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt)); memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(*new_session); channel = switch_core_session_get_channel(*new_session);
switch_core_session_set_private(*new_session, tech_pvt); switch_core_session_set_private(*new_session, tech_pvt);
@ -601,10 +611,8 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit
} }
iax_call(tech_pvt->iax_session, iax_call(tech_pvt->iax_session,
caller_profile->caller_id_number, caller_profile->caller_id_number,
caller_profile->caller_id_name, caller_profile->caller_id_name, caller_profile->destination_number, NULL, 0, req, cap);
caller_profile->destination_number,
NULL, 0, req, cap);
switch_channel_set_flag(channel, CF_OUTBOUND); switch_channel_set_flag(channel, CF_OUTBOUND);
switch_set_flag(tech_pvt, TFLAG_OUTBOUND); switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
@ -645,7 +653,7 @@ static switch_status channel_send_dtmf(switch_core_session *session, char *dtmf)
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
if (tech_pvt->iax_session) { if (tech_pvt->iax_session) {
for(digit = dtmf; *digit; digit++) { for (digit = dtmf; *digit; digit++) {
iax_send_dtmf(tech_pvt->iax_session, *digit); iax_send_dtmf(tech_pvt->iax_session, *digit);
} }
} }
@ -653,7 +661,8 @@ static switch_status channel_send_dtmf(switch_core_session *session, char *dtmf)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id) static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
switch_channel *channel = NULL; switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
@ -673,7 +682,7 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) { if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
switch_clear_flag(tech_pvt, TFLAG_VOICE); switch_clear_flag(tech_pvt, TFLAG_VOICE);
if(!tech_pvt->read_frame.datalen) { if (!tech_pvt->read_frame.datalen) {
continue; continue;
} }
@ -687,7 +696,8 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id) static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
switch_channel *channel = NULL; switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
@ -699,16 +709,16 @@ static switch_status channel_write_frame(switch_core_session *session, switch_fr
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
if(!switch_test_flag(tech_pvt, TFLAG_IO)) { if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
#ifndef BIGENDIAN #ifndef BIGENDIAN
if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
switch_swap_linear(frame->data, (int)frame->datalen / 2); switch_swap_linear(frame->data, (int) frame->datalen / 2);
} }
#endif #endif
iax_send_voice(tech_pvt->iax_session, tech_pvt->codec, frame->data, (int)frame->datalen, tech_pvt->write_codec.implementation->samples_per_frame); iax_send_voice(tech_pvt->iax_session, tech_pvt->codec, frame->data, (int) frame->datalen,
tech_pvt->write_codec.implementation->samples_per_frame);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -732,44 +742,45 @@ static switch_status channel_answer_channel(switch_core_session *session)
} }
static const switch_event_handler_table channel_event_handlers = { static const switch_event_handler_table channel_event_handlers = {
/*.on_init*/ channel_on_init, /*.on_init */ channel_on_init,
/*.on_ring*/ channel_on_ring, /*.on_ring */ channel_on_ring,
/*.on_execute*/ channel_on_execute, /*.on_execute */ channel_on_execute,
/*.on_hangup*/ channel_on_hangup, /*.on_hangup */ channel_on_hangup,
/*.on_loopback*/ channel_on_loopback, /*.on_loopback */ channel_on_loopback,
/*.on_transmit*/ channel_on_transmit /*.on_transmit */ channel_on_transmit
}; };
static const switch_io_routines channel_io_routines = { static const switch_io_routines channel_io_routines = {
/*.outgoing_channel*/ channel_outgoing_channel, /*.outgoing_channel */ channel_outgoing_channel,
/*.answer_channel*/ channel_answer_channel, /*.answer_channel */ channel_answer_channel,
/*.read_frame*/ channel_read_frame, /*.read_frame */ channel_read_frame,
/*.write_frame*/ channel_write_frame, /*.write_frame */ channel_write_frame,
/*.kill_channel*/ channel_kill_channel, /*.kill_channel */ channel_kill_channel,
/*.waitfor_read*/ channel_waitfor_read, /*.waitfor_read */ channel_waitfor_read,
/*.waitfor_write*/ channel_waitfor_write, /*.waitfor_write */ channel_waitfor_write,
/*.send_dtmf*/ channel_send_dtmf /*.send_dtmf */ channel_send_dtmf
}; };
static const switch_endpoint_interface channel_endpoint_interface = { static const switch_endpoint_interface channel_endpoint_interface = {
/*.interface_name*/ "iax", /*.interface_name */ "iax",
/*.io_routines*/ &channel_io_routines, /*.io_routines */ &channel_io_routines,
/*.event_handlers*/ &channel_event_handlers, /*.event_handlers */ &channel_event_handlers,
/*.private*/ NULL, /*.private */ NULL,
/*.next*/ NULL /*.next */ NULL
}; };
static const switch_loadable_module_interface channel_module_interface = { static const switch_loadable_module_interface channel_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ &channel_endpoint_interface, /*.endpoint_interface */ &channel_endpoint_interface,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) { if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OH OH no pool\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OH OH no pool\n");
@ -820,10 +831,12 @@ static switch_status load_config(void)
set_global_dialplan(val); set_global_dialplan(val);
} else if (!strcmp(var, "codec_prefs")) { } else if (!strcmp(var, "codec_prefs")) {
set_global_codec_string(val); set_global_codec_string(val);
globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS); globals.codec_order_last =
switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS);
} else if (!strcmp(var, "codec_rates")) { } else if (!strcmp(var, "codec_rates")) {
set_global_codec_rates_string(val); set_global_codec_rates_string(val);
globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS); globals.codec_rates_last =
switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS);
} }
} }
} }
@ -864,13 +877,13 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "IAX Ready Port %d\n", globals.port); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "IAX Ready Port %d\n", globals.port);
for(;;) { for (;;) {
if (running == -1) { if (running == -1) {
break; break;
} }
/* Wait for an event.*/ /* Wait for an event. */
if ((iaxevent = iax_get_event(0)) == NULL) { if ((iaxevent = iax_get_event(0)) == NULL) {
switch_yield(1000); switch_yield(1000);
continue; continue;
@ -879,173 +892,182 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
if (globals.debug && iaxevent->etype != IAX_EVENT_VOICE) { if (globals.debug && iaxevent->etype != IAX_EVENT_VOICE) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Event %d [%s]!\n", switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Event %d [%s]!\n",
iaxevent->etype, IAXNAMES[iaxevent->etype]); iaxevent->etype, IAXNAMES[iaxevent->etype]);
} }
switch (iaxevent->etype) { switch (iaxevent->etype) {
case IAX_EVENT_REGACK: case IAX_EVENT_REGACK:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Registration completed successfully.\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Registration completed successfully.\n");
if (iaxevent->ies.refresh) refresh = iaxevent->ies.refresh; if (iaxevent->ies.refresh)
break; refresh = iaxevent->ies.refresh;
case IAX_EVENT_REGREJ: break;
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Registration failed.\n"); case IAX_EVENT_REGREJ:
break; switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Registration failed.\n");
case IAX_EVENT_TIMEOUT: break;
break; case IAX_EVENT_TIMEOUT:
case IAX_EVENT_ACCEPT: break;
if (tech_pvt) { case IAX_EVENT_ACCEPT:
unsigned int cap = iax_session_get_capability(iaxevent->session); if (tech_pvt) {
unsigned int format = iaxevent->ies.format; unsigned int cap = iax_session_get_capability(iaxevent->session);
unsigned int format = iaxevent->ies.format;
if (iax_set_codec(tech_pvt, iaxevent->session, &format, &cap, &iaxevent->ies.samprate, IAX_SET) != SWITCH_STATUS_SUCCESS) { if (iax_set_codec(tech_pvt, iaxevent->session, &format, &cap, &iaxevent->ies.samprate, IAX_SET) !=
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WTF? %d %d\n",iaxevent->ies.format, iaxevent->ies.capability); SWITCH_STATUS_SUCCESS) {
} switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WTF? %d %d\n", iaxevent->ies.format,
iaxevent->ies.capability);
} }
}
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Call accepted.\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Call accepted.\n");
break; break;
case IAX_EVENT_RINGA: case IAX_EVENT_RINGA:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Ringing heard.\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Ringing heard.\n");
break; break;
case IAX_EVENT_PONG: case IAX_EVENT_PONG:
// informative only // informative only
break; break;
case IAX_EVENT_ANSWER: case IAX_EVENT_ANSWER:
// the other side answered our call // the other side answered our call
if (tech_pvt) { if (tech_pvt) {
switch_channel *channel; switch_channel *channel;
if ((channel = switch_core_session_get_channel(tech_pvt->session))) { if ((channel = switch_core_session_get_channel(tech_pvt->session))) {
if (switch_channel_test_flag(channel, CF_ANSWERED)) { if (switch_channel_test_flag(channel, CF_ANSWERED)) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WTF Mutiple Answer %s?\n", switch_channel_get_name(channel)); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WTF Mutiple Answer %s?\n",
} else { switch_channel_get_name(channel));
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Answer %s\n", switch_channel_get_name(channel));
switch_channel_answer(channel);
}
}
}
break;
case IAX_EVENT_CONNECT:
// incoming call detected
switch_console_printf(SWITCH_CHANNEL_CONSOLE,
"Incoming call connected %s, %s, %s %d/%d\n",
iaxevent->ies.called_number,
iaxevent->ies.calling_number,
iaxevent->ies.calling_name,
iaxevent->ies.format,
iaxevent->ies.capability);
if (iaxevent) {
switch_core_session *session;
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "New Inbound Channel %s!\n", iaxevent->ies.calling_name);
if ((session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
struct private_object *tech_pvt;
switch_channel *channel;
switch_core_session_add_stream(session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(session);
switch_core_session_set_private(session, tech_pvt);
tech_pvt->session = session;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
switch_core_session_destroy(&session);
break;
}
if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan,
iaxevent->ies.calling_name,
iaxevent->ies.calling_number,
iax_get_peer_ip(iaxevent->session),
iaxevent->ies.calling_ani,
NULL,
iaxevent->ies.called_number))) {
char name[128];
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
snprintf(name, sizeof(name), "IAX/%s-%04x", tech_pvt->caller_profile->destination_number, rand() & 0xffff);
switch_channel_set_name(channel, name);
}
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);
switch_core_session_thread_launch(session);
}
}
}
break;
case IAX_EVENT_REJECT:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Rejected call.\n");
case IAX_EVENT_BUSY:
case IAX_EVENT_HANGUP:
if (tech_pvt) {
switch_channel *channel;
switch_clear_flag(tech_pvt, TFLAG_IO);
switch_clear_flag(tech_pvt, TFLAG_VOICE);
if ((channel = switch_core_session_get_channel(tech_pvt->session))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hangup %s\n", switch_channel_get_name(channel));
switch_set_flag(tech_pvt, TFLAG_HANGUP);
switch_channel_hangup(channel);
//switch_thread_cond_signal(tech_pvt->cond);
iaxevent->session = NULL;
} else { } else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Session? %s\n", switch_test_flag(tech_pvt, TFLAG_VOICE) ? "yes" : "no"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Answer %s\n",
} switch_channel_get_name(channel));
} switch_channel_answer(channel);
break;
case IAX_EVENT_CNG:
// pseudo-silence
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "sending silence\n");
break;
case IAX_EVENT_VOICE:
if (tech_pvt && (tech_pvt->read_frame.datalen = iaxevent->datalen)) {
switch_channel *channel;
if ((channel = switch_core_session_get_channel(tech_pvt->session)) && switch_channel_get_state(channel) <= CS_HANGUP) {
int bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
int frames = (int)(tech_pvt->read_frame.datalen / bytes);
tech_pvt->read_frame.samples = frames * tech_pvt->read_codec.implementation->samples_per_frame;
memcpy(tech_pvt->read_frame.data, iaxevent->data, iaxevent->datalen);
/* wake up the i/o thread*/
switch_set_flag(tech_pvt, TFLAG_VOICE);
//switch_thread_cond_signal(tech_pvt->cond);
}
}
break;
case IAX_EVENT_TRANSFER:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Call transfer occurred.\n");
//session[0] = iaxevent->session;
break;
case IAX_EVENT_DTMF:
if (tech_pvt) {
switch_channel *channel;
if ((channel = switch_core_session_get_channel(tech_pvt->session))) {
char str[2] = {iaxevent->subclass};
if (globals.debug) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s DTMF %s\n", str, switch_channel_get_name(channel));
}
switch_channel_queue_dtmf(channel, str);
} }
} }
}
break; break;
default: case IAX_EVENT_CONNECT:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Don't know what to do with IAX event %d.\n", iaxevent->etype); // incoming call detected
break; switch_console_printf(SWITCH_CHANNEL_CONSOLE,
"Incoming call connected %s, %s, %s %d/%d\n",
iaxevent->ies.called_number,
iaxevent->ies.calling_number,
iaxevent->ies.calling_name, iaxevent->ies.format, iaxevent->ies.capability);
if (iaxevent) {
switch_core_session *session;
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "New Inbound Channel %s!\n",
iaxevent->ies.calling_name);
if ((session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
struct private_object *tech_pvt;
switch_channel *channel;
switch_core_session_add_stream(session, NULL);
if ((tech_pvt =
(struct private_object *) switch_core_session_alloc(session,
sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(session);
switch_core_session_set_private(session, tech_pvt);
tech_pvt->session = session;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
switch_core_session_destroy(&session);
break;
}
if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan,
iaxevent->ies.calling_name,
iaxevent->ies.calling_number,
iax_get_peer_ip(iaxevent->session),
iaxevent->ies.calling_ani,
NULL, iaxevent->ies.called_number))) {
char name[128];
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
snprintf(name, sizeof(name), "IAX/%s-%04x", tech_pvt->caller_profile->destination_number,
rand() & 0xffff);
switch_channel_set_name(channel, name);
}
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);
switch_core_session_thread_launch(session);
}
}
}
break;
case IAX_EVENT_REJECT:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Rejected call.\n");
case IAX_EVENT_BUSY:
case IAX_EVENT_HANGUP:
if (tech_pvt) {
switch_channel *channel;
switch_clear_flag(tech_pvt, TFLAG_IO);
switch_clear_flag(tech_pvt, TFLAG_VOICE);
if ((channel = switch_core_session_get_channel(tech_pvt->session))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hangup %s\n", switch_channel_get_name(channel));
switch_set_flag(tech_pvt, TFLAG_HANGUP);
switch_channel_hangup(channel);
//switch_thread_cond_signal(tech_pvt->cond);
iaxevent->session = NULL;
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Session? %s\n",
switch_test_flag(tech_pvt, TFLAG_VOICE) ? "yes" : "no");
}
}
break;
case IAX_EVENT_CNG:
// pseudo-silence
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "sending silence\n");
break;
case IAX_EVENT_VOICE:
if (tech_pvt && (tech_pvt->read_frame.datalen = iaxevent->datalen)) {
switch_channel *channel;
if ((channel = switch_core_session_get_channel(tech_pvt->session))
&& switch_channel_get_state(channel) <= CS_HANGUP) {
int bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
int frames = (int) (tech_pvt->read_frame.datalen / bytes);
tech_pvt->read_frame.samples = frames * tech_pvt->read_codec.implementation->samples_per_frame;
memcpy(tech_pvt->read_frame.data, iaxevent->data, iaxevent->datalen);
/* wake up the i/o thread */
switch_set_flag(tech_pvt, TFLAG_VOICE);
//switch_thread_cond_signal(tech_pvt->cond);
}
}
break;
case IAX_EVENT_TRANSFER:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Call transfer occurred.\n");
//session[0] = iaxevent->session;
break;
case IAX_EVENT_DTMF:
if (tech_pvt) {
switch_channel *channel;
if ((channel = switch_core_session_get_channel(tech_pvt->session))) {
char str[2] = { iaxevent->subclass };
if (globals.debug) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s DTMF %s\n", str,
switch_channel_get_name(channel));
}
switch_channel_queue_dtmf(channel, str);
}
}
break;
default:
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Don't know what to do with IAX event %d.\n",
iaxevent->etype);
break;
} }
iax_event_free(iaxevent); iax_event_free(iaxevent);
@ -1075,4 +1097,3 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -65,9 +65,12 @@ static switch_status channel_on_hangup(switch_core_session *session);
static switch_status channel_on_ring(switch_core_session *session); static switch_status channel_on_ring(switch_core_session *session);
static switch_status channel_on_loopback(switch_core_session *session); static switch_status channel_on_loopback(switch_core_session *session);
static switch_status channel_on_transmit(switch_core_session *session); static switch_status channel_on_transmit(switch_core_session *session);
static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session); static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id); switch_core_session **new_session);
static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id); static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id);
static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id);
static switch_status channel_kill_channel(switch_core_session *session, int sig); static switch_status channel_kill_channel(switch_core_session *session, int sig);
@ -177,7 +180,8 @@ static switch_status channel_on_transmit(switch_core_session *session)
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines /* 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! that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
*/ */
static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session) static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
switch_core_session **new_session)
{ {
if ((*new_session = switch_core_session_request(&channel_endpoint_interface, NULL))) { if ((*new_session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
struct private_object *tech_pvt; struct private_object *tech_pvt;
@ -185,7 +189,8 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit
switch_caller_profile *caller_profile, *originator_caller_profile = NULL; switch_caller_profile *caller_profile, *originator_caller_profile = NULL;
switch_core_session_add_stream(*new_session, NULL); switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) { if ((tech_pvt =
(struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt)); memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(*new_session); channel = switch_core_session_get_channel(*new_session);
switch_core_session_set_private(*new_session, tech_pvt); switch_core_session_set_private(*new_session, tech_pvt);
@ -250,7 +255,8 @@ static switch_status channel_waitfor_write(switch_core_session *session, int ms,
} }
static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id) static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
switch_channel *channel = NULL; switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
@ -266,7 +272,8 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id) static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
switch_channel *channel = NULL; switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
@ -283,39 +290,39 @@ static switch_status channel_write_frame(switch_core_session *session, switch_fr
} }
static const switch_event_handler_table channel_event_handlers = { static const switch_event_handler_table channel_event_handlers = {
/*.on_init*/ channel_on_init, /*.on_init */ channel_on_init,
/*.on_ring*/ channel_on_ring, /*.on_ring */ channel_on_ring,
/*.on_execute*/ channel_on_execute, /*.on_execute */ channel_on_execute,
/*.on_hangup*/ channel_on_hangup, /*.on_hangup */ channel_on_hangup,
/*.on_loopback*/ channel_on_loopback, /*.on_loopback */ channel_on_loopback,
/*.on_transmit*/ channel_on_transmit /*.on_transmit */ channel_on_transmit
}; };
static const switch_io_routines channel_io_routines = { static const switch_io_routines channel_io_routines = {
/*.outgoing_channel*/ channel_outgoing_channel, /*.outgoing_channel */ channel_outgoing_channel,
/*.answer_channel*/ NULL, /*.answer_channel */ NULL,
/*.read_frame*/ channel_read_frame, /*.read_frame */ channel_read_frame,
/*.write_frame*/ channel_write_frame, /*.write_frame */ channel_write_frame,
/*.kill_channel*/ channel_kill_channel, /*.kill_channel */ channel_kill_channel,
/*.waitfor_read*/ channel_waitfor_read, /*.waitfor_read */ channel_waitfor_read,
/*.waitfor_write*/ channel_waitfor_write /*.waitfor_write */ channel_waitfor_write
}; };
static const switch_endpoint_interface channel_endpoint_interface = { static const switch_endpoint_interface channel_endpoint_interface = {
/*.interface_name*/ "opal", /*.interface_name */ "opal",
/*.io_routines*/ &channel_io_routines, /*.io_routines */ &channel_io_routines,
/*.event_handlers*/ &channel_event_handlers, /*.event_handlers */ &channel_event_handlers,
/*.private*/ NULL, /*.private */ NULL,
/*.next*/ NULL /*.next */ NULL
}; };
static const switch_loadable_module_interface channel_module_interface = { static const switch_loadable_module_interface channel_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ &channel_endpoint_interface, /*.endpoint_interface */ &channel_endpoint_interface,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
@ -338,7 +345,8 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
} }
*/ */
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
switch_config cfg; switch_config cfg;
char *var, *val; char *var, *val;

View File

@ -81,51 +81,55 @@ static struct {
struct private_object { struct private_object {
unsigned int flags; unsigned int flags;
switch_codec read_codec; switch_codec read_codec;
switch_codec write_codec; switch_codec write_codec;
struct switch_frame read_frame; struct switch_frame read_frame;
unsigned char databuf[SWITCH_RECCOMMENDED_BUFFER_SIZE]; unsigned char databuf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
switch_core_session *session; switch_core_session *session;
switch_caller_profile *caller_profile; switch_caller_profile *caller_profile;
char call_id[50]; char call_id[50];
PaError err; PaError err;
PABLIO_Stream *audio_in; PABLIO_Stream *audio_in;
PABLIO_Stream *audio_out; PABLIO_Stream *audio_out;
int indev; int indev;
int outdev; int outdev;
}; };
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_name, globals.cid_name) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_name, globals.cid_name)
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_num, globals.cid_num) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_num, globals.cid_num)
static const switch_endpoint_interface channel_endpoint_interface; static const switch_endpoint_interface channel_endpoint_interface;
static switch_status channel_on_init(switch_core_session *session); static switch_status channel_on_init(switch_core_session *session);
static switch_status channel_on_hangup(switch_core_session *session); static switch_status channel_on_hangup(switch_core_session *session);
static switch_status channel_on_ring(switch_core_session *session); static switch_status channel_on_ring(switch_core_session *session);
static switch_status channel_on_loopback(switch_core_session *session); static switch_status channel_on_loopback(switch_core_session *session);
static switch_status channel_on_transmit(switch_core_session *session); static switch_status channel_on_transmit(switch_core_session *session);
static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session); static switch_status channel_outgoing_channel(switch_core_session *session,
static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id); switch_caller_profile *outbound_profile,
static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id); switch_core_session **new_session);
static switch_status channel_kill_channel(switch_core_session *session, int sig); static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
static switch_status engage_device(struct private_object *tech_pvt); switch_io_flag flags, int stream_id);
static int dump_info(void); static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
static switch_status load_config(void); switch_io_flag flags, int stream_id);
static int get_dev_by_name(char *name, int in); static switch_status channel_kill_channel(switch_core_session *session, int sig);
static switch_status place_call(char *dest, char *out, size_t outlen); static switch_status engage_device(struct private_object *tech_pvt);
static switch_status hup_call(char *callid, char *out, size_t outlen); static int dump_info(void);
static switch_status call_info(char *callid, char *out, size_t outlen); static switch_status load_config(void);
static switch_status send_dtmf(char *callid, char *out, size_t outlen); static int get_dev_by_name(char *name, int in);
static switch_status answer_call(char *callid, char *out, size_t outlen); static switch_status place_call(char *dest, char *out, size_t outlen);
static switch_status hup_call(char *callid, char *out, size_t outlen);
static switch_status call_info(char *callid, char *out, size_t outlen);
static switch_status send_dtmf(char *callid, char *out, size_t outlen);
static switch_status answer_call(char *callid, char *out, size_t outlen);
/* /*
State methods they get called when the state changes to the specific state 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 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. so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
*/ */
static switch_status channel_on_init(switch_core_session *session) static switch_status channel_on_init(switch_core_session *session)
{ {
switch_channel *channel; switch_channel *channel;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
@ -264,20 +268,20 @@ static switch_status channel_on_transmit(switch_core_session *session)
/* Turn on the device */ /* Turn on the device */
engage_device(tech_pvt); engage_device(tech_pvt);
while(switch_channel_get_state(channel) == CS_TRANSMIT && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) { while (switch_channel_get_state(channel) == CS_TRANSMIT && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
if (switch_time_now() - last >= waitsec) { if (switch_time_now() - last >= waitsec) {
char buf[512]; char buf[512];
switch_event *event; switch_event *event;
snprintf(buf, sizeof(buf), "BRRRRING! BRRRRING! call %s\n", tech_pvt->call_id); snprintf(buf, sizeof(buf), "BRRRRING! BRRRRING! call %s\n", tech_pvt->call_id);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_RINGING) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_RINGING) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_info", buf); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_info", buf);
switch_event_fire(&event); switch_event_fire(&event);
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s\n", buf); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s\n", buf);
last = switch_time_now(); last = switch_time_now();
} }
switch_yield(50000); switch_yield(50000);
} }
@ -293,7 +297,8 @@ static switch_status channel_on_transmit(switch_core_session *session)
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines /* 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! that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
*/ */
static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session) static switch_status channel_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
switch_core_session **new_session)
{ {
if ((*new_session = switch_core_session_request(&channel_endpoint_interface, NULL))) { if ((*new_session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
struct private_object *tech_pvt; struct private_object *tech_pvt;
@ -301,7 +306,8 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit
switch_caller_profile *caller_profile; switch_caller_profile *caller_profile;
switch_core_session_add_stream(*new_session, NULL); switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) { if ((tech_pvt =
(struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt)); memset(tech_pvt, 0, sizeof(*tech_pvt));
channel = switch_core_session_get_channel(*new_session); channel = switch_core_session_get_channel(*new_session);
switch_core_session_set_private(*new_session, tech_pvt); switch_core_session_set_private(*new_session, tech_pvt);
@ -317,7 +323,9 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
switch_channel_set_caller_profile(channel, caller_profile); switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile; tech_pvt->caller_profile = caller_profile;
snprintf(name, sizeof(name), "PortAudio/%s-%04x", caller_profile->destination_number ? caller_profile->destination_number : modname, rand() & 0xffff); snprintf(name, sizeof(name), "PortAudio/%s-%04x",
caller_profile->destination_number ? caller_profile->destination_number : modname,
rand() & 0xffff);
switch_channel_set_name(channel, name); switch_channel_set_name(channel, name);
} else { } else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Doh! no caller profile\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Doh! no caller profile\n");
@ -365,10 +373,11 @@ static switch_status channel_send_dtmf(switch_core_session *session, char *dtmf)
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "DTMF ON CALL %s [%s]\n", tech_pvt->call_id, dtmf); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "DTMF ON CALL %s [%s]\n", tech_pvt->call_id, dtmf);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id) static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
switch_channel *channel = NULL; switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
@ -387,8 +396,10 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
switch_mutex_lock(globals.device_lock); switch_mutex_lock(globals.device_lock);
if (tech_pvt->audio_in && if (tech_pvt->audio_in &&
(samples = ReadAudioStream(tech_pvt->audio_in, tech_pvt->read_frame.data, tech_pvt->read_codec.implementation->samples_per_frame))) { (samples =
ReadAudioStream(tech_pvt->audio_in, tech_pvt->read_frame.data,
tech_pvt->read_codec.implementation->samples_per_frame))) {
tech_pvt->read_frame.datalen = samples * 2; tech_pvt->read_frame.datalen = samples * 2;
tech_pvt->read_frame.samples = samples; tech_pvt->read_frame.samples = samples;
*frame = &tech_pvt->read_frame; *frame = &tech_pvt->read_frame;
@ -399,7 +410,8 @@ static switch_status channel_read_frame(switch_core_session *session, switch_fra
return status; return status;
} }
static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id) static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
switch_channel *channel = NULL; switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
@ -410,13 +422,12 @@ static switch_status channel_write_frame(switch_core_session *session, switch_fr
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); assert(tech_pvt != NULL);
if(!switch_test_flag(tech_pvt, TFLAG_IO)) { if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
//switch_mutex_lock(globals.device_lock); //switch_mutex_lock(globals.device_lock);
if (tech_pvt->audio_out) { if (tech_pvt->audio_out) {
WriteAudioStream(tech_pvt->audio_out, (short *)frame->data, (int)(frame->datalen / sizeof(SAMPLE))); WriteAudioStream(tech_pvt->audio_out, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)));
status = SWITCH_STATUS_SUCCESS; status = SWITCH_STATUS_SUCCESS;
} }
//switch_mutex_unlock(globals.device_lock); //switch_mutex_unlock(globals.device_lock);
@ -441,82 +452,83 @@ static switch_status channel_answer_channel(switch_core_session *session)
static struct switch_api_interface send_dtmf_interface = { static struct switch_api_interface send_dtmf_interface = {
/*.interface_name*/ "padtmf", /*.interface_name */ "padtmf",
/*.desc*/ "PortAudio Dial DTMF", /*.desc */ "PortAudio Dial DTMF",
/*.function*/ send_dtmf, /*.function */ send_dtmf,
/*.next*/ NULL /*.next */ NULL
}; };
static struct switch_api_interface answer_call_interface = { static struct switch_api_interface answer_call_interface = {
/*.interface_name*/ "paoffhook", /*.interface_name */ "paoffhook",
/*.desc*/ "PortAudio Answer Call", /*.desc */ "PortAudio Answer Call",
/*.function*/ answer_call, /*.function */ answer_call,
/*.next*/ &send_dtmf_interface /*.next */ &send_dtmf_interface
}; };
static struct switch_api_interface channel_info_interface = { static struct switch_api_interface channel_info_interface = {
/*.interface_name*/ "painfo", /*.interface_name */ "painfo",
/*.desc*/ "PortAudio Call Info", /*.desc */ "PortAudio Call Info",
/*.function*/ call_info, /*.function */ call_info,
/*.next*/ &answer_call_interface /*.next */ &answer_call_interface
}; };
static struct switch_api_interface channel_hup_interface = { static struct switch_api_interface channel_hup_interface = {
/*.interface_name*/ "pahup", /*.interface_name */ "pahup",
/*.desc*/ "PortAudio Hangup Call", /*.desc */ "PortAudio Hangup Call",
/*.function*/ hup_call, /*.function */ hup_call,
/*.next*/ &channel_info_interface /*.next */ &channel_info_interface
}; };
static struct switch_api_interface channel_api_interface = { static struct switch_api_interface channel_api_interface = {
/*.interface_name*/ "pacall", /*.interface_name */ "pacall",
/*.desc*/ "PortAudio Call", /*.desc */ "PortAudio Call",
/*.function*/ place_call, /*.function */ place_call,
/*.next*/ &channel_hup_interface /*.next */ &channel_hup_interface
}; };
static const switch_event_handler_table channel_event_handlers = { static const switch_event_handler_table channel_event_handlers = {
/*.on_init*/ channel_on_init, /*.on_init */ channel_on_init,
/*.on_ring*/ channel_on_ring, /*.on_ring */ channel_on_ring,
/*.on_execute*/ channel_on_execute, /*.on_execute */ channel_on_execute,
/*.on_hangup*/ channel_on_hangup, /*.on_hangup */ channel_on_hangup,
/*.on_loopback*/ channel_on_loopback, /*.on_loopback */ channel_on_loopback,
/*.on_transmit*/ channel_on_transmit /*.on_transmit */ channel_on_transmit
}; };
static const switch_io_routines channel_io_routines = { static const switch_io_routines channel_io_routines = {
/*.outgoing_channel*/ channel_outgoing_channel, /*.outgoing_channel */ channel_outgoing_channel,
/*.answer_channel*/ channel_answer_channel, /*.answer_channel */ channel_answer_channel,
/*.read_frame*/ channel_read_frame, /*.read_frame */ channel_read_frame,
/*.write_frame*/ channel_write_frame, /*.write_frame */ channel_write_frame,
/*.kill_channel*/ channel_kill_channel, /*.kill_channel */ channel_kill_channel,
/*.waitfor_read*/ channel_waitfor_read, /*.waitfor_read */ channel_waitfor_read,
/*.waitfor_write*/ channel_waitfor_write, /*.waitfor_write */ channel_waitfor_write,
/*.send_dtmf*/ channel_send_dtmf /*.send_dtmf */ channel_send_dtmf
}; };
static const switch_endpoint_interface channel_endpoint_interface = { static const switch_endpoint_interface channel_endpoint_interface = {
/*.interface_name*/ "portaudio", /*.interface_name */ "portaudio",
/*.io_routines*/ &channel_io_routines, /*.io_routines */ &channel_io_routines,
/*.event_handlers*/ &channel_event_handlers, /*.event_handlers */ &channel_event_handlers,
/*.private*/ NULL, /*.private */ NULL,
/*.next*/ NULL /*.next */ NULL
}; };
static const switch_loadable_module_interface channel_module_interface = { static const switch_loadable_module_interface channel_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ &channel_endpoint_interface, /*.endpoint_interface */ &channel_endpoint_interface,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL, /*.application_interface */ NULL,
/*.api_interface*/ &channel_api_interface /*.api_interface */ &channel_api_interface
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) { if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OH OH no pool\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OH OH no pool\n");
@ -571,13 +583,13 @@ static switch_status load_config(void)
set_global_cid_num(val); set_global_cid_num(val);
} else if (!strcmp(var, "indev")) { } else if (!strcmp(var, "indev")) {
if (*val == '#') { if (*val == '#') {
globals.indev = atoi(val+1); globals.indev = atoi(val + 1);
} else { } else {
globals.indev = get_dev_by_name(val, 1); globals.indev = get_dev_by_name(val, 1);
} }
} else if (!strcmp(var, "outdev")) { } else if (!strcmp(var, "outdev")) {
if (*val == '#') { if (*val == '#') {
globals.outdev = atoi(val+1); globals.outdev = atoi(val + 1);
} else { } else {
globals.outdev = get_dev_by_name(val, 0); globals.outdev = get_dev_by_name(val, 0);
} }
@ -610,7 +622,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void) SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
{ {
Pa_Terminate(); Pa_Terminate();
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -618,20 +630,20 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
static int get_dev_by_name(char *name, int in) static int get_dev_by_name(char *name, int in)
{ {
int i; int i;
int numDevices; int numDevices;
const PaDeviceInfo *pdi; const PaDeviceInfo *pdi;
numDevices = Pa_CountDevices(); numDevices = Pa_CountDevices();
if( numDevices < 0 ) { if (numDevices < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices ); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices);
return -2; return -2;
} }
for( i=0; i<numDevices; i++ ) { for (i = 0; i < numDevices; i++) {
pdi = Pa_GetDeviceInfo( i ); pdi = Pa_GetDeviceInfo(i);
if(strstr(pdi->name, name)) { if (strstr(pdi->name, name)) {
if(in && pdi->maxInputChannels) { if (in && pdi->maxInputChannels) {
return i; return i;
} else if (!in && pdi->maxOutputChannels) { } else if (!in && pdi->maxOutputChannels) {
return i; return i;
@ -644,58 +656,62 @@ static int get_dev_by_name(char *name, int in)
static int dump_info(void) static int dump_info(void)
{ {
int i,j; int i, j;
int numDevices; int numDevices;
const PaDeviceInfo *pdi; const PaDeviceInfo *pdi;
PaError err; PaError err;
numDevices = Pa_CountDevices(); numDevices = Pa_CountDevices();
if( numDevices < 0 ) if (numDevices < 0) {
{ switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices);
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "ERROR: Pa_CountDevices returned 0x%x\n", numDevices ); err = numDevices;
err = numDevices; goto error;
goto error; }
} switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Number of devices = %d\n", numDevices);
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Number of devices = %d\n", numDevices ); for (i = 0; i < numDevices; i++) {
for( i=0; i<numDevices; i++ ) pdi = Pa_GetDeviceInfo(i);
{ switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "---------------------------------------------- #%d", i);
pdi = Pa_GetDeviceInfo( i ); if (i == Pa_GetDefaultInputDeviceID())
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "---------------------------------------------- #%d", i ); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, " DefaultInput");
if( i == Pa_GetDefaultInputDeviceID() ) switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, " DefaultInput"); if (i == Pa_GetDefaultOutputDeviceID())
if( i == Pa_GetDefaultOutputDeviceID() ) switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, " DefaultOutput"); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, " DefaultOutput");
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "\nName = %s\n", pdi->name ); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "\nName = %s\n", pdi->name);
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Max Inputs = %d", pdi->maxInputChannels ); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Max Inputs = %d", pdi->maxInputChannels);
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, ", Max Outputs = %d\n", pdi->maxOutputChannels ); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, ", Max Outputs = %d\n", pdi->maxOutputChannels);
if( pdi->numSampleRates == -1 ) if (pdi->numSampleRates == -1) {
{ switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Sample Rate Range = %f to %f\n", pdi->sampleRates[0],
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Sample Rate Range = %f to %f\n", pdi->sampleRates[0], pdi->sampleRates[1] ); pdi->sampleRates[1]);
} } else {
else switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Sample Rates =");
{ for (j = 0; j < pdi->numSampleRates; j++) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Sample Rates ="); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, " %8.2f,", pdi->sampleRates[j]);
for( j=0; j<pdi->numSampleRates; j++ ) }
{ switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "\n");
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, " %8.2f,", pdi->sampleRates[j] ); }
} switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Native Sample Formats = ");
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "\n"); if (pdi->nativeSampleFormats & paInt8)
} switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paInt8, ");
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Native Sample Formats = "); if (pdi->nativeSampleFormats & paUInt8)
if( pdi->nativeSampleFormats & paInt8 ) switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paInt8, "); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paUInt8, ");
if( pdi->nativeSampleFormats & paUInt8 ) switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paUInt8, "); if (pdi->nativeSampleFormats & paInt16)
if( pdi->nativeSampleFormats & paInt16 ) switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paInt16, "); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paInt16, ");
if( pdi->nativeSampleFormats & paInt32 ) switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paInt32, "); if (pdi->nativeSampleFormats & paInt32)
if( pdi->nativeSampleFormats & paFloat32 ) switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paFloat32, "); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paInt32, ");
if( pdi->nativeSampleFormats & paInt24 ) switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paInt24, "); if (pdi->nativeSampleFormats & paFloat32)
if( pdi->nativeSampleFormats & paPackedInt24 ) switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paPackedInt24, "); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paFloat32, ");
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "\n"); if (pdi->nativeSampleFormats & paInt24)
} switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paInt24, ");
if (pdi->nativeSampleFormats & paPackedInt24)
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "paPackedInt24, ");
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "\n");
}
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "----------------------------------------------\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "----------------------------------------------\n");
return 0; return 0;
error: error:
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "An error occured while using the portaudio stream\n" ); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "An error occured while using the portaudio stream\n");
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Error number: %d\n", err ); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Error number: %d\n", err);
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Error message: %s\n", Pa_GetErrorText( err ) ); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Error message: %s\n", Pa_GetErrorText(err));
return err; return err;
} }
static switch_status engage_device(struct private_object *tech_pvt) static switch_status engage_device(struct private_object *tech_pvt)
@ -713,56 +729,59 @@ static switch_status engage_device(struct private_object *tech_pvt)
codec_ms, codec_ms,
1, 1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
return SWITCH_STATUS_FALSE;
} else {
if (switch_core_codec_init(&tech_pvt->write_codec,
"L16",
sample_rate,
codec_ms,
1,
SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE,
NULL,
switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_core_codec_destroy(&tech_pvt->read_codec);
return SWITCH_STATUS_FALSE;
}
}
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Loaded codec L16 %dhz %dms on %s\n", sample_rate, codec_ms, switch_channel_get_name(channel));
tech_pvt->read_frame.rate = sample_rate;
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
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);
tech_pvt->indev = globals.indev;
tech_pvt->outdev = globals.outdev;
switch_mutex_lock(globals.device_lock);
if ((tech_pvt->err = OpenAudioStream( &tech_pvt->audio_in, sample_rate, SAMPLE_TYPE, PABLIO_READ | PABLIO_MONO, tech_pvt->indev, -1)) == paNoError) {
if ((tech_pvt->err = OpenAudioStream(&tech_pvt->audio_out, sample_rate, SAMPLE_TYPE, PABLIO_WRITE | PABLIO_MONO, -1, tech_pvt->outdev)) != paNoError) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio out [%d]!\n", tech_pvt->outdev);
CloseAudioStream(tech_pvt->audio_in);
tech_pvt->audio_in = NULL;
}
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio in [%d]!\n", tech_pvt->indev);
}
switch_mutex_unlock(globals.device_lock);
if (tech_pvt->err == paNoError) {
snprintf(tech_pvt->call_id, sizeof(tech_pvt->call_id), "%d", globals.call_id++);
switch_core_hash_insert(globals.call_hash, tech_pvt->call_id, tech_pvt);
return SWITCH_STATUS_SUCCESS;
} else {
switch_core_codec_destroy(&tech_pvt->read_codec);
switch_core_codec_destroy(&tech_pvt->write_codec);
switch_core_session_destroy(&tech_pvt->session);
}
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} else {
if (switch_core_codec_init(&tech_pvt->write_codec,
"L16",
sample_rate,
codec_ms,
1,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_core_codec_destroy(&tech_pvt->read_codec);
return SWITCH_STATUS_FALSE;
}
}
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Loaded codec L16 %dhz %dms on %s\n", sample_rate, codec_ms,
switch_channel_get_name(channel));
tech_pvt->read_frame.rate = sample_rate;
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
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);
tech_pvt->indev = globals.indev;
tech_pvt->outdev = globals.outdev;
switch_mutex_lock(globals.device_lock);
if ((tech_pvt->err =
OpenAudioStream(&tech_pvt->audio_in, sample_rate, SAMPLE_TYPE, PABLIO_READ | PABLIO_MONO, tech_pvt->indev,
-1)) == paNoError) {
if ((tech_pvt->err =
OpenAudioStream(&tech_pvt->audio_out, sample_rate, SAMPLE_TYPE, PABLIO_WRITE | PABLIO_MONO, -1,
tech_pvt->outdev)) != paNoError) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio out [%d]!\n", tech_pvt->outdev);
CloseAudioStream(tech_pvt->audio_in);
tech_pvt->audio_in = NULL;
}
} else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open audio in [%d]!\n", tech_pvt->indev);
}
switch_mutex_unlock(globals.device_lock);
if (tech_pvt->err == paNoError) {
snprintf(tech_pvt->call_id, sizeof(tech_pvt->call_id), "%d", globals.call_id++);
switch_core_hash_insert(globals.call_hash, tech_pvt->call_id, tech_pvt);
return SWITCH_STATUS_SUCCESS;
} else {
switch_core_codec_destroy(&tech_pvt->read_codec);
switch_core_codec_destroy(&tech_pvt->write_codec);
switch_core_session_destroy(&tech_pvt->session);
}
return SWITCH_STATUS_FALSE;
} }
static switch_status place_call(char *dest, char *out, size_t outlen) static switch_status place_call(char *dest, char *out, size_t outlen)
@ -796,14 +815,12 @@ static switch_status place_call(char *dest, char *out, size_t outlen)
if ((tech_pvt->caller_profile = switch_caller_profile_new(session, if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan, globals.dialplan,
globals.cid_name, globals.cid_name,
globals.cid_num, globals.cid_num, NULL, NULL, NULL, dest))) {
NULL,
NULL,
NULL,
dest))) {
char name[128]; char name[128];
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
snprintf(name, sizeof(name), "PortAudio/%s-%04x", tech_pvt->caller_profile->destination_number ? tech_pvt->caller_profile->destination_number : modname, rand() & 0xffff); snprintf(name, sizeof(name), "PortAudio/%s-%04x",
tech_pvt->caller_profile->destination_number ? tech_pvt->caller_profile->
destination_number : modname, rand() & 0xffff);
switch_channel_set_name(channel, name); switch_channel_set_name(channel, name);
} }
tech_pvt->session = session; tech_pvt->session = session;
@ -828,7 +845,7 @@ static switch_status hup_call(char *callid, char *out, size_t outlen)
callid = tmp; callid = tmp;
} }
if (!callid || !strcasecmp(callid, "all")) { if (!callid || !strcasecmp(callid, "all")) {
switch_hash_index_t* hi; switch_hash_index_t *hi;
void *val; void *val;
int i = 0; int i = 0;
@ -909,7 +926,7 @@ static void print_info(struct private_object *tech_pvt, char *out, size_t outlen
assert(channel != NULL); assert(channel != NULL);
snprintf(out, outlen, "CALL %s\t%s\t%s\t%s\t%s\n", snprintf(out, outlen, "CALL %s\t%s\t%s\t%s\t%s\n",
tech_pvt->call_id, tech_pvt->call_id,
tech_pvt->caller_profile->caller_id_name ? tech_pvt->caller_profile->caller_id_name : "n/a", tech_pvt->caller_profile->caller_id_name ? tech_pvt->caller_profile->caller_id_name : "n/a",
tech_pvt->caller_profile->caller_id_number ? tech_pvt->caller_profile->caller_id_number : "n/a", tech_pvt->caller_profile->caller_id_number ? tech_pvt->caller_profile->caller_id_number : "n/a",
tech_pvt->caller_profile->destination_number ? tech_pvt->caller_profile->destination_number : "n/a", tech_pvt->caller_profile->destination_number ? tech_pvt->caller_profile->destination_number : "n/a",
@ -920,7 +937,7 @@ static void print_info(struct private_object *tech_pvt, char *out, size_t outlen
static switch_status call_info(char *callid, char *out, size_t outlen) static switch_status call_info(char *callid, char *out, size_t outlen)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_hash_index_t* hi; switch_hash_index_t *hi;
void *val; void *val;
if (!callid || !strcasecmp(callid, "all")) { if (!callid || !strcasecmp(callid, "all")) {
for (hi = apr_hash_first(module_pool, globals.call_hash); hi; hi = switch_hash_next(hi)) { for (hi = apr_hash_first(module_pool, globals.call_hash); hi; hi = switch_hash_next(hi)) {

View File

@ -55,12 +55,10 @@
/************************************************************************/ /************************************************************************/
/******** Prototypes ****************************************************/ /******** Prototypes ****************************************************/
/************************************************************************/ /************************************************************************/
static int blockingIOCallback(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer,
static int blockingIOCallback( void *inputBuffer, void *outputBuffer, PaTimestamp outTime, void *userData);
unsigned long framesPerBuffer, static PaError PABLIO_InitFIFO(RingBuffer * rbuf, long numFrames, long bytesPerFrame);
PaTimestamp outTime, void *userData ); static PaError PABLIO_TermFIFO(RingBuffer * rbuf);
static PaError PABLIO_InitFIFO( RingBuffer *rbuf, long numFrames, long bytesPerFrame );
static PaError PABLIO_TermFIFO( RingBuffer *rbuf );
/************************************************************************/ /************************************************************************/
/******** Functions *****************************************************/ /******** Functions *****************************************************/
@ -69,121 +67,132 @@ static PaError PABLIO_TermFIFO( RingBuffer *rbuf );
/* Called from PortAudio. /* Called from PortAudio.
* Read and write data only if there is room in FIFOs. * Read and write data only if there is room in FIFOs.
*/ */
static int blockingIOCallback( void *inputBuffer, void *outputBuffer, static int blockingIOCallback(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer,
unsigned long framesPerBuffer, PaTimestamp outTime, void *userData)
PaTimestamp outTime, void *userData )
{ {
PABLIO_Stream *data = (PABLIO_Stream*)userData; PABLIO_Stream * data = (PABLIO_Stream *) userData;
long numBytes = data->bytesPerFrame * framesPerBuffer; long numBytes = data->bytesPerFrame * framesPerBuffer;
(void) outTime; (void) outTime;
/* This may get called with NULL inputBuffer during initial setup. */ /* This may get called with NULL inputBuffer during initial setup. */
if( inputBuffer != NULL ) if (inputBuffer != NULL)
{ {
RingBuffer_Write( &data->inFIFO, inputBuffer, numBytes ); RingBuffer_Write(&data->inFIFO, inputBuffer, numBytes);
} }
if( outputBuffer != NULL ) if (outputBuffer != NULL)
{ {
int i; int i;
int numRead = RingBuffer_Read( &data->outFIFO, outputBuffer, numBytes ); int numRead = RingBuffer_Read(&data->outFIFO, outputBuffer, numBytes);
/* Zero out remainder of buffer if we run out of data. */
for( i=numRead; i<numBytes; i++ ) /* Zero out remainder of buffer if we run out of data. */
{ for (i = numRead; i < numBytes; i++)
((char *)outputBuffer)[i] = 0; {
} ((char *) outputBuffer)[i] = 0;
} } }
return 0;
}
return 0;
}
/* Allocate buffer. */ /* Allocate buffer. */
static PaError PABLIO_InitFIFO( RingBuffer *rbuf, long numFrames, long bytesPerFrame ) static PaError PABLIO_InitFIFO(RingBuffer * rbuf, long numFrames, long bytesPerFrame)
{ {
long numBytes = numFrames * bytesPerFrame; long numBytes = numFrames * bytesPerFrame;
char *buffer = (char *) malloc( numBytes ); char *buffer = (char *) malloc(numBytes);
if( buffer == NULL ) return paInsufficientMemory; if (buffer == NULL)
memset( buffer, 0, numBytes ); return paInsufficientMemory;
return (PaError) RingBuffer_Init( rbuf, numBytes, buffer ); memset(buffer, 0, numBytes);
} return (PaError) RingBuffer_Init(rbuf, numBytes, buffer);
}
/* Free buffer. */ /* Free buffer. */
static PaError PABLIO_TermFIFO( RingBuffer *rbuf ) static PaError PABLIO_TermFIFO(RingBuffer * rbuf)
{ {
if( rbuf->buffer ) free( rbuf->buffer ); if (rbuf->buffer)
rbuf->buffer = NULL; free(rbuf->buffer);
return paNoError; rbuf->buffer = NULL;
} return paNoError;
}
/************************************************************ /************************************************************
* Write data to ring buffer. * Write data to ring buffer.
* Will not return until all the data has been written. * Will not return until all the data has been written.
*/ */
long WriteAudioStream( PABLIO_Stream *aStream, void *data, long numFrames ) long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames)
{ {
long bytesWritten; long bytesWritten;
char *p = (char *) data; char *p = (char *) data;
long numBytes = aStream->bytesPerFrame * numFrames; long numBytes = aStream->bytesPerFrame * numFrames;
while( numBytes > 0) while (numBytes > 0)
{ {
bytesWritten = RingBuffer_Write( &aStream->outFIFO, p, numBytes ); bytesWritten = RingBuffer_Write(&aStream->outFIFO, p, numBytes);
numBytes -= bytesWritten; numBytes -= bytesWritten;
p += bytesWritten; p += bytesWritten;
if( numBytes > 0) Pa_Sleep(10); if (numBytes > 0)
} Pa_Sleep(10);
return numFrames; }
} return numFrames;
}
/************************************************************ /************************************************************
* Read data from ring buffer. * Read data from ring buffer.
* Will not return until all the data has been read. * Will not return until all the data has been read.
*/ */
long ReadAudioStream( PABLIO_Stream *aStream, void *data, long numFrames ) long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames)
{ {
long bytesRead; long bytesRead;
char *p = (char *) data; char *p = (char *) data;
long numBytes = aStream->bytesPerFrame * numFrames; long numBytes = aStream->bytesPerFrame * numFrames;
while( numBytes > 0) while (numBytes > 0)
{ {
bytesRead = RingBuffer_Read( &aStream->inFIFO, p, numBytes ); bytesRead = RingBuffer_Read(&aStream->inFIFO, p, numBytes);
numBytes -= bytesRead; numBytes -= bytesRead;
p += bytesRead; p += bytesRead;
if( numBytes > 0) Pa_Sleep(10); if (numBytes > 0)
} Pa_Sleep(10);
return numFrames; }
} return numFrames;
}
/************************************************************ /************************************************************
* Return the number of frames that could be written to the stream without * Return the number of frames that could be written to the stream without
* having to wait. * having to wait.
*/ */
long GetAudioStreamWriteable( PABLIO_Stream *aStream ) long GetAudioStreamWriteable(PABLIO_Stream * aStream)
{ {
int bytesEmpty = RingBuffer_GetWriteAvailable( &aStream->outFIFO ); int bytesEmpty = RingBuffer_GetWriteAvailable(&aStream->outFIFO);
return bytesEmpty / aStream->bytesPerFrame; return bytesEmpty / aStream->bytesPerFrame;
} }
/************************************************************ /************************************************************
* Return the number of frames that are available to be read from the * Return the number of frames that are available to be read from the
* stream without having to wait. * stream without having to wait.
*/ */
long GetAudioStreamReadable( PABLIO_Stream *aStream ) long GetAudioStreamReadable(PABLIO_Stream * aStream)
{ {
int bytesFull = RingBuffer_GetReadAvailable( &aStream->inFIFO ); int bytesFull = RingBuffer_GetReadAvailable(&aStream->inFIFO);
return bytesFull / aStream->bytesPerFrame; return bytesFull / aStream->bytesPerFrame;
} }
/************************************************************/ /************************************************************/
static unsigned long RoundUpToNextPowerOf2( unsigned long n ) static unsigned long RoundUpToNextPowerOf2(unsigned long n)
{ {
long numBits = 0; long numBits = 0;
if( ((n-1) & n) == 0) return n; /* Already Power of two. */ if (((n - 1) & n) == 0)
while( n > 0 ) return n; /* Already Power of two. */
{ while (n > 0)
n= n>>1; {
numBits++; n = n >> 1;
} numBits++;
return (1<<numBits); }
} return (1 << numBits);
}
/************************************************************ /************************************************************
* Opens a PortAudio stream with default characteristics. * Opens a PortAudio stream with default characteristics.
@ -193,135 +202,132 @@ static unsigned long RoundUpToNextPowerOf2( unsigned long n )
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE, * PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO * and either PABLIO_MONO or PABLIO_STEREO
*/ */
PaError OpenAudioStream( PABLIO_Stream **rwblPtr, double sampleRate, PaError OpenAudioStream(PABLIO_Stream ** rwblPtr, double sampleRate, PaSampleFormat format, long flags, int indev,
PaSampleFormat format, long flags, int indev, int outdev ) int outdev)
{ {
long bytesPerSample; long bytesPerSample;
long doRead = 0; long doRead = 0;
long doWrite = 0; long doWrite = 0;
PaError err; PaError err;
PABLIO_Stream *aStream; PABLIO_Stream * aStream;
long minNumBuffers; long minNumBuffers;
long numFrames; long numFrames;
/* Allocate PABLIO_Stream structure for caller. */ /* Allocate PABLIO_Stream structure for caller. */
aStream = (PABLIO_Stream *) malloc( sizeof(PABLIO_Stream) ); aStream = (PABLIO_Stream *) malloc(sizeof(PABLIO_Stream));
if( aStream == NULL ) return paInsufficientMemory; if (aStream == NULL)
memset( aStream, 0, sizeof(PABLIO_Stream) ); return paInsufficientMemory;
memset(aStream, 0, sizeof(PABLIO_Stream));
/* Determine size of a sample. */ /* Determine size of a sample. */
bytesPerSample = Pa_GetSampleSize( format ); bytesPerSample = Pa_GetSampleSize(format);
if( bytesPerSample < 0 ) if (bytesPerSample < 0)
{ {
err = (PaError) bytesPerSample; err = (PaError) bytesPerSample;
goto error; goto error;
} }
aStream->samplesPerFrame = ((flags&PABLIO_MONO) != 0) ? 1 : 2; aStream->samplesPerFrame = ((flags & PABLIO_MONO) != 0) ? 1 : 2;
aStream->bytesPerFrame = bytesPerSample * aStream->samplesPerFrame; aStream->bytesPerFrame = bytesPerSample * aStream->samplesPerFrame;
/* Initialize PortAudio */ /* Initialize PortAudio */
err = Pa_Initialize(); err = Pa_Initialize();
if( err != paNoError ) goto error; if (err != paNoError)
goto error;
/* Warning: numFrames must be larger than amount of data processed per interrupt /* Warning: numFrames must be larger than amount of data processed per interrupt
* inside PA to prevent glitches. Just to be safe, adjust size upwards. * inside PA to prevent glitches. Just to be safe, adjust size upwards.
*/ */
minNumBuffers = 2 * Pa_GetMinNumBuffers( FRAMES_PER_BUFFER, sampleRate ); minNumBuffers = 2 * Pa_GetMinNumBuffers(FRAMES_PER_BUFFER, sampleRate);
numFrames = minNumBuffers * FRAMES_PER_BUFFER; numFrames = minNumBuffers * FRAMES_PER_BUFFER;
/* The PortAudio callback runs in a high priority thread. But PABLIO
* runs in a normal foreground thread. So we may have much worse
* latency in PABLIO. So adjust latency to a safe level.
*/
{
const int safeLatencyMSec = 200;
int minLatencyMSec = (int) ((1000 * numFrames) / sampleRate);
if( minLatencyMSec < safeLatencyMSec )
{
numFrames = (int) ((safeLatencyMSec * sampleRate) / 1000);
}
}
numFrames = RoundUpToNextPowerOf2( numFrames );
/* Initialize Ring Buffers */ /* The PortAudio callback runs in a high priority thread. But PABLIO
doRead = ((flags & PABLIO_READ) != 0); * runs in a normal foreground thread. So we may have much worse
doWrite = ((flags & PABLIO_WRITE) != 0); * latency in PABLIO. So adjust latency to a safe level.
if(doRead) */
{ {
err = PABLIO_InitFIFO( &aStream->inFIFO, numFrames, aStream->bytesPerFrame ); const int safeLatencyMSec = 200;
if( err != paNoError ) goto error; int minLatencyMSec = (int) ((1000 * numFrames) / sampleRate);
} if (minLatencyMSec < safeLatencyMSec)
if(doWrite) {
{ numFrames = (int) ((safeLatencyMSec * sampleRate) / 1000);
long numBytes; }
err = PABLIO_InitFIFO( &aStream->outFIFO, numFrames, aStream->bytesPerFrame ); } numFrames = RoundUpToNextPowerOf2(numFrames);
if( err != paNoError ) goto error;
/* Make Write FIFO appear full initially. */
numBytes = RingBuffer_GetWriteAvailable( &aStream->outFIFO );
RingBuffer_AdvanceWriteIndex( &aStream->outFIFO, numBytes );
}
/* Open a PortAudio stream that we will use to communicate with the underlying /* Initialize Ring Buffers */
* audio drivers. */ doRead = ((flags & PABLIO_READ) != 0);
err = Pa_OpenStream( doWrite = ((flags & PABLIO_WRITE) != 0);
&aStream->stream, if (doRead)
(doRead ? (indev > -1) ? indev : Pa_GetDefaultInputDeviceID() : paNoDevice), {
(doRead ? aStream->samplesPerFrame : 0 ), err = PABLIO_InitFIFO(&aStream->inFIFO, numFrames, aStream->bytesPerFrame);
format, if (err != paNoError)
NULL, goto error;
(doWrite ? (outdev > -1) ? outdev : Pa_GetDefaultOutputDeviceID() : paNoDevice), }
(doWrite ? aStream->samplesPerFrame : 0 ), if (doWrite)
format, {
NULL, long numBytes;
sampleRate, err = PABLIO_InitFIFO(&aStream->outFIFO, numFrames, aStream->bytesPerFrame);
FRAMES_PER_BUFFER, if (err != paNoError)
minNumBuffers, goto error;
paClipOff, /* we won't output out of range samples so don't bother clipping them */
blockingIOCallback,
aStream );
if( err != paNoError ) goto error;
err = Pa_StartStream( aStream->stream ); /* Make Write FIFO appear full initially. */
if( err != paNoError ) goto error; numBytes = RingBuffer_GetWriteAvailable(&aStream->outFIFO);
RingBuffer_AdvanceWriteIndex(&aStream->outFIFO, numBytes);
}
*rwblPtr = aStream; /* Open a PortAudio stream that we will use to communicate with the underlying
return paNoError; * audio drivers. */
err = Pa_OpenStream( &aStream->stream,
(doRead ? (indev > -1) ? indev : Pa_GetDefaultInputDeviceID() : paNoDevice),
(doRead ? aStream->samplesPerFrame : 0), format, NULL,
(doWrite ? (outdev > -1) ? outdev : Pa_GetDefaultOutputDeviceID() : paNoDevice),
(doWrite ? aStream->samplesPerFrame : 0), format, NULL, sampleRate, FRAMES_PER_BUFFER,
minNumBuffers, paClipOff,
/* we won't output out of range samples so don't bother clipping them */
blockingIOCallback, aStream);
if (err != paNoError)
goto error;
err = Pa_StartStream(aStream->stream);
if (err != paNoError)
goto error;
*rwblPtr = aStream;
return paNoError;
error: CloseAudioStream(aStream);
*rwblPtr = NULL;
return err;
}
error:
CloseAudioStream( aStream );
*rwblPtr = NULL;
return err;
}
/************************************************************/ /************************************************************/
PaError CloseAudioStream( PABLIO_Stream *aStream ) PaError CloseAudioStream(PABLIO_Stream * aStream)
{ {
PaError err = paNoError; PaError err = paNoError;
int bytesEmpty; int bytesEmpty;
int byteSize = aStream->outFIFO.bufferSize; int byteSize = aStream->outFIFO.bufferSize;
if (aStream->stream != NULL) /* Make sure stream was opened. PLB021214 */
{
/* If we are writing data, make sure we play everything written. */
if (byteSize > 0)
{
int timeOutMSec = 2000;
bytesEmpty = RingBuffer_GetWriteAvailable(&aStream->outFIFO);
while ((bytesEmpty < byteSize) && (timeOutMSec > 0))
{
Pa_Sleep(20);
timeOutMSec -= 20;
bytesEmpty = RingBuffer_GetWriteAvailable(&aStream->outFIFO);
}
}
err = Pa_StopStream(aStream->stream);
if (err != paNoError)
goto error;
err = Pa_CloseStream(aStream->stream);
}
error: Pa_Terminate();
PABLIO_TermFIFO(&aStream->inFIFO);
PABLIO_TermFIFO(&aStream->outFIFO);
free(aStream);
return err;
}
if( aStream->stream != NULL ) /* Make sure stream was opened. PLB021214 */
{
/* If we are writing data, make sure we play everything written. */
if( byteSize > 0 )
{
int timeOutMSec = 2000;
bytesEmpty = RingBuffer_GetWriteAvailable( &aStream->outFIFO );
while( (bytesEmpty < byteSize) && (timeOutMSec > 0) )
{
Pa_Sleep( 20 );
timeOutMSec -= 20;
bytesEmpty = RingBuffer_GetWriteAvailable( &aStream->outFIFO );
}
}
err = Pa_StopStream( aStream->stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( aStream->stream );
}
error:
Pa_Terminate();
PABLIO_TermFIFO( &aStream->inFIFO );
PABLIO_TermFIFO( &aStream->outFIFO );
free( aStream );
return err;
}

View File

@ -43,35 +43,41 @@
* Initialize FIFO. * Initialize FIFO.
* numBytes must be power of 2, returns -1 if not. * numBytes must be power of 2, returns -1 if not.
*/ */
long RingBuffer_Init( RingBuffer *rbuf, long numBytes, void *dataPtr ) long RingBuffer_Init(RingBuffer * rbuf, long numBytes, void *dataPtr)
{ {
if( ((numBytes-1) & numBytes) != 0) return -1; /* Not Power of two. */ if (((numBytes - 1) & numBytes) != 0)
rbuf->bufferSize = numBytes; return -1; /* Not Power of two. */
rbuf->buffer = (char *)dataPtr; rbuf->bufferSize = numBytes;
RingBuffer_Flush( rbuf ); rbuf->buffer = (char *) dataPtr;
rbuf->bigMask = (numBytes*2)-1; RingBuffer_Flush(rbuf);
rbuf->smallMask = (numBytes)-1; rbuf->bigMask = (numBytes * 2) - 1;
return 0; rbuf->smallMask = (numBytes) - 1;
} return 0;
}
/*************************************************************************** /***************************************************************************
** Return number of bytes available for reading. */ ** Return number of bytes available for reading. */
long RingBuffer_GetReadAvailable( RingBuffer *rbuf ) long RingBuffer_GetReadAvailable(RingBuffer * rbuf)
{ {
return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask ); return ((rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask);
} }
/*************************************************************************** /***************************************************************************
** Return number of bytes available for writing. */ ** Return number of bytes available for writing. */
long RingBuffer_GetWriteAvailable( RingBuffer *rbuf ) long RingBuffer_GetWriteAvailable(RingBuffer * rbuf)
{ {
return ( rbuf->bufferSize - RingBuffer_GetReadAvailable(rbuf)); return (rbuf->bufferSize - RingBuffer_GetReadAvailable(rbuf));
} }
/*************************************************************************** /***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read. */ ** Clear buffer. Should only be called when buffer is NOT being read. */
void RingBuffer_Flush( RingBuffer *rbuf ) void RingBuffer_Flush(RingBuffer * rbuf)
{ {
rbuf->writeIndex = rbuf->readIndex = 0; rbuf->writeIndex = rbuf->readIndex = 0;
} }
/*************************************************************************** /***************************************************************************
** Get address of region(s) to which we can write data. ** Get address of region(s) to which we can write data.
@ -79,41 +85,45 @@ void RingBuffer_Flush( RingBuffer *rbuf )
** If non-contiguous, size2 will be the size of second region. ** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller. ** Returns room available to be written or numBytes, whichever is smaller.
*/ */
long RingBuffer_GetWriteRegions( RingBuffer *rbuf, long numBytes, long RingBuffer_GetWriteRegions(RingBuffer * rbuf, long numBytes, void **dataPtr1, long *sizePtr1, void **dataPtr2,
void **dataPtr1, long *sizePtr1, long *sizePtr2)
void **dataPtr2, long *sizePtr2 )
{ {
long index; long index;
long available = RingBuffer_GetWriteAvailable( rbuf ); long available = RingBuffer_GetWriteAvailable(rbuf);
if( numBytes > available ) numBytes = available; if (numBytes > available)
/* Check to see if write is not contiguous. */ numBytes = available;
index = rbuf->writeIndex & rbuf->smallMask;
if( (index + numBytes) > rbuf->bufferSize ) /* Check to see if write is not contiguous. */
{ index = rbuf->writeIndex & rbuf->smallMask;
/* Write data in two blocks that wrap the buffer. */ if ((index + numBytes) > rbuf->bufferSize)
long firstHalf = rbuf->bufferSize - index; {
*dataPtr1 = &rbuf->buffer[index];
*sizePtr1 = firstHalf; /* Write data in two blocks that wrap the buffer. */
*dataPtr2 = &rbuf->buffer[0]; long firstHalf = rbuf->bufferSize - index;
*sizePtr2 = numBytes - firstHalf; *dataPtr1 = &rbuf->buffer[index];
} *sizePtr1 = firstHalf;
else *dataPtr2 = &rbuf->buffer[0];
{ *sizePtr2 = numBytes - firstHalf;
*dataPtr1 = &rbuf->buffer[index]; }
*sizePtr1 = numBytes;
*dataPtr2 = NULL; else
*sizePtr2 = 0; {
} *dataPtr1 = &rbuf->buffer[index];
return numBytes; *sizePtr1 = numBytes;
} *dataPtr2 = NULL;
*sizePtr2 = 0;
}
return numBytes;
}
/*************************************************************************** /***************************************************************************
*/ */
long RingBuffer_AdvanceWriteIndex( RingBuffer *rbuf, long numBytes ) long RingBuffer_AdvanceWriteIndex(RingBuffer * rbuf, long numBytes)
{ {
return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask; return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask;
} }
/*************************************************************************** /***************************************************************************
** Get address of region(s) from which we can read data. ** Get address of region(s) from which we can read data.
@ -121,79 +131,89 @@ long RingBuffer_AdvanceWriteIndex( RingBuffer *rbuf, long numBytes )
** If non-contiguous, size2 will be the size of second region. ** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller. ** Returns room available to be written or numBytes, whichever is smaller.
*/ */
long RingBuffer_GetReadRegions( RingBuffer *rbuf, long numBytes, long RingBuffer_GetReadRegions(RingBuffer * rbuf, long numBytes, void **dataPtr1, long *sizePtr1, void **dataPtr2,
void **dataPtr1, long *sizePtr1, long *sizePtr2)
void **dataPtr2, long *sizePtr2 )
{ {
long index; long index;
long available = RingBuffer_GetReadAvailable( rbuf ); long available = RingBuffer_GetReadAvailable(rbuf);
if( numBytes > available ) numBytes = available; if (numBytes > available)
/* Check to see if read is not contiguous. */ numBytes = available;
index = rbuf->readIndex & rbuf->smallMask;
if( (index + numBytes) > rbuf->bufferSize ) /* Check to see if read is not contiguous. */
{ index = rbuf->readIndex & rbuf->smallMask;
/* Write data in two blocks that wrap the buffer. */ if ((index + numBytes) > rbuf->bufferSize)
long firstHalf = rbuf->bufferSize - index; {
*dataPtr1 = &rbuf->buffer[index];
*sizePtr1 = firstHalf; /* Write data in two blocks that wrap the buffer. */
*dataPtr2 = &rbuf->buffer[0]; long firstHalf = rbuf->bufferSize - index;
*sizePtr2 = numBytes - firstHalf; *dataPtr1 = &rbuf->buffer[index];
} *sizePtr1 = firstHalf;
else *dataPtr2 = &rbuf->buffer[0];
{ *sizePtr2 = numBytes - firstHalf;
*dataPtr1 = &rbuf->buffer[index]; }
*sizePtr1 = numBytes;
*dataPtr2 = NULL; else
*sizePtr2 = 0; {
} *dataPtr1 = &rbuf->buffer[index];
return numBytes; *sizePtr1 = numBytes;
} *dataPtr2 = NULL;
*sizePtr2 = 0;
}
return numBytes;
}
/*************************************************************************** /***************************************************************************
*/ */
long RingBuffer_AdvanceReadIndex( RingBuffer *rbuf, long numBytes ) long RingBuffer_AdvanceReadIndex(RingBuffer * rbuf, long numBytes)
{ {
return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask; return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask;
} }
/*************************************************************************** /***************************************************************************
** Return bytes written. */ ** Return bytes written. */
long RingBuffer_Write( RingBuffer *rbuf, void *data, long numBytes ) long RingBuffer_Write(RingBuffer * rbuf, void *data, long numBytes)
{ {
long size1, size2, numWritten; long size1, size2, numWritten;
void *data1, *data2; void *data1, *data2;
numWritten = RingBuffer_GetWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 ); numWritten = RingBuffer_GetWriteRegions(rbuf, numBytes, &data1, &size1, &data2, &size2);
if( size2 > 0 ) if (size2 > 0)
{ {
memcpy(data1, data, size1);
data = ((char *) data) + size1;
memcpy(data2, data, size2);
}
else
{
memcpy(data1, data, size1);
}
RingBuffer_AdvanceWriteIndex(rbuf, numWritten);
return numWritten;
}
memcpy( data1, data, size1 );
data = ((char *)data) + size1;
memcpy( data2, data, size2 );
}
else
{
memcpy( data1, data, size1 );
}
RingBuffer_AdvanceWriteIndex( rbuf, numWritten );
return numWritten;
}
/*************************************************************************** /***************************************************************************
** Return bytes read. */ ** Return bytes read. */
long RingBuffer_Read( RingBuffer *rbuf, void *data, long numBytes ) long RingBuffer_Read(RingBuffer * rbuf, void *data, long numBytes)
{ {
long size1, size2, numRead; long size1, size2, numRead;
void *data1, *data2; void *data1, *data2;
numRead = RingBuffer_GetReadRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 ); numRead = RingBuffer_GetReadRegions(rbuf, numBytes, &data1, &size1, &data2, &size2);
if( size2 > 0 ) if (size2 > 0)
{ {
memcpy( data, data1, size1 ); memcpy(data, data1, size1);
data = ((char *)data) + size1; data = ((char *) data) + size1;
memcpy( data, data2, size2 ); memcpy(data, data2, size2);
} }
else
{ else
memcpy( data, data1, size1 ); {
} memcpy(data, data1, size1);
RingBuffer_AdvanceReadIndex( rbuf, numRead ); }
return numRead; RingBuffer_AdvanceReadIndex(rbuf, numRead);
} return numRead;
}

View File

@ -86,8 +86,8 @@ static struct {
struct private_object { struct private_object {
unsigned int flags; /* FLAGS */ unsigned int flags; /* FLAGS */
struct switch_frame frame; /* Frame for Writing */ struct switch_frame frame; /* Frame for Writing */
unsigned char databuf[SWITCH_RECCOMMENDED_BUFFER_SIZE]; unsigned char databuf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
struct sangoma_pri *spri; struct sangoma_pri *spri;
pri_event ring_event; pri_event ring_event;
@ -153,15 +153,18 @@ static switch_status wanpipe_on_init(switch_core_session *session);
static switch_status wanpipe_on_hangup(switch_core_session *session); static switch_status wanpipe_on_hangup(switch_core_session *session);
static switch_status wanpipe_on_loopback(switch_core_session *session); static switch_status wanpipe_on_loopback(switch_core_session *session);
static switch_status wanpipe_on_transmit(switch_core_session *session); static switch_status wanpipe_on_transmit(switch_core_session *session);
static switch_status wanpipe_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session); static switch_status wanpipe_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
static switch_status wanpipe_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id); switch_core_session **new_session);
static switch_status wanpipe_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id); static switch_status wanpipe_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event); switch_io_flag flags, int stream_id);
static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event); static switch_status wanpipe_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event); switch_io_flag flags, int stream_id);
static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event);
static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event);
static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event);
static int check_flags(struct sangoma_pri *spri); static int check_flags(struct sangoma_pri *spri);
static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event); static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event);
static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event); static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event);
static void *pri_thread_run(switch_thread *thread, void *obj); static void *pri_thread_run(switch_thread *thread, void *obj);
static int config_wanpipe(int reload); static int config_wanpipe(int reload);
@ -222,8 +225,12 @@ static switch_status wanpipe_on_hangup(switch_core_session *session)
switch_socket_close(&tech_pvt->socket); switch_socket_close(&tech_pvt->socket);
pri_hangup(tech_pvt->spri->pri, tech_pvt->hangup_event.hangup.call ? tech_pvt->hangup_event.hangup.call : tech_pvt->ring_event.ring.call, tech_pvt->cause); pri_hangup(tech_pvt->spri->pri,
pri_destroycall(tech_pvt->spri->pri, tech_pvt->hangup_event.hangup.call ? tech_pvt->hangup_event.hangup.call : tech_pvt->ring_event.ring.call); tech_pvt->hangup_event.hangup.call ? tech_pvt->hangup_event.hangup.call : tech_pvt->ring_event.ring.call,
tech_pvt->cause);
pri_destroycall(tech_pvt->spri->pri,
tech_pvt->hangup_event.hangup.call ? tech_pvt->hangup_event.hangup.call : tech_pvt->ring_event.ring.
call);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANPIPE HANGUP\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "WANPIPE HANGUP\n");
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -241,7 +248,8 @@ static switch_status wanpipe_on_transmit(switch_core_session *session)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status wanpipe_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session) static switch_status wanpipe_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
switch_core_session **new_session)
{ {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "NOT IMPLEMENTED\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "NOT IMPLEMENTED\n");
@ -266,7 +274,8 @@ static switch_status wanpipe_answer_channel(switch_core_session *session)
static switch_status wanpipe_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id) static switch_status wanpipe_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel = NULL; switch_channel *channel = NULL;
@ -284,19 +293,16 @@ static switch_status wanpipe_read_frame(switch_core_session *session, switch_fra
*frame = NULL; *frame = NULL;
memset(tech_pvt->databuf, 0, sizeof(tech_pvt->databuf)); memset(tech_pvt->databuf, 0, sizeof(tech_pvt->databuf));
while (bytes < globals.bytes_per_frame) { while (bytes < globals.bytes_per_frame) {
if ((res = switch_socket_waitfor(tech_pvt->socket, timeout, POLLIN|POLLERR)) < 0) { if ((res = switch_socket_waitfor(tech_pvt->socket, timeout, POLLIN | POLLERR)) < 0) {
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} else if (res == 0) { } else if (res == 0) {
tech_pvt->frame.datalen = 0; tech_pvt->frame.datalen = 0;
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
if ((res = sangoma_readmsg_socket( if ((res = sangoma_readmsg_socket(tech_pvt->socket,
tech_pvt->socket,
&tech_pvt->hdrframe, &tech_pvt->hdrframe,
sizeof(tech_pvt->hdrframe), sizeof(tech_pvt->hdrframe), bp, sizeof(tech_pvt->databuf) - bytes, 0)) < 0) {
bp,
sizeof(tech_pvt->databuf) - bytes, 0)) < 0) {
if (errno == EBUSY) { if (errno == EBUSY) {
continue; continue;
} else { } else {
@ -312,7 +318,8 @@ static switch_status wanpipe_read_frame(switch_core_session *session, switch_fra
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status wanpipe_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id) static switch_status wanpipe_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel = NULL; switch_channel *channel = NULL;
@ -329,14 +336,12 @@ static switch_status wanpipe_write_frame(switch_core_session *session, switch_fr
while (bytes > 0) { while (bytes > 0) {
switch_socket_waitfor(tech_pvt->socket, -1, POLLOUT | POLLERR | POLLHUP); switch_socket_waitfor(tech_pvt->socket, -1, POLLOUT | POLLERR | POLLHUP);
res = sangoma_sendmsg_socket( res = sangoma_sendmsg_socket(tech_pvt->socket,
tech_pvt->socket, &tech_pvt->hdrframe, sizeof(tech_pvt->hdrframe), bp, PACKET_LEN, 0);
&tech_pvt->hdrframe,
sizeof(tech_pvt->hdrframe),
bp,
PACKET_LEN, 0);
if (res < 0) { if (res < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Bad Write frame len %d write %d bytes returned %d errno %d!\n", frame->datalen, PACKET_LEN, res, errno); switch_console_printf(SWITCH_CHANNEL_CONSOLE,
"Bad Write frame len %d write %d bytes returned %d errno %d!\n", frame->datalen,
PACKET_LEN, res, errno);
if (errno == EBUSY) { if (errno == EBUSY) {
continue; continue;
} }
@ -352,40 +357,41 @@ static switch_status wanpipe_write_frame(switch_core_session *session, switch_fr
return status; return status;
} }
static const switch_io_routines wanpipe_io_routines*/ { static const switch_io_routines wanpipe_io_routines */ {
/*.outgoing_channel*/ wanpipe_outgoing_channel, /*.outgoing_channel */ wanpipe_outgoing_channel,
/*.answer_channel*/ wanpipe_answer_channel, /*.answer_channel */ wanpipe_answer_channel,
/*.read_frame*/ wanpipe_read_frame, /*.read_frame */ wanpipe_read_frame,
/*.write_frame*/ wanpipe_write_frame /*.write_frame */ wanpipe_write_frame
}; };
static const switch_event_handler_table wanpipe_event_handlers = { static const switch_event_handler_table wanpipe_event_handlers = {
/*.on_init*/ wanpipe_on_init, /*.on_init */ wanpipe_on_init,
/*.on_ring*/ wanpipe_on_ring, /*.on_ring */ wanpipe_on_ring,
/*.on_execute*/ NULL, /*.on_execute */ NULL,
/*.on_hangup*/ wanpipe_on_hangup, /*.on_hangup */ wanpipe_on_hangup,
/*.on_loopback*/ wanpipe_on_loopback, /*.on_loopback */ wanpipe_on_loopback,
/*.on_transmit*/ wanpipe_on_transmit /*.on_transmit */ wanpipe_on_transmit
}; };
static const switch_endpoint_interface wanpipe_endpoint_interface = { static const switch_endpoint_interface wanpipe_endpoint_interface = {
/*.interface_name*/ "wanpipe", /*.interface_name */ "wanpipe",
/*.io_routines*/ &wanpipe_io_routines, /*.io_routines */ &wanpipe_io_routines,
/*.event_handlers*/ &wanpipe_event_handlers, /*.event_handlers */ &wanpipe_event_handlers,
/*.private*/ NULL, /*.private */ NULL,
/*.next*/ NULL /*.next */ NULL
}; };
static const switch_loadable_module_interface wanpipe_module_interface = { static const switch_loadable_module_interface wanpipe_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ &wanpipe_endpoint_interface, /*.endpoint_interface */ &wanpipe_endpoint_interface,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
Public switch_status switch_module_load(const switch_loadable_module_interface **interface, chanr *filename) { Public switch_status switch_module_load(const switch_loadable_module_interface **interface, chanr * filename)
{
if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) { if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
@ -406,7 +412,7 @@ Public switch_status switch_module_load(const switch_loadable_module_interface *
/* Event Handlers */ /* Event Handlers */
static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event)
{ {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "number is: %s\n", event->ring.callednum); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "number is: %s\n", event->ring.callednum);
if (strlen(event->ring.callednum) > 3) { if (strlen(event->ring.callednum) > 3) {
@ -416,7 +422,7 @@ static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri
return 0; return 0;
} }
static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event)
{ {
struct channel_map *chanmap; struct channel_map *chanmap;
switch_core_session *session; switch_core_session *session;
@ -438,11 +444,11 @@ static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, p
switch_channel_set_state(channel, CS_HANGUP); switch_channel_set_state(channel, CS_HANGUP);
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"-- Hanging up channel %d\n", event->hangup.channel); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Hanging up channel %d\n", event->hangup.channel);
return 0; return 0;
} }
static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event)
{ {
char name[128]; char name[128];
switch_core_session *session; switch_core_session *session;
@ -453,11 +459,13 @@ static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri
chanmap = spri->private; chanmap = spri->private;
if (chanmap->map[event->ring.channel]) { if (chanmap->map[event->ring.channel]) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"--Duplicate Ring on channel %d (ignored)\n", event->ring.channel); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "--Duplicate Ring on channel %d (ignored)\n",
event->ring.channel);
return 0; return 0;
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"-- Ring on channel %d (from %s to %s)\n", event->ring.channel, event->ring.callingnum, event->ring.callednum); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Ring on channel %d (from %s to %s)\n", event->ring.channel,
event->ring.callingnum, event->ring.callednum);
sprintf(name, "w%dg%d", globals.span, event->ring.channel); sprintf(name, "w%dg%d", globals.span, event->ring.channel);
if ((session = switch_core_session_request(&wanpipe_endpoint_interface, NULL))) { if ((session = switch_core_session_request(&wanpipe_endpoint_interface, NULL))) {
@ -482,12 +490,12 @@ static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri
} }
if ((tech_pvt->caller_profile = switch_caller_profile_new(session, if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
globals.dialplan, globals.dialplan,
"wanpipe fixme", "wanpipe fixme",
event->ring.callingnum, event->ring.callingnum,
event->ring.callingani, event->ring.callingani,
switch_strlen_zero(ani2str) ? NULL : ani2str, switch_strlen_zero(ani2str) ? NULL : ani2str,
event->ring.callednum))) { event->ring.callednum))) {
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
} }
@ -502,7 +510,6 @@ static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri
if ((fd = sangoma_create_socket_intr(spri->span, event->ring.channel)) < 0) { if ((fd = sangoma_create_socket_intr(spri->span, event->ring.channel)) < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open fd!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open fd!\n");
} }
//sangoma_tdm_set_hw_period(fd, &tdm_api, 480); //sangoma_tdm_set_hw_period(fd, &tdm_api, 480);
tech_pvt->socket = fd; tech_pvt->socket = fd;
@ -524,23 +531,24 @@ static int check_flags(struct sangoma_pri *spri)
return 0; return 0;
} }
static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event)
{ {
int fd; int fd;
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"-- Restarting channel %d\n", event->restart.channel); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "-- Restarting channel %d\n", event->restart.channel);
if ((fd = sangoma_create_socket_intr(spri->span, event->restart.channel)) < 0) { if ((fd = sangoma_create_socket_intr(spri->span, event->restart.channel)) < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"Can't open fd!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open fd!\n");
} else { } else {
close(fd); close(fd);
} }
return 0; return 0;
} }
static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event * event)
{ {
switch_console_printf(SWITCH_CHANNEL_CONSOLE,"Caught Event %d (%s)\n", event_type, sangoma_pri_event_str(event_type)); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Caught Event %d (%s)\n", event_type,
sangoma_pri_event_str(event_type));
return 0; return 0;
} }
@ -606,15 +614,9 @@ static int config_wanpipe(int reload)
set_global_dialplan("default"); set_global_dialplan("default");
} }
if ((spri=switch_core_alloc(module_pool, sizeof(*spri)))) { if ((spri = switch_core_alloc(module_pool, sizeof(*spri)))) {
memset(spri, 0, sizeof(*spri)); memset(spri, 0, sizeof(*spri));
sangoma_init_pri(spri, sangoma_init_pri(spri, globals.span, globals.dchan, 23, globals.pswitch, globals.node, globals.debug);
globals.span,
globals.dchan,
23,
globals.pswitch,
globals.node,
globals.debug);
pri_thread_run(NULL, spri); pri_thread_run(NULL, spri);
@ -632,4 +634,3 @@ Public switch_status switch_module_runtime(void)
config_wanpipe(0); config_wanpipe(0);
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }

View File

@ -122,7 +122,7 @@ struct woomera_profile {
int woomera_port; int woomera_port;
char audio_ip[WOOMERA_STRLEN]; char audio_ip[WOOMERA_STRLEN];
char dialplan[WOOMERA_STRLEN]; char dialplan[WOOMERA_STRLEN];
// pthread_t thread; // pthread_t thread;
unsigned int flags; unsigned int flags;
int thread_running; int thread_running;
struct woomera_event_queue event_queue; struct woomera_event_queue event_queue;
@ -171,23 +171,27 @@ static switch_status woomerachan_on_hangup(switch_core_session *session);
static switch_status woomerachan_on_ring(switch_core_session *session); static switch_status woomerachan_on_ring(switch_core_session *session);
static switch_status woomerachan_on_loopback(switch_core_session *session); static switch_status woomerachan_on_loopback(switch_core_session *session);
static switch_status woomerachan_on_transmit(switch_core_session *session); static switch_status woomerachan_on_transmit(switch_core_session *session);
static switch_status woomerachan_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session); static switch_status woomerachan_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
static switch_status woomerachan_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id); switch_core_session **new_session);
static switch_status woomerachan_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id); static switch_status woomerachan_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id);
static switch_status woomerachan_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id);
static switch_status woomerachan_kill_channel(switch_core_session *session, int sig); static switch_status woomerachan_kill_channel(switch_core_session *session, int sig);
static void tech_destroy(private_object *tech_pvt); static void tech_destroy(private_object * tech_pvt);
static void woomera_printf(woomera_profile *profile, switch_socket_t *socket, char *fmt, ...); static void woomera_printf(woomera_profile * profile, switch_socket_t *socket, char *fmt, ...);
static char *woomera_message_header(woomera_message *wmsg, char *key); static char *woomera_message_header(woomera_message * wmsg, char *key);
static int woomera_enqueue_event(woomera_event_queue *event_queue, woomera_message *wmsg); static int woomera_enqueue_event(woomera_event_queue * event_queue, woomera_message * wmsg);
static int woomera_dequeue_event(woomera_event_queue *event_queue, woomera_message *wmsg); static int woomera_dequeue_event(woomera_event_queue * event_queue, woomera_message * wmsg);
static int woomera_message_parse(switch_socket_t *fd, woomera_message *wmsg, int timeout, woomera_profile *profile, woomera_event_queue *event_queue); static int woomera_message_parse(switch_socket_t *fd, woomera_message * wmsg, int timeout, woomera_profile * profile,
static int connect_woomera(switch_socket_t **new_sock, woomera_profile *profile, int flags); woomera_event_queue * event_queue);
static int woomera_profile_thread_running(woomera_profile *profile, int set, int new); static int connect_woomera(switch_socket_t **new_sock, woomera_profile * profile, int flags);
static int woomera_locate_socket(woomera_profile *profile, switch_socket_t **woomera_socket); static int woomera_profile_thread_running(woomera_profile * profile, int set, int new);
static int tech_create_read_socket(private_object *tech_pvt); static int woomera_locate_socket(woomera_profile * profile, switch_socket_t **woomera_socket);
static int tech_create_read_socket(private_object * tech_pvt);
static void *woomera_channel_thread_run(switch_thread *thread, void *obj); static void *woomera_channel_thread_run(switch_thread *thread, void *obj);
static void *woomera_thread_run(void *obj); static void *woomera_thread_run(void *obj);
static int tech_activate(private_object *tech_pvt); static int tech_activate(private_object * tech_pvt);
/* /*
State methods they get called when the state changes to the specific state State methods they get called when the state changes to the specific state
@ -208,13 +212,17 @@ static switch_status woomerachan_on_init(switch_core_session *session)
tech_pvt->frame.data = tech_pvt->databuf; tech_pvt->frame.data = tech_pvt->databuf;
if (switch_core_codec_init(&tech_pvt->read_codec, "L16", rate, 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { if (switch_core_codec_init
(&tech_pvt->read_codec, "L16", rate, 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s Cannot set read codec\n", switch_channel_get_name(channel)); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s Cannot set read codec\n", switch_channel_get_name(channel));
switch_channel_hangup(channel); switch_channel_hangup(channel);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
if (switch_core_codec_init(&tech_pvt->write_codec, "L16", rate, 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { if (switch_core_codec_init
(&tech_pvt->write_codec, "L16", rate, 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s Cannot set read codec\n", switch_channel_get_name(channel)); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s Cannot set read codec\n", switch_channel_get_name(channel));
switch_channel_hangup(channel); switch_channel_hangup(channel);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
@ -322,7 +330,8 @@ static switch_status woomerachan_kill_channel(switch_core_session *session, int
udp_socket_close(tech_pvt); udp_socket_close(tech_pvt);
switch_channel_hangup(channel); switch_channel_hangup(channel);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s WOOMERACHAN KILL %d\n", switch_channel_get_name(channel), tech_pvt->udp_socket); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s WOOMERACHAN KILL %d\n", switch_channel_get_name(channel),
tech_pvt->udp_socket);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -344,14 +353,16 @@ static switch_status woomerachan_on_transmit(switch_core_session *session)
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines /* 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! that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
*/ */
static switch_status woomerachan_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile, switch_core_session **new_session) static switch_status woomerachan_outgoing_channel(switch_core_session *session, switch_caller_profile *outbound_profile,
switch_core_session **new_session)
{ {
if ((*new_session = switch_core_session_request(&woomerachan_endpoint_interface, NULL))) { if ((*new_session = switch_core_session_request(&woomerachan_endpoint_interface, NULL))) {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel *channel; switch_channel *channel;
switch_core_session_add_stream(*new_session, NULL); switch_core_session_add_stream(*new_session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) { if ((tech_pvt =
(struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt)); memset(tech_pvt, 0, sizeof(*tech_pvt));
tech_pvt->profile = &default_profile; tech_pvt->profile = &default_profile;
channel = switch_core_session_get_channel(*new_session); channel = switch_core_session_get_channel(*new_session);
@ -409,7 +420,8 @@ static switch_status woomerachan_waitfor_write(switch_core_session *session, int
return switch_socket_waitfor(&tech_pvt->write_poll, ms); return switch_socket_waitfor(&tech_pvt->write_poll, ms);
} }
static switch_status woomerachan_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags, int stream_id) static switch_status woomerachan_read_frame(switch_core_session *session, switch_frame **frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
switch_channel *channel = NULL; switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
@ -426,21 +438,24 @@ static switch_status woomerachan_read_frame(switch_core_session *session, switch
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
/* /*
if ((status = woomerachan_waitfor_read(session, -1)) != SWITCH_STATUS_SUCCESS) { if ((status = woomerachan_waitfor_read(session, -1)) != SWITCH_STATUS_SUCCESS) {
return status; return status;
}1< }1<
*/ */
pframe = &tech_pvt->frame; pframe = &tech_pvt->frame;
*frame = pframe; *frame = pframe;
pframe->datalen = sizeof(tech_pvt->databuf); pframe->datalen = sizeof(tech_pvt->databuf);
if ((status = switch_socket_recvfrom (tech_pvt->udpread, tech_pvt->udp_socket, 0, tech_pvt->databuf, &pframe->datalen)) == SWITCH_STATUS_SUCCESS) { if ((status =
pframe->samples = (int)pframe->datalen / 2; switch_socket_recvfrom(tech_pvt->udpread, tech_pvt->udp_socket, 0, tech_pvt->databuf,
&pframe->datalen)) == SWITCH_STATUS_SUCCESS) {
pframe->samples = (int) pframe->datalen / 2;
} }
return status; return status;
} }
static switch_status woomerachan_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags, int stream_id) static switch_status woomerachan_write_frame(switch_core_session *session, switch_frame *frame, int timeout,
switch_io_flag flags, int stream_id)
{ {
switch_channel *channel = NULL; switch_channel *channel = NULL;
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
@ -462,43 +477,43 @@ static switch_status woomerachan_write_frame(switch_core_session *session, switc
} }
static const switch_event_handler_table woomerachan_event_handlers = { static const switch_event_handler_table woomerachan_event_handlers = {
/*.on_init*/ woomerachan_on_init, /*.on_init */ woomerachan_on_init,
/*.on_ring*/ woomerachan_on_ring, /*.on_ring */ woomerachan_on_ring,
/*.on_execute*/ woomerachan_on_execute, /*.on_execute */ woomerachan_on_execute,
/*.on_hangup*/ woomerachan_on_hangup, /*.on_hangup */ woomerachan_on_hangup,
/*.on_loopback*/ woomerachan_on_loopback, /*.on_loopback */ woomerachan_on_loopback,
/*.on_transmit*/ woomerachan_on_transmit /*.on_transmit */ woomerachan_on_transmit
}; };
static const switch_io_routines woomerachan_io_routines = { static const switch_io_routines woomerachan_io_routines = {
/*.outgoing_channel*/ woomerachan_outgoing_channel, /*.outgoing_channel */ woomerachan_outgoing_channel,
/*.answer_channel*/ NULL, /*.answer_channel */ NULL,
/*.read_frame*/ woomerachan_read_frame, /*.read_frame */ woomerachan_read_frame,
/*.write_frame*/ woomerachan_write_frame, /*.write_frame */ woomerachan_write_frame,
/*.kill_channel*/ woomerachan_kill_channel, /*.kill_channel */ woomerachan_kill_channel,
/*.waitfor_read*/ woomerachan_waitfor_read, /*.waitfor_read */ woomerachan_waitfor_read,
/*.waitfor_write*/ woomerachan_waitfor_write /*.waitfor_write */ woomerachan_waitfor_write
}; };
static const switch_endpoint_interface woomerachan_endpoint_interface = { static const switch_endpoint_interface woomerachan_endpoint_interface = {
/*.interface_name*/ "woomera", /*.interface_name */ "woomera",
/*.io_routines*/ &woomerachan_io_routines, /*.io_routines */ &woomerachan_io_routines,
/*.event_handlers*/ &woomerachan_event_handlers, /*.event_handlers */ &woomerachan_event_handlers,
/*.private*/ NULL, /*.private */ NULL,
/*.next*/ NULL /*.next */ NULL
}; };
static const switch_loadable_module_interface woomerachan_module_interface = { static const switch_loadable_module_interface woomerachan_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ &woomerachan_endpoint_interface, /*.endpoint_interface */ &woomerachan_endpoint_interface,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
static void tech_destroy(private_object *tech_pvt) static void tech_destroy(private_object * tech_pvt)
{ {
woomera_message wmsg; woomera_message wmsg;
@ -507,14 +522,11 @@ static void tech_destroy(private_object *tech_pvt)
} }
woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "hangup %s%s", tech_pvt->call_info.callid, WOOMERA_RECORD_SEPERATOR); woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "hangup %s%s", tech_pvt->call_info.callid,
if(woomera_message_parse(tech_pvt->command_channel, WOOMERA_RECORD_SEPERATOR);
&wmsg, if (woomera_message_parse
WOOMERA_HARD_TIMEOUT, (tech_pvt->command_channel, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) {
tech_pvt->profile, switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} Already Disconnected\n", tech_pvt->profile->name);
&tech_pvt->event_queue
) < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} Already Disconnected\n", tech_pvt->profile->name);
} }
woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "bye%s", WOOMERA_RECORD_SEPERATOR); woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "bye%s", WOOMERA_RECORD_SEPERATOR);
@ -523,7 +535,7 @@ static void tech_destroy(private_object *tech_pvt)
} }
static void woomera_printf(woomera_profile *profile, switch_socket_t *socket, char *fmt, ...) static void woomera_printf(woomera_profile * profile, switch_socket_t *socket, char *fmt, ...)
{ {
char *stuff; char *stuff;
size_t res = 0, len = 0; size_t res = 0, len = 0;
@ -531,7 +543,7 @@ static void woomera_printf(woomera_profile *profile, switch_socket_t *socket, ch
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
#ifndef vasprintf #ifndef vasprintf
stuff = (char *)malloc(10240); stuff = (char *) malloc(10240);
vsnprintf(stuff, 10240, fmt, ap); vsnprintf(stuff, 10240, fmt, ap);
#else #else
res = vasprintf(&stuff, fmt, ap); res = vasprintf(&stuff, fmt, ap);
@ -541,7 +553,8 @@ static void woomera_printf(woomera_profile *profile, switch_socket_t *socket, ch
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Out of memory\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Out of memory\n");
} else { } else {
if (profile && globals.debug) { if (profile && globals.debug) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Send Message: {%s} [%s/%d]\n%s\n%s", profile->name, profile->woomera_host, profile->woomera_port, WOOMERA_DEBUG_LINE, stuff); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Send Message: {%s} [%s/%d]\n%s\n%s", profile->name,
profile->woomera_host, profile->woomera_port, WOOMERA_DEBUG_LINE, stuff);
} }
len = strlen(stuff); len = strlen(stuff);
switch_socket_send(socket, stuff, &len); switch_socket_send(socket, stuff, &len);
@ -551,12 +564,12 @@ static void woomera_printf(woomera_profile *profile, switch_socket_t *socket, ch
} }
static char *woomera_message_header(woomera_message *wmsg, char *key) static char *woomera_message_header(woomera_message * wmsg, char *key)
{ {
int x = 0; int x = 0;
char *value = NULL; char *value = NULL;
for (x = 0 ; x < wmsg->last ; x++) { for (x = 0; x < wmsg->last; x++) {
if (!strcasecmp(wmsg->names[x], key)) { if (!strcasecmp(wmsg->names[x], key)) {
value = wmsg->values[x]; value = wmsg->values[x];
break; break;
@ -566,7 +579,7 @@ static char *woomera_message_header(woomera_message *wmsg, char *key)
return value; return value;
} }
static int woomera_enqueue_event(woomera_event_queue *event_queue, woomera_message *wmsg) static int woomera_enqueue_event(woomera_event_queue * event_queue, woomera_message * wmsg)
{ {
woomera_message *new, *mptr; woomera_message *new, *mptr;
@ -577,7 +590,7 @@ static int woomera_enqueue_event(woomera_event_queue *event_queue, woomera_messa
if (!event_queue->head) { if (!event_queue->head) {
event_queue->head = new; event_queue->head = new;
} else { } else {
for (mptr = event_queue->head; mptr && mptr->next ; mptr = mptr->next); for (mptr = event_queue->head; mptr && mptr->next; mptr = mptr->next);
mptr->next = new; mptr->next = new;
} }
return 1; return 1;
@ -588,7 +601,7 @@ static int woomera_enqueue_event(woomera_event_queue *event_queue, woomera_messa
return 0; return 0;
} }
static int woomera_dequeue_event(woomera_event_queue *event_queue, woomera_message *wmsg) static int woomera_dequeue_event(woomera_event_queue * event_queue, woomera_message * wmsg)
{ {
woomera_message *mptr = NULL; woomera_message *mptr = NULL;
@ -608,7 +621,8 @@ static int woomera_dequeue_event(woomera_event_queue *event_queue, woomera_messa
return 0; return 0;
} }
static int woomera_message_parse(switch_socket_t *fd, woomera_message *wmsg, int timeout, woomera_profile *profile, woomera_event_queue *event_queue) static int woomera_message_parse(switch_socket_t *fd, woomera_message * wmsg, int timeout, woomera_profile * profile,
woomera_event_queue * event_queue)
{ {
char *cur, *cr, *next = NULL, *eor = NULL; char *cur, *cr, *next = NULL, *eor = NULL;
char buf[2048] = "", *ptr; char buf[2048] = "", *ptr;
@ -617,7 +631,7 @@ static int woomera_message_parse(switch_socket_t *fd, woomera_message *wmsg, int
memset(wmsg, 0, sizeof(woomera_message)); memset(wmsg, 0, sizeof(woomera_message));
if (fd < 0 ) { if (fd < 0) {
return -1; return -1;
} }
@ -647,10 +661,11 @@ static int woomera_message_parse(switch_socket_t *fd, woomera_message *wmsg, int
next = buf; next = buf;
if (globals.debug) { if (globals.debug) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Receive Message: {%s} [%s/%d]\n%s\n%s", profile->name, profile->woomera_host, profile->woomera_port, WOOMERA_DEBUG_LINE, buf); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Receive Message: {%s} [%s/%d]\n%s\n%s", profile->name,
profile->woomera_host, profile->woomera_port, WOOMERA_DEBUG_LINE, buf);
} }
while((cur = next)) { while ((cur = next)) {
if ((cr = strstr(cur, WOOMERA_LINE_SEPERATOR))) { if ((cr = strstr(cur, WOOMERA_LINE_SEPERATOR))) {
*cr = '\0'; *cr = '\0';
next = cr + (sizeof(WOOMERA_LINE_SEPERATOR) - 1); next = cr + (sizeof(WOOMERA_LINE_SEPERATOR) - 1);
@ -710,9 +725,9 @@ static int woomera_message_parse(switch_socket_t *fd, woomera_message *wmsg, int
*val = '\0'; *val = '\0';
val++; val++;
} }
strncpy(wmsg->values[wmsg->last-1], val, WOOMERA_STRLEN); strncpy(wmsg->values[wmsg->last - 1], val, WOOMERA_STRLEN);
} }
strncpy(wmsg->names[wmsg->last-1], name, WOOMERA_STRLEN); strncpy(wmsg->names[wmsg->last - 1], name, WOOMERA_STRLEN);
if (name && val && !strcasecmp(name, "content-type")) { if (name && val && !strcasecmp(name, "content-type")) {
switch_set_flag(wmsg, WFLAG_CONTENT); switch_set_flag(wmsg, WFLAG_CONTENT);
bytes = atoi(val); bytes = atoi(val);
@ -748,7 +763,7 @@ static int woomera_message_parse(switch_socket_t *fd, woomera_message *wmsg, int
} else if (wmsg->mval > 99 && wmsg->mval < 200) { } else if (wmsg->mval > 99 && wmsg->mval < 200) {
/* reply in the 100's are nice but we need to wait for another reply /* reply in the 100's are nice but we need to wait for another reply
call ourself recursively to find the reply > 199 and forget this reply. call ourself recursively to find the reply > 199 and forget this reply.
*/ */
return woomera_message_parse(fd, wmsg, timeout, profile, event_queue); return woomera_message_parse(fd, wmsg, timeout, profile, event_queue);
} else { } else {
return switch_test_flag(wmsg, WFLAG_EXISTS); return switch_test_flag(wmsg, WFLAG_EXISTS);
@ -756,7 +771,7 @@ static int woomera_message_parse(switch_socket_t *fd, woomera_message *wmsg, int
} }
static int connect_woomera(switch_socket_t **new_sock, woomera_profile *profile, int flags) static int connect_woomera(switch_socket_t **new_sock, woomera_profile * profile, int flags)
{ {
switch_sockaddr_t *sa; switch_sockaddr_t *sa;
@ -771,12 +786,12 @@ static int connect_woomera(switch_socket_t **new_sock, woomera_profile *profile,
return -1; return -1;
} }
/* /*
status = switch_socket_bind((*new_sock), sa); status = switch_socket_bind((*new_sock), sa);
if (0 && status != SWITCH_STATUS_SUCCESS) { if (0 && status != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't Bind to %s:%d!\n", profile->woomera_host, profile->woomera_port); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't Bind to %s:%d!\n", profile->woomera_host, profile->woomera_port);
return -1; return -1;
} }
*/ */
status = switch_socket_connect((*new_sock), sa); status = switch_socket_connect((*new_sock), sa);
if (status != SWITCH_STATUS_SUCCESS) { if (status != SWITCH_STATUS_SUCCESS) {
return -1; return -1;
@ -785,7 +800,7 @@ static int connect_woomera(switch_socket_t **new_sock, woomera_profile *profile,
return 1; return 1;
} }
static int woomera_profile_thread_running(woomera_profile *profile, int set, int new) static int woomera_profile_thread_running(woomera_profile * profile, int set, int new)
{ {
int running = 0; int running = 0;
@ -799,7 +814,7 @@ static int woomera_profile_thread_running(woomera_profile *profile, int set, int
} }
static int woomera_locate_socket(woomera_profile *profile, switch_socket_t **woomera_socket) static int woomera_locate_socket(woomera_profile * profile, switch_socket_t **woomera_socket)
{ {
woomera_message wmsg; woomera_message wmsg;
@ -809,7 +824,8 @@ static int woomera_locate_socket(woomera_profile *profile, switch_socket_t **woo
if (!woomera_profile_thread_running(profile, 0, 0)) { if (!woomera_profile_thread_running(profile, 0, 0)) {
break; break;
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} Cannot Reconnect to Woomera! retry in 5 seconds\n", profile->name); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} Cannot Reconnect to Woomera! retry in 5 seconds\n",
profile->name);
switch_sleep(WOOMERA_RECONNECT_TIME); switch_sleep(WOOMERA_RECONNECT_TIME);
} }
@ -817,11 +833,7 @@ static int woomera_locate_socket(woomera_profile *profile, switch_socket_t **woo
if (switch_test_flag(profile, PFLAG_INBOUND)) { if (switch_test_flag(profile, PFLAG_INBOUND)) {
woomera_printf(profile, *woomera_socket, "LISTEN%s", WOOMERA_RECORD_SEPERATOR); woomera_printf(profile, *woomera_socket, "LISTEN%s", WOOMERA_RECORD_SEPERATOR);
if (woomera_message_parse(*woomera_socket, if (woomera_message_parse(*woomera_socket,
&wmsg, &wmsg, WOOMERA_HARD_TIMEOUT, profile, &profile->event_queue) < 0) {
WOOMERA_HARD_TIMEOUT,
profile,
&profile->event_queue
) < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n", profile->name); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n", profile->name);
globals.panic = 1; globals.panic = 1;
woomera_profile_thread_running(&default_profile, 1, 0); woomera_profile_thread_running(&default_profile, 1, 0);
@ -843,7 +855,7 @@ static int woomera_locate_socket(woomera_profile *profile, switch_socket_t **woo
static int tech_create_read_socket(private_object *tech_pvt) static int tech_create_read_socket(private_object * tech_pvt)
{ {
switch_memory_pool *pool = switch_core_session_get_pool(tech_pvt->session); switch_memory_pool *pool = switch_core_session_get_pool(tech_pvt->session);
@ -857,20 +869,20 @@ static int tech_create_read_socket(private_object *tech_pvt)
switch_sockaddr_info_get(&tech_pvt->udpread, tech_pvt->profile->audio_ip, SWITCH_UNSPEC, tech_pvt->port, 0, pool); switch_sockaddr_info_get(&tech_pvt->udpread, tech_pvt->profile->audio_ip, SWITCH_UNSPEC, tech_pvt->port, 0, pool);
if (switch_socket_create(&tech_pvt->udp_socket, AF_INET, SOCK_DGRAM, 0, pool) == SWITCH_STATUS_SUCCESS) { if (switch_socket_create(&tech_pvt->udp_socket, AF_INET, SOCK_DGRAM, 0, pool) == SWITCH_STATUS_SUCCESS) {
switch_socket_bind(tech_pvt->udp_socket, tech_pvt->udpread); switch_socket_bind(tech_pvt->udp_socket, tech_pvt->udpread);
switch_socket_create_pollfd(&tech_pvt->read_poll, tech_pvt->udp_socket, SWITCH_POLLIN|SWITCH_POLLERR, pool); switch_socket_create_pollfd(&tech_pvt->read_poll, tech_pvt->udp_socket, SWITCH_POLLIN | SWITCH_POLLERR, pool);
switch_socket_create_pollfd(&tech_pvt->write_poll, tech_pvt->udp_socket, SWITCH_POLLOUT|SWITCH_POLLERR, pool); switch_socket_create_pollfd(&tech_pvt->write_poll, tech_pvt->udp_socket, SWITCH_POLLOUT | SWITCH_POLLERR, pool);
} }
return 0; return 0;
} }
static int tech_activate(private_object *tech_pvt) static int tech_activate(private_object * tech_pvt)
{ {
woomera_message wmsg; woomera_message wmsg;
if (tech_pvt) { if (tech_pvt) {
if((connect_woomera(&tech_pvt->command_channel, tech_pvt->profile, 0))) { if ((connect_woomera(&tech_pvt->command_channel, tech_pvt->profile, 0))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "connected to woomera!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "connected to woomera!\n");
} else { } else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't connect to woomera!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't connect to woomera!\n");
@ -889,26 +901,17 @@ static int tech_activate(private_object *tech_pvt)
tech_pvt->port, tech_pvt->port,
WOOMERA_LINE_SEPERATOR, WOOMERA_LINE_SEPERATOR,
tech_pvt->caller_profile->caller_id_name, tech_pvt->caller_profile->caller_id_name,
tech_pvt->caller_profile->caller_id_number, tech_pvt->caller_profile->caller_id_number, WOOMERA_RECORD_SEPERATOR);
WOOMERA_RECORD_SEPERATOR
);
woomera_message_parse(tech_pvt->command_channel, woomera_message_parse(tech_pvt->command_channel,
&wmsg, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue);
WOOMERA_HARD_TIMEOUT,
tech_pvt->profile,
&tech_pvt->event_queue
);
} else { } else {
switch_set_flag(tech_pvt, TFLAG_PARSE_INCOMING); switch_set_flag(tech_pvt, TFLAG_PARSE_INCOMING);
woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "LISTEN%s", WOOMERA_RECORD_SEPERATOR); woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "LISTEN%s", WOOMERA_RECORD_SEPERATOR);
if (woomera_message_parse(tech_pvt->command_channel, if (woomera_message_parse(tech_pvt->command_channel,
&wmsg, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) {
WOOMERA_HARD_TIMEOUT, switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n",
tech_pvt->profile, tech_pvt->profile->name);
&tech_pvt->event_queue
) < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n", tech_pvt->profile->name);
switch_set_flag(tech_pvt, TFLAG_ABORT); switch_set_flag(tech_pvt, TFLAG_ABORT);
globals.panic = 1; globals.panic = 1;
} }
@ -943,7 +946,7 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
} }
for(;;) { for (;;) {
if (globals.panic) { if (globals.panic) {
switch_set_flag(tech_pvt, TFLAG_ABORT); switch_set_flag(tech_pvt, TFLAG_ABORT);
} }
@ -964,14 +967,13 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
if (switch_test_flag(tech_pvt, TFLAG_ANSWER)) { if (switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
switch_clear_flag(tech_pvt, TFLAG_ANSWER); switch_clear_flag(tech_pvt, TFLAG_ANSWER);
#ifdef USE_ANSWER #ifdef USE_ANSWER
woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "ANSWER %s%s",tech_pvt->call_info.callid, WOOMERA_RECORD_SEPERATOR); woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "ANSWER %s%s", tech_pvt->call_info.callid,
if(woomera_message_parse(tech_pvt->command_channel, WOOMERA_RECORD_SEPERATOR);
&wmsg, if (woomera_message_parse
WOOMERA_HARD_TIMEOUT, (tech_pvt->command_channel, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile,
tech_pvt->profile, &tech_pvt->event_queue) < 0) {
&tech_pvt->event_queue switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n",
) < 0) { tech_pvt->profile->name);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n", tech_pvt->profile->name);
switch_set_flag(tech_pvt, TFLAG_ABORT); switch_set_flag(tech_pvt, TFLAG_ABORT);
globals.panic = 1; globals.panic = 1;
continue; continue;
@ -981,14 +983,13 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
if (switch_test_flag(tech_pvt, TFLAG_DTMF)) { if (switch_test_flag(tech_pvt, TFLAG_DTMF)) {
switch_mutex_lock(tech_pvt->iolock); switch_mutex_lock(tech_pvt->iolock);
woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "DTMF %s %s%s",tech_pvt->call_info.callid, tech_pvt->dtmfbuf, WOOMERA_RECORD_SEPERATOR); woomera_printf(tech_pvt->profile, tech_pvt->command_channel, "DTMF %s %s%s", tech_pvt->call_info.callid,
if(woomera_message_parse(tech_pvt->command_channel, tech_pvt->dtmfbuf, WOOMERA_RECORD_SEPERATOR);
&wmsg, if (woomera_message_parse
WOOMERA_HARD_TIMEOUT, (tech_pvt->command_channel, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile,
tech_pvt->profile, &tech_pvt->event_queue) < 0) {
&tech_pvt->event_queue switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n",
) < 0) { tech_pvt->profile->name);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n", tech_pvt->profile->name);
switch_set_flag(tech_pvt, TFLAG_ABORT); switch_set_flag(tech_pvt, TFLAG_ABORT);
globals.panic = 1; globals.panic = 1;
continue; continue;
@ -997,13 +998,14 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
memset(tech_pvt->dtmfbuf, 0, sizeof(tech_pvt->dtmfbuf)); memset(tech_pvt->dtmfbuf, 0, sizeof(tech_pvt->dtmfbuf));
switch_mutex_unlock(tech_pvt->iolock); switch_mutex_unlock(tech_pvt->iolock);
} }
#if 1==0 /*convert to use switch_time_now */
#if 1==0 /*convert to use switch_time_now */ if (tech_pvt->timeout) {
if(tech_pvt->timeout) {
struct timeval now; struct timeval now;
int elapsed; int elapsed;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
elapsed = (((now.tv_sec * 1000) + now.tv_usec / 1000) - ((tech_pvt->started.tv_sec * 1000) + tech_pvt->started.tv_usec / 1000)); elapsed =
(((now.tv_sec * 1000) + now.tv_usec / 1000) -
((tech_pvt->started.tv_sec * 1000) + tech_pvt->started.tv_usec / 1000));
if (elapsed > tech_pvt->timeout) { if (elapsed > tech_pvt->timeout) {
/* call timed out! */ /* call timed out! */
switch_set_flag(tech_pvt, TFLAG_ABORT); switch_set_flag(tech_pvt, TFLAG_ABORT);
@ -1015,29 +1017,24 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
break; break;
} }
/* Check for events */ /* Check for events */
if((res = woomera_dequeue_event(&tech_pvt->event_queue, &wmsg)) || if ((res = woomera_dequeue_event(&tech_pvt->event_queue, &wmsg)) ||
(res = woomera_message_parse(tech_pvt->command_channel, (res = woomera_message_parse(tech_pvt->command_channel, &wmsg, 100, tech_pvt->profile, NULL))) {
&wmsg,
100,
tech_pvt->profile,
NULL
))) {
if (res < 0 || !strcasecmp(wmsg.command, "HANGUP")) { if (res < 0 || !strcasecmp(wmsg.command, "HANGUP")) {
switch_set_flag(tech_pvt, TFLAG_ABORT); switch_set_flag(tech_pvt, TFLAG_ABORT);
continue; continue;
} else if (!strcasecmp(wmsg.command, "DTMF")) { } else if (!strcasecmp(wmsg.command, "DTMF")) {
/* /*
struct ast_frame dtmf_frame = {AST_FRAME_DTMF}; struct ast_frame dtmf_frame = {AST_FRAME_DTMF};
int x = 0; int x = 0;
for (x = 0; x < strlen(wmsg.command_args); x++) { for (x = 0; x < strlen(wmsg.command_args); x++) {
dtmf_frame.subclass = wmsg.command_args[x]; dtmf_frame.subclass = wmsg.command_args[x];
ast_queue_frame(tech_pvt->owner, ast_frdup(&dtmf_frame)); ast_queue_frame(tech_pvt->owner, ast_frdup(&dtmf_frame));
if (globals.debug > 1) { if (globals.debug > 1) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, WOOMERA_DEBUG_PREFIX "SEND DTMF [%c] to %s\n", dtmf_frame.subclass, tech_pvt->owner->name); switch_console_printf(SWITCH_CHANNEL_CONSOLE, WOOMERA_DEBUG_PREFIX "SEND DTMF [%c] to %s\n", dtmf_frame.subclass, tech_pvt->owner->name);
} }
} }
*/ */
} else if (!strcasecmp(wmsg.command, "PROCEED")) { } else if (!strcasecmp(wmsg.command, "PROCEED")) {
/* This packet has lots of info so well keep it */ /* This packet has lots of info so well keep it */
tech_pvt->call_info = wmsg; tech_pvt->call_info = wmsg;
@ -1070,15 +1067,11 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
if ((tech_pvt->caller_profile = switch_caller_profile_new(session, if ((tech_pvt->caller_profile = switch_caller_profile_new(session,
tech_pvt->profile->dialplan, tech_pvt->profile->dialplan,
cid_name, cid_name, cid_num, ip, NULL, NULL, exten))) {
cid_num,
ip,
NULL,
NULL,
exten))) {
char name[128]; char name[128];
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
snprintf(name, sizeof(name), "Woomera/%s-%04x", tech_pvt->caller_profile->destination_number, rand() & 0xffff); snprintf(name, sizeof(name), "Woomera/%s-%04x", tech_pvt->caller_profile->destination_number,
rand() & 0xffff);
switch_channel_set_name(channel, name); switch_channel_set_name(channel, name);
} }
@ -1088,17 +1081,12 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
MEDIA_ANSWER, MEDIA_ANSWER,
wmsg.callid, wmsg.callid,
WOOMERA_LINE_SEPERATOR, WOOMERA_LINE_SEPERATOR,
tech_pvt->profile->audio_ip, tech_pvt->profile->audio_ip, tech_pvt->port, WOOMERA_RECORD_SEPERATOR);
tech_pvt->port,
WOOMERA_RECORD_SEPERATOR);
if(woomera_message_parse(tech_pvt->command_channel, if (woomera_message_parse(tech_pvt->command_channel,
&wmsg, &wmsg, WOOMERA_HARD_TIMEOUT, tech_pvt->profile, &tech_pvt->event_queue) < 0) {
WOOMERA_HARD_TIMEOUT, switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n",
tech_pvt->profile, tech_pvt->profile->name);
&tech_pvt->event_queue
) < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n", tech_pvt->profile->name);
switch_set_flag(tech_pvt, TFLAG_ABORT); switch_set_flag(tech_pvt, TFLAG_ABORT);
globals.panic = 1; globals.panic = 1;
continue; continue;
@ -1115,7 +1103,7 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
int port = 0; int port = 0;
strncpy(ip, raw_audio_header, sizeof(ip) - 1); strncpy(ip, raw_audio_header, sizeof(ip) - 1);
if ((ptr=strchr(ip, '/'))) { if ((ptr = strchr(ip, '/'))) {
*ptr = '\0'; *ptr = '\0';
ptr++; ptr++;
port = atoi(ptr); port = atoi(ptr);
@ -1129,9 +1117,12 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
SWITCH_UNSPEC, SWITCH_UNSPEC,
port, port,
0, 0,
switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { switch_core_session_get_pool(tech_pvt->session)) !=
SWITCH_STATUS_SUCCESS) {
if (globals.debug) { if (globals.debug) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, WOOMERA_DEBUG_PREFIX "{%s} Cannot resolve %s\n", tech_pvt->profile->name, ip); switch_console_printf(SWITCH_CHANNEL_CONSOLE,
WOOMERA_DEBUG_PREFIX "{%s} Cannot resolve %s\n",
tech_pvt->profile->name, ip);
} }
switch_channel_hangup(channel); switch_channel_hangup(channel);
} }
@ -1139,11 +1130,13 @@ static void *woomera_channel_thread_run(switch_thread *thread, void *obj)
} }
} }
if (globals.debug > 2) { if (globals.debug > 2) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, WOOMERA_DEBUG_PREFIX "CHECK {%s}(%d)\n", tech_pvt->profile->name, res); switch_console_printf(SWITCH_CHANNEL_CONSOLE, WOOMERA_DEBUG_PREFIX "CHECK {%s}(%d)\n",
tech_pvt->profile->name, res);
} }
} }
if (globals.debug > 1) { if (globals.debug > 1) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, WOOMERA_DEBUG_PREFIX "Monitor thread for %s done.\n", tech_pvt->profile->name); switch_console_printf(SWITCH_CHANNEL_CONSOLE, WOOMERA_DEBUG_PREFIX "Monitor thread for %s done.\n",
tech_pvt->profile->name);
} }
return NULL; return NULL;
@ -1166,7 +1159,7 @@ static void *woomera_thread_run(void *obj)
profile->woomera_socket = NULL; profile->woomera_socket = NULL;
while(woomera_profile_thread_running(profile, 0, 0)) { while (woomera_profile_thread_running(profile, 0, 0)) {
/* listen on socket and handle events */ /* listen on socket and handle events */
if (globals.panic == 2) { if (globals.panic == 2) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Woomera is disabled!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Woomera is disabled!\n");
@ -1174,21 +1167,22 @@ static void *woomera_thread_run(void *obj)
continue; continue;
} }
if (! profile->woomera_socket) { if (!profile->woomera_socket) {
if (woomera_locate_socket(profile, &profile->woomera_socket)) { if (woomera_locate_socket(profile, &profile->woomera_socket)) {
globals.panic = 0; globals.panic = 0;
} }
if (!woomera_profile_thread_running(profile, 0, 0)) { if (!woomera_profile_thread_running(profile, 0, 0)) {
break; break;
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Woomera Thread Up {%s} %s/%d\n", profile->name, profile->woomera_host, profile->woomera_port); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Woomera Thread Up {%s} %s/%d\n", profile->name,
profile->woomera_host, profile->woomera_port);
} }
if (globals.panic) { if (globals.panic) {
if (globals.panic != 2) { if (globals.panic != 2) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Help I'm in a state of panic!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Help I'm in a state of panic!\n");
globals.panic = 0;//fix globals.panic = 0; //fix
} }
woomera_socket_close(&profile->woomera_socket); woomera_socket_close(&profile->woomera_socket);
@ -1197,15 +1191,12 @@ static void *woomera_thread_run(void *obj)
} }
if ((res = woomera_dequeue_event(&profile->event_queue, &wmsg) || if ((res = woomera_dequeue_event(&profile->event_queue, &wmsg) ||
(res = woomera_message_parse(profile->woomera_socket, (res = woomera_message_parse(profile->woomera_socket, &wmsg,
&wmsg,
/* if we are not stingy with threads we can block forever */ /* if we are not stingy with threads we can block forever */
0, 0, profile, NULL)))) {
profile,
NULL
)))) {
if (res < 0) { if (res < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! I lost my connection to woomera!\n", profile->name); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! I lost my connection to woomera!\n",
profile->name);
woomera_socket_close(&profile->woomera_socket); woomera_socket_close(&profile->woomera_socket);
//global_set_flag(TFLAG_ABORT); //global_set_flag(TFLAG_ABORT);
@ -1216,18 +1207,16 @@ static void *woomera_thread_run(void *obj)
if (switch_test_flag(profile, PFLAG_INBOUND)) { if (switch_test_flag(profile, PFLAG_INBOUND)) {
woomera_printf(profile, profile->woomera_socket, "LISTEN%s", WOOMERA_RECORD_SEPERATOR); woomera_printf(profile, profile->woomera_socket, "LISTEN%s", WOOMERA_RECORD_SEPERATOR);
if (woomera_message_parse(profile->woomera_socket, if (woomera_message_parse(profile->woomera_socket,
&wmsg, &wmsg, WOOMERA_HARD_TIMEOUT, profile, &profile->event_queue) < 0) {
WOOMERA_HARD_TIMEOUT, switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n",
profile, profile->name);
&profile->event_queue
) < 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "{%s} HELP! Woomera is broken!\n", profile->name);
globals.panic = 1; globals.panic = 1;
woomera_socket_close(&profile->woomera_socket); woomera_socket_close(&profile->woomera_socket);
} }
} }
if (profile->woomera_socket) { if (profile->woomera_socket) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Woomera Thread Up {%s} %s/%d\n", profile->name, profile->woomera_host, profile->woomera_port); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Woomera Thread Up {%s} %s/%d\n", profile->name,
profile->woomera_host, profile->woomera_port);
} }
} }
continue; continue;
@ -1248,7 +1237,8 @@ static void *woomera_thread_run(void *obj)
switch_core_session_add_stream(session, NULL); switch_core_session_add_stream(session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(session, sizeof(struct private_object)))) { if ((tech_pvt =
(struct private_object *) switch_core_session_alloc(session, sizeof(struct private_object)))) {
memset(tech_pvt, 0, sizeof(*tech_pvt)); memset(tech_pvt, 0, sizeof(*tech_pvt));
tech_pvt->profile = &default_profile; tech_pvt->profile = &default_profile;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
@ -1305,7 +1295,8 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
switch_config cfg; switch_config cfg;
char *var, *val; char *var, *val;
@ -1326,9 +1317,9 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul
while (switch_config_next_pair(&cfg, &var, &val)) { while (switch_config_next_pair(&cfg, &var, &val)) {
if (!strcasecmp(cfg.category, "settings")) { if (!strcasecmp(cfg.category, "settings")) {
if (!strcmp(var, "noload") && atoi(val)) { if (!strcmp(var, "noload") && atoi(val)) {
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }
if (!strcmp(var, "debug")) { if (!strcmp(var, "debug")) {
globals.debug = atoi(val); globals.debug = atoi(val);
} }
@ -1384,6 +1375,3 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul
/* indicate that the module should continue to be loaded */ /* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -33,11 +33,11 @@
static const char modname[] = "mod_event_test"; static const char modname[] = "mod_event_test";
static void event_handler (switch_event *event) static void event_handler(switch_event *event)
{ {
char buf[1024]; char buf[1024];
switch(event->event_id) { switch (event->event_id) {
case SWITCH_EVENT_LOG: case SWITCH_EVENT_LOG:
return; return;
break; break;
@ -50,12 +50,12 @@ static void event_handler (switch_event *event)
static switch_loadable_module_interface event_test_module_interface = { static switch_loadable_module_interface event_test_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ NULL, /*.endpoint_interface */ NULL,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
#define MY_EVENT_COOL "test::cool" #define MY_EVENT_COOL "test::cool"
@ -76,9 +76,9 @@ static void *torture_thread(switch_thread *thread, void *obj)
z = THREADS++; z = THREADS++;
while(THREADS > 0) { while (THREADS > 0) {
int x; int x;
for(x = 0; x < 1; x++) { for (x = 0; x < 1; x++) {
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_COOL) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_COOL) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, "event_info", "hello world %d %d", z, y++); switch_event_add_header(event, "event_info", "hello world %d %d", z, y++);
switch_event_fire(&event); switch_event_fire(&event);
@ -104,7 +104,8 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
#endif #endif
SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &event_test_module_interface; *interface = &event_test_module_interface;
@ -112,16 +113,16 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_inte
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't register subclass!"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't register subclass!");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
#ifdef TORTURE_ME #ifdef TORTURE_ME
if (switch_event_bind((char *)modname, SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL) != SWITCH_STATUS_SUCCESS) { if (switch_event_bind((char *) modname, SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL) !=
SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't bind!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't bind!\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
if (1) { if (1) {
int x = 0; int x = 0;
for(x = 0 ; x < TTHREADS ; x++) { for (x = 0; x < TTHREADS; x++) {
switch_core_launch_thread(torture_thread, NULL); switch_core_launch_thread(torture_thread, NULL);
} }
} }
@ -130,4 +131,3 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_inte
/* indicate that the module should continue to be loaded */ /* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -58,7 +58,7 @@ static struct {
struct session session; struct session session;
} globals; } globals;
static void event_handler (switch_event *event) static void event_handler(switch_event *event)
{ {
char buf[1024]; char buf[1024];
iks *msg; iks *msg;
@ -76,7 +76,7 @@ static void event_handler (switch_event *event)
} }
} }
switch(event->event_id) { switch (event->event_id) {
default: default:
switch_event_serialize(event, buf, sizeof(buf), NULL); switch_event_serialize(event, buf, sizeof(buf), NULL);
//switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\nEVENT\n--------------------------------\n%s\n", buf); //switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\nEVENT\n--------------------------------\n%s\n", buf);
@ -91,8 +91,8 @@ static void event_handler (switch_event *event)
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_jid, globals.jid) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_jid, globals.jid)
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_target_jid, globals.target_jid) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_target_jid, globals.target_jid)
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_passwd, globals.passwd) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_passwd, globals.passwd)
static switch_status load_config(void) static switch_status load_config(void)
@ -131,7 +131,8 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_jid, globals.jid)
if (count == 3) { if (count == 3) {
/* TBD use config to pick what events to bind to */ /* TBD use config to pick what events to bind to */
if (switch_event_bind((char *)modname, SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL) != SWITCH_STATUS_SUCCESS) { if (switch_event_bind((char *) modname, SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL) !=
SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't bind!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't bind!\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
@ -143,57 +144,59 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_jid, globals.jid)
} }
int on_result (struct session *sess, ikspak *pak) int on_result(struct session *sess, ikspak * pak)
{ {
return IKS_FILTER_EAT; return IKS_FILTER_EAT;
} }
int on_stream (struct session *sess, int type, iks *node) int on_stream(struct session *sess, int type, iks * node)
{ {
sess->counter = opt_timeout; sess->counter = opt_timeout;
switch (type) { switch (type) {
case IKS_NODE_START: case IKS_NODE_START:
if (opt_use_tls && !iks_is_secure (sess->parser)) { if (opt_use_tls && !iks_is_secure(sess->parser)) {
iks_start_tls (sess->parser); iks_start_tls(sess->parser);
} }
break; break;
case IKS_NODE_NORMAL: case IKS_NODE_NORMAL:
if (strcmp ("stream:features", iks_name (node)) == 0) { if (strcmp("stream:features", iks_name(node)) == 0) {
sess->features = iks_stream_features (node); sess->features = iks_stream_features(node);
if (opt_use_tls && !iks_is_secure (sess->parser)) break; if (opt_use_tls && !iks_is_secure(sess->parser))
break;
if (sess->authorized) { if (sess->authorized) {
iks *t; iks *t;
if (sess->features & IKS_STREAM_BIND) { if (sess->features & IKS_STREAM_BIND) {
t = iks_make_resource_bind (sess->acc); t = iks_make_resource_bind(sess->acc);
iks_send (sess->parser, t); iks_send(sess->parser, t);
iks_delete (t); iks_delete(t);
} }
if (sess->features & IKS_STREAM_SESSION) { if (sess->features & IKS_STREAM_SESSION) {
t = iks_make_session (); t = iks_make_session();
iks_insert_attrib (t, "id", "auth"); iks_insert_attrib(t, "id", "auth");
iks_send (sess->parser, t); iks_send(sess->parser, t);
iks_delete (t); iks_delete(t);
} }
} else { } else {
if (sess->features & IKS_STREAM_SASL_MD5) if (sess->features & IKS_STREAM_SASL_MD5)
iks_start_sasl (sess->parser, IKS_SASL_DIGEST_MD5, sess->acc->user, sess->pass); iks_start_sasl(sess->parser, IKS_SASL_DIGEST_MD5, sess->acc->user, sess->pass);
else if (sess->features & IKS_STREAM_SASL_PLAIN) else if (sess->features & IKS_STREAM_SASL_PLAIN)
iks_start_sasl (sess->parser, IKS_SASL_PLAIN, sess->acc->user, sess->pass); iks_start_sasl(sess->parser, IKS_SASL_PLAIN, sess->acc->user, sess->pass);
} }
} else if (strcmp ("failure", iks_name (node)) == 0) { } else if (strcmp("failure", iks_name(node)) == 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "sasl authentication failed\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "sasl authentication failed\n");
} else if (strcmp ("success", iks_name (node)) == 0) { } else if (strcmp("success", iks_name(node)) == 0) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "server connected\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "server connected\n");
sess->authorized = 1; sess->authorized = 1;
iks_send_header (sess->parser, sess->acc->server); iks_send_header(sess->parser, sess->acc->server);
} else { } else {
ikspak *pak; ikspak *pak;
pak = iks_packet (node); pak = iks_packet(node);
iks_filter_packet (my_filter, pak); iks_filter_packet(my_filter, pak);
if (sess->job_done == 1) return IKS_HOOK; if (sess->job_done == 1)
return IKS_HOOK;
} }
break; break;
#if 0 #if 0
@ -208,13 +211,14 @@ int on_stream (struct session *sess, int type, iks *node)
} }
if (node) iks_delete (node); if (node)
iks_delete(node);
return IKS_OK; return IKS_OK;
} }
int on_msg (void *user_data, ikspak *pak) int on_msg(void *user_data, ikspak * pak)
{ {
char *cmd = iks_find_cdata (pak->x, "body"); char *cmd = iks_find_cdata(pak->x, "body");
char *arg = NULL; char *arg = NULL;
char retbuf[1024] = ""; char retbuf[1024] = "";
char *p; char *p;
@ -234,60 +238,60 @@ int on_msg (void *user_data, ikspak *pak)
return 0; return 0;
} }
int on_error (void *user_data, ikspak *pak) int on_error(void *user_data, ikspak * pak)
{ {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "authorization failed\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "authorization failed\n");
return IKS_FILTER_EAT; return IKS_FILTER_EAT;
} }
void on_log (struct session *sess, const char *data, size_t size, int is_incoming) void on_log(struct session *sess, const char *data, size_t size, int is_incoming)
{ {
if (iks_is_secure (sess->parser)) fprintf (stderr, "Sec"); if (iks_is_secure(sess->parser))
if (is_incoming) fprintf (stderr, "RECV"); else fprintf (stderr, "SEND"); fprintf(stderr, "Sec");
fprintf (stderr, "[%s]\n", data); if (is_incoming)
fprintf(stderr, "RECV");
else
fprintf(stderr, "SEND");
fprintf(stderr, "[%s]\n", data);
} }
void j_setup_filter (struct session *sess) void j_setup_filter(struct session *sess)
{ {
if (my_filter) iks_filter_delete (my_filter); if (my_filter)
my_filter = iks_filter_new (); iks_filter_delete(my_filter);
iks_filter_add_rule (my_filter, on_msg, 0, my_filter = iks_filter_new();
IKS_RULE_TYPE, IKS_PAK_MESSAGE, iks_filter_add_rule(my_filter, on_msg, 0,
IKS_RULE_SUBTYPE, IKS_TYPE_CHAT, IKS_RULE_TYPE, IKS_PAK_MESSAGE,
IKS_RULE_FROM, globals.target_jid, IKS_RULE_SUBTYPE, IKS_TYPE_CHAT, IKS_RULE_FROM, globals.target_jid, IKS_RULE_DONE);
IKS_RULE_DONE); iks_filter_add_rule(my_filter, (iksFilterHook *) on_result, sess,
iks_filter_add_rule (my_filter, (iksFilterHook *) on_result, sess, IKS_RULE_TYPE, IKS_PAK_IQ,
IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "auth", IKS_RULE_DONE);
IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, iks_filter_add_rule(my_filter, on_error, sess,
IKS_RULE_ID, "auth", IKS_RULE_TYPE, IKS_PAK_IQ,
IKS_RULE_DONE); IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_ID, "auth", IKS_RULE_DONE);
iks_filter_add_rule (my_filter, on_error, sess,
IKS_RULE_TYPE, IKS_PAK_IQ,
IKS_RULE_SUBTYPE, IKS_TYPE_ERROR,
IKS_RULE_ID, "auth",
IKS_RULE_DONE);
} }
static void xmpp_connect (char *jabber_id, char *pass) static void xmpp_connect(char *jabber_id, char *pass)
{ {
while (RUNNING == 1) { while (RUNNING == 1) {
int e; int e;
memset (&globals.session, 0, sizeof (globals.session)); memset(&globals.session, 0, sizeof(globals.session));
globals.session.parser = iks_stream_new (IKS_NS_CLIENT, &globals.session, (iksStreamHook *) on_stream); globals.session.parser = iks_stream_new(IKS_NS_CLIENT, &globals.session, (iksStreamHook *) on_stream);
if (globals.debug) iks_set_log_hook (globals.session.parser, (iksLogHook *) on_log); if (globals.debug)
globals.session.acc = iks_id_new (iks_parser_stack (globals.session.parser), jabber_id); iks_set_log_hook(globals.session.parser, (iksLogHook *) on_log);
globals.session.acc = iks_id_new(iks_parser_stack(globals.session.parser), jabber_id);
if (NULL == globals.session.acc->resource) { if (NULL == globals.session.acc->resource) {
/* user gave no resource name, use the default */ /* user gave no resource name, use the default */
char tmp[512]; char tmp[512];
sprintf (tmp, "%s@%s/%s", globals.session.acc->user, globals.session.acc->server, modname); sprintf(tmp, "%s@%s/%s", globals.session.acc->user, globals.session.acc->server, modname);
globals.session.acc = iks_id_new (iks_parser_stack (globals.session.parser), tmp); globals.session.acc = iks_id_new(iks_parser_stack(globals.session.parser), tmp);
} }
globals.session.pass = pass; globals.session.pass = pass;
j_setup_filter (&globals.session); j_setup_filter(&globals.session);
e = iks_connect_tcp (globals.session.parser, globals.session.acc->server, IKS_JABBER_PORT); e = iks_connect_tcp(globals.session.parser, globals.session.acc->server, IKS_JABBER_PORT);
switch (e) { switch (e) {
case IKS_OK: case IKS_OK:
break; break;
@ -303,9 +307,9 @@ static void xmpp_connect (char *jabber_id, char *pass)
globals.session.counter = opt_timeout; globals.session.counter = opt_timeout;
while (RUNNING == 1) { while (RUNNING == 1) {
e = iks_recv (globals.session.parser, 1); e = iks_recv(globals.session.parser, 1);
if(globals.session.job_done) { if (globals.session.job_done) {
break; break;
} }
@ -335,7 +339,7 @@ static void xmpp_connect (char *jabber_id, char *pass)
} }
iks_disconnect(globals.session.parser); iks_disconnect(globals.session.parser);
iks_parser_delete (globals.session.parser); iks_parser_delete(globals.session.parser);
globals.session.authorized = 0; globals.session.authorized = 0;
} }
RUNNING = 0; RUNNING = 0;
@ -343,15 +347,16 @@ static void xmpp_connect (char *jabber_id, char *pass)
} }
static switch_loadable_module_interface xmpp_event_module_interface = { static switch_loadable_module_interface xmpp_event_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ NULL, /*.endpoint_interface */ NULL,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL /*.application_interface */ NULL
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &xmpp_event_module_interface; *interface = &xmpp_event_module_interface;

View File

@ -36,7 +36,7 @@ static const char modname[] = "mod_sndfile";
struct sndfile_context { struct sndfile_context {
SF_INFO sfinfo; SF_INFO sfinfo;
SNDFILE* handle; SNDFILE *handle;
}; };
typedef struct sndfile_context sndfile_context; typedef struct sndfile_context sndfile_context;
@ -48,10 +48,10 @@ switch_status sndfile_file_open(switch_file_handle *handle, char *path)
char *ext; char *ext;
if (!(ext = strrchr(path, '.'))) { if (!(ext = strrchr(path, '.'))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid Format\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid Format\n");
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
ext++; ext++;
if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) { if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
@ -97,18 +97,19 @@ switch_status sndfile_file_open(switch_file_handle *handle, char *path)
} }
if (!strcmp(ext, "gsm")) { if (!strcmp(ext, "gsm")) {
context->sfinfo.format = SF_FORMAT_RAW |SF_FORMAT_GSM610; context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_GSM610;
context->sfinfo.channels = 1; context->sfinfo.channels = 1;
context->sfinfo.samplerate = 8000; context->sfinfo.samplerate = 8000;
} }
if (!(context->handle = sf_open(path, mode, &context->sfinfo))) { if (!(context->handle = sf_open(path, mode, &context->sfinfo))) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error Opening File [%s] [%s]\n", path, sf_strerror(context->handle)); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error Opening File [%s] [%s]\n", path,
sf_strerror(context->handle));
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Opening File [%s] %dhz\n", path, context->sfinfo.samplerate); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Opening File [%s] %dhz\n", path, context->sfinfo.samplerate);
handle->samples = (unsigned int)context->sfinfo.frames; handle->samples = (unsigned int) context->sfinfo.frames;
handle->samplerate = context->sfinfo.samplerate; handle->samplerate = context->sfinfo.samplerate;
handle->channels = context->sfinfo.channels; handle->channels = context->sfinfo.channels;
handle->format = context->sfinfo.format; handle->format = context->sfinfo.format;
@ -137,51 +138,51 @@ switch_status sndfile_file_seek(switch_file_handle *handle, unsigned int *cur_sa
return SWITCH_STATUS_NOTIMPL; return SWITCH_STATUS_NOTIMPL;
} }
*cur_sample = (unsigned int)sf_seek(context->handle, samples, whence); *cur_sample = (unsigned int) sf_seek(context->handle, samples, whence);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
switch_status sndfile_file_read (switch_file_handle *handle, void *data, size_t *len) switch_status sndfile_file_read(switch_file_handle *handle, void *data, size_t *len)
{ {
size_t inlen = *len; size_t inlen = *len;
sndfile_context *context = handle->private; sndfile_context *context = handle->private;
if (switch_test_flag(handle, SWITCH_FILE_DATA_RAW)) { if (switch_test_flag(handle, SWITCH_FILE_DATA_RAW)) {
*len = (size_t)sf_read_raw (context->handle, data, inlen); *len = (size_t) sf_read_raw(context->handle, data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_INT)) { } else if (switch_test_flag(handle, SWITCH_FILE_DATA_INT)) {
*len = (size_t)sf_readf_int(context->handle, (int *) data, inlen); *len = (size_t) sf_readf_int(context->handle, (int *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_SHORT)) { } else if (switch_test_flag(handle, SWITCH_FILE_DATA_SHORT)) {
*len = (size_t)sf_readf_short(context->handle, (short *) data, inlen); *len = (size_t) sf_readf_short(context->handle, (short *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_FLOAT)) { } else if (switch_test_flag(handle, SWITCH_FILE_DATA_FLOAT)) {
*len = (size_t)sf_readf_float(context->handle, (float *) data, inlen); *len = (size_t) sf_readf_float(context->handle, (float *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_DOUBLE)) { } else if (switch_test_flag(handle, SWITCH_FILE_DATA_DOUBLE)) {
*len = (size_t)sf_readf_double(context->handle, (double *) data, inlen); *len = (size_t) sf_readf_double(context->handle, (double *) data, inlen);
} else { } else {
*len = (size_t)sf_readf_int(context->handle, (int *) data, inlen); *len = (size_t) sf_readf_int(context->handle, (int *) data, inlen);
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
switch_status sndfile_file_write (switch_file_handle *handle, void *data, size_t *len) switch_status sndfile_file_write(switch_file_handle *handle, void *data, size_t *len)
{ {
size_t inlen = *len; size_t inlen = *len;
sndfile_context *context = handle->private; sndfile_context *context = handle->private;
if (switch_test_flag(handle, SWITCH_FILE_DATA_RAW)) { if (switch_test_flag(handle, SWITCH_FILE_DATA_RAW)) {
*len = (size_t)sf_write_raw (context->handle, data, inlen); *len = (size_t) sf_write_raw(context->handle, data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_INT)) { } else if (switch_test_flag(handle, SWITCH_FILE_DATA_INT)) {
*len = (size_t)sf_writef_int(context->handle, (int *) data, inlen); *len = (size_t) sf_writef_int(context->handle, (int *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_SHORT)) { } else if (switch_test_flag(handle, SWITCH_FILE_DATA_SHORT)) {
*len = (size_t)sf_writef_short(context->handle, (short *) data, inlen); *len = (size_t) sf_writef_short(context->handle, (short *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_FLOAT)) { } else if (switch_test_flag(handle, SWITCH_FILE_DATA_FLOAT)) {
*len = (size_t)sf_writef_float(context->handle, (float *) data, inlen); *len = (size_t) sf_writef_float(context->handle, (float *) data, inlen);
} else if (switch_test_flag(handle, SWITCH_FILE_DATA_DOUBLE)) { } else if (switch_test_flag(handle, SWITCH_FILE_DATA_DOUBLE)) {
*len = (size_t)sf_writef_double(context->handle, (double *) data, inlen); *len = (size_t) sf_writef_double(context->handle, (double *) data, inlen);
} else { } else {
*len = (size_t)sf_writef_int(context->handle, (int *) data, inlen); *len = (size_t) sf_writef_int(context->handle, (int *) data, inlen);
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -192,60 +193,61 @@ switch_status sndfile_file_write (switch_file_handle *handle, void *data, size_t
static char **supported_formats; static char **supported_formats;
static switch_file_interface sndfile_file_interface = { static switch_file_interface sndfile_file_interface = {
/*.interface_name*/ modname, /*.interface_name */ modname,
/*.file_open*/ sndfile_file_open, /*.file_open */ sndfile_file_open,
/*.file_close*/ sndfile_file_close, /*.file_close */ sndfile_file_close,
/*.file_read*/ sndfile_file_read, /*.file_read */ sndfile_file_read,
/*.file_write*/ sndfile_file_write, /*.file_write */ sndfile_file_write,
/*.file_seek*/ sndfile_file_seek, /*.file_seek */ sndfile_file_seek,
/*.extens*/ NULL, /*.extens */ NULL,
/*.next*/ NULL, /*.next */ NULL,
}; };
static switch_loadable_module_interface sndfile_module_interface = { static switch_loadable_module_interface sndfile_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ NULL, /*.endpoint_interface */ NULL,
/*.timer_interface*/ NULL, /*.timer_interface */ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface */ NULL,
/*.codec_interface*/ NULL, /*.codec_interface */ NULL,
/*.application_interface*/ NULL, /*.application_interface */ NULL,
/*.api_interface*/ NULL, /*.api_interface */ NULL,
/*.file_interface*/ &sndfile_file_interface /*.file_interface */ &sndfile_file_interface
}; };
static switch_status setup_formats(void) static switch_status setup_formats(void)
{ {
SF_FORMAT_INFO info ; SF_FORMAT_INFO info;
SF_INFO sfinfo ; SF_INFO sfinfo;
char buffer [128] ; char buffer[128];
int format, major_count, subtype_count, m, s ; int format, major_count, subtype_count, m, s;
int len,x,skip; int len, x, skip;
char *extras[] = {"r8", "r16", "r24", "r32", "gsm", NULL}; char *extras[] = { "r8", "r16", "r24", "r32", "gsm", NULL };
int exlen = (sizeof(extras) / sizeof(extras[0])); int exlen = (sizeof(extras) / sizeof(extras[0]));
buffer [0] = 0 ; buffer[0] = 0;
sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ; sf_command(NULL, SFC_GET_LIB_VERSION, buffer, sizeof(buffer));
if (strlen (buffer) < 1) { if (strlen(buffer) < 1) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Line %d: could not retrieve lib version.\n", __LINE__) ; switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "Line %d: could not retrieve lib version.\n", __LINE__);
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\nLibSndFile Version : %s Supported Formats\n", buffer) ; switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\nLibSndFile Version : %s Supported Formats\n", buffer);
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "================================================================================\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN,
sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof (int)) ; "================================================================================\n");
sf_command (NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &subtype_count, sizeof (int)) ; sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof(int));
sf_command(NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &subtype_count, sizeof(int));
sfinfo.channels = 1 ; sfinfo.channels = 1;
len = ((major_count + (exlen + 2)) * sizeof(char *)); len = ((major_count + (exlen + 2)) * sizeof(char *));
supported_formats = switch_core_permenant_alloc(len); supported_formats = switch_core_permenant_alloc(len);
len = 0; len = 0;
for (m = 0 ; m < major_count ; m++) { for (m = 0; m < major_count; m++) {
skip = 0; skip = 0;
info.format = m ; info.format = m;
sf_command (NULL, SFC_GET_FORMAT_MAJOR, &info, sizeof (info)) ; sf_command(NULL, SFC_GET_FORMAT_MAJOR, &info, sizeof(info));
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "%s (extension \"%s\")\n", info.name, info.extension) ; switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "%s (extension \"%s\")\n", info.name, info.extension);
for (x = 0 ; x < len ; x++) { for (x = 0; x < len; x++) {
if (supported_formats[x] == info.extension) { if (supported_formats[x] == info.extension) {
skip++; skip++;
break; break;
@ -256,28 +258,30 @@ static switch_status setup_formats(void)
} }
format = info.format; format = info.format;
for (s = 0 ; s < subtype_count ; s++) { for (s = 0; s < subtype_count; s++) {
info.format = s ; info.format = s;
sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &info, sizeof (info)) ; sf_command(NULL, SFC_GET_FORMAT_SUBTYPE, &info, sizeof(info));
format = (format & SF_FORMAT_TYPEMASK) | info.format ; format = (format & SF_FORMAT_TYPEMASK) | info.format;
sfinfo.format = format ; sfinfo.format = format;
if (sf_format_check (&sfinfo)) { if (sf_format_check(&sfinfo)) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, " %s\n", info.name) ; switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, " %s\n", info.name);
} }
} }
} }
for(m=0; m< exlen; m++) { for (m = 0; m < exlen; m++) {
supported_formats[len++] = extras[m]; supported_formats[len++] = extras[m];
} }
switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "================================================================================\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN,
"================================================================================\n");
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_interface **interface, char *filename)
{
if (setup_formats() != SWITCH_STATUS_SUCCESS) { if (setup_formats() != SWITCH_STATUS_SUCCESS) {
@ -291,4 +295,3 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_inte
/* indicate that the module should continue to be loaded */ /* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -71,9 +71,9 @@ static switch_status soft_timer_next(switch_timer *timer)
#ifdef WINTIMER #ifdef WINTIMER
private->base.QuadPart += timer->interval * (private->freq.QuadPart / 1000); private->base.QuadPart += timer->interval * (private->freq.QuadPart / 1000);
for(;;) { for (;;) {
QueryPerformanceCounter(&private->now); QueryPerformanceCounter(&private->now);
if(private->now.QuadPart >= private->base.QuadPart) { if (private->now.QuadPart >= private->base.QuadPart) {
break; break;
} }
switch_yield(100); switch_yield(100);
@ -98,22 +98,23 @@ static switch_status soft_timer_destroy(switch_timer *timer)
} }
static const switch_timer_interface soft_timer_interface = { static const switch_timer_interface soft_timer_interface = {
/*.interface_name*/ "soft", /*.interface_name */ "soft",
/*.timer_init*/ soft_timer_init, /*.timer_init */ soft_timer_init,
/*.timer_next*/ soft_timer_next, /*.timer_next */ soft_timer_next,
/*.timer_destroy*/ soft_timer_destroy /*.timer_destroy */ soft_timer_destroy
}; };
static const switch_loadable_module_interface mod_timers_module_interface = { static const switch_loadable_module_interface mod_timers_module_interface = {
/*.module_name*/ modname, /*.module_name */ modname,
/*.endpoint_interface*/ NULL, /*.endpoint_interface */ NULL,
/*.timer_interface*/ &soft_timer_interface, /*.timer_interface */ &soft_timer_interface,
/*.switch_dialplan_interface*/ NULL, /*.switch_dialplan_interface */ NULL,
/*.switch_codec_interface*/ NULL, /*.switch_codec_interface */ NULL,
/*.switch_application_interface*/ NULL /*.switch_application_interface */ NULL
}; };
SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &mod_timers_module_interface; *interface = &mod_timers_module_interface;
@ -121,8 +122,3 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul
/* indicate that the module should continue to be loaded */ /* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }