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