Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Data Structures | Macros | Functions | Variables
udptl.c File Reference

UDPTL support for T.38 faxing. More...

#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include "asterisk/module.h"
#include "asterisk/udptl.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config_options.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/netsock2.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"
Include dependency graph for udptl.c:

Go to the source code of this file.

Data Structures

struct  ast_udptl
 Structure for an UDPTL session. More...
 
struct  udptl_config
 
struct  udptl_fec_rx_buffer_t
 
struct  udptl_fec_tx_buffer_t
 
struct  udptl_global_options
 

Macros

#define DEFAULT_FAX_MAX_DATAGRAM   400
 
#define DEFAULT_UDPTLEND   4999
 
#define DEFAULT_UDPTLSTART   4000
 
#define FALSE   0
 
#define FAX_MAX_DATAGRAM_LIMIT   1400
 
#define LOCAL_FAX_MAX_DATAGRAM   1400
 
#define LOG_TAG(u)   S_OR(u->tag, "no tag")
 
#define MAX_FEC_ENTRIES   5
 
#define MAX_FEC_SPAN   5
 
#define TRUE   (!FALSE)
 
#define UDPTL_BUF_MASK   15
 
#define UDPTL_MTU   1200
 

Functions

static void __ast_udptl_reload (int reload)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static AO2_GLOBAL_OBJ_STATIC (globals)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
void ast_udptl_destroy (struct ast_udptl *udptl)
 
int ast_udptl_fd (const struct ast_udptl *udptl)
 
enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme (const struct ast_udptl *udptl)
 
unsigned int ast_udptl_get_far_max_datagram (const struct ast_udptl *udptl)
 
unsigned int ast_udptl_get_far_max_ifp (struct ast_udptl *udptl)
 retrieves far max ifp More...
 
unsigned int ast_udptl_get_local_max_datagram (struct ast_udptl *udptl)
 retrieves local_max_datagram. More...
 
void ast_udptl_get_peer (const struct ast_udptl *udptl, struct ast_sockaddr *them)
 
void ast_udptl_get_us (const struct ast_udptl *udptl, struct ast_sockaddr *us)
 
struct ast_udptlast_udptl_new_with_bindaddr (struct ast_sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *addr)
 
struct ast_frameast_udptl_read (struct ast_udptl *udptl)
 
void ast_udptl_set_callback (struct ast_udptl *udptl, ast_udptl_callback callback)
 
void ast_udptl_set_data (struct ast_udptl *udptl, void *data)
 
