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