#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include "asterisk/udptl.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"
Go to the source code of this file.
Data Structures | |
struct | ast_udptl |
Structure for an UDPTL session. More... | |
struct | protos |
List of current sessions. More... | |
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 | |
static void | __ast_udptl_reload (int reload) |
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) |
int | 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_setqos (struct ast_udptl *udptl, int tos, int cos) |
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 char * | handle_cli_udptl_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_udptl_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
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_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_handle_udptl_debug_deprecated = { .handler = handle_cli_udptl_debug_deprecated , .summary = "Enable/Disable UDPTL debugging" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_udptl [] |
static int | udptldebug |
static struct sockaddr_in | udptldebugaddr |
static int | udptlend = 4599 |
static int | udptlfecentries |
static int | udptlfecspan |
static int | udptlfectype |
static int | udptlmaxdatagram |
static int | udptlstart = 4500 |
Definition in file udptl.c.
#define LOCAL_FAX_MAX_DATAGRAM 1400 |
Definition at line 89 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 |
static void __ast_udptl_reload | ( | int | reload | ) | [static] |
Definition at line 1226 of file udptl.c.
References ast_config_destroy(), ast_config_load2(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, LOCAL_FAX_MAX_DATAGRAM, LOG_WARNING, MAX_FEC_ENTRIES, MAX_FEC_SPAN, and s.
Referenced by ast_udptl_init(), and ast_udptl_reload().
01227 { 01228 struct ast_config *cfg; 01229 const char *s; 01230 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01231 01232 if ((cfg = ast_config_load2("udptl.conf", "udptl", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 01233 return; 01234 01235 udptlstart = 4500; 01236 udptlend = 4999; 01237 udptlfectype = 0; 01238 udptlfecentries = 0; 01239 udptlfecspan = 0; 01240 udptlmaxdatagram = 0; 01241 01242 if (cfg) { 01243 if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) { 01244 udptlstart = atoi(s); 01245 if (udptlstart < 1024) { 01246 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01247 udptlstart = 1024; 01248 } 01249 if (udptlstart > 65535) { 01250 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01251 udptlstart = 65535; 01252 } 01253 } 01254 if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) { 01255 udptlend = atoi(s); 01256 if (udptlend < 1024) { 01257 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01258 udptlend = 1024; 01259 } 01260 if (udptlend > 65535) { 01261 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01262 udptlend = 65535; 01263 } 01264 } 01265 if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) { 01266 #ifdef SO_NO_CHECK 01267 if (ast_false(s)) 01268 nochecksums = 1; 01269 else 01270 nochecksums = 0; 01271 #else 01272 if (ast_false(s)) 01273 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n"); 01274 #endif 01275 } 01276 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) { 01277 if (strcmp(s, "t38UDPFEC") == 0) 01278 udptlfectype = 2; 01279 else if (strcmp(s, "t38UDPRedundancy") == 0) 01280 udptlfectype = 1; 01281 } 01282 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) { 01283 udptlmaxdatagram = atoi(s); 01284 if (udptlmaxdatagram < 100) { 01285 ast_log(LOG_WARNING, "Too small T38FaxMaxDatagram size. Defaulting to 100.\n"); 01286 udptlmaxdatagram = 100; 01287 } 01288 if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM) { 01289 ast_log(LOG_WARNING, "Too large T38FaxMaxDatagram size. Defaulting to %d.\n", LOCAL_FAX_MAX_DATAGRAM); 01290 udptlmaxdatagram = LOCAL_FAX_MAX_DATAGRAM; 01291 } 01292 } 01293 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) { 01294 udptlfecentries = atoi(s); 01295 if (udptlfecentries < 1) { 01296 ast_log(LOG_WARNING, "Too small UDPTLFECentries value. Defaulting to 1.\n"); 01297 udptlfecentries = 1; 01298 } 01299 if (udptlfecentries > MAX_FEC_ENTRIES) { 01300 ast_log(LOG_WARNING, "Too large UDPTLFECentries value. Defaulting to %d.\n", MAX_FEC_ENTRIES); 01301 udptlfecentries = MAX_FEC_ENTRIES; 01302 } 01303 } 01304 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) { 01305 udptlfecspan = atoi(s); 01306 if (udptlfecspan < 1) { 01307 ast_log(LOG_WARNING, "Too small UDPTLFECspan value. Defaulting to 1.\n"); 01308 udptlfecspan = 1; 01309 } 01310 if (udptlfecspan > MAX_FEC_SPAN) { 01311 ast_log(LOG_WARNING, "Too large UDPTLFECspan value. Defaulting to %d.\n", MAX_FEC_SPAN); 01312 udptlfecspan = MAX_FEC_SPAN; 01313 } 01314 } 01315 ast_config_destroy(cfg); 01316 } 01317 if (udptlstart >= udptlend) { 01318 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end\n"); 01319 udptlstart = 4500; 01320 udptlend = 4999; 01321 } 01322 ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend); 01323 }
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 973 of file udptl.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_debug, 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_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_udptl_protocol::set_udptl_peer, and ast_channel::tech_pvt.
00974 { 00975 struct ast_frame *f; 00976 struct ast_channel *who; 00977 struct ast_channel *cs[3]; 00978 struct ast_udptl *p0; 00979 struct ast_udptl *p1; 00980 struct ast_udptl_protocol *pr0; 00981 struct ast_udptl_protocol *pr1; 00982 struct sockaddr_in ac0; 00983 struct sockaddr_in ac1; 00984 struct sockaddr_in t0; 00985 struct sockaddr_in t1; 00986 void *pvt0; 00987 void *pvt1; 00988 int to; 00989 00990 ast_channel_lock(c0); 00991 while (ast_channel_trylock(c1)) { 00992 ast_channel_unlock(c0); 00993 usleep(1); 00994 ast_channel_lock(c0); 00995 } 00996 pr0 = get_proto(c0); 00997 pr1 = get_proto(c1); 00998 if (!pr0) { 00999 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01000 ast_channel_unlock(c0); 01001 ast_channel_unlock(c1); 01002 return -1; 01003 } 01004 if (!pr1) { 01005 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01006 ast_channel_unlock(c0); 01007 ast_channel_unlock(c1); 01008 return -1; 01009 } 01010 pvt0 = c0->tech_pvt; 01011 pvt1 = c1->tech_pvt; 01012 p0 = pr0->get_udptl_info(c0); 01013 p1 = pr1->get_udptl_info(c1); 01014 if (!p0 || !p1) { 01015 /* Somebody doesn't want to play... */ 01016 ast_channel_unlock(c0); 01017 ast_channel_unlock(c1); 01018 return -2; 01019 } 01020 if (pr0->set_udptl_peer(c0, p1)) { 01021 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01022 memset(&ac1, 0, sizeof(ac1)); 01023 } else { 01024 /* Store UDPTL peer */ 01025 ast_udptl_get_peer(p1, &ac1); 01026 } 01027 if (pr1->set_udptl_peer(c1, p0)) { 01028 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01029 memset(&ac0, 0, sizeof(ac0)); 01030 } else { 01031 /* Store UDPTL peer */ 01032 ast_udptl_get_peer(p0, &ac0); 01033 } 01034 ast_channel_unlock(c0); 01035 ast_channel_unlock(c1); 01036 cs[0] = c0; 01037 cs[1] = c1; 01038 cs[2] = NULL; 01039 for (;;) { 01040 if ((c0->tech_pvt != pvt0) || 01041 (c1->tech_pvt != pvt1) || 01042 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01043 ast_debug(1, "Oooh, something is weird, backing out\n"); 01044 /* Tell it to try again later */ 01045 return -3; 01046 } 01047 to = -1; 01048 ast_udptl_get_peer(p1, &t1); 01049 ast_udptl_get_peer(p0, &t0); 01050 if (inaddrcmp(&t1, &ac1)) { 01051 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 01052 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port)); 01053 ast_debug(1, "Oooh, '%s' was %s:%d\n", 01054 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port)); 01055 memcpy(&ac1, &t1, sizeof(ac1)); 01056 } 01057 if (inaddrcmp(&t0, &ac0)) { 01058 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 01059 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port)); 01060 ast_debug(1, "Oooh, '%s' was %s:%d\n", 01061 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port)); 01062 memcpy(&ac0, &t0, sizeof(ac0)); 01063 } 01064 who = ast_waitfor_n(cs, 2, &to); 01065 if (!who) { 01066 ast_debug(1, "Ooh, empty read...\n"); 01067 /* check for hangup / whentohangup */ 01068 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01069 break; 01070 continue; 01071 } 01072 f = ast_read(who); 01073 if (!f) { 01074 *fo = f; 01075 *rc = who; 01076 ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01077 /* That's all we needed */ 01078 return 0; 01079 } else { 01080 if (f->frametype == AST_FRAME_MODEM) { 01081 /* Forward T.38 frames if they happen upon us */ 01082 if (who == c0) { 01083 ast_write(c1, f); 01084 } else if (who == c1) { 01085 ast_write(c0, f); 01086 } 01087 } 01088 ast_frfree(f); 01089 } 01090 /* Swap priority. Not that it's a big deal at this point */ 01091 cs[2] = cs[0]; 01092 cs[0] = cs[1]; 01093 cs[1] = cs[2]; 01094 } 01095 return -1; 01096 }
void ast_udptl_destroy | ( | struct ast_udptl * | udptl | ) |
Definition at line 885 of file udptl.c.
References ast_free, ast_io_remove(), ast_udptl::fd, ast_udptl::io, and ast_udptl::ioid.
Referenced by __sip_destroy(), and create_addr_from_peer().
00886 { 00887 if (udptl->ioid) 00888 ast_io_remove(udptl->io, udptl->ioid); 00889 if (udptl->fd > -1) 00890 close(udptl->fd); 00891 ast_free(udptl); 00892 }
int ast_udptl_fd | ( | struct ast_udptl * | udptl | ) |
Definition at line 615 of file udptl.c.
References ast_udptl::fd.
Referenced by __oh323_new(), and sip_new().
00616 { 00617 return udptl->fd; 00618 }
int ast_udptl_get_error_correction_scheme | ( | struct ast_udptl * | udptl | ) |
Definition at line 706 of file udptl.c.
References ast_log(), ast_udptl::error_correction_scheme, and LOG_WARNING.
Referenced by set_t38_capabilities().
00707 { 00708 if (udptl) 00709 return udptl->error_correction_scheme; 00710 else { 00711 ast_log(LOG_WARNING, "udptl structure is null\n"); 00712 return -1; 00713 } 00714 }
int ast_udptl_get_far_max_datagram | ( | struct ast_udptl * | udptl | ) |
Definition at line 746 of file udptl.c.
References ast_log(), ast_udptl::far_max_datagram_size, and LOG_WARNING.
00747 { 00748 if (udptl) 00749 return udptl->far_max_datagram_size; 00750 else { 00751 ast_log(LOG_WARNING, "udptl structure is null\n"); 00752 return -1; 00753 } 00754 }
int ast_udptl_get_local_max_datagram | ( | struct ast_udptl * | udptl | ) |
Definition at line 736 of file udptl.c.
References ast_log(), ast_udptl::local_max_datagram_size, and LOG_WARNING.
Referenced by add_sdp().
00737 { 00738 if (udptl) 00739 return udptl->local_max_datagram_size; 00740 else { 00741 ast_log(LOG_WARNING, "udptl structure is null\n"); 00742 return -1; 00743 } 00744 }
void ast_udptl_get_peer | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | them | |||
) |
Definition at line 866 of file udptl.c.
References ast_udptl::them.
Referenced by ast_udptl_bridge(), and sip_set_udptl_peer().
00867 { 00868 memset(them, 0, sizeof(*them)); 00869 them->sin_family = AF_INET; 00870 them->sin_port = udptl->them.sin_port; 00871 them->sin_addr = udptl->them.sin_addr; 00872 }
void ast_udptl_get_us | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | us | |||
) |
void ast_udptl_init | ( | void | ) |
Definition at line 1331 of file udptl.c.
References __ast_udptl_reload(), ast_cli_register_multiple(), and cli_udptl.
Referenced by main().
01332 { 01333 ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry)); 01334 __ast_udptl_reload(0); 01335 }
struct ast_udptl* ast_udptl_new | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | callbackmode | |||
) |
Definition at line 848 of file udptl.c.
References ast_udptl_new_with_bindaddr(), io, and sched.
00849 { 00850 struct in_addr ia; 00851 memset(&ia, 0, sizeof(ia)); 00852 return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia); 00853 }
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 772 of file udptl.c.
References ast_calloc, ast_free, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), errno, ast_udptl::flags, io, LOG_WARNING, sched, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and udptlread().
Referenced by ast_udptl_new(), create_addr_from_peer(), and sip_alloc().
00773 { 00774 struct ast_udptl *udptl; 00775 int x; 00776 int startplace; 00777 int i; 00778 long int flags; 00779 00780 if (!(udptl = ast_calloc(1, sizeof(*udptl)))) 00781 return NULL; 00782 00783 if (udptlfectype == 2) 00784 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00785 else if (udptlfectype == 1) 00786 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00787 else 00788 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00789 udptl->error_correction_span = udptlfecspan; 00790 udptl->error_correction_entries = udptlfecentries; 00791 00792 udptl->far_max_datagram_size = udptlmaxdatagram; 00793 udptl->local_max_datagram_size = udptlmaxdatagram; 00794 00795 memset(&udptl->rx, 0, sizeof(udptl->rx)); 00796 memset(&udptl->tx, 0, sizeof(udptl->tx)); 00797 for (i = 0; i <= UDPTL_BUF_MASK; i++) { 00798 udptl->rx[i].buf_len = -1; 00799 udptl->tx[i].buf_len = -1; 00800 } 00801 00802 udptl->them.sin_family = AF_INET; 00803 udptl->us.sin_family = AF_INET; 00804 00805 if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00806 ast_free(udptl); 00807 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00808 return NULL; 00809 } 00810 flags = fcntl(udptl->fd, F_GETFL); 00811 fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK); 00812 #ifdef SO_NO_CHECK 00813 if (nochecksums) 00814 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00815 #endif 00816 /* Find us a place */ 00817 x = (udptlstart == udptlend) ? udptlstart : (ast_random() % (udptlend - udptlstart)) + udptlstart; 00818 startplace = x; 00819 for (;;) { 00820 udptl->us.sin_port = htons(x); 00821 udptl->us.sin_addr = addr; 00822 if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0) 00823 break; 00824 if (errno != EADDRINUSE) { 00825 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00826 close(udptl->fd); 00827 ast_free(udptl); 00828 return NULL; 00829 } 00830 if (++x > udptlend) 00831 x = udptlstart; 00832 if (x == startplace) { 00833 ast_log(LOG_WARNING, "No UDPTL ports remaining\n"); 00834 close(udptl->fd); 00835 ast_free(udptl); 00836 return NULL; 00837 } 00838 } 00839 if (io && sched && callbackmode) { 00840 /* Operate this one in a callback mode */ 00841 udptl->sched = sched; 00842 udptl->io = io; 00843 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl); 00844 } 00845 return udptl; 00846 }
void ast_udptl_offered_from_local | ( | struct ast_udptl * | udptl, | |
int | local | |||
) |
Definition at line 698 of file udptl.c.
References ast_log(), LOG_WARNING, and ast_udptl::udptl_offered_from_local.
Referenced by transmit_invite(), and transmit_response_with_t38_sdp().
00699 { 00700 if (udptl) 00701 udptl->udptl_offered_from_local = local; 00702 else 00703 ast_log(LOG_WARNING, "udptl structure is null\n"); 00704 }
int ast_udptl_proto_register | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 942 of file udptl.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_udptl_protocol::list, LOG_WARNING, and ast_udptl_protocol::type.
Referenced by load_module().
00943 { 00944 struct ast_udptl_protocol *cur; 00945 00946 AST_RWLIST_WRLOCK(&protos); 00947 AST_RWLIST_TRAVERSE(&protos, cur, list) { 00948 if (cur->type == proto->type) { 00949 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 00950 AST_RWLIST_UNLOCK(&protos); 00951 return -1; 00952 } 00953 } 00954 AST_RWLIST_INSERT_TAIL(&protos, proto, list); 00955 AST_RWLIST_UNLOCK(&protos); 00956 return 0; 00957 }
void ast_udptl_proto_unregister | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 935 of file udptl.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by unload_module().
00936 { 00937 AST_RWLIST_WRLOCK(&protos); 00938 AST_RWLIST_REMOVE(&protos, proto, list); 00939 AST_RWLIST_UNLOCK(&protos); 00940 }
Definition at line 647 of file udptl.c.
References ast_assert, ast_debug, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verb, errno, ast_udptl::f, ast_udptl::fd, len(), 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().
00648 { 00649 int res; 00650 struct sockaddr_in sin; 00651 socklen_t len; 00652 uint16_t seqno = 0; 00653 uint16_t *udptlheader; 00654 00655 len = sizeof(sin); 00656 00657 /* Cache where the header will go */ 00658 res = recvfrom(udptl->fd, 00659 udptl->rawdata + AST_FRIENDLY_OFFSET, 00660 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET, 00661 0, 00662 (struct sockaddr *) &sin, 00663 &len); 00664 udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET); 00665 if (res < 0) { 00666 if (errno != EAGAIN) 00667 ast_log(LOG_WARNING, "UDPTL read error: %s\n", strerror(errno)); 00668 ast_assert(errno != EBADF); 00669 return &ast_null_frame; 00670 } 00671 00672 /* Ignore if the other side hasn't been given an address yet. */ 00673 if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port) 00674 return &ast_null_frame; 00675 00676 if (udptl->nat) { 00677 /* Send to whoever sent to us */ 00678 if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00679 (udptl->them.sin_port != sin.sin_port)) { 00680 memcpy(&udptl->them, &sin, sizeof(udptl->them)); 00681 ast_debug(1, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00682 } 00683 } 00684 00685 if (udptl_debug_test_addr(&sin)) { 00686 ast_verb(1, "Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n", 00687 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res); 00688 } 00689 #if 0 00690 printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res); 00691 #endif 00692 if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1) 00693 return &ast_null_frame; 00694 00695 return &udptl->f[0]; 00696 }
int ast_udptl_reload | ( | void | ) |
Definition at line 1325 of file udptl.c.
References __ast_udptl_reload().
01326 { 01327 __ast_udptl_reload(1); 01328 return 0; 01329 }
void ast_udptl_set_callback | ( | struct ast_udptl * | udptl, | |
ast_udptl_callback | callback | |||
) |
Definition at line 625 of file udptl.c.
References ast_udptl::callback.
00626 { 00627 udptl->callback = callback; 00628 }
void ast_udptl_set_data | ( | struct ast_udptl * | udptl, | |
void * | data | |||
) |
Definition at line 620 of file udptl.c.
References ast_udptl::data.
00621 { 00622 udptl->data = data; 00623 }
void ast_udptl_set_error_correction_scheme | ( | struct ast_udptl * | udptl, | |
int | ec | |||
) |
Definition at line 716 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().
00717 { 00718 if (udptl) { 00719 switch (ec) { 00720 case UDPTL_ERROR_CORRECTION_FEC: 00721 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00722 break; 00723 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00724 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00725 break; 00726 case UDPTL_ERROR_CORRECTION_NONE: 00727 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE; 00728 break; 00729 default: 00730 ast_log(LOG_WARNING, "error correction parameter invalid\n"); 00731 }; 00732 } else 00733 ast_log(LOG_WARNING, "udptl structure is null\n"); 00734 }
void ast_udptl_set_far_max_datagram | ( | struct ast_udptl * | udptl, | |
int | max_datagram | |||
) |
Definition at line 764 of file udptl.c.
References ast_log(), ast_udptl::far_max_datagram_size, and LOG_WARNING.
Referenced by process_sdp().
00765 { 00766 if (udptl) 00767 udptl->far_max_datagram_size = max_datagram; 00768 else 00769 ast_log(LOG_WARNING, "udptl structure is null\n"); 00770 }
void ast_udptl_set_local_max_datagram | ( | struct ast_udptl * | udptl, | |
int | max_datagram | |||
) |
Definition at line 756 of file udptl.c.
References ast_log(), ast_udptl::local_max_datagram_size, and LOG_WARNING.
Referenced by process_sdp().
00757 { 00758 if (udptl) 00759 udptl->local_max_datagram_size = max_datagram; 00760 else 00761 ast_log(LOG_WARNING, "udptl structure is null\n"); 00762 }
void ast_udptl_set_peer | ( | struct ast_udptl * | udptl, | |
struct sockaddr_in * | them | |||
) |
Definition at line 860 of file udptl.c.
References ast_udptl::them.
Referenced by process_sdp().
00861 { 00862 udptl->them.sin_port = them->sin_port; 00863 udptl->them.sin_addr = them->sin_addr; 00864 }
void ast_udptl_setnat | ( | struct ast_udptl * | udptl, | |
int | nat | |||
) |
int ast_udptl_setqos | ( | struct ast_udptl * | udptl, | |
int | tos, | |||
int | cos | |||
) |
Definition at line 855 of file udptl.c.
References ast_netsock_set_qos(), and ast_udptl::fd.
Referenced by sip_alloc().
00856 { 00857 return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL"); 00858 }
void ast_udptl_stop | ( | struct ast_udptl * | udptl | ) |
Definition at line 879 of file udptl.c.
References ast_udptl::them.
Referenced by process_sdp(), and stop_media_flows().
00880 { 00881 memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr)); 00882 memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port)); 00883 }
Definition at line 894 of file udptl.c.
References AST_FRAME_MODEM, ast_inet_ntoa(), ast_log(), ast_verb, buf, 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().
00895 { 00896 int seq; 00897 int len; 00898 int res; 00899 uint8_t buf[LOCAL_FAX_MAX_DATAGRAM * 2]; 00900 00901 /* If we have no peer, return immediately */ 00902 if (s->them.sin_addr.s_addr == INADDR_ANY) 00903 return 0; 00904 00905 /* If there is no data length, return immediately */ 00906 if (f->datalen == 0) 00907 return 0; 00908 00909 if (f->frametype != AST_FRAME_MODEM) { 00910 ast_log(LOG_WARNING, "UDPTL can only send T.38 data\n"); 00911 return -1; 00912 } 00913 00914 /* Save seq_no for debug output because udptl_build_packet increments it */ 00915 seq = s->tx_seq_no & 0xFFFF; 00916 00917 /* Cook up the UDPTL packet, with the relevant EC info. */ 00918 len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, f->datalen); 00919 00920 if (len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) { 00921 if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0) 00922 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)); 00923 #if 0 00924 printf("Sent %d bytes of UDPTL data to %s:%d\n", res, ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00925 #endif 00926 if (udptl_debug_test_addr(&s->them)) 00927 ast_verb(1, "Sent UDPTL packet to %s:%d (type %d, seq %d, len %d)\n", 00928 ast_inet_ntoa(s->them.sin_addr), 00929 ntohs(s->them.sin_port), 0, seq, len); 00930 } 00931 00932 return 0; 00933 }
static int decode_length | ( | uint8_t * | buf, | |
int | limit, | |||
int * | len, | |||
int * | pvalue | |||
) | [static] |
Definition at line 177 of file udptl.c.
Referenced by decode_open_type(), and udptl_rx_packet().
00178 { 00179 if (*len >= limit) 00180 return -1; 00181 if ((buf[*len] & 0x80) == 0) { 00182 *pvalue = buf[*len]; 00183 (*len)++; 00184 return 0; 00185 } 00186 if ((buf[*len] & 0x40) == 0) { 00187 if (*len == limit - 1) 00188 return -1; 00189 *pvalue = (buf[*len] & 0x3F) << 8; 00190 (*len)++; 00191 *pvalue |= buf[*len]; 00192 (*len)++; 00193 return 0; 00194 } 00195 *pvalue = (buf[*len] & 0x3F) << 14; 00196 (*len)++; 00197 /* Indicate we have a fragment */ 00198 return 1; 00199 }
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 202 of file udptl.c.
References decode_length().
Referenced by udptl_rx_packet().
00203 { 00204 int octet_cnt; 00205 int octet_idx; 00206 int length; 00207 int i; 00208 const uint8_t **pbuf; 00209 00210 for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) { 00211 if ((length = decode_length(buf, limit, len, &octet_cnt)) < 0) 00212 return -1; 00213 if (octet_cnt > 0) { 00214 *p_num_octets += octet_cnt; 00215 00216 pbuf = &p_object[octet_idx]; 00217 i = 0; 00218 /* Make sure the buffer contains at least the number of bits requested */ 00219 if ((*len + octet_cnt) > limit) 00220 return -1; 00221 00222 *pbuf = &buf[*len]; 00223 *len += octet_cnt; 00224 } 00225 if (length == 0) 00226 break; 00227 } 00228 return 0; 00229 }
static int encode_length | ( | uint8_t * | buf, | |
int * | len, | |||
int | value | |||
) | [static] |
Definition at line 232 of file udptl.c.
Referenced by encode_open_type(), and udptl_build_packet().
00233 { 00234 int multiplier; 00235 00236 if (value < 0x80) { 00237 /* 1 octet */ 00238 buf[*len] = value; 00239 (*len)++; 00240 return value; 00241 } 00242 if (value < 0x4000) { 00243 /* 2 octets */ 00244 /* Set the first bit of the first octet */ 00245 buf[*len] = ((0x8000 | value) >> 8) & 0xFF; 00246 (*len)++; 00247 buf[*len] = value & 0xFF; 00248 (*len)++; 00249 return value; 00250 } 00251 /* Fragmentation */ 00252 multiplier = (value < 0x10000) ? (value >> 14) : 4; 00253 /* Set the first 2 bits of the octet */ 00254 buf[*len] = 0xC0 | multiplier; 00255 (*len)++; 00256 return multiplier << 14; 00257 }
static int encode_open_type | ( | uint8_t * | buf, | |
int | buflen, | |||
int * | len, | |||
const uint8_t * | data, | |||
int | num_octets | |||
) | [static] |
Definition at line 260 of file udptl.c.
References ast_log(), encode_length(), and LOG_ERROR.
Referenced by udptl_build_packet().
00261 { 00262 int enclen; 00263 int octet_idx; 00264 uint8_t zero_byte; 00265 00266 /* If open type is of zero length, add a single zero byte (10.1) */ 00267 if (num_octets == 0) { 00268 zero_byte = 0; 00269 data = &zero_byte; 00270 num_octets = 1; 00271 } 00272 /* Encode the open type */ 00273 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) { 00274 if ((enclen = encode_length(buf, len, num_octets)) < 0) 00275 return -1; 00276 if (enclen + *len > buflen) { 00277 ast_log(LOG_ERROR, "Buffer overflow detected (%d + %d > %d)\n", enclen, *len, buflen); 00278 return -1; 00279 } 00280 if (enclen > 0) { 00281 memcpy(&buf[*len], &data[octet_idx], enclen); 00282 *len += enclen; 00283 } 00284 if (enclen >= num_octets) 00285 break; 00286 } 00287 00288 return 0; 00289 }
static struct ast_udptl_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 959 of file udptl.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, chan, ast_udptl_protocol::list, ast_channel::tech, ast_channel_tech::type, and ast_udptl_protocol::type.
00960 { 00961 struct ast_udptl_protocol *cur = NULL; 00962 00963 AST_RWLIST_RDLOCK(&protos); 00964 AST_RWLIST_TRAVERSE(&protos, cur, list) { 00965 if (cur->type == chan->tech->type) 00966 break; 00967 } 00968 AST_RWLIST_UNLOCK(&protos); 00969 00970 return cur; 00971 }
static char* handle_cli_udptl_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1098 of file udptl.c.
References ahp, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, hp, and ast_cli_entry::usage.
01099 { 01100 struct hostent *hp; 01101 struct ast_hostent ahp; 01102 int port; 01103 char *p; 01104 char *arg; 01105 01106 switch (cmd) { 01107 case CLI_INIT: 01108 e->command = "udptl debug [off|ip]"; 01109 e->usage = 01110 "Usage: udptl debug [off]|[ip host[:port]]\n" 01111 " Enable or disable dumping of UDPTL packets.\n" 01112 " If ip is specified, limit the dumped packets to those to and from\n" 01113 " the specified 'host' with optional port.\n"; 01114 return NULL; 01115 case CLI_GENERATE: 01116 return NULL; 01117 } 01118 01119 if (a->argc < 2 || a->argc > 4) 01120 return CLI_SHOWUSAGE; 01121 01122 if (a->argc == 2) { 01123 udptldebug = 1; 01124 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr)); 01125 ast_cli(a->fd, "UDPTL Debugging Enabled\n"); 01126 } else if (a->argc == 3) { 01127 if (strncasecmp(a->argv[2], "off", 3)) 01128 return CLI_SHOWUSAGE; 01129 udptldebug = 0; 01130 ast_cli(a->fd, "UDPTL Debugging Disabled\n"); 01131 } else { 01132 if (strncasecmp(a->argv[2], "ip", 2)) 01133 return CLI_SHOWUSAGE; 01134 port = 0; 01135 arg = a->argv[3]; 01136 p = strstr(arg, ":"); 01137 if (p) { 01138 *p = '\0'; 01139 p++; 01140 port = atoi(p); 01141 } 01142 hp = ast_gethostbyname(arg, &ahp); 01143 if (hp == NULL) 01144 return CLI_SHOWUSAGE; 01145 udptldebugaddr.sin_family = AF_INET; 01146 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr)); 01147 udptldebugaddr.sin_port = htons(port); 01148 if (port == 0) 01149 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr)); 01150 else 01151 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port); 01152 udptldebug = 1; 01153 } 01154 01155 return CLI_SUCCESS; 01156 }
static char* handle_cli_udptl_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1158 of file udptl.c.
References ahp, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, hp, and ast_cli_entry::usage.
01159 { 01160 struct hostent *hp; 01161 struct ast_hostent ahp; 01162 int port; 01163 char *p; 01164 char *arg; 01165 01166 switch (cmd) { 01167 case CLI_INIT: 01168 e->command = "udptl set debug {on|off|ip}"; 01169 e->usage = 01170 "Usage: udptl set debug {on|off|ip host[:port]}\n" 01171 " Enable or disable dumping of UDPTL packets.\n" 01172 " If ip is specified, limit the dumped packets to those to and from\n" 01173 " the specified 'host' with optional port.\n"; 01174 return NULL; 01175 case CLI_GENERATE: 01176 return NULL; 01177 } 01178 01179 if (a->argc < 4 || a->argc > 5) 01180 return CLI_SHOWUSAGE; 01181 01182 if (a->argc == 4) { 01183 if (!strncasecmp(a->argv[3], "on", 2)) { 01184 udptldebug = 1; 01185 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr)); 01186 ast_cli(a->fd, "UDPTL Debugging Enabled\n"); 01187 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01188 udptldebug = 0; 01189 ast_cli(a->fd, "UDPTL Debugging Disabled\n"); 01190 } else { 01191 return CLI_SHOWUSAGE; 01192 } 01193 } else { 01194 if (strncasecmp(a->argv[3], "ip", 2)) 01195 return CLI_SHOWUSAGE; 01196 port = 0; 01197 arg = a->argv[4]; 01198 p = strstr(arg, ":"); 01199 if (p) { 01200 *p = '\0'; 01201 p++; 01202 port = atoi(p); 01203 } 01204 hp = ast_gethostbyname(arg, &ahp); 01205 if (hp == NULL) 01206 return CLI_SHOWUSAGE; 01207 udptldebugaddr.sin_family = AF_INET; 01208 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr)); 01209 udptldebugaddr.sin_port = htons(port); 01210 if (port == 0) 01211 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr)); 01212 else 01213 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port); 01214 udptldebug = 1; 01215 } 01216 01217 return CLI_SUCCESS; 01218 }
static int udptl_build_packet | ( | struct ast_udptl * | s, | |
uint8_t * | buf, | |||
int | buflen, | |||
uint8_t * | ifp, | |||
int | ifp_len | |||
) | [static] |
Definition at line 500 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().
00501 { 00502 uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2]; 00503 int i; 00504 int j; 00505 int seq; 00506 int entry; 00507 int entries; 00508 int span; 00509 int m; 00510 int len; 00511 int limit; 00512 int high_tide; 00513 00514 seq = s->tx_seq_no & 0xFFFF; 00515 00516 /* Map the sequence number to an entry in the circular buffer */ 00517 entry = seq & UDPTL_BUF_MASK; 00518 00519 /* We save the message in a circular buffer, for generating FEC or 00520 redundancy sets later on. */ 00521 s->tx[entry].buf_len = ifp_len; 00522 memcpy(s->tx[entry].buf, ifp, ifp_len); 00523 00524 /* Build the UDPTLPacket */ 00525 00526 len = 0; 00527 /* Encode the sequence number */ 00528 buf[len++] = (seq >> 8) & 0xFF; 00529 buf[len++] = seq & 0xFF; 00530 00531 /* Encode the primary IFP packet */ 00532 if (encode_open_type(buf, buflen, &len, ifp, ifp_len) < 0) 00533 return -1; 00534 00535 /* Encode the appropriate type of error recovery information */ 00536 switch (s->error_correction_scheme) 00537 { 00538 case UDPTL_ERROR_CORRECTION_NONE: 00539 /* Encode the error recovery type */ 00540 buf[len++] = 0x00; 00541 /* The number of entries will always be zero, so it is pointless allowing 00542 for the fragmented case here. */ 00543 if (encode_length(buf, &len, 0) < 0) 00544 return -1; 00545 break; 00546 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00547 /* Encode the error recovery type */ 00548 buf[len++] = 0x00; 00549 if (s->tx_seq_no > s->error_correction_entries) 00550 entries = s->error_correction_entries; 00551 else 00552 entries = s->tx_seq_no; 00553 /* The number of entries will always be small, so it is pointless allowing 00554 for the fragmented case here. */ 00555 if (encode_length(buf, &len, entries) < 0) 00556 return -1; 00557 /* Encode the elements */ 00558 for (i = 0; i < entries; i++) { 00559 j = (entry - i - 1) & UDPTL_BUF_MASK; 00560 if (encode_open_type(buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) { 00561 if (option_debug) { 00562 ast_log(LOG_DEBUG, "Encoding failed at i=%d, j=%d\n", i, j); 00563 } 00564 return -1; 00565 } 00566 } 00567 break; 00568 case UDPTL_ERROR_CORRECTION_FEC: 00569 span = s->error_correction_span; 00570 entries = s->error_correction_entries; 00571 if (seq < s->error_correction_span*s->error_correction_entries) { 00572 /* In the initial stages, wind up the FEC smoothly */ 00573 entries = seq/s->error_correction_span; 00574 if (seq < s->error_correction_span) 00575 span = 0; 00576 } 00577 /* Encode the error recovery type */ 00578 buf[len++] = 0x80; 00579 /* Span is defined as an inconstrained integer, which it dumb. It will only 00580 ever be a small value. Treat it as such. */ 00581 buf[len++] = 1; 00582 buf[len++] = span; 00583 /* The number of entries is defined as a length, but will only ever be a small 00584 value. Treat it as such. */ 00585 buf[len++] = entries; 00586 for (m = 0; m < entries; m++) { 00587 /* Make an XOR'ed entry the maximum length */ 00588 limit = (entry + m) & UDPTL_BUF_MASK; 00589 high_tide = 0; 00590 for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { 00591 if (high_tide < s->tx[i].buf_len) { 00592 for (j = 0; j < high_tide; j++) 00593 fec[j] ^= s->tx[i].buf[j]; 00594 for ( ; j < s->tx[i].buf_len; j++) 00595 fec[j] = s->tx[i].buf[j]; 00596 high_tide = s->tx[i].buf_len; 00597 } else { 00598 for (j = 0; j < s->tx[i].buf_len; j++) 00599 fec[j] ^= s->tx[i].buf[j]; 00600 } 00601 } 00602 if (encode_open_type(buf, buflen, &len, fec, high_tide) < 0) 00603 return -1; 00604 } 00605 break; 00606 } 00607 00608 if (s->verbose) 00609 fprintf(stderr, "\n"); 00610 00611 s->tx_seq_no++; 00612 return len; 00613 }
static int udptl_debug_test_addr | ( | struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 164 of file udptl.c.
Referenced by ast_udptl_read(), and ast_udptl_write().
00165 { 00166 if (udptldebug == 0) 00167 return 0; 00168 if (udptldebugaddr.sin_addr.s_addr) { 00169 if (((ntohs(udptldebugaddr.sin_port) != 0) 00170 && (udptldebugaddr.sin_port != addr->sin_port)) 00171 || (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00172 return 0; 00173 } 00174 return 1; 00175 }
static int udptl_rx_packet | ( | struct ast_udptl * | s, | |
uint8_t * | buf, | |||
int | len | |||
) | [static] |
Definition at line 292 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().
00293 { 00294 int stat1; 00295 int stat2; 00296 int i; 00297 int j; 00298 int k; 00299 int l; 00300 int m; 00301 int x; 00302 int limit; 00303 int which; 00304 int ptr; 00305 int count; 00306 int total_count; 00307 int seq_no; 00308 const uint8_t *ifp; 00309 const uint8_t *data; 00310 int ifp_len; 00311 int repaired[16]; 00312 const uint8_t *bufs[16]; 00313 int lengths[16]; 00314 int span; 00315 int entries; 00316 int ifp_no; 00317 00318 ptr = 0; 00319 ifp_no = 0; 00320 memset(&s->f[0], 0, sizeof(s->f[0])); 00321 00322 /* Decode seq_number */ 00323 if (ptr + 2 > len) 00324 return -1; 00325 seq_no = (buf[0] << 8) | buf[1]; 00326 ptr += 2; 00327 00328 /* Break out the primary packet */ 00329 if ((stat1 = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0) 00330 return -1; 00331 /* Decode error_recovery */ 00332 if (ptr + 1 > len) 00333 return -1; 00334 if ((buf[ptr++] & 0x80) == 0) { 00335 /* Secondary packet mode for error recovery */ 00336 if (seq_no > s->rx_seq_no) { 00337 /* We received a later packet than we expected, so we need to check if we can fill in the gap from the 00338 secondary packets. */ 00339 total_count = 0; 00340 do { 00341 if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) 00342 return -1; 00343 for (i = 0; i < count; i++) { 00344 if ((stat1 = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) 00345 return -1; 00346 } 00347 total_count += count; 00348 } 00349 while (stat2 > 0); 00350 /* Step through in reverse order, so we go oldest to newest */ 00351 for (i = total_count; i > 0; i--) { 00352 if (seq_no - i >= s->rx_seq_no) { 00353 /* This one wasn't seen before */ 00354 /* Decode the secondary IFP packet */ 00355 //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); 00356 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00357 s->f[ifp_no].subclass = AST_MODEM_T38; 00358 00359 s->f[ifp_no].mallocd = 0; 00360 s->f[ifp_no].seqno = seq_no - i; 00361 s->f[ifp_no].datalen = lengths[i - 1]; 00362 s->f[ifp_no].data.ptr = (uint8_t *) bufs[i - 1]; 00363 s->f[ifp_no].offset = 0; 00364 s->f[ifp_no].src = "UDPTL"; 00365 if (ifp_no > 0) 00366 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00367 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00368 ifp_no++; 00369 } 00370 } 00371 } 00372 } 00373 else 00374 { 00375 /* FEC mode for error recovery */ 00376 /* Our buffers cannot tolerate overlength IFP packets in FEC mode */ 00377 if (ifp_len > LOCAL_FAX_MAX_DATAGRAM) 00378 return -1; 00379 /* Update any missed slots in the buffer */ 00380 for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) { 00381 x = s->rx_seq_no & UDPTL_BUF_MASK; 00382 s->rx[x].buf_len = -1; 00383 s->rx[x].fec_len[0] = 0; 00384 s->rx[x].fec_span = 0; 00385 s->rx[x].fec_entries = 0; 00386 } 00387 00388 x = seq_no & UDPTL_BUF_MASK; 00389 00390 memset(repaired, 0, sizeof(repaired)); 00391 00392 /* Save the new IFP packet */ 00393 memcpy(s->rx[x].buf, ifp, ifp_len); 00394 s->rx[x].buf_len = ifp_len; 00395 repaired[x] = TRUE; 00396 00397 /* Decode the FEC packets */ 00398 /* The span is defined as an unconstrained integer, but will never be more 00399 than a small value. */ 00400 if (ptr + 2 > len) 00401 return -1; 00402 if (buf[ptr++] != 1) 00403 return -1; 00404 span = buf[ptr++]; 00405 s->rx[x].fec_span = span; 00406 00407 /* The number of entries is defined as a length, but will only ever be a small 00408 value. Treat it as such. */ 00409 if (ptr + 1 > len) 00410 return -1; 00411 entries = buf[ptr++]; 00412 s->rx[x].fec_entries = entries; 00413 00414 /* Decode the elements */ 00415 for (i = 0; i < entries; i++) { 00416 if ((stat1 = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) 00417 return -1; 00418 if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM) 00419 return -1; 00420 00421 /* Save the new FEC data */ 00422 memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); 00423 #if 0 00424 fprintf(stderr, "FEC: "); 00425 for (j = 0; j < s->rx[x].fec_len[i]; j++) 00426 fprintf(stderr, "%02X ", data[j]); 00427 fprintf(stderr, "\n"); 00428 #endif 00429 } 00430 00431 /* See if we can reconstruct anything which is missing */ 00432 /* TODO: this does not comprehensively hunt back and repair everything that is possible */ 00433 for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { 00434 if (s->rx[l].fec_len[0] <= 0) 00435 continue; 00436 for (m = 0; m < s->rx[l].fec_entries; m++) { 00437 limit = (l + m) & UDPTL_BUF_MASK; 00438 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) { 00439 if (s->rx[k].buf_len <= 0) 00440 which = (which == -1) ? k : -2; 00441 } 00442 if (which >= 0) { 00443 /* Repairable */ 00444 for (j = 0; j < s->rx[l].fec_len[m]; j++) { 00445 s->rx[which].buf[j] = s->rx[l].fec[m][j]; 00446 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) 00447 s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; 00448 } 00449 s->rx[which].buf_len = s->rx[l].fec_len[m]; 00450 repaired[which] = TRUE; 00451 } 00452 } 00453 } 00454 /* Now play any new packets forwards in time */ 00455 for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { 00456 if (repaired[l]) { 00457 //fprintf(stderr, "Fixed packet %d, len %d\n", j, l); 00458 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00459 s->f[ifp_no].subclass = AST_MODEM_T38; 00460 00461 s->f[ifp_no].mallocd = 0; 00462 s->f[ifp_no].seqno = j; 00463 s->f[ifp_no].datalen = s->rx[l].buf_len; 00464 s->f[ifp_no].data.ptr = s->rx[l].buf; 00465 s->f[ifp_no].offset = 0; 00466 s->f[ifp_no].src = "UDPTL"; 00467 if (ifp_no > 0) 00468 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00469 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00470 ifp_no++; 00471 } 00472 } 00473 } 00474 00475 /* If packets are received out of sequence, we may have already processed this packet from the error 00476 recovery information in a packet already received. */ 00477 if (seq_no >= s->rx_seq_no) { 00478 /* Decode the primary IFP packet */ 00479 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00480 s->f[ifp_no].subclass = AST_MODEM_T38; 00481 00482 s->f[ifp_no].mallocd = 0; 00483 s->f[ifp_no].seqno = seq_no; 00484 s->f[ifp_no].datalen = ifp_len; 00485 s->f[ifp_no].data.ptr = (uint8_t *) ifp; 00486 s->f[ifp_no].offset = 0; 00487 s->f[ifp_no].src = "UDPTL"; 00488 if (ifp_no > 0) 00489 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00490 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00491 00492 ifp_no++; 00493 } 00494 00495 s->rx_seq_no = seq_no + 1; 00496 return ifp_no; 00497 }
static int udptlread | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 635 of file udptl.c.
References ast_udptl_read(), ast_udptl::callback, and f.
Referenced by ast_udptl_new_with_bindaddr().
00636 { 00637 struct ast_udptl *udptl = cbdata; 00638 struct ast_frame *f; 00639 00640 if ((f = ast_udptl_read(udptl))) { 00641 if (udptl->callback) 00642 udptl->callback(udptl, f, udptl->data); 00643 } 00644 return 1; 00645 }
struct ast_cli_entry cli_handle_udptl_debug_deprecated = { .handler = handle_cli_udptl_debug_deprecated , .summary = "Enable/Disable UDPTL debugging" ,__VA_ARGS__ } [static] |
struct ast_cli_entry cli_udptl[] [static] |
Initial value:
{ { .handler = handle_cli_udptl_set_debug , .summary = "Enable/Disable UDPTL debugging" ,__VA_ARGS__ } .deprecate_cmd = &cli_handle_udptl_debug_deprecated) }
Definition at line 1222 of file udptl.c.
Referenced by ast_udptl_init().
int udptldebug [static] |
struct sockaddr_in udptldebugaddr [static] |
int udptlfecentries [static] |
int udptlfecspan [static] |
int udptlfectype [static] |
int udptlmaxdatagram [static] |
int udptlstart = 4500 [static] |