Merge branch 'master' into v1.4.beta

This commit is contained in:
Ken Rice
2013-07-19 15:43:49 -05:00
52 changed files with 1031 additions and 639 deletions
+3 -1
View File
@@ -11,8 +11,10 @@
<param name="record-file-prefix" value="$${recordings_dir}/"/>
</record>
<!-- domain to use in from attribute of client messages -->
<!-- XMPP server domain -->
<domain name="$${rayo_domain_name}" shared-secret="ClueCon">
<!-- use this instead if you want secure XMPP client to server connections. Put .crt and .key file in freeswitch/certs -->
<!--domain name="$${rayo_domain_name}" shared-secret="ClueCon" cert="$${base_dir}/certs/$${rayo_domain_name}.crt" key="$${base_dir}/certs/$${rayo_domain_name}.key"-->
<!-- Listeners for new Rayo client connections -->
<!--listen type="c2s" port="5222" address="$${local_ip_v4}" acl="rayo-clients"/-->
+5 -2
View File
@@ -334,12 +334,15 @@
<macro name="voicemail_say_phone_number">
<input pattern="^000|^$|^[Aa]non|^[Pp]rivate" break_on_match="true">
<match>
<!-- add 'anonymous caller' sound here -->
<action function="play-file" data="voicemail/vm-message_from.wav"/>
<action function="execute" data="sleep(100)"/>
<action function="play-file" data="ivr/ivr-anonymous_caller.wav"/>
<action function="execute" data="sleep(500)"/>
</match>
</input>
<input pattern="^(.*)$">
<match>
<action function="play-file" data="ivr/ivr-this_is_a_call_from.wav"/>
<action function="play-file" data="voicemail/vm-message_from.wav"/>
<action function="execute" data="sleep(100)"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(500)"/>
+24
View File
@@ -154,6 +154,12 @@ App.ShowSaysRoute = Ember.Route.extend({
}
});
App.ShowNatMapsRoute = Ember.Route.extend({
setupController: function(controller) {
App.showNatMapsController.load();
}
});
App.ShowChatsRoute = Ember.Route.extend({
setupController: function(controller) {
App.showChatsController.load();
@@ -203,6 +209,7 @@ App.Router.map(function(){
this.route("showAliases");
this.route("showCompletes");
this.route("showManagements");
this.route("showNatMaps");
this.route("showSays");
this.route("showChats");
this.route("showInterfaces");
@@ -550,6 +557,23 @@ App.showManagementsController = Ember.ArrayController.create({
}
});
App.showNatMapsController = Ember.ArrayController.create({
content: [],
init: function(){
},
load: function() {
var me = this;
$.getJSON("/txtapi/show?nat_map%20as%20json", function(data){
me.set('total', data.row_count);
me.content.clear();
if (data.row_count == 0) return;
me.pushObjects(data.rows);
});
}
});
App.showSaysController = Ember.ArrayController.create({
content: [],
init: function(){
+23 -1
View File
@@ -357,6 +357,28 @@
</div>
</script>
<script type="text/x-handlebars" data-template-name="showNatMaps">
<h1>Nat Maps</h1>
<div>
<table class="table">
<tr>
<th>Port</th>
<th>Protocol</th>
<th>Protocol Number</th>
<th>Sticky</th>
</tr>
{{#each App.showNatMapsController.content}}
<tr>
<td>{{ port }}</td>
<td>{{ proto }}</td>
<td>{{ proto_num }}</td>
<td>{{ sticky }}</td>
</tr>
{{/each}}
</table>
</div>
</script>
<script type="text/x-handlebars" data-template-name="showSays">
<h1>Say</h1>
<div>
@@ -492,7 +514,7 @@
{{#linkTo "showCompletes"}} Complete {{/linkTo}} |
{{#linkTo "showChats"}} Chat {{/linkTo}} |
{{#linkTo "showManagements"}} Management {{/linkTo}} |
Nat_map |
{{#linkTo "showNatMaps"}} Nat Map {{/linkTo}} |
{{#linkTo "showSays"}} Say {{/linkTo}} |
{{#linkTo "showInterfaces"}} Interfaces {{/linkTo}} |
{{#linkTo "showInterfaceTypes"}} InterfaceTypes {{/linkTo}} |
+1 -1
View File
@@ -1201,7 +1201,7 @@ static void read_config(const char *dft_cfile, const char *cfile) {
if (strcmp(cur_cat, cfg.category)) {
esl_set_string(cur_cat, cfg.category);
esl_set_string(profiles[pcount].name, cur_cat);
esl_set_string(profiles[pcount].host, "localhost");
esl_set_string(profiles[pcount].host, "127.0.0.1");
esl_set_string(profiles[pcount].pass, "ClueCon");
profiles[pcount].port = 8021;
set_fn_keys(&profiles[pcount]);
-7
View File
@@ -21,15 +21,8 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Based on a single channel G.722 codec which is:
*
***** Copyright (c) CMU 1993 *****
* Computer Science, Speech Group
* Chengxiang Lu and Alex Hauptmann
*/
/*! \file */
#if !defined(_SPANDSP_PRIVATE_G722_H_)
+5
View File
@@ -26,6 +26,8 @@
#if !defined(_SPANDSP_PRIVATE_T4_RX_H_)
#define _SPANDSP_PRIVATE_T4_RX_H_
typedef int (*t4_image_put_handler_t)(void *user_data, const uint8_t buf[], size_t len);
/*!
TIFF specific state information to go with T.4 compression or decompression handling.
*/
@@ -125,6 +127,9 @@ struct t4_rx_state_s
t45_decode_state_t t45;
#endif
} decoder;
t4_image_put_handler_t image_put_handler;
int current_decoder;
uint8_t *pre_encoded_buf;
+21 -18
View File
@@ -26,6 +26,8 @@
#if !defined(_SPANDSP_PRIVATE_T4_TX_H_)
#define _SPANDSP_PRIVATE_T4_TX_H_
typedef int (*t4_image_get_handler_t)(void *user_data, uint8_t buf[], size_t len);
/*!
TIFF specific state information to go with T.4 compression or decompression handling.
*/
@@ -45,6 +47,17 @@ typedef struct
/*! \brief The TIFF fill order setting for the current page. */
uint16_t fill_order;
/*! \brief Width of the image in the file. */
uint32_t image_width;
/*! \brief Length of the image in the file. */
uint32_t image_length;
/*! \brief Column-to-column (X) resolution in pixels per metre of the image in the file. */
int x_resolution;
/*! \brief Row-to-row (Y) resolution in pixels per metre of the image in the file. */
int y_resolution;
/*! \brief Code for the combined X and Y resolution of the image in the file. */
int resolution_code;
/*! \brief The number of pages in the current image file. */
int pages_in_file;
@@ -56,18 +69,6 @@ typedef struct
int image_buffer_size;
/*! \brief Row counter for playing out the rows of the image. */
int row;
/*! \brief Width of the image in the file. */
uint32_t image_width;
/*! \brief Length of the image in the file. */
uint32_t image_length;
/*! \brief Column-to-column (X) resolution in pixels per metre of the image in the file. */
int image_x_resolution;
/*! \brief Row-to-row (Y) resolution in pixels per metre of the image in the file. */
int image_y_resolution;
/*! \brief Code for the combined X and Y resolution of the image in the file. */
int resolution_code;
/*! \brief Row counter used when the image is resized or dithered flat. */
int raw_row;
} t4_tx_tiff_state_t;
@@ -162,23 +163,25 @@ struct t4_tx_state_s
#endif
} encoder;
image_translate_state_t translator;
uint8_t *pack_buf;
int pack_ptr;
int pack_row;
int pack_bit_mask;
t4_image_get_handler_t image_get_handler;
int apply_lab;
lab_params_t lab_params;
uint8_t *colour_map;
int colour_map_entries;
image_translate_state_t translator;
uint8_t *pack_buf;
int pack_ptr;
int pack_row;
int pack_bit_mask;
uint8_t *pre_encoded_buf;
int pre_encoded_len;
int pre_encoded_ptr;
int pre_encoded_bit;
/* Supporting information, like resolutions, which the backend may want. */
/*! \brief Supporting information, like resolutions, which the backend may want. */
t4_tx_metadata_t metadata;
/*! \brief All TIFF file specific state information for the T.4 context. */
+5 -5
View File
@@ -43,15 +43,15 @@ struct v18_state_s
} queue;
tone_gen_descriptor_t alert_tone_desc;
tone_gen_state_t alert_tone_gen;
fsk_tx_state_t fsktx;
dtmf_tx_state_t dtmftx;
async_tx_state_t asynctx;
fsk_tx_state_t fsk_tx;
dtmf_tx_state_t dtmf_tx;
async_tx_state_t async_tx;
int baudot_tx_shift;
int tx_signal_on;
uint8_t next_byte;
fsk_rx_state_t fskrx;
dtmf_rx_state_t dtmfrx;
fsk_rx_state_t fsk_rx;
dtmf_rx_state_t dtmf_rx;
int baudot_rx_shift;
int consecutive_ones;
uint8_t rx_msg[256 + 1];
+17 -22
View File
@@ -434,7 +434,7 @@ static void disconnect(t30_state_t *s);
static void decode_20digit_msg(t30_state_t *s, char *msg, const uint8_t *pkt, int len);
static void decode_url_msg(t30_state_t *s, char *msg, const uint8_t *pkt, int len);
static int decode_nsf_nss_nsc(t30_state_t *s, uint8_t *msg[], const uint8_t *pkt, int len);
static int set_min_scan_time_code(t30_state_t *s);
static void set_min_scan_time(t30_state_t *s);
static int send_cfr_sequence(t30_state_t *s, int start);
static void timer_t2_start(t30_state_t *s);
static void timer_t2a_start(t30_state_t *s);
@@ -1682,7 +1682,7 @@ static int build_dcs(t30_state_t *s)
||
((s->image_width == T4_WIDTH_1200_A4) && (s->x_resolution == T4_X_RESOLUTION_1200)))
{
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4 at %ddpi x %ddpi\n", s->x_resolution, s->y_resolution);
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
/* No width related bits need to be set. */
}
else if (((s->image_width == T4_WIDTH_200_B4) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8))
@@ -1697,7 +1697,7 @@ static int build_dcs(t30_state_t *s)
{
if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_255MM))
{
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4 at %ddpi x %ddpi\n", s->x_resolution, s->y_resolution);
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_255MM_WIDTH);
}
else
@@ -1718,7 +1718,7 @@ static int build_dcs(t30_state_t *s)
{
if ((s->mutual_image_sizes & T4_SUPPORT_WIDTH_303MM))
{
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3 at %ddpi x %ddpi\n", s->x_resolution, s->y_resolution);
span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3 at %ddpm x %ddpm\n", s->x_resolution, s->y_resolution);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_303MM_WIDTH);
}
else
@@ -2392,8 +2392,6 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
static int step_fallback_entry(t30_state_t *s)
{
int min_row_bits;
while (fallback_sequence[++s->current_fallback].which)
{
if ((fallback_sequence[s->current_fallback].which & s->current_permitted_modems))
@@ -2404,8 +2402,7 @@ static int step_fallback_entry(t30_state_t *s)
/* TODO: This only sets the minimum row time for future pages. It doesn't fix up the
current page, though it is benign - fallback will only result in an excessive
minimum. */
min_row_bits = set_min_scan_time_code(s);
t4_tx_set_min_bits_per_row(&s->t4.tx, min_row_bits);
set_min_scan_time(s);
/* We need to rebuild the DCS message we will send. */
build_dcs(s);
return s->current_fallback;
@@ -2629,7 +2626,7 @@ static void disconnect(t30_state_t *s)
}
/*- End of function --------------------------------------------------------*/
static int set_min_scan_time_code(t30_state_t *s)
static void set_min_scan_time(t30_state_t *s)
{
/* Translation between the codes for the minimum scan times the other end needs,
and the codes for what we say will be used. We need 0 minimum. */
@@ -2645,6 +2642,7 @@ static int set_min_scan_time_code(t30_state_t *s)
20, 5, 10, 0, 40, 0, 0, 0
};
int min_bits_field;
int min_row_bits;
/* Set the minimum scan time bits */
if (s->error_correcting_mode)
@@ -2654,6 +2652,7 @@ static int set_min_scan_time_code(t30_state_t *s)
switch (s->y_resolution)
{
case T4_Y_RESOLUTION_SUPERFINE:
case T4_Y_RESOLUTION_400:
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
{
s->min_scan_time_code = translate_min_scan_time[(test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_MIN_SCAN_TIME_HALVES)) ? 2 : 1][min_bits_field];
@@ -2662,6 +2661,7 @@ static int set_min_scan_time_code(t30_state_t *s)
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support super-fine resolution. Squashing image.\n");
/* Fall through */
case T4_Y_RESOLUTION_FINE:
case T4_Y_RESOLUTION_200:
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
{
s->min_scan_time_code = translate_min_scan_time[1][min_bits_field];
@@ -2671,19 +2671,21 @@ static int set_min_scan_time_code(t30_state_t *s)
/* Fall through */
default:
case T4_Y_RESOLUTION_STANDARD:
case T4_Y_RESOLUTION_100:
s->min_scan_time_code = translate_min_scan_time[0][min_bits_field];
break;
}
if (!s->error_correcting_mode && (s->iaf & T30_IAF_MODE_NO_FILL_BITS))
return 0;
return fallback_sequence[s->current_fallback].bit_rate*min_scan_times[s->min_scan_time_code]/1000;
min_row_bits = 0;
else
min_row_bits = fallback_sequence[s->current_fallback].bit_rate*min_scan_times[s->min_scan_time_code]/1000;
span_log(&s->logging, SPAN_LOG_FLOW, "Minimum bits per row will be %d\n", min_row_bits);
t4_tx_set_min_bits_per_row(&s->t4.tx, min_row_bits);
}
/*- End of function --------------------------------------------------------*/
static int start_sending_document(t30_state_t *s)
{
int min_row_bits;
if (s->tx_file[0] == '\0')
{
/* There is nothing to send */
@@ -2715,15 +2717,8 @@ static int start_sending_document(t30_state_t *s)
s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
s->image_width = t4_tx_get_image_width(&s->t4.tx);
/* The minimum scan time to be used can't be evaluated until we know the Y resolution, and
must be evaluated before the minimum scan row bits can be evaluated. */
if ((min_row_bits = set_min_scan_time_code(s)) < 0)
{
terminate_operation_in_progress(s);
return -1;
}
span_log(&s->logging, SPAN_LOG_FLOW, "Minimum bits per row will be %d\n", min_row_bits);
t4_tx_set_min_bits_per_row(&s->t4.tx, min_row_bits);
/* The minimum scan time to be used can't be evaluated until we know the Y resolution. */
set_min_scan_time(s);
if (s->error_correcting_mode)
{
+6 -6
View File
@@ -369,18 +369,18 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
t->fill_order = FILLORDER_LSB2MSB;
if (res_unit == RESUNIT_INCH)
t->image_x_resolution = x_resolution*100.0f/CM_PER_INCH;
t->x_resolution = x_resolution*100.0f/CM_PER_INCH;
else
t->image_x_resolution = x_resolution*100.0f;
t->x_resolution = x_resolution*100.0f;
/* Treat everything we can't match as R8. Most FAXes are this resolution anyway. */
if ((best_x_entry = match_resolution(res_unit, x_resolution, x_res_table)) < 0)
best_x_entry = 3;
s->metadata.x_resolution = x_res_table[best_x_entry].code;
if (res_unit == RESUNIT_INCH)
t->image_y_resolution = y_resolution*100.0f/CM_PER_INCH;
t->y_resolution = y_resolution*100.0f/CM_PER_INCH;
else
t->image_y_resolution = y_resolution*100.0f;
t->y_resolution = y_resolution*100.0f;
if ((best_y_entry = match_resolution(res_unit, y_resolution, y_res_table)) < 0)
best_y_entry = 0;
s->metadata.y_resolution = y_res_table[best_y_entry].code;
@@ -1354,8 +1354,8 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t
t->image_type = s->tiff.image_type;
t->image_width = s->tiff.image_width;
t->image_length = s->tiff.image_length;
t->image_x_resolution = s->tiff.image_x_resolution;
t->image_y_resolution = s->tiff.image_y_resolution;
t->image_x_resolution = s->tiff.x_resolution;
t->image_y_resolution = s->tiff.y_resolution;
t->x_resolution = s->metadata.x_resolution;
t->y_resolution = s->metadata.y_resolution/s->row_squashing_ratio;
+30 -30
View File
@@ -665,7 +665,7 @@ static void v18_dtmf_get(void *user_data)
if ((ch = queue_read_byte(&s->queue.queue)) >= 0)
{
v = ascii_to_dtmf[ch & 0x7F];
dtmf_tx_put(&s->dtmftx, v, strlen(v));
dtmf_tx_put(&s->dtmf_tx, v, strlen(v));
s->rx_suppression = ((300 + 100*strlen(v))*SAMPLE_RATE)/1000;
}
}
@@ -809,12 +809,12 @@ SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len)
{
case V18_MODE_DTMF:
if (len < max_len)
len += dtmf_tx(&s->dtmftx, amp, max_len - len);
len += dtmf_tx(&s->dtmf_tx, amp, max_len - len);
break;
default:
if (len < max_len)
{
if ((lenx = fsk_tx(&s->fsktx, amp + len, max_len - len)) <= 0)
if ((lenx = fsk_tx(&s->fsk_tx, amp + len, max_len - len)) <= 0)
s->tx_signal_on = FALSE;
len += lenx;
}
@@ -841,10 +841,10 @@ SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len)
s->in_progress -= len;
if (s->in_progress <= 0)
s->rx_msg_len = 0;
dtmf_rx(&s->dtmfrx, amp, len);
dtmf_rx(&s->dtmf_rx, amp, len);
break;
default:
fsk_rx(&s->fskrx, amp, len);
fsk_rx(&s->fsk_rx, amp, len);
break;
}
return 0;
@@ -867,10 +867,10 @@ SPAN_DECLARE_NONSTD(int) v18_rx_fillin(v18_state_t *s, int len)
//s->in_progress -= len;
//if (s->in_progress <= 0)
// s->rx_msg_len = 0;
dtmf_rx_fillin(&s->dtmfrx, len);
dtmf_rx_fillin(&s->dtmf_rx, len);
break;
default:
fsk_rx_fillin(&s->fskrx, len);
fsk_rx_fillin(&s->fsk_rx, len);
break;
}
return 0;
@@ -973,56 +973,56 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
{
case V18_MODE_5BIT_45:
s->repeat_shifts = mode & 0x100;
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */
s->baudot_tx_shift = 2;
/* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
ride over the fraction. */
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
fsk_rx_init(&s->fsk_rx, &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
s->baudot_rx_shift = 0;
s->next_byte = (uint8_t) 0xFF;
break;
case V18_MODE_5BIT_50:
s->repeat_shifts = mode & 0x100;
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT50], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_WEITBRECHT50], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */
s->baudot_tx_shift = 2;
/* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
ride over the fraction. */
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT50], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
fsk_rx_init(&s->fsk_rx, &preset_fsk_specs[FSK_WEITBRECHT50], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
s->baudot_rx_shift = 0;
s->next_byte = (uint8_t) 0xFF;
break;
case V18_MODE_DTMF:
dtmf_tx_init(&s->dtmftx, v18_dtmf_get, s);
dtmf_rx_init(&s->dtmfrx, v18_dtmf_put, s);
dtmf_tx_init(&s->dtmf_tx, v18_dtmf_get, s);
dtmf_rx_init(&s->dtmf_rx, v18_dtmf_put, s);
break;
case V18_MODE_EDT:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V21CH1_110], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 2, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V21CH1_110], FSK_FRAME_MODE_7E2_FRAMES, v18_edt_put_async_byte, s);
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_V21CH1_110], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 7, ASYNC_PARITY_EVEN, 2, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fsk_rx, &preset_fsk_specs[FSK_V21CH1_110], FSK_FRAME_MODE_7E2_FRAMES, v18_edt_put_async_byte, s);
break;
case V18_MODE_BELL103:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_BELL103CH1], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_BELL103CH2], FSK_FRAME_MODE_7E1_FRAMES, v18_bell103_put_async_byte, s);
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_BELL103CH1], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fsk_rx, &preset_fsk_specs[FSK_BELL103CH2], FSK_FRAME_MODE_7E1_FRAMES, v18_bell103_put_async_byte, s);
break;
case V18_MODE_V23VIDEOTEX:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V23CH1], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V23CH2], FSK_FRAME_MODE_7E1_FRAMES, v18_videotex_put_async_byte, s);
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_V23CH1], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fsk_rx, &preset_fsk_specs[FSK_V23CH2], FSK_FRAME_MODE_7E1_FRAMES, v18_videotex_put_async_byte, s);
break;
case V18_MODE_V21TEXTPHONE:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V21CH1], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V21CH1], FSK_FRAME_MODE_7E1_FRAMES, v18_textphone_put_async_byte, s);
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_V21CH1], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fsk_rx, &preset_fsk_specs[FSK_V21CH1], FSK_FRAME_MODE_7E1_FRAMES, v18_textphone_put_async_byte, s);
break;
case V18_MODE_V18TEXTPHONE:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V21CH1], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V21CH1], FSK_FRAME_MODE_7E1_FRAMES, v18_textphone_put_async_byte, s);
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_V21CH1], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fsk_rx, &preset_fsk_specs[FSK_V21CH1], FSK_FRAME_MODE_7E1_FRAMES, v18_textphone_put_async_byte, s);
break;
}
s->nation = nation;
+2 -2
View File
@@ -45,7 +45,7 @@
uint8_t buffer[256];
#define PATTERN 0x11111111
#define PATTERN 0x1111111
#define SEQUENCE_LENGTH 17
uint8_t left[] =
@@ -111,7 +111,7 @@ int main(int argc, char *argv[])
total_bits = 0;
for (i = 0; i < SEQUENCE_LENGTH; i++)
{
bitstream_put(s, &w, PATTERN*i, i + 1);
bitstream_put(s, &w, i*PATTERN, i + 1);
total_bits += (i + 1);
}
bitstream_flush(s, &w);
+63 -36
View File
@@ -490,6 +490,7 @@ int main(int argc, char *argv[])
int noise_level;
int code_to_look_up;
int scan_line_time;
int allowed_bilevel_resolutions;
int colour_enabled;
t38_stats_t t38_stats;
t30_stats_t t30_stats;
@@ -529,12 +530,16 @@ int main(int argc, char *argv[])
scan_line_time = 0;
decode_file_name = NULL;
code_to_look_up = -1;
allowed_bilevel_resolutions = 0;
colour_enabled = FALSE;
t38_transport = T38_TRANSPORT_UDPTL;
while ((opt = getopt(argc, argv, "c:Cd:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1)
while ((opt = getopt(argc, argv, "b:c:Cd:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1)
{
switch (opt)
{
case 'b':
allowed_bilevel_resolutions = atoi(optarg);
break;
case 'c':
code_to_look_up = atoi(optarg);
break;
@@ -850,41 +855,63 @@ int main(int argc, char *argv[])
| T4_SUPPORT_LENGTH_US_LETTER
| T4_SUPPORT_LENGTH_US_LEGAL
| T4_SUPPORT_LENGTH_UNLIMITED);
#if 1
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_R8_STANDARD
| T4_SUPPORT_RESOLUTION_R8_FINE
| T4_SUPPORT_RESOLUTION_R8_SUPERFINE
| T4_SUPPORT_RESOLUTION_R16_SUPERFINE
| T4_SUPPORT_RESOLUTION_200_100
| T4_SUPPORT_RESOLUTION_200_200
| T4_SUPPORT_RESOLUTION_200_400
| T4_SUPPORT_RESOLUTION_300_300
| T4_SUPPORT_RESOLUTION_300_600
| T4_SUPPORT_RESOLUTION_400_400
| T4_SUPPORT_RESOLUTION_400_800
| T4_SUPPORT_RESOLUTION_600_600
| T4_SUPPORT_RESOLUTION_600_1200
| T4_SUPPORT_RESOLUTION_1200_1200);
#elif 0
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_R8_STANDARD
| T4_SUPPORT_RESOLUTION_R8_FINE
| T4_SUPPORT_RESOLUTION_R8_SUPERFINE
| T4_SUPPORT_RESOLUTION_R16_SUPERFINE);
#else
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_200_100
| T4_SUPPORT_RESOLUTION_200_200
| T4_SUPPORT_RESOLUTION_200_400
| T4_SUPPORT_RESOLUTION_300_300
| T4_SUPPORT_RESOLUTION_300_600
| T4_SUPPORT_RESOLUTION_400_400
| T4_SUPPORT_RESOLUTION_400_800
| T4_SUPPORT_RESOLUTION_600_600
| T4_SUPPORT_RESOLUTION_600_1200
| T4_SUPPORT_RESOLUTION_1200_1200);
#endif
switch (allowed_bilevel_resolutions)
{
case 0:
/* Allow anything */
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_R8_STANDARD
| T4_SUPPORT_RESOLUTION_R8_FINE
| T4_SUPPORT_RESOLUTION_R8_SUPERFINE
| T4_SUPPORT_RESOLUTION_R16_SUPERFINE
| T4_SUPPORT_RESOLUTION_200_100
| T4_SUPPORT_RESOLUTION_200_200
| T4_SUPPORT_RESOLUTION_200_400
| T4_SUPPORT_RESOLUTION_300_300
| T4_SUPPORT_RESOLUTION_300_600
| T4_SUPPORT_RESOLUTION_400_400
| T4_SUPPORT_RESOLUTION_400_800
| T4_SUPPORT_RESOLUTION_600_600
| T4_SUPPORT_RESOLUTION_600_1200
| T4_SUPPORT_RESOLUTION_1200_1200);
break;
case 1:
/* Allow anything metric */
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_R8_STANDARD
| T4_SUPPORT_RESOLUTION_R8_FINE
| T4_SUPPORT_RESOLUTION_R8_SUPERFINE
| T4_SUPPORT_RESOLUTION_R16_SUPERFINE);
break;
case 2:
/* Allow anything inch based */
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_200_100
| T4_SUPPORT_RESOLUTION_200_200
| T4_SUPPORT_RESOLUTION_200_400
| T4_SUPPORT_RESOLUTION_300_300
| T4_SUPPORT_RESOLUTION_300_600
| T4_SUPPORT_RESOLUTION_400_400
| T4_SUPPORT_RESOLUTION_400_800
| T4_SUPPORT_RESOLUTION_600_600
| T4_SUPPORT_RESOLUTION_600_1200
| T4_SUPPORT_RESOLUTION_1200_1200);
break;
case 3:
/* Allow only restricted length resolution */
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_R8_STANDARD
| T4_SUPPORT_RESOLUTION_R8_FINE
| T4_SUPPORT_RESOLUTION_200_100
| T4_SUPPORT_RESOLUTION_200_200);
break;
case 4:
/* Allow only more restricted length resolution */
t30_set_supported_bilevel_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_R8_STANDARD
| T4_SUPPORT_RESOLUTION_200_100);
break;
}
if (colour_enabled)
{
t30_set_supported_colour_resolutions(t30_state[i],
+5
View File
@@ -147,11 +147,15 @@ int main(int argc, char *argv[])
uint16_t *map_b;
uint16_t *map_z;
uint32_t jpeg_table_len;
#if 0
logging_state_t *logging;
#endif
printf("Demo of ITU/Lab library.\n");
#if 0
logging = span_log_init(NULL, SPAN_LOG_FLOW, "T.42");
#endif
#if defined(SPANDSP_SUPPORT_TIFF_FX)
TIFF_FX_init();
@@ -265,6 +269,7 @@ int main(int argc, char *argv[])
break;
}
outsize = 0;
if (process_raw)
{
uint8_t *jpeg_table;
+9 -7
View File
@@ -552,7 +552,6 @@ int read_compressed_image(meta_t *meta, uint8_t **buf)
int read_decompressed_image(meta_t *meta, uint8_t **buf)
{
int bytes_per_row;
tsize_t off;
int x;
int y;
int xx;
@@ -561,21 +560,23 @@ int read_decompressed_image(meta_t *meta, uint8_t **buf)
int yyy;
int i;
int j;
uint32_t w;
uint32_t h;
uint16_t samples_per_pixel;
int result;
int total_raw;
int total_data;
uint8_t *raw_buf;
uint8_t *image_buf;
uint8_t *jpeg_table;
uint32_t jpeg_table_len;
t85_decode_state_t t85;
t43_decode_state_t t43;
packer_t pack;
logging_state_t *logging;
logging_state_t logging2;
#if 0
uint8_t *jpeg_table;
uint32_t jpeg_table_len;
tsize_t off;
uint32_t w;
uint32_t h;
#endif
image_buf = NULL;
total_data = 0;
@@ -652,8 +653,8 @@ total_data *= 8;
if ((image_buf = malloc(total_data)) == NULL)
printf("Failed to allocated image buffer\n");
jpeg_table_len = 0;
#if 0
jpeg_table_len = 0;
if (TIFFGetField(meta->tif, TIFFTAG_JPEGTABLES, &jpeg_table_len, &jpeg_table))
{
total_image_len += (jpeg_table_len - 4);
@@ -921,6 +922,7 @@ int main(int argc, char *argv[])
set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f);
set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE);
outptr = NULL;
for (page_no = 0; ; page_no++)
{
if (read_file(&in_meta, page_no) < 0)
+70 -232
View File
@@ -53,48 +53,6 @@ in ITU specifications T.4 and T.6.
t4_tx_state_t *send_state;
t4_rx_state_t *receive_state;
/* The following are some test cases from T.4 */
#define FILL_70 " "
#define FILL_80 " "
#define FILL_100 " "
#define FILL_670 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_70
#define FILL_980 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_80
static const char t4_t6_test_patterns[][1728 + 1] =
{
"XXXXXX " FILL_980 " XXX XXX X " FILL_670 " XXXX",
"XXXXXX " FILL_980 " XXX X " FILL_670 " XXXX",
/* Line start should code to V(0). Line middle codes to VR(3) VL(2) V(0). Line end should code to V(0) V(0). */
" XXXX " FILL_980 " XXXXXXX " FILL_670 " XX ",
"XXXXX " FILL_980 "XX XX " FILL_670 " XXXX",
/* Line start should code to VL(1). Line middle codes to H(7,2). Line end should code to V(0) VR(2) */
"XXX " FILL_980 " XX XX XX XXX " FILL_670 " X ",
" " FILL_980 " X XXX XXXX " FILL_670 " X XX",
/* Line start should code to P. Line middle codes to P VL(1) V(0) H(3,4) P. Line end codes to V(0) VL(2) V(0). */
"XXXXX " FILL_980 " " FILL_670 " XXXX",
" XXX " FILL_980 " " FILL_670 " XX ",
/* Line start should code to VR(2). Line end codes to V(0) VL(2) V(0). */
" XX " FILL_980 " " FILL_670 " X XXX",
"XXX X " FILL_980 " " FILL_670 " X ",
/* Line start should code to H(0,3) VR(1). Line end codes to V(0) VR(3). */
" " FILL_980 " " FILL_670 " XX ",
" " FILL_980 " " FILL_670 " ",
/* Line end codes to P V(0) a'0. */
" " FILL_980 " " FILL_670 " XXXXXXXXXX",
" " FILL_980 " " FILL_670 " XXXXXX XXXXXX",
/* Line end codes to H(2,6). */
" " FILL_980 " " FILL_670 " XX XXXXX",
" " FILL_980 " " FILL_670 " XX ",
/* Line end codes to V(0) H(7,0). */
};
int rows_written = 0;
int rows_read = 0;
@@ -140,63 +98,7 @@ static void display_page_stats(t4_rx_state_t *s)
}
/*- End of function --------------------------------------------------------*/
static int row_read_handler(void *user_data, uint8_t buf[], size_t len)
{
int i;
int j;
const char *s;
/* Send the test pattern. */
if (rows_read >= 16)
return 0;
s = t4_t6_test_patterns[rows_read++];
memset(buf, 0, len);
for (i = 0; i < len; i++)
{
for (j = 0; j < 8; j++)
{
if (*s++ != ' ')
buf[i] |= (0x80 >> j);
}
}
if (*s)
printf("Oops - '%c' at end of row %d\n", *s, rows_read);
return len;
}
/*- End of function --------------------------------------------------------*/
static int row_write_handler(void *user_data, const uint8_t buf[], size_t len)
{
int i;
int j;
const char *s;
uint8_t ref[8192];
/* Verify that what is received matches the test pattern. */
if (len == 0)
return 0;
s = t4_t6_test_patterns[rows_written++];
memset(ref, 0, len);
for (i = 0; i < len; i++)
{
for (j = 0; j < 8; j++)
{
if (*s++ != ' ')
ref[i] |= (0x80 >> j);
}
}
if (*s)
printf("Oops - '%c' at end of row %d\n", *s, rows_written);
if (memcmp(buf, ref, len))
{
printf("Test failed at row %d\n", rows_written);
exit(2);
}
return 0;
}
/*- End of function --------------------------------------------------------*/
static int detect_page_end(int bit, int page_ended)
static int detect_non_ecm_page_end(int bit, int page_ended)
{
static int consecutive_eols;
static int max_consecutive_eols;
@@ -207,10 +109,10 @@ static int detect_page_end(int bit, int page_ended)
static int expected_eols;
static int end_marks;
/* Check the EOLs are added properly to the end of an image. We can't rely on the
decoder giving the right answer, as a full set of EOLs is not needed for the
decoder to work. */
if (bit == -1000000)
/* Check the EOLs are added properly to the end of a non-ECM image. We can't rely
on the decoder giving the right answer, as a full set of EOLs is not needed for
the decoder to work. */
if (bit == -1)
{
/* Reset */
consecutive_eols = 0;
@@ -287,6 +189,9 @@ int main(int argc, char *argv[])
T4_COMPRESSION_T6,
T4_COMPRESSION_T85,
T4_COMPRESSION_T85_L0,
#if defined(SPANDSP_SUPPORT_T88x)
T4_COMPRESSION_T88,
#endif
#if defined(SPANDSP_SUPPORT_T42x)
T4_COMPRESSION_T42_T81,
T4_COMPRESSION_SYCC_T81,
@@ -294,7 +199,9 @@ int main(int argc, char *argv[])
#if defined(SPANDSP_SUPPORT_T43x)
T4_COMPRESSION_T43,
#endif
//T4_COMPRESSION_T45,
#if defined(SPANDSP_SUPPORT_T45x)
T4_COMPRESSION_T45,
#endif
-1
};
int sends;
@@ -348,7 +255,10 @@ int main(int argc, char *argv[])
case 'b':
block_size = atoi(optarg);
if (block_size > 1024)
block_size = 1024;
{
printf("Block size too large. Must be 1024 or less\n");
exit(2);
}
break;
case 'c':
if (strcmp(optarg, "T41D") == 0)
@@ -371,6 +281,13 @@ int main(int argc, char *argv[])
compression = T4_COMPRESSION_T85;
compression_step = -1;
}
#if defined(SPANDSP_SUPPORT_T88)
else if (strcmp(optarg, "T88") == 0)
{
compression = T4_COMPRESSION_T88;
compression_step = -1;
}
#endif
#if defined(SPANDSP_SUPPORT_T42)
else if (strcmp(optarg, "T81") == 0)
{
@@ -385,6 +302,18 @@ int main(int argc, char *argv[])
compression_step = -1;
}
#endif
#if defined(SPANDSP_SUPPORT_T45)
else if (strcmp(optarg, "T45") == 0)
{
compression = T4_COMPRESSION_T45;
compression_step = -1;
}
#endif
else
{
printf("Unrecognised compression.\n");
exit(2);
}
break;
case 'd':
decode_file_name = optarg;
@@ -533,130 +462,6 @@ int main(int argc, char *argv[])
}
else
{
#if 1
printf("Testing image_function->compress->decompress->image_function\n");
/* Send end gets image from a function */
if ((send_state = t4_tx_init(NULL, NULL, -1, -1)) == NULL)
{
printf("Failed to init T.4 tx\n");
exit(2);
}
span_log_set_level(t4_tx_get_logging_state(send_state), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
t4_tx_set_row_read_handler(send_state, row_read_handler, NULL);
t4_tx_set_image_width(send_state, 1728);
t4_tx_set_min_bits_per_row(send_state, min_row_bits);
t4_tx_set_max_2d_rows_per_1d_row(send_state, 2);
/* Receive end puts TIFF to a function. */
if ((receive_state = t4_rx_init(NULL, NULL, T4_COMPRESSION_T4_2D)) == NULL)
{
printf("Failed to init T.4 rx\n");
exit(2);
}
span_log_set_level(t4_rx_get_logging_state(receive_state), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
t4_rx_set_row_write_handler(receive_state, row_write_handler, NULL);
t4_rx_set_image_width(receive_state, t4_tx_get_image_width(send_state));
t4_rx_set_x_resolution(receive_state, t4_tx_get_x_resolution(send_state));
t4_rx_set_y_resolution(receive_state, t4_tx_get_y_resolution(send_state));
/* Now send and receive the test data with all compression modes. */
/* If we are stepping around the compression schemes, reset to the start of the sequence. */
if (compression_step > 0)
compression_step = 0;
for (;;)
{
end_marks = 0;
if (compression_step >= 0)
{
compression = compression_sequence[compression_step++];
if (compression < 0 || (block_size == 0 && compression_step >= 3))
break;
}
t4_tx_set_tx_encoding(send_state, compression);
t4_rx_set_rx_encoding(receive_state, compression);
rows_read = 0;
rows_written = 0;
if (t4_tx_start_page(send_state))
break;
if (t4_rx_start_page(receive_state))
break;
detect_page_end(-1000000, compression);
page_ended = FALSE;
switch (block_size)
{
case 0:
while ((bit = t4_tx_get_bit(send_state)) >= 0)
{
/* Monitor whether the EOLs are there in the correct amount */
if ((res = detect_page_end(bit, page_ended)))
{
printf("Incorrect EOLs - %d\n", res);
tests_failed += (res - 1);
break;
}
if (bit >= 0)
{
if (bit_error_rate)
{
if ((rand() % bit_error_rate) == 0)
bit ^= 1;
}
end_of_page = t4_rx_put_bit(receive_state, bit);
}
}
while (end_of_page != T4_DECODE_OK)
{
end_of_page = t4_rx_put_bit(receive_state, 0);
if (++end_marks > 50)
{
printf("Receiver missed the end of page mark\n");
tests_failed++;
break;
}
}
/* Now throw junk at the receive context, to ensure stuff occuring
after the end of page condition has no bad effect. */
for (i = 0; i < 1000; i++)
t4_rx_put_bit(receive_state, (rand() >> 10) & 1);
break;
default:
/* Some decoders require a few extra bits before the recognise the end
of an image, so be prepared to offer it a few. */
do
{
len = t4_tx_get(send_state, block, block_size);
if (len > 0)
end_of_page = t4_rx_put(receive_state, block, len);
}
while (len > 0);
while (end_of_page != T4_DECODE_OK)
{
block[0] = 0;
end_of_page = t4_rx_put(receive_state, block, 1);
if (++end_marks > 5)
{
printf("Receiver missed the end of page mark\n");
tests_failed++;
break;
}
}
break;
}
display_page_stats(receive_state);
t4_tx_end_page(send_state);
t4_rx_end_page(receive_state);
if (rows_read != (15 + 1) || rows_written != (15 + 1))
{
printf("Test failed: %d rows read, %d rows written\n", rows_read, rows_written);
exit(2);
}
if (compression_step < 0)
break;
}
t4_tx_release(send_state);
t4_rx_release(receive_state);
#endif
#if 1
printf("Testing TIFF->compress->decompress->TIFF cycle\n");
/* Send end gets TIFF from a file */
@@ -713,6 +518,37 @@ int main(int argc, char *argv[])
compression = compression_sequence[compression_step++];
}
}
#if 0
if (t4_tx_set_tx_image_format(send_state,
compression,
T4_SUPPORT_WIDTH_215MM
| T4_SUPPORT_LENGTH_US_LETTER
| T4_SUPPORT_LENGTH_US_LEGAL
| T4_SUPPORT_LENGTH_UNLIMITED,
T4_RESOLUTION_R8_STANDARD
| T4_RESOLUTION_R8_FINE
| T4_RESOLUTION_R8_SUPERFINE
| T4_RESOLUTION_R16_SUPERFINE
| T4_RESOLUTION_200_100
| T4_RESOLUTION_200_200
| T4_RESOLUTION_200_400
| T4_RESOLUTION_300_300
| T4_RESOLUTION_300_600
| T4_RESOLUTION_400_400
| T4_RESOLUTION_400_800
| T4_RESOLUTION_600_600
| T4_RESOLUTION_600_1200
| T4_RESOLUTION_1200_1200,
T4_RESOLUTION_100_100
| T4_RESOLUTION_200_200
| T4_RESOLUTION_300_300
| T4_RESOLUTION_400_400
| T4_RESOLUTION_600_600
| T4_RESOLUTION_1200_1200) < 0)
{
break;
}
#endif
t4_tx_set_tx_encoding(send_state, compression);
t4_rx_set_rx_encoding(receive_state, compression);
@@ -723,15 +559,17 @@ int main(int argc, char *argv[])
t4_rx_set_image_width(receive_state, t4_tx_get_image_width(send_state));
}
t4_rx_start_page(receive_state);
detect_page_end(-1000000, compression);
detect_non_ecm_page_end(-1, compression);
page_ended = FALSE;
switch (block_size)
{
case 0:
/* Bit by bit operation. This is only appropriate for T.4 1D and 2D,
which are used without ECM. */
while ((bit = t4_tx_get_bit(send_state)) >= 0)
{
/* Monitor whether the EOLs are there in the correct amount */
if ((res = detect_page_end(bit, page_ended)))
if ((res = detect_non_ecm_page_end(bit, page_ended)))
{
printf("Incorrect EOLs - %d\n", res);
tests_failed += (res - 1);
@@ -767,7 +605,7 @@ int main(int argc, char *argv[])
end_of_page = t4_rx_put(receive_state, block, len);
}
while (len > 0);
/* Some decoders require a few extra bits before the recognise the end
/* Some decoders require a few extra bits before they recognise the end
of an image, so be prepared to offer it a few. */
while (end_of_page != T4_DECODE_OK)
{
+5 -4
View File
@@ -54,8 +54,8 @@ static int test_vec_copyf(void)
for (i = 0; i < 99; i++)
{
x[i] = i;
za[i] = -1.0f;
zb[i] = -1.0f;
za[i] = -0.5f;
zb[i] = -0.5f;
}
vec_copyf_dumb(za + 3, x + 1, 0);
vec_copyf(zb + 3, x + 1, 0);
@@ -114,8 +114,8 @@ static int test_vec_negatef(void)
for (i = 0; i < 99; i++)
{
x[i] = i;
za[i] = -1.0f;
zb[i] = -1.0f;
za[i] = -0.5f;
zb[i] = -0.5f;
}
vec_negatef_dumb(za + 3, x + 1, 0);
vec_negatef(zb + 3, x + 1, 0);
@@ -143,6 +143,7 @@ static int test_vec_negatef(void)
vec_negatef(zb + 3, x + 1, 29);
for (i = 0; i < 99; i++)
{
printf("C %d %f %f %f\n", i, x[i], za[i], zb[i]);
if (za[i] != zb[i])
{
printf("vec_negatef() - %d %f %f\n", i, za[i], zb[i]);
+1
View File
@@ -240,6 +240,7 @@ struct switch_runtime {
uint32_t sps_total;
int32_t sps;
int32_t sps_last;
int32_t sps_peak;
switch_log_level_t hard_log_level;
char *mailer_app;
char *mailer_app_args;
+9
View File
@@ -1967,6 +1967,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_check_results(switch_asr_handle_
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
/*!
\brief Get result headers from an asr handle
\param ah the handle to get results from
\param headers a pointer to dynamically allocate an switch_event_t result to
\param flags flags to influence behaviour
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags);
/*!
\brief Load a grammar to an asr handle
\param ah the handle to load to
+15
View File
@@ -184,6 +184,18 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_and_detect_speech(switch_core_se
switch_input_args_t *args);
/*!
\brief Initialize background Speech detection on a session, so that parameters can be set, and grammars loaded.
After calling this function, it is possible to call switch_ivr_set_param_detect_speech() to set recognition parameters.
Calling switch_ivr_detect_speech_load_grammar() starts the speech recognition.
\param session the session to attach
\param mod_name the module name of the ASR library
\param dest the destination address
\param ah an ASR handle to use (NULL to create one)
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_init(switch_core_session_t *session, const char *mod_name,
const char *dest, switch_asr_handle_t *ah);
/*!
\brief Engage background Speech detection on a session
\param session the session to attach
@@ -934,6 +946,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say_ip(switch_core_session_t *session
switch_input_args_t *args);
SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *session, const char *data);
SWITCH_DECLARE(switch_status_t) switch_ivr_set_user_xml(switch_core_session_t *session, const char *prefix,
const char *user, const char *domain, switch_xml_t x_user);
SWITCH_DECLARE(switch_status_t) switch_ivr_sound_test(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_process_import(switch_core_session_t *session, switch_channel_t *peer_channel, const char *varname, const char *prefix);
SWITCH_DECLARE(switch_bool_t) switch_ivr_uuid_exists(const char *uuid);
+2
View File
@@ -377,6 +377,8 @@ struct switch_asr_interface {
switch_status_t (*asr_check_results) (switch_asr_handle_t *ah, switch_asr_flag_t *flags);
/*! function to read results from the ASR */
switch_status_t (*asr_get_results) (switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
/*! function to read result headers from the ASR */
switch_status_t (*asr_get_result_headers) (switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags);
/*! function to start ASR input timers */
switch_status_t (*asr_start_input_timers) (switch_asr_handle_t *ah);
void (*asr_text_param) (switch_asr_handle_t *ah, char *param, const char *val);
+2 -1
View File
@@ -1887,7 +1887,8 @@ typedef enum {
SCSC_DEBUG_SQL,
SCSC_SQL,
SCSC_API_EXPANSION,
SCSC_RECOVER
SCSC_RECOVER,
SCSC_SPS_PEAK
} switch_session_ctl_t;
typedef enum {
@@ -2012,7 +2012,7 @@ SWITCH_STANDARD_API(lan_addr_function)
SWITCH_STANDARD_API(status_function)
{
switch_core_time_duration_t duration = { 0 };
int sps = 0, last_sps = 0;
int sps = 0, last_sps = 0, max_sps = 0;
switch_bool_t html = SWITCH_FALSE; /* shortcut to format.html */
char * nl = "\n"; /* shortcut to format.nl */
stream_format format = { 0 };
@@ -2058,7 +2058,8 @@ SWITCH_STANDARD_API(status_function)
stream->write_function(stream, "%" SWITCH_SIZE_T_FMT " session(s) since startup%s", switch_core_session_id() - 1, nl);
switch_core_session_ctl(SCSC_LAST_SPS, &last_sps);
switch_core_session_ctl(SCSC_SPS, &sps);
stream->write_function(stream, "%d session(s) - %d out of max %d per sec %s", switch_core_session_count(), last_sps, sps, nl);
switch_core_session_ctl(SCSC_SPS_PEAK, &max_sps);
stream->write_function(stream, "%d session(s) - %d out of max %d per sec peak %d %s", switch_core_session_count(), last_sps, sps, max_sps, nl);
stream->write_function(stream, "%d session(s) max%s", switch_core_session_limit(0), nl);
stream->write_function(stream, "min idle cpu %0.2f/%0.2f%s", switch_core_min_idle_cpu(-1.0), switch_core_idle_cpu(), nl);
@@ -2067,7 +2068,7 @@ SWITCH_STANDARD_API(status_function)
return SWITCH_STATUS_SUCCESS;
}
#define CTL_SYNTAX "[recover|send_sighup|hupall|pause [inbound|outbound]|resume [inbound|outbound]|shutdown [cancel|elegant|asap|now|restart]|sps|sync_clock|sync_clock_when_idle|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]]"
#define CTL_SYNTAX "[recover|send_sighup|hupall|pause [inbound|outbound]|resume [inbound|outbound]|shutdown [cancel|elegant|asap|now|restart]|sps|sps_peak_reset|sync_clock|sync_clock_when_idle|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]]"
SWITCH_STANDARD_API(ctl_function)
{
int argc;
@@ -2289,6 +2290,10 @@ SWITCH_STANDARD_API(ctl_function)
switch_core_session_ctl(SCSC_DEBUG_LEVEL, &arg);
stream->write_function(stream, "+OK DEBUG level: %d\n", arg);
} else if (!strcasecmp(argv[0], "sps_peak_reset")) {
arg = -1;
switch_core_session_ctl(SCSC_SPS_PEAK, &arg);
stream->write_function(stream, "+OK max sessions per second counter reset\n");
} else if (!strcasecmp(argv[0], "last_sps")) {
switch_core_session_ctl(SCSC_LAST_SPS, &arg);
stream->write_function(stream, "+OK last sessions per second: %d\n", arg);
@@ -202,7 +202,8 @@ typedef enum {
CFLAG_AUDIO_ALWAYS = (1 << 15),
CFLAG_ENDCONF_FORCED = (1 << 16),
CFLAG_RFC4579 = (1 << 17),
CFLAG_FLOOR_CHANGE = (1 << 18)
CFLAG_FLOOR_CHANGE = (1 << 18),
CFLAG_VID_FLOOR_LOCK = (1 << 19)
} conf_flag_t;
typedef enum {
@@ -1454,10 +1455,10 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
switch_channel_set_variable(channel, "conference_recording", conference->record_filename);
switch_channel_set_variable(channel, CONFERENCE_UUID_VARIABLE, conference->uuid_str);
if (switch_channel_test_flag(channel, CF_VIDEO)) {
if (!switch_test_flag(conference, CFLAG_VIDEO_BRIDGE)) {
if (switch_test_flag(conference, CFLAG_VIDEO_BRIDGE)) {
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
} else {
switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
}
/* Tell the channel to request a fresh vid frame */
@@ -1576,32 +1577,62 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
return status;
}
static void conference_set_video_floor_holder(conference_obj_t *conference, conference_member_t *member)
static void conference_set_video_floor_holder(conference_obj_t *conference, conference_member_t *member, switch_bool_t force)
{
switch_event_t *event;
conference_member_t *old_member = NULL;
int old_id = 0;
if (switch_test_flag(conference, CFLAG_VIDEO_BRIDGE)) {
if (!member) {
switch_clear_flag(conference, CFLAG_VID_FLOOR_LOCK);
}
if (switch_test_flag(conference, CFLAG_VIDEO_BRIDGE) || (!force && switch_test_flag(conference, CFLAG_VID_FLOOR_LOCK))) {
return;
}
if (conference->video_floor_holder) {
if (conference->video_floor_holder == member) {
return;
} else {
old_id = conference->video_floor_holder->id;
switch_channel_clear_flag(conference->video_floor_holder->channel, CF_VIDEO_PASSIVE);
switch_core_session_refresh_video(conference->video_floor_holder->session);
} else {
old_member = conference->video_floor_holder;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Dropping video floor %s\n",
switch_channel_get_name(old_member->channel));
}
}
if ((conference->video_floor_holder = member)) {
switch_channel_set_flag(member->channel, CF_VIDEO_PASSIVE);
switch_core_session_refresh_video(conference->video_floor_holder->session);
switch_set_flag(conference, CFLAG_FLOOR_CHANGE);
switch_mutex_lock(conference->mutex);
if (!member) {
conference_member_t *imember;
for (imember = conference->members; imember; imember = imember->next) {
if (imember != conference->video_floor_holder && switch_channel_test_flag(imember->channel, CF_VIDEO)) {
member = imember;
break;
}
}
}
if (old_id > -1 && test_eflag(conference, EFLAG_FLOOR_CHANGE)) {
if (member) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Adding video floor %s\n",
switch_channel_get_name(member->channel));
switch_channel_set_flag(member->channel, CF_VIDEO_PASSIVE);
switch_core_session_refresh_video(member->session);
conference->video_floor_holder = member;
} else {
conference->video_floor_holder = NULL;
}
if (old_member) {
old_id = old_member->id;
switch_channel_clear_flag(old_member->channel, CF_VIDEO_PASSIVE);
}
switch_set_flag(conference, CFLAG_FLOOR_CHANGE);
switch_mutex_unlock(conference->mutex);
if (test_eflag(conference, EFLAG_FLOOR_CHANGE)) {
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
conference_add_event_data(conference, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "video-floor-change");
@@ -1623,29 +1654,44 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf
static void conference_set_floor_holder(conference_obj_t *conference, conference_member_t *member)
{
switch_event_t *event;
conference_member_t *old_member = NULL;
int old_id = 0;
if (!switch_test_flag(conference, CFLAG_VIDEO_BRIDGE) &&
((conference->video_floor_holder && !member) || (member && switch_channel_test_flag(member->channel, CF_VIDEO)))) {
conference_set_video_floor_holder(conference, member, SWITCH_FALSE);
}
if (conference->floor_holder) {
if (conference->floor_holder == member) {
return;
} else {
old_id = conference->floor_holder->id;
if (!conference->video_floor_holder && !switch_test_flag(conference, CFLAG_VIDEO_BRIDGE)) {
switch_channel_clear_flag(conference->floor_holder->channel, CF_VIDEO_PASSIVE);
switch_core_session_refresh_video(conference->floor_holder->session);
}
old_member = conference->floor_holder;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Dropping floor %s\n",
switch_channel_get_name(old_member->channel));
}
}
if ((conference->floor_holder = member)) {
if (!conference->video_floor_holder && !switch_test_flag(conference, CFLAG_VIDEO_BRIDGE)) {
switch_channel_set_flag(member->channel, CF_VIDEO_PASSIVE);
switch_core_session_refresh_video(conference->floor_holder->session);
}
switch_set_flag(conference, CFLAG_FLOOR_CHANGE);
switch_mutex_lock(conference->mutex);
if (member) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Adding floor %s\n",
switch_channel_get_name(member->channel));
conference->floor_holder = member;
} else {
conference->floor_holder = NULL;
}
if (old_id > -1 && test_eflag(conference, EFLAG_FLOOR_CHANGE)) {
if (old_member) {
old_id = old_member->id;
}
switch_set_flag(conference, CFLAG_FLOOR_CHANGE);
switch_mutex_unlock(conference->mutex);
if (test_eflag(conference, EFLAG_FLOOR_CHANGE)) {
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
conference_add_event_data(conference, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "floor-change");
@@ -1754,7 +1800,7 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
if (member == member->conference->video_floor_holder) {
conference_set_video_floor_holder(member->conference, NULL);
conference_set_video_floor_holder(member->conference, NULL, SWITCH_TRUE);
}
member->conference = NULL;
@@ -1770,11 +1816,6 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
}
}
if (switch_channel_test_flag(channel, CF_VIDEO)) {
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
}
conference_send_presence(conference);
switch_channel_set_variable(channel, "conference_call_key", NULL);
@@ -1906,7 +1947,7 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
if (conference->video_floor_holder) {
floor_holder = conference->video_floor_holder;
} else {
floor_holder = conference->floor_holder;
floor_holder = NULL;
}
@@ -1915,7 +1956,7 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
goto do_continue;
}
if (!switch_channel_test_flag(switch_core_session_get_channel(floor_holder->session), CF_VIDEO)) {
if (!floor_holder->session || !floor_holder->channel || !switch_channel_test_flag(floor_holder->channel, CF_VIDEO)) {
yield = 100000;
goto do_continue;
}
@@ -2065,8 +2106,8 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
if (switch_test_flag(imember, MFLAG_RUNNING) && imember->session) {
switch_channel_t *channel = switch_core_session_get_channel(imember->session);
if ((!floor_holder || (imember->score_iir > SCORE_IIR_SPEAKING_MAX && (floor_holder->score_iir < SCORE_IIR_SPEAKING_MIN))) &&
(!switch_test_flag(conference, CFLAG_VID_FLOOR) || switch_channel_test_flag(channel, CF_VIDEO))) {
if ((!floor_holder || (imember->score_iir > SCORE_IIR_SPEAKING_MAX && (floor_holder->score_iir < SCORE_IIR_SPEAKING_MIN)))) {// &&
//(!switch_test_flag(conference, CFLAG_VID_FLOOR) || switch_channel_test_flag(channel, CF_VIDEO))) {
floor_holder = imember;
}
@@ -5273,7 +5314,8 @@ static switch_status_t conf_api_sub_clear_vid_floor(conference_obj_t *conference
}
switch_mutex_lock(conference->mutex);
conference_set_video_floor_holder(conference, NULL);
switch_clear_flag(conference, CFLAG_VID_FLOOR_LOCK);
//conference_set_video_floor_holder(conference, NULL);
switch_mutex_unlock(conference->mutex);
return SWITCH_STATUS_SUCCESS;
@@ -5286,8 +5328,13 @@ static switch_status_t conf_api_sub_vid_floor(conference_member_t *member, switc
if (member == NULL)
return SWITCH_STATUS_GENERR;
if (!switch_channel_test_flag(member->channel, CF_VIDEO)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Channel %s does not have video capability!\n", switch_channel_get_name(member->channel));
return SWITCH_STATUS_FALSE;
}
if (switch_test_flag(member->conference, CFLAG_VIDEO_BRIDGE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"conference %s is in video bridge mode, this functionality is not compatible\n", member->conference->name);
return SWITCH_STATUS_FALSE;
}
@@ -5298,19 +5345,22 @@ static switch_status_t conf_api_sub_vid_floor(conference_member_t *member, switc
force = 1;
}
if (!force && member->conference->video_floor_holder == member) {
conference_set_video_floor_holder(member->conference, NULL);
if (member->conference->video_floor_holder == member && switch_test_flag(member->conference, CFLAG_VID_FLOOR_LOCK)) {
switch_clear_flag(member->conference, CFLAG_VID_FLOOR_LOCK);
conference_set_floor_holder(member->conference, member);
if (stream == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "conference %s OK floor none\n", member->conference->name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "conference %s OK video floor auto\n", member->conference->name);
} else {
stream->write_function(stream, "OK floor none\n");
}
} else if (force || member->conference->video_floor_holder == NULL) {
conference_set_video_floor_holder(member->conference, member);
switch_set_flag(member->conference, CFLAG_VID_FLOOR_LOCK);
conference_set_video_floor_holder(member->conference, member, SWITCH_TRUE);
if (test_eflag(member->conference, EFLAG_FLOOR_CHANGE)) {
if (stream == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "conference %s OK floor %d %s\n",
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "conference %s OK video floor %d %s\n",
member->conference->name, member->id, switch_channel_get_name(member->channel));
} else {
stream->write_function(stream, "OK floor %u\n", member->id);
@@ -7725,7 +7775,9 @@ SWITCH_STANDARD_APP(conference_function)
}
while (!pin_valid && pin_retries && status == SWITCH_STATUS_SUCCESS) {
int maxpin = strlen(dpin) > strlen(mdpin) ? strlen(dpin) : strlen(mdpin);
size_t dpin_length = dpin ? strlen(dpin) : 0;
size_t mdpin_length = mdpin ? strlen(mdpin) : 0;
int maxpin = dpin_length > mdpin_length ? dpin_length : mdpin_length;
switch_status_t pstatus = SWITCH_STATUS_FALSE;
/* be friendly */
@@ -445,6 +445,8 @@ SWITCH_STANDARD_APP(detect_speech_function)
switch_ivr_detect_speech_disable_grammar(session, argv[1]);
} else if (!strcasecmp(argv[0], "grammarsalloff")) {
switch_ivr_detect_speech_disable_all_grammars(session);
} else if (!strcasecmp(argv[0], "init")) {
switch_ivr_detect_speech_init(session, argv[1], argv[2], NULL);
} else if (!strcasecmp(argv[0], "pause")) {
switch_ivr_pause_detect_speech(session);
} else if (!strcasecmp(argv[0], "resume")) {
+2
View File
@@ -4069,6 +4069,8 @@ static switch_status_t load_config(int reload, int del_all)
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
}
} else if (!strcasecmp(var, "dbname") && !zstr(val)) {
globals.dbname = switch_core_strdup(globals.pool, val);
} else if (!strcasecmp(var, "allow-transcoding") && !zstr(val)) {
globals.allow_transcoding = switch_true(val);
} else if (!strcasecmp(var, "db-pre-trans-execute") && !zstr(val)) {
+6 -2
View File
@@ -1002,6 +1002,7 @@ static switch_bool_t test_profile(char *lcr_profile)
callback_t routes = { 0 };
switch_memory_pool_t *pool = NULL;
switch_event_t *event = NULL;
switch_bool_t r;
switch_core_new_memory_pool(&pool);
switch_event_create(&event, SWITCH_EVENT_MESSAGE);
@@ -1016,8 +1017,11 @@ static switch_bool_t test_profile(char *lcr_profile)
routes.lookup_number = "15555551212";
routes.cid = "18005551212";
lcr_destroy(routes.head);
return (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) ?
SWITCH_TRUE : SWITCH_FALSE;
r = (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) ? SWITCH_TRUE : SWITCH_FALSE;
switch_event_destroy(&event);
return r;
}
static switch_status_t lcr_load_config()
@@ -1672,6 +1672,9 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
char vm_cc[256] = "";
char macro_buf[80] = "";
switch_xml_t xml_root, x_domain, x_param, x_params, x_user = NULL;
switch_event_t *my_params = NULL;
switch_bool_t vm_enabled = SWITCH_TRUE;
switch_snprintf(key_buf, sizeof(key_buf), "%s:%s", profile->prepend_key, profile->forward_key);
TRY_CODE(vm_macro_get(session, VM_FORWARD_PREPEND_MACRO, key_buf, input, sizeof(input), 1, "", &term, profile->digit_timeout));
@@ -1712,15 +1715,51 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
cmd = switch_core_session_sprintf(session, "%s@%s@%s %s %s '%s'", vm_cc, cbt->domain, profile->name,
new_file_path, cbt->cid_number, cbt->cid_name);
if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Sent Carbon Copy to %s\n", vm_cc);
TRY_CODE(switch_ivr_phrase_macro(session, VM_ACK_MACRO, "saved", NULL, NULL));
cbt->move = VM_MOVE_SAME;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to Carbon Copy to %s\n", vm_cc);
switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(my_params);
if (switch_xml_locate_domain(cbt->domain, my_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to forward message - Cannot locate domain %s\n", cbt->domain);
TRY_CODE(switch_ivr_phrase_macro(session, VM_INVALID_EXTENSION_MACRO, vm_cc, NULL, NULL));
goto get_exten;
} else if (switch_xml_locate_user_in_domain(vm_cc, x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to forward message - Cannot locate user %s@%s\n", vm_cc, cbt->domain);
TRY_CODE(switch_ivr_phrase_macro(session, VM_INVALID_EXTENSION_MACRO, vm_cc, NULL, NULL));
goto get_exten;
} else {
x_params = switch_xml_child(x_user, "params");
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr_soft(x_param, "name");
const char *val = switch_xml_attr_soft(x_param, "value");
if (zstr(var) || zstr(val)) {
continue; /* Ignore empty entires */
}
if (!strcasecmp(var, "vm-enabled")) {
vm_enabled = !switch_false(val);
}
}
if (!vm_enabled) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to forward message - Voicemail is disabled for user %s@%s\n", vm_cc, cbt->domain);
TRY_CODE(switch_ivr_phrase_macro(session, VM_INVALID_EXTENSION_MACRO, vm_cc, NULL, NULL));
goto get_exten;
} else {
if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Forwarded message to %s\n", vm_cc);
TRY_CODE(switch_ivr_phrase_macro(session, VM_ACK_MACRO, "saved", NULL, NULL));
cbt->move = VM_MOVE_SAME;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to forward message to %s\n", vm_cc);
TRY_CODE(switch_ivr_phrase_macro(session, VM_INVALID_EXTENSION_MACRO, vm_cc, NULL, NULL));
goto get_exten;
}
}
}
switch_xml_free(xml_root);
switch_event_destroy(&my_params);
} else if (!strcmp(input, profile->delete_file_key) || (!strcmp(input, profile->email_key) && !zstr(cbt->email))) {
char *sql = switch_mprintf("update voicemail_msgs set flags='delete' where uuid='%s'", cbt->uuid);
vm_execute_sql(profile, sql, profile->mutex);
+189 -3
View File
@@ -450,6 +450,8 @@ struct recognizer_data {
switch_hash_t *enabled_grammars;
/** recognize result */
char *result;
/** recognize result headers */
switch_event_t *result_headers;
/** true, if voice has started */
int start_of_input;
/** true, if input timers have started */
@@ -483,6 +485,7 @@ static switch_status_t recog_asr_resume(switch_asr_handle_t *ah);
static switch_status_t recog_asr_pause(switch_asr_handle_t *ah);
static switch_status_t recog_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
static switch_status_t recog_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
static switch_status_t recog_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags);
static switch_status_t recog_asr_start_input_timers(switch_asr_handle_t *ah);
static void recog_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val);
static void recog_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val);
@@ -505,7 +508,9 @@ static switch_status_t recog_channel_check_results(speech_channel_t *schannel);
static switch_status_t recog_channel_set_start_of_input(speech_channel_t *schannel);
static switch_status_t recog_channel_start_input_timers(speech_channel_t *schannel);
static switch_status_t recog_channel_set_results(speech_channel_t *schannel, const char *results);
static switch_status_t recog_channel_set_result_headers(speech_channel_t *schannel, mrcp_recog_header_t *recog_hdr);
static switch_status_t recog_channel_get_results(speech_channel_t *schannel, char **results);
static switch_status_t recog_channel_get_result_headers(speech_channel_t *schannel, switch_event_t **result_headers);
static switch_status_t recog_channel_set_params(speech_channel_t *schannel, mrcp_message_t *msg, mrcp_generic_header_t *gen_hdr,
mrcp_recog_header_t *recog_hdr);
static switch_status_t recog_channel_set_header(speech_channel_t *schannel, int id, char *val, mrcp_message_t *msg, mrcp_recog_header_t *recog_hdr);
@@ -2156,9 +2161,9 @@ static switch_status_t recog_channel_start(speech_channel_t *schannel)
recognizer_data_t *r;
char *start_input_timers;
const char *mime_type;
char *key;
char *key = NULL;
switch_size_t len;
grammar_t *grammar;
grammar_t *grammar = NULL;
switch_size_t grammar_uri_count = 0;
switch_size_t grammar_uri_list_len = 0;
char *grammar_uri_list = NULL;
@@ -2176,6 +2181,9 @@ static switch_status_t recog_channel_start(speech_channel_t *schannel)
}
r = (recognizer_data_t *) schannel->data;
r->result = NULL;
if (r->result_headers) {
switch_event_destroy(&r->result_headers);
}
r->start_of_input = 0;
/* input timers are started by default unless the start-input-timers=false param is set */
@@ -2598,6 +2606,141 @@ static switch_status_t recog_channel_set_results(speech_channel_t *schannel, con
return status;
}
/**
* Find a parameter from a ;-separated string
*
* @param str the input string to find data in
* @param param the parameter to to look for
* @return a pointer in the str if successful, or NULL.
*/
static char *find_parameter(const char *str, const char *param)
{
char *ptr = (char *) str;
while (ptr) {
if (!strncasecmp(ptr, param, strlen(param)))
return ptr;
if ((ptr = strchr(ptr, ';')))
ptr++;
while (ptr && *ptr == ' ') {
ptr++;
}
}
return NULL;
}
/**
* Get a parameter value from a ;-separated string
*
* @param str the input string to parse data from
* @param param the parameter to to look for
* @return a malloc'ed char* if successful, or NULL.
*/
static char *get_parameter_value(const char *str, const char *param)
{
const char *param_ptr;
char *param_value = NULL;
char *tmp;
switch_size_t param_len;
char *param_tmp;
if (zstr(str) || zstr(param)) return NULL;
/* Append "=" to the end of the string */
param_tmp = switch_mprintf("%s=", param);
if (!param_tmp) return NULL;
param = param_tmp;
param_len = strlen(param);
param_ptr = find_parameter(str, param);
if (zstr(param_ptr)) goto fail;
param_value = strdup(param_ptr + param_len);
if (zstr(param_value)) goto fail;
if ((tmp = strchr(param_value, ';'))) *tmp = '\0';
switch_safe_free(param_tmp);
return param_value;
fail:
switch_safe_free(param_tmp);
switch_safe_free(param_value);
return NULL;
}
/**
* Set the recognition result headers
*
* @param schannel the channel whose results are set
* @param recog_hdr the recognition headers
* @return SWITCH_STATUS_SUCCESS if successful
*/
static switch_status_t recog_channel_set_result_headers(speech_channel_t *schannel, mrcp_recog_header_t *recog_hdr)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
recognizer_data_t *r;
switch_mutex_lock(schannel->mutex);
r = (recognizer_data_t *) schannel->data;
if (r->result_headers) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) result headers are already set\n", schannel->name);
status = SWITCH_STATUS_FALSE;
goto done;
}
if (!recog_hdr) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) result headers are NULL\n", schannel->name);
status = SWITCH_STATUS_FALSE;
goto done;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) ASR adding result headers\n", schannel->name);
if ((status = switch_event_create(&r->result_headers, SWITCH_EVENT_CLONE)) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Completion-Cause", "%d", recog_hdr->completion_cause);
if (!zstr(recog_hdr->completion_reason.buf)) {
switch_event_add_header_string(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Completion-Reason", recog_hdr->completion_reason.buf);
}
if (!zstr(recog_hdr->waveform_uri.buf)) {
char *tmp;
if ((tmp = strdup(recog_hdr->waveform_uri.buf))) {
char *tmp2;
if ((tmp2 = strchr(tmp, ';'))) *tmp2 = '\0';
switch_event_add_header_string(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Waveform-URI", tmp);
free(tmp);
}
if ((tmp = get_parameter_value(recog_hdr->waveform_uri.buf, "size"))) {
switch_event_add_header_string(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Waveform-Size", tmp);
free(tmp);
}
if ((tmp = get_parameter_value(recog_hdr->waveform_uri.buf, "duration"))) {
switch_event_add_header_string(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Waveform-Duration", tmp);
free(tmp);
}
}
}
done:
switch_mutex_unlock(schannel->mutex);
return status;
}
/**
* Get the recognition results.
*
@@ -2627,6 +2770,29 @@ static switch_status_t recog_channel_get_results(speech_channel_t *schannel, cha
return status;
}
/**
* Get the recognition result headers.
*
* @param schannel the channel to get results from
* @param result_headers the recognition result headers. switch_event_destroy() the results when finished with them.
* @return SWITCH_STATUS_SUCCESS will always be returned, since this is just optional data.
*/
static switch_status_t recog_channel_get_result_headers(speech_channel_t *schannel, switch_event_t **result_headers)
{
recognizer_data_t *r = (recognizer_data_t *) schannel->data;
switch_mutex_lock(schannel->mutex);
if (r->result_headers && result_headers) {
*result_headers = r->result_headers;
r->result_headers = NULL;
}
switch_mutex_unlock(schannel->mutex);
return SWITCH_STATUS_SUCCESS;
}
/**
* Set parameters in a recognizer MRCP header
*
@@ -3207,6 +3373,9 @@ static switch_status_t recog_asr_close(switch_asr_handle_t *ah, switch_asr_flag_
r->dtmf_generator_active = 0;
mpf_dtmf_generator_destroy(r->dtmf_generator);
}
if (r->result_headers) {
switch_event_destroy(&r->result_headers);
}
switch_mutex_unlock(schannel->mutex);
speech_channel_destroy(schannel);
}
@@ -3326,6 +3495,19 @@ static switch_status_t recog_asr_get_results(switch_asr_handle_t *ah, char **xml
return recog_channel_get_results(schannel, xmlstr);
}
/**
* Process asr_get_result_headers request from FreeSWITCH. Return the headers back
* to FreeSWITCH. FreeSWITCH will switch_event_destroy() the headers.
*
* @param ah the FreeSWITCH speech recognition handle
* @param flags other flags
*/
static switch_status_t recog_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags)
{
speech_channel_t *schannel = (speech_channel_t *) ah->private_info;
return recog_channel_get_result_headers(schannel, headers);
}
/**
* Send START-INPUT-TIMERS to executing recognition request
* @param ah the handle to start timers on
@@ -3473,6 +3655,7 @@ static apt_bool_t recog_on_message_receive(mrcp_application_t *application, mrcp
recog_hdr->completion_cause);
if (message->body.length > 0) {
if (message->body.buf[message->body.length - 1] == '\0') {
recog_channel_set_result_headers(schannel, recog_hdr);
recog_channel_set_results(schannel, message->body.buf);
} else {
/* string is not null terminated */
@@ -3481,11 +3664,13 @@ static apt_bool_t recog_on_message_receive(mrcp_application_t *application, mrcp
"(%s) Recognition result is not null-terminated. Appending null terminator.\n", schannel->name);
strncpy(result, message->body.buf, message->body.length);
result[message->body.length] = '\0';
recog_channel_set_result_headers(schannel, recog_hdr);
recog_channel_set_results(schannel, result);
}
} else {
char *completion_cause = switch_mprintf("Completion-Cause: %03d", recog_hdr->completion_cause);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) No result\n", schannel->name);
recog_channel_set_result_headers(schannel, recog_hdr);
recog_channel_set_results(schannel, completion_cause);
switch_safe_free(completion_cause);
}
@@ -3584,6 +3769,7 @@ static switch_status_t recog_load(switch_loadable_module_interface_t *module_int
asr_interface->asr_pause = recog_asr_pause;
asr_interface->asr_check_results = recog_asr_check_results;
asr_interface->asr_get_results = recog_asr_get_results;
asr_interface->asr_get_result_headers = recog_asr_get_result_headers;
asr_interface->asr_start_input_timers = recog_asr_start_input_timers;
asr_interface->asr_text_param = recog_asr_text_param;
asr_interface->asr_numeric_param = recog_asr_numeric_param;
@@ -3620,7 +3806,7 @@ static switch_status_t recog_load(switch_loadable_module_interface_t *module_int
switch_core_hash_insert(globals.recog.param_id_map, "N-Best-List-Length", unimrcp_param_id_create(RECOGNIZER_HEADER_N_BEST_LIST_LENGTH, pool));
switch_core_hash_insert(globals.recog.param_id_map, "No-Input-Timeout", unimrcp_param_id_create(RECOGNIZER_HEADER_NO_INPUT_TIMEOUT, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Recognition-Timeout", unimrcp_param_id_create(RECOGNIZER_HEADER_RECOGNITION_TIMEOUT, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Waveform-Url", unimrcp_param_id_create(RECOGNIZER_HEADER_WAVEFORM_URI, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Waveform-Uri", unimrcp_param_id_create(RECOGNIZER_HEADER_WAVEFORM_URI, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Completion-Cause", unimrcp_param_id_create(RECOGNIZER_HEADER_COMPLETION_CAUSE, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Recognizer-Context-Block",
unimrcp_param_id_create(RECOGNIZER_HEADER_RECOGNIZER_CONTEXT_BLOCK, pool));
+2 -2
View File
@@ -888,7 +888,7 @@ void sofia_reg_auth_challenge(sofia_profile_t *profile, nua_handle_t *nh, sofia_
auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization,
sip_t const *sip,
sofia_dispatch_event_t *de, const char *regstr, char *np, size_t nplen, char *ip, switch_event_t **v_event,
long exptime, sofia_regtype_t regtype, const char *to_user, switch_event_t **auth_params, long *reg_count);
long exptime, sofia_regtype_t regtype, const char *to_user, switch_event_t **auth_params, long *reg_count, switch_xml_t *user_xml);
void sofia_reg_handle_sip_r_challenge(int status,
@@ -935,7 +935,7 @@ void sofia_glue_do_xfer_invite(switch_core_session_t *session);
uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
sofia_dispatch_event_t *de,
sofia_regtype_t regtype, char *key,
uint32_t keylen, switch_event_t **v_event, const char *is_nat, sofia_private_t **sofia_private_p);
uint32_t keylen, switch_event_t **v_event, const char *is_nat, sofia_private_t **sofia_private_p, switch_xml_t *user_xml);
extern switch_endpoint_interface_t *sofia_endpoint_interface;
void sofia_presence_set_chat_hash(private_object_t *tech_pvt, sip_t const *sip);
switch_status_t sofia_on_hangup(switch_core_session_t *session);
+28 -14
View File
@@ -1108,7 +1108,7 @@ static void our_sofia_event_callback(nua_event_t event,
sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), NULL);
auth_res = sofia_reg_parse_auth(profile, authorization, sip, de,
(char *) sip->sip_request->rq_method_name, tech_pvt->key, strlen(tech_pvt->key), network_ip, NULL, 0,
REG_INVITE, NULL, NULL, NULL);
REG_INVITE, NULL, NULL, NULL, NULL);
}
if ((auth_res != AUTH_OK && auth_res != AUTH_RENEWED)) {
@@ -2946,8 +2946,9 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
sofia_gateway_t *gateway;
char *pkey = switch_mprintf("%s::%s", profile->name, name);
if (zstr(name)) {
name = "anonymous";
if (zstr(name) || switch_regex_match(name, "^[\\w\\.\\-\\_]+$") != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring invalid name '%s'\n", name ? name : "NULL");
goto skip;
}
switch_mutex_lock(mod_sofia_globals.hash_mutex);
@@ -5794,6 +5795,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_channel_get_name(channel), nua_callstate_name(ss_state), status);
if (r_sdp) {
switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
if (!(profile->mndlb & SM_NDLB_ALLOW_NONDUP_SDP) || (!zstr(tech_pvt->mparams.remote_sdp_str) && !strcmp(tech_pvt->mparams.remote_sdp_str, r_sdp))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Duplicate SDP\n%s\n", r_sdp);
@@ -5801,7 +5803,6 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote SDP:\n%s\n", r_sdp);
tech_pvt->mparams.remote_sdp_str = switch_core_session_strdup(session, r_sdp);
switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
if ((sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) {
switch_core_media_set_sdp_codec_string(session, r_sdp);
@@ -7762,6 +7763,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
char network_ip[80];
char proxied_client_ip[80];
switch_event_t *v_event = NULL;
switch_xml_t x_user = NULL;
uint32_t sess_count = switch_core_session_count();
uint32_t sess_max = switch_core_session_limit(0);
int is_auth = 0, calling_myself = 0;
@@ -7999,10 +8001,13 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
if (!strcmp(network_ip, profile->sipip) && network_port == profile->sip_port) {
calling_myself++;
} else {
if (sofia_reg_handle_register(nua, profile, nh, sip, de, REG_INVITE, key, sizeof(key), &v_event, NULL, NULL)) {
if (sofia_reg_handle_register(nua, profile, nh, sip, de, REG_INVITE, key, sizeof(key), &v_event, NULL, NULL, &x_user)) {
if (v_event) {
switch_event_destroy(&v_event);
}
if (x_user) {
switch_xml_free(x_user);
}
if (sip->sip_authorization || sip->sip_proxy_authorization) {
goto fail;
@@ -8085,15 +8090,6 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
switch_channel_set_variable(channel, "sip_looped_call", "true");
}
if (v_event) {
switch_event_header_t *hp;
for (hp = v_event->headers; hp; hp = hp->next) {
switch_channel_set_variable(channel, hp->name, hp->value);
}
switch_event_destroy(&v_event);
}
if (sip->sip_from && sip->sip_from->a_url) {
from_user = sip->sip_from->a_url->url_user;
from_host = sip->sip_from->a_url->url_host;
@@ -8840,6 +8836,24 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
}
if (x_user) {
const char *user = NULL, *domain = NULL;
if (v_event) {
user = switch_event_get_header(v_event, "username");
domain = switch_event_get_header(v_event, "domain_name");
}
switch_ivr_set_user_xml(session, NULL, user, domain, x_user);
switch_xml_free(x_user);
x_user = NULL;
}
if (v_event) {
switch_event_destroy(&v_event);
}
tech_pvt->sofia_private = sofia_private;
tech_pvt->nh = nh;
+2 -2
View File
@@ -4475,8 +4475,8 @@ void sofia_presence_handle_sip_i_message(int status,
sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), NULL);
auth_res = sofia_reg_parse_auth(profile, authorization, sip, de,
(char *) sip->sip_request->rq_method_name, key, keylen, network_ip, NULL, 0,
REG_INVITE, NULL, NULL, NULL);
} else if ( sofia_reg_handle_register(nua, profile, nh, sip, de, REG_INVITE, key, keylen, &v_event, NULL, NULL)) {
REG_INVITE, NULL, NULL, NULL, NULL);
} else if ( sofia_reg_handle_register(nua, profile, nh, sip, de, REG_INVITE, key, keylen, &v_event, NULL, NULL, NULL)) {
if (v_event) {
switch_event_destroy(&v_event);
}
+19 -7
View File
@@ -1121,7 +1121,7 @@ void sofia_reg_close_handles(sofia_profile_t *profile)
uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
sofia_dispatch_event_t *de, sofia_regtype_t regtype, char *key,
uint32_t keylen, switch_event_t **v_event, const char *is_nat, sofia_private_t **sofia_private_p)
uint32_t keylen, switch_event_t **v_event, const char *is_nat, sofia_private_t **sofia_private_p, switch_xml_t *user_xml)
{
sip_to_t const *to = NULL;
sip_from_t const *from = NULL;
@@ -1135,6 +1135,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
const char *to_host = NULL;
char *mwi_account = NULL;
char *dup_mwi_account = NULL;
char *display_m = NULL;
char *mwi_user = NULL;
char *mwi_host = NULL;
char *var = NULL;
@@ -1320,11 +1321,17 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (to) {
display = to->a_display;
if (zstr(display)) {
display = "\"user\"";
display = "\"\"";
}
}
}
if (display && !strchr(display, '"')) {
display_m = switch_mprintf("\"%q\"", display);
display = display_m;
}
if (sip->sip_path) {
path_val = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_path);
path_encoded_len = (int)(strlen(path_val) * 3) + 1;
@@ -1392,7 +1399,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
const char *username = "unknown";
const char *realm = reg_host;
if ((auth_res = sofia_reg_parse_auth(profile, authorization, sip, de, sip->sip_request->rq_method_name,
key, keylen, network_ip, v_event, exptime, regtype, to_user, &auth_params, &reg_count)) == AUTH_STALE) {
key, keylen, network_ip, v_event, exptime, regtype, to_user, &auth_params, &reg_count, user_xml)) == AUTH_STALE) {
stale = 1;
}
@@ -2023,6 +2030,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
end:
switch_safe_free(display_m);
switch_safe_free(dup_mwi_account);
switch_safe_free(utmp);
@@ -2152,7 +2160,7 @@ void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_h
is_nat = NULL;
}
sofia_reg_handle_register(nua, profile, nh, sip, de, type, key, sizeof(key), &v_event, is_nat, sofia_private_p);
sofia_reg_handle_register(nua, profile, nh, sip, de, type, key, sizeof(key), &v_event, is_nat, sofia_private_p, NULL);
if (v_event) {
switch_event_destroy(&v_event);
@@ -2459,7 +2467,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
size_t nplen,
char *ip,
switch_event_t **v_event,
long exptime, sofia_regtype_t regtype, const char *to_user, switch_event_t **auth_params, long *reg_count)
long exptime, sofia_regtype_t regtype, const char *to_user, switch_event_t **auth_params, long *reg_count, switch_xml_t *user_xml)
{
int indexnum;
const char *cur;
@@ -2883,7 +2891,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
skip_auth:
if (first && (ret == AUTH_OK || ret == AUTH_RENEWED)) {
if (v_event) {
if (!v_event) {
switch_event_create_plain(v_event, SWITCH_EVENT_REQUEST_PARAMS);
}
@@ -3015,7 +3023,11 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
switch_event_destroy(&params);
if (user) {
switch_xml_free(user);
if (user_xml) {
*user_xml = user;
} else {
switch_xml_free(user);
}
}
switch_safe_free(input);
@@ -11,8 +11,10 @@
<param name="record-file-prefix" value="$${recordings_dir}/"/>
</record>
<!-- domain to use in from attribute of client messages -->
<!-- XMPP server domain -->
<domain name="$${rayo_domain_name}" shared-secret="ClueCon">
<!-- use this instead if you want secure XMPP client to server connections. Put .crt and .key file in freeswitch/certs -->
<!--domain name="$${rayo_domain_name}" shared-secret="ClueCon" cert="$${base_dir}/certs/$${rayo_domain_name}.crt" key="$${base_dir}/certs/$${rayo_domain_name}.key"-->
<!-- Listeners for new Rayo client connections -->
<!--listen type="c2s" port="5222" address="$${local_ip_v4}" acl="rayo-clients"/-->
@@ -39,8 +39,7 @@
#define IKS_NS_XMPP_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas"
#define IKS_NS_XMPP_STREAMS "http://etherx.jabber.org/streams"
#define IKS_NS_XMPP_DIALBACK "jabber:server:dialback"
#define IKS_NS_BIDI_FEATURE "urn:xmpp:features:bidi"
#define IKS_NS_BIDI "urn:xmpp:bidi"
#define IKS_NS_XMPP_TLS "urn:ietf:params:xml:ns:xmpp-tls"
struct xmpp_error {
const char *name;
+18 -8
View File
@@ -3079,6 +3079,8 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_
switch_xml_t l;
const char *shared_secret = switch_xml_attr_soft(domain, "shared-secret");
const char *name = switch_xml_attr_soft(domain, "name");
const char *cert = switch_xml_attr_soft(domain, "cert");
const char *key = switch_xml_attr_soft(domain, "key");
if (zstr(name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing <domain name=\"... failed to configure rayo server\n");
status = SWITCH_STATUS_FALSE;
@@ -3093,6 +3095,14 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_
globals.xmpp_context = xmpp_stream_context_create(name, shared_secret, on_xmpp_stream_ready, on_xmpp_stream_recv, on_xmpp_stream_destroy);
globals.server = rayo_server_create(name);
/* set up TLS */
if (!zstr(cert)) {
xmpp_stream_context_add_cert(globals.xmpp_context, cert);
}
if (!zstr(key)) {
xmpp_stream_context_add_key(globals.xmpp_context, key);
}
/* configure authorized users for this domain */
l = switch_xml_child(domain, "users");
if (l) {
@@ -3719,14 +3729,14 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_rayo_shutdown)
switch_event_unbind_callback(on_call_end_event);
switch_event_unbind_callback(route_mixer_event);
switch_core_hash_destroy(&globals.command_handlers);
switch_core_hash_destroy(&globals.event_handlers);
switch_core_hash_destroy(&globals.clients_roster);
switch_core_hash_destroy(&globals.actors);
switch_core_hash_destroy(&globals.destroy_actors);
switch_core_hash_destroy(&globals.actors_by_id);
switch_core_hash_destroy(&globals.dial_gateways);
switch_core_hash_destroy(&globals.cmd_aliases);
switch_core_hash_destroy(&globals.command_handlers);
switch_core_hash_destroy(&globals.event_handlers);
switch_core_hash_destroy(&globals.clients_roster);
switch_core_hash_destroy(&globals.actors);
switch_core_hash_destroy(&globals.destroy_actors);
switch_core_hash_destroy(&globals.actors_by_id);
switch_core_hash_destroy(&globals.dial_gateways);
switch_core_hash_destroy(&globals.cmd_aliases);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Module shutdown\n");
+76 -53
View File
@@ -29,6 +29,8 @@
#include <switch.h>
#include <iksemel.h>
#include <openssl/ssl.h>
#include "xmpp_streams.h"
#include "iks_helpers.h"
#include "sasl.h"
@@ -63,6 +65,10 @@ struct xmpp_stream_context {
int shutdown;
/** prevents context shutdown until all threads are finished */
switch_thread_rwlock_t *shutdown_rwlock;
/** path to cert PEM file */
const char *cert_pem_file;
/** path to key PEM file */
const char *key_pem_file;
};
/**
@@ -71,8 +77,8 @@ struct xmpp_stream_context {
enum xmpp_stream_state {
/** new connection */
XSS_CONNECT,
/** bidirectional comms established */
XSS_BIDI,
/** encrypted comms established */
XSS_SECURE,
/** remote party authenticated */
XSS_AUTHENTICATED,
/** client resource bound */
@@ -159,7 +165,7 @@ static const char *xmpp_stream_state_to_string(enum xmpp_stream_state state)
{
switch(state) {
case XSS_CONNECT: return "CONNECT";
case XSS_BIDI: return "BIDI";
case XSS_SECURE: return "SECURE";
case XSS_AUTHENTICATED: return "AUTHENTICATED";
case XSS_RESOURCE_BOUND: return "RESOURCE_BOUND";
case XSS_READY: return "READY";
@@ -358,6 +364,31 @@ static void xmpp_send_client_header_auth(struct xmpp_stream *stream)
free(header);
}
/**
* Send sasl + starttls reply to xmpp <stream>
* @param stream the xmpp stream
*/
static void xmpp_send_client_header_tls(struct xmpp_stream *stream)
{
if (stream->context->key_pem_file && stream->context->cert_pem_file) {
struct xmpp_stream_context *context = stream->context;
char *header = switch_mprintf(
"<stream:stream xmlns='"IKS_NS_CLIENT"' xmlns:db='"IKS_NS_XMPP_DIALBACK"'"
" from='%s' id='%s' xml:lang='en' version='1.0'"
" xmlns:stream='"IKS_NS_XMPP_STREAMS"'><stream:features>"
"<starttls xmlns='"IKS_NS_XMPP_TLS"'><required/></starttls>"
"<mechanisms xmlns='"IKS_NS_XMPP_SASL"'>"
"<mechanism>PLAIN</mechanism>"
"</mechanisms></stream:features>", context->domain, stream->id);
iks_send_raw(stream->parser, header);
free(header);
} else {
/* not set up for TLS, skip it */
stream->state = XSS_SECURE;
xmpp_send_client_header_auth(stream);
}
}
/**
* Send sasl reply to xmpp <stream>
* @param stream the xmpp stream
@@ -370,12 +401,6 @@ static void xmpp_send_server_header_auth(struct xmpp_stream *stream)
" from='%s' id='%s' xml:lang='en' version='1.0'"
" xmlns:stream='"IKS_NS_XMPP_STREAMS"'>"
"<stream:features>"
#if 0
"<bidi xmlns='"IKS_NS_BIDI_FEATURE"'/>"
"<mechanisms xmlns='"IKS_NS_XMPP_SASL"'>"
"<mechanism>PLAIN</mechanism>"
"</mechanisms>"
#endif
"</stream:features>",
context->domain, stream->id);
iks_send_raw(stream->parser, header);
@@ -417,6 +442,21 @@ static void xmpp_send_outbound_server_header(struct xmpp_stream *stream)
free(header);
}
/**
* Handle <starttls> message.
* @param the xmpp stream
* @param node the <starttls> packet
*/
static void on_stream_starttls(struct xmpp_stream *stream, iks *node)
{
/* wait for handshake to start */
if (iks_proceed_tls(stream->parser, stream->context->cert_pem_file, stream->context->key_pem_file, 1) == IKS_OK) {
stream->state = XSS_SECURE;
} else {
stream->state = XSS_ERROR;
}
}
/**
* Handle <auth> message. Only PLAIN supported.
* @param stream the xmpp stream
@@ -431,7 +471,7 @@ static void on_stream_auth(struct xmpp_stream *stream, iks *node)
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(stream->id), SWITCH_LOG_DEBUG, "%s, auth, state = %s\n", stream->jid, xmpp_stream_state_to_string(stream->state));
/* wrong state for authentication */
if (stream->state != XSS_BIDI) {
if (stream->state != XSS_SECURE) {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(stream->id), SWITCH_LOG_WARNING, "%s, auth UNEXPECTED, state = %s\n", stream->jid, xmpp_stream_state_to_string(stream->state));
/* on_auth unexpected error */
stream->state = XSS_ERROR;
@@ -486,38 +526,6 @@ static void on_stream_auth(struct xmpp_stream *stream, iks *node)
}
}
/**
* Handle <bidi> message.
* @param stream the xmpp stream
* @param node the <bidi> packet
*/
static void on_stream_bidi(struct xmpp_stream *stream, iks *node)
{
/* only allow bidi on s2s connections before auth */
if (stream->s2s) {
switch(stream->state) {
case XSS_CONNECT:
stream->state = XSS_BIDI;
break;
case XSS_BIDI:
case XSS_AUTHENTICATED:
case XSS_RESOURCE_BOUND:
case XSS_READY:
case XSS_SHUTDOWN:
case XSS_ERROR:
case XSS_DESTROY:
/* error */
stream->state = XSS_ERROR;
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(stream->id), SWITCH_LOG_INFO, "%s, bad state: %s\n", stream->jid, xmpp_stream_state_to_string(stream->state));
break;
}
} else {
/* error */
stream->state = XSS_ERROR;
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(stream->id), SWITCH_LOG_INFO, "%s, bidi not allowed from client\n", stream->jid);
}
}
/**
* Handle <iq><session> request
* @param stream the xmpp stream
@@ -606,7 +614,7 @@ static void on_stream_iq(struct xmpp_stream *stream, iks *iq)
struct xmpp_stream_context *context = stream->context;
switch(stream->state) {
case XSS_CONNECT:
case XSS_BIDI: {
case XSS_SECURE: {
iks *error = iks_new_error(iq, STANZA_ERROR_NOT_AUTHORIZED);
xmpp_stream_stanza_send(stream, error);
break;
@@ -689,7 +697,9 @@ static void on_client_stream_start(struct xmpp_stream *stream, iks *node)
switch (stream->state) {
case XSS_CONNECT:
case XSS_BIDI:
xmpp_send_client_header_tls(stream);
break;
case XSS_SECURE:
xmpp_send_client_header_auth(stream);
break;
case XSS_AUTHENTICATED:
@@ -960,7 +970,7 @@ static void on_outbound_server_stream_start(struct xmpp_stream *stream, iks *nod
/* strange... I expect IKS_NODE_STOP, this is a workaround. */
stream->state = XSS_DESTROY;
break;
case XSS_BIDI:
case XSS_SECURE:
case XSS_AUTHENTICATED:
case XSS_RESOURCE_BOUND:
case XSS_READY:
@@ -1001,7 +1011,7 @@ static void on_inbound_server_stream_start(struct xmpp_stream *stream, iks *node
case XSS_CONNECT:
xmpp_send_server_header_auth(stream);
break;
case XSS_BIDI:
case XSS_SECURE:
break;
case XSS_AUTHENTICATED: {
/* all set */
@@ -1075,8 +1085,8 @@ static int on_stream(void *user_data, int type, iks *node)
on_stream_presence(stream, node);
} else if (!strcmp("auth", name)) {
on_stream_auth(stream, node);
} else if (!strcmp("bidi", name)) {
on_stream_bidi(stream, node);
} else if (!strcmp("starttls", name)) {
on_stream_starttls(stream, node);
} else if (!strcmp("db:result", name)) {
on_stream_dialback_result(stream, node);
} else if (!strcmp("db:verify", name)) {
@@ -1194,6 +1204,7 @@ static void *SWITCH_THREAD_FUNC xmpp_stream_thread(switch_thread_t *thread, void
case IKS_OK:
err_count = 0;
break;
case IKS_NET_TLSFAIL:
case IKS_NET_RWERR:
case IKS_NET_NOCONN:
case IKS_NET_NOSOCK:
@@ -1291,11 +1302,6 @@ static struct xmpp_stream *xmpp_stream_init(struct xmpp_stream_context *context,
stream->incoming = incoming;
switch_queue_create(&stream->msg_queue, MAX_QUEUE_LEN, pool);
if (!stream->s2s) {
/* client is already bi-directional */
stream->state = XSS_BIDI;
}
/* set up XMPP stream parser */
stream->parser = iks_stream_new(stream->s2s ? IKS_NS_SERVER : IKS_NS_CLIENT, stream, on_stream);
@@ -1829,6 +1835,23 @@ void *xmpp_stream_get_private(struct xmpp_stream *stream)
return stream->user_private;
}
/**
* Add PEM cert file to stream for new SSL connections
*/
void xmpp_stream_context_add_cert(struct xmpp_stream_context *context, const char *cert_pem_file)
{
context->cert_pem_file = switch_core_strdup(context->pool, cert_pem_file);
}
/**
* Add PEM key file to stream for new SSL connections
*/
void xmpp_stream_context_add_key(struct xmpp_stream_context *context, const char *key_pem_file)
{
context->key_pem_file = switch_core_strdup(context->pool, key_pem_file);
}
/* For Emacs:
* Local Variables:
* mode:c
@@ -37,6 +37,8 @@ typedef void (* xmpp_stream_recv_callback)(struct xmpp_stream *stream, iks *stan
typedef void (* xmpp_stream_destroy_callback)(struct xmpp_stream *stream);
extern struct xmpp_stream_context *xmpp_stream_context_create(const char *domain, const char *domain_secret, xmpp_stream_ready_callback ready, xmpp_stream_recv_callback recv, xmpp_stream_destroy_callback destroy);
extern void xmpp_stream_context_add_cert(struct xmpp_stream_context *context, const char *cert_pem_file);
extern void xmpp_stream_context_add_key(struct xmpp_stream_context *context, const char *key_pem_file);
extern void xmpp_stream_context_add_user(struct xmpp_stream_context *context, const char *user, const char *password);
extern void xmpp_stream_context_dump(struct xmpp_stream_context *context, switch_stream_handle_t *stream);
extern void xmpp_stream_context_destroy(struct xmpp_stream_context *context);
@@ -257,6 +257,10 @@ int handle_systemStats(netsnmp_mib_handler *handler, netsnmp_handler_registratio
switch_core_session_ctl(SCSC_SPS, &int_val);
snmp_set_var_typed_integer(requests->requestvb, ASN_GAUGE, int_val);
break;
case SS_PEAK_SESSIONS_PER_SECOND:
switch_core_session_ctl(SCSC_SPS_PEAK, &int_val);
snmp_set_var_typed_integer(requests->requestvb, ASN_GAUGE, int_val);
break;
default:
snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid);
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
@@ -46,6 +46,7 @@
#define SS_CURRENT_CALLS 5
#define SS_SESSIONS_PER_SECOND 6
#define SS_MAX_SESSIONS_PER_SECOND 7
#define SS_PEAK_SESSIONS_PER_SECOND 8
/* .1.3.6.1.4.1.27880.1.9 */
#define CH_INDEX 1
+1 -1
View File
@@ -4814,7 +4814,7 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_
}
if (switch_event_create(&event, SWITCH_EVENT_DEVICE_STATE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-State-Name", drec->device_id);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-ID", drec->device_id);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-Device-State", switch_channel_device_state2str(drec->last_state));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-State", switch_channel_device_state2str(drec->state));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-Call-State", switch_channel_callstate2str(callstate));
+7
View File
@@ -88,6 +88,7 @@ static void send_heartbeat(void)
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count());
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Max-Sessions", "%u", switch_core_session_limit(0));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec", "%u", runtime.sps);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec-Max", "%u", runtime.sps_peak);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Since-Startup", "%" SWITCH_SIZE_T_FMT, switch_core_session_id() - 1);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Idle-CPU", "%f", switch_core_idle_cpu());
switch_event_fire(&event);
@@ -2477,6 +2478,12 @@ SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void *
case SCSC_LAST_SPS:
newintval = runtime.sps_last;
break;
case SCSC_SPS_PEAK:
if (oldintval == -1) {
runtime.sps_peak = 0;
}
newintval = runtime.sps_peak;
break;
case SCSC_MAX_DTMF_DURATION:
newintval = switch_core_max_dtmf_duration(oldintval);
break;
+12
View File
@@ -299,6 +299,18 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t
return ah->asr_interface->asr_get_results(ah, xmlstr, flags);
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags)
{
switch_assert(ah != NULL);
if (ah->asr_interface->asr_get_result_headers) {
return ah->asr_interface->asr_get_result_headers(ah, headers, flags);
} else {
/* Since this is not always implemented, return success if the function can't be called */
return SWITCH_STATUS_SUCCESS;
}
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_start_input_timers(switch_asr_handle_t *ah)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
+4 -3
View File
@@ -3792,14 +3792,15 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started\n", switch_channel_get_name(session->channel));
switch_core_session_refresh_video(session);
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
while (switch_channel_up_nosig(channel)) {
if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread paused\n", switch_channel_get_name(session->channel));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread paused. Echo is %s\n",
switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
switch_thread_cond_wait(mh->cond, mh->cond_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread resumed\n", switch_channel_get_name(session->channel));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread resumed Echo is %s\n",
switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
switch_core_session_refresh_video(session);
}
+12 -1
View File
@@ -2625,7 +2625,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(switch_core_session_t *
int scope = 0;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
char *app_uuid = uuid_str;
if ((app_uuid_var = switch_channel_get_variable(channel, "app_uuid"))) {
app_uuid = (char *)app_uuid_var;
switch_channel_set_variable(channel, "app_uuid", NULL);
@@ -2727,8 +2727,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(switch_core_session_t *
msg.string_array_arg[1] = expanded;
switch_core_session_receive_message(session, &msg);
if (switch_channel_test_flag(channel, CF_VIDEO)) {
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
switch_core_session_refresh_video(session);
}
application_interface->application_function(session, expanded);
if (switch_channel_test_flag(channel, CF_VIDEO)) {
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
switch_core_session_refresh_video(session);
}
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE) == SWITCH_STATUS_SUCCESS) {
const char *resp = switch_channel_get_variable(session->channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE);
switch_channel_event_set_data(session->channel, event);
+47 -71
View File
@@ -3190,36 +3190,18 @@ static const char *get_prefixed_str(char *buffer, size_t buffer_size, const char
return buffer;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *session, const char *data)
SWITCH_DECLARE(switch_status_t) switch_ivr_set_user_xml(switch_core_session_t *session, const char *prefix,
const char *user, const char *domain, switch_xml_t x_user)
{
switch_xml_t x_domain, xml = NULL, x_user, x_param, x_params, x_group = NULL;
char *user, *number_alias, *domain;
switch_xml_t x_params, x_param;
char *number_alias;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_FALSE;
char *prefix_buffer = NULL, *prefix;
char *prefix_buffer = NULL;
size_t buffer_size = 0;
size_t prefix_size = 0;
if (zstr(data)) {
goto error;
}
user = switch_core_session_strdup(session, data);
if ((prefix = strchr(user, ' '))) {
*prefix++ = 0;
}
if (!(domain = strchr(user, '@'))) {
goto error;
}
*domain++ = '\0';
if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, &x_group, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain);
goto done;
}
status = SWITCH_STATUS_SUCCESS;
@@ -3233,50 +3215,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *sessi
switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "number_alias"), number_alias);
}
if ((x_params = switch_xml_child(x_domain, "variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (var && val) {
switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, var), val);
}
}
}
if ((x_params = switch_xml_child(x_domain, "profile-variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (var && val) {
switch_channel_set_profile_var(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, var), val);
}
}
}
if (x_group && (x_params = switch_xml_child(x_group, "variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (var && val) {
switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, var), val);
}
}
}
if ((x_params = switch_xml_child(x_group, "profile-variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (var && val) {
switch_channel_set_profile_var(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, var), val);
}
}
}
if ((x_params = switch_xml_child(x_user, "variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *var = switch_xml_attr(x_param, "name");
@@ -3299,17 +3237,55 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *sessi
}
}
switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "user_name"), user);
switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "domain_name"), domain);
if (user && domain) {
switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "user_name"), user);
switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "domain_name"), domain);
}
return status;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *session, const char *data)
{
switch_xml_t x_user;
char *user, *domain;
switch_status_t status = SWITCH_STATUS_FALSE;
char *prefix;
if (zstr(data)) {
goto error;
}
user = switch_core_session_strdup(session, data);
if ((prefix = strchr(user, ' '))) {
*prefix++ = 0;
}
if (!(domain = strchr(user, '@'))) {
goto error;
}
*domain++ = '\0';
if (switch_xml_locate_user_merged("id", user, domain, NULL, &x_user, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain);
goto done;
}
status = switch_ivr_set_user_xml(session, prefix, user, domain, x_user);
goto done;
error:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No user@domain specified.\n");
done:
if (xml) {
switch_xml_free(xml);
if (x_user) {
switch_xml_free(x_user);
}
return status;
+57 -27
View File
@@ -3791,6 +3791,7 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj
while (switch_channel_up_nosig(channel) && !switch_test_flag(sth->ah, SWITCH_ASR_FLAG_CLOSED)) {
char *xmlstr = NULL;
switch_event_t *headers = NULL;
switch_thread_cond_wait(sth->cond, sth->mutex);
@@ -3804,6 +3805,9 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
goto done;
} else if (status == SWITCH_STATUS_SUCCESS) {
/* Try to fetch extra information for this result, the return value doesn't really matter here - it's just optional data. */
switch_core_asr_get_result_headers(sth->ah, &headers, &flags);
}
if (status == SWITCH_STATUS_SUCCESS && switch_true(switch_channel_get_variable(channel, "asr_intercept_dtmf"))) {
@@ -3853,6 +3857,11 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj
if (switch_event_create(&event, SWITCH_EVENT_DETECTED_SPEECH) == SWITCH_STATUS_SUCCESS) {
if (status == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Speech-Type", "detected-speech");
if (headers) {
switch_event_merge(event, headers);
}
switch_event_add_body(event, "%s", xmlstr);
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Speech-Type", "begin-speaking");
@@ -3876,6 +3885,10 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj
}
switch_safe_free(xmlstr);
if (headers) {
switch_event_destroy(&headers);
}
}
}
done:
@@ -4121,9 +4134,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_disable_all_grammars(sw
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session,
const char *mod_name,
const char *grammar, const char *name, const char *dest, switch_asr_handle_t *ah)
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_init(switch_core_session_t *session, const char *mod_name,
const char *dest, switch_asr_handle_t *ah)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status;
@@ -4133,9 +4145,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *
const char *p;
char key[512] = "";
switch_core_session_get_read_impl(session, &read_impl);
switch_snprintf(key, sizeof(key), "%s/%s/%s/%s", mod_name, grammar, name, dest);
if (sth) {
/* Already initialized */
return SWITCH_STATUS_SUCCESS;
}
if (!ah) {
if (!(ah = switch_core_session_alloc(session, sizeof(*ah)))) {
@@ -4143,32 +4156,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *
}
}
if (sth) {
if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
switch_ivr_stop_detect_speech(session);
return SWITCH_STATUS_FALSE;
}
if ((p = switch_channel_get_variable(channel, "fire_asr_events")) && switch_true(p)) {
switch_set_flag(sth->ah, SWITCH_ASR_FLAG_FIRE_EVENTS);
}
return SWITCH_STATUS_SUCCESS;
}
switch_core_session_get_read_impl(session, &read_impl);
if ((status = switch_core_asr_open(ah,
mod_name,
"L16",
read_impl.actual_samples_per_second, dest, &flags,
switch_core_session_get_pool(session))) == SWITCH_STATUS_SUCCESS) {
if (switch_core_asr_load_grammar(ah, grammar, name) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
switch_core_asr_close(ah, &flags);
return SWITCH_STATUS_FALSE;
}
} else {
switch_core_session_get_pool(session))) != SWITCH_STATUS_SUCCESS) {
return status;
}
@@ -4181,6 +4175,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *
switch_set_flag(ah, SWITCH_ASR_FLAG_FIRE_EVENTS);
}
switch_snprintf(key, sizeof(key), "%s/%s/%s/%s", mod_name, NULL, NULL, dest);
if ((status = switch_core_media_bug_add(session, "detect_speech", key,
speech_callback, sth, 0, SMBF_READ_STREAM | SMBF_NO_PAUSE, &sth->bug)) != SWITCH_STATUS_SUCCESS) {
switch_core_asr_close(ah, &flags);
@@ -4197,6 +4193,40 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session,
const char *mod_name,
const char *grammar, const char *name, const char *dest, switch_asr_handle_t *ah)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status;
struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
const char *p;
if (!sth) {
/* No speech thread handle available yet, init speech detection first. */
if ((status = switch_ivr_detect_speech_init(session, mod_name, dest, ah)) != SWITCH_STATUS_SUCCESS) {
return status;
}
/* Fetch the new speech thread handle */
if (!(sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
return SWITCH_STATUS_FALSE;
}
}
if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n");
switch_ivr_stop_detect_speech(session);
return SWITCH_STATUS_FALSE;
}
if ((p = switch_channel_get_variable(channel, "fire_asr_events")) && switch_true(p)) {
switch_set_flag(sth->ah, SWITCH_ASR_FLAG_FIRE_EVENTS);
}
return SWITCH_STATUS_SUCCESS;
}
struct hangup_helper {
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
switch_bool_t bleg;
+10
View File
@@ -1676,6 +1676,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_sess
*cause = SWITCH_CAUSE_NO_ANSWER;
}
if (channel) {
if (*cause == SWITCH_CAUSE_SUCCESS) {
switch_channel_set_variable(channel, "originate_disposition", "success");
} else {
switch_channel_set_variable(channel, "originate_disposition", "failure");
switch_channel_set_variable(channel, "hangup_cause", switch_channel_cause2str(*cause));
}
}
if (var_event && var_event != ovars) {
switch_event_destroy(&var_event);
}
+47 -13
View File
@@ -54,7 +54,7 @@
#include <switch_version.h>
#include <switch_ssl.h>
#define FIR_COUNTDOWN 100
#define FIR_COUNTDOWN 50
#define READ_INC(rtp_session) switch_mutex_lock(rtp_session->read_mutex); rtp_session->reading++
#define READ_DEC(rtp_session) switch_mutex_unlock(rtp_session->read_mutex); rtp_session->reading--
@@ -270,6 +270,12 @@ typedef struct ts_normalize_s {
uint32_t last_frame;
uint32_t ts;
uint32_t delta;
uint32_t delta_ct;
uint32_t delta_ttl;
uint32_t delta_avg;
uint32_t delta_delta;
double delta_percent;
uint8_t m;
} ts_normalize_t;
struct switch_rtp {
@@ -3349,6 +3355,10 @@ SWITCH_DECLARE(void) switch_rtp_break(switch_rtp_t *rtp_session)
return;
}
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
return;
}
switch_mutex_lock(rtp_session->flag_mutex);
rtp_session->flags[SWITCH_RTP_FLAG_BREAK] = 1;
@@ -4247,15 +4257,6 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
return SWITCH_STATUS_SUCCESS;
}
if (*bytes && rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
unsigned int diff = ts - rtp_session->last_read_ts;
if (abs(diff) > 10000) {
switch_rtp_video_refresh(rtp_session);
}
}
if (ts) {
rtp_session->last_read_ts = ts;
}
@@ -4645,7 +4646,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
goto end;
}
// This is dumb
switch_rtp_video_refresh(rtp_session);
//switch_rtp_video_refresh(rtp_session);
goto rtcp;
}
}
@@ -4712,7 +4713,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
has_rtcp = 0;
} else if (rtp_session->rtcp_read_pollfd) {
rtcp_poll_status = switch_poll(rtp_session->rtcp_read_pollfd, 1, &rtcp_fdr, 0);
}
@@ -5272,7 +5273,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
}
if (rtp_session->fir_countdown) {
if (--rtp_session->fir_countdown == 0) {
rtp_session->fir_countdown--;
if (rtp_session->fir_countdown == FIR_COUNTDOWN / 2 || rtp_session->fir_countdown == 0) {
send_fir(rtp_session);
//send_pli(rtp_session);
}
@@ -5483,6 +5486,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
if (!rtp_session->ts_norm.last_ssrc || send_msg->header.ssrc != rtp_session->ts_norm.last_ssrc) {
if (rtp_session->ts_norm.last_ssrc) {
rtp_session->ts_norm.m = 1;
rtp_session->ts_norm.delta_ct = 1;
rtp_session->ts_norm.delta_ttl = 0;
if (rtp_session->ts_norm.delta) {
rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
}
@@ -5494,12 +5500,40 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
if (ntohl(send_msg->header.ts) != rtp_session->ts_norm.last_frame) {
rtp_session->ts_norm.delta = ntohl(send_msg->header.ts) - rtp_session->ts_norm.last_frame;
if (rtp_session->ts_norm.delta > 0) {
rtp_session->ts_norm.delta_ct++;
if (rtp_session->ts_norm.delta_ct == 1000) {
rtp_session->ts_norm.delta_ct = 1;
rtp_session->ts_norm.delta_ttl = 0;
}
rtp_session->ts_norm.delta_ttl += rtp_session->ts_norm.delta;
rtp_session->ts_norm.delta_avg = rtp_session->ts_norm.delta_ttl / rtp_session->ts_norm.delta_ct;
rtp_session->ts_norm.delta_delta = abs(rtp_session->ts_norm.delta_avg - rtp_session->ts_norm.delta);
rtp_session->ts_norm.delta_percent = (double)((double)rtp_session->ts_norm.delta / (double)rtp_session->ts_norm.delta_avg) * 100.0f;
if (rtp_session->ts_norm.delta_ct > 50 && rtp_session->ts_norm.delta_percent > 125.0) {
//printf("%s diff %d %d (%.2f)\n", switch_core_session_get_name(rtp_session->session),
//rtp_session->ts_norm.delta, rtp_session->ts_norm.delta_avg, rtp_session->ts_norm.delta_percent);
switch_rtp_video_refresh(rtp_session);
}
}
rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
}
rtp_session->ts_norm.last_frame = ntohl(send_msg->header.ts);
send_msg->header.ts = htonl(rtp_session->ts_norm.ts);
/* wait for a marked frame since we just switched streams */
if (rtp_session->ts_norm.m) {
if (send_msg->header.m) {
rtp_session->ts_norm.m = 0;
} else {
send = 0;
}
}
}
send_msg->header.ssrc = htonl(rtp_session->ssrc);
+4
View File
@@ -1008,6 +1008,10 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
}
switch_mutex_lock(runtime.throttle_mutex);
runtime.sps_last = runtime.sps_total - runtime.sps;
if (runtime.sps_last > runtime.sps_peak) {
runtime.sps_peak = runtime.sps_last;
}
runtime.sps = runtime.sps_total;
switch_mutex_unlock(runtime.throttle_mutex);
tick = 0;
+2
View File
@@ -1919,8 +1919,10 @@ SWITCH_DECLARE(void) switch_xml_merge_user(switch_xml_t user, switch_xml_t domai
do_merge(user, group, "params", "param");
do_merge(user, group, "variables", "variable");
do_merge(user, group, "profile-variables", "variable");
do_merge(user, domain, "params", "param");
do_merge(user, domain, "variables", "variable");
do_merge(user, domain, "profile-variables", "variable");
}
SWITCH_DECLARE(uint32_t) switch_xml_clear_user_cache(const char *key, const char *user_name, const char *domain_name)