mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-15 06:18:38 +00:00
fixes crash during T.38 negotiation caused by invalid or missing FaxMaxDatagram field
AST-2010-001 (closes issue #16634) Reported by: krn (closes issue #16724) Reported by: barthpbx (closes issue #16517) Reported by: bklang (closes issue #16485) Reported by: elsto git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@244443 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -4067,7 +4067,7 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int res
|
|||||||
p->packets = pkt; /* Add it to the queue */
|
p->packets = pkt; /* Add it to the queue */
|
||||||
if (resp) {
|
if (resp) {
|
||||||
/* Parse out the response code */
|
/* Parse out the response code */
|
||||||
if (sscanf(ast_str_buffer(pkt->data), "SIP/2.0 %30d", &respid) == 1) {
|
if (sscanf(ast_str_buffer(pkt->data), "SIP/2.0 %30u", &respid) == 1) {
|
||||||
pkt->response_code = respid;
|
pkt->response_code = respid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5301,20 +5301,30 @@ static void change_t38_state(struct sip_pvt *p, int state)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Given the state requested and old state determine what control frame we want to queue up */
|
/* Given the state requested and old state determine what control frame we want to queue up */
|
||||||
if (state == T38_PEER_REINVITE) {
|
switch (state) {
|
||||||
|
case T38_PEER_REINVITE:
|
||||||
parameters = p->t38.their_parms;
|
parameters = p->t38.their_parms;
|
||||||
parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
|
parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
|
||||||
parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
|
parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
|
||||||
ast_udptl_set_tag(p->udptl, "SIP/%s", p->username);
|
ast_udptl_set_tag(p->udptl, "SIP/%s", p->username);
|
||||||
} else if (state == T38_ENABLED) {
|
break;
|
||||||
|
case T38_ENABLED:
|
||||||
parameters = p->t38.their_parms;
|
parameters = p->t38.their_parms;
|
||||||
parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
|
parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
|
||||||
parameters.request_response = AST_T38_NEGOTIATED;
|
parameters.request_response = AST_T38_NEGOTIATED;
|
||||||
ast_udptl_set_tag(p->udptl, "SIP/%s", p->username);
|
ast_udptl_set_tag(p->udptl, "SIP/%s", p->username);
|
||||||
} else if (state == T38_DISABLED && old == T38_ENABLED)
|
break;
|
||||||
parameters.request_response = AST_T38_TERMINATED;
|
case T38_DISABLED:
|
||||||
else if (state == T38_DISABLED && old == T38_LOCAL_REINVITE)
|
if (old == T38_ENABLED) {
|
||||||
parameters.request_response = AST_T38_REFUSED;
|
parameters.request_response = AST_T38_TERMINATED;
|
||||||
|
} else if (old == T38_LOCAL_REINVITE) {
|
||||||
|
parameters.request_response = AST_T38_REFUSED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case T38_LOCAL_REINVITE:
|
||||||
|
/* wait until we get a peer response before responding to local reinvite */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Woot we got a message, create a control frame and send it on! */
|
/* Woot we got a message, create a control frame and send it on! */
|
||||||
if (parameters.request_response)
|
if (parameters.request_response)
|
||||||
@@ -6745,10 +6755,21 @@ static int sip_transfer(struct ast_channel *ast, const char *dest)
|
|||||||
/*! \brief Helper function which updates T.38 capability information and triggers a reinvite */
|
/*! \brief Helper function which updates T.38 capability information and triggers a reinvite */
|
||||||
static void interpret_t38_parameters(struct sip_pvt *p, const struct ast_control_t38_parameters *parameters)
|
static void interpret_t38_parameters(struct sip_pvt *p, const struct ast_control_t38_parameters *parameters)
|
||||||
{
|
{
|
||||||
|
if (!ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (parameters->request_response) {
|
switch (parameters->request_response) {
|
||||||
case AST_T38_NEGOTIATED:
|
case AST_T38_NEGOTIATED:
|
||||||
case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */
|
case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */
|
||||||
if (p->t38.state == T38_PEER_REINVITE) {
|
/* Negotiation can not take place without a valid max_ifp value. */
|
||||||
|
if (!parameters->max_ifp) {
|
||||||
|
change_t38_state(p, T38_DISABLED);
|
||||||
|
if (p->t38.state == T38_PEER_REINVITE) {
|
||||||
|
AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
|
||||||
|
transmit_response_reliable(p, "488 Not acceptable here", &p->initreq);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (p->t38.state == T38_PEER_REINVITE) {
|
||||||
AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
|
AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
|
||||||
p->t38.our_parms = *parameters;
|
p->t38.our_parms = *parameters;
|
||||||
/* modify our parameters to conform to the peer's parameters,
|
/* modify our parameters to conform to the peer's parameters,
|
||||||
@@ -6768,7 +6789,7 @@ static void interpret_t38_parameters(struct sip_pvt *p, const struct ast_control
|
|||||||
ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp);
|
ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp);
|
||||||
change_t38_state(p, T38_ENABLED);
|
change_t38_state(p, T38_ENABLED);
|
||||||
transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
|
transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
|
||||||
} else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->t38.state != T38_ENABLED) {
|
} else if (p->t38.state != T38_ENABLED) {
|
||||||
p->t38.our_parms = *parameters;
|
p->t38.our_parms = *parameters;
|
||||||
ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp);
|
ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp);
|
||||||
change_t38_state(p, T38_LOCAL_REINVITE);
|
change_t38_state(p, T38_LOCAL_REINVITE);
|
||||||
@@ -8318,10 +8339,10 @@ static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_ty
|
|||||||
}
|
}
|
||||||
/* We only want the m and c lines for audio */
|
/* We only want the m and c lines for audio */
|
||||||
for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) {
|
for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) {
|
||||||
if ((media == SDP_AUDIO && ((sscanf(m, "audio %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
if ((media == SDP_AUDIO && ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
||||||
(sscanf(m, "audio %30d RTP/AVP %n", &x, &len) == 1 && len > 0))) ||
|
(sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0))) ||
|
||||||
(media == SDP_VIDEO && ((sscanf(m, "video %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
(media == SDP_VIDEO && ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
||||||
(sscanf(m, "video %30d RTP/AVP %n", &x, &len) == 1 && len > 0)))) {
|
(sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len > 0)))) {
|
||||||
/* See if there's a c= line for this media stream.
|
/* See if there's a c= line for this media stream.
|
||||||
* XXX There is no guarantee that we'll be grabbing the c= line for this
|
* XXX There is no guarantee that we'll be grabbing the c= line for this
|
||||||
* particular media stream here. However, this is the same logic used in process_sdp.
|
* particular media stream here. However, this is the same logic used in process_sdp.
|
||||||
@@ -8509,8 +8530,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
|
|||||||
nextm = get_sdp_iterate(&next, req, "m");
|
nextm = get_sdp_iterate(&next, req, "m");
|
||||||
|
|
||||||
/* Search for audio media definition */
|
/* Search for audio media definition */
|
||||||
if ((sscanf(m, "audio %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
if ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
||||||
(sscanf(m, "audio %30d RTP/AVP %n", &x, &len) == 1 && len > 0)) {
|
(sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) {
|
||||||
audio = TRUE;
|
audio = TRUE;
|
||||||
p->offered_media[SDP_AUDIO].offered = TRUE;
|
p->offered_media[SDP_AUDIO].offered = TRUE;
|
||||||
numberofmediastreams++;
|
numberofmediastreams++;
|
||||||
@@ -8520,7 +8541,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
|
|||||||
codecs = m + len;
|
codecs = m + len;
|
||||||
ast_copy_string(p->offered_media[SDP_AUDIO].codecs, codecs, sizeof(p->offered_media[SDP_AUDIO].codecs));
|
ast_copy_string(p->offered_media[SDP_AUDIO].codecs, codecs, sizeof(p->offered_media[SDP_AUDIO].codecs));
|
||||||
for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
|
for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
|
||||||
if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
|
if (sscanf(codecs, "%30u%n", &codec, &len) != 1) {
|
||||||
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
|
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -8530,8 +8551,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
|
|||||||
ast_rtp_codecs_payloads_set_m_type(&newaudiortp, NULL, codec);
|
ast_rtp_codecs_payloads_set_m_type(&newaudiortp, NULL, codec);
|
||||||
}
|
}
|
||||||
/* Search for video media definition */
|
/* Search for video media definition */
|
||||||
} else if ((sscanf(m, "video %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
} else if ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
||||||
(sscanf(m, "video %30d RTP/AVP %n", &x, &len) == 1 && len >= 0)) {
|
(sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len >= 0)) {
|
||||||
video = TRUE;
|
video = TRUE;
|
||||||
p->novideo = FALSE;
|
p->novideo = FALSE;
|
||||||
p->offered_media[SDP_VIDEO].offered = TRUE;
|
p->offered_media[SDP_VIDEO].offered = TRUE;
|
||||||
@@ -8542,7 +8563,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
|
|||||||
codecs = m + len;
|
codecs = m + len;
|
||||||
ast_copy_string(p->offered_media[SDP_VIDEO].codecs, codecs, sizeof(p->offered_media[SDP_VIDEO].codecs));
|
ast_copy_string(p->offered_media[SDP_VIDEO].codecs, codecs, sizeof(p->offered_media[SDP_VIDEO].codecs));
|
||||||
for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
|
for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
|
||||||
if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
|
if (sscanf(codecs, "%30u%n", &codec, &len) != 1) {
|
||||||
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
|
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -8551,8 +8572,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
|
|||||||
ast_rtp_codecs_payloads_set_m_type(&newvideortp, NULL, codec);
|
ast_rtp_codecs_payloads_set_m_type(&newvideortp, NULL, codec);
|
||||||
}
|
}
|
||||||
/* Search for text media definition */
|
/* Search for text media definition */
|
||||||
} else if ((sscanf(m, "text %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
} else if ((sscanf(m, "text %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
||||||
(sscanf(m, "text %30d RTP/AVP %n", &x, &len) == 1 && len > 0)) {
|
(sscanf(m, "text %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) {
|
||||||
text = TRUE;
|
text = TRUE;
|
||||||
p->notext = FALSE;
|
p->notext = FALSE;
|
||||||
p->offered_media[SDP_TEXT].offered = TRUE;
|
p->offered_media[SDP_TEXT].offered = TRUE;
|
||||||
@@ -8563,7 +8584,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
|
|||||||
codecs = m + len;
|
codecs = m + len;
|
||||||
ast_copy_string(p->offered_media[SDP_TEXT].codecs, codecs, sizeof(p->offered_media[SDP_TEXT].codecs));
|
ast_copy_string(p->offered_media[SDP_TEXT].codecs, codecs, sizeof(p->offered_media[SDP_TEXT].codecs));
|
||||||
for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
|
for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
|
||||||
if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
|
if (sscanf(codecs, "%30u%n", &codec, &len) != 1) {
|
||||||
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
|
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -8572,8 +8593,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
|
|||||||
ast_rtp_codecs_payloads_set_m_type(&newtextrtp, NULL, codec);
|
ast_rtp_codecs_payloads_set_m_type(&newtextrtp, NULL, codec);
|
||||||
}
|
}
|
||||||
/* Search for image media definition */
|
/* Search for image media definition */
|
||||||
} else if (p->udptl && ((sscanf(m, "image %30d udptl t38%n", &x, &len) == 1 && len > 0) ||
|
} else if (p->udptl && ((sscanf(m, "image %30u udptl t38%n", &x, &len) == 1 && len > 0) ||
|
||||||
(sscanf(m, "image %30d UDPTL t38%n", &x, &len) == 1 && len > 0) )) {
|
(sscanf(m, "image %30u UDPTL t38%n", &x, &len) == 1 && len > 0) )) {
|
||||||
image = TRUE;
|
image = TRUE;
|
||||||
if (debug)
|
if (debug)
|
||||||
ast_verbose("Got T.38 offer in SDP in dialog %s\n", p->callid);
|
ast_verbose("Got T.38 offer in SDP in dialog %s\n", p->callid);
|
||||||
@@ -8819,6 +8840,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
|
|||||||
if (debug)
|
if (debug)
|
||||||
ast_debug(1,"Peer T.38 UDPTL is at port %s:%d\n", ast_inet_ntoa(isin.sin_addr), ntohs(isin.sin_port));
|
ast_debug(1,"Peer T.38 UDPTL is at port %s:%d\n", ast_inet_ntoa(isin.sin_addr), ntohs(isin.sin_port));
|
||||||
|
|
||||||
|
/* verify the far max ifp can be calculated. this requires far max datagram to be set. */
|
||||||
|
if (!ast_udptl_get_far_max_datagram(p->udptl)) {
|
||||||
|
/* setting to zero will force a default if none was provided by the SDP */
|
||||||
|
ast_udptl_set_far_max_datagram(p->udptl, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Remote party offers T38, we need to update state */
|
/* Remote party offers T38, we need to update state */
|
||||||
if ((t38action == SDP_T38_ACCEPT) &&
|
if ((t38action == SDP_T38_ACCEPT) &&
|
||||||
(p->t38.state == T38_LOCAL_REINVITE)) {
|
(p->t38.state == T38_LOCAL_REINVITE)) {
|
||||||
@@ -9201,12 +9228,12 @@ static int process_sdp_a_image(const char *a, struct sip_pvt *p)
|
|||||||
{
|
{
|
||||||
int found = FALSE;
|
int found = FALSE;
|
||||||
char s[256];
|
char s[256];
|
||||||
int x;
|
unsigned int x;
|
||||||
|
|
||||||
if ((sscanf(a, "T38FaxMaxBuffer:%30d", &x) == 1)) {
|
if ((sscanf(a, "T38FaxMaxBuffer:%30u", &x) == 1)) {
|
||||||
ast_debug(3, "MaxBufferSize:%d\n", x);
|
ast_debug(3, "MaxBufferSize:%d\n", x);
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
} else if ((sscanf(a, "T38MaxBitRate:%30d", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%30d", &x) == 1)) {
|
} else if ((sscanf(a, "T38MaxBitRate:%30u", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%30u", &x) == 1)) {
|
||||||
ast_debug(3, "T38MaxBitRate: %d\n", x);
|
ast_debug(3, "T38MaxBitRate: %d\n", x);
|
||||||
switch (x) {
|
switch (x) {
|
||||||
case 14400:
|
case 14400:
|
||||||
@@ -9229,21 +9256,21 @@ static int process_sdp_a_image(const char *a, struct sip_pvt *p)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
} else if ((sscanf(a, "T38FaxVersion:%30d", &x) == 1)) {
|
} else if ((sscanf(a, "T38FaxVersion:%30u", &x) == 1)) {
|
||||||
ast_debug(3, "FaxVersion: %d\n", x);
|
ast_debug(3, "FaxVersion: %u\n", x);
|
||||||
p->t38.their_parms.version = x;
|
p->t38.their_parms.version = x;
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
} else if ((sscanf(a, "T38FaxMaxDatagram:%30d", &x) == 1) || (sscanf(a, "T38MaxDatagram:%30d", &x) == 1)) {
|
} else if ((sscanf(a, "T38FaxMaxDatagram:%30u", &x) == 1) || (sscanf(a, "T38MaxDatagram:%30u", &x) == 1)) {
|
||||||
/* override the supplied value if the configuration requests it */
|
/* override the supplied value if the configuration requests it */
|
||||||
if (p->t38_maxdatagram > x) {
|
if (p->t38_maxdatagram > x) {
|
||||||
ast_debug(1, "Overriding T38FaxMaxDatagram '%d' with '%d'\n", x, p->t38_maxdatagram);
|
ast_debug(1, "Overriding T38FaxMaxDatagram '%d' with '%d'\n", x, p->t38_maxdatagram);
|
||||||
x = p->t38_maxdatagram;
|
x = p->t38_maxdatagram;
|
||||||
}
|
}
|
||||||
ast_debug(3, "FaxMaxDatagram: %d\n", x);
|
ast_debug(3, "FaxMaxDatagram: %u\n", x);
|
||||||
ast_udptl_set_far_max_datagram(p->udptl, x);
|
ast_udptl_set_far_max_datagram(p->udptl, x);
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
} else if ((strncmp(a, "T38FaxFillBitRemoval", 20) == 0)) {
|
} else if ((strncmp(a, "T38FaxFillBitRemoval", 20) == 0)) {
|
||||||
if (sscanf(a, "T38FaxFillBitRemoval:%30d", &x) == 1) {
|
if (sscanf(a, "T38FaxFillBitRemoval:%30u", &x) == 1) {
|
||||||
ast_debug(3, "FillBitRemoval: %d\n", x);
|
ast_debug(3, "FillBitRemoval: %d\n", x);
|
||||||
if (x == 1) {
|
if (x == 1) {
|
||||||
p->t38.their_parms.fill_bit_removal = TRUE;
|
p->t38.their_parms.fill_bit_removal = TRUE;
|
||||||
@@ -9254,7 +9281,7 @@ static int process_sdp_a_image(const char *a, struct sip_pvt *p)
|
|||||||
}
|
}
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
} else if ((strncmp(a, "T38FaxTranscodingMMR", 20) == 0)) {
|
} else if ((strncmp(a, "T38FaxTranscodingMMR", 20) == 0)) {
|
||||||
if (sscanf(a, "T38FaxTranscodingMMR:%30d", &x) == 1) {
|
if (sscanf(a, "T38FaxTranscodingMMR:%30u", &x) == 1) {
|
||||||
ast_debug(3, "Transcoding MMR: %d\n", x);
|
ast_debug(3, "Transcoding MMR: %d\n", x);
|
||||||
if (x == 1) {
|
if (x == 1) {
|
||||||
p->t38.their_parms.transcoding_mmr = TRUE;
|
p->t38.their_parms.transcoding_mmr = TRUE;
|
||||||
@@ -9265,7 +9292,7 @@ static int process_sdp_a_image(const char *a, struct sip_pvt *p)
|
|||||||
}
|
}
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
} else if ((strncmp(a, "T38FaxTranscodingJBIG", 21) == 0)) {
|
} else if ((strncmp(a, "T38FaxTranscodingJBIG", 21) == 0)) {
|
||||||
if (sscanf(a, "T38FaxTranscodingJBIG:%30d", &x) == 1) {
|
if (sscanf(a, "T38FaxTranscodingJBIG:%30u", &x) == 1) {
|
||||||
ast_debug(3, "Transcoding JBIG: %d\n", x);
|
ast_debug(3, "Transcoding JBIG: %d\n", x);
|
||||||
if (x == 1) {
|
if (x == 1) {
|
||||||
p->t38.their_parms.transcoding_jbig = TRUE;
|
p->t38.their_parms.transcoding_jbig = TRUE;
|
||||||
@@ -10770,7 +10797,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
|
|||||||
ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:localTCF\r\n");
|
ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:localTCF\r\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", ast_udptl_get_local_max_datagram(p->udptl));
|
ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%u\r\n", ast_udptl_get_local_max_datagram(p->udptl));
|
||||||
switch (ast_udptl_get_error_correction_scheme(p->udptl)) {
|
switch (ast_udptl_get_error_correction_scheme(p->udptl)) {
|
||||||
case UDPTL_ERROR_CORRECTION_NONE:
|
case UDPTL_ERROR_CORRECTION_NONE:
|
||||||
break;
|
break;
|
||||||
@@ -24447,7 +24474,7 @@ static int handle_t38_options(struct ast_flags *flags, struct ast_flags *mask, s
|
|||||||
ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
|
ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
|
||||||
ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
|
ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
|
||||||
} else if (!strncasecmp(word, "maxdatagram=", 12)) {
|
} else if (!strncasecmp(word, "maxdatagram=", 12)) {
|
||||||
if (sscanf(&word[12], "%30d", maxdatagram) != 1) {
|
if (sscanf(&word[12], "%30u", maxdatagram) != 1) {
|
||||||
ast_log(LOG_WARNING, "Invalid maxdatagram '%s' at line %d of %s\n", v->value, v->lineno, config);
|
ast_log(LOG_WARNING, "Invalid maxdatagram '%s' at line %d of %s\n", v->value, v->lineno, config);
|
||||||
*maxdatagram = global_t38_maxdatagram;
|
*maxdatagram = global_t38_maxdatagram;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,12 +108,28 @@ void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38
|
|||||||
|
|
||||||
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp);
|
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief retrieves local_max_datagram.
|
||||||
|
*
|
||||||
|
* \retval positive value representing max datagram size.
|
||||||
|
* \retval 0 if no value is present
|
||||||
|
*/
|
||||||
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl);
|
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief 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_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram);
|
void ast_udptl_set_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram);
|
||||||
|
|
||||||
unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl);
|
unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief retrieves far max ifp
|
||||||
|
*
|
||||||
|
* \retval positive value representing max ifp size
|
||||||
|
* \retval 0 if no value is present
|
||||||
|
*/
|
||||||
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl);
|
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl);
|
||||||
|
|
||||||
void ast_udptl_setnat(struct ast_udptl *udptl, int nat);
|
void ast_udptl_setnat(struct ast_udptl *udptl, int nat);
|
||||||
|
|||||||
36
main/udptl.c
36
main/udptl.c
@@ -91,6 +91,8 @@ static int udptlfecspan;
|
|||||||
static int use_even_ports;
|
static int use_even_ports;
|
||||||
|
|
||||||
#define LOCAL_FAX_MAX_DATAGRAM 1400
|
#define LOCAL_FAX_MAX_DATAGRAM 1400
|
||||||
|
#define DEFAULT_FAX_MAX_DATAGRAM 400
|
||||||
|
#define FAX_MAX_DATAGRAM_LIMIT 1400
|
||||||
#define MAX_FEC_ENTRIES 5
|
#define MAX_FEC_ENTRIES 5
|
||||||
#define MAX_FEC_SPAN 5
|
#define MAX_FEC_SPAN 5
|
||||||
|
|
||||||
@@ -861,9 +863,13 @@ void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38
|
|||||||
|
|
||||||
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
|
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
|
||||||
{
|
{
|
||||||
udptl->local_max_ifp = max_ifp;
|
/* make sure max_ifp is a positive value since a cast will take place when
|
||||||
/* reset calculated values so they'll be computed again */
|
* when setting local_max_ifp */
|
||||||
udptl->local_max_datagram = -1;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
|
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
|
||||||
@@ -871,18 +877,30 @@ unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
|
|||||||
if (udptl->local_max_datagram == -1) {
|
if (udptl->local_max_datagram == -1) {
|
||||||
calculate_local_max_datagram(udptl);
|
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;
|
return udptl->local_max_datagram;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_udptl_set_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram)
|
void ast_udptl_set_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram)
|
||||||
{
|
{
|
||||||
udptl->far_max_datagram = max_datagram;
|
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 */
|
/* reset calculated values so they'll be computed again */
|
||||||
udptl->far_max_ifp = -1;
|
udptl->far_max_ifp = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl)
|
unsigned int ast_udptl_get_far_max_datagram(const struct ast_udptl *udptl)
|
||||||
{
|
{
|
||||||
|
if (udptl->far_max_datagram < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return udptl->far_max_datagram;
|
return udptl->far_max_datagram;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -891,6 +909,10 @@ unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
|
|||||||
if (udptl->far_max_ifp == -1) {
|
if (udptl->far_max_ifp == -1) {
|
||||||
calculate_far_max_ifp(udptl);
|
calculate_far_max_ifp(udptl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (udptl->far_max_ifp < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return udptl->far_max_ifp;
|
return udptl->far_max_ifp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1040,7 +1062,11 @@ int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
|
|||||||
unsigned int seq;
|
unsigned int seq;
|
||||||
unsigned int len = f->datalen;
|
unsigned int len = f->datalen;
|
||||||
int res;
|
int res;
|
||||||
uint8_t buf[s->far_max_datagram];
|
/* 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 we have no peer, return immediately */
|
||||||
if (s->them.sin_addr.s_addr == INADDR_ANY)
|
if (s->them.sin_addr.s_addr == INADDR_ANY)
|
||||||
|
|||||||
Reference in New Issue
Block a user