Mon Mar 19 11:30:56 2012

Asterisk developer's documentation


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.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"

Go to the source code of this file.

Data Structures

struct  ast_udptl
 Structure for an UDPTL session. More...
struct  protos
struct  udptl_fec_rx_buffer_t
struct  udptl_fec_tx_buffer_t

Defines

#define DEFAULT_FAX_MAX_DATAGRAM   400
#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)
int ast_udptl_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
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)
ast_udptlast_udptl_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *addr)
int ast_udptl_proto_register (struct ast_udptl_protocol *proto)
void ast_udptl_proto_unregister (struct ast_udptl_protocol *proto)
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)
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 struct ast_udptl_protocolget_proto (struct ast_channel *chan)
static char * handle_cli_udptl_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int udptl_build_packet (struct ast_udptl *s, uint8_t *buf, unsigned int buflen, uint8_t *ifp, unsigned int ifp_len)
static int udptl_debug_test_addr (const struct ast_sockaddr *addr)
static int udptl_rx_packet (struct ast_udptl *s, uint8_t *buf, unsigned int len)
static int udptlread (int *id, int fd, short events, void *cbdata)

Variables

static struct ast_cli_entry cli_udptl []
static int udptldebug
static struct ast_sockaddr udptldebugaddr
static int udptlend = 4599
static int udptlfecentries
static int udptlfecspan
static int udptlstart = 4500
static int use_even_ports


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

Referenced by ast_udptl_set_far_max_datagram(), and ast_udptl_write().

#define FALSE   0

Definition at line 74 of file udptl.c.

#define FAX_MAX_DATAGRAM_LIMIT   1400

Definition at line 95 of file udptl.c.

Referenced by ast_udptl_set_far_max_datagram().

#define LOCAL_FAX_MAX_DATAGRAM   1400

Definition at line 93 of file udptl.c.

Referenced by calculate_local_max_datagram(), and udptl_build_packet().

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

Definition at line 80 of file udptl.c.

Referenced by ast_udptl_read(), ast_udptl_write(), calculate_far_max_ifp(), calculate_local_max_datagram(), encode_open_type(), and udptl_build_packet().

#define MAX_FEC_ENTRIES   5

Definition at line 96 of file udptl.c.

Referenced by __ast_udptl_reload().

#define MAX_FEC_SPAN   5

Definition at line 97 of file udptl.c.

Referenced by __ast_udptl_reload().

#define TRUE   (!FALSE)

Definition at line 77 of file udptl.c.

#define UDPTL_BUF_MASK   15

Definition at line 99 of file udptl.c.

#define UDPTL_MTU   1200

Definition at line 71 of file udptl.c.


Function Documentation

static void __ast_udptl_reload ( int  reload  )  [static]

Definition at line 1307 of file udptl.c.

References ast_config_destroy(), ast_config_load2(), ast_false(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, LOG_NOTICE, LOG_WARNING, MAX_FEC_ENTRIES, and MAX_FEC_SPAN.

Referenced by ast_udptl_init(), and ast_udptl_reload().

01308 {
01309    struct ast_config *cfg;
01310    const char *s;
01311    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01312 
01313    cfg = ast_config_load2("udptl.conf", "udptl", config_flags);
01314    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
01315       return;
01316    }
01317 
01318    udptlstart = 4500;
01319    udptlend = 4999;
01320    udptlfecentries = 0;
01321    udptlfecspan = 0;
01322    use_even_ports = 0;
01323 
01324    if (cfg) {
01325       if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) {
01326          udptlstart = atoi(s);
01327          if (udptlstart < 1024) {
01328             ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n");
01329             udptlstart = 1024;
01330          }
01331          if (udptlstart > 65535) {
01332             ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n");
01333             udptlstart = 65535;
01334          }
01335       }
01336       if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) {
01337          udptlend = atoi(s);
01338          if (udptlend < 1024) {
01339             ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n");
01340             udptlend = 1024;
01341          }
01342          if (udptlend > 65535) {
01343             ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n");
01344             udptlend = 65535;
01345          }
01346       }
01347       if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) {
01348 #ifdef SO_NO_CHECK
01349          if (ast_false(s))
01350             nochecksums = 1;
01351          else
01352             nochecksums = 0;
01353 #else
01354          if (ast_false(s))
01355             ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n");
01356 #endif
01357       }
01358       if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) {
01359          ast_log(LOG_WARNING, "T38FaxUdpEC in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n");
01360       }
01361       if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) {
01362          ast_log(LOG_WARNING, "T38FaxMaxDatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n");
01363       }
01364       if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECEntries"))) {
01365          udptlfecentries = atoi(s);
01366          if (udptlfecentries < 1) {
01367             ast_log(LOG_WARNING, "Too small UDPTLFECEntries value.  Defaulting to 1.\n");
01368             udptlfecentries = 1;
01369          }
01370          if (udptlfecentries > MAX_FEC_ENTRIES) {
01371             ast_log(LOG_WARNING, "Too large UDPTLFECEntries value.  Defaulting to %d.\n", MAX_FEC_ENTRIES);
01372             udptlfecentries = MAX_FEC_ENTRIES;
01373          }
01374       }
01375       if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECSpan"))) {
01376          udptlfecspan = atoi(s);
01377          if (udptlfecspan < 1) {
01378             ast_log(LOG_WARNING, "Too small UDPTLFECSpan value.  Defaulting to 1.\n");
01379             udptlfecspan = 1;
01380          }
01381          if (udptlfecspan > MAX_FEC_SPAN) {
01382             ast_log(LOG_WARNING, "Too large UDPTLFECSpan value.  Defaulting to %d.\n", MAX_FEC_SPAN);
01383             udptlfecspan = MAX_FEC_SPAN;
01384          }
01385       }
01386       if ((s = ast_variable_retrieve(cfg, "general", "use_even_ports"))) {
01387          use_even_ports = ast_true(s);
01388       }
01389       ast_config_destroy(cfg);
01390    }
01391    if (udptlstart >= udptlend) {
01392       ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to 4500-4999.\n");
01393       udptlstart = 4500;
01394       udptlend = 4999;
01395    }
01396    if (use_even_ports && (udptlstart & 1)) {
01397       ++udptlstart;
01398       ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", udptlstart);
01399    }
01400    if (use_even_ports && (udptlend & 1)) {
01401       --udptlend;
01402       ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_event_ports enabled. udptlend is now %d\n", udptlend);
01403    }
01404    ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend);
01405 }

int ast_udptl_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc 
)

