Tue Mar 2 17:34:38 2010

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"
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_fec_rx_buffer_t
struct  udptl_fec_tx_buffer_t

Defines

#define DEFAULT_FAX_MAX_DATAGRAM   400
#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 UDPTL_BUF_MASK   15
#define UDPTL_MTU   1200

Functions

static void __ast_udptl_reload (int reload)
static AST_RWLIST_HEAD_STATIC (protos, ast_udptl_protocol)
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 sockaddr_in *them)
void ast_udptl_get_us (const struct ast_udptl *udptl, struct sockaddr_in *us)
void ast_udptl_init (void)
struct ast_udptlast_udptl_new (struct sched_context *sched, struct io_context *io, int callbackmode)
struct ast_udptlast_udptl_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr addr)
int ast_udptl_proto_register (struct ast_udptl_protocol *proto)
void ast_udptl_proto_unregister (struct ast_udptl_protocol *proto)
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 sockaddr_in *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_debug_deprecated (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 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 sockaddr_in *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_handle_udptl_debug_deprecated = AST_CLI_DEFINE(handle_cli_udptl_debug_deprecated, "Enable/Disable UDPTL debugging")
static struct ast_cli_entry cli_udptl []
static int udptldebug
static struct sockaddr_in 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 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(), udptl_build_packet(), and udptl_rx_packet().

#define LOG_TAG (  )     S_OR(u->tag, "no tag")
#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 UDPTL_BUF_MASK   15

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


Function Documentation

static void __ast_udptl_reload ( int  reload  )  [static]

Definition at line 1396 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_STATUS_FILEUNCHANGED, LOG_NOTICE, LOG_WARNING, MAX_FEC_ENTRIES, MAX_FEC_SPAN, and s.

Referenced by ast_udptl_init(), and ast_udptl_reload().

01397 {
01398    struct ast_config *cfg;
01399    const char *s;
01400    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01401 
01402    if ((cfg = ast_config_load2("udptl.conf", "udptl", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
01403       return;
01404 
01405    udptlstart = 4500;
01406    udptlend = 4999;
01407    udptlfecentries = 0;
01408    udptlfecspan = 0;
01409    use_even_ports = 0;
01410 
01411    if (cfg) {
01412       if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) {
01413          udptlstart = atoi(s);
01414          if (udptlstart < 1024) {
01415             ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n");
01416             udptlstart = 1024;
01417          }
01418          if (udptlstart > 65535) {
01419             ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n");
01420             udptlstart = 65535;
01421          }
01422       }
01423       if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) {
01424          udptlend = atoi(s);
01425          if (udptlend < 1024) {
01426             ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n");
01427             udptlend = 1024;
01428          }
01429          if (udptlend > 65535) {
01430             ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n");
01431             udptlend = 65535;
01432          }
01433       }
01434       if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) {
01435 #ifdef SO_NO_CHECK
01436          if (ast_false(s))
01437             nochecksums = 1;
01438          else
01439             nochecksums = 0;
01440 #else
01441          if (ast_false(s))
01442             ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n");
01443 #endif
01444       }
01445       if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) {
01446          ast_log(LOG_WARNING, "T38FaxUdpEC in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n");
01447       }
01448       if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) {
01449          ast_log(LOG_WARNING, "T38FaxMaxDatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n");
01450       }
01451       if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECEntries"))) {
01452          udptlfecentries = atoi(s);
01453          if (udptlfecentries < 1) {
01454             ast_log(LOG_WARNING, "Too small UDPTLFECEntries value.  Defaulting to 1.\n");
01455             udptlfecentries = 1;
01456          }
01457          if (udptlfecentries > MAX_FEC_ENTRIES) {
01458             ast_log(LOG_WARNING, "Too large UDPTLFECEntries value.  Defaulting to %d.\n", MAX_FEC_ENTRIES);
01459             udptlfecentries = MAX_FEC_ENTRIES;
01460          }
01461       }
01462       if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECSpan"))) {
01463          udptlfecspan = atoi(s);
01464          if (udptlfecspan < 1) {
01465             ast_log(LOG_WARNING, "Too small UDPTLFECSpan value.  Defaulting to 1.\n");
01466             udptlfecspan = 1;
01467          }
01468          if (udptlfecspan > MAX_FEC_SPAN) {
01469             ast_log(LOG_WARNING, "Too large UDPTLFECSpan value.  Defaulting to %d.\n", MAX_FEC_SPAN);
01470             udptlfecspan = MAX_FEC_SPAN;
01471          }
01472       }
01473       if ((s = ast_variable_retrieve(cfg, "general", "use_even_ports"))) {
01474          use_even_ports = ast_true(s);
01475       }
01476       ast_config_destroy(cfg);
01477    }
01478    if (udptlstart >= udptlend) {
01479       ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to 4500-4999.\n");
01480       udptlstart = 4500;
01481       udptlend = 4999;
01482    }
01483    if (use_even_ports && (udptlstart & 1)) {
01484       ++udptlstart;
01485       ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", udptlstart);
01486    }
01487    if (use_even_ports && (udptlend & 1)) {
01488       --udptlend;
01489       ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_event_ports enabled. udptlend is now %d\n", udptlend);
01490    }
01491    ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend);
01492 }

