#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk/udptl.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"
Go to the source code of this file.
Data Structures | |
struct | ast_udptl |
struct | udptl_fec_rx_buffer_t |
struct | udptl_fec_tx_buffer_t |
Defines | |
#define | FALSE 0 |
#define | LOCAL_FAX_MAX_DATAGRAM 1400 |
#define | MAX_FEC_ENTRIES 5 |
#define | MAX_FEC_SPAN 5 |
#define | TRUE (!FALSE) |
#define | UDPTL_BUF_MASK 15 |
#define | UDPTL_MTU 1200 |
Functions | |
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 (struct ast_udptl *udptl) |
int | ast_udptl_get_error_correction_scheme (struct ast_udptl *udptl) |
int | ast_udptl_get_far_max_datagram (struct ast_udptl *udptl) |
int | ast_udptl_get_local_max_datagram (struct ast_udptl *udptl) |
void | ast_udptl_get_peer (struct ast_udptl *udptl, struct sockaddr_in *them) |
void | ast_udptl_get_us (struct ast_udptl *udptl, struct sockaddr_in *us) |
void | ast_udptl_init (void) |
ast_udptl * | ast_udptl_new (struct sched_context *sched, struct io_context *io, int callbackmode) |
ast_udptl * | ast_udptl_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr addr) |
void | ast_udptl_offered_from_local (struct ast_udptl *udptl, int local) |
int | ast_udptl_proto_register (struct ast_udptl_protocol *proto) |
void | ast_udptl_proto_unregister (struct ast_udptl_protocol *proto) |
ast_frame * | ast_udptl_read (struct ast_udptl *udptl) |
void | 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, int ec) |
void | ast_udptl_set_far_max_datagram (struct ast_udptl *udptl, int max_datagram) |
void | ast_udptl_set_local_max_datagram (struct ast_udptl *udptl, int max_datagram) |
void | ast_udptl_set_peer (struct ast_udptl *udptl, struct sockaddr_in *them) |
void | ast_udptl_setnat (struct ast_udptl *udptl, int nat) |
int | ast_udptl_settos (struct ast_udptl *udptl, int tos) |
void | ast_udptl_stop (struct ast_udptl *udptl) |
int | ast_udptl_write (struct ast_udptl *s, struct ast_frame *f) |
static int | decode_length (uint8_t *buf, int limit, int *len, int *pvalue) |
static int | decode_open_type (uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets) |
static int | encode_length (uint8_t *buf, int *len, int value) |
static int | encode_open_type (uint8_t *buf, int buflen, int *len, const uint8_t *data, int num_octets) |
static struct ast_udptl_protocol * | get_proto (struct ast_channel *chan) |
static int | udptl_build_packet (struct ast_udptl *s, uint8_t *buf, int buflen, uint8_t *ifp, int ifp_len) |
static int | udptl_debug_test_addr (struct sockaddr_in *addr) |
static int | udptl_do_debug (int fd, int argc, char *argv[]) |
static int | udptl_do_debug_ip (int fd, int argc, char *argv[]) |
static int | udptl_nodebug (int fd, int argc, char *argv[]) |
static int | udptl_rx_packet (struct ast_udptl *s, uint8_t *buf, int len) |
static int | udptlread (int *id, int fd, short events, void *cbdata) |
Variables | |
static struct ast_cli_entry | cli_udptl [] |
static struct ast_cli_entry | cli_udptl_no_debug |
static char | debug_usage [] |
static char | nodebug_usage [] |
static struct ast_udptl_protocol * | protos |
static int | udptldebug |
static struct sockaddr_in | udptldebugaddr |
static int | udptlend |
static int | udptlfecentries |
static int | udptlfecspan |
static int | udptlfectype |
static int | udptlmaxdatagram |
static int | udptlstart |
static int | use_even_ports |
#define LOCAL_FAX_MAX_DATAGRAM 1400 |
Definition at line 71 of file udptl.c.
Referenced by ast_udptl_reload(), ast_udptl_write(), and udptl_build_packet().
#define MAX_FEC_ENTRIES 5 |
#define MAX_FEC_SPAN 5 |
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 970 of file udptl.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), 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_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_udptl_protocol::set_udptl_peer, and ast_channel::tech_pvt.
00971 { 00972 struct ast_frame *f; 00973 struct ast_channel *who; 00974 struct ast_channel *cs[3]; 00975 struct ast_udptl *p0; 00976 struct ast_udptl *p1; 00977 struct ast_udptl_protocol *pr0; 00978 struct ast_udptl_protocol *pr1; 00979 struct sockaddr_in ac0; 00980 struct sockaddr_in ac1; 00981 struct sockaddr_in t0; 00982 struct sockaddr_in t1; 00983 void *pvt0; 00984 void *pvt1; 00985 int to; 00986 00987 ast_channel_lock(c0); 00988 while (ast_channel_trylock(c1)) { 00989 ast_channel_unlock(c0); 00990 usleep(1); 00991 ast_channel_lock(c0); 00992 } 00993 pr0 = get_proto(c0); 00994 pr1 = get_proto(c1); 00995 if (!pr0) { 00996 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 00997 ast_channel_unlock(c0); 00998 ast_channel_unlock(c1); 00999 return -1; 01000 } 01001 if (!pr1) { 01002 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01003 ast_channel_unlock(c0); 01004 ast_channel_unlock(c1); 01005 return -1; 01006 } 01007 pvt0 = c0->tech_pvt; 01008 pvt1 = c1->tech_pvt; 01009 p0 = pr0->get_udptl_info(c0); 01010 p1 = pr1->get_udptl_info(c1); 01011 if (!p0 || !p1) { 01012 /* Somebody doesn't want to play... */ 01013 ast_channel_unlock(c0); 01014 ast_channel_unlock(c1); 01015 return -2; 01016 } 01017 if (pr0->set_udptl_peer(c0, p1)) { 01018 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01019 memset(&ac1, 0, sizeof(ac1)); 01020 } else { 01021 /* Store UDPTL peer */ 01022 ast_udptl_get_peer(p1, &ac1); 01023 } 01024 if (pr1->set_udptl_peer(c1, p0)) { 01025 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01026 memset(&ac0, 0, sizeof(ac0)); 01027 } else { 01028 /* Store UDPTL peer */ 01029 ast_udptl_get_peer(p0, &ac0); 01030 } 01031 ast_channel_unlock(c0); 01032 ast_channel_unlock(c1); 01033 cs[0] = c0; 01034 cs[1] = c1; 01035 cs[2] = NULL; 01036 for (;;) { 01037 if ((c0->tech_pvt != pvt0) || 01038 (c1->tech_pvt != pvt1) || 01039 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01040 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01041 /* Tell it to try again later */ 01042 return -3; 01043 } 01044 to = -1; 01045 ast_udptl_get_peer(p1, &t1); 01046 ast_udptl_get_peer(p0, &t0); 01047 if (inaddrcmp(&t1, &ac1)) { 01048 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 01049 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port)); 01050 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 01051 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port)); 01052 memcpy(&ac1, &t1, sizeof(ac1)); 01053 } 01054 if (inaddrcmp(&t0, &ac0)) { 01055 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 01056 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port)); 01057 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 01058 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port)); 01059 memcpy(&ac0, &t0, sizeof(ac0)); 01060 } 01061 who = ast_waitfor_n(cs, 2, &to); 01062 if (!who) { 01063 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01064 /* check for hangup / whentohangup */ 01065 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01066 break; 01067 continue; 01068 } 01069 f = ast_read(who); 01070 if (!f) { 01071 *fo = f; 01072 *rc = who; 01073 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01074 /* That's all we needed */ 01075 return 0; 01076 } else { 01077 if (f->frametype == AST_FRAME_MODEM) { 01078 /* Forward T.38 frames if they happen upon us */ 01079 if (who == c0) { 01080 ast_write(c1, f); 01081 } else if (who == c1) { 01082 ast_write(c0, f); 01083 } 01084 } 01085 ast_frfree(f); 01086 } 01087 /* Swap priority. Not that it's a big deal at this point */ 01088 cs[2] = cs[0]; 01089 cs[0] = cs[1]; 01090 cs[1] = cs[2]; 01091 } 01092 return -1; 01093 }
void ast_udptl_destroy | ( | struct ast_udptl * | udptl | ) |
Definition at line 870 of file udptl.c.
References ast_io_remove(), ast_udptl::fd, free, ast_udptl::io, and ast_udptl::ioid.
Referenced by __sip_destroy(), create_addr_from_peer(), and sip_alloc().
00871 { 00872 if (udptl->ioid) 00873 ast_io_remove(udptl->io, udptl->ioid); 00874 if (udptl->fd > -1) 00875 close(udptl->fd); 00876 free(udptl); 00877 }
int ast_udptl_fd | ( | struct ast_udptl * | udptl | ) |
Definition at line 588 of file udptl.c.
References ast_udptl::fd.
Referenced by __oh323_new(), and sip_new().
00589 { 00590 return udptl->fd; 00591 }
int ast_udptl_get_error_correction_scheme | ( | struct ast_udptl * | udptl | ) |
Definition at line 679 of file udptl.c.
References ast_log(), ast_udptl::error_correction_scheme, and LOG_WARNING.
Referenced by create_addr_from_peer(), sip_alloc(), and sip_handle_t38_reinvite().
00680 { 00681 if (udptl) 00682 return udptl->error_correction_scheme; 00683 else { 00684 ast_log(LOG_WARNING, "udptl structure is null\n"); 00685 return -1; 00686 } 00687 }
int ast_udptl_get_far_max_datagram | ( | struct ast_udptl * | udptl | ) |
Definition at line 719 of file udptl.c.
References ast_log(), ast_udptl::far_max_datagram_size, and LOG_WARNING.
00720 { 00721 if (udptl) 00722 return udptl->far_max_datagram_size; 00723 else { 00724 ast_log(LOG_WARNING, "udptl structure is null\n"); 00725 return -1; 00726 } 00727 }
int ast_udptl_get_local_max_datagram | ( | struct ast_udptl * | udptl | ) |
Definition at line 709 of file udptl.c.
References ast_log(), ast_udptl::local_max_datagram_size, and LOG_WARNING.
Referenced by add_sdp(), and sip_handle_t38_reinvite().
00710 { 00711 if (udptl) 00712 return udptl->local_max_datagram_size; 00713 else { 00714 ast_log(LOG_WARNING, "udptl structure is null\n"); 00715 return -1; 00716 } 00717 }
void ast_udptl_get_peer | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | them | |||
) |
Definition at line 851 of file udptl.c.
References ast_udptl::them.
Referenced by ast_udptl_bridge(), sip_handle_t38_reinvite(), and sip_set_udptl_peer().
00852 { 00853 memset(them, 0, sizeof(*them)); 00854 them->sin_family = AF_INET; 00855 them->sin_port = udptl->them.sin_port; 00856 them->sin_addr = udptl->them.sin_addr; 00857 }
void ast_udptl_get_us | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | us | |||
) |
void ast_udptl_init | ( | void | ) |
Definition at line 1284 of file udptl.c.
References ast_cli_register_multiple(), ast_udptl_reload(), and cli_udptl.
Referenced by main().
01285 { 01286 ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry)); 01287 ast_udptl_reload(); 01288 }
struct ast_udptl* ast_udptl_new | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | callbackmode | |||
) |
Definition at line 829 of file udptl.c.
References ast_udptl_new_with_bindaddr(), io, and sched.
00830 { 00831 struct in_addr ia; 00832 memset(&ia, 0, sizeof(ia)); 00833 return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia); 00834 }
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 745 of file udptl.c.
References ast_calloc, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), errno, ast_udptl::flags, free, io, LOG_WARNING, sched, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and udptlread().
Referenced by ast_udptl_new(), and sip_alloc().
00746 { 00747 struct ast_udptl *udptl; 00748 int x; 00749 int startplace; 00750 int i; 00751 long int flags; 00752 00753 if (!(udptl = ast_calloc(1, sizeof(*udptl)))) 00754 return NULL; 00755 00756 if (udptlfectype == 2) 00757 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00758 else if (udptlfectype == 1) 00759 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00760 else 00761 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00762 udptl->error_correction_span = udptlfecspan; 00763 udptl->error_correction_entries = udptlfecentries; 00764 00765 udptl->far_max_datagram_size = udptlmaxdatagram; 00766 udptl->local_max_datagram_size = udptlmaxdatagram; 00767 00768 memset(&udptl->rx, 0, sizeof(udptl->rx)); 00769 memset(&udptl->tx, 0, sizeof(udptl->tx)); 00770 for (i = 0; i <= UDPTL_BUF_MASK; i++) { 00771 udptl->rx[i].buf_len = -1; 00772 udptl->tx[i].buf_len = -1; 00773 } 00774 00775 udptl->them.sin_family = AF_INET; 00776 udptl->us.sin_family = AF_INET; 00777 00778 if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00779 free(udptl); 00780 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00781 return NULL; 00782 } 00783 flags = fcntl(udptl->fd, F_GETFL); 00784 fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK); 00785 #ifdef SO_NO_CHECK 00786 if (nochecksums) 00787 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00788 #endif 00789 /* Find us a place */ 00790 x = (ast_random() % (udptlend - udptlstart)) + udptlstart; 00791 if (use_even_ports && (x & 1)) { 00792 ++x; 00793 } 00794 startplace = x; 00795 for (;;) { 00796 udptl->us.sin_port = htons(x); 00797 udptl->us.sin_addr = addr; 00798 if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0) 00799 break; 00800 if (errno != EADDRINUSE) { 00801 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00802 close(udptl->fd); 00803 free(udptl); 00804 return NULL; 00805 } 00806 if (use_even_ports) { 00807 x += 2; 00808 } else { 00809 ++x; 00810 } 00811 if (x > udptlend) 00812 x = udptlstart; 00813 if (x == startplace) { 00814 ast_log(LOG_WARNING, "No UDPTL ports remaining\n"); 00815 close(udptl->fd); 00816 free(udptl); 00817 return NULL; 00818 } 00819 } 00820 if (io && sched && callbackmode) { 00821 /* Operate this one in a callback mode */ 00822 udptl->sched = sched; 00823 udptl->io = io; 00824 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl); 00825 } 00826 return udptl; 00827 }
void ast_udptl_offered_from_local | ( | struct ast_udptl * | udptl, | |
int | local | |||
) |
Definition at line 671 of file udptl.c.
References ast_log(), LOG_WARNING, and ast_udptl::udptl_offered_from_local.
Referenced by transmit_invite().
00672 { 00673 if (udptl) 00674 udptl->udptl_offered_from_local = local; 00675 else 00676 ast_log(LOG_WARNING, "udptl structure is null\n"); 00677 }
int ast_udptl_proto_register | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 940 of file udptl.c.
References ast_log(), LOG_WARNING, ast_udptl_protocol::next, protos, and ast_udptl_protocol::type.
Referenced by load_module().
00941 { 00942 struct ast_udptl_protocol *cur; 00943 00944 cur = protos; 00945 while (cur) { 00946 if (cur->type == proto->type) { 00947 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 00948 return -1; 00949 } 00950 cur = cur->next; 00951 } 00952 proto->next = protos; 00953 protos = proto; 00954 return 0; 00955 }
void ast_udptl_proto_unregister | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 920 of file udptl.c.
References ast_udptl_protocol::next, and protos.
Referenced by unload_module().
00921 { 00922 struct ast_udptl_protocol *cur; 00923 struct ast_udptl_protocol *prev; 00924 00925 cur = protos; 00926 prev = NULL; 00927 while (cur) { 00928 if (cur == proto) { 00929 if (prev) 00930 prev->next = proto->next; 00931 else 00932 protos = proto->next; 00933 return; 00934 } 00935 prev = cur; 00936 cur = cur->next; 00937 } 00938 }
Definition at line 620 of file udptl.c.
References ast_assert, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), errno, ast_udptl::f, ast_udptl::fd, len(), LOG_DEBUG, 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().
00621 { 00622 int res; 00623 struct sockaddr_in sin; 00624 socklen_t len; 00625 uint16_t seqno = 0; 00626 uint16_t *udptlheader; 00627 00628 len = sizeof(sin); 00629 00630 /* Cache where the header will go */ 00631 res = recvfrom(udptl->fd, 00632 udptl->rawdata + AST_FRIENDLY_OFFSET, 00633 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET, 00634 0, 00635 (struct sockaddr *) &sin, 00636 &len); 00637 udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET); 00638 if (res < 0) { 00639 if (errno != EAGAIN) 00640 ast_log(LOG_WARNING, "UDPTL read error: %s\n", strerror(errno)); 00641 ast_assert(errno != EBADF); 00642 return &ast_null_frame; 00643 } 00644 00645 /* Ignore if the other side hasn't been given an address yet. */ 00646 if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port) 00647 return &ast_null_frame; 00648 00649 if (udptl->nat) { 00650 /* Send to whoever sent to us */ 00651 if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00652 (udptl->them.sin_port != sin.sin_port)) { 00653 memcpy(&udptl->them, &sin, sizeof(udptl->them)); 00654 ast_log(LOG_DEBUG, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00655 } 00656 } 00657 00658 if (udptl_debug_test_addr(&sin)) { 00659 ast_verbose("Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n", 00660 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res); 00661 } 00662 #if 0 00663 printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res); 00664 #endif 00665 if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1) 00666 return &ast_null_frame; 00667 00668 return &udptl->f[0]; 00669 }
void ast_udptl_reload | ( | void | ) |
Definition at line 1176 of file udptl.c.
References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verbose(), LOCAL_FAX_MAX_DATAGRAM, LOG_NOTICE, LOG_WARNING, MAX_FEC_ENTRIES, MAX_FEC_SPAN, option_verbose, s, and VERBOSE_PREFIX_2.
Referenced by ast_udptl_init().
01177 { 01178 struct ast_config *cfg; 01179 const char *s; 01180 01181 udptlstart = 4500; 01182 udptlend = 4999; 01183 udptlfectype = 0; 01184 udptlfecentries = 0; 01185 udptlfecspan = 0; 01186 udptlmaxdatagram = 0; 01187 use_even_ports = 0; 01188 01189 if ((cfg = ast_config_load("udptl.conf"))) { 01190 if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) { 01191 udptlstart = atoi(s); 01192 if (udptlstart < 1024) { 01193 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01194 udptlstart = 1024; 01195 } 01196 if (udptlstart > 65535) { 01197 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01198 udptlstart = 65535; 01199 } 01200 } 01201 if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) { 01202 udptlend = atoi(s); 01203 if (udptlend < 1024) { 01204 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01205 udptlend = 1024; 01206 } 01207 if (udptlend > 65535) { 01208 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01209 udptlend = 65535; 01210 } 01211 } 01212 if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) { 01213 #ifdef SO_NO_CHECK 01214 if (ast_false(s)) 01215 nochecksums = 1; 01216 else 01217 nochecksums = 0; 01218 #else 01219 if (ast_false(s)) 01220 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n"); 01221 #endif 01222 } 01223 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) { 01224 if (strcmp(s, "t38UDPFEC") == 0) 01225 udptlfectype = 2; 01226 else if (strcmp(s, "t38UDPRedundancy") == 0) 01227 udptlfectype = 1; 01228 } 01229 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) { 01230 udptlmaxdatagram = atoi(s); 01231 if (udptlmaxdatagram < 100) { 01232 ast_log(LOG_WARNING, "Too small T38FaxMaxDatagram size. Defaulting to 100.\n"); 01233 udptlmaxdatagram = 100; 01234 } 01235 if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM) { 01236 ast_log(LOG_WARNING, "Too large T38FaxMaxDatagram size. Defaulting to %d.\n", LOCAL_FAX_MAX_DATAGRAM); 01237 udptlmaxdatagram = LOCAL_FAX_MAX_DATAGRAM; 01238 } 01239 } 01240 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) { 01241 udptlfecentries = atoi(s); 01242 if (udptlfecentries < 1) { 01243 ast_log(LOG_WARNING, "Too small UDPTLFECentries value. Defaulting to 1.\n"); 01244 udptlfecentries = 1; 01245 } 01246 if (udptlfecentries > MAX_FEC_ENTRIES) { 01247 ast_log(LOG_WARNING, "Too large UDPTLFECentries value. Defaulting to %d.\n", MAX_FEC_ENTRIES); 01248 udptlfecentries = MAX_FEC_ENTRIES; 01249 } 01250 } 01251 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) { 01252 udptlfecspan = atoi(s); 01253 if (udptlfecspan < 1) { 01254 ast_log(LOG_WARNING, "Too small UDPTLFECspan value. Defaulting to 1.\n"); 01255 udptlfecspan = 1; 01256 } 01257 if (udptlfecspan > MAX_FEC_SPAN) { 01258 ast_log(LOG_WARNING, "Too large UDPTLFECspan value. Defaulting to %d.\n", MAX_FEC_SPAN); 01259 udptlfecspan = MAX_FEC_SPAN; 01260 } 01261 } 01262 if ((s = ast_variable_retrieve(cfg, "general", "use_even_ports"))) { 01263 use_even_ports = ast_true(s); 01264 } 01265 ast_config_destroy(cfg); 01266 } 01267 if (udptlstart >= udptlend) { 01268 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end\n"); 01269 udptlstart = 4500; 01270 udptlend = 4999; 01271 } 01272 if (use_even_ports && (udptlstart & 1)) { 01273 ++udptlstart; 01274 ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", udptlstart); 01275 } 01276 if (use_even_ports && (udptlend & 1)) { 01277 --udptlend; 01278 ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_event_ports enabled. udptlend is now %d\n", udptlend); 01279 } 01280 if (option_verbose > 1) 01281 ast_verbose(VERBOSE_PREFIX_2 "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend); 01282 }
void ast_udptl_set_callback | ( | struct ast_udptl * | udptl, | |
ast_udptl_callback | callback | |||
) |
Definition at line 598 of file udptl.c.
References ast_udptl::callback.
00599 { 00600 udptl->callback = callback; 00601 }
void ast_udptl_set_data | ( | struct ast_udptl * | udptl, | |
void * | data | |||
) |
Definition at line 593 of file udptl.c.
References ast_udptl::data.
00594 { 00595 udptl->data = data; 00596 }
void ast_udptl_set_error_correction_scheme | ( | struct ast_udptl * | udptl, | |
int | ec | |||
) |
Definition at line 689 of file udptl.c.
References ast_log(), ast_udptl::error_correction_scheme, LOG_WARNING, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by process_sdp(), process_sdp_a_image(), and sip_handle_t38_reinvite().
00690 { 00691 if (udptl) { 00692 switch (ec) { 00693 case UDPTL_ERROR_CORRECTION_FEC: 00694 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00695 break; 00696 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00697 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00698 break; 00699 case UDPTL_ERROR_CORRECTION_NONE: 00700 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00701 break; 00702 default: 00703 ast_log(LOG_WARNING, "error correction parameter invalid\n"); 00704 }; 00705 } else 00706 ast_log(LOG_WARNING, "udptl structure is null\n"); 00707 }
void ast_udptl_set_far_max_datagram | ( | struct ast_udptl * | udptl, | |
int | max_datagram | |||
) |
Definition at line 737 of file udptl.c.
References ast_log(), ast_udptl::far_max_datagram_size, and LOG_WARNING.
Referenced by process_sdp_a_image(), and sip_handle_t38_reinvite().
00738 { 00739 if (udptl) 00740 udptl->far_max_datagram_size = max_datagram; 00741 else 00742 ast_log(LOG_WARNING, "udptl structure is null\n"); 00743 }
void ast_udptl_set_local_max_datagram | ( | struct ast_udptl * | udptl, | |
int | max_datagram | |||
) |
Definition at line 729 of file udptl.c.
References ast_log(), ast_udptl::local_max_datagram_size, and LOG_WARNING.
Referenced by process_sdp_a_image(), and sip_handle_t38_reinvite().
00730 { 00731 if (udptl) 00732 udptl->local_max_datagram_size = max_datagram; 00733 else 00734 ast_log(LOG_WARNING, "udptl structure is null\n"); 00735 }
void ast_udptl_set_peer | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | them | |||
) |
Definition at line 845 of file udptl.c.
References ast_udptl::them.
Referenced by process_sdp().
00846 { 00847 udptl->them.sin_port = them->sin_port; 00848 udptl->them.sin_addr = them->sin_addr; 00849 }
void ast_udptl_setnat | ( | struct ast_udptl * | udptl, | |
int | nat | |||
) |
int ast_udptl_settos | ( | struct ast_udptl * | udptl, | |
int | tos | |||
) |
Definition at line 836 of file udptl.c.
References ast_log(), ast_udptl::fd, and LOG_WARNING.
Referenced by sip_alloc().
00837 { 00838 int res; 00839 00840 if ((res = setsockopt(udptl->fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 00841 ast_log(LOG_WARNING, "UDPTL unable to set TOS to %d\n", tos); 00842 return res; 00843 }
void ast_udptl_stop | ( | struct ast_udptl * | udptl | ) |
Definition at line 864 of file udptl.c.
References ast_udptl::them.
Referenced by process_sdp(), and stop_media_flows().
00865 { 00866 memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr)); 00867 memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port)); 00868 }
Definition at line 879 of file udptl.c.
References AST_FRAME_MODEM, ast_inet_ntoa(), ast_log(), ast_verbose(), errno, f, len(), LOCAL_FAX_MAX_DATAGRAM, LOG_NOTICE, LOG_WARNING, s, seq, udptl_build_packet(), and udptl_debug_test_addr().
Referenced by sip_write().
00880 { 00881 int seq; 00882 int len; 00883 int res; 00884 uint8_t buf[LOCAL_FAX_MAX_DATAGRAM * 2]; 00885 00886 /* If we have no peer, return immediately */ 00887 if (s->them.sin_addr.s_addr == INADDR_ANY) 00888 return 0; 00889 00890 /* If there is no data length, return immediately */ 00891 if (f->datalen == 0) 00892 return 0; 00893 00894 if (f->frametype != AST_FRAME_MODEM) { 00895 ast_log(LOG_WARNING, "UDPTL can only send T.38 data\n"); 00896 return -1; 00897 } 00898 00899 /* Save seq_no for debug output because udptl_build_packet increments it */ 00900 seq = s->tx_seq_no & 0xFFFF; 00901 00902 /* Cook up the UDPTL packet, with the relevant EC info. */ 00903 len = udptl_build_packet(s, buf, sizeof(buf), f->data, f->datalen); 00904 00905 if (len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) { 00906 if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0) 00907 ast_log(LOG_NOTICE, "UDPTL Transmission error to %s:%d: %s\n", ast_inet_ntoa(s->them.sin_addr), ntohs(s->them.sin_port), strerror(errno)); 00908 #if 0 00909 printf("Sent %d bytes of UDPTL data to %s:%d\n", res, ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00910 #endif 00911 if (udptl_debug_test_addr(&s->them)) 00912 ast_verbose("Sent UDPTL packet to %s:%d (type %d, seq %d, len %d)\n", 00913 ast_inet_ntoa(s->them.sin_addr), 00914 ntohs(s->them.sin_port), 0, seq, len); 00915 } 00916 00917 return 0; 00918 }
static int decode_length | ( | uint8_t * | buf, | |
int | limit, | |||
int * | len, | |||
int * | pvalue | |||
) | [static] |
Definition at line 156 of file udptl.c.
References ast_log(), LOG_DEBUG, and option_debug.
Referenced by decode_open_type(), and udptl_rx_packet().
00157 { 00158 if (*len >= limit) 00159 return -1; 00160 if ((buf[*len] & 0x80) == 0) { 00161 *pvalue = buf[*len]; 00162 (*len)++; 00163 return 0; 00164 } 00165 if ((buf[*len] & 0x40) == 0) { 00166 if (*len == limit - 1) 00167 return -1; 00168 *pvalue = (buf[*len] & 0x3F) << 8; 00169 (*len)++; 00170 *pvalue |= buf[*len]; 00171 (*len)++; 00172 return 0; 00173 } 00174 *pvalue = (buf[*len] & 0x3F) << 14; 00175 (*len)++; 00176 /* We have a fragment. Currently we don't process fragments. */ 00177 if (option_debug) { 00178 ast_log(LOG_DEBUG, "UDPTL packet with length greater than 16K received, decoding will fail\n"); 00179 } 00180 return 1; 00181 }
static int decode_open_type | ( | uint8_t * | buf, | |
int | limit, | |||
int * | len, | |||
const uint8_t ** | p_object, | |||
int * | p_num_octets | |||
) | [static] |
Definition at line 184 of file udptl.c.
References decode_length().
Referenced by udptl_rx_packet().
00185 { 00186 int octet_cnt = 0; 00187 00188 if (decode_length(buf, limit, len, &octet_cnt) != 0) 00189 return -1; 00190 00191 if (octet_cnt > 0) { 00192 /* Make sure the buffer contains at least the number of bits requested */ 00193 if ((*len + octet_cnt) > limit) 00194 return -1; 00195 00196 *p_num_octets = octet_cnt; 00197 *p_object = &buf[*len]; 00198 *len += octet_cnt; 00199 } 00200 00201 return 0; 00202 }
static int encode_length | ( | uint8_t * | buf, | |
int * | len, | |||
int | value | |||
) | [static] |
Definition at line 205 of file udptl.c.
Referenced by encode_open_type(), and udptl_build_packet().
00206 { 00207 int multiplier; 00208 00209 if (value < 0x80) { 00210 /* 1 octet */ 00211 buf[*len] = value; 00212 (*len)++; 00213 return value; 00214 } 00215 if (value < 0x4000) { 00216 /* 2 octets */ 00217 /* Set the first bit of the first octet */ 00218 buf[*len] = ((0x8000 | value) >> 8) & 0xFF; 00219 (*len)++; 00220 buf[*len] = value & 0xFF; 00221 (*len)++; 00222 return value; 00223 } 00224 /* Fragmentation */ 00225 multiplier = (value < 0x10000) ? (value >> 14) : 4; 00226 /* Set the first 2 bits of the octet */ 00227 buf[*len] = 0xC0 | multiplier; 00228 (*len)++; 00229 return multiplier << 14; 00230 }
static int encode_open_type | ( | uint8_t * | buf, | |
int | buflen, | |||
int * | len, | |||
const uint8_t * | data, | |||
int | num_octets | |||
) | [static] |
Definition at line 233 of file udptl.c.
References ast_log(), encode_length(), and LOG_ERROR.
Referenced by udptl_build_packet().
00234 { 00235 int enclen; 00236 int octet_idx; 00237 uint8_t zero_byte; 00238 00239 /* If open type is of zero length, add a single zero byte (10.1) */ 00240 if (num_octets == 0) { 00241 zero_byte = 0; 00242 data = &zero_byte; 00243 num_octets = 1; 00244 } 00245 /* Encode the open type */ 00246 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) { 00247 if ((enclen = encode_length(buf, len, num_octets)) < 0) 00248 return -1; 00249 if (enclen + *len > buflen) { 00250 ast_log(LOG_ERROR, "Buffer overflow detected (%d + %d > %d)\n", enclen, *len, buflen); 00251 return -1; 00252 } 00253 if (enclen > 0) { 00254 memcpy(&buf[*len], &data[octet_idx], enclen); 00255 *len += enclen; 00256 } 00257 if (enclen >= num_octets) 00258 break; 00259 } 00260 00261 return 0; 00262 }
static struct ast_udptl_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 957 of file udptl.c.
References ast_udptl_protocol::next, protos, ast_channel::tech, ast_channel_tech::type, and ast_udptl_protocol::type.
00958 { 00959 struct ast_udptl_protocol *cur; 00960 00961 cur = protos; 00962 while (cur) { 00963 if (cur->type == chan->tech->type) 00964 return cur; 00965 cur = cur->next; 00966 } 00967 return NULL; 00968 }
static int udptl_build_packet | ( | struct ast_udptl * | s, | |
uint8_t * | buf, | |||
int | buflen, | |||
uint8_t * | ifp, | |||
int | ifp_len | |||
) | [static] |
Definition at line 476 of file udptl.c.
References ast_log(), encode_length(), encode_open_type(), len(), LOCAL_FAX_MAX_DATAGRAM, LOG_DEBUG, option_debug, s, seq, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by ast_udptl_write().
00477 { 00478 uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2]; 00479 int i; 00480 int j; 00481 int seq; 00482 int entry; 00483 int entries; 00484 int span; 00485 int m; 00486 int len; 00487 int limit; 00488 int high_tide; 00489 00490 seq = s->tx_seq_no & 0xFFFF; 00491 00492 /* Map the sequence number to an entry in the circular buffer */ 00493 entry = seq & UDPTL_BUF_MASK; 00494 00495 /* We save the message in a circular buffer, for generating FEC or 00496 redundancy sets later on. */ 00497 s->tx[entry].buf_len = ifp_len; 00498 memcpy(s->tx[entry].buf, ifp, ifp_len); 00499 00500 /* Build the UDPTLPacket */ 00501 00502 len = 0; 00503 /* Encode the sequence number */ 00504 buf[len++] = (seq >> 8) & 0xFF; 00505 buf[len++] = seq & 0xFF; 00506 00507 /* Encode the primary IFP packet */ 00508 if (encode_open_type(buf, buflen, &len, ifp, ifp_len) < 0) 00509 return -1; 00510 00511 /* Encode the appropriate type of error recovery information */ 00512 switch (s->error_correction_scheme) 00513 { 00514 case UDPTL_ERROR_CORRECTION_NONE: 00515 /* Encode the error recovery type */ 00516 buf[len++] = 0x00; 00517 /* The number of entries will always be zero, so it is pointless allowing 00518 for the fragmented case here. */ 00519 if (encode_length(buf, &len, 0) < 0) 00520 return -1; 00521 break; 00522 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00523 /* Encode the error recovery type */ 00524 buf[len++] = 0x00; 00525 if (s->tx_seq_no > s->error_correction_entries) 00526 entries = s->error_correction_entries; 00527 else 00528 entries = s->tx_seq_no; 00529 /* The number of entries will always be small, so it is pointless allowing 00530 for the fragmented case here. */ 00531 if (encode_length(buf, &len, entries) < 0) 00532 return -1; 00533 /* Encode the elements */ 00534 for (i = 0; i < entries; i++) { 00535 j = (entry - i - 1) & UDPTL_BUF_MASK; 00536 if (encode_open_type(buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) { 00537 if (option_debug) { 00538 ast_log(LOG_DEBUG, "Encoding failed at i=%d, j=%d\n", i, j); 00539 } 00540 return -1; 00541 } 00542 } 00543 break; 00544 case UDPTL_ERROR_CORRECTION_FEC: 00545 span = s->error_correction_span; 00546 entries = s->error_correction_entries; 00547 if (seq < s->error_correction_span*s->error_correction_entries) { 00548 /* In the initial stages, wind up the FEC smoothly */ 00549 entries = seq/s->error_correction_span; 00550 if (seq < s->error_correction_span) 00551 span = 0; 00552 } 00553 /* Encode the error recovery type */ 00554 buf[len++] = 0x80; 00555 /* Span is defined as an inconstrained integer, which it dumb. It will only 00556 ever be a small value. Treat it as such. */ 00557 buf[len++] = 1; 00558 buf[len++] = span; 00559 /* The number of entries is defined as a length, but will only ever be a small 00560 value. Treat it as such. */ 00561 buf[len++] = entries; 00562 for (m = 0; m < entries; m++) { 00563 /* Make an XOR'ed entry the maximum length */ 00564 limit = (entry + m) & UDPTL_BUF_MASK; 00565 high_tide = 0; 00566 for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { 00567 if (high_tide < s->tx[i].buf_len) { 00568 for (j = 0; j < high_tide; j++) 00569 fec[j] ^= s->tx[i].buf[j]; 00570 for ( ; j < s->tx[i].buf_len; j++) 00571 fec[j] = s->tx[i].buf[j]; 00572 high_tide = s->tx[i].buf_len; 00573 } else { 00574 for (j = 0; j < s->tx[i].buf_len; j++) 00575 fec[j] ^= s->tx[i].buf[j]; 00576 } 00577 } 00578 if (encode_open_type(buf, buflen, &len, fec, high_tide) < 0) 00579 return -1; 00580 } 00581 break; 00582 } 00583 00584 s->tx_seq_no++; 00585 return len; 00586 }
static int udptl_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 143 of file udptl.c.
Referenced by ast_udptl_read(), and ast_udptl_write().
00144 { 00145 if (udptldebug == 0) 00146 return 0; 00147 if (udptldebugaddr.sin_addr.s_addr) { 00148 if (((ntohs(udptldebugaddr.sin_port) != 0) 00149 && (udptldebugaddr.sin_port != addr->sin_port)) 00150 || (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00151 return 0; 00152 } 00153 return 1; 00154 }
static int udptl_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1127 of file udptl.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and udptl_do_debug_ip().
01128 { 01129 if (argc != 2) { 01130 if (argc != 4) 01131 return RESULT_SHOWUSAGE; 01132 return udptl_do_debug_ip(fd, argc, argv); 01133 } 01134 udptldebug = 1; 01135 memset(&udptldebugaddr,0,sizeof(udptldebugaddr)); 01136 ast_cli(fd, "UDPTL Debugging Enabled\n"); 01137 return RESULT_SUCCESS; 01138 }
static int udptl_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1095 of file udptl.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by udptl_do_debug().
01096 { 01097 struct hostent *hp; 01098 struct ast_hostent ahp; 01099 int port; 01100 char *p; 01101 char *arg; 01102 01103 port = 0; 01104 if (argc != 4) 01105 return RESULT_SHOWUSAGE; 01106 arg = argv[3]; 01107 p = strstr(arg, ":"); 01108 if (p) { 01109 *p = '\0'; 01110 p++; 01111 port = atoi(p); 01112 } 01113 hp = ast_gethostbyname(arg, &ahp); 01114 if (hp == NULL) 01115 return RESULT_SHOWUSAGE; 01116 udptldebugaddr.sin_family = AF_INET; 01117 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr)); 01118 udptldebugaddr.sin_port = htons(port); 01119 if (port == 0) 01120 ast_cli(fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr)); 01121 else 01122 ast_cli(fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port); 01123 udptldebug = 1; 01124 return RESULT_SUCCESS; 01125 }
static int udptl_nodebug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1140 of file udptl.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01141 { 01142 if (argc != 3) 01143 return RESULT_SHOWUSAGE; 01144 udptldebug = 0; 01145 ast_cli(fd,"UDPTL Debugging Disabled\n"); 01146 return RESULT_SUCCESS; 01147 }
static int udptl_rx_packet | ( | struct ast_udptl * | s, | |
uint8_t * | buf, | |||
int | len | |||
) | [static] |
Definition at line 265 of file udptl.c.
References ARRAY_LEN, AST_FRAME_MODEM, AST_LIST_NEXT, AST_MODEM_T38, decode_length(), decode_open_type(), and s.
Referenced by ast_udptl_read().
00266 { 00267 int stat; 00268 int stat2; 00269 int i; 00270 int j; 00271 int k; 00272 int l; 00273 int m; 00274 int x; 00275 int limit; 00276 int which; 00277 int ptr; 00278 int count; 00279 int total_count; 00280 int seq_no; 00281 const uint8_t *ifp = NULL; 00282 const uint8_t *data = NULL; 00283 int ifp_len = 0; 00284 int repaired[16]; 00285 const uint8_t *bufs[ARRAY_LEN(s->f) - 1]; 00286 int lengths[ARRAY_LEN(s->f) - 1]; 00287 int span; 00288 int entries; 00289 int ifp_no; 00290 00291 ptr = 0; 00292 ifp_no = 0; 00293 memset(&s->f[0], 0, sizeof(s->f[0])); 00294 00295 /* Decode seq_number */ 00296 if (ptr + 2 > len) 00297 return -1; 00298 seq_no = (buf[0] << 8) | buf[1]; 00299 ptr += 2; 00300 00301 /* Break out the primary packet */ 00302 if ((stat = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0) 00303 return -1; 00304 /* Decode error_recovery */ 00305 if (ptr + 1 > len) 00306 return -1; 00307 if ((buf[ptr++] & 0x80) == 0) { 00308 /* Secondary packet mode for error recovery */ 00309 if (seq_no > s->rx_seq_no) { 00310 /* We received a later packet than we expected, so we need to check if we can fill in the gap from the 00311 secondary packets. */ 00312 total_count = 0; 00313 do { 00314 if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) 00315 return -1; 00316 for (i = 0; i < count && total_count + i < ARRAY_LEN(bufs); i++) { 00317 if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) 00318 return -1; 00319 } 00320 total_count += i; 00321 } 00322 while (stat2 > 0 && total_count < ARRAY_LEN(bufs)); 00323 /* Step through in reverse order, so we go oldest to newest */ 00324 for (i = total_count; i > 0; i--) { 00325 if (seq_no - i >= s->rx_seq_no) { 00326 /* This one wasn't seen before */ 00327 /* Decode the secondary IFP packet */ 00328 //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); 00329 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00330 s->f[ifp_no].subclass = AST_MODEM_T38; 00331 00332 s->f[ifp_no].mallocd = 0; 00333 s->f[ifp_no].seqno = seq_no - i; 00334 s->f[ifp_no].datalen = lengths[i - 1]; 00335 s->f[ifp_no].data = (uint8_t *) bufs[i - 1]; 00336 s->f[ifp_no].offset = 0; 00337 s->f[ifp_no].src = "UDPTL"; 00338 if (ifp_no > 0) 00339 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00340 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00341 ifp_no++; 00342 } 00343 } 00344 } 00345 } 00346 else 00347 { 00348 /* FEC mode for error recovery */ 00349 /* Our buffers cannot tolerate overlength IFP packets in FEC mode */ 00350 if (ifp_len > LOCAL_FAX_MAX_DATAGRAM) 00351 return -1; 00352 /* Update any missed slots in the buffer */ 00353 for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) { 00354 x = s->rx_seq_no & UDPTL_BUF_MASK; 00355 s->rx[x].buf_len = -1; 00356 s->rx[x].fec_len[0] = 0; 00357 s->rx[x].fec_span = 0; 00358 s->rx[x].fec_entries = 0; 00359 } 00360 00361 x = seq_no & UDPTL_BUF_MASK; 00362 00363 memset(repaired, 0, sizeof(repaired)); 00364 00365 /* Save the new IFP packet */ 00366 memcpy(s->rx[x].buf, ifp, ifp_len); 00367 s->rx[x].buf_len = ifp_len; 00368 repaired[x] = TRUE; 00369 00370 /* Decode the FEC packets */ 00371 /* The span is defined as an unconstrained integer, but will never be more 00372 than a small value. */ 00373 if (ptr + 2 > len) 00374 return -1; 00375 if (buf[ptr++] != 1) 00376 return -1; 00377 span = buf[ptr++]; 00378 s->rx[x].fec_span = span; 00379 00380 /* The number of entries is defined as a length, but will only ever be a small 00381 value. Treat it as such. */ 00382 if (ptr + 1 > len) 00383 return -1; 00384 entries = buf[ptr++]; 00385 if (entries > MAX_FEC_ENTRIES) { 00386 return -1; 00387 } 00388 s->rx[x].fec_entries = entries; 00389 00390 /* Decode the elements */ 00391 for (i = 0; i < entries; i++) { 00392 if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) 00393 return -1; 00394 if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM) 00395 return -1; 00396 00397 /* Save the new FEC data */ 00398 memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); 00399 #if 0 00400 fprintf(stderr, "FEC: "); 00401 for (j = 0; j < s->rx[x].fec_len[i]; j++) 00402 fprintf(stderr, "%02X ", data[j]); 00403 fprintf(stderr, "\n"); 00404 #endif 00405 } 00406 00407 /* See if we can reconstruct anything which is missing */ 00408 /* TODO: this does not comprehensively hunt back and repair everything that is possible */ 00409 for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { 00410 if (s->rx[l].fec_len[0] <= 0) 00411 continue; 00412 for (m = 0; m < s->rx[l].fec_entries; m++) { 00413 limit = (l + m) & UDPTL_BUF_MASK; 00414 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) { 00415 if (s->rx[k].buf_len <= 0) 00416 which = (which == -1) ? k : -2; 00417 } 00418 if (which >= 0) { 00419 /* Repairable */ 00420 for (j = 0; j < s->rx[l].fec_len[m]; j++) { 00421 s->rx[which].buf[j] = s->rx[l].fec[m][j]; 00422 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) 00423 s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; 00424 } 00425 s->rx[which].buf_len = s->rx[l].fec_len[m]; 00426 repaired[which] = TRUE; 00427 } 00428 } 00429 } 00430 /* Now play any new packets forwards in time */ 00431 for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { 00432 if (repaired[l]) { 00433 //fprintf(stderr, "Fixed packet %d, len %d\n", j, l); 00434 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00435 s->f[ifp_no].subclass = AST_MODEM_T38; 00436 00437 s->f[ifp_no].mallocd = 0; 00438 s->f[ifp_no].seqno = j; 00439 s->f[ifp_no].datalen = s->rx[l].buf_len; 00440 s->f[ifp_no].data = s->rx[l].buf; 00441 s->f[ifp_no].offset = 0; 00442 s->f[ifp_no].src = "UDPTL"; 00443 if (ifp_no > 0) 00444 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00445 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00446 ifp_no++; 00447 } 00448 } 00449 } 00450 00451 /* If packets are received out of sequence, we may have already processed this packet from the error 00452 recovery information in a packet already received. */ 00453 if (seq_no >= s->rx_seq_no) { 00454 /* Decode the primary IFP packet */ 00455 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00456 s->f[ifp_no].subclass = AST_MODEM_T38; 00457 00458 s->f[ifp_no].mallocd = 0; 00459 s->f[ifp_no].seqno = seq_no; 00460 s->f[ifp_no].datalen = ifp_len; 00461 s->f[ifp_no].data = (uint8_t *) ifp; 00462 s->f[ifp_no].offset = 0; 00463 s->f[ifp_no].src = "UDPTL"; 00464 if (ifp_no > 0) 00465 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00466 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00467 00468 ifp_no++; 00469 } 00470 00471 s->rx_seq_no = seq_no + 1; 00472 return ifp_no; 00473 }
static int udptlread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 608 of file udptl.c.
References ast_udptl_read(), ast_udptl::callback, and f.
Referenced by ast_udptl_new_with_bindaddr().
00609 { 00610 struct ast_udptl *udptl = cbdata; 00611 struct ast_frame *f; 00612 00613 if ((f = ast_udptl_read(udptl))) { 00614 if (udptl->callback) 00615 udptl->callback(udptl, f, udptl->data); 00616 } 00617 return 1; 00618 }
struct ast_cli_entry cli_udptl[] [static] |
struct ast_cli_entry cli_udptl_no_debug [static] |
Initial value:
{ { "udptl", "no", "debug", NULL }, udptl_nodebug, NULL, NULL }
char debug_usage[] [static] |
char nodebug_usage[] [static] |
struct ast_udptl_protocol* protos [static] |
Definition at line 138 of file udptl.c.
Referenced by ast_udptl_proto_register(), ast_udptl_proto_unregister(), and get_proto().
int udptldebug [static] |
struct sockaddr_in udptldebugaddr [static] |
int udptlfecentries [static] |
int udptlfecspan [static] |
int udptlfectype [static] |
int udptlmaxdatagram [static] |
int udptlstart [static] |
int use_even_ports [static] |