void ast_udptl_set_error_correction_scheme (struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
 
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 value. More...
 
void ast_udptl_set_local_max_ifp (struct ast_udptl *udptl, unsigned int max_ifp)
 
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. More...
 
void ast_udptl_setnat (struct ast_udptl *udptl, int nat)
 
int ast_udptl_setqos (struct ast_udptl *udptl, unsigned int tos, unsigned int cos)
 
void ast_udptl_stop (struct ast_udptl *udptl)
 
int ast_udptl_write (struct ast_udptl *s, struct ast_frame *f)
 
static void calculate_far_max_ifp (struct ast_udptl *udptl)
 
static void calculate_local_max_datagram (struct ast_udptl *udptl)
 
 CONFIG_INFO_CORE ("udptl", cfg_info, globals, udptl_snapshot_alloc,.files=ACO_FILES(&udptl_conf),.pre_apply_config=udptl_pre_apply_config,)
 
static int decode_length (uint8_t *buf, unsigned int limit, unsigned int *len, unsigned int *pvalue)
 
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 unsigned int encode_length (uint8_t *buf, unsigned int *len, unsigned int value)
 
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 char * handle_cli_show_config (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_udptl_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int load_module (void)
 
static int reload_module (void)
 
static int removed_options_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int udptl_build_packet (struct ast_udptl *s, uint8_t *buf, unsigned int buflen, uint8_t *ifp, unsigned int ifp_len)
 
static void udptl_config_destructor (void *obj)
 
static int udptl_debug_test_addr (const struct ast_sockaddr *addr)
 
static int udptl_pre_apply_config (void)
 
static int udptl_rx_packet (struct ast_udptl *s, uint8_t *buf, unsigned int len)
 
static void * udptl_snapshot_alloc (void)
 
static int udptlread (int *id, int fd, short events, void *cbdata)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "UDPTL" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_udptl []
 
static struct aco_type general_option
 
static struct aco_typegeneral_options [] = ACO_TYPES(&general_option)
 
static struct aco_file udptl_conf
 
static int udptldebug
 
static struct ast_sockaddr udptldebugaddr
 

Detailed Description

UDPTL support for T.38 faxing.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Steve Underwood steve.nosp@m.u@co.nosp@m.ppice.nosp@m..org
Kevin P. Fleming kpfle.nosp@m.ming.nosp@m.@digi.nosp@m.um.c.nosp@m.om

Definition in file udptl.c.

Macro Definition Documentation

◆ DEFAULT_FAX_MAX_DATAGRAM

#define DEFAULT_FAX_MAX_DATAGRAM   400

Definition at line 134 of file udptl.c.

◆ DEFAULT_UDPTLEND

#define DEFAULT_UDPTLEND   4999

Definition at line 128 of file udptl.c.

◆ DEFAULT_UDPTLSTART

#define DEFAULT_UDPTLSTART   4000

Definition at line 127 of file udptl.c.

◆ FALSE

#define FALSE   0

Definition at line 119 of file udptl.c.

◆ FAX_MAX_DATAGRAM_LIMIT

#define FAX_MAX_DATAGRAM_LIMIT   1400

Definition at line 135 of file udptl.c.

◆ LOCAL_FAX_MAX_DATAGRAM

#define LOCAL_FAX_MAX_DATAGRAM   1400

Definition at line 133 of file udptl.c.

◆ LOG_TAG

#define LOG_TAG (   u)    S_OR(u->tag, "no tag")

Definition at line 125 of file udptl.c.

◆ MAX_FEC_ENTRIES

#define MAX_FEC_ENTRIES   5

Definition at line 136 of file udptl.c.

◆ MAX_FEC_SPAN

#define MAX_FEC_SPAN   5

Definition at line 137 of file udptl.c.

◆ TRUE

#define TRUE   (!FALSE)

Definition at line 122 of file udptl.c.

◆ UDPTL_BUF_MASK

#define UDPTL_BUF_MASK   15

Definition at line 139 of file udptl.c.

◆ UDPTL_MTU

#define UDPTL_MTU   1200

Definition at line 116 of file udptl.c.

Function Documentation

◆ __ast_udptl_reload()

static void __ast_udptl_reload ( int  reload)
static

Definition at line 1327 of file udptl.c.

1328 {
1329  if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) {
1330  if (!reload) {
1331  RAII_VAR(struct udptl_config *, udptl_cfg, udptl_snapshot_alloc(), ao2_cleanup);
1332 
1333  if (aco_set_defaults(&general_option, "general", udptl_cfg->general)) {
1334  ast_log(LOG_ERROR, "Failed to load udptl.conf and failed to initialize defaults.\n");
1335  return;
1336  }
1337 
1338  ast_log(LOG_NOTICE, "Could not load udptl config; using defaults\n");
1340  }
1341  }
1342 }
#define ast_log
Definition: astobj2.c:42
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
Definition: astobj2.h:901
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
static struct console_pvt globals
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
@ ACO_PROCESS_ERROR
Their was an error and no changes were applied.
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 LOG_ERROR
#define LOG_NOTICE
static int reload(void)
static void * udptl_snapshot_alloc(void)
Definition: udptl.c:1302
static struct aco_type general_option
Definition: udptl.c:238
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:936

References aco_process_config(), ACO_PROCESS_ERROR, aco_set_defaults(), ao2_cleanup, ao2_global_obj_replace_unref, ast_log, general_option, globals, LOG_ERROR, LOG_NOTICE, RAII_VAR, reload(), and udptl_snapshot_alloc().

Referenced by reload_module().

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1441 of file udptl.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1441 of file udptl.c.

◆ AO2_GLOBAL_OBJ_STATIC()

static AO2_GLOBAL_OBJ_STATIC ( globals  )
static

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1441 of file udptl.c.

◆ ast_udptl_destroy()

void ast_udptl_destroy ( struct ast_udptl udptl)

Definition at line 1150 of file udptl.c.

1151 {
1152  if (udptl->ioid)
1153  ast_io_remove(udptl->io, udptl->ioid);
1154  if (udptl->fd > -1)
1155  close(udptl->fd);
1156  if (udptl->tag)
1157  ast_free(udptl->tag);
1158  ast_free(udptl);
1159 }
#define ast_free(a)
Definition: astmm.h:180
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Definition: io.c:245
int * ioid
Definition: udptl.c:166
int fd
Definition: udptl.c:157
char * tag
Definition: udptl.c:170
struct io_context * io
Definition: udptl.c:168

References ast_free, ast_io_remove(), ast_udptl::fd, ast_udptl::io, ast_udptl::ioid, and ast_udptl::tag.

Referenced by ooh323_destroy(), and sip_pvt_dtor().

◆ ast_udptl_fd()

int ast_udptl_fd ( const struct ast_udptl udptl)

Definition at line 730 of file udptl.c.

731 {
732  return udptl->fd;
733 }

References ast_udptl::fd.

Referenced by apply_negotiated_sdp_stream(), configure_local_rtp(), initialize_udptl(), and sip_new().

◆ ast_udptl_get_error_correction_scheme()

enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme ( const struct ast_udptl udptl)

◆ ast_udptl_get_far_max_datagram()

unsigned int ast_udptl_get_far_max_datagram ( const struct ast_udptl udptl)

Definition at line 1008 of file udptl.c.

1009 {
1010  if (udptl->far_max_datagram < 0) {
1011  return 0;
1012  }
1013  return udptl->far_max_datagram;
1014 }
int far_max_datagram
Definition: udptl.c:191

References ast_udptl::far_max_datagram.

Referenced by process_sdp().

◆ ast_udptl_get_far_max_ifp()

unsigned int ast_udptl_get_far_max_ifp ( struct ast_udptl udptl)

retrieves far max ifp

Returns
positive value representing max ifp size
Return values
0if no value is present

Definition at line 1016 of file udptl.c.

1017 {
1018  if (udptl->far_max_ifp == -1) {
1019  calculate_far_max_ifp(udptl);
1020  }
1021 
1022  if (udptl->far_max_ifp < 0) {
1023  return 0;
1024  }
1025  return udptl->far_max_ifp;
1026 }
int far_max_ifp
Definition: udptl.c:205
static void calculate_far_max_ifp(struct ast_udptl *udptl)
Definition: udptl.c:872

References calculate_far_max_ifp(), and ast_udptl::far_max_ifp.

Referenced by change_t38_state(), interpret_t38_parameters(), onModeChanged(), ooh323_indicate(), setup_udptl_connection(), t38_change_state(), and t38_interpret_parameters().

◆ ast_udptl_get_local_max_datagram()

unsigned int ast_udptl_get_local_max_datagram ( struct ast_udptl udptl)

retrieves local_max_datagram.

Returns
positive value representing max datagram size.
Return values
0if no value is present

Definition at line 984 of file udptl.c.

985 {
986  if (udptl->local_max_datagram == -1) {
988  }
989 
990  /* this function expects a unsigned value in return. */
991  if (udptl->local_max_datagram < 0) {
992  return 0;
993  }
994  return udptl->local_max_datagram;
995 }
int local_max_datagram
Definition: udptl.c:197
static void calculate_local_max_datagram(struct ast_udptl *udptl)
Definition: udptl.c:831

References calculate_local_max_datagram(), and ast_udptl::local_max_datagram.

Referenced by create_outgoing_sdp_stream().

◆ ast_udptl_get_peer()

void ast_udptl_get_peer ( const struct ast_udptl udptl,
struct ast_sockaddr them 
)

Definition at line 1135 of file udptl.c.

1136 {
1137  ast_sockaddr_copy(them, &udptl->them);
1138 }
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
Definition: netsock2.h:167
struct ast_sockaddr them
Definition: udptl.c:165

References ast_sockaddr_copy(), and ast_udptl::them.

◆ ast_udptl_get_us()

void ast_udptl_get_us ( const struct ast_udptl udptl,
struct ast_sockaddr us 
)

Definition at line 1140 of file udptl.c.

1141 {
1142  ast_sockaddr_copy(us, &udptl->us);
1143 }
struct ast_sockaddr us
Definition: udptl.c:164

References ast_sockaddr_copy(), and ast_udptl::us.

Referenced by configure_local_rtp(), and create_outgoing_sdp_stream().

◆ ast_udptl_new_with_bindaddr()

struct ast_udptl* ast_udptl_new_with_bindaddr ( struct ast_sched_context sched,
struct io_context io,
int  callbackmode,
struct ast_sockaddr addr 
)

Definition at line 1028 of file udptl.c.

1029 {
1030  struct ast_udptl *udptl;
1031  int x;
1032  int startplace;
1033  int i;
1035 
1036  if (!cfg || !cfg->general) {
1037  ast_log(LOG_ERROR, "Could not access global udptl options!\n");
1038  return NULL;
1039  }
1040 
1041  if (!(udptl = ast_calloc(1, sizeof(*udptl)))) {
1042  return NULL;
1043  }
1044 
1045  udptl->error_correction_span = cfg->general->fecspan;
1046  udptl->error_correction_entries = cfg->general->fecentries;
1047 
1048  udptl->far_max_datagram = -1;
1049  udptl->far_max_ifp = -1;
1050  udptl->local_max_ifp = -1;
1051  udptl->local_max_datagram = -1;
1052 
1053  for (i = 0; i <= UDPTL_BUF_MASK; i++) {
1054  udptl->rx[i].buf_len = -1;
1055  udptl->tx[i].buf_len = -1;
1056  }
1057 
1058  if ((udptl->fd = ast_socket_nonblock(ast_sockaddr_is_ipv6(addr) ?
1059  AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) {
1060  ast_free(udptl);
1061  ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
1062  return NULL;
1063  }
1064 
1065 #ifdef SO_NO_CHECK
1066  if (cfg->general->nochecksums)
1067  setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &cfg->general->nochecksums, sizeof(cfg->general->nochecksums));
1068 #endif
1069 
1070  /* Find us a place */
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)) {
1073  ++x;
1074  }
1075  startplace = x;
1076  for (;;) {
1077  ast_sockaddr_copy(&udptl->us, addr);
1078  ast_sockaddr_set_port(&udptl->us, x);
1079  if (ast_bind(udptl->fd, &udptl->us) == 0) {
1080  break;
1081  }
1082  if (errno != EADDRINUSE && errno != EACCES) {
1083  ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
1084  close(udptl->fd);
1085  ast_free(udptl);
1086  return NULL;
1087  }
1088  if (cfg->general->use_even_ports) {
1089  x += 2;
1090  } else {
1091  ++x;
1092  }
1093  if (x > cfg->general->end)
1094  x = cfg->general->start;
1095  if (x == startplace) {
1096  ast_log(LOG_WARNING, "No UDPTL ports remaining\n");
1097  close(udptl->fd);
1098  ast_free(udptl);
1099  return NULL;
1100  }
1101  }
1102  if (io && sched && callbackmode) {
1103  /* Operate this one in a callback mode */
1104  udptl->sched = sched;
1105  udptl->io = io;
1106  udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl);
1107  }
1108 
1109  return udptl;
1110 }
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
static struct ast_sched_context * sched
Definition: chan_ooh323.c:400
static struct io_context * io
Definition: chan_ooh323.c:401
#define LOG_WARNING
#define AST_IO_IN
Definition: io.h:34
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
Definition: io.c:162
int errno
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
#define NULL
Definition: resample.c:96
Structure for an UDPTL session.
Definition: udptl.c:156
struct ast_sched_context * sched
Definition: udptl.c:167
unsigned int error_correction_entries
Definition: udptl.c:181
int local_max_ifp
Definition: udptl.c:211
udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK+1]
Definition: udptl.c:217
unsigned int error_correction_span
Definition: udptl.c:186
udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK+1]
Definition: udptl.c:216
Definition: sched.c:76
#define UDPTL_BUF_MASK
Definition: udptl.c:139
static int udptlread(int *id, int fd, short events, void *cbdata)
Definition: udptl.c:750
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1068
long int ast_random(void)
Definition: main/utils.c:2210