static AST_RWLIST_HEAD_STATIC ( protos  ,
ast_udptl_protocol   
) [static]
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 1143 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_inet_ntoa(), ast_log(), ast_read(), ast_udptl_get_peer(), ast_waitfor_n(), ast_write(), f, ast_frame::frametype, get_proto(), ast_udptl_protocol::get_udptl_info, inaddrcmp(), LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_udptl_protocol::set_udptl_peer, and ast_channel::tech_pvt.

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

void ast_udptl_destroy ( struct ast_udptl udptl  ) 

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

01043 {
01044    if (udptl->ioid)
01045       ast_io_remove(udptl->io, udptl->ioid);
01046    if (udptl->fd > -1)
01047       close(udptl->fd);
01048    if (udptl->tag)
01049       ast_free(udptl->tag);
01050    ast_free(udptl);
01051 }

int ast_udptl_fd ( const struct ast_udptl udptl  ) 

Definition at line 640 of file udptl.c.

References ast_udptl::fd.

Referenced by __oh323_new(), and sip_new().

00641 {
00642    return udptl->fd;
00643 }

enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme ( const struct ast_udptl udptl  ) 

Definition at line 824 of file udptl.c.

References ast_udptl::error_correction_scheme.

Referenced by add_sdp().

00825 {
00826    return udptl->error_correction_scheme;
00827 }

unsigned int ast_udptl_get_far_max_datagram ( const struct ast_udptl udptl  ) 

Definition at line 892 of file udptl.c.

References ast_udptl::far_max_datagram.

Referenced by process_sdp().

00893 {
00894    if (udptl->far_max_datagram < 0) {
00895       return 0;
00896    }
00897    return udptl->far_max_datagram;
00898 }

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

References calculate_far_max_ifp(), and ast_udptl::far_max_ifp.

Referenced by change_t38_state().

00901 {
00902    if (udptl->far_max_ifp == -1) {
00903       calculate_far_max_ifp(udptl);
00904    }
00905 
00906    if (udptl->far_max_ifp < 0) {
00907       return 0;
00908    }
00909    return udptl->far_max_ifp;
00910 }

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

References calculate_local_max_datagram(), and ast_udptl::local_max_datagram.

Referenced by add_sdp().

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

void ast_udptl_get_peer ( const struct ast_udptl udptl,
struct sockaddr_in *  them 
)

Definition at line 1023 of file udptl.c.

References ast_udptl::them.

Referenced by ast_udptl_bridge(), and sip_set_udptl_peer().

01024 {
01025    memset(them, 0, sizeof(*them));
01026    them->sin_family = AF_INET;
01027    them->sin_port = udptl->them.sin_port;
01028    them->sin_addr = udptl->them.sin_addr;
01029 }

void ast_udptl_get_us ( const struct ast_udptl udptl,
struct sockaddr_in *  us 
)

Definition at line 1031 of file udptl.c.

References ast_udptl::us.

Referenced by add_sdp().

01032 {
01033    memcpy(us, &udptl->us, sizeof(udptl->us));
01034 }

void ast_udptl_init ( void   ) 

Definition at line 1500 of file udptl.c.

References __ast_udptl_reload(), and ast_cli_register_multiple().

Referenced by main().

01501 {
01502    ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry));
01503    __ast_udptl_reload(0);
01504 }

struct ast_udptl* ast_udptl_new ( struct sched_context sched,
struct io_context io,
int  callbackmode 
) [read]

