Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 159 of file udptl.c.

◆ DEFAULT_UDPTLEND

#define DEFAULT_UDPTLEND   4999

Definition at line 153 of file udptl.c.

◆ DEFAULT_UDPTLSTART

#define DEFAULT_UDPTLSTART   4000

Definition at line 152 of file udptl.c.

◆ FALSE

#define FALSE   0

Definition at line 144 of file udptl.c.

◆ FAX_MAX_DATAGRAM_LIMIT

#define FAX_MAX_DATAGRAM_LIMIT   1400

Definition at line 160 of file udptl.c.

◆ LOCAL_FAX_MAX_DATAGRAM

#define LOCAL_FAX_MAX_DATAGRAM   1400

Definition at line 158 of file udptl.c.

◆ LOG_TAG

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

Definition at line 150 of file udptl.c.

◆ MAX_FEC_ENTRIES

#define MAX_FEC_ENTRIES   5

Definition at line 161 of file udptl.c.

◆ MAX_FEC_SPAN

#define MAX_FEC_SPAN   5

Definition at line 162 of file udptl.c.

◆ TRUE

#define TRUE   (!FALSE)

Definition at line 147 of file udptl.c.

◆ UDPTL_BUF_MASK

#define UDPTL_BUF_MASK   15

Definition at line 164 of file udptl.c.

◆ UDPTL_MTU

#define UDPTL_MTU   1200

Definition at line 141 of file udptl.c.

Function Documentation

◆ __ast_udptl_reload()

static void __ast_udptl_reload ( int  reload)
static

Definition at line 1352 of file udptl.c.

1353{
1354 if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) {
1355 if (!reload) {
1356 RAII_VAR(struct udptl_config *, udptl_cfg, udptl_snapshot_alloc(), ao2_cleanup);
1357
1358 if (aco_set_defaults(&general_option, "general", udptl_cfg->general)) {
1359 ast_log(LOG_ERROR, "Failed to load udptl.conf and failed to initialize defaults.\n");
1360 return;
1361 }
1362
1363 ast_log(LOG_NOTICE, "Could not load udptl config; using defaults\n");
1365 }
1366 }
1367}
#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:1327
static struct aco_type general_option
Definition: udptl.c:263
#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:941

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 load_module(), and reload_module().

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1466 of file udptl.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1466 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 1466 of file udptl.c.

◆ ast_udptl_destroy()

void ast_udptl_destroy ( struct ast_udptl udptl)

Definition at line 1175 of file udptl.c.

1176{
1177 if (udptl->ioid)
1178 ast_io_remove(udptl->io, udptl->ioid);
1179 if (udptl->fd > -1)
1180 close(udptl->fd);
1181 if (udptl->tag)
1182 ast_free(udptl->tag);
1183 ast_free(udptl);
1184}
#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:191
int fd
Definition: udptl.c:182
char * tag
Definition: udptl.c:195
struct io_context * io
Definition: udptl.c:193

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

Referenced by ooh323_destroy(), and stream_destroy().

◆ ast_udptl_fd()

int ast_udptl_fd ( const struct ast_udptl udptl)

Definition at line 755 of file udptl.c.

756{
757 return udptl->fd;
758}

References ast_udptl::fd.

Referenced by apply_negotiated_sdp_stream(), and configure_local_rtp().

◆ ast_udptl_get_error_correction_scheme()

enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme ( const struct ast_udptl udptl)

Definition at line 965 of file udptl.c.

966{
967 return udptl->error_correction_scheme;
968}
enum ast_t38_ec_modes error_correction_scheme
Definition: udptl.c:201

References ast_udptl::error_correction_scheme.

Referenced by create_outgoing_sdp_stream().

◆ ast_udptl_get_far_max_datagram()

unsigned int ast_udptl_get_far_max_datagram ( const struct ast_udptl udptl)

Definition at line 1033 of file udptl.c.

1034{
1035 if (udptl->far_max_datagram < 0) {
1036 return 0;
1037 }
1038 return udptl->far_max_datagram;
1039}
int far_max_datagram
Definition: udptl.c:216

References ast_udptl::far_max_datagram.

◆ 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 1041 of file udptl.c.

1042{
1043 if (udptl->far_max_ifp == -1) {
1044 calculate_far_max_ifp(udptl);
1045 }
1046
1047 if (udptl->far_max_ifp < 0) {
1048 return 0;
1049 }
1050 return udptl->far_max_ifp;
1051}
int far_max_ifp
Definition: udptl.c:230
static void calculate_far_max_ifp(struct ast_udptl *udptl)
Definition: udptl.c:897

References calculate_far_max_ifp(), and ast_udptl::far_max_ifp.

Referenced by 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 1009 of file udptl.c.

