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/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

Defines

#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 AO2_GLOBAL_OBJ_STATIC (globals)
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
unsigned int ast_udptl_get_local_max_datagram (struct ast_udptl *udptl)
 retrieves local_max_datagram.
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)
void ast_udptl_init (void)
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)
int ast_udptl_reload (void)
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.
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.
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 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_shutdown (void)
static void * udptl_snapshot_alloc (void)
static int udptlread (int *id, int fd, short events, void *cbdata)

Variables

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 <markster@digium.com>

Steve Underwood <steveu@coppice.org>

Kevin P. Fleming <kpfleming@digium.com>

Definition in file udptl.c.


Define Documentation

#define DEFAULT_FAX_MAX_DATAGRAM   400

Definition at line 135 of file udptl.c.

Referenced by ast_udptl_set_far_max_datagram(), and ast_udptl_write().

#define DEFAULT_UDPTLEND   4999

Definition at line 129 of file udptl.c.

Referenced by ast_udptl_init(), and udptl_pre_apply_config().

#define DEFAULT_UDPTLSTART   4000

Definition at line 128 of file udptl.c.

Referenced by ast_udptl_init(), and udptl_pre_apply_config().

#define FALSE   0

Definition at line 120 of file udptl.c.

#define FAX_MAX_DATAGRAM_LIMIT   1400

Definition at line 136 of file udptl.c.

Referenced by ast_udptl_set_far_max_datagram().

#define LOCAL_FAX_MAX_DATAGRAM   1400

Definition at line 134 of file udptl.c.

Referenced by calculate_local_max_datagram(), udptl_build_packet(), and udptl_rx_packet().

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

#define MAX_FEC_ENTRIES   5

Definition at line 137 of file udptl.c.

Referenced by ast_udptl_init(), and udptl_rx_packet().

#define MAX_FEC_SPAN   5

Definition at line 138 of file udptl.c.

Referenced by ast_udptl_init().

#define TRUE   (!FALSE)

Definition at line 123 of file udptl.c.

#define UDPTL_BUF_MASK   15

Definition at line 140 of file udptl.c.

Referenced by ast_udptl_new_with_bindaddr(), udptl_build_packet(), and udptl_rx_packet().

#define UDPTL_MTU   1200

Definition at line 117 of file udptl.c.


Function Documentation

static void __ast_udptl_reload ( int  reload  )  [static]

Definition at line 1302 of file udptl.c.

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

Referenced by ast_udptl_init(), and ast_udptl_reload().

01303 {
01304    if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) {
01305       if (!reload) {
01306          RAII_VAR(struct udptl_config *, udptl_cfg, udptl_snapshot_alloc(), ao2_cleanup);
01307 
01308          if (aco_set_defaults(&general_option, "general", udptl_cfg->general)) {
01309             ast_log(LOG_ERROR, "Failed to load udptl.conf and failed to initialize defaults.\n");
01310             return;
01311          }
01312 
01313          ast_log(LOG_NOTICE, "Could not load udptl config; using defaults\n");
01314          ao2_global_obj_replace_unref(globals, udptl_cfg);
01315       }
01316    }
01317 }

static AO2_GLOBAL_OBJ_STATIC ( globals   )  [static]

void ast_udptl_destroy ( struct ast_udptl udptl  ) 

Definition at line 1125 of file udptl.c.

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

Referenced by __sip_destroy(), ooh323_destroy(), and stream_destroy().

01126 {
01127    if (udptl->ioid)
01128       ast_io_remove(udptl->io, udptl->ioid);
01129    if (udptl->fd > -1)
01130       close(udptl->fd);
01131    if (udptl->tag)
01132       ast_free(udptl->tag);
01133    ast_free(udptl);
01134 }

int ast_udptl_fd ( const struct ast_udptl udptl  ) 

Definition at line 714 of file udptl.c.

References ast_udptl::fd.

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

00715 {
00716    return udptl->fd;
00717 }

enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme ( const struct ast_udptl udptl  ) 

Definition at line 912 of file udptl.c.

References ast_udptl::error_correction_scheme.

Referenced by add_sdp(), and create_outgoing_sdp_stream().

00913 {
00914    return udptl->error_correction_scheme;
00915 }

unsigned int ast_udptl_get_far_max_datagram ( const struct ast_udptl udptl  ) 

Definition at line 980 of file udptl.c.

References ast_udptl::far_max_datagram.

Referenced by process_sdp().

00981 {
00982    if (udptl->far_max_datagram < 0) {
00983       return 0;
00984    }
00985    return udptl->far_max_datagram;
00986 }

unsigned int ast_udptl_get_far_max_ifp ( struct ast_udptl udptl  ) 

retrieves far max ifp

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

Definition at line 988 of file udptl.c.

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().

00989 {
00990    if (udptl->far_max_ifp == -1) {
00991       calculate_far_max_ifp(udptl);
00992    }
00993 
00994    if (udptl->far_max_ifp < 0) {
00995       return 0;
00996    }
00997    return udptl->far_max_ifp;
00998 }

unsigned int ast_udptl_get_local_max_datagram ( struct ast_udptl udptl  ) 

retrieves local_max_datagram.

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

Definition at line 956 of file udptl.c.

References calculate_local_max_datagram(), and ast_udptl::local_max_datagram.

Referenced by add_sdp(), and create_outgoing_sdp_stream().

00957 {
00958    if (udptl->local_max_datagram == -1) {
00959       calculate_local_max_datagram(udptl);
00960    }
00961 
00962    /* this function expects a unsigned value in return. */
00963    if (udptl->local_max_datagram < 0) {
00964       return 0;
00965    }
00966    return udptl->local_max_datagram;
00967 }

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

Definition at line 1110 of file udptl.c.

References ast_sockaddr_copy(), and ast_udptl::them.

01111 {
01112    ast_sockaddr_copy(them, &udptl->them);
01113 }

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

Definition at line 1115 of file udptl.c.

References ast_sockaddr_copy(), and ast_udptl::us.

Referenced by add_sdp(), configure_local_rtp(), and create_outgoing_sdp_stream().

01116 {
01117    ast_sockaddr_copy(us, &udptl->us);
01118 }

void ast_udptl_init ( void   ) 

Definition at line 1368 of file udptl.c.

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

Referenced by main().