References ao2_cleanup, ao2_global_obj_ref, ast_bind(), ast_calloc, ast_free, ast_io_add(), AST_IO_IN, ast_log, ast_random(), ast_sockaddr_copy(), ast_sockaddr_is_ipv6(), ast_sockaddr_set_port, ast_socket_nonblock, udptl_fec_tx_buffer_t::buf_len, udptl_fec_rx_buffer_t::buf_len, errno, ast_udptl::error_correction_entries, ast_udptl::error_correction_span, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, ast_udptl::fd, globals, io, ast_udptl::io, ast_udptl::ioid, ast_udptl::local_max_datagram, ast_udptl::local_max_ifp, LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, ast_udptl::rx, sched, ast_udptl::sched, ast_udptl::tx, UDPTL_BUF_MASK, udptlread(), and ast_udptl::us.

Referenced by configure_local_rtp(), initialize_udptl(), and t38_initialize_session().

◆ ast_udptl_read()

struct ast_frame* ast_udptl_read ( struct ast_udptl udptl)

Definition at line 762 of file udptl.c.

763 {
764  int res;
765  struct ast_sockaddr addr;
766  uint8_t *buf;
767 
768  buf = udptl->rawdata + AST_FRIENDLY_OFFSET;
769 
770  /* Cache where the header will go */
771  res = ast_recvfrom(udptl->fd,
772  buf,
773  sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
774  0,
775  &addr);
776  if (res < 0) {
777  if (errno != EAGAIN)
778  ast_log(LOG_WARNING, "UDPTL (%s): read error: %s\n",
779  LOG_TAG(udptl), strerror(errno));
780  ast_assert(errno != EBADF);
781  return &ast_null_frame;
782  }
783 
784  /* Ignore if the other side hasn't been given an address yet. */
785  if (ast_sockaddr_isnull(&udptl->them)) {
786  return &ast_null_frame;
787  }
788 
789  /*
790  * If early media isn't turned on for the channel driver, it's going to
791  * drop this frame. By that time though, udptl has already incremented
792  * the expected sequence number so if the CPE re-sends, the second frame
793  * will be dropped as a dup even though the first frame never went through.
794  * So we drop the frame here if the channel isn't up. 'tag' is set by the
795  * channel drivers on T38_ENABLED or T38_PEER_REINVITE.
796  */
797  if (udptl->tag == NULL) {
798  return &ast_null_frame;
799  }
800 
801  if (udptl->nat) {
802  /* Send to whoever sent to us */
803  if (ast_sockaddr_cmp(&udptl->them, &addr)) {
804  ast_sockaddr_copy(&udptl->them, &addr);
805  ast_debug(1, "UDPTL (%s): NAT, Using address %s\n",
806  LOG_TAG(udptl), ast_sockaddr_stringify(&udptl->them));
807  }
808  }
809 
810  if (udptl_debug_test_addr(&addr)) {
811  int seq_no;
812 
813  /* Decode sequence number just for verbose message. */
814  if (res < 2) {
815  /* Short packet. */
816  seq_no = -1;
817  } else {
818  seq_no = (buf[0] << 8) | buf[1];
819  }
820 
821  ast_verb(1, "UDPTL (%s): packet from %s (seq %d, len %d)\n",
822  LOG_TAG(udptl), ast_sockaddr_stringify(&addr), seq_no, res);
823  }
824  if (udptl_rx_packet(udptl, buf, res) < 1) {
825  return &ast_null_frame;
826  }
827 
828  return &udptl->f[0];
829 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
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.
Definition: netsock2.c:606
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
Socket address structure.
Definition: netsock2.h:97
unsigned char rawdata[8192+AST_FRIENDLY_OFFSET]
Definition: udptl.c:160
struct ast_frame f[16]
Definition: udptl.c:159
int nat
Definition: udptl.c:162
static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len)
Definition: udptl.c:381
#define LOG_TAG(u)
Definition: udptl.c:125
static int udptl_debug_test_addr(const struct ast_sockaddr *addr)
Definition: udptl.c:258
#define ast_assert(a)
Definition: utils.h:734

References ast_assert, ast_debug, AST_FRIENDLY_OFFSET, ast_log, ast_null_frame, ast_recvfrom(), ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verb, buf, errno, ast_udptl::f, ast_udptl::fd, LOG_TAG, LOG_WARNING, ast_udptl::nat, NULL, ast_udptl::rawdata, ast_udptl::tag, ast_udptl::them, udptl_debug_test_addr(), and udptl_rx_packet().

Referenced by media_session_udptl_read_callback(), ooh323_rtp_read(), sip_rtp_read(), skinny_rtp_read(), and udptlread().

◆ ast_udptl_set_callback()

void ast_udptl_set_callback ( struct ast_udptl udptl,
ast_udptl_callback  callback 
)

Definition at line 740 of file udptl.c.

741 {
742  udptl->callback = callback;
743 }
ast_udptl_callback callback
Definition: udptl.c:171

References ast_udptl::callback.

◆ ast_udptl_set_data()

void ast_udptl_set_data ( struct ast_udptl udptl,
void *  data 
)

Definition at line 735 of file udptl.c.

736 {
737  udptl->data = data;
738 }
void * data
Definition: udptl.c:169

References ast_udptl::data.

◆ ast_udptl_set_error_correction_scheme()

void ast_udptl_set_error_correction_scheme ( struct ast_udptl udptl,
enum ast_t38_ec_modes  ec 
)

Definition at line 945 of file udptl.c.

946 {
947  udptl->error_correction_scheme = ec;
948  switch (ec) {
951  if (udptl->error_correction_entries == 0) {
952  udptl->error_correction_entries = 3;
953  }
954  if (udptl->error_correction_span == 0) {
955  udptl->error_correction_span = 3;
956  }
957  break;
960  if (udptl->error_correction_entries == 0) {
961  udptl->error_correction_entries = 3;
962  }
963  break;
964  default:
965  /* nothing to do */
966  break;
967  };
968  /* reset calculated values so they'll be computed again */
969  udptl->local_max_datagram = -1;
970  udptl->far_max_ifp = -1;
971 }
@ UDPTL_ERROR_CORRECTION_FEC
Definition: udptl.h:39
@ UDPTL_ERROR_CORRECTION_REDUNDANCY
Definition: udptl.h:40

References ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, ast_udptl::error_correction_span, ast_udptl::far_max_ifp, ast_udptl::local_max_datagram, UDPTL_ERROR_CORRECTION_FEC, and UDPTL_ERROR_CORRECTION_REDUNDANCY.

Referenced by defer_incoming_sdp_stream(), process_sdp(), process_sdp_a_image(), set_t38_capabilities(), and t38_initialize_session().

◆ ast_udptl_set_far_max_datagram()

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 value.

Definition at line 997 of file udptl.c.

998 {
999  if (!max_datagram || (max_datagram > FAX_MAX_DATAGRAM_LIMIT)) {
1001  } else {
1002  udptl->far_max_datagram = max_datagram;
1003  }
1004  /* reset calculated values so they'll be computed again */
1005  udptl->far_max_ifp = -1;
1006 }
#define DEFAULT_FAX_MAX_DATAGRAM
Definition: udptl.c:134
#define FAX_MAX_DATAGRAM_LIMIT
Definition: udptl.c:135

References DEFAULT_FAX_MAX_DATAGRAM, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, and FAX_MAX_DATAGRAM_LIMIT.

Referenced by configure_local_rtp(), defer_incoming_sdp_stream(), onModeChanged(), process_sdp(), process_sdp_a_image(), and t38_initialize_session().

◆ ast_udptl_set_local_max_ifp()

void ast_udptl_set_local_max_ifp ( struct ast_udptl udptl,
unsigned int  max_ifp 
)

Definition at line 973 of file udptl.c.

974 {
975  /* make sure max_ifp is a positive value since a cast will take place when
976  * when setting local_max_ifp */
977  if ((signed int) max_ifp > 0) {
978  udptl->local_max_ifp = max_ifp;
979  /* reset calculated values so they'll be computed again */
980  udptl->local_max_datagram = -1;
981  }
982 }

References ast_udptl::local_max_datagram, and ast_udptl::local_max_ifp.

Referenced by interpret_t38_parameters(), and t38_interpret_parameters().

◆ ast_udptl_set_peer()

void ast_udptl_set_peer ( struct ast_udptl udptl,
const struct ast_sockaddr them 
)

Definition at line 1130 of file udptl.c.