Definition at line 990 of file udptl.c.

References ast_udptl_new_with_bindaddr().

00991 {
00992    struct in_addr ia;
00993    memset(&ia, 0, sizeof(ia));
00994    return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia);
00995 }

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

Definition at line 912 of file udptl.c.

References ast_calloc, ast_free, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), 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, ast_udptl::io, ast_udptl::ioid, ast_udptl::local_max_datagram, ast_udptl::local_max_ifp, LOG_WARNING, ast_udptl::rx, ast_udptl::sched, ast_udptl::them, ast_udptl::tx, UDPTL_BUF_MASK, udptlread(), and ast_udptl::us.

Referenced by ast_udptl_new(), create_addr_from_peer(), handle_request_invite(), and sip_alloc().

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

int ast_udptl_proto_register ( struct ast_udptl_protocol proto  ) 

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

01113 {
01114    struct ast_udptl_protocol *cur;
01115 
01116    AST_RWLIST_WRLOCK(&protos);
01117    AST_RWLIST_TRAVERSE(&protos, cur, list) {
01118       if (cur->type == proto->type) {
01119          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01120          AST_RWLIST_UNLOCK(&protos);
01121          return -1;
01122       }
01123    }
01124    AST_RWLIST_INSERT_TAIL(&protos, proto, list);
01125    AST_RWLIST_UNLOCK(&protos);
01126    return 0;
01127 }

void ast_udptl_proto_unregister ( struct ast_udptl_protocol proto  ) 

Definition at line 1105 of file udptl.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by unload_module().

01106 {
01107    AST_RWLIST_WRLOCK(&protos);
01108    AST_RWLIST_REMOVE(&protos, proto, list);
01109    AST_RWLIST_UNLOCK(&protos);
01110 }

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

Definition at line 672 of file udptl.c.

References ast_assert, ast_debug, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verb, errno, ast_udptl::f, ast_udptl::fd, len(), 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().

00673 {
00674    int res;
00675    struct sockaddr_in sin;
00676    socklen_t len;
00677    uint16_t seqno = 0;
00678    uint16_t *udptlheader;
00679 
00680    len = sizeof(sin);
00681    
00682    /* Cache where the header will go */
00683    res = recvfrom(udptl->fd,
00684          udptl->rawdata + AST_FRIENDLY_OFFSET,
00685          sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
00686          0,
00687          (struct sockaddr *) &sin,
00688          &len);
00689    udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET);
00690    if (res < 0) {
00691       if (errno != EAGAIN)
00692          ast_log(LOG_WARNING, "(%s): UDPTL read error: %s\n",
00693             LOG_TAG(udptl), strerror(errno));
00694       ast_assert(errno != EBADF);
00695       return &ast_null_frame;
00696    }
00697 
00698    /* Ignore if the other side hasn't been given an address yet. */
00699    if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port)
00700       return &ast_null_frame;
00701 
00702    if (udptl->nat) {
00703       /* Send to whoever sent to us */
00704       if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00705          (udptl->them.sin_port != sin.sin_port)) {
00706          memcpy(&udptl->them, &sin, sizeof(udptl->them));
00707          ast_debug(1, "UDPTL NAT (%s): Using address %s:%d\n",
00708               LOG_TAG(udptl), ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
00709       }
00710    }
00711 
00712    if (udptl_debug_test_addr(&sin)) {
00713       ast_verb(1, "UDPTL (%s): packet from %s:%d (type %d, seq %d, len %d)\n",
00714           LOG_TAG(udptl), ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res);
00715    }
00716    if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1)
00717       return &ast_null_frame;
00718 
00719    return &udptl->f[0];
00720 }

int ast_udptl_reload ( void   ) 
Version:
1.6.1 return changed to int

Definition at line 1494 of file udptl.c.

References __ast_udptl_reload().

01495 {
01496    __ast_udptl_reload(1);
01497    return 0;
01498 }

void ast_udptl_set_callback ( struct ast_udptl udptl,
ast_udptl_callback  callback 
)

Definition at line 650 of file udptl.c.

References ast_udptl::callback.

00651 {
00652    udptl->callback = callback;
00653 }

void ast_udptl_set_data ( struct ast_udptl udptl,
void *  data 
)

Definition at line 645 of file udptl.c.