1010{
1011 if (udptl->local_max_datagram == -1) {
1013 }
1014
1015 /* this function expects a unsigned value in return. */
1016 if (udptl->local_max_datagram < 0) {
1017 return 0;
1018 }
1019 return udptl->local_max_datagram;
1020}
int local_max_datagram
Definition: udptl.c:222
static void calculate_local_max_datagram(struct ast_udptl *udptl)
Definition: udptl.c:856

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 1160 of file udptl.c.

1161{
1162 ast_sockaddr_copy(them, &udptl->them);
1163}
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:190

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 1165 of file udptl.c.

1166{
1167 ast_sockaddr_copy(us, &udptl->us);
1168}
struct ast_sockaddr us
Definition: udptl.c:189

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 1053 of file udptl.c.

1054{
1055 struct ast_udptl *udptl;
1056 int x;
1057 int startplace;
1058 int i;
1060
1061 if (!cfg || !cfg->general) {
1062 ast_log(LOG_ERROR, "Could not access global udptl options!\n");
1063 return NULL;
1064 }
1065
1066 if (!(udptl = ast_calloc(1, sizeof(*udptl)))) {
1067 return NULL;
1068 }
1069
1070 udptl->error_correction_span = cfg->general->fecspan;
1071 udptl->error_correction_entries = cfg->general->fecentries;
1072
1073 udptl->far_max_datagram = -1;
1074 udptl->far_max_ifp = -1;
1075 udptl->local_max_ifp = -1;
1076 udptl->local_max_datagram = -1;
1077
1078 for (i = 0; i <= UDPTL_BUF_MASK; i++) {
1079 udptl->rx[i].buf_len = -1;
1080 udptl->tx[i].buf_len = -1;
1081 }
1082
1083 if ((udptl->fd = ast_socket_nonblock(ast_sockaddr_is_ipv6(addr) ?
1084 AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) {
1085 ast_free(udptl);
1086 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
1087 return NULL;
1088 }
1089
1090#ifdef SO_NO_CHECK
1091 if (cfg->general->nochecksums)
1092 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &cfg->general->nochecksums, sizeof(cfg->general->nochecksums));
1093#endif
1094
1095 /* Find us a place */
1096 x = (cfg->general->start == cfg->general->end) ? cfg->general->start : (ast_random() % (cfg->general->end - cfg->general->start)) + cfg->general->start;
1097 if (cfg->general->use_even_ports && (x & 1)) {
1098 ++x;
1099 }
1100 startplace = x;
1101 for (;;) {
1102 ast_sockaddr_copy(&udptl->us, addr);
1103 ast_sockaddr_set_port(&udptl->us, x);
1104 if (ast_bind(udptl->fd, &udptl->us) == 0) {
1105 break;
1106 }
1107 if (errno != EADDRINUSE && errno != EACCES) {
1108 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
1109 close(udptl->fd);
1110 ast_free(udptl);
1111 return NULL;
1112 }
1113 if (cfg->general->use_even_ports) {
1114 x += 2;
1115 } else {
1116 ++x;
1117 }
1118 if (x > cfg->general->end)
1119 x = cfg->general->start;
1120 if (x == startplace) {
1121 ast_log(LOG_WARNING, "No UDPTL ports remaining\n");
1122 close(udptl->fd);
1123 ast_free(udptl);
1124 return NULL;
1125 }
1126 }
1127 if (io && sched && callbackmode) {
1128 /* Operate this one in a callback mode */
1129 udptl->sched = sched;
1130 udptl->io = io;
1131 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl);
1132 }
1133
1134 return udptl;
1135}
#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:181
struct ast_sched_context * sched
Definition: udptl.c:192
unsigned int error_correction_entries
Definition: udptl.c:206
int local_max_ifp
Definition: udptl.c:236
udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK+1]
Definition: udptl.c:242
unsigned int error_correction_span
Definition: udptl.c:211
udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK+1]
Definition: udptl.c:241
Definition: sched.c:76
#define UDPTL_BUF_MASK
Definition: udptl.c:164
static int udptlread(int *id, int fd, short events, void *cbdata)
Definition: udptl.c:775
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1073
long int ast_random(void)
Definition: utils.c:2312

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(), and t38_initialize_session().

◆ ast_udptl_read()

struct ast_frame * ast_udptl_read ( struct ast_udptl udptl)

Definition at line 787 of file udptl.c.

