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