Wed Aug 18 22:34:34 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"

Go to the source code of this file.

Data Structures

struct  ast_udptl
 Structure for an UDPTL session. More...
struct  protos
 List of current sessions. More...
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 sockaddr_in *them)
void ast_udptl_get_us (const struct ast_udptl *udptl, struct sockaddr_in *us)
void ast_udptl_init (void)
ast_udptlast_udptl_new (struct sched_context *sched, struct io_context *io, int callbackmode)
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)
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 = { .handler = handle_cli_udptl_debug_deprecated , .summary = "Enable/Disable UDPTL debugging" ,__VA_ARGS__ }
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 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 1403 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_FILEUNCHANGED, LOG_NOTICE, LOG_WARNING, MAX_FEC_ENTRIES, MAX_FEC_SPAN, and s.

Referenced by ast_udptl_init(), and ast_udptl_reload().

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

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 1150 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, get_proto(), ast_udptl_protocol::get_udptl_info, inaddrcmp(), LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_udptl_protocol::set_udptl_peer, and ast_channel::tech_pvt.

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

void ast_udptl_destroy ( struct ast_udptl udptl  ) 

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

01050 {
01051    if (udptl->ioid)
01052       ast_io_remove(udptl->io, udptl->ioid);
01053    if (udptl->fd > -1)
01054       close(udptl->fd);
01055    if (udptl->tag)
01056       ast_free(udptl->tag);
01057    ast_free(udptl);
01058 }

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

References ast_udptl::error_correction_scheme.

Referenced by add_sdp().

00832 {
00833    return udptl->error_correction_scheme;
00834 }

unsigned int ast_udptl_get_far_max_datagram ( const struct ast_udptl udptl  ) 

Definition at line 899 of file udptl.c.

References ast_udptl::far_max_datagram.

Referenced by process_sdp().

00900 {
00901    if (udptl->far_max_datagram < 0) {
00902       return 0;
00903    }
00904    return udptl->far_max_datagram;
00905 }

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

References calculate_far_max_ifp(), and ast_udptl::far_max_ifp.

Referenced by change_t38_state().

00908 {
00909    if (udptl->far_max_ifp == -1) {
00910       calculate_far_max_ifp(udptl);
00911    }
00912 
00913    if (udptl->far_max_ifp < 0) {
00914       return 0;
00915    }
00916    return udptl->far_max_ifp;
00917 }

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

References calculate_local_max_datagram(), and ast_udptl::local_max_datagram.

Referenced by add_sdp().

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

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

Definition at line 1030 of file udptl.c.

References ast_udptl::them.

Referenced by ast_udptl_bridge(), and sip_set_udptl_peer().

01031 {
01032    memset(them, 0, sizeof(*them));
01033    them->sin_family = AF_INET;
01034    them->sin_port = udptl->them.sin_port;
01035    them->sin_addr = udptl->them.sin_addr;
01036 }

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

Definition at line 1038 of file udptl.c.

References ast_udptl::us.

Referenced by add_sdp().

01039 {
01040    memcpy(us, &udptl->us, sizeof(udptl->us));
01041 }

void ast_udptl_init ( void   ) 

Definition at line 1507 of file udptl.c.

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

Referenced by main().

01508 {
01509    ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry));
01510    __ast_udptl_reload(0);
01511 }

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

Definition at line 997 of file udptl.c.

References ast_udptl_new_with_bindaddr(), io, and sched.

00998 {
00999    struct in_addr ia;
01000    memset(&ia, 0, sizeof(ia));
01001    return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia);
01002 }

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

Definition at line 919 of file udptl.c.

References ast_calloc, ast_free, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), errno, ast_udptl::flags, io, LOG_WARNING, sched, and udptlread().

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

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

int ast_udptl_proto_register ( struct ast_udptl_protocol proto  ) 

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

01120 {
01121    struct ast_udptl_protocol *cur;
01122 
01123    AST_RWLIST_WRLOCK(&protos);
01124    AST_RWLIST_TRAVERSE(&protos, cur, list) {
01125       if (cur->type == proto->type) {
01126          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01127          AST_RWLIST_UNLOCK(&protos);
01128          return -1;
01129       }
01130    }
01131    AST_RWLIST_INSERT_TAIL(&protos, proto, list);
01132    AST_RWLIST_UNLOCK(&protos);
01133    return 0;
01134 }

void ast_udptl_proto_unregister ( struct ast_udptl_protocol proto  ) 

Definition at line 1112 of file udptl.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by unload_module().

