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 | DEFAULT_FAX_MAX_DATAGRAM 400 |
| #define | FAX_MAX_DATAGRAM_LIMIT 1400 |
| #define | LOCAL_FAX_MAX_DATAGRAM 1400 |
| #define | LOG_TAG(u) S_OR(u->tag, "no tag") |
| #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 (struct ast_udptl *udptl) |
| retrieves far max ifp | |
| unsigned int | ast_udptl_get_local_max_datagram (struct ast_udptl *udptl) |
| retrieves local_max_datagram. | |
| 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) |
| sets far max datagram size. If max_datagram is = 0, the far max datagram size is set to a default value. | |
| 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_set_tag (struct ast_udptl *udptl, const char *format,...) |
| Associates a character string 'tag' with a UDPTL session. | |
| 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 (const struct ast_udptl *udptl, 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 int | udptlstart = 4500 |
| static int | use_even_ports |
UDPTL support for T.38 faxing.
Definition in file udptl.c.
| #define DEFAULT_FAX_MAX_DATAGRAM 400 |
Definition at line 94 of file udptl.c.
Referenced by ast_udptl_set_far_max_datagram(), and ast_udptl_write().
| #define FAX_MAX_DATAGRAM_LIMIT 1400 |
Definition at line 95 of file udptl.c.
Referenced by ast_udptl_set_far_max_datagram().
| #define LOCAL_FAX_MAX_DATAGRAM 1400 |
Definition at line 93 of file udptl.c.
Referenced by calculate_local_max_datagram(), udptl_build_packet(), and udptl_rx_packet().
| #define LOG_TAG | ( | u | ) | S_OR(u->tag, "no tag") |
Definition at line 80 of file udptl.c.
Referenced by ast_udptl_read(), ast_udptl_write(), calculate_far_max_ifp(), calculate_local_max_datagram(), encode_open_type(), and udptl_build_packet().
| #define MAX_FEC_ENTRIES 5 |
Definition at line 96 of file udptl.c.
Referenced by __ast_udptl_reload().
| #define MAX_FEC_SPAN 5 |
Definition at line 97 of file udptl.c.
Referenced by __ast_udptl_reload().
| #define UDPTL_BUF_MASK 15 |
Definition at line 99 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 1403 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, LOG_NOTICE, LOG_WARNING, MAX_FEC_ENTRIES, MAX_FEC_SPAN, and s.
Referenced by ast_udptl_init(), and ast_udptl_reload().
01404 { 01405 struct ast_config *cfg; 01406 const char *s; 01407 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01408 01409 if ((cfg = ast_config_load2("udptl.conf", "udptl", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 01410 return; 01411 01412 udptlstart = 4500; 01413 udptlend = 4999; 01414 udptlfecentries = 0; 01415 udptlfecspan = 0; 01416 use_even_ports = 0; 01417 01418 if (cfg) { 01419 if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) { 01420 udptlstart = atoi(s); 01421 if (udptlstart < 1024) { 01422 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01423 udptlstart = 1024; 01424 } 01425 if (udptlstart > 65535) { 01426 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01427 udptlstart = 65535; 01428 } 01429 } 01430 if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) { 01431 udptlend = atoi(s); 01432 if (udptlend < 1024) { 01433 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01434 udptlend = 1024; 01435 } 01436 if (udptlend > 65535) { 01437 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01438 udptlend = 65535; 01439 } 01440 } 01441 if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) { 01442 #ifdef SO_NO_CHECK 01443 if (ast_false(s)) 01444 nochecksums = 1; 01445 else 01446 nochecksums = 0; 01447 #else 01448 if (ast_false(s)) 01449 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n"); 01450 #endif 01451 } 01452 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) { 01453 ast_log(LOG_WARNING, "T38FaxUdpEC in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n"); 01454 } 01455 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) { 01456 ast_log(LOG_WARNING, "T38FaxMaxDatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n"); 01457 } 01458 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECEntries"))) { 01459 udptlfecentries = atoi(s); 01460 if (udptlfecentries < 1) { 01461 ast_log(LOG_WARNING, "Too small UDPTLFECEntries value. Defaulting to 1.\n"); 01462 udptlfecentries = 1; 01463 } 01464 if (udptlfecentries > MAX_FEC_ENTRIES) { 01465 ast_log(LOG_WARNING, "Too large UDPTLFECEntries value. Defaulting to %d.\n", MAX_FEC_ENTRIES); 01466 udptlfecentries = MAX_FEC_ENTRIES; 01467 } 01468 } 01469 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECSpan"))) { 01470 udptlfecspan = atoi(s); 01471 if (udptlfecspan < 1) { 01472 ast_log(LOG_WARNING, "Too small UDPTLFECSpan value. Defaulting to 1.\n"); 01473 udptlfecspan = 1; 01474 } 01475 if (udptlfecspan > MAX_FEC_SPAN) { 01476 ast_log(LOG_WARNING, "Too large UDPTLFECSpan value. Defaulting to %d.\n", MAX_FEC_SPAN); 01477 udptlfecspan = MAX_FEC_SPAN; 01478 } 01479 } 01480 if ((s = ast_variable_retrieve(cfg, "general", "use_even_ports"))) { 01481 use_even_ports = ast_true(s); 01482 } 01483 ast_config_destroy(cfg); 01484 } 01485 if (udptlstart >= udptlend) { 01486 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to 4500-4999.\n"); 01487 udptlstart = 4500; 01488 udptlend = 4999; 01489 } 01490 if (use_even_ports && (udptlstart & 1)) { 01491 ++udptlstart; 01492 ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", udptlstart); 01493 } 01494 if (use_even_ports && (udptlend & 1)) { 01495 --udptlend; 01496 ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_event_ports enabled. udptlend is now %d\n", udptlend); 01497 } 01498 ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend); 01499 }
| 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 1150 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.
01151 { 01152 struct ast_frame *f; 01153 struct ast_channel *who; 01154 struct ast_channel *cs[3]; 01155 struct ast_udptl *p0; 01156 struct ast_udptl *p1; 01157 struct ast_udptl_protocol *pr0; 01158 struct ast_udptl_protocol *pr1; 01159 struct sockaddr_in ac0; 01160 struct sockaddr_in ac1; 01161 struct sockaddr_in t0; 01162 struct sockaddr_in t1; 01163 void *pvt0; 01164 void *pvt1; 01165 int to; 01166 01167 ast_channel_lock(c0); 01168 while (ast_channel_trylock(c1)) { 01169 ast_channel_unlock(c0); 01170 usleep(1); 01171 ast_channel_lock(c0); 01172 } 01173 pr0 = get_proto(c0); 01174 pr1 = get_proto(c1); 01175 if (!pr0) { 01176 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01177 ast_channel_unlock(c0); 01178 ast_channel_unlock(c1); 01179 return -1; 01180 } 01181 if (!pr1) { 01182 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01183 ast_channel_unlock(c0); 01184 ast_channel_unlock(c1); 01185 return -1; 01186 } 01187 pvt0 = c0->tech_pvt; 01188 pvt1 = c1->tech_pvt; 01189 p0 = pr0->get_udptl_info(c0); 01190 p1 = pr1->get_udptl_info(c1); 01191 if (!p0 || !p1) { 01192 /* Somebody doesn't want to play... */ 01193 ast_channel_unlock(c0); 01194 ast_channel_unlock(c1); 01195 return -2; 01196 } 01197 if (pr0->set_udptl_peer(c0, p1)) { 01198 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01199 memset(&ac1, 0, sizeof(ac1)); 01200 } else { 01201 /* Store UDPTL peer */ 01202 ast_udptl_get_peer(p1, &ac1); 01203 } 01204 if (pr1->set_udptl_peer(c1, p0)) { 01205 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01206 memset(&ac0, 0, sizeof(ac0)); 01207 } else { 01208 /* Store UDPTL peer */ 01209 ast_udptl_get_peer(p0, &ac0); 01210 } 01211 ast_channel_unlock(c0); 01212 ast_channel_unlock(c1); 01213 cs[0] = c0; 01214 cs[1] = c1; 01215 cs[2] = NULL; 01216 for (;;) { 01217 if ((c0->tech_pvt != pvt0) || 01218 (c1->tech_pvt != pvt1) || 01219 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01220 ast_debug(1, "Oooh, something is weird, backing out\n"); 01221 /* Tell it to try again later */ 01222 return -3; 01223 } 01224 to = -1; 01225 ast_udptl_get_peer(p1, &t1); 01226 ast_udptl_get_peer(p0, &t0); 01227 if (inaddrcmp(&t1, &ac1)) { 01228 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 01229 c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port)); 01230 ast_debug(1, "Oooh, '%s' was %s:%d\n", 01231 c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port)); 01232 memcpy(&ac1, &t1, sizeof(ac1)); 01233 } 01234 if (inaddrcmp(&t0, &ac0)) { 01235 ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 01236 c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port)); 01237 ast_debug(1, "Oooh, '%s' was %s:%d\n", 01238 c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port)); 01239 memcpy(&ac0, &t0, sizeof(ac0)); 01240 } 01241 who = ast_waitfor_n(cs, 2, &to); 01242 if (!who) { 01243 ast_debug(1, "Ooh, empty read...\n"); 01244 /* check for hangup / whentohangup */ 01245 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01246 break; 01247 continue; 01248 } 01249 f = ast_read(who); 01250 if (!f) { 01251 *fo = f; 01252 *rc = who; 01253 ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01254 /* That's all we needed */ 01255 return 0; 01256 } else { 01257 if (f->frametype == AST_FRAME_MODEM) { 01258 /* Forward T.38 frames if they happen upon us */ 01259 if (who == c0) { 01260 ast_write(c1, f); 01261 } else if (who == c1) { 01262 ast_write(c0, f); 01263 } 01264 } 01265 ast_frfree(f); 01266 } 01267 /* Swap priority. Not that it's a big deal at this point */ 01268 cs[2] = cs[0]; 01269 cs[0] = cs[1]; 01270 cs[1] = cs[2]; 01271 } 01272 return -1; 01273 }
| void ast_udptl_destroy | ( | struct ast_udptl * | udptl | ) |
Definition at line 1049 of file udptl.c.
References ast_free, ast_io_remove(), ast_udptl::fd, ast_udptl::io, ast_udptl::ioid, and ast_udptl::tag.
Referenced by __sip_destroy(), and create_addr_from_peer().
| int ast_udptl_fd | ( | const struct ast_udptl * | udptl | ) |
Definition at line 640 of file udptl.c.
References ast_udptl::fd.
Referenced by __oh323_new(), and sip_new().
00641 { 00642 return udptl->fd; 00643 }
| enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme | ( | const struct ast_udptl * | udptl | ) |
Definition at line 831 of file udptl.c.
References ast_udptl::error_correction_scheme.
Referenced by add_sdp().
00832 { 00833 return udptl->error_correction_scheme; 00834 }
| unsigned int ast_udptl_get_far_max_datagram | ( | const struct ast_udptl * | udptl | ) |
Definition at line 899 of file udptl.c.
References ast_udptl::far_max_datagram.
Referenced by process_sdp().
00900 { 00901 if (udptl->far_max_datagram < 0) { 00902 return 0; 00903 } 00904 return udptl->far_max_datagram; 00905 }
| unsigned int ast_udptl_get_far_max_ifp | ( | struct ast_udptl * | udptl | ) |
retrieves far max ifp
| positive | value representing max ifp size | |
| 0 | if no value is present |
Definition at line 907 of file udptl.c.
References calculate_far_max_ifp(), and ast_udptl::far_max_ifp.
Referenced by change_t38_state().
00908 { 00909 if (udptl->far_max_ifp == -1) { 00910 calculate_far_max_ifp(udptl); 00911 } 00912 00913 if (udptl->far_max_ifp < 0) { 00914 return 0; 00915 } 00916 return udptl->far_max_ifp; 00917 }
| unsigned int ast_udptl_get_local_max_datagram | ( | struct ast_udptl * | udptl | ) |
retrieves local_max_datagram.
| positive | value representing max datagram size. | |
| 0 | if no value is present |
Definition at line 875 of file udptl.c.
References calculate_local_max_datagram(), and ast_udptl::local_max_datagram.
Referenced by add_sdp().
00876 { 00877 if (udptl->local_max_datagram == -1) { 00878 calculate_local_max_datagram(udptl); 00879 } 00880 00881 /* this function expects a unsigned value in return. */ 00882 if (udptl->local_max_datagram < 0) { 00883 return 0; 00884 } 00885 return udptl->local_max_datagram; 00886 }
| void ast_udptl_get_peer | ( | const struct ast_udptl * | udptl, | |
| struct sockaddr_in * | them | |||
| ) |
Definition at line 1030 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 1507 of file udptl.c.
References __ast_udptl_reload(), and ast_cli_register_multiple().
Referenced by main().
01508 { 01509 ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry)); 01510 __ast_udptl_reload(0); 01511 }
| struct ast_udptl* ast_udptl_new | ( | struct sched_context * | sched, | |
| struct io_context * | io, | |||
| int | callbackmode | |||
| ) | [read] |
Definition at line 997 of file udptl.c.
References ast_udptl_new_with_bindaddr().
00998 { 00999 struct in_addr ia; 01000 memset(&ia, 0, sizeof(ia)); 01001 return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia); 01002 }
| 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 919 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_span, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, ast_udptl::fd, ast_udptl::flags, ast_udptl::io, ast_udptl::ioid, ast_udptl::local_max_datagram, ast_udptl::local_max_ifp, 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().
00920 { 00921 struct ast_udptl *udptl; 00922 int x; 00923 int startplace; 00924 int i; 00925 long int flags; 00926 00927 if (!(udptl = ast_calloc(1, sizeof(*udptl)))) 00928 return NULL; 00929 00930 udptl->error_correction_span = udptlfecspan; 00931 udptl->error_correction_entries = udptlfecentries; 00932 00933 udptl->far_max_datagram = -1; 00934 udptl->far_max_ifp = -1; 00935 udptl->local_max_ifp = -1; 00936 udptl->local_max_datagram = -1; 00937 00938 for (i = 0; i <= UDPTL_BUF_MASK; i++) { 00939 udptl->rx[i].buf_len = -1; 00940 udptl->tx[i].buf_len = -1; 00941 } 00942 00943 udptl->them.sin_family = AF_INET; 00944 udptl->us.sin_family = AF_INET; 00945 00946 if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00947 ast_free(udptl); 00948 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00949 return NULL; 00950 } 00951 flags = fcntl(udptl->fd, F_GETFL); 00952 fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK); 00953 #ifdef SO_NO_CHECK 00954 if (nochecksums) 00955 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00956 #endif 00957 /* Find us a place */ 00958 x = (udptlstart == udptlend) ? udptlstart : (ast_random() % (udptlend - udptlstart)) + udptlstart; 00959 if (use_even_ports && (x & 1)) { 00960 ++x; 00961 } 00962 startplace = x; 00963 for (;;) { 00964 udptl->us.sin_port = htons(x); 00965 udptl->us.sin_addr = addr; 00966 if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0) 00967 break; 00968 if (errno != EADDRINUSE) { 00969 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00970 close(udptl->fd); 00971 ast_free(udptl); 00972 return NULL; 00973 } 00974 if (use_even_ports) { 00975 x += 2; 00976 } else { 00977 ++x; 00978 } 00979 if (x > udptlend) 00980 x = udptlstart; 00981 if (x == startplace) { 00982 ast_log(LOG_WARNING, "No UDPTL ports remaining\n"); 00983 close(udptl->fd); 00984 ast_free(udptl); 00985 return NULL; 00986 } 00987 } 00988 if (io && sched && callbackmode) { 00989 /* Operate this one in a callback mode */ 00990 udptl->sched = sched; 00991 udptl->io = io; 00992 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl); 00993 } 00994 return udptl; 00995 }
| int ast_udptl_proto_register | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 1119 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().
01120 { 01121 struct ast_udptl_protocol *cur; 01122 01123 AST_RWLIST_WRLOCK(&protos); 01124 AST_RWLIST_TRAVERSE(&protos, cur, list) { 01125 if (cur->type == proto->type) { 01126 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01127 AST_RWLIST_UNLOCK(&protos); 01128 return -1; 01129 } 01130 } 01131 AST_RWLIST_INSERT_TAIL(&protos, proto, list); 01132 AST_RWLIST_UNLOCK(&protos); 01133 return 0; 01134 }
| void ast_udptl_proto_unregister | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 1112 of file udptl.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by unload_module().
01113 { 01114 AST_RWLIST_WRLOCK(&protos); 01115 AST_RWLIST_REMOVE(&protos, proto, list); 01116 AST_RWLIST_UNLOCK(&protos); 01117 }
Definition at line 672 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_TAG, 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().
00673 { 00674 int res; 00675 struct sockaddr_in sin; 00676 socklen_t len; 00677 uint16_t seqno = 0; 00678 uint16_t *udptlheader; 00679 00680 len = sizeof(sin); 00681 00682 /* Cache where the header will go */ 00683 res = recvfrom(udptl->fd, 00684 udptl->rawdata + AST_FRIENDLY_OFFSET, 00685 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET, 00686 0, 00687 (struct sockaddr *) &sin, 00688 &len); 00689 udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET); 00690 if (res < 0) { 00691 if (errno != EAGAIN) 00692 ast_log(LOG_WARNING, "(%s): UDPTL read error: %s\n", 00693 LOG_TAG(udptl), strerror(errno)); 00694 ast_assert(errno != EBADF); 00695 return &ast_null_frame; 00696 } 00697 00698 /* Ignore if the other side hasn't been given an address yet. */ 00699 if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port) 00700 return &ast_null_frame; 00701 00702 if (udptl->nat) { 00703 /* Send to whoever sent to us */ 00704 if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00705 (udptl->them.sin_port != sin.sin_port)) { 00706 memcpy(&udptl->them, &sin, sizeof(udptl->them)); 00707 ast_debug(1, "UDPTL NAT (%s): Using address %s:%d\n", 00708 LOG_TAG(udptl), ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port)); 00709 } 00710 } 00711 00712 if (udptl_debug_test_addr(&sin)) { 00713 ast_verb(1, "UDPTL (%s): packet from %s:%d (type %d, seq %d, len %d)\n", 00714 LOG_TAG(udptl), ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res); 00715 } 00716 if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1) 00717 return &ast_null_frame; 00718 00719 return &udptl->f[0]; 00720 }
| int ast_udptl_reload | ( | void | ) |
Definition at line 1501 of file udptl.c.
References __ast_udptl_reload().
01502 { 01503 __ast_udptl_reload(1); 01504 return 0; 01505 }
| void ast_udptl_set_callback | ( | struct ast_udptl * | udptl, | |
| ast_udptl_callback | callback | |||
| ) |
Definition at line 650 of file udptl.c.
References ast_udptl::callback.
00651 { 00652 udptl->callback = callback; 00653 }
| void ast_udptl_set_data | ( | struct ast_udptl * | udptl, | |
| void * | data | |||
| ) |
Definition at line 645 of file udptl.c.
References ast_udptl::data.
00646 { 00647 udptl->data = data; 00648 }
| void ast_udptl_set_error_correction_scheme | ( | struct ast_udptl * | udptl, | |
| enum ast_t38_ec_modes | ec | |||
| ) |
Definition at line 836 of file udptl.c.
References ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, ast_udptl::error_correction_span, ast_udptl::far_max_ifp, ast_udptl::local_max_datagram, UDPTL_ERROR_CORRECTION_FEC, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by process_sdp_a_image(), and set_t38_capabilities().
00837 { 00838 udptl->error_correction_scheme = ec; 00839 switch (ec) { 00840 case UDPTL_ERROR_CORRECTION_FEC: 00841 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00842 if (udptl->error_correction_entries == 0) { 00843 udptl->error_correction_entries = 3; 00844 } 00845 if (udptl->error_correction_span == 0) { 00846 udptl->error_correction_span = 3; 00847 } 00848 break; 00849 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00850 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00851 if (udptl->error_correction_entries == 0) { 00852 udptl->error_correction_entries = 3; 00853 } 00854 break; 00855 default: 00856 /* nothing to do */ 00857 break; 00858 }; 00859 /* reset calculated values so they'll be computed again */ 00860 udptl->local_max_datagram = -1; 00861 udptl->far_max_ifp = -1; 00862 }
| void ast_udptl_set_far_max_datagram | ( | struct ast_udptl * | udptl, | |
| unsigned int | max_datagram | |||
| ) |
sets far max datagram size. If max_datagram is = 0, the far max datagram size is set to a default value.
Definition at line 888 of file udptl.c.
References DEFAULT_FAX_MAX_DATAGRAM, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, and FAX_MAX_DATAGRAM_LIMIT.
Referenced by process_sdp(), and process_sdp_a_image().
00889 { 00890 if (!max_datagram || (max_datagram > FAX_MAX_DATAGRAM_LIMIT)) { 00891 udptl->far_max_datagram = DEFAULT_FAX_MAX_DATAGRAM; 00892 } else { 00893 udptl->far_max_datagram = max_datagram; 00894 } 00895 /* reset calculated values so they'll be computed again */ 00896 udptl->far_max_ifp = -1; 00897 }
| void ast_udptl_set_local_max_ifp | ( | struct ast_udptl * | udptl, | |
| unsigned int | max_ifp | |||
| ) |
Definition at line 864 of file udptl.c.
References ast_udptl::local_max_datagram, and ast_udptl::local_max_ifp.
Referenced by interpret_t38_parameters().
00865 { 00866 /* make sure max_ifp is a positive value since a cast will take place when 00867 * when setting local_max_ifp */ 00868 if ((signed int) max_ifp > 0) { 00869 udptl->local_max_ifp = max_ifp; 00870 /* reset calculated values so they'll be computed again */ 00871 udptl->local_max_datagram = -1; 00872 } 00873 }
| void ast_udptl_set_peer | ( | struct ast_udptl * | udptl, | |
| const struct sockaddr_in * | them | |||
| ) |
| void ast_udptl_set_tag | ( | struct ast_udptl * | udptl, | |
| const char * | format, | |||
| ... | ||||
| ) |
Associates a character string 'tag' with a UDPTL session.
| udptl | The UDPTL session. | |
| format | printf-style format string used to construct the tag |
This function formats a tag for the specified UDPTL session, so that any log messages generated by the UDPTL stack related to that session will include the tag and the reader of the messages will be able to identify which endpoint caused them to be generated.
| none |
Definition at line 1004 of file udptl.c.
References ast_free, ast_vasprintf, and ast_udptl::tag.
Referenced by change_t38_state().
| 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 1019 of file udptl.c.
References ast_netsock_set_qos(), and ast_udptl::fd.
Referenced by sip_alloc().
01020 { 01021 return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL"); 01022 }
| void ast_udptl_stop | ( | struct ast_udptl * | udptl | ) |
Definition at line 1043 of file udptl.c.
References ast_udptl::them.
Referenced by process_sdp(), and stop_media_flows().
Definition at line 1060 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, DEFAULT_FAX_MAX_DATAGRAM, errno, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, ast_udptl::fd, ast_frame::frametype, len(), LOG_NOTICE, LOG_TAG, 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().
01061 { 01062 unsigned int seq; 01063 unsigned int len = f->datalen; 01064 int res; 01065 /* if no max datagram size is provided, use default value */ 01066 const int bufsize = (s->far_max_datagram > 0) ? s->far_max_datagram : DEFAULT_FAX_MAX_DATAGRAM; 01067 uint8_t buf[bufsize]; 01068 01069 memset(buf, 0, sizeof(buf)); 01070 01071 /* If we have no peer, return immediately */ 01072 if (s->them.sin_addr.s_addr == INADDR_ANY) 01073 return 0; 01074 01075 /* If there is no data length, return immediately */ 01076 if (f->datalen == 0) 01077 return 0; 01078 01079 if ((f->frametype != AST_FRAME_MODEM) || 01080 (f->subclass != AST_MODEM_T38)) { 01081 ast_log(LOG_WARNING, "(%s): UDPTL can only send T.38 data.\n", 01082 LOG_TAG(s)); 01083 return -1; 01084 } 01085 01086 if (len > s->far_max_ifp) { 01087 ast_log(LOG_WARNING, 01088 "(%s): UDPTL asked to send %d bytes of IFP when far end only prepared to accept %d bytes; data loss will occur." 01089 "You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n", 01090 LOG_TAG(s), len, s->far_max_ifp); 01091 len = s->far_max_ifp; 01092 } 01093 01094 /* Save seq_no for debug output because udptl_build_packet increments it */ 01095 seq = s->tx_seq_no & 0xFFFF; 01096 01097 /* Cook up the UDPTL packet, with the relevant EC info. */ 01098 len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, len); 01099 01100 if (len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) { 01101 if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0) 01102 ast_log(LOG_NOTICE, "(%s): UDPTL Transmission error to %s:%d: %s\n", 01103 LOG_TAG(s), ast_inet_ntoa(s->them.sin_addr), ntohs(s->them.sin_port), strerror(errno)); 01104 if (udptl_debug_test_addr(&s->them)) 01105 ast_verb(1, "UDPTL (%s): packet to %s:%d (type %d, seq %d, len %d)\n", 01106 LOG_TAG(s), ast_inet_ntoa(s->them.sin_addr), ntohs(s->them.sin_port), 0, seq, len); 01107 } 01108 01109 return 0; 01110 }
| static void calculate_far_max_ifp | ( | struct ast_udptl * | udptl | ) | [static] |
Definition at line 763 of file udptl.c.
References ast_log(), ast_udptl::error_correction_entries, ast_udptl::error_correction_scheme, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, LOG_TAG, LOG_WARNING, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by ast_udptl_get_far_max_ifp().
00764 { 00765 unsigned new_max = 0; 00766 00767 if (udptl->far_max_datagram == -1) { 00768 ast_log(LOG_WARNING, "(%s): Cannot calculate far_max_ifp before far_max_datagram has been set.\n", 00769 LOG_TAG(udptl)); 00770 udptl->far_max_ifp = -1; 00771 return; 00772 } 00773 00774 /* the goal here is to supply the local endpoint (application 00775 * or bridged channel) a maximum IFP value that will allow it 00776 * to effectively and efficiently transfer image data at its 00777 * selected bit rate, taking into account the selected error 00778 * correction mode, but without overrunning the far endpoint's 00779 * datagram buffer. this is complicated by the fact that some 00780 * far endpoints send us bogus (small) max datagram values, 00781 * which would result in either buffer overrun or no error 00782 * correction. we try to accomodate those, but if the supplied 00783 * value is too small to do so, we'll emit warning messages and 00784 * the user will have to use configuration options to override 00785 * the max datagram value supplied by the far endpoint. 00786 */ 00787 switch (udptl->error_correction_scheme) { 00788 case UDPTL_ERROR_CORRECTION_NONE: 00789 /* need room for sequence number, length indicator, redundancy 00790 * indicator and following length indicator 00791 */ 00792 new_max = udptl->far_max_datagram - 5; 00793 break; 00794 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00795 /* for this case, we'd like to send as many error correction entries 00796 * as possible (up to the number we're configured for), but we'll settle 00797 * for sending fewer if the configured number would cause the 00798 * calculated max IFP to be too small for effective operation 00799 * 00800 * need room for sequence number, length indicators and the 00801 * configured number of redundant packets 00802 * 00803 * note: we purposely don't allow error_correction_entries to drop to 00804 * zero in this loop; we'd rather send smaller IFPs (and thus reduce 00805 * the image data transfer rate) than sacrifice redundancy completely 00806 */ 00807 for (;;) { 00808 new_max = (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1); 00809 00810 if ((new_max < 80) && (udptl->error_correction_entries > 1)) { 00811 /* the max ifp is not large enough, subtract an 00812 * error correction entry and calculate again 00813 * */ 00814 --udptl->error_correction_entries; 00815 } else { 00816 break; 00817 } 00818 } 00819 break; 00820 case UDPTL_ERROR_CORRECTION_FEC: 00821 /* need room for sequence number, length indicators and a 00822 * a single IFP of the maximum size expected 00823 */ 00824 new_max = (udptl->far_max_datagram - 10) / 2; 00825 break; 00826 } 00827 /* subtract 5% of space for insurance */ 00828 udptl->far_max_ifp = new_max * 0.95; 00829 }
| static void calculate_local_max_datagram | ( | struct ast_udptl * | udptl | ) | [static] |
Definition at line 722 of file udptl.c.
References ast_log(), ast_udptl::error_correction_scheme, LOCAL_FAX_MAX_DATAGRAM, ast_udptl::local_max_datagram, ast_udptl::local_max_ifp, LOG_TAG, LOG_WARNING, MIN, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by ast_udptl_get_local_max_datagram().
00723 { 00724 unsigned int new_max = 0; 00725 00726 if (udptl->local_max_ifp == -1) { 00727 ast_log(LOG_WARNING, "(%s): Cannot calculate local_max_datagram before local_max_ifp has been set.\n", 00728 LOG_TAG(udptl)); 00729 udptl->local_max_datagram = -1; 00730 return; 00731 } 00732 00733 /* calculate the amount of space required to receive an IFP 00734 * of the maximum size supported by the application/endpoint 00735 * that we are delivering them to (local endpoint), and add 00736 * the amount of space required to support the selected 00737 * error correction mode 00738 */ 00739 switch (udptl->error_correction_scheme) { 00740 case UDPTL_ERROR_CORRECTION_NONE: 00741 /* need room for sequence number, length indicator, redundancy 00742 * indicator and following length indicator 00743 */ 00744 new_max = 5 + udptl->local_max_ifp; 00745 break; 00746 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00747 /* need room for sequence number, length indicators, plus 00748 * room for up to 3 redundancy packets 00749 */ 00750 new_max = 5 + udptl->local_max_ifp + 2 + (3 * udptl->local_max_ifp); 00751 break; 00752 case UDPTL_ERROR_CORRECTION_FEC: 00753 /* need room for sequence number, length indicators and a 00754 * a single IFP of the maximum size expected 00755 */ 00756 new_max = 5 + udptl->local_max_ifp + 4 + udptl->local_max_ifp; 00757 break; 00758 } 00759 /* add 5% extra space for insurance, but no larger than LOCAL_FAX_MAX_DATAGRAM */ 00760 udptl->local_max_datagram = MIN(new_max * 1.05, LOCAL_FAX_MAX_DATAGRAM); 00761 }
| static int decode_length | ( | uint8_t * | buf, | |
| unsigned int | limit, | |||
| unsigned int * | len, | |||
| unsigned int * | pvalue | |||
| ) | [static] |
Definition at line 200 of file udptl.c.
Referenced by decode_open_type(), and udptl_rx_packet().
00201 { 00202 if (*len >= limit) 00203 return -1; 00204 if ((buf[*len] & 0x80) == 0) { 00205 *pvalue = buf[*len]; 00206 (*len)++; 00207 return 0; 00208 } 00209 if ((buf[*len] & 0x40) == 0) { 00210 if (*len == limit - 1) 00211 return -1; 00212 *pvalue = (buf[*len] & 0x3F) << 8; 00213 (*len)++; 00214 *pvalue |= buf[*len]; 00215 (*len)++; 00216 return 0; 00217 } 00218 *pvalue = (buf[*len] & 0x3F) << 14; 00219 (*len)++; 00220 /* Indicate we have a fragment */ 00221 return 1; 00222 }
| 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 225 of file udptl.c.
References decode_length().
Referenced by udptl_rx_packet().
00226 { 00227 unsigned int octet_cnt; 00228 unsigned int octet_idx; 00229 unsigned int length; 00230 unsigned int i; 00231 const uint8_t **pbuf; 00232 00233 for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) { 00234 octet_cnt = 0; 00235 if ((length = decode_length(buf, limit, len, &octet_cnt)) < 0) 00236 return -1; 00237 if (octet_cnt > 0) { 00238 *p_num_octets += octet_cnt; 00239 00240 pbuf = &p_object[octet_idx]; 00241 i = 0; 00242 /* Make sure the buffer contains at least the number of bits requested */ 00243 if ((*len + octet_cnt) > limit) 00244 return -1; 00245 00246 *pbuf = &buf[*len]; 00247 *len += octet_cnt; 00248 } 00249 if (length == 0) 00250 break; 00251 } 00252 return 0; 00253 }
| static unsigned int encode_length | ( | uint8_t * | buf, | |
| unsigned int * | len, | |||
| unsigned int | value | |||
| ) | [static] |
Definition at line 256 of file udptl.c.
Referenced by encode_open_type(), and udptl_build_packet().
00257 { 00258 unsigned int multiplier; 00259 00260 if (value < 0x80) { 00261 /* 1 octet */ 00262 buf[*len] = value; 00263 (*len)++; 00264 return value; 00265 } 00266 if (value < 0x4000) { 00267 /* 2 octets */ 00268 /* Set the first bit of the first octet */ 00269 buf[*len] = ((0x8000 | value) >> 8) & 0xFF; 00270 (*len)++; 00271 buf[*len] = value & 0xFF; 00272 (*len)++; 00273 return value; 00274 } 00275 /* Fragmentation */ 00276 multiplier = (value < 0x10000) ? (value >> 14) : 4; 00277 /* Set the first 2 bits of the octet */ 00278 buf[*len] = 0xC0 | multiplier; 00279 (*len)++; 00280 return multiplier << 14; 00281 }
| static int encode_open_type | ( | const struct ast_udptl * | udptl, | |
| uint8_t * | buf, | |||
| unsigned int | buflen, | |||
| unsigned int * | len, | |||
| const uint8_t * | data, | |||
| unsigned int | num_octets | |||
| ) | [static] |
Definition at line 284 of file udptl.c.
References ast_log(), encode_length(), LOG_ERROR, and LOG_TAG.
Referenced by udptl_build_packet().
00286 { 00287 unsigned int enclen; 00288 unsigned int octet_idx; 00289 uint8_t zero_byte; 00290 00291 /* If open type is of zero length, add a single zero byte (10.1) */ 00292 if (num_octets == 0) { 00293 zero_byte = 0; 00294 data = &zero_byte; 00295 num_octets = 1; 00296 } 00297 /* Encode the open type */ 00298 for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) { 00299 if ((enclen = encode_length(buf, len, num_octets)) < 0) 00300 return -1; 00301 if (enclen + *len > buflen) { 00302 ast_log(LOG_ERROR, "(%s): Buffer overflow detected (%d + %d > %d)\n", 00303 LOG_TAG(udptl), enclen, *len, buflen); 00304 return -1; 00305 } 00306 if (enclen > 0) { 00307 memcpy(&buf[*len], &data[octet_idx], enclen); 00308 *len += enclen; 00309 } 00310 if (enclen >= num_octets) 00311 break; 00312 } 00313 00314 return 0; 00315 }
| static struct ast_udptl_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 1136 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().
01137 { 01138 struct ast_udptl_protocol *cur = NULL; 01139 01140 AST_RWLIST_RDLOCK(&protos); 01141 AST_RWLIST_TRAVERSE(&protos, cur, list) { 01142 if (cur->type == chan->tech->type) 01143 break; 01144 } 01145 AST_RWLIST_UNLOCK(&protos); 01146 01147 return cur; 01148 }
| static char* handle_cli_udptl_debug_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1275 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.
01276 { 01277 struct hostent *hp; 01278 struct ast_hostent ahp; 01279 int port; 01280 char *p; 01281 char *arg; 01282 01283 switch (cmd) { 01284 case CLI_INIT: 01285 e->command = "udptl debug [off|ip]"; 01286 e->usage = 01287 "Usage: udptl debug [off]|[ip host[:port]]\n" 01288 " Enable or disable dumping of UDPTL packets.\n" 01289 " If ip is specified, limit the dumped packets to those to and from\n" 01290 " the specified 'host' with optional port.\n"; 01291 return NULL; 01292 case CLI_GENERATE: 01293 return NULL; 01294 } 01295 01296 if (a->argc < 2 || a->argc > 4) 01297 return CLI_SHOWUSAGE; 01298 01299 if (a->argc == 2) { 01300 udptldebug = 1; 01301 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr)); 01302 ast_cli(a->fd, "UDPTL Debugging Enabled\n"); 01303 } else if (a->argc == 3) { 01304 if (strncasecmp(a->argv[2], "off", 3)) 01305 return CLI_SHOWUSAGE; 01306 udptldebug = 0; 01307 ast_cli(a->fd, "UDPTL Debugging Disabled\n"); 01308 } else { 01309 if (strncasecmp(a->argv[2], "ip", 2)) 01310 return CLI_SHOWUSAGE; 01311 port = 0; 01312 arg = a->argv[3]; 01313 p = strstr(arg, ":"); 01314 if (p) { 01315 *p = '\0'; 01316 p++; 01317 port = atoi(p); 01318 } 01319 hp = ast_gethostbyname(arg, &ahp); 01320 if (hp == NULL) 01321 return CLI_SHOWUSAGE; 01322 udptldebugaddr.sin_family = AF_INET; 01323 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr)); 01324 udptldebugaddr.sin_port = htons(port); 01325 if (port == 0) 01326 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr)); 01327 else 01328 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port); 01329 udptldebug = 1; 01330 } 01331 01332 return CLI_SUCCESS; 01333 }
| static char* handle_cli_udptl_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1335 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.
01336 { 01337 struct hostent *hp; 01338 struct ast_hostent ahp; 01339 int port; 01340 char *p; 01341 char *arg; 01342 01343 switch (cmd) { 01344 case CLI_INIT: 01345 e->command = "udptl set debug {on|off|ip}"; 01346 e->usage = 01347 "Usage: udptl set debug {on|off|ip host[:port]}\n" 01348 " Enable or disable dumping of UDPTL packets.\n" 01349 " If ip is specified, limit the dumped packets to those to and from\n" 01350 " the specified 'host' with optional port.\n"; 01351 return NULL; 01352 case CLI_GENERATE: 01353 return NULL; 01354 } 01355 01356 if (a->argc < 4 || a->argc > 5) 01357 return CLI_SHOWUSAGE; 01358 01359 if (a->argc == 4) { 01360 if (!strncasecmp(a->argv[3], "on", 2)) { 01361 udptldebug = 1; 01362 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr)); 01363 ast_cli(a->fd, "UDPTL Debugging Enabled\n"); 01364 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01365 udptldebug = 0; 01366 ast_cli(a->fd, "UDPTL Debugging Disabled\n"); 01367 } else { 01368 return CLI_SHOWUSAGE; 01369 } 01370 } else { 01371 if (strncasecmp(a->argv[3], "ip", 2)) 01372 return CLI_SHOWUSAGE; 01373 port = 0; 01374 arg = a->argv[4]; 01375 p = strstr(arg, ":"); 01376 if (p) { 01377 *p = '\0'; 01378 p++; 01379 port = atoi(p); 01380 } 01381 hp = ast_gethostbyname(arg, &ahp); 01382 if (hp == NULL) 01383 return CLI_SHOWUSAGE; 01384 udptldebugaddr.sin_family = AF_INET; 01385 memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr)); 01386 udptldebugaddr.sin_port = htons(port); 01387 if (port == 0) 01388 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr)); 01389 else 01390 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port); 01391 udptldebug = 1; 01392 } 01393 01394 return CLI_SUCCESS; 01395 }
| 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 526 of file udptl.c.
References ast_debug, 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_TAG, 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().
00527 { 00528 uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2]; 00529 int i; 00530 int j; 00531 int seq; 00532 int entry; 00533 int entries; 00534 int span; 00535 int m; 00536 unsigned int len; 00537 int limit; 00538 int high_tide; 00539 00540 seq = s->tx_seq_no & 0xFFFF; 00541 00542 /* Map the sequence number to an entry in the circular buffer */ 00543 entry = seq & UDPTL_BUF_MASK; 00544 00545 /* We save the message in a circular buffer, for generating FEC or 00546 redundancy sets later on. */ 00547 s->tx[entry].buf_len = ifp_len; 00548 memcpy(s->tx[entry].buf, ifp, ifp_len); 00549 00550 /* Build the UDPTLPacket */ 00551 00552 len = 0; 00553 /* Encode the sequence number */ 00554 buf[len++] = (seq >> 8) & 0xFF; 00555 buf[len++] = seq & 0xFF; 00556 00557 /* Encode the primary IFP packet */ 00558 if (encode_open_type(s, buf, buflen, &len, ifp, ifp_len) < 0) 00559 return -1; 00560 00561 /* Encode the appropriate type of error recovery information */ 00562 switch (s->error_correction_scheme) 00563 { 00564 case UDPTL_ERROR_CORRECTION_NONE: 00565 /* Encode the error recovery type */ 00566 buf[len++] = 0x00; 00567 /* The number of entries will always be zero, so it is pointless allowing 00568 for the fragmented case here. */ 00569 if (encode_length(buf, &len, 0) < 0) 00570 return -1; 00571 break; 00572 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00573 /* Encode the error recovery type */ 00574 buf[len++] = 0x00; 00575 if (s->tx_seq_no > s->error_correction_entries) 00576 entries = s->error_correction_entries; 00577 else 00578 entries = s->tx_seq_no; 00579 /* The number of entries will always be small, so it is pointless allowing 00580 for the fragmented case here. */ 00581 if (encode_length(buf, &len, entries) < 0) 00582 return -1; 00583 /* Encode the elements */ 00584 for (i = 0; i < entries; i++) { 00585 j = (entry - i - 1) & UDPTL_BUF_MASK; 00586 if (encode_open_type(s, buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) { 00587 ast_debug(1, "(%s): Encoding failed at i=%d, j=%d\n", 00588 LOG_TAG(s), i, j); 00589 return -1; 00590 } 00591 } 00592 break; 00593 case UDPTL_ERROR_CORRECTION_FEC: 00594 span = s->error_correction_span; 00595 entries = s->error_correction_entries; 00596 if (seq < s->error_correction_span*s->error_correction_entries) { 00597 /* In the initial stages, wind up the FEC smoothly */ 00598 entries = seq/s->error_correction_span; 00599 if (seq < s->error_correction_span) 00600 span = 0; 00601 } 00602 /* Encode the error recovery type */ 00603 buf[len++] = 0x80; 00604 /* Span is defined as an inconstrained integer, which it dumb. It will only 00605 ever be a small value. Treat it as such. */ 00606 buf[len++] = 1; 00607 buf[len++] = span; 00608 /* The number of entries is defined as a length, but will only ever be a small 00609 value. Treat it as such. */ 00610 buf[len++] = entries; 00611 for (m = 0; m < entries; m++) { 00612 /* Make an XOR'ed entry the maximum length */ 00613 limit = (entry + m) & UDPTL_BUF_MASK; 00614 high_tide = 0; 00615 for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { 00616 if (high_tide < s->tx[i].buf_len) { 00617 for (j = 0; j < high_tide; j++) 00618 fec[j] ^= s->tx[i].buf[j]; 00619 for ( ; j < s->tx[i].buf_len; j++) 00620 fec[j] = s->tx[i].buf[j]; 00621 high_tide = s->tx[i].buf_len; 00622 } else { 00623 for (j = 0; j < s->tx[i].buf_len; j++) 00624 fec[j] ^= s->tx[i].buf[j]; 00625 } 00626 } 00627 if (encode_open_type(s, buf, buflen, &len, fec, high_tide) < 0) 00628 return -1; 00629 } 00630 break; 00631 } 00632 00633 if (s->verbose) 00634 fprintf(stderr, "\n"); 00635 00636 s->tx_seq_no++; 00637 return len; 00638 }
| static int udptl_debug_test_addr | ( | const struct sockaddr_in * | addr | ) | [inline, static] |
Definition at line 187 of file udptl.c.
References udptldebugaddr.
Referenced by ast_udptl_read(), and ast_udptl_write().
00188 { 00189 if (udptldebug == 0) 00190 return 0; 00191 if (udptldebugaddr.sin_addr.s_addr) { 00192 if (((ntohs(udptldebugaddr.sin_port) != 0) && 00193 (udptldebugaddr.sin_port != addr->sin_port)) || 00194 (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 00195 return 0; 00196 } 00197 return 1; 00198 }
| static int udptl_rx_packet | ( | struct ast_udptl * | s, | |
| uint8_t * | buf, | |||
| unsigned int | len | |||
| ) | [static] |
Definition at line 318 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().
00319 { 00320 int stat1; 00321 int stat2; 00322 int i; 00323 int j; 00324 int k; 00325 int l; 00326 int m; 00327 int x; 00328 int limit; 00329 int which; 00330 unsigned int ptr; 00331 unsigned int count; 00332 int total_count; 00333 int seq_no; 00334 const uint8_t *ifp; 00335 const uint8_t *data; 00336 unsigned int ifp_len; 00337 int repaired[16]; 00338 const uint8_t *bufs[16]; 00339 unsigned int lengths[16]; 00340 int span; 00341 int entries; 00342 int ifp_no; 00343 00344 ptr = 0; 00345 ifp_no = 0; 00346 memset(&s->f[0], 0, sizeof(s->f[0])); 00347 00348 /* Decode seq_number */ 00349 if (ptr + 2 > len) 00350 return -1; 00351 seq_no = (buf[0] << 8) | buf[1]; 00352 ptr += 2; 00353 00354 /* Break out the primary packet */ 00355 if ((stat1 = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0) 00356 return -1; 00357 /* Decode error_recovery */ 00358 if (ptr + 1 > len) 00359 return -1; 00360 if ((buf[ptr++] & 0x80) == 0) { 00361 /* Secondary packet mode for error recovery */ 00362 if (seq_no > s->rx_seq_no) { 00363 /* We received a later packet than we expected, so we need to check if we can fill in the gap from the 00364 secondary packets. */ 00365 total_count = 0; 00366 do { 00367 if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) 00368 return -1; 00369 for (i = 0; i < count; i++) { 00370 if ((stat1 = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) 00371 return -1; 00372 } 00373 total_count += count; 00374 } 00375 while (stat2 > 0); 00376 /* Step through in reverse order, so we go oldest to newest */ 00377 for (i = total_count; i > 0; i--) { 00378 if (seq_no - i >= s->rx_seq_no) { 00379 /* This one wasn't seen before */ 00380 /* Decode the secondary IFP packet */ 00381 //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); 00382 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00383 s->f[ifp_no].subclass = AST_MODEM_T38; 00384 00385 s->f[ifp_no].mallocd = 0; 00386 s->f[ifp_no].seqno = seq_no - i; 00387 s->f[ifp_no].datalen = lengths[i - 1]; 00388 s->f[ifp_no].data.ptr = (uint8_t *) bufs[i - 1]; 00389 s->f[ifp_no].offset = 0; 00390 s->f[ifp_no].src = "UDPTL"; 00391 if (ifp_no > 0) 00392 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00393 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00394 ifp_no++; 00395 } 00396 } 00397 } 00398 } 00399 else 00400 { 00401 /* FEC mode for error recovery */ 00402 /* Our buffers cannot tolerate overlength IFP packets in FEC mode */ 00403 if (ifp_len > LOCAL_FAX_MAX_DATAGRAM) 00404 return -1; 00405 /* Update any missed slots in the buffer */ 00406 for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) { 00407 x = s->rx_seq_no & UDPTL_BUF_MASK; 00408 s->rx[x].buf_len = -1; 00409 s->rx[x].fec_len[0] = 0; 00410 s->rx[x].fec_span = 0; 00411 s->rx[x].fec_entries = 0; 00412 } 00413 00414 x = seq_no & UDPTL_BUF_MASK; 00415 00416 memset(repaired, 0, sizeof(repaired)); 00417 00418 /* Save the new IFP packet */ 00419 memcpy(s->rx[x].buf, ifp, ifp_len); 00420 s->rx[x].buf_len = ifp_len; 00421 repaired[x] = TRUE; 00422 00423 /* Decode the FEC packets */ 00424 /* The span is defined as an unconstrained integer, but will never be more 00425 than a small value. */ 00426 if (ptr + 2 > len) 00427 return -1; 00428 if (buf[ptr++] != 1) 00429 return -1; 00430 span = buf[ptr++]; 00431 s->rx[x].fec_span = span; 00432 00433 /* The number of entries is defined as a length, but will only ever be a small 00434 value. Treat it as such. */ 00435 if (ptr + 1 > len) 00436 return -1; 00437 entries = buf[ptr++]; 00438 s->rx[x].fec_entries = entries; 00439 00440 /* Decode the elements */ 00441 for (i = 0; i < entries; i++) { 00442 if ((stat1 = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) 00443 return -1; 00444 if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM) 00445 return -1; 00446 00447 /* Save the new FEC data */ 00448 memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); 00449 #if 0 00450 fprintf(stderr, "FEC: "); 00451 for (j = 0; j < s->rx[x].fec_len[i]; j++) 00452 fprintf(stderr, "%02X ", data[j]); 00453 fprintf(stderr, "\n"); 00454 #endif 00455 } 00456 00457 /* See if we can reconstruct anything which is missing */ 00458 /* TODO: this does not comprehensively hunt back and repair everything that is possible */ 00459 for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { 00460 if (s->rx[l].fec_len[0] <= 0) 00461 continue; 00462 for (m = 0; m < s->rx[l].fec_entries; m++) { 00463 limit = (l + m) & UDPTL_BUF_MASK; 00464 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) { 00465 if (s->rx[k].buf_len <= 0) 00466 which = (which == -1) ? k : -2; 00467 } 00468 if (which >= 0) { 00469 /* Repairable */ 00470 for (j = 0; j < s->rx[l].fec_len[m]; j++) { 00471 s->rx[which].buf[j] = s->rx[l].fec[m][j]; 00472 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) 00473 s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; 00474 } 00475 s->rx[which].buf_len = s->rx[l].fec_len[m]; 00476 repaired[which] = TRUE; 00477 } 00478 } 00479 } 00480 /* Now play any new packets forwards in time */ 00481 for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { 00482 if (repaired[l]) { 00483 //fprintf(stderr, "Fixed packet %d, len %d\n", j, l); 00484 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00485 s->f[ifp_no].subclass = AST_MODEM_T38; 00486 00487 s->f[ifp_no].mallocd = 0; 00488 s->f[ifp_no].seqno = j; 00489 s->f[ifp_no].datalen = s->rx[l].buf_len; 00490 s->f[ifp_no].data.ptr = s->rx[l].buf; 00491 s->f[ifp_no].offset = 0; 00492 s->f[ifp_no].src = "UDPTL"; 00493 if (ifp_no > 0) 00494 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00495 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00496 ifp_no++; 00497 } 00498 } 00499 } 00500 00501 /* If packets are received out of sequence, we may have already processed this packet from the error 00502 recovery information in a packet already received. */ 00503 if (seq_no >= s->rx_seq_no) { 00504 /* Decode the primary IFP packet */ 00505 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00506 s->f[ifp_no].subclass = AST_MODEM_T38; 00507 00508 s->f[ifp_no].mallocd = 0; 00509 s->f[ifp_no].seqno = seq_no; 00510 s->f[ifp_no].datalen = ifp_len; 00511 s->f[ifp_no].data.ptr = (uint8_t *) ifp; 00512 s->f[ifp_no].offset = 0; 00513 s->f[ifp_no].src = "UDPTL"; 00514 if (ifp_no > 0) 00515 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00516 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00517 00518 ifp_no++; 00519 } 00520 00521 s->rx_seq_no = seq_no + 1; 00522 return ifp_no; 00523 }
| static int udptlread | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | cbdata | |||
| ) | [static] |
Definition at line 660 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 85 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] |
int udptlstart = 4500 [static] |
int use_even_ports [static] |
1.6.1