#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 970 of file udptl.c.
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 } else { 01020 /* Store UDPTL peer */ 01021 ast_udptl_get_peer(p1, &ac1); 01022 } 01023 if (pr1->set_udptl_peer(c1, p0)) 01024 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01025 else { 01026 /* Store UDPTL peer */ 01027 ast_udptl_get_peer(p0, &ac0); 01028 } 01029 ast_channel_unlock(c0); 01030 ast_channel_unlock(c1); 01031 cs[0] = c0; 01032 cs[1] = c1; 01033 cs[2] = NULL; 01034 for (;;) { 01035 if ((c0->tech_pvt != pvt0) || 01036 (c1->tech_pvt != pvt1) || 01037 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01038 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01039 /* Tell it to try again later */ 01040 return -3; 01041 } 01042 to = -1; 01043 ast_udptl_get_peer(p1, &t1); 01044 ast_udptl_get_peer(p0, &t0); 01045 if (inaddrcmp(&t1, &ac1)) { 01046 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 01047 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port)); 01048 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 01049 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port)); 01050 memcpy(&ac1, &t1, sizeof(ac1)); 01051 } 01052 if (inaddrcmp(&t0, &ac0)) { 01053 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n", 01054 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port)); 01055 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n", 01056 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port)); 01057 memcpy(&ac0, &t0, sizeof(ac0)); 01058 } 01059 who = ast_waitfor_n(cs, 2, &to); 01060 if (!who) { 01061 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01062 /* check for hangup / whentohangup */ 01063 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01064 break; 01065 continue; 01066 } 01067 f = ast_read(who); 01068 if (!f) { 01069 *fo = f; 01070 *rc = who; 01071 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01072 /* That's all we needed */ 01073 return 0; 01074 } else { 01075 if (f->frametype == AST_FRAME_MODEM) { 01076 /* Forward T.38 frames if they happen upon us */ 01077 if (who == c0) { 01078 ast_write(c1, f); 01079 } else if (who == c1) { 01080 ast_write(c0, f); 01081 } 01082 } 01083 ast_frfree(f); 01084 } 01085 /* Swap priority. Not that it's a big deal at this point */ 01086 cs[2] = cs[0]; 01087 cs[0] = cs[1]; 01088 cs[1] = cs[2]; 01089 } 01090 return -1; 01091 }
void ast_udptl_destroy | ( | struct ast_udptl * | udptl | ) |
Definition at line 874 of file udptl.c.
Referenced by __sip_destroy(), and create_addr_from_peer().
00875 { 00876 if (udptl->ioid) 00877 ast_io_remove(udptl->io, udptl->ioid); 00878 if (udptl->fd > -1) 00879 close(udptl->fd); 00880 free(udptl); 00881 }
int ast_udptl_fd | ( | struct ast_udptl * | udptl | ) |
Definition at line 600 of file udptl.c.
Referenced by __oh323_new(), and sip_new().
00601 { 00602 return udptl->fd; 00603 }
int ast_udptl_get_error_correction_scheme | ( | struct ast_udptl * | udptl | ) |
Definition at line 691 of file udptl.c.
Referenced by create_addr_from_peer(), sip_alloc(), and sip_handle_t38_reinvite().
00692 { 00693 if (udptl) 00694 return udptl->error_correction_scheme; 00695 else { 00696 ast_log(LOG_WARNING, "udptl structure is null\n"); 00697 return -1; 00698 } 00699 }
int ast_udptl_get_far_max_datagram | ( | struct ast_udptl * | udptl | ) |
Definition at line 731 of file udptl.c.
00732 { 00733 if (udptl) 00734 return udptl->far_max_datagram_size; 00735 else { 00736 ast_log(LOG_WARNING, "udptl structure is null\n"); 00737 return -1; 00738 } 00739 }
int ast_udptl_get_local_max_datagram | ( | struct ast_udptl * | udptl | ) |
Definition at line 721 of file udptl.c.
Referenced by add_t38_sdp(), and sip_handle_t38_reinvite().
00722 { 00723 if (udptl) 00724 return udptl->local_max_datagram_size; 00725 else { 00726 ast_log(LOG_WARNING, "udptl structure is null\n"); 00727 return -1; 00728 } 00729 }
void ast_udptl_get_peer | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | them | |||
) |
Definition at line 856 of file udptl.c.
Referenced by ast_udptl_bridge(), sip_handle_t38_reinvite(), and sip_set_udptl_peer().
00857 { 00858 them->sin_family = AF_INET; 00859 them->sin_port = udptl->them.sin_port; 00860 them->sin_addr = udptl->them.sin_addr; 00861 }
void ast_udptl_get_us | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | us | |||
) |
void ast_udptl_init | ( | void | ) |
Definition at line 1250 of file udptl.c.
Referenced by main().
01251 { 01252 ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry)); 01253 ast_udptl_reload(); 01254 }
struct ast_udptl* ast_udptl_new | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | callbackmode | |||
) | [read] |
Definition at line 834 of file udptl.c.
00835 { 00836 struct in_addr ia; 00837 memset(&ia, 0, sizeof(ia)); 00838 return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia); 00839 }
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 757 of file udptl.c.
Referenced by ast_udptl_new(), and sip_alloc().
00758 { 00759 struct ast_udptl *udptl; 00760 int x; 00761 int startplace; 00762 int i; 00763 long int flags; 00764 00765 if (!(udptl = ast_calloc(1, sizeof(*udptl)))) 00766 return NULL; 00767 00768 if (udptlfectype == 2) 00769 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00770 else if (udptlfectype == 1) 00771 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00772 else 00773 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00774 udptl->error_correction_span = udptlfecspan; 00775 udptl->error_correction_entries = udptlfecentries; 00776 00777 udptl->far_max_datagram_size = udptlmaxdatagram; 00778 udptl->local_max_datagram_size = udptlmaxdatagram; 00779 00780 memset(&udptl->rx, 0, sizeof(udptl->rx)); 00781 memset(&udptl->tx, 0, sizeof(udptl->tx)); 00782 for (i = 0; i <= UDPTL_BUF_MASK; i++) { 00783 udptl->rx[i].buf_len = -1; 00784 udptl->tx[i].buf_len = -1; 00785 } 00786 00787 udptl->seqno = ast_random() & 0xffff; 00788 udptl->them.sin_family = AF_INET; 00789 udptl->us.sin_family = AF_INET; 00790 00791 if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00792 free(udptl); 00793 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00794 return NULL; 00795 } 00796 flags = fcntl(udptl->fd, F_GETFL); 00797 fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK); 00798 #ifdef SO_NO_CHECK 00799 if (nochecksums) 00800 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00801 #endif 00802 /* Find us a place */ 00803 x = (ast_random() % (udptlend - udptlstart)) + udptlstart; 00804 startplace = x; 00805 for (;;) { 00806 udptl->us.sin_port = htons(x); 00807 udptl->us.sin_addr = addr; 00808 if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0) 00809 break; 00810 if (errno != EADDRINUSE) { 00811 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00812 close(udptl->fd); 00813 free(udptl); 00814 return NULL; 00815 } 00816 if (++x > udptlend) 00817 x = udptlstart; 00818 if (x == startplace) { 00819 ast_log(LOG_WARNING, "No UDPTL ports remaining\n"); 00820 close(udptl->fd); 00821 free(udptl); 00822 return NULL; 00823 } 00824 } 00825 if (io && sched && callbackmode) { 00826 /* Operate this one in a callback mode */ 00827 udptl->sched = sched; 00828 udptl->io = io; 00829 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl); 00830 } 00831 return udptl; 00832 }
void ast_udptl_offered_from_local | ( | struct ast_udptl * | udptl, | |
int | local | |||
) |
Definition at line 683 of file udptl.c.
Referenced by transmit_invite(), transmit_reinvite_with_t38_sdp(), and transmit_response_with_t38_sdp().
00684 { 00685 if (udptl) 00686 udptl->udptl_offered_from_local = local; 00687 else 00688 ast_log(LOG_WARNING, "udptl structure is null\n"); 00689 }
int ast_udptl_proto_register | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 940 of file udptl.c.
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.
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 632 of file udptl.c.
Referenced by sip_rtp_read(), skinny_rtp_read(), and udptlread().
00633 { 00634 int res; 00635 struct sockaddr_in sin; 00636 socklen_t len; 00637 uint16_t seqno = 0; 00638 uint16_t *udptlheader; 00639 00640 len = sizeof(sin); 00641 00642 /* Cache where the header will go */ 00643 res = recvfrom(udptl->fd, 00644 udptl->rawdata + AST_FRIENDLY_OFFSET, 00645 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET, 00646 0, 00647 (struct sockaddr *) &sin, 00648 &len); 00649 udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET); 00650 if (res < 0) { 00651 if (errno != EAGAIN) 00652 ast_log(LOG_WARNING, "UDPTL read error: %s\n", strerror(errno)); 00653 if (errno == EBADF) 00654 CRASH; 00655 return &ast_null_frame; 00656 } 00657 00658 /* Ignore if the other side hasn't been given an address yet. */ 00659 if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port) 00660 return &ast_null_frame; 00661 00662 if (udptl->nat) { 00663 /* Send to whoever sent to us */ 00664 if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00665 (udptl->them.sin_port != sin.sin_port)) { 00666 memcpy(&udptl->them, &sin, sizeof(udptl->them)); 00667 ast_log(LOG_DEBUG, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00668 } 00669 } 00670 00671 if (udptl_debug_test_addr(&sin)) { 00672 ast_verbose("Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n", 00673 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res); 00674 } 00675 #if 0 00676 printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res); 00677 #endif 00678 udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res); 00679 00680 return &udptl->f[0]; 00681 }
void ast_udptl_reload | ( | void | ) |
Definition at line 1174 of file udptl.c.
Referenced by ast_udptl_init().
01175 { 01176 struct ast_config *cfg; 01177 const char *s; 01178 01179 udptlstart = 4500; 01180 udptlend = 4999; 01181 udptlfectype = 0; 01182 udptlfecentries = 0; 01183 udptlfecspan = 0; 01184 udptlmaxdatagram = 0; 01185 01186 if ((cfg = ast_config_load("udptl.conf"))) { 01187 if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) { 01188 udptlstart = atoi(s); 01189 if (udptlstart < 1024) 01190 udptlstart = 1024; 01191 if (udptlstart > 65535) 01192 udptlstart = 65535; 01193 } 01194 if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) { 01195 udptlend = atoi(s); 01196 if (udptlend < 1024) 01197 udptlend = 1024; 01198 if (udptlend > 65535) 01199 udptlend = 65535; 01200 } 01201 if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) { 01202 #ifdef SO_NO_CHECK 01203 if (ast_false(s)) 01204 nochecksums = 1; 01205 else 01206 nochecksums = 0; 01207 #else 01208 if (ast_false(s)) 01209 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n"); 01210 #endif 01211 } 01212 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) { 01213 if (strcmp(s, "t38UDPFEC") == 0) 01214 udptlfectype = 2; 01215 else if (strcmp(s, "t38UDPRedundancy") == 0) 01216 udptlfectype = 1; 01217 } 01218 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) { 01219 udptlmaxdatagram = atoi(s); 01220 if (udptlmaxdatagram < 0) 01221 udptlmaxdatagram = 0; 01222 if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM) 01223 udptlmaxdatagram = LOCAL_FAX_MAX_DATAGRAM; 01224 } 01225 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) { 01226 udptlfecentries = atoi(s); 01227 if (udptlfecentries < 0) 01228 udptlfecentries = 0; 01229 if (udptlfecentries > MAX_FEC_ENTRIES) 01230 udptlfecentries = MAX_FEC_ENTRIES; 01231 } 01232 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) { 01233 udptlfecspan = atoi(s); 01234 if (udptlfecspan < 0) 01235 udptlfecspan = 0; 01236 if (udptlfecspan > MAX_FEC_SPAN) 01237 udptlfecspan = MAX_FEC_SPAN; 01238 } 01239 ast_config_destroy(cfg); 01240 } 01241 if (udptlstart >= udptlend) { 01242 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end\n"); 01243 udptlstart = 4500; 01244 udptlend = 4999; 01245 } 01246 if (option_verbose > 1) 01247 ast_verbose(VERBOSE_PREFIX_2 "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend); 01248 }
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 | |||
) |
Definition at line 701 of file udptl.c.
Referenced by process_sdp(), and sip_handle_t38_reinvite().
00702 { 00703 if (udptl) { 00704 switch (ec) { 00705 case UDPTL_ERROR_CORRECTION_FEC: 00706 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00707 break; 00708 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00709 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00710 break; 00711 case UDPTL_ERROR_CORRECTION_NONE: 00712 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00713 break; 00714 default: 00715 ast_log(LOG_WARNING, "error correction parameter invalid\n"); 00716 }; 00717 } else 00718 ast_log(LOG_WARNING, "udptl structure is null\n"); 00719 }
void ast_udptl_set_far_max_datagram | ( | struct ast_udptl * | udptl, | |
int | max_datagram | |||
) |
Definition at line 749 of file udptl.c.
Referenced by process_sdp(), and sip_handle_t38_reinvite().
00750 { 00751 if (udptl) 00752 udptl->far_max_datagram_size = max_datagram; 00753 else 00754 ast_log(LOG_WARNING, "udptl structure is null\n"); 00755 }
void ast_udptl_set_local_max_datagram | ( | struct ast_udptl * | udptl, | |
int | max_datagram | |||
) |
Definition at line 741 of file udptl.c.
Referenced by process_sdp(), and sip_handle_t38_reinvite().
00742 { 00743 if (udptl) 00744 udptl->local_max_datagram_size = max_datagram; 00745 else 00746 ast_log(LOG_WARNING, "udptl structure is null\n"); 00747 }
void ast_udptl_set_peer | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | them | |||
) |
Definition at line 850 of file udptl.c.
Referenced by process_sdp().
00851 { 00852 udptl->them.sin_port = them->sin_port; 00853 udptl->them.sin_addr = them->sin_addr; 00854 }
void ast_udptl_setnat | ( | struct ast_udptl * | udptl, | |
int | nat | |||
) |
int ast_udptl_settos | ( | struct ast_udptl * | udptl, | |
int | tos | |||
) |
Definition at line 841 of file udptl.c.
Referenced by sip_alloc().
00842 { 00843 int res; 00844 00845 if ((res = setsockopt(udptl->fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 00846 ast_log(LOG_WARNING, "UDPTL unable to set TOS to %d\n", tos); 00847 return res; 00848 }
void ast_udptl_stop | ( | struct ast_udptl * | udptl | ) |
Definition at line 868 of file udptl.c.
Referenced by process_sdp(), and stop_media_flows().
00869 { 00870 memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr)); 00871 memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port)); 00872 }
Definition at line 883 of file udptl.c.
Referenced by sip_write().
00884 { 00885 int len; 00886 int res; 00887 uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]; 00888 00889 /* If we have no peer, return immediately */ 00890 if (s->them.sin_addr.s_addr == INADDR_ANY) 00891 return 0; 00892 00893 /* If there is no data length, return immediately */ 00894 if (f->datalen == 0) 00895 return 0; 00896 00897 if (f->frametype != AST_FRAME_MODEM) { 00898 ast_log(LOG_WARNING, "UDPTL can only send T.38 data\n"); 00899 return -1; 00900 } 00901 00902 /* Cook up the UDPTL packet, with the relevant EC info. */ 00903 len = udptl_build_packet(s, 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, s->seqno, len); 00915 } 00916 00917 return 0; 00918 }
static int decode_length | ( | uint8_t * | buf, | |
int | limit, | |||
int * | len, | |||
int * | pvalue | |||
) | [static] |
Definition at line 158 of file udptl.c.
Referenced by decode_open_type(), and udptl_rx_packet().
00159 { 00160 if ((buf[*len] & 0x80) == 0) { 00161 if (*len >= limit) 00162 return -1; 00163 *pvalue = buf[*len]; 00164 (*len)++; 00165 return 0; 00166 } 00167 if ((buf[*len] & 0x40) == 0) { 00168 if (*len >= limit - 1) 00169 return -1; 00170 *pvalue = (buf[*len] & 0x3F) << 8; 00171 (*len)++; 00172 *pvalue |= buf[*len]; 00173 (*len)++; 00174 return 0; 00175 } 00176 if (*len >= limit) 00177 return -1; 00178 *pvalue = (buf[*len] & 0x3F) << 14; 00179 (*len)++; 00180 /* Indicate we have a fragment */ 00181 return 1; 00182 }
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 185 of file udptl.c.
References decode_length().
Referenced by udptl_rx_packet().
00186 { 00187 int octet_cnt; 00188 int octet_idx; 00189 int stat; 00190 int i; 00191 const uint8_t **pbuf; 00192 00193 for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) { 00194 if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0) 00195 return -1; 00196 if (octet_cnt > 0) { 00197 *p_num_octets += octet_cnt; 00198 00199 pbuf = &p_object[octet_idx]; 00200 i = 0; 00201 /* Make sure the buffer contains at least the number of bits requested */ 00202 if ((*len + octet_cnt) > limit) 00203 return -1; 00204 00205 *pbuf = &buf[*len]; 00206 *len += octet_cnt; 00207 } 00208 if (stat == 0) 00209 break; 00210 } 00211 return 0; 00212 }
static int encode_length | ( | uint8_t * | buf, | |
int * | len, | |||
int | value | |||
) | [static] |
Definition at line 215 of file udptl.c.
Referenced by encode_open_type(), and udptl_build_packet().
00216 { 00217 int multiplier; 00218 00219 if (value < 0x80) { 00220 /* 1 octet */ 00221 buf[*len] = value; 00222 (*len)++; 00223 return value; 00224 } 00225 if (value < 0x4000) { 00226 /* 2 octets */ 00227 /* Set the first bit of the first octet */ 00228 buf[*len] = ((0x8000 | value) >> 8) & 0xFF; 00229 (*len)++; 00230 buf[*len] = value & 0xFF; 00231 (*len)++; 00232 return value; 00233 } 00234 /* Fragmentation */ 00235 multiplier = (value < 0x10000) ? (value >> 14) : 4; 00236 /* Set the first 2 bits of the octet */ 00237 buf[*len] = 0xC0 | multiplier; 00238 (*len)++; 00239 return multiplier << 14; 00240 }
static int encode_open_type | ( | uint8_t * | buf, | |
int * | len, | |||
const uint8_t * | data, | |||
int | num_octets | |||
) | [static] |
Definition at line 243 of file udptl.c.
References encode_length().
Referenced by udptl_build_packet().
00244 { 00245 int enclen; 00246 int octet_idx; 00247 uint8_t zero_byte; 00248 00249 /* If open type is of zero length, add a single zero byte (10.1) */ 00250 if (num_octets == 0) { 00251 zero_byte = 0; 00252 data = &zero_byte; 00253 num_octets = 1; 00254 } 00255 /* Encode the open type */ 00256 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) { 00257 if ((enclen = encode_length(buf, len, num_octets)) < 0) 00258 return -1; 00259 if (enclen > 0) { 00260 memcpy(&buf[*len], &data[octet_idx], enclen); 00261 *len += enclen; 00262 } 00263 if (enclen >= num_octets) 00264 break; 00265 } 00266 00267 return 0; 00268 }
static struct ast_udptl_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 957 of file udptl.c.
References ast_udptl_protocol::next, 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, | |||
uint8_t * | ifp, | |||
int | ifp_len | |||
) | [static] |
Definition at line 489 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().
00490 { 00491 uint8_t fec[LOCAL_FAX_MAX_DATAGRAM]; 00492 int i; 00493 int j; 00494 int seq; 00495 int entry; 00496 int entries; 00497 int span; 00498 int m; 00499 int len; 00500 int limit; 00501 int high_tide; 00502 00503 seq = s->tx_seq_no & 0xFFFF; 00504 00505 /* Map the sequence number to an entry in the circular buffer */ 00506 entry = seq & UDPTL_BUF_MASK; 00507 00508 /* We save the message in a circular buffer, for generating FEC or 00509 redundancy sets later on. */ 00510 s->tx[entry].buf_len = ifp_len; 00511 memcpy(s->tx[entry].buf, ifp, ifp_len); 00512 00513 /* Build the UDPTLPacket */ 00514 00515 len = 0; 00516 /* Encode the sequence number */ 00517 buf[len++] = (seq >> 8) & 0xFF; 00518 buf[len++] = seq & 0xFF; 00519 00520 /* Encode the primary IFP packet */ 00521 if (encode_open_type(buf, &len, ifp, ifp_len) < 0) 00522 return -1; 00523 00524 /* Encode the appropriate type of error recovery information */ 00525 switch (s->error_correction_scheme) 00526 { 00527 case UDPTL_ERROR_CORRECTION_NONE: 00528 /* Encode the error recovery type */ 00529 buf[len++] = 0x00; 00530 /* The number of entries will always be zero, so it is pointless allowing 00531 for the fragmented case here. */ 00532 if (encode_length(buf, &len, 0) < 0) 00533 return -1; 00534 break; 00535 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00536 /* Encode the error recovery type */ 00537 buf[len++] = 0x00; 00538 if (s->tx_seq_no > s->error_correction_entries) 00539 entries = s->error_correction_entries; 00540 else 00541 entries = s->tx_seq_no; 00542 /* The number of entries will always be small, so it is pointless allowing 00543 for the fragmented case here. */ 00544 if (encode_length(buf, &len, entries) < 0) 00545 return -1; 00546 /* Encode the elements */ 00547 for (i = 0; i < entries; i++) { 00548 j = (entry - i - 1) & UDPTL_BUF_MASK; 00549 if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) 00550 return -1; 00551 } 00552 break; 00553 case UDPTL_ERROR_CORRECTION_FEC: 00554 span = s->error_correction_span; 00555 entries = s->error_correction_entries; 00556 if (seq < s->error_correction_span*s->error_correction_entries) { 00557 /* In the initial stages, wind up the FEC smoothly */ 00558 entries = seq/s->error_correction_span; 00559 if (seq < s->error_correction_span) 00560 span = 0; 00561 } 00562 /* Encode the error recovery type */ 00563 buf[len++] = 0x80; 00564 /* Span is defined as an inconstrained integer, which it dumb. It will only 00565 ever be a small value. Treat it as such. */ 00566 buf[len++] = 1; 00567 buf[len++] = span; 00568 /* The number of entries is defined as a length, but will only ever be a small 00569 value. Treat it as such. */ 00570 buf[len++] = entries; 00571 for (m = 0; m < entries; m++) { 00572 /* Make an XOR'ed entry the maximum length */ 00573 limit = (entry + m) & UDPTL_BUF_MASK; 00574 high_tide = 0; 00575 for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { 00576 if (high_tide < s->tx[i].buf_len) { 00577 for (j = 0; j < high_tide; j++) 00578 fec[j] ^= s->tx[i].buf[j]; 00579 for ( ; j < s->tx[i].buf_len; j++) 00580 fec[j] = s->tx[i].buf[j]; 00581 high_tide = s->tx[i].buf_len; 00582 } else { 00583 for (j = 0; j < s->tx[i].buf_len; j++) 00584 fec[j] ^= s->tx[i].buf[j]; 00585 } 00586 } 00587 if (encode_open_type(buf, &len, fec, high_tide) < 0) 00588 return -1; 00589 } 00590 break; 00591 } 00592 00593 if (s->verbose) 00594 fprintf(stderr, "\n"); 00595 00596 s->tx_seq_no++; 00597 return len; 00598 }
static int udptl_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 145 of file udptl.c.
References udptldebugaddr.
Referenced by ast_udptl_read(), and ast_udptl_write().
00146 { 00147 if (udptldebug == 0) 00148 return 0; 00149 if (udptldebugaddr.sin_addr.s_addr) { 00150 if (((ntohs(udptldebugaddr.sin_port) != 0) 00151 && (udptldebugaddr.sin_port != addr->sin_port)) 00152 || (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00153 return 0; 00154 } 00155 return 1; 00156 }
static int udptl_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1125 of file udptl.c.
References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, udptl_do_debug_ip(), and udptldebugaddr.
01126 { 01127 if (argc != 2) { 01128 if (argc != 4) 01129 return RESULT_SHOWUSAGE; 01130 return udptl_do_debug_ip(fd, argc, argv); 01131 } 01132 udptldebug = 1; 01133 memset(&udptldebugaddr,0,sizeof(udptldebugaddr)); 01134 ast_cli(fd, "UDPTL Debugging Enabled\n"); 01135 return RESULT_SUCCESS; 01136 }
static int udptl_do_debug_ip | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1093 of file udptl.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and udptldebugaddr.
Referenced by udptl_do_debug().
01094 { 01095 struct hostent *hp; 01096 struct ast_hostent ahp; 01097 int port; 01098 char *p; 01099 char *arg; 01100 01101 port = 0; 01102 if (argc != 4) 01103 return RESULT_SHOWUSAGE; 01104 arg = argv[3]; 01105 p = strstr(arg, ":"); 01106 if (p) { 01107 *p = '\0'; 01108 p++; 01109 port = atoi(p); 01110 } 01111 hp = ast_gethostbyname(arg, &ahp); 01112 if (hp == NULL) 01113 return RESULT_SHOWUSAGE; 01114 udptldebugaddr.sin_family = AF_INET; 01115 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr)); 01116 udptldebugaddr.sin_port = htons(port); 01117 if (port == 0) 01118 ast_cli(fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr)); 01119 else 01120 ast_cli(fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port); 01121 udptldebug = 1; 01122 return RESULT_SUCCESS; 01123 }
static int udptl_nodebug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1138 of file udptl.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01139 { 01140 if (argc != 3) 01141 return RESULT_SHOWUSAGE; 01142 udptldebug = 0; 01143 ast_cli(fd,"UDPTL Debugging Disabled\n"); 01144 return RESULT_SUCCESS; 01145 }
static int udptl_rx_packet | ( | struct ast_udptl * | s, | |
uint8_t * | buf, | |||
int | len | |||
) | [static] |
Definition at line 271 of file udptl.c.
References AST_FRAME_MODEM, AST_LIST_NEXT, AST_MODEM_T38, udptl_fec_rx_buffer_t::buf, udptl_fec_rx_buffer_t::buf_len, ast_frame::data, ast_frame::datalen, decode_length(), decode_open_type(), ast_udptl::f, udptl_fec_rx_buffer_t::fec, udptl_fec_rx_buffer_t::fec_entries, udptl_fec_rx_buffer_t::fec_len, udptl_fec_rx_buffer_t::fec_span, ast_frame::frametype, LOCAL_FAX_MAX_DATAGRAM, ast_frame::mallocd, ast_frame::offset, ast_udptl::rx, ast_udptl::rx_seq_no, ast_frame::src, ast_frame::subclass, TRUE, and UDPTL_BUF_MASK.
Referenced by ast_udptl_read().
00272 { 00273 int stat; 00274 int stat2; 00275 int i; 00276 int j; 00277 int k; 00278 int l; 00279 int m; 00280 int x; 00281 int limit; 00282 int which; 00283 int ptr; 00284 int count; 00285 int total_count; 00286 int seq_no; 00287 const uint8_t *ifp; 00288 const uint8_t *data; 00289 int ifp_len; 00290 int repaired[16]; 00291 const uint8_t *bufs[16]; 00292 int lengths[16]; 00293 int span; 00294 int entries; 00295 int ifp_no; 00296 00297 ptr = 0; 00298 ifp_no = 0; 00299 memset(&s->f[0], 0, sizeof(s->f[0])); 00300 00301 /* Decode seq_number */ 00302 if (ptr + 2 > len) 00303 return -1; 00304 seq_no = (buf[0] << 8) | buf[1]; 00305 ptr += 2; 00306 00307 /* Break out the primary packet */ 00308 if ((stat = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0) 00309 return -1; 00310 /* Decode error_recovery */ 00311 if (ptr + 1 > len) 00312 return -1; 00313 if ((buf[ptr++] & 0x80) == 0) { 00314 /* Secondary packet mode for error recovery */ 00315 if (seq_no > s->rx_seq_no) { 00316 /* We received a later packet than we expected, so we need to check if we can fill in the gap from the 00317 secondary packets. */ 00318 total_count = 0; 00319 do { 00320 if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) 00321 return -1; 00322 for (i = 0; i < count; i++) { 00323 if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) 00324 return -1; 00325 } 00326 total_count += count; 00327 } 00328 while (stat2 > 0); 00329 /* Step through in reverse order, so we go oldest to newest */ 00330 for (i = total_count; i > 0; i--) { 00331 if (seq_no - i >= s->rx_seq_no) { 00332 /* This one wasn't seen before */ 00333 /* Decode the secondary IFP packet */ 00334 //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); 00335 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00336 s->f[ifp_no].subclass = AST_MODEM_T38; 00337 00338 s->f[ifp_no].mallocd = 0; 00339 //s->f[ifp_no].???seq_no = seq_no - i; 00340 s->f[ifp_no].datalen = lengths[i - 1]; 00341 s->f[ifp_no].data = (uint8_t *) bufs[i - 1]; 00342 s->f[ifp_no].offset = 0; 00343 s->f[ifp_no].src = "UDPTL"; 00344 if (ifp_no > 0) 00345 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00346 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00347 ifp_no++; 00348 } 00349 } 00350 } 00351 /* If packets are received out of sequence, we may have already processed this packet from the error 00352 recovery information in a packet already received. */ 00353 if (seq_no >= s->rx_seq_no) { 00354 /* Decode the primary IFP packet */ 00355 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00356 s->f[ifp_no].subclass = AST_MODEM_T38; 00357 00358 s->f[ifp_no].mallocd = 0; 00359 //s->f[ifp_no].???seq_no = seq_no; 00360 s->f[ifp_no].datalen = ifp_len; 00361 s->f[ifp_no].data = (uint8_t *) ifp; 00362 s->f[ifp_no].offset = 0; 00363 s->f[ifp_no].src = "UDPTL"; 00364 if (ifp_no > 0) 00365 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00366 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00367 } 00368 } 00369 else 00370 { 00371 /* FEC mode for error recovery */ 00372 /* Our buffers cannot tolerate overlength IFP packets in FEC mode */ 00373 if (ifp_len > LOCAL_FAX_MAX_DATAGRAM) 00374 return -1; 00375 /* Update any missed slots in the buffer */ 00376 for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) { 00377 x = s->rx_seq_no & UDPTL_BUF_MASK; 00378 s->rx[x].buf_len = -1; 00379 s->rx[x].fec_len[0] = 0; 00380 s->rx[x].fec_span = 0; 00381 s->rx[x].fec_entries = 0; 00382 } 00383 00384 x = seq_no & UDPTL_BUF_MASK; 00385 00386 memset(repaired, 0, sizeof(repaired)); 00387 00388 /* Save the new IFP packet */ 00389 memcpy(s->rx[x].buf, ifp, ifp_len); 00390 s->rx[x].buf_len = ifp_len; 00391 repaired[x] = TRUE; 00392 00393 /* Decode the FEC packets */ 00394 /* The span is defined as an unconstrained integer, but will never be more 00395 than a small value. */ 00396 if (ptr + 2 > len) 00397 return -1; 00398 if (buf[ptr++] != 1) 00399 return -1; 00400 span = buf[ptr++]; 00401 s->rx[x].fec_span = span; 00402 00403 /* The number of entries is defined as a length, but will only ever be a small 00404 value. Treat it as such. */ 00405 if (ptr + 1 > len) 00406 return -1; 00407 entries = buf[ptr++]; 00408 s->rx[x].fec_entries = entries; 00409 00410 /* Decode the elements */ 00411 for (i = 0; i < entries; i++) { 00412 if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) 00413 return -1; 00414 if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM) 00415 return -1; 00416 00417 /* Save the new FEC data */ 00418 memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); 00419 #if 0 00420 fprintf(stderr, "FEC: "); 00421 for (j = 0; j < s->rx[x].fec_len[i]; j++) 00422 fprintf(stderr, "%02X ", data[j]); 00423 fprintf(stderr, "\n"); 00424 #endif 00425 } 00426 00427 /* See if we can reconstruct anything which is missing */ 00428 /* TODO: this does not comprehensively hunt back and repair everything that is possible */ 00429 for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { 00430 if (s->rx[l].fec_len[0] <= 0) 00431 continue; 00432 for (m = 0; m < s->rx[l].fec_entries; m++) { 00433 limit = (l + m) & UDPTL_BUF_MASK; 00434 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) { 00435 if (s->rx[k].buf_len <= 0) 00436 which = (which == -1) ? k : -2; 00437 } 00438 if (which >= 0) { 00439 /* Repairable */ 00440 for (j = 0; j < s->rx[l].fec_len[m]; j++) { 00441 s->rx[which].buf[j] = s->rx[l].fec[m][j]; 00442 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) 00443 s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; 00444 } 00445 s->rx[which].buf_len = s->rx[l].fec_len[m]; 00446 repaired[which] = TRUE; 00447 } 00448 } 00449 } 00450 /* Now play any new packets forwards in time */ 00451 for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { 00452 if (repaired[l]) { 00453 //fprintf(stderr, "Fixed packet %d, len %d\n", j, l); 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].???seq_no = j; 00459 s->f[ifp_no].datalen = s->rx[l].buf_len; 00460 s->f[ifp_no].data = s->rx[l].buf; 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 ifp_no++; 00467 } 00468 } 00469 /* Decode the primary IFP packet */ 00470 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00471 s->f[ifp_no].subclass = AST_MODEM_T38; 00472 00473 s->f[ifp_no].mallocd = 0; 00474 //s->f[ifp_no].???seq_no = j; 00475 s->f[ifp_no].datalen = ifp_len; 00476 s->f[ifp_no].data = (uint8_t *) ifp; 00477 s->f[ifp_no].offset = 0; 00478 s->f[ifp_no].src = "UDPTL"; 00479 if (ifp_no > 0) 00480 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00481 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00482 } 00483 00484 s->rx_seq_no = seq_no + 1; 00485 return 0; 00486 }
static int udptlread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 620 of file udptl.c.
References ast_udptl_read(), ast_udptl::callback, ast_udptl::data, and f.
Referenced by ast_udptl_new_with_bindaddr().
00621 { 00622 struct ast_udptl *udptl = cbdata; 00623 struct ast_frame *f; 00624 00625 if ((f = ast_udptl_read(udptl))) { 00626 if (udptl->callback) 00627 udptl->callback(udptl, f, udptl->data); 00628 } 00629 return 1; 00630 }
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 140 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] |