Merge pull request #756 from micmac1/ast-18.11.2
asterisk: bump to 18.11.2
This commit is contained in:
commit
1518d145c3
12 changed files with 2036 additions and 267 deletions
|
@ -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
|
||||
+ },
|
||||
|
||||
};
|
||||
|
|
@ -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(¶m->name, "p2"))
|
||||
return -956;
|
||||
- if (pj_strcmp2(¶m->value, "ab:cd"))
|
||||
+ if (pj_strcmp2(¶m->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;
|
|
@ -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)
|
||||
{
|
|
@ -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);
|
|
@ -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,,))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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])
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
366
net/asterisk/patches/170-time-add-support-for-time64-libcs.patch
Normal file
366
net/asterisk/patches/170-time-add-support-for-time64-libcs.patch
Normal 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);
|
||||
}
|
|
@ -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@
|
||||
|
|
|
@ -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) {
|
Loading…
Reference in a new issue