UDPTL support for T.38 faxing. More...
#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 | udptl_fec_rx_buffer_t |
| struct | udptl_fec_tx_buffer_t |
Defines | |
| #define | LOCAL_FAX_MAX_DATAGRAM 1400 |
| #define | MAX_FEC_ENTRIES 5 |
| #define | MAX_FEC_SPAN 5 |
| #define | UDPTL_BUF_MASK 15 |
| #define | UDPTL_MTU 1200 |
Functions | |
| static void | __ast_udptl_reload (int reload) |
| static | AST_RWLIST_HEAD_STATIC (protos, ast_udptl_protocol) |
| 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 (const struct ast_udptl *udptl) |
| enum ast_t38_ec_modes | ast_udptl_get_error_correction_scheme (const struct ast_udptl *udptl) |
| unsigned int | ast_udptl_get_far_max_datagram (const struct ast_udptl *udptl) |
| unsigned int | ast_udptl_get_far_max_ifp (const struct ast_udptl *udptl) |
| unsigned int | ast_udptl_get_local_max_datagram (const struct ast_udptl *udptl) |
| void | ast_udptl_get_peer (const struct ast_udptl *udptl, struct sockaddr_in *them) |
| void | ast_udptl_get_us (const struct ast_udptl *udptl, struct sockaddr_in *us) |
| void | ast_udptl_init (void) |
| struct ast_udptl * | ast_udptl_new (struct sched_context *sched, struct io_context *io, int callbackmode) |
| struct ast_udptl * | ast_udptl_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr addr) |
| int | ast_udptl_proto_register (struct ast_udptl_protocol *proto) |
| void | ast_udptl_proto_unregister (struct ast_udptl_protocol *proto) |
| struct ast_frame * | ast_udptl_read (struct ast_udptl *udptl) |
| 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, enum ast_t38_ec_modes ec) |
| void | ast_udptl_set_far_max_datagram (struct ast_udptl *udptl, unsigned int max_datagram) |
| void | ast_udptl_set_local_max_ifp (struct ast_udptl *udptl, unsigned int max_ifp) |
| void | ast_udptl_set_peer (struct ast_udptl *udptl, const struct sockaddr_in *them) |
| void | ast_udptl_setnat (struct ast_udptl *udptl, int nat) |
| int | ast_udptl_setqos (struct ast_udptl *udptl, unsigned int tos, unsigned int cos) |
| void | ast_udptl_stop (struct ast_udptl *udptl) |
| int | ast_udptl_write (struct ast_udptl *s, struct ast_frame *f) |
| static void | calculate_far_max_ifp (struct ast_udptl *udptl) |
| static void | calculate_local_max_datagram (struct ast_udptl *udptl) |
| static int | decode_length (uint8_t *buf, unsigned int limit, unsigned int *len, unsigned int *pvalue) |
| static int | decode_open_type (uint8_t *buf, unsigned int limit, unsigned int *len, const uint8_t **p_object, unsigned int *p_num_octets) |
| static unsigned int | encode_length (uint8_t *buf, unsigned int *len, unsigned int value) |
| static int | encode_open_type (uint8_t *buf, unsigned int buflen, unsigned int *len, const uint8_t *data, unsigned 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, unsigned int buflen, uint8_t *ifp, unsigned int ifp_len) |
| static int | udptl_debug_test_addr (const struct sockaddr_in *addr) |
| static int | udptl_rx_packet (struct ast_udptl *s, uint8_t *buf, unsigned int len) |
| static int | udptlread (int *id, int fd, short events, void *cbdata) |
Variables | |
| static struct ast_cli_entry | cli_handle_udptl_debug_deprecated = AST_CLI_DEFINE(handle_cli_udptl_debug_deprecated, "Enable/Disable UDPTL debugging") |
| 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 enum ast_t38_ec_modes | udptlfectype |
| static int | udptlmaxdatagram |
| static int | udptlstart = 4500 |
| static int | use_even_ports |
UDPTL support for T.38 faxing.
Definition in file udptl.c.
| #define LOCAL_FAX_MAX_DATAGRAM 1400 |
Definition at line 90 of file udptl.c.
Referenced by __ast_udptl_reload(), calculate_local_max_datagram(), udptl_build_packet(), and udptl_rx_packet().
| #define MAX_FEC_ENTRIES 5 |
Definition at line 91 of file udptl.c.
Referenced by __ast_udptl_reload().
| #define MAX_FEC_SPAN 5 |
Definition at line 92 of file udptl.c.
Referenced by __ast_udptl_reload().
| #define UDPTL_BUF_MASK 15 |
Definition at line 94 of file udptl.c.
Referenced by ast_udptl_new_with_bindaddr(), udptl_build_packet(), and udptl_rx_packet().
| static void __ast_udptl_reload | ( | int | reload | ) | [static] |
Definition at line 1318 of file udptl.c.
References ast_config_destroy(), ast_config_load2(), ast_false(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, LOCAL_FAX_MAX_DATAGRAM, LOG_NOTICE, LOG_WARNING, MAX_FEC_ENTRIES, MAX_FEC_SPAN, s, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by ast_udptl_init(), and ast_udptl_reload().
01319 { 01320 struct ast_config *cfg; 01321 const char *s; 01322 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01323 01324 if ((cfg = ast_config_load2("udptl.conf", "udptl", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 01325 return; 01326 01327 udptlstart = 4500; 01328 udptlend = 4999; 01329 udptlfectype = UDPTL_ERROR_CORRECTION_NONE; 01330 udptlfecentries = 0; 01331 udptlfecspan = 0; 01332 udptlmaxdatagram = 0; 01333 use_even_ports = 0; 01334 01335 if (cfg) { 01336 if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) { 01337 udptlstart = atoi(s); 01338 if (udptlstart < 1024) { 01339 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01340 udptlstart = 1024; 01341 } 01342 if (udptlstart > 65535) { 01343 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01344 udptlstart = 65535; 01345 } 01346 } 01347 if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) { 01348 udptlend = atoi(s); 01349 if (udptlend < 1024) { 01350 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01351 udptlend = 1024; 01352 } 01353 if (udptlend > 65535) { 01354 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01355 udptlend = 65535; 01356 } 01357 } 01358 if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) { 01359 #ifdef SO_NO_CHECK 01360 if (ast_false(s)) 01361 nochecksums = 1; 01362 else 01363 nochecksums = 0; 01364 #else 01365 if (ast_false(s)) 01366 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n"); 01367 #endif 01368 } 01369 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) { 01370 if (strcmp(s, "t38UDPFEC") == 0) 01371 udptlfectype = UDPTL_ERROR_CORRECTION_FEC; 01372 else if (strcmp(s, "t38UDPRedundancy") == 0) 01373 udptlfectype = UDPTL_ERROR_CORRECTION_REDUNDANCY; 01374 } 01375 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) { 01376 udptlmaxdatagram = atoi(s); 01377 if (udptlmaxdatagram < 100) { 01378 ast_log(LOG_WARNING, "Too small T38FaxMaxDatagram size. Defaulting to 100.\n"); 01379 udptlmaxdatagram = 100; 01380 } 01381 if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM) { 01382 ast_log(LOG_WARNING, "Too large T38FaxMaxDatagram size. Defaulting to %d.\n", LOCAL_FAX_MAX_DATAGRAM); 01383 udptlmaxdatagram = LOCAL_FAX_MAX_DATAGRAM; 01384 } 01385 } 01386 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) { 01387 udptlfecentries = atoi(s); 01388 if (udptlfecentries < 1) { 01389 ast_log(LOG_WARNING, "Too small UDPTLFECentries value. Defaulting to 1.\n"); 01390 udptlfecentries = 1; 01391 } 01392 if (udptlfecentries > MAX_FEC_ENTRIES) { 01393 ast_log(LOG_WARNING, "Too large UDPTLFECentries value. Defaulting to %d.\n", MAX_FEC_ENTRIES); 01394 udptlfecentries = MAX_FEC_ENTRIES; 01395 } 01396 } 01397 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) { 01398 udptlfecspan = atoi(s); 01399 if (udptlfecspan < 1) { 01400 ast_log(LOG_WARNING, "Too small UDPTLFECspan value. Defaulting to 1.\n"); 01401 udptlfecspan = 1; 01402 } 01403 if (udptlfecspan > MAX_FEC_SPAN) { 01404 ast_log(LOG_WARNING, "Too large UDPTLFECspan value. Defaulting to %d.\n", MAX_FEC_SPAN); 01405 udptlfecspan = MAX_FEC_SPAN; 01406 } 01407 } 01408 if ((s = ast_variable_retrieve(cfg, "general", "use_even_ports"))) { 01409 use_even_ports = ast_true(s); 01410 } 01411 ast_config_destroy(cfg); 01412 } 01413 if (udptlstart >= udptlend) { 01414 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end\n"); 01415 udptlstart = 4500; 01416 udptlend = 4999; 01417 } 01418 if (use_even_ports && (udptlstart & 1)) { 01419 ++udptlstart; 01420 ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", udptlstart); 01421 } 01422 if (use_even_ports && (udptlend & 1)) { 01423 --udptlend; 01424 ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_event_ports enabled. udptlend is now %d\n", udptlend); 01425 } 01426 ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend); 01427 }
| static AST_RWLIST_HEAD_STATIC | ( | protos | , | |
| ast_udptl_protocol | ||||
| ) | [static] |
| 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 1065 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, ast_frame::frametype, get_proto(), ast_udptl_protocol::get_udptl_info, inaddrcmp(), LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_udptl_protocol::set_udptl_peer, and ast_channel::tech_pvt.
01066 { 01067 struct ast_frame *f; 01068 struct ast_channel *who; 01069 struct ast_channel *cs[3]; 01070 struct ast_udptl *p0; 01071 struct ast_udptl *p1; 01072 struct ast_udptl_protocol *pr0; 01073 struct ast_udptl_protocol *pr1; 01074 struct sockaddr_in ac0; 01075 struct sockaddr_in ac1; 01076 struct sockaddr_in t0; 01077 struct sockaddr_in t1; 01078 void *pvt0; 01079 void *pvt1; 01080 int to; 01081 01082 ast_channel_lock(c0); 01083 while (ast_channel_trylock(c1)) { 01084 ast_channel_unlock(c0); 01085 usleep(1); 01086 ast_channel_lock(c0); 01087 } 01088 pr0 = get_proto(c0); 01089 pr1 = get_proto(c1); 01090 if (!pr0) { 01091 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01092 ast_channel_unlock(c0); 01093 ast_channel_unlock(c1); 01094 return -1; 01095 } 01096 if (!pr1) { 01097 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01098 ast_channel_unlock(c0); 01099 ast_channel_unlock(c1); 01100 return -1; 01101 } 01102 pvt0 = c0->tech_pvt; 01103 pvt1 = c1->tech_pvt; 01104 p0 = pr0->get_udptl_info(c0); 01105 p1 = pr1->get_udptl_info(c1); 01106 if (!p0 || !p1) { 01107 /* Somebody doesn't want to play... */ 01108 ast_channel_unlock(c0); 01109 ast_channel_unlock(c1); 01110 return -2; 01111 } 01112 if (pr0->set_udptl_peer(c0, p1)) { 01113 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01114 memset(&ac1, 0, sizeof(ac1)); 01115 } else { 01116 /* Store UDPTL peer */ 01117 ast_udptl_get_peer(p1, &ac1); 01118 } 01119 if (pr1->set_udptl_peer(c1, p0)) { 01120 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01121 memset(&ac0, 0, sizeof(ac0)); 01122 } else { 01123 /* Store UDPTL peer */ 01124 ast_udptl_get_peer(p0, &ac0); 01125 } 01126 ast_channel_unlock(c0); 01127 ast_channel_unlock(c1); 01128 cs[0] = c0; 01129 cs[1] = c1; 01130 cs[2] = NULL; 01131 for (;;) { 01132 if ((c0->tech_pvt != pvt0) || 01133 (c1->tech_pvt != pvt1) || 01134 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01135 ast_debug(1, "Oooh, something is weird, backing out\n"); 01136 /* Tell it to try again later */ 01137 return -3; 01138 } 01139 to = -1; 01140 ast_udptl_get_peer(p1, &t1); 01141 ast_udptl_get_peer(p0, &t0); 01142 if (inaddrcmp(&t1, &ac1)) { 01143 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 01144 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port)); 01145 ast_debug(1, "Oooh, '%s' was %s:%d\n", 01146 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port)); 01147 memcpy(&ac1, &t1, sizeof(ac1)); 01148 } 01149 if (inaddrcmp(&t0, &ac0)) { 01150 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 01151 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port)); 01152 ast_debug(1, "Oooh, '%s' was %s:%d\n", 01153 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port)); 01154 memcpy(&ac0, &t0, sizeof(ac0)); 01155 } 01156 who = ast_waitfor_n(cs, 2, &to); 01157 if (!who) { 01158 ast_debug(1, "Ooh, empty read...\n"); 01159 /* check for hangup / whentohangup */ 01160 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01161 break; 01162 continue; 01163 } 01164 f = ast_read(who); 01165 if (!f) { 01166 *fo = f; 01167 *rc = who; 01168 ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01169 /* That's all we needed */ 01170 return 0; 01171 } else { 01172 if (f->frametype == AST_FRAME_MODEM) { 01173 /* Forward T.38 frames if they happen upon us */ 01174 if (who == c0) { 01175 ast_write(c1, f); 01176 } else if (who == c1) { 01177 ast_write(c0, f); 01178 } 01179 } 01180 ast_frfree(f); 01181 } 01182 /* Swap priority. Not that it's a big deal at this point */ 01183 cs[2] = cs[0]; 01184 cs[0] = cs[1]; 01185 cs[1] = cs[2]; 01186 } 01187 return -1; 01188 }
| void ast_udptl_destroy | ( | struct ast_udptl * | udptl | ) |
Definition at line 972 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().
| int ast_udptl_fd | ( | const struct ast_udptl * | udptl | ) |
Definition at line 630 of file udptl.c.
References ast_udptl::fd.
Referenced by __oh323_new(), and sip_new().
00631 { 00632 return udptl->fd; 00633 }
| enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme | ( | const struct ast_udptl * | udptl | ) |
Definition at line 777 of file udptl.c.
References ast_log(), ast_udptl::error_correction_scheme, and LOG_WARNING.
Referenced by add_sdp().
00778 { 00779 if (udptl) 00780 return udptl->error_correction_scheme; 00781 else { 00782 ast_log(LOG_WARNING, "udptl structure is null\n"); 00783 return -1; 00784 } 00785 }
| unsigned int ast_udptl_get_far_max_datagram | ( | const struct ast_udptl * | udptl | ) |
Definition at line 827 of file udptl.c.
References ast_log(), ast_udptl::far_max_datagram, and LOG_WARNING.
00828 { 00829 if (udptl) 00830 return udptl->far_max_datagram; 00831 else { 00832 ast_log(LOG_WARNING, "udptl structure is null\n"); 00833 return 0; 00834 } 00835 }
| unsigned int ast_udptl_get_far_max_ifp | ( | const struct ast_udptl * | udptl | ) |
Definition at line 853 of file udptl.c.
References ast_udptl::far_max_ifp.
Referenced by change_t38_state().
00854 { 00855 return udptl->far_max_ifp; 00856 }
| unsigned int ast_udptl_get_local_max_datagram | ( | const struct ast_udptl * | udptl | ) |
Definition at line 817 of file udptl.c.
References ast_log(), ast_udptl::local_max_datagram, and LOG_WARNING.
Referenced by add_sdp().
00818 { 00819 if (udptl) 00820 return udptl->local_max_datagram; 00821 else { 00822 ast_log(LOG_WARNING, "udptl structure is null\n"); 00823 return 0; 00824 } 00825 }
| void ast_udptl_get_peer | ( | const struct ast_udptl * | udptl, | |
| struct sockaddr_in * | them | |||
| ) |
Definition at line 953 of file udptl.c.
References ast_udptl::them.
Referenced by ast_udptl_bridge(), and sip_set_udptl_peer().
| void ast_udptl_get_us | ( | const struct ast_udptl * | udptl, | |
| struct sockaddr_in * | us | |||
| ) |
| void ast_udptl_init | ( | void | ) |
Definition at line 1435 of file udptl.c.
References __ast_udptl_reload(), and ast_cli_register_multiple().
Referenced by main().
01436 { 01437 ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry)); 01438 __ast_udptl_reload(0); 01439 }
| struct ast_udptl* ast_udptl_new | ( | struct sched_context * | sched, | |
| struct io_context * | io, | |||
| int | callbackmode | |||
| ) | [read] |
Definition at line 935 of file udptl.c.
References ast_udptl_new_with_bindaddr().
00936 { 00937 struct in_addr ia; 00938 memset(&ia, 0, sizeof(ia)); 00939 return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia); 00940 }
| struct ast_udptl* ast_udptl_new_with_bindaddr | ( | struct sched_context * | sched, | |
| struct io_context * | io, | |||
| int | callbackmode, | |||
| struct in_addr | addr | |||
| ) | [read] |
Definition at line 858 of file udptl.c.
References ast_calloc, ast_free, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), udptl_fec_tx_buffer_t::buf_len, udptl_fec_rx_buffer_t::buf_len, errno, ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, ast_udptl::error_correction_span, ast_udptl::far_max_datagram, ast_udptl::fd, ast_udptl::flags, ast_udptl::io, ast_udptl::ioid, ast_udptl::local_max_datagram, LOG_WARNING, ast_udptl::rx, ast_udptl::sched, ast_udptl::them, ast_udptl::tx, UDPTL_BUF_MASK, udptlread(), and ast_udptl::us.
Referenced by ast_udptl_new(), create_addr_from_peer(), handle_request_invite(), and sip_alloc().
00859 { 00860 struct ast_udptl *udptl; 00861 int x; 00862 int startplace; 00863 int i; 00864 long int flags; 00865 00866 if (!(udptl = ast_calloc(1, sizeof(*udptl)))) 00867 return NULL; 00868 00869 udptl->error_correction_scheme = udptlfectype; 00870 udptl->error_correction_span = udptlfecspan; 00871 udptl->error_correction_entries = udptlfecentries; 00872 00873 udptl->far_max_datagram = udptlmaxdatagram; 00874 udptl->local_max_datagram = udptlmaxdatagram; 00875 00876 for (i = 0; i <= UDPTL_BUF_MASK; i++) { 00877 udptl->rx[i].buf_len = -1; 00878 udptl->tx[i].buf_len = -1; 00879 } 00880 00881 udptl->them.sin_family = AF_INET; 00882 udptl->us.sin_family = AF_INET; 00883 00884 if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00885 ast_free(udptl); 00886 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00887 return NULL; 00888 } 00889 flags = fcntl(udptl->fd, F_GETFL); 00890 fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK); 00891 #ifdef SO_NO_CHECK 00892 if (nochecksums) 00893 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00894 #endif 00895 /* Find us a place */ 00896 x = (udptlstart == udptlend) ? udptlstart : (ast_random() % (udptlend - udptlstart)) + udptlstart; 00897 if (use_even_ports && (x & 1)) { 00898 ++x; 00899 } 00900 startplace = x; 00901 for (;;) { 00902 udptl->us.sin_port = htons(x); 00903 udptl->us.sin_addr = addr; 00904 if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0) 00905 break; 00906 if (errno != EADDRINUSE) { 00907 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00908 close(udptl->fd); 00909 ast_free(udptl); 00910 return NULL; 00911 } 00912 if (use_even_ports) { 00913 x += 2; 00914 } else { 00915 ++x; 00916 } 00917 if (x > udptlend) 00918 x = udptlstart; 00919 if (x == startplace) { 00920 ast_log(LOG_WARNING, "No UDPTL ports remaining\n"); 00921 close(udptl->fd); 00922 ast_free(udptl); 00923 return NULL; 00924 } 00925 } 00926 if (io && sched && callbackmode) { 00927 /* Operate this one in a callback mode */ 00928 udptl->sched = sched; 00929 udptl->io = io; 00930 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl); 00931 } 00932 return udptl; 00933 }
| int ast_udptl_proto_register | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 1034 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().
01035 { 01036 struct ast_udptl_protocol *cur; 01037 01038 AST_RWLIST_WRLOCK(&protos); 01039 AST_RWLIST_TRAVERSE(&protos, cur, list) { 01040 if (cur->type == proto->type) { 01041 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01042 AST_RWLIST_UNLOCK(&protos); 01043 return -1; 01044 } 01045 } 01046 AST_RWLIST_INSERT_TAIL(&protos, proto, list); 01047 AST_RWLIST_UNLOCK(&protos); 01048 return 0; 01049 }
| void ast_udptl_proto_unregister | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 1027 of file udptl.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by unload_module().
01028 { 01029 AST_RWLIST_WRLOCK(&protos); 01030 AST_RWLIST_REMOVE(&protos, proto, list); 01031 AST_RWLIST_UNLOCK(&protos); 01032 }
Definition at line 662 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().
00663 { 00664 int res; 00665 struct sockaddr_in sin; 00666 socklen_t len; 00667 uint16_t seqno = 0; 00668 uint16_t *udptlheader; 00669 00670 len = sizeof(sin); 00671 00672 /* Cache where the header will go */ 00673 res = recvfrom(udptl->fd, 00674 udptl->rawdata + AST_FRIENDLY_OFFSET, 00675 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET, 00676 0, 00677 (struct sockaddr *) &sin, 00678 &len); 00679 udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET); 00680 if (res < 0) { 00681 if (errno != EAGAIN) 00682 ast_log(LOG_WARNING, "UDPTL read error: %s\n", strerror(errno)); 00683 ast_assert(errno != EBADF); 00684 return &ast_null_frame; 00685 } 00686 00687 /* Ignore if the other side hasn't been given an address yet. */ 00688 if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port) 00689 return &ast_null_frame; 00690 00691 if (udptl->nat) { 00692 /* Send to whoever sent to us */ 00693 if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00694 (udptl->them.sin_port != sin.sin_port)) { 00695 memcpy(&udptl->them, &sin, sizeof(udptl->them)); 00696 ast_debug(1, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00697 } 00698 } 00699 00700 if (udptl_debug_test_addr(&sin)) { 00701 ast_verb(1, "Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n", 00702 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res); 00703 } 00704 #if 0 00705 printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res); 00706 #endif 00707 if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1) 00708 return &ast_null_frame; 00709 00710 return &udptl->f[0]; 00711 }
| int ast_udptl_reload | ( | void | ) |
Definition at line 1429 of file udptl.c.
References __ast_udptl_reload().
01430 { 01431 __ast_udptl_reload(1); 01432 return 0; 01433 }
| void ast_udptl_set_callback | ( | struct ast_udptl * | udptl, | |
| ast_udptl_callback | callback | |||
| ) |
Definition at line 640 of file udptl.c.
References ast_udptl::callback.
00641 { 00642 udptl->callback = callback; 00643 }
| void ast_udptl_set_data | ( | struct ast_udptl * | udptl, | |
| void * | data | |||
| ) |
Definition at line 635 of file udptl.c.
References ast_udptl::data.
00636 { 00637 udptl->data = data; 00638 }
| void ast_udptl_set_error_correction_scheme | ( | struct ast_udptl * | udptl, | |
| enum ast_t38_ec_modes | ec | |||
| ) |
Definition at line 787 of file udptl.c.
References ast_log(), calculate_far_max_ifp(), calculate_local_max_datagram(), ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, ast_udptl::error_correction_span, LOG_WARNING, UDPTL_ERROR_CORRECTION_FEC, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by process_sdp(), and set_t38_capabilities().
00788 { 00789 if (udptl) { 00790 udptl->error_correction_scheme = ec; 00791 switch (ec) { 00792 case UDPTL_ERROR_CORRECTION_FEC: 00793 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00794 if (udptl->error_correction_entries == 0) { 00795 udptl->error_correction_entries = 3; 00796 } 00797 if (udptl->error_correction_span == 0) { 00798 udptl->error_correction_span = 3; 00799 } 00800 break; 00801 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00802 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00803 if (udptl->error_correction_entries == 0) { 00804 udptl->error_correction_entries = 3; 00805 } 00806 break; 00807 default: 00808 /* nothing to do */ 00809 break; 00810 }; 00811 calculate_local_max_datagram(udptl); 00812 calculate_far_max_ifp(udptl); 00813 } else 00814 ast_log(LOG_WARNING, "udptl structure is null\n"); 00815 }
| void ast_udptl_set_far_max_datagram | ( | struct ast_udptl * | udptl, | |
| unsigned int | max_datagram | |||
| ) |
Definition at line 837 of file udptl.c.
References ast_log(), calculate_far_max_ifp(), ast_udptl::far_max_datagram, and LOG_WARNING.
Referenced by process_sdp().
00838 { 00839 if (udptl) { 00840 udptl->far_max_datagram = max_datagram; 00841 calculate_far_max_ifp(udptl); 00842 } else { 00843 ast_log(LOG_WARNING, "udptl structure is null\n"); 00844 } 00845 }
| void ast_udptl_set_local_max_ifp | ( | struct ast_udptl * | udptl, | |
| unsigned int | max_ifp | |||
| ) |
Definition at line 847 of file udptl.c.
References calculate_local_max_datagram(), and ast_udptl::local_max_ifp.
Referenced by interpret_t38_parameters().
00848 { 00849 udptl->local_max_ifp = max_ifp; 00850 calculate_local_max_datagram(udptl); 00851 }
| void ast_udptl_set_peer | ( | struct ast_udptl * | udptl, | |
| const struct sockaddr_in * | them | |||
| ) |
| void ast_udptl_setnat | ( | struct ast_udptl * | udptl, | |
| int | nat | |||
| ) |
| int ast_udptl_setqos | ( | struct ast_udptl * | udptl, | |
| unsigned int | tos, | |||
| unsigned int | cos | |||
| ) |
Definition at line 942 of file udptl.c.
References ast_netsock_set_qos(), and ast_udptl::fd.
Referenced by sip_alloc().
00943 { 00944 return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL"); 00945 }
| void ast_udptl_stop | ( | struct ast_udptl * | udptl | ) |
Definition at line 966 of file udptl.c.
References ast_udptl::them.
Referenced by process_sdp(), and stop_media_flows().
Definition at line 981 of file udptl.c.
References AST_FRAME_MODEM, ast_inet_ntoa(), ast_log(), AST_MODEM_T38, ast_verb, buf, ast_frame::data, ast_frame::datalen, errno, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, ast_udptl::fd, ast_frame::frametype, len(), LOG_NOTICE, LOG_WARNING, ast_frame::ptr, seq, ast_frame::subclass, ast_udptl::them, ast_udptl::tx_seq_no, udptl_build_packet(), and udptl_debug_test_addr().
Referenced by sip_write().
00982 { 00983 unsigned int seq; 00984 unsigned int len; 00985 int res; 00986 uint8_t buf[s->far_max_datagram]; 00987 00988 /* If we have no peer, return immediately */ 00989 if (s->them.sin_addr.s_addr == INADDR_ANY) 00990 return 0; 00991 00992 /* If there is no data length, return immediately */ 00993 if (f->datalen == 0) 00994 return 0; 00995 00996 if ((f->frametype != AST_FRAME_MODEM) || 00997 (f->subclass != AST_MODEM_T38)) { 00998 ast_log(LOG_WARNING, "UDPTL can only send T.38 data.\n"); 00999 return -1; 01000 } 01001 01002 if (f->datalen > s->far_max_ifp) { 01003 ast_log(LOG_WARNING, "UDPTL asked to send %d bytes of IFP when far end only prepared to accept %d bytes; data loss may occur.\n", f->datalen, s->far_max_ifp); 01004 } 01005 01006 /* Save seq_no for debug output because udptl_build_packet increments it */ 01007 seq = s->tx_seq_no & 0xFFFF; 01008 01009 /* Cook up the UDPTL packet, with the relevant EC info. */ 01010 len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, f->datalen); 01011 01012 if (len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) { 01013 if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0) 01014 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)); 01015 #if 0 01016 printf("Sent %d bytes of UDPTL data to %s:%d\n", res, ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 01017 #endif 01018 if (udptl_debug_test_addr(&s->them)) 01019 ast_verb(1, "Sent UDPTL packet to %s:%d (type %d, seq %d, len %d)\n", 01020 ast_inet_ntoa(s->them.sin_addr), 01021 ntohs(s->them.sin_port), 0, seq, len); 01022 } 01023 01024 return 0; 01025 }
| static void calculate_far_max_ifp | ( | struct ast_udptl * | udptl | ) | [static] |
Definition at line 743 of file udptl.c.
References ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, MAX, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by ast_udptl_set_error_correction_scheme(), and ast_udptl_set_far_max_datagram().
00744 { 00745 unsigned new_max = 60; 00746 00747 /* calculate the maximum IFP the local endpoint should 00748 * generate based on the far end's maximum datagram size 00749 * and the current error correction mode. some endpoints 00750 * bogus 'max datagram' values that would result in unusable 00751 * (too small) maximum IFP values, so we have a a reasonable 00752 * minimum value to ensure that we can actually construct 00753 * UDPTL packets. 00754 */ 00755 switch (udptl->error_correction_scheme) { 00756 case UDPTL_ERROR_CORRECTION_NONE: 00757 /* only need room for sequence number and length indicators */ 00758 new_max = MAX(new_max, udptl->far_max_datagram - 6); 00759 break; 00760 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00761 /* need room for sequence number, length indicators and the 00762 * configured number of redundant packets 00763 */ 00764 new_max = MAX(new_max, (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1)); 00765 break; 00766 case UDPTL_ERROR_CORRECTION_FEC: 00767 /* need room for sequence number, length indicators and a 00768 * a single IFP of the maximum size expected 00769 */ 00770 new_max = MAX(new_max, (udptl->far_max_datagram - 10) / 2); 00771 break; 00772 } 00773 /* subtract 25% of space for insurance */ 00774 udptl->far_max_ifp = new_max * 0.75; 00775 }
| static void calculate_local_max_datagram | ( | struct ast_udptl * | udptl | ) | [static] |
Definition at line 713 of file udptl.c.
References ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, LOCAL_FAX_MAX_DATAGRAM, ast_udptl::local_max_datagram, ast_udptl::local_max_ifp, MIN, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by ast_udptl_set_error_correction_scheme(), and ast_udptl_set_local_max_ifp().
00714 { 00715 unsigned int new_max = 200; 00716 00717 /* calculate the amount of space required to receive an IFP 00718 * using the current error correction mode, and ensure that our 00719 * local max datagram size is at least that big 00720 */ 00721 switch (udptl->error_correction_scheme) { 00722 case UDPTL_ERROR_CORRECTION_NONE: 00723 /* only need room for sequence number and length indicators */ 00724 new_max = 6 + udptl->local_max_ifp; 00725 break; 00726 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00727 /* need room for sequence number, length indicators and the 00728 * configured number of redundant packets 00729 */ 00730 new_max = 6 + udptl->local_max_ifp + 2 + (udptl->error_correction_entries * udptl->local_max_ifp); 00731 break; 00732 case UDPTL_ERROR_CORRECTION_FEC: 00733 /* need room for sequence number, length indicators and a 00734 * a single IFP of the maximum size expected 00735 */ 00736 new_max = 6 + udptl->local_max_ifp + 4 + udptl->local_max_ifp; 00737 break; 00738 } 00739 /* add 25% of extra space for insurance, but no larger than LOCAL_FAX_MAX_DATAGRAM */ 00740 udptl->local_max_datagram = MIN(new_max * 1.25, LOCAL_FAX_MAX_DATAGRAM); 00741 }
| static int decode_length | ( | uint8_t * | buf, | |
| unsigned int | limit, | |||
| unsigned int * | len, | |||
| unsigned int * | pvalue | |||
| ) | [static] |
Definition at line 191 of file udptl.c.
Referenced by decode_open_type(), and udptl_rx_packet().
00192 { 00193 if (*len >= limit) 00194 return -1; 00195 if ((buf[*len] & 0x80) == 0) { 00196 *pvalue = buf[*len]; 00197 (*len)++; 00198 return 0; 00199 } 00200 if ((buf[*len] & 0x40) == 0) { 00201 if (*len == limit - 1) 00202 return -1; 00203 *pvalue = (buf[*len] & 0x3F) << 8; 00204 (*len)++; 00205 *pvalue |= buf[*len]; 00206 (*len)++; 00207 return 0; 00208 } 00209 *pvalue = (buf[*len] & 0x3F) << 14; 00210 (*len)++; 00211 /* Indicate we have a fragment */ 00212 return 1; 00213 }
| static int decode_open_type | ( | uint8_t * | buf, | |
| unsigned int | limit, | |||
| unsigned int * | len, | |||
| const uint8_t ** | p_object, | |||
| unsigned int * | p_num_octets | |||
| ) | [static] |
Definition at line 216 of file udptl.c.
References decode_length().
Referenced by udptl_rx_packet().
00217 { 00218 unsigned int octet_cnt; 00219 unsigned int octet_idx; 00220 unsigned int length; 00221 unsigned int i; 00222 const uint8_t **pbuf; 00223 00224 for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) { 00225 octet_cnt = 0; 00226 if ((length = decode_length(buf, limit, len, &octet_cnt)) < 0) 00227 return -1; 00228 if (octet_cnt > 0) { 00229 *p_num_octets += octet_cnt; 00230 00231 pbuf = &p_object[octet_idx]; 00232 i = 0; 00233 /* Make sure the buffer contains at least the number of bits requested */ 00234 if ((*len + octet_cnt) > limit) 00235 return -1; 00236 00237 *pbuf = &buf[*len]; 00238 *len += octet_cnt; 00239 } 00240 if (length == 0) 00241 break; 00242 } 00243 return 0; 00244 }
| static unsigned int encode_length | ( | uint8_t * | buf, | |
| unsigned int * | len, | |||
| unsigned int | value | |||
| ) | [static] |
Definition at line 247 of file udptl.c.
Referenced by encode_open_type(), and udptl_build_packet().
00248 { 00249 unsigned int multiplier; 00250 00251 if (value < 0x80) { 00252 /* 1 octet */ 00253 buf[*len] = value; 00254 (*len)++; 00255 return value; 00256 } 00257 if (value < 0x4000) { 00258 /* 2 octets */ 00259 /* Set the first bit of the first octet */ 00260 buf[*len] = ((0x8000 | value) >> 8) & 0xFF; 00261 (*len)++; 00262 buf[*len] = value & 0xFF; 00263 (*len)++; 00264 return value; 00265 } 00266 /* Fragmentation */ 00267 multiplier = (value < 0x10000) ? (value >> 14) : 4; 00268 /* Set the first 2 bits of the octet */ 00269 buf[*len] = 0xC0 | multiplier; 00270 (*len)++; 00271 return multiplier << 14; 00272 }
| static int encode_open_type | ( | uint8_t * | buf, | |
| unsigned int | buflen, | |||
| unsigned int * | len, | |||
| const uint8_t * | data, | |||
| unsigned int | num_octets | |||
| ) | [static] |
Definition at line 275 of file udptl.c.
References ast_log(), encode_length(), and LOG_ERROR.
Referenced by udptl_build_packet().
00276 { 00277 unsigned int enclen; 00278 unsigned int octet_idx; 00279 uint8_t zero_byte; 00280 00281 /* If open type is of zero length, add a single zero byte (10.1) */ 00282 if (num_octets == 0) { 00283 zero_byte = 0; 00284 data = &zero_byte; 00285 num_octets = 1; 00286 } 00287 /* Encode the open type */ 00288 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) { 00289 if ((enclen = encode_length(buf, len, num_octets)) < 0) 00290 return -1; 00291 if (enclen + *len > buflen) { 00292 ast_log(LOG_ERROR, "Buffer overflow detected (%d + %d > %d)\n", enclen, *len, buflen); 00293 return -1; 00294 } 00295 if (enclen > 0) { 00296 memcpy(&buf[*len], &data[octet_idx], enclen); 00297 *len += enclen; 00298 } 00299 if (enclen >= num_octets) 00300 break; 00301 } 00302 00303 return 0; 00304 }
| static struct ast_udptl_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 1051 of file udptl.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_udptl_protocol::list, ast_channel::tech, ast_channel_tech::type, and ast_udptl_protocol::type.
Referenced by ast_udptl_bridge().
01052 { 01053 struct ast_udptl_protocol *cur = NULL; 01054 01055 AST_RWLIST_RDLOCK(&protos); 01056 AST_RWLIST_TRAVERSE(&protos, cur, list) { 01057 if (cur->type == chan->tech->type) 01058 break; 01059 } 01060 AST_RWLIST_UNLOCK(&protos); 01061 01062 return cur; 01063 }
| static char* handle_cli_udptl_debug_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1190 of file udptl.c.
References 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, udptldebugaddr, and ast_cli_entry::usage.
01191 { 01192 struct hostent *hp; 01193 struct ast_hostent ahp; 01194 int port; 01195 char *p; 01196 char *arg; 01197 01198 switch (cmd) { 01199 case CLI_INIT: 01200 e->command = "udptl debug [off|ip]"; 01201 e->usage = 01202 "Usage: udptl debug [off]|[ip host[:port]]\n" 01203 " Enable or disable dumping of UDPTL packets.\n" 01204 " If ip is specified, limit the dumped packets to those to and from\n" 01205 " the specified 'host' with optional port.\n"; 01206 return NULL; 01207 case CLI_GENERATE: 01208 return NULL; 01209 } 01210 01211 if (a->argc < 2 || a->argc > 4) 01212 return CLI_SHOWUSAGE; 01213 01214 if (a->argc == 2) { 01215 udptldebug = 1; 01216 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr)); 01217 ast_cli(a->fd, "UDPTL Debugging Enabled\n"); 01218 } else if (a->argc == 3) { 01219 if (strncasecmp(a->argv[2], "off", 3)) 01220 return CLI_SHOWUSAGE; 01221 udptldebug = 0; 01222 ast_cli(a->fd, "UDPTL Debugging Disabled\n"); 01223 } else { 01224 if (strncasecmp(a->argv[2], "ip", 2)) 01225 return CLI_SHOWUSAGE; 01226 port = 0; 01227 arg = a->argv[3]; 01228 p = strstr(arg, ":"); 01229 if (p) { 01230 *p = '\0'; 01231 p++; 01232 port = atoi(p); 01233 } 01234 hp = ast_gethostbyname(arg, &ahp); 01235 if (hp == NULL) 01236 return CLI_SHOWUSAGE; 01237 udptldebugaddr.sin_family = AF_INET; 01238 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr)); 01239 udptldebugaddr.sin_port = htons(port); 01240 if (port == 0) 01241 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr)); 01242 else 01243 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port); 01244 udptldebug = 1; 01245 } 01246 01247 return CLI_SUCCESS; 01248 }
| static char* handle_cli_udptl_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1250 of file udptl.c.
References 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, udptldebugaddr, and ast_cli_entry::usage.
01251 { 01252 struct hostent *hp; 01253 struct ast_hostent ahp; 01254 int port; 01255 char *p; 01256 char *arg; 01257 01258 switch (cmd) { 01259 case CLI_INIT: 01260 e->command = "udptl set debug {on|off|ip}"; 01261 e->usage = 01262 "Usage: udptl set debug {on|off|ip host[:port]}\n" 01263 " Enable or disable dumping of UDPTL packets.\n" 01264 " If ip is specified, limit the dumped packets to those to and from\n" 01265 " the specified 'host' with optional port.\n"; 01266 return NULL; 01267 case CLI_GENERATE: 01268 return NULL; 01269 } 01270 01271 if (a->argc < 4 || a->argc > 5) 01272 return CLI_SHOWUSAGE; 01273 01274 if (a->argc == 4) { 01275 if (!strncasecmp(a->argv[3], "on", 2)) { 01276 udptldebug = 1; 01277 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr)); 01278 ast_cli(a->fd, "UDPTL Debugging Enabled\n"); 01279 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01280 udptldebug = 0; 01281 ast_cli(a->fd, "UDPTL Debugging Disabled\n"); 01282 } else { 01283 return CLI_SHOWUSAGE; 01284 } 01285 } else { 01286 if (strncasecmp(a->argv[3], "ip", 2)) 01287 return CLI_SHOWUSAGE; 01288 port = 0; 01289 arg = a->argv[4]; 01290 p = strstr(arg, ":"); 01291 if (p) { 01292 *p = '\0'; 01293 p++; 01294 port = atoi(p); 01295 } 01296 hp = ast_gethostbyname(arg, &ahp); 01297 if (hp == NULL) 01298 return CLI_SHOWUSAGE; 01299 udptldebugaddr.sin_family = AF_INET; 01300 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr)); 01301 udptldebugaddr.sin_port = htons(port); 01302 if (port == 0) 01303 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr)); 01304 else 01305 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port); 01306 udptldebug = 1; 01307 } 01308 01309 return CLI_SUCCESS; 01310 }
| static int udptl_build_packet | ( | struct ast_udptl * | s, | |
| uint8_t * | buf, | |||
| unsigned int | buflen, | |||
| uint8_t * | ifp, | |||
| unsigned int | ifp_len | |||
| ) | [static] |
Definition at line 515 of file udptl.c.
References ast_log(), udptl_fec_tx_buffer_t::buf, udptl_fec_tx_buffer_t::buf_len, encode_length(), encode_open_type(), ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, ast_udptl::error_correction_span, len(), LOCAL_FAX_MAX_DATAGRAM, LOG_DEBUG, option_debug, seq, ast_udptl::tx, ast_udptl::tx_seq_no, UDPTL_BUF_MASK, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and ast_udptl::verbose.
Referenced by ast_udptl_write().
00516 { 00517 uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2]; 00518 int i; 00519 int j; 00520 int seq; 00521 int entry; 00522 int entries; 00523 int span; 00524 int m; 00525 unsigned int len; 00526 int limit; 00527 int high_tide; 00528 00529 seq = s->tx_seq_no & 0xFFFF; 00530 00531 /* Map the sequence number to an entry in the circular buffer */ 00532 entry = seq & UDPTL_BUF_MASK; 00533 00534 /* We save the message in a circular buffer, for generating FEC or 00535 redundancy sets later on. */ 00536 s->tx[entry].buf_len = ifp_len; 00537 memcpy(s->tx[entry].buf, ifp, ifp_len); 00538 00539 /* Build the UDPTLPacket */ 00540 00541 len = 0; 00542 /* Encode the sequence number */ 00543 buf[len++] = (seq >> 8) & 0xFF; 00544 buf[len++] = seq & 0xFF; 00545 00546 /* Encode the primary IFP packet */ 00547 if (encode_open_type(buf, buflen, &len, ifp, ifp_len) < 0) 00548 return -1; 00549 00550 /* Encode the appropriate type of error recovery information */ 00551 switch (s->error_correction_scheme) 00552 { 00553 case UDPTL_ERROR_CORRECTION_NONE: 00554 /* Encode the error recovery type */ 00555 buf[len++] = 0x00; 00556 /* The number of entries will always be zero, so it is pointless allowing 00557 for the fragmented case here. */ 00558 if (encode_length(buf, &len, 0) < 0) 00559 return -1; 00560 break; 00561 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00562 /* Encode the error recovery type */ 00563 buf[len++] = 0x00; 00564 if (s->tx_seq_no > s->error_correction_entries) 00565 entries = s->error_correction_entries; 00566 else 00567 entries = s->tx_seq_no; 00568 /* The number of entries will always be small, so it is pointless allowing 00569 for the fragmented case here. */ 00570 if (encode_length(buf, &len, entries) < 0) 00571 return -1; 00572 /* Encode the elements */ 00573 for (i = 0; i < entries; i++) { 00574 j = (entry - i - 1) & UDPTL_BUF_MASK; 00575 if (encode_open_type(buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) { 00576 if (option_debug) { 00577 ast_log(LOG_DEBUG, "Encoding failed at i=%d, j=%d\n", i, j); 00578 } 00579 return -1; 00580 } 00581 } 00582 break; 00583 case UDPTL_ERROR_CORRECTION_FEC: 00584 span = s->error_correction_span; 00585 entries = s->error_correction_entries; 00586 if (seq < s->error_correction_span*s->error_correction_entries) { 00587 /* In the initial stages, wind up the FEC smoothly */ 00588 entries = seq/s->error_correction_span; 00589 if (seq < s->error_correction_span) 00590 span = 0; 00591 } 00592 /* Encode the error recovery type */ 00593 buf[len++] = 0x80; 00594 /* Span is defined as an inconstrained integer, which it dumb. It will only 00595 ever be a small value. Treat it as such. */ 00596 buf[len++] = 1; 00597 buf[len++] = span; 00598 /* The number of entries is defined as a length, but will only ever be a small 00599 value. Treat it as such. */ 00600 buf[len++] = entries; 00601 for (m = 0; m < entries; m++) { 00602 /* Make an XOR'ed entry the maximum length */ 00603 limit = (entry + m) & UDPTL_BUF_MASK; 00604 high_tide = 0; 00605 for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { 00606 if (high_tide < s->tx[i].buf_len) { 00607 for (j = 0; j < high_tide; j++) 00608 fec[j] ^= s->tx[i].buf[j]; 00609 for ( ; j < s->tx[i].buf_len; j++) 00610 fec[j] = s->tx[i].buf[j]; 00611 high_tide = s->tx[i].buf_len; 00612 } else { 00613 for (j = 0; j < s->tx[i].buf_len; j++) 00614 fec[j] ^= s->tx[i].buf[j]; 00615 } 00616 } 00617 if (encode_open_type(buf, buflen, &len, fec, high_tide) < 0) 00618 return -1; 00619 } 00620 break; 00621 } 00622 00623 if (s->verbose) 00624 fprintf(stderr, "\n"); 00625 00626 s->tx_seq_no++; 00627 return len; 00628 }
| static int udptl_debug_test_addr | ( | const struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 178 of file udptl.c.
References udptldebugaddr.
Referenced by ast_udptl_read(), and ast_udptl_write().
00179 { 00180 if (udptldebug == 0) 00181 return 0; 00182 if (udptldebugaddr.sin_addr.s_addr) { 00183 if (((ntohs(udptldebugaddr.sin_port) != 0) && 00184 (udptldebugaddr.sin_port != addr->sin_port)) || 00185 (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00186 return 0; 00187 } 00188 return 1; 00189 }
| static int udptl_rx_packet | ( | struct ast_udptl * | s, | |
| uint8_t * | buf, | |||
| unsigned int | len | |||
| ) | [static] |
Definition at line 307 of file udptl.c.
References AST_FRAME_MODEM, AST_LIST_NEXT, AST_MODEM_T38, udptl_fec_rx_buffer_t::buf, udptl_fec_rx_buffer_t::buf_len, ast_frame::data, ast_frame::datalen, decode_length(), decode_open_type(), ast_udptl::f, udptl_fec_rx_buffer_t::fec, udptl_fec_rx_buffer_t::fec_entries, udptl_fec_rx_buffer_t::fec_len, udptl_fec_rx_buffer_t::fec_span, ast_frame::frametype, LOCAL_FAX_MAX_DATAGRAM, ast_frame::mallocd, ast_frame::offset, ast_frame::ptr, ast_udptl::rx, ast_udptl::rx_seq_no, ast_frame::seqno, ast_frame::src, ast_frame::subclass, TRUE, and UDPTL_BUF_MASK.
Referenced by ast_udptl_read().
00308 { 00309 int stat1; 00310 int stat2; 00311 int i; 00312 int j; 00313 int k; 00314 int l; 00315 int m; 00316 int x; 00317 int limit; 00318 int which; 00319 unsigned int ptr; 00320 unsigned int count; 00321 int total_count; 00322 int seq_no; 00323 const uint8_t *ifp; 00324 const uint8_t *data; 00325 unsigned int ifp_len; 00326 int repaired[16]; 00327 const uint8_t *bufs[16]; 00328 unsigned int lengths[16]; 00329 int span; 00330 int entries; 00331 int ifp_no; 00332 00333 ptr = 0; 00334 ifp_no = 0; 00335 memset(&s->f[0], 0, sizeof(s->f[0])); 00336 00337 /* Decode seq_number */ 00338 if (ptr + 2 > len) 00339 return -1; 00340 seq_no = (buf[0] << 8) | buf[1]; 00341 ptr += 2; 00342 00343 /* Break out the primary packet */ 00344 if ((stat1 = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0) 00345 return -1; 00346 /* Decode error_recovery */ 00347 if (ptr + 1 > len) 00348 return -1; 00349 if ((buf[ptr++] & 0x80) == 0) { 00350 /* Secondary packet mode for error recovery */ 00351 if (seq_no > s->rx_seq_no) { 00352 /* We received a later packet than we expected, so we need to check if we can fill in the gap from the 00353 secondary packets. */ 00354 total_count = 0; 00355 do { 00356 if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) 00357 return -1; 00358 for (i = 0; i < count; i++) { 00359 if ((stat1 = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) 00360 return -1; 00361 } 00362 total_count += count; 00363 } 00364 while (stat2 > 0); 00365 /* Step through in reverse order, so we go oldest to newest */ 00366 for (i = total_count; i > 0; i--) { 00367 if (seq_no - i >= s->rx_seq_no) { 00368 /* This one wasn't seen before */ 00369 /* Decode the secondary IFP packet */ 00370 //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); 00371 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00372 s->f[ifp_no].subclass = AST_MODEM_T38; 00373 00374 s->f[ifp_no].mallocd = 0; 00375 s->f[ifp_no].seqno = seq_no - i; 00376 s->f[ifp_no].datalen = lengths[i - 1]; 00377 s->f[ifp_no].data.ptr = (uint8_t *) bufs[i - 1]; 00378 s->f[ifp_no].offset = 0; 00379 s->f[ifp_no].src = "UDPTL"; 00380 if (ifp_no > 0) 00381 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00382 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00383 ifp_no++; 00384 } 00385 } 00386 } 00387 } 00388 else 00389 { 00390 /* FEC mode for error recovery */ 00391 /* Our buffers cannot tolerate overlength IFP packets in FEC mode */ 00392 if (ifp_len > LOCAL_FAX_MAX_DATAGRAM) 00393 return -1; 00394 /* Update any missed slots in the buffer */ 00395 for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) { 00396 x = s->rx_seq_no & UDPTL_BUF_MASK; 00397 s->rx[x].buf_len = -1; 00398 s->rx[x].fec_len[0] = 0; 00399 s->rx[x].fec_span = 0; 00400 s->rx[x].fec_entries = 0; 00401 } 00402 00403 x = seq_no & UDPTL_BUF_MASK; 00404 00405 memset(repaired, 0, sizeof(repaired)); 00406 00407 /* Save the new IFP packet */ 00408 memcpy(s->rx[x].buf, ifp, ifp_len); 00409 s->rx[x].buf_len = ifp_len; 00410 repaired[x] = TRUE; 00411 00412 /* Decode the FEC packets */ 00413 /* The span is defined as an unconstrained integer, but will never be more 00414 than a small value. */ 00415 if (ptr + 2 > len) 00416 return -1; 00417 if (buf[ptr++] != 1) 00418 return -1; 00419 span = buf[ptr++]; 00420 s->rx[x].fec_span = span; 00421 00422 /* The number of entries is defined as a length, but will only ever be a small 00423 value. Treat it as such. */ 00424 if (ptr + 1 > len) 00425 return -1; 00426 entries = buf[ptr++]; 00427 s->rx[x].fec_entries = entries; 00428 00429 /* Decode the elements */ 00430 for (i = 0; i < entries; i++) { 00431 if ((stat1 = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) 00432 return -1; 00433 if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM) 00434 return -1; 00435 00436 /* Save the new FEC data */ 00437 memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); 00438 #if 0 00439 fprintf(stderr, "FEC: "); 00440 for (j = 0; j < s->rx[x].fec_len[i]; j++) 00441 fprintf(stderr, "%02X ", data[j]); 00442 fprintf(stderr, "\n"); 00443 #endif 00444 } 00445 00446 /* See if we can reconstruct anything which is missing */ 00447 /* TODO: this does not comprehensively hunt back and repair everything that is possible */ 00448 for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { 00449 if (s->rx[l].fec_len[0] <= 0) 00450 continue; 00451 for (m = 0; m < s->rx[l].fec_entries; m++) { 00452 limit = (l + m) & UDPTL_BUF_MASK; 00453 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) { 00454 if (s->rx[k].buf_len <= 0) 00455 which = (which == -1) ? k : -2; 00456 } 00457 if (which >= 0) { 00458 /* Repairable */ 00459 for (j = 0; j < s->rx[l].fec_len[m]; j++) { 00460 s->rx[which].buf[j] = s->rx[l].fec[m][j]; 00461 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) 00462 s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; 00463 } 00464 s->rx[which].buf_len = s->rx[l].fec_len[m]; 00465 repaired[which] = TRUE; 00466 } 00467 } 00468 } 00469 /* Now play any new packets forwards in time */ 00470 for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { 00471 if (repaired[l]) { 00472 //fprintf(stderr, "Fixed packet %d, len %d\n", j, l); 00473 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00474 s->f[ifp_no].subclass = AST_MODEM_T38; 00475 00476 s->f[ifp_no].mallocd = 0; 00477 s->f[ifp_no].seqno = j; 00478 s->f[ifp_no].datalen = s->rx[l].buf_len; 00479 s->f[ifp_no].data.ptr = s->rx[l].buf; 00480 s->f[ifp_no].offset = 0; 00481 s->f[ifp_no].src = "UDPTL"; 00482 if (ifp_no > 0) 00483 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00484 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00485 ifp_no++; 00486 } 00487 } 00488 } 00489 00490 /* If packets are received out of sequence, we may have already processed this packet from the error 00491 recovery information in a packet already received. */ 00492 if (seq_no >= s->rx_seq_no) { 00493 /* Decode the primary IFP packet */ 00494 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00495 s->f[ifp_no].subclass = AST_MODEM_T38; 00496 00497 s->f[ifp_no].mallocd = 0; 00498 s->f[ifp_no].seqno = seq_no; 00499 s->f[ifp_no].datalen = ifp_len; 00500 s->f[ifp_no].data.ptr = (uint8_t *) ifp; 00501 s->f[ifp_no].offset = 0; 00502 s->f[ifp_no].src = "UDPTL"; 00503 if (ifp_no > 0) 00504 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00505 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00506 00507 ifp_no++; 00508 } 00509 00510 s->rx_seq_no = seq_no + 1; 00511 return ifp_no; 00512 }
| static int udptlread | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 650 of file udptl.c.
References ast_udptl_read(), ast_udptl::callback, ast_udptl::data, and f.
Referenced by ast_udptl_new_with_bindaddr().
struct ast_cli_entry cli_handle_udptl_debug_deprecated = AST_CLI_DEFINE(handle_cli_udptl_debug_deprecated, "Enable/Disable UDPTL debugging") [static] |
struct ast_cli_entry cli_udptl[] [static] |
int udptldebug [static] |
struct sockaddr_in udptldebugaddr [static] |
Debug packets to/from this host
Definition at line 80 of file udptl.c.
Referenced by handle_cli_udptl_debug_deprecated(), handle_cli_udptl_set_debug(), and udptl_debug_test_addr().
int udptlfecentries [static] |
int udptlfecspan [static] |
enum ast_t38_ec_modes udptlfectype [static] |
int udptlmaxdatagram [static] |
int udptlstart = 4500 [static] |
int use_even_ports [static] |
1.6.1