Definition at line 1132 of file udptl.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_debug, AST_FRAME_MODEM, ast_frfree, ast_log(), ast_read(), ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_udptl_get_peer(), ast_waitfor_n(), ast_write(), f, get_proto(), ast_udptl_protocol::get_udptl_info, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_udptl_protocol::set_udptl_peer, t1, and ast_channel::tech_pvt.

01133 {
01134    struct ast_frame *f;
01135    struct ast_channel *who;
01136    struct ast_channel *cs[3];
01137    struct ast_udptl *p0;
01138    struct ast_udptl *p1;
01139    struct ast_udptl_protocol *pr0;
01140    struct ast_udptl_protocol *pr1;
01141    struct ast_sockaddr ac0;
01142    struct ast_sockaddr ac1;
01143    struct ast_sockaddr t0;
01144    struct ast_sockaddr t1;
01145    void *pvt0;
01146    void *pvt1;
01147    int to;
01148    
01149    ast_channel_lock(c0);
01150    while (ast_channel_trylock(c1)) {
01151       ast_channel_unlock(c0);
01152       usleep(1);
01153       ast_channel_lock(c0);
01154    }
01155    pr0 = get_proto(c0);
01156    pr1 = get_proto(c1);
01157    if (!pr0) {
01158       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
01159       ast_channel_unlock(c0);
01160       ast_channel_unlock(c1);
01161       return -1;
01162    }
01163    if (!pr1) {
01164       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
01165       ast_channel_unlock(c0);
01166       ast_channel_unlock(c1);
01167       return -1;
01168    }
01169    pvt0 = c0->tech_pvt;
01170    pvt1 = c1->tech_pvt;
01171    p0 = pr0->get_udptl_info(c0);
01172    p1 = pr1->get_udptl_info(c1);
01173    if (!p0 || !p1) {
01174       /* Somebody doesn't want to play... */
01175       ast_channel_unlock(c0);
01176       ast_channel_unlock(c1);
01177       return -2;
01178    }
01179    if (pr0->set_udptl_peer(c0, p1)) {
01180       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
01181       memset(&ac1, 0, sizeof(ac1));
01182    } else {
01183       /* Store UDPTL peer */
01184       ast_udptl_get_peer(p1, &ac1);
01185    }
01186    if (pr1->set_udptl_peer(c1, p0)) {
01187       ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
01188       memset(&ac0, 0, sizeof(ac0));
01189    } else {
01190       /* Store UDPTL peer */
01191       ast_udptl_get_peer(p0, &ac0);
01192    }
01193    ast_channel_unlock(c0);
01194    ast_channel_unlock(c1);
01195    cs[0] = c0;
01196    cs[1] = c1;
01197    cs[2] = NULL;
01198    for (;;) {
01199       if ((c0->tech_pvt != pvt0) ||
01200          (c1->tech_pvt != pvt1) ||
01201          (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
01202             ast_debug(1, "Oooh, something is weird, backing out\n");
01203             /* Tell it to try again later */
01204             return -3;
01205       }
01206       to = -1;
01207       ast_udptl_get_peer(p1, &t1);
01208       ast_udptl_get_peer(p0, &t0);
01209       if (ast_sockaddr_cmp(&t1, &ac1)) {
01210          ast_debug(1, "Oooh, '%s' changed end address to %s\n", 
01211             c1->name, ast_sockaddr_stringify(&t1));
01212          ast_debug(1, "Oooh, '%s' was %s\n", 
01213             c1->name, ast_sockaddr_stringify(&ac1));
01214          ast_sockaddr_copy(&ac1, &t1);
01215       }
01216       if (ast_sockaddr_cmp(&t0, &ac0)) {
01217          ast_debug(1, "Oooh, '%s' changed end address to %s\n", 
01218             c0->name, ast_sockaddr_stringify(&t0));
01219          ast_debug(1, "Oooh, '%s' was %s\n", 
01220             c0->name, ast_sockaddr_stringify(&ac0));
01221          ast_sockaddr_copy(&ac0, &t0);
01222       }
01223       who = ast_waitfor_n(cs, 2, &to);
01224       if (!who) {
01225          ast_debug(1, "Ooh, empty read...\n");
01226          /* check for hangup / whentohangup */
01227          if (ast_check_hangup(c0) || ast_check_hangup(c1))
01228             break;
01229          continue;
01230       }
01231       f = ast_read(who);
01232       if (!f) {
01233          *fo = f;
01234          *rc = who;
01235          ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup");
01236          /* That's all we needed */
01237          return 0;
01238       } else {
01239          if (f->frametype == AST_FRAME_MODEM) {
01240             /* Forward T.38 frames if they happen upon us */
01241             if (who == c0) {
01242                ast_write(c1, f);
01243             } else if (who == c1) {
01244                ast_write(c0, f);
01245             }
01246          }
01247          ast_frfree(f);
01248       }
01249       /* Swap priority. Not that it's a big deal at this point */
01250       cs[2] = cs[0];
01251       cs[0] = cs[1];
01252       cs[1] = cs[2];
01253    }
01254    return -1;
01255 }

void ast_udptl_destroy ( struct ast_udptl udptl  ) 

Definition at line 1030 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().

01031 {
01032    if (udptl->ioid)
01033       ast_io_remove(udptl->io, udptl->ioid);
01034    if (udptl->fd > -1)
01035       close(udptl->fd);
01036    if (udptl->tag)
01037       ast_free(udptl->tag);
01038    ast_free(udptl);
01039 }

int ast_udptl_fd ( const struct ast_udptl udptl  ) 

Definition at line 629 of file udptl.c.

References ast_udptl::fd.

Referenced by __oh323_new(), initialize_udptl(), and sip_new().

00630 {
00631    return udptl->fd;
00632 }

enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme ( const struct ast_udptl udptl  ) 

Definition at line 827 of file udptl.c.

References ast_udptl::error_correction_scheme.

Referenced by add_sdp().

00828 {
00829    return udptl->error_correction_scheme;
00830 }

unsigned int ast_udptl_get_far_max_datagram ( const struct ast_udptl udptl  ) 

Definition at line 895 of file udptl.c.

References ast_udptl::far_max_datagram.

Referenced by process_sdp().

00896 {
00897    if (udptl->far_max_datagram < 0) {
00898       return 0;
00899    }
00900    return udptl->far_max_datagram;
00901 }

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

References calculate_far_max_ifp(), and ast_udptl::far_max_ifp.

Referenced by change_t38_state(), and interpret_t38_parameters().

00904 {
00905    if (udptl->far_max_ifp == -1) {
00906       calculate_far_max_ifp(udptl);
00907    }
00908 
00909    if (udptl->far_max_ifp < 0) {
00910       return 0;
00911    }
00912    return udptl->far_max_ifp;
00913 }

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

References calculate_local_max_datagram(), and ast_udptl::local_max_datagram.

Referenced by add_sdp().

00872 {
00873    if (udptl->local_max_datagram == -1) {
00874       calculate_local_max_datagram(udptl);
00875    }
00876 
00877    /* this function expects a unsigned value in return. */
00878    if (udptl->local_max_datagram < 0) {
00879       return 0;
00880    }
00881    return udptl->local_max_datagram;
00882 }

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

Definition at line 1015 of file udptl.c.

References ast_sockaddr_copy(), and ast_udptl::them.

Referenced by ast_udptl_bridge(), and sip_set_udptl_peer().

01016 {
01017    ast_sockaddr_copy(them, &udptl->them);
01018 }

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

Definition at line 1020 of file udptl.c.

References ast_sockaddr_copy(), and ast_udptl::us.

Referenced by add_sdp().

01021 {
01022    ast_sockaddr_copy(us, &udptl->us);
01023 }

void ast_udptl_init ( void   ) 

Definition at line 1413 of file udptl.c.

References __ast_udptl_reload(), ARRAY_LEN, ast_cli_register_multiple(), and cli_udptl.

Referenced by main().

01414 {
01415    ast_cli_register_multiple(cli_udptl, ARRAY_LEN(cli_udptl));
01416    __ast_udptl_reload(0);
01417 }

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

Definition at line 915 of file udptl.c.

References ast_bind(), ast_calloc, ast_free, ast_log(), ast_random(), ast_sockaddr_copy(), ast_sockaddr_is_ipv6(), ast_sockaddr_set_port, errno, ast_udptl::flags, and LOG_WARNING.

Referenced by initialize_udptl().

00916 {
00917    struct ast_udptl *udptl;
00918    int x;
00919    int startplace;
00920    int i;
00921    long int flags;
00922 
00923    if (!(udptl = ast_calloc(1, sizeof(*udptl))))
00924       return NULL;
00925 
00926    udptl->error_correction_span = udptlfecspan;
00927    udptl->error_correction_entries = udptlfecentries;
00928    
00929    udptl->far_max_datagram = -1;
00930    udptl->far_max_ifp = -1;
00931    udptl->local_max_ifp = -1;
00932    udptl->local_max_datagram = -1;
00933 
00934    for (i = 0; i <= UDPTL_BUF_MASK; i++) {
00935       udptl->rx[i].buf_len = -1;
00936       udptl->tx[i].buf_len = -1;
00937    }
00938 
00939    if ((udptl->fd = socket(ast_sockaddr_is_ipv6(addr) ?
00940                AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) {
00941       ast_free(udptl);
00942       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00943       return NULL;
00944    }
00945    flags = fcntl(udptl->fd, F_GETFL);
00946    fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK);
00947 #ifdef SO_NO_CHECK
00948    if (nochecksums)
00949       setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
00950 #endif
00951    /* Find us a place */
00952    x = (udptlstart == udptlend) ? udptlstart : (ast_random() % (udptlend - udptlstart)) + udptlstart;
00953    if (use_even_ports && (x & 1)) {
00954       ++x;
00955    }
00956    startplace = x;
00957    for (;;) {
00958       ast_sockaddr_copy(&udptl->us, addr);
00959       ast_sockaddr_set_port(&udptl->us, x);
00960       if (ast_bind(udptl->fd, &udptl->us) == 0) {
00961          break;
00962       }
00963       if (errno != EADDRINUSE) {
00964          ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
00965          close(udptl->fd);
00966          ast_free(udptl);
00967          return NULL;
00968       }
00969       if (use_even_ports) {
00970          x += 2;
00971       } else {
00972          ++x;
00973       }
00974       if (x > udptlend)
00975          x = udptlstart;
00976       if (x == startplace) {
00977          ast_log(LOG_WARNING, "No UDPTL ports remaining\n");
00978          close(udptl->fd);
00979          ast_free(udptl);
00980          return NULL;
00981       }
00982    }
00983    if (io && sched && callbackmode) {
00984       /* Operate this one in a callback mode */
00985       udptl->sched = sched;
00986       udptl->io = io;
00987       udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl);
00988    }
00989    return udptl;
00990 }

int ast_udptl_proto_register ( struct ast_udptl_protocol proto  ) 

Definition at line 1101 of file udptl.c.

References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_udptl_protocol::list, LOG_WARNING, and ast_udptl_protocol::type.

Referenced by load_module().

01102 {
01103    struct ast_udptl_protocol *cur;
01104 
01105    AST_RWLIST_WRLOCK(&protos);
01106    AST_RWLIST_TRAVERSE(&protos, cur, list) {
01107       if (cur->type == proto->type) {
01108          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01109          AST_RWLIST_UNLOCK(&protos);
01110          return -1;
01111       }
01112    }
01113    AST_RWLIST_INSERT_TAIL(&protos, proto, list);
01114    AST_RWLIST_UNLOCK(&protos);
01115    return 0;
01116 }

void ast_udptl_proto_unregister ( struct ast_udptl_protocol proto  ) 

Definition at line 1094 of file udptl.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by unload_module().

01095 {
01096    AST_RWLIST_WRLOCK(&protos);
01097    AST_RWLIST_REMOVE(&protos, proto, list);
01098    AST_RWLIST_UNLOCK(&protos);
01099 }

struct ast_frame* ast_udptl_read ( struct ast_udptl udptl  ) 

Definition at line 661 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, 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 sip_rtp_read(), skinny_rtp_read(), and udptlread().

00662 {
00663    int res;
00664    struct ast_sockaddr addr;
00665    uint8_t *buf;
00666 
00667    buf = udptl->rawdata + AST_FRIENDLY_OFFSET;
00668 
00669    /* Cache where the header will go */
00670    res = ast_recvfrom(udptl->fd,
00671          buf,
00672          sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
00673          0,
00674          &addr);
00675    if (res < 0) {
00676       if (errno != EAGAIN)
00677          ast_log(LOG_WARNING, "UDPTL (%s): read error: %s\n",
00678             LOG_TAG(udptl), strerror(errno));
00679       ast_assert(errno != EBADF);
00680       return &ast_null_frame;
00681    }
00682 
00683    /* Ignore if the other side hasn't been given an address yet. */
00684    if (ast_sockaddr_isnull(&udptl->them)) {
00685       return &ast_null_frame;
00686    }
00687 
00688    if (udptl->nat) {
00689       /* Send to whoever sent to us */
00690       if (ast_sockaddr_cmp(&udptl->them, &addr)) {
00691          ast_sockaddr_copy(&udptl->them, &addr);
00692          ast_debug(1, "UDPTL (%s): NAT, Using address %s\n",
00693               LOG_TAG(udptl), ast_sockaddr_stringify(&udptl->them));
00694       }
00695    }
00696 
00697    if (udptl_debug_test_addr(&addr)) {
00698       int seq_no;
00699 
00700       /* Decode sequence number just for verbose message. */
00701       if (res < 2) {
00702          /* Short packet. */
00703          seq_no = -1;
00704       } else {
00705          seq_no = (buf[0] << 8) | buf[1];
00706       }
00707 
00708       ast_verb(1, "UDPTL (%s): packet from %s (seq %d, len %d)\n",
00709          LOG_TAG(udptl), ast_sockaddr_stringify(&addr), seq_no, res);
00710    }
00711    if (udptl_rx_packet(udptl, buf, res) < 1) {
00712       return &ast_null_frame;
00713    }
00714 
00715    return &udptl->f[0];
00716 }

int ast_udptl_reload ( void   ) 

Version:
1.6.1 return changed to int

Definition at line 1407 of file udptl.c.

References __ast_udptl_reload().

01408 {
01409    __ast_udptl_reload(1);
01410    return 0;
01411 }

void ast_udptl_set_callback ( struct ast_udptl udptl,
ast_udptl_callback  callback 
)

Definition at line 639 of file udptl.c.

References ast_udptl::callback.

00640 {
00641    udptl->callback = callback;
00642 }

void ast_udptl_set_data ( struct ast_udptl udptl,
void *  data 
)

Definition at line 634 of file udptl.c.

References ast_udptl::data.

00635 {
00636    udptl->data = data;
00637 }

void ast_udptl_set_error_correction_scheme ( struct ast_udptl udptl,
enum ast_t38_ec_modes  ec 
)

Definition at line 832 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(), and set_t38_capabilities().

00833 {
00834    udptl->error_correction_scheme = ec;
00835    switch (ec) {
00836    case UDPTL_ERROR_CORRECTION_FEC:
00837       udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC;
00838       if (udptl->error_correction_entries == 0) {
00839          udptl->error_correction_entries = 3;
00840       }
00841       if (udptl->error_correction_span == 0) {
00842          udptl->error_correction_span = 3;
00843       }
00844       break;
00845    case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00846       udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY;
00847       if (udptl->error_correction_entries == 0) {
00848          udptl->error_correction_entries = 3;
00849       }
00850       break;
00851    default:
00852       /* nothing to do */
00853       break;
00854    };
00855    /* reset calculated values so they'll be computed again */
00856    udptl->local_max_datagram = -1;
00857    udptl->far_max_ifp = -1;
00858 }

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

00885 {
00886    if (!max_datagram || (max_datagram > FAX_MAX_DATAGRAM_LIMIT)) {
00887       udptl->far_max_datagram = DEFAULT_FAX_MAX_DATAGRAM;
00888    } else {
00889       udptl->far_max_datagram = max_datagram;
00890    }
00891    /* reset calculated values so they'll be computed again */
00892    udptl->far_max_ifp = -1;
00893 }

void ast_udptl_set_local_max_ifp ( struct ast_udptl udptl,
unsigned int  max_ifp 
)

Definition at line 860 of file udptl.c.

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

Referenced by interpret_t38_parameters().

00861 {
00862    /* make sure max_ifp is a positive value since a cast will take place when
00863     * when setting local_max_ifp */
00864    if ((signed int) max_ifp > 0) {
00865       udptl->local_max_ifp = max_ifp;
00866       /* reset calculated values so they'll be computed again */
00867       udptl->local_max_datagram = -1;
00868    }
00869 }

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

Definition at line 1010 of file udptl.c.

References ast_sockaddr_copy(), and ast_udptl::them.

Referenced by process_sdp().

01011 {
01012    ast_sockaddr_copy(&udptl->them, them);
01013 }

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

References ast_free, ast_vasprintf, and ast_udptl::tag.

Referenced by change_t38_state().

00993 {
00994    va_list ap;
00995 
00996    ast_free(udptl->tag);
00997    udptl->tag = NULL;
00998    va_start(ap, format);
00999    if (ast_vasprintf(&udptl->tag, format, ap) == -1) {
01000       udptl->tag = NULL;
01001    }
01002    va_end(ap);
01003 }

void ast_udptl_setnat ( struct ast_udptl udptl,
int  nat 
)

Definition at line 644 of file udptl.c.

References ast_udptl::nat.

Referenced by do_setnat(), and initialize_udptl().

00645 {
00646    udptl->nat = nat;
00647 }

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

Definition at line 1005 of file udptl.c.

References ast_netsock_set_qos(), and ast_udptl::fd.

Referenced by initialize_udptl().

01006 {
01007    return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL");
01008 }

void ast_udptl_stop ( struct ast_udptl udptl  ) 

Definition at line 1025 of file udptl.c.

References ast_sockaddr_setnull(), and ast_udptl::them.

Referenced by process_sdp(), and stop_media_flows().

01026 {
01027    ast_sockaddr_setnull(&udptl->them);
01028 }

int ast_udptl_write ( struct ast_udptl s,
struct ast_frame f 
)

Definition at line 1041 of file udptl.c.

References AST_FRAME_MODEM, ast_log(), AST_MODEM_T38, ast_sendto(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verb, DEFAULT_FAX_MAX_DATAGRAM, errno, f, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, ast_udptl::fd, len(), LOG_NOTICE, LOG_TAG, LOG_WARNING, seq, ast_udptl::them, ast_udptl::tx_seq_no, udptl_build_packet(), and udptl_debug_test_addr().

Referenced by sip_write().

01042 {
01043    unsigned int seq;
01044    unsigned int len = f->datalen;
01045    int res;
01046    /* if no max datagram size is provided, use default value */
01047    const int bufsize = (s->far_max_datagram > 0) ? s->far_max_datagram : DEFAULT_FAX_MAX_DATAGRAM;
01048    uint8_t buf[bufsize];
01049 
01050    memset(buf, 0, sizeof(buf));
01051 
01052    /* If we have no peer, return immediately */
01053    if (ast_sockaddr_isnull(&s->them)) {
01054       return 0;
01055    }
01056 
01057    /* If there is no data length, return immediately */
01058    if (f->datalen == 0)
01059       return 0;
01060    
01061    if ((f->frametype != AST_FRAME_MODEM) ||
01062        (f->subclass.codec != AST_MODEM_T38)) {
01063       ast_log(LOG_WARNING, "UDPTL (%s): UDPTL can only send T.38 data.\n",
01064          LOG_TAG(s));
01065       return -1;
01066    }
01067 
01068    if (len > s->far_max_ifp) {
01069       ast_log(LOG_WARNING,
01070          "UDPTL (%s): UDPTL asked to send %d bytes of IFP when far end only prepared to accept %d bytes; data loss will occur."
01071          "You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n",
01072          LOG_TAG(s), len, s->far_max_ifp);
01073       len = s->far_max_ifp;
01074    }
01075 
01076    /* Save seq_no for debug output because udptl_build_packet increments it */
01077    seq = s->tx_seq_no & 0xFFFF;
01078 
01079    /* Cook up the UDPTL packet, with the relevant EC info. */
01080    len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, len);
01081 
01082    if ((signed int) len > 0 && !ast_sockaddr_isnull(&s->them)) {
01083       if ((res = ast_sendto(s->fd, buf, len, 0, &s->them)) < 0)
01084          ast_log(LOG_NOTICE, "UDPTL (%s): Transmission error to %s: %s\n",
01085             LOG_TAG(s), ast_sockaddr_stringify(&s->them), strerror(errno));
01086       if (udptl_debug_test_addr(&s->them))
01087          ast_verb(1, "UDPTL (%s): packet to %s (seq %d, len %d)\n",
01088             LOG_TAG(s), ast_sockaddr_stringify(&s->them), seq, len);
01089    }
01090       
01091    return 0;
01092 }

static void calculate_far_max_ifp ( struct ast_udptl udptl  )  [static]

Definition at line 759 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().

00760 {
00761    unsigned new_max = 0;
00762 
00763    if (udptl->far_max_datagram == -1) {
00764       ast_log(LOG_WARNING, "UDPTL (%s): Cannot calculate far_max_ifp before far_max_datagram has been set.\n",
00765          LOG_TAG(udptl));
00766       udptl->far_max_ifp = -1;
00767       return;
00768    }
00769 
00770    /* the goal here is to supply the local endpoint (application
00771     * or bridged channel) a maximum IFP value that will allow it
00772     * to effectively and efficiently transfer image data at its
00773     * selected bit rate, taking into account the selected error
00774     * correction mode, but without overrunning the far endpoint's
00775     * datagram buffer. this is complicated by the fact that some
00776     * far endpoints send us bogus (small) max datagram values,
00777     * which would result in either buffer overrun or no error
00778     * correction. we try to accomodate those, but if the supplied
00779     * value is too small to do so, we'll emit warning messages and
00780     * the user will have to use configuration options to override
00781     * the max datagram value supplied by the far endpoint.
00782     */
00783    switch (udptl->error_correction_scheme) {
00784    case UDPTL_ERROR_CORRECTION_NONE:
00785       /* need room for sequence number, length indicator, redundancy
00786        * indicator and following length indicator
00787        */
00788       new_max = udptl->far_max_datagram - 5;
00789       break;
00790    case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00791       /* for this case, we'd like to send as many error correction entries
00792        * as possible (up to the number we're configured for), but we'll settle
00793        * for sending fewer if the configured number would cause the
00794        * calculated max IFP to be too small for effective operation
00795        *
00796        * need room for sequence number, length indicators and the
00797        * configured number of redundant packets
00798        *
00799        * note: we purposely don't allow error_correction_entries to drop to
00800        * zero in this loop; we'd rather send smaller IFPs (and thus reduce
00801        * the image data transfer rate) than sacrifice redundancy completely
00802        */
00803       for (;;) {
00804          new_max = (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1);
00805 
00806          if ((new_max < 80) && (udptl->error_correction_entries > 1)) {
00807             /* the max ifp is not large enough, subtract an
00808              * error correction entry and calculate again
00809              * */
00810             --udptl->error_correction_entries;
00811          } else {
00812             break;
00813          }
00814       }
00815       break;
00816    case UDPTL_ERROR_CORRECTION_FEC:
00817       /* need room for sequence number, length indicators and a
00818        * a single IFP of the maximum size expected
00819        */
00820       new_max = (udptl->far_max_datagram - 10) / 2;
00821       break;
00822    }
00823    /* subtract 5% of space for insurance */
00824    udptl->far_max_ifp = new_max * 0.95;
00825 }

static void calculate_local_max_datagram ( struct ast_udptl udptl  )  [static]

Definition at line 718 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().

00719 {
00720    unsigned int new_max = 0;
00721 
00722    if (udptl->local_max_ifp == -1) {
00723       ast_log(LOG_WARNING, "UDPTL (%s): Cannot calculate local_max_datagram before local_max_ifp has been set.\n",
00724          LOG_TAG(udptl));
00725       udptl->local_max_datagram = -1;
00726       return;
00727    }
00728 
00729    /* calculate the amount of space required to receive an IFP
00730     * of the maximum size supported by the application/endpoint
00731     * that we are delivering them to (local endpoint), and add
00732     * the amount of space required to support the selected
00733     * error correction mode
00734     */
00735    switch (udptl->error_correction_scheme) {
00736    case UDPTL_ERROR_CORRECTION_NONE:
00737       /* need room for sequence number, length indicator, redundancy
00738        * indicator and following length indicator
00739        */
00740       new_max = 5 + udptl->local_max_ifp;
00741       break;
00742    case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00743       /* need room for sequence number, length indicators, plus
00744        * room for up to 3 redundancy packets
00745        */
00746       new_max = 5 + udptl->local_max_ifp + 2 + (3 * udptl->local_max_ifp);
00747       break;
00748    case UDPTL_ERROR_CORRECTION_FEC:
00749       /* need room for sequence number, length indicators and a
00750        * a single IFP of the maximum size expected
00751        */
00752       new_max = 5 + udptl->local_max_ifp + 4 + udptl->local_max_ifp;
00753       break;
00754    }
00755    /* add 5% extra space for insurance, but no larger than LOCAL_FAX_MAX_DATAGRAM */
00756    udptl->local_max_datagram = MIN(new_max * 1.05, LOCAL_FAX_MAX_DATAGRAM);
00757 }

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

Definition at line 198 of file udptl.c.

References ast_debug.

Referenced by decode_open_type(), and udptl_rx_packet().

00199 {
00200    if (*len >= limit)
00201       return -1;
00202    if ((buf[*len] & 0x80) == 0) {
00203       *pvalue = buf[*len];
00204       (*len)++;
00205       return 0;
00206    }
00207    if ((buf[*len] & 0x40) == 0) {
00208       if (*len == limit - 1)
00209          return -1;
00210       *pvalue = (buf[*len] & 0x3F) << 8;
00211       (*len)++;
00212       *pvalue |= buf[*len];
00213       (*len)++;
00214       return 0;
00215    }
00216    *pvalue = (buf[*len] & 0x3F) << 14;
00217    (*len)++;
00218    /* We have a fragment.  Currently we don't process fragments. */
00219    ast_debug(1, "UDPTL packet with length greater than 16K received, decoding will fail\n");
00220    return 1;
00221 }

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

References decode_length().

Referenced by udptl_rx_packet().

00225 {
00226    unsigned int octet_cnt = 0;
00227 
00228    if (decode_length(buf, limit, len, &octet_cnt) != 0)
00229       return -1;
00230 
00231    if (octet_cnt > 0) {
00232       /* Make sure the buffer contains at least the number of bits requested */
00233       if ((*len + octet_cnt) > limit)
00234          return -1;
00235 
00236       *p_num_octets = octet_cnt;
00237       *p_object = &buf[*len];
00238       *len += octet_cnt;
00239    }
00240 
00241    return 0;
00242 }

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

Definition at line 245 of file udptl.c.

Referenced by encode_open_type(), and udptl_build_packet().

00246 {
00247    unsigned int multiplier;
00248 
00249    if (value < 0x80) {
00250       /* 1 octet */
00251       buf[*len] = value;
00252       (*len)++;
00253       return value;
00254    }
00255    if (value < 0x4000) {
00256       /* 2 octets */
00257       /* Set the first bit of the first octet */
00258       buf[*len] = ((0x8000 | value) >> 8) & 0xFF;
00259       (*len)++;
00260       buf[*len] = value & 0xFF;
00261       (*len)++;
00262       return value;
00263    }
00264    /* Fragmentation */
00265    multiplier = (value < 0x10000) ? (value >> 14) : 4;
00266    /* Set the first 2 bits of the octet */
00267    buf[*len] = 0xC0 | multiplier;
00268    (*len)++;
00269    return multiplier << 14;
00270 }

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

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

Referenced by udptl_build_packet().

00275 {
00276    unsigned int enclen;
00277    unsigned int octet_idx;
00278    uint8_t zero_byte;
00279 
00280    /* If open type is of zero length, add a single zero byte (10.1) */
00281    if (num_octets == 0) {
00282       zero_byte = 0;
00283       data = &zero_byte;
00284       num_octets = 1;
00285    }
00286    /* Encode the open type */
00287    for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
00288       if ((enclen = encode_length(buf, len, num_octets)) < 0)
00289          return -1;
00290       if (enclen + *len > buflen) {
00291          ast_log(LOG_ERROR, "UDPTL (%s): Buffer overflow detected (%d + %d > %d)\n",
00292             LOG_TAG(udptl), enclen, *len, buflen);
00293          return -1;
00294       }
00295       if (enclen > 0) {
00296          memcpy(&buf[*len], &data[octet_idx], enclen);
00297          *len += enclen;
00298       }
00299       if (enclen >= num_octets)
00300          break;
00301    }
00302 
00303    return 0;
00304 }