788{
789 int res;
790 struct ast_sockaddr addr;
791 uint8_t *buf;
792
794
795 /* Cache where the header will go */
796 res = ast_recvfrom(udptl->fd,
797 buf,
798 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
799 0,
800 &addr);
801 if (res < 0) {
802 if (errno != EAGAIN)
803 ast_log(LOG_WARNING, "UDPTL (%s): read error: %s\n",
804 LOG_TAG(udptl), strerror(errno));
805 ast_assert(errno != EBADF);
806 return &ast_null_frame;
807 }
808
809 /* Ignore if the other side hasn't been given an address yet. */
810 if (ast_sockaddr_isnull(&udptl->them)) {
811 return &ast_null_frame;
812 }
813
814 /*
815 * If early media isn't turned on for the channel driver, it's going to
816 * drop this frame. By that time though, udptl has already incremented
817 * the expected sequence number so if the CPE re-sends, the second frame
818 * will be dropped as a dup even though the first frame never went through.
819 * So we drop the frame here if the channel isn't up. 'tag' is set by the
820 * channel drivers on T38_ENABLED or T38_PEER_REINVITE.
821 */
822 if (udptl->tag == NULL) {
823 return &ast_null_frame;
824 }
825
826 if (udptl->nat) {
827 /* Send to whoever sent to us */
828 if (ast_sockaddr_cmp(&udptl->them, &addr)) {
829 ast_sockaddr_copy(&udptl->them, &addr);
830 ast_debug(1, "UDPTL (%s): NAT, Using address %s\n",
831 LOG_TAG(udptl), ast_sockaddr_stringify(&udptl->them));
832 }
833 }
834
835 if (udptl_debug_test_addr(&addr)) {
836 int seq_no;
837
838 /* Decode sequence number just for verbose message. */
839 if (res < 2) {
840 /* Short packet. */
841 seq_no = -1;
842 } else {
843 seq_no = (buf[0] << 8) | buf[1];
844 }
845
846 ast_verb(1, "UDPTL (%s): packet from %s (seq %d, len %d)\n",
847 LOG_TAG(udptl), ast_sockaddr_stringify(&addr), seq_no, res);
848 }
849 if (udptl_rx_packet(udptl, buf, res) < 1) {
850 return &ast_null_frame;
851 }
852
853 return &udptl->f[0];
854}
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 char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
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
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:185
struct ast_frame f[16]
Definition: udptl.c:184
int nat
Definition: udptl.c:187
static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len)
Definition: udptl.c:406
#define LOG_TAG(u)
Definition: udptl.c:150
static int udptl_debug_test_addr(const struct ast_sockaddr *addr)
Definition: udptl.c:283
#define ast_assert(a)
Definition: utils.h:739

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(), and udptlread().

◆ ast_udptl_set_callback()

void ast_udptl_set_callback ( struct ast_udptl udptl,
ast_udptl_callback  callback 
)

Definition at line 765 of file udptl.c.

766{
767 udptl->callback = callback;
768}
ast_udptl_callback callback
Definition: udptl.c:196

References ast_udptl::callback.

◆ ast_udptl_set_data()

void ast_udptl_set_data ( struct ast_udptl udptl,
void *  data 
)

Definition at line 760 of file udptl.c.

761{
762 udptl->data = data;
763}
void * data
Definition: udptl.c:194

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 970 of file udptl.c.

971{
972 udptl->error_correction_scheme = ec;
973 switch (ec) {
976 if (udptl->error_correction_entries == 0) {
977 udptl->error_correction_entries = 3;
978 }
979 if (udptl->error_correction_span == 0) {
980 udptl->error_correction_span = 3;
981 }
982 break;
985 if (udptl->error_correction_entries == 0) {
986 udptl->error_correction_entries = 3;
987 }
988 break;
989 default:
990 /* nothing to do */
991 break;
992 };
993 /* reset calculated values so they'll be computed again */
994 udptl->local_max_datagram = -1;
995 udptl->far_max_ifp = -1;
996}
@ 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 t38_initialize_session(), and t38_interpret_sdp().

◆ 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 1022 of file udptl.c.

1023{
1024 if (!max_datagram || (max_datagram > FAX_MAX_DATAGRAM_LIMIT)) {
1026 } else {
1027 udptl->far_max_datagram = max_datagram;
1028 }
1029 /* reset calculated values so they'll be computed again */
1030 udptl->far_max_ifp = -1;
1031}
#define DEFAULT_FAX_MAX_DATAGRAM
Definition: udptl.c:159
#define FAX_MAX_DATAGRAM_LIMIT
Definition: udptl.c:160

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(), onModeChanged(), t38_initialize_session(), and t38_interpret_sdp().

◆ ast_udptl_set_local_max_ifp()

void ast_udptl_set_local_max_ifp ( struct ast_udptl udptl,
unsigned int  max_ifp 
)

Definition at line 998 of file udptl.c.