References ast_udptl::data.

00646 {
00647    udptl->data = data;
00648 }

void ast_udptl_set_error_correction_scheme ( struct ast_udptl udptl,
enum ast_t38_ec_modes  ec 
)

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

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

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

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

void ast_udptl_set_local_max_ifp ( struct ast_udptl udptl,
unsigned int  max_ifp 
)

Definition at line 857 of file udptl.c.

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

Referenced by interpret_t38_parameters().

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

void ast_udptl_set_peer ( struct ast_udptl udptl,
const struct sockaddr_in *  them 
)

Definition at line 1017 of file udptl.c.

References ast_udptl::them.

Referenced by process_sdp().

01018 {
01019    udptl->them.sin_port = them->sin_port;
01020    udptl->them.sin_addr = them->sin_addr;
01021 }

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

References ast_free, ast_vasprintf, and ast_udptl::tag.

Referenced by change_t38_state().

00998 {
00999    va_list ap;
01000 
01001    if (udptl->tag) {
01002       ast_free(udptl->tag);
01003       udptl->tag = NULL;
01004    }
01005    va_start(ap, format);
01006    if (ast_vasprintf(&udptl->tag, format, ap) == -1) {
01007       udptl->tag = NULL;
01008    }
01009    va_end(ap);
01010 }

void ast_udptl_setnat ( struct ast_udptl udptl,
int  nat 
)

Definition at line 655 of file udptl.c.

References ast_udptl::nat.

Referenced by do_setnat().

00656 {
00657    udptl->nat = nat;
00658 }

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

Definition at line 1012 of file udptl.c.

References ast_netsock_set_qos(), and ast_udptl::fd.

Referenced by sip_alloc().

01013 {
01014    return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL");
01015 }

void ast_udptl_stop ( struct ast_udptl udptl  ) 

Definition at line 1036 of file udptl.c.

References ast_udptl::them.

Referenced by process_sdp(), and stop_media_flows().

01037 {
01038    memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr));
01039    memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port));
01040 }

int ast_udptl_write ( struct ast_udptl s,
struct ast_frame f 
)

Definition at line 1053 of file udptl.c.

References AST_FRAME_MODEM, ast_inet_ntoa(), ast_log(), AST_MODEM_T38, 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, 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 sip_write().

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

static void calculate_far_max_ifp ( struct ast_udptl udptl  )  [static]

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

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

static void calculate_local_max_datagram ( struct ast_udptl udptl  )  [static]

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

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

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

Definition at line 200 of file udptl.c.

Referenced by decode_open_type(), and udptl_rx_packet().

00201 {
00202    if (*len >= limit)
00203       return -1;
00204    if ((buf[*len] & 0x80) == 0) {
00205       *pvalue = buf[*len];
00206       (*len)++;
00207       return 0;
00208    }
00209    if ((buf[*len] & 0x40) == 0) {
00210       if (*len == limit - 1)
00211          return -1;
00212       *pvalue = (buf[*len] & 0x3F) << 8;
00213       (*len)++;
00214       *pvalue |= buf[*len];
00215       (*len)++;
00216       return 0;
00217    }
00218    *pvalue = (buf[*len] & 0x3F) << 14;
00219    (*len)++;
00220    /* Indicate we have a fragment */
00221    return 1;
00222 }

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

References decode_length().

Referenced by udptl_rx_packet().

00226 {
00227    unsigned int octet_cnt;
00228    unsigned int octet_idx;
00229    unsigned int length;
00230    unsigned int i;
00231    const uint8_t **pbuf;
00232 
00233    for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) {
00234       octet_cnt = 0;
00235       if ((length = decode_length(buf, limit, len, &octet_cnt)) < 0)
00236          return -1;
00237       if (octet_cnt > 0) {
00238          *p_num_octets += octet_cnt;
00239 
00240          pbuf = &p_object[octet_idx];
00241          i = 0;
00242          /* Make sure the buffer contains at least the number of bits requested */
00243          if ((*len + octet_cnt) > limit)
00244             return -1;
00245 
00246          *pbuf = &buf[*len];
00247          *len += octet_cnt;
00248       }
00249       if (length == 0)
00250          break;
00251    }
00252    return 0;
00253 }

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

Definition at line 256 of file udptl.c.

