5
|
1 /*
|
|
2 * SpanDSP - a series of DSP components for telephony
|
|
3 *
|
|
4 * t38_core.h - An implementation of T.38, less the packet exchange part
|
|
5 *
|
|
6 * Written by Steve Underwood <steveu@coppice.org>
|
|
7 *
|
|
8 * Copyright (C) 2005 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 General Public License version 2, as
|
|
14 * 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 General Public License for more details.
|
|
20 *
|
|
21 * You should have received a copy of the GNU General Public License
|
|
22 * 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_core.h,v 1.11 2006/12/07 13:22:26 steveu Exp $
|
|
26 */
|
|
27
|
|
28 /*! \file */
|
|
29
|
|
30 #if !defined(_T38_CORE_H_)
|
|
31 #define _T38_CORE_H_
|
|
32
|
|
33 /*! \page t38_core_page T.38 real time FAX over IP message handling
|
|
34 There are two ITU recommendations which address sending FAXes over IP networks. T.37 specifies a
|
|
35 method of encapsulating FAX images in e-mails, and transporting them to the recipient (an e-mail
|
|
36 box, or another FAX machine) in a store-and-forward manner. T.38 defines a protocol for
|
|
37 transmitting a FAX across an IP network in real time. The core T.38 modules implements the basic
|
|
38 message handling for the T.38, real time, FAX over IP (FoIP) protocol.
|
|
39
|
|
40 The T.38 protocol can operate between:
|
|
41 - Internet-aware FAX terminals, which connect directly to an IP network. The T.38 terminal module
|
|
42 extends this module to provide a complete T.38 terminal.
|
|
43 - FAX gateways, which allow traditional PSTN FAX terminals to communicate through the Internet.
|
|
44 The T.38 gateway module extends this module to provide a T.38 gateway.
|
|
45 - A combination of terminals and gateways.
|
|
46
|
|
47 T.38 is the only standardised protocol which exists for real-time FoIP. Reliably transporting a
|
|
48 FAX between PSTN FAX terminals, through an IP network, requires use of the T.38 protocol at FAX
|
|
49 gateways. VoIP connections are not robust for modem use, including FAX modem use. Most use low
|
|
50 bit rate codecs, which cannot convey the modem signals accurately. Even when high bit rate
|
|
51 codecs are used, VoIP connections suffer dropouts and timing adjustments, which modems cannot
|
|
52 tolerate. In a LAN environment the dropout rate may be very low, but the timing adjustments which
|
|
53 occur in VoIP connections still make modem operation unreliable. T.38 FAX gateways deal with the
|
|
54 delays, timing jitter, and packet loss experienced in packet networks, and isolate the PSTN FAX
|
|
55 terminals from these as far as possible. In addition, by sending FAXes as image data, rather than
|
|
56 digitised audio, they reduce the required bandwidth of the IP network.
|
|
57
|
|
58 \section t38_core_page_sec_1 What does it do?
|
|
59
|
|
60 \section t38_core_page_sec_2 How does it work?
|
|
61
|
|
62 Timing differences and jitter between two T.38 entities can be a serious problem, if one of those
|
|
63 entities is a PSTN gateway.
|
|
64
|
|
65 Flow control for non-ECM image data takes advantage of several features of the T.30 specification.
|
|
66 First, an unspecified number of 0xFF octets may be sent at the start of transmission. This means we
|
|
67 can add endless extra 0xFF bytes at this point, without breaking the T.30 spec. In practice, we
|
|
68 cannot add too many, or we will affect the timing tolerance of the T.30 protocol by delaying the
|
|
69 response at the end of each image. Secondly, just before an end of line (EOL) marker we can pad
|
|
70 with zero bits. Again, the number is limited only by need to avoid upsetting the timing of the
|
|
71 step following the non-ECM data.
|
|
72 */
|
|
73
|
|
74 enum t30_indicator_types_e
|
|
75 {
|
|
76 T38_IND_NO_SIGNAL = 0,
|
|
77 T38_IND_CNG,
|
|
78 T38_IND_CED,
|
|
79 T38_IND_V21_PREAMBLE,
|
|
80 T38_IND_V27TER_2400_TRAINING,
|
|
81 T38_IND_V27TER_4800_TRAINING,
|
|
82 T38_IND_V29_7200_TRAINING,
|
|
83 T38_IND_V29_9600_TRAINING,
|
|
84 T38_IND_V17_7200_SHORT_TRAINING,
|
|
85 T38_IND_V17_7200_LONG_TRAINING,
|
|
86 T38_IND_V17_9600_SHORT_TRAINING,
|
|
87 T38_IND_V17_9600_LONG_TRAINING,
|
|
88 T38_IND_V17_12000_SHORT_TRAINING,
|
|
89 T38_IND_V17_12000_LONG_TRAINING,
|
|
90 T38_IND_V17_14400_SHORT_TRAINING,
|
|
91 T38_IND_V17_14400_LONG_TRAINING,
|
|
92 T38_IND_V8_ANSAM,
|
|
93 T38_IND_V8_SIGNAL,
|
|
94 T38_IND_V34_CNTL_CHANNEL_1200,
|
|
95 T38_IND_V34_PRI_CHANNEL,
|
|
96 T38_IND_V34_CC_RETRAIN,
|
|
97 T38_IND_V33_12000_TRAINING,
|
|
98 T38_IND_V33_14400_TRAINING
|
|
99 };
|
|
100
|
|
101 enum t38_data_types_e
|
|
102 {
|
|
103 T38_DATA_NONE = -1,
|
|
104 T38_DATA_V21 = 0,
|
|
105 T38_DATA_V27TER_2400,
|
|
106 T38_DATA_V27TER_4800,
|
|
107 T38_DATA_V29_7200,
|
|
108 T38_DATA_V29_9600,
|
|
109 T38_DATA_V17_7200,
|
|
110 T38_DATA_V17_9600,
|
|
111 T38_DATA_V17_12000,
|
|
112 T38_DATA_V17_14400,
|
|
113 T38_DATA_V8,
|
|
114 T38_DATA_V34_PRI_RATE,
|
|
115 T38_DATA_V34_CC_1200,
|
|
116 T38_DATA_V34_PRI_CH,
|
|
117 T38_DATA_V33_12000,
|
|
118 T38_DATA_V33_14400
|
|
119 };
|
|
120
|
|
121 enum t38_field_types_e
|
|
122 {
|
|
123 T38_FIELD_HDLC_DATA = 0,
|
|
124 T38_FIELD_HDLC_SIG_END,
|
|
125 T38_FIELD_HDLC_FCS_OK,
|
|
126 T38_FIELD_HDLC_FCS_BAD,
|
|
127 T38_FIELD_HDLC_FCS_OK_SIG_END,
|
|
128 T38_FIELD_HDLC_FCS_BAD_SIG_END,
|
|
129 T38_FIELD_T4_NON_ECM_DATA,
|
|
130 T38_FIELD_T4_NON_ECM_SIG_END,
|
|
131 T38_FIELD_CM_MESSAGE,
|
|
132 T38_FIELD_JM_MESSAGE,
|
|
133 T38_FIELD_CI_MESSAGE,
|
|
134 T38_FIELD_V34RATE
|
|
135 };
|
|
136
|
|
137 enum t38_field_classes_e
|
|
138 {
|
|
139 T38_FIELD_CLASS_NONE = 0,
|
|
140 T38_FIELD_CLASS_HDLC,
|
|
141 T38_FIELD_CLASS_NON_ECM,
|
|
142 };
|
|
143
|
|
144 enum t38_message_types_e
|
|
145 {
|
|
146 T38_TYPE_OF_MSG_T30_INDICATOR = 0,
|
|
147 T38_TYPE_OF_MSG_T30_DATA
|
|
148 };
|
|
149
|
|
150 enum t38_transport_types_e
|
|
151 {
|
|
152 T38_TRANSPORT_UDPTL = 0,
|
|
153 T38_TRANSPORT_RTP,
|
|
154 T38_TRANSPORT_TCP
|
|
155 };
|
|
156
|
|
157 #define T38_RX_BUF_LEN 2048
|
|
158 #define T38_TX_BUF_LEN 16384
|
|
159
|
|
160 typedef struct
|
|
161 {
|
|
162 int numocts;
|
|
163 const uint8_t *data;
|
|
164 } asn1_dyn_oct_str_t;
|
|
165
|
|
166 typedef struct
|
|
167 {
|
|
168 uint8_t field_data_present;
|
|
169 unsigned int field_type;
|
|
170 asn1_dyn_oct_str_t field_data;
|
|
171 } data_field_element_t;
|
|
172
|
|
173 typedef struct t38_core_state_s t38_core_state_t;
|
|
174
|
|
175 typedef int (t38_tx_packet_handler_t)(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count);
|
|
176
|
|
177 typedef int (t38_rx_indicator_handler_t)(t38_core_state_t *s, void *user_data, int indicator);
|
|
178 typedef int (t38_rx_data_handler_t)(t38_core_state_t *s, void *user_data, int data_type, int field_type, const uint8_t *buf, int len);
|
|
179 typedef int (t38_rx_missing_handler_t)(t38_core_state_t *s, void *user_data, int rx_seq_no, int expected_seq_no);
|
|
180
|
|
181 #include <sys/time.h>
|
|
182
|
|
183 /*
|
|
184 Core T.38 state, common to all modes of T.38.
|
|
185 */
|
|
186 struct t38_core_state_s
|
|
187 {
|
|
188 t38_tx_packet_handler_t *tx_packet_handler;
|
|
189 void *tx_packet_user_data;
|
|
190
|
|
191 t38_rx_indicator_handler_t *rx_indicator_handler;
|
|
192 t38_rx_data_handler_t *rx_data_handler;
|
|
193 t38_rx_missing_handler_t *rx_missing_handler;
|
|
194 void *rx_user_data;
|
|
195
|
|
196 /*! NOTE - Bandwidth reduction shall only be done on suitable Phase C data, i.e., MH, MR
|
|
197 and - in the case of transcoding to JBIG - MMR. MMR and JBIG require reliable data
|
|
198 transport such as that provided by TCP. When transcoding is selected, it shall be
|
|
199 applied to every suitable page in a call. */
|
|
200
|
|
201 /*! Method 1: Local generation of TCF (required for use with TCP).
|
|
202 Method 2: Transfer of TCF is required for use with UDP (UDPTL or RTP).
|
|
203 Method 2 is not recommended for use with TCP. */
|
|
204 int data_rate_management_method;
|
|
205
|
|
206 /*! The emitting gateway may indicate a preference for either UDP/UDPTL, or
|
|
207 UDP/RTP, or TCP for transport of T.38 IFP Packets. The receiving device
|
|
208 selects the transport protocol. */
|
|
209 int data_transport_protocol;
|
|
210
|
|
211 /*! Indicates the capability to remove and insert fill bits in Phase C, non-ECM
|
|
212 data to reduce bandwidth in the packet network. Optional. See Note. */
|
|
213 int fill_bit_removal;
|
|
214
|
|
215 /*! Indicates the ability to convert to/from MMR from/to the line format to
|
|
216 improve the compression of the data, and reduce the bandwidth, in the
|
|
217 packet network. Optional. See Note. */
|
|
218 int mmr_transcoding;
|
|
219
|
|
220 /*! Indicates the ability to convert to/from JBIG to reduce bandwidth. Optional.
|
|
221 See Note. */
|
|
222 int jbig_transcoding;
|
|
223
|
|
224 /*! For UDP (UDPTL or RTP) modes, this option indicates the maximum
|
|
225 number of octets that can be stored on the remote device before an overflow
|
|
226 condition occurs. It is the responsibility of the transmitting application to
|
|
227 limit the transfer rate to prevent an overflow. The negotiated data rate
|
|
228 should be used to determine the rate at which data is being removed from
|
|
229 the buffer. */
|
|
230 int max_buffer_size;
|
|
231
|
|
232 /*! This option indicates the maximum size of a UDPTL packet or the
|
|
233 maximum size of the payload within an RTP packet that can be accepted by
|
|
234 the remote device. */
|
|
235 int max_datagram_size;
|
|
236
|
|
237 /*! This is the version number of ITU-T Rec. T.38. New versions shall be
|
|
238 compatible with previous versions. */
|
|
239 int t38_version;
|
|
240
|
|
241 /*! The fastest data rate supported by the T.38 channel. */
|
|
242 int fastest_image_data_rate;
|
|
243
|
|
244 /*! Internet aware FAX (IAF) mode. */
|
|
245 int iaf;
|
|
246
|
|
247 int tx_seq_no;
|
|
248 int rx_expected_seq_no;
|
|
249
|
|
250 int current_rx_indicator;
|
|
251 int current_tx_indicator;
|
|
252
|
|
253 int missing_packets;
|
|
254
|
|
255 logging_state_t logging;
|
|
256 };
|
|
257
|
|
258 #ifdef __cplusplus
|
|
259 extern "C" {
|
|
260 #endif
|
|
261
|
|
262 /*! \brief Convert the code for an indicator to a short text name.
|
|
263 \param indicator The type of indicator.
|
|
264 \return A pointer to a short text name for the indicator. */
|
|
265 const char *t38_indicator(int indicator);
|
|
266
|
|
267 /*! \brief Convert the code for a type of data to a short text name.
|
|
268 \param data_type The data type.
|
|
269 \return A pointer to a short text name for the data type. */
|
|
270 const char *t38_data_type(int data_type);
|
|
271
|
|
272 /*! \brief Convert the code for a type of data field to a short text name.
|
|
273 \param field_type The field type.
|
|
274 \return A pointer to a short text name for the field type. */
|
|
275 const char *t38_field_type(int field_type);
|
|
276
|
|
277 int t38_core_send_indicator(t38_core_state_t *s, int indicator, int count);
|
|
278
|
|
279 int t38_core_send_data(t38_core_state_t *s, int data_type, int field_type, const uint8_t *msg, int msglen);
|
|
280
|
|
281 /*! \brief Process a received T.38 IFP packet.
|
|
282 \param s The T.38 context.
|
|
283 \param seq_no The packet sequence number.
|
|
284 \param buf The packet contents.
|
|
285 \param len The length of the packet contents.
|
|
286 \return 0 for OK, else -1. */
|
|
287 int t38_core_rx_ifp_packet(t38_core_state_t *s, int seq_no, const uint8_t *buf, int len);
|
|
288
|
|
289 /*! Set the method to be used for data rate management, as per the T.38 spec.
|
|
290 \param s The T.38 context.
|
|
291 \param method 1 for pass TCF across the T.38 link, 2 for handle TCF locally.
|
|
292 */
|
|
293 void t38_set_data_rate_management_method(t38_core_state_t *s, int method);
|
|
294
|
|
295 /*! Set the data transport protocol.
|
|
296 \param s The T.38 context.
|
|
297 \param data_transport_protocol UDPTL, RTP or TPKT.
|
|
298 */
|
|
299 void t38_set_data_transport_protocol(t38_core_state_t *s, int data_transport_protocol);
|
|
300
|
|
301 /*! Set the non-ECM fill bit removal mode.
|
|
302 \param s The T.38 context.
|
|
303 \param fill_bit_removal TRUE to remove fill bits across the T.38 link, else FALSE.
|
|
304 */
|
|
305 void t38_set_fill_bit_removal(t38_core_state_t *s, int fill_bit_removal);
|
|
306
|
|
307 /*! Set the MMR transcoding mode.
|
|
308 \param s The T.38 context.
|
|
309 \param mmr_transcoding TRUE to transcode to MMR across the T.38 link, else FALSE.
|
|
310 */
|
|
311 void t38_set_mmr_transcoding(t38_core_state_t *s, int mmr_transcoding);
|
|
312
|
|
313 /*! Set the JBIG transcoding mode.
|
|
314 \param s The T.38 context.
|
|
315 \param jbig_transcoding TRUE to transcode to JBIG across the T.38 link, else FALSE.
|
|
316 */
|
|
317 void t38_set_jbig_transcoding(t38_core_state_t *s, int jbig_transcoding);
|
|
318
|
|
319 void t38_set_max_buffer_size(t38_core_state_t *s, int max_buffer_size);
|
|
320
|
|
321 void t38_set_max_datagram_size(t38_core_state_t *s, int max_datagram_size);
|
|
322
|
|
323 int t38_get_fastest_image_data_rate(t38_core_state_t *s);
|
|
324
|
|
325 /*! Set the T.38 version to be emulated.
|
|
326 \param s The T.38 context.
|
|
327 \param t38_version Version number, as in the T.38 spec.
|
|
328 */
|
|
329 void t38_set_t38_version(t38_core_state_t *s, int t38_version);
|
|
330
|
|
331 t38_core_state_t *t38_core_init(t38_core_state_t *s,
|
|
332 t38_rx_indicator_handler_t *rx_indicator_handler,
|
|
333 t38_rx_data_handler_t *rx_data_handler,
|
|
334 t38_rx_missing_handler_t *rx_missing_handler,
|
|
335 void *rx_user_data);
|
|
336 #ifdef __cplusplus
|
|
337 }
|
|
338 #endif
|
|
339
|
|
340 #endif
|
|
341 /*- End of file ------------------------------------------------------------*/
|