999{
1000 /* make sure max_ifp is a positive value since a cast will take place when
1001 * when setting local_max_ifp */
1002 if ((signed int) max_ifp > 0) {
1003 udptl->local_max_ifp = max_ifp;
1004 /* reset calculated values so they'll be computed again */
1005 udptl->local_max_datagram = -1;
1006 }
1007}

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

Referenced by t38_interpret_parameters().

◆ ast_udptl_set_peer()

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

Definition at line 1155 of file udptl.c.

1156{
1157 ast_sockaddr_copy(&udptl->them, them);
1158}

References ast_sockaddr_copy(), and ast_udptl::them.

Referenced by apply_negotiated_sdp_stream(), 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 1137 of file udptl.c.

1138{
1139 va_list ap;
1140
1141 ast_free(udptl->tag);
1142 udptl->tag = NULL;
1143 va_start(ap, format);
1144 if (ast_vasprintf(&udptl->tag, format, ap) == -1) {
1145 udptl->tag = NULL;
1146 }
1147 va_end(ap);
1148}
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
Definition: astmm.h:278

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

Referenced by setup_udptl_connection(), and t38_change_state().

◆ ast_udptl_setnat()

void ast_udptl_setnat ( struct ast_udptl udptl,
int  nat 
)

Definition at line 770 of file udptl.c.

771{
772 udptl->nat = nat;
773}

References ast_udptl::nat.

Referenced by t38_initialize_session().

◆ ast_udptl_setqos()

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

Definition at line 1150 of file udptl.c.

1151{
1152 return ast_set_qos(udptl->fd, tos, cos, "UDPTL");
1153}
unsigned int tos
Definition: chan_iax2.c:379
unsigned int cos
Definition: chan_iax2.c:380
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.

◆ ast_udptl_stop()

void ast_udptl_stop ( struct ast_udptl udptl)

Definition at line 1170 of file udptl.c.

1171{
1172 ast_sockaddr_setnull(&udptl->them);
1173}
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.

◆ ast_udptl_write()

int ast_udptl_write ( struct ast_udptl s,
struct ast_frame f 
)

Definition at line 1186 of file udptl.c.

1187{
1188 unsigned int seq;
1189 unsigned int len = f->datalen;
1190 /* if no max datagram size is provided, use default value */
1191 const int bufsize = (s->far_max_datagram > 0) ? s->far_max_datagram : DEFAULT_FAX_MAX_DATAGRAM;
1192 uint8_t buf[bufsize];
1193
1194 memset(buf, 0, sizeof(buf));
1195
1196 /* If we have no peer, return immediately */
1197 if (ast_sockaddr_isnull(&s->them)) {
1198 return 0;
1199 }
1200
1201 /* If there is no data length, return immediately */
1202 if (f->datalen == 0)
1203 return 0;
1204
1205 if ((f->frametype != AST_FRAME_MODEM) ||
1206 (f->subclass.integer != AST_MODEM_T38)) {
1207 ast_log(LOG_WARNING, "UDPTL (%s): UDPTL can only send T.38 data.\n",
1208 LOG_TAG(s));
1209 return -1;
1210 }
1211
1212 if (len > s->far_max_ifp) {
1214 "UDPTL (%s): UDPTL asked to send %u bytes of IFP when far end only prepared to accept %d bytes; data loss will occur."
1215 "You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n",
1216 LOG_TAG(s), len, s->far_max_ifp);
1217 len = s->far_max_ifp;
1218 }
1219
1220 /* Save seq_no for debug output because udptl_build_packet increments it */
1221 seq = s->tx_seq_no & 0xFFFF;
1222
1223 /* Cook up the UDPTL packet, with the relevant EC info. */
1224 len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, len);
1225
1226 if ((signed int) len > 0 && !ast_sockaddr_isnull(&s->them)) {
1227 if (ast_sendto(s->fd, buf, len, 0, &s->them) < 0) {
1228 ast_log(LOG_NOTICE, "UDPTL (%s): Transmission error to %s: %s\n",
1229 LOG_TAG(s), ast_sockaddr_stringify(&s->them), strerror(errno));
1230 }
1231 if (udptl_debug_test_addr(&s->them)) {
1232 ast_verb(1, "UDPTL (%s): packet to %s (seq %u, len %u)\n",
1234 }
1235 }
1236
1237 return 0;
1238}
static volatile unsigned int seq
Definition: app_sms.c:123
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
union ast_frame::@228 data
struct ast_frame_subclass subclass
enum ast_frame_type frametype
unsigned int tx_seq_no
Definition: udptl.c:238
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:646

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(), and ooh323_write().

◆ calculate_far_max_ifp()

static void calculate_far_max_ifp ( struct ast_udptl udptl)
static

Definition at line 897 of file udptl.c.

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

References ast_log, ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, LOG_TAG, LOG_WARNING, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.

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 856 of file udptl.c.