01369 {
01370    if (aco_info_init(&cfg_info)) {
01371       return;
01372    }
01373 
01374    aco_option_register(&cfg_info, "udptlstart", ACO_EXACT, general_options, __stringify(DEFAULT_UDPTLSTART),
01375       OPT_UINT_T, PARSE_IN_RANGE | PARSE_DEFAULT,
01376       FLDSET(struct udptl_global_options, start), DEFAULT_UDPTLSTART, 1024, 65535);
01377 
01378    aco_option_register(&cfg_info, "udptlend", ACO_EXACT, general_options, __stringify(DEFAULT_UDPTLEND),
01379       OPT_UINT_T, PARSE_IN_RANGE | PARSE_DEFAULT,
01380       FLDSET(struct udptl_global_options, end), DEFAULT_UDPTLEND, 1024, 65535);
01381 
01382    aco_option_register(&cfg_info, "udptlfecentries", ACO_EXACT, general_options, NULL,
01383       OPT_UINT_T, PARSE_IN_RANGE | PARSE_RANGE_DEFAULTS,
01384       FLDSET(struct udptl_global_options, fecentries), 1, MAX_FEC_ENTRIES);
01385 
01386    aco_option_register(&cfg_info, "udptlfecspan", ACO_EXACT, general_options, NULL,
01387       OPT_UINT_T, PARSE_IN_RANGE | PARSE_RANGE_DEFAULTS,
01388       FLDSET(struct udptl_global_options, fecspan), 1, MAX_FEC_SPAN);
01389 
01390    aco_option_register(&cfg_info, "udptlchecksums", ACO_EXACT, general_options, "yes",
01391       OPT_BOOL_T, 0, FLDSET(struct udptl_global_options, nochecksums));
01392 
01393    aco_option_register(&cfg_info, "use_even_ports", ACO_EXACT, general_options, "no",
01394       OPT_BOOL_T, 1, FLDSET(struct udptl_global_options, use_even_ports));
01395 
01396    aco_option_register_custom(&cfg_info, "t38faxudpec", ACO_EXACT, general_options, NULL, removed_options_handler, 0);
01397    aco_option_register_custom(&cfg_info, "t38faxmaxdatagram", ACO_EXACT, general_options, NULL, removed_options_handler, 0);
01398 
01399    __ast_udptl_reload(0);
01400 
01401    ast_cli_register_multiple(cli_udptl, ARRAY_LEN(cli_udptl));
01402 
01403    ast_register_cleanup(udptl_shutdown);
01404 }

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

Definition at line 1000 of file udptl.c.

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, 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, ast_udptl::flags, globals, 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, 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().

01001 {
01002    struct ast_udptl *udptl;
01003    int x;
01004    int startplace;
01005    int i;
01006    long int flags;
01007    RAII_VAR(struct udptl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
01008 
01009    if (!cfg || !cfg->general) {
01010       ast_log(LOG_ERROR, "Could not access global udptl options!\n");
01011       return NULL;
01012    }
01013 
01014    if (!(udptl = ast_calloc(1, sizeof(*udptl)))) {
01015       return NULL;
01016    }
01017 
01018    udptl->error_correction_span = cfg->general->fecspan;
01019    udptl->error_correction_entries = cfg->general->fecentries;
01020 
01021    udptl->far_max_datagram = -1;
01022    udptl->far_max_ifp = -1;
01023    udptl->local_max_ifp = -1;
01024    udptl->local_max_datagram = -1;
01025 
01026    for (i = 0; i <= UDPTL_BUF_MASK; i++) {
01027       udptl->rx[i].buf_len = -1;
01028       udptl->tx[i].buf_len = -1;
01029    }
01030 
01031    if ((udptl->fd = socket(ast_sockaddr_is_ipv6(addr) ?
01032                AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) {
01033       ast_free(udptl);
01034       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
01035       return NULL;
01036    }
01037    flags = fcntl(udptl->fd, F_GETFL);
01038    fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK);
01039 
01040 #ifdef SO_NO_CHECK
01041    if (cfg->general->nochecksums)
01042       setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &cfg->general->nochecksums, sizeof(cfg->general->nochecksums));
01043 #endif
01044 
01045    /* Find us a place */
01046    x = (cfg->general->start == cfg->general->end) ? cfg->general->start : (ast_random() % (cfg->general->end - cfg->general->start)) + cfg->general->start;
01047    if (cfg->general->use_even_ports && (x & 1)) {
01048       ++x;
01049    }
01050    startplace = x;
01051    for (;;) {
01052       ast_sockaddr_copy(&udptl->us, addr);
01053       ast_sockaddr_set_port(&udptl->us, x);
01054       if (ast_bind(udptl->fd, &udptl->us) == 0) {
01055          break;
01056       }
01057       if (errno != EADDRINUSE && errno != EACCES) {
01058          ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
01059          close(udptl->fd);
01060          ast_free(udptl);
01061          return NULL;
01062       }
01063       if (cfg->general->use_even_ports) {
01064          x += 2;
01065       } else {
01066          ++x;
01067       }
01068       if (x > cfg->general->end)
01069          x = cfg->general->start;
01070       if (x == startplace) {
01071          ast_log(LOG_WARNING, "No UDPTL ports remaining\n");
01072          close(udptl->fd);
01073          ast_free(udptl);
01074          return NULL;
01075       }
01076    }
01077    if (io && sched && callbackmode) {
01078       /* Operate this one in a callback mode */
01079       udptl->sched = sched;
01080       udptl->io = io;
01081       udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl);
01082    }
01083 
01084    return udptl;
01085 }

struct ast_frame* ast_udptl_read ( struct ast_udptl udptl  )  [read]

Definition at line 746 of file udptl.c.

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, ast_udptl::rawdata, ast_udptl::them, udptl_debug_test_addr(), and udptl_rx_packet().

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