Referenced by encode_open_type(), and udptl_build_packet().

00257 {
00258    unsigned int multiplier;
00259 
00260    if (value < 0x80) {
00261       /* 1 octet */
00262       buf[*len] = value;
00263       (*len)++;
00264       return value;
00265    }
00266    if (value < 0x4000) {
00267       /* 2 octets */
00268       /* Set the first bit of the first octet */
00269       buf[*len] = ((0x8000 | value) >> 8) & 0xFF;
00270       (*len)++;
00271       buf[*len] = value & 0xFF;
00272       (*len)++;
00273       return value;
00274    }
00275    /* Fragmentation */
00276    multiplier = (value < 0x10000) ? (value >> 14) : 4;
00277    /* Set the first 2 bits of the octet */
00278    buf[*len] = 0xC0 | multiplier;
00279    (*len)++;
00280    return multiplier << 14;
00281 }

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

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

Referenced by udptl_build_packet().

00286 {
00287    unsigned int enclen;
00288    unsigned int octet_idx;
00289    uint8_t zero_byte;
00290 
00291    /* If open type is of zero length, add a single zero byte (10.1) */
00292    if (num_octets == 0) {
00293       zero_byte = 0;
00294       data = &zero_byte;
00295       num_octets = 1;
00296    }
00297    /* Encode the open type */
00298    for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
00299       if ((enclen = encode_length(buf, len, num_octets)) < 0)
00300          return -1;
00301       if (enclen + *len > buflen) {
00302          ast_log(LOG_ERROR, "(%s): Buffer overflow detected (%d + %d > %d)\n",
00303             LOG_TAG(udptl), enclen, *len, buflen);
00304          return -1;
00305       }
00306       if (enclen > 0) {
00307          memcpy(&buf[*len], &data[octet_idx], enclen);
00308          *len += enclen;
00309       }
00310       if (enclen >= num_octets)
00311          break;
00312    }
00313 
00314    return 0;
00315 }

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

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

01130 {
01131    struct ast_udptl_protocol *cur = NULL;
01132 
01133    AST_RWLIST_RDLOCK(&protos);
01134    AST_RWLIST_TRAVERSE(&protos, cur, list) {
01135       if (cur->type == chan->tech->type)
01136          break;
01137    }
01138    AST_RWLIST_UNLOCK(&protos);
01139 
01140    return cur;
01141 }

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

Definition at line 1268 of file udptl.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, hp, udptldebugaddr, and ast_cli_entry::usage.

01269 {
01270    struct hostent *hp;
01271    struct ast_hostent ahp;
01272    int port;
01273    char *p;
01274    char *arg;
01275 
01276    switch (cmd) {
01277    case CLI_INIT:
01278       e->command = "udptl debug [off|ip]";
01279       e->usage = 
01280          "Usage: udptl debug [off]|[ip host[:port]]\n"
01281          "       Enable or disable dumping of UDPTL packets.\n"
01282          "       If ip is specified, limit the dumped packets to those to and from\n"
01283          "       the specified 'host' with optional port.\n";
01284       return NULL;
01285    case CLI_GENERATE:
01286       return NULL;
01287    }
01288 
01289    if (a->argc < 2 || a->argc > 4)
01290       return CLI_SHOWUSAGE;
01291 
01292    if (a->argc == 2) { 
01293       udptldebug = 1;
01294       memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
01295       ast_cli(a->fd, "UDPTL Debugging Enabled\n");
01296    } else if (a->argc == 3) {
01297       if (strncasecmp(a->argv[2], "off", 3))
01298          return CLI_SHOWUSAGE;
01299       udptldebug = 0;
01300       ast_cli(a->fd, "UDPTL Debugging Disabled\n");
01301    } else {
01302       if (strncasecmp(a->argv[2], "ip", 2))
01303          return CLI_SHOWUSAGE;
01304       port = 0;
01305       arg = a->argv[3];
01306       p = strstr(arg, ":");
01307       if (p) {
01308          *p = '\0';
01309          p++;
01310          port = atoi(p);
01311       }
01312       hp = ast_gethostbyname(arg, &ahp);
01313       if (hp == NULL)
01314          return CLI_SHOWUSAGE;
01315       udptldebugaddr.sin_family = AF_INET;
01316       memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
01317       udptldebugaddr.sin_port = htons(port);
01318       if (port == 0)
01319          ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
01320       else
01321          ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
01322       udptldebug = 1;
01323    }
01324 
01325    return CLI_SUCCESS;
01326 }

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