857{
858 unsigned int new_max = 0;
859
860 if (udptl->local_max_ifp == -1) {
861 ast_log(LOG_WARNING, "UDPTL (%s): Cannot calculate local_max_datagram before local_max_ifp has been set.\n",
862 LOG_TAG(udptl));
863 udptl->local_max_datagram = -1;
864 return;
865 }
866
867 /* calculate the amount of space required to receive an IFP
868 * of the maximum size supported by the application/endpoint
869 * that we are delivering them to (local endpoint), and add
870 * the amount of space required to support the selected
871 * error correction mode
872 */
873 switch (udptl->error_correction_scheme) {
875 /* need room for sequence number, length indicator, redundancy
876 * indicator and following length indicator
877 */
878 new_max = 5 + udptl->local_max_ifp;
879 break;
881 /* need room for sequence number, length indicators, plus
882 * room for up to 3 redundancy packets
883 */
884 new_max = 5 + udptl->local_max_ifp + 2 + (3 * udptl->local_max_ifp);
885 break;
887 /* need room for sequence number, length indicators and a
888 * a single IFP of the maximum size expected
889 */
890 new_max = 5 + udptl->local_max_ifp + 4 + udptl->local_max_ifp;
891 break;
892 }
893 /* add 5% extra space for insurance, but no larger than LOCAL_FAX_MAX_DATAGRAM */
894 udptl->local_max_datagram = MIN(new_max * 1.05, LOCAL_FAX_MAX_DATAGRAM);
895}
#define LOCAL_FAX_MAX_DATAGRAM
Definition: udptl.c:158
#define MIN(a, b)
Definition: utils.h:231

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 299 of file udptl.c.

300{
301 if (*len >= limit)
302 return -1;
303 if ((buf[*len] & 0x80) == 0) {
304 *pvalue = buf[*len];
305 (*len)++;
306 return 0;
307 }
308 if ((buf[*len] & 0x40) == 0) {
309 if (*len == limit - 1)
310 return -1;
311 *pvalue = (buf[*len] & 0x3F) << 8;
312 (*len)++;
313 *pvalue |= buf[*len];
314 (*len)++;
315 return 0;
316 }
317 *pvalue = (buf[*len] & 0x3F) << 14;
318 (*len)++;
319 /* We have a fragment. Currently we don't process fragments. */
320 ast_debug(1, "UDPTL packet with length greater than 16K received, decoding will fail\n");
321 return 1;
322}

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 325 of file udptl.c.

326{
327 unsigned int octet_cnt = 0;
328
329 if (decode_length(buf, limit, len, &octet_cnt) != 0)
330 return -1;
331
332 /* Make sure the buffer contains at least the number of bits requested */
333 if ((*len + octet_cnt) > limit) {
334 return -1;
335 }
336
337 *p_num_octets = octet_cnt;
338 *p_object = &buf[*len];
339 *len += octet_cnt;
340
341 return 0;
342}
static int decode_length(uint8_t *buf, unsigned int limit, unsigned int *len, unsigned int *pvalue)
Definition: udptl.c:299

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 345 of file udptl.c.

346{
347 unsigned int multiplier;
348
349 if (value < 0x80) {
350 /* 1 octet */
351 buf[*len] = value;
352 (*len)++;
353 return value;
354 }
355 if (value < 0x4000) {
356 /* 2 octets */
357 /* Set the first bit of the first octet */
358 buf[*len] = ((0x8000 | value) >> 8) & 0xFF;
359 (*len)++;
360 buf[*len] = value & 0xFF;
361 (*len)++;
362 return value;
363 }
364 /* Fragmentation */
365 multiplier = (value < 0x10000) ? (value >> 14) : 4;
366 /* Set the first 2 bits of the octet */
367 buf[*len] = 0xC0 | multiplier;
368 (*len)++;
369 return multiplier << 14;
370}
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 373 of file udptl.c.

375{
376 unsigned int enclen;
377 unsigned int octet_idx;
378 uint8_t zero_byte;
379
380 /* If open type is of zero length, add a single zero byte (10.1) */
381 if (num_octets == 0) {
382 zero_byte = 0;
383 data = &zero_byte;
384 num_octets = 1;
385 }
386 /* Encode the open type */
387 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
388 enclen = encode_length(buf, len, num_octets);
389 if (enclen + *len > buflen) {
390 ast_log(LOG_ERROR, "UDPTL (%s): Buffer overflow detected (%u + %u > %u)\n",
391 LOG_TAG(udptl), enclen, *len, buflen);
392 return -1;
393 }
394 if (enclen > 0) {
395 memcpy(&buf[*len], &data[octet_idx], enclen);
396 *len += enclen;
397 }
398 if (enclen >= num_octets)
399 break;
400 }
401
402 return 0;
403}
static unsigned int encode_length(uint8_t *buf, unsigned int *len, unsigned int value)
Definition: udptl.c:345

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 1285 of file udptl.c.