static struct ast_udptl_protocol* get_proto ( struct ast_channel chan  )  [static]

Definition at line 1118 of file udptl.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_udptl_protocol::list, ast_channel::tech, ast_channel_tech::type, and ast_udptl_protocol::type.

Referenced by ast_udptl_bridge().

01119 {
01120    struct ast_udptl_protocol *cur = NULL;
01121 
01122    AST_RWLIST_RDLOCK(&protos);
01123    AST_RWLIST_TRAVERSE(&protos, cur, list) {
01124       if (cur->type == chan->tech->type)
01125          break;
01126    }
01127    AST_RWLIST_UNLOCK(&protos);
01128 
01129    return cur;
01130 }

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

Definition at line 1257 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, udptldebugaddr, and ast_cli_entry::usage.

01258 {
01259    switch (cmd) {
01260    case CLI_INIT:
01261       e->command = "udptl set debug {on|off|ip}";
01262       e->usage = 
01263          "Usage: udptl set debug {on|off|ip host[:port]}\n"
01264          "       Enable or disable dumping of UDPTL packets.\n"
01265          "       If ip is specified, limit the dumped packets to those to and from\n"
01266          "       the specified 'host' with optional port.\n";
01267       return NULL;
01268    case CLI_GENERATE:
01269       return NULL;
01270    }
01271 
01272    if (a->argc < 4 || a->argc > 5)
01273       return CLI_SHOWUSAGE;
01274 
01275    if (a->argc == 4) {
01276       if (!strncasecmp(a->argv[3], "on", 2)) {
01277          udptldebug = 1;
01278          memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
01279          ast_cli(a->fd, "UDPTL Debugging Enabled\n");
01280       } else if (!strncasecmp(a->argv[3], "off", 3)) {
01281          udptldebug = 0;
01282          ast_cli(a->fd, "UDPTL Debugging Disabled\n");
01283       } else {
01284          return CLI_SHOWUSAGE;
01285       }
01286    } else {
01287       struct ast_sockaddr *addrs;
01288       if (strncasecmp(a->argv[3], "ip", 2))
01289          return CLI_SHOWUSAGE;
01290       if (!ast_sockaddr_resolve(&addrs, a->argv[4], 0, 0)) {
01291          return CLI_SHOWUSAGE;
01292       }
01293       ast_sockaddr_copy(&udptldebugaddr, &addrs[0]);
01294          ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_sockaddr_stringify(&udptldebugaddr));
01295       udptldebug = 1;
01296       ast_free(addrs);
01297    }
01298 
01299    return CLI_SUCCESS;
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 518 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_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.

