Merge pull request #756 from micmac1/ast-18.11.2

asterisk: bump to 18.11.2
This commit is contained in:
Jiri Slachta 2022-04-16 19:20:54 +02:00 committed by GitHub
commit 1518d145c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 2036 additions and 267 deletions

View file

@ -0,0 +1,653 @@
From 0ed41eb5fd0e4192e1b7dc374f819d17aef3e805 Mon Sep 17 00:00:00 2001
From: George Joseph <gtjoseph@users.noreply.github.com>
Date: Tue, 21 Dec 2021 19:32:22 -0700
Subject: [PATCH] sip_inv: Additional multipart support (#2919) (#2920)
---
pjsip/include/pjsip-ua/sip_inv.h | 108 ++++++++++-
pjsip/src/pjsip-ua/sip_inv.c | 240 ++++++++++++++++++++-----
pjsip/src/test/inv_offer_answer_test.c | 103 ++++++++++-
3 files changed, 394 insertions(+), 57 deletions(-)
--- a/pjsip/include/pjsip-ua/sip_inv.h
+++ b/pjsip/include/pjsip-ua/sip_inv.h
@@ -451,11 +451,11 @@ struct pjsip_inv_session
/**
- * This structure represents SDP information in a pjsip_rx_data. Application
- * retrieve this information by calling #pjsip_rdata_get_sdp_info(). This
+ * This structure represents SDP information in a pjsip_(rx|tx)_data. Application
+ * retrieve this information by calling #pjsip_get_sdp_info(). This
* mechanism supports multipart message body.
*/
-typedef struct pjsip_rdata_sdp_info
+typedef struct pjsip_sdp_info
{
/**
* Pointer and length of the text body in the incoming message. If
@@ -475,7 +475,15 @@ typedef struct pjsip_rdata_sdp_info
*/
pjmedia_sdp_session *sdp;
-} pjsip_rdata_sdp_info;
+} pjsip_sdp_info;
+
+/**
+ * For backwards compatibility and completeness,
+ * pjsip_rdata_sdp_info and pjsip_tdata_sdp_info
+ * are typedef'd to pjsip_sdp_info.
+ */
+typedef pjsip_sdp_info pjsip_rdata_sdp_info;
+typedef pjsip_sdp_info pjsip_tdata_sdp_info;
/**
@@ -1046,6 +1054,44 @@ PJ_DECL(pj_status_t) pjsip_create_sdp_bo
pjsip_msg_body **p_body);
/**
+ * This is a utility function to create a multipart body with the
+ * SIP body as the first part.
+ *
+ * @param pool Pool to allocate memory.
+ * @param sdp SDP session to be put in the SIP message body.
+ * @param p_body Pointer to receive SIP message body containing
+ * the SDP session.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_create_multipart_sdp_body( pj_pool_t *pool,
+ pjmedia_sdp_session *sdp,
+ pjsip_msg_body **p_body);
+
+/**
+ * Retrieve SDP information from a message body. Application should
+ * prefer to use this function rather than parsing the SDP manually since
+ * this function supports multipart message body.
+ *
+ * This function will only parse the SDP once, the first time it is called
+ * on the same message. Subsequent call on the same message will just pick
+ * up the already parsed SDP from the message.
+ *
+ * @param pool Pool to allocate memory.
+ * @param body The message body.
+ * @param msg_media_type From the rdata or tdata Content-Type header, if available.
+ * If NULL, the content_type from the body will be used.
+ * @param search_media_type The media type to search for.
+ * If NULL, "application/sdp" will be used.
+ *
+ * @return The SDP info.
+ */
+PJ_DECL(pjsip_sdp_info*) pjsip_get_sdp_info(pj_pool_t *pool,
+ pjsip_msg_body *body,
+ pjsip_media_type *msg_media_type,
+ const pjsip_media_type *search_media_type);
+
+/**
* Retrieve SDP information from an incoming message. Application should
* prefer to use this function rather than parsing the SDP manually since
* this function supports multipart message body.
@@ -1061,6 +1107,60 @@ PJ_DECL(pj_status_t) pjsip_create_sdp_bo
PJ_DECL(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata);
+/**
+ * Retrieve SDP information from an incoming message. Application should
+ * prefer to use this function rather than parsing the SDP manually since
+ * this function supports multipart message body.
+ *
+ * This function will only parse the SDP once, the first time it is called
+ * on the same message. Subsequent call on the same message will just pick
+ * up the already parsed SDP from the message.
+ *
+ * @param rdata The incoming message.
+ * @param search_media_type The SDP media type to search for.
+ * If NULL, "application/sdp" will be used.
+ *
+ * @return The SDP info.
+ */
+PJ_DECL(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info2(
+ pjsip_rx_data *rdata,
+ const pjsip_media_type *search_media_type);
+
+/**
+ * Retrieve SDP information from an outgoing message. Application should
+ * prefer to use this function rather than parsing the SDP manually since
+ * this function supports multipart message body.
+ *
+ * This function will only parse the SDP once, the first time it is called
+ * on the same message. Subsequent call on the same message will just pick
+ * up the already parsed SDP from the message.
+ *
+ * @param tdata The outgoing message.
+ *
+ * @return The SDP info.
+ */
+PJ_DECL(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info(pjsip_tx_data *tdata);
+
+/**
+ * Retrieve SDP information from an outgoing message. Application should
+ * prefer to use this function rather than parsing the SDP manually since
+ * this function supports multipart message body.
+ *
+ * This function will only parse the SDP once, the first time it is called
+ * on the same message. Subsequent call on the same message will just pick
+ * up the already parsed SDP from the message.
+ *
+ * @param tdata The outgoing message.
+ * @param search_media_type The SDP media type to search for.
+ * If NULL, "application/sdp" will be used.
+ *
+ * @return The SDP info.
+ */
+PJ_DECL(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info2(
+ pjsip_tx_data *tdata,
+ const pjsip_media_type *search_media_type);
+
+
PJ_END_DECL
/**
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -118,6 +118,8 @@ static pj_status_t handle_timer_response
static pj_bool_t inv_check_secure_dlg(pjsip_inv_session *inv,
pjsip_event *e);
+static int print_sdp(pjsip_msg_body *body, char *buf, pj_size_t len);
+
static void (*inv_state_handler[])( pjsip_inv_session *inv, pjsip_event *e) =
{
&inv_on_state_null,
@@ -956,66 +958,170 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uac
return PJ_SUCCESS;
}
-PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata)
-{
- pjsip_rdata_sdp_info *sdp_info;
- pjsip_msg_body *body = rdata->msg_info.msg->body;
- pjsip_ctype_hdr *ctype_hdr = rdata->msg_info.ctype;
- pjsip_media_type app_sdp;
+PJ_DEF(pjsip_sdp_info*) pjsip_get_sdp_info(pj_pool_t *pool,
+ pjsip_msg_body *body,
+ pjsip_media_type *msg_media_type,
+ const pjsip_media_type *search_media_type)
+{
+ pjsip_sdp_info *sdp_info;
+ pjsip_media_type search_type;
+ pjsip_media_type multipart_mixed;
+ pjsip_media_type multipart_alternative;
+ pjsip_media_type *msg_type;
+ pj_status_t status;
- sdp_info = (pjsip_rdata_sdp_info*)
- rdata->endpt_info.mod_data[mod_inv.mod.id];
- if (sdp_info)
- return sdp_info;
+ sdp_info = PJ_POOL_ZALLOC_T(pool,
+ pjsip_sdp_info);
- sdp_info = PJ_POOL_ZALLOC_T(rdata->tp_info.pool,
- pjsip_rdata_sdp_info);
PJ_ASSERT_RETURN(mod_inv.mod.id >= 0, sdp_info);
- rdata->endpt_info.mod_data[mod_inv.mod.id] = sdp_info;
- pjsip_media_type_init2(&app_sdp, "application", "sdp");
+ if (!body) {
+ return sdp_info;
+ }
- if (body && ctype_hdr &&
- pj_stricmp(&ctype_hdr->media.type, &app_sdp.type)==0 &&
- pj_stricmp(&ctype_hdr->media.subtype, &app_sdp.subtype)==0)
+ if (msg_media_type) {
+ msg_type = msg_media_type;
+ } else {
+ if (body->content_type.type.slen == 0) {
+ return sdp_info;
+ }
+ msg_type = &body->content_type;
+ }
+
+ if (!search_media_type) {
+ pjsip_media_type_init2(&search_type, "application", "sdp");
+ } else {
+ pj_memcpy(&search_type, search_media_type, sizeof(search_type));
+ }
+
+ pjsip_media_type_init2(&multipart_mixed, "multipart", "mixed");
+ pjsip_media_type_init2(&multipart_alternative, "multipart", "alternative");
+
+ if (pjsip_media_type_cmp(msg_type, &search_type, PJ_FALSE) == 0)
{
- sdp_info->body.ptr = (char*)body->data;
- sdp_info->body.slen = body->len;
- } else if (body && ctype_hdr &&
- pj_stricmp2(&ctype_hdr->media.type, "multipart")==0 &&
- (pj_stricmp2(&ctype_hdr->media.subtype, "mixed")==0 ||
- pj_stricmp2(&ctype_hdr->media.subtype, "alternative")==0))
+ /*
+ * If the print_body function is print_sdp, we know that
+ * body->data is a pjmedia_sdp_session object and came from
+ * a tx_data. If not, it's the text representation of the
+ * sdp from an rx_data.
+ */
+ if (body->print_body == print_sdp) {
+ sdp_info->sdp = body->data;
+ } else {
+ sdp_info->body.ptr = (char*)body->data;
+ sdp_info->body.slen = body->len;
+ }
+ } else if (pjsip_media_type_cmp(&multipart_mixed, msg_type, PJ_FALSE) == 0 ||
+ pjsip_media_type_cmp(&multipart_alternative, msg_type, PJ_FALSE) == 0)
{
- pjsip_multipart_part *part;
+ pjsip_multipart_part *part;
+ part = pjsip_multipart_find_part(body, &search_type, NULL);
+ if (part) {
+ if (part->body->print_body == print_sdp) {
+ sdp_info->sdp = part->body->data;
+ } else {
+ sdp_info->body.ptr = (char*)part->body->data;
+ sdp_info->body.slen = part->body->len;
+ }
+ }
+ }
- part = pjsip_multipart_find_part(body, &app_sdp, NULL);
- if (part) {
- sdp_info->body.ptr = (char*)part->body->data;
- sdp_info->body.slen = part->body->len;
- }
+ /*
+ * If the body was already a pjmedia_sdp_session, we can just
+ * return it. If not and there wasn't a text representation
+ * of the sdp either, we can also just return.
+ */
+ if (sdp_info->sdp || !sdp_info->body.ptr) {
+ return sdp_info;
}
- if (sdp_info->body.ptr) {
- pj_status_t status;
- status = pjmedia_sdp_parse(rdata->tp_info.pool,
- sdp_info->body.ptr,
- sdp_info->body.slen,
- &sdp_info->sdp);
- if (status == PJ_SUCCESS)
- status = pjmedia_sdp_validate2(sdp_info->sdp, PJ_FALSE);
+ /*
+ * If the body was the text representation of teh SDP, we need
+ * to parse it to create a pjmedia_sdp_session object.
+ */
+ status = pjmedia_sdp_parse(pool,
+ sdp_info->body.ptr,
+ sdp_info->body.slen,
+ &sdp_info->sdp);
+ if (status == PJ_SUCCESS)
+ status = pjmedia_sdp_validate2(sdp_info->sdp, PJ_FALSE);
- if (status != PJ_SUCCESS) {
- sdp_info->sdp = NULL;
- PJ_PERROR(1,(THIS_FILE, status,
- "Error parsing/validating SDP body"));
- }
+ if (status != PJ_SUCCESS) {
+ sdp_info->sdp = NULL;
+ PJ_PERROR(1, (THIS_FILE, status,
+ "Error parsing/validating SDP body"));
+ }
+
+ sdp_info->sdp_err = status;
+
+ return sdp_info;
+}
+
+PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info2(
+ pjsip_rx_data *rdata,
+ const pjsip_media_type *search_media_type)
+{
+ pjsip_media_type *msg_media_type = NULL;
+ pjsip_rdata_sdp_info *sdp_info;
- sdp_info->sdp_err = status;
+ if (rdata->endpt_info.mod_data[mod_inv.mod.id]) {
+ return (pjsip_rdata_sdp_info *)rdata->endpt_info.mod_data[mod_inv.mod.id];
+ }
+
+ /*
+ * rdata should have a Content-Type header at this point but we'll
+ * make sure.
+ */
+ if (rdata->msg_info.ctype) {
+ msg_media_type = &rdata->msg_info.ctype->media;
}
+ sdp_info = pjsip_get_sdp_info(rdata->tp_info.pool,
+ rdata->msg_info.msg->body,
+ msg_media_type,
+ search_media_type);
+ rdata->endpt_info.mod_data[mod_inv.mod.id] = sdp_info;
return sdp_info;
}
+PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata)
+{
+ return pjsip_rdata_get_sdp_info2(rdata, NULL);
+}
+
+PJ_DEF(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info2(
+ pjsip_tx_data *tdata,
+ const pjsip_media_type *search_media_type)
+{
+ pjsip_ctype_hdr *ctype_hdr = NULL;
+ pjsip_media_type *msg_media_type = NULL;
+ pjsip_tdata_sdp_info *sdp_info;
+
+ if (tdata->mod_data[mod_inv.mod.id]) {
+ return (pjsip_tdata_sdp_info *)tdata->mod_data[mod_inv.mod.id];
+ }
+ /*
+ * tdata won't usually have a Content-Type header at this point
+ * but we'll check just the same,
+ */
+ ctype_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTENT_TYPE, NULL);
+ if (ctype_hdr) {
+ msg_media_type = &ctype_hdr->media;
+ }
+
+ sdp_info = pjsip_get_sdp_info(tdata->pool,
+ tdata->msg->body,
+ msg_media_type,
+ search_media_type);
+ tdata->mod_data[mod_inv.mod.id] = sdp_info;
+
+ return sdp_info;
+}
+
+PJ_DEF(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info(pjsip_tx_data *tdata)
+{
+ return pjsip_tdata_get_sdp_info2(tdata, NULL);
+}
/*
* Verify incoming INVITE request.
@@ -1740,13 +1846,55 @@ PJ_DEF(pj_status_t) pjsip_create_sdp_bod
return PJ_SUCCESS;
}
+static pjsip_multipart_part* create_sdp_part(pj_pool_t *pool, pjmedia_sdp_session *sdp)
+{
+ pjsip_multipart_part *sdp_part;
+ pjsip_media_type media_type;
+
+ pjsip_media_type_init2(&media_type, "application", "sdp");
+
+ sdp_part = pjsip_multipart_create_part(pool);
+ PJ_ASSERT_RETURN(sdp_part != NULL, NULL);
+
+ sdp_part->body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body);
+ PJ_ASSERT_RETURN(sdp_part->body != NULL, NULL);
+
+ pjsip_media_type_cp(pool, &sdp_part->body->content_type, &media_type);
+
+ sdp_part->body->data = sdp;
+ sdp_part->body->clone_data = clone_sdp;
+ sdp_part->body->print_body = print_sdp;
+
+ return sdp_part;
+}
+
+PJ_DEF(pj_status_t) pjsip_create_multipart_sdp_body(pj_pool_t *pool,
+ pjmedia_sdp_session *sdp,
+ pjsip_msg_body **p_body)
+{
+ pjsip_media_type media_type;
+ pjsip_msg_body *multipart;
+ pjsip_multipart_part *sdp_part;
+
+ pjsip_media_type_init2(&media_type, "multipart", "mixed");
+ multipart = pjsip_multipart_create(pool, &media_type, NULL);
+ PJ_ASSERT_RETURN(multipart != NULL, PJ_ENOMEM);
+
+ sdp_part = create_sdp_part(pool, sdp);
+ PJ_ASSERT_RETURN(sdp_part != NULL, PJ_ENOMEM);
+ pjsip_multipart_add_part(pool, multipart, sdp_part);
+ *p_body = multipart;
+
+ return PJ_SUCCESS;
+}
+
static pjsip_msg_body *create_sdp_body(pj_pool_t *pool,
const pjmedia_sdp_session *c_sdp)
{
pjsip_msg_body *body;
pj_status_t status;
- status = pjsip_create_sdp_body(pool,
+ status = pjsip_create_sdp_body(pool,
pjmedia_sdp_session_clone(pool, c_sdp),
&body);
@@ -2069,6 +2217,7 @@ static pj_status_t inv_check_sdp_in_inco
)
)
{
+ pjsip_sdp_info *tdata_sdp_info;
const pjmedia_sdp_session *reoffer_sdp = NULL;
PJ_LOG(4,(inv->obj_name, "Received %s response "
@@ -2077,14 +2226,15 @@ static pj_status_t inv_check_sdp_in_inco
(st_code/10==18? "early" : "final" )));
/* Retrieve original SDP offer from INVITE request */
- reoffer_sdp = (const pjmedia_sdp_session*)
- tsx->last_tx->msg->body->data;
+ tdata_sdp_info = pjsip_tdata_get_sdp_info(tsx->last_tx);
+ reoffer_sdp = tdata_sdp_info->sdp;
/* Feed the original offer to negotiator */
status = pjmedia_sdp_neg_modify_local_offer2(inv->pool_prov,
inv->neg,
inv->sdp_neg_flags,
reoffer_sdp);
+
if (status != PJ_SUCCESS) {
PJ_LOG(1,(inv->obj_name, "Error updating local offer for "
"forked 2xx/18x response (err=%d)", status));
--- a/pjsip/src/test/inv_offer_answer_test.c
+++ b/pjsip/src/test/inv_offer_answer_test.c
@@ -137,6 +137,7 @@ typedef struct inv_test_param_t
pj_bool_t need_established;
unsigned count;
oa_t oa[4];
+ pj_bool_t multipart_body;
} inv_test_param_t;
typedef struct inv_test_t
@@ -257,6 +258,17 @@ static void on_media_update(pjsip_inv_se
}
}
+ /* Special handling for standard offer/answer */
+ if (inv_test.param.count == 1 &&
+ inv_test.param.oa[0] == OFFERER_UAC &&
+ inv_test.param.need_established)
+ {
+ jobs[job_cnt].type = ESTABLISH_CALL;
+ jobs[job_cnt].who = PJSIP_ROLE_UAS;
+ job_cnt++;
+ TRACE_((THIS_FILE, " C+++"));
+ }
+
pj_assert(job_cnt <= PJ_ARRAY_SIZE(jobs));
}
}
@@ -333,6 +345,15 @@ static pj_bool_t on_rx_request(pjsip_rx_
NULL, &tdata);
pj_assert(status == PJ_SUCCESS);
+ /* Use multipart body, if configured */
+ if (sdp && inv_test.param.multipart_body) {
+ status = pjsip_create_multipart_sdp_body(
+ tdata->pool,
+ pjmedia_sdp_session_clone(tdata->pool, sdp),
+ &tdata->msg->body);
+ }
+ pj_assert(status == PJ_SUCCESS);
+
status = pjsip_inv_send_msg(inv_test.uas, tdata);
pj_assert(status == PJ_SUCCESS);
@@ -426,6 +447,7 @@ static int perform_test(inv_test_param_t
sdp = NULL;
status = pjsip_inv_create_uac(dlg, sdp, inv_test.param.inv_option, &inv_test.uac);
+ //inv_test.uac->create_multipart = param->multipart_body;
PJ_ASSERT_RETURN(status==PJ_SUCCESS, -20);
TRACE_((THIS_FILE, " Sending INVITE %s offer", (sdp ? "with" : "without")));
@@ -436,8 +458,17 @@ static int perform_test(inv_test_param_t
status = pjsip_inv_invite(inv_test.uac, &tdata);
PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30);
+ /* Use multipart body, if configured */
+ if (sdp && param->multipart_body) {
+ status = pjsip_create_multipart_sdp_body(
+ tdata->pool,
+ pjmedia_sdp_session_clone(tdata->pool, sdp),
+ &tdata->msg->body);
+ }
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, -40);
+
status = pjsip_inv_send_msg(inv_test.uac, tdata);
- PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, -50);
/*
* Wait until test completes
@@ -525,13 +556,14 @@ static inv_test_param_t test_params[] =
200/INVITE (answer) <--
ACK -->
*/
-#if 0
+#if 1
{
"Standard INVITE with offer",
0,
PJ_TRUE,
1,
- { OFFERER_UAC }
+ { OFFERER_UAC },
+ PJ_FALSE
},
{
@@ -539,7 +571,25 @@ static inv_test_param_t test_params[] =
PJSIP_INV_REQUIRE_100REL,
PJ_TRUE,
1,
- { OFFERER_UAC }
+ { OFFERER_UAC },
+ PJ_FALSE
+ },
+ {
+ "Standard INVITE with offer, with Multipart",
+ 0,
+ PJ_TRUE,
+ 1,
+ { OFFERER_UAC },
+ PJ_TRUE
+ },
+
+ {
+ "Standard INVITE with offer, with 100rel, with Multipart",
+ PJSIP_INV_REQUIRE_100REL,
+ PJ_TRUE,
+ 1,
+ { OFFERER_UAC },
+ PJ_TRUE
},
#endif
@@ -555,7 +605,8 @@ static inv_test_param_t test_params[] =
0,
PJ_TRUE,
1,
- { OFFERER_UAS }
+ { OFFERER_UAS },
+ PJ_FALSE
},
{
@@ -563,7 +614,25 @@ static inv_test_param_t test_params[] =
PJSIP_INV_REQUIRE_100REL,
PJ_TRUE,
1,
- { OFFERER_UAS }
+ { OFFERER_UAS },
+ PJ_FALSE
+ },
+ {
+ "INVITE with no offer, with Multipart",
+ 0,
+ PJ_TRUE,
+ 1,
+ { OFFERER_UAS },
+ PJ_TRUE
+ },
+
+ {
+ "INVITE with no offer, with 100rel, with Multipart",
+ PJSIP_INV_REQUIRE_100REL,
+ PJ_TRUE,
+ 1,
+ { OFFERER_UAS },
+ PJ_TRUE
},
#endif
@@ -584,14 +653,24 @@ static inv_test_param_t test_params[] =
0,
PJ_TRUE,
2,
- { OFFERER_UAC, OFFERER_UAC }
+ { OFFERER_UAC, OFFERER_UAC },
+ PJ_FALSE
+ },
+ {
+ "INVITE and UPDATE by UAC, with Multipart",
+ 0,
+ PJ_TRUE,
+ 2,
+ { OFFERER_UAC, OFFERER_UAC },
+ PJ_TRUE
},
{
"INVITE and UPDATE by UAC, with 100rel",
PJSIP_INV_REQUIRE_100REL,
PJ_TRUE,
2,
- { OFFERER_UAC, OFFERER_UAC }
+ { OFFERER_UAC, OFFERER_UAC },
+ PJ_FALSE
},
#endif
@@ -617,6 +696,14 @@ static inv_test_param_t test_params[] =
4,
{ OFFERER_UAC, OFFERER_UAS, OFFERER_UAC, OFFERER_UAS }
},
+ {
+ "INVITE and many UPDATE by UAC and UAS, with Multipart",
+ 0,
+ PJ_TRUE,
+ 4,
+ { OFFERER_UAC, OFFERER_UAS, OFFERER_UAC, OFFERER_UAS },
+ PJ_TRUE
+ },
};