1286{
1287 RAII_VAR(struct udptl_config *, cfg, NULL, ao2_cleanup);
1288
1289 switch (cmd) {
1290 case CLI_INIT:
1291 e->command = "udptl show config";
1292 e->usage =
1293 "Usage: udptl show config\n"
1294 " Display UDPTL configuration options\n";
1295 return NULL;
1296 case CLI_GENERATE:
1297 return NULL;
1298 }
1299
1300 if (!(cfg = ao2_global_obj_ref(globals))) {
1301 return CLI_FAILURE;
1302 }
1303
1304 ast_cli(a->fd, "UDPTL Global options\n");
1305 ast_cli(a->fd, "--------------------\n");
1306 ast_cli(a->fd, "udptlstart: %u\n", cfg->general->start);
1307 ast_cli(a->fd, "udptlend: %u\n", cfg->general->end);
1308 ast_cli(a->fd, "udptlfecentries: %u\n", cfg->general->fecentries);
1309 ast_cli(a->fd, "udptlfecspan: %u\n", cfg->general->fecspan);
1310 ast_cli(a->fd, "use_even_ports: %s\n", AST_CLI_YESNO(cfg->general->use_even_ports));
1311 ast_cli(a->fd, "udptlchecksums: %s\n", AST_CLI_YESNO(!cfg->general->nochecksums));
1312
1313 return CLI_SUCCESS;
1314}
#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

References a, ao2_cleanup, ao2_global_obj_ref, ast_cli(), AST_CLI_YESNO, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, globals, NULL, RAII_VAR, and ast_cli_entry::usage.

◆ 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 1240 of file udptl.c.

1241{
1242 switch (cmd) {
1243 case CLI_INIT:
1244 e->command = "udptl set debug {on|off|ip}";
1245 e->usage =
1246 "Usage: udptl set debug {on|off|ip host[:port]}\n"
1247 " Enable or disable dumping of UDPTL packets.\n"
1248 " If ip is specified, limit the dumped packets to those to and from\n"
1249 " the specified 'host' with optional port.\n";
1250 return NULL;
1251 case CLI_GENERATE:
1252 return NULL;
1253 }
1254
1255 if (a->argc < 4 || a->argc > 5)
1256 return CLI_SHOWUSAGE;
1257
1258 if (a->argc == 4) {
1259 if (!strncasecmp(a->argv[3], "on", 2)) {
1260 udptldebug = 1;
1261 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
1262 ast_cli(a->fd, "UDPTL Debugging Enabled\n");
1263 } else if (!strncasecmp(a->argv[3], "off", 3)) {
1264 udptldebug = 0;
1265 ast_cli(a->fd, "UDPTL Debugging Disabled\n");
1266 } else {
1267 return CLI_SHOWUSAGE;
1268 }
1269 } else {
1270 struct ast_sockaddr *addrs;
1271 if (strncasecmp(a->argv[3], "ip", 2))
1272 return CLI_SHOWUSAGE;
1273 if (!ast_sockaddr_resolve(&addrs, a->argv[4], 0, 0)) {
1274 return CLI_SHOWUSAGE;
1275 }
1276 ast_sockaddr_copy(&udptldebugaddr, &addrs[0]);
1277 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_sockaddr_stringify(&udptldebugaddr));
1278 udptldebug = 1;
1279 ast_free(addrs);
1280 }
1281
1282 return CLI_SUCCESS;
1283}
#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:156
static int udptldebug
Definition: udptl.c:155

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 1421 of file udptl.c.

1422{
1423 if (aco_info_init(&cfg_info)) {
1425 }
1426
1429 FLDSET(struct udptl_global_options, start), DEFAULT_UDPTLSTART, 1024, 65535);
1430
1433 FLDSET(struct udptl_global_options, end), DEFAULT_UDPTLEND, 1024, 65535);
1434
1435 aco_option_register(&cfg_info, "udptlfecentries", ACO_EXACT, general_options, NULL,
1437 FLDSET(struct udptl_global_options, fecentries), 1, MAX_FEC_ENTRIES);
1438
1439 aco_option_register(&cfg_info, "udptlfecspan", ACO_EXACT, general_options, NULL,
1441 FLDSET(struct udptl_global_options, fecspan), 1, MAX_FEC_SPAN);
1442
1443 aco_option_register(&cfg_info, "udptlchecksums", ACO_EXACT, general_options, "yes",
1444 OPT_BOOL_T, 0, FLDSET(struct udptl_global_options, nochecksums));
1445
1446 aco_option_register(&cfg_info, "use_even_ports", ACO_EXACT, general_options, "no",
1447 OPT_BOOL_T, 1, FLDSET(struct udptl_global_options, use_even_ports));
1448
1451
1453
1455
1457}
#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:161
#define DEFAULT_UDPTLEND
Definition: udptl.c:153
static int removed_options_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: udptl.c:1342
#define DEFAULT_UDPTLSTART
Definition: udptl.c:152
static struct ast_cli_entry cli_udptl[]
Definition: udptl.c:1316
#define MAX_FEC_SPAN
Definition: udptl.c:162
static struct aco_type * general_options[]
Definition: udptl.c:271
static void __ast_udptl_reload(int reload)
Definition: udptl.c:1352
#define ARRAY_LEN(a)
Definition: utils.h:666

