#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include "asterisk/udptl.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"
Go to the source code of this file.
Data Structures | |
struct | ast_udptl |
Structure for an UDPTL session. More... | |
struct | protos |
struct | udptl_fec_rx_buffer_t |
struct | udptl_fec_tx_buffer_t |
Defines | |
#define | DEFAULT_FAX_MAX_DATAGRAM 400 |
#define | FALSE 0 |
#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 | TRUE (!FALSE) |
#define | UDPTL_BUF_MASK 15 |
#define | UDPTL_MTU 1200 |
Functions | |
static void | __ast_udptl_reload (int reload) |
int | ast_udptl_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) |
void | ast_udptl_destroy (struct ast_udptl *udptl) |
int | ast_udptl_fd (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 ast_sockaddr *them) |
void | ast_udptl_get_us (const struct ast_udptl *udptl, struct ast_sockaddr *us) |
void | ast_udptl_init (void) |
ast_udptl * | ast_udptl_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *addr) |
int | ast_udptl_proto_register (struct ast_udptl_protocol *proto) |
void | ast_udptl_proto_unregister (struct ast_udptl_protocol *proto) |
ast_frame * | ast_udptl_read (struct ast_udptl *udptl) |
int | ast_udptl_reload (void) |
void | ast_udptl_set_callback (struct ast_udptl *udptl, ast_udptl_callback callback) |
void | ast_udptl_set_data (struct ast_udptl *udptl, void *data) |
void | ast_udptl_set_error_correction_scheme (struct ast_udptl *udptl, 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 ast_sockaddr *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_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 ast_sockaddr *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_udptl [] |
static int | udptldebug |
static struct ast_sockaddr | udptldebugaddr |
static int | udptlend = 4599 |
static int | udptlfecentries |
static int | udptlfecspan |
static int | udptlstart = 4500 |
static int | use_even_ports |
Steve Underwood <steveu@coppice.org>
Kevin P. Fleming <kpfleming@digium.com>
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 |
#define LOCAL_FAX_MAX_DATAGRAM 1400 |
Definition at line 93 of file udptl.c.
Referenced by calculate_local_max_datagram(), and udptl_build_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 |
#define MAX_FEC_SPAN 5 |
static void __ast_udptl_reload | ( | int | reload | ) | [static] |
Definition at line 1299 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_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, LOG_NOTICE, LOG_WARNING, MAX_FEC_ENTRIES, and MAX_FEC_SPAN.
Referenced by ast_udptl_init(), and ast_udptl_reload().
01300 { 01301 struct ast_config *cfg; 01302 const char *s; 01303 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01304 01305 cfg = ast_config_load2("udptl.conf", "udptl", config_flags); 01306 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) { 01307 return; 01308 } 01309 01310 udptlstart = 4500; 01311 udptlend = 4999; 01312 udptlfecentries = 0; 01313 udptlfecspan = 0; 01314 use_even_ports = 0; 01315 01316 if (cfg) { 01317 if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) { 01318 udptlstart = atoi(s); 01319 if (udptlstart < 1024) { 01320 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01321 udptlstart = 1024; 01322 } 01323 if (udptlstart > 65535) { 01324 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01325 udptlstart = 65535; 01326 } 01327 } 01328 if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) { 01329 udptlend = atoi(s); 01330 if (udptlend < 1024) { 01331 ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); 01332 udptlend = 1024; 01333 } 01334 if (udptlend > 65535) { 01335 ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); 01336 udptlend = 65535; 01337 } 01338 } 01339 if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) { 01340 #ifdef SO_NO_CHECK 01341 if (ast_false(s)) 01342 nochecksums = 1; 01343 else 01344 nochecksums = 0; 01345 #else 01346 if (ast_false(s)) 01347 ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n"); 01348 #endif 01349 } 01350 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) { 01351 ast_log(LOG_WARNING, "T38FaxUdpEC in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n"); 01352 } 01353 if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) { 01354 ast_log(LOG_WARNING, "T38FaxMaxDatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n"); 01355 } 01356 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECEntries"))) { 01357 udptlfecentries = atoi(s); 01358 if (udptlfecentries < 1) { 01359 ast_log(LOG_WARNING, "Too small UDPTLFECEntries value. Defaulting to 1.\n"); 01360 udptlfecentries = 1; 01361 } 01362 if (udptlfecentries > MAX_FEC_ENTRIES) { 01363 ast_log(LOG_WARNING, "Too large UDPTLFECEntries value. Defaulting to %d.\n", MAX_FEC_ENTRIES); 01364 udptlfecentries = MAX_FEC_ENTRIES; 01365 } 01366 } 01367 if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECSpan"))) { 01368 udptlfecspan = atoi(s); 01369 if (udptlfecspan < 1) { 01370 ast_log(LOG_WARNING, "Too small UDPTLFECSpan value. Defaulting to 1.\n"); 01371 udptlfecspan = 1; 01372 } 01373 if (udptlfecspan > MAX_FEC_SPAN) { 01374 ast_log(LOG_WARNING, "Too large UDPTLFECSpan value. Defaulting to %d.\n", MAX_FEC_SPAN); 01375 udptlfecspan = MAX_FEC_SPAN; 01376 } 01377 } 01378 if ((s = ast_variable_retrieve(cfg, "general", "use_even_ports"))) { 01379 use_even_ports = ast_true(s); 01380 } 01381 ast_config_destroy(cfg); 01382 } 01383 if (udptlstart >= udptlend) { 01384 ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to 4500-4999.\n"); 01385 udptlstart = 4500; 01386 udptlend = 4999; 01387 } 01388 if (use_even_ports && (udptlstart & 1)) { 01389 ++udptlstart; 01390 ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", udptlstart); 01391 } 01392 if (use_even_ports && (udptlend & 1)) { 01393 --udptlend; 01394 ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_event_ports enabled. udptlend is now %d\n", udptlend); 01395 } 01396 ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend); 01397 }
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 1124 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_log(), ast_read(), ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_udptl_get_peer(), ast_waitfor_n(), ast_write(), f, get_proto(), ast_udptl_protocol::get_udptl_info, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_udptl_protocol::set_udptl_peer, t1, and ast_channel::tech_pvt.
01125 { 01126 struct ast_frame *f; 01127 struct ast_channel *who; 01128 struct ast_channel *cs[3]; 01129 struct ast_udptl *p0; 01130 struct ast_udptl *p1; 01131 struct ast_udptl_protocol *pr0; 01132 struct ast_udptl_protocol *pr1; 01133 struct ast_sockaddr ac0; 01134 struct ast_sockaddr ac1; 01135 struct ast_sockaddr t0; 01136 struct ast_sockaddr t1; 01137 void *pvt0; 01138 void *pvt1; 01139 int to; 01140 01141 ast_channel_lock(c0); 01142 while (ast_channel_trylock(c1)) { 01143 ast_channel_unlock(c0); 01144 usleep(1); 01145 ast_channel_lock(c0); 01146 } 01147 pr0 = get_proto(c0); 01148 pr1 = get_proto(c1); 01149 if (!pr0) { 01150 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01151 ast_channel_unlock(c0); 01152 ast_channel_unlock(c1); 01153 return -1; 01154 } 01155 if (!pr1) { 01156 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01157 ast_channel_unlock(c0); 01158 ast_channel_unlock(c1); 01159 return -1; 01160 } 01161 pvt0 = c0->tech_pvt; 01162 pvt1 = c1->tech_pvt; 01163 p0 = pr0->get_udptl_info(c0); 01164 p1 = pr1->get_udptl_info(c1); 01165 if (!p0 || !p1) { 01166 /* Somebody doesn't want to play... */ 01167 ast_channel_unlock(c0); 01168 ast_channel_unlock(c1); 01169 return -2; 01170 } 01171 if (pr0->set_udptl_peer(c0, p1)) { 01172 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01173 memset(&ac1, 0, sizeof(ac1)); 01174 } else { 01175 /* Store UDPTL peer */ 01176 ast_udptl_get_peer(p1, &ac1); 01177 } 01178 if (pr1->set_udptl_peer(c1, p0)) { 01179 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01180 memset(&ac0, 0, sizeof(ac0)); 01181 } else { 01182 /* Store UDPTL peer */ 01183 ast_udptl_get_peer(p0, &ac0); 01184 } 01185 ast_channel_unlock(c0); 01186 ast_channel_unlock(c1); 01187 cs[0] = c0; 01188 cs[1] = c1; 01189 cs[2] = NULL; 01190 for (;;) { 01191 if ((c0->tech_pvt != pvt0) || 01192 (c1->tech_pvt != pvt1) || 01193 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01194 ast_debug(1, "Oooh, something is weird, backing out\n"); 01195 /* Tell it to try again later */ 01196 return -3; 01197 } 01198 to = -1; 01199 ast_udptl_get_peer(p1, &t1); 01200 ast_udptl_get_peer(p0, &t0); 01201 if (ast_sockaddr_cmp(&t1, &ac1)) { 01202 ast_debug(1, "Oooh, '%s' changed end address to %s\n", 01203 c1->name, ast_sockaddr_stringify(&t1)); 01204 ast_debug(1, "Oooh, '%s' was %s\n", 01205 c1->name, ast_sockaddr_stringify(&ac1)); 01206 ast_sockaddr_copy(&ac1, &t1); 01207 } 01208 if (ast_sockaddr_cmp(&t0, &ac0)) { 01209 ast_debug(1, "Oooh, '%s' changed end address to %s\n", 01210 c0->name, ast_sockaddr_stringify(&t0)); 01211 ast_debug(1, "Oooh, '%s' was %s\n", 01212 c0->name, ast_sockaddr_stringify(&ac0)); 01213 ast_sockaddr_copy(&ac0, &t0); 01214 } 01215 who = ast_waitfor_n(cs, 2, &to); 01216 if (!who) { 01217 ast_debug(1, "Ooh, empty read...\n"); 01218 /* check for hangup / whentohangup */ 01219 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01220 break; 01221 continue; 01222 } 01223 f = ast_read(who); 01224 if (!f) { 01225 *fo = f; 01226 *rc = who; 01227 ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01228 /* That's all we needed */ 01229 return 0; 01230 } else { 01231 if (f->frametype == AST_FRAME_MODEM) { 01232 /* Forward T.38 frames if they happen upon us */ 01233 if (who == c0) { 01234 ast_write(c1, f); 01235 } else if (who == c1) { 01236 ast_write(c0, f); 01237 } 01238 } 01239 ast_frfree(f); 01240 } 01241 /* Swap priority. Not that it's a big deal at this point */ 01242 cs[2] = cs[0]; 01243 cs[0] = cs[1]; 01244 cs[1] = cs[2]; 01245 } 01246 return -1; 01247 }
void ast_udptl_destroy | ( | struct ast_udptl * | udptl | ) |
Definition at line 1022 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().
01023 { 01024 if (udptl->ioid) 01025 ast_io_remove(udptl->io, udptl->ioid); 01026 if (udptl->fd > -1) 01027 close(udptl->fd); 01028 if (udptl->tag) 01029 ast_free(udptl->tag); 01030 ast_free(udptl); 01031 }
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 817 of file udptl.c.
References ast_udptl::error_correction_scheme.
Referenced by add_sdp().
00818 { 00819 return udptl->error_correction_scheme; 00820 }
unsigned int ast_udptl_get_far_max_datagram | ( | const struct ast_udptl * | udptl | ) |
Definition at line 885 of file udptl.c.
References ast_udptl::far_max_datagram.
Referenced by process_sdp().
00886 { 00887 if (udptl->far_max_datagram < 0) { 00888 return 0; 00889 } 00890 return udptl->far_max_datagram; 00891 }
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 893 of file udptl.c.
References calculate_far_max_ifp(), and ast_udptl::far_max_ifp.
Referenced by change_t38_state(), and interpret_t38_parameters().
00894 { 00895 if (udptl->far_max_ifp == -1) { 00896 calculate_far_max_ifp(udptl); 00897 } 00898 00899 if (udptl->far_max_ifp < 0) { 00900 return 0; 00901 } 00902 return udptl->far_max_ifp; 00903 }
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 861 of file udptl.c.
References calculate_local_max_datagram(), and ast_udptl::local_max_datagram.
Referenced by add_sdp().
00862 { 00863 if (udptl->local_max_datagram == -1) { 00864 calculate_local_max_datagram(udptl); 00865 } 00866 00867 /* this function expects a unsigned value in return. */ 00868 if (udptl->local_max_datagram < 0) { 00869 return 0; 00870 } 00871 return udptl->local_max_datagram; 00872 }
void ast_udptl_get_peer | ( | const struct ast_udptl * | udptl, | |
struct ast_sockaddr * | them | |||
) |
Definition at line 1007 of file udptl.c.
References ast_sockaddr_copy(), and ast_udptl::them.
Referenced by ast_udptl_bridge(), and sip_set_udptl_peer().
01008 { 01009 ast_sockaddr_copy(them, &udptl->them); 01010 }
void ast_udptl_get_us | ( | const struct ast_udptl * | udptl, | |
struct ast_sockaddr * | us | |||
) |
Definition at line 1012 of file udptl.c.
References ast_sockaddr_copy(), and ast_udptl::us.
Referenced by add_sdp().
01013 { 01014 ast_sockaddr_copy(us, &udptl->us); 01015 }
void ast_udptl_init | ( | void | ) |
Definition at line 1405 of file udptl.c.
References __ast_udptl_reload(), ARRAY_LEN, ast_cli_register_multiple(), and cli_udptl.
Referenced by main().
01406 { 01407 ast_cli_register_multiple(cli_udptl, ARRAY_LEN(cli_udptl)); 01408 __ast_udptl_reload(0); 01409 }
struct ast_udptl* ast_udptl_new_with_bindaddr | ( | struct sched_context * | sched, | |
struct io_context * | io, | |||
int | callbackmode, | |||
struct ast_sockaddr * | addr | |||
) |
Definition at line 905 of file udptl.c.
References ast_bind(), ast_calloc, ast_free, ast_log(), ast_random(), ast_sockaddr_copy(), ast_sockaddr_is_ipv6(), ast_sockaddr_set_port, errno, ast_udptl::flags, and LOG_WARNING.
Referenced by create_addr_from_peer(), handle_request_invite(), and sip_alloc().
00906 { 00907 struct ast_udptl *udptl; 00908 int x; 00909 int startplace; 00910 int i; 00911 long int flags; 00912 00913 if (!(udptl = ast_calloc(1, sizeof(*udptl)))) 00914 return NULL; 00915 00916 udptl->error_correction_span = udptlfecspan; 00917 udptl->error_correction_entries = udptlfecentries; 00918 00919 udptl->far_max_datagram = -1; 00920 udptl->far_max_ifp = -1; 00921 udptl->local_max_ifp = -1; 00922 udptl->local_max_datagram = -1; 00923 00924 for (i = 0; i <= UDPTL_BUF_MASK; i++) { 00925 udptl->rx[i].buf_len = -1; 00926 udptl->tx[i].buf_len = -1; 00927 } 00928 00929 if ((udptl->fd = socket(ast_sockaddr_is_ipv6(addr) ? 00930 AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) { 00931 ast_free(udptl); 00932 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00933 return NULL; 00934 } 00935 flags = fcntl(udptl->fd, F_GETFL); 00936 fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK); 00937 #ifdef SO_NO_CHECK 00938 if (nochecksums) 00939 setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 00940 #endif 00941 /* Find us a place */ 00942 x = (udptlstart == udptlend) ? udptlstart : (ast_random() % (udptlend - udptlstart)) + udptlstart; 00943 if (use_even_ports && (x & 1)) { 00944 ++x; 00945 } 00946 startplace = x; 00947 for (;;) { 00948 ast_sockaddr_copy(&udptl->us, addr); 00949 ast_sockaddr_set_port(&udptl->us, x); 00950 if (ast_bind(udptl->fd, &udptl->us) == 0) { 00951 break; 00952 } 00953 if (errno != EADDRINUSE) { 00954 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00955 close(udptl->fd); 00956 ast_free(udptl); 00957 return NULL; 00958 } 00959 if (use_even_ports) { 00960 x += 2; 00961 } else { 00962 ++x; 00963 } 00964 if (x > udptlend) 00965 x = udptlstart; 00966 if (x == startplace) { 00967 ast_log(LOG_WARNING, "No UDPTL ports remaining\n"); 00968 close(udptl->fd); 00969 ast_free(udptl); 00970 return NULL; 00971 } 00972 } 00973 if (io && sched && callbackmode) { 00974 /* Operate this one in a callback mode */ 00975 udptl->sched = sched; 00976 udptl->io = io; 00977 udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl); 00978 } 00979 return udptl; 00980 }
int ast_udptl_proto_register | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 1093 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().
01094 { 01095 struct ast_udptl_protocol *cur; 01096 01097 AST_RWLIST_WRLOCK(&protos); 01098 AST_RWLIST_TRAVERSE(&protos, cur, list) { 01099 if (cur->type == proto->type) { 01100 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01101 AST_RWLIST_UNLOCK(&protos); 01102 return -1; 01103 } 01104 } 01105 AST_RWLIST_INSERT_TAIL(&protos, proto, list); 01106 AST_RWLIST_UNLOCK(&protos); 01107 return 0; 01108 }
void ast_udptl_proto_unregister | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 1086 of file udptl.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by unload_module().
01087 { 01088 AST_RWLIST_WRLOCK(&protos); 01089 AST_RWLIST_REMOVE(&protos, proto, list); 01090 AST_RWLIST_UNLOCK(&protos); 01091 }
Definition at line 662 of file udptl.c.
References ast_assert, ast_debug, AST_FRIENDLY_OFFSET, ast_log(), ast_null_frame, ast_recvfrom(), ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verb, errno, ast_udptl::f, ast_udptl::fd, 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().
00663 { 00664 int res; 00665 struct ast_sockaddr addr; 00666 uint16_t seqno = 0; 00667 uint16_t *udptlheader; 00668 00669 /* Cache where the header will go */ 00670 res = ast_recvfrom(udptl->fd, 00671 udptl->rawdata + AST_FRIENDLY_OFFSET, 00672 sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET, 00673 0, 00674 &addr); 00675 udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET); 00676 if (res < 0) { 00677 if (errno != EAGAIN) 00678 ast_log(LOG_WARNING, "(%s): UDPTL read error: %s\n", 00679 LOG_TAG(udptl), strerror(errno)); 00680 ast_assert(errno != EBADF); 00681 return &ast_null_frame; 00682 } 00683 00684 /* Ignore if the other side hasn't been given an address yet. */ 00685 if (ast_sockaddr_isnull(&udptl->them)) { 00686 return &ast_null_frame; 00687 } 00688 00689 if (udptl->nat) { 00690 /* Send to whoever sent to us */ 00691 if (ast_sockaddr_cmp(&udptl->them, &addr)) { 00692 ast_sockaddr_copy(&udptl->them, &addr); 00693 ast_debug(1, "UDPTL NAT (%s): Using address %s\n", 00694 LOG_TAG(udptl), ast_sockaddr_stringify(&udptl->them)); 00695 } 00696 } 00697 00698 if (udptl_debug_test_addr(&addr)) { 00699 ast_verb(1, "UDPTL (%s): packet from %s (type %d, seq %d, len %d)\n", 00700 LOG_TAG(udptl), ast_sockaddr_stringify(&addr), 0, seqno, res); 00701 } 00702 if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1) 00703 return &ast_null_frame; 00704 00705 return &udptl->f[0]; 00706 }
int ast_udptl_reload | ( | void | ) |
Definition at line 1399 of file udptl.c.
References __ast_udptl_reload().
01400 { 01401 __ast_udptl_reload(1); 01402 return 0; 01403 }
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 822 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(), process_sdp_a_image(), and set_t38_capabilities().
00823 { 00824 udptl->error_correction_scheme = ec; 00825 switch (ec) { 00826 case UDPTL_ERROR_CORRECTION_FEC: 00827 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC; 00828 if (udptl->error_correction_entries == 0) { 00829 udptl->error_correction_entries = 3; 00830 } 00831 if (udptl->error_correction_span == 0) { 00832 udptl->error_correction_span = 3; 00833 } 00834 break; 00835 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00836 udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY; 00837 if (udptl->error_correction_entries == 0) { 00838 udptl->error_correction_entries = 3; 00839 } 00840 break; 00841 default: 00842 /* nothing to do */ 00843 break; 00844 }; 00845 /* reset calculated values so they'll be computed again */ 00846 udptl->local_max_datagram = -1; 00847 udptl->far_max_ifp = -1; 00848 }
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 874 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().
00875 { 00876 if (!max_datagram || (max_datagram > FAX_MAX_DATAGRAM_LIMIT)) { 00877 udptl->far_max_datagram = DEFAULT_FAX_MAX_DATAGRAM; 00878 } else { 00879 udptl->far_max_datagram = max_datagram; 00880 } 00881 /* reset calculated values so they'll be computed again */ 00882 udptl->far_max_ifp = -1; 00883 }
void ast_udptl_set_local_max_ifp | ( | struct ast_udptl * | udptl, | |
unsigned int | max_ifp | |||
) |
Definition at line 850 of file udptl.c.
References ast_udptl::local_max_datagram, and ast_udptl::local_max_ifp.
Referenced by interpret_t38_parameters().
00851 { 00852 /* make sure max_ifp is a positive value since a cast will take place when 00853 * when setting local_max_ifp */ 00854 if ((signed int) max_ifp > 0) { 00855 udptl->local_max_ifp = max_ifp; 00856 /* reset calculated values so they'll be computed again */ 00857 udptl->local_max_datagram = -1; 00858 } 00859 }
void ast_udptl_set_peer | ( | struct ast_udptl * | udptl, | |
const struct ast_sockaddr * | them | |||
) |
Definition at line 1002 of file udptl.c.
References ast_sockaddr_copy(), and ast_udptl::them.
Referenced by process_sdp().
01003 { 01004 ast_sockaddr_copy(&udptl->them, them); 01005 }
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 |
none |
Definition at line 982 of file udptl.c.
References ast_free, ast_vasprintf, and ast_udptl::tag.
Referenced by change_t38_state().
00983 { 00984 va_list ap; 00985 00986 if (udptl->tag) { 00987 ast_free(udptl->tag); 00988 udptl->tag = NULL; 00989 } 00990 va_start(ap, format); 00991 if (ast_vasprintf(&udptl->tag, format, ap) == -1) { 00992 udptl->tag = NULL; 00993 } 00994 va_end(ap); 00995 }
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 997 of file udptl.c.
References ast_netsock_set_qos(), and ast_udptl::fd.
Referenced by sip_alloc().
00998 { 00999 return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL"); 01000 }
void ast_udptl_stop | ( | struct ast_udptl * | udptl | ) |
Definition at line 1017 of file udptl.c.
References ast_sockaddr_setnull(), and ast_udptl::them.
Referenced by process_sdp(), and stop_media_flows().
01018 { 01019 ast_sockaddr_setnull(&udptl->them); 01020 }
Definition at line 1033 of file udptl.c.
References AST_FRAME_MODEM, ast_log(), AST_MODEM_T38, ast_sendto(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verb, DEFAULT_FAX_MAX_DATAGRAM, errno, f, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, ast_udptl::fd, len(), LOG_NOTICE, LOG_TAG, LOG_WARNING, seq, ast_udptl::them, ast_udptl::tx_seq_no, udptl_build_packet(), and udptl_debug_test_addr().
Referenced by sip_write().
01034 { 01035 unsigned int seq; 01036 unsigned int len = f->datalen; 01037 int res; 01038 /* if no max datagram size is provided, use default value */ 01039 const int bufsize = (s->far_max_datagram > 0) ? s->far_max_datagram : DEFAULT_FAX_MAX_DATAGRAM; 01040 uint8_t buf[bufsize]; 01041 01042 memset(buf, 0, sizeof(buf)); 01043 01044 /* If we have no peer, return immediately */ 01045 if (ast_sockaddr_isnull(&s->them)) { 01046 return 0; 01047 } 01048 01049 /* If there is no data length, return immediately */ 01050 if (f->datalen == 0) 01051 return 0; 01052 01053 if ((f->frametype != AST_FRAME_MODEM) || 01054 (f->subclass.codec != AST_MODEM_T38)) { 01055 ast_log(LOG_WARNING, "(%s): UDPTL can only send T.38 data.\n", 01056 LOG_TAG(s)); 01057 return -1; 01058 } 01059 01060 if (len > s->far_max_ifp) { 01061 ast_log(LOG_WARNING, 01062 "(%s): UDPTL asked to send %d bytes of IFP when far end only prepared to accept %d bytes; data loss will occur." 01063 "You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n", 01064 LOG_TAG(s), len, s->far_max_ifp); 01065 len = s->far_max_ifp; 01066 } 01067 01068 /* Save seq_no for debug output because udptl_build_packet increments it */ 01069 seq = s->tx_seq_no & 0xFFFF; 01070 01071 /* Cook up the UDPTL packet, with the relevant EC info. */ 01072 len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, len); 01073 01074 if ((signed int) len > 0 && !ast_sockaddr_isnull(&s->them)) { 01075 if ((res = ast_sendto(s->fd, buf, len, 0, &s->them)) < 0) 01076 ast_log(LOG_NOTICE, "(%s): UDPTL Transmission error to %s: %s\n", 01077 LOG_TAG(s), ast_sockaddr_stringify(&s->them), strerror(errno)); 01078 if (udptl_debug_test_addr(&s->them)) 01079 ast_verb(1, "UDPTL (%s): packet to %s (type %d, seq %d, len %d)\n", 01080 LOG_TAG(s), ast_sockaddr_stringify(&s->them), 0, seq, len); 01081 } 01082 01083 return 0; 01084 }
static void calculate_far_max_ifp | ( | struct ast_udptl * | udptl | ) | [static] |
Definition at line 749 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().
00750 { 00751 unsigned new_max = 0; 00752 00753 if (udptl->far_max_datagram == -1) { 00754 ast_log(LOG_WARNING, "(%s): Cannot calculate far_max_ifp before far_max_datagram has been set.\n", 00755 LOG_TAG(udptl)); 00756 udptl->far_max_ifp = -1; 00757 return; 00758 } 00759 00760 /* the goal here is to supply the local endpoint (application 00761 * or bridged channel) a maximum IFP value that will allow it 00762 * to effectively and efficiently transfer image data at its 00763 * selected bit rate, taking into account the selected error 00764 * correction mode, but without overrunning the far endpoint's 00765 * datagram buffer. this is complicated by the fact that some 00766 * far endpoints send us bogus (small) max datagram values, 00767 * which would result in either buffer overrun or no error 00768 * correction. we try to accomodate those, but if the supplied 00769 * value is too small to do so, we'll emit warning messages and 00770 * the user will have to use configuration options to override 00771 * the max datagram value supplied by the far endpoint. 00772 */ 00773 switch (udptl->error_correction_scheme) { 00774 case UDPTL_ERROR_CORRECTION_NONE: 00775 /* need room for sequence number, length indicator, redundancy 00776 * indicator and following length indicator 00777 */ 00778 new_max = udptl->far_max_datagram - 5; 00779 break; 00780 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00781 /* for this case, we'd like to send as many error correction entries 00782 * as possible (up to the number we're configured for), but we'll settle 00783 * for sending fewer if the configured number would cause the 00784 * calculated max IFP to be too small for effective operation 00785 * 00786 * need room for sequence number, length indicators and the 00787 * configured number of redundant packets 00788 * 00789 * note: we purposely don't allow error_correction_entries to drop to 00790 * zero in this loop; we'd rather send smaller IFPs (and thus reduce 00791 * the image data transfer rate) than sacrifice redundancy completely 00792 */ 00793 for (;;) { 00794 new_max = (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1); 00795 00796 if ((new_max < 80) && (udptl->error_correction_entries > 1)) { 00797 /* the max ifp is not large enough, subtract an 00798 * error correction entry and calculate again 00799 * */ 00800 --udptl->error_correction_entries; 00801 } else { 00802 break; 00803 } 00804 } 00805 break; 00806 case UDPTL_ERROR_CORRECTION_FEC: 00807 /* need room for sequence number, length indicators and a 00808 * a single IFP of the maximum size expected 00809 */ 00810 new_max = (udptl->far_max_datagram - 10) / 2; 00811 break; 00812 } 00813 /* subtract 5% of space for insurance */ 00814 udptl->far_max_ifp = new_max * 0.95; 00815 }
static void calculate_local_max_datagram | ( | struct ast_udptl * | udptl | ) | [static] |
Definition at line 708 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().
00709 { 00710 unsigned int new_max = 0; 00711 00712 if (udptl->local_max_ifp == -1) { 00713 ast_log(LOG_WARNING, "(%s): Cannot calculate local_max_datagram before local_max_ifp has been set.\n", 00714 LOG_TAG(udptl)); 00715 udptl->local_max_datagram = -1; 00716 return; 00717 } 00718 00719 /* calculate the amount of space required to receive an IFP 00720 * of the maximum size supported by the application/endpoint 00721 * that we are delivering them to (local endpoint), and add 00722 * the amount of space required to support the selected 00723 * error correction mode 00724 */ 00725 switch (udptl->error_correction_scheme) { 00726 case UDPTL_ERROR_CORRECTION_NONE: 00727 /* need room for sequence number, length indicator, redundancy 00728 * indicator and following length indicator 00729 */ 00730 new_max = 5 + udptl->local_max_ifp; 00731 break; 00732 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00733 /* need room for sequence number, length indicators, plus 00734 * room for up to 3 redundancy packets 00735 */ 00736 new_max = 5 + udptl->local_max_ifp + 2 + (3 * udptl->local_max_ifp); 00737 break; 00738 case UDPTL_ERROR_CORRECTION_FEC: 00739 /* need room for sequence number, length indicators and a 00740 * a single IFP of the maximum size expected 00741 */ 00742 new_max = 5 + udptl->local_max_ifp + 4 + udptl->local_max_ifp; 00743 break; 00744 } 00745 /* add 5% extra space for insurance, but no larger than LOCAL_FAX_MAX_DATAGRAM */ 00746 udptl->local_max_datagram = MIN(new_max * 1.05, LOCAL_FAX_MAX_DATAGRAM); 00747 }
static int decode_length | ( | uint8_t * | buf, | |
unsigned int | limit, | |||
unsigned int * | len, | |||
unsigned int * | pvalue | |||
) | [static] |
Definition at line 199 of file udptl.c.
References ast_debug.
Referenced by decode_open_type(), and udptl_rx_packet().
00200 { 00201 if (*len >= limit) 00202 return -1; 00203 if ((buf[*len] & 0x80) == 0) { 00204 *pvalue = buf[*len]; 00205 (*len)++; 00206 return 0; 00207 } 00208 if ((buf[*len] & 0x40) == 0) { 00209 if (*len == limit - 1) 00210 return -1; 00211 *pvalue = (buf[*len] & 0x3F) << 8; 00212 (*len)++; 00213 *pvalue |= buf[*len]; 00214 (*len)++; 00215 return 0; 00216 } 00217 *pvalue = (buf[*len] & 0x3F) << 14; 00218 (*len)++; 00219 /* We have a fragment. Currently we don't process fragments. */ 00220 ast_debug(1, "UDPTL packet with length greater than 16K received, decoding will fail\n"); 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 = 0; 00228 00229 if (decode_length(buf, limit, len, &octet_cnt) != 0) 00230 return -1; 00231 00232 if (octet_cnt > 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 *p_num_octets = octet_cnt; 00238 *p_object = &buf[*len]; 00239 *len += octet_cnt; 00240 } 00241 00242 return 0; 00243 }
static unsigned int encode_length | ( | uint8_t * | buf, | |
unsigned int * | len, | |||
unsigned int | value | |||
) | [static] |
Definition at line 246 of file udptl.c.
Referenced by encode_open_type(), and udptl_build_packet().
00247 { 00248 unsigned int multiplier; 00249 00250 if (value < 0x80) { 00251 /* 1 octet */ 00252 buf[*len] = value; 00253 (*len)++; 00254 return value; 00255 } 00256 if (value < 0x4000) { 00257 /* 2 octets */ 00258 /* Set the first bit of the first octet */ 00259 buf[*len] = ((0x8000 | value) >> 8) & 0xFF; 00260 (*len)++; 00261 buf[*len] = value & 0xFF; 00262 (*len)++; 00263 return value; 00264 } 00265 /* Fragmentation */ 00266 multiplier = (value < 0x10000) ? (value >> 14) : 4; 00267 /* Set the first 2 bits of the octet */ 00268 buf[*len] = 0xC0 | multiplier; 00269 (*len)++; 00270 return multiplier << 14; 00271 }
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 274 of file udptl.c.
References ast_log(), encode_length(), LOG_ERROR, and LOG_TAG.
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, "(%s): Buffer overflow detected (%d + %d > %d)\n", 00293 LOG_TAG(udptl), enclen, *len, buflen); 00294 return -1; 00295 } 00296 if (enclen > 0) { 00297 memcpy(&buf[*len], &data[octet_idx], enclen); 00298 *len += enclen; 00299 } 00300 if (enclen >= num_octets) 00301 break; 00302 } 00303 00304 return 0; 00305 }
static struct ast_udptl_protocol* get_proto | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 1110 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().
01111 { 01112 struct ast_udptl_protocol *cur = NULL; 01113 01114 AST_RWLIST_RDLOCK(&protos); 01115 AST_RWLIST_TRAVERSE(&protos, cur, list) { 01116 if (cur->type == chan->tech->type) 01117 break; 01118 } 01119 AST_RWLIST_UNLOCK(&protos); 01120 01121 return cur; 01122 }
static char* handle_cli_udptl_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1249 of file udptl.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_free, ast_sockaddr_copy(), ast_sockaddr_resolve(), ast_sockaddr_stringify(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, udptldebugaddr, and ast_cli_entry::usage.
01250 { 01251 switch (cmd) { 01252 case CLI_INIT: 01253 e->command = "udptl set debug {on|off|ip}"; 01254 e->usage = 01255 "Usage: udptl set debug {on|off|ip host[:port]}\n" 01256 " Enable or disable dumping of UDPTL packets.\n" 01257 " If ip is specified, limit the dumped packets to those to and from\n" 01258 " the specified 'host' with optional port.\n"; 01259 return NULL; 01260 case CLI_GENERATE: 01261 return NULL; 01262 } 01263 01264 if (a->argc < 4 || a->argc > 5) 01265 return CLI_SHOWUSAGE; 01266 01267 if (a->argc == 4) { 01268 if (!strncasecmp(a->argv[3], "on", 2)) { 01269 udptldebug = 1; 01270 memset(&udptldebugaddr, 0, sizeof(udptldebugaddr)); 01271 ast_cli(a->fd, "UDPTL Debugging Enabled\n"); 01272 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01273 udptldebug = 0; 01274 ast_cli(a->fd, "UDPTL Debugging Disabled\n"); 01275 } else { 01276 return CLI_SHOWUSAGE; 01277 } 01278 } else { 01279 struct ast_sockaddr *addrs; 01280 if (strncasecmp(a->argv[3], "ip", 2)) 01281 return CLI_SHOWUSAGE; 01282 if (!ast_sockaddr_resolve(&addrs, a->argv[4], 0, 0)) { 01283 return CLI_SHOWUSAGE; 01284 } 01285 ast_sockaddr_copy(&udptldebugaddr, &addrs[0]); 01286 ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_sockaddr_stringify(&udptldebugaddr)); 01287 udptldebug = 1; 01288 ast_free(addrs); 01289 } 01290 01291 return CLI_SUCCESS; 01292 }
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 519 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_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by ast_udptl_write().
00520 { 00521 uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2]; 00522 int i; 00523 int j; 00524 int seq; 00525 int entry; 00526 int entries; 00527 int span; 00528 int m; 00529 unsigned int len; 00530 int limit; 00531 int high_tide; 00532 00533 seq = s->tx_seq_no & 0xFFFF; 00534 00535 /* Map the sequence number to an entry in the circular buffer */ 00536 entry = seq & UDPTL_BUF_MASK; 00537 00538 /* We save the message in a circular buffer, for generating FEC or 00539 redundancy sets later on. */ 00540 s->tx[entry].buf_len = ifp_len; 00541 memcpy(s->tx[entry].buf, ifp, ifp_len); 00542 00543 /* Build the UDPTLPacket */ 00544 00545 len = 0; 00546 /* Encode the sequence number */ 00547 buf[len++] = (seq >> 8) & 0xFF; 00548 buf[len++] = seq & 0xFF; 00549 00550 /* Encode the primary IFP packet */ 00551 if (encode_open_type(s, buf, buflen, &len, ifp, ifp_len) < 0) 00552 return -1; 00553 00554 /* Encode the appropriate type of error recovery information */ 00555 switch (s->error_correction_scheme) 00556 { 00557 case UDPTL_ERROR_CORRECTION_NONE: 00558 /* Encode the error recovery type */ 00559 buf[len++] = 0x00; 00560 /* The number of entries will always be zero, so it is pointless allowing 00561 for the fragmented case here. */ 00562 if (encode_length(buf, &len, 0) < 0) 00563 return -1; 00564 break; 00565 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 00566 /* Encode the error recovery type */ 00567 buf[len++] = 0x00; 00568 if (s->tx_seq_no > s->error_correction_entries) 00569 entries = s->error_correction_entries; 00570 else 00571 entries = s->tx_seq_no; 00572 /* The number of entries will always be small, so it is pointless allowing 00573 for the fragmented case here. */ 00574 if (encode_length(buf, &len, entries) < 0) 00575 return -1; 00576 /* Encode the elements */ 00577 for (i = 0; i < entries; i++) { 00578 j = (entry - i - 1) & UDPTL_BUF_MASK; 00579 if (encode_open_type(s, buf, buflen, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) { 00580 ast_debug(1, "(%s): Encoding failed at i=%d, j=%d\n", 00581 LOG_TAG(s), i, j); 00582 return -1; 00583 } 00584 } 00585 break; 00586 case UDPTL_ERROR_CORRECTION_FEC: 00587 span = s->error_correction_span; 00588 entries = s->error_correction_entries; 00589 if (seq < s->error_correction_span*s->error_correction_entries) { 00590 /* In the initial stages, wind up the FEC smoothly */ 00591 entries = seq/s->error_correction_span; 00592 if (seq < s->error_correction_span) 00593 span = 0; 00594 } 00595 /* Encode the error recovery type */ 00596 buf[len++] = 0x80; 00597 /* Span is defined as an inconstrained integer, which it dumb. It will only 00598 ever be a small value. Treat it as such. */ 00599 buf[len++] = 1; 00600 buf[len++] = span; 00601 /* The number of entries is defined as a length, but will only ever be a small 00602 value. Treat it as such. */ 00603 buf[len++] = entries; 00604 for (m = 0; m < entries; m++) { 00605 /* Make an XOR'ed entry the maximum length */ 00606 limit = (entry + m) & UDPTL_BUF_MASK; 00607 high_tide = 0; 00608 for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { 00609 if (high_tide < s->tx[i].buf_len) { 00610 for (j = 0; j < high_tide; j++) 00611 fec[j] ^= s->tx[i].buf[j]; 00612 for ( ; j < s->tx[i].buf_len; j++) 00613 fec[j] = s->tx[i].buf[j]; 00614 high_tide = s->tx[i].buf_len; 00615 } else { 00616 for (j = 0; j < s->tx[i].buf_len; j++) 00617 fec[j] ^= s->tx[i].buf[j]; 00618 } 00619 } 00620 if (encode_open_type(s, buf, buflen, &len, fec, high_tide) < 0) 00621 return -1; 00622 } 00623 break; 00624 } 00625 00626 s->tx_seq_no++; 00627 return len; 00628 }
static int udptl_debug_test_addr | ( | const struct ast_sockaddr * | addr | ) | [inline, static] |
Definition at line 183 of file udptl.c.
References ast_sockaddr_cmp(), ast_sockaddr_cmp_addr(), ast_sockaddr_isnull(), ast_sockaddr_port, and udptldebugaddr.
Referenced by ast_udptl_read(), and ast_udptl_write().
00184 { 00185 if (udptldebug == 0) 00186 return 0; 00187 00188 if (ast_sockaddr_isnull(&udptldebugaddr)) { 00189 return 1; 00190 } 00191 00192 if (ast_sockaddr_port(&udptldebugaddr)) { 00193 return !ast_sockaddr_cmp(&udptldebugaddr, addr); 00194 } else { 00195 return !ast_sockaddr_cmp_addr(&udptldebugaddr, addr); 00196 } 00197 }
static int udptl_rx_packet | ( | struct ast_udptl * | s, | |
uint8_t * | buf, | |||
unsigned int | len | |||
) | [static] |
Definition at line 308 of file udptl.c.
References ARRAY_LEN, AST_FRAME_MODEM, AST_LIST_NEXT, AST_MODEM_T38, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, decode_length(), decode_open_type(), ast_udptl::f, ast_frame::frametype, ast_frame::mallocd, ast_frame::offset, ast_frame::ptr, ast_udptl::rx_seq_no, ast_frame::seqno, ast_frame::src, and ast_frame::subclass.
Referenced by ast_udptl_read().
00309 { 00310 int stat1; 00311 int stat2; 00312 int i; 00313 int j; 00314 int k; 00315 int l; 00316 int m; 00317 int x; 00318 int limit; 00319 int which; 00320 unsigned int ptr; 00321 unsigned int count; 00322 int total_count; 00323 int seq_no; 00324 const uint8_t *ifp; 00325 const uint8_t *data; 00326 unsigned int ifp_len; 00327 int repaired[16]; 00328 const uint8_t *bufs[ARRAY_LEN(s->f) - 1]; 00329 unsigned int lengths[ARRAY_LEN(s->f) - 1]; 00330 int span; 00331 int entries; 00332 int ifp_no; 00333 00334 ptr = 0; 00335 ifp_no = 0; 00336 memset(&s->f[0], 0, sizeof(s->f[0])); 00337 00338 /* Decode seq_number */ 00339 if (ptr + 2 > len) 00340 return -1; 00341 seq_no = (buf[0] << 8) | buf[1]; 00342 ptr += 2; 00343 00344 /* Break out the primary packet */ 00345 if ((stat1 = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0) 00346 return -1; 00347 /* Decode error_recovery */ 00348 if (ptr + 1 > len) 00349 return -1; 00350 if ((buf[ptr++] & 0x80) == 0) { 00351 /* Secondary packet mode for error recovery */ 00352 if (seq_no > s->rx_seq_no) { 00353 /* We received a later packet than we expected, so we need to check if we can fill in the gap from the 00354 secondary packets. */ 00355 total_count = 0; 00356 do { 00357 if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) 00358 return -1; 00359 for (i = 0; i < count && total_count + i < ARRAY_LEN(bufs); i++) { 00360 if ((stat1 = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) 00361 return -1; 00362 } 00363 total_count += i; 00364 } 00365 while (stat2 > 0 && total_count < ARRAY_LEN(bufs)); 00366 /* Step through in reverse order, so we go oldest to newest */ 00367 for (i = total_count; i > 0; i--) { 00368 if (seq_no - i >= s->rx_seq_no) { 00369 /* This one wasn't seen before */ 00370 /* Decode the secondary IFP packet */ 00371 //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); 00372 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00373 s->f[ifp_no].subclass.codec = AST_MODEM_T38; 00374 00375 s->f[ifp_no].mallocd = 0; 00376 s->f[ifp_no].seqno = seq_no - i; 00377 s->f[ifp_no].datalen = lengths[i - 1]; 00378 s->f[ifp_no].data.ptr = (uint8_t *) bufs[i - 1]; 00379 s->f[ifp_no].offset = 0; 00380 s->f[ifp_no].src = "UDPTL"; 00381 if (ifp_no > 0) 00382 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00383 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00384 ifp_no++; 00385 } 00386 } 00387 } 00388 } 00389 else 00390 { 00391 /* FEC mode for error recovery */ 00392 /* Our buffers cannot tolerate overlength IFP packets in FEC mode */ 00393 if (ifp_len > LOCAL_FAX_MAX_DATAGRAM) 00394 return -1; 00395 /* Update any missed slots in the buffer */ 00396 for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) { 00397 x = s->rx_seq_no & UDPTL_BUF_MASK; 00398 s->rx[x].buf_len = -1; 00399 s->rx[x].fec_len[0] = 0; 00400 s->rx[x].fec_span = 0; 00401 s->rx[x].fec_entries = 0; 00402 } 00403 00404 x = seq_no & UDPTL_BUF_MASK; 00405 00406 memset(repaired, 0, sizeof(repaired)); 00407 00408 /* Save the new IFP packet */ 00409 memcpy(s->rx[x].buf, ifp, ifp_len); 00410 s->rx[x].buf_len = ifp_len; 00411 repaired[x] = TRUE; 00412 00413 /* Decode the FEC packets */ 00414 /* The span is defined as an unconstrained integer, but will never be more 00415 than a small value. */ 00416 if (ptr + 2 > len) 00417 return -1; 00418 if (buf[ptr++] != 1) 00419 return -1; 00420 span = buf[ptr++]; 00421 s->rx[x].fec_span = span; 00422 00423 /* The number of entries is defined as a length, but will only ever be a small 00424 value. Treat it as such. */ 00425 if (ptr + 1 > len) 00426 return -1; 00427 entries = buf[ptr++]; 00428 if (entries > MAX_FEC_ENTRIES) { 00429 return -1; 00430 } 00431 s->rx[x].fec_entries = entries; 00432 00433 /* Decode the elements */ 00434 for (i = 0; i < entries; i++) { 00435 if ((stat1 = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) 00436 return -1; 00437 if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM) 00438 return -1; 00439 00440 /* Save the new FEC data */ 00441 memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); 00442 #if 0 00443 fprintf(stderr, "FEC: "); 00444 for (j = 0; j < s->rx[x].fec_len[i]; j++) 00445 fprintf(stderr, "%02X ", data[j]); 00446 fprintf(stderr, "\n"); 00447 #endif 00448 } 00449 00450 /* See if we can reconstruct anything which is missing */ 00451 /* TODO: this does not comprehensively hunt back and repair everything that is possible */ 00452 for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { 00453 if (s->rx[l].fec_len[0] <= 0) 00454 continue; 00455 for (m = 0; m < s->rx[l].fec_entries; m++) { 00456 limit = (l + m) & UDPTL_BUF_MASK; 00457 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) { 00458 if (s->rx[k].buf_len <= 0) 00459 which = (which == -1) ? k : -2; 00460 } 00461 if (which >= 0) { 00462 /* Repairable */ 00463 for (j = 0; j < s->rx[l].fec_len[m]; j++) { 00464 s->rx[which].buf[j] = s->rx[l].fec[m][j]; 00465 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) 00466 s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; 00467 } 00468 s->rx[which].buf_len = s->rx[l].fec_len[m]; 00469 repaired[which] = TRUE; 00470 } 00471 } 00472 } 00473 /* Now play any new packets forwards in time */ 00474 for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { 00475 if (repaired[l]) { 00476 //fprintf(stderr, "Fixed packet %d, len %d\n", j, l); 00477 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00478 s->f[ifp_no].subclass.codec = AST_MODEM_T38; 00479 00480 s->f[ifp_no].mallocd = 0; 00481 s->f[ifp_no].seqno = j; 00482 s->f[ifp_no].datalen = s->rx[l].buf_len; 00483 s->f[ifp_no].data.ptr = s->rx[l].buf; 00484 s->f[ifp_no].offset = 0; 00485 s->f[ifp_no].src = "UDPTL"; 00486 if (ifp_no > 0) 00487 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00488 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00489 ifp_no++; 00490 } 00491 } 00492 } 00493 00494 /* If packets are received out of sequence, we may have already processed this packet from the error 00495 recovery information in a packet already received. */ 00496 if (seq_no >= s->rx_seq_no) { 00497 /* Decode the primary IFP packet */ 00498 s->f[ifp_no].frametype = AST_FRAME_MODEM; 00499 s->f[ifp_no].subclass.codec = AST_MODEM_T38; 00500 00501 s->f[ifp_no].mallocd = 0; 00502 s->f[ifp_no].seqno = seq_no; 00503 s->f[ifp_no].datalen = ifp_len; 00504 s->f[ifp_no].data.ptr = (uint8_t *) ifp; 00505 s->f[ifp_no].offset = 0; 00506 s->f[ifp_no].src = "UDPTL"; 00507 if (ifp_no > 0) 00508 AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no]; 00509 AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL; 00510 00511 ifp_no++; 00512 } 00513 00514 s->rx_seq_no = seq_no + 1; 00515 return ifp_no; 00516 }
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, and f.
00651 { 00652 struct ast_udptl *udptl = cbdata; 00653 struct ast_frame *f; 00654 00655 if ((f = ast_udptl_read(udptl))) { 00656 if (udptl->callback) 00657 udptl->callback(udptl, f, udptl->data); 00658 } 00659 return 1; 00660 }
struct ast_cli_entry cli_udptl[] [static] |
Initial value:
{ { .handler = handle_cli_udptl_set_debug , .summary = "Enable/Disable UDPTL debugging" ,__VA_ARGS__ } }
Definition at line 1295 of file udptl.c.
Referenced by ast_udptl_init().
int udptldebug [static] |
struct ast_sockaddr udptldebugaddr [static] |
Debug packets to/from this host
Definition at line 85 of file udptl.c.
Referenced by 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] |