Referenced by ast_udptl_write().

00519 {
00520    uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2];
00521    int i;
00522    int j;
00523    int seq;
00524    int entry;
00525    int entries;
00526    int span;
00527    int m;
00528    unsigned int len;
00529    int limit;
00530    int high_tide;
00531 
00532    seq = s->tx_seq_no & 0xFFFF;
00533 
00534    /* Map the sequence number to an entry in the circular buffer */
00535    entry = seq & UDPTL_BUF_MASK;
00536 
00537    /* We save the message in a circular buffer, for generating FEC or
00538       redundancy sets later on. */
00539    s->tx[entry].buf_len = ifp_len;
00540    memcpy(s->tx[entry].buf, ifp, ifp_len);
00541    
00542    /* Build the UDPTLPacket */
00543 
00544    len = 0;
00545    /* Encode the sequence number */
00546    buf[len++] = (seq >> 8) & 0xFF;
00547    buf[len++] = seq & 0xFF;
00548 
00549    /* Encode the primary IFP packet */
00550    if (encode_open_type(s, buf, buflen, &len, ifp, ifp_len) < 0)
00551       return -1;
00552 
00553    /* Encode the appropriate type of error recovery information */
00554    switch (s->error_correction_scheme)
00555    {
00556    case UDPTL_ERROR_CORRECTION_NONE:
00557       /* Encode the error recovery type */
00558       buf[len++] = 0x00;
00559       /* The number of entries will always be zero, so it is pointless allowing
00560          for the fragmented case here. */
00561       if (encode_length(buf, &len, 0) < 0)
00562          return -1;
00563       break;
00564    case UDPTL_ERROR_CORRECTION_REDUNDANCY:
00565       /* Encode the error recovery type */
00566       buf[len++] = 0x00;
00567       if (s->tx_seq_no > s->error_correction_entries)
00568          entries = s->error_correction_entries;
00569       else
00570          entries = s->tx_seq_no;
00571       /* The number of entries will always be small, so it is pointless allowing
00572          for the fragmented case here. */
00573       if (encode_length(buf, &len, entries) < 0)
00574          return -1;
00575       /* Encode the elements */
00576       for (i = 0; i < entries; i++) {
00577          j = (entry - i - 1) & UDPTL_BUF_MASK;
00578          if (encode_open_type(s, buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) {
00579             ast_debug(1, "UDPTL (%s): Encoding failed at i=%d, j=%d\n",
00580                  LOG_TAG(s), i, j);
00581             return -1;
00582          }
00583       }
00584       break;
00585    case UDPTL_ERROR_CORRECTION_FEC:
00586       span = s->error_correction_span;
00587       entries = s->error_correction_entries;
00588       if (seq < s->error_correction_span*s->error_correction_entries) {
00589          /* In the initial stages, wind up the FEC smoothly */
00590          entries = seq/s->error_correction_span;
00591          if (seq < s->error_correction_span)
00592             span = 0;
00593       }
00594       /* Encode the error recovery type */
00595       buf[len++] = 0x80;
00596       /* Span is defined as an inconstrained integer, which it dumb. It will only
00597          ever be a small value. Treat it as such. */
00598       buf[len++] = 1;
00599       buf[len++] = span;
00600       /* The number of entries is defined as a length, but will only ever be a small
00601          value. Treat it as such. */
00602       buf[len++] = entries;
00603       for (m = 0; m < entries; m++) {
00604          /* Make an XOR'ed entry the maximum length */
00605          limit = (entry + m) & UDPTL_BUF_MASK;
00606          high_tide = 0;
00607          for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) {
00608             if (high_tide < s->tx[i].buf_len) {
00609                for (j = 0; j < high_tide; j++)
00610                   fec[j] ^= s->tx[i].buf[j];
00611                for ( ; j < s->tx[i].buf_len; j++)
00612                   fec[j] = s->tx[i].buf[j];
00613                high_tide = s->tx[i].buf_len;
00614             } else {
00615                for (j = 0; j < s->tx[i].buf_len; j++)
00616                   fec[j] ^= s->tx[i].buf[j];
00617             }
00618          }
00619          if (encode_open_type(s, buf, buflen, &len, fec, high_tide) < 0)
00620             return -1;
00621       }
00622       break;
00623    }
00624 
00625    s->tx_seq_no++;
00626    return len;
00627 }

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