References __ast_udptl_reload(), __stringify, ACO_EXACT, aco_info_init(), aco_option_register, aco_option_register_custom, ARRAY_LEN, ast_cli_register_multiple, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, cli_udptl, DEFAULT_UDPTLEND, DEFAULT_UDPTLSTART, end, FLDSET, general_options, MAX_FEC_ENTRIES, MAX_FEC_SPAN, NULL, OPT_BOOL_T, OPT_UINT_T, PARSE_DEFAULT, PARSE_IN_RANGE, PARSE_RANGE_DEFAULTS, and removed_options_handler().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 1401 of file udptl.c.

1402{
1404
1405 return 0;
1406}

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 1342 of file udptl.c.

1343{
1344 if (!strcasecmp(var->name, "t38faxudpec")) {
1345 ast_log(LOG_WARNING, "t38faxudpec in udptl.conf is no longer supported.\n");
1346 } else if (!strcasecmp(var->name, "t38faxmaxdatagram")) {
1347 ast_log(LOG_WARNING, "t38faxmaxdatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n");
1348 }
1349 return 0;
1350}
#define var
Definition: ast_expr2f.c:605

References ast_log, LOG_WARNING, and var.

Referenced by load_module().

◆ 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 646 of file udptl.c.

647{
648 uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2] = { 0, };
649 int i;
650 int j;
651 int seq;
652 int entry;
653 int entries;
654 int span;
655 int m;
656 unsigned int len;
657 int limit;
658 int high_tide;
659
660 seq = s->tx_seq_no & 0xFFFF;
661
662 /* Map the sequence number to an entry in the circular buffer */
663 entry = seq & UDPTL_BUF_MASK;
664
665 /* We save the message in a circular buffer, for generating FEC or
666 redundancy sets later on. */
667 s->tx[entry].buf_len = ifp_len;
668 memcpy(s->tx[entry].buf, ifp, ifp_len);
669
670 /* Build the UDPTLPacket */
671
672 len = 0;
673 /* Encode the sequence number */
674 buf[len++] = (seq >> 8) & 0xFF;
675 buf[len++] = seq & 0xFF;
676
677 /* Encode the primary IFP packet */
678 if (encode_open_type(s, buf, buflen, &len, ifp, ifp_len) < 0)
679 return -1;
680
681 /* Encode the appropriate type of error recovery information */
682 switch (s->error_correction_scheme)
683 {
685 /* Encode the error recovery type */
686 buf[len++] = 0x00;
687 /* The number of entries will always be zero, so it is pointless allowing
688 for the fragmented case here. */
689 encode_length(buf, &len, 0);
690 break;
692 /* Encode the error recovery type */
693 buf[len++] = 0x00;
695 entries = s->error_correction_entries;
696 else
697 entries = s->tx_seq_no;
698 /* The number of entries will always be small, so it is pointless allowing
699 for the fragmented case here. */
700 encode_length(buf, &len, entries);
701 /* Encode the elements */
702 for (i = 0; i < entries; i++) {
703 j = (entry - i - 1) & UDPTL_BUF_MASK;
704 if (encode_open_type(s, buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) {
705 ast_debug(1, "UDPTL (%s): Encoding failed at i=%d, j=%d\n",
706 LOG_TAG(s), i, j);
707 return -1;
708 }
709 }
710 break;
712 span = s->error_correction_span;
713 entries = s->error_correction_entries;
714 if (seq < s->error_correction_span*s->error_correction_entries) {
715 /* In the initial stages, wind up the FEC smoothly */
716 entries = seq/s->error_correction_span;
717 if (seq < s->error_correction_span)
718 span = 0;
719 }
720 /* Encode the error recovery type */
721 buf[len++] = 0x80;
722 /* Span is defined as an unconstrained integer, which it dumb. It will only
723 ever be a small value. Treat it as such. */
724 buf[len++] = 1;
725 buf[len++] = span;
726 /* The number of entries is defined as a length, but will only ever be a small
727 value. Treat it as such. */
728 buf[len++] = entries;
729 for (m = 0; m < entries; m++) {
730 /* Make an XOR'ed entry the maximum length */
731 limit = (entry + m) & UDPTL_BUF_MASK;
732 high_tide = 0;
733 for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) {
734 if (high_tide < s->tx[i].buf_len) {
735 for (j = 0; j < high_tide; j++)
736 fec[j] ^= s->tx[i].buf[j];
737 for ( ; j < s->tx[i].buf_len; j++)
738 fec[j] = s->tx[i].buf[j];
739 high_tide = s->tx[i].buf_len;
740 } else {
741 for (j = 0; j < s->tx[i].buf_len; j++)
742 fec[j] ^= s->tx[i].buf[j];
743 }
744 }
745 if (encode_open_type(s, buf, buflen, &len, fec, high_tide) < 0)
746 return -1;
747 }
748 break;
749 }
750
751 s->tx_seq_no++;
752 return len;
753}
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]
Definition: udptl.c:168
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:373

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 1321 of file udptl.c.