1131 {
1132  ast_sockaddr_copy(&udptl->them, them);
1133 }

References ast_sockaddr_copy(), and ast_udptl::them.

Referenced by apply_negotiated_sdp_stream(), process_sdp(), and setup_udptl_connection().

◆ ast_udptl_set_tag()

void ast_udptl_set_tag ( struct ast_udptl udptl,
const char *  format,
  ... 
)

Associates a character string 'tag' with a UDPTL session.

Parameters
udptlThe UDPTL session.
formatprintf-style format string used to construct the tag

This function formats a tag for the specified UDPTL session, so that any log messages generated by the UDPTL stack related to that session will include the tag and the reader of the messages will be able to identify which endpoint caused them to be generated.

Definition at line 1112 of file udptl.c.

1113 {
1114  va_list ap;
1115 
1116  ast_free(udptl->tag);
1117  udptl->tag = NULL;
1118  va_start(ap, format);
1119  if (ast_vasprintf(&udptl->tag, format, ap) == -1) {
1120  udptl->tag = NULL;
1121  }
1122  va_end(ap);
1123 }
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
Definition: astmm.h:278
static snd_pcm_format_t format
Definition: chan_alsa.c:106

References ast_free, ast_vasprintf, format, NULL, and ast_udptl::tag.

Referenced by change_t38_state(), setup_udptl_connection(), and t38_change_state().

◆ ast_udptl_setnat()

void ast_udptl_setnat ( struct ast_udptl udptl,
int  nat 
)

Definition at line 745 of file udptl.c.

746 {
747  udptl->nat = nat;
748 }
static int nat
Definition: chan_mgcp.c:171

References nat, and ast_udptl::nat.

Referenced by do_setnat(), initialize_udptl(), and t38_initialize_session().

◆ ast_udptl_setqos()

int ast_udptl_setqos ( struct ast_udptl udptl,
unsigned int  tos,
unsigned int  cos 
)

Definition at line 1125 of file udptl.c.

1126 {
1127  return ast_set_qos(udptl->fd, tos, cos, "UDPTL");
1128 }
unsigned int tos
Definition: chan_iax2.c:348
unsigned int cos
Definition: chan_iax2.c:349
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
Definition: netsock2.c:621

References ast_set_qos(), cos, ast_udptl::fd, and tos.

Referenced by initialize_udptl().

◆ ast_udptl_stop()

void ast_udptl_stop ( struct ast_udptl udptl)

Definition at line 1145 of file udptl.c.

1146 {
1147  ast_sockaddr_setnull(&udptl->them);
1148 }
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:138

References ast_sockaddr_setnull(), and ast_udptl::them.

Referenced by process_sdp(), and stop_media_flows().

◆ ast_udptl_write()

int ast_udptl_write ( struct ast_udptl s,
struct ast_frame f 
)

Definition at line 1161 of file udptl.c.

1162 {
1163  unsigned int seq;
1164  unsigned int len = f->datalen;
1165  /* if no max datagram size is provided, use default value */
1166  const int bufsize = (s->far_max_datagram > 0) ? s->far_max_datagram : DEFAULT_FAX_MAX_DATAGRAM;
1167  uint8_t buf[bufsize];
1168 
1169  memset(buf, 0, sizeof(buf));
1170 
1171  /* If we have no peer, return immediately */
1172  if (ast_sockaddr_isnull(&s->them)) {
1173  return 0;
1174  }
1175 
1176  /* If there is no data length, return immediately */
1177  if (f->datalen == 0)
1178  return 0;
1179 
1180  if ((f->frametype != AST_FRAME_MODEM) ||
1181  (f->subclass.integer != AST_MODEM_T38)) {
1182  ast_log(LOG_WARNING, "UDPTL (%s): UDPTL can only send T.38 data.\n",
1183  LOG_TAG(s));
1184  return -1;
1185  }
1186 
1187  if (len > s->far_max_ifp) {
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",
1191  LOG_TAG(s), len, s->far_max_ifp);
1192  len = s->far_max_ifp;
1193  }
1194 
1195  /* Save seq_no for debug output because udptl_build_packet increments it */
1196  seq = s->tx_seq_no & 0xFFFF;
1197 
1198  /* Cook up the UDPTL packet, with the relevant EC info. */
1199  len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, len);
1200 
1201  if ((signed int) len > 0 && !ast_sockaddr_isnull(&s->them)) {
1202  if (ast_sendto(s->fd, buf, len, 0, &s->them) < 0) {
1203  ast_log(LOG_NOTICE, "UDPTL (%s): Transmission error to %s: %s\n",
1204  LOG_TAG(s), ast_sockaddr_stringify(&s->them), strerror(errno));
1205  }
1206  if (udptl_debug_test_addr(&s->them)) {
1207  ast_verb(1, "UDPTL (%s): packet to %s (seq %u, len %u)\n",
1209  }
1210  }
1211 
1212  return 0;
1213 }
static volatile unsigned int seq
Definition: app_sms.c:120
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_MODEM_T38
@ AST_FRAME_MODEM
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.
Definition: netsock2.c:614
struct ast_frame_subclass subclass
union ast_frame::@254 data
enum ast_frame_type frametype
unsigned int tx_seq_no
Definition: udptl.c:213
static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, unsigned int buflen, uint8_t *ifp, unsigned int ifp_len)
Definition: udptl.c:621

