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