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