References AST_FRAME_MODEM, ast_log, AST_MODEM_T38, ast_sendto(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verb, buf, ast_frame::data, ast_frame::datalen, DEFAULT_FAX_MAX_DATAGRAM, errno, ast_udptl::f, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, ast_udptl::fd, ast_frame::frametype, ast_frame_subclass::integer, len(), LOG_NOTICE, LOG_TAG, LOG_WARNING, ast_frame::ptr, seq, ast_frame::subclass, ast_udptl::them, ast_udptl::tx_seq_no, udptl_build_packet(), and udptl_debug_test_addr().

Referenced by media_session_udptl_write_callback(), ooh323_write(), and sip_write().

◆ calculate_far_max_ifp()

static void calculate_far_max_ifp ( struct ast_udptl udptl)
static

Definition at line 872 of file udptl.c.

873 {
874  unsigned new_max = 0;
875 
876  if (udptl->far_max_datagram == -1) {
877  ast_log(LOG_WARNING, "UDPTL (%s): Cannot calculate far_max_ifp before far_max_datagram has been set.\n",
878  LOG_TAG(udptl));
879  udptl->far_max_ifp = -1;
880  return;
881  }
882 
883  /* the goal here is to supply the local endpoint (application
884  * or bridged channel) a maximum IFP value that will allow it
885  * to effectively and efficiently transfer image data at its
886  * selected bit rate, taking into account the selected error
887  * correction mode, but without overrunning the far endpoint's
888  * datagram buffer. this is complicated by the fact that some
889  * far endpoints send us bogus (small) max datagram values,
890  * which would result in either buffer overrun or no error
891  * correction. we try to accomodate those, but if the supplied
892  * value is too small to do so, we'll emit warning messages and
893  * the user will have to use configuration options to override
894  * the max datagram value supplied by the far endpoint.
895  */
896  switch (udptl->error_correction_scheme) {
898  /* need room for sequence number, length indicator, redundancy
899  * indicator and following length indicator
900  */
901  new_max = udptl->far_max_datagram - 5;
902  break;
904  /* for this case, we'd like to send as many error correction entries
905  * as possible (up to the number we're configured for), but we'll settle
906  * for sending fewer if the configured number would cause the
907  * calculated max IFP to be too small for effective operation
908  *
909  * need room for sequence number, length indicators and the
910  * configured number of redundant packets
911  *
912  * note: we purposely don't allow error_correction_entries to drop to
913  * zero in this loop; we'd rather send smaller IFPs (and thus reduce
914  * the image data transfer rate) than sacrifice redundancy completely
915  */
916  for (;;) {
917  new_max = (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1);
918 
919  if ((new_max < 80) && (udptl->error_correction_entries > 1)) {
920  /* the max ifp is not large enough, subtract an
921  * error correction entry and calculate again
922  * */
923  --udptl->error_correction_entries;
924  } else {
925  break;
926  }
927  }
928  break;
930  /* need room for sequence number, length indicators and a
931  * a single IFP of the maximum size expected
932  */
933  new_max = (udptl->far_max_datagram - 10) / 2;
934  break;
935  }
936  /* subtract 5% of space for insurance */
937  udptl->far_max_ifp = new_max * 0.95;
938 }
@ UDPTL_ERROR_CORRECTION_NONE
Definition: udptl.h:38

Referenced by ast_udptl_get_far_max_ifp().

◆ calculate_local_max_datagram()

static void calculate_local_max_datagram ( struct ast_udptl udptl)
static

Definition at line 831 of file udptl.c.

832 {
833  unsigned int new_max = 0;
834 
835  if (udptl->local_max_ifp == -1) {
836  ast_log(LOG_WARNING, "UDPTL (%s): Cannot calculate local_max_datagram before local_max_ifp has been set.\n",
837  LOG_TAG(udptl));
838  udptl->local_max_datagram = -1;
839  return;
840  }
841 
842  /* calculate the amount of space required to receive an IFP
843  * of the maximum size supported by the application/endpoint
844  * that we are delivering them to (local endpoint), and add
845  * the amount of space required to support the selected
846  * error correction mode
847  */
848  switch (udptl->error_correction_scheme) {
850  /* need room for sequence number, length indicator, redundancy
851  * indicator and following length indicator
852  */
853  new_max = 5 + udptl->local_max_ifp;
854  break;
856  /* need room for sequence number, length indicators, plus
857  * room for up to 3 redundancy packets
858  */
859  new_max = 5 + udptl->local_max_ifp + 2 + (3 * udptl->local_max_ifp);
860  break;
862  /* need room for sequence number, length indicators and a
863  * a single IFP of the maximum size expected
864  */
865  new_max = 5 + udptl->local_max_ifp + 4 + udptl->local_max_ifp;
866  break;
867  }
868  /* add 5% extra space for insurance, but no larger than LOCAL_FAX_MAX_DATAGRAM */
869  udptl->local_max_datagram = MIN(new_max * 1.05, LOCAL_FAX_MAX_DATAGRAM);
870 }
#define LOCAL_FAX_MAX_DATAGRAM
Definition: udptl.c:133
#define MIN(a, b)
Definition: utils.h:226

References ast_log, ast_udptl::error_correction_scheme, LOCAL_FAX_MAX_DATAGRAM, ast_udptl::local_max_datagram, ast_udptl::local_max_ifp, LOG_TAG, LOG_WARNING, MIN, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.

Referenced by ast_udptl_get_local_max_datagram().

◆ CONFIG_INFO_CORE()

CONFIG_INFO_CORE ( "udptl"  ,
cfg_info  ,
globals  ,
udptl_snapshot_alloc  ,
files = ACO_FILES(&udptl_conf),
pre_apply_config = udptl_pre_apply_config 
)

◆ decode_length()

static int decode_length ( uint8_t *  buf,
unsigned int  limit,
unsigned int *  len,
unsigned int *  pvalue 
)
static

Definition at line 274 of file udptl.c.

275 {
276  if (*len >= limit)
277  return -1;
278  if ((buf[*len] & 0x80) == 0) {
279  *pvalue = buf[*len];
280  (*len)++;
281  return 0;
282  }
283  if ((buf[*len] & 0x40) == 0) {
284  if (*len == limit - 1)
285  return -1;
286  *pvalue = (buf[*len] & 0x3F) << 8;
287  (*len)++;
288  *pvalue |= buf[*len];
289  (*len)++;
290  return 0;
291  }
292  *pvalue = (buf[*len] & 0x3F) << 14;
293  (*len)++;
294  /* We have a fragment. Currently we don't process fragments. */
295  ast_debug(1, "UDPTL packet with length greater than 16K received, decoding will fail\n");
296  return 1;
297 }

References ast_debug, buf, and len().

Referenced by decode_open_type(), and udptl_rx_packet().

◆ decode_open_type()

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

Definition at line 300 of file udptl.c.

301 {
302  unsigned int octet_cnt = 0;
303 
304  if (decode_length(buf, limit, len, &octet_cnt) != 0)
305  return -1;
306 
307  /* Make sure the buffer contains at least the number of bits requested */
308  if ((*len + octet_cnt) > limit) {
309  return -1;
310  }
311 
312  *p_num_octets = octet_cnt;
313  *p_object = &buf[*len];
314  *len += octet_cnt;
315 
316  return 0;
317 }
static int decode_length(uint8_t *buf, unsigned int limit, unsigned int *len, unsigned int *pvalue)
Definition: udptl.c:274

References buf, decode_length(), and len().

Referenced by udptl_rx_packet().

◆ encode_length()

static unsigned int encode_length ( uint8_t *  buf,
unsigned int *  len,
unsigned int  value 
)
static

Definition at line 320 of file udptl.c.

321 {
322  unsigned int multiplier;
323 
324  if (value < 0x80) {
325  /* 1 octet */
326  buf[*len] = value;
327  (*len)++;
328  return value;
329  }
330  if (value < 0x4000) {
331  /* 2 octets */
332  /* Set the first bit of the first octet */
333  buf[*len] = ((0x8000 | value) >> 8) & 0xFF;
334  (*len)++;
335  buf[*len] = value & 0xFF;
336  (*len)++;
337  return value;
338  }
339  /* Fragmentation */
340  multiplier = (value < 0x10000) ? (value >> 14) : 4;
341  /* Set the first 2 bits of the octet */
342  buf[*len] = 0xC0 | multiplier;
343  (*len)++;
344  return multiplier << 14;
345 }
int value
Definition: syslog.c:37

References buf, len(), and value.

Referenced by encode_open_type(), and udptl_build_packet().

◆ encode_open_type()

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

Definition at line 348 of file udptl.c.

350 {
351  unsigned int enclen;
352  unsigned int octet_idx;
353  uint8_t zero_byte;
354 
355  /* If open type is of zero length, add a single zero byte (10.1) */
356  if (num_octets == 0) {
357  zero_byte = 0;
358  data = &zero_byte;
359  num_octets = 1;
360  }
361  /* Encode the open type */
362  for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
363  enclen = encode_length(buf, len, num_octets);
364  if (enclen + *len > buflen) {
365  ast_log(LOG_ERROR, "UDPTL (%s): Buffer overflow detected (%u + %u > %u)\n",
366  LOG_TAG(udptl), enclen, *len, buflen);
367  return -1;
368  }
369  if (enclen > 0) {
370  memcpy(&buf[*len], &data[octet_idx], enclen);
371  *len += enclen;
372  }
373  if (enclen >= num_octets)
374  break;
375  }
376 
377  return 0;
378 }
static unsigned int encode_length(uint8_t *buf, unsigned int *len, unsigned int value)
Definition: udptl.c:320

References ast_log, buf, encode_length(), len(), LOG_ERROR, and LOG_TAG.

Referenced by udptl_build_packet().

◆ handle_cli_show_config()

static char* handle_cli_show_config ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1260 of file udptl.c.

1261 {
1262  RAII_VAR(struct udptl_config *, cfg, NULL, ao2_cleanup);
1263 
1264  switch (cmd) {
1265  case CLI_INIT:
1266  e->command = "udptl show config";
1267  e->usage =
1268  "Usage: udptl show config\n"
1269  " Display UDPTL configuration options\n";
1270  return NULL;
1271  case CLI_GENERATE:
1272  return NULL;
1273  }
1274 
1275  if (!(cfg = ao2_global_obj_ref(globals))) {
1276  return CLI_FAILURE;
1277  }
1278 
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);
1285  ast_cli(a->fd, "use_even_ports: %s\n", AST_CLI_YESNO(cfg->general->use_even_ports));
1286  ast_cli(a->fd, "udptlchecksums: %s\n", AST_CLI_YESNO(!cfg->general->nochecksums));
1287 
1288  return CLI_SUCCESS;
1289 }
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition: cli.h:71
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

◆ handle_cli_udptl_set_debug()

static char* handle_cli_udptl_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1215 of file udptl.c.

