Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/src/t38_terminal.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
| author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
|---|---|
| date | Fri, 25 Jun 2010 15:50:58 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 3:c6c5a16ce2f2 | 4:26cd8f1ef0b1 |
|---|---|
| 1 /* | |
| 2 * SpanDSP - a series of DSP components for telephony | |
| 3 * | |
| 4 * t38_terminal.c - T.38 termination, less the packet exchange part | |
| 5 * | |
| 6 * Written by Steve Underwood <steveu@coppice.org> | |
| 7 * | |
| 8 * Copyright (C) 2005, 2006, 2008 Steve Underwood | |
| 9 * | |
| 10 * All rights reserved. | |
| 11 * | |
| 12 * This program is free software; you can redistribute it and/or modify | |
| 13 * it under the terms of the GNU Lesser General Public License version 2.1, | |
| 14 * as published by the Free Software Foundation. | |
| 15 * | |
| 16 * This program is distributed in the hope that it will be useful, | |
| 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 * GNU Lesser General Public License for more details. | |
| 20 * | |
| 21 * You should have received a copy of the GNU Lesser General Public | |
| 22 * License along with this program; if not, write to the Free Software | |
| 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
| 24 * | |
| 25 * $Id: t38_terminal.c,v 1.129.4.2 2009/12/19 10:44:10 steveu Exp $ | |
| 26 */ | |
| 27 | |
| 28 /*! \file */ | |
| 29 | |
| 30 #if defined(HAVE_CONFIG_H) | |
| 31 #include "config.h" | |
| 32 #endif | |
| 33 | |
| 34 #include <inttypes.h> | |
| 35 #include <stdlib.h> | |
| 36 #include <stdio.h> | |
| 37 #include <fcntl.h> | |
| 38 #include <time.h> | |
| 39 #include <string.h> | |
| 40 #if defined(HAVE_TGMATH_H) | |
| 41 #include <tgmath.h> | |
| 42 #endif | |
| 43 #if defined(HAVE_MATH_H) | |
| 44 #include <math.h> | |
| 45 #endif | |
| 46 #include "floating_fudge.h" | |
| 47 #include <assert.h> | |
| 48 #include <tiffio.h> | |
| 49 | |
| 50 #include "spandsp/telephony.h" | |
| 51 #include "spandsp/logging.h" | |
| 52 #include "spandsp/bit_operations.h" | |
| 53 #include "spandsp/queue.h" | |
| 54 #include "spandsp/power_meter.h" | |
| 55 #include "spandsp/complex.h" | |
| 56 #include "spandsp/tone_generate.h" | |
| 57 #include "spandsp/async.h" | |
| 58 #include "spandsp/hdlc.h" | |
| 59 #include "spandsp/fsk.h" | |
| 60 #include "spandsp/v29tx.h" | |
| 61 #include "spandsp/v29rx.h" | |
| 62 #include "spandsp/v27ter_tx.h" | |
| 63 #include "spandsp/v27ter_rx.h" | |
| 64 #include "spandsp/v17tx.h" | |
| 65 #include "spandsp/v17rx.h" | |
| 66 #include "spandsp/t4_rx.h" | |
| 67 #include "spandsp/t4_tx.h" | |
| 68 #include "spandsp/t30_fcf.h" | |
| 69 #include "spandsp/t35.h" | |
| 70 #include "spandsp/t30.h" | |
| 71 #include "spandsp/t30_api.h" | |
| 72 #include "spandsp/t30_logging.h" | |
| 73 #include "spandsp/t38_core.h" | |
| 74 #include "spandsp/t38_terminal.h" | |
| 75 | |
| 76 #include "spandsp/private/logging.h" | |
| 77 #include "spandsp/private/t4_rx.h" | |
| 78 #include "spandsp/private/t4_tx.h" | |
| 79 #include "spandsp/private/t30.h" | |
| 80 #include "spandsp/private/t38_core.h" | |
| 81 #include "spandsp/private/t38_terminal.h" | |
| 82 | |
| 83 /* Settings suitable for paced transmission over a UDP transport */ | |
| 84 #define MS_PER_TX_CHUNK 30 | |
| 85 | |
| 86 #define INDICATOR_TX_COUNT 3 | |
| 87 #define DATA_TX_COUNT 1 | |
| 88 #define DATA_END_TX_COUNT 3 | |
| 89 | |
| 90 /* Settings suitable for unpaced transmission over a TCP transport */ | |
| 91 #define MAX_OCTETS_PER_UNPACED_CHUNK 300 | |
| 92 | |
| 93 /* Backstop timeout if reception of packets stops in the middle of a burst */ | |
| 94 #define MID_RX_TIMEOUT 15000 | |
| 95 | |
| 96 enum | |
| 97 { | |
| 98 T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001, | |
| 99 T38_CHUNKING_WHOLE_FRAMES = 0x0002, | |
| 100 T38_CHUNKING_ALLOW_TEP_TIME = 0x0004 | |
| 101 }; | |
| 102 | |
| 103 enum | |
| 104 { | |
| 105 T38_TIMED_STEP_NONE = 0, | |
| 106 T38_TIMED_STEP_NON_ECM_MODEM = 0x10, | |
| 107 T38_TIMED_STEP_NON_ECM_MODEM_2 = 0x11, | |
| 108 T38_TIMED_STEP_NON_ECM_MODEM_3 = 0x12, | |
| 109 T38_TIMED_STEP_NON_ECM_MODEM_4 = 0x13, | |
| 110 T38_TIMED_STEP_NON_ECM_MODEM_5 = 0x14, | |
| 111 T38_TIMED_STEP_HDLC_MODEM = 0x20, | |
| 112 T38_TIMED_STEP_HDLC_MODEM_2 = 0x21, | |
| 113 T38_TIMED_STEP_HDLC_MODEM_3 = 0x22, | |
| 114 T38_TIMED_STEP_HDLC_MODEM_4 = 0x23, | |
| 115 T38_TIMED_STEP_HDLC_MODEM_5 = 0x24, | |
| 116 T38_TIMED_STEP_CED = 0x30, | |
| 117 T38_TIMED_STEP_CED_2 = 0x31, | |
| 118 T38_TIMED_STEP_CED_3 = 0x32, | |
| 119 T38_TIMED_STEP_CNG = 0x40, | |
| 120 T38_TIMED_STEP_CNG_2 = 0x41, | |
| 121 T38_TIMED_STEP_PAUSE = 0x50 | |
| 122 }; | |
| 123 | |
| 124 static __inline__ void front_end_status(t38_terminal_state_t *s, int status) | |
| 125 { | |
| 126 t30_front_end_status(&s->t30, status); | |
| 127 } | |
| 128 /*- End of function --------------------------------------------------------*/ | |
| 129 | |
| 130 static __inline__ void hdlc_accept_frame(t38_terminal_state_t *s, const uint8_t *msg, int len, int ok) | |
| 131 { | |
| 132 t30_hdlc_accept(&s->t30, msg, len, ok); | |
| 133 } | |
| 134 /*- End of function --------------------------------------------------------*/ | |
| 135 | |
| 136 static int extra_bits_in_stuffed_frame(const uint8_t buf[], int len) | |
| 137 { | |
| 138 int bitstream; | |
| 139 int ones; | |
| 140 int stuffed; | |
| 141 int i; | |
| 142 int j; | |
| 143 | |
| 144 bitstream = 0; | |
| 145 ones = 0; | |
| 146 stuffed = 0; | |
| 147 /* We should really append the CRC, and include the stuffed bits for that, to get | |
| 148 the exact number of bits in the frame. */ | |
| 149 //len = crc_itu16_append(buf, len); | |
| 150 for (i = 0; i < len; i++) | |
| 151 { | |
| 152 bitstream = buf[i]; | |
| 153 for (j = 0; j < 8; j++) | |
| 154 { | |
| 155 if ((bitstream & 1)) | |
| 156 { | |
| 157 if (++ones >= 5) | |
| 158 { | |
| 159 ones = 0; | |
| 160 stuffed++; | |
| 161 } | |
| 162 } | |
| 163 else | |
| 164 { | |
| 165 ones = 0; | |
| 166 } | |
| 167 bitstream >>= 1; | |
| 168 } | |
| 169 } | |
| 170 /* The total length of the frame is: | |
| 171 the number of bits in the body | |
| 172 + the number of additional bits in the body due to stuffing | |
| 173 + the number of bits in the CRC | |
| 174 + the number of additional bits in the CRC due to stuffing | |
| 175 + 16 bits for the two terminating flag octets. | |
| 176 Lets just allow 3 bits for the CRC, which is the worst case. It | |
| 177 avoids calculating the real CRC, and the worst it can do is cause | |
| 178 a flag octet's worth of additional output. | |
| 179 */ | |
| 180 return stuffed + 16 + 3 + 16; | |
| 181 } | |
| 182 /*- End of function --------------------------------------------------------*/ | |
| 183 | |
| 184 static int process_rx_missing(t38_core_state_t *t, void *user_data, int rx_seq_no, int expected_seq_no) | |
| 185 { | |
| 186 t38_terminal_state_t *s; | |
| 187 | |
| 188 s = (t38_terminal_state_t *) user_data; | |
| 189 s->t38_fe.rx_data_missing = TRUE; | |
| 190 return 0; | |
| 191 } | |
| 192 /*- End of function --------------------------------------------------------*/ | |
| 193 | |
| 194 static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator) | |
| 195 { | |
| 196 t38_terminal_state_t *s; | |
| 197 t38_terminal_front_end_state_t *fe; | |
| 198 | |
| 199 s = (t38_terminal_state_t *) user_data; | |
| 200 fe = &s->t38_fe; | |
| 201 | |
| 202 if (t->current_rx_indicator == indicator) | |
| 203 { | |
| 204 /* This is probably due to the far end repeating itself, or slipping | |
| 205 preamble messages in between HDLC frames. T.38/V.1.3 tells us to | |
| 206 ignore it. Its harmless. */ | |
| 207 return 0; | |
| 208 } | |
| 209 /* In termination mode we don't care very much about indicators telling us training | |
| 210 is starting. We only care about V.21 preamble starting, for timeout control, and | |
| 211 the actual data. */ | |
| 212 switch (indicator) | |
| 213 { | |
| 214 case T38_IND_NO_SIGNAL: | |
| 215 if (t->current_rx_indicator == T38_IND_V21_PREAMBLE | |
| 216 && | |
| 217 (fe->current_rx_type == T30_MODEM_V21 || fe->current_rx_type == T30_MODEM_CNG)) | |
| 218 { | |
| 219 hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE); | |
| 220 } | |
| 221 fe->timeout_rx_samples = 0; | |
| 222 front_end_status(s, T30_FRONT_END_SIGNAL_ABSENT); | |
| 223 break; | |
| 224 case T38_IND_CNG: | |
| 225 /* We are completely indifferent to the startup tones. They serve no purpose for us. | |
| 226 We can't even assume that the existance of a tone means the far end is achieving | |
| 227 proper communication. Some T.38 gateways will just send out a CED or CNG indicator | |
| 228 without having seen anything from the far end FAX terminal. | |
| 229 Just report them for completeness. */ | |
| 230 front_end_status(s, T30_FRONT_END_CNG_PRESENT); | |
| 231 break; | |
| 232 case T38_IND_CED: | |
| 233 front_end_status(s, T30_FRONT_END_CED_PRESENT); | |
| 234 break; | |
| 235 case T38_IND_V21_PREAMBLE: | |
| 236 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
| 237 front_end_status(s, T30_FRONT_END_SIGNAL_PRESENT); | |
| 238 break; | |
| 239 case T38_IND_V27TER_2400_TRAINING: | |
| 240 case T38_IND_V27TER_4800_TRAINING: | |
| 241 case T38_IND_V29_7200_TRAINING: | |
| 242 case T38_IND_V29_9600_TRAINING: | |
| 243 case T38_IND_V17_7200_SHORT_TRAINING: | |
| 244 case T38_IND_V17_7200_LONG_TRAINING: | |
| 245 case T38_IND_V17_9600_SHORT_TRAINING: | |
| 246 case T38_IND_V17_9600_LONG_TRAINING: | |
| 247 case T38_IND_V17_12000_SHORT_TRAINING: | |
| 248 case T38_IND_V17_12000_LONG_TRAINING: | |
| 249 case T38_IND_V17_14400_SHORT_TRAINING: | |
| 250 case T38_IND_V17_14400_LONG_TRAINING: | |
| 251 case T38_IND_V34_CNTL_CHANNEL_1200: | |
| 252 case T38_IND_V34_PRI_CHANNEL: | |
| 253 case T38_IND_V33_12000_TRAINING: | |
| 254 case T38_IND_V33_14400_TRAINING: | |
| 255 /* We really don't care what kind of modem is delivering the following image data. | |
| 256 We only care that some kind of fast modem signal is coming next. */ | |
| 257 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
| 258 front_end_status(s, T30_FRONT_END_SIGNAL_PRESENT); | |
| 259 break; | |
| 260 case T38_IND_V8_ANSAM: | |
| 261 case T38_IND_V8_SIGNAL: | |
| 262 case T38_IND_V34_CC_RETRAIN: | |
| 263 /* V.34 support is a work in progress. */ | |
| 264 break; | |
| 265 default: | |
| 266 front_end_status(s, T30_FRONT_END_SIGNAL_ABSENT); | |
| 267 break; | |
| 268 } | |
| 269 /*endswitch*/ | |
| 270 fe->hdlc_rx.len = 0; | |
| 271 fe->rx_data_missing = FALSE; | |
| 272 return 0; | |
| 273 } | |
| 274 /*- End of function --------------------------------------------------------*/ | |
| 275 | |
| 276 static int fake_rx_indicator(t38_core_state_t *t, t38_terminal_state_t *s, int indicator) | |
| 277 { | |
| 278 int ret; | |
| 279 | |
| 280 ret = process_rx_indicator(t, s, indicator); | |
| 281 t->current_rx_indicator = indicator; | |
| 282 return ret; | |
| 283 } | |
| 284 /*- End of function --------------------------------------------------------*/ | |
| 285 | |
| 286 static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, int field_type, const uint8_t *buf, int len) | |
| 287 { | |
| 288 t38_terminal_state_t *s; | |
| 289 t38_terminal_front_end_state_t *fe; | |
| 290 #if defined(_MSC_VER) | |
| 291 uint8_t *buf2 = (uint8_t *) _alloca(len); | |
| 292 #else | |
| 293 uint8_t buf2[len]; | |
| 294 #endif | |
| 295 | |
| 296 s = (t38_terminal_state_t *) user_data; | |
| 297 fe = &s->t38_fe; | |
| 298 /* In termination mode we don't care very much what the data type is apart from a couple of | |
| 299 special cases. */ | |
| 300 switch (data_type) | |
| 301 { | |
| 302 case T38_DATA_V8: | |
| 303 switch (field_type) | |
| 304 { | |
| 305 case T38_FIELD_CM_MESSAGE: | |
| 306 if (len >= 1) | |
| 307 span_log(&s->logging, SPAN_LOG_FLOW, "CM profile %d - %s\n", buf[0] - '0', t38_cm_profile_to_str(buf[0])); | |
| 308 else | |
| 309 span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for CM message - %d\n", len); | |
| 310 //front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
| 311 break; | |
| 312 case T38_FIELD_JM_MESSAGE: | |
| 313 if (len >= 2) | |
| 314 span_log(&s->logging, SPAN_LOG_FLOW, "JM - %s\n", t38_jm_to_str(buf, len)); | |
| 315 else | |
| 316 span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for JM message - %d\n", len); | |
| 317 //front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
| 318 break; | |
| 319 case T38_FIELD_CI_MESSAGE: | |
| 320 if (len >= 1) | |
| 321 span_log(&s->logging, SPAN_LOG_FLOW, "CI 0x%X\n", buf[0]); | |
| 322 else | |
| 323 span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for CI message - %d\n", len); | |
| 324 //front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
| 325 break; | |
| 326 default: | |
| 327 break; | |
| 328 } | |
| 329 /*endswitch*/ | |
| 330 return 0; | |
| 331 case T38_DATA_V34_PRI_RATE: | |
| 332 switch (field_type) | |
| 333 { | |
| 334 case T38_FIELD_V34RATE: | |
| 335 if (len >= 3) | |
| 336 { | |
| 337 /* Just get and store the rate. The front end has no real interest in the | |
| 338 actual bit rate. */ | |
| 339 fe->t38.v34_rate = t38_v34rate_to_bps(buf, len); | |
| 340 span_log(&s->logging, SPAN_LOG_FLOW, "V.34 rate %d bps\n", fe->t38.v34_rate); | |
| 341 } | |
| 342 else | |
| 343 { | |
| 344 span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for V34rate message - %d\n", len); | |
| 345 } | |
| 346 break; | |
| 347 default: | |
| 348 break; | |
| 349 } | |
| 350 /*endswitch*/ | |
| 351 return 0; | |
| 352 default: | |
| 353 break; | |
| 354 } | |
| 355 /*endswitch*/ | |
| 356 switch (field_type) | |
| 357 { | |
| 358 case T38_FIELD_HDLC_DATA: | |
| 359 if (fe->timeout_rx_samples == 0) | |
| 360 { | |
| 361 /* HDLC can just start without any signal indicator on some platforms, even when | |
| 362 there is zero packet lost. Nasty, but true. Its a good idea to be tolerant of | |
| 363 loss, though, so accepting a sudden start of HDLC data is the right thing to do. */ | |
| 364 fake_rx_indicator(t, s, T38_IND_V21_PREAMBLE); | |
| 365 /* All real HDLC messages in the FAX world start with 0xFF. If this one is not starting | |
| 366 with 0xFF it would appear some octets must have been missed before this one. */ | |
| 367 if (len <= 0 || buf[0] != 0xFF) | |
| 368 fe->rx_data_missing = TRUE; | |
| 369 } | |
| 370 if (len > 0 && fe->hdlc_rx.len + len <= T38_MAX_HDLC_LEN) | |
| 371 { | |
| 372 bit_reverse(fe->hdlc_rx.buf + fe->hdlc_rx.len, buf, len); | |
| 373 fe->hdlc_rx.len += len; | |
| 374 } | |
| 375 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
| 376 break; | |
| 377 case T38_FIELD_HDLC_FCS_OK: | |
| 378 if (len > 0) | |
| 379 { | |
| 380 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n"); | |
| 381 /* The sender has incorrectly included data in this message. It is unclear what we should do | |
| 382 with it, to maximise tolerance of buggy implementations. */ | |
| 383 } | |
| 384 /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK messages, in IFP packets with | |
| 385 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
| 386 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
| 387 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
| 388 { | |
| 389 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean"); | |
| 390 hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing); | |
| 391 } | |
| 392 fe->hdlc_rx.len = 0; | |
| 393 fe->rx_data_missing = FALSE; | |
| 394 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
| 395 break; | |
| 396 case T38_FIELD_HDLC_FCS_BAD: | |
| 397 if (len > 0) | |
| 398 { | |
| 399 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n"); | |
| 400 /* The sender has incorrectly included data in this message. We can safely ignore it, as the | |
| 401 bad FCS means we will throw away the whole message, anyway. */ | |
| 402 } | |
| 403 /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD messages, in IFP packets with | |
| 404 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
| 405 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
| 406 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
| 407 { | |
| 408 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean"); | |
| 409 hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE); | |
| 410 } | |
| 411 fe->hdlc_rx.len = 0; | |
| 412 fe->rx_data_missing = FALSE; | |
| 413 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
| 414 break; | |
| 415 case T38_FIELD_HDLC_FCS_OK_SIG_END: | |
| 416 if (len > 0) | |
| 417 { | |
| 418 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n"); | |
| 419 /* The sender has incorrectly included data in this message. It is unclear what we should do | |
| 420 with it, to maximise tolerance of buggy implementations. */ | |
| 421 } | |
| 422 /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK_SIG_END messages, in IFP packets with | |
| 423 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
| 424 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
| 425 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
| 426 { | |
| 427 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean"); | |
| 428 hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing); | |
| 429 hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE); | |
| 430 } | |
| 431 fe->hdlc_rx.len = 0; | |
| 432 fe->rx_data_missing = FALSE; | |
| 433 /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */ | |
| 434 fake_rx_indicator(t, s, T38_IND_NO_SIGNAL); | |
| 435 break; | |
| 436 case T38_FIELD_HDLC_FCS_BAD_SIG_END: | |
| 437 if (len > 0) | |
| 438 { | |
| 439 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n"); | |
| 440 /* The sender has incorrectly included data in this message. We can safely ignore it, as the | |
| 441 bad FCS means we will throw away the whole message, anyway. */ | |
| 442 } | |
| 443 /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD_SIG_END messages, in IFP packets with | |
| 444 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
| 445 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
| 446 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
| 447 { | |
| 448 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean"); | |
| 449 hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE); | |
| 450 hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE); | |
| 451 } | |
| 452 fe->hdlc_rx.len = 0; | |
| 453 fe->rx_data_missing = FALSE; | |
| 454 /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */ | |
| 455 fake_rx_indicator(t, s, T38_IND_NO_SIGNAL); | |
| 456 break; | |
| 457 case T38_FIELD_HDLC_SIG_END: | |
| 458 if (len > 0) | |
| 459 { | |
| 460 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_SIG_END!\n"); | |
| 461 /* The sender has incorrectly included data in this message, but there seems nothing meaningful | |
| 462 it could be. There could not be an FCS good/bad report beyond this. */ | |
| 463 } | |
| 464 /* Some T.38 implementations send multiple T38_FIELD_HDLC_SIG_END messages, in IFP packets with | |
| 465 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
| 466 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
| 467 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
| 468 { | |
| 469 /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the | |
| 470 end of non-ECM data. We need to tolerate this. We use the generic receive complete | |
| 471 indication, rather than the specific HDLC carrier down. */ | |
| 472 /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - | |
| 473 i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops. | |
| 474 The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */ | |
| 475 fe->hdlc_rx.len = 0; | |
| 476 fe->rx_data_missing = FALSE; | |
| 477 front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
| 478 } | |
| 479 /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */ | |
| 480 fake_rx_indicator(t, s, T38_IND_NO_SIGNAL); | |
| 481 break; | |
| 482 case T38_FIELD_T4_NON_ECM_DATA: | |
| 483 if (!fe->rx_signal_present) | |
| 484 { | |
| 485 t30_non_ecm_put_bit(&s->t30, SIG_STATUS_TRAINING_SUCCEEDED); | |
| 486 fe->rx_signal_present = TRUE; | |
| 487 } | |
| 488 if (len > 0) | |
| 489 { | |
| 490 bit_reverse(buf2, buf, len); | |
| 491 t30_non_ecm_put_chunk(&s->t30, buf2, len); | |
| 492 } | |
| 493 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
| 494 break; | |
| 495 case T38_FIELD_T4_NON_ECM_SIG_END: | |
| 496 /* Some T.38 implementations send multiple T38_FIELD_T4_NON_ECM_SIG_END messages, in IFP packets with | |
| 497 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
| 498 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
| 499 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
| 500 { | |
| 501 if (len > 0) | |
| 502 { | |
| 503 if (!fe->rx_signal_present) | |
| 504 { | |
| 505 t30_non_ecm_put_bit(&s->t30, SIG_STATUS_TRAINING_SUCCEEDED); | |
| 506 fe->rx_signal_present = TRUE; | |
| 507 } | |
| 508 bit_reverse(buf2, buf, len); | |
| 509 t30_non_ecm_put_chunk(&s->t30, buf2, len); | |
| 510 } | |
| 511 /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send HDLC signal end where | |
| 512 they should send non-ECM signal end. It is possible they also do the opposite. | |
| 513 We need to tolerate this, so we use the generic receive complete | |
| 514 indication, rather than the specific non-ECM carrier down. */ | |
| 515 front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
| 516 } | |
| 517 fe->rx_signal_present = FALSE; | |
| 518 /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */ | |
| 519 fake_rx_indicator(t, s, T38_IND_NO_SIGNAL); | |
| 520 break; | |
| 521 default: | |
| 522 break; | |
| 523 } | |
| 524 /*endswitch*/ | |
| 525 return 0; | |
| 526 } | |
| 527 /*- End of function --------------------------------------------------------*/ | |
| 528 | |
| 529 static void send_hdlc(void *user_data, const uint8_t *msg, int len) | |
| 530 { | |
| 531 t38_terminal_state_t *s; | |
| 532 | |
| 533 s = (t38_terminal_state_t *) user_data; | |
| 534 if (len <= 0) | |
| 535 { | |
| 536 s->t38_fe.hdlc_tx.len = -1; | |
| 537 } | |
| 538 else | |
| 539 { | |
| 540 s->t38_fe.hdlc_tx.extra_bits = extra_bits_in_stuffed_frame(msg, len); | |
| 541 bit_reverse(s->t38_fe.hdlc_tx.buf, msg, len); | |
| 542 s->t38_fe.hdlc_tx.len = len; | |
| 543 s->t38_fe.hdlc_tx.ptr = 0; | |
| 544 } | |
| 545 } | |
| 546 /*- End of function --------------------------------------------------------*/ | |
| 547 | |
| 548 static __inline__ int bits_to_us(t38_terminal_state_t *s, int bits) | |
| 549 { | |
| 550 if (s->t38_fe.ms_per_tx_chunk == 0 || s->t38_fe.tx_bit_rate == 0) | |
| 551 return 0; | |
| 552 return bits*1000000/s->t38_fe.tx_bit_rate; | |
| 553 } | |
| 554 /*- End of function --------------------------------------------------------*/ | |
| 555 | |
| 556 static void set_octets_per_data_packet(t38_terminal_state_t *s, int bit_rate) | |
| 557 { | |
| 558 s->t38_fe.tx_bit_rate = bit_rate; | |
| 559 if (s->t38_fe.ms_per_tx_chunk) | |
| 560 { | |
| 561 s->t38_fe.octets_per_data_packet = s->t38_fe.ms_per_tx_chunk*bit_rate/(8*1000); | |
| 562 /* Make sure we have a positive number (i.e. we didn't truncate to zero). */ | |
| 563 if (s->t38_fe.octets_per_data_packet < 1) | |
| 564 s->t38_fe.octets_per_data_packet = 1; | |
| 565 } | |
| 566 else | |
| 567 { | |
| 568 s->t38_fe.octets_per_data_packet = MAX_OCTETS_PER_UNPACED_CHUNK; | |
| 569 } | |
| 570 } | |
| 571 /*- End of function --------------------------------------------------------*/ | |
| 572 | |
| 573 static int stream_non_ecm(t38_terminal_state_t *s) | |
| 574 { | |
| 575 t38_terminal_front_end_state_t *fe; | |
| 576 uint8_t buf[MAX_OCTETS_PER_UNPACED_CHUNK + 50]; | |
| 577 int delay; | |
| 578 int len; | |
| 579 | |
| 580 fe = &s->t38_fe; | |
| 581 for (delay = 0; delay == 0; ) | |
| 582 { | |
| 583 switch (fe->timed_step) | |
| 584 { | |
| 585 case T38_TIMED_STEP_NON_ECM_MODEM: | |
| 586 /* Create a 75ms silence */ | |
| 587 if (fe->t38.current_tx_indicator != T38_IND_NO_SIGNAL) | |
| 588 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
| 589 else | |
| 590 delay = 75000; | |
| 591 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2; | |
| 592 fe->next_tx_samples = fe->samples; | |
| 593 break; | |
| 594 case T38_TIMED_STEP_NON_ECM_MODEM_2: | |
| 595 /* Switch on a fast modem, and give the training time to complete */ | |
| 596 delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator); | |
| 597 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3; | |
| 598 break; | |
| 599 case T38_TIMED_STEP_NON_ECM_MODEM_3: | |
| 600 /* Send a chunk of non-ECM image data */ | |
| 601 /* T.38 says it is OK to send the last of the non-ECM data in the signal end message. | |
| 602 However, I think the early versions of T.38 said the signal end message should not | |
| 603 contain data. Hopefully, following the current spec will not cause compatibility | |
| 604 issues. */ | |
| 605 len = t30_non_ecm_get_chunk(&s->t30, buf, fe->octets_per_data_packet); | |
| 606 if (len > 0) | |
| 607 bit_reverse(buf, buf, len); | |
| 608 if (len < fe->octets_per_data_packet) | |
| 609 { | |
| 610 /* That's the end of the image data. */ | |
| 611 if (s->t38_fe.ms_per_tx_chunk) | |
| 612 { | |
| 613 /* Pad the end of the data with some zeros. If we just stop abruptly | |
| 614 at the end of the EOLs, some ATAs fail to clean up properly before | |
| 615 shutting down their transmit modem, and the last few rows of the image | |
| 616 are lost or corrupted. Simply delaying the no-signal message does not | |
| 617 help for all implentations. It is usually ignored, which is probably | |
| 618 the right thing to do after receiving a message saying the signal has | |
| 619 ended. */ | |
| 620 memset(buf + len, 0, fe->octets_per_data_packet - len); | |
| 621 fe->non_ecm_trailer_bytes = 3*fe->octets_per_data_packet + len; | |
| 622 len = fe->octets_per_data_packet; | |
| 623 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_4; | |
| 624 } | |
| 625 else | |
| 626 { | |
| 627 /* If we are sending quickly there seems no point in doing any padding */ | |
| 628 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA_END); | |
| 629 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5; | |
| 630 delay = 0; | |
| 631 break; | |
| 632 } | |
| 633 } | |
| 634 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA); | |
| 635 delay = bits_to_us(s, 8*len); | |
| 636 break; | |
| 637 case T38_TIMED_STEP_NON_ECM_MODEM_4: | |
| 638 /* Send padding */ | |
| 639 len = fe->octets_per_data_packet; | |
| 640 fe->non_ecm_trailer_bytes -= fe->octets_per_data_packet; | |
| 641 if (fe->non_ecm_trailer_bytes <= 0) | |
| 642 { | |
| 643 len += fe->non_ecm_trailer_bytes; | |
| 644 memset(buf, 0, len); | |
| 645 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA_END); | |
| 646 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5; | |
| 647 /* Allow a bit more time than the data will take to play out, to ensure the far ATA does not | |
| 648 cut things short. */ | |
| 649 delay = bits_to_us(s, 8*len); | |
| 650 if (s->t38_fe.ms_per_tx_chunk) | |
| 651 delay += 60000; | |
| 652 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
| 653 break; | |
| 654 } | |
| 655 memset(buf, 0, len); | |
| 656 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA); | |
| 657 delay = bits_to_us(s, 8*len); | |
| 658 break; | |
| 659 case T38_TIMED_STEP_NON_ECM_MODEM_5: | |
| 660 /* This should not be needed, since the message above indicates the end of the signal, but it | |
| 661 seems like it can improve compatibility with quirky implementations. */ | |
| 662 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
| 663 fe->timed_step = T38_TIMED_STEP_NONE; | |
| 664 return delay; | |
| 665 } | |
| 666 } | |
| 667 return delay; | |
| 668 } | |
| 669 /*- End of function --------------------------------------------------------*/ | |
| 670 | |
| 671 static int stream_hdlc(t38_terminal_state_t *s) | |
| 672 { | |
| 673 t38_terminal_front_end_state_t *fe; | |
| 674 uint8_t buf[MAX_OCTETS_PER_UNPACED_CHUNK + 50]; | |
| 675 t38_data_field_t data_fields[2]; | |
| 676 int category; | |
| 677 int previous; | |
| 678 int delay; | |
| 679 int i; | |
| 680 | |
| 681 fe = &s->t38_fe; | |
| 682 for (delay = 0; delay == 0; ) | |
| 683 { | |
| 684 switch (fe->timed_step) | |
| 685 { | |
| 686 case T38_TIMED_STEP_HDLC_MODEM: | |
| 687 /* Create a 75ms silence */ | |
| 688 if (fe->t38.current_tx_indicator != T38_IND_NO_SIGNAL) | |
| 689 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
| 690 else | |
| 691 delay = 75000; | |
| 692 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_2; | |
| 693 fe->next_tx_samples = fe->samples; | |
| 694 break; | |
| 695 case T38_TIMED_STEP_HDLC_MODEM_2: | |
| 696 /* Send HDLC preambling */ | |
| 697 delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator); | |
| 698 delay += t38_core_send_flags_delay(&fe->t38, fe->next_tx_indicator); | |
| 699 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3; | |
| 700 break; | |
| 701 case T38_TIMED_STEP_HDLC_MODEM_3: | |
| 702 /* Send a chunk of HDLC data */ | |
| 703 i = fe->hdlc_tx.len - fe->hdlc_tx.ptr; | |
| 704 if (fe->octets_per_data_packet >= i) | |
| 705 { | |
| 706 /* The last part of an HDLC frame */ | |
| 707 if (fe->chunking_modes & T38_CHUNKING_MERGE_FCS_WITH_DATA) | |
| 708 { | |
| 709 /* Copy the data, as we might be about to refill the buffer it is in */ | |
| 710 memcpy(buf, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i); | |
| 711 data_fields[0].field_type = T38_FIELD_HDLC_DATA; | |
| 712 data_fields[0].field = buf; | |
| 713 data_fields[0].field_len = i; | |
| 714 | |
| 715 /* Now see about the next HDLC frame. This will tell us whether to send FCS_OK or FCS_OK_SIG_END */ | |
| 716 previous = fe->current_tx_data_type; | |
| 717 fe->hdlc_tx.ptr = 0; | |
| 718 fe->hdlc_tx.len = 0; | |
| 719 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
| 720 /* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */ | |
| 721 if (fe->hdlc_tx.len < 0) | |
| 722 { | |
| 723 data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK_SIG_END; | |
| 724 data_fields[1].field = NULL; | |
| 725 data_fields[1].field_len = 0; | |
| 726 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END; | |
| 727 t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category); | |
| 728 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_5; | |
| 729 /* We add a bit of extra time here, as with some implementations | |
| 730 the carrier falling too abruptly causes data loss. */ | |
| 731 delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits); | |
| 732 if (s->t38_fe.ms_per_tx_chunk) | |
| 733 delay += 100000; | |
| 734 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
| 735 } | |
| 736 else | |
| 737 { | |
| 738 data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK; | |
| 739 data_fields[1].field = NULL; | |
| 740 data_fields[1].field_len = 0; | |
| 741 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA; | |
| 742 t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category); | |
| 743 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3; | |
| 744 delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits); | |
| 745 } | |
| 746 break; | |
| 747 } | |
| 748 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA; | |
| 749 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category); | |
| 750 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_4; | |
| 751 } | |
| 752 else | |
| 753 { | |
| 754 i = fe->octets_per_data_packet; | |
| 755 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA; | |
| 756 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category); | |
| 757 fe->hdlc_tx.ptr += i; | |
| 758 } | |
| 759 delay = bits_to_us(s, i*8); | |
| 760 break; | |
| 761 case T38_TIMED_STEP_HDLC_MODEM_4: | |
| 762 /* End of HDLC frame */ | |
| 763 previous = fe->current_tx_data_type; | |
| 764 fe->hdlc_tx.ptr = 0; | |
| 765 fe->hdlc_tx.len = 0; | |
| 766 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
| 767 /* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */ | |
| 768 if (fe->hdlc_tx.len < 0) | |
| 769 { | |
| 770 /* End of transmission */ | |
| 771 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END; | |
| 772 t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, category); | |
| 773 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_5; | |
| 774 /* We add a bit of extra time here, as with some implementations | |
| 775 the carrier falling too abruptly causes data loss. */ | |
| 776 delay = bits_to_us(s, fe->hdlc_tx.extra_bits); | |
| 777 if (s->t38_fe.ms_per_tx_chunk) | |
| 778 delay += 100000; | |
| 779 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
| 780 break; | |
| 781 } | |
| 782 if (fe->hdlc_tx.len == 0) | |
| 783 { | |
| 784 /* Now, how did we get here? We have finished a frame, but have no new frame to | |
| 785 send, and no end of transmission condition. */ | |
| 786 span_log(&s->logging, SPAN_LOG_FLOW, "No new frame or end transmission condition.\n"); | |
| 787 } | |
| 788 /* Finish the current frame off, and prepare for the next one. */ | |
| 789 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA; | |
| 790 t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, category); | |
| 791 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3; | |
| 792 /* We should now wait enough time for everything to clear through an analogue modem at the far end. */ | |
| 793 delay = bits_to_us(s, fe->hdlc_tx.extra_bits); | |
| 794 break; | |
| 795 case T38_TIMED_STEP_HDLC_MODEM_5: | |
| 796 /* Note that some boxes do not like us sending a T38_FIELD_HDLC_SIG_END at this point. | |
| 797 A T38_IND_NO_SIGNAL should always be OK. */ | |
| 798 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
| 799 fe->timed_step = T38_TIMED_STEP_NONE; | |
| 800 return delay; | |
| 801 } | |
| 802 } | |
| 803 return delay; | |
| 804 } | |
| 805 /*- End of function --------------------------------------------------------*/ | |
| 806 | |
| 807 static int stream_ced(t38_terminal_state_t *s) | |
| 808 { | |
| 809 t38_terminal_front_end_state_t *fe; | |
| 810 int delay; | |
| 811 | |
| 812 fe = &s->t38_fe; | |
| 813 for (delay = 0; delay == 0; ) | |
| 814 { | |
| 815 switch (fe->timed_step) | |
| 816 { | |
| 817 case T38_TIMED_STEP_CED: | |
| 818 /* It seems common practice to start with a no signal indicator, though | |
| 819 this is not a specified requirement. Since we should be sending 200ms | |
| 820 of silence, starting the delay with a no signal indication makes sense. | |
| 821 We do need a 200ms delay, as that is a specification requirement. */ | |
| 822 fe->timed_step = T38_TIMED_STEP_CED_2; | |
| 823 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
| 824 delay = 200000; | |
| 825 fe->next_tx_samples = fe->samples; | |
| 826 break; | |
| 827 case T38_TIMED_STEP_CED_2: | |
| 828 /* Initial 200ms delay over. Send the CED indicator */ | |
| 829 fe->timed_step = T38_TIMED_STEP_CED_3; | |
| 830 delay = t38_core_send_indicator(&fe->t38, T38_IND_CED); | |
| 831 fe->current_tx_data_type = T38_DATA_NONE; | |
| 832 break; | |
| 833 case T38_TIMED_STEP_CED_3: | |
| 834 /* End of CED */ | |
| 835 fe->timed_step = T38_TIMED_STEP_NONE; | |
| 836 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
| 837 return 0; | |
| 838 } | |
| 839 } | |
| 840 return delay; | |
| 841 } | |
| 842 /*- End of function --------------------------------------------------------*/ | |
| 843 | |
| 844 static int stream_cng(t38_terminal_state_t *s) | |
| 845 { | |
| 846 t38_terminal_front_end_state_t *fe; | |
| 847 int delay; | |
| 848 | |
| 849 fe = &s->t38_fe; | |
| 850 for (delay = 0; delay == 0; ) | |
| 851 { | |
| 852 switch (fe->timed_step) | |
| 853 { | |
| 854 case T38_TIMED_STEP_CNG: | |
| 855 /* It seems common practice to start with a no signal indicator, though | |
| 856 this is not a specified requirement of the T.38 spec. Since we should | |
| 857 be sending 200ms of silence, according to T.30, starting that delay with | |
| 858 a no signal indication makes sense. */ | |
| 859 fe->timed_step = T38_TIMED_STEP_CNG_2; | |
| 860 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
| 861 delay = 200000; | |
| 862 fe->next_tx_samples = fe->samples; | |
| 863 break; | |
| 864 case T38_TIMED_STEP_CNG_2: | |
| 865 /* Initial short delay over. Send the CNG indicator. CNG persists until something | |
| 866 coming the other way interrupts it, or a long timeout controlled by the T.30 engine | |
| 867 expires. */ | |
| 868 fe->timed_step = T38_TIMED_STEP_NONE; | |
| 869 delay = t38_core_send_indicator(&fe->t38, T38_IND_CNG); | |
| 870 fe->current_tx_data_type = T38_DATA_NONE; | |
| 871 return delay; | |
| 872 } | |
| 873 } | |
| 874 return delay; | |
| 875 } | |
| 876 /*- End of function --------------------------------------------------------*/ | |
| 877 | |
| 878 SPAN_DECLARE(int) t38_terminal_send_timeout(t38_terminal_state_t *s, int samples) | |
| 879 { | |
| 880 t38_terminal_front_end_state_t *fe; | |
| 881 int delay; | |
| 882 | |
| 883 fe = &s->t38_fe; | |
| 884 if (fe->current_rx_type == T30_MODEM_DONE || fe->current_tx_type == T30_MODEM_DONE) | |
| 885 return TRUE; | |
| 886 | |
| 887 fe->samples += samples; | |
| 888 t30_timer_update(&s->t30, samples); | |
| 889 if (fe->timeout_rx_samples && fe->samples > fe->timeout_rx_samples) | |
| 890 { | |
| 891 span_log(&s->logging, SPAN_LOG_FLOW, "Timeout mid-receive\n"); | |
| 892 fe->timeout_rx_samples = 0; | |
| 893 front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
| 894 } | |
| 895 if (fe->timed_step == T38_TIMED_STEP_NONE) | |
| 896 return FALSE; | |
| 897 /* Wait until the right time comes along, unless we are working in "no delays" mode, while talking to an | |
| 898 IAF terminal. */ | |
| 899 if (fe->ms_per_tx_chunk && fe->samples < fe->next_tx_samples) | |
| 900 return FALSE; | |
| 901 /* Its time to send something */ | |
| 902 delay = 0; | |
| 903 switch (fe->timed_step & 0xFFF0) | |
| 904 { | |
| 905 case T38_TIMED_STEP_NON_ECM_MODEM: | |
| 906 delay = stream_non_ecm(s); | |
| 907 break; | |
| 908 case T38_TIMED_STEP_HDLC_MODEM: | |
| 909 delay = stream_hdlc(s); | |
| 910 break; | |
| 911 case T38_TIMED_STEP_CED: | |
| 912 delay = stream_ced(s); | |
| 913 break; | |
| 914 case T38_TIMED_STEP_CNG: | |
| 915 delay = stream_cng(s); | |
| 916 break; | |
| 917 case T38_TIMED_STEP_PAUSE: | |
| 918 /* End of timed pause */ | |
| 919 fe->timed_step = T38_TIMED_STEP_NONE; | |
| 920 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
| 921 break; | |
| 922 } | |
| 923 fe->next_tx_samples += us_to_samples(delay); | |
| 924 return FALSE; | |
| 925 } | |
| 926 /*- End of function --------------------------------------------------------*/ | |
| 927 | |
| 928 static void set_rx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc) | |
| 929 { | |
| 930 t38_terminal_state_t *s; | |
| 931 | |
| 932 s = (t38_terminal_state_t *) user_data; | |
| 933 span_log(&s->logging, SPAN_LOG_FLOW, "Set rx type %d\n", type); | |
| 934 s->t38_fe.current_rx_type = type; | |
| 935 } | |
| 936 /*- End of function --------------------------------------------------------*/ | |
| 937 | |
| 938 static void start_tx(t38_terminal_front_end_state_t *fe, int use_hdlc) | |
| 939 { | |
| 940 /* The actual transmission process depends on whether we are sending at a paced manner, | |
| 941 for interaction with a traditional FAX machine, or streaming as fast as we can, normally | |
| 942 over a TCP connection to a machine directly connected to the internet. */ | |
| 943 if (fe->ms_per_tx_chunk) | |
| 944 { | |
| 945 /* Start the paced packet transmission process. */ | |
| 946 fe->timed_step = (use_hdlc) ? T38_TIMED_STEP_HDLC_MODEM : T38_TIMED_STEP_NON_ECM_MODEM; | |
| 947 if (fe->next_tx_samples < fe->samples) | |
| 948 fe->next_tx_samples = fe->samples; | |
| 949 } | |
| 950 else | |
| 951 { | |
| 952 /* Start the fast streaming transmission process. */ | |
| 953 } | |
| 954 } | |
| 955 /*- End of function --------------------------------------------------------*/ | |
| 956 | |
| 957 static void set_tx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc) | |
| 958 { | |
| 959 t38_terminal_state_t *s; | |
| 960 t38_terminal_front_end_state_t *fe; | |
| 961 | |
| 962 s = (t38_terminal_state_t *) user_data; | |
| 963 fe = &s->t38_fe; | |
| 964 span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type); | |
| 965 if (fe->current_tx_type == type) | |
| 966 return; | |
| 967 | |
| 968 set_octets_per_data_packet(s, bit_rate); | |
| 969 switch (type) | |
| 970 { | |
| 971 case T30_MODEM_NONE: | |
| 972 /* If a "no signal" indicator is waiting to be played out, don't disturb it. */ | |
| 973 if (fe->timed_step != T38_TIMED_STEP_NON_ECM_MODEM_5 && fe->timed_step != T38_TIMED_STEP_HDLC_MODEM_5) | |
| 974 fe->timed_step = T38_TIMED_STEP_NONE; | |
| 975 fe->current_tx_data_type = T38_DATA_NONE; | |
| 976 break; | |
| 977 case T30_MODEM_PAUSE: | |
| 978 fe->next_tx_samples = fe->samples + ms_to_samples(short_train); | |
| 979 fe->timed_step = T38_TIMED_STEP_PAUSE; | |
| 980 fe->current_tx_data_type = T38_DATA_NONE; | |
| 981 break; | |
| 982 case T30_MODEM_CED: | |
| 983 fe->next_tx_samples = fe->samples; | |
| 984 fe->timed_step = T38_TIMED_STEP_CED; | |
| 985 fe->current_tx_data_type = T38_DATA_NONE; | |
| 986 break; | |
| 987 case T30_MODEM_CNG: | |
| 988 fe->next_tx_samples = fe->samples; | |
| 989 fe->timed_step = T38_TIMED_STEP_CNG; | |
| 990 fe->current_tx_data_type = T38_DATA_NONE; | |
| 991 break; | |
| 992 case T30_MODEM_V21: | |
| 993 fe->next_tx_indicator = T38_IND_V21_PREAMBLE; | |
| 994 fe->current_tx_data_type = T38_DATA_V21; | |
| 995 start_tx(fe, use_hdlc); | |
| 996 break; | |
| 997 case T30_MODEM_V27TER: | |
| 998 switch (bit_rate) | |
| 999 { | |
| 1000 case 2400: | |
| 1001 fe->next_tx_indicator = T38_IND_V27TER_2400_TRAINING; | |
| 1002 fe->current_tx_data_type = T38_DATA_V27TER_2400; | |
| 1003 break; | |
| 1004 case 4800: | |
| 1005 fe->next_tx_indicator = T38_IND_V27TER_4800_TRAINING; | |
| 1006 fe->current_tx_data_type = T38_DATA_V27TER_4800; | |
| 1007 break; | |
| 1008 } | |
| 1009 start_tx(fe, use_hdlc); | |
| 1010 break; | |
| 1011 case T30_MODEM_V29: | |
| 1012 switch (bit_rate) | |
| 1013 { | |
| 1014 case 7200: | |
| 1015 fe->next_tx_indicator = T38_IND_V29_7200_TRAINING; | |
| 1016 fe->current_tx_data_type = T38_DATA_V29_7200; | |
| 1017 break; | |
| 1018 case 9600: | |
| 1019 fe->next_tx_indicator = T38_IND_V29_9600_TRAINING; | |
| 1020 fe->current_tx_data_type = T38_DATA_V29_9600; | |
| 1021 break; | |
| 1022 } | |
| 1023 start_tx(fe, use_hdlc); | |
| 1024 break; | |
| 1025 case T30_MODEM_V17: | |
| 1026 switch (bit_rate) | |
| 1027 { | |
| 1028 case 7200: | |
| 1029 fe->next_tx_indicator = (short_train) ? T38_IND_V17_7200_SHORT_TRAINING : T38_IND_V17_7200_LONG_TRAINING; | |
| 1030 fe->current_tx_data_type = T38_DATA_V17_7200; | |
| 1031 break; | |
| 1032 case 9600: | |
| 1033 fe->next_tx_indicator = (short_train) ? T38_IND_V17_9600_SHORT_TRAINING : T38_IND_V17_9600_LONG_TRAINING; | |
| 1034 fe->current_tx_data_type = T38_DATA_V17_9600; | |
| 1035 break; | |
| 1036 case 12000: | |
| 1037 fe->next_tx_indicator = (short_train) ? T38_IND_V17_12000_SHORT_TRAINING : T38_IND_V17_12000_LONG_TRAINING; | |
| 1038 fe->current_tx_data_type = T38_DATA_V17_12000; | |
| 1039 break; | |
| 1040 case 14400: | |
| 1041 fe->next_tx_indicator = (short_train) ? T38_IND_V17_14400_SHORT_TRAINING : T38_IND_V17_14400_LONG_TRAINING; | |
| 1042 fe->current_tx_data_type = T38_DATA_V17_14400; | |
| 1043 break; | |
| 1044 } | |
| 1045 start_tx(fe, use_hdlc); | |
| 1046 break; | |
| 1047 case T30_MODEM_DONE: | |
| 1048 span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n"); | |
| 1049 fe->timed_step = T38_TIMED_STEP_NONE; | |
| 1050 fe->current_tx_data_type = T38_DATA_NONE; | |
| 1051 break; | |
| 1052 } | |
| 1053 fe->current_tx_type = type; | |
| 1054 } | |
| 1055 /*- End of function --------------------------------------------------------*/ | |
| 1056 | |
| 1057 SPAN_DECLARE(void) t38_terminal_set_config(t38_terminal_state_t *s, int without_pacing) | |
| 1058 { | |
| 1059 if (without_pacing) | |
| 1060 { | |
| 1061 /* Continuous streaming mode, as used for TPKT over TCP transport */ | |
| 1062 /* Inhibit indicator packets */ | |
| 1063 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 0); | |
| 1064 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA, 1); | |
| 1065 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, 1); | |
| 1066 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, 1); | |
| 1067 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, 1); | |
| 1068 s->t38_fe.ms_per_tx_chunk = 0; | |
| 1069 } | |
| 1070 else | |
| 1071 { | |
| 1072 /* Paced streaming mode, as used for UDP transports */ | |
| 1073 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, INDICATOR_TX_COUNT); | |
| 1074 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA, DATA_TX_COUNT); | |
| 1075 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, DATA_END_TX_COUNT); | |
| 1076 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, DATA_TX_COUNT); | |
| 1077 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, DATA_END_TX_COUNT); | |
| 1078 s->t38_fe.ms_per_tx_chunk = MS_PER_TX_CHUNK; | |
| 1079 } | |
| 1080 set_octets_per_data_packet(s, 300); | |
| 1081 } | |
| 1082 /*- End of function --------------------------------------------------------*/ | |
| 1083 | |
| 1084 SPAN_DECLARE(void) t38_terminal_set_tep_mode(t38_terminal_state_t *s, int use_tep) | |
| 1085 { | |
| 1086 if (use_tep) | |
| 1087 s->t38_fe.chunking_modes |= T38_CHUNKING_ALLOW_TEP_TIME; | |
| 1088 else | |
| 1089 s->t38_fe.chunking_modes &= ~T38_CHUNKING_ALLOW_TEP_TIME; | |
| 1090 t38_set_tep_handling(&s->t38_fe.t38, use_tep); | |
| 1091 } | |
| 1092 /*- End of function --------------------------------------------------------*/ | |
| 1093 | |
| 1094 SPAN_DECLARE(void) t38_terminal_set_fill_bit_removal(t38_terminal_state_t *s, int remove) | |
| 1095 { | |
| 1096 if (remove) | |
| 1097 s->t38_fe.iaf |= T30_IAF_MODE_NO_FILL_BITS; | |
| 1098 else | |
| 1099 s->t38_fe.iaf &= ~T30_IAF_MODE_NO_FILL_BITS; | |
| 1100 t30_set_iaf_mode(&s->t30, s->t38_fe.iaf); | |
| 1101 } | |
| 1102 /*- End of function --------------------------------------------------------*/ | |
| 1103 | |
| 1104 SPAN_DECLARE(t30_state_t *) t38_terminal_get_t30_state(t38_terminal_state_t *s) | |
| 1105 { | |
| 1106 return &s->t30; | |
| 1107 } | |
| 1108 /*- End of function --------------------------------------------------------*/ | |
| 1109 | |
| 1110 SPAN_DECLARE(t38_core_state_t *) t38_terminal_get_t38_core_state(t38_terminal_state_t *s) | |
| 1111 { | |
| 1112 return &s->t38_fe.t38; | |
| 1113 } | |
| 1114 /*- End of function --------------------------------------------------------*/ | |
| 1115 | |
| 1116 static int t38_terminal_t38_fe_init(t38_terminal_state_t *t, | |
| 1117 t38_tx_packet_handler_t *tx_packet_handler, | |
| 1118 void *tx_packet_user_data) | |
| 1119 { | |
| 1120 t38_terminal_front_end_state_t *s; | |
| 1121 | |
| 1122 s = &t->t38_fe; | |
| 1123 t38_core_init(&s->t38, | |
| 1124 process_rx_indicator, | |
| 1125 process_rx_data, | |
| 1126 process_rx_missing, | |
| 1127 (void *) t, | |
| 1128 tx_packet_handler, | |
| 1129 tx_packet_user_data); | |
| 1130 t38_set_fastest_image_data_rate(&s->t38, 14400); | |
| 1131 | |
| 1132 s->rx_signal_present = FALSE; | |
| 1133 s->timed_step = T38_TIMED_STEP_NONE; | |
| 1134 //s->iaf = T30_IAF_MODE_T37 | T30_IAF_MODE_T38; | |
| 1135 s->iaf = T30_IAF_MODE_T38; | |
| 1136 | |
| 1137 s->current_tx_data_type = T38_DATA_NONE; | |
| 1138 s->next_tx_samples = 0; | |
| 1139 s->chunking_modes = T38_CHUNKING_ALLOW_TEP_TIME; | |
| 1140 | |
| 1141 s->hdlc_tx.ptr = 0; | |
| 1142 | |
| 1143 return 0; | |
| 1144 } | |
| 1145 /*- End of function --------------------------------------------------------*/ | |
| 1146 | |
| 1147 SPAN_DECLARE(logging_state_t *) t38_terminal_get_logging_state(t38_terminal_state_t *s) | |
| 1148 { | |
| 1149 return &s->logging; | |
| 1150 } | |
| 1151 /*- End of function --------------------------------------------------------*/ | |
| 1152 | |
| 1153 SPAN_DECLARE(t38_terminal_state_t *) t38_terminal_init(t38_terminal_state_t *s, | |
| 1154 int calling_party, | |
| 1155 t38_tx_packet_handler_t *tx_packet_handler, | |
| 1156 void *tx_packet_user_data) | |
| 1157 { | |
| 1158 if (tx_packet_handler == NULL) | |
| 1159 return NULL; | |
| 1160 | |
| 1161 if (s == NULL) | |
| 1162 { | |
| 1163 if ((s = (t38_terminal_state_t *) malloc(sizeof(*s))) == NULL) | |
| 1164 return NULL; | |
| 1165 } | |
| 1166 memset(s, 0, sizeof(*s)); | |
| 1167 span_log_init(&s->logging, SPAN_LOG_NONE, NULL); | |
| 1168 span_log_set_protocol(&s->logging, "T.38T"); | |
| 1169 | |
| 1170 t38_terminal_t38_fe_init(s, tx_packet_handler, tx_packet_user_data); | |
| 1171 | |
| 1172 t38_terminal_set_config(s, FALSE); | |
| 1173 | |
| 1174 t30_init(&s->t30, | |
| 1175 calling_party, | |
| 1176 set_rx_type, | |
| 1177 (void *) s, | |
| 1178 set_tx_type, | |
| 1179 (void *) s, | |
| 1180 send_hdlc, | |
| 1181 (void *) s); | |
| 1182 t30_set_iaf_mode(&s->t30, s->t38_fe.iaf); | |
| 1183 t30_set_supported_modems(&s->t30, | |
| 1184 T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17 | T30_SUPPORT_IAF); | |
| 1185 t30_restart(&s->t30); | |
| 1186 return s; | |
| 1187 } | |
| 1188 /*- End of function --------------------------------------------------------*/ | |
| 1189 | |
| 1190 SPAN_DECLARE(int) t38_terminal_release(t38_terminal_state_t *s) | |
| 1191 { | |
| 1192 t30_release(&s->t30); | |
| 1193 return 0; | |
| 1194 } | |
| 1195 /*- End of function --------------------------------------------------------*/ | |
| 1196 | |
| 1197 SPAN_DECLARE(int) t38_terminal_free(t38_terminal_state_t *s) | |
| 1198 { | |
| 1199 t38_terminal_release(s); | |
| 1200 free(s); | |
| 1201 return 0; | |
| 1202 } | |
| 1203 /*- End of function --------------------------------------------------------*/ | |
| 1204 /*- End of file ------------------------------------------------------------*/ |
