74 #define UDPTL_MTU 1200
83 #define LOG_TAG(u) S_OR(u->tag, "no tag")
90 static int nochecksums;
96 #define LOCAL_FAX_MAX_DATAGRAM 1400
97 #define DEFAULT_FAX_MAX_DATAGRAM 400
98 #define FAX_MAX_DATAGRAM_LIMIT 1400
99 #define MAX_FEC_ENTRIES 5
100 #define MAX_FEC_SPAN 5
102 #define UDPTL_BUF_MASK 15
201 static int decode_length(uint8_t *buf,
unsigned int limit,
unsigned int *
len,
unsigned int *pvalue)
205 if ((buf[*len] & 0x80) == 0) {
210 if ((buf[*len] & 0x40) == 0) {
211 if (*len == limit - 1)
213 *pvalue = (buf[*
len] & 0x3F) << 8;
215 *pvalue |= buf[*
len];
219 *pvalue = (buf[*
len] & 0x3F) << 14;
222 ast_debug(1,
"UDPTL packet with length greater than 16K received, decoding will fail\n");
227 static int decode_open_type(uint8_t *buf,
unsigned int limit,
unsigned int *
len,
const uint8_t **p_object,
unsigned int *p_num_octets)
229 unsigned int octet_cnt = 0;
236 if ((*len + octet_cnt) > limit)
239 *p_num_octets = octet_cnt;
240 *p_object = &buf[*
len];
250 unsigned int multiplier;
258 if (value < 0x4000) {
261 buf[*
len] = ((0x8000 |
value) >> 8) & 0xFF;
263 buf[*
len] = value & 0xFF;
268 multiplier = (value < 0x10000) ? (value >> 14) : 4;
270 buf[*
len] = 0xC0 | multiplier;
272 return multiplier << 14;
277 unsigned int *
len,
const uint8_t *data,
unsigned int num_octets)
280 unsigned int octet_idx;
284 if (num_octets == 0) {
290 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
293 if (enclen + *len > buflen) {
295 LOG_TAG(udptl), enclen, *len, buflen);
299 memcpy(&buf[*len], &data[octet_idx], enclen);
302 if (enclen >= num_octets)
317 const uint8_t *ifp = NULL;
318 const uint8_t *data = NULL;
319 unsigned int ifp_len = 0;
329 memset(&s->
f[0], 0,
sizeof(s->
f[0]));
334 seq_no = (buf[0] << 8) | buf[1];
343 if ((buf[ptr++] & 0x80) == 0) {
353 for (i = 0; i < count && total_count + i <
ARRAY_LEN(bufs); i++) {
354 if ((stat1 =
decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) {
358 if (!bufs[total_count + i] || !lengths[total_count + i]) {
366 while (stat2 > 0 && total_count <
ARRAY_LEN(bufs));
368 for (i = total_count; i > 0; i--) {
372 ast_debug(3,
"Recovering lost packet via secondary %d, len %u\n", seq_no - i, lengths[i - 1]);
377 s->
f[ifp_no].
seqno = seq_no - i;
378 s->
f[ifp_no].
datalen = lengths[i - 1];
379 s->
f[ifp_no].
data.
ptr = (uint8_t *) bufs[i - 1];
381 s->
f[ifp_no].
src =
"UDPTL";
410 memset(repaired, 0,
sizeof(repaired));
413 memcpy(s->
rx[x].
buf, ifp, ifp_len);
431 entries = buf[ptr++];
438 for (i = 0; i < entries; i++) {
447 fprintf(stderr,
"FEC: ");
448 for (j = 0; j < s->
rx[x].
fec_len[i]; j++)
449 fprintf(stderr,
"%02X ", data[j]);
450 fprintf(stderr,
"\n");
456 for (l = x; l != ((x - (16 - span*entries)) &
UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) {
463 int limit = (l + m) & UDPTL_BUF_MASK;
472 which = (which == -1) ? k : -2;
476 for (j = 0; j < s->
rx[l].
fec_len[m]; j++) {
482 repaired[which] =
TRUE;
498 s->
f[ifp_no].
src =
"UDPTL";
515 s->
f[ifp_no].
seqno = seq_no;
517 s->
f[ifp_no].
data.
ptr = (uint8_t *) ifp;
519 s->
f[ifp_no].
src =
"UDPTL";
554 memcpy(s->
tx[entry].
buf, ifp, ifp_len);
560 buf[len++] = (seq >> 8) & 0xFF;
561 buf[len++] = seq & 0xFF;
590 for (i = 0; i < entries; i++) {
591 j = (entry - i - 1) & UDPTL_BUF_MASK;
593 ast_debug(1,
"UDPTL (%s): Encoding failed at i=%d, j=%d\n",
605 if (seq < s->error_correction_span)
616 buf[len++] = entries;
617 for (m = 0; m < entries; m++) {
619 limit = (entry + m) & UDPTL_BUF_MASK;
621 for (i = (limit - span*entries) &
UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) {
622 if (high_tide < s->tx[i].buf_len) {
623 for (j = 0; j < high_tide; j++)
624 fec[j] ^= s->
tx[i].
buf[j];
626 fec[j] = s->
tx[i].
buf[j];
630 fec[j] ^= s->
tx[i].
buf[j];
706 ast_debug(1,
"UDPTL (%s): NAT, Using address %s\n",
719 seq_no = (buf[0] << 8) | buf[1];
722 ast_verb(1,
"UDPTL (%s): packet from %s (seq %d, len %d)\n",
734 unsigned int new_max = 0;
737 ast_log(
LOG_WARNING,
"UDPTL (%s): Cannot calculate local_max_datagram before local_max_ifp has been set.\n",
775 unsigned new_max = 0;
778 ast_log(
LOG_WARNING,
"UDPTL (%s): Cannot calculate far_max_ifp before far_max_datagram has been set.\n",
878 if ((
signed int) max_ifp > 0) {
954 AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) {
959 flags = fcntl(udptl->
fd, F_GETFL);
960 fcntl(udptl->
fd, F_SETFL, flags | O_NONBLOCK);
963 setsockopt(udptl->
fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums,
sizeof(nochecksums));
967 if (use_even_ports && (x & 1)) {
983 if (use_even_ports) {
990 if (x == startplace) {
997 if (io && sched && callbackmode) {
1012 va_start(ap, format);
1062 uint8_t buf[bufsize];
1064 memset(buf, 0,
sizeof(buf));
1084 "UDPTL (%s): UDPTL asked to send %u bytes of IFP when far end only prepared to accept %d bytes; data loss will occur."
1085 "You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n",
1101 ast_verb(1,
"UDPTL (%s): packet to %s (seq %u, len %u)\n",
1195 memset(&ac1, 0,
sizeof(ac1));
1202 memset(&ac0, 0,
sizeof(ac0));
1216 ast_debug(1,
"Oooh, something is weird, backing out\n");
1224 ast_debug(1,
"Oooh, '%s' changed end address to %s\n",
1231 ast_debug(1,
"Oooh, '%s' changed end address to %s\n",
1249 ast_debug(1,
"Oooh, got a %s\n", f ?
"digit" :
"hangup");
1257 }
else if (who == c1) {
1275 e->
command =
"udptl set debug {on|off|ip}";
1277 "Usage: udptl set debug {on|off|ip host[:port]}\n"
1278 " Enable or disable dumping of UDPTL packets.\n"
1279 " If ip is specified, limit the dumped packets to those to and from\n"
1280 " the specified 'host' with optional port.\n";
1290 if (!strncasecmp(a->
argv[3],
"on", 2)) {
1293 ast_cli(a->
fd,
"UDPTL Debugging Enabled\n");
1294 }
else if (!strncasecmp(a->
argv[3],
"off", 3)) {
1296 ast_cli(a->
fd,
"UDPTL Debugging Disabled\n");
1302 if (strncasecmp(a->
argv[3],
"ip", 2))
1334 udptlfecentries = 0;
1340 udptlstart = atoi(s);
1341 if (udptlstart < 1024) {
1345 if (udptlstart > 65535) {
1352 if (udptlend < 1024) {
1356 if (udptlend > 65535) {
1369 ast_log(
LOG_WARNING,
"Disabling UDPTL checksums is not supported on this operating system!\n");
1373 ast_log(
LOG_WARNING,
"T38FaxUdpEC in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n");
1376 ast_log(
LOG_WARNING,
"T38FaxMaxDatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n");
1379 udptlfecentries = atoi(s);
1380 if (udptlfecentries < 1) {
1382 udptlfecentries = 1;
1390 udptlfecspan = atoi(s);
1391 if (udptlfecspan < 1) {
1405 if (udptlstart >= udptlend) {
1406 ast_log(
LOG_WARNING,
"Unreasonable values for UDPTL start/end ports; defaulting to 4500-4999.\n");
1410 if (use_even_ports && (udptlstart & 1)) {
1412 ast_log(
LOG_NOTICE,
"Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", udptlstart);
1414 if (use_even_ports && (udptlend & 1)) {
1416 ast_log(
LOG_NOTICE,
"Odd numbered udptlend specified but use_event_ports enabled. udptlend is now %d\n", udptlend);
1418 ast_verb(2,
"UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend);
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
union ast_frame_subclass subclass
struct ast_channel * masqr
#define ast_channel_lock(chan)
Main Channel structure associated with a channel.
#define AST_CLI_DEFINE(fn, txt,...)
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.
struct ast_channel * masq
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
struct ast_frame ast_null_frame
void ast_udptl_set_data(struct ast_udptl *udptl, void *data)
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
unsigned int error_correction_span
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
static struct io_context * io
#define ast_vasprintf(a, b, c)
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
void ast_udptl_init(void)
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.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
ast_udptl_callback callback
static void calculate_local_max_datagram(struct ast_udptl *udptl)
descriptor for a cli entry.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
void ast_udptl_set_callback(struct ast_udptl *udptl, ast_udptl_callback callback)
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
retrieves local_max_datagram.
int(*const set_udptl_peer)(struct ast_channel *chan, struct ast_udptl *peer)
Set UDPTL peer.
Structure for an UDPTL session.
Configuration File Parser.
int ast_netsock_set_qos(int netsocket, int tos, int cos, const char *desc)
int ast_udptl_reload(void)
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
void ast_udptl_get_peer(const struct ast_udptl *udptl, struct ast_sockaddr *them)
struct ast_udptl *(* get_udptl_info)(struct ast_channel *chan)
Get UDPTL struct, or NULL if unwilling to transfer.
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 struct ast_udptl_protocol * get_proto(struct ast_channel *chan)
unsigned int error_correction_entries
void ast_udptl_destroy(struct ast_udptl *udptl)
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)
void ast_cli(int fd, const char *fmt,...)
static int use_even_ports
Socket address structure.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
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.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme(const struct ast_udptl *udptl)
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
struct sched_context * sched
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]
static void udptl_shutdown(void)
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]
#define CONFIG_STATUS_FILEMISSING
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)
void ast_udptl_get_us(const struct ast_udptl *udptl, struct ast_sockaddr *us)
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
unsigned int lasteventseqn
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define ast_debug(level,...)
Log a DEBUG message.
Handle unaligned data access.
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK+1]
Access Control of various sorts.
Asterisk internal frame definitions.
Global IO variables are now in a struct in order to be made threadsafe.
#define LOCAL_FAX_MAX_DATAGRAM
#define AST_RWLIST_TRAVERSE
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
long int ast_random(void)
static int decode_open_type(uint8_t *buf, unsigned int limit, unsigned int *len, const uint8_t **p_object, unsigned int *p_num_octets)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]
static int udptlread(int *id, int fd, short events, void *cbdata)
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
retrieves far max ifp
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
void ast_udptl_proto_unregister(struct ast_udptl_protocol *proto)
void ast_udptl_set_peer(struct ast_udptl *udptl, const struct ast_sockaddr *them)
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
const ast_string_field name
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.
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
int ast_udptl_setqos(struct ast_udptl *udptl, unsigned int tos, unsigned int cos)
uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM]
#define ast_channel_unlock(chan)
int ast_udptl_fd(const struct ast_udptl *udptl)
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, unsigned int buflen, uint8_t *ifp, unsigned int ifp_len)
Structure used to handle boolean flags.
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
struct ast_frame * ast_udptl_read(struct ast_udptl *udptl)
static volatile unsigned int seq
#define AST_RWLIST_INSERT_TAIL
struct sched_context * sched
Standard Command Line Interface.
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
struct ast_udptl * ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *in)
int ast_udptl_proto_register(struct ast_udptl_protocol *proto)
void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
void ast_udptl_stop(struct ast_udptl *udptl)
unsigned char rawdata[8192+AST_FRIENDLY_OFFSET]
int ast_udptl_write(struct ast_udptl *udptl, struct ast_frame *f)
void ast_udptl_set_tag(struct ast_udptl *udptl, const char *format,...)
Associates a character string 'tag' with a UDPTL session.
Data structure associated with a single frame of data.
#define AST_RWLIST_REMOVE
unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl)
enum ast_frame_type frametype
static struct adsi_event events[]
#define ast_channel_trylock(chan)
static int udptlfecentries
#define CONFIG_STATUS_FILEINVALID
static void calculate_far_max_ifp(struct ast_udptl *udptl)
int(* ast_udptl_callback)(struct ast_udptl *udptl, struct ast_frame *f, void *data)
#define FAX_MAX_DATAGRAM_LIMIT
udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK+1]
static struct ast_cli_entry cli_udptl[]
static snd_pcm_format_t format
union ast_frame::@172 data
struct ast_channel_tech * tech
void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
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
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
#define DEFAULT_FAX_MAX_DATAGRAM
#define CONFIG_STATUS_FILEUNCHANGED
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.