00747 {
00748    int res;
00749    struct ast_sockaddr addr;
00750    uint8_t *buf;
00751 
00752    buf = udptl->rawdata + AST_FRIENDLY_OFFSET;
00753 
00754    /* Cache where the header will go */
00755    res = ast_recvfrom(udptl->fd,
00756          buf,
00757          sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
00758          0,
00759          &addr);
00760    if (res < 0) {
00761       if (errno != EAGAIN)
00762          ast_log(LOG_WARNING, "UDPTL (%s): read error: %s\n",
00763             LOG_TAG(udptl), strerror(errno));
00764       ast_assert(errno != EBADF);
00765       return &ast_null_frame;
00766    }
00767 
00768    /* Ignore if the other side hasn't been given an address yet. */
00769    if (ast_sockaddr_isnull(&udptl->them)) {
00770       return &ast_null_frame;
00771    }
00772 
00773    if (udptl->nat) {
00774       /* Send to whoever sent to us */
00775       if (ast_sockaddr_cmp(&udptl->them, &addr)) {
00776          ast_sockaddr_copy(&udptl->them, &addr);
00777          ast_debug(1, "UDPTL (%s): NAT, Using address %s\n",
00778               LOG_TAG(udptl), ast_sockaddr_stringify(&udptl->them));
00779       }
00780    }
00781 
00782    if (udptl_debug_test_addr(&addr)) {
00783       int seq_no;
00784 
00785       /* Decode sequence number just for verbose message. */
00786       if (res < 2) {
00787          /* Short packet. */
00788          seq_no = -1;
00789       } else {
00790          seq_no = (buf[0] << 8) | buf[1];
00791       }
00792 
00793       ast_verb(1, "UDPTL (%s): packet from %s (seq %d, len %d)\n",
00794          LOG_TAG(udptl), ast_sockaddr_stringify(&addr), seq_no, res);
00795    }
00796    if (udptl_rx_packet(udptl, buf, res) < 1) {
00797       return &ast_null_frame;
00798    }
00799 
00800    return &udptl->f[0];
00801 }

int ast_udptl_reload ( void   ) 

Version:
1.6.1 return changed to int

Definition at line 1351 of file udptl.c.

References __ast_udptl_reload().

01352 {
01353    __ast_udptl_reload(1);
01354    return 0;
01355 }

void ast_udptl_set_callback ( struct ast_udptl udptl,
ast_udptl_callback  callback 
)

Definition at line 724 of file udptl.c.

References ast_udptl::callback.

00725 {
00726    udptl->callback = callback;
00727 }

void ast_udptl_set_data ( struct ast_udptl udptl,
void *  data 
)

Definition at line 719 of file udptl.c.

References ast_udptl::data.

00720 {
00721    udptl->data = data;
00722 }

void ast_udptl_set_error_correction_scheme ( struct ast_udptl udptl,
enum ast_t38_ec_modes  ec 
)

Definition at line 917 of file udptl.c.

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 process_sdp(), process_sdp_a_image(), set_t38_capabilities(), t38_initialize_session(), and t38_interpret_sdp().

00918 {
00919    udptl->error_correction_scheme = ec;
00920    switch (ec) {
00921    case UDPTL_ERROR_CORRECTION_FEC:
00922       udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC;
00923       if (udptl->error_correction_entries == 0) {
00924          udptl->error_correction_entries = 3;
00925       }
00926       if (udptl->error_correction_span == 0) {
00927          udptl->error_correction_span = 3;
00928       }
00929       break;
00930    case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00931       udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY;
00932       if (udptl->error_correction_entries == 0) {
00933          udptl->error_correction_entries = 3;
00934       }
00935       break;
00936    default:
00937       /* nothing to do */
00938       break;
00939    };
00940    /* reset calculated values so they'll be computed again */
00941    udptl->local_max_datagram = -1;
00942    udptl->far_max_ifp = -1;
00943 }

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

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

00970 {
00971    if (!max_datagram || (max_datagram > FAX_MAX_DATAGRAM_LIMIT)) {
00972       udptl->far_max_datagram = DEFAULT_FAX_MAX_DATAGRAM;
00973    } else {
00974       udptl->far_max_datagram = max_datagram;
00975    }
00976    /* reset calculated values so they'll be computed again */
00977    udptl->far_max_ifp = -1;
00978 }

void ast_udptl_set_local_max_ifp ( struct ast_udptl udptl,
unsigned int  max_ifp 
)

Definition at line 945 of file udptl.c.

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

Referenced by interpret_t38_parameters(), and t38_interpret_parameters().

00946 {
00947    /* make sure max_ifp is a positive value since a cast will take place when
00948     * when setting local_max_ifp */
00949    if ((signed int) max_ifp > 0) {
00950       udptl->local_max_ifp = max_ifp;
00951       /* reset calculated values so they'll be computed again */
00952       udptl->local_max_datagram = -1;
00953    }
00954 }

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

Definition at line 1105 of file udptl.c.

References ast_sockaddr_copy(), and ast_udptl::them.

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

01106 {
01107    ast_sockaddr_copy(&udptl->them, them);
01108 }

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

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

Parameters:
udptl The UDPTL session.
format printf-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.

Return values:
none 

Definition at line 1087 of file udptl.c.

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

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

01088 {
01089    va_list ap;
01090 
01091    ast_free(udptl->tag);
01092    udptl->tag = NULL;
01093    va_start(ap, format);
01094    if (ast_vasprintf(&udptl->tag, format, ap) == -1) {
01095       udptl->tag = NULL;
01096    }
01097    va_end(ap);
01098 }

void ast_udptl_setnat ( struct ast_udptl udptl,
int  nat 
)

Definition at line 729 of file udptl.c.

References ast_udptl::nat.

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

00730 {
00731    udptl->nat = nat;
00732 }

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

Definition at line 1100 of file udptl.c.

References ast_set_qos(), and ast_udptl::fd.

Referenced by initialize_udptl().

01101 {
01102    return ast_set_qos(udptl->fd, tos, cos, "UDPTL");
01103 }

void ast_udptl_stop ( struct ast_udptl udptl  ) 

Definition at line 1120 of file udptl.c.

References ast_sockaddr_setnull(), and ast_udptl::them.

Referenced by process_sdp(), and stop_media_flows().

01121 {
01122    ast_sockaddr_setnull(&udptl->them);
01123 }

int ast_udptl_write ( struct ast_udptl s,
struct ast_frame f 
)

Definition at line 1136 of file udptl.c.

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