01113 {
01114    AST_RWLIST_WRLOCK(&protos);
01115    AST_RWLIST_REMOVE(&protos, proto, list);
01116    AST_RWLIST_UNLOCK(&protos);
01117 }

struct ast_frame* ast_udptl_read ( struct ast_udptl udptl  ) 

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

References __ast_udptl_reload().

01502 {
01503    __ast_udptl_reload(1);
01504    return 0;
01505 }

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

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

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

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

void ast_udptl_set_local_max_ifp ( struct ast_udptl udptl,
unsigned int  max_ifp 
)

Definition at line 864 of file udptl.c.

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

Referenced by interpret_t38_parameters().

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

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

Definition at line 1024 of file udptl.c.

References ast_udptl::them.

Referenced by process_sdp().

01025 {
01026    udptl->them.sin_port = them->sin_port;
01027    udptl->them.sin_addr = them->sin_addr;
01028 }

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

References ast_free, ast_vasprintf, and ast_udptl::tag.

Referenced by change_t38_state().

01005 {
01006    va_list ap;
01007 
01008    if (udptl->tag) {
01009       ast_free(udptl->tag);
01010       udptl->tag = NULL;
01011    }
01012    va_start(ap, format);
01013    if (ast_vasprintf(&udptl->tag, format, ap) == -1) {
01014       udptl->tag = NULL;
01015    }
01016    va_end(ap);
01017 }

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

References ast_netsock_set_qos(), and ast_udptl::fd.

Referenced by sip_alloc().

01020 {
01021    return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL");
01022 }

void ast_udptl_stop ( struct ast_udptl udptl  ) 

Definition at line 1043 of file udptl.c.

References ast_udptl::them.

Referenced by process_sdp(), and stop_media_flows().

01044 {
01045    memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr));
01046    memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port));
01047 }

int ast_udptl_write ( struct ast_udptl s,
struct ast_frame f 
)

Definition at line 1060 of file udptl.c.

References AST_FRAME_MODEM, ast_inet_ntoa(), ast_log(), AST_MODEM_T38, ast_verb, buf, DEFAULT_FAX_MAX_DATAGRAM, errno, f, len(), LOG_NOTICE, LOG_TAG, LOG_WARNING, s, seq, udptl_build_packet(), and udptl_debug_test_addr().

Referenced by sip_write().

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

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 = (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1);
00809 
00810          if ((new_max < 80) && (udptl->error_correction_entries > 1)) {
00811             /* the max ifp is not large enough, subtract an
00812              * error correction entry and calculate again
00813              * */
00814             --udptl->error_correction_entries;
00815          } else {
00816             break;
00817          }
00818       }
00819       break;
00820    case UDPTL_ERROR_CORRECTION_FEC:
00821       /* need room for sequence number, length indicators and a
00822        * a single IFP of the maximum size expected
00823        */
00824       new_max = (udptl->far_max_datagram - 10) / 2;
00825       break;
00826    }
00827    /* subtract 5% of space for insurance */
00828    udptl->far_max_ifp = new_max * 0.95;
00829 }

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]

Definition at line 1136 of file udptl.c.

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

01137 {
01138    struct ast_udptl_protocol *cur = NULL;
01139 
01140    AST_RWLIST_RDLOCK(&protos);
01141    AST_RWLIST_TRAVERSE(&protos, cur, list) {
01142       if (cur->type == chan->tech->type)
01143          break;
01144    }
01145    AST_RWLIST_UNLOCK(&protos);
01146 
01147    return cur;
01148 }

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

Definition at line 1275 of file udptl.c.

References ahp, 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, and ast_cli_entry::usage.

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

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

Definition at line 1335 of file udptl.c.

References ahp, 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, and ast_cli_entry::usage.

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

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, encode_length(), encode_open_type(), len(), LOCAL_FAX_MAX_DATAGRAM, LOG_TAG, s, seq, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.

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.

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, decode_length(), decode_open_type(), and s.

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, 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 = { .handler = handle_cli_udptl_debug_deprecated , .summary = "Enable/Disable UDPTL debugging" ,__VA_ARGS__ } [static]

Definition at line 1397 of file udptl.c.

struct ast_cli_entry cli_udptl[] [static]

Initial value:

 {
   { .handler =  handle_cli_udptl_set_debug , .summary =  "Enable/Disable UDPTL debugging" ,__VA_ARGS__ } .deprecate_cmd = &cli_handle_udptl_debug_deprecated)
}

Definition at line 1399 of file udptl.c.

Referenced by ast_udptl_init().

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.

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 Wed Aug 18 22:34:34 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7