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