01137 {
01138    unsigned int seq;
01139    unsigned int len = f->datalen;
01140    /* if no max datagram size is provided, use default value */
01141    const int bufsize = (s->far_max_datagram > 0) ? s->far_max_datagram : DEFAULT_FAX_MAX_DATAGRAM;
01142    uint8_t buf[bufsize];
01143 
01144    memset(buf, 0, sizeof(buf));
01145 
01146    /* If we have no peer, return immediately */
01147    if (ast_sockaddr_isnull(&s->them)) {
01148       return 0;
01149    }
01150 
01151    /* If there is no data length, return immediately */
01152    if (f->datalen == 0)
01153       return 0;
01154 
01155    if ((f->frametype != AST_FRAME_MODEM) ||
01156        (f->subclass.integer != AST_MODEM_T38)) {
01157       ast_log(LOG_WARNING, "UDPTL (%s): UDPTL can only send T.38 data.\n",
01158          LOG_TAG(s));
01159       return -1;
01160    }
01161 
01162    if (len > s->far_max_ifp) {
01163       ast_log(LOG_WARNING,
01164          "UDPTL (%s): UDPTL asked to send %u bytes of IFP when far end only prepared to accept %d bytes; data loss will occur."
01165          "You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n",
01166          LOG_TAG(s), len, s->far_max_ifp);
01167       len = s->far_max_ifp;
01168    }
01169 
01170    /* Save seq_no for debug output because udptl_build_packet increments it */
01171    seq = s->tx_seq_no & 0xFFFF;
01172 
01173    /* Cook up the UDPTL packet, with the relevant EC info. */
01174    len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, len);
01175 
01176    if ((signed int) len > 0 && !ast_sockaddr_isnull(&s->them)) {
01177       if (ast_sendto(s->fd, buf, len, 0, &s->them) < 0) {
01178          ast_log(LOG_NOTICE, "UDPTL (%s): Transmission error to %s: %s\n",
01179             LOG_TAG(s), ast_sockaddr_stringify(&s->them), strerror(errno));
01180       }
01181       if (udptl_debug_test_addr(&s->them)) {
01182          ast_verb(1, "UDPTL (%s): packet to %s (seq %u, len %u)\n",
01183             LOG_TAG(s), ast_sockaddr_stringify(&s->them), seq, len);
01184       }
01185    }
01186 
01187    return 0;
01188 }

static void calculate_far_max_ifp ( struct ast_udptl udptl  )  [static]

Definition at line 844 of file udptl.c.

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().

00845 {
00846    unsigned new_max = 0;
00847 
00848    if (udptl->far_max_datagram == -1) {
00849       ast_log(LOG_WARNING, "UDPTL (%s): Cannot calculate far_max_ifp before far_max_datagram has been set.\n",
00850          LOG_TAG(udptl));
00851       udptl->far_max_ifp = -1;
00852       return;
00853    }
00854 
00855    /* the goal here is to supply the local endpoint (application
00856     * or bridged channel) a maximum IFP value that will allow it
00857     * to effectively and efficiently transfer image data at its
00858     * selected bit rate, taking into account the selected error
00859     * correction mode, but without overrunning the far endpoint's
00860     * datagram buffer. this is complicated by the fact that some
00861     * far endpoints send us bogus (small) max datagram values,
00862     * which would result in either buffer overrun or no error
00863     * correction. we try to accomodate those, but if the supplied
00864     * value is too small to do so, we'll emit warning messages and
00865     * the user will have to use configuration options to override
00866     * the max datagram value supplied by the far endpoint.
00867     */
00868    switch (udptl->error_correction_scheme) {
00869    case UDPTL_ERROR_CORRECTION_NONE:
00870       /* need room for sequence number, length indicator, redundancy
00871        * indicator and following length indicator
00872        */
00873       new_max = udptl->far_max_datagram - 5;
00874       break;
00875    case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00876       /* for this case, we'd like to send as many error correction entries
00877        * as possible (up to the number we're configured for), but we'll settle
00878        * for sending fewer if the configured number would cause the
00879        * calculated max IFP to be too small for effective operation
00880        *
00881        * need room for sequence number, length indicators and the
00882        * configured number of redundant packets
00883        *
00884        * note: we purposely don't allow error_correction_entries to drop to
00885        * zero in this loop; we'd rather send smaller IFPs (and thus reduce
00886        * the image data transfer rate) than sacrifice redundancy completely
00887        */
00888       for (;;) {
00889          new_max = (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1);
00890 
00891          if ((new_max < 80) && (udptl->error_correction_entries > 1)) {
00892             /* the max ifp is not large enough, subtract an
00893              * error correction entry and calculate again
00894              * */
00895             --udptl->error_correction_entries;
00896          } else {
00897             break;
00898          }
00899       }
00900       break;
00901    case UDPTL_ERROR_CORRECTION_FEC:
00902       /* need room for sequence number, length indicators and a
00903        * a single IFP of the maximum size expected
00904        */
00905       new_max = (udptl->far_max_datagram - 10) / 2;
00906       break;
00907    }
00908    /* subtract 5% of space for insurance */
00909    udptl->far_max_ifp = new_max * 0.95;
00910 }

static void calculate_local_max_datagram ( struct ast_udptl udptl  )  [static]

Definition at line 803 of file udptl.c.

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().

00804 {
00805    unsigned int new_max = 0;
00806 
00807    if (udptl->local_max_ifp == -1) {
00808       ast_log(LOG_WARNING, "UDPTL (%s): Cannot calculate local_max_datagram before local_max_ifp has been set.\n",
00809          LOG_TAG(udptl));
00810       udptl->local_max_datagram = -1;
00811       return;
00812    }
00813 
00814    /* calculate the amount of space required to receive an IFP
00815     * of the maximum size supported by the application/endpoint
00816     * that we are delivering them to (local endpoint), and add
00817     * the amount of space required to support the selected
00818     * error correction mode
00819     */
00820    switch (udptl->error_correction_scheme) {
00821    case UDPTL_ERROR_CORRECTION_NONE:
00822       /* need room for sequence number, length indicator, redundancy
00823        * indicator and following length indicator
00824        */
00825       new_max = 5 + udptl->local_max_ifp;
00826       break;
00827    case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00828       /* need room for sequence number, length indicators, plus
00829        * room for up to 3 redundancy packets
00830        */
00831       new_max = 5 + udptl->local_max_ifp + 2 + (3 * udptl->local_max_ifp);
00832       break;
00833    case UDPTL_ERROR_CORRECTION_FEC:
00834       /* need room for sequence number, length indicators and a
00835        * a single IFP of the maximum size expected
00836        */
00837       new_max = 5 + udptl->local_max_ifp + 4 + udptl->local_max_ifp;
00838       break;
00839    }
00840    /* add 5% extra space for insurance, but no larger than LOCAL_FAX_MAX_DATAGRAM */
00841    udptl->local_max_datagram = MIN(new_max * 1.05, LOCAL_FAX_MAX_DATAGRAM);
00842 }

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]

