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