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