Definition at line 275 of file udptl.c.

References ast_debug.

Referenced by decode_open_type(), and udptl_rx_packet().

00276 {
00277    if (*len >= limit)
00278       return -1;
00279    if ((buf[*len] & 0x80) == 0) {
00280       *pvalue = buf[*len];
00281       (*len)++;
00282       return 0;
00283    }
00284    if ((buf[*len] & 0x40) == 0) {
00285       if (*len == limit - 1)
00286          return -1;
00287       *pvalue = (buf[*len] & 0x3F) << 8;
00288       (*len)++;
00289       *pvalue |= buf[*len];
00290       (*len)++;
00291       return 0;
00292    }
00293    *pvalue = (buf[*len] & 0x3F) << 14;
00294    (*len)++;
00295    /* We have a fragment.  Currently we don't process fragments. */
00296    ast_debug(1, "UDPTL packet with length greater than 16K received, decoding will fail\n");
00297    return 1;
00298 }

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

References decode_length().

Referenced by udptl_rx_packet().

00302 {
00303    unsigned int octet_cnt = 0;
00304 
00305    if (decode_length(buf, limit, len, &octet_cnt) != 0)
00306       return -1;
00307 
00308    if (octet_cnt > 0) {
00309       /* Make sure the buffer contains at least the number of bits requested */
00310       if ((*len + octet_cnt) > limit)
00311          return -1;
00312 
00313       *p_num_octets = octet_cnt;
00314       *p_object = &buf[*len];
00315       *len += octet_cnt;
00316    }
00317 
00318    return 0;
00319 }

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

Definition at line 322 of file udptl.c.

Referenced by encode_open_type(), and udptl_build_packet().

00323 {
00324    unsigned int multiplier;
00325 
00326    if (value < 0x80) {
00327       /* 1 octet */
00328       buf[*len] = value;
00329       (*len)++;
00330       return value;
00331    }
00332    if (value < 0x4000) {
00333       /* 2 octets */
00334       /* Set the first bit of the first octet */
00335       buf[*len] = ((0x8000 | value) >> 8) & 0xFF;
00336       (*len)++;
00337       buf[*len] = value & 0xFF;
00338       (*len)++;
00339       return value;
00340    }
00341    /* Fragmentation */
00342    multiplier = (value < 0x10000) ? (value >> 14) : 4;
00343    /* Set the first 2 bits of the octet */
00344    buf[*len] = 0xC0 | multiplier;
00345    (*len)++;
00346    return multiplier << 14;
00347 }

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

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

Referenced by udptl_build_packet().

00352 {
00353    unsigned int enclen;
00354    unsigned int octet_idx;
00355    uint8_t zero_byte;
00356 
00357    /* If open type is of zero length, add a single zero byte (10.1) */
00358    if (num_octets == 0) {
00359       zero_byte = 0;
00360       data = &zero_byte;
00361       num_octets = 1;
00362    }
00363    /* Encode the open type */
00364    for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
00365       enclen = encode_length(buf, len, num_octets);
00366       if (enclen + *len > buflen) {
00367          ast_log(LOG_ERROR, "UDPTL (%s): Buffer overflow detected (%u + %u > %u)\n",
00368             LOG_TAG(udptl), enclen, *len, buflen);
00369          return -1;
00370       }
00371       if (enclen > 0) {
00372          memcpy(&buf[*len], &data[octet_idx], enclen);
00373          *len += enclen;
00374       }
00375       if (enclen >= num_octets)
00376          break;
00377    }
00378 
00379    return 0;
00380 }

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

Definition at line 1235 of file udptl.c.

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

01236 {
01237    RAII_VAR(struct udptl_config *, cfg, NULL, ao2_cleanup);
01238 
01239    switch (cmd) {
01240    case CLI_INIT:
01241       e->command = "udptl show config";
01242       e->usage =
01243          "Usage: udptl show config\n"
01244          "       Display UDPTL configuration options\n";
01245       return NULL;
01246    case CLI_GENERATE:
01247       return NULL;
01248    }
01249 
01250    if (!(cfg = ao2_global_obj_ref(globals))) {
01251       return CLI_FAILURE;
01252    }
01253 
01254    ast_cli(a->fd, "UDPTL Global options\n");
01255    ast_cli(a->fd, "--------------------\n");
01256    ast_cli(a->fd, "udptlstart:      %u\n", cfg->general->start);
01257    ast_cli(a->fd, "udptlend:        %u\n", cfg->general->end);
01258    ast_cli(a->fd, "udptlfecentries: %u\n", cfg->general->fecentries);
01259    ast_cli(a->fd, "udptlfecspan:    %u\n", cfg->general->fecspan);
01260    ast_cli(a->fd, "use_even_ports:  %s\n", AST_CLI_YESNO(cfg->general->use_even_ports));
01261    ast_cli(a->fd, "udptlchecksums: %s\n", AST_CLI_YESNO(!cfg->general->nochecksums));
01262 
01263    return CLI_SUCCESS;
01264 }

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

Definition at line 1190 of file udptl.c.

References ast_cli_args::argc, ast_cli_args::argv, 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, ast_cli_args::fd, NULL, udptldebugaddr, and ast_cli_entry::usage.

01191 {
01192    switch (cmd) {
01193    case CLI_INIT:
01194       e->command = "udptl set debug {on|off|ip}";
01195       e->usage =
01196          "Usage: udptl set debug {on|off|ip host[:port]}\n"
01197          "       Enable or disable dumping of UDPTL packets.\n"
01198          "       If ip is specified, limit the dumped packets to those to and from\n"
01199          "       the specified 'host' with optional port.\n";
01200       return NULL;
01201    case CLI_GENERATE:
01202       return NULL;
01203    }
01204 
01205    if (a->argc < 4 || a->argc > 5)
01206       return CLI_SHOWUSAGE;
01207 
01208    if (a->argc == 4) {
01209       if (!strncasecmp(a->argv[3], "on", 2)) {
01210          udptldebug = 1;
01211          memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
01212          ast_cli(a->fd, "UDPTL Debugging Enabled\n");
01213       } else if (!strncasecmp(a->argv[3], "off", 3)) {
01214          udptldebug = 0;
01215          ast_cli(a->fd, "UDPTL Debugging Disabled\n");
01216       } else {
01217          return CLI_SHOWUSAGE;
01218       }
01219    } else {
01220       struct ast_sockaddr *addrs;
01221       if (strncasecmp(a->argv[3], "ip", 2))
01222          return CLI_SHOWUSAGE;
01223       if (!ast_sockaddr_resolve(&addrs, a->argv[4], 0, 0)) {
01224          return CLI_SHOWUSAGE;
01225       }
01226       ast_sockaddr_copy(&udptldebugaddr, &addrs[0]);
01227          ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_sockaddr_stringify(&udptldebugaddr));
01228       udptldebug = 1;
01229       ast_free(addrs);
01230    }
01231 
01232    return CLI_SUCCESS;
01233 }

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

