Bug Summary

File:src/mod/applications/mod_spandsp/mod_spandsp_fax.c
Location:line 1988, column 3
Description:Value stored to 'write_fd' is never read

Annotated Source Code

1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH mod_fax.
18 *
19 * The Initial Developer of the Original Code is
20 * Massimo Cetra <devel@navynet.it>
21 *
22 * Portions created by the Initial Developer are Copyright (C)
23 * the Initial Developer. All Rights Reserved.
24 *
25 * Contributor(s):
26 *
27 * Brian West <brian@freeswitch.org>
28 * Anthony Minessale II <anthm@freeswitch.org>
29 * Steve Underwood <steveu@coppice.org>
30 * Antonio Gallo <agx@linux.it>
31 * mod_spandsp_fax.c -- Fax applications provided by SpanDSP
32 *
33 */
34
35#include "mod_spandsp.h"
36
37#include "udptl.h"
38
39#define LOCAL_FAX_MAX_DATAGRAM400 400
40#define MAX_FEC_ENTRIES4 4
41#define MAX_FEC_SPAN4 4
42#define DEFAULT_FEC_ENTRIES3 3
43#define DEFAULT_FEC_SPAN3 3
44
45#define SPANDSP_EVENT_TXFAXRESULT"spandsp::txfaxresult" "spandsp::txfaxresult"
46#define SPANDSP_EVENT_RXFAXRESULT"spandsp::rxfaxresult" "spandsp::rxfaxresult"
47
48#define SPANDSP_EVENT_TXFAXPAGERESULT"spandsp::txfaxpageresult" "spandsp::txfaxpageresult"
49#define SPANDSP_EVENT_RXFAXPAGERESULT"spandsp::rxfaxpageresult" "spandsp::rxfaxpageresult"
50
51#define SPANDSP_EVENT_TXFAXNEGOCIATERESULT"spandsp::txfaxnegociateresult" "spandsp::txfaxnegociateresult"
52#define SPANDSP_EVENT_RXFAXNEGOCIATERESULT"spandsp::rxfaxnegociateresult" "spandsp::rxfaxnegociateresult"
53
54
55/*****************************************************************************
56 OUR DEFINES AND STRUCTS
57*****************************************************************************/
58
59typedef enum {
60 T38_MODE,
61 AUDIO_MODE,
62 T38_GATEWAY_MODE
63} transport_mode_t;
64
65typedef enum {
66 T38_MODE_UNKNOWN = 0,
67 T38_MODE_NEGOTIATED = 1,
68 T38_MODE_REQUESTED = 2,
69 T38_MODE_REFUSED = -1,
70} t38_mode_t;
71
72
73struct pvt_s {
74 switch_core_session_t *session;
75
76 mod_spandsp_fax_application_mode_t app_mode;
77
78 t30_state_t *t30;
79 fax_state_t *fax_state;
80 t38_terminal_state_t *t38_state;
81 t38_gateway_state_t *t38_gateway_state;
82 t38_core_state_t *t38_core;
83
84 udptl_state_t *udptl_state;
85
86 char *filename;
87 char *ident;
88 char *header;
89 char *timezone;
90
91 int use_ecm;
92 int disable_v17;
93 int enable_tep;
94 int enable_colour_fax;
95 int enable_image_resizing;
96 int enable_colour_to_bilevel;
97 int enable_grayscale_to_bilevel;
98 int verbose;
99 int caller;
100
101 int tx_page_start;
102 int tx_page_end;
103
104 int done;
105
106 t38_mode_t t38_mode;
107
108 struct pvt_s *next;
109};
110
111typedef struct pvt_s pvt_t;
112
113static void launch_timer_thread(void);
114
115static struct {
116 pvt_t *head;
117 switch_mutex_t *mutex;
118 switch_thread_t *thread;
119 int thread_running;
120} t38_state_list;
121
122
123
124static void wake_thread(int force)
125{
126 if (force) {
127 switch_thread_cond_signal(spandsp_globals.cond);
128 return;
129 }
130
131 if (switch_mutex_trylock(spandsp_globals.cond_mutex) == SWITCH_STATUS_SUCCESS) {
132 switch_thread_cond_signal(spandsp_globals.cond);
133 switch_mutex_unlock(spandsp_globals.cond_mutex);
134 }
135}
136
137static int add_pvt(pvt_t *pvt)
138{
139 int r = 0;
140
141 if (t38_state_list.thread_running) {
142 switch_mutex_lock(t38_state_list.mutex);
143 pvt->next = t38_state_list.head;
144 t38_state_list.head = pvt;
145 switch_mutex_unlock(t38_state_list.mutex);
146 r = 1;
147 wake_thread(0);
148 } else {
149 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_spandsp_fax.c", (const char *)__func__
, 149, ((void*)0)
, SWITCH_LOG_CRIT, "Error launching thread\n");
150 }
151
152 return r;
153
154}
155
156
157static int del_pvt(pvt_t *del_pvt)
158{
159 pvt_t *p, *l = NULL((void*)0);
160 int r = 0;
161
162
163 switch_mutex_lock(t38_state_list.mutex);
164
165 for (p = t38_state_list.head; p; p = p->next) {
166 if (p == del_pvt) {
167 if (l) {
168 l->next = p->next;
169 } else {
170 t38_state_list.head = p->next;
171 }
172 p->next = NULL((void*)0);
173 r = 1;
174 break;
175 }
176
177 l = p;
178 }
179
180 switch_mutex_unlock(t38_state_list.mutex);
181
182 wake_thread(0);
183
184 return r;
185}
186
187static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *obj)
188{
189 switch_timer_t timer = { 0 };
190 pvt_t *pvt;
191 int samples = 160;
192 int ms = 20;
193
194 switch_mutex_lock(t38_state_list.mutex);
195 t38_state_list.thread_running = 1;
196 switch_mutex_unlock(t38_state_list.mutex);
197
198 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_spandsp_fax.c", (const char *)__func__
, 198, ((void*)0)
, SWITCH_LOG_DEBUG, "FAX timer thread started.\n");
199
200 if (switch_core_timer_init(&timer, "soft", ms, samples, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
201 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_spandsp_fax.c", (const char *)__func__
, 201, ((void*)0)
, SWITCH_LOG_CRIT, "timer init failed.\n");
202 goto end;
203 }
204
205 switch_mutex_lock(spandsp_globals.cond_mutex);
206
207 while(t38_state_list.thread_running) {
208
209 switch_mutex_lock(t38_state_list.mutex);
210
211 if (!t38_state_list.head) {
212 switch_mutex_unlock(t38_state_list.mutex);
213 switch_thread_cond_wait(spandsp_globals.cond, spandsp_globals.cond_mutex);
214 switch_core_timer_sync(&timer);
215 continue;
216 }
217
218 for (pvt = t38_state_list.head; pvt; pvt = pvt->next) {
219 if (pvt->udptl_state && pvt->session && switch_channel_ready(switch_core_session_get_channel(pvt->session))switch_channel_test_ready(switch_core_session_get_channel(pvt
->session), SWITCH_TRUE, SWITCH_FALSE)
) {
220 t38_terminal_send_timeout(pvt->t38_state, samples);
221 }
222 }
223
224 switch_mutex_unlock(t38_state_list.mutex);
225
226 switch_core_timer_next(&timer);
227 }
228
229 switch_mutex_unlock(spandsp_globals.cond_mutex);
230
231 end:
232
233 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_spandsp_fax.c", (const char *)__func__
, 233, ((void*)0)
, SWITCH_LOG_DEBUG, "FAX timer thread ended.\n");
234
235 switch_mutex_lock(t38_state_list.mutex);
236 t38_state_list.thread_running = 0;
237 switch_mutex_unlock(t38_state_list.mutex);
238
239 if (timer.timer_interface) {
240 switch_core_timer_destroy(&timer);
241 }
242
243 return NULL((void*)0);
244}
245
246static void launch_timer_thread(void)
247{
248
249 switch_threadattr_t *thd_attr = NULL((void*)0);
250
251 switch_threadattr_create(&thd_attr, spandsp_globals.pool);
252 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024);
253 switch_thread_create(&t38_state_list.thread, thd_attr, timer_thread_run, NULL((void*)0), spandsp_globals.pool);
254}
255
256
257/*****************************************************************************
258 LOGGING AND HELPER FUNCTIONS
259*****************************************************************************/
260
261static void counter_increment(void)
262{
263 switch_mutex_lock(spandsp_globals.mutex);
264 spandsp_globals.total_sessions++;
265 switch_mutex_unlock(spandsp_globals.mutex);
266}
267
268void mod_spandsp_log_message(void *user_data, int level, const char *msg)
269{
270 int fs_log_level;
271 switch_core_session_t *session = (switch_core_session_t *)user_data;
272
273 switch (level) {
274 case SPAN_LOG_NONE:
275 return;
276 case SPAN_LOG_ERROR:
277 case SPAN_LOG_PROTOCOL_ERROR:
278 fs_log_level = SWITCH_LOG_ERROR;
279 break;
280 case SPAN_LOG_WARNING:
281 case SPAN_LOG_PROTOCOL_WARNING:
282 fs_log_level = SWITCH_LOG_WARNING;
283 break;
284 case SPAN_LOG_FLOW:
285 case SPAN_LOG_FLOW_2:
286 case SPAN_LOG_FLOW_3:
287 default: /* SPAN_LOG_DEBUG, SPAN_LOG_DEBUG_2, SPAN_LOG_DEBUG_3 */
288 fs_log_level = SWITCH_LOG_DEBUG;
289 break;
290 }
291
292 if (!zstr(msg)_zstr(msg)) {
293 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 293, (const char*)(session)
, fs_log_level, "%s", msg);
294 }
295}
296
297static int phase_b_handler(void *user_data, int result)
298{
299 t30_stats_t t30_stats;
300 switch_core_session_t *session;
301 switch_channel_t *channel;
302 const char *local_ident;
303 const char *far_ident;
304 char *fax_transfer_rate = NULL((void*)0);
305 pvt_t *pvt;
306 switch_event_t *event;
307
308 pvt = (pvt_t *) user_data;
309 switch_assert(pvt)((pvt) ? (void) (0) : __assert_fail ("pvt", "mod_spandsp_fax.c"
, 309, __PRETTY_FUNCTION__))
;
310
311 session = pvt->session;
312 switch_assert(session)((session) ? (void) (0) : __assert_fail ("session", "mod_spandsp_fax.c"
, 312, __PRETTY_FUNCTION__))
;
313
314 channel = switch_core_session_get_channel(session);
315 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "mod_spandsp_fax.c"
, 315, __PRETTY_FUNCTION__))
;
316
317 t30_get_transfer_statistics(pvt->t30, &t30_stats);
318
319 local_ident = switch_str_nil(t30_get_tx_ident(pvt->t30))(t30_get_tx_ident(pvt->t30) ? t30_get_tx_ident(pvt->t30
) : "")
;
320 far_ident = switch_str_nil(t30_get_rx_ident(pvt->t30))(t30_get_rx_ident(pvt->t30) ? t30_get_rx_ident(pvt->t30
) : "")
;
321
322 fax_transfer_rate = switch_core_session_sprintf(session, "%i", t30_stats.bit_rate);
323 if (fax_transfer_rate) {
324 switch_channel_set_variable(channel, "fax_transfer_rate", fax_transfer_rate)switch_channel_set_variable_var_check(channel, "fax_transfer_rate"
, fax_transfer_rate, SWITCH_TRUE)
;
325 }
326 switch_channel_set_variable(channel, "fax_ecm_used", (t30_stats.error_correcting_mode) ? "on" : "off")switch_channel_set_variable_var_check(channel, "fax_ecm_used"
, (t30_stats.error_correcting_mode) ? "on" : "off", SWITCH_TRUE
)
;
327 switch_channel_set_variable(channel, "fax_local_station_id", local_ident)switch_channel_set_variable_var_check(channel, "fax_local_station_id"
, local_ident, SWITCH_TRUE)
;
328 switch_channel_set_variable(channel, "fax_remote_station_id", far_ident)switch_channel_set_variable_var_check(channel, "fax_remote_station_id"
, far_ident, SWITCH_TRUE)
;
329 switch_channel_set_variable(channel, "fax_remote_country", switch_str_nil(t30_get_rx_country(pvt->t30)))switch_channel_set_variable_var_check(channel, "fax_remote_country"
, (t30_get_rx_country(pvt->t30) ? t30_get_rx_country(pvt->
t30) : ""), SWITCH_TRUE)
;
330 switch_channel_set_variable(channel, "fax_remote_vendor", switch_str_nil(t30_get_rx_vendor(pvt->t30)))switch_channel_set_variable_var_check(channel, "fax_remote_vendor"
, (t30_get_rx_vendor(pvt->t30) ? t30_get_rx_vendor(pvt->
t30) : ""), SWITCH_TRUE)
;
331 switch_channel_set_variable(channel, "fax_remote_model", switch_str_nil(t30_get_rx_model(pvt->t30)))switch_channel_set_variable_var_check(channel, "fax_remote_model"
, (t30_get_rx_model(pvt->t30) ? t30_get_rx_model(pvt->t30
) : ""), SWITCH_TRUE)
;
332
333
334 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 334, (const char*)(session)
, SWITCH_LOG_DEBUG, "=== Negotiation Result =======================================================\n");
335 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 335, (const char*)(session)
, SWITCH_LOG_DEBUG, "Remote station id: %s\n", far_ident);
336 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 336, (const char*)(session)
, SWITCH_LOG_DEBUG, "Local station id: %s\n", local_ident);
337 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 337, (const char*)(session)
, SWITCH_LOG_DEBUG, "Transfer Rate: %i\n", t30_stats.bit_rate);
338
339 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 339, (const char*)(session)
, SWITCH_LOG_DEBUG, "ECM status %s\n", (t30_stats.error_correcting_mode) ? "on" : "off");
340 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 340, (const char*)(session)
, SWITCH_LOG_DEBUG, "remote country: %s\n", switch_str_nil(t30_get_rx_country(pvt->t30))(t30_get_rx_country(pvt->t30) ? t30_get_rx_country(pvt->
t30) : "")
);
341 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 341, (const char*)(session)
, SWITCH_LOG_DEBUG, "remote vendor: %s\n", switch_str_nil(t30_get_rx_vendor(pvt->t30))(t30_get_rx_vendor(pvt->t30) ? t30_get_rx_vendor(pvt->t30
) : "")
);
342 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 342, (const char*)(session)
, SWITCH_LOG_DEBUG, "remote model: %s\n", switch_str_nil(t30_get_rx_model(pvt->t30))(t30_get_rx_model(pvt->t30) ? t30_get_rx_model(pvt->t30
) : "")
);
343
344 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 344, (const char*)(session)
, SWITCH_LOG_DEBUG, "==============================================================================\n");
345
346 switch_channel_execute_on(channel, "execute_on_fax_phase_b");
347
348 /* Fire event */
349
350 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXNEGOCIATERESULT : SPANDSP_EVENT_RXFAXNEGOCIATERESULT)switch_event_create_subclass_detailed("mod_spandsp_fax.c", (const
char * )(const char *)__func__, 350, &event, SWITCH_EVENT_CUSTOM
, pvt->app_mode == FUNCTION_TX ? "spandsp::txfaxnegociateresult"
: "spandsp::rxfaxnegociateresult")
== SWITCH_STATUS_SUCCESS) {
351 switch_channel_event_set_data(channel, event);
352
353 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", switch_core_session_get_uuid(session));
354 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-transfer-rate", fax_transfer_rate);
355 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-ecm-used", (t30_stats.error_correcting_mode) ? "on" : "off");
356 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-local-station-id", local_ident);
357 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-station-id", far_ident);
358 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-country", switch_str_nil(t30_get_rx_country(pvt->t30))(t30_get_rx_country(pvt->t30) ? t30_get_rx_country(pvt->
t30) : "")
);
359 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-vendor", switch_str_nil(t30_get_rx_vendor(pvt->t30))(t30_get_rx_vendor(pvt->t30) ? t30_get_rx_vendor(pvt->t30
) : "")
);
360 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-model", switch_str_nil(t30_get_rx_model(pvt->t30))(t30_get_rx_model(pvt->t30) ? t30_get_rx_model(pvt->t30
) : "")
);
361 switch_event_fire(&event)switch_event_fire_detailed("mod_spandsp_fax.c", (const char *
)(const char *)__func__, 361, &event, ((void*)0))
;
362 }
363
364 return T30_ERR_OK;
365}
366
367static int phase_d_handler(void *user_data, int msg)
368{
369 t30_stats_t t30_stats;
370 char *fax_file_image_resolution = NULL((void*)0);
371 char *fax_line_image_resolution = NULL((void*)0);
372 char *fax_file_image_pixel_size = NULL((void*)0);
373 char *fax_line_image_pixel_size = NULL((void*)0);
374 char *fax_image_size = NULL((void*)0);
375 char *fax_bad_rows = NULL((void*)0);
376 char *fax_encoding = NULL((void*)0);
377 char *fax_longest_bad_row_run = NULL((void*)0);
378 char *fax_document_transferred_pages = NULL((void*)0);
379 switch_core_session_t *session;
380 switch_channel_t *channel;
381 pvt_t *pvt;
382 switch_event_t *event;
383
384 pvt = (pvt_t *) user_data;
385 switch_assert(pvt)((pvt) ? (void) (0) : __assert_fail ("pvt", "mod_spandsp_fax.c"
, 385, __PRETTY_FUNCTION__))
;
386
387 session = pvt->session;
388 switch_assert(session)((session) ? (void) (0) : __assert_fail ("session", "mod_spandsp_fax.c"
, 388, __PRETTY_FUNCTION__))
;
389
390 channel = switch_core_session_get_channel(session);
391 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "mod_spandsp_fax.c"
, 391, __PRETTY_FUNCTION__))
;
392
393 t30_get_transfer_statistics(pvt->t30, &t30_stats);
394
395 /* Set Channel Variable */
396
397 fax_line_image_resolution = switch_core_session_sprintf(session, "%ix%i", t30_stats.x_resolution, t30_stats.y_resolution);
398 if (fax_line_image_resolution) {
399 switch_channel_set_variable(channel, "fax_image_resolution", fax_line_image_resolution)switch_channel_set_variable_var_check(channel, "fax_image_resolution"
, fax_line_image_resolution, SWITCH_TRUE)
;
400 }
401
402 fax_file_image_resolution = switch_core_session_sprintf(session, "%ix%i", t30_stats.image_x_resolution, t30_stats.image_y_resolution);
403 if (fax_file_image_resolution) {
404 switch_channel_set_variable(channel, "fax_file_image_resolution", fax_file_image_resolution)switch_channel_set_variable_var_check(channel, "fax_file_image_resolution"
, fax_file_image_resolution, SWITCH_TRUE)
;
405 }
406
407 fax_line_image_pixel_size = switch_core_session_sprintf(session, "%ix%i", t30_stats.width, t30_stats.length);
408 if (fax_line_image_pixel_size) {
409 switch_channel_set_variable(channel, "fax_image_pixel_size", fax_line_image_pixel_size)switch_channel_set_variable_var_check(channel, "fax_image_pixel_size"
, fax_line_image_pixel_size, SWITCH_TRUE)
;;
410 }
411
412 fax_file_image_pixel_size = switch_core_session_sprintf(session, "%ix%i", t30_stats.image_width, t30_stats.image_length);
413 if (fax_file_image_pixel_size) {
414 switch_channel_set_variable(channel, "fax_file_image_pixel_size", fax_file_image_pixel_size)switch_channel_set_variable_var_check(channel, "fax_file_image_pixel_size"
, fax_file_image_pixel_size, SWITCH_TRUE)
;;
415 }
416
417 fax_image_size = switch_core_session_sprintf(session, "%d", t30_stats.image_size);
418 if (fax_image_size) {
419 switch_channel_set_variable(channel, "fax_image_size", fax_image_size)switch_channel_set_variable_var_check(channel, "fax_image_size"
, fax_image_size, SWITCH_TRUE)
;
420 }
421
422 fax_bad_rows = switch_core_session_sprintf(session, "%d", t30_stats.bad_rows);
423 if (fax_bad_rows) {
424 switch_channel_set_variable(channel, "fax_bad_rows", fax_bad_rows)switch_channel_set_variable_var_check(channel, "fax_bad_rows"
, fax_bad_rows, SWITCH_TRUE)
;
425 }
426
427 fax_longest_bad_row_run = switch_core_session_sprintf(session, "%d", t30_stats.longest_bad_row_run);
428 if (fax_longest_bad_row_run) {
429 switch_channel_set_variable(channel, "fax_longest_bad_row_run", fax_longest_bad_row_run)switch_channel_set_variable_var_check(channel, "fax_longest_bad_row_run"
, fax_longest_bad_row_run, SWITCH_TRUE)
;
430 }
431
432 fax_encoding = switch_core_session_sprintf(session, "%d", t30_stats.compression);
433 if (fax_encoding) {
434 switch_channel_set_variable(channel, "fax_encoding", fax_encoding)switch_channel_set_variable_var_check(channel, "fax_encoding"
, fax_encoding, SWITCH_TRUE)
;
435 }
436
437 switch_channel_set_variable(channel, "fax_encoding_name", t4_compression_to_str(t30_stats.compression))switch_channel_set_variable_var_check(channel, "fax_encoding_name"
, t4_compression_to_str(t30_stats.compression), SWITCH_TRUE)
;
438
439 fax_document_transferred_pages = switch_core_session_sprintf(session, "%d", (pvt->app_mode == FUNCTION_TX) ? t30_stats.pages_tx : t30_stats.pages_rx);
440 if (fax_document_transferred_pages) {
441 switch_channel_set_variable(channel, "fax_document_transferred_pages", fax_document_transferred_pages)switch_channel_set_variable_var_check(channel, "fax_document_transferred_pages"
, fax_document_transferred_pages, SWITCH_TRUE)
;
442 }
443
444
445 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 445, (const char*)(session)
, SWITCH_LOG_DEBUG, "==== Page %s===========================================================\n", pvt->app_mode == FUNCTION_TX ? "Sent ====": "Received ");
446 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 446, (const char*)(session)
, SWITCH_LOG_DEBUG, "Page no = %d\n", (pvt->app_mode == FUNCTION_TX) ? t30_stats.pages_tx : t30_stats.pages_rx);
447 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 447, (const char*)(session)
, SWITCH_LOG_DEBUG, "Image type = %s (%s in the file)\n", t4_image_type_to_str(t30_stats.type), t4_image_type_to_str(t30_stats.image_type));
448 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 448, (const char*)(session)
, SWITCH_LOG_DEBUG, "Image size = %d x %d pixels (%d x %d pixels in the file)\n", t30_stats.width, t30_stats.length, t30_stats.image_width, t30_stats.image_length);
449 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 449, (const char*)(session)
, SWITCH_LOG_DEBUG, "Image resolution = %d/m x %d/m (%d/m x %d/m in the file)\n", t30_stats.x_resolution, t30_stats.y_resolution, t30_stats.image_x_resolution, t30_stats.image_y_resolution);
450 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 450, (const char*)(session)
, SWITCH_LOG_DEBUG, "Compression = %s (%d)\n", t4_compression_to_str(t30_stats.compression), t30_stats.compression);
451 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 451, (const char*)(session)
, SWITCH_LOG_DEBUG, "Compressed image size = %d bytes\n", t30_stats.image_size);
452 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 452, (const char*)(session)
, SWITCH_LOG_DEBUG, "Bad rows = %d\n", t30_stats.bad_rows);
453 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 453, (const char*)(session)
, SWITCH_LOG_DEBUG, "Longest bad row run = %d\n", t30_stats.longest_bad_row_run);
454 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 454, (const char*)(session)
, SWITCH_LOG_DEBUG, "==============================================================================\n");
455
456 switch_channel_execute_on(channel, "execute_on_fax_phase_d");
457
458 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXPAGERESULT : SPANDSP_EVENT_RXFAXPAGERESULT)switch_event_create_subclass_detailed("mod_spandsp_fax.c", (const
char * )(const char *)__func__, 458, &event, SWITCH_EVENT_CUSTOM
, pvt->app_mode == FUNCTION_TX ? "spandsp::txfaxpageresult"
: "spandsp::rxfaxpageresult")
== SWITCH_STATUS_SUCCESS) {
459 switch_channel_event_set_data(channel, event);
460
461 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", switch_core_session_get_uuid(session));
462 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-transferred-pages", fax_document_transferred_pages);
463 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_line_image_resolution);
464 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-file-image-resolution", fax_file_image_resolution);
465 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-size", fax_image_size);
466 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-pixel-size", fax_line_image_pixel_size);
467 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-file-image-pixel-size", fax_file_image_pixel_size);
468 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-bad-rows", fax_bad_rows);
469 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-longest-bad-row-run", fax_longest_bad_row_run);
470 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-encoding", fax_encoding);
471 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-encoding-name", t4_compression_to_str(t30_stats.compression));
472 switch_event_fire(&event)switch_event_fire_detailed("mod_spandsp_fax.c", (const char *
)(const char *)__func__, 472, &event, ((void*)0))
;
473 }
474
475 return T30_ERR_OK; /* I don't think this does anything */
476}
477
478/*
479 * Called at the end of the document
480 */
481static void phase_e_handler(void *user_data, int result)
482{
483 t30_stats_t t;
484 const char *local_ident;
485 const char *far_ident;
486 switch_core_session_t *session;
487 switch_channel_t *channel;
488 pvt_t *pvt;
489 char *fax_document_transferred_pages = NULL((void*)0);
490 char *fax_document_total_pages = NULL((void*)0);
491 char *fax_image_resolution = NULL((void*)0);
492 char *fax_image_size = NULL((void*)0);
493 char *fax_bad_rows = NULL((void*)0);
494 char *fax_transfer_rate = NULL((void*)0);
495 char *fax_result_code = NULL((void*)0);
496 switch_event_t *event;
497 const char *var;
498 char *expanded;
499
500 pvt = (pvt_t *) user_data;
501 switch_assert(pvt)((pvt) ? (void) (0) : __assert_fail ("pvt", "mod_spandsp_fax.c"
, 501, __PRETTY_FUNCTION__))
;
502
503 session = pvt->session;
504 switch_assert(session)((session) ? (void) (0) : __assert_fail ("session", "mod_spandsp_fax.c"
, 504, __PRETTY_FUNCTION__))
;
505
506 channel = switch_core_session_get_channel(session);
507 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "mod_spandsp_fax.c"
, 507, __PRETTY_FUNCTION__))
;
508
509 t30_get_transfer_statistics(pvt->t30, &t);
510 local_ident = switch_str_nil(t30_get_tx_ident(pvt->t30))(t30_get_tx_ident(pvt->t30) ? t30_get_tx_ident(pvt->t30
) : "")
;
511 far_ident = switch_str_nil(t30_get_rx_ident(pvt->t30))(t30_get_rx_ident(pvt->t30) ? t30_get_rx_ident(pvt->t30
) : "")
;
512
513 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 513, (const char*)(session)
, SWITCH_LOG_DEBUG, "==============================================================================\n");
514
515 if (result == T30_ERR_OK) {
516 if (pvt->app_mode == FUNCTION_TX) {
517 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 517, (const char*)(session)
, SWITCH_LOG_DEBUG, "Fax successfully sent.\n");
518 } else if (pvt->app_mode == FUNCTION_RX) {
519 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 519, (const char*)(session)
, SWITCH_LOG_DEBUG, "Fax successfully received.\n");
520 } else {
521 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 521, (const char*)(session)
, SWITCH_LOG_DEBUG, "Fax successfully managed. How ?\n");
522 }
523 switch_channel_set_variable(channel, "fax_success", "1")switch_channel_set_variable_var_check(channel, "fax_success",
"1", SWITCH_TRUE)
;
524 } else {
525 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 525, (const char*)(session)
, SWITCH_LOG_DEBUG, "Fax processing not successful - result (%d) %s.\n", result,
526 t30_completion_code_to_str(result));
527 switch_channel_set_variable(channel, "fax_success", "0")switch_channel_set_variable_var_check(channel, "fax_success",
"0", SWITCH_TRUE)
;
528 }
529
530 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 530, (const char*)(session)
, SWITCH_LOG_DEBUG, "Remote station id: %s\n", far_ident);
531 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 531, (const char*)(session)
, SWITCH_LOG_DEBUG, "Local station id: %s\n", local_ident);
532 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 532, (const char*)(session)
, SWITCH_LOG_DEBUG, "Pages transferred: %i\n",
533 pvt->app_mode == FUNCTION_TX ? t.pages_tx : t.pages_rx);
534 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 534, (const char*)(session)
, SWITCH_LOG_DEBUG, "Total fax pages: %i\n", t.pages_in_file);
535 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 535, (const char*)(session)
, SWITCH_LOG_DEBUG, "Image resolution: %ix%i\n", t.x_resolution, t.y_resolution);
536 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 536, (const char*)(session)
, SWITCH_LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate);
537
538 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 538, (const char*)(session)
, SWITCH_LOG_DEBUG, "ECM status %s\n", (t.error_correcting_mode) ? "on" : "off");
539 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 539, (const char*)(session)
, SWITCH_LOG_DEBUG, "remote country: %s\n", switch_str_nil(t30_get_rx_country(pvt->t30))(t30_get_rx_country(pvt->t30) ? t30_get_rx_country(pvt->
t30) : "")
);
540 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 540, (const char*)(session)
, SWITCH_LOG_DEBUG, "remote vendor: %s\n", switch_str_nil(t30_get_rx_vendor(pvt->t30))(t30_get_rx_vendor(pvt->t30) ? t30_get_rx_vendor(pvt->t30
) : "")
);
541 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 541, (const char*)(session)
, SWITCH_LOG_DEBUG, "remote model: %s\n", switch_str_nil(t30_get_rx_model(pvt->t30))(t30_get_rx_model(pvt->t30) ? t30_get_rx_model(pvt->t30
) : "")
);
542
543 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 543, (const char*)(session)
, SWITCH_LOG_DEBUG, "==============================================================================\n");
544
545 /*
546 Set our channel variables, variables are also used in event
547 */
548
549 fax_result_code = switch_core_session_sprintf(session, "%i", result);
550 if (fax_result_code) {
551 switch_channel_set_variable(channel, "fax_result_code", fax_result_code)switch_channel_set_variable_var_check(channel, "fax_result_code"
, fax_result_code, SWITCH_TRUE)
;
552 }
553
554 switch_channel_set_variable(channel, "fax_result_text", t30_completion_code_to_str(result))switch_channel_set_variable_var_check(channel, "fax_result_text"
, t30_completion_code_to_str(result), SWITCH_TRUE)
;
555
556 switch_channel_set_variable(channel, "fax_ecm_used", (t.error_correcting_mode) ? "on" : "off")switch_channel_set_variable_var_check(channel, "fax_ecm_used"
, (t.error_correcting_mode) ? "on" : "off", SWITCH_TRUE)
;
557 switch_channel_set_variable(channel, "fax_local_station_id", local_ident)switch_channel_set_variable_var_check(channel, "fax_local_station_id"
, local_ident, SWITCH_TRUE)
;
558 switch_channel_set_variable(channel, "fax_remote_station_id", far_ident)switch_channel_set_variable_var_check(channel, "fax_remote_station_id"
, far_ident, SWITCH_TRUE)
;
559
560 fax_document_transferred_pages = switch_core_session_sprintf(session, "%i", pvt->app_mode == FUNCTION_TX ? t.pages_tx : t.pages_rx);
561 if (fax_document_transferred_pages) {
562 switch_channel_set_variable(channel, "fax_document_transferred_pages", fax_document_transferred_pages)switch_channel_set_variable_var_check(channel, "fax_document_transferred_pages"
, fax_document_transferred_pages, SWITCH_TRUE)
;
563 }
564
565 fax_document_total_pages = switch_core_session_sprintf(session, "%i", t.pages_in_file);
566 if (fax_document_total_pages) {
567 switch_channel_set_variable(channel, "fax_document_total_pages", fax_document_total_pages)switch_channel_set_variable_var_check(channel, "fax_document_total_pages"
, fax_document_total_pages, SWITCH_TRUE)
;
568 }
569
570 fax_image_resolution = switch_core_session_sprintf(session, "%ix%i", t.x_resolution, t.y_resolution);
571 if (fax_image_resolution) {
572 switch_channel_set_variable(channel, "fax_image_resolution", fax_image_resolution)switch_channel_set_variable_var_check(channel, "fax_image_resolution"
, fax_image_resolution, SWITCH_TRUE)
;
573 }
574
575 fax_image_size = switch_core_session_sprintf(session, "%d", t.image_size);
576 if (fax_image_size) {
577 switch_channel_set_variable(channel, "fax_image_size", fax_image_size)switch_channel_set_variable_var_check(channel, "fax_image_size"
, fax_image_size, SWITCH_TRUE)
;
578 }
579
580 fax_bad_rows = switch_core_session_sprintf(session, "%d", t.bad_rows);
581 if (fax_bad_rows) {
582 switch_channel_set_variable(channel, "fax_bad_rows", fax_bad_rows)switch_channel_set_variable_var_check(channel, "fax_bad_rows"
, fax_bad_rows, SWITCH_TRUE)
;
583 }
584
585 fax_transfer_rate = switch_core_session_sprintf(session, "%i", t.bit_rate);
586 if (fax_transfer_rate) {
587 switch_channel_set_variable(channel, "fax_transfer_rate", fax_transfer_rate)switch_channel_set_variable_var_check(channel, "fax_transfer_rate"
, fax_transfer_rate, SWITCH_TRUE)
;
588 }
589
590 /* switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); */
591
592 pvt->done = 1;
593
594 /* Fire event */
595
596 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXRESULT : SPANDSP_EVENT_RXFAXRESULT)switch_event_create_subclass_detailed("mod_spandsp_fax.c", (const
char * )(const char *)__func__, 596, &event, SWITCH_EVENT_CUSTOM
, pvt->app_mode == FUNCTION_TX ? "spandsp::txfaxresult" : "spandsp::rxfaxresult"
)
== SWITCH_STATUS_SUCCESS) {
597 switch_channel_event_set_data(channel, event);
598
599 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-success", (result == T30_ERR_OK) ? "1" : "0");
600 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-result-code", fax_result_code);
601 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-result-text", t30_completion_code_to_str(result));
602 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-transferred-pages", fax_document_transferred_pages);
603 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-total-pages", fax_document_total_pages);
604 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_image_resolution);
605 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-size", fax_image_size);
606 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-bad-rows", fax_bad_rows);
607 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-transfer-rate", fax_transfer_rate);
608 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-ecm-used", (t.error_correcting_mode) ? "on" : "off");
609 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-local-station-id", local_ident);
610 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-station-id", far_ident);
611 switch_event_fire(&event)switch_event_fire_detailed("mod_spandsp_fax.c", (const char *
)(const char *)__func__, 611, &event, ((void*)0))
;
612 }
613
614 if ((var = switch_channel_get_variable(channel, "system_on_fax_result")switch_channel_get_variable_dup(channel, "system_on_fax_result"
, SWITCH_TRUE, -1)
)) {
615 expanded = switch_channel_expand_variables(channel, var)switch_channel_expand_variables_check(channel, var, ((void*)0
), ((void*)0), 0)
;
616 switch_system(expanded, SWITCH_FALSE);
617 if (expanded != var) {
618 free(expanded);
619 }
620 }
621
622 switch_channel_execute_on(channel, "execute_on_fax_result");
623
624 if (result == T30_ERR_OK) {
625 if ((var = switch_channel_get_variable(channel, "system_on_fax_success")switch_channel_get_variable_dup(channel, "system_on_fax_success"
, SWITCH_TRUE, -1)
)) {
626 expanded = switch_channel_expand_variables(channel, var)switch_channel_expand_variables_check(channel, var, ((void*)0
), ((void*)0), 0)
;
627 switch_system(expanded, SWITCH_FALSE);
628 if (expanded != var) {
629 free(expanded);
630 }
631 }
632 switch_channel_execute_on(channel, "execute_on_fax_success");
633 } else {
634 if ((var = switch_channel_get_variable(channel, "system_on_fax_failure")switch_channel_get_variable_dup(channel, "system_on_fax_failure"
, SWITCH_TRUE, -1)
)) {
635 expanded = switch_channel_expand_variables(channel, var)switch_channel_expand_variables_check(channel, var, ((void*)0
), ((void*)0), 0)
;
636 switch_system(expanded, SWITCH_FALSE);
637 if (expanded != var) {
638 free(expanded);
639 }
640 }
641 switch_channel_execute_on(channel, "execute_on_fax_failure");
642 }
643}
644
645static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
646{
647 switch_frame_t out_frame = { 0 };
648 switch_core_session_t *session;
649 pvt_t *pvt;
650 uint8_t pkt[LOCAL_FAX_MAX_DATAGRAM400];
651 int x;
652 int r = 0;
653
654 pvt = (pvt_t *) user_data;
655 session = pvt->session;
656
657 /* we need to build a real packet here and make write_frame.packet and write_frame.packetlen point to it */
658 out_frame.flags = SFF_UDPTL_PACKET | SFF_PROXY_PACKET;
659 out_frame.packet = pkt;
660 if ((r = udptl_build_packet(pvt->udptl_state, pkt, buf, len)) > 0) {
661 out_frame.packetlen = r;
662 //switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "WRITE %d udptl bytes\n", out_frame.packetlen);
663
664 for (x = 0; x < count; x++) {
665 if (switch_core_session_write_frame(session, &out_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
666 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 666, (const char*)(session)
, SWITCH_LOG_ERROR, "INVALID WRITE: %d:%d\n", out_frame.packetlen, count);
667 r = -1;
668 break;
669 }
670 }
671 } else {
672 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 672, (const char*)(session)
, SWITCH_LOG_ERROR, "INVALID PACKETLEN: %d PASSED: %d:%d\n", r, len, count);
673 }
674
675 if (r < 0) {
676 t30_state_t *t30;
677
678 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 678, (const char*)(session)
, SWITCH_LOG_ERROR, "TERMINATING T30 STATE\n");
679
680 if (pvt->t38_state && (t30 = t38_terminal_get_t30_state(pvt->t38_state))) {
681 t30_terminate(t30);
682 }
683 switch_yield(10000)switch_sleep(10000);;
684 }
685
686 return r < 0 ? r : 0;
687}
688
689static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
690{
691 switch_core_session_t *session;
692 switch_channel_t *channel;
693 fax_state_t *fax;
694 t38_terminal_state_t *t38;
695 t30_state_t *t30;
696 const char *tmp;
697 const char *tz;
698 int fec_entries = DEFAULT_FEC_ENTRIES3;
699 int fec_span = DEFAULT_FEC_SPAN3;
700 int compressions;
701
702 session = (switch_core_session_t *) pvt->session;
703 switch_assert(session)((session) ? (void) (0) : __assert_fail ("session", "mod_spandsp_fax.c"
, 703, __PRETTY_FUNCTION__))
;
704
705 channel = switch_core_session_get_channel(session);
706 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "mod_spandsp_fax.c"
, 706, __PRETTY_FUNCTION__))
;
707
708 if ((tmp = switch_channel_get_variable(channel, "t38_gateway_redundancy")switch_channel_get_variable_dup(channel, "t38_gateway_redundancy"
, SWITCH_TRUE, -1)
)) {
709 int tmp_value;
710 tmp_value = atoi(tmp);
711 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_spandsp_fax.c", (const char *)__func__
, 711, ((void*)0)
, SWITCH_LOG_DEBUG, "FAX changing redundancy from %d:%d to %d:%d\n", fec_span, fec_entries, tmp_value, tmp_value );
712 fec_entries = tmp_value;
713 fec_span = tmp_value;
714 }
715
716 switch (trans_mode) {
717 case AUDIO_MODE:
718 if (pvt->fax_state == NULL((void*)0)) {
719 pvt->fax_state = (fax_state_t *) switch_core_session_alloc(pvt->session, sizeof(fax_state_t))switch_core_perform_session_alloc(pvt->session, sizeof(fax_state_t
), "mod_spandsp_fax.c", (const char *)__func__, 719)
;
720 }
721 if (pvt->fax_state == NULL((void*)0)) {
722 return SWITCH_STATUS_FALSE;
723 }
724
725 fax = pvt->fax_state;
726 pvt->t30 = fax_get_t30_state(fax);
727 t30 = pvt->t30;
728
729 memset(fax, 0, sizeof(fax_state_t));
730 if (fax_init(fax, pvt->caller) == NULL((void*)0)) {
731 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 731, (const char*)(session)
, SWITCH_LOG_ERROR, "Cannot initialize my fax structs\n");
732 return SWITCH_STATUS_FALSE;
733 }
734
735 fax_set_transmit_on_idle(fax, TRUE(!0));
736
737 span_log_set_message_handler(fax_get_logging_state(fax), mod_spandsp_log_message, pvt->session);
738 span_log_set_message_handler(t30_get_logging_state(t30), mod_spandsp_log_message, pvt->session);
739
740 if (pvt->verbose) {
741 span_log_set_level(fax_get_logging_state(fax), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
742 span_log_set_level(t30_get_logging_state(t30), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
743 }
744 break;
745 case T38_MODE:
746 {
747 switch_core_session_message_t msg = { 0 };
748
749 if (pvt->t38_state == NULL((void*)0)) {
750 pvt->t38_state = (t38_terminal_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_terminal_state_t))switch_core_perform_session_alloc(pvt->session, sizeof(t38_terminal_state_t
), "mod_spandsp_fax.c", (const char *)__func__, 750)
;
751 }
752 if (pvt->t38_state == NULL((void*)0)) {
753 return SWITCH_STATUS_FALSE;
754 }
755 if (pvt->udptl_state == NULL((void*)0)) {
756 pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t))switch_core_perform_session_alloc(pvt->session, sizeof(udptl_state_t
), "mod_spandsp_fax.c", (const char *)__func__, 756)
;
757 }
758 if (pvt->udptl_state == NULL((void*)0)) {
759 t38_terminal_free(pvt->t38_state);
760 pvt->t38_state = NULL((void*)0);
761 return SWITCH_STATUS_FALSE;
762 }
763
764 t38 = pvt->t38_state;
765 pvt->t30 = t38_terminal_get_t30_state(t38);
766 t30 = pvt->t30;
767
768 memset(t38, 0, sizeof(t38_terminal_state_t));
769
770 if (t38_terminal_init(t38, pvt->caller, t38_tx_packet_handler, pvt) == NULL((void*)0)) {
771 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 771, (const char*)(session)
, SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n");
772 return SWITCH_STATUS_FALSE;
773 }
774
775 pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state);
776
777 if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, fec_span, fec_entries,
778 (udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL((void*)0)) {
779 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 779, (const char*)(session)
, SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
780 return SWITCH_STATUS_FALSE;
781 }
782
783 msg.from = __FILE__"mod_spandsp_fax.c";
784 msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE;
785 switch_core_session_receive_message(pvt->session, &msg)switch_core_session_perform_receive_message(pvt->session, &
msg, "mod_spandsp_fax.c", (const char *)__func__, 785)
;
786
787 /* add to timer thread processing */
788 if (!add_pvt(pvt)) {
789 if (channel) {
790 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_spandsp_fax.c", (
const char *)__func__, 790, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
791 }
792 }
793
794 span_log_set_message_handler(t38_terminal_get_logging_state(t38), mod_spandsp_log_message, pvt->session);
795 span_log_set_message_handler(t30_get_logging_state(t30), mod_spandsp_log_message, pvt->session);
796
797 if (pvt->verbose) {
798 span_log_set_level(t38_terminal_get_logging_state(t38), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
799 span_log_set_level(t30_get_logging_state(t30), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
800 }
801 }
802 break;
803 case T38_GATEWAY_MODE:
804 if (pvt->t38_gateway_state == NULL((void*)0)) {
805 pvt->t38_gateway_state = (t38_gateway_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_gateway_state_t))switch_core_perform_session_alloc(pvt->session, sizeof(t38_gateway_state_t
), "mod_spandsp_fax.c", (const char *)__func__, 805)
;
806 }
807
808 if (pvt->udptl_state == NULL((void*)0)) {
809 pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t))switch_core_perform_session_alloc(pvt->session, sizeof(udptl_state_t
), "mod_spandsp_fax.c", (const char *)__func__, 809)
;
810 }
811
812 if (t38_gateway_init(pvt->t38_gateway_state, t38_tx_packet_handler, pvt) == NULL((void*)0)) {
813 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 813, (const char*)(session)
, SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n");
814 t38_gateway_free(pvt->t38_gateway_state);
815 pvt->t38_gateway_state = NULL((void*)0);
816
817 return SWITCH_STATUS_FALSE;
818 }
819
820 pvt->t38_core = t38_gateway_get_t38_core_state(pvt->t38_gateway_state);
821
822 if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, fec_span, fec_entries,
823 (udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL((void*)0)) {
824 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 824, (const char*)(session)
, SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n");
825 t38_gateway_free(pvt->t38_gateway_state);
826 udptl_release(pvt->udptl_state);
827 pvt->udptl_state = NULL((void*)0);
828 return SWITCH_STATUS_FALSE;
829 }
830
831 t38_gateway_set_transmit_on_idle(pvt->t38_gateway_state, TRUE(!0));
832
833 if (switch_true(switch_channel_get_variable(channel, "fax_v17_disabled")switch_channel_get_variable_dup(channel, "fax_v17_disabled", SWITCH_TRUE
, -1)
)) {
834 t38_gateway_set_supported_modems(pvt->t38_gateway_state, T30_SUPPORT_V29 | T30_SUPPORT_V27TER);
835 } else {
836 t38_gateway_set_supported_modems(pvt->t38_gateway_state, T30_SUPPORT_V17 | T30_SUPPORT_V29 | T30_SUPPORT_V27TER);
837 }
838
839 t38_gateway_set_tep_mode(pvt->t38_gateway_state, pvt->enable_tep);
840
841 t38_gateway_set_ecm_capability(pvt->t38_gateway_state, pvt->use_ecm);
842 switch_channel_set_variable(channel, "fax_ecm_requested", pvt->use_ecm ? "true" : "false")switch_channel_set_variable_var_check(channel, "fax_ecm_requested"
, pvt->use_ecm ? "true" : "false", SWITCH_TRUE)
;
843
844 span_log_set_message_handler(t38_gateway_get_logging_state(pvt->t38_gateway_state), mod_spandsp_log_message, pvt->session);
845 span_log_set_message_handler(t38_core_get_logging_state(pvt->t38_core), mod_spandsp_log_message, pvt->session);
846
847 if (pvt->verbose) {
848 span_log_set_level(t38_gateway_get_logging_state(pvt->t38_gateway_state), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
849 span_log_set_level(t38_core_get_logging_state(pvt->t38_core), SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
850 }
851
852 t38_set_t38_version(pvt->t38_core, 0);
853
854 return SWITCH_STATUS_SUCCESS;
855 default:
856 assert(0)((0) ? (void) (0) : __assert_fail ("0", "mod_spandsp_fax.c", 856
, __PRETTY_FUNCTION__))
; /* What? */
857 return SWITCH_STATUS_SUCCESS;
858 } /* Switch trans mode */
859
860 /* All the things which are common to audio and T.38 FAX setup */
861 t30_set_tx_ident(t30, pvt->ident);
862 t30_set_tx_page_header_info(t30, pvt->header);
863 if (pvt->timezone && pvt->timezone[0]) {
864 if ((tz = switch_lookup_timezone(pvt->timezone)))
865 t30_set_tx_page_header_tz(t30, tz);
866 else
867 t30_set_tx_page_header_tz(t30, pvt->timezone);
868 }
869
870 t30_set_phase_e_handler(t30, phase_e_handler, pvt);
871 t30_set_phase_d_handler(t30, phase_d_handler, pvt);
872 t30_set_phase_b_handler(t30, phase_b_handler, pvt);
873
874 t30_set_supported_image_sizes(t30,
875 T4_SUPPORT_LENGTH_US_LETTER
876 | T4_SUPPORT_LENGTH_US_LEGAL
877 | T4_SUPPORT_LENGTH_UNLIMITED
878 | T4_SUPPORT_WIDTH_215MM
879 | T4_SUPPORT_WIDTH_255MM
880 | T4_SUPPORT_WIDTH_303MM);
881 t30_set_supported_bilevel_resolutions(t30,
882 T4_RESOLUTION_R8_STANDARD
883 | T4_RESOLUTION_R8_FINE
884 | T4_RESOLUTION_R8_SUPERFINE
885 | T4_RESOLUTION_R16_SUPERFINE
886 | T4_RESOLUTION_200_100
887 | T4_RESOLUTION_200_200
888 | T4_RESOLUTION_200_400
889 | T4_RESOLUTION_400_400);
890 compressions = T4_COMPRESSION_T4_1D
891 | T4_COMPRESSION_T4_2D
892 | T4_COMPRESSION_T6
893 | T4_COMPRESSION_T85
894 | T4_COMPRESSION_T85_L0;
895 if (pvt->enable_colour_fax) {
896 t30_set_supported_colour_resolutions(t30, T4_RESOLUTION_100_100
897 | T4_RESOLUTION_200_200
898 | T4_RESOLUTION_300_300
899 | T4_RESOLUTION_400_400);
900 compressions |= (T4_COMPRESSION_COLOUR | T4_COMPRESSION_T42_T81);
901 } else {
902 t30_set_supported_colour_resolutions(t30, 0);
903 }
904 if (pvt->enable_image_resizing)
905 compressions |= T4_COMPRESSION_RESCALING;
906 if (pvt->enable_colour_to_bilevel)
907 compressions |= T4_COMPRESSION_COLOUR_TO_BILEVEL;
908 if (pvt->enable_grayscale_to_bilevel)
909 compressions |= T4_COMPRESSION_GRAY_TO_BILEVEL;
910
911 t30_set_supported_compressions(t30, compressions);
912
913 if (pvt->disable_v17) {
914 t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER);
915 switch_channel_set_variable(channel, "fax_v17_disabled", "1")switch_channel_set_variable_var_check(channel, "fax_v17_disabled"
, "1", SWITCH_TRUE)
;
916 } else {
917 t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER | T30_SUPPORT_V17);
918 switch_channel_set_variable(channel, "fax_v17_disabled", "0")switch_channel_set_variable_var_check(channel, "fax_v17_disabled"
, "0", SWITCH_TRUE)
;
919 }
920
921 if (pvt->use_ecm) {
922 t30_set_ecm_capability(t30, TRUE(!0));
923 switch_channel_set_variable(channel, "fax_ecm_requested", "1")switch_channel_set_variable_var_check(channel, "fax_ecm_requested"
, "1", SWITCH_TRUE)
;
924 } else {
925 t30_set_ecm_capability(t30, FALSE0);
926 switch_channel_set_variable(channel, "fax_ecm_requested", "0")switch_channel_set_variable_var_check(channel, "fax_ecm_requested"
, "0", SWITCH_TRUE)
;
927 }
928
929 if (pvt->app_mode == FUNCTION_TX) {
930 t30_set_tx_file(t30, pvt->filename, pvt->tx_page_start, pvt->tx_page_end);
931 } else {
932 t30_set_rx_file(t30, pvt->filename, -1);
933 }
934 switch_channel_set_variable(channel, "fax_filename", pvt->filename)switch_channel_set_variable_var_check(channel, "fax_filename"
, pvt->filename, SWITCH_TRUE)
;
935
936 return SWITCH_STATUS_SUCCESS;
937}
938
939static switch_status_t spanfax_destroy(pvt_t *pvt)
940{
941 int terminate;
942 t30_state_t *t30;
943
944 if (!pvt) return SWITCH_STATUS_FALSE;
945
946 if (pvt->fax_state) {
947 if (pvt->t38_state) {
948 terminate = 0;
949 } else {
950 terminate = 1;
951 }
952
953 t30 = fax_get_t30_state(pvt->fax_state);
954 if (terminate && t30) {
955 t30_terminate(t30);
956 }
957
958 fax_release(pvt->fax_state);
959 }
960
961 if (pvt->t38_state) {
962
963 /* remove from timer thread processing */
964 del_pvt(pvt);
965
966 if (pvt->t38_state) {
967 terminate = 1;
968 } else {
969 terminate = 0;
970 }
971
972 t30 = t38_terminal_get_t30_state(pvt->t38_state);
973 if (terminate && t30) {
974 t30_terminate(t30);
975 }
976
977 t38_terminal_release(pvt->t38_state);
978 }
979
980 if (pvt->t38_gateway_state) {
981 t38_gateway_release(pvt->t38_gateway_state);
982 }
983
984 if (pvt->udptl_state) {
985 udptl_release(pvt->udptl_state);
986 }
987 return SWITCH_STATUS_SUCCESS;
988}
989
990static t38_mode_t configure_t38(pvt_t *pvt)
991{
992 switch_core_session_t *session = pvt->session;
993 switch_channel_t *channel = switch_core_session_get_channel(session);
994 switch_t38_options_t *t38_options = switch_channel_get_private(channel, "t38_options");
995 int method = 2;
996
997 if (!t38_options || !pvt || !pvt->t38_core) {
998 pvt->t38_mode = T38_MODE_REFUSED;
999 return pvt->t38_mode;
1000 }
1001
1002 t38_set_t38_version(pvt->t38_core, t38_options->T38FaxVersion);
1003 t38_set_max_buffer_size(pvt->t38_core, t38_options->T38FaxMaxBuffer);
1004 t38_set_fastest_image_data_rate(pvt->t38_core, t38_options->T38MaxBitRate);
1005 t38_set_fill_bit_removal(pvt->t38_core, t38_options->T38FaxFillBitRemoval);
1006 t38_set_mmr_transcoding(pvt->t38_core, t38_options->T38FaxTranscodingMMR);
1007 t38_set_jbig_transcoding(pvt->t38_core, t38_options->T38FaxTranscodingJBIG);
1008 t38_set_max_datagram_size(pvt->t38_core, t38_options->T38FaxMaxDatagram);
1009
1010 if (t38_options->T38FaxRateManagement) {
1011 if (!strcasecmp(t38_options->T38FaxRateManagement, "transferredTCF")) {
1012 method = 2;
1013 } else {
1014 method = 1;
1015 }
1016 }
1017
1018 t38_set_data_rate_management_method(pvt->t38_core, method);
1019
1020
1021 //t38_set_data_transport_protocol(pvt->t38_core, int data_transport_protocol);
1022 //t38_set_redundancy_control(pvt->t38_core, int category, int setting);
1023
1024 return pvt->t38_mode;
1025}
1026
1027static t38_mode_t negotiate_t38(pvt_t *pvt)
1028{
1029 switch_core_session_t *session = pvt->session;
1030 switch_channel_t *channel = switch_core_session_get_channel(session);
1031 switch_core_session_message_t msg = { 0 };
1032 switch_t38_options_t *t38_options = switch_channel_get_private(channel, "t38_options");
1033 int enabled = 0, insist = 0;
1034 const char *v;
1035
1036 pvt->t38_mode = T38_MODE_REFUSED;
1037
1038 if (pvt->app_mode == FUNCTION_GW) {
1039 enabled = 1;
1040 } else if ((v = switch_channel_get_variable(channel, "fax_enable_t38")switch_channel_get_variable_dup(channel, "fax_enable_t38", SWITCH_TRUE
, -1)
)) {
1041 enabled = switch_true(v);
1042 } else {
1043 enabled = spandsp_globals.enable_t38;
1044 }
1045
1046 if (!(enabled && t38_options)) {
1047 /* if there is no t38_options the endpoint will refuse the transition */
1048 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1048, (const char*)(session)
, SWITCH_LOG_WARNING, "%s NO T38 options detected.\n", switch_channel_get_name(channel));
1049 switch_channel_set_private(channel, "t38_options", NULL((void*)0));
1050 } else {
1051 pvt->t38_mode = T38_MODE_NEGOTIATED;
1052 switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_NEGOTIATED);
1053
1054 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1054, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38 SDP Origin = %s\n", t38_options->sdp_o_line);
1055 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1055, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38FaxVersion = %d\n", t38_options->T38FaxVersion);
1056 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1056, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38MaxBitRate = %d\n", t38_options->T38MaxBitRate);
1057 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1057, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38FaxFillBitRemoval = %d\n", t38_options->T38FaxFillBitRemoval);
1058 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1058, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38FaxTranscodingMMR = %d\n", t38_options->T38FaxTranscodingMMR);
1059 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1059, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38FaxTranscodingJBIG = %d\n", t38_options->T38FaxTranscodingJBIG);
1060 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1060, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38FaxRateManagement = '%s'\n", t38_options->T38FaxRateManagement);
1061 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1061, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38FaxMaxBuffer = %d\n", t38_options->T38FaxMaxBuffer);
1062 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1062, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38FaxMaxDatagram = %d\n", t38_options->T38FaxMaxDatagram);
1063 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1063, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38FaxUdpEC = '%s'\n", t38_options->T38FaxUdpEC);
1064 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1064, (const char*)(session)
, SWITCH_LOG_DEBUG, "T38VendorInfo = '%s'\n", switch_str_nil(t38_options->T38VendorInfo)(t38_options->T38VendorInfo ? t38_options->T38VendorInfo
: "")
);
1065 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1065, (const char*)(session)
, SWITCH_LOG_DEBUG, "ip = '%s'\n",
1066 t38_options->remote_ip ? t38_options->remote_ip : "Not specified");
1067 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1067, (const char*)(session)
, SWITCH_LOG_DEBUG, "port = %d\n", t38_options->remote_port);
1068
1069 /* Time to practice our negotiating skills, by editing the t38_options */
1070
1071 if (t38_options->T38FaxVersion > 3) {
1072 t38_options->T38FaxVersion = 3;
1073 }
1074 t38_options->T38MaxBitRate = (pvt->disable_v17) ? 9600 : 14400;
1075
1076 /* cisco gets mad when we set this to one in a response where they set it to 0, are we allowed to hardcode this to 1 on responses? */
1077 /*
1078 if (!zstr(t38_options->sdp_o_line) && !switch_stristr("cisco", t38_options->sdp_o_line)) {
1079 t38_options->T38FaxFillBitRemoval = 1;
1080 }
1081 */
1082
1083 t38_options->T38FaxTranscodingMMR = 0;
1084 t38_options->T38FaxTranscodingJBIG = 0;
1085 t38_options->T38FaxRateManagement = "transferredTCF";
1086 if (!t38_options->T38FaxMaxBuffer) {
1087 t38_options->T38FaxMaxBuffer = 2000;
1088 }
1089 t38_options->T38FaxMaxDatagram = LOCAL_FAX_MAX_DATAGRAM400;
1090 if (!zstr(t38_options->T38FaxUdpEC)_zstr(t38_options->T38FaxUdpEC) &&
1091 (strcasecmp(t38_options->T38FaxUdpEC, "t38UDPRedundancy") == 0 ||
1092 strcasecmp(t38_options->T38FaxUdpEC, "t38UDPFEC") == 0)) {
1093 t38_options->T38FaxUdpEC = "t38UDPRedundancy";
1094 } else {
1095 t38_options->T38FaxUdpEC = NULL((void*)0);
1096 }
1097 t38_options->T38VendorInfo = "0 0 0";
1098 }
1099
1100 if ((v = switch_channel_get_variable(channel, "fax_enable_t38_insist")switch_channel_get_variable_dup(channel, "fax_enable_t38_insist"
, SWITCH_TRUE, -1)
)) {
1101 insist = switch_true(v);
1102 } else {
1103 insist = spandsp_globals.enable_t38_insist;
1104 }
1105
1106 /* This will send the options back in a response */
1107 msg.from = __FILE__"mod_spandsp_fax.c";
1108 msg.message_id = SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION;
1109 msg.numeric_arg = insist;
1110 switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg
, "mod_spandsp_fax.c", (const char *)__func__, 1110)
;
1111
1112 return pvt->t38_mode;
1113}
1114
1115
1116
1117static t38_mode_t request_t38(pvt_t *pvt)
1118{
1119 switch_core_session_t *session = pvt->session;
1120 switch_channel_t *channel = switch_core_session_get_channel(session);
1121 switch_core_session_message_t msg = { 0 };
1122 switch_t38_options_t *t38_options = NULL((void*)0);
1123 int enabled = 0, insist = 0;
1124 const char *v;
1125
1126 pvt->t38_mode = T38_MODE_UNKNOWN;
1127
1128 if (pvt->app_mode == FUNCTION_GW) {
1129 enabled = 1;
1130 } else if ((v = switch_channel_get_variable(channel, "fax_enable_t38")switch_channel_get_variable_dup(channel, "fax_enable_t38", SWITCH_TRUE
, -1)
)) {
1131 enabled = switch_true(v);
1132 } else {
1133 enabled = spandsp_globals.enable_t38;
1134 }
1135
1136 if (enabled) {
1137 if ((v = switch_channel_get_variable(channel, "fax_enable_t38_request")switch_channel_get_variable_dup(channel, "fax_enable_t38_request"
, SWITCH_TRUE, -1)
)) {
1138 enabled = switch_true(v);
1139 } else {
1140 enabled = spandsp_globals.enable_t38_request;
1141 }
1142 }
1143
1144
1145 if ((v = switch_channel_get_variable(channel, "fax_enable_t38_insist")switch_channel_get_variable_dup(channel, "fax_enable_t38_insist"
, SWITCH_TRUE, -1)
)) {
1146 insist = switch_true(v);
1147 } else {
1148 insist = spandsp_globals.enable_t38_insist;
1149 }
1150
1151 if ((t38_options = switch_channel_get_private(channel, "t38_options"))) {
1152 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1152, (const char*)(session)
, SWITCH_LOG_WARNING,
1153 "%s already has T.38 data\n", switch_channel_get_name(channel));
1154 enabled = 0;
1155 }
1156
1157
1158
1159 if (enabled) {
1160
1161 if (!(t38_options = switch_channel_get_private(channel, "_preconfigured_t38_options"))) {
1162 t38_options = switch_core_session_alloc(session, sizeof(*t38_options))switch_core_perform_session_alloc(session, sizeof(*t38_options
), "mod_spandsp_fax.c", (const char *)__func__, 1162)
;
1163 t38_options->T38MaxBitRate = (pvt->disable_v17) ? 9600 : 14400;
1164 t38_options->T38FaxVersion = 0;
1165 t38_options->T38FaxFillBitRemoval = 1;
1166 t38_options->T38FaxTranscodingMMR = 0;
1167 t38_options->T38FaxTranscodingJBIG = 0;
1168 t38_options->T38FaxRateManagement = "transferredTCF";
1169 t38_options->T38FaxMaxBuffer = 2000;
1170 t38_options->T38FaxMaxDatagram = LOCAL_FAX_MAX_DATAGRAM400;
1171 t38_options->T38FaxUdpEC = "t38UDPRedundancy";
1172 t38_options->T38VendorInfo = "0 0 0";
1173 }
1174
1175 switch_channel_set_private(channel, "t38_options", t38_options);
1176 switch_channel_set_private(channel, "_preconfigured_t38_options", NULL((void*)0));
1177
1178 pvt->t38_mode = T38_MODE_REQUESTED;
1179 switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_REQ);
1180
1181 /* This will send a request for t.38 mode */
1182 msg.from = __FILE__"mod_spandsp_fax.c";
1183 msg.message_id = SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA;
1184 msg.numeric_arg = insist;
1185 switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg
, "mod_spandsp_fax.c", (const char *)__func__, 1185)
;
1186 }
1187
1188 return pvt->t38_mode;
1189}
1190
1191/*****************************************************************************
1192 MAIN FAX PROCESSING
1193*****************************************************************************/
1194
1195static pvt_t *pvt_init(switch_core_session_t *session, mod_spandsp_fax_application_mode_t app_mode)
1196{
1197 switch_channel_t *channel;
1198 pvt_t *pvt = NULL((void*)0);
1199 const char *tmp;
1200
1201 /* Make sure we have a valid channel when starting the FAX application */
1202 channel = switch_core_session_get_channel(session);
1203 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "mod_spandsp_fax.c", 1203, __PRETTY_FUNCTION__))
;
1204
1205 if (!switch_channel_media_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_TRUE)) {
1206 switch_channel_answer(channel)switch_channel_perform_answer(channel, "mod_spandsp_fax.c", (
const char *)__func__, 1206)
;
1207 }
1208
1209 /* Allocate our structs */
1210 pvt = switch_core_session_alloc(session, sizeof(pvt_t))switch_core_perform_session_alloc(session, sizeof(pvt_t), "mod_spandsp_fax.c"
, (const char *)__func__, 1210)
;
1211 pvt->session = session;
1212
1213 pvt->app_mode = app_mode;
1214
1215 pvt->tx_page_start = -1;
1216 pvt->tx_page_end = -1;
1217
1218
1219 switch(pvt->app_mode) {
1220
1221 case FUNCTION_TX:
1222 pvt->caller = 1;
1223 break;
1224 case FUNCTION_RX:
1225 pvt->caller = 0;
1226 break;
1227 case FUNCTION_GW:
1228 break;
1229 }
1230
1231 /* Retrieving our settings from the channel variables */
1232
1233 if ((tmp = switch_channel_get_variable(channel, "fax_use_ecm")switch_channel_get_variable_dup(channel, "fax_use_ecm", SWITCH_TRUE
, -1)
)) {
1234 pvt->use_ecm = switch_true(tmp);
1235 } else {
1236 pvt->use_ecm = spandsp_globals.use_ecm;
1237 }
1238
1239 if ((tmp = switch_channel_get_variable(channel, "fax_enable_tep")switch_channel_get_variable_dup(channel, "fax_enable_tep", SWITCH_TRUE
, -1)
)) {
1240 pvt->enable_tep = switch_true(tmp);
1241 } else {
1242 pvt->enable_tep = spandsp_globals.enable_tep;
1243 }
1244
1245 if ((tmp = switch_channel_get_variable(channel, "fax_disable_v17")switch_channel_get_variable_dup(channel, "fax_disable_v17", SWITCH_TRUE
, -1)
)) {
1246 pvt->disable_v17 = switch_true(tmp);
1247 } else {
1248 pvt->disable_v17 = spandsp_globals.disable_v17;
1249 }
1250
1251 if ((tmp = switch_channel_get_variable(channel, "fax_enable_colour")switch_channel_get_variable_dup(channel, "fax_enable_colour",
SWITCH_TRUE, -1)
)) {
1252 pvt->enable_colour_fax = switch_true(tmp);
1253 } else {
1254 pvt->enable_colour_fax = spandsp_globals.enable_colour_fax;
1255 }
1256
1257 if ((tmp = switch_channel_get_variable(channel, "fax_enable_image_resizing")switch_channel_get_variable_dup(channel, "fax_enable_image_resizing"
, SWITCH_TRUE, -1)
)) {
1258 pvt->enable_image_resizing = switch_true(tmp);
1259 } else {
1260 pvt->enable_image_resizing = spandsp_globals.enable_image_resizing;
1261 }
1262
1263 if ((tmp = switch_channel_get_variable(channel, "fax_enable_colour_to_bilevel")switch_channel_get_variable_dup(channel, "fax_enable_colour_to_bilevel"
, SWITCH_TRUE, -1)
)) {
1264 pvt->enable_colour_to_bilevel = switch_true(tmp);
1265 } else {
1266 pvt->enable_colour_to_bilevel = spandsp_globals.enable_colour_to_bilevel;
1267 }
1268
1269 if ((tmp = switch_channel_get_variable(channel, "fax_enable_grayscale_to_bilevel")switch_channel_get_variable_dup(channel, "fax_enable_grayscale_to_bilevel"
, SWITCH_TRUE, -1)
)) {
1270 pvt->enable_grayscale_to_bilevel = switch_true(tmp);
1271 } else {
1272 pvt->enable_grayscale_to_bilevel = spandsp_globals.enable_grayscale_to_bilevel;
1273 }
1274
1275 if ((tmp = switch_channel_get_variable(channel, "fax_verbose")switch_channel_get_variable_dup(channel, "fax_verbose", SWITCH_TRUE
, -1)
)) {
1276 pvt->verbose = switch_true(tmp);
1277 } else {
1278 pvt->verbose = spandsp_globals.verbose;
1279 }
1280
1281 if ((tmp = switch_channel_get_variable(channel, "fax_force_caller")switch_channel_get_variable_dup(channel, "fax_force_caller", SWITCH_TRUE
, -1)
)) {
1282 if (switch_true(tmp)) {
1283 pvt->caller = 1;
1284 } else {
1285 pvt->caller = 0;
1286 }
1287 }
1288
1289 if ((tmp = switch_channel_get_variable(channel, "fax_ident")switch_channel_get_variable_dup(channel, "fax_ident", SWITCH_TRUE
, -1)
)) {
1290 char *data = NULL((void*)0);
1291
1292 data = strdup(tmp)(__extension__ (__builtin_constant_p (tmp) && ((size_t
)(const void *)((tmp) + 1) - (size_t)(const void *)(tmp) == 1
) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, tmp, __len); __retval
; })) : __strdup (tmp)))
;
1293 switch_url_decode(data);
1294 pvt->ident = switch_core_session_strdup(session, data)switch_core_perform_session_strdup(session, data, "mod_spandsp_fax.c"
, (const char *)__func__, 1294)
;
1295
1296 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
1297 } else {
1298 pvt->ident = switch_core_session_strdup(session, spandsp_globals.ident)switch_core_perform_session_strdup(session, spandsp_globals.ident
, "mod_spandsp_fax.c", (const char *)__func__, 1298)
;
1299 }
1300
1301 if ((tmp = switch_channel_get_variable(channel, "fax_header")switch_channel_get_variable_dup(channel, "fax_header", SWITCH_TRUE
, -1)
)) {
1302 char *data = NULL((void*)0);
1303
1304 data = strdup(tmp)(__extension__ (__builtin_constant_p (tmp) && ((size_t
)(const void *)((tmp) + 1) - (size_t)(const void *)(tmp) == 1
) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, tmp, __len); __retval
; })) : __strdup (tmp)))
;
1305 switch_url_decode(data);
1306 pvt->header = switch_core_session_strdup(session, data)switch_core_perform_session_strdup(session, data, "mod_spandsp_fax.c"
, (const char *)__func__, 1306)
;
1307
1308 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
1309 } else {
1310 pvt->header = switch_core_session_strdup(session, spandsp_globals.header)switch_core_perform_session_strdup(session, spandsp_globals.header
, "mod_spandsp_fax.c", (const char *)__func__, 1310)
;
1311 }
1312
1313 if ((tmp = switch_channel_get_variable(channel, "fax_timezone")switch_channel_get_variable_dup(channel, "fax_timezone", SWITCH_TRUE
, -1)
)) {
1314 char *data = NULL((void*)0);
1315
1316 data = strdup(tmp)(__extension__ (__builtin_constant_p (tmp) && ((size_t
)(const void *)((tmp) + 1) - (size_t)(const void *)(tmp) == 1
) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, tmp, __len); __retval
; })) : __strdup (tmp)))
;
1317 switch_url_decode(data);
1318 pvt->timezone = switch_core_session_strdup(session, data)switch_core_perform_session_strdup(session, data, "mod_spandsp_fax.c"
, (const char *)__func__, 1318)
;
1319
1320 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
1321 } else {
1322 pvt->timezone = switch_core_session_strdup(session, spandsp_globals.timezone)switch_core_perform_session_strdup(session, spandsp_globals.timezone
, "mod_spandsp_fax.c", (const char *)__func__, 1322)
;
1323 }
1324
1325 if (pvt->app_mode == FUNCTION_TX) {
1326 if ((tmp = switch_channel_get_variable(channel, "fax_start_page")switch_channel_get_variable_dup(channel, "fax_start_page", SWITCH_TRUE
, -1)
)) {
1327 pvt->tx_page_start = atoi(tmp);
1328 }
1329
1330 if ((tmp = switch_channel_get_variable(channel, "fax_end_page")switch_channel_get_variable_dup(channel, "fax_end_page", SWITCH_TRUE
, -1)
)) {
1331 pvt->tx_page_end = atoi(tmp);
1332 }
1333
1334 if (pvt->tx_page_end < -1) {
1335 pvt->tx_page_end = -1;
1336 }
1337
1338 if (pvt->tx_page_start < -1) {
1339 pvt->tx_page_start = -1;
1340 }
1341
1342 if ((pvt->tx_page_end < pvt->tx_page_start) && (pvt->tx_page_end != -1)) {
1343 pvt->tx_page_end = pvt->tx_page_start;
1344 }
1345 }
1346
1347 return pvt;
1348}
1349
1350void mod_spandsp_fax_stop_fax(switch_core_session_t *session)
1351{
1352 pvt_t *pvt = switch_channel_get_private(switch_core_session_get_channel(session), "_fax_pvt");
1353 if (pvt) {
1354 pvt->done = 1;
1355 }
1356}
1357
1358void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *data, mod_spandsp_fax_application_mode_t app_mode)
1359{
1360 pvt_t *pvt;
1361 switch_channel_t *channel = switch_core_session_get_channel(session);
1362 switch_codec_t read_codec = { 0 };
1363 switch_codec_t write_codec = { 0 };
1364 switch_frame_t *read_frame = { 0 };
1365 switch_frame_t write_frame = { 0 };
1366 switch_codec_implementation_t read_impl = { 0 };
1367 int16_t *buf = NULL((void*)0);
1368 uint32_t req_counter = 0;
1369
1370 switch_core_session_get_read_impl(session, &read_impl);
1371
1372 counter_increment();
1373
1374
1375 pvt = pvt_init(session, app_mode);
1376 switch_channel_set_private(channel, "_fax_pvt", pvt);
1377
1378 buf = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE)switch_core_perform_session_alloc(session, 8192, "mod_spandsp_fax.c"
, (const char *)__func__, 1378)
;
1379
1380 if (!zstr(data)_zstr(data)) {
1381 pvt->filename = switch_core_session_strdup(session, data)switch_core_perform_session_strdup(session, data, "mod_spandsp_fax.c"
, (const char *)__func__, 1381)
;
1382 if (pvt->app_mode == FUNCTION_TX) {
1383 if ((switch_file_exists(pvt->filename, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS)) {
1384 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1384, (const char*)(session)
, SWITCH_LOG_ERROR, "Cannot send non-existant fax file [%s]\n",
1385 switch_str_nil(pvt->filename)(pvt->filename ? pvt->filename : ""));
1386 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Cannot send non-existant fax file")switch_channel_set_variable_var_check(channel, "current_application_response"
, "Cannot send non-existant fax file", SWITCH_TRUE)
;
1387 goto done;
1388 }
1389 }
1390 } else {
1391 if (pvt->app_mode == FUNCTION_TX) {
1392 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1392, (const char*)(session)
, SWITCH_LOG_ERROR, "Fax TX filename not set.\n");
1393 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Fax TX filename not set")switch_channel_set_variable_var_check(channel, "current_application_response"
, "Fax TX filename not set", SWITCH_TRUE)
;
1394 goto done;
1395 } else if (pvt->app_mode == FUNCTION_RX) {
1396 const char *prefix;
1397 switch_time_t time;
1398
1399 time = switch_time_now();
1400
1401 if (!(prefix = switch_channel_get_variable(channel, "fax_prefix")switch_channel_get_variable_dup(channel, "fax_prefix", SWITCH_TRUE
, -1)
)) {
1402 prefix = spandsp_globals.prepend_string;
1403 }
1404
1405 if (!(pvt->filename = switch_core_session_sprintf(session, "%s/%s-%ld-%" SWITCH_TIME_T_FMT"ld" ".tif", spandsp_globals.spool, prefix, spandsp_globals.total_sessions, time))) {
1406 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1406, (const char*)(session)
, SWITCH_LOG_ERROR, "Cannot automatically set fax RX destination file\n");
1407 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Cannot automatically set fax RX destination file")switch_channel_set_variable_var_check(channel, "current_application_response"
, "Cannot automatically set fax RX destination file", SWITCH_TRUE
)
;
1408 goto done;
1409 }
1410 } else {
1411 assert(0)((0) ? (void) (0) : __assert_fail ("0", "mod_spandsp_fax.c", 1411
, __PRETTY_FUNCTION__))
; /* UH ?? */
1412 }
1413 }
1414
1415 /*
1416 *** Initialize the SpanDSP elements ***
1417
1418 Note: we could analyze if a fax was already detected in previous stages
1419 and if so, when T.38 will be supported, send a reinvite in T38_MODE,
1420 bypassing AUDIO_MODE.
1421 */
1422
1423 if ((spanfax_init(pvt, AUDIO_MODE) != SWITCH_STATUS_SUCCESS)) {
1424 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1424, (const char*)(session)
, SWITCH_LOG_ERROR, "Cannot initialize Fax engine\n");
1425 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Cannot initialize Fax engine")switch_channel_set_variable_var_check(channel, "current_application_response"
, "Cannot initialize Fax engine", SWITCH_TRUE)
;
1426 return;
1427 }
1428
1429 /*
1430 Note: Disable echocan on the channel, remember to call app "disable_ec" in the dialplan
1431 before invoking fax applications
1432 */
1433
1434 /*
1435 Note: we are disabling the Jitterbuffer, here, before we answer.
1436 If you have set it to something else and the channel is pre-answered,
1437 it will have no effect. Make sure that if you want more reliable
1438 faxes, it is disabled.
1439 */
1440 switch_channel_set_variable(channel, "jitterbuffer_msec", NULL)switch_channel_set_variable_var_check(channel, "jitterbuffer_msec"
, ((void*)0), SWITCH_TRUE)
;
1441
1442
1443 /* We store the original channel codec before switching both
1444 * legs of the calls to a linear 16 bit codec that is the one
1445 * used internally by spandsp and FS will do the transcoding
1446 * from G.711 or any other original codec
1447 */
1448 if (switch_core_codec_init(&read_codec,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1449 "L16",switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1450 NULL,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1451 read_impl.samples_per_second,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1452 read_impl.microseconds_per_packet / 1000,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1453 1,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1454 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1455 NULL, switch_core_session_get_pool(session))switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
== SWITCH_STATUS_SUCCESS) {
1456 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1456, (const char*)(session)
, SWITCH_LOG_DEBUG, "Raw read codec activation Success L16 %u\n",
1457 read_codec.implementation->microseconds_per_packet);
1458 switch_core_session_set_read_codec(session, &read_codec);
1459 } else {
1460 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1460, (const char*)(session)
, SWITCH_LOG_ERROR, "Raw read codec activation Failed L16\n");
1461 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Raw read codec activation Failed L16")switch_channel_set_variable_var_check(channel, "current_application_response"
, "Raw read codec activation Failed L16", SWITCH_TRUE)
;
1462 goto done;
1463 }
1464
1465 if (switch_core_codec_init(&write_codec,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1466 "L16",switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1467 NULL,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1468 read_impl.samples_per_second,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1469 read_impl.microseconds_per_packet / 1000,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1470 1,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1471 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1472 NULL, switch_core_session_get_pool(session))switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
== SWITCH_STATUS_SUCCESS) {
1473 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1473, (const char*)(session)
, SWITCH_LOG_DEBUG, "Raw write codec activation Success L16\n");
1474 write_frame.codec = &write_codec;
1475 write_frame.data = buf;
1476 write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE8192;
1477 } else {
1478 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1478, (const char*)(session)
, SWITCH_LOG_ERROR, "Raw write codec activation Failed L16\n");
1479 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Raw write codec activation Failed L16")switch_channel_set_variable_var_check(channel, "current_application_response"
, "Raw write codec activation Failed L16", SWITCH_TRUE)
;
1480 goto done;
1481 }
1482
1483 switch_ivr_sleep(session, 250, SWITCH_TRUE, NULL((void*)0));
1484
1485 if (pvt->app_mode == FUNCTION_TX) {
1486 req_counter = 100;
1487 } else {
1488 req_counter = 50;
1489 }
1490
1491 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
1492 int tx = 0;
1493 switch_status_t status;
1494
1495 switch_ivr_parse_all_events(session);
1496
1497 /*
1498 if we are in T.38 mode, we should: 1- initialize the ptv->t38_state stuff, if not done
1499 and then set some callbacks when reading frames.
1500 The only thing we need, then, in this loop, is:
1501 - read a frame without blocking
1502 - eventually feed that frame in spandsp,
1503 - call t38_terminal_send_timeout(), sleep for a while
1504
1505 The T.38 stuff can be placed here (and the audio stuff can be skipped)
1506 */
1507
1508 /* read new audio frame from the channel */
1509 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1510
1511 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
|| pvt->done) {
1512 /* Our duty is over */
1513 goto done;
1514 }
1515
1516 switch (pvt->t38_mode) {
1517 case T38_MODE_REQUESTED:
1518 {
1519 if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38_FAIL)) {
1520 pvt->t38_mode = T38_MODE_REFUSED;
1521 continue;
1522 } else if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) {
1523 switch_core_session_message_t msg = { 0 };
1524 pvt->t38_mode = T38_MODE_NEGOTIATED;
1525 switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_NEGOTIATED);
1526 spanfax_init(pvt, T38_MODE);
1527 configure_t38(pvt);
1528
1529 /* This will change the rtp stack to udptl mode */
1530 msg.from = __FILE__"mod_spandsp_fax.c";
1531 msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE;
1532 switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg
, "mod_spandsp_fax.c", (const char *)__func__, 1532)
;
1533 }
1534 continue;
1535 }
1536 break;
1537 case T38_MODE_UNKNOWN:
1538 {
1539 if (req_counter) {
1540 if (!--req_counter) {
1541 /* If you have the means, I highly recommend picking one up. ...*/
1542 request_t38(pvt);
1543 }
1544 }
1545
1546 if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) {
1547 if (negotiate_t38(pvt) == T38_MODE_NEGOTIATED) {
1548 /* is is safe to call this again, it was already called above in AUDIO_MODE */
1549 /* but this is the only way to set up the t38 stuff */
1550 spanfax_init(pvt, T38_MODE);
1551 continue;
1552 }
1553 }
1554 }
1555 break;
1556 case T38_MODE_NEGOTIATED:
1557 {
1558 /* do what we need to do when we are in t38 mode */
1559 if (switch_test_flag(read_frame, SFF_CNG)((read_frame)->flags & SFF_CNG)) {
1560 /* dunno what to do, most likely you will not get too many of these since we turn off the timer in udptl mode */
1561 continue;
1562 }
1563
1564 if (switch_test_flag(read_frame, SFF_UDPTL_PACKET)((read_frame)->flags & SFF_UDPTL_PACKET) && read_frame->packet && read_frame->packetlen) {
1565 /* now we know we can cast frame->packet to a udptl structure */
1566 //switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "READ %d udptl bytes\n", read_frame->packetlen);
1567
1568 udptl_rx_packet(pvt->udptl_state, read_frame->packet, read_frame->packetlen);
1569 }
1570 }
1571 continue;
1572 default:
1573 break;
1574 }
1575
1576 if (switch_test_flag(read_frame, SFF_CNG)((read_frame)->flags & SFF_CNG)) {
1577 /* We have no real signal data for the FAX software, but we have a space in time if we have a CNG indication.
1578 Do a fill-in operation in the FAX machine, to keep things rolling along. */
1579 if (fax_rx_fillin(pvt->fax_state, read_impl.samples_per_packet)) {
1580 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1580, (const char*)(session)
, SWITCH_LOG_ERROR, "fax_rx_fillin reported an error\n");
1581 continue;
1582 }
1583 } else {
1584 /* Pass the new incoming audio frame to the fax_rx function */
1585 if (fax_rx(pvt->fax_state, (int16_t *) read_frame->data, read_frame->samples)) {
1586 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1586, (const char*)(session)
, SWITCH_LOG_ERROR, "fax_rx reported an error\n");
1587 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "fax_rx reported an error")switch_channel_set_variable_var_check(channel, "current_application_response"
, "fax_rx reported an error", SWITCH_TRUE)
;
1588 goto done;
1589 }
1590 }
1591
1592 if ((tx = fax_tx(pvt->fax_state, buf, write_codec.implementation->samples_per_packet)) < 0) {
1593 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1593, (const char*)(session)
, SWITCH_LOG_ERROR, "fax_tx reported an error\n");
1594 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "fax_tx reported an error")switch_channel_set_variable_var_check(channel, "current_application_response"
, "fax_tx reported an error", SWITCH_TRUE)
;
1595 goto done;
1596 }
1597
1598 if (!tx) {
1599 /* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No audio samples to send\n"); */
1600 continue;
1601 } else {
1602 /* Set our write_frame data */
1603 write_frame.datalen = tx * sizeof(int16_t);
1604 write_frame.samples = tx;
1605 }
1606
1607 if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
1608 goto done;
1609 }
1610
1611 }
1612
1613 done:
1614 /* Destroy the SpanDSP structures */
1615 spanfax_destroy(pvt);
1616
1617 /* restore the original codecs over the channel */
1618
1619 switch_core_session_set_read_codec(session, NULL((void*)0));
1620
1621 if (switch_core_codec_ready(&read_codec)) {
1622 switch_core_codec_destroy(&read_codec);
1623 }
1624
1625 if (switch_core_codec_ready(&write_codec)) {
1626 switch_core_codec_destroy(&write_codec);
1627 }
1628}
1629
1630void mod_spandsp_fax_load(switch_memory_pool_t *pool)
1631{
1632 uint32_t sanity = 200;
1633
1634 memset(&t38_state_list, 0, sizeof(t38_state_list));
1635
1636 switch_mutex_init(&spandsp_globals.mutex, SWITCH_MUTEX_NESTED0x1, spandsp_globals.pool);
1637 switch_mutex_init(&t38_state_list.mutex, SWITCH_MUTEX_NESTED0x1, spandsp_globals.pool);
1638
1639 switch_mutex_init(&spandsp_globals.cond_mutex, SWITCH_MUTEX_NESTED0x1, spandsp_globals.pool);
1640 switch_thread_cond_create(&spandsp_globals.cond, spandsp_globals.pool);
1641
1642 launch_timer_thread();
1643
1644 while(--sanity && !t38_state_list.thread_running) {
1645 switch_yield(20000)switch_sleep(20000);;
1646 }
1647}
1648
1649void mod_spandsp_fax_shutdown(void)
1650{
1651 switch_status_t tstatus = SWITCH_STATUS_SUCCESS;
1652
1653 t38_state_list.thread_running = 0;
1654 wake_thread(1);
1655 switch_thread_join(&tstatus, t38_state_list.thread);
1656}
1657
1658static const switch_state_handler_table_t t38_gateway_state_handlers;
1659
1660static switch_status_t t38_gateway_on_soft_execute(switch_core_session_t *session)
1661{
1662 switch_core_session_t *other_session;
1663
1664 switch_channel_t *other_channel, *channel = switch_core_session_get_channel(session);
1665 pvt_t *pvt;
1666 const char *peer_uuid = switch_channel_get_variable(channel, "t38_peer")switch_channel_get_variable_dup(channel, "t38_peer", SWITCH_TRUE
, -1)
;
1667 switch_core_session_message_t msg = { 0 };
1668 switch_status_t status;
1669 switch_frame_t *read_frame = { 0 };
1670
1671 if (!(other_session = switch_core_session_locate(peer_uuid)switch_core_session_perform_locate(peer_uuid, "mod_spandsp_fax.c"
, (const char *)__func__, 1671)
)) {
1672 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_spandsp_fax.c", (
const char *)__func__, 1672, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
1673 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1673, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Cannot locate channel with uuid %s",
1674 switch_channel_get_name(channel), peer_uuid);
1675 goto end;
1676 }
1677
1678 other_channel = switch_core_session_get_channel(other_session);
1679
1680 pvt = pvt_init(session, FUNCTION_GW);
1681 request_t38(pvt);
1682
1683 msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
1684 msg.from = __FILE__"mod_spandsp_fax.c";
1685 msg.string_arg = peer_uuid;
1686 switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg
, "mod_spandsp_fax.c", (const char *)__func__, 1686)
;
1687
1688 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_up(other_channel)(switch_channel_check_signal(other_channel, SWITCH_TRUE) || switch_channel_get_state
(other_channel) < CS_HANGUP)
&& !switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) {
1689 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1690
1691 if (pvt->done) {
1692 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1692, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Premature exit while negotiating\n", switch_channel_get_name(channel));
1693 /* Our duty is over */
1694 goto end_unlock;
1695 }
1696
1697 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
) {
1698 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1698, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Read failed, status=%u\n", switch_channel_get_name(channel), status);
1699 goto end_unlock;
1700 }
1701
1702 if (switch_test_flag(read_frame, SFF_CNG)((read_frame)->flags & SFF_CNG)) {
1703 continue;
1704 }
1705
1706 if (switch_core_session_write_frame(other_session, read_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
1707 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1707, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Write failed\n", switch_channel_get_name(channel));
1708 goto end_unlock;
1709 }
1710 }
1711
1712 if (!(switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_up(other_channel)(switch_channel_check_signal(other_channel, SWITCH_TRUE) || switch_channel_get_state
(other_channel) < CS_HANGUP)
)) {
1713 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1713, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Channel not ready\n", switch_channel_get_name(channel));
1714 goto end_unlock;
1715 }
1716
1717 if (!switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) {
1718 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_spandsp_fax.c", (
const char *)__func__, 1718, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
1719 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1719, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Could not negotiate T38\n", switch_channel_get_name(channel));
1720 goto end_unlock;
1721 }
1722
1723 if (pvt->t38_mode == T38_MODE_REQUESTED) {
1724 spanfax_init(pvt, T38_GATEWAY_MODE);
1725 configure_t38(pvt);
1726 pvt->t38_mode = T38_MODE_NEGOTIATED;
1727 switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_NEGOTIATED);
1728 } else {
1729 if (negotiate_t38(pvt) != T38_MODE_NEGOTIATED) {
1730 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1730, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Could not negotiate T38\n", switch_channel_get_name(channel));
1731 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_spandsp_fax.c", (
const char *)__func__, 1731, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
1732 goto end_unlock;
1733 }
1734 switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_NEGOTIATED);
1735 spanfax_init(pvt, T38_GATEWAY_MODE);
1736 }
1737
1738 /* This will change the rtp stack to udptl mode */
1739 msg.from = __FILE__"mod_spandsp_fax.c";
1740 msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE;
1741 switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg
, "mod_spandsp_fax.c", (const char *)__func__, 1741)
;
1742
1743
1744 /* wake up the audio side */
1745 switch_channel_set_private(channel, "_t38_pvt", pvt);
1746 switch_channel_set_app_flag_key("T38", other_channel, CF_APP_T38);
1747
1748
1749 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_up(other_channel)(switch_channel_check_signal(other_channel, SWITCH_TRUE) || switch_channel_get_state
(other_channel) < CS_HANGUP)
) {
1750
1751 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1752
1753 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
|| pvt->done) {
1754 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1754, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Premature exit while negotiating (%i)\n", switch_channel_get_name(channel), status);
1755 /* Our duty is over */
1756 goto end_unlock;
1757 }
1758
1759 if (switch_test_flag(read_frame, SFF_CNG)((read_frame)->flags & SFF_CNG)) {
1760 continue;
1761 }
1762
1763 if (switch_test_flag(read_frame, SFF_UDPTL_PACKET)((read_frame)->flags & SFF_UDPTL_PACKET)) {
1764 if (udptl_rx_packet(pvt->udptl_state, read_frame->packet, read_frame->packetlen) < 0) {
1765 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1765, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s Error decoding UDPTL (%u bytes)\n", switch_channel_get_name(channel), read_frame->packetlen);
1766 }
1767 }
1768 }
1769
1770 end_unlock:
1771
1772
1773 msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
1774 msg.from = __FILE__"mod_spandsp_fax.c";
1775 msg.string_arg = peer_uuid;
1776 switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg
, "mod_spandsp_fax.c", (const char *)__func__, 1776)
;
1777
1778 switch_channel_hangup(other_channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(other_channel, "mod_spandsp_fax.c"
, (const char *)__func__, 1778, SWITCH_CAUSE_NORMAL_CLEARING)
;
1779 switch_core_session_rwunlock(other_session);
1780
1781 end:
1782
1783 switch_channel_clear_state_handler(channel, &t38_gateway_state_handlers);
1784 switch_channel_set_variable(channel, "t38_peer", NULL)switch_channel_set_variable_var_check(channel, "t38_peer", ((
void*)0), SWITCH_TRUE)
;
1785
1786 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(channel, "mod_spandsp_fax.c", (
const char *)__func__, 1786, SWITCH_CAUSE_NORMAL_CLEARING)
;
1787 return SWITCH_STATUS_SUCCESS;
1788}
1789
1790static switch_status_t t38_gateway_on_consume_media(switch_core_session_t *session)
1791{
1792 switch_core_session_t *other_session;
1793 switch_channel_t *other_channel, *channel = switch_core_session_get_channel(session);
1794 const char *peer_uuid = switch_channel_get_variable(channel, "t38_peer")switch_channel_get_variable_dup(channel, "t38_peer", SWITCH_TRUE
, -1)
;
1795 pvt_t *pvt = NULL((void*)0);
1796 switch_codec_t read_codec = { 0 };
1797 switch_codec_t write_codec = { 0 };
1798 switch_frame_t *read_frame = { 0 };
1799 switch_frame_t write_frame = { 0 };
1800 switch_codec_implementation_t read_impl = { 0 };
1801 int16_t *buf = NULL((void*)0);
1802 switch_status_t status;
1803 int tx;
1804 const char *t38_trace = switch_channel_get_variable(channel, "t38_trace")switch_channel_get_variable_dup(channel, "t38_trace", SWITCH_TRUE
, -1)
;
1805 char *trace_read, *trace_write;
1806 zap_socket_t read_fd = FAX_INVALID_SOCKET-1, write_fd = FAX_INVALID_SOCKET-1;
1807 switch_core_session_message_t msg = { 0 };
1808 switch_event_t *event;
1809
1810 switch_core_session_get_read_impl(session, &read_impl);
1811
1812 buf = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE)switch_core_perform_session_alloc(session, 8192, "mod_spandsp_fax.c"
, (const char *)__func__, 1812)
;
1813
1814 if (!(other_session = switch_core_session_locate(peer_uuid)switch_core_session_perform_locate(peer_uuid, "mod_spandsp_fax.c"
, (const char *)__func__, 1814)
)) {
1815 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_spandsp_fax.c", (
const char *)__func__, 1815, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
1816 goto end;
1817 }
1818
1819 other_channel = switch_core_session_get_channel(other_session);
1820
1821 msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
1822 msg.from = __FILE__"mod_spandsp_fax.c";
1823 msg.string_arg = peer_uuid;
1824 switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg
, "mod_spandsp_fax.c", (const char *)__func__, 1824)
;
1825
1826 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_BRIDGE)switch_event_create_subclass_detailed("mod_spandsp_fax.c", (const
char * )(const char *)__func__, 1826, &event, SWITCH_EVENT_CHANNEL_BRIDGE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
1827 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(session));
1828 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", peer_uuid);
1829 switch_channel_event_set_data(channel, event);
1830 switch_event_fire(&event)switch_event_fire_detailed("mod_spandsp_fax.c", (const char *
)(const char *)__func__, 1830, &event, ((void*)0))
;
1831 }
1832
1833 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_up(other_channel)(switch_channel_check_signal(other_channel, SWITCH_TRUE) || switch_channel_get_state
(other_channel) < CS_HANGUP)
&& !switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) {
1834 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1835
1836 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
) {
1837 /* Our duty is over */
1838 goto end_unlock;
1839 }
1840
1841 if (switch_test_flag(read_frame, SFF_CNG)((read_frame)->flags & SFF_CNG)) {
1842 continue;
1843 }
1844
1845 if (switch_core_session_write_frame(other_session, read_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
1846 goto end_unlock;
1847 }
1848 }
1849
1850 if (!(switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_up(other_channel)(switch_channel_check_signal(other_channel, SWITCH_TRUE) || switch_channel_get_state
(other_channel) < CS_HANGUP)
)) {
1851 goto end_unlock;
1852 }
1853
1854 if (!switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) {
1855 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_spandsp_fax.c", (
const char *)__func__, 1855, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
1856 goto end_unlock;
1857 }
1858
1859 if (!(pvt = switch_channel_get_private(other_channel, "_t38_pvt"))) {
1860 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_spandsp_fax.c", (
const char *)__func__, 1860, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
)
;
1861 goto end_unlock;
1862 }
1863
1864 if (switch_core_codec_init(&read_codec,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1865 "L16",switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1866 NULL,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1867 read_impl.samples_per_second,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1868 read_impl.microseconds_per_packet / 1000,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1869 1,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1870 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1871 NULL, switch_core_session_get_pool(session))switch_core_codec_init_with_bitrate(&read_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
== SWITCH_STATUS_SUCCESS) {
1872 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1872, (const char*)(session)
, SWITCH_LOG_DEBUG, "Raw read codec activation Success L16 %u\n",
1873 read_codec.implementation->microseconds_per_packet);
1874 switch_core_session_set_read_codec(session, &read_codec);
1875 } else {
1876 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1876, (const char*)(session)
, SWITCH_LOG_ERROR, "Raw read codec activation Failed L16\n");
1877 goto end_unlock;
1878 }
1879
1880 if (switch_core_codec_init(&write_codec,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1881 "L16",switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1882 NULL,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1883 read_impl.samples_per_second,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1884 read_impl.microseconds_per_packet / 1000,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1885 1,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1886 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
1887 NULL, switch_core_session_get_pool(session))switch_core_codec_init_with_bitrate(&write_codec, "L16", (
(void*)0), read_impl.samples_per_second, read_impl.microseconds_per_packet
/ 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
, ((void*)0), switch_core_session_get_pool(session))
== SWITCH_STATUS_SUCCESS) {
1888 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1888, (const char*)(session)
, SWITCH_LOG_DEBUG, "Raw write codec activation Success L16\n");
1889 write_frame.codec = &write_codec;
1890 write_frame.data = buf;
1891 write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE8192;
1892 } else {
1893 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1893, (const char*)(session)
, SWITCH_LOG_ERROR, "Raw write codec activation Failed L16\n");
1894 goto end_unlock;
1895 }
1896
1897 switch_ivr_sleep(session, 0, SWITCH_TRUE, NULL((void*)0));
1898
1899 if (switch_true(t38_trace)) {
1900 trace_read = switch_core_session_sprintf(session, "%s%s%s_read.raw", SWITCH_GLOBAL_dirs.temp_dir,
1901 SWITCH_PATH_SEPARATOR"/", switch_core_session_get_uuid(session));
1902
1903 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1903, (const char*)(session)
, SWITCH_LOG_WARNING, "Tracing inbound audio to %s\n", trace_read);
1904 switch_channel_set_variable(channel, "t38_trace_read", trace_read)switch_channel_set_variable_var_check(channel, "t38_trace_read"
, trace_read, SWITCH_TRUE)
;
1905
1906 trace_write = switch_core_session_sprintf(session, "%s%s%s_write.raw", SWITCH_GLOBAL_dirs.temp_dir,
1907 SWITCH_PATH_SEPARATOR"/", switch_core_session_get_uuid(session));
1908
1909 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1909, (const char*)(session)
, SWITCH_LOG_WARNING, "Tracing outbound audio to %s\n", trace_write);
1910 switch_channel_set_variable(channel, "t38_trace_read", trace_write)switch_channel_set_variable_var_check(channel, "t38_trace_read"
, trace_write, SWITCH_TRUE)
;
1911
1912
1913 if ((write_fd = open(trace_read, O_WRONLY01 | O_CREAT0100 | O_TRUNC01000, S_IRUSR0400 | S_IWUSR0200)) != FAX_INVALID_SOCKET-1) {
1914 if ((read_fd = open(trace_write, O_WRONLY01 | O_CREAT0100 | O_TRUNC01000, S_IRUSR0400 | S_IWUSR0200)) == FAX_INVALID_SOCKET-1) {
1915 close(write_fd);
1916 write_fd = FAX_INVALID_SOCKET-1;
1917 }
1918 }
1919 }
1920
1921 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_up(other_channel)(switch_channel_check_signal(other_channel, SWITCH_TRUE) || switch_channel_get_state
(other_channel) < CS_HANGUP)
) {
1922 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
1923
1924 if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK
|| status == SWITCH_STATUS_INUSE)
|| pvt->done) {
1925 /* Our duty is over */
1926 goto end_unlock;
1927 }
1928
1929 if (switch_test_flag(read_frame, SFF_CNG)((read_frame)->flags & SFF_CNG)) {
1930 /* We have no real signal data for the FAX software, but we have a space in time if we have a CNG indication.
1931 Do a fill-in operation in the FAX machine, to keep things rolling along. */
1932 t38_gateway_rx_fillin(pvt->t38_gateway_state, read_impl.samples_per_packet);
1933 } else {
1934 if (read_fd != FAX_INVALID_SOCKET-1) {
1935 switch_ssize_t rv;
1936 do { rv = write(read_fd, read_frame->data, read_frame->datalen); } while (rv == -1 && errno(*__errno_location ()) == EINTR4);
1937 }
1938 if (t38_gateway_rx(pvt->t38_gateway_state, (int16_t *) read_frame->data, read_frame->samples)) {
1939 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1939, (const char*)(session)
, SWITCH_LOG_ERROR, "fax_rx reported an error\n");
1940 goto end_unlock;
1941 }
1942 }
1943
1944 if ((tx = t38_gateway_tx(pvt->t38_gateway_state, buf, write_codec.implementation->samples_per_packet)) < 0) {
1945 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 1945, (const char*)(session)
, SWITCH_LOG_ERROR, "fax_tx reported an error\n");
1946 goto end_unlock;
1947 }
1948
1949 if (!tx) {
1950 /* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No audio samples to send\n"); */
1951 continue;
1952 } else {
1953 /* Set our write_frame data */
1954 write_frame.datalen = tx * sizeof(int16_t);
1955 write_frame.samples = tx;
1956 }
1957
1958 if (write_fd != FAX_INVALID_SOCKET-1) {
1959 switch_ssize_t rv;
1960 do { rv = write(write_fd, write_frame.data, write_frame.datalen); } while (rv == -1 && errno(*__errno_location ()) == EINTR4);
1961 }
1962
1963 if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
1964 goto end_unlock;
1965 }
1966 }
1967
1968 end_unlock:
1969
1970 msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
1971 msg.from = __FILE__"mod_spandsp_fax.c";
1972 msg.string_arg = peer_uuid;
1973 switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg
, "mod_spandsp_fax.c", (const char *)__func__, 1973)
;
1974
1975
1976 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE)switch_event_create_subclass_detailed("mod_spandsp_fax.c", (const
char * )(const char *)__func__, 1976, &event, SWITCH_EVENT_CHANNEL_UNBRIDGE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
1977 switch_channel_event_set_data(channel, event);
1978 switch_event_fire(&event)switch_event_fire_detailed("mod_spandsp_fax.c", (const char *
)(const char *)__func__, 1978, &event, ((void*)0))
;
1979 }
1980
1981 if (read_fd != FAX_INVALID_SOCKET-1) {
1982 close(read_fd);
1983 read_fd = FAX_INVALID_SOCKET-1;
1984 }
1985
1986 if (write_fd != FAX_INVALID_SOCKET-1) {
1987 close(write_fd);
1988 write_fd = FAX_INVALID_SOCKET-1;
Value stored to 'write_fd' is never read
1989 }
1990
1991
1992 switch_channel_hangup(other_channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(other_channel, "mod_spandsp_fax.c"
, (const char *)__func__, 1992, SWITCH_CAUSE_NORMAL_CLEARING)
;
1993 switch_core_session_rwunlock(other_session);
1994
1995 switch_core_session_set_read_codec(session, NULL((void*)0));
1996
1997 if (switch_core_codec_ready(&read_codec)) {
1998 switch_core_codec_destroy(&read_codec);
1999 }
2000
2001 if (switch_core_codec_ready(&write_codec)) {
2002 switch_core_codec_destroy(&write_codec);
2003 }
2004
2005
2006 end:
2007
2008 switch_channel_clear_state_handler(channel, &t38_gateway_state_handlers);
2009 switch_channel_set_variable(channel, "t38_peer", NULL)switch_channel_set_variable_var_check(channel, "t38_peer", ((
void*)0), SWITCH_TRUE)
;
2010 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(channel, "mod_spandsp_fax.c", (
const char *)__func__, 2010, SWITCH_CAUSE_NORMAL_CLEARING)
;
2011
2012 return SWITCH_STATUS_SUCCESS;
2013}
2014
2015static switch_status_t t38_gateway_on_reset(switch_core_session_t *session)
2016{
2017 switch_channel_t *channel = switch_core_session_get_channel(session);
2018
2019 switch_channel_set_variable(channel, "rtp_autoflush_during_bridge", "false")switch_channel_set_variable_var_check(channel, "rtp_autoflush_during_bridge"
, "false", SWITCH_TRUE)
;
2020
2021 switch_channel_clear_flag(channel, CF_REDIRECT);
2022
2023 if (switch_channel_test_app_flag_key("T38", channel, CF_APP_TAGGED)) {
2024 switch_channel_clear_app_flag_key("T38", channel, CF_APP_TAGGED);
2025 switch_channel_set_state(channel, CS_CONSUME_MEDIA)switch_channel_perform_set_state(channel, "mod_spandsp_fax.c"
, (const char *)__func__, 2025, CS_CONSUME_MEDIA)
;
2026 } else {
2027 switch_channel_set_state(channel, CS_SOFT_EXECUTE)switch_channel_perform_set_state(channel, "mod_spandsp_fax.c"
, (const char *)__func__, 2027, CS_SOFT_EXECUTE)
;
2028 }
2029
2030 return SWITCH_STATUS_SUCCESS;
2031}
2032
2033static const switch_state_handler_table_t t38_gateway_state_handlers = {
2034 /*.on_init */ NULL((void*)0),
2035 /*.on_routing */ NULL((void*)0),
2036 /*.on_execute */ NULL((void*)0),
2037 /*.on_hangup */ NULL((void*)0),
2038 /*.on_exchange_media */ NULL((void*)0),
2039 /*.on_soft_execute */ t38_gateway_on_soft_execute,
2040 /*.on_consume_media */ t38_gateway_on_consume_media,
2041 /*.on_hibernate */ NULL((void*)0),
2042 /*.on_reset */ t38_gateway_on_reset,
2043 /*.on_park */ NULL((void*)0),
2044 /*.on_reporting */ NULL((void*)0),
2045 /*.on_destroy */ NULL((void*)0),
2046 SSH_FLAG_STICKY
2047};
2048
2049switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app, const char *data)
2050{
2051 switch_channel_t *other_channel = NULL((void*)0), *channel = switch_core_session_get_channel(session);
2052 switch_core_session_t *other_session = NULL((void*)0);
2053 int peer = app && !strcasecmp(app, "peer");
2054
2055 if (switch_core_session_get_partner(session, &other_session)switch_core_session_perform_get_partner(session, &other_session
, "mod_spandsp_fax.c", (const char *)__func__, 2055)
== SWITCH_STATUS_SUCCESS) {
2056 other_channel = switch_core_session_get_channel(other_session);
2057
2058 switch_channel_set_variable(channel, "t38_peer", switch_core_session_get_uuid(other_session))switch_channel_set_variable_var_check(channel, "t38_peer", switch_core_session_get_uuid
(other_session), SWITCH_TRUE)
;
2059 switch_channel_set_variable(other_channel, "t38_peer", switch_core_session_get_uuid(session))switch_channel_set_variable_var_check(other_channel, "t38_peer"
, switch_core_session_get_uuid(session), SWITCH_TRUE)
;
2060
2061 switch_channel_set_variable(peer ? other_channel : channel, "t38_gateway_format", "udptl")switch_channel_set_variable_var_check(peer ? other_channel : channel
, "t38_gateway_format", "udptl", SWITCH_TRUE)
;
2062 switch_channel_set_variable(peer ? channel : other_channel, "t38_gateway_format", "audio")switch_channel_set_variable_var_check(peer ? channel : other_channel
, "t38_gateway_format", "audio", SWITCH_TRUE)
;
2063
2064
2065 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 2065, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s starting gateway mode to %s\n",
2066 switch_channel_get_name(peer ? channel : other_channel),
2067 switch_channel_get_name(peer ? other_channel : channel));
2068
2069
2070 switch_channel_clear_state_handler(channel, NULL((void*)0));
2071 switch_channel_clear_state_handler(other_channel, NULL((void*)0));
2072
2073 switch_channel_add_state_handler(channel, &t38_gateway_state_handlers);
2074 switch_channel_add_state_handler(other_channel, &t38_gateway_state_handlers);
2075
2076 switch_channel_set_app_flag_key("T38", peer ? channel : other_channel, CF_APP_TAGGED);
2077 switch_channel_clear_app_flag_key("T38", peer ? other_channel : channel, CF_APP_TAGGED);
2078
2079 switch_channel_set_flag(channel, CF_REDIRECT)switch_channel_set_flag_value(channel, CF_REDIRECT, 1);
2080 switch_channel_set_state(channel, CS_RESET)switch_channel_perform_set_state(channel, "mod_spandsp_fax.c"
, (const char *)__func__, 2080, CS_RESET)
;
2081
2082 switch_channel_set_flag(other_channel, CF_REDIRECT)switch_channel_set_flag_value(other_channel, CF_REDIRECT, 1);
2083 switch_channel_set_state(other_channel, CS_RESET)switch_channel_perform_set_state(other_channel, "mod_spandsp_fax.c"
, (const char *)__func__, 2083, CS_RESET)
;
2084
2085 switch_core_session_rwunlock(other_session);
2086
2087 }
2088
2089 return SWITCH_FALSE;
2090}
2091
2092typedef struct {
2093 char *app;
2094 char *data;
2095 char *key;
2096 int up;
2097 int tone_type;
2098 int total_hits;
2099 int hits;
2100 int sleep;
2101 int expires;
2102 int default_sleep;
2103 int default_expires;
2104 switch_tone_detect_callback_t callback;
2105 modem_connect_tones_rx_state_t rx_tones;
2106
2107 switch_media_bug_t *bug;
2108 switch_core_session_t *session;
2109 int bug_running;
2110
2111} spandsp_fax_tone_container_t;
2112
2113static switch_status_t tone_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
2114{
2115 switch_channel_t *channel = switch_core_session_get_channel(session);
2116 spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
2117
2118
2119 if (!cont || dtmf->digit != 'f') {
2120 return SWITCH_STATUS_SUCCESS;
2121 }
2122
2123 if (cont->callback) {
2124 cont->callback(cont->session, cont->app, cont->data);
2125 } else {
2126 switch_channel_execute_on(switch_core_session_get_channel(cont->session), "execute_on_fax_detect");
2127 if (cont->app) {
2128 switch_core_session_execute_application_async(cont->session, cont->app, cont->data);
2129 }
2130 }
2131
2132 return SWITCH_STATUS_SUCCESS;
2133
2134}
2135
2136
2137static switch_bool_t tone_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
2138{
2139 spandsp_fax_tone_container_t *cont = (spandsp_fax_tone_container_t *) user_data;
2140 switch_frame_t *frame = NULL((void*)0);
2141 switch_bool_t rval = SWITCH_TRUE;
2142
2143 switch (type) {
2144 case SWITCH_ABC_TYPE_INIT:
2145 if (cont) {
2146 cont->bug_running = 1;
2147 modem_connect_tones_rx_init(&cont->rx_tones, cont->tone_type, NULL((void*)0), NULL((void*)0));
2148 }
2149 break;
2150 case SWITCH_ABC_TYPE_CLOSE:
2151 break;
2152 case SWITCH_ABC_TYPE_READ_REPLACE:
2153 case SWITCH_ABC_TYPE_WRITE_REPLACE:
2154 {
2155 int skip = 0;
2156
2157 if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
2158 frame = switch_core_media_bug_get_read_replace_frame(bug);
2159 } else {
2160 frame = switch_core_media_bug_get_write_replace_frame(bug);
2161 }
2162
2163 if (cont->sleep) {
2164 cont->sleep--;
2165 if (cont->sleep) {
2166 skip = 1;
2167 }
2168 }
2169
2170 if (cont->expires) {
2171 cont->expires--;
2172 if (!cont->expires) {
2173 cont->hits = 0;
2174 cont->sleep = 0;
2175 cont->expires = 0;
2176 }
2177 }
2178
2179 if (!cont->up) {
2180 skip = 1;
2181 }
2182
2183 if (skip) {
2184 return SWITCH_TRUE;
2185 }
2186
2187 cont->hits = 0;
2188 modem_connect_tones_rx(&cont->rx_tones, frame->data, frame->samples);
2189 cont->hits = modem_connect_tones_rx_get(&cont->rx_tones);
2190
2191 if (cont->hits) {
2192 switch_event_t *event;
2193
2194 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug))SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 2194, (const char*)(switch_core_media_bug_get_session
(bug))
, SWITCH_LOG_DEBUG,
2195 "Fax Tone Detected. [%s][%s]\n", cont->app, switch_str_nil(cont->data)(cont->data ? cont->data : ""));
2196
2197 if (cont->callback) {
2198 cont->callback(cont->session, cont->app, cont->data);
2199 } else {
2200 switch_channel_execute_on(switch_core_session_get_channel(cont->session), "execute_on_fax_detect");
2201 if (cont->app) {
2202 switch_core_session_execute_application_async(cont->session, cont->app, cont->data);
2203 }
2204 }
2205
2206
2207 if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE)switch_event_create_subclass_detailed("mod_spandsp_fax.c", (const
char * )(const char *)__func__, 2207, &event, SWITCH_EVENT_DETECTED_TONE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2208 switch_event_t *dup;
2209 switch_core_session_t *session = NULL((void*)0);
2210 switch_channel_t *channel = NULL((void*)0);
2211
2212 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detected-Fax-Tone", "true");
2213
2214 session = switch_core_media_bug_get_session(bug);
2215 if (session) {
2216 channel = switch_core_session_get_channel(session);
2217 if (channel) switch_channel_event_set_data(channel, event);
2218 }
2219
2220 if (switch_event_dup(&dup, event) == SWITCH_STATUS_SUCCESS) {
2221 switch_event_fire(&dup)switch_event_fire_detailed("mod_spandsp_fax.c", (const char *
)(const char *)__func__, 2221, &dup, ((void*)0))
;
2222 }
2223
2224 if (switch_core_session_queue_event(cont->session, &event) != SWITCH_STATUS_SUCCESS) {
2225 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug))SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 2225, (const char*)(switch_core_media_bug_get_session
(bug))
, SWITCH_LOG_ERROR,
2226 "Event queue failed!\n");
2227 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
2228 switch_event_fire(&event)switch_event_fire_detailed("mod_spandsp_fax.c", (const char *
)(const char *)__func__, 2228, &event, ((void*)0))
;
2229 }
2230 }
2231
2232 rval = SWITCH_FALSE;
2233 }
2234
2235 }
2236 break;
2237 case SWITCH_ABC_TYPE_WRITE:
2238 default:
2239 break;
2240 }
2241
2242 if (rval == SWITCH_FALSE) {
2243 cont->bug_running = 0;
2244 }
2245
2246 return rval;
2247}
2248
2249switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session)
2250{
2251 switch_channel_t *channel = switch_core_session_get_channel(session);
2252 spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
2253
2254 if (cont) {
2255 switch_channel_set_private(channel, "_fax_tone_detect_", NULL((void*)0));
2256 cont->up = 0;
2257 switch_core_media_bug_remove(session, &cont->bug);
2258 return SWITCH_STATUS_SUCCESS;
2259 }
2260 return SWITCH_STATUS_FALSE;
2261}
2262
2263switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
2264 const char *flags, int timeout, int tone_type,
2265 int hits, const char *app, const char *data, switch_tone_detect_callback_t callback)
2266{
2267 switch_channel_t *channel = switch_core_session_get_channel(session);
2268 switch_status_t status;
2269 time_t to = 0;
2270 spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
2271 switch_media_bug_flag_t bflags = 0;
2272 const char *var;
2273 switch_codec_implementation_t read_impl = { 0 };
2274 switch_core_session_get_read_impl(session, &read_impl);
2275
2276 if (timeout) {
2277 to = switch_epoch_time_now(NULL((void*)0)) + timeout;
2278 }
2279
2280 if (cont) {
2281 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_spandsp_fax.c", (const char *
)__func__, 2281, (const char*)(session)
, SWITCH_LOG_ERROR, "Max Tones Reached!\n");
2282 return SWITCH_STATUS_FALSE;
2283 }
2284
2285 if (!cont && !(cont = switch_core_session_alloc(session, sizeof(*cont))switch_core_perform_session_alloc(session, sizeof(*cont), "mod_spandsp_fax.c"
, (const char *)__func__, 2285)
)) {
2286 return SWITCH_STATUS_MEMERR;
2287 }
2288
2289 if (app) {
2290 cont->app = switch_core_session_strdup(session, app)switch_core_perform_session_strdup(session, app, "mod_spandsp_fax.c"
, (const char *)__func__, 2290)
;
2291 }
2292
2293 if (data) {
2294 cont->data = switch_core_session_strdup(session, data)switch_core_perform_session_strdup(session, data, "mod_spandsp_fax.c"
, (const char *)__func__, 2294)
;
2295 }
2296
2297 cont->tone_type = tone_type;
2298 cont->callback = callback;
2299 cont->up = 1;
2300 cont->session = session;
2301
2302 if (switch_channel_pre_answer(channel)switch_channel_perform_pre_answer(channel, "mod_spandsp_fax.c"
, (const char *)__func__, 2302)
!= SWITCH_STATUS_SUCCESS) {
2303 return SWITCH_STATUS_FALSE;
2304 }
2305
2306 cont->default_sleep = 25;
2307 cont->default_expires = 250;
2308
2309 if ((var = switch_channel_get_variable(channel, "fax_tone_detect_sleep")switch_channel_get_variable_dup(channel, "fax_tone_detect_sleep"
, SWITCH_TRUE, -1)
)) {
2310 int tmp = atoi(var);
2311 if (tmp > 0) {
2312 cont->default_sleep = tmp;
2313 }
2314 }
2315
2316 if ((var = switch_channel_get_variable(channel, "fax_tone_detect_expires")switch_channel_get_variable_dup(channel, "fax_tone_detect_expires"
, SWITCH_TRUE, -1)
)) {
2317 int tmp = atoi(var);
2318 if (tmp > 0) {
2319 cont->default_expires = tmp;
2320 }
2321 }
2322
2323 if (zstr(flags)_zstr(flags)) {
2324 bflags = SMBF_READ_REPLACE;
2325 } else {
2326 if (strchr(flags, 'r')(__extension__ (__builtin_constant_p ('r') && !__builtin_constant_p
(flags) && ('r') == '\0' ? (char *) __rawmemchr (flags
, 'r') : __builtin_strchr (flags, 'r')))
) {
2327 bflags |= SMBF_READ_REPLACE;
2328 } else if (strchr(flags, 'w')(__extension__ (__builtin_constant_p ('w') && !__builtin_constant_p
(flags) && ('w') == '\0' ? (char *) __rawmemchr (flags
, 'w') : __builtin_strchr (flags, 'w')))
) {
2329 bflags |= SMBF_WRITE_REPLACE;
2330 }
2331 }
2332
2333 bflags |= SMBF_NO_PAUSE;
2334
2335
2336 switch_core_event_hook_add_send_dtmf(session, tone_on_dtmf);
2337 switch_core_event_hook_add_recv_dtmf(session, tone_on_dtmf);
2338
2339
2340 if ((status = switch_core_media_bug_add(session, "fax_tone_detect", "",
2341 tone_detect_callback, cont, to, bflags, &cont->bug)) != SWITCH_STATUS_SUCCESS) {
2342 cont->bug_running = 0;
2343 return status;
2344 }
2345
2346 switch_channel_set_private(channel, "_fax_tone_detect_", cont);
2347
2348 return SWITCH_STATUS_SUCCESS;
2349}
2350
2351
2352
2353
2354/* For Emacs:
2355 * Local Variables:
2356 * mode:c
2357 * indent-tabs-mode:nil
2358 * tab-width:4
2359 * c-basic-offset:4
2360 * End:
2361 * For VIM:
2362 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
2363 */