aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2009-07-23 22:21:57 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2009-07-23 22:21:57 +0000
commit2d426c817d7c5b55415475cbfadc7e8250c8d092 (patch)
treeeef9fd65ffb815cb366cfff4fb43f780df1c14aa /main
parent1c2ca7b1fa0b164e413d52c76d39d214ff4b431c (diff)
Merged revisions 208464 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r208464 | kpfleming | 2009-07-23 16:57:24 -0500 (Thu, 23 Jul 2009) | 46 lines Rework of T.38 negotiation and UDPTL API to address interoperability problems Over the past couple of months, a number of issues with Asterisk negotiating (and successfully completing) T.38 sessions with various endpoints have been found. This patch attempts to address many of them, primarily focused around ensuring that the endpoints' MaxDatagram size is honored, and in addition by ensuring that T.38 session parameter negotiation is performed correctly according to the ITU T.38 Recommendation. The major changes here are: 1) T.38 applications in Asterisk (app_fax) only generate/receive IFP packets, they do not ever work with UDPTL packets. As a result of this, they cannot be allowed to generate packets that would overflow the other endpoints' MaxDatagram size after the UDPTL stack adds any error correction information. With this patch, the application is told the maximum *IFP* size it can generate, based on a calculation using the far end MaxDatagram size and the active error correction mode on the T.38 session. The same is true for sending *our* MaxDatagram size to the remote endpoint; it is computed from the value that the application says it can accept (for a single IFP packet) combined with the active error correction mode. 2) All treatment of T.38 session parameters as 'capabilities' in chan_sip has been removed; these parameters are not at all like audio/video stream capabilities. There are strict rules to follow for computing an answer to a T.38 offer, and chan_sip now follows those rules, using the desired parameters from the application (or channel) that wants to accept the T.38 negotiation. 3) chan_sip now stores and forwards ast_control_t38_parameters structures for tracking 'our' and 'their' T.38 session parameters; this greatly simplifies negotiation, especially for pass-through calls. 4) Since T.38 negotiation without specifying parameters or receiving the final negotiated parameters is not very worthwhile, the AST_CONTROL_T38 control frame has been removed. A note has been added to UPGRADE.txt about this removal, since any out-of-tree applications that use it will no longer function properly until they are upgraded to use AST_CONTROL_T38_PARAMETERS. Review: https://reviewboard.asterisk.org/r/310/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.1@208484 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/channel.c9
-rw-r--r--main/frame.c18
-rw-r--r--main/rtp.c2
-rw-r--r--main/udptl.c271
4 files changed, 180 insertions, 120 deletions
diff --git a/main/channel.c b/main/channel.c
index f40099045..e054d7b95 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3044,9 +3044,9 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
case AST_CONTROL_TAKEOFFHOOK:
case AST_CONTROL_ANSWER:
case AST_CONTROL_HANGUP:
- case AST_CONTROL_T38:
case AST_CONTROL_T38_PARAMETERS:
- return 0;
+ case _XXX_AST_CONTROL_T38:
+ break;
case AST_CONTROL_CONGESTION:
case AST_CONTROL_BUSY:
@@ -3106,7 +3106,9 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
/* Handle conditions that we have tones for. */
switch (condition) {
- case AST_CONTROL_T38:
+ case _XXX_AST_CONTROL_T38:
+ /* deprecated T.38 control frame */
+ return -1;
case AST_CONTROL_T38_PARAMETERS:
/* there is no way to provide 'default' behavior for these
* control frames, so we need to return failure, but there
@@ -4764,7 +4766,6 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
case AST_CONTROL_UNHOLD:
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_SRCUPDATE:
- case AST_CONTROL_T38:
case AST_CONTROL_T38_PARAMETERS:
ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
if (jb_in_use) {
diff --git a/main/frame.c b/main/frame.c
index 976c537ff..83e8a0e91 100644
--- a/main/frame.c
+++ b/main/frame.c
@@ -835,24 +835,6 @@ void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
case AST_CONTROL_UNHOLD:
strcpy(subclass, "Unhold");
break;
- case AST_CONTROL_T38:
- if (f->datalen != sizeof(enum ast_control_t38)) {
- message = "Invalid";
- } else {
- enum ast_control_t38 state = *((enum ast_control_t38 *) f->data.ptr);
- if (state == AST_T38_REQUEST_NEGOTIATE)
- message = "Negotiation Requested";
- else if (state == AST_T38_REQUEST_TERMINATE)
- message = "Negotiation Request Terminated";
- else if (state == AST_T38_NEGOTIATED)
- message = "Negotiated";
- else if (state == AST_T38_TERMINATED)
- message = "Terminated";
- else if (state == AST_T38_REFUSED)
- message = "Refused";
- }
- snprintf(subclass, sizeof(subclass), "T38/%s", message);
- break;
case AST_CONTROL_T38_PARAMETERS:
if (f->datalen != sizeof(struct ast_control_t38_parameters *)) {
message = "Invalid";
diff --git a/main/rtp.c b/main/rtp.c
index 641311f18..8a51050b9 100644
--- a/main/rtp.c
+++ b/main/rtp.c
@@ -4003,7 +4003,6 @@ static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct
if ((fr->subclass == AST_CONTROL_HOLD) ||
(fr->subclass == AST_CONTROL_UNHOLD) ||
(fr->subclass == AST_CONTROL_VIDUPDATE) ||
- (fr->subclass == AST_CONTROL_T38) ||
(fr->subclass == AST_CONTROL_SRCUPDATE) ||
(fr->subclass == AST_CONTROL_T38_PARAMETERS)) {
if (fr->subclass == AST_CONTROL_HOLD) {
@@ -4244,7 +4243,6 @@ static enum ast_bridge_result bridge_p2p_loop(struct ast_channel *c0, struct ast
if ((fr->subclass == AST_CONTROL_HOLD) ||
(fr->subclass == AST_CONTROL_UNHOLD) ||
(fr->subclass == AST_CONTROL_VIDUPDATE) ||
- (fr->subclass == AST_CONTROL_T38) ||
(fr->subclass == AST_CONTROL_SRCUPDATE) ||
(fr->subclass == AST_CONTROL_T38_PARAMETERS)) {
/* If we are going on hold, then break callback mode and P2P bridging */
diff --git a/main/udptl.c b/main/udptl.c
index e39a9e7f2..35211ccb0 100644
--- a/main/udptl.c
+++ b/main/udptl.c
@@ -81,7 +81,7 @@ static struct sockaddr_in udptldebugaddr; /*!< Debug packets to/from this host
#ifdef SO_NO_CHECK
static int nochecksums;
#endif
-static int udptlfectype;
+static enum ast_t38_ec_modes udptlfectype;
static int udptlfecentries;
static int udptlfecspan;
static int udptlmaxdatagram;
@@ -100,10 +100,10 @@ typedef struct {
typedef struct {
int buf_len;
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
- int fec_len[MAX_FEC_ENTRIES];
+ unsigned int fec_len[MAX_FEC_ENTRIES];
uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM];
- int fec_span;
- int fec_entries;
+ unsigned int fec_span;
+ unsigned int fec_entries;
} udptl_fec_rx_buffer_t;
/*! \brief Structure for an UDPTL session */
@@ -122,35 +122,51 @@ struct ast_udptl {
struct io_context *io;
void *data;
ast_udptl_callback callback;
- int udptl_offered_from_local;
/*! This option indicates the error correction scheme used in transmitted UDPTL
- packets. */
- int error_correction_scheme;
+ * packets and expected in received UDPTL packets.
+ */
+ enum ast_t38_ec_modes error_correction_scheme;
/*! This option indicates the number of error correction entries transmitted in
- UDPTL packets. */
- int error_correction_entries;
+ * UDPTL packets and expected in received UDPTL packets.
+ */
+ unsigned int error_correction_entries;
/*! This option indicates the span of the error correction entries in transmitted
- UDPTL packets (FEC only). */
- int error_correction_span;
-
- /*! This option indicates the maximum size of a UDPTL packet that can be accepted by
- the remote device. */
- int far_max_datagram_size;
-
- /*! This option indicates the maximum size of a UDPTL packet that we are prepared to
- accept. */
- int local_max_datagram_size;
+ * UDPTL packets (FEC only).
+ */
+ unsigned int error_correction_span;
+
+ /*! The maximum size UDPTL packet that can be accepted by
+ * the remote device.
+ */
+ unsigned int far_max_datagram;
+
+ /*! The maximum size UDPTL packet that we are prepared to
+ * accept.
+ */
+ unsigned int local_max_datagram;
+
+ /*! The maximum IFP that can be submitted for sending
+ * to the remote device. Calculated from far_max_datagram,
+ * error_correction_scheme and error_correction_entries.
+ */
+ unsigned int far_max_ifp;
+
+ /*! The maximum IFP that the local endpoint is prepared
+ * to accept. Along with error_correction_scheme and
+ * error_correction_entries, used to calculate local_max_datagram.
+ */
+ unsigned int local_max_ifp;
int verbose;
struct sockaddr_in far;
- int tx_seq_no;
- int rx_seq_no;
- int rx_expected_seq_no;
+ unsigned int tx_seq_no;
+ unsigned int rx_seq_no;
+ unsigned int rx_expected_seq_no;
udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1];
udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1];
@@ -158,23 +174,20 @@ struct ast_udptl {
static AST_RWLIST_HEAD_STATIC(protos, ast_udptl_protocol);
-static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len);
-static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, int buflen, uint8_t *ifp, int ifp_len);
-
-static inline int udptl_debug_test_addr(struct sockaddr_in *addr)
+static inline int udptl_debug_test_addr(const struct sockaddr_in *addr)
{
if (udptldebug == 0)
return 0;
if (udptldebugaddr.sin_addr.s_addr) {
- if (((ntohs(udptldebugaddr.sin_port) != 0)
- && (udptldebugaddr.sin_port != addr->sin_port))
- || (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
+ if (((ntohs(udptldebugaddr.sin_port) != 0) &&
+ (udptldebugaddr.sin_port != addr->sin_port)) ||
+ (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
return 0;
}
return 1;
}
-static int decode_length(uint8_t *buf, int limit, int *len, int *pvalue)
+static int decode_length(uint8_t *buf, unsigned int limit, unsigned int *len, unsigned int *pvalue)
{
if (*len >= limit)
return -1;
@@ -199,15 +212,16 @@ static int decode_length(uint8_t *buf, int limit, int *len, int *pvalue)
}
/*- End of function --------------------------------------------------------*/
-static int decode_open_type(uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets)
+static int decode_open_type(uint8_t *buf, unsigned int limit, unsigned int *len, const uint8_t **p_object, unsigned int *p_num_octets)
{
- int octet_cnt;
- int octet_idx;
- int length;
- int i;
+ unsigned int octet_cnt;
+ unsigned int octet_idx;
+ unsigned int length;
+ unsigned int i;
const uint8_t **pbuf;
for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) {
+ octet_cnt = 0;
if ((length = decode_length(buf, limit, len, &octet_cnt)) < 0)
return -1;
if (octet_cnt > 0) {
@@ -229,9 +243,9 @@ static int decode_open_type(uint8_t *buf, int limit, int *len, const uint8_t **p
}
/*- End of function --------------------------------------------------------*/
-static int encode_length(uint8_t *buf, int *len, int value)
+static unsigned int encode_length(uint8_t *buf, unsigned int *len, unsigned int value)
{
- int multiplier;
+ unsigned int multiplier;
if (value < 0x80) {
/* 1 octet */
@@ -257,10 +271,10 @@ static int encode_length(uint8_t *buf, int *len, int value)
}
/*- End of function --------------------------------------------------------*/
-static int encode_open_type(uint8_t *buf, int buflen, int *len, const uint8_t *data, int num_octets)
+static int encode_open_type(uint8_t *buf, unsigned int buflen, unsigned int *len, const uint8_t *data, unsigned int num_octets)
{
- int enclen;
- int octet_idx;
+ unsigned int enclen;
+ unsigned int octet_idx;
uint8_t zero_byte;
/* If open type is of zero length, add a single zero byte (10.1) */
@@ -289,7 +303,7 @@ static int encode_open_type(uint8_t *buf, int buflen, int *len, const uint8_t *d
}
/*- End of function --------------------------------------------------------*/
-static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
+static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len)
{
int stat1;
int stat2;
@@ -301,16 +315,16 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
int x;
int limit;
int which;
- int ptr;
- int count;
+ unsigned int ptr;
+ unsigned int count;
int total_count;
int seq_no;
const uint8_t *ifp;
const uint8_t *data;
- int ifp_len;
+ unsigned int ifp_len;
int repaired[16];
const uint8_t *bufs[16];
- int lengths[16];
+ unsigned int lengths[16];
int span;
int entries;
int ifp_no;
@@ -497,7 +511,7 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
}
/*- End of function --------------------------------------------------------*/
-static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, int buflen, uint8_t *ifp, int ifp_len)
+static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, unsigned int buflen, uint8_t *ifp, unsigned int ifp_len)
{
uint8_t fec[LOCAL_FAX_MAX_DATAGRAM * 2];
int i;
@@ -507,7 +521,7 @@ static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, int buflen, uin
int entries;
int span;
int m;
- int len;
+ unsigned int len;
int limit;
int high_tide;
@@ -612,7 +626,7 @@ static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, int buflen, uin
return len;
}
-int ast_udptl_fd(struct ast_udptl *udptl)
+int ast_udptl_fd(const struct ast_udptl *udptl)
{
return udptl->fd;
}
@@ -695,15 +709,67 @@ struct ast_frame *ast_udptl_read(struct ast_udptl *udptl)
return &udptl->f[0];
}
-void ast_udptl_offered_from_local(struct ast_udptl* udptl, int local)
+static void calculate_local_max_datagram(struct ast_udptl *udptl)
{
- if (udptl)
- udptl->udptl_offered_from_local = local;
- else
- ast_log(LOG_WARNING, "udptl structure is null\n");
+ unsigned int new_max = 200;
+
+ /* calculate the amount of space required to receive an IFP
+ * using the current error correction mode, and ensure that our
+ * local max datagram size is at least that big
+ */
+ switch (udptl->error_correction_scheme) {
+ case UDPTL_ERROR_CORRECTION_NONE:
+ /* only need room for sequence number and length indicators */
+ new_max = 6 + udptl->local_max_ifp;
+ break;
+ case UDPTL_ERROR_CORRECTION_REDUNDANCY:
+ /* need room for sequence number, length indicators and the
+ * configured number of redundant packets
+ */
+ new_max = 6 + udptl->local_max_ifp + 2 + (udptl->error_correction_entries * udptl->local_max_ifp);
+ break;
+ case UDPTL_ERROR_CORRECTION_FEC:
+ /* need room for sequence number, length indicators and a
+ * a single IFP of the maximum size expected
+ */
+ new_max = 6 + udptl->local_max_ifp + 4 + udptl->local_max_ifp;
+ break;
+ }
+ /* add 25% of extra space for insurance, but no larger than LOCAL_FAX_MAX_DATAGRAM */
+ udptl->local_max_datagram = MIN(new_max * 1.25, LOCAL_FAX_MAX_DATAGRAM);
+}
+
+static void calculate_far_max_ifp(struct ast_udptl *udptl)
+{
+ unsigned new_max = 40;
+
+ /* calculate the maximum IFP the local endpoint should
+ * generate based on the far end's maximum datagram size
+ * and the current error correction mode
+ */
+ switch (udptl->error_correction_scheme) {
+ case UDPTL_ERROR_CORRECTION_NONE:
+ /* only need room for sequence number and length indicators */
+ new_max = udptl->far_max_datagram - 6;
+ break;
+ case UDPTL_ERROR_CORRECTION_REDUNDANCY:
+ /* need room for sequence number, length indicators and the
+ * configured number of redundant packets
+ */
+ new_max = (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1);
+ break;
+ case UDPTL_ERROR_CORRECTION_FEC:
+ /* need room for sequence number, length indicators and a
+ * a single IFP of the maximum size expected
+ */
+ new_max = (udptl->far_max_datagram - 10) / 2;
+ break;
+ }
+ /* subtract 25% of space for insurance */
+ udptl->far_max_ifp = new_max * 0.75;
}
-int ast_udptl_get_error_correction_scheme(struct ast_udptl* udptl)
+int ast_udptl_get_error_correction_scheme(const struct ast_udptl *udptl)
{
if (udptl)
return udptl->error_correction_scheme;
@@ -713,60 +779,75 @@ int ast_udptl_get_error_correction_scheme(struct ast_udptl* udptl)
}
}
-void ast_udptl_set_error_correction_scheme(struct ast_udptl* udptl, int ec)
+void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
{
if (udptl) {
+ 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;
- break;
- case UDPTL_ERROR_CORRECTION_NONE:
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE;
+ if (udptl->error_correction_entries == 0) {
+ udptl->error_correction_entries = 3;
+ }
break;
default:
- ast_log(LOG_WARNING, "error correction parameter invalid\n");
+ /* nothing to do */
+ break;
};
+ calculate_local_max_datagram(udptl);
+ calculate_far_max_ifp(udptl);
} else
ast_log(LOG_WARNING, "udptl structure is null\n");
}
-int ast_udptl_get_local_max_datagram(struct ast_udptl* udptl)
+unsigned int ast_udptl_get_local_max_datagram(const struct ast_udptl *udptl)
{
if (udptl)
- return udptl->local_max_datagram_size;
+ return udptl->local_max_datagram;
else {
ast_log(LOG_WARNING, "udptl structure is null\n");
- return -1;
+ return 0;
}
}
-int ast_udptl_get_far_max_datagram(struct ast_udptl* udptl)
+unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl)
{
if (udptl)
- return udptl->far_max_datagram_size;
+ return udptl->far_max_datagram;
else {
ast_log(LOG_WARNING, "udptl structure is null\n");
- return -1;
+ return 0;
}
}
-void ast_udptl_set_local_max_datagram(struct ast_udptl* udptl, int max_datagram)
+void ast_udptl_set_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram)
{
- if (udptl)
- udptl->local_max_datagram_size = max_datagram;
- else
+ if (udptl) {
+ udptl->far_max_datagram = max_datagram;
+ calculate_far_max_ifp(udptl);
+ } else {
ast_log(LOG_WARNING, "udptl structure is null\n");
+ }
}
-void ast_udptl_set_far_max_datagram(struct ast_udptl* udptl, int max_datagram)
+void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
{
- if (udptl)
- udptl->far_max_datagram_size = max_datagram;
- else
- ast_log(LOG_WARNING, "udptl structure is null\n");
+ udptl->local_max_ifp = max_ifp;
+ calculate_local_max_datagram(udptl);
+}
+
+unsigned int ast_udptl_get_far_max_ifp(const struct ast_udptl *udptl)
+{
+ return udptl->far_max_ifp;
}
struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr addr)
@@ -780,20 +861,13 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struc
if (!(udptl = ast_calloc(1, sizeof(*udptl))))
return NULL;
- if (udptlfectype == 2)
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC;
- else if (udptlfectype == 1)
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY;
- else
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE;
+ udptl->error_correction_scheme = udptlfectype;
udptl->error_correction_span = udptlfecspan;
udptl->error_correction_entries = udptlfecentries;
- udptl->far_max_datagram_size = udptlmaxdatagram;
- udptl->local_max_datagram_size = udptlmaxdatagram;
+ udptl->far_max_datagram = udptlmaxdatagram;
+ udptl->local_max_datagram = udptlmaxdatagram;
- memset(&udptl->rx, 0, sizeof(udptl->rx));
- memset(&udptl->tx, 0, sizeof(udptl->tx));
for (i = 0; i <= UDPTL_BUF_MASK; i++) {
udptl->rx[i].buf_len = -1;
udptl->tx[i].buf_len = -1;
@@ -852,18 +926,18 @@ struct ast_udptl *ast_udptl_new(struct sched_context *sched, struct io_context *
return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia);
}
-int ast_udptl_setqos(struct ast_udptl *udptl, int tos, int cos)
+int ast_udptl_setqos(struct ast_udptl *udptl, unsigned int tos, unsigned int cos)
{
return ast_netsock_set_qos(udptl->fd, tos, cos, "UDPTL");
}
-void ast_udptl_set_peer(struct ast_udptl *udptl, struct sockaddr_in *them)
+void ast_udptl_set_peer(struct ast_udptl *udptl, const struct sockaddr_in *them)
{
udptl->them.sin_port = them->sin_port;
udptl->them.sin_addr = them->sin_addr;
}
-void ast_udptl_get_peer(struct ast_udptl *udptl, struct sockaddr_in *them)
+void ast_udptl_get_peer(const struct ast_udptl *udptl, struct sockaddr_in *them)
{
memset(them, 0, sizeof(*them));
them->sin_family = AF_INET;
@@ -871,7 +945,7 @@ void ast_udptl_get_peer(struct ast_udptl *udptl, struct sockaddr_in *them)
them->sin_addr = udptl->them.sin_addr;
}
-void ast_udptl_get_us(struct ast_udptl *udptl, struct sockaddr_in *us)
+void ast_udptl_get_us(const struct ast_udptl *udptl, struct sockaddr_in *us)
{
memcpy(us, &udptl->us, sizeof(udptl->us));
}
@@ -893,10 +967,10 @@ void ast_udptl_destroy(struct ast_udptl *udptl)
int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
{
- int seq;
- int len;
+ unsigned int seq;
+ unsigned int len;
int res;
- uint8_t buf[LOCAL_FAX_MAX_DATAGRAM * 2];
+ uint8_t buf[s->far_max_datagram];
/* If we have no peer, return immediately */
if (s->them.sin_addr.s_addr == INADDR_ANY)
@@ -906,11 +980,16 @@ int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
if (f->datalen == 0)
return 0;
- if (f->frametype != AST_FRAME_MODEM) {
- ast_log(LOG_WARNING, "UDPTL can only send T.38 data\n");
+ if ((f->frametype != AST_FRAME_MODEM) ||
+ (f->subclass != AST_MODEM_T38)) {
+ ast_log(LOG_WARNING, "UDPTL can only send T.38 data.\n");
return -1;
}
+ if (f->datalen > s->far_max_ifp) {
+ ast_log(LOG_WARNING, "UDPTL asked to send %d bytes of IFP when far end only prepared to accept %d bytes; data loss may occur.\n", f->datalen, s->far_max_ifp);
+ }
+
/* Save seq_no for debug output because udptl_build_packet increments it */
seq = s->tx_seq_no & 0xFFFF;
@@ -1234,7 +1313,7 @@ static void __ast_udptl_reload(int reload)
udptlstart = 4500;
udptlend = 4999;
- udptlfectype = 0;
+ udptlfectype = UDPTL_ERROR_CORRECTION_NONE;
udptlfecentries = 0;
udptlfecspan = 0;
udptlmaxdatagram = 0;
@@ -1275,9 +1354,9 @@ static void __ast_udptl_reload(int reload)
}
if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) {
if (strcmp(s, "t38UDPFEC") == 0)
- udptlfectype = 2;
+ udptlfectype = UDPTL_ERROR_CORRECTION_FEC;
else if (strcmp(s, "t38UDPRedundancy") == 0)
- udptlfectype = 1;
+ udptlfectype = UDPTL_ERROR_CORRECTION_REDUNDANCY;
}
if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) {
udptlmaxdatagram = atoi(s);