Definition at line 1292 of file udptl.c.

References ast_log, LOG_WARNING, and ast_variable::name.

Referenced by ast_udptl_init().

01293 {
01294    if (!strcasecmp(var->name, "t38faxudpec")) {
01295       ast_log(LOG_WARNING, "t38faxudpec in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n");
01296    } else if (!strcasecmp(var->name, "t38faxmaxdatagram")) {
01297       ast_log(LOG_WARNING, "t38faxmaxdatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n");
01298    }
01299    return 0;
01300 }

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

References ast_debug, 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().

00606 {
00607    uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2] = { 0, };
00608    int i;
00609    int j;
00610    int seq;
00611    int entry;
00612    int entries;
00613    int span;
00614    int m;
00615    unsigned int len;
00616    int limit;
00617    int high_tide;
00618 
00619    seq = s->tx_seq_no & 0xFFFF;
00620 
00621    /* Map the sequence number to an entry in the circular buffer */
00622    entry = seq & UDPTL_BUF_MASK;
00623 
00624    /* We save the message in a circular buffer, for generating FEC or
00625       redundancy sets later on. */
00626    s->tx[entry].buf_len = ifp_len;
00627    memcpy(s->tx[entry].buf, ifp, ifp_len);
00628 
00629    /* Build the UDPTLPacket */
00630 
00631    len = 0;
00632    /* Encode the sequence number */
00633    buf[len++] = (seq >> 8) & 0xFF;
00634    buf[len++] = seq & 0xFF;
00635 
00636    /* Encode the primary IFP packet */
00637    if (encode_open_type(s, buf, buflen, &len, ifp, ifp_len) < 0)
00638       return -1;
00639 
00640    /* Encode the appropriate type of error recovery information */
00641    switch (s->error_correction_scheme)
00642    {
00643    case UDPTL_ERROR_CORRECTION_NONE:
00644       /* Encode the error recovery type */
00645       buf[len++] = 0x00;
00646       /* The number of entries will always be zero, so it is pointless allowing
00647          for the fragmented case here. */
00648       encode_length(buf, &len, 0);
00649       break;
00650    case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00651       /* Encode the error recovery type */
00652       buf[len++] = 0x00;
00653       if (s->tx_seq_no > s->error_correction_entries)
00654          entries = s->error_correction_entries;
00655       else
00656          entries = s->tx_seq_no;
00657       /* The number of entries will always be small, so it is pointless allowing
00658          for the fragmented case here. */
00659       encode_length(buf, &len, entries);
00660       /* Encode the elements */
00661       for (i = 0; i < entries; i++) {
00662          j = (entry - i - 1) & UDPTL_BUF_MASK;
00663          if (encode_open_type(s, buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) {
00664             ast_debug(1, "UDPTL (%s): Encoding failed at i=%d, j=%d\n",
00665                  LOG_TAG(s), i, j);
00666             return -1;
00667          }
00668       }
00669       break;
00670    case UDPTL_ERROR_CORRECTION_FEC:
00671       span = s->error_correction_span;
00672       entries = s->error_correction_entries;
00673       if (seq < s->error_correction_span*s->error_correction_entries) {
00674          /* In the initial stages, wind up the FEC smoothly */
00675          entries = seq/s->error_correction_span;
00676          if (seq < s->error_correction_span)
00677             span = 0;
00678       }
00679       /* Encode the error recovery type */
00680       buf[len++] = 0x80;
00681       /* Span is defined as an inconstrained integer, which it dumb. It will only
00682          ever be a small value. Treat it as such. */
00683       buf[len++] = 1;
00684       buf[len++] = span;
00685       /* The number of entries is defined as a length, but will only ever be a small
00686          value. Treat it as such. */
00687       buf[len++] = entries;
00688       for (m = 0; m < entries; m++) {
00689          /* Make an XOR'ed entry the maximum length */
00690          limit = (entry + m) & UDPTL_BUF_MASK;
00691          high_tide = 0;
00692          for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) {
00693             if (high_tide < s->tx[i].buf_len) {
00694                for (j = 0; j < high_tide; j++)
00695                   fec[j] ^= s->tx[i].buf[j];
00696                for ( ; j < s->tx[i].buf_len; j++)
00697                   fec[j] = s->tx[i].buf[j];
00698                high_tide = s->tx[i].buf_len;
00699             } else {
00700                for (j = 0; j < s->tx[i].buf_len; j++)
00701                   fec[j] ^= s->tx[i].buf[j];
00702             }
00703          }
00704          if (encode_open_type(s, buf, buflen, &len, fec, high_tide) < 0)
00705             return -1;
00706       }
00707       break;
00708    }
00709 
00710    s->tx_seq_no++;
00711    return len;
00712 }

static void udptl_config_destructor ( void *  obj  )  [static]

Definition at line 1271 of file udptl.c.

References ao2_cleanup, and udptl_config::general.

Referenced by udptl_snapshot_alloc().

01272 {
01273    struct udptl_config *cfg = obj;
01274    ao2_cleanup(cfg->general);
01275 }

static int udptl_debug_test_addr ( const struct ast_sockaddr addr  )  [inline, static]

Definition at line 259 of file udptl.c.

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

Referenced by ast_udptl_read(), and ast_udptl_write().