Definition at line 182 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().

00183 {
00184    if (udptldebug == 0)
00185       return 0;
00186 
00187    if (ast_sockaddr_isnull(&udptldebugaddr)) {
00188       return 1;
00189    }
00190 
00191    if (ast_sockaddr_port(&udptldebugaddr)) {
00192       return !ast_sockaddr_cmp(&udptldebugaddr, addr);
00193    } else {
00194       return !ast_sockaddr_cmp_addr(&udptldebugaddr, addr);
00195    }
00196 }

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

Definition at line 307 of file udptl.c.

References ARRAY_LEN, AST_FRAME_MODEM, AST_LIST_NEXT, AST_MODEM_T38, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, decode_length(), decode_open_type(), ast_udptl::f, ast_frame::frametype, ast_frame::mallocd, ast_frame::offset, ast_frame::ptr, ast_udptl::rx_seq_no, ast_frame::seqno, ast_frame::src, and ast_frame::subclass.

Referenced by ast_udptl_read().

00308 {
00309    int stat1;
00310    int stat2;
00311    int i;
00312    int j;
00313    int k;
00314    int l;
00315    int m;
00316    int x;
00317    int limit;
00318    int which;
00319    unsigned int ptr;
00320    unsigned int count;
00321    int total_count;
00322    int seq_no;
00323    const uint8_t *ifp = NULL;
00324    const uint8_t *data = NULL;
00325    unsigned int ifp_len = 0;
00326    int repaired[16];
00327    const uint8_t *bufs[ARRAY_LEN(s->f) - 1];
00328    unsigned int lengths[ARRAY_LEN(s->f) - 1];
00329    int span;
00330    int entries;
00331    int ifp_no;
00332 
00333    ptr = 0;
00334    ifp_no = 0;
00335    memset(&s->f[0], 0, sizeof(s->f[0]));
00336 
00337    /* Decode seq_number */
00338    if (ptr + 2 > len)
00339       return -1;
00340    seq_no = (buf[0] << 8) | buf[1];
00341    ptr += 2;
00342 
00343    /* Break out the primary packet */
00344    if ((stat1 = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0)
00345       return -1;
00346    /* Decode error_recovery */
00347    if (ptr + 1 > len)
00348       return -1;
00349    if ((buf[ptr++] & 0x80) == 0) {
00350       /* Secondary packet mode for error recovery */
00351       if (seq_no > s->rx_seq_no) {
00352          /* We received a later packet than we expected, so we need to check if we can fill in the gap from the
00353             secondary packets. */
00354          total_count = 0;
00355          do {
00356             if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
00357                return -1;
00358             for (i = 0; i < count && total_count + i < ARRAY_LEN(bufs); i++) {
00359                if ((stat1 = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0)
00360                   return -1;
00361             }
00362             total_count += i;
00363          }
00364          while (stat2 > 0 && total_count < ARRAY_LEN(bufs));
00365          /* Step through in reverse order, so we go oldest to newest */
00366          for (i = total_count; i > 0; i--) {
00367             if (seq_no - i >= s->rx_seq_no) {
00368                /* This one wasn't seen before */
00369                /* Decode the secondary IFP packet */
00370                //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]);
00371                s->f[ifp_no].frametype = AST_FRAME_MODEM;
00372                s->f[ifp_no].subclass.codec = AST_MODEM_T38;
00373 
00374                s->f[ifp_no].mallocd = 0;
00375                s->f[ifp_no].seqno = seq_no - i;
00376                s->f[ifp_no].datalen = lengths[i - 1];
00377                s->f[ifp_no].data.ptr = (uint8_t *) bufs[i - 1];
00378                s->f[ifp_no].offset = 0;
00379                s->f[ifp_no].src = "UDPTL";
00380                if (ifp_no > 0)
00381                   AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
00382                AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
00383                ifp_no++;
00384             }
00385          }
00386       }
00387    }
00388    else
00389    {
00390       /* FEC mode for error recovery */
00391       /* Our buffers cannot tolerate overlength IFP packets in FEC mode */
00392       if (ifp_len > LOCAL_FAX_MAX_DATAGRAM)
00393          return -1;
00394       /* Update any missed slots in the buffer */
00395       for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) {
00396          x = s->rx_seq_no & UDPTL_BUF_MASK;
00397          s->rx[x].buf_len = -1;
00398          s->rx[x].fec_len[0] = 0;
00399          s->rx[x].fec_span = 0;
00400          s->rx[x].fec_entries = 0;
00401       }
00402 
00403       x = seq_no & UDPTL_BUF_MASK;
00404 
00405       memset(repaired, 0, sizeof(repaired));
00406 
00407       /* Save the new IFP packet */
00408       memcpy(s->rx[x].buf, ifp, ifp_len);
00409       s->rx[x].buf_len = ifp_len;
00410       repaired[x] = TRUE;
00411 
00412       /* Decode the FEC packets */
00413       /* The span is defined as an unconstrained integer, but will never be more
00414          than a small value. */
00415       if (ptr + 2 > len)
00416          return -1;
00417       if (buf[ptr++] != 1)
00418          return -1;
00419       span = buf[ptr++];
00420       s->rx[x].fec_span = span;
00421 
00422       /* The number of entries is defined as a length, but will only ever be a small
00423          value. Treat it as such. */
00424       if (ptr + 1 > len)
00425          return -1;
00426       entries = buf[ptr++];
00427       if (entries > MAX_FEC_ENTRIES) {
00428          return -1;
00429       }
00430       s->rx[x].fec_entries = entries;
00431 
00432       /* Decode the elements */
00433       for (i = 0; i < entries; i++) {
00434          if ((stat1 = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0)
00435             return -1;
00436          if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM)
00437             return -1;
00438 
00439          /* Save the new FEC data */
00440          memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]);
00441 #if 0
00442          fprintf(stderr, "FEC: ");
00443          for (j = 0; j < s->rx[x].fec_len[i]; j++)
00444             fprintf(stderr, "%02X ", data[j]);
00445          fprintf(stderr, "\n");
00446 #endif
00447       }
00448 
00449       /* See if we can reconstruct anything which is missing */
00450       /* TODO: this does not comprehensively hunt back and repair everything that is possible */
00451       for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) {
00452          if (s->rx[l].fec_len[0] <= 0)
00453             continue;
00454          for (m = 0; m < s->rx[l].fec_entries; m++) {
00455             limit = (l + m) & UDPTL_BUF_MASK;
00456             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) {
00457                if (s->rx[k].buf_len <= 0)
00458                   which = (which == -1) ? k : -2;
00459             }
00460             if (which >= 0) {
00461                /* Repairable */
00462                for (j = 0; j < s->rx[l].fec_len[m]; j++) {
00463                   s->rx[which].buf[j] = s->rx[l].fec[m][j];
00464                   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)
00465                      s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
00466                }
00467                s->rx[which].buf_len = s->rx[l].fec_len[m];
00468                repaired[which] = TRUE;
00469             }
00470          }
00471       }
00472       /* Now play any new packets forwards in time */
00473       for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) {
00474          if (repaired[l]) {
00475             //fprintf(stderr, "Fixed packet %d, len %d\n", j, l);
00476             s->f[ifp_no].frametype = AST_FRAME_MODEM;
00477             s->f[ifp_no].subclass.codec = AST_MODEM_T38;
00478          
00479             s->f[ifp_no].mallocd = 0;
00480             s->f[ifp_no].seqno = j;
00481             s->f[ifp_no].datalen = s->rx[l].buf_len;
00482             s->f[ifp_no].data.ptr = s->rx[l].buf;
00483             s->f[ifp_no].offset = 0;
00484             s->f[ifp_no].src = "UDPTL";
00485             if (ifp_no > 0)
00486                AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
00487             AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
00488             ifp_no++;
00489          }
00490       }
00491    }
00492 
00493    /* If packets are received out of sequence, we may have already processed this packet from the error
00494       recovery information in a packet already received. */
00495    if (seq_no >= s->rx_seq_no) {
00496       /* Decode the primary IFP packet */
00497       s->f[ifp_no].frametype = AST_FRAME_MODEM;
00498       s->f[ifp_no].subclass.codec = AST_MODEM_T38;
00499       
00500       s->f[ifp_no].mallocd = 0;
00501       s->f[ifp_no].seqno = seq_no;
00502       s->f[ifp_no].datalen = ifp_len;
00503       s->f[ifp_no].data.ptr = (uint8_t *) ifp;
00504       s->f[ifp_no].offset = 0;
00505       s->f[ifp_no].src = "UDPTL";
00506       if (ifp_no > 0)
00507          AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
00508       AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
00509 
00510       ifp_no++;
00511    }
00512 
00513    s->rx_seq_no = seq_no + 1;
00514    return ifp_no;
00515 }

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

