![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
udptl.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- A telephony toolkit for Linux. 00003 * 00004 * UDPTL support for T.38 00005 * 00006 * Copyright (C) 2005, Steve Underwood, partly based on RTP code which is 00007 * Copyright (C) 1999-2006, Digium, Inc. 00008 * 00009 * Steve Underwood <steveu@coppice.org> 00010 * 00011 * See http://www.asterisk.org for more information about 00012 * the Asterisk project. Please do not directly contact 00013 * any of the maintainers of this project for assistance; 00014 * the project provides a web site, mailing lists and IRC 00015 * channels for your use. 00016 * 00017 * This program is free software, distributed under the terms of 00018 * the GNU General Public License Version 2. See the LICENSE file 00019 * at the top of the source tree. 00020 * 00021 * A license has been granted to Digium (via disclaimer) for the use of 00022 * this code. 00023 */ 00024 00025 /*! 00026 * \file 00027 * 00028 * \brief UDPTL support for T.38 faxing 00029 * 00030 * 00031 * \author Mark Spencer <markster@digium.com>, Steve Underwood <steveu@coppice.org> 00032 * 00033 * \page T38fax_udptl T38 fax passhtrough :: UDPTL 00034 * 00035 * Asterisk supports T.38 fax passthrough. Asterisk will not be a client, server 00036 * or any form of gateway. Currently fax passthrough is only implemented in the 00037 * SIP channel for strict SIP to SIP calls. If you are using chan_local or chan_agent 00038 * as a proxy channel, T.38 passthrough will not work. 00039 * 00040 * UDPTL is handled very much like RTP. It can be reinvited to go directly between 00041 * the endpoints, without involving Asterisk in the media stream. 00042 * 00043 * \b References: 00044 * - chan_sip.c 00045 * - udptl.c 00046 */ 00047 00048 00049 #include "asterisk.h" 00050 00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 51915 $") 00052 00053 #include <stdio.h> 00054 #include <stdlib.h> 00055 #include <string.h> 00056 #include <sys/time.h> 00057 #include <signal.h> 00058 #include <errno.h> 00059 #include <unistd.h> 00060 #include <netinet/in.h> 00061 #include <sys/time.h> 00062 #include <sys/socket.h> 00063 #include <arpa/inet.h> 00064 #include <fcntl.h> 00065 00066 #include "asterisk/udptl.h" 00067 #include "asterisk/frame.h" 00068 #include "asterisk/logger.h" 00069 #include "asterisk/options.h" 00070 #include "asterisk/channel.h" 00071 #include "asterisk/acl.h" 00072 #include "asterisk/channel.h" 00073 #include "asterisk/config.h" 00074 #include "asterisk/lock.h" 00075 #include "asterisk/utils.h" 00076 #include "asterisk/cli.h" 00077 #include "asterisk/unaligned.h" 00078 #include "asterisk/utils.h" 00079 00080 #define UDPTL_MTU 1200 00081 00082 #if !defined(FALSE) 00083 #define FALSE 0 00084 #endif 00085 #if !defined(TRUE) 00086 #define TRUE (!FALSE) 00087 #endif 00088 00089 static int udptlstart; 00090 static int udptlend; 00091 static int udptldebug; /*!< Are we debugging? */ 00092 static struct sockaddr_in udptldebugaddr; /*!< Debug packets to/from this host */ 00093 #ifdef SO_NO_CHECK 00094 static int nochecksums; 00095 #endif 00096 static int udptlfectype; 00097 static int udptlfecentries; 00098 static int udptlfecspan; 00099 static int udptlmaxdatagram; 00100 00101 #define LOCAL_FAX_MAX_DATAGRAM 400 00102 #define MAX_FEC_ENTRIES 5 00103 #define MAX_FEC_SPAN 5 00104 00105 #define UDPTL_BUF_MASK 15 00106 00107 typedef struct { 00108 int buf_len; 00109 uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]; 00110 } udptl_fec_tx_buffer_t; 00111 00112 typedef struct { 00113 int buf_len; 00114 uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]; 00115 int fec_len[MAX_FEC_ENTRIES]; 00116 uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM]; 00117 int fec_span; 00118 int fec_entries; 00119 } udptl_fec_rx_buffer_t; 00120 00121 /*! \brief Structure for an UDPTL session */ 00122 struct ast_udptl { 00123 int fd; 00124 char resp; 00125 struct ast_frame f[16]; 00126 unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET]; 00127 unsigned int lasteventseqn; 00128 int nat; 00129 int flags; 00130 struct sockaddr_in us; 00131 struct sockaddr_in them; 00132 int *ioid; 00133 uint16_t seqno; 00134 struct sched_context *sched; 00135 struct io_context *io; 00136 void *data; 00137 ast_udptl_callback callback; 00138 int udptl_offered_from_local; 00139 00140 /*! This option indicates the error correction scheme used in transmitted UDPTL 00141 packets. */ 00142 int error_correction_scheme; 00143 00144 /*! This option indicates the number of error correction entries transmitted in 00145 UDPTL packets. */ 00146 int error_correction_entries; 00147 00148 /*! This option indicates the span of the error correction entries in transmitted 00149 UDPTL packets (FEC only). */ 00150 int error_correction_span; 00151 00152 /*! This option indicates the maximum size of a UDPTL packet that can be accepted by 00153 the remote device. */ 00154 int far_max_datagram_size; 00155 00156 /*! This option indicates the maximum size of a UDPTL packet that we are prepared to 00157 accept. */ 00158 int local_max_datagram_size; 00159 00160 int verbose; 00161 00162 struct sockaddr_in far; 00163 00164 int tx_seq_no; 00165 int rx_seq_no; 00166 int rx_expected_seq_no; 00167 00168 udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1]; 00169 udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1]; 00170 }; 00171 00172 static struct ast_udptl_protocol *protos; 00173 00174 static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len); 00175 static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, int ifp_len); 00176 00177 static inline int udptl_debug_test_addr(struct sockaddr_in *addr) 00178 { 00179 if (udptldebug == 0) 00180 return 0; 00181 if (udptldebugaddr.sin_addr.s_addr) { 00182 if (((ntohs(udptldebugaddr.sin_port) != 0) 00183 && (udptldebugaddr.sin_port != addr->sin_port)) 00184 || (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00185 return 0; 00186 } 00187 return 1; 00188 } 00189 00190 static int decode_length(uint8_t *buf, int limit, int *len, int *pvalue) 00191 { 00192 if ((buf[*len] & 0x80) == 0) { 00193 if (*len >= limit) 00194 return -1; 00195 *pvalue = buf[*len]; 00196 (*len)++; 00197 return 0; 00198 } 00199 if ((buf[*len] & 0x40) == 0) { 00200 if (*len >= limit - 1) 00201 return -1; 00202 *pvalue = (buf[*len] & 0x3F) << 8; 00203 (*len)++; 00204 *pvalue |= buf[*len]; 00205 (*len)++; 00206 return 0; 00207 } 00208 if (*len >= limit) 00209 return -1; 00210 *pvalue = (buf[*len] & 0x3F) << 14; 00211 (*len)++; 00212 /* Indicate we have a fragment */ 00213 return 1; 00214 } 00215 /*- End of function --------------------------------------------------------*/ 00216 00217 static int decode_open_type(uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets) 00218 { 00219 int octet_cnt; 00220 int octet_idx; 00221 int stat; 00222 int i; 00223 const uint8_t **pbuf; 00224 00225 for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) { 00226 if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0) 00227 return -1; 00228 if (octet_cnt > 0) { 00229 *p_num_octets += octet_cnt; 00230 00231 pbuf = &p_object[octet_idx]; 00232 i = 0; 00233 /* Make sure the buffer contains at least the number of bits requested */ 00234 if ((*len + octet_cnt) > limit) 00235 return -1; 00236 00237 *pbuf = &buf[*len]; 00238 *len += octet_cnt; 00239 } 00240 if (stat == 0) 00241 break; 00242 } 00243 return 0; 00244 } 00245 /*- End of function --------------------------------------------------------*/ 00246 00247 static int encode_length(uint8_t *buf, int *len, int value) 00248 { 00249 int multiplier; 00250 00251 if (value < 0x80) { 00252 /* 1 octet */ 00253 buf[*len] = value; 00254 (*len)++; 00255 return value; 00256 } 00257 if (value < 0x4000) { 00258 /* 2 octets */ 00259 /* Set the first bit of the first octet */ 00260 buf[*len] = ((0x8000 | value) >> 8) & 0xFF; 00261 (*len)++; 00262 buf[*len] = value & 0xFF; 00263 (*len)++; 00264 return value; 00265 } 00266 /* Fragmentation */ 00267 multiplier = (value < 0x10000) ? (value >> 14) : 4; 00268 /* Set the first 2 bits of the octet */ 00269 buf[*len] = 0xC0 | multiplier; 00270 (*len)++; 00271 return multiplier << 14; 00272 } 00273 /*- End of function --------------------------------------------------------*/ 00274 00275 static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num_octets) 00276 { 00277 int enclen; 00278 int octet_idx; 00279 uint8_t zero_byte; 00280 00281 /* If open type is of zero length, add a single zero byte (10.1) */ 00282 if (num_octets == 0) { 00283 zero_byte = 0; 00284 data = &zero_byte; 00285 num_octets = 1; 00286 } 00287 /* Encode the open type */ 00288 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) { 00289 if ((enclen = encode_length(buf, len, num_octets)) < 0) 00290 return -1; 00291 if (enclen > 0) { 00292 memcpy(&buf[*len], &data[octet_idx], enclen); 00293 *len += enclen; 00294 } 00295 if (enclen >= num_octets) 00296 break; 00297 } 00298 00299 return 0; 00300 } 00301 /*- End of function --------------------------------------------------------*/ 00302 00303 static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len) 00304 { 00305 int stat; 00306 int stat2; 00307 int i; 00308 int j; 00309 int k; 00310 int l; 00311 int m; 00312 int x; 00313 int limit; 00314 int which; 00315 int ptr; 00316 int count; 00317 int total_count; 00318 int seq_no; 00319 const uint8_t *ifp; 00320 const uint8_t *data; 00321 int ifp_len; 00322 int repaired[16]; 00323 const uint8_t *bufs[16]; 00324 int lengths[16]; 00325 int span; 00326 int entries; 00327 int ifp_no; 00328 00329 ptr = 0; 00330 ifp_no = 0; 00331 memset(&s->f[0], 0, sizeof(s->f[0])); 00332 00333 /* Decode seq_number */ 00334 if (ptr + 2 > len) 00335 return -1; 00336 seq_no = (buf[0] << 8) | buf[1]; 00337 ptr += 2; 00338 00339 /* Break out the primary packet */ 00340 if ((stat = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0) 00341 return -1; 00342 /* Decode error_recovery */ 00343 if (ptr + 1 > len) 00344 return -1; 00345 if ((buf[ptr++] & 0x80) == 0) { 00346 /* Secondary packet mode for error recovery */ 00347 if (seq_no > s->rx_seq_no) { 00348 /* We received a later packet than we expected, so we need to check if we can fill in the gap from the 00349 secondary packets. */ 00350 total_count = 0; 00351 do { 00352 if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) 00353 return -1; 00354 for (i = 0; i < count; i++) { 00355 if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) 00356 return -1; 00357 } 00358 total_count += count; 00359 } 00360 while (stat2 > 0); 00361 /* Step through in reverse order, so we go oldest to newest */ 00362 for (i = total_count; i > 0; i--) { 00363 if (seq_no - i >= s->rx_seq_no) { 00364 /* This one wasn't seen before */ 00365 /* Decode the secondary IFP packet */ 00366 //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); 00367 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00368 s->f[ifp_no].subclass = AST_MODEM_T38; 00369 00370 s->f[ifp_no].mallocd = 0; 00371 //s->f[ifp_no].???seq_no = seq_no - i; 00372 s->f[ifp_no].datalen = lengths[i - 1]; 00373 s->f[ifp_no].data = (uint8_t *) bufs[i - 1]; 00374 s->f[ifp_no].offset = 0; 00375 s->f[ifp_no].src = "UDPTL"; 00376 if (ifp_no > 0) 00377 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00378 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00379 ifp_no++; 00380 } 00381 } 00382 } 00383 /* If packets are received out of sequence, we may have already processed this packet from the error 00384 recovery information in a packet already received. */ 00385 if (seq_no >= s->rx_seq_no) { 00386 /* Decode the primary IFP packet */ 00387 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00388 s->f[ifp_no].subclass = AST_MODEM_T38; 00389 00390 s->f[ifp_no].mallocd = 0; 00391 //s->f[ifp_no].???seq_no = seq_no; 00392 s->f[ifp_no].datalen = ifp_len; 00393 s->f[ifp_no].data = (uint8_t *) ifp; 00394 s->f[ifp_no].offset = 0; 00395 s->f[ifp_no].src = "UDPTL"; 00396 if (ifp_no > 0) 00397 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00398 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00399 } 00400 } 00401 else 00402 { 00403 /* FEC mode for error recovery */ 00404 /* Our buffers cannot tolerate overlength IFP packets in FEC mode */ 00405 if (ifp_len > LOCAL_FAX_MAX_DATAGRAM) 00406 return -1; 00407 /* Update any missed slots in the buffer */ 00408 for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) { 00409 x = s->rx_seq_no & UDPTL_BUF_MASK; 00410 s->rx[x].buf_len = -1; 00411 s->rx[x].fec_len[0] = 0; 00412 s->rx[x].fec_span = 0; 00413 s->rx[x].fec_entries = 0; 00414 } 00415 00416 x = seq_no & UDPTL_BUF_MASK; 00417 00418 memset(repaired, 0, sizeof(repaired)); 00419 00420 /* Save the new IFP packet */ 00421 memcpy(s->rx[x].buf, ifp, ifp_len); 00422 s->rx[x].buf_len = ifp_len; 00423 repaired[x] = TRUE; 00424 00425 /* Decode the FEC packets */ 00426 /* The span is defined as an unconstrained integer, but will never be more 00427 than a small value. */ 00428 if (ptr + 2 > len) 00429 return -1; 00430 if (buf[ptr++] != 1) 00431 return -1; 00432 span = buf[ptr++]; 00433 s->rx[x].fec_span = span; 00434 00435 /* The number of entries is defined as a length, but will only ever be a small 00436 value. Treat it as such. */ 00437 if (ptr + 1 > len) 00438 return -1; 00439 entries = buf[ptr++]; 00440 s->rx[x].fec_entries = entries; 00441 00442 /* Decode the elements */ 00443 for (i = 0; i < entries; i++) { 00444 if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) 00445 return -1; 00446 if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM) 00447 return -1; 00448 00449 /* Save the new FEC data */ 00450 memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); 00451 #if 0 00452 fprintf(stderr, "FEC: "); 00453 for (j = 0; j < s->rx[x].fec_len[i]; j++) 00454 fprintf(stderr, "%02X ", data[j]); 00455 fprintf(stderr, "\n"); 00456 #endif 00457 } 00458 00459 /* See if we can reconstruct anything which is missing */ 00460 /* TODO: this does not comprehensively hunt back and repair everything that is possible */ 00461 for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { 00462 if (s->rx[l].fec_len[0] <= 0) 00463 continue; 00464 for (m = 0; m < s->rx[l].fec_entries; m++) { 00465 limit = (l + m) & UDPTL_BUF_MASK; 00466 for (which = -1, k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) { 00467 if (s->rx[k].buf_len <= 0) 00468 which = (which == -1) ? k : -2; 00469 } 00470 if (which >= 0) { 00471 /* Repairable */ 00472 for (j = 0; j < s->rx[l].fec_len[m]; j++) { 00473 s->rx[which].buf[j] = s->rx[l].fec[m][j]; 00474 for (k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) 00475 s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; 00476 } 00477 s->rx[which].buf_len = s->rx[l].fec_len[m]; 00478 repaired[which] = TRUE; 00479 } 00480 } 00481 } 00482 /* Now play any new packets forwards in time */ 00483 for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { 00484 if (repaired[l]) { 00485 //fprintf(stderr, "Fixed packet %d, len %d\n", j, l); 00486 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00487 s->f[ifp_no].subclass = AST_MODEM_T38; 00488 00489 s->f[ifp_no].mallocd = 0; 00490 //s->f[ifp_no].???seq_no = j; 00491 s->f[ifp_no].datalen = s->rx[l].buf_len; 00492 s->f[ifp_no].data = s->rx[l].buf; 00493 s->f[ifp_no].offset = 0; 00494 s->f[ifp_no].src = "UDPTL"; 00495 if (ifp_no > 0) 00496 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00497 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00498 ifp_no++; 00499 } 00500 } 00501 /* Decode the primary IFP packet */ 00502 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00503 s->f[ifp_no].subclass = AST_MODEM_T38; 00504 00505 s->f[ifp_no].mallocd = 0; 00506 //s->f[ifp_no].???seq_no = j; 00507 s->f[ifp_no].datalen = ifp_len; 00508 s->f[ifp_no].data = (uint8_t *) ifp; 00509 s->f[ifp_no].offset = 0; 00510 s->f[ifp_no].src = "UDPTL"; 00511 if (ifp_no > 0) 00512 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00513 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00514 } 00515 00516 s->rx_seq_no = seq_no + 1; 00517 return 0; 00518 } 00519 /*- End of function --------------------------------------------------------*/ 00520 00521 static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, int ifp_len) 00522 { 00523 uint8_t fec[LOCAL_FAX_MAX_DATAGRAM]; 00524 int i; 00525 int j; 00526 int seq; 00527 int entry; 00528 int entries; 00529 int span; 00530 int m; 00531 int len; 00532 int limit; 00533 int high_tide; 00534 00535 seq = s->tx_seq_no & 0xFFFF; 00536 00537 /* Map the sequence number to an entry in the circular buffer */ 00538 entry = seq & UDPTL_BUF_MASK; 00539 00540 /* We save the message in a circular buffer, for generating FEC or 00541 redundancy sets later on. */ 00542 s->tx[entry].buf_len = ifp_len; 00543 memcpy(s->tx[entry].buf, ifp, ifp_len); 00544 00545 /* Build the UDPTLPacket */ 00546 00547 len = 0; 00548 /* Encode the sequence number */ 00549 buf[len++] = (seq >> 8) & 0xFF; 00550 buf[len++] = seq & 0xFF; 00551 00552 /* Encode the primary IFP packet */ 00553 if (encode_open_type(buf, &len, ifp, ifp_len) < 0) 00554 return -1; 00555 00556 /* Encode the appropriate type of error recovery information */ 00557 switch (s->error_correction_scheme) 00558 { 00559 case UDPTL_ERROR_CORRECTION_NONE: 00560 /* Encode the error recovery type */ 00561 buf[len++] = 0x00; 00562 /* The number of entries will always be zero, so it is pointless allowing 00563 for the fragmented case here. */ 00564 if (encode_length(buf, &len, 0) < 0) 00565 return -1; 00566 break; 00567 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00568 /* Encode the error recovery type */ 00569 buf[len++] = 0x00; 00570 if (s->tx_seq_no > s->error_correction_entries) 00571 entries = s->error_correction_entries; 00572 else 00573 entries = s->tx_seq_no; 00574 /* The number of entries will always be small, so it is pointless allowing 00575 for the fragmented case here. */ 00576 if (encode_length(buf, &len, entries) < 0) 00577 return -1; 00578 /* Encode the elements */ 00579 for (i = 0; i < entries; i++) { 00580 j = (entry - i - 1) & UDPTL_BUF_MASK; 00581 if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) 00582 return -1; 00583 } 00584 break; 00585 case UDPTL_ERROR_CORRECTION_FEC: 00586 span = s->error_correction_span; 00587 entries = s->error_correction_entries; 00588 if (seq < s->error_correction_span*s->error_correction_entries) { 00589 /* In the initial stages, wind up the FEC smoothly */ 00590 entries = seq/s->error_correction_span; 00591 if (seq < s->error_correction_span) 00592 span = 0; 00593 } 00594 /* Encode the error recovery type */ 00595 buf[len++] = 0x80; 00596 /* Span is defined as an inconstrained integer, which it dumb. It will only 00597 ever be a small value. Treat it as such. */ 00598 buf[len++] = 1; 00599 buf[len++] = span; 00600 /* The number of entries is defined as a length, but will only ever be a small 00601 value. Treat it as such. */ 00602 buf[len++] = entries; 00603 for (m = 0; m < entries; m++) { 00604 /* Make an XOR'ed entry the maximum length */ 00605 limit = (entry + m) & UDPTL_BUF_MASK; 00606 high_tide = 0; 00607 for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { 00608 if (high_tide < s->tx[i].buf_len) { 00609 for (j = 0; j < high_tide; j++) 00610 fec[j] ^= s->tx[i].buf[j]; 00611 for ( ; j < s->tx[i].buf_len; j++) 00612 fec[j] = s->tx[i].buf[j]; 00613 high_tide = s->tx[i].buf_len; 00614 } else { 00615 for (j = 0; j < s->tx[i].buf_len; j++) 00616 fec[j] ^= s->tx[i].buf[j]; 00617 } 00618 } 00619 if (encode_open_type(buf, &len, fec, high_tide) < 0) 00620 return -1; 00621 } 00622 break; 00623 } 00624 00625 if (s->verbose) 00626 fprintf(stderr, "\n"); 00627 00628 s->tx_seq_no++; 00629 return len; 00630 } 00631 00632 int ast_udptl_fd(struct ast_udptl *udptl) 00633 { 00634 return udptl->fd; 00635 } 00636 00637 void ast_udptl_set_data(struct ast_udptl *udptl, void *data) 00638 { 00639 udptl->data = data; 00640 } 00641 00642 void ast_udptl_set_callback(struct ast_udptl *udptl, ast_udptl_callback callback) 00643 { 00644 udptl->callback = callback; 00645 } 00646 00647 void ast_udptl_setnat(struct ast_udptl *udptl, int nat) 00648 { 00649 udptl->nat = nat; 00650 } 00651 00652 static int udptlread(int *id, int fd, short events, void *cbdata) 00653 { 00654 struct ast_udptl *udptl = cbdata; 00655 struct ast_frame *f; 00656 00657 if ((f = ast_udptl_read(udptl))) { 00658 if (udptl->callback) 00659 udptl->callback(udptl, f, udptl->data); 00660 } 00661 return 1; 00662 } 00663 00664 struct ast_frame *ast_udptl_read(struct ast_udptl *udptl) 00665 { 00666 int res; 00667 struct sockaddr_in sin; 00668 socklen_t len; 00669 uint16_t seqno = 0; 00670 uint16_t *udptlheader; 00671 00672 len = sizeof(sin); 00673 00674 /* Cache where the header will go */ 00675 res = recvfrom(udptl->fd, 00676 udptl->rawdata + AST_FRIENDLY_OFFSET, 00677 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET, 00678 0, 00679 (struct sockaddr *) &sin, 00680 &len); 00681 udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET); 00682 if (res < 0) { 00683 if (errno != EAGAIN) 00684 ast_log(LOG_WARNING, "UDPTL read error: %s\n", strerror(errno)); 00685 if (errno == EBADF) 00686 CRASH; 00687 return &ast_null_frame; 00688 } 00689 00690 /* Ignore if the other side hasn't been given an address yet. */ 00691 if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port) 00692 return &ast_null_frame; 00693 00694 if (udptl->nat) { 00695 /* Send to whoever sent to us */ 00696 if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00697 (udptl->them.sin_port != sin.sin_port)) { 00698 memcpy(&udptl->them, &sin, sizeof(udptl->them)); 00699 if (option_debug) 00700 ast_log(LOG_DEBUG, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00701 } 00702 } 00703 00704 if (udptl_debug_test_addr(&sin)) { 00705 if (option_verbose) 00706 ast_verbose("Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n", 00707 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res); 00708 } 00709 #if 0 00710 printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res); 00711 #endif 00712 udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res); 00713 00714 return &udptl->f[0]; 00715 } 00716 00717 void ast_udptl_offered_from_local(struct ast_udptl* udptl, int local) 00718 { 00719 if (udptl) 00720 udptl->udptl_offered_from_local = local; 00721 else 00722 ast_log(LOG_WARNING, "udptl structure is null\n"); 00723 } 00724 00725 int ast_udptl_get_error_correction_scheme(struct ast_udptl* udptl) 00726 { 00727 if (udptl) 00728 return udptl->error_correction_scheme; 00729 else { 00730 ast_log(LOG_WARNING, "udptl structure is null\n"); 00731 return -1; 00732 } 00733 } 00734 00735 void ast_udptl_set_error_correction_scheme(struct ast_udptl* udptl, int ec) 00736 { 00737 if (udptl) { 00738 switch (ec) { 00739 case UDPTL_ERROR_CORRECTION_FEC: 00740 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00741 break; 00742 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00743 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00744 break; 00745 case UDPTL_ERROR_CORRECTION_NONE: 00746 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00747 break; 00748 default: 00749 ast_log(LOG_WARNING, "error correction parameter invalid\n"); 00750 }; 00751 } else 00752 ast_log(LOG_WARNING, "udptl structure is null\n"); 00753 } 00754 00755 int ast_udptl_get_local_max_datagram(struct ast_udptl* udptl) 00756 { 00757 if (udptl) 00758 return udptl->local_max_datagram_size; 00759 else { 00760 ast_log(LOG_WARNING, "udptl structure is null\n"); 00761 return -1; 00762 } 00763 } 00764 00765 int ast_udptl_get_far_max_datagram(struct ast_udptl* udptl) 00766 { 00767 if (udptl) 00768 return udptl->far_max_datagram_size; 00769 else { 00770 ast_log(LOG_WARNING, "udptl structure is null\n"); 00771 return -1; 00772 } 00773 } 00774 00775 void ast_udptl_set_local_max_datagram(struct ast_udptl* udptl, int max_datagram) 00776 { 00777 if (udptl) 00778 udptl->local_max_datagram_size = max_datagram; 00779 else 00780 ast_log(LOG_WARNING, "udptl structure is null\n"); 00781 } 00782 00783 void ast_udptl_set_far_max_datagram(struct ast_udptl* udptl, int max_datagram) 00784 { 00785 if (udptl) 00786 udptl->far_max_datagram_size = max_datagram; 00787 else 00788 ast_log(LOG_WARNING, "udptl structure is null\n"); 00789 } 00790 00791 struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr addr) 00792 { 00793 struct ast_udptl *udptl; 00794 int x; 00795 int startplace; 00796 int i; 00797 long int flags; 00798 00799 if (!(udptl = ast_calloc(1, sizeof(*udptl)))) 00800 return NULL; 00801 00802 if (udptlfectype == 2) 00803 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00804 else if (udptlfectype == 1) 00805 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00806 else 00807 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00808 udptl->error_correction_span = udptlfecspan; 00809 udptl->error_correction_entries = udptlfecentries; 00810 00811 udptl->far_max_datagram_size = udptlmaxdatagram; 00812 udptl->local_max_datagram_size = udptlmaxdatagram; 00813 00814 memset(&udptl->rx, 0, sizeof(udptl->rx)); 00815 memset(&udptl->tx, 0, sizeof(udptl->tx)); 00816 for (i = 0; i <= UDPTL_BUF_MASK; i++) { 00817 udptl->rx[i].buf_len = -1; 00818 udptl->tx[i].buf_len = -1; 00819 } 00820 00821 udptl->seqno = ast_random() & 0xffff; 00822 udptl->them.sin_family = AF_INET; 00823 udptl->us.sin_family = AF_INET; 00824 00825 if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00826 free(udptl); 00827 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00828 return NULL; 00829 } 00830 flags = fcntl(udptl->fd, F_GETFL); 00831 fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK); 00832 #ifdef SO_NO_CHECK 00833 if (nochecksums) 00834 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00835 #endif 00836 /* Find us a place */ 00837 x = (ast_random() % (udptlend - udptlstart)) + udptlstart; 00838 startplace = x; 00839 for (;;) { 00840 udptl->us.sin_port = htons(x); 00841 udptl->us.sin_addr = addr; 00842 if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0) 00843 break; 00844 if (errno != EADDRINUSE) { 00845 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00846 close(udptl->fd); 00847 free(udptl); 00848 return NULL; 00849 } 00850 if (++x > udptlend) 00851 x = udptlstart; 00852 if (x == startplace) { 00853 ast_log(LOG_WARNING, "No UDPTL ports remaining\n"); 00854 close(udptl->fd); 00855 free(udptl); 00856 return NULL; 00857 } 00858 } 00859 if (io && sched && callbackmode) { 00860 /* Operate this one in a callback mode */ 00861 udptl->sched = sched; 00862 udptl->io = io; 00863 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl); 00864 } 00865 return udptl; 00866 } 00867 00868 struct ast_udptl *ast_udptl_new(struct sched_context *sched, struct io_context *io, int callbackmode) 00869 { 00870 struct in_addr ia; 00871 memset(&ia, 0, sizeof(ia)); 00872 return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia); 00873 } 00874 00875 int ast_udptl_settos(struct ast_udptl *udptl, int tos) 00876 { 00877 int res; 00878 00879 if ((res = setsockopt(udptl->fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 00880 ast_log(LOG_WARNING, "UDPTL unable to set TOS to %d\n", tos); 00881 return res; 00882 } 00883 00884 void ast_udptl_set_peer(struct ast_udptl *udptl, struct sockaddr_in *them) 00885 { 00886 udptl->them.sin_port = them->sin_port; 00887 udptl->them.sin_addr = them->sin_addr; 00888 } 00889 00890 void ast_udptl_get_peer(struct ast_udptl *udptl, struct sockaddr_in *them) 00891 { 00892 them->sin_family = AF_INET; 00893 them->sin_port = udptl->them.sin_port; 00894 them->sin_addr = udptl->them.sin_addr; 00895 } 00896 00897 void ast_udptl_get_us(struct ast_udptl *udptl, struct sockaddr_in *us) 00898 { 00899 memcpy(us, &udptl->us, sizeof(udptl->us)); 00900 } 00901 00902 void ast_udptl_stop(struct ast_udptl *udptl) 00903 { 00904 memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr)); 00905 memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port)); 00906 } 00907 00908 void ast_udptl_destroy(struct ast_udptl *udptl) 00909 { 00910 if (udptl->ioid) 00911 ast_io_remove(udptl->io, udptl->ioid); 00912 if (udptl->fd > -1) 00913 close(udptl->fd); 00914 free(udptl); 00915 } 00916 00917 int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f) 00918 { 00919 int len; 00920 int res; 00921 uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]; 00922 00923 /* If we have no peer, return immediately */ 00924 if (s->them.sin_addr.s_addr == INADDR_ANY) 00925 return 0; 00926 00927 /* If there is no data length, return immediately */ 00928 if (f->datalen == 0) 00929 return 0; 00930 00931 if (f->frametype != AST_FRAME_MODEM) { 00932 ast_log(LOG_WARNING, "UDPTL can only send T.38 data\n"); 00933 return -1; 00934 } 00935 00936 /* Cook up the UDPTL packet, with the relevant EC info. */ 00937 len = udptl_build_packet(s, buf, f->data, f->datalen); 00938 00939 if (len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) { 00940 if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0) 00941 ast_log(LOG_NOTICE, "UDPTL Transmission error to %s:%d: %s\n", ast_inet_ntoa(s->them.sin_addr), ntohs(s->them.sin_port), strerror(errno)); 00942 #if 0 00943 printf("Sent %d bytes of UDPTL data to %s:%d\n", res, ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00944 #endif 00945 if (udptl_debug_test_addr(&s->them)) 00946 ast_verbose("Sent UDPTL packet to %s:%d (type %d, seq %d, len %d)\n", 00947 ast_inet_ntoa(s->them.sin_addr), 00948 ntohs(s->them.sin_port), 0, s->seqno, len); 00949 } 00950 00951 return 0; 00952 } 00953 00954 void ast_udptl_proto_unregister(struct ast_udptl_protocol *proto) 00955 { 00956 struct ast_udptl_protocol *cur; 00957 struct ast_udptl_protocol *prev; 00958 00959 cur = protos; 00960 prev = NULL; 00961 while (cur) { 00962 if (cur == proto) { 00963 if (prev) 00964 prev->next = proto->next; 00965 else 00966 protos = proto->next; 00967 return; 00968 } 00969 prev = cur; 00970 cur = cur->next; 00971 } 00972 } 00973 00974 int ast_udptl_proto_register(struct ast_udptl_protocol *proto) 00975 { 00976 struct ast_udptl_protocol *cur; 00977 00978 cur = protos; 00979 while (cur) { 00980 if (cur->type == proto->type) { 00981 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 00982 return -1; 00983 } 00984 cur = cur->next; 00985 } 00986 proto->next = protos; 00987 protos = proto; 00988 return 0; 00989 } 00990 00991 static struct ast_udptl_protocol *get_proto(struct ast_channel *chan) 00992 { 00993 struct ast_udptl_protocol *cur; 00994 00995 cur = protos; 00996 while (cur) { 00997 if (cur->type == chan->tech->type) 00998 return cur; 00999 cur = cur->next; 01000 } 01001 return NULL; 01002 } 01003 01004 int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) 01005 { 01006 struct ast_frame *f; 01007 struct ast_channel *who; 01008 struct ast_channel *cs[3]; 01009 struct ast_udptl *p0; 01010 struct ast_udptl *p1; 01011 struct ast_udptl_protocol *pr0; 01012 struct ast_udptl_protocol *pr1; 01013 struct sockaddr_in ac0; 01014 struct sockaddr_in ac1; 01015 struct sockaddr_in t0; 01016 struct sockaddr_in t1; 01017 void *pvt0; 01018 void *pvt1; 01019 int to; 01020 01021 ast_channel_lock(c0); 01022 while (ast_channel_trylock(c1)) { 01023 ast_channel_unlock(c0); 01024 usleep(1); 01025 ast_channel_lock(c0); 01026 } 01027 pr0 = get_proto(c0); 01028 pr1 = get_proto(c1); 01029 if (!pr0) { 01030 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01031 ast_channel_unlock(c0); 01032 ast_channel_unlock(c1); 01033 return -1; 01034 } 01035 if (!pr1) { 01036 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01037 ast_channel_unlock(c0); 01038 ast_channel_unlock(c1); 01039 return -1; 01040 } 01041 pvt0 = c0->tech_pvt; 01042 pvt1 = c1->tech_pvt; 01043 p0 = pr0->get_udptl_info(c0); 01044 p1 = pr1->get_udptl_info(c1); 01045 if (!p0 || !p1) { 01046 /* Somebody doesn't want to play... */ 01047 ast_channel_unlock(c0); 01048 ast_channel_unlock(c1); 01049 return -2; 01050 } 01051 if (pr0->set_udptl_peer(c0, p1)) { 01052 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01053 } else { 01054 /* Store UDPTL peer */ 01055 ast_udptl_get_peer(p1, &ac1); 01056 } 01057 if (pr1->set_udptl_peer(c1, p0)) 01058 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01059 else { 01060 /* Store UDPTL peer */ 01061 ast_udptl_get_peer(p0, &ac0); 01062 } 01063 ast_channel_unlock(c0); 01064 ast_channel_unlock(c1); 01065 cs[0] = c0; 01066 cs[1] = c1; 01067 cs[2] = NULL; 01068 for (;;) { 01069 if ((c0->tech_pvt != pvt0) || 01070 (c1->tech_pvt != pvt1) || 01071 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01072 if (option_debug) 01073 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01074 /* Tell it to try again later */ 01075 return -3; 01076 } 01077 to = -1; 01078 ast_udptl_get_peer(p1, &t1); 01079 ast_udptl_get_peer(p0, &t0); 01080 if (inaddrcmp(&t1, &ac1)) { 01081 if (option_debug) { 01082 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 01083 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port)); 01084 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 01085 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port)); 01086 } 01087 memcpy(&ac1, &t1, sizeof(ac1)); 01088 } 01089 if (inaddrcmp(&t0, &ac0)) { 01090 if (option_debug) { 01091 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 01092 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port)); 01093 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 01094 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port)); 01095 } 01096 memcpy(&ac0, &t0, sizeof(ac0)); 01097 } 01098 who = ast_waitfor_n(cs, 2, &to); 01099 if (!who) { 01100 if (option_debug) 01101 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01102 /* check for hangup / whentohangup */ 01103 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01104 break; 01105 continue; 01106 } 01107 f = ast_read(who); 01108 if (!f) { 01109 *fo = f; 01110 *rc = who; 01111 if (option_debug) 01112 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01113 /* That's all we needed */ 01114 return 0; 01115 } else { 01116 if (f->frametype == AST_FRAME_MODEM) { 01117 /* Forward T.38 frames if they happen upon us */ 01118 if (who == c0) { 01119 ast_write(c1, f); 01120 } else if (who == c1) { 01121 ast_write(c0, f); 01122 } 01123 } 01124 ast_frfree(f); 01125 } 01126 /* Swap priority. Not that it's a big deal at this point */ 01127 cs[2] = cs[0]; 01128 cs[0] = cs[1]; 01129 cs[1] = cs[2]; 01130 } 01131 return -1; 01132 } 01133 01134 static int udptl_do_debug_ip(int fd, int argc, char *argv[]) 01135 { 01136 struct hostent *hp; 01137 struct ast_hostent ahp; 01138 int port; 01139 char *p; 01140 char *arg; 01141 01142 port = 0; 01143 if (argc != 4) 01144 return RESULT_SHOWUSAGE; 01145 arg = argv[3]; 01146 p = strstr(arg, ":"); 01147 if (p) { 01148 *p = '\0'; 01149 p++; 01150 port = atoi(p); 01151 } 01152 hp = ast_gethostbyname(arg, &ahp); 01153 if (hp == NULL) 01154 return RESULT_SHOWUSAGE; 01155 udptldebugaddr.sin_family = AF_INET; 01156 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr)); 01157 udptldebugaddr.sin_port = htons(port); 01158 if (port == 0) 01159 ast_cli(fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr)); 01160 else 01161 ast_cli(fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port); 01162 udptldebug = 1; 01163 return RESULT_SUCCESS; 01164 } 01165 01166 static int udptl_do_debug(int fd, int argc, char *argv[]) 01167 { 01168 if (argc != 2) { 01169 if (argc != 4) 01170 return RESULT_SHOWUSAGE; 01171 return udptl_do_debug_ip(fd, argc, argv); 01172 } 01173 udptldebug = 1; 01174 memset(&udptldebugaddr,0,sizeof(udptldebugaddr)); 01175 ast_cli(fd, "UDPTL Debugging Enabled\n"); 01176 return RESULT_SUCCESS; 01177 } 01178 01179 static int udptl_nodebug(int fd, int argc, char *argv[]) 01180 { 01181 if (argc != 3) 01182 return RESULT_SHOWUSAGE; 01183 udptldebug = 0; 01184 ast_cli(fd,"UDPTL Debugging Disabled\n"); 01185 return RESULT_SUCCESS; 01186 } 01187 01188 static const char debug_usage[] = 01189 "Usage: udptl debug [ip host[:port]]\n" 01190 " Enable dumping of all UDPTL packets to and from host.\n"; 01191 01192 static const char nodebug_usage[] = 01193 "Usage: udptl debug off\n" 01194 " Disable all UDPTL debugging\n"; 01195 01196 static struct ast_cli_entry cli_udptl[] = { 01197 { { "udptl", "debug", NULL }, 01198 udptl_do_debug, "Enable UDPTL debugging", 01199 debug_usage }, 01200 01201 { { "udptl", "debug", "ip", NULL }, 01202 udptl_do_debug, "Enable UDPTL debugging on IP", 01203 debug_usage }, 01204 01205 { { "udptl", "debug", "off", NULL }, 01206 udptl_nodebug, "Disable UDPTL debugging", 01207 nodebug_usage }, 01208 }; 01209 01210 void ast_udptl_reload(void) 01211 { 01212 struct ast_config *cfg; 01213 const char *s; 01214 01215 udptlstart = 4500; 01216 udptlend = 4999; 01217 udptlfectype = 0; 01218 udptlfecentries = 0; 01219 udptlfecspan = 0; 01220 udptlmaxdatagram = 0; 01221 01222 if ((cfg = ast_config_load("udptl.conf"))) { 01223 if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) { 01224 udptlstart = atoi(s); 01225 if (udptlstart < 1024) 01226 udptlstart = 1024; 01227 if (udptlstart > 65535) 01228 udptlstart = 65535; 01229 } 01230 if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) { 01231 udptlend = atoi(s); 01232 if (udptlend < 1024) 01233 udptlend = 1024; 01234 if (udptlend > 65535) 01235 udptlend = 65535; 01236 } 01237 if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) { 01238 #ifdef SO_NO_CHECK 01239 if (ast_false(s)) 01240 nochecksums = 1; 01241 else 01242 nochecksums = 0; 01243 #else 01244 if (ast_false(s)) 01245 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n"); 01246 #endif 01247 } 01248 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) { 01249 if (strcmp(s, "t38UDPFEC") == 0) 01250 udptlfectype = 2; 01251 else if (strcmp(s, "t38UDPRedundancy") == 0) 01252 udptlfectype = 1; 01253 } 01254 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) { 01255 udptlmaxdatagram = atoi(s); 01256 if (udptlmaxdatagram < 0) 01257 udptlmaxdatagram = 0; 01258 if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM) 01259 udptlmaxdatagram = LOCAL_FAX_MAX_DATAGRAM; 01260 } 01261 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) { 01262 udptlfecentries = atoi(s); 01263 if (udptlfecentries < 0) 01264 udptlfecentries = 0; 01265 if (udptlfecentries > MAX_FEC_ENTRIES) 01266 udptlfecentries = MAX_FEC_ENTRIES; 01267 } 01268 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) { 01269 udptlfecspan = atoi(s); 01270 if (udptlfecspan < 0) 01271 udptlfecspan = 0; 01272 if (udptlfecspan > MAX_FEC_SPAN) 01273 udptlfecspan = MAX_FEC_SPAN; 01274 } 01275 ast_config_destroy(cfg); 01276 } 01277 if (udptlstart >= udptlend) { 01278 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end\n"); 01279 udptlstart = 4500; 01280 udptlend = 4999; 01281 } 01282 if (option_verbose > 1) 01283 ast_verbose(VERBOSE_PREFIX_2 "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend); 01284 } 01285 01286 void ast_udptl_init(void) 01287 { 01288 ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry)); 01289 ast_udptl_reload(); 01290 }