UDPTL support for T.38. More...
#include "asterisk/network.h"#include "asterisk/frame.h"#include "asterisk/io.h"#include "asterisk/sched.h"#include "asterisk/channel.h"#include "asterisk/netsock2.h"

Go to the source code of this file.
Data Structures | |
| struct | ast_udptl_protocol |
Typedefs | |
| typedef int(* | ast_udptl_callback )(struct ast_udptl *udptl, struct ast_frame *f, void *data) |
Enumerations | |
| enum | ast_t38_ec_modes { UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_REDUNDANCY } |
Functions | |
| 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 sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *in) |
| 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_reset (struct ast_udptl *udptl) |
| 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_m_type (struct ast_udptl *udptl, unsigned int pt) |
| 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_set_udptlmap_type (struct ast_udptl *udptl, unsigned int pt, char *mimeType, char *mimeSubtype) |
| 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 *udptl, struct ast_frame *f) |
| typedef int(* ast_udptl_callback)(struct ast_udptl *udptl, struct ast_frame *f, void *data) |
| enum ast_t38_ec_modes |
| 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 1122 of file udptl.c.
References f, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, get_proto(), ast_log(), LOG_WARNING, ast_channel::name, ast_channel::tech_pvt, ast_udptl_protocol::get_udptl_info, ast_udptl_protocol::set_udptl_peer, ast_udptl_get_peer(), ast_channel::masq, ast_channel::masqr, ast_debug, ast_sockaddr_cmp(), ast_sockaddr_stringify(), ast_sockaddr_copy(), ast_waitfor_n(), ast_check_hangup(), ast_read(), ast_frame::frametype, AST_FRAME_MODEM, ast_write(), and ast_frfree.
{
struct ast_frame *f;
struct ast_channel *who;
struct ast_channel *cs[3];
struct ast_udptl *p0;
struct ast_udptl *p1;
struct ast_udptl_protocol *pr0;
struct ast_udptl_protocol *pr1;
struct ast_sockaddr ac0;
struct ast_sockaddr ac1;
struct ast_sockaddr t0;
struct ast_sockaddr t1;
void *pvt0;
void *pvt1;
int to;
ast_channel_lock(c0);
while (ast_channel_trylock(c1)) {
ast_channel_unlock(c0);
usleep(1);
ast_channel_lock(c0);
}
pr0 = get_proto(c0);
pr1 = get_proto(c1);
if (!pr0) {
ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
return -1;
}
if (!pr1) {
ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
return -1;
}
pvt0 = c0->tech_pvt;
pvt1 = c1->tech_pvt;
p0 = pr0->get_udptl_info(c0);
p1 = pr1->get_udptl_info(c1);
if (!p0 || !p1) {
/* Somebody doesn't want to play... */
ast_channel_unlock(c0);
ast_channel_unlock(c1);
return -2;
}
if (pr0->set_udptl_peer(c0, p1)) {
ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
memset(&ac1, 0, sizeof(ac1));
} else {
/* Store UDPTL peer */
ast_udptl_get_peer(p1, &ac1);
}
if (pr1->set_udptl_peer(c1, p0)) {
ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
memset(&ac0, 0, sizeof(ac0));
} else {
/* Store UDPTL peer */
ast_udptl_get_peer(p0, &ac0);
}
ast_channel_unlock(c0);
ast_channel_unlock(c1);
cs[0] = c0;
cs[1] = c1;
cs[2] = NULL;
for (;;) {
if ((c0->tech_pvt != pvt0) ||
(c1->tech_pvt != pvt1) ||
(c0->masq || c0->masqr || c1->masq || c1->masqr)) {
ast_debug(1, "Oooh, something is weird, backing out\n");
/* Tell it to try again later */
return -3;
}
to = -1;
ast_udptl_get_peer(p1, &t1);
ast_udptl_get_peer(p0, &t0);
if (ast_sockaddr_cmp(&t1, &ac1)) {
ast_debug(1, "Oooh, '%s' changed end address to %s\n",
c1->name, ast_sockaddr_stringify(&t1));
ast_debug(1, "Oooh, '%s' was %s\n",
c1->name, ast_sockaddr_stringify(&ac1));
ast_sockaddr_copy(&ac1, &t1);
}
if (ast_sockaddr_cmp(&t0, &ac0)) {
ast_debug(1, "Oooh, '%s' changed end address to %s\n",
c0->name, ast_sockaddr_stringify(&t0));
ast_debug(1, "Oooh, '%s' was %s\n",
c0->name, ast_sockaddr_stringify(&ac0));
ast_sockaddr_copy(&ac0, &t0);
}
who = ast_waitfor_n(cs, 2, &to);
if (!who) {
ast_debug(1, "Ooh, empty read...\n");
/* check for hangup / whentohangup */
if (ast_check_hangup(c0) || ast_check_hangup(c1))
break;
continue;
}
f = ast_read(who);
if (!f) {
*fo = f;
*rc = who;
ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup");
/* That's all we needed */
return 0;
} else {
if (f->frametype == AST_FRAME_MODEM) {
/* Forward T.38 frames if they happen upon us */
if (who == c0) {
ast_write(c1, f);
} else if (who == c1) {
ast_write(c0, f);
}
}
ast_frfree(f);
}
/* Swap priority. Not that it's a big deal at this point */
cs[2] = cs[0];
cs[0] = cs[1];
cs[1] = cs[2];
}
return -1;
}
| void ast_udptl_destroy | ( | struct ast_udptl * | udptl | ) |
Definition at line 1020 of file udptl.c.
References ast_udptl::ioid, ast_io_remove(), ast_udptl::io, ast_udptl::fd, ast_udptl::tag, and ast_free.
Referenced by create_addr_from_peer(), and __sip_destroy().
| int ast_udptl_fd | ( | const struct ast_udptl * | udptl | ) |
Definition at line 630 of file udptl.c.
References ast_udptl::fd.
Referenced by __oh323_new(), and sip_new().
{
return udptl->fd;
}
| enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme | ( | const struct ast_udptl * | udptl | ) |
Definition at line 815 of file udptl.c.
References ast_udptl::error_correction_scheme.
Referenced by add_sdp().
{
return udptl->error_correction_scheme;
}
| unsigned int ast_udptl_get_far_max_datagram | ( | const struct ast_udptl * | udptl | ) |
Definition at line 883 of file udptl.c.
References ast_udptl::far_max_datagram.
Referenced by process_sdp().
{
if (udptl->far_max_datagram < 0) {
return 0;
}
return udptl->far_max_datagram;
}
| 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 891 of file udptl.c.
References ast_udptl::far_max_ifp, and calculate_far_max_ifp().
Referenced by change_t38_state(), and interpret_t38_parameters().
{
if (udptl->far_max_ifp == -1) {
calculate_far_max_ifp(udptl);
}
if (udptl->far_max_ifp < 0) {
return 0;
}
return udptl->far_max_ifp;
}
| 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 859 of file udptl.c.
References ast_udptl::local_max_datagram, and calculate_local_max_datagram().
Referenced by add_sdp().
{
if (udptl->local_max_datagram == -1) {
calculate_local_max_datagram(udptl);
}
/* this function expects a unsigned value in return. */
if (udptl->local_max_datagram < 0) {
return 0;
}
return udptl->local_max_datagram;
}
| void ast_udptl_get_peer | ( | const struct ast_udptl * | udptl, |
| struct ast_sockaddr * | them | ||
| ) |
Definition at line 1005 of file udptl.c.
References ast_sockaddr_copy(), and ast_udptl::them.
Referenced by sip_set_udptl_peer(), and ast_udptl_bridge().
{
ast_sockaddr_copy(them, &udptl->them);
}
| void ast_udptl_get_us | ( | const struct ast_udptl * | udptl, |
| struct ast_sockaddr * | us | ||
| ) |
Definition at line 1010 of file udptl.c.
References ast_sockaddr_copy(), and ast_udptl::us.
Referenced by add_sdp().
{
ast_sockaddr_copy(us, &udptl->us);
}
| void ast_udptl_init | ( | void | ) |
Definition at line 1403 of file udptl.c.
References ast_cli_register_multiple(), ARRAY_LEN, and __ast_udptl_reload().
Referenced by main().
| struct ast_udptl* ast_udptl_new_with_bindaddr | ( | struct sched_context * | sched, |
| struct io_context * | io, | ||
| int | callbackmode, | ||
| struct ast_sockaddr * | in | ||
| ) | [read] |
Definition at line 903 of file udptl.c.
References ast_udptl::flags, ast_calloc, ast_udptl::error_correction_span, udptlfecspan, ast_udptl::error_correction_entries, udptlfecentries, ast_udptl::far_max_datagram, ast_udptl::far_max_ifp, ast_udptl::local_max_ifp, ast_udptl::local_max_datagram, UDPTL_BUF_MASK, ast_udptl::rx, udptl_fec_rx_buffer_t::buf_len, ast_udptl::tx, udptl_fec_tx_buffer_t::buf_len, ast_udptl::fd, ast_sockaddr_is_ipv6(), ast_free, ast_log(), LOG_WARNING, errno, udptlend, ast_random(), udptlstart, ast_sockaddr_copy(), ast_udptl::us, ast_sockaddr_set_port, ast_bind(), ast_udptl::sched, sched, ast_udptl::io, io, ast_udptl::ioid, ast_io_add(), udptlread(), and AST_IO_IN.
Referenced by create_addr_from_peer(), sip_alloc(), and handle_request_invite().
{
struct ast_udptl *udptl;
int x;
int startplace;
int i;
long int flags;
if (!(udptl = ast_calloc(1, sizeof(*udptl))))
return NULL;
udptl->error_correction_span = udptlfecspan;
udptl->error_correction_entries = udptlfecentries;
udptl->far_max_datagram = -1;
udptl->far_max_ifp = -1;
udptl->local_max_ifp = -1;
udptl->local_max_datagram = -1;
for (i = 0; i <= UDPTL_BUF_MASK; i++) {
udptl->rx[i].buf_len = -1;
udptl->tx[i].buf_len = -1;
}
if ((udptl->fd = socket(ast_sockaddr_is_ipv6(addr) ?
AF_INET6 : AF_INET, SOCK_DGRAM, 0)) < 0) {
ast_free(udptl);
ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
return NULL;
}
flags = fcntl(udptl->fd, F_GETFL);
fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK);
#ifdef SO_NO_CHECK
if (nochecksums)
setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
#endif
/* Find us a place */
x = (udptlstart == udptlend) ? udptlstart : (ast_random() % (udptlend - udptlstart)) + udptlstart;
if (use_even_ports && (x & 1)) {
++x;
}
startplace = x;
for (;;) {
ast_sockaddr_copy(&udptl->us, addr);
ast_sockaddr_set_port(&udptl->us, x);
if (ast_bind(udptl->fd, &udptl->us) == 0) {
break;
}
if (errno != EADDRINUSE) {
ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
close(udptl->fd);
ast_free(udptl);
return NULL;
}
if (use_even_ports) {
x += 2;
} else {
++x;
}
if (x > udptlend)
x = udptlstart;
if (x == startplace) {
ast_log(LOG_WARNING, "No UDPTL ports remaining\n");
close(udptl->fd);
ast_free(udptl);
return NULL;
}
}
if (io && sched && callbackmode) {
/* Operate this one in a callback mode */
udptl->sched = sched;
udptl->io = io;
udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl);
}
return udptl;
}
| int ast_udptl_proto_register | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 1091 of file udptl.c.
References AST_RWLIST_WRLOCK, AST_RWLIST_TRAVERSE, ast_udptl_protocol::type, ast_log(), LOG_WARNING, AST_RWLIST_UNLOCK, and AST_RWLIST_INSERT_TAIL.
Referenced by load_module().
{
struct ast_udptl_protocol *cur;
AST_RWLIST_WRLOCK(&protos);
AST_RWLIST_TRAVERSE(&protos, cur, list) {
if (cur->type == proto->type) {
ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
AST_RWLIST_UNLOCK(&protos);
return -1;
}
}
AST_RWLIST_INSERT_TAIL(&protos, proto, list);
AST_RWLIST_UNLOCK(&protos);
return 0;
}
| void ast_udptl_proto_unregister | ( | struct ast_udptl_protocol * | proto | ) |
Definition at line 1084 of file udptl.c.
References AST_RWLIST_WRLOCK, AST_RWLIST_REMOVE, and AST_RWLIST_UNLOCK.
Referenced by unload_module().
{
AST_RWLIST_WRLOCK(&protos);
AST_RWLIST_REMOVE(&protos, proto, list);
AST_RWLIST_UNLOCK(&protos);
}
Definition at line 662 of file udptl.c.
References ast_recvfrom(), ast_udptl::fd, ast_udptl::rawdata, AST_FRIENDLY_OFFSET, errno, ast_log(), LOG_WARNING, LOG_TAG, ast_assert, ast_null_frame, ast_sockaddr_isnull(), ast_udptl::them, ast_udptl::nat, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_debug, ast_sockaddr_stringify(), udptl_debug_test_addr(), ast_verb, udptl_rx_packet(), and ast_udptl::f.
Referenced by sip_rtp_read(), skinny_rtp_read(), and udptlread().
{
int res;
struct ast_sockaddr addr;
uint16_t seqno = 0;
/* Cache where the header will go */
res = ast_recvfrom(udptl->fd,
udptl->rawdata + AST_FRIENDLY_OFFSET,
sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
0,
&addr);
if (res < 0) {
if (errno != EAGAIN)
ast_log(LOG_WARNING, "(%s): UDPTL read error: %s\n",
LOG_TAG(udptl), strerror(errno));
ast_assert(errno != EBADF);
return &ast_null_frame;
}
/* Ignore if the other side hasn't been given an address yet. */
if (ast_sockaddr_isnull(&udptl->them)) {
return &ast_null_frame;
}
if (udptl->nat) {
/* Send to whoever sent to us */
if (ast_sockaddr_cmp(&udptl->them, &addr)) {
ast_sockaddr_copy(&udptl->them, &addr);
ast_debug(1, "UDPTL NAT (%s): Using address %s\n",
LOG_TAG(udptl), ast_sockaddr_stringify(&udptl->them));
}
}
if (udptl_debug_test_addr(&addr)) {
ast_verb(1, "UDPTL (%s): packet from %s (type %d, seq %d, len %d)\n",
LOG_TAG(udptl), ast_sockaddr_stringify(&addr), 0, seqno, res);
}
if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1)
return &ast_null_frame;
return &udptl->f[0];
}
| int ast_udptl_reload | ( | void | ) |
Definition at line 1397 of file udptl.c.
References __ast_udptl_reload().
{
__ast_udptl_reload(1);
return 0;
}
| void ast_udptl_reset | ( | struct ast_udptl * | udptl | ) |
| void ast_udptl_set_callback | ( | struct ast_udptl * | udptl, |
| ast_udptl_callback | callback | ||
| ) |
Definition at line 640 of file udptl.c.
References ast_udptl::callback.
{
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 | ||
| ) |
Definition at line 820 of file udptl.c.
References ast_udptl::error_correction_scheme, UDPTL_ERROR_CORRECTION_FEC, ast_udptl::error_correction_entries, ast_udptl::error_correction_span, UDPTL_ERROR_CORRECTION_REDUNDANCY, ast_udptl::local_max_datagram, and ast_udptl::far_max_ifp.
Referenced by set_t38_capabilities(), process_sdp(), and process_sdp_a_image().
{
udptl->error_correction_scheme = ec;
switch (ec) {
case UDPTL_ERROR_CORRECTION_FEC:
udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC;
if (udptl->error_correction_entries == 0) {
udptl->error_correction_entries = 3;
}
if (udptl->error_correction_span == 0) {
udptl->error_correction_span = 3;
}
break;
case UDPTL_ERROR_CORRECTION_REDUNDANCY:
udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY;
if (udptl->error_correction_entries == 0) {
udptl->error_correction_entries = 3;
}
break;
default:
/* nothing to do */
break;
};
/* reset calculated values so they'll be computed again */
udptl->local_max_datagram = -1;
udptl->far_max_ifp = -1;
}
| 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 872 of file udptl.c.
References FAX_MAX_DATAGRAM_LIMIT, ast_udptl::far_max_datagram, DEFAULT_FAX_MAX_DATAGRAM, and ast_udptl::far_max_ifp.
Referenced by process_sdp(), and process_sdp_a_image().
{
if (!max_datagram || (max_datagram > FAX_MAX_DATAGRAM_LIMIT)) {
udptl->far_max_datagram = DEFAULT_FAX_MAX_DATAGRAM;
} else {
udptl->far_max_datagram = max_datagram;
}
/* reset calculated values so they'll be computed again */
udptl->far_max_ifp = -1;
}
| void ast_udptl_set_local_max_ifp | ( | struct ast_udptl * | udptl, |
| unsigned int | max_ifp | ||
| ) |
Definition at line 848 of file udptl.c.
References ast_udptl::local_max_ifp, and ast_udptl::local_max_datagram.
Referenced by interpret_t38_parameters().
{
/* make sure max_ifp is a positive value since a cast will take place when
* when setting local_max_ifp */
if ((signed int) max_ifp > 0) {
udptl->local_max_ifp = max_ifp;
/* reset calculated values so they'll be computed again */
udptl->local_max_datagram = -1;
}
}
| void ast_udptl_set_m_type | ( | struct ast_udptl * | udptl, |
| unsigned int | pt | ||
| ) |
| void ast_udptl_set_peer | ( | struct ast_udptl * | udptl, |
| const struct ast_sockaddr * | them | ||
| ) |
Definition at line 1000 of file udptl.c.
References ast_sockaddr_copy(), and ast_udptl::them.
Referenced by process_sdp().
{
ast_sockaddr_copy(&udptl->them, them);
}
| void ast_udptl_set_tag | ( | struct ast_udptl * | udptl, |
| const char * | format, | ||
| ... | |||
| ) |
Associates a character string 'tag' with a UDPTL session.
| udptl | The UDPTL session. |
| format | printf-style format string used to construct the tag |
This function formats a tag for the specified UDPTL session, so that any log messages generated by the UDPTL stack related to that session will include the tag and the reader of the messages will be able to identify which endpoint caused them to be generated.
| none |
Definition at line 980 of file udptl.c.
References ast_udptl::tag, ast_free, and ast_vasprintf.
Referenced by change_t38_state().
| void ast_udptl_set_udptlmap_type | ( | struct ast_udptl * | udptl, |
| unsigned int | pt, | ||
| char * | mimeType, | ||
| char * | mimeSubtype | ||
| ) |
| void ast_udptl_setnat | ( | struct ast_udptl * | udptl, |
| int | nat | ||
| ) |
Definition at line 645 of file udptl.c.
References ast_udptl::nat, and nat.
Referenced by do_setnat().
| int ast_udptl_setqos | ( | struct ast_udptl * | udptl, |
| unsigned int | tos, | ||
| unsigned int | cos | ||
| ) |
Definition at line 995 of file udptl.c.
References ast_netsock_set_qos(), and ast_udptl::fd.
Referenced by sip_alloc().
{
return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL");
}
| void ast_udptl_stop | ( | struct ast_udptl * | udptl | ) |
Definition at line 1015 of file udptl.c.
References ast_sockaddr_setnull(), and ast_udptl::them.
Referenced by process_sdp(), and stop_media_flows().
{
ast_sockaddr_setnull(&udptl->them);
}
Definition at line 1031 of file udptl.c.
References seq, len(), ast_frame::datalen, ast_udptl::far_max_datagram, DEFAULT_FAX_MAX_DATAGRAM, ast_sockaddr_isnull(), ast_udptl::them, ast_frame::frametype, AST_FRAME_MODEM, ast_frame::subclass, ast_frame_subclass::codec, AST_MODEM_T38, ast_log(), LOG_WARNING, LOG_TAG, ast_udptl::far_max_ifp, ast_udptl::tx_seq_no, udptl_build_packet(), ast_frame::data, ast_frame::ptr, ast_sendto(), ast_udptl::fd, LOG_NOTICE, ast_sockaddr_stringify(), errno, udptl_debug_test_addr(), and ast_verb.
Referenced by sip_write().
{
unsigned int seq;
unsigned int len = f->datalen;
int res;
/* if no max datagram size is provided, use default value */
const int bufsize = (s->far_max_datagram > 0) ? s->far_max_datagram : DEFAULT_FAX_MAX_DATAGRAM;
uint8_t buf[bufsize];
memset(buf, 0, sizeof(buf));
/* If we have no peer, return immediately */
if (ast_sockaddr_isnull(&s->them)) {
return 0;
}
/* If there is no data length, return immediately */
if (f->datalen == 0)
return 0;
if ((f->frametype != AST_FRAME_MODEM) ||
(f->subclass.codec != AST_MODEM_T38)) {
ast_log(LOG_WARNING, "(%s): UDPTL can only send T.38 data.\n",
LOG_TAG(s));
return -1;
}
if (len > s->far_max_ifp) {
ast_log(LOG_WARNING,
"(%s): UDPTL asked to send %d bytes of IFP when far end only prepared to accept %d bytes; data loss will occur."
"You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n",
LOG_TAG(s), len, s->far_max_ifp);
len = s->far_max_ifp;
}
/* Save seq_no for debug output because udptl_build_packet increments it */
seq = s->tx_seq_no & 0xFFFF;
/* Cook up the UDPTL packet, with the relevant EC info. */
len = udptl_build_packet(s, buf, sizeof(buf), f->data.ptr, len);
if ((signed int) len > 0 && !ast_sockaddr_isnull(&s->them)) {
if ((res = ast_sendto(s->fd, buf, len, 0, &s->them)) < 0)
ast_log(LOG_NOTICE, "(%s): UDPTL Transmission error to %s: %s\n",
LOG_TAG(s), ast_sockaddr_stringify(&s->them), strerror(errno));
if (udptl_debug_test_addr(&s->them))
ast_verb(1, "UDPTL (%s): packet to %s (type %d, seq %d, len %d)\n",
LOG_TAG(s), ast_sockaddr_stringify(&s->them), 0, seq, len);
}
return 0;
}