141#define UDPTL_MTU       1200 
  150#define LOG_TAG(u) S_OR(u->tag, "no tag") 
  152#define DEFAULT_UDPTLSTART 4000 
  153#define DEFAULT_UDPTLEND 4999 
  158#define LOCAL_FAX_MAX_DATAGRAM      1400 
  159#define DEFAULT_FAX_MAX_DATAGRAM    400 
  160#define FAX_MAX_DATAGRAM_LIMIT      1400 
  161#define MAX_FEC_ENTRIES             5 
  162#define MAX_FEC_SPAN                5 
  164#define UDPTL_BUF_MASK              15 
  268    .category = 
"general",
 
 
  303    if ((
buf[*
len] & 0x80) == 0) {
 
  308    if ((
buf[*
len] & 0x40) == 0) {
 
  309        if (*
len == limit - 1)
 
  311        *pvalue = (
buf[*
len] & 0x3F) << 8;
 
  317    *pvalue = (
buf[*
len] & 0x3F) << 14;
 
  320    ast_debug(1, 
"UDPTL packet with length greater than 16K received, decoding will fail\n");
 
 
  325static int decode_open_type(uint8_t *
buf, 
unsigned int limit, 
unsigned int *
len, 
const uint8_t **p_object, 
unsigned int *p_num_octets)
 
  327    unsigned int octet_cnt = 0;
 
  333    if ((*
len + octet_cnt) > limit) {
 
  337    *p_num_octets = octet_cnt;
 
 
  347    unsigned int multiplier;
 
  355    if (
value < 0x4000) {
 
  365    multiplier = (
value < 0x10000) ? (
value >> 14) : 4;
 
  367    buf[*
len] = 0xC0 | multiplier;
 
  369    return multiplier << 14;
 
 
  374                unsigned int *
len, 
const uint8_t *data, 
unsigned int num_octets)
 
  377    unsigned int octet_idx;
 
  381    if (num_octets == 0) {
 
  387    for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
 
  389        if (enclen + *
len > buflen) {
 
  395            memcpy(&
buf[*
len], &data[octet_idx], enclen);
 
  398        if (enclen >= num_octets)
 
 
  413    const uint8_t *ifp = 
NULL;
 
  414    const uint8_t *data = 
NULL;
 
  415    unsigned int ifp_len = 0;
 
  425    memset(&s->
f[0], 0, 
sizeof(s->
f[0]));
 
  430    seq_no = (
buf[0] << 8) | 
buf[1];
 
  443    if (seq_no < 0x000F && s->rx_seq_no > 0xFFF0) {
 
  457    if ((
buf[ptr++] & 0x80) == 0) {
 
  467                for (i = 0; i < count && total_count + i < 
ARRAY_LEN(bufs); i++) {
 
  472                    if (!bufs[total_count + i] || !lengths[total_count + i]) {
 
  480            while (stat2 > 0 && total_count < 
ARRAY_LEN(bufs));
 
  482            for (i = total_count; i > 0; i--) {
 
  486                    ast_debug(3, 
"Recovering lost packet via secondary %d, len %u\n", seq_no - i, lengths[i - 1]);
 
  491                    s->
f[ifp_no].
seqno = seq_no - i;
 
  492                    s->
f[ifp_no].
datalen = lengths[i - 1];
 
  493                    s->
f[ifp_no].
data.
ptr = (uint8_t *) bufs[i - 1];
 
  495                    s->
f[ifp_no].
src = 
"UDPTL";
 
  524        memset(repaired, 0, 
sizeof(repaired));
 
  527        memcpy(s->
rx[x].
buf, ifp, ifp_len);
 
  545        entries = 
buf[ptr++];
 
  552        for (i = 0; i < entries; i++) {
 
  561            fprintf(stderr, 
"FEC: ");
 
  562            for (j = 0; j < s->
rx[x].
fec_len[i]; j++)
 
  563                fprintf(stderr, 
"%02hhX ", data[j]);
 
  564            fprintf(stderr, 
"\n");
 
  586                        which = (which == -1) ? k : -2;
 
  590                    for (j = 0; j < s->
rx[l].
fec_len[m]; j++) {
 
  596                    repaired[which] = 
TRUE;
 
  612                s->
f[ifp_no].
src = 
"UDPTL";
 
  629        s->
f[ifp_no].
seqno = seq_no;
 
  631        s->
f[ifp_no].
data.
ptr = (uint8_t *) ifp;
 
  633        s->
f[ifp_no].
src = 
"UDPTL";
 
 
  668    memcpy(s->
tx[entry].
buf, ifp, ifp_len);
 
  702        for (i = 0; i < entries; i++) {
 
  705                ast_debug(1, 
"UDPTL (%s): Encoding failed at i=%d, j=%d\n",
 
  717            if (seq < s->error_correction_span)
 
  729        for (m = 0; m < entries; m++) {
 
  734                if (high_tide < s->tx[i].buf_len) {
 
  735                    for (j = 0; j < high_tide; j++)
 
  736                        fec[j] ^= s->
tx[i].
buf[j];
 
  738                        fec[j] = s->
tx[i].
buf[j];
 
  742                        fec[j] ^= s->
tx[i].
buf[j];
 
 
  830            ast_debug(1, 
"UDPTL (%s): NAT, Using address %s\n",
 
  843            seq_no = (
buf[0] << 8) | 
buf[1];
 
  846        ast_verb(1, 
"UDPTL (%s): packet from %s (seq %d, len %d)\n",
 
 
  858    unsigned int new_max = 0;
 
  861        ast_log(
LOG_WARNING, 
"UDPTL (%s): Cannot calculate local_max_datagram before local_max_ifp has been set.\n",
 
 
  899    unsigned new_max = 0;
 
  902        ast_log(
LOG_WARNING, 
"UDPTL (%s): Cannot calculate far_max_ifp before far_max_datagram has been set.\n",
 
 
 1002    if ((
signed int) max_ifp > 0) {
 
 
 1061    if (!cfg || !cfg->general) {
 
 1066    if (!(udptl = 
ast_calloc(1, 
sizeof(*udptl)))) {
 
 1084                    AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) {
 
 1091    if (cfg->general->nochecksums)
 
 1092        setsockopt(udptl->
fd, SOL_SOCKET, SO_NO_CHECK, &cfg->general->nochecksums, 
sizeof(cfg->general->nochecksums));
 
 1096    x = (cfg->general->start == cfg->general->end) ? cfg->general->start : (
ast_random() % (cfg->general->end - cfg->general->start)) + cfg->general->start;
 
 1097    if (cfg->general->use_even_ports && (x & 1)) {
 
 1107        if (
errno != EADDRINUSE && 
errno != EACCES) {
 
 1113        if (cfg->general->use_even_ports) {
 
 1118        if (x > cfg->general->end)
 
 1119            x = cfg->general->start;
 
 1120        if (x == startplace) {
 
 1127    if (
io && 
sched && callbackmode) {
 
 
 1143    va_start(ap, format);
 
 
 1192    uint8_t 
buf[bufsize];
 
 1194    memset(
buf, 0, 
sizeof(
buf));
 
 1214            "UDPTL (%s): UDPTL asked to send %u bytes of IFP when far end only prepared to accept %d bytes; data loss will occur." 
 1215            "You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n",
 
 1232            ast_verb(1, 
"UDPTL (%s): packet to %s (seq %u, len %u)\n",
 
 
 1244        e->
command = 
"udptl set debug {on|off|ip}";
 
 1246            "Usage: udptl set debug {on|off|ip host[:port]}\n" 
 1247            "       Enable or disable dumping of UDPTL packets.\n" 
 1248            "       If ip is specified, limit the dumped packets to those to and from\n" 
 1249            "       the specified 'host' with optional port.\n";
 
 1255    if (
a->argc < 4 || 
a->argc > 5)
 
 1259        if (!strncasecmp(
a->argv[3], 
"on", 2)) {
 
 1262            ast_cli(
a->fd, 
"UDPTL Debugging Enabled\n");
 
 1263        } 
else if (!strncasecmp(
a->argv[3], 
"off", 3)) {
 
 1265            ast_cli(
a->fd, 
"UDPTL Debugging Disabled\n");
 
 1271        if (strncasecmp(
a->argv[3], 
"ip", 2))
 
 
 1291        e->
command = 
"udptl show config";
 
 1293            "Usage: udptl show config\n" 
 1294            "       Display UDPTL configuration options\n";
 
 1304    ast_cli(
a->fd, 
"UDPTL Global options\n");
 
 1305    ast_cli(
a->fd, 
"--------------------\n");
 
 1306    ast_cli(
a->fd, 
"udptlstart:      %u\n", cfg->general->start);
 
 1307    ast_cli(
a->fd, 
"udptlend:        %u\n", cfg->general->end);
 
 1308    ast_cli(
a->fd, 
"udptlfecentries: %u\n", cfg->general->fecentries);
 
 1309    ast_cli(
a->fd, 
"udptlfecspan:    %u\n", cfg->general->fecspan);
 
 
 1344    if (!strcasecmp(
var->name, 
"t38faxudpec")) {
 
 1346    } 
else if (!strcasecmp(
var->name, 
"t38faxmaxdatagram")) {
 
 1347        ast_log(
LOG_WARNING, 
"t38faxmaxdatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n");
 
 
 1359                ast_log(
LOG_ERROR, 
"Failed to load udptl.conf and failed to initialize defaults.\n");
 
 
 1378        ast_log(
LOG_WARNING, 
"Disabling UDPTL checksums is not supported on this operating system!\n");
 
 
 1465    .
requires = 
"extconfig",
 
Access Control of various sorts.
void ast_cli_unregister_multiple(void)
static const struct adsi_event events[]
static volatile unsigned int seq
Asterisk main include file. File version handling, generic pbx functions.
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define AO2_GLOBAL_OBJ_STATIC(name)
Define a global object holder to be used to hold an ao2 object, statically initialized.
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc(data_size, destructor_fn)
#define ao2_t_global_obj_release(holder, tag)
static struct console_pvt globals
static struct io_context * io
General Asterisk PBX channel definitions.
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
Standard Command Line Interface.
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Configuration option-handling.
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
@ ACO_PROCESS_ERROR
Their was an error and no changes were applied.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_BOOL_T
Type for default option handler for bools (ast_true/ast_false)
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
#define CONFIG_INFO_CORE(mod, name, arr, alloc,...)
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Asterisk internal frame definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
struct ast_frame ast_null_frame
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Asterisk locking-related definitions:
Asterisk module definitions.
@ AST_MODFLAG_GLOBAL_SYMBOLS
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
@ AST_MODULE_LOAD_SUCCESS
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
ssize_t ast_recvfrom(int sockfd, void *buf, size_t len, int flags, struct ast_sockaddr *src_addr)
Wrapper around recvfrom(2) that uses struct ast_sockaddr.
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
The representation of a single configuration file to be processed.
Type information about a category-level configurable object.
descriptor for a cli entry.
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@239 data
Socket address structure.
Structure for an UDPTL session.
ast_udptl_callback callback
struct ast_sched_context * sched
unsigned int lasteventseqn
unsigned int error_correction_entries
udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK+1]
unsigned char rawdata[8192+AST_FRIENDLY_OFFSET]
unsigned int error_correction_span
enum ast_t38_ec_modes error_correction_scheme
udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK+1]
Structure for variables, used for configurations and for channel variables.
Global IO variables are now in a struct in order to be made threadsafe.
struct udptl_global_options * general
uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM]
unsigned int fec_len[MAX_FEC_ENTRIES]
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]
unsigned int use_even_ports
void ast_udptl_destroy(struct ast_udptl *udptl)
static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len)
enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme(const struct ast_udptl *udptl)
static int encode_open_type(const struct ast_udptl *udptl, uint8_t *buf, unsigned int buflen, unsigned int *len, const uint8_t *data, unsigned int num_octets)
static void * udptl_snapshot_alloc(void)
static int removed_options_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int udptl_debug_test_addr(const struct ast_sockaddr *addr)
#define DEFAULT_UDPTLSTART
static struct aco_file udptl_conf
static struct ast_cli_entry cli_udptl[]
void ast_udptl_stop(struct ast_udptl *udptl)
int ast_udptl_fd(const struct ast_udptl *udptl)
void ast_udptl_get_peer(const struct ast_udptl *udptl, struct ast_sockaddr *them)
static void calculate_far_max_ifp(struct ast_udptl *udptl)
static struct aco_type general_option
int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
static void udptl_config_destructor(void *obj)
void ast_udptl_set_peer(struct ast_udptl *udptl, const struct ast_sockaddr *them)
void ast_udptl_set_tag(struct ast_udptl *udptl, const char *format,...)
Associates a character string 'tag' with a UDPTL session.
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
static unsigned int encode_length(uint8_t *buf, unsigned int *len, unsigned int value)
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
retrieves far max ifp
void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
static int reload_module(void)
#define LOCAL_FAX_MAX_DATAGRAM
void ast_udptl_get_us(const struct ast_udptl *udptl, struct ast_sockaddr *us)
#define DEFAULT_FAX_MAX_DATAGRAM
struct ast_frame * ast_udptl_read(struct ast_udptl *udptl)
static int udptl_pre_apply_config(void)
static struct aco_type * general_options[]
int ast_udptl_setqos(struct ast_udptl *udptl, unsigned int tos, unsigned int cos)
static char * handle_cli_udptl_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define FAX_MAX_DATAGRAM_LIMIT
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
retrieves local_max_datagram.
void ast_udptl_set_data(struct ast_udptl *udptl, void *data)
static void calculate_local_max_datagram(struct ast_udptl *udptl)
void ast_udptl_set_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram)
sets far max datagram size. If max_datagram is = 0, the far max datagram size is set to a default val...
static int load_module(void)
void ast_udptl_set_callback(struct ast_udptl *udptl, ast_udptl_callback callback)
static int udptlread(int *id, int fd, short events, void *cbdata)
static int decode_open_type(uint8_t *buf, unsigned int limit, unsigned int *len, const uint8_t **p_object, unsigned int *p_num_octets)
static void __ast_udptl_reload(int reload)
static int unload_module(void)
static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, unsigned int buflen, uint8_t *ifp, unsigned int ifp_len)
unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl)
static struct ast_sockaddr udptldebugaddr
static int decode_length(uint8_t *buf, unsigned int limit, unsigned int *len, unsigned int *pvalue)
void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
struct ast_udptl * ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *addr)
static char * handle_cli_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int(* ast_udptl_callback)(struct ast_udptl *udptl, struct ast_frame *f, void *data)
@ UDPTL_ERROR_CORRECTION_FEC
@ UDPTL_ERROR_CORRECTION_NONE
@ UDPTL_ERROR_CORRECTION_REDUNDANCY
Handle unaligned data access.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
long int ast_random(void)