1216 {
1217  switch (cmd) {
1218  case CLI_INIT:
1219  e->command = "udptl set debug {on|off|ip}";
1220  e->usage =
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";
1225  return NULL;
1226  case CLI_GENERATE:
1227  return NULL;
1228  }
1229 
1230  if (a->argc < 4 || a->argc > 5)
1231  return CLI_SHOWUSAGE;
1232 
1233  if (a->argc == 4) {
1234  if (!strncasecmp(a->argv[3], "on", 2)) {
1235  udptldebug = 1;
1236  memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
1237  ast_cli(a->fd, "UDPTL Debugging Enabled\n");
1238  } else if (!strncasecmp(a->argv[3], "off", 3)) {
1239  udptldebug = 0;
1240  ast_cli(a->fd, "UDPTL Debugging Disabled\n");
1241  } else {
1242  return CLI_SHOWUSAGE;
1243  }
1244  } else {
1245  struct ast_sockaddr *addrs;
1246  if (strncasecmp(a->argv[3], "ip", 2))
1247  return CLI_SHOWUSAGE;
1248  if (!ast_sockaddr_resolve(&addrs, a->argv[4], 0, 0)) {
1249  return CLI_SHOWUSAGE;
1250  }
1251  ast_sockaddr_copy(&udptldebugaddr, &addrs[0]);
1252  ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_sockaddr_stringify(&udptldebugaddr));
1253  udptldebug = 1;
1254  ast_free(addrs);
1255  }
1256 
1257  return CLI_SUCCESS;
1258 }
#define CLI_SHOWUSAGE
Definition: cli.h:45
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.
Definition: netsock2.c:280
static struct ast_sockaddr udptldebugaddr
Definition: udptl.c:131
static int udptldebug
Definition: udptl.c:130

References a, ast_cli(), ast_free, ast_sockaddr_copy(), ast_sockaddr_resolve(), ast_sockaddr_stringify(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, udptldebug, udptldebugaddr, and ast_cli_entry::usage.

◆ load_module()

static int load_module ( void  )
static

Definition at line 1396 of file udptl.c.

1397 {
1398  if (aco_info_init(&cfg_info)) {
1399  return AST_MODULE_LOAD_FAILURE;
1400  }
1401 
1404  FLDSET(struct udptl_global_options, start), DEFAULT_UDPTLSTART, 1024, 65535);
1405 
1408  FLDSET(struct udptl_global_options, end), DEFAULT_UDPTLEND, 1024, 65535);
1409 
1410  aco_option_register(&cfg_info, "udptlfecentries", ACO_EXACT, general_options, NULL,
1412  FLDSET(struct udptl_global_options, fecentries), 1, MAX_FEC_ENTRIES);
1413 
1414  aco_option_register(&cfg_info, "udptlfecspan", ACO_EXACT, general_options, NULL,
1416  FLDSET(struct udptl_global_options, fecspan), 1, MAX_FEC_SPAN);
1417 
1418  aco_option_register(&cfg_info, "udptlchecksums", ACO_EXACT, general_options, "yes",
1419  OPT_BOOL_T, 0, FLDSET(struct udptl_global_options, nochecksums));
1420 
1421  aco_option_register(&cfg_info, "use_even_ports", ACO_EXACT, general_options, "no",
1422  OPT_BOOL_T, 1, FLDSET(struct udptl_global_options, use_even_ports));
1423 
1425  aco_option_register_custom(&cfg_info, "t38faxmaxdatagram", ACO_EXACT, general_options, NULL, removed_options_handler, 0);
1426 
1427  __ast_udptl_reload(0);
1428 
1430 
1431  return AST_MODULE_LOAD_SUCCESS;
1432 }
#define __stringify(x)
Definition: asterisk.h:216
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
@ ACO_EXACT
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.
char * end
Definition: eagi_proxy.c:73
@ PARSE_RANGE_DEFAULTS
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition: module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define MAX_FEC_ENTRIES
Definition: udptl.c:136
#define DEFAULT_UDPTLEND
Definition: udptl.c:128
static int removed_options_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: udptl.c:1317
#define DEFAULT_UDPTLSTART
Definition: udptl.c:127
static struct ast_cli_entry cli_udptl[]
Definition: udptl.c:1291
#define MAX_FEC_SPAN
Definition: udptl.c:137
static struct aco_type * general_options[]
Definition: udptl.c:246
static void __ast_udptl_reload(int reload)
Definition: udptl.c:1327
#define ARRAY_LEN(a)
Definition: utils.h:661

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 1376 of file udptl.c.

1377 {
1378  __ast_udptl_reload(1);
1379 
1380  return 0;
1381 }

References __ast_udptl_reload().

◆ removed_options_handler()

static int removed_options_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 1317 of file udptl.c.

1318 {
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");
1323  }
1324  return 0;
1325 }
#define var
Definition: ast_expr2f.c:614

References ast_log, LOG_WARNING, and var.

◆ udptl_build_packet()

static int udptl_build_packet ( struct ast_udptl s,
uint8_t *  buf,
unsigned int  buflen,
uint8_t *  ifp,
unsigned int  ifp_len 
)
static

Definition at line 621 of file udptl.c.

622 {
623  uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2] = { 0, };
624  int i;
625  int j;
626  int seq;
627  int entry;
628  int entries;
629  int span;
630  int m;
631  unsigned int len;
632  int limit;
633  int high_tide;
634 
635  seq = s->tx_seq_no & 0xFFFF;
636 
637  /* Map the sequence number to an entry in the circular buffer */
639 
640  /* We save the message in a circular buffer, for generating FEC or
641  redundancy sets later on. */
642  s->tx[entry].buf_len = ifp_len;
643  memcpy(s->tx[entry].buf, ifp, ifp_len);
644 
645  /* Build the UDPTLPacket */
646 
647  len = 0;
648  /* Encode the sequence number */
649  buf[len++] = (seq >> 8) & 0xFF;
650  buf[len++] = seq & 0xFF;
651 
652  /* Encode the primary IFP packet */
653  if (encode_open_type(s, buf, buflen, &len, ifp, ifp_len) < 0)
654  return -1;
655 
656  /* Encode the appropriate type of error recovery information */
657  switch (s->error_correction_scheme)
658  {
660  /* Encode the error recovery type */
661  buf[len++] = 0x00;
662  /* The number of entries will always be zero, so it is pointless allowing
663  for the fragmented case here. */
664  encode_length(buf, &len, 0);
665  break;
667  /* Encode the error recovery type */
668  buf[len++] = 0x00;
670  entries = s->error_correction_entries;
671  else
672  entries = s->tx_seq_no;
673  /* The number of entries will always be small, so it is pointless allowing
674  for the fragmented case here. */
675  encode_length(buf, &len, entries);
676  /* Encode the elements */
677  for (i = 0; i < entries; i++) {
678  j = (entry - i - 1) & UDPTL_BUF_MASK;
679  if (encode_open_type(s, buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) {
680  ast_debug(1, "UDPTL (%s): Encoding failed at i=%d, j=%d\n",
681  LOG_TAG(s), i, j);
682  return -1;
683  }
684  }
685  break;
687  span = s->error_correction_span;
688  entries = s->error_correction_entries;
689  if (seq < s->error_correction_span*s->error_correction_entries) {
690  /* In the initial stages, wind up the FEC smoothly */
691  entries = seq/s->error_correction_span;
692  if (seq < s->error_correction_span)
693  span = 0;
694  }
695  /* Encode the error recovery type */
696  buf[len++] = 0x80;
697  /* Span is defined as an unconstrained integer, which it dumb. It will only
698  ever be a small value. Treat it as such. */
699  buf[len++] = 1;
700  buf[len++] = span;
701  /* The number of entries is defined as a length, but will only ever be a small
702  value. Treat it as such. */
703  buf[len++] = entries;
704  for (m = 0; m < entries; m++) {
705  /* Make an XOR'ed entry the maximum length */
706  limit = (entry + m) & UDPTL_BUF_MASK;
707  high_tide = 0;
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];
712  for ( ; j < s->tx[i].buf_len; j++)
713  fec[j] = s->tx[i].buf[j];
714  high_tide = s->tx[i].buf_len;
715  } else {
716  for (j = 0; j < s->tx[i].buf_len; j++)
717  fec[j] ^= s->tx[i].buf[j];
718  }
719  }
720  if (encode_open_type(s, buf, buflen, &len, fec, high_tide) < 0)
721  return -1;
722  }
723  break;
724  }
725 
726  s->tx_seq_no++;
727  return len;
728 }
Definition: search.h:40
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]
Definition: udptl.c:143
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)
Definition: udptl.c:348