00260 {
00261    if (udptldebug == 0)
00262       return 0;
00263 
00264    if (ast_sockaddr_isnull(&udptldebugaddr)) {
00265       return 1;
00266    }
00267 
00268    if (ast_sockaddr_port(&udptldebugaddr)) {
00269       return !ast_sockaddr_cmp(&udptldebugaddr, addr);
00270    } else {
00271       return !ast_sockaddr_cmp_addr(&udptldebugaddr, addr);
00272    }
00273 }

static int udptl_pre_apply_config ( void   )  [static]

Definition at line 1319 of file udptl.c.

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.

01319                                         {
01320    struct udptl_config *cfg = aco_pending_config(&cfg_info);
01321 
01322    if (!cfg->general) {
01323       return -1;
01324    }
01325 
01326 #ifndef SO_NO_CHECK
01327    if (cfg->general->nochecksums) {
01328       ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n");
01329       cfg->general->nochecksums = 0;
01330    }
01331 #endif
01332 
01333    /* Fix up any global config values that we can handle before replacing the config */
01334    if (cfg->general->use_even_ports && (cfg->general->start & 1)) {
01335       ++cfg->general->start;
01336       ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %u\n", cfg->general->start);
01337    }
01338    if (cfg->general->start > cfg->general->end) {
01339       ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to %s-%s.\n", __stringify(DEFAULT_UDPTLSTART), __stringify(DEFAULT_UDPTLEND));
01340       cfg->general->start = DEFAULT_UDPTLSTART;
01341       cfg->general->end = DEFAULT_UDPTLEND;
01342    }
01343    if (cfg->general->use_even_ports && (cfg->general->end & 1)) {
01344       --cfg->general->end;
01345       ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_even_ports enabled. udptlend is now %u\n", cfg->general->end);
01346    }
01347 
01348    return 0;
01349 }

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

Definition at line 383 of file udptl.c.

References ARRAY_LEN, ast_debug, AST_FRAME_MODEM, AST_LIST_NEXT, AST_MODEM_T38, 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, 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().

00384 {
00385    int stat1;
00386    int stat2;
00387    int i;
00388    unsigned int ptr; /* an index that keeps track of how much of the UDPTL packet has been processed */
00389    int seq_no;
00390    const uint8_t *ifp = NULL;
00391    const uint8_t *data = NULL;
00392    unsigned int ifp_len = 0;
00393    int repaired[16];
00394    const uint8_t *bufs[ARRAY_LEN(s->f) - 1];
00395    unsigned int lengths[ARRAY_LEN(s->f) - 1];
00396    int span;
00397    int entries;
00398    int ifp_no;
00399 
00400    ptr = 0;
00401    ifp_no = 0;
00402    memset(&s->f[0], 0, sizeof(s->f[0]));
00403 
00404    /* Decode seq_number */
00405    if (ptr + 2 > len)
00406       return -1;
00407    seq_no = (buf[0] << 8) | buf[1];
00408    ptr += 2;
00409 
00410    /* Break out the primary packet */
00411    if ((stat1 = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0)
00412       return -1;
00413    /* Decode error_recovery */
00414    if (ptr + 1 > len)
00415       return -1;
00416    if ((buf[ptr++] & 0x80) == 0) {
00417       /* Secondary packet mode for error recovery */
00418       if (seq_no > s->rx_seq_no) {
00419          /* We received a later packet than we expected, so we need to check if we can fill in the gap from the
00420             secondary packets. */
00421          int total_count = 0;
00422          do {
00423             unsigned int count;
00424             if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
00425                return -1;
00426             for (i = 0; i < count && total_count + i < ARRAY_LEN(bufs); i++) {
00427                if ((stat1 = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) {
00428                   return -1;
00429                }
00430                /* valid secondaries can contain zero-length packets that should be ignored */
00431                if (!bufs[total_count + i] || !lengths[total_count + i]) {
00432                   /* drop the count of items to process and reuse the buffers that were just set */
00433                   i--;
00434                   count--;
00435                }
00436             }
00437             total_count += i;
00438          }
00439          while (stat2 > 0 && total_count < ARRAY_LEN(bufs));
00440          /* Step through in reverse order, so we go oldest to newest */
00441          for (i = total_count; i > 0; i--) {
00442             if (seq_no - i >= s->rx_seq_no) {
00443                /* This one wasn't seen before */
00444                /* Decode the secondary IFP packet */
00445                ast_debug(3, "Recovering lost packet via secondary %d, len %u\n", seq_no - i, lengths[i - 1]);
00446                s->f[ifp_no].frametype = AST_FRAME_MODEM;
00447                s->f[ifp_no].subclass.integer = AST_MODEM_T38;
00448 
00449                s->f[ifp_no].mallocd = 0;
00450                s->f[ifp_no].seqno = seq_no - i;
00451                s->f[ifp_no].datalen = lengths[i - 1];
00452                s->f[ifp_no].data.ptr = (uint8_t *) bufs[i - 1];
00453                s->f[ifp_no].offset = 0;
00454                s->f[ifp_no].src = "UDPTL";
00455                if (ifp_no > 0)
00456                   AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
00457                AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
00458                ifp_no++;
00459             }
00460          }
00461       }
00462    }
00463    else
00464    {
00465       int j;
00466       int l;
00467       int x;
00468       /* FEC mode for error recovery */
00469       /* Our buffers cannot tolerate overlength IFP packets in FEC mode */
00470       if (ifp_len > LOCAL_FAX_MAX_DATAGRAM)
00471          return -1;
00472       /* Update any missed slots in the buffer */
00473       for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) {
00474          x = s->rx_seq_no & UDPTL_BUF_MASK;
00475          s->rx[x].buf_len = -1;
00476          s->rx[x].fec_len[0] = 0;
00477          s->rx[x].fec_span = 0;
00478          s->rx[x].fec_entries = 0;
00479       }
00480 
00481       x = seq_no & UDPTL_BUF_MASK;
00482 
00483       memset(repaired, 0, sizeof(repaired));
00484 
00485       /* Save the new IFP packet */
00486       memcpy(s->rx[x].buf, ifp, ifp_len);
00487       s->rx[x].buf_len = ifp_len;
00488       repaired[x] = TRUE;
00489 
00490       /* Decode the FEC packets */
00491       /* The span is defined as an unconstrained integer, but will never be more
00492          than a small value. */
00493       if (ptr + 2 > len)
00494          return -1;
00495       if (buf[ptr++] != 1)
00496          return -1;
00497       span = buf[ptr++];
00498       s->rx[x].fec_span = span;
00499 
00500       /* The number of entries is defined as a length, but will only ever be a small
00501          value. Treat it as such. */
00502       if (ptr + 1 > len)
00503          return -1;
00504       entries = buf[ptr++];
00505       if (entries > MAX_FEC_ENTRIES) {
00506          return -1;
00507       }
00508       s->rx[x].fec_entries = entries;
00509 
00510       /* Decode the elements */
00511       for (i = 0; i < entries; i++) {
00512          if ((stat1 = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0)
00513             return -1;
00514          if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM)
00515             return -1;
00516 
00517          /* Save the new FEC data */
00518          memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]);
00519 #if 0
00520          fprintf(stderr, "FEC: ");
00521          for (j = 0; j < s->rx[x].fec_len[i]; j++)
00522             fprintf(stderr, "%02hhX ", data[j]);
00523          fprintf(stderr, "\n");
00524 #endif
00525       }
00526 
00527       /* See if we can reconstruct anything which is missing */
00528       /* TODO: this does not comprehensively hunt back and repair everything that is possible */
00529       for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) {
00530          int m;
00531          if (s->rx[l].fec_len[0] <= 0)
00532             continue;
00533          for (m = 0; m < s->rx[l].fec_entries; m++) {
00534             int k;
00535             int which;
00536             int limit = (l + m) & UDPTL_BUF_MASK;
00537 
00538             /* only repair buffers that actually exist! */
00539             if (seq_no <= (s->rx[l].fec_span * s->rx[l].fec_entries) - m) {
00540                continue;
00541             }
00542 
00543             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) {
00544                if (s->rx[k].buf_len <= 0)
00545                   which = (which == -1) ? k : -2;
00546             }
00547             if (which >= 0) {
00548                /* Repairable */
00549                for (j = 0; j < s->rx[l].fec_len[m]; j++) {
00550                   s->rx[which].buf[j] = s->rx[l].fec[m][j];
00551                   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)
00552                      s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
00553                }
00554                s->rx[which].buf_len = s->rx[l].fec_len[m];
00555                repaired[which] = TRUE;
00556             }
00557          }
00558       }
00559       /* Now play any new packets forwards in time */
00560       for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) {
00561          if (repaired[l]) {
00562             //fprintf(stderr, "Fixed packet %d, len %d\n", j, l);
00563             s->f[ifp_no].frametype = AST_FRAME_MODEM;
00564             s->f[ifp_no].subclass.integer = AST_MODEM_T38;
00565 
00566             s->f[ifp_no].mallocd = 0;
00567             s->f[ifp_no].seqno = j;
00568             s->f[ifp_no].datalen = s->rx[l].buf_len;
00569             s->f[ifp_no].data.ptr = s->rx[l].buf;
00570             s->f[ifp_no].offset = 0;
00571             s->f[ifp_no].src = "UDPTL";
00572             if (ifp_no > 0)
00573                AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
00574             AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
00575             ifp_no++;
00576          }
00577       }
00578    }
00579 
00580    /* If packets are received out of sequence, we may have already processed this packet from the error
00581       recovery information in a packet already received. */
00582    if (seq_no >= s->rx_seq_no) {
00583       /* Decode the primary IFP packet */
00584       s->f[ifp_no].frametype = AST_FRAME_MODEM;
00585       s->f[ifp_no].subclass.integer = AST_MODEM_T38;
00586 
00587       s->f[ifp_no].mallocd = 0;
00588       s->f[ifp_no].seqno = seq_no;
00589       s->f[ifp_no].datalen = ifp_len;
00590       s->f[ifp_no].data.ptr = (uint8_t *) ifp;
00591       s->f[ifp_no].offset = 0;
00592       s->f[ifp_no].src = "UDPTL";
00593       if (ifp_no > 0)
00594          AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
00595       AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
00596 
00597       ifp_no++;
00598    }
00599 
00600    s->rx_seq_no = seq_no + 1;
00601    return ifp_no;
00602 }