Definition at line 1328 of file udptl.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, hp, udptldebugaddr, and ast_cli_entry::usage.

01329 {
01330    struct hostent *hp;
01331    struct ast_hostent ahp;
01332    int port;
01333    char *p;
01334    char *arg;
01335 
01336    switch (cmd) {
01337    case CLI_INIT:
01338       e->command = "udptl set debug {on|off|ip}";
01339       e->usage = 
01340          "Usage: udptl set debug {on|off|ip host[:port]}\n"
01341          "       Enable or disable dumping of UDPTL packets.\n"
01342          "       If ip is specified, limit the dumped packets to those to and from\n"
01343          "       the specified 'host' with optional port.\n";
01344       return NULL;
01345    case CLI_GENERATE:
01346       return NULL;
01347    }
01348 
01349    if (a->argc < 4 || a->argc > 5)
01350       return CLI_SHOWUSAGE;
01351 
01352    if (a->argc == 4) {
01353       if (!strncasecmp(a->argv[3], "on", 2)) {
01354          udptldebug = 1;
01355          memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
01356          ast_cli(a->fd, "UDPTL Debugging Enabled\n");
01357       } else if (!strncasecmp(a->argv[3], "off", 3)) {
01358          udptldebug = 0;
01359          ast_cli(a->fd, "UDPTL Debugging Disabled\n");
01360       } else {
01361          return CLI_SHOWUSAGE;
01362       }
01363    } else {
01364       if (strncasecmp(a->argv[3], "ip", 2))
01365          return CLI_SHOWUSAGE;
01366       port = 0;
01367       arg = a->argv[4];
01368       p = strstr(arg, ":");
01369       if (p) {
01370          *p = '\0';
01371          p++;
01372          port = atoi(p);
01373       }
01374       hp = ast_gethostbyname(arg, &ahp);
01375       if (hp == NULL)
01376          return CLI_SHOWUSAGE;
01377       udptldebugaddr.sin_family = AF_INET;
01378       memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
01379       udptldebugaddr.sin_port = htons(port);
01380       if (port == 0)
01381          ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
01382       else
01383          ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
01384       udptldebug = 1;
01385    }
01386 
01387    return CLI_SUCCESS;
01388 }

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 526 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, UDPTL_ERROR_CORRECTION_REDUNDANCY, and ast_udptl::verbose.

Referenced by ast_udptl_write().

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

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

Definition at line 187 of file udptl.c.

References udptldebugaddr.

Referenced by ast_udptl_read(), and ast_udptl_write().

00188 {
00189    if (udptldebug == 0)
00190       return 0;
00191    if (udptldebugaddr.sin_addr.s_addr) {
00192       if (((ntohs(udptldebugaddr.sin_port) != 0) &&
00193            (udptldebugaddr.sin_port != addr->sin_port)) ||
00194           (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00195          return 0;
00196    }
00197    return 1;
00198 }

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

Definition at line 318 of file udptl.c.

References 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, LOCAL_FAX_MAX_DATAGRAM, ast_frame::mallocd, 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().

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

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

Definition at line 660 of file udptl.c.

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

Referenced by ast_udptl_new_with_bindaddr().

00661 {
00662    struct ast_udptl *udptl = cbdata;
00663    struct ast_frame *f;
00664 
00665    if ((f = ast_udptl_read(udptl))) {
00666       if (udptl->callback)
00667          udptl->callback(udptl, f, udptl->data);
00668    }
00669    return 1;
00670 }


Variable Documentation

struct ast_cli_entry cli_handle_udptl_debug_deprecated = AST_CLI_DEFINE(handle_cli_udptl_debug_deprecated, "Enable/Disable UDPTL debugging") [static]

Definition at line 1390 of file udptl.c.

struct ast_cli_entry cli_udptl[] [static]
Initial value:
 {

}

Definition at line 1392 of file udptl.c.

int udptldebug [static]

Are we debugging?

Definition at line 84 of file udptl.c.

struct sockaddr_in udptldebugaddr [static]

Debug packets to/from this host

Definition at line 85 of file udptl.c.

Referenced by handle_cli_udptl_debug_deprecated(), 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 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1