References ast_debug, buf, udptl_fec_tx_buffer_t::buf, udptl_fec_tx_buffer_t::buf_len, encode_length(), encode_open_type(), ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, ast_udptl::error_correction_span, len(), LOCAL_FAX_MAX_DATAGRAM, LOG_TAG, seq, ast_udptl::tx, ast_udptl::tx_seq_no, UDPTL_BUF_MASK, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.

Referenced by ast_udptl_write().

◆ udptl_config_destructor()

static void udptl_config_destructor ( void *  obj)
static

Definition at line 1296 of file udptl.c.

1297 {
1298  struct udptl_config *cfg = obj;
1299  ao2_cleanup(cfg->general);
1300 }
struct udptl_global_options * general
Definition: udptl.c:232

References ao2_cleanup, and udptl_config::general.

Referenced by udptl_snapshot_alloc().

◆ udptl_debug_test_addr()

static int udptl_debug_test_addr ( const struct ast_sockaddr addr)
inlinestatic

Definition at line 258 of file udptl.c.

259 {
260  if (udptldebug == 0)
261  return 0;
262 
264  return 1;
265  }
266 
268  return !ast_sockaddr_cmp(&udptldebugaddr, addr);
269  } else {
270  return !ast_sockaddr_cmp_addr(&udptldebugaddr, addr);
271  }
272 }
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
Definition: netsock2.c:413

References ast_sockaddr_cmp(), ast_sockaddr_cmp_addr(), ast_sockaddr_isnull(), ast_sockaddr_port, udptldebug, and udptldebugaddr.

Referenced by ast_udptl_read(), and ast_udptl_write().

◆ udptl_pre_apply_config()

static int udptl_pre_apply_config ( void  )
static

Definition at line 1344 of file udptl.c.

1344  {
1345  struct udptl_config *cfg = aco_pending_config(&cfg_info);
1346 
1347  if (!cfg->general) {
1348  return -1;
1349  }
1350 
1351 #ifndef SO_NO_CHECK
1352  if (cfg->general->nochecksums) {
1353  ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n");
1354  cfg->general->nochecksums = 0;
1355  }
1356 #endif
1357 
1358  /* Fix up any global config values that we can handle before replacing the config */
1359  if (cfg->general->use_even_ports && (cfg->general->start & 1)) {
1360  ++cfg->general->start;
1361  ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %u\n", cfg->general->start);
1362  }
1363  if (cfg->general->start > cfg->general->end) {
1364  ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to %s-%s.\n", __stringify(DEFAULT_UDPTLSTART), __stringify(DEFAULT_UDPTLEND));
1366  cfg->general->end = DEFAULT_UDPTLEND;
1367  }
1368  if (cfg->general->use_even_ports && (cfg->general->end & 1)) {
1369  --cfg->general->end;
1370  ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_even_ports enabled. udptlend is now %u\n", cfg->general->end);
1371  }
1372 
1373  return 0;
1374 }
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
unsigned int use_even_ports
Definition: udptl.c:226
unsigned int nochecksums
Definition: udptl.c:225
unsigned int start
Definition: udptl.c:221
unsigned int end
Definition: udptl.c:222

References __stringify, aco_pending_config(), ast_log, DEFAULT_UDPTLEND, DEFAULT_UDPTLSTART, udptl_global_options::end, udptl_config::general, LOG_NOTICE, LOG_WARNING, udptl_global_options::nochecksums, udptl_global_options::start, and udptl_global_options::use_even_ports.

◆ udptl_rx_packet()

static int udptl_rx_packet ( struct ast_udptl s,
uint8_t *  buf,
unsigned int  len 
)
static

Definition at line 381 of file udptl.c.

382 {
383  int stat1;
384  int stat2;
385  int i;
386  unsigned int ptr; /* an index that keeps track of how much of the UDPTL packet has been processed */
387  int seq_no;
388  const uint8_t *ifp = NULL;
389  const uint8_t *data = NULL;
390  unsigned int ifp_len = 0;
391  int repaired[16];
392  const uint8_t *bufs[ARRAY_LEN(s->f) - 1];
393  unsigned int lengths[ARRAY_LEN(s->f) - 1];
394  int span;
395  int entries;
396  int ifp_no;
397 
398  ptr = 0;
399  ifp_no = 0;
400  memset(&s->f[0], 0, sizeof(s->f[0]));
401 
402  /* Decode seq_number */
403  if (ptr + 2 > len)
404  return -1;
405  seq_no = (buf[0] << 8) | buf[1];
406  ptr += 2;
407 
408  /* UDPTL sequence numbers are 16 bit so after 0xFFFF comes
409  0 which breaks all packet recovery logic. To fix this
410  if we see that next expected packet (rx_seq_no) is close
411  to or beyond the wrap around limit & the received packet
412  is still near zero, then we 'unwrap' the received seqno
413  so it has the value it would have had. After a 16
414  packet grace period (there shouldn't be more than
415  that many recovery packets) we wrap the expected
416  sequence number around and things can return back
417  to normal */
418  if (seq_no < 0x000F && s->rx_seq_no > 0xFFF0) {
419  /* received seq_no has wrapped adjust it */
420  seq_no += 0x10000;
421  } else {
422  /* otherwise make sure expected rx_seq_no is properly wrapped */
423  s->rx_seq_no &= 0xFFFF;
424  }
425 
426  /* Break out the primary packet */
427  if ((stat1 = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0)
428  return -1;
429  /* Decode error_recovery */
430  if (ptr + 1 > len)
431  return -1;
432  if ((buf[ptr++] & 0x80) == 0) {
433  /* Secondary packet mode for error recovery */
434  if (seq_no > s->rx_seq_no) {
435  /* We received a later packet than we expected, so we need to check if we can fill in the gap from the
436  secondary packets. */
437  int total_count = 0;
438  do {
439  unsigned int count;
440  if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
441  return -1;
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) {
444  return -1;
445  }
446  /* valid secondaries can contain zero-length packets that should be ignored */
447  if (!bufs[total_count + i] || !lengths[total_count + i]) {
448  /* drop the count of items to process and reuse the buffers that were just set */
449  i--;
450  count--;
451  }
452  }
453  total_count += i;
454  }
455  while (stat2 > 0 && total_count < ARRAY_LEN(bufs));
456  /* Step through in reverse order, so we go oldest to newest */
457  for (i = total_count; i > 0; i--) {
458  if (seq_no - i >= s->rx_seq_no) {
459  /* This one wasn't seen before */
460  /* Decode the secondary IFP packet */
461  ast_debug(3, "Recovering lost packet via secondary %d, len %u\n", seq_no - i, lengths[i - 1]);
462  s->f[ifp_no].frametype = AST_FRAME_MODEM;
463  s->f[ifp_no].subclass.integer = AST_MODEM_T38;
464 
465  s->f[ifp_no].mallocd = 0;
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];
469  s->f[ifp_no].offset = 0;
470  s->f[ifp_no].src = "UDPTL";
471  if (ifp_no > 0)
472  AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
473  AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
474  ifp_no++;
475  }
476  }
477  }
478  }
479  else
480  {
481  int j;
482  int l;
483  int x;
484  /* FEC mode for error recovery */
485  /* Our buffers cannot tolerate overlength IFP packets in FEC mode */
486  if (ifp_len > LOCAL_FAX_MAX_DATAGRAM)
487  return -1;
488  /* Update any missed slots in the buffer */
489  for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) {
490  x = s->rx_seq_no & UDPTL_BUF_MASK;
491  s->rx[x].buf_len = -1;
492  s->rx[x].fec_len[0] = 0;
493  s->rx[x].fec_span = 0;
494  s->rx[x].fec_entries = 0;
495  }
496 
497  x = seq_no & UDPTL_BUF_MASK;
498 
499  memset(repaired, 0, sizeof(repaired));
500 
501  /* Save the new IFP packet */
502  memcpy(s->rx[x].buf, ifp, ifp_len);
503  s->rx[x].buf_len = ifp_len;
504  repaired[x] = TRUE;
505 
506  /* Decode the FEC packets */
507  /* The span is defined as an unconstrained integer, but will never be more
508  than a small value. */
509  if (ptr + 2 > len)
510  return -1;
511  if (buf[ptr++] != 1)
512  return -1;
513  span = buf[ptr++];
514  s->rx[x].fec_span = span;
515 
516  /* The number of entries is defined as a length, but will only ever be a small
517  value. Treat it as such. */
518  if (ptr + 1 > len)
519  return -1;
520  entries = buf[ptr++];
521  if (entries > MAX_FEC_ENTRIES) {
522  return -1;
523  }
524  s->rx[x].fec_entries = entries;
525 
526  /* Decode the elements */
527  for (i = 0; i < entries; i++) {
528  if ((stat1 = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0)
529  return -1;
530  if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM)
531  return -1;
532 
533  /* Save the new FEC data */
534  memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]);
535 #if 0
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");
540 #endif
541  }
542 
543  /* See if we can reconstruct anything which is missing */
544  /* TODO: this does not comprehensively hunt back and repair everything that is possible */
545  for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) {
546  int m;
547  if (s->rx[l].fec_len[0] <= 0)
548  continue;
549  for (m = 0; m < s->rx[l].fec_entries; m++) {
550  int k;
551  int which;
552  int limit = (l + m) & UDPTL_BUF_MASK;
553 
554  /* only repair buffers that actually exist! */
555  if (seq_no <= (s->rx[l].fec_span * s->rx[l].fec_entries) - m) {
556  continue;
557  }
558 
559  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) {
560  if (s->rx[k].buf_len <= 0)
561  which = (which == -1) ? k : -2;
562  }
563  if (which >= 0) {
564  /* Repairable */
565  for (j = 0; j < s->rx[l].fec_len[m]; j++) {
566  s->rx[which].buf[j] = s->rx[l].fec[m][j];
567  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)
568  s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
569  }
570  s->rx[which].buf_len = s->rx[l].fec_len[m];
571  repaired[which] = TRUE;
572  }
573  }
574  }
575  /* Now play any new packets forwards in time */
576  for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) {
577  if (repaired[l]) {
578  //fprintf(stderr, "Fixed packet %d, len %d\n", j, l);
579  s->f[ifp_no].frametype = AST_FRAME_MODEM;
580  s->f[ifp_no].subclass.integer = AST_MODEM_T38;
581 
582  s->f[ifp_no].mallocd = 0;
583  s->f[ifp_no].seqno = j;
584  s->f[ifp_no].datalen = s->rx[l].buf_len;
585  s->f[ifp_no].data.ptr = s->rx[l].buf;
586  s->f[ifp_no].offset = 0;
587  s->f[ifp_no].src = "UDPTL";
588  if (ifp_no > 0)
589  AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
590  AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
591  ifp_no++;
592  }
593  }
594  }
595 
596  /* If packets are received out of sequence, we may have already processed this packet from the error
597  recovery information in a packet already received. */
598  if (seq_no >= s->rx_seq_no) {
599  /* Decode the primary IFP packet */
600  s->f[ifp_no].frametype = AST_FRAME_MODEM;
601  s->f[ifp_no].subclass.integer = AST_MODEM_T38;
602 
603  s->f[ifp_no].mallocd = 0;
604  s->f[ifp_no].seqno = seq_no;
605  s->f[ifp_no].datalen = ifp_len;
606  s->f[ifp_no].data.ptr = (uint8_t *) ifp;
607  s->f[ifp_no].offset = 0;
608  s->f[ifp_no].src = "UDPTL";
609  if (ifp_no > 0)
610  AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
611  AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
612 
613  ifp_no++;
614  }
615 
616  s->rx_seq_no = seq_no + 1;
617  return ifp_no;
618 }
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
const char * src
unsigned int rx_seq_no
Definition: udptl.c:214
uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM]
Definition: udptl.c:150
unsigned int fec_entries
Definition: udptl.c:152
unsigned int fec_len[MAX_FEC_ENTRIES]
Definition: udptl.c:149
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]
Definition: udptl.c:148
unsigned int fec_span
Definition: udptl.c:151
#define TRUE
Definition: udptl.c:122
static int decode_open_type(uint8_t *buf, unsigned int limit, unsigned int *len, const uint8_t **p_object, unsigned int *p_num_octets)
Definition: udptl.c:300