static void udptl_shutdown ( void   )  [static]

Definition at line 1361 of file udptl.c.

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

Referenced by ast_udptl_init().

01362 {
01363    ast_cli_unregister_multiple(cli_udptl, ARRAY_LEN(cli_udptl));
01364    ao2_t_global_obj_release(globals, "Unref udptl global container in shutdown");
01365    aco_info_destroy(&cfg_info);
01366 }

static void * udptl_snapshot_alloc ( void   )  [static]

Definition at line 1277 of file udptl.c.

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

Referenced by __ast_udptl_reload().

01278 {
01279    struct udptl_config *cfg;
01280 
01281    if (!(cfg = ao2_alloc(sizeof(*cfg), udptl_config_destructor))) {
01282       return NULL;
01283    }
01284    if (!(cfg->general = ao2_alloc(sizeof(*cfg->general), NULL))) {
01285       ao2_ref(cfg, -1);
01286       return NULL;
01287    }
01288 
01289    return cfg;
01290 }

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

Definition at line 734 of file udptl.c.

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

Referenced by ast_udptl_new_with_bindaddr().

00735 {
00736    struct ast_udptl *udptl = cbdata;
00737    struct ast_frame *f;
00738 
00739    if ((f = ast_udptl_read(udptl))) {
00740       if (udptl->callback)
00741          udptl->callback(udptl, f, udptl->data);
00742    }
00743    return 1;
00744 }


Variable Documentation

struct ast_cli_entry cli_udptl[] [static]

Initial value:

 {
   AST_CLI_DEFINE(handle_cli_udptl_set_debug, "Enable/Disable UDPTL debugging"),
   AST_CLI_DEFINE(handle_cli_show_config, "Show UDPTL config options"),
}

Definition at line 1266 of file udptl.c.

struct aco_type general_option [static]

Definition at line 239 of file udptl.c.

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

Definition at line 247 of file udptl.c.

struct aco_file udptl_conf [static]

Initial value:

 {
   .filename = "udptl.conf",
   .types = ACO_TYPES(&general_option),
}

Definition at line 249 of file udptl.c.

int udptldebug [static]

Are we debugging?

Definition at line 131 of file udptl.c.

struct ast_sockaddr udptldebugaddr [static]

Debug packets to/from this host

Definition at line 132 of file udptl.c.

Referenced by handle_cli_udptl_set_debug(), and udptl_debug_test_addr().


Generated on Thu Apr 16 06:34:35 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6