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