View file

@ -0,0 +1,116 @@
From 3faf1d2b4da553bbaee04f9a13a5d084b381e5fb Mon Sep 17 00:00:00 2001
From: sauwming <ming@teluu.com>
Date: Tue, 4 Jan 2022 15:28:49 +0800
Subject: [PATCH] Fix incorrect unescaping of tokens during parsing (#2933)
---
pjsip/src/pjsip/sip_parser.c | 29 +++++++++++++++++++++++++----
pjsip/src/test/msg_test.c | 6 +++---
2 files changed, 28 insertions(+), 7 deletions(-)
--- a/pjsip/src/pjsip/sip_parser.c
+++ b/pjsip/src/pjsip/sip_parser.c
@@ -378,17 +378,23 @@ static pj_status_t init_parser()
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str( &pconst.pjsip_TOKEN_SPEC, TOKEN);
+ /* Token is allowed to have '%' so we do not need this. */
+ /*
status = pj_cis_dup(&pconst.pjsip_TOKEN_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_del_str(&pconst.pjsip_TOKEN_SPEC_ESC, "%");
+ */
status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC, &pconst.pjsip_TOKEN_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, "[:]");
+ /* Token is allowed to have '%' */
+ /*
status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC_ESC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC_ESC, "[:]");
+ */
status = pj_cis_dup(&pconst.pjsip_HOST_SPEC, &pconst.pjsip_ALNUM_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
@@ -1210,7 +1216,11 @@ static void parse_param_imp( pj_scanner
unsigned option)
{
/* pname */
- parser_get_and_unescape(scanner, pool, spec, esc_spec, pname);
+ if (!esc_spec) {
+ pj_scan_get(scanner, spec, pname);
+ } else {
+ parser_get_and_unescape(scanner, pool, spec, esc_spec, pname);
+ }
/* init pvalue */
pvalue->ptr = NULL;
@@ -1240,7 +1250,12 @@ static void parse_param_imp( pj_scanner
// pj_scan_get_until_ch(scanner, ']', pvalue);
// pj_scan_get_char(scanner);
} else if(pj_cis_match(spec, *scanner->curptr)) {
- parser_get_and_unescape(scanner, pool, spec, esc_spec, pvalue);
+ if (!esc_spec) {
+ pj_scan_get(scanner, spec, pvalue);
+ } else {
+ parser_get_and_unescape(scanner, pool, spec, esc_spec,
+ pvalue);
+ }
}
}
}
@@ -1252,7 +1267,10 @@ PJ_DEF(void) pjsip_parse_param_imp(pj_sc
unsigned option)
{
parse_param_imp(scanner, pool, pname, pvalue, &pconst.pjsip_TOKEN_SPEC,
- &pconst.pjsip_TOKEN_SPEC_ESC, option);
+ // Token does not need to be unescaped.
+ // Refer to PR #2933.
+ // &pconst.pjsip_TOKEN_SPEC_ESC,
+ NULL, option);
}
@@ -2168,7 +2186,10 @@ static void int_parse_via_param( pjsip_v
pj_scan_get_char(scanner);
parse_param_imp(scanner, pool, &pname, &pvalue,
&pconst.pjsip_VIA_PARAM_SPEC,
- &pconst.pjsip_VIA_PARAM_SPEC_ESC,
+ // Token does not need to be unescaped.
+ // Refer to PR #2933.
+ // &pconst.pjsip_VIA_PARAM_SPEC_ESC,
+ NULL,
0);
if (!parser_stricmp(pname, pconst.pjsip_BRANCH_STR) && pvalue.slen) {
--- a/pjsip/src/test/msg_test.c
+++ b/pjsip/src/test/msg_test.c
@@ -953,7 +953,7 @@ static int hdr_test_subject_utf(pjsip_hd
#define GENERIC_PARAM "p0=a;p1=\"ab:;cd\";p2=ab%3acd;p3"
-#define GENERIC_PARAM_PARSED "p0=a;p1=\"ab:;cd\";p2=ab:cd;p3"
+#define GENERIC_PARAM_PARSED "p0=a;p1=\"ab:;cd\";p2=ab%3acd;p3"
#define PARAM_CHAR "][/:&+$"
#define SIMPLE_ADDR_SPEC "sip:host"
#define ADDR_SPEC SIMPLE_ADDR_SPEC ";"PARAM_CHAR"="PARAM_CHAR ";p1=\";\""
@@ -1401,7 +1401,7 @@ static int generic_param_test(pjsip_para
param = param->next;
if (pj_strcmp2(&param->name, "p2"))
return -956;
- if (pj_strcmp2(&param->value, "ab:cd"))
+ if (pj_strcmp2(&param->value, "ab%3acd"))
return -957;
param = param->next;
@@ -1621,7 +1621,7 @@ static int hdr_test_content_type(pjsip_h
prm = prm->next;
if (prm == &hdr->media.param) return -1960;
if (pj_strcmp2(&prm->name, "p2")) return -1961;
- if (pj_strcmp2(&prm->value, "ab:cd")) return -1962;
+ if (pj_strcmp2(&prm->value, "ab%3acd")) return -1962;
prm = prm->next;
if (prm == &hdr->media.param) return -1970;

View file

@ -0,0 +1,169 @@
From 7e3dfd8a15fd0f98dbf0e04d2d7a5bded90ee401 Mon Sep 17 00:00:00 2001
From: George Joseph <gjoseph@sangoma.com>
Date: Tue, 11 Jan 2022 09:27:23 -0700
Subject: [PATCH] Create generic pjsip_hdr_find functions
pjsip_msg_find_hdr(), pjsip_msg_find_hdr_by_name(), and
pjsip_msg_find_hdr_by_names() require a pjsip_msg to be passed in
so if you need to search a header list that's not in a pjsip_msg,
you have to do it yourself. This commit adds generic versions of
those 3 functions that take in the actual header list head instead
of a pjsip_msg so if you need to search a list of headers in
something like a pjsip_multipart_part, you can do so easily.
---
pjsip/include/pjsip/sip_msg.h | 53 +++++++++++++++++++++++++++++++++++
pjsip/src/pjsip/sip_msg.c | 51 +++++++++++++++++++++++----------
2 files changed, 89 insertions(+), 15 deletions(-)
--- a/pjsip/include/pjsip/sip_msg.h
+++ b/pjsip/include/pjsip/sip_msg.h
@@ -363,6 +363,59 @@ PJ_DECL(void*) pjsip_hdr_shallow_clone(
PJ_DECL(int) pjsip_hdr_print_on( void *hdr, char *buf, pj_size_t len);
/**
+ * Find a header in a header list by the header type.
+ *
+ * @param hdr_list The "head" of the header list.
+ * @param type The header type to find.
+ * @param start The first header field where the search should begin.
+ * If NULL is specified, then the search will begin from the
+ * first header, otherwise the search will begin at the
+ * specified header.
+ *
+ * @return The header field, or NULL if no header with the specified
+ * type is found.
+ */
+PJ_DECL(void*) pjsip_hdr_find( const void *hdr_list,
+ pjsip_hdr_e type,
+ const void *start);
+
+/**
+ * Find a header in a header list by its name.
+ *
+ * @param hdr_list The "head" of the header list.
+ * @param name The header name to find.
+ * @param start The first header field where the search should begin.
+ * If NULL is specified, then the search will begin from the
+ * first header, otherwise the search will begin at the
+ * specified header.
+ *
+ * @return The header field, or NULL if no header with the specified
+ * type is found.
+ */
+PJ_DECL(void*) pjsip_hdr_find_by_name( const void *hdr_list,
+ const pj_str_t *name,
+ const void *start);
+
+/**
+ * Find a header in a header list by its name and short name version.
+ *
+ * @param hdr_list The "head" of the header list.
+ * @param name The header name to find.
+ * @param sname The short name version of the header name.
+ * @param start The first header field where the search should begin.
+ * If NULL is specified, then the search will begin from the
+ * first header, otherwise the search will begin at the
+ * specified header.
+ *
+ * @return The header field, or NULL if no header with the specified
+ * type is found.
+ */
+PJ_DECL(void*) pjsip_hdr_find_by_names( const void *hdr_list,
+ const pj_str_t *name,
+ const pj_str_t *sname,
+ const void *start);
+
+/**
* @}
*/
--- a/pjsip/src/pjsip/sip_msg.c
+++ b/pjsip/src/pjsip/sip_msg.c
@@ -334,13 +334,13 @@ PJ_DEF(pjsip_msg*) pjsip_msg_clone( pj_p
return dst;
}
-PJ_DEF(void*) pjsip_msg_find_hdr( const pjsip_msg *msg,
- pjsip_hdr_e hdr_type, const void *start)
+PJ_DEF(void*) pjsip_hdr_find( const void *hdr_list,
+ pjsip_hdr_e hdr_type, const void *start)
{
- const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=&msg->hdr;
+ const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=hdr_list;
if (hdr == NULL) {
- hdr = msg->hdr.next;
+ hdr = end->next;
}
for (; hdr!=end; hdr = hdr->next) {
if (hdr->type == hdr_type)
@@ -349,14 +349,14 @@ PJ_DEF(void*) pjsip_msg_find_hdr( const
return NULL;
}
-PJ_DEF(void*) pjsip_msg_find_hdr_by_name( const pjsip_msg *msg,
- const pj_str_t *name,
- const void *start)
+PJ_DEF(void*) pjsip_hdr_find_by_name( const void *hdr_list,
+ const pj_str_t *name,
+ const void *start)
{
- const pjsip_hdr *hdr=(const pjsip_hdr*)start, *end=&msg->hdr;
+ const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=hdr_list;
if (hdr == NULL) {
- hdr = msg->hdr.next;
+ hdr = end->next;
}
for (; hdr!=end; hdr = hdr->next) {
if (pj_stricmp(&hdr->name, name) == 0)
@@ -365,15 +365,15 @@ PJ_DEF(void*) pjsip_msg_find_hdr_by_nam
return NULL;
}
-PJ_DEF(void*) pjsip_msg_find_hdr_by_names( const pjsip_msg *msg,
- const pj_str_t *name,
- const pj_str_t *sname,
- const void *start)
+PJ_DEF(void*) pjsip_hdr_find_by_names( const void *hdr_list,
+ const pj_str_t *name,
+ const pj_str_t *sname,
+ const void *start)
{
- const pjsip_hdr *hdr=(const pjsip_hdr*)start, *end=&msg->hdr;
+ const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=hdr_list;
if (hdr == NULL) {
- hdr = msg->hdr.next;
+ hdr = end->next;
}
for (; hdr!=end; hdr = hdr->next) {
if (pj_stricmp(&hdr->name, name) == 0)
@@ -384,6 +384,27 @@ PJ_DEF(void*) pjsip_msg_find_hdr_by_nam
return NULL;
}
+PJ_DEF(void*) pjsip_msg_find_hdr( const pjsip_msg *msg,
+ pjsip_hdr_e hdr_type, const void *start)
+{
+ return pjsip_hdr_find(&msg->hdr, hdr_type, start);
+}
+
+PJ_DEF(void*) pjsip_msg_find_hdr_by_name( const pjsip_msg *msg,
+ const pj_str_t *name,
+ const void *start)
+{
+ return pjsip_hdr_find_by_name(&msg->hdr, name, start);
+}
+
+PJ_DEF(void*) pjsip_msg_find_hdr_by_names( const pjsip_msg *msg,
+ const pj_str_t *name,
+ const pj_str_t *sname,
+ const void *start)
+{
+ return pjsip_hdr_find_by_names(&msg->hdr, name, sname, start);
+}
+
PJ_DEF(void*) pjsip_msg_find_remove_hdr( pjsip_msg *msg,
pjsip_hdr_e hdr_type, void *start)
{

View file

@ -0,0 +1,635 @@
From b7ecff22e77887626fd8e8608c4dd73bc7b7366f Mon Sep 17 00:00:00 2001
From: George Joseph <gjoseph@sangoma.com>
Date: Tue, 18 Jan 2022 06:14:31 -0700
Subject: [PATCH] Additional multipart improvements
Added the following APIs:
pjsip_multipart_find_part_by_header()
pjsip_multipart_find_part_by_header_str()
pjsip_multipart_find_part_by_cid_str()
pjsip_multipart_find_part_by_cid_uri()
---
pjsip/include/pjsip/sip_multipart.h | 83 ++++++++++
pjsip/src/pjsip/sip_multipart.c | 223 +++++++++++++++++++++++++++
pjsip/src/test/multipart_test.c | 225 +++++++++++++++++++++++++++-
3 files changed, 530 insertions(+), 1 deletion(-)
--- a/pjsip/include/pjsip/sip_multipart.h
+++ b/pjsip/include/pjsip/sip_multipart.h
@@ -154,6 +154,89 @@ pjsip_multipart_find_part( const pjsip_m
const pjsip_multipart_part *start);
/**
+ * Find a body inside multipart bodies which has a header matching the
+ * supplied one. Most useful for finding a part with a specific Content-ID.
+ *
+ * @param pool Memory pool to use for temp space.
+ * @param mp The multipart body.
+ * @param search_hdr Header to search for.
+ * @param start If specified, the search will begin at
+ * start->next part. Otherwise it will begin at
+ * the first part in the multipart bodies.
+ *
+ * @return The first part which has a header matching the
+ * specified one, or NULL if not found.
+ */
+PJ_DECL(pjsip_multipart_part*)
+pjsip_multipart_find_part_by_header(pj_pool_t *pool,
+ const pjsip_msg_body *mp,
+ void *search_hdr,
+ const pjsip_multipart_part *start);
+
+/**
+ * Find a body inside multipart bodies which has a header matching the
+ * supplied name and value. Most useful for finding a part with a specific
+ * Content-ID.
+ *
+ * @param pool Memory pool to use for temp space.
+ * @param mp The multipart body.
+ * @param hdr_name Header name to search for.
+ * @param hdr_value Header value search for.
+ * @param start If specified, the search will begin at
+ * start->next part. Otherwise it will begin at
+ * the first part in the multipart bodies.
+ *
+ * @return The first part which has a header matching the
+ * specified one, or NULL if not found.
+ */
+PJ_DECL(pjsip_multipart_part*)
+pjsip_multipart_find_part_by_header_str(pj_pool_t *pool,
+ const pjsip_msg_body *mp,
+ const pj_str_t *hdr_name,
+ const pj_str_t *hdr_value,
+ const pjsip_multipart_part *start);
+
+
+
+/**
+ * Find a body inside multipart bodies which has a Content-ID value matching the
+ * supplied "cid" URI in pj_str form. The "cid:" scheme will be assumed if the
+ * URL doesn't start with it. Enclosing angle brackets will also be handled
+ * correctly if they exist.
+ *
+ * @see RFC2392 Content-ID and Message-ID Uniform Resource Locators
+ *
+ * @param pool Memory pool to use for temp space.
+ * @param mp The multipart body.
+ * @param cid The "cid" URI to search for in pj_str form.
+ *
+ * @return The first part which has a Content-ID header matching the
+ * specified "cid" URI. or NULL if not found.
+ */
+PJ_DECL(pjsip_multipart_part*)
+pjsip_multipart_find_part_by_cid_str(pj_pool_t *pool,
+ const pjsip_msg_body *mp,
+ pj_str_t *cid);
+
+/**
+ * Find a body inside multipart bodies which has a Content-ID value matching the
+ * supplied "cid" URI.
+ *
+ * @see RFC2392 Content-ID and Message-ID Uniform Resource Locators
+ *
+ * @param pool Memory pool to use for temp space.
+ * @param mp The multipart body.
+ * @param cid The "cid" URI to search for.
+ *
+ * @return The first part which had a Content-ID header matching the
+ * specified "cid" URI. or NULL if not found.
+ */
+PJ_DECL(pjsip_multipart_part*)
+pjsip_multipart_find_part_by_cid_uri(pj_pool_t *pool,
+ const pjsip_msg_body *mp,
+ pjsip_other_uri *cid_uri);
+
+/**
* Parse multipart message.
*
* @param pool Memory pool.
--- a/pjsip/src/pjsip/sip_multipart.c
+++ b/pjsip/src/pjsip/sip_multipart.c
@@ -19,6 +19,7 @@
#include <pjsip/sip_multipart.h>
#include <pjsip/sip_parser.h>
#include <pjlib-util/scanner.h>
+#include <pjlib-util/string.h>
#include <pj/assert.h>
#include <pj/ctype.h>
#include <pj/errno.h>
@@ -416,6 +417,220 @@ pjsip_multipart_find_part( const pjsip_m
return NULL;
}
+/*
+ * Find a body inside multipart bodies which has the header and value.
+ */
+PJ_DEF(pjsip_multipart_part*)
+pjsip_multipart_find_part_by_header_str(pj_pool_t *pool,
+ const pjsip_msg_body *mp,
+ const pj_str_t *hdr_name,
+ const pj_str_t *hdr_value,
+ const pjsip_multipart_part *start)
+{
+ struct multipart_data *m_data;
+ pjsip_multipart_part *part;
+ pjsip_hdr *found_hdr;
+ pj_str_t found_hdr_str;
+ pj_str_t found_hdr_value;
+ pj_size_t expected_hdr_slen;
+ pj_size_t buf_size;
+ int hdr_name_len;
+#define REASONABLE_PADDING 32
+#define SEPARATOR_LEN 2
+ /* Must specify mandatory params */
+ PJ_ASSERT_RETURN(mp && hdr_name && hdr_value, NULL);
+
+ /* mp must really point to an actual multipart msg body */
+ PJ_ASSERT_RETURN(mp->print_body==&multipart_print_body, NULL);
+
+ /*
+ * We'll need to "print" each header we find to test it but
+ * allocating a buffer of PJSIP_MAX_URL_SIZE is overkill.
+ * Instead, we'll allocate one large enough to hold the search
+ * header name, the ": " separator, the search hdr value, and
+ * the NULL terminator. If we can't print the found header
+ * into that buffer then it can't be a match.
+ *
+ * Some header print functions such as generic_int require enough
+ * space to print the maximum possible header length so we'll
+ * add a reasonable amount to the print buffer size.
+ */
+ expected_hdr_slen = hdr_name->slen + SEPARATOR_LEN + hdr_value->slen;
+ buf_size = expected_hdr_slen + REASONABLE_PADDING;
+ found_hdr_str.ptr = pj_pool_alloc(pool, buf_size);
+ found_hdr_str.slen = 0;
+ hdr_name_len = hdr_name->slen + SEPARATOR_LEN;
+
+ m_data = (struct multipart_data*)mp->data;
+
+ if (start)
+ part = start->next;
+ else
+ part = m_data->part_head.next;
+
+ while (part != &m_data->part_head) {
+ found_hdr = NULL;
+ while ((found_hdr = pjsip_hdr_find_by_name(&part->hdr, hdr_name,
+ (found_hdr ? found_hdr->next : NULL))) != NULL) {
+
+ found_hdr_str.slen = pjsip_hdr_print_on((void*) found_hdr, found_hdr_str.ptr, buf_size);
+ /*
+ * If the buffer was too small (slen = -1) or the result wasn't
+ * the same length as the search header, it can't be a match.
+ */
+ if (found_hdr_str.slen != expected_hdr_slen) {
+ continue;
+ }
+ /*
+ * Set the value overlay to start at the found header value...
+ */
+ found_hdr_value.ptr = found_hdr_str.ptr + hdr_name_len;
+ found_hdr_value.slen = found_hdr_str.slen - hdr_name_len;
+ /* ...and compare it to the supplied header value. */
+ if (pj_strcmp(hdr_value, &found_hdr_value) == 0) {
+ return part;
+ }
+ }
+ part = part->next;
+ }
+ return NULL;
+#undef SEPARATOR_LEN
+#undef REASONABLE_PADDING
+}
+
+PJ_DEF(pjsip_multipart_part*)
+pjsip_multipart_find_part_by_header(pj_pool_t *pool,
+ const pjsip_msg_body *mp,
+ void *search_for,
+ const pjsip_multipart_part *start)
+{
+ struct multipart_data *m_data;
+ pjsip_hdr *search_hdr = search_for;
+ pj_str_t search_buf;
+
+ /* Must specify mandatory params */
+ PJ_ASSERT_RETURN(mp && search_hdr, NULL);
+
+ /* mp must really point to an actual multipart msg body */
+ PJ_ASSERT_RETURN(mp->print_body==&multipart_print_body, NULL);
+
+ /*
+ * Unfortunately, there isn't enough information to determine
+ * the maximum printed size of search_hdr at this point so we
+ * have to allocate a reasonable max.
+ */
+ search_buf.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
+ search_buf.slen = pjsip_hdr_print_on(search_hdr, search_buf.ptr, PJSIP_MAX_URL_SIZE - 1);
+ if (search_buf.slen <= 0) {
+ return NULL;
+ }
+ /*
+ * Set the header value to start after the header name plus the ":", then
+ * strip leading and trailing whitespace.
+ */
+ search_buf.ptr += (search_hdr->name.slen + 1);
+ search_buf.slen -= (search_hdr->name.slen + 1);
+ pj_strtrim(&search_buf);
+
+ return pjsip_multipart_find_part_by_header_str(pool, mp, &search_hdr->name, &search_buf, start);
+}
+
+/*
+ * Convert a Content-ID URI to it's corresponding header value.
+ * RFC2392 says...
+ * A "cid" URL is converted to the corresponding Content-ID message
+ * header by removing the "cid:" prefix, converting the % encoded
+ * character(s) to their equivalent US-ASCII characters, and enclosing
+ * the remaining parts with an angle bracket pair, "<" and ">".
+ *
+ * This implementation will accept URIs with or without the "cid:"
+ * scheme and optional angle brackets.
+ */
+static pj_str_t cid_uri_to_hdr_value(pj_pool_t *pool, pj_str_t *cid_uri)
+{
+ pj_size_t cid_len = pj_strlen(cid_uri);
+ pj_size_t alloc_len = cid_len + 2 /* for the leading and trailing angle brackets */;
+ pj_str_t uri_overlay;
+ pj_str_t cid_hdr;
+ pj_str_t hdr_overlay;
+
+ pj_strassign(&uri_overlay, cid_uri);
+ /* If the URI is already enclosed in angle brackets, remove them. */
+ if (uri_overlay.ptr[0] == '<') {
+ uri_overlay.ptr++;
+ uri_overlay.slen -= 2;
+ }
+ /* If the URI starts with the "cid:" scheme, skip over it. */
+ if (pj_strncmp2(&uri_overlay, "cid:", 4) == 0) {
+ uri_overlay.ptr += 4;
+ uri_overlay.slen -= 4;
+ }
+ /* Start building */
+ cid_hdr.ptr = pj_pool_alloc(pool, alloc_len);
+ cid_hdr.ptr[0] = '<';
+ cid_hdr.slen = 1;
+ hdr_overlay.ptr = cid_hdr.ptr + 1;
+ hdr_overlay.slen = 0;
+ pj_strcpy_unescape(&hdr_overlay, &uri_overlay);
+ cid_hdr.slen += hdr_overlay.slen;
+ cid_hdr.ptr[cid_hdr.slen] = '>';
+ cid_hdr.slen++;
+
+ return cid_hdr;
+}
+
+PJ_DEF(pjsip_multipart_part*)
+pjsip_multipart_find_part_by_cid_str(pj_pool_t *pool,
+ const pjsip_msg_body *mp,
+ pj_str_t *cid)
+{
+ struct multipart_data *m_data;
+ pjsip_multipart_part *part;
+ pjsip_generic_string_hdr *found_hdr;
+ pj_str_t found_hdr_value;
+ static pj_str_t hdr_name = { "Content-ID", 10};
+ pj_str_t hdr_value;
+
+ PJ_ASSERT_RETURN(pool && mp && cid && (pj_strlen(cid) > 0), NULL);
+
+ hdr_value = cid_uri_to_hdr_value(pool, cid);
+ if (pj_strlen(&hdr_value) == 0) {
+ return NULL;
+ }
+
+ m_data = (struct multipart_data*)mp->data;
+ part = m_data->part_head.next;
+
+ while (part != &m_data->part_head) {
+ found_hdr = NULL;
+ while ((found_hdr = pjsip_hdr_find_by_name(&part->hdr, &hdr_name,
+ (found_hdr ? found_hdr->next : NULL))) != NULL) {
+ if (pj_strcmp(&hdr_value, &found_hdr->hvalue) == 0) {
+ return part;
+ }
+ }
+ part = part->next;
+ }
+ return NULL;
+}
+
+PJ_DEF(pjsip_multipart_part*)
+pjsip_multipart_find_part_by_cid_uri(pj_pool_t *pool,
+ const pjsip_msg_body *mp,
+ pjsip_other_uri *cid_uri)
+{
+ PJ_ASSERT_RETURN(pool && mp && cid_uri, NULL);
+
+ if (pj_strcmp2(&cid_uri->scheme, "cid") != 0) {
+ return NULL;
+ }
+ /*
+ * We only need to pass the URI content so we
+ * can do that directly.
+ */
+ return pjsip_multipart_find_part_by_cid_str(pool, mp, &cid_uri->content);
+}
+
/* Parse a multipart part. "pct" is parent content-type */
static pjsip_multipart_part *parse_multipart_part(pj_pool_t *pool,
char *start,
@@ -584,6 +799,7 @@ PJ_DEF(pjsip_msg_body*) pjsip_multipart_
(int)boundary.slen, boundary.ptr));
}
+
/* Build the delimiter:
* delimiter = "--" boundary
*/
@@ -630,6 +846,8 @@ PJ_DEF(pjsip_msg_body*) pjsip_multipart_
if (*curptr=='\r') ++curptr;
if (*curptr!='\n') {
/* Expecting a newline here */
+ PJ_LOG(2, (THIS_FILE, "Failed to find newline"));
+
return NULL;
}
++curptr;
@@ -645,6 +863,7 @@ PJ_DEF(pjsip_msg_body*) pjsip_multipart_
curptr = pj_strstr(&subbody, &delim);
if (!curptr) {
/* We're really expecting end delimiter to be found. */
+ PJ_LOG(2, (THIS_FILE, "Failed to find end-delimiter"));
return NULL;
}
}
@@ -670,9 +889,13 @@ PJ_DEF(pjsip_msg_body*) pjsip_multipart_
part = parse_multipart_part(pool, start_body, end_body - start_body,
ctype);
if (part) {
+ TRACE_((THIS_FILE, "Adding part"));
pjsip_multipart_add_part(pool, body, part);
+ } else {
+ PJ_LOG(2, (THIS_FILE, "Failed to add part"));
}
}
+ TRACE_((THIS_FILE, "pjsip_multipart_parse finished: %p", body));
return body;
}
--- a/pjsip/src/test/multipart_test.c
+++ b/pjsip/src/test/multipart_test.c
@@ -28,6 +28,7 @@
typedef pj_status_t (*verify_ptr)(pj_pool_t*,pjsip_msg_body*);
static pj_status_t verify1(pj_pool_t *pool, pjsip_msg_body *body);
+static pj_status_t verify2(pj_pool_t *pool, pjsip_msg_body *body);
static struct test_t
{
@@ -68,7 +69,41 @@ static struct test_t
"This is epilogue, which should be ignored too",
&verify1
+ },
+ {
+ /* Content-type */
+ "multipart", "mixed", "12345",
+
+ /* Body: */
+ "This is the prolog, which should be ignored.\r\n"
+ "--12345\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-ID: <header1@example.org>\r\n"
+ "Content-ID: <\"header1\"@example.org>\r\n"
+ "Content-Length: 13\r\n"
+ "\r\n"
+ "has header1\r\n"
+ "--12345 \t\r\n"
+ "Content-Type: application/pidf+xml\r\n"
+ "Content-ID: <my header2@example.org>\r\n"
+ "Content-ID: <my\xffheader2@example.org>\r\n"
+ "Content-Length: 13\r\n"
+ "\r\n"
+ "has header2\r\n"
+ "--12345\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-ID: <my header3@example.org>\r\n"
+ "Content-ID: <header1@example.org>\r\n"
+ "Content-ID: <my header4@example.org>\r\n"
+ "Content-Length: 13\r\n"
+ "\r\n"
+ "has header4\r\n"
+ "--12345--\r\n"
+ "This is epilogue, which should be ignored too",
+
+ &verify2
}
+
};
static void init_media_type(pjsip_media_type *mt,
@@ -87,6 +122,192 @@ static void init_media_type(pjsip_media_
}
}
+static int verify_hdr(pj_pool_t *pool, pjsip_msg_body *multipart_body,
+ void *hdr, char *part_body)
+{
+ pjsip_media_type mt;
+ pjsip_multipart_part *part;
+ pj_str_t the_body;
+
+
+ part = pjsip_multipart_find_part_by_header(pool, multipart_body, hdr, NULL);
+ if (!part) {
+ return -1;
+ }
+
+ the_body.ptr = (char*)part->body->data;
+ the_body.slen = part->body->len;
+
+ if (pj_strcmp2(&the_body, part_body) != 0) {
+ return -2;
+ }
+
+ return 0;
+}
+
+static int verify_cid_str(pj_pool_t *pool, pjsip_msg_body *multipart_body,
+ pj_str_t cid_url, char *part_body)
+{
+ pjsip_media_type mt;
+ pjsip_multipart_part *part;
+ pj_str_t the_body;
+
+ part = pjsip_multipart_find_part_by_cid_str(pool, multipart_body, &cid_url);
+ if (!part) {
+ return -3;
+ }
+
+ the_body.ptr = (char*)part->body->data;
+ the_body.slen = part->body->len;
+
+ if (pj_strcmp2(&the_body, part_body) != 0) {
+ return -4;
+ }
+
+ return 0;
+}
+
+static int verify_cid_uri(pj_pool_t *pool, pjsip_msg_body *multipart_body,
+ pjsip_other_uri *cid_uri, char *part_body)
+{
+ pjsip_media_type mt;
+ pjsip_multipart_part *part;
+ pj_str_t the_body;
+
+ part = pjsip_multipart_find_part_by_cid_uri(pool, multipart_body, cid_uri);
+ if (!part) {
+ return -5;
+ }
+
+ the_body.ptr = (char*)part->body->data;
+ the_body.slen = part->body->len;
+
+ if (pj_strcmp2(&the_body, part_body) != 0) {
+ return -6;
+ }
+
+ return 0;
+}
+
+static pj_status_t verify2(pj_pool_t *pool, pjsip_msg_body *body)
+{
+ int rc = 0;
+ int rcbase = 300;
+ pjsip_other_uri *cid_uri;
+ pjsip_ctype_hdr *ctype_hdr = pjsip_ctype_hdr_create(pool);
+
+ ctype_hdr->media.type = pj_str("application");
+ ctype_hdr->media.subtype = pj_str("pidf+xml");
+
+ rc = verify_hdr(pool, body, ctype_hdr, "has header2");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("cid:header1@example.org"), "has header1");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("%22header1%22@example.org"), "has header1");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ cid_uri = pjsip_uri_get_uri(pjsip_parse_uri(pool, "<cid:%22header1%22@example.org>",
+ strlen("<cid:%22header1%22@example.org>"), 0));
+ rcbase += 10;
+ rc = verify_cid_uri(pool, body, cid_uri, "has header1");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("<cid:my%20header2@example.org>"), "has header2");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("cid:my%ffheader2@example.org"), "has header2");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ cid_uri = pjsip_uri_get_uri(pjsip_parse_uri(pool, "<cid:my%ffheader2@example.org>",
+ strlen("<cid:my%ffheader2@example.org>"), 0));
+ rcbase += 10;
+ rc = verify_cid_uri(pool, body, cid_uri, "has header2");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("cid:my%20header3@example.org"), "has header4");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("<cid:my%20header4@example.org>"), "has header4");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ cid_uri = pjsip_uri_get_uri(pjsip_parse_uri(pool, "<cid:my%20header4@example.org>",
+ strlen("<cid:my%20header4@example.org>"), 0));
+ rcbase += 10;
+ rc = verify_cid_uri(pool, body, cid_uri, "has header4");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("<my%20header3@example.org>"), "has header4");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ /* These should all fail for malformed or missing URI */
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("cid:"), "has header4");
+ if (!rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str(""), "has header4");
+ if (!rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("<>"), "has header4");
+ if (!rc) {
+ return (rc - rcbase);
+ }
+
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("<cid>"), "has header4");
+ if (!rc) {
+ return (rc - rcbase);
+ }
+
+ /*
+ * This is going to pass but the ' ' in the uri is un-encoded which is invalid
+ * so we should never see it.
+ */
+ rcbase += 10;
+ rc = verify_cid_str(pool, body, pj_str("cid:my header3@example.org"), "has header4");
+ if (rc) {
+ return (rc - rcbase);
+ }
+
+ return 0;
+}
+
static int verify_part(pjsip_multipart_part *part,
char *h_content_type,
char *h_content_subtype,
@@ -236,8 +457,10 @@ static int parse_test(void)
pj_strdup2_with_null(pool, &str, p_tests[i].msg);
body = pjsip_multipart_parse(pool, str.ptr, str.slen, &ctype, 0);
- if (!body)
+ if (!body) {
+ pj_pool_release(pool);
return -100;
+ }
if (p_tests[i].verify) {
rc = p_tests[i].verify(pool, body);

View file

@ -8,12 +8,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=asterisk
PKG_VERSION:=18.7.1
PKG_VERSION:=18.11.2
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=asterisk-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://downloads.asterisk.org/pub/telephony/asterisk/releases
PKG_HASH:=11c8728718b59af74440276ba888484bc9201217719d56436e1e0e85bf533c17
PKG_HASH:=b456d19610e53789446e097bb9773a82a04088922de0cfaff2b818326b67296b
PKG_BUILD_DEPENDS:=libxml2/host
@ -88,6 +88,7 @@ MODULES_AVAILABLE:= \
app-sayunixtime \
app-senddtmf \
app-sendtext \
app-sf \
app-skel \
app-sms \
app-softhangup \
@ -192,6 +193,7 @@ MODULES_AVAILABLE:= \
func-holdintercept \
func-iconv \
func-jitterbuffer \
func-json \
func-lock \
func-math \
func-md5 \
@ -818,6 +820,7 @@ $(eval $(call BuildAsteriskModule,app-saycounted,Decline words,Decline words acc
$(eval $(call BuildAsteriskModule,app-sayunixtime,Say Unix time,Say time.,,,app_sayunixtime,,))
$(eval $(call BuildAsteriskModule,app-senddtmf,Send DTMF digits,Send DTMF digits application.,,,app_senddtmf,,))
$(eval $(call BuildAsteriskModule,app-sendtext,Send text,Send text applications.,,,app_sendtext,,))
$(eval $(call BuildAsteriskModule,app-sf,SF Sender and Receiver Applications,SF Sender and Receiver Applications.,,,app_sf,,))
$(eval $(call BuildAsteriskModule,app-skel,Skeleton [sample],Skeleton application.,,app_skel.conf,app_skel,,))
$(eval $(call BuildAsteriskModule,app-sms,SMS,SMS/PSTN handler.,,,app_sms,,))
$(eval $(call BuildAsteriskModule,app-softhangup,Hang up requested channel,Hangs up the requested channel.,,,app_softhangup,,))
@ -922,6 +925,7 @@ $(eval $(call BuildAsteriskModule,func-hangupcause,HANGUPCAUSE related functions
$(eval $(call BuildAsteriskModule,func-holdintercept,Hold interception dialplan function,Hold interception dialplan function.,,,func_holdintercept,,))
$(eval $(call BuildAsteriskModule,func-iconv,Charset conversion,Charset conversions.,,,func_iconv,,,$(ICONV_DEPENDS)))
$(eval $(call BuildAsteriskModule,func-jitterbuffer,Jitter buffer for read side of channel,Jitter buffer for read side of channel.,,,func_jitterbuffer,,))
$(eval $(call BuildAsteriskModule,func-json,JSON decoding function,JSON decoding function.,,,func_json,,))
$(eval $(call BuildAsteriskModule,func-lock,Dialplan mutexes,Dialplan mutexes.,,,func_lock,,))
$(eval $(call BuildAsteriskModule,func-math,Math functions,Mathematical dialplan function.,,,func_math,,))
$(eval $(call BuildAsteriskModule,func-md5,MD5 digest dialplan functions,MD5 digest dialplan functions.,,,func_md5,,))

View file

@ -15,14 +15,14 @@
cat << END
/*
* build.h
--- a/Makefile
+++ b/Makefile
@@ -489,7 +489,7 @@ doc/core-en_US.xml: makeopts .lastclean
@echo "<docs xmlns:xi=\"http://www.w3.org/2001/XInclude\">" >> $@
@for x in $(MOD_SUBDIRS); do \
printf "$$x " ; \
- for i in `find $$x -name '*.c'`; do \
+ for i in `find $$x -name '*.c' | LC_ALL=C sort`; do \
MODULEINFO=$$($(AWK) -f build_tools/get_moduleinfo $$i) ; \
if [ -n "$$MODULEINFO" ] ; \
then \
--- a/build_tools/make_xml_documentation
+++ b/build_tools/make_xml_documentation
@@ -187,7 +187,7 @@ printf "Building Documentation For: "
for subdir in ${mod_subdirs} ; do
printf "%s " "${subdir}"
subdir_path="${source_tree}/${subdir}"
- for i in $(${FIND} "${subdir_path}" -name '*.c' -or -name '*.cc'); do
+ for i in $(${FIND} "${subdir_path}" -name '*.c' -or -name '*.cc' | LC_ALL=C sort); do
if [ "${with_moduleinfo}" -eq "1" ] ; then
MODULEINFO=$(${AWK} -f "${source_tree}/build_tools/get_moduleinfo" "${i}")
if [ "${MODULEINFO}" != "" ] ; then

View file

@ -1,6 +1,6 @@
--- a/configure.ac
+++ b/configure.ac
@@ -1205,7 +1205,7 @@ if test "${ac_cv_have_variable_fdset}x"
@@ -1260,7 +1260,7 @@ if test "${ac_cv_have_variable_fdset}x"
fi
AC_MSG_CHECKING([if we have usable eventfd support])

View file

@ -1,6 +1,6 @@
--- a/configure.ac
+++ b/configure.ac
@@ -2556,7 +2556,7 @@ if test -z "$__opus_include" -o x"$__opu
@@ -2612,7 +2612,7 @@ if test -z "$__opus_include" -o x"$__opu
fi
AST_EXT_LIB_CHECK([OPUSFILE], [opusfile], [op_open_callbacks], [opus/opusfile.h], [], [$__opus_include])

View file

@ -1,250 +0,0 @@
From 472086370630e1547cf9b497295b4a53d811e872 Mon Sep 17 00:00:00 2001
From: Sebastian Kemper <sebastian_ml@gmx.net>
Date: Sun, 17 Oct 2021 20:17:57 +0200
Subject: [PATCH] time: add support for time64 libc
libcs are implementing changes to fix the year 2038 issue on 32 bit
platforms (see [1]). musl libc already went ahead and implemented it,
starting with musl-1.2.0 (see [2]).
Running asterisk on a 32 bit box with a time64 libc causes some
problems. For instance registering to pjsip doesn't work. The
registration completes fine, but the AOR disappears immediately, making
the registered clients unreachable.
This commit adds two new definitions to include/asterisk/time.h:
TIME_T_INT_FMT
TIME_T_UINT_FMT
If __USE_TIME_BITS64 is defined (by a time64 libc, see [1]), they're set
to the proper conversions for type int64_t, PRId64 and PRIu64
respectively. If __USE_TIME_BITS64 is not defined, the status quo
remains unchanged ("%ld" and "%lu" are used).
The new definitions are used in the different parts of asterisk, where
appropriate.
These changes get rid of the new warnings that appeared with musl-1.2.0 and
make the pjsip registration work again. Below an example warning:
In file included from ../include/asterisk.h:23,
from res_pjsip/location.c:19:
res_pjsip/location.c: In function 'expiration_struct2str':
../include/asterisk/astmm.h:270:72: warning: format '%ld' expects argument of type 'long int', but argument 6 has type 'time_t' {aka 'long long int'} [-Wformat=]
270 | __ast_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, (ret), (fmt), __VA_ARGS__)
| ^~~~~
res_pjsip/location.c:492:17: note: in expansion of macro 'ast_asprintf'
492 | return (ast_asprintf(buf, "%ld", contact->expiration_time.tv_sec) < 0) ? -1 : 0;
| ^~~~~~~~~~~~
[1] https://sourceware.org/glibc/wiki/Y2038ProofnessDesign
[2] https://musl.libc.org/time64.html
ASTERISK-29674 #close
Signed-off-by: Sebastian Kemper <sebastian_ml@gmx.net>
Change-Id: Ic8d61b26033f5c486b917e738c9608b0923a844e
---
include/asterisk/time.h | 16 ++++++++++++++++
res/res_calendar_caldav.c | 2 +-
res/res_calendar_icalendar.c | 2 +-
res/res_http_media_cache.c | 4 ++--
res/res_odbc.c | 2 +-
res/res_pjsip/location.c | 2 +-
res/res_pjsip/pjsip_options.c | 2 +-
res/res_pjsip_history.c | 12 ++++++------
res/res_pjsip_pubsub.c | 2 +-
res/res_pjsip_registrar.c | 2 +-
res/res_stir_shaken.c | 2 +-
11 files changed, 32 insertions(+), 16 deletions(-)
--- a/include/asterisk/time.h
+++ b/include/asterisk/time.h
@@ -29,6 +29,22 @@
#include <sys/time.h>
#endif
+#ifndef TIME_T_INT_FMT
+#ifdef __USE_TIME_BITS64
+#define TIME_T_INT_FMT PRId64
+#else
+#define TIME_T_INT_FMT "ld"
+#endif
+#endif
+
+#ifndef TIME_T_UINT_FMT
+#ifdef __USE_TIME_BITS64
+#define TIME_T_UINT_FMT PRIu64
+#else
+#define TIME_T_UINT_FMT "lu"
+#endif
+#endif
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
--- a/res/res_calendar_caldav.c
+++ b/res/res_calendar_caldav.c
@@ -405,7 +405,7 @@ static void caldav_add_event(icalcompone
ast_string_field_set(event, uid, event->summary);
} else {
char tmp[100];
- snprintf(tmp, sizeof(tmp), "%ld", event->start);
+ snprintf(tmp, sizeof(tmp), "%" TIME_T_INT_FMT, event->start);
ast_string_field_set(event, uid, tmp);
}
}
--- a/res/res_calendar_icalendar.c
+++ b/res/res_calendar_icalendar.c
@@ -246,7 +246,7 @@ static void icalendar_add_event(icalcomp
ast_string_field_set(event, uid, event->summary);
} else {
char tmp[100];
- snprintf(tmp, sizeof(tmp), "%ld", event->start);
+ snprintf(tmp, sizeof(tmp), "%" TIME_T_INT_FMT, event->start);
ast_string_field_set(event, uid, tmp);
}
}
--- a/res/res_http_media_cache.c
+++ b/res/res_http_media_cache.c
@@ -152,7 +152,7 @@ static void bucket_file_set_expiration(s
}
/* Use 'now' if we didn't get an expiration time */
- snprintf(time_buf, sizeof(time_buf), "%30lu", actual_expires.tv_sec);
+ snprintf(time_buf, sizeof(time_buf), "%30" TIME_T_UINT_FMT, actual_expires.tv_sec);
ast_bucket_file_metadata_set(bucket_file, "__actual_expires", time_buf);
}
@@ -302,7 +302,7 @@ static int bucket_file_expired(struct as
return 1;
}
- if (sscanf(metadata->value, "%lu", &expires.tv_sec) != 1) {
+ if (sscanf(metadata->value, "%" TIME_T_UINT_FMT, &expires.tv_sec) != 1) {
return 1;
}
--- a/res/res_odbc.c
+++ b/res/res_odbc.c
@@ -1038,7 +1038,7 @@ static odbc_status odbc_obj_connect(stru
/* Dont connect while server is marked as unreachable via negative_connection_cache */
negative_cache_expiration = obj->parent->last_negative_connect.tv_sec + obj->parent->negative_connection_cache.tv_sec;
if (time(NULL) < negative_cache_expiration) {
- ast_log(LOG_WARNING, "Not connecting to %s. Negative connection cache for %ld seconds\n", obj->parent->name, negative_cache_expiration - time(NULL));
+ ast_log(LOG_WARNING, "Not connecting to %s. Negative connection cache for %" TIME_T_INT_FMT " seconds\n", obj->parent->name, negative_cache_expiration - time(NULL));
return ODBC_FAIL;
}
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -489,7 +489,7 @@ static int expiration_str2struct(const s
static int expiration_struct2str(const void *obj, const intptr_t *args, char **buf)
{
const struct ast_sip_contact *contact = obj;
- return (ast_asprintf(buf, "%ld", contact->expiration_time.tv_sec) < 0) ? -1 : 0;
+ return (ast_asprintf(buf, "%" TIME_T_INT_FMT, contact->expiration_time.tv_sec) < 0) ? -1 : 0;
}
static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -2733,7 +2733,7 @@ int ast_sip_format_contact_ami(void *obj
ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id);
ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri);
ast_str_append(&buf, 0, "UserAgent: %s\r\n", contact->user_agent);
- ast_str_append(&buf, 0, "RegExpire: %ld\r\n", contact->expiration_time.tv_sec);
+ ast_str_append(&buf, 0, "RegExpire: %" TIME_T_INT_FMT "\r\n", contact->expiration_time.tv_sec);
if (!ast_strlen_zero(contact->via_addr)) {
ast_str_append(&buf, 0, "ViaAddress: %s", contact->via_addr);
if (contact->via_port) {
--- a/res/res_pjsip_history.c
+++ b/res/res_pjsip_history.c
@@ -199,7 +199,7 @@ static int evaluate_equal(struct operato
{
struct timeval right = { 0, };
- if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
+ if (sscanf(op_right->field, "%" TIME_T_INT_FMT, &right.tv_sec) != 1) {
ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
return -1;
}
@@ -270,7 +270,7 @@ static int evaluate_less_than(struct ope
{
struct timeval right = { 0, };
- if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
+ if (sscanf(op_right->field, "%" TIME_T_INT_FMT, &right.tv_sec) != 1) {
ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
return -1;
}
@@ -319,7 +319,7 @@ static int evaluate_greater_than(struct
{
struct timeval right = { 0, };
- if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
+ if (sscanf(op_right->field, "%" TIME_T_INT_FMT, &right.tv_sec) != 1) {
ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
return -1;
}
@@ -668,7 +668,7 @@ static void sprint_list_entry(struct pjs
char uri[128];
pjsip_uri_print(PJSIP_URI_IN_REQ_URI, entry->msg->line.req.uri, uri, sizeof(uri));
- snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s %.*s %s SIP/2.0",
+ snprintf(line, len, "%-5.5d %-10.10" TIME_T_INT_FMT " %-5.5s %-24.24s %.*s %s SIP/2.0",
entry->number,
entry->timestamp.tv_sec,
entry->transmitted ? "* ==>" : "* <==",
@@ -677,7 +677,7 @@ static void sprint_list_entry(struct pjs
pj_strbuf(&entry->msg->line.req.method.name),
uri);
} else {
- snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s SIP/2.0 %u %.*s",
+ snprintf(line, len, "%-5.5d %-10.10" TIME_T_INT_FMT " %-5.5s %-24.24s SIP/2.0 %u %.*s",
entry->number,
entry->timestamp.tv_sec,
entry->transmitted ? "* ==>" : "* <==",
@@ -1169,7 +1169,7 @@ static void display_single_entry(struct
pj_sockaddr_print(&entry->src, addr, sizeof(addr), 3);
}
- ast_cli(a->fd, "<--- History Entry %d %s %s at %-10.10ld --->\n",
+ ast_cli(a->fd, "<--- History Entry %d %s %s at %-10.10" TIME_T_INT_FMT " --->\n",
entry->number,
entry->transmitted ? "Sent to" : "Received from",
addr,
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -4744,7 +4744,7 @@ static int persistence_expires_str2struc
static int persistence_expires_struct2str(const void *obj, const intptr_t *args, char **buf)
{
const struct subscription_persistence *persistence = obj;
- return (ast_asprintf(buf, "%ld", persistence->expires.tv_sec) < 0) ? -1 : 0;
+ return (ast_asprintf(buf, "%" TIME_T_INT_FMT, persistence->expires.tv_sec) < 0) ? -1 : 0;
}
#define RESOURCE_LIST_INIT_SIZE 4
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -1272,7 +1272,7 @@ static void *check_expiration_thread(voi
while (check_interval) {
sleep(check_interval);
- sprintf(time, "%ld", ast_tvnow().tv_sec);
+ sprintf(time, "%" TIME_T_INT_FMT, ast_tvnow().tv_sec);
var = ast_variable_new("expiration_time <=", time, "");
ast_debug(4, "Woke up at %s Interval: %d\n", time, check_interval);
--- a/res/res_stir_shaken.c
+++ b/res/res_stir_shaken.c
@@ -389,7 +389,7 @@ static void set_public_key_expiration(co
actual_expires.tv_sec += EXPIRATION_BUFFER;
}
- snprintf(time_buf, sizeof(time_buf), "%30lu", actual_expires.tv_sec);
+ snprintf(time_buf, sizeof(time_buf), "%30" TIME_T_UINT_FMT, actual_expires.tv_sec);
ast_db_put(hash, "expiration", time_buf);
}

View file

@ -0,0 +1,366 @@
From f50e793665ea66b5cea7c612cc95ca27bf45afb8 Mon Sep 17 00:00:00 2001
From: Philip Prindeville <philipp@redfish-solutions.com>
Date: Sun, 13 Feb 2022 12:06:37 -0700
Subject: [PATCH] time: add support for time64 libcs
Treat time_t's as entirely unique and use the POSIX API's for
converting to/from strings.
Lastly, a 64-bit integer formats as 20 digits at most in base10.
Don't need to have any 100 byte buffers to hold that.
ASTERISK-29674 #close
Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
Change-Id: Id7b25bdca8f92e34229f6454f6c3e500f2cd6f56
---
include/asterisk/time.h | 20 ++++++++++++++++++++
main/Makefile | 1 +
main/time.c | 29 +++++++++++++++++++++++++++++
res/res_calendar_caldav.c | 4 ++--
res/res_calendar_icalendar.c | 4 ++--
res/res_http_media_cache.c | 7 ++++---
res/res_odbc.c | 4 +++-
res/res_pjsip/location.c | 5 ++++-
res/res_pjsip/pjsip_options.c | 4 +++-
res/res_pjsip_history.c | 25 ++++++++++++++-----------
res/res_pjsip_pubsub.c | 6 +++++-
res/res_pjsip_registrar.c | 5 +++--
res/res_stir_shaken.c | 6 ++++--
13 files changed, 94 insertions(+), 26 deletions(-)
--- a/include/asterisk/time.h
+++ b/include/asterisk/time.h
@@ -35,6 +35,13 @@
#include "asterisk/inline_api.h"
+/* A time_t can be represented as an unsigned long long (or uint64_t).
+ * Formatted in base 10, UINT64_MAX is 20 digits long, plus one for NUL.
+ * This should be the size of the receiving char buffer for calls to
+ * ast_time_t_to_string().
+ */
+#define AST_TIME_T_LEN 21
+
/* We have to let the compiler learn what types to use for the elements of a
struct timeval since on linux, it's time_t and suseconds_t, but on *BSD,
they are just a long.
@@ -316,4 +323,17 @@ struct timeval ast_time_create_by_unit(u
*/
struct timeval ast_time_create_by_unit_str(unsigned long val, const char *unit);
+/*!
+ * \brief Converts to a string representation of a time_t as decimal
+ * seconds since the epoch. Returns -1 on failure, zero otherwise.
+ *
+ * The buffer should be at least 22 bytes long.
+ */
+int ast_time_t_to_string(time_t time, char *buf, size_t length);
+
+/*!
+ * \brief Returns a time_t from a string containing seconds since the epoch.
+ */
+time_t ast_string_to_time_t(const char *str);
+
#endif /* _ASTERISK_TIME_H */
--- a/main/Makefile
+++ b/main/Makefile
@@ -169,6 +169,7 @@ sched.o: _ASTCFLAGS+=$(call get_menusele
tcptls.o: _ASTCFLAGS+=$(OPENSSL_INCLUDE) -Wno-deprecated-declarations
uuid.o: _ASTCFLAGS+=$(UUID_INCLUDE)
stasis.o: _ASTCFLAGS+=$(call get_menuselect_cflags,AO2_DEBUG)
+time.o: _ASTCFLAGS+=-D_XOPEN_SOURCE=700
OBJS:=$(sort $(OBJS))
--- a/main/time.c
+++ b/main/time.c
@@ -25,6 +25,7 @@
#include <inttypes.h>
#include <string.h>
+#include <strings.h>
#include <time.h>
#include "asterisk/time.h"
@@ -143,3 +144,31 @@ struct timeval ast_time_create_by_unit_s
{
return ast_time_create_by_unit(val, ast_time_str_to_unit(unit));
}
+
+/*!
+ * \brief Returns a string representation of a time_t as decimal seconds
+ * since the epoch.
+ */
+int ast_time_t_to_string(time_t time, char *buf, size_t length)
+{
+ struct tm tm;
+
+ localtime_r(&time, &tm);
+ return (strftime(buf, length, "%s", &tm) == 0) ? -1 : 0;
+}
+
+/*!
+ * \brief Returns a time_t from a string containing seconds since the epoch.
+ */
+time_t ast_string_to_time_t(const char *str)
+{
+ struct tm tm = { 0, };
+
+ /* handle leading spaces */
+ if (strptime(str, " %s", &tm) == NULL) {
+ return (time_t)-1;
+ }
+ tm.tm_isdst = -1;
+ return mktime(&tm);
+}
+
--- a/res/res_calendar_caldav.c
+++ b/res/res_calendar_caldav.c
@@ -404,8 +404,8 @@ static void caldav_add_event(icalcompone
if (!ast_strlen_zero(event->summary)) {
ast_string_field_set(event, uid, event->summary);
} else {
- char tmp[100];
- snprintf(tmp, sizeof(tmp), "%ld", event->start);
+ char tmp[AST_TIME_T_LEN];
+ ast_time_t_to_string(event->start, tmp, sizeof(tmp));
ast_string_field_set(event, uid, tmp);
}
}
--- a/res/res_calendar_icalendar.c
+++ b/res/res_calendar_icalendar.c
@@ -245,8 +245,8 @@ static void icalendar_add_event(icalcomp
if (!ast_strlen_zero(event->summary)) {
ast_string_field_set(event, uid, event->summary);
} else {
- char tmp[100];
- snprintf(tmp, sizeof(tmp), "%ld", event->start);
+ char tmp[AST_TIME_T_LEN];
+ ast_time_t_to_string(event->start, tmp, sizeof(tmp));
ast_string_field_set(event, uid, tmp);
}
}
--- a/res/res_http_media_cache.c
+++ b/res/res_http_media_cache.c
@@ -116,7 +116,7 @@ static size_t curl_body_callback(void *p
static void bucket_file_set_expiration(struct ast_bucket_file *bucket_file)
{
struct ast_bucket_metadata *metadata;
- char time_buf[32];
+ char time_buf[32], secs[AST_TIME_T_LEN];
struct timeval actual_expires = ast_tvnow();
metadata = ast_bucket_file_metadata_get(bucket_file, "cache-control");
@@ -150,7 +150,8 @@ static void bucket_file_set_expiration(s
}
/* Use 'now' if we didn't get an expiration time */
- snprintf(time_buf, sizeof(time_buf), "%30lu", actual_expires.tv_sec);
+ ast_time_t_to_string(actual_expires.tv_sec, secs, sizeof(secs));
+ snprintf(time_buf, sizeof(time_buf), "%30s", secs);
ast_bucket_file_metadata_set(bucket_file, "__actual_expires", time_buf);
}
@@ -314,7 +315,7 @@ static int bucket_file_expired(struct as
return 1;
}
- if (sscanf(metadata->value, "%lu", &expires.tv_sec) != 1) {
+ if ((expires.tv_sec = ast_string_to_time_t(metadata->value)) == -1) {
return 1;
}
--- a/res/res_odbc.c
+++ b/res/res_odbc.c
@@ -1029,7 +1029,9 @@ static odbc_status odbc_obj_connect(stru
/* Dont connect while server is marked as unreachable via negative_connection_cache */
negative_cache_expiration = obj->parent->last_negative_connect.tv_sec + obj->parent->negative_connection_cache.tv_sec;
if (time(NULL) < negative_cache_expiration) {
- ast_log(LOG_WARNING, "Not connecting to %s. Negative connection cache for %ld seconds\n", obj->parent->name, negative_cache_expiration - time(NULL));
+ char secs[AST_TIME_T_LEN];
+ ast_time_t_to_string(negative_cache_expiration - time(NULL), secs, sizeof(secs));
+ ast_log(LOG_WARNING, "Not connecting to %s. Negative connection cache for %s seconds\n", obj->parent->name, secs);
return ODBC_FAIL;
}
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -489,7 +489,10 @@ static int expiration_str2struct(const s
static int expiration_struct2str(const void *obj, const intptr_t *args, char **buf)
{
const struct ast_sip_contact *contact = obj;
- return (ast_asprintf(buf, "%ld", contact->expiration_time.tv_sec) < 0) ? -1 : 0;
+ char secs[AST_TIME_T_LEN];
+
+ ast_time_t_to_string(contact->expiration_time.tv_sec, secs, sizeof(secs));
+ return (ast_asprintf(buf, "%s", secs) < 0) ? -1 : 0;
}
static int permanent_uri_sort_fn(const void *obj_left, const void *obj_right, int flags)
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -2722,6 +2722,7 @@ int ast_sip_format_contact_ami(void *obj
struct ast_sip_contact_status *status;
struct ast_str *buf;
const struct ast_sip_endpoint *endpoint = ami->arg;
+ char secs[AST_TIME_T_LEN];
buf = ast_sip_create_ami_event("ContactStatusDetail", ami);
if (!buf) {
@@ -2733,7 +2734,8 @@ int ast_sip_format_contact_ami(void *obj
ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id);
ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri);
ast_str_append(&buf, 0, "UserAgent: %s\r\n", contact->user_agent);
- ast_str_append(&buf, 0, "RegExpire: %ld\r\n", contact->expiration_time.tv_sec);
+ ast_time_t_to_string(contact->expiration_time.tv_sec, secs, sizeof(secs));
+ ast_str_append(&buf, 0, "RegExpire: %s\r\n", secs);
if (!ast_strlen_zero(contact->via_addr)) {
ast_str_append(&buf, 0, "ViaAddress: %s", contact->via_addr);
if (contact->via_port) {
--- a/res/res_pjsip_history.c
+++ b/res/res_pjsip_history.c
@@ -199,7 +199,7 @@ static int evaluate_equal(struct operato
{
struct timeval right = { 0, };
- if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
+ if ((right.tv_sec = ast_string_to_time_t(op_right->field)) == -1) {
ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
return -1;
}
@@ -270,7 +270,7 @@ static int evaluate_less_than(struct ope
{
struct timeval right = { 0, };
- if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
+ if ((right.tv_sec = ast_string_to_time_t(op_right->field)) == -1) {
ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
return -1;
}
@@ -319,7 +319,7 @@ static int evaluate_greater_than(struct
{
struct timeval right = { 0, };
- if (sscanf(op_right->field, "%ld", &right.tv_sec) != 1) {
+ if ((right.tv_sec = ast_string_to_time_t(op_right->field)) == -1) {
ast_log(LOG_WARNING, "Unable to extract field '%s': not a timestamp\n", op_right->field);
return -1;
}
@@ -656,7 +656,7 @@ static struct pjsip_history_entry *pjsip
/*! \brief Format single line history entry */
static void sprint_list_entry(struct pjsip_history_entry *entry, char *line, int len)
{
- char addr[64];
+ char addr[64], secs[AST_TIME_T_LEN];
if (entry->transmitted) {
pj_sockaddr_print(&entry->dst, addr, sizeof(addr), 3);
@@ -664,22 +664,24 @@ static void sprint_list_entry(struct pjs
pj_sockaddr_print(&entry->src, addr, sizeof(addr), 3);
}
+ ast_time_t_to_string(entry->timestamp.tv_sec, secs, sizeof(secs));
+
if (entry->msg->type == PJSIP_REQUEST_MSG) {
char uri[128];
pjsip_uri_print(PJSIP_URI_IN_REQ_URI, entry->msg->line.req.uri, uri, sizeof(uri));
- snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s %.*s %s SIP/2.0",
+ snprintf(line, len, "%-5.5d %-10.10s %-5.5s %-24.24s %.*s %s SIP/2.0",
entry->number,
- entry->timestamp.tv_sec,
+ secs,
entry->transmitted ? "* ==>" : "* <==",
addr,
(int)pj_strlen(&entry->msg->line.req.method.name),
pj_strbuf(&entry->msg->line.req.method.name),
uri);
} else {
- snprintf(line, len, "%-5.5d %-10.10ld %-5.5s %-24.24s SIP/2.0 %u %.*s",
+ snprintf(line, len, "%-5.5d %-10.10s %-5.5s %-24.24s SIP/2.0 %u %.*s",
entry->number,
- entry->timestamp.tv_sec,
+ secs,
entry->transmitted ? "* ==>" : "* <==",
addr,
entry->msg->line.status.code,
@@ -1149,7 +1151,7 @@ static struct vector_history_t *filter_h
/*! \brief Print a detailed view of a single entry in the history to the CLI */
static void display_single_entry(struct ast_cli_args *a, struct pjsip_history_entry *entry)
{
- char addr[64];
+ char addr[64], secs[AST_TIME_T_LEN];
char *buf;
buf = ast_calloc(1, PJSIP_MAX_PKT_LEN * sizeof(char));
@@ -1169,11 +1171,12 @@ static void display_single_entry(struct
pj_sockaddr_print(&entry->src, addr, sizeof(addr), 3);
}
- ast_cli(a->fd, "<--- History Entry %d %s %s at %-10.10ld --->\n",
+ ast_time_t_to_string(entry->timestamp.tv_sec, secs, sizeof(secs));
+ ast_cli(a->fd, "<--- History Entry %d %s %s at %-10.10s --->\n",
entry->number,
entry->transmitted ? "Sent to" : "Received from",
addr,
- entry->timestamp.tv_sec);
+ secs);
ast_cli(a->fd, "%s\n", buf);
ast_free(buf);
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -4872,7 +4872,11 @@ static int persistence_expires_str2struc
static int persistence_expires_struct2str(const void *obj, const intptr_t *args, char **buf)
{
const struct subscription_persistence *persistence = obj;
- return (ast_asprintf(buf, "%ld", persistence->expires.tv_sec) < 0) ? -1 : 0;
+ char secs[AST_TIME_T_LEN];
+
+ ast_time_t_to_string(persistence->expires.tv_sec, secs, sizeof(secs));
+
+ return (ast_asprintf(buf, "%s", secs) < 0) ? -1 : 0;
}
#define RESOURCE_LIST_INIT_SIZE 4
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -1365,12 +1365,13 @@ static void *check_expiration_thread(voi
{
struct ao2_container *contacts;
struct ast_variable *var;
- char *time = alloca(64);
+ char time[AST_TIME_T_LEN];
while (check_interval) {
sleep(check_interval);
- sprintf(time, "%ld", ast_tvnow().tv_sec);
+ ast_time_t_to_string(ast_tvnow().tv_sec, time, sizeof(time));
+
var = ast_variable_new("expiration_time <=", time, "");
ast_debug(4, "Woke up at %s Interval: %d\n", time, check_interval);
--- a/res/res_stir_shaken.c
+++ b/res/res_stir_shaken.c
@@ -403,7 +403,7 @@ int ast_stir_shaken_add_verification(str
*/
static void set_public_key_expiration(const char *public_cert_url, const struct curl_cb_data *data)
{
- char time_buf[32];
+ char time_buf[32], secs[AST_TIME_T_LEN];
char *value;
struct timeval actual_expires = ast_tvnow();
char hash[41];
@@ -441,7 +441,9 @@ static void set_public_key_expiration(co
actual_expires.tv_sec += EXPIRATION_BUFFER;
}
- snprintf(time_buf, sizeof(time_buf), "%30lu", actual_expires.tv_sec);
+ ast_time_t_to_string(actual_expires.tv_sec, secs, sizeof(secs));
+
+ snprintf(time_buf, sizeof(time_buf), "%30s", secs);
ast_db_put(hash, "expiration", time_buf);
}

View file

@ -32,7 +32,7 @@ Signed-off-by: Sergey V. Lobanov <sergey@lobanov.in>
--- a/Makefile
+++ b/Makefile
@@ -589,9 +589,9 @@ bininstall: _all installdirs $(SUBDIRS_I
@@ -558,9 +558,9 @@ bininstall: _all installdirs $(SUBDIRS_I
$(INSTALL) -m 755 contrib/scripts/astversion "$(DESTDIR)$(ASTSBINDIR)/"
$(INSTALL) -m 755 contrib/scripts/astgenkey "$(DESTDIR)$(ASTSBINDIR)/"
$(INSTALL) -m 755 contrib/scripts/autosupport "$(DESTDIR)$(ASTSBINDIR)/"
@ -47,7 +47,7 @@ Signed-off-by: Sergey V. Lobanov <sergey@lobanov.in>
$(INSTALL) -m 644 doc/core-*.xml "$(DESTDIR)$(ASTDATADIR)/documentation"
--- a/makeopts.in
+++ b/makeopts.in
@@ -369,3 +369,5 @@ SNDFILE_LIB=@SNDFILE_LIB@
@@ -373,3 +373,5 @@ SNDFILE_LIB=@SNDFILE_LIB@
BEANSTALK_INCLUDE=@BEANSTALK_INCLUDE@
BEANSTALK_LIB=@BEANSTALK_LIB@

View file

@ -0,0 +1,76 @@
From 140c19c2067a5e2dcedfbb4dfa08c57758b822cb Mon Sep 17 00:00:00 2001
From: Philip Prindeville <philipp@redfish-solutions.com>
Date: Mon, 21 Feb 2022 18:05:49 -0700
Subject: [PATCH] logger: workaround woefully small BUFSIZ in MUSL
MUSL defines BUFSIZ as 1024 which is not reasonable for log messages.
More broadly, BUFSIZ is the amount of buffering stdio.h does, which
is arbitrary and largely orthogonal to what logging should accept
as the maximum message size.
ASTERISK-29928
Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
Change-Id: Iaa49fbbab029c64ae3d95e4b18270e0442cce170
---
main/logger.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
--- a/main/logger.c
+++ b/main/logger.c
@@ -97,6 +97,11 @@ static int logger_queue_limit = 1000;
static int logger_messages_discarded;
static unsigned int high_water_alert;
+/* On some platforms, like those with MUSL as the runtime, BUFSIZ is
+ * unreasonably small (1024). Use a larger value in those environments.
+ */
+#define LOGMSG_SIZE MAX(BUFSIZ, 8192)
+
static enum rotatestrategy {
NONE = 0, /* Do not rotate log files at all, instead rely on external mechanisms */
SEQUENTIAL = 1 << 0, /* Original method - create a new file, in order */
@@ -1665,7 +1670,7 @@ static struct sigaction handle_SIGXFSZ =
static void logger_print_normal(struct logmsg *logmsg)
{
struct logchannel *chan = NULL;
- char buf[BUFSIZ];
+ char buf[LOGMSG_SIZE];
int level = 0;
AST_RWLIST_RDLOCK(&logchannels);
@@ -1698,13 +1703,13 @@ static void logger_print_normal(struct l
/* Don't use LOG_MAKEPRI because it's broken in glibc<2.17 */
syslog_level = chan->facility | syslog_level; /* LOG_MAKEPRI(chan->facility, syslog_level); */
- if (!chan->formatter.format_log(chan, logmsg, buf, BUFSIZ)) {
+ if (!chan->formatter.format_log(chan, logmsg, buf, sizeof(buf))) {
syslog(syslog_level, "%s", buf);
}
}
break;
case LOGTYPE_CONSOLE:
- if (!chan->formatter.format_log(chan, logmsg, buf, BUFSIZ)) {
+ if (!chan->formatter.format_log(chan, logmsg, buf, sizeof(buf))) {
ast_console_puts_mutable_full(buf, logmsg->level, logmsg->sublevel);
}
break;
@@ -1716,7 +1721,7 @@ static void logger_print_normal(struct l
continue;
}
- if (chan->formatter.format_log(chan, logmsg, buf, BUFSIZ)) {
+ if (chan->formatter.format_log(chan, logmsg, buf, sizeof(buf))) {
continue;
}
@@ -1780,7 +1785,7 @@ static struct logmsg * __attribute__((fo
}
/* Build string */
- res = ast_str_set_va(&buf, BUFSIZ, fmt, ap);
+ res = ast_str_set_va(&buf, LOGMSG_SIZE, fmt, ap);
/* If the build failed, then abort and free this structure */
if (res == AST_DYNSTR_BUILD_FAILED) {