00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "asterisk.h"
00050
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 222111 $")
00052
00053 #include <sys/time.h>
00054 #include <signal.h>
00055 #include <fcntl.h>
00056
00057 #include "asterisk/udptl.h"
00058 #include "asterisk/frame.h"
00059 #include "asterisk/channel.h"
00060 #include "asterisk/acl.h"
00061 #include "asterisk/config.h"
00062 #include "asterisk/lock.h"
00063 #include "asterisk/utils.h"
00064 #include "asterisk/netsock.h"
00065 #include "asterisk/cli.h"
00066 #include "asterisk/unaligned.h"
00067
00068 #define UDPTL_MTU 1200
00069
00070 #if !defined(FALSE)
00071 #define FALSE 0
00072 #endif
00073 #if !defined(TRUE)
00074 #define TRUE (!FALSE)
00075 #endif
00076
00077 static int udptlstart = 4500;
00078 static int udptlend = 4599;
00079 static int udptldebug;
00080 static struct sockaddr_in udptldebugaddr;
00081 #ifdef SO_NO_CHECK
00082 static int nochecksums;
00083 #endif
00084 static int udptlfecentries;
00085 static int udptlfecspan;
00086 static int udptlmaxdatagram;
00087 static int use_even_ports;
00088
00089 #define LOCAL_FAX_MAX_DATAGRAM 1400
00090 #define MAX_FEC_ENTRIES 5
00091 #define MAX_FEC_SPAN 5
00092
00093 #define UDPTL_BUF_MASK 15
00094
00095 typedef struct {
00096 int buf_len;
00097 uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
00098 } udptl_fec_tx_buffer_t;
00099
00100 typedef struct {
00101 int buf_len;
00102 uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
00103 unsigned int fec_len[MAX_FEC_ENTRIES];
00104 uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM];
00105 unsigned int fec_span;
00106 unsigned int fec_entries;
00107 } udptl_fec_rx_buffer_t;
00108
00109
00110 struct ast_udptl {
00111 int fd;
00112 char resp;
00113 struct ast_frame f[16];
00114 unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
00115 unsigned int lasteventseqn;
00116 int nat;
00117 int flags;
00118 struct sockaddr_in us;
00119 struct sockaddr_in them;
00120 int *ioid;
00121 struct sched_context *sched;
00122 struct io_context *io;
00123 void *data;
00124 ast_udptl_callback callback;
00125
00126
00127
00128
00129 enum ast_t38_ec_modes error_correction_scheme;
00130
00131
00132
00133
00134 unsigned int error_correction_entries;
00135
00136
00137
00138
00139 unsigned int error_correction_span;
00140
00141
00142
00143
00144 unsigned int far_max_datagram;
00145
00146
00147
00148
00149 unsigned int local_max_datagram;
00150
00151
00152
00153
00154
00155 unsigned int far_max_ifp;
00156
00157
00158
00159
00160
00161 unsigned int local_max_ifp;
00162
00163 int verbose;
00164
00165 struct sockaddr_in far;
00166
00167 unsigned int tx_seq_no;
00168 unsigned int rx_seq_no;
00169 unsigned int rx_expected_seq_no;
00170
00171 udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1];
00172 udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1];
00173 };
00174
00175 static AST_RWLIST_HEAD_STATIC(protos, ast_udptl_protocol);
00176
00177 static inline int udptl_debug_test_addr(const 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, unsigned int limit, unsigned int *len, unsigned int *pvalue)
00191 {
00192 if (*len >= limit)
00193 return -1;
00194 if ((buf[*len] & 0x80) == 0) {
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 *pvalue = (buf[*len] & 0x3F) << 14;
00209 (*len)++;
00210
00211 return 1;
00212 }
00213
00214
00215 static int decode_open_type(uint8_t *buf, unsigned int limit, unsigned int *len, const uint8_t **p_object, unsigned int *p_num_octets)
00216 {
00217 unsigned int octet_cnt;
00218 unsigned int octet_idx;
00219 unsigned int length;
00220 unsigned int i;
00221 const uint8_t **pbuf;
00222
00223 for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) {
00224 octet_cnt = 0;
00225 if ((length = decode_length(buf, limit, len, &octet_cnt)) < 0)
00226 return -1;
00227 if (octet_cnt > 0) {
00228 *p_num_octets += octet_cnt;
00229
00230 pbuf = &p_object[octet_idx];
00231 i = 0;
00232
00233 if ((*len + octet_cnt) > limit)
00234 return -1;
00235
00236 *pbuf = &buf[*len];
00237 *len += octet_cnt;
00238 }
00239 if (length == 0)
00240 break;
00241 }
00242 return 0;
00243 }
00244
00245
00246 static unsigned int encode_length(uint8_t *buf, unsigned int *len, unsigned int value)
00247 {
00248 unsigned int multiplier;
00249
00250 if (value < 0x80) {
00251
00252 buf[*len] = value;
00253 (*len)++;
00254 return value;
00255 }
00256 if (value < 0x4000) {
00257
00258
00259 buf[*len] = ((0x8000 | value) >> 8) & 0xFF;
00260 (*len)++;
00261 buf[*len] = value & 0xFF;
00262 (*len)++;
00263 return value;
00264 }
00265
00266 multiplier = (value < 0x10000) ? (value >> 14) : 4;
00267
00268 buf[*len] = 0xC0 | multiplier;
00269 (*len)++;
00270 return multiplier << 14;
00271 }
00272
00273
00274 static int encode_open_type(uint8_t *buf, unsigned int buflen, unsigned int *len, const uint8_t *data, unsigned int num_octets)
00275 {
00276 unsigned int enclen;
00277 unsigned int octet_idx;
00278 uint8_t zero_byte;
00279
00280
00281 if (num_octets == 0) {
00282 zero_byte = 0;
00283 data = &zero_byte;
00284 num_octets = 1;
00285 }
00286
00287 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
00288 if ((enclen = encode_length(buf, len, num_octets)) < 0)
00289 return -1;
00290 if (enclen + *len > buflen) {
00291 ast_log(LOG_ERROR, "Buffer overflow detected (%d + %d > %d)\n", enclen, *len, buflen);
00292 return -1;
00293 }
00294 if (enclen > 0) {
00295 memcpy(&buf[*len], &data[octet_idx], enclen);
00296 *len += enclen;
00297 }
00298 if (enclen >= num_octets)
00299 break;
00300 }
00301
00302 return 0;
00303 }
00304
00305
00306 static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len)
00307 {
00308 int stat;
00309 int stat2;
00310 int i;
00311 int j;
00312 int k;
00313 int l;
00314 int m;
00315 int x;
00316 int limit;
00317 int which;
00318 unsigned int ptr;
00319 unsigned int count;
00320 int total_count;
00321 int seq_no;
00322 const uint8_t *ifp;
00323 const uint8_t *data;
00324 unsigned int ifp_len;
00325 int repaired[16];
00326 const uint8_t *bufs[16];
00327 unsigned int lengths[16];
00328 int span;
00329 int entries;
00330 int ifp_no;
00331
00332 ptr = 0;
00333 ifp_no = 0;
00334 memset(&s->f[0], 0, sizeof(s->f[0]));
00335
00336
00337 if (ptr + 2 > len)
00338 return -1;
00339 seq_no = (buf[0] << 8) | buf[1];
00340 ptr += 2;
00341
00342
00343 if ((stat = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0)
00344 return -1;
00345
00346 if (ptr + 1 > len)
00347 return -1;
00348 if ((buf[ptr++] & 0x80) == 0) {
00349
00350 if (seq_no > s->rx_seq_no) {
00351
00352
00353 total_count = 0;
00354 do {
00355 if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
00356 return -1;
00357 for (i = 0; i < count; i++) {
00358 if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0)
00359 return -1;
00360 }
00361 total_count += count;
00362 }
00363 while (stat2 > 0);
00364
00365 for (i = total_count; i > 0; i--) {
00366 if (seq_no - i >= s->rx_seq_no) {
00367
00368
00369
00370 s->f[ifp_no].frametype = AST_FRAME_MODEM;
00371 s->f[ifp_no].subclass = AST_MODEM_T38;
00372
00373 s->f[ifp_no].mallocd = 0;
00374 s->f[ifp_no].seqno = seq_no - i;
00375 s->f[ifp_no].datalen = lengths[i - 1];
00376 s->f[ifp_no].data = (uint8_t *) bufs[i - 1];
00377 s->f[ifp_no].offset = 0;
00378 s->f[ifp_no].src = "UDPTL";
00379 if (ifp_no > 0)
00380 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
00381 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
00382 ifp_no++;
00383 }
00384 }
00385 }
00386 }
00387 else
00388 {
00389
00390
00391 if (ifp_len > LOCAL_FAX_MAX_DATAGRAM)
00392 return -1;
00393
00394 for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) {
00395 x = s->rx_seq_no & UDPTL_BUF_MASK;
00396 s->rx[x].buf_len = -1;
00397 s->rx[x].fec_len[0] = 0;
00398 s->rx[x].fec_span = 0;
00399 s->rx[x].fec_entries = 0;
00400 }
00401
00402 x = seq_no & UDPTL_BUF_MASK;
00403
00404 memset(repaired, 0, sizeof(repaired));
00405
00406
00407 memcpy(s->rx[x].buf, ifp, ifp_len);
00408 s->rx[x].buf_len = ifp_len;
00409 repaired[x] = TRUE;
00410
00411
00412
00413
00414 if (ptr + 2 > len)
00415 return -1;
00416 if (buf[ptr++] != 1)
00417 return -1;
00418 span = buf[ptr++];
00419 s->rx[x].fec_span = span;
00420
00421
00422
00423 if (ptr + 1 > len)
00424 return -1;
00425 entries = buf[ptr++];
00426 s->rx[x].fec_entries = entries;
00427
00428
00429 for (i = 0; i < entries; i++) {
00430 if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0)
00431 return -1;
00432 if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM)
00433 return -1;
00434
00435
00436 memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]);
00437 #if 0
00438 fprintf(stderr, "FEC: ");
00439 for (j = 0; j < s->rx[x].fec_len[i]; j++)
00440 fprintf(stderr, "%02X ", data[j]);
00441 fprintf(stderr, "\n");
00442 #endif
00443 }
00444
00445
00446
00447 for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) {
00448 if (s->rx[l].fec_len[0] <= 0)
00449 continue;
00450 for (m = 0; m < s->rx[l].fec_entries; m++) {
00451 limit = (l + m) & UDPTL_BUF_MASK;
00452 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) {
00453 if (s->rx[k].buf_len <= 0)
00454 which = (which == -1) ? k : -2;
00455 }
00456 if (which >= 0) {
00457
00458 for (j = 0; j < s->rx[l].fec_len[m]; j++) {
00459 s->rx[which].buf[j] = s->rx[l].fec[m][j];
00460 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)
00461 s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
00462 }
00463 s->rx[which].buf_len = s->rx[l].fec_len[m];
00464 repaired[which] = TRUE;
00465 }
00466 }
00467 }
00468
00469 for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) {
00470 if (repaired[l]) {
00471
00472 s->f[ifp_no].frametype = AST_FRAME_MODEM;
00473 s->f[ifp_no].subclass = AST_MODEM_T38;
00474
00475 s->f[ifp_no].mallocd = 0;
00476 s->f[ifp_no].seqno = j;
00477 s->f[ifp_no].datalen = s->rx[l].buf_len;
00478 s->f[ifp_no].data = s->rx[l].buf;
00479 s->f[ifp_no].offset = 0;
00480 s->f[ifp_no].src = "UDPTL";
00481 if (ifp_no > 0)
00482 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
00483 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
00484 ifp_no++;
00485 }
00486 }
00487 }
00488
00489
00490
00491 if (seq_no >= s->rx_seq_no) {
00492
00493 s->f[ifp_no].frametype = AST_FRAME_MODEM;
00494 s->f[ifp_no].subclass = AST_MODEM_T38;
00495
00496 s->f[ifp_no].mallocd = 0;
00497 s->f[ifp_no].seqno = seq_no;
00498 s->f[ifp_no].datalen = ifp_len;
00499 s->f[ifp_no].data = (uint8_t *) ifp;
00500 s->f[ifp_no].offset = 0;
00501 s->f[ifp_no].src = "UDPTL";
00502 if (ifp_no > 0)
00503 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
00504 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
00505
00506 ifp_no++;
00507 }
00508
00509 s->rx_seq_no = seq_no + 1;
00510 return ifp_no;
00511 }
00512
00513
00514 static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, unsigned int buflen, uint8_t *ifp, unsigned int ifp_len)
00515 {
00516 uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2];
00517 int i;
00518 int j;
00519 int seq;
00520 int entry;
00521 int entries;
00522 int span;
00523 int m;
00524 unsigned int len;
00525 int limit;
00526 int high_tide;
00527
00528 seq = s->tx_seq_no & 0xFFFF;
00529
00530
00531 entry = seq & UDPTL_BUF_MASK;
00532
00533
00534
00535 s->tx[entry].buf_len = ifp_len;
00536 memcpy(s->tx[entry].buf, ifp, ifp_len);
00537
00538
00539
00540 len = 0;
00541
00542 buf[len++] = (seq >> 8) & 0xFF;
00543 buf[len++] = seq & 0xFF;
00544
00545
00546 if (encode_open_type(buf, buflen, &len, ifp, ifp_len) < 0)
00547 return -1;
00548
00549
00550 switch (s->error_correction_scheme)
00551 {
00552 case UDPTL_ERROR_CORRECTION_NONE:
00553
00554 buf[len++] = 0x00;
00555
00556
00557 if (encode_length(buf, &len, 0) < 0)
00558 return -1;
00559 break;
00560 case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00561
00562 buf[len++] = 0x00;
00563 if (s->tx_seq_no > s->error_correction_entries)
00564 entries = s->error_correction_entries;
00565 else
00566 entries = s->tx_seq_no;
00567
00568
00569 if (encode_length(buf, &len, entries) < 0)
00570 return -1;
00571
00572 for (i = 0; i < entries; i++) {
00573 j = (entry - i - 1) & UDPTL_BUF_MASK;
00574 if (encode_open_type(buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) {
00575 if (option_debug) {
00576 ast_log(LOG_DEBUG, "Encoding failed at i=%d, j=%d\n", i, j);
00577 }
00578 return -1;
00579 }
00580 }
00581 break;
00582 case UDPTL_ERROR_CORRECTION_FEC:
00583 span = s->error_correction_span;
00584 entries = s->error_correction_entries;
00585 if (seq < s->error_correction_span*s->error_correction_entries) {
00586
00587 entries = seq/s->error_correction_span;
00588 if (seq < s->error_correction_span)
00589 span = 0;
00590 }
00591
00592 buf[len++] = 0x80;
00593
00594
00595 buf[len++] = 1;
00596 buf[len++] = span;
00597
00598
00599 buf[len++] = entries;
00600 for (m = 0; m < entries; m++) {
00601
00602 limit = (entry + m) & UDPTL_BUF_MASK;
00603 high_tide = 0;
00604 for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) {
00605 if (high_tide < s->tx[i].buf_len) {
00606 for (j = 0; j < high_tide; j++)
00607 fec[j] ^= s->tx[i].buf[j];
00608 for ( ; j < s->tx[i].buf_len; j++)
00609 fec[j] = s->tx[i].buf[j];
00610 high_tide = s->tx[i].buf_len;
00611 } else {
00612 for (j = 0; j < s->tx[i].buf_len; j++)
00613 fec[j] ^= s->tx[i].buf[j];
00614 }
00615 }
00616 if (encode_open_type(buf, buflen, &len, fec, high_tide) < 0)
00617 return -1;
00618 }
00619 break;
00620 }
00621
00622 if (s->verbose)
00623 fprintf(stderr, "\n");
00624
00625 s->tx_seq_no++;
00626 return len;
00627 }
00628
00629 int ast_udptl_fd(const struct ast_udptl *udptl)
00630 {
00631 return udptl->fd;
00632 }
00633
00634 void ast_udptl_set_data(struct ast_udptl *udptl, void *data)
00635 {
00636 udptl->data = data;
00637 }
00638
00639 void ast_udptl_set_callback(struct ast_udptl *udptl, ast_udptl_callback callback)
00640 {
00641 udptl->callback = callback;
00642 }
00643
00644 void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
00645 {
00646 udptl->nat = nat;
00647 }
00648
00649 static int udptlread(int *id, int fd, short events, void *cbdata)
00650 {
00651 struct ast_udptl *udptl = cbdata;
00652 struct ast_frame *f;
00653
00654 if ((f = ast_udptl_read(udptl))) {
00655 if (udptl->callback)
00656 udptl->callback(udptl, f, udptl->data);
00657 }
00658 return 1;
00659 }
00660
00661 struct ast_frame *ast_udptl_read(struct ast_udptl *udptl)
00662 {
00663 int res;
00664 struct sockaddr_in sin;
00665 socklen_t len;
00666 uint16_t seqno = 0;
00667 uint16_t *udptlheader;
00668
00669 len = sizeof(sin);
00670
00671
00672 res = recvfrom(udptl->fd,
00673 udptl->rawdata + AST_FRIENDLY_OFFSET,
00674 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
00675 0,
00676 (struct sockaddr *) &sin,
00677 &len);
00678 udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET);
00679 if (res < 0) {
00680 if (errno != EAGAIN)
00681 ast_log(LOG_WARNING, "UDPTL read error: %s\n", strerror(errno));
00682 ast_assert(errno != EBADF);
00683 return &ast_null_frame;
00684 }
00685
00686
00687 if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port)
00688 return &ast_null_frame;
00689
00690 if (udptl->nat) {
00691
00692 if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00693 (udptl->them.sin_port != sin.sin_port)) {
00694 memcpy(&udptl->them, &sin, sizeof(udptl->them));
00695 ast_debug(1, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
00696 }
00697 }
00698
00699 if (udptl_debug_test_addr(&sin)) {
00700 ast_verb(1, "Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n",
00701 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res);
00702 }
00703 #if 0
00704 printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res);
00705 #endif
00706 if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1)
00707 return &ast_null_frame;
00708
00709 return &udptl->f[0];
00710 }
00711
00712 static void calculate_local_max_datagram(struct ast_udptl *udptl)
00713 {
00714 unsigned int new_max = 0;
00715
00716
00717
00718
00719
00720 switch (udptl->error_correction_scheme) {
00721 case UDPTL_ERROR_CORRECTION_NONE:
00722
00723 new_max = 6 + udptl->local_max_ifp;
00724 break;
00725 case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00726
00727
00728
00729 new_max = 6 + udptl->local_max_ifp + 2 + (udptl->error_correction_entries * udptl->local_max_ifp);
00730 break;
00731 case UDPTL_ERROR_CORRECTION_FEC:
00732
00733
00734
00735 new_max = 6 + udptl->local_max_ifp + 4 + udptl->local_max_ifp;
00736 break;
00737 }
00738
00739 udptl->local_max_datagram = MIN(new_max * 1.25, LOCAL_FAX_MAX_DATAGRAM);
00740 }
00741
00742 static void calculate_far_max_ifp(struct ast_udptl *udptl)
00743 {
00744 unsigned new_max = 0;
00745
00746
00747
00748
00749
00750 switch (udptl->error_correction_scheme) {
00751 case UDPTL_ERROR_CORRECTION_NONE:
00752
00753 new_max = udptl->far_max_datagram - 6;
00754 break;
00755 case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00756
00757
00758
00759 new_max = (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1);
00760 break;
00761 case UDPTL_ERROR_CORRECTION_FEC:
00762
00763
00764
00765 new_max = (udptl->far_max_datagram - 10) / 2;
00766 break;
00767 }
00768
00769 udptl->far_max_ifp = new_max * 0.75;
00770 }
00771
00772 enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme(const struct ast_udptl *udptl)
00773 {
00774 if (udptl)
00775 return udptl->error_correction_scheme;
00776 else {
00777 ast_log(LOG_WARNING, "udptl structure is null\n");
00778 return -1;
00779 }
00780 }
00781
00782 void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
00783 {
00784 if (udptl) {
00785 udptl->error_correction_scheme = ec;
00786 switch (ec) {
00787 case UDPTL_ERROR_CORRECTION_FEC:
00788 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC;
00789 if (udptl->error_correction_entries == 0) {
00790 udptl->error_correction_entries = 3;
00791 }
00792 if (udptl->error_correction_span == 0) {
00793 udptl->error_correction_span = 3;
00794 }
00795 break;
00796 case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00797 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY;
00798 if (udptl->error_correction_entries == 0) {
00799 udptl->error_correction_entries = 3;
00800 }
00801 break;
00802 default:
00803
00804 break;
00805 };
00806 calculate_local_max_datagram(udptl);
00807 calculate_far_max_ifp(udptl);
00808 } else
00809 ast_log(LOG_WARNING, "udptl structure is null\n");
00810 }
00811
00812 unsigned int ast_udptl_get_local_max_datagram(const struct ast_udptl *udptl)
00813 {
00814 if (udptl)
00815 return udptl->local_max_datagram;
00816 else {
00817 ast_log(LOG_WARNING, "udptl structure is null\n");
00818 return 0;
00819 }
00820 }
00821
00822 unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl)
00823 {
00824 if (udptl)
00825 return udptl->far_max_datagram;
00826 else {
00827 ast_log(LOG_WARNING, "udptl structure is null\n");
00828 return 0;
00829 }
00830 }
00831
00832 void ast_udptl_set_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram)
00833 {
00834 if (udptl) {
00835 udptl->far_max_datagram = max_datagram;
00836 calculate_far_max_ifp(udptl);
00837 } else {
00838 ast_log(LOG_WARNING, "udptl structure is null\n");
00839 }
00840 }
00841
00842 void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
00843 {
00844 udptl->local_max_ifp = max_ifp;
00845 calculate_local_max_datagram(udptl);
00846 }
00847
00848 unsigned int ast_udptl_get_far_max_ifp(const struct ast_udptl *udptl)
00849 {
00850 return udptl->far_max_ifp;
00851 }
00852
00853 struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr addr)
00854 {
00855 struct ast_udptl *udptl;
00856 int x;
00857 int startplace;
00858 int i;
00859 long int flags;
00860
00861 if (!(udptl = ast_calloc(1, sizeof(*udptl))))
00862 return NULL;
00863
00864 udptl->error_correction_span = udptlfecspan;
00865 udptl->error_correction_entries = udptlfecentries;
00866
00867 udptl->far_max_datagram = udptlmaxdatagram;
00868 udptl->local_max_datagram = udptlmaxdatagram;
00869
00870 for (i = 0; i <= UDPTL_BUF_MASK; i++) {
00871 udptl->rx[i].buf_len = -1;
00872 udptl->tx[i].buf_len = -1;
00873 }
00874
00875 udptl->them.sin_family = AF_INET;
00876 udptl->us.sin_family = AF_INET;
00877
00878 if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
00879 ast_free(udptl);
00880 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00881 return NULL;
00882 }
00883 flags = fcntl(udptl->fd, F_GETFL);
00884 fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK);
00885 #ifdef SO_NO_CHECK
00886 if (nochecksums)
00887 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
00888 #endif
00889
00890 x = (udptlstart == udptlend) ? udptlstart : (ast_random() % (udptlend - udptlstart)) + udptlstart;
00891 if (use_even_ports && (x & 1)) {
00892 ++x;
00893 }
00894 startplace = x;
00895 for (;;) {
00896 udptl->us.sin_port = htons(x);
00897 udptl->us.sin_addr = addr;
00898 if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0)
00899 break;
00900 if (errno != EADDRINUSE) {
00901 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
00902 close(udptl->fd);
00903 ast_free(udptl);
00904 return NULL;
00905 }
00906 if (use_even_ports) {
00907 x += 2;
00908 } else {
00909 ++x;
00910 }
00911 if (x > udptlend)
00912 x = udptlstart;
00913 if (x == startplace) {
00914 ast_log(LOG_WARNING, "No UDPTL ports remaining\n");
00915 close(udptl->fd);
00916 ast_free(udptl);
00917 return NULL;
00918 }
00919 }
00920 if (io && sched && callbackmode) {
00921
00922 udptl->sched = sched;
00923 udptl->io = io;
00924 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl);
00925 }
00926 return udptl;
00927 }
00928
00929 struct ast_udptl *ast_udptl_new(struct sched_context *sched, struct io_context *io, int callbackmode)
00930 {
00931 struct in_addr ia;
00932 memset(&ia, 0, sizeof(ia));
00933 return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia);
00934 }
00935
00936 int ast_udptl_setqos(struct ast_udptl *udptl, unsigned int tos, unsigned int cos)
00937 {
00938 return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL");
00939 }
00940
00941 void ast_udptl_set_peer(struct ast_udptl *udptl, const struct sockaddr_in *them)
00942 {
00943 udptl->them.sin_port = them->sin_port;
00944 udptl->them.sin_addr = them->sin_addr;
00945 }
00946
00947 void ast_udptl_get_peer(const struct ast_udptl *udptl, struct sockaddr_in *them)
00948 {
00949 memset(them, 0, sizeof(*them));
00950 them->sin_family = AF_INET;
00951 them->sin_port = udptl->them.sin_port;
00952 them->sin_addr = udptl->them.sin_addr;
00953 }
00954
00955 void ast_udptl_get_us(const struct ast_udptl *udptl, struct sockaddr_in *us)
00956 {
00957 memcpy(us, &udptl->us, sizeof(udptl->us));
00958 }
00959
00960 void ast_udptl_stop(struct ast_udptl *udptl)
00961 {
00962 memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr));
00963 memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port));
00964 }
00965
00966 void ast_udptl_destroy(struct ast_udptl *udptl)
00967 {
00968 if (udptl->ioid)
00969 ast_io_remove(udptl->io, udptl->ioid);
00970 if (udptl->fd > -1)
00971 close(udptl->fd);
00972 ast_free(udptl);
00973 }
00974
00975 int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
00976 {
00977 unsigned int seq;
00978 unsigned int len;
00979 int res;
00980 uint8_t buf[s->far_max_datagram];
00981
00982
00983 if (s->them.sin_addr.s_addr == INADDR_ANY)
00984 return 0;
00985
00986
00987 if (f->datalen == 0)
00988 return 0;
00989
00990 if ((f->frametype != AST_FRAME_MODEM) ||
00991 (f->subclass != AST_MODEM_T38)) {
00992 ast_log(LOG_WARNING, "UDPTL can only send T.38 data.\n");
00993 return -1;
00994 }
00995
00996 if (f->datalen > s->far_max_ifp) {
00997 ast_log(LOG_WARNING,
00998 "UDPTL asked to send %d bytes of IFP when far end only prepared to accept %d bytes; data loss may occur. "
00999 "You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n", f->datalen, s->far_max_ifp);
01000 }
01001
01002
01003 seq = s->tx_seq_no & 0xFFFF;
01004
01005
01006 len = udptl_build_packet(s, buf, sizeof(buf), f->data, f->datalen);
01007
01008 if (len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) {
01009 if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0)
01010 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));
01011 #if 0
01012 printf("Sent %d bytes of UDPTL data to %s:%d\n", res, ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
01013 #endif
01014 if (udptl_debug_test_addr(&s->them))
01015 ast_verb(1, "Sent UDPTL packet to %s:%d (type %d, seq %d, len %d)\n",
01016 ast_inet_ntoa(s->them.sin_addr),
01017 ntohs(s->them.sin_port), 0, seq, len);
01018 }
01019
01020 return 0;
01021 }
01022
01023 void ast_udptl_proto_unregister(struct ast_udptl_protocol *proto)
01024 {
01025 AST_RWLIST_WRLOCK(&protos);
01026 AST_RWLIST_REMOVE(&protos, proto, list);
01027 AST_RWLIST_UNLOCK(&protos);
01028 }
01029
01030 int ast_udptl_proto_register(struct ast_udptl_protocol *proto)
01031 {
01032 struct ast_udptl_protocol *cur;
01033
01034 AST_RWLIST_WRLOCK(&protos);
01035 AST_RWLIST_TRAVERSE(&protos, cur, list) {
01036 if (cur->type == proto->type) {
01037 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01038 AST_RWLIST_UNLOCK(&protos);
01039 return -1;
01040 }
01041 }
01042 AST_RWLIST_INSERT_TAIL(&protos, proto, list);
01043 AST_RWLIST_UNLOCK(&protos);
01044 return 0;
01045 }
01046
01047 static struct ast_udptl_protocol *get_proto(struct ast_channel *chan)
01048 {
01049 struct ast_udptl_protocol *cur = NULL;
01050
01051 AST_RWLIST_RDLOCK(&protos);
01052 AST_RWLIST_TRAVERSE(&protos, cur, list) {
01053 if (cur->type == chan->tech->type)
01054 break;
01055 }
01056 AST_RWLIST_UNLOCK(&protos);
01057
01058 return cur;
01059 }
01060
01061 int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
01062 {
01063 struct ast_frame *f;
01064 struct ast_channel *who;
01065 struct ast_channel *cs[3];
01066 struct ast_udptl *p0;
01067 struct ast_udptl *p1;
01068 struct ast_udptl_protocol *pr0;
01069 struct ast_udptl_protocol *pr1;
01070 struct sockaddr_in ac0;
01071 struct sockaddr_in ac1;
01072 struct sockaddr_in t0;
01073 struct sockaddr_in t1;
01074 void *pvt0;
01075 void *pvt1;
01076 int to;
01077
01078 ast_channel_lock(c0);
01079 while (ast_channel_trylock(c1)) {
01080 ast_channel_unlock(c0);
01081 usleep(1);
01082 ast_channel_lock(c0);
01083 }
01084 pr0 = get_proto(c0);
01085 pr1 = get_proto(c1);
01086 if (!pr0) {
01087 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
01088 ast_channel_unlock(c0);
01089 ast_channel_unlock(c1);
01090 return -1;
01091 }
01092 if (!pr1) {
01093 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
01094 ast_channel_unlock(c0);
01095 ast_channel_unlock(c1);
01096 return -1;
01097 }
01098 pvt0 = c0->tech_pvt;
01099 pvt1 = c1->tech_pvt;
01100 p0 = pr0->get_udptl_info(c0);
01101 p1 = pr1->get_udptl_info(c1);
01102 if (!p0 || !p1) {
01103
01104 ast_channel_unlock(c0);
01105 ast_channel_unlock(c1);
01106 return -2;
01107 }
01108 if (pr0->set_udptl_peer(c0, p1)) {
01109 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
01110 memset(&ac1, 0, sizeof(ac1));
01111 } else {
01112
01113 ast_udptl_get_peer(p1, &ac1);
01114 }
01115 if (pr1->set_udptl_peer(c1, p0)) {
01116 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
01117 memset(&ac0, 0, sizeof(ac0));
01118 } else {
01119
01120 ast_udptl_get_peer(p0, &ac0);
01121 }
01122 ast_channel_unlock(c0);
01123 ast_channel_unlock(c1);
01124 cs[0] = c0;
01125 cs[1] = c1;
01126 cs[2] = NULL;
01127 for (;;) {
01128 if ((c0->tech_pvt != pvt0) ||
01129 (c1->tech_pvt != pvt1) ||
01130 (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
01131 ast_debug(1, "Oooh, something is weird, backing out\n");
01132
01133 return -3;
01134 }
01135 to = -1;
01136 ast_udptl_get_peer(p1, &t1);
01137 ast_udptl_get_peer(p0, &t0);
01138 if (inaddrcmp(&t1, &ac1)) {
01139 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n",
01140 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port));
01141 ast_debug(1, "Oooh, '%s' was %s:%d\n",
01142 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port));
01143 memcpy(&ac1, &t1, sizeof(ac1));
01144 }
01145 if (inaddrcmp(&t0, &ac0)) {
01146 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n",
01147 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port));
01148 ast_debug(1, "Oooh, '%s' was %s:%d\n",
01149 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port));
01150 memcpy(&ac0, &t0, sizeof(ac0));
01151 }
01152 who = ast_waitfor_n(cs, 2, &to);
01153 if (!who) {
01154 ast_debug(1, "Ooh, empty read...\n");
01155
01156 if (ast_check_hangup(c0) || ast_check_hangup(c1))
01157 break;
01158 continue;
01159 }
01160 f = ast_read(who);
01161 if (!f) {
01162 *fo = f;
01163 *rc = who;
01164 ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup");
01165
01166 return 0;
01167 } else {
01168 if (f->frametype == AST_FRAME_MODEM) {
01169
01170 if (who == c0) {
01171 ast_write(c1, f);
01172 } else if (who == c1) {
01173 ast_write(c0, f);
01174 }
01175 }
01176 ast_frfree(f);
01177 }
01178
01179 cs[2] = cs[0];
01180 cs[0] = cs[1];
01181 cs[1] = cs[2];
01182 }
01183 return -1;
01184 }
01185
01186 static char *handle_cli_udptl_debug_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01187 {
01188 struct hostent *hp;
01189 struct ast_hostent ahp;
01190 int port;
01191 char *p;
01192 char *arg;
01193
01194 switch (cmd) {
01195 case CLI_INIT:
01196 e->command = "udptl debug [off|ip]";
01197 e->usage =
01198 "Usage: udptl debug [off]|[ip host[:port]]\n"
01199 " Enable or disable dumping of UDPTL packets.\n"
01200 " If ip is specified, limit the dumped packets to those to and from\n"
01201 " the specified 'host' with optional port.\n";
01202 return NULL;
01203 case CLI_GENERATE:
01204 return NULL;
01205 }
01206
01207 if (a->argc < 2 || a->argc > 4)
01208 return CLI_SHOWUSAGE;
01209
01210 if (a->argc == 2) {
01211 udptldebug = 1;
01212 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
01213 ast_cli(a->fd, "UDPTL Debugging Enabled\n");
01214 } else if (a->argc == 3) {
01215 if (strncasecmp(a->argv[2], "off", 3))
01216 return CLI_SHOWUSAGE;
01217 udptldebug = 0;
01218 ast_cli(a->fd, "UDPTL Debugging Disabled\n");
01219 } else {
01220 if (strncasecmp(a->argv[2], "ip", 2))
01221 return CLI_SHOWUSAGE;
01222 port = 0;
01223 arg = a->argv[3];
01224 p = strstr(arg, ":");
01225 if (p) {
01226 *p = '\0';
01227 p++;
01228 port = atoi(p);
01229 }
01230 hp = ast_gethostbyname(arg, &ahp);
01231 if (hp == NULL)
01232 return CLI_SHOWUSAGE;
01233 udptldebugaddr.sin_family = AF_INET;
01234 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
01235 udptldebugaddr.sin_port = htons(port);
01236 if (port == 0)
01237 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
01238 else
01239 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
01240 udptldebug = 1;
01241 }
01242
01243 return CLI_SUCCESS;
01244 }
01245
01246 static char *handle_cli_udptl_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01247 {
01248 struct hostent *hp;
01249 struct ast_hostent ahp;
01250 int port;
01251 char *p;
01252 char *arg;
01253
01254 switch (cmd) {
01255 case CLI_INIT:
01256 e->command = "udptl set debug {on|off|ip}";
01257 e->usage =
01258 "Usage: udptl set debug {on|off|ip host[:port]}\n"
01259 " Enable or disable dumping of UDPTL packets.\n"
01260 " If ip is specified, limit the dumped packets to those to and from\n"
01261 " the specified 'host' with optional port.\n";
01262 return NULL;
01263 case CLI_GENERATE:
01264 return NULL;
01265 }
01266
01267 if (a->argc < 4 || a->argc > 5)
01268 return CLI_SHOWUSAGE;
01269
01270 if (a->argc == 4) {
01271 if (!strncasecmp(a->argv[3], "on", 2)) {
01272 udptldebug = 1;
01273 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
01274 ast_cli(a->fd, "UDPTL Debugging Enabled\n");
01275 } else if (!strncasecmp(a->argv[3], "off", 3)) {
01276 udptldebug = 0;
01277 ast_cli(a->fd, "UDPTL Debugging Disabled\n");
01278 } else {
01279 return CLI_SHOWUSAGE;
01280 }
01281 } else {
01282 if (strncasecmp(a->argv[3], "ip", 2))
01283 return CLI_SHOWUSAGE;
01284 port = 0;
01285 arg = a->argv[4];
01286 p = strstr(arg, ":");
01287 if (p) {
01288 *p = '\0';
01289 p++;
01290 port = atoi(p);
01291 }
01292 hp = ast_gethostbyname(arg, &ahp);
01293 if (hp == NULL)
01294 return CLI_SHOWUSAGE;
01295 udptldebugaddr.sin_family = AF_INET;
01296 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
01297 udptldebugaddr.sin_port = htons(port);
01298 if (port == 0)
01299 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
01300 else
01301 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
01302 udptldebug = 1;
01303 }
01304
01305 return CLI_SUCCESS;
01306 }
01307
01308 static struct ast_cli_entry cli_handle_udptl_debug_deprecated = AST_CLI_DEFINE(handle_cli_udptl_debug_deprecated, "Enable/Disable UDPTL debugging");
01309
01310 static struct ast_cli_entry cli_udptl[] = {
01311 AST_CLI_DEFINE(handle_cli_udptl_set_debug, "Enable/Disable UDPTL debugging", .deprecate_cmd = &cli_handle_udptl_debug_deprecated)
01312 };
01313
01314 static void __ast_udptl_reload(int reload)
01315 {
01316 struct ast_config *cfg;
01317 const char *s;
01318 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01319
01320 if ((cfg = ast_config_load("udptl.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
01321 return;
01322
01323 udptlstart = 4500;
01324 udptlend = 4999;
01325 udptlfecentries = 0;
01326 udptlfecspan = 0;
01327 udptlmaxdatagram = 0;
01328 use_even_ports = 0;
01329
01330 if (cfg) {
01331 if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) {
01332 udptlstart = atoi(s);
01333 if (udptlstart < 1024) {
01334 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n");
01335 udptlstart = 1024;
01336 }
01337 if (udptlstart > 65535) {
01338 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n");
01339 udptlstart = 65535;
01340 }
01341 }
01342 if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) {
01343 udptlend = atoi(s);
01344 if (udptlend < 1024) {
01345 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n");
01346 udptlend = 1024;
01347 }
01348 if (udptlend > 65535) {
01349 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n");
01350 udptlend = 65535;
01351 }
01352 }
01353 if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) {
01354 #ifdef SO_NO_CHECK
01355 if (ast_false(s))
01356 nochecksums = 1;
01357 else
01358 nochecksums = 0;
01359 #else
01360 if (ast_false(s))
01361 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n");
01362 #endif
01363 }
01364 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) {
01365 ast_log(LOG_WARNING, "T38FaxUdpEC in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n");
01366 }
01367 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) {
01368 ast_log(LOG_WARNING, "T38FaxMaxDatagram in udptl.conf is no longer supported.\n");
01369 }
01370 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) {
01371 udptlfecentries = atoi(s);
01372 if (udptlfecentries < 1) {
01373 ast_log(LOG_WARNING, "Too small UDPTLFECentries value. Defaulting to 1.\n");
01374 udptlfecentries = 1;
01375 }
01376 if (udptlfecentries > MAX_FEC_ENTRIES) {
01377 ast_log(LOG_WARNING, "Too large UDPTLFECentries value. Defaulting to %d.\n", MAX_FEC_ENTRIES);
01378 udptlfecentries = MAX_FEC_ENTRIES;
01379 }
01380 }
01381 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) {
01382 udptlfecspan = atoi(s);
01383 if (udptlfecspan < 1) {
01384 ast_log(LOG_WARNING, "Too small UDPTLFECspan value. Defaulting to 1.\n");
01385 udptlfecspan = 1;
01386 }
01387 if (udptlfecspan > MAX_FEC_SPAN) {
01388 ast_log(LOG_WARNING, "Too large UDPTLFECspan value. Defaulting to %d.\n", MAX_FEC_SPAN);
01389 udptlfecspan = MAX_FEC_SPAN;
01390 }
01391 }
01392 if ((s = ast_variable_retrieve(cfg, "general", "use_even_ports"))) {
01393 use_even_ports = ast_true(s);
01394 }
01395 ast_config_destroy(cfg);
01396 }
01397 if (udptlstart >= udptlend) {
01398 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end\n");
01399 udptlstart = 4500;
01400 udptlend = 4999;
01401 }
01402 if (use_even_ports && (udptlstart & 1)) {
01403 ++udptlstart;
01404 ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", udptlstart);
01405 }
01406 if (use_even_ports && (udptlend & 1)) {
01407 --udptlend;
01408 ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_event_ports enabled. udptlend is now %d\n", udptlend);
01409 }
01410 ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend);
01411 }
01412
01413 void ast_udptl_reload(void)
01414 {
01415 __ast_udptl_reload(1);
01416 }
01417
01418 void ast_udptl_init(void)
01419 {
01420 ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry));
01421 __ast_udptl_reload(0);
01422 }