References ARRAY_LEN, ast_debug, AST_FRAME_MODEM, AST_LIST_NEXT, AST_MODEM_T38, buf, udptl_fec_rx_buffer_t::buf, udptl_fec_rx_buffer_t::buf_len, ast_frame::data, ast_frame::datalen, decode_length(), decode_open_type(), ast_udptl::f, udptl_fec_rx_buffer_t::fec, udptl_fec_rx_buffer_t::fec_entries, udptl_fec_rx_buffer_t::fec_len, udptl_fec_rx_buffer_t::fec_span, ast_frame::frametype, ast_frame_subclass::integer, len(), LOCAL_FAX_MAX_DATAGRAM, ast_frame::mallocd, MAX_FEC_ENTRIES, NULL, ast_frame::offset, ast_frame::ptr, ast_udptl::rx, ast_udptl::rx_seq_no, ast_frame::seqno, ast_frame::src, ast_frame::subclass, TRUE, and UDPTL_BUF_MASK.

Referenced by ast_udptl_read().

◆ udptl_snapshot_alloc()

static void * udptl_snapshot_alloc ( void  )
static

Definition at line 1302 of file udptl.c.

1303 {
1304  struct udptl_config *cfg;
1305 
1306  if (!(cfg = ao2_alloc(sizeof(*cfg), udptl_config_destructor))) {
1307  return NULL;
1308  }
1309  if (!(cfg->general = ao2_alloc(sizeof(*cfg->general), NULL))) {
1310  ao2_ref(cfg, -1);
1311  return NULL;
1312  }
1313 
1314  return cfg;
1315 }
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
static void udptl_config_destructor(void *obj)
Definition: udptl.c:1296

References ao2_alloc, ao2_ref, udptl_config::general, NULL, and udptl_config_destructor().

Referenced by __ast_udptl_reload().

◆ udptlread()

static int udptlread ( int *  id,
int  fd,
short  events,
void *  cbdata 
)
static

Definition at line 750 of file udptl.c.

751 {
752  struct ast_udptl *udptl = cbdata;
753  struct ast_frame *f;
754 
755  if ((f = ast_udptl_read(udptl))) {
756  if (udptl->callback)
757  udptl->callback(udptl, f, udptl->data);
758  }
759  return 1;
760 }
Data structure associated with a single frame of data.
struct ast_frame * ast_udptl_read(struct ast_udptl *udptl)
Definition: udptl.c:762

References ast_udptl_read(), ast_udptl::callback, and ast_udptl::data.

Referenced by ast_udptl_new_with_bindaddr().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1387 of file udptl.c.

1388 {
1390  ao2_t_global_obj_release(globals, "Unref udptl global container in shutdown");
1391  aco_info_destroy(&cfg_info);
1392 
1393  return 0;
1394 }
#define ao2_t_global_obj_release(holder, tag)
Definition: astobj2.h:861
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.

References aco_info_destroy(), ao2_t_global_obj_release, ARRAY_LEN, ast_cli_unregister_multiple(), cli_udptl, and globals.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "UDPTL" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
static

Definition at line 1396 of file udptl.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1441 of file udptl.c.

◆ cli_udptl

struct ast_cli_entry cli_udptl[]
static
Initial value:
= {
{ .handler = handle_cli_udptl_set_debug , .summary = "Enable/Disable UDPTL debugging" ,},
{ .handler = handle_cli_show_config , .summary = "Show UDPTL config options" ,},
}
static char * handle_cli_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: udptl.c:1260
static char * handle_cli_udptl_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: udptl.c:1215

Definition at line 1260 of file udptl.c.

Referenced by unload_module().

◆ general_option

struct aco_type general_option
static

Definition at line 236 of file udptl.c.

Referenced by __ast_udptl_reload().

◆ general_options

struct aco_type* general_options[] = ACO_TYPES(&general_option)
static

Definition at line 246 of file udptl.c.

◆ udptl_conf

struct aco_file udptl_conf
static
Initial value:
= {
.filename = "udptl.conf",
}
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.

Definition at line 246 of file udptl.c.

◆ udptldebug

int udptldebug
static

Are we debugging?

Definition at line 130 of file udptl.c.

Referenced by handle_cli_udptl_set_debug(), and udptl_debug_test_addr().

◆ udptldebugaddr

struct ast_sockaddr udptldebugaddr
static

Debug packets to/from this host

Definition at line 130 of file udptl.c.

Referenced by handle_cli_udptl_set_debug(), and udptl_debug_test_addr().