116 #define UDPTL_MTU 1200 122 #define TRUE (!FALSE) 125 #define LOG_TAG(u) S_OR(u->tag, "no tag") 127 #define DEFAULT_UDPTLSTART 4000 128 #define DEFAULT_UDPTLEND 4999 133 #define LOCAL_FAX_MAX_DATAGRAM 1400 134 #define DEFAULT_FAX_MAX_DATAGRAM 400 135 #define FAX_MAX_DATAGRAM_LIMIT 1400 136 #define MAX_FEC_ENTRIES 5 137 #define MAX_FEC_SPAN 5 139 #define UDPTL_BUF_MASK 15 243 .category =
"general",
278 if ((buf[*len] & 0x80) == 0) {
283 if ((buf[*len] & 0x40) == 0) {
284 if (*len == limit - 1)
286 *pvalue = (buf[*
len] & 0x3F) << 8;
288 *pvalue |= buf[*
len];
292 *pvalue = (buf[*
len] & 0x3F) << 14;
295 ast_debug(1,
"UDPTL packet with length greater than 16K received, decoding will fail\n");
300 static int decode_open_type(uint8_t *
buf,
unsigned int limit,
unsigned int *
len,
const uint8_t **p_object,
unsigned int *p_num_octets)
302 unsigned int octet_cnt = 0;
308 if ((*len + octet_cnt) > limit) {
312 *p_num_octets = octet_cnt;
313 *p_object = &buf[*
len];
322 unsigned int multiplier;
330 if (value < 0x4000) {
333 buf[*
len] = ((0x8000 |
value) >> 8) & 0xFF;
335 buf[*
len] = value & 0xFF;
340 multiplier = (value < 0x10000) ? (value >> 14) : 4;
342 buf[*
len] = 0xC0 | multiplier;
344 return multiplier << 14;
349 unsigned int *
len,
const uint8_t *data,
unsigned int num_octets)
352 unsigned int octet_idx;
356 if (num_octets == 0) {
362 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
364 if (enclen + *len > buflen) {
366 LOG_TAG(udptl), enclen, *len, buflen);
370 memcpy(&buf[*len], &data[octet_idx], enclen);
373 if (enclen >= num_octets)
388 const uint8_t *ifp =
NULL;
389 const uint8_t *data =
NULL;
390 unsigned int ifp_len = 0;
400 memset(&s->
f[0], 0,
sizeof(s->
f[0]));
405 seq_no = (buf[0] << 8) | buf[1];
418 if (seq_no < 0x000F && s->rx_seq_no > 0xFFF0) {
432 if ((buf[ptr++] & 0x80) == 0) {
442 for (i = 0; i < count && total_count + i <
ARRAY_LEN(bufs); i++) {
443 if ((stat1 =
decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) {
447 if (!bufs[total_count + i] || !lengths[total_count + i]) {
455 while (stat2 > 0 && total_count <
ARRAY_LEN(bufs));
457 for (i = total_count; i > 0; i--) {
461 ast_debug(3,
"Recovering lost packet via secondary %d, len %u\n", seq_no - i, lengths[i - 1]);
466 s->
f[ifp_no].
seqno = seq_no - i;
467 s->
f[ifp_no].
datalen = lengths[i - 1];
468 s->
f[ifp_no].
data.
ptr = (uint8_t *) bufs[i - 1];
470 s->
f[ifp_no].
src =
"UDPTL";
499 memset(repaired, 0,
sizeof(repaired));
502 memcpy(s->
rx[x].
buf, ifp, ifp_len);
520 entries = buf[ptr++];
527 for (i = 0; i < entries; i++) {
536 fprintf(stderr,
"FEC: ");
537 for (j = 0; j < s->
rx[x].
fec_len[i]; j++)
538 fprintf(stderr,
"%02hhX ", data[j]);
539 fprintf(stderr,
"\n");
545 for (l = x; l != ((x - (16 - span*entries)) &
UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) {
552 int limit = (l + m) & UDPTL_BUF_MASK;
561 which = (which == -1) ? k : -2;
565 for (j = 0; j < s->
rx[l].
fec_len[m]; j++) {
571 repaired[which] =
TRUE;
587 s->
f[ifp_no].
src =
"UDPTL";
604 s->
f[ifp_no].
seqno = seq_no;
606 s->
f[ifp_no].
data.
ptr = (uint8_t *) ifp;
608 s->
f[ifp_no].
src =
"UDPTL";
643 memcpy(s->
tx[entry].
buf, ifp, ifp_len);
649 buf[len++] = (seq >> 8) & 0xFF;
650 buf[len++] = seq & 0xFF;
677 for (i = 0; i < entries; i++) {
678 j = (entry - i - 1) & UDPTL_BUF_MASK;
680 ast_debug(1,
"UDPTL (%s): Encoding failed at i=%d, j=%d\n",
692 if (seq < s->error_correction_span)
703 buf[len++] = entries;
704 for (m = 0; m < entries; m++) {
706 limit = (entry + m) & UDPTL_BUF_MASK;
708 for (i = (limit - span*entries) &
UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) {
709 if (high_tide < s->tx[i].buf_len) {
710 for (j = 0; j < high_tide; j++)
711 fec[j] ^= s->
tx[i].
buf[j];
713 fec[j] = s->
tx[i].
buf[j];
717 fec[j] ^= s->
tx[i].
buf[j];
805 ast_debug(1,
"UDPTL (%s): NAT, Using address %s\n",
818 seq_no = (buf[0] << 8) | buf[1];
821 ast_verb(1,
"UDPTL (%s): packet from %s (seq %d, len %d)\n",
833 unsigned int new_max = 0;
836 ast_log(
LOG_WARNING,
"UDPTL (%s): Cannot calculate local_max_datagram before local_max_ifp has been set.\n",
874 unsigned new_max = 0;
877 ast_log(
LOG_WARNING,
"UDPTL (%s): Cannot calculate far_max_ifp before far_max_datagram has been set.\n",
977 if ((
signed int) max_ifp > 0) {
1036 if (!cfg || !cfg->general) {
1041 if (!(udptl =
ast_calloc(1,
sizeof(*udptl)))) {
1059 AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) {
1066 if (cfg->general->nochecksums)
1067 setsockopt(udptl->
fd, SOL_SOCKET, SO_NO_CHECK, &cfg->general->nochecksums,
sizeof(cfg->general->nochecksums));
1071 x = (cfg->general->start == cfg->general->end) ? cfg->general->start : (
ast_random() % (cfg->general->end - cfg->general->start)) + cfg->general->start;
1072 if (cfg->general->use_even_ports && (x & 1)) {
1082 if (
errno != EADDRINUSE &&
errno != EACCES) {
1088 if (cfg->general->use_even_ports) {
1093 if (x > cfg->general->end)
1094 x = cfg->general->start;
1095 if (x == startplace) {
1102 if (io && sched && callbackmode) {
1118 va_start(ap, format);
1167 uint8_t
buf[bufsize];
1169 memset(
buf, 0,
sizeof(
buf));
1189 "UDPTL (%s): UDPTL asked to send %u bytes of IFP when far end only prepared to accept %d bytes; data loss will occur." 1190 "You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n",
1207 ast_verb(1,
"UDPTL (%s): packet to %s (seq %u, len %u)\n",
1219 e->
command =
"udptl set debug {on|off|ip}";
1221 "Usage: udptl set debug {on|off|ip host[:port]}\n" 1222 " Enable or disable dumping of UDPTL packets.\n" 1223 " If ip is specified, limit the dumped packets to those to and from\n" 1224 " the specified 'host' with optional port.\n";
1234 if (!strncasecmp(a->
argv[3],
"on", 2)) {
1237 ast_cli(a->
fd,
"UDPTL Debugging Enabled\n");
1238 }
else if (!strncasecmp(a->
argv[3],
"off", 3)) {
1240 ast_cli(a->
fd,
"UDPTL Debugging Disabled\n");
1246 if (strncasecmp(a->
argv[3],
"ip", 2))
1266 e->
command =
"udptl show config";
1268 "Usage: udptl show config\n" 1269 " Display UDPTL configuration options\n";
1279 ast_cli(a->
fd,
"UDPTL Global options\n");
1280 ast_cli(a->
fd,
"--------------------\n");
1281 ast_cli(a->
fd,
"udptlstart: %u\n", cfg->general->start);
1282 ast_cli(a->
fd,
"udptlend: %u\n", cfg->general->end);
1283 ast_cli(a->
fd,
"udptlfecentries: %u\n", cfg->general->fecentries);
1284 ast_cli(a->
fd,
"udptlfecspan: %u\n", cfg->general->fecspan);
1319 if (!strcasecmp(var->
name,
"t38faxudpec")) {
1320 ast_log(
LOG_WARNING,
"t38faxudpec in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n");
1321 }
else if (!strcasecmp(var->
name,
"t38faxmaxdatagram")) {
1322 ast_log(
LOG_WARNING,
"t38faxmaxdatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n");
1334 ast_log(
LOG_ERROR,
"Failed to load udptl.conf and failed to initialize defaults.\n");
1353 ast_log(
LOG_WARNING,
"Disabling UDPTL checksums is not supported on this operating system!\n");
1440 .requires =
"extconfig",
static void * udptl_snapshot_alloc(void)
CONFIG_INFO_CORE("udptl", cfg_info, globals, udptl_snapshot_alloc,.files=ACO_FILES(&udptl_conf),.pre_apply_config=udptl_pre_apply_config,)
#define AST_CLI_DEFINE(fn, txt,...)
static AO2_GLOBAL_OBJ_STATIC(globals)
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_udptl_setqos(struct ast_udptl *udptl, unsigned int tos, unsigned int cos)
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static struct aco_file udptl_conf
static void udptl_config_destructor(void *obj)
static struct ast_sched_context * sched
unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl)
unsigned int error_correction_span
static int udptl_pre_apply_config(void)
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
int ast_udptl_fd(const struct ast_udptl *udptl)
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme(const struct ast_udptl *udptl)
static char * handle_cli_udptl_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_sockaddr udptldebugaddr
static void __ast_udptl_reload(int reload)
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
void ast_udptl_get_us(const struct ast_udptl *udptl, struct ast_sockaddr *us)
ast_udptl_callback callback
static void calculate_local_max_datagram(struct ast_udptl *udptl)
descriptor for a cli entry.
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
void ast_udptl_set_peer(struct ast_udptl *udptl, const struct ast_sockaddr *them)
Structure for variables, used for configurations and for channel variables.
static int reload_module(void)
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
#define ao2_t_global_obj_release(holder, tag)
Release the ao2 object held in the global holder.
Structure for an UDPTL session.
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
static const struct adsi_event events[]
#define ast_cli_register_multiple(e, len)
Register multiple commands.
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 ao2_global_obj_ref(holder)
#define DEFAULT_UDPTLSTART
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
unsigned int error_correction_entries
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
static int udptl_debug_test_addr(const struct ast_sockaddr *addr)
The representation of a single configuration file to be processed.
void ast_cli(int fd, const char *fmt,...)
Socket address structure.
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
#define ast_verb(level,...)
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
static struct aco_type * general_options[]
struct ast_frame_subclass subclass
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]
static int decode_length(uint8_t *buf, unsigned int limit, unsigned int *len, unsigned int *pvalue)
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)
unsigned int fec_len[MAX_FEC_ENTRIES]
static int removed_options_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
static unsigned int encode_length(uint8_t *buf, unsigned int *len, unsigned int value)
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
unsigned int lasteventseqn
#define ast_debug(level,...)
Log a DEBUG message.
Handle unaligned data access.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Type for default option handler for unsigned integers.
struct ast_sched_context * sched
static struct io_context * io
int(* ast_udptl_callback)(struct ast_udptl *udptl, struct ast_frame *f, void *data)
udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK+1]
Access Control of various sorts.
Global IO variables are now in a struct in order to be made threadsafe.
#define LOCAL_FAX_MAX_DATAGRAM
Asterisk internal frame definitions.
#define ao2_ref(o, delta)
long int ast_random(void)
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
static struct console_pvt globals
static int decode_open_type(uint8_t *buf, unsigned int limit, unsigned int *len, const uint8_t **p_object, unsigned int *p_num_octets)
struct ast_frame * ast_udptl_read(struct ast_udptl *udptl)
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]
Their was an error and no changes were applied.
static int udptlread(int *id, int fd, short events, void *cbdata)
Configuration option-handling.
static int unload_module(void)
void ast_udptl_stop(struct ast_udptl *udptl)
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
void ast_udptl_set_tag(struct ast_udptl *udptl, const char *format,...)
Associates a character string 'tag' with a UDPTL session.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
void ast_udptl_set_callback(struct ast_udptl *udptl, ast_udptl_callback callback)
Type for default option handler for bools (ast_true/ast_false)
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
retrieves local_max_datagram.
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.
#define ao2_alloc(data_size, destructor_fn)
static int load_module(void)
void ast_udptl_get_peer(const struct ast_udptl *udptl, struct ast_sockaddr *them)
uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM]
struct ast_udptl * ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *addr)
void ast_udptl_set_data(struct ast_udptl *udptl, void *data)
#define ast_calloc(num, len)
A wrapper for calloc()
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...
unsigned int use_even_ports
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
Module could not be loaded properly.
void ast_udptl_destroy(struct ast_udptl *udptl)
void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, unsigned int buflen, uint8_t *ifp, unsigned int ifp_len)
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct ast_frame ast_null_frame
#define ao2_global_obj_replace_unref(holder, obj)
static volatile unsigned int seq
Standard Command Line Interface.
Type information about a category-level configurable object.
unsigned char rawdata[8192+AST_FRIENDLY_OFFSET]
Data structure associated with a single frame of data.
union ast_frame::@263 data
enum ast_frame_type frametype
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
static void calculate_far_max_ifp(struct ast_udptl *udptl)
#define FAX_MAX_DATAGRAM_LIMIT
static char * handle_cli_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK+1]
struct udptl_global_options * general
static struct ast_cli_entry cli_udptl[]
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
static snd_pcm_format_t format
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len)
enum ast_t38_ec_modes error_correction_scheme
static struct aco_type general_option
#define DEFAULT_FAX_MAX_DATAGRAM
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
retrieves far max ifp
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.