1322{
1323 struct udptl_config *cfg = obj;
1324 ao2_cleanup(cfg->general);
1325}
struct udptl_global_options * general
Definition: udptl.c:257

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 283 of file udptl.c.

284{
285 if (udptldebug == 0)
286 return 0;
287
289 return 1;
290 }
291
293 return !ast_sockaddr_cmp(&udptldebugaddr, addr);
294 } else {
296 }
297}
#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 1369 of file udptl.c.

1369 {
1370 struct udptl_config *cfg = aco_pending_config(&cfg_info);
1371
1372 if (!cfg->general) {
1373 return -1;
1374 }
1375
1376#ifndef SO_NO_CHECK
1377 if (cfg->general->nochecksums) {
1378 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n");
1379 cfg->general->nochecksums = 0;
1380 }
1381#endif
1382
1383 /* Fix up any global config values that we can handle before replacing the config */
1384 if (cfg->general->use_even_ports && (cfg->general->start & 1)) {
1385 ++cfg->general->start;
1386 ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %u\n", cfg->general->start);
1387 }
1388 if (cfg->general->start > cfg->general->end) {
1389 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to %s-%s.\n", __stringify(DEFAULT_UDPTLSTART), __stringify(DEFAULT_UDPTLEND));
1392 }
1393 if (cfg->general->use_even_ports && (cfg->general->end & 1)) {
1394 --cfg->general->end;
1395 ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_even_ports enabled. udptlend is now %u\n", cfg->general->end);
1396 }
1397
1398 return 0;
1399}
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
unsigned int use_even_ports
Definition: udptl.c:251
unsigned int nochecksums
Definition: udptl.c:250
unsigned int start
Definition: udptl.c:246
unsigned int end
Definition: udptl.c:247

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 406 of file udptl.c.

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

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 1327 of file udptl.c.

1328{
1329 struct udptl_config *cfg;
1330
1331 if (!(cfg = ao2_alloc(sizeof(*cfg), udptl_config_destructor))) {
1332 return NULL;
1333 }
1334 if (!(cfg->general = ao2_alloc(sizeof(*cfg->general), NULL))) {
1335 ao2_ref(cfg, -1);
1336 return NULL;
1337 }
1338
1339 return cfg;
1340}
#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:1321

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 775 of file udptl.c.

776{
777 struct ast_udptl *udptl = cbdata;
778 struct ast_frame *f;
779
780 if ((f = ast_udptl_read(udptl))) {
781 if (udptl->callback)
782 udptl->callback(udptl, f, udptl->data);
783 }
784 return 1;
785}
Data structure associated with a single frame of data.
struct ast_frame * ast_udptl_read(struct ast_udptl *udptl)
Definition: udptl.c:787

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 1412 of file udptl.c.

1413{
1415 ao2_t_global_obj_release(globals, "Unref udptl global container in shutdown");
1416 aco_info_destroy(&cfg_info);
1417
1418 return 0;
1419}
#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 1466 of file udptl.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1466 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_udptl_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: udptl.c:1240
static char * handle_cli_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: udptl.c:1285

Definition at line 1316 of file udptl.c.

Referenced by load_module(), and unload_module().

◆ general_option

struct aco_type general_option
static

Definition at line 263 of file udptl.c.

Referenced by __ast_udptl_reload().

◆ general_options

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

Definition at line 271 of file udptl.c.

Referenced by load_module().

◆ 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 273 of file udptl.c.

◆ udptldebug

int udptldebug
static

Are we debugging?

Definition at line 155 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 156 of file udptl.c.

Referenced by handle_cli_udptl_set_debug(), and udptl_debug_test_addr().