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