Definition at line 649 of file udptl.c.

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

00650 {
00651    struct ast_udptl *udptl = cbdata;
00652    struct ast_frame *f;
00653 
00654    if ((f = ast_udptl_read(udptl))) {
00655       if (udptl->callback)
00656          udptl->callback(udptl, f, udptl->data);
00657    }
00658    return 1;
00659 }


Variable Documentation

struct ast_cli_entry cli_udptl[] [static]

Initial value:

 {
   { .handler =  handle_cli_udptl_set_debug , .summary =  "Enable/Disable UDPTL debugging" ,__VA_ARGS__ }
}

Definition at line 1303 of file udptl.c.

Referenced by ast_udptl_init().

int udptldebug [static]

Are we debugging?

Definition at line 84 of file udptl.c.

struct ast_sockaddr udptldebugaddr [static]

Debug packets to/from this host

Definition at line 85 of file udptl.c.

Referenced by handle_cli_udptl_set_debug(), and udptl_debug_test_addr().

int udptlend = 4599 [static]

Definition at line 83 of file udptl.c.

int udptlfecentries [static]

Definition at line 89 of file udptl.c.

int udptlfecspan [static]

Definition at line 90 of file udptl.c.

int udptlstart = 4500 [static]

Definition at line 82 of file udptl.c.

int use_even_ports [static]

Definition at line 91 of file udptl.c.


Generated on Mon Mar 19 11:30:56 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7