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