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