From ccc57cff3c3d540713dcd5e77b688da214a46de3 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Thu, 7 Oct 2021 18:31:07 +0200 Subject: pjproject: sync patches with asterisk 18.11.2 pjproject: sync patches with asterisk 18.7.1 Signed-off-by: Andre Heider (cherry picked from commit 376473b38c0a6f4a8e742a26caafbf484ed1b9c5) pjproject: sync patches with asterisk 18.11.2 Signed-off-by: Sebastian Kemper (cherry picked from commit 0c67ab5831bb1509af035ce8f142eabbf14bd82a) --- libs/pjproject/Makefile | 2 +- ..._attr_get_rtpmap-Strip-param-trailing-whi.patch | 27 + ...nv-Additional-multipart-support-2919-2920.patch | 653 +++++++++++++++++++++ ...ct-unescaping-of-tokens-during-parsing-29.patch | 116 ++++ ...0-Create-generic-pjsip_hdr_find-functions.patch | 169 ++++++ .../0160-Additional-multipart-improvements.patch | 635 ++++++++++++++++++++ 6 files changed, 1601 insertions(+), 1 deletion(-) create mode 100644 libs/pjproject/patches/0120-pjmedia_sdp_attr_get_rtpmap-Strip-param-trailing-whi.patch create mode 100644 libs/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch create mode 100644 libs/pjproject/patches/0140-Fix-incorrect-unescaping-of-tokens-during-parsing-29.patch create mode 100644 libs/pjproject/patches/0150-Create-generic-pjsip_hdr_find-functions.patch create mode 100644 libs/pjproject/patches/0160-Additional-multipart-improvements.patch diff --git a/libs/pjproject/Makefile b/libs/pjproject/Makefile index 8bba564..5e7b645 100644 --- a/libs/pjproject/Makefile +++ b/libs/pjproject/Makefile @@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=pjproject PKG_VERSION:=2.10 -PKG_RELEASE:=6 +PKG_RELEASE:=7 # download "vX.Y.tar.gz" as "pjproject-vX.Y.tar.gz" PKG_SOURCE_URL_FILE:=$(PKG_VERSION).tar.gz diff --git a/libs/pjproject/patches/0120-pjmedia_sdp_attr_get_rtpmap-Strip-param-trailing-whi.patch b/libs/pjproject/patches/0120-pjmedia_sdp_attr_get_rtpmap-Strip-param-trailing-whi.patch new file mode 100644 index 0000000..a3e668c --- /dev/null +++ b/libs/pjproject/patches/0120-pjmedia_sdp_attr_get_rtpmap-Strip-param-trailing-whi.patch @@ -0,0 +1,27 @@ +From 2ae784030b0d9cf217c3d562af20e4967f19a3dc Mon Sep 17 00:00:00 2001 +From: George Joseph +Date: Tue, 14 Sep 2021 10:47:29 -0600 +Subject: [PATCH] pjmedia_sdp_attr_get_rtpmap: Strip param trailing whitespace + +Use pj_scan_get() to parse the param part of rtpmap so +trailing whitespace is automatically stripped. + +Fixes #2827 +--- + pjmedia/src/pjmedia/sdp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/pjmedia/src/pjmedia/sdp.c ++++ b/pjmedia/src/pjmedia/sdp.c +@@ -313,9 +313,9 @@ PJ_DEF(pj_status_t) pjmedia_sdp_attr_get + + /* Expecting either '/' or EOF */ + if (*scanner.curptr == '/') { ++ /* Skip the '/' */ + pj_scan_get_char(&scanner); +- rtpmap->param.ptr = scanner.curptr; +- rtpmap->param.slen = scanner.end - scanner.curptr; ++ pj_scan_get(&scanner, &cs_token, &rtpmap->param); + } else { + rtpmap->param.slen = 0; + } diff --git a/libs/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch b/libs/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch new file mode 100644 index 0000000..8db8aab --- /dev/null +++ b/libs/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch @@ -0,0 +1,653 @@ +From 0ed41eb5fd0e4192e1b7dc374f819d17aef3e805 Mon Sep 17 00:00:00 2001 +From: George Joseph +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 ++ }, + + }; + diff --git a/libs/pjproject/patches/0140-Fix-incorrect-unescaping-of-tokens-during-parsing-29.patch b/libs/pjproject/patches/0140-Fix-incorrect-unescaping-of-tokens-during-parsing-29.patch new file mode 100644 index 0000000..deb9d8c --- /dev/null +++ b/libs/pjproject/patches/0140-Fix-incorrect-unescaping-of-tokens-during-parsing-29.patch @@ -0,0 +1,116 @@ +From 3faf1d2b4da553bbaee04f9a13a5d084b381e5fb Mon Sep 17 00:00:00 2001 +From: sauwming +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; diff --git a/libs/pjproject/patches/0150-Create-generic-pjsip_hdr_find-functions.patch b/libs/pjproject/patches/0150-Create-generic-pjsip_hdr_find-functions.patch new file mode 100644 index 0000000..5979a3b --- /dev/null +++ b/libs/pjproject/patches/0150-Create-generic-pjsip_hdr_find-functions.patch @@ -0,0 +1,169 @@ +From 7e3dfd8a15fd0f98dbf0e04d2d7a5bded90ee401 Mon Sep 17 00:00:00 2001 +From: George Joseph +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) + { diff --git a/libs/pjproject/patches/0160-Additional-multipart-improvements.patch b/libs/pjproject/patches/0160-Additional-multipart-improvements.patch new file mode 100644 index 0000000..3de67b5 --- /dev/null +++ b/libs/pjproject/patches/0160-Additional-multipart-improvements.patch @@ -0,0 +1,635 @@ +From b7ecff22e77887626fd8e8608c4dd73bc7b7366f Mon Sep 17 00:00:00 2001 +From: George Joseph +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 + #include + #include ++#include + #include + #include + #include +@@ -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: \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: \r\n" ++ "Content-ID: \r\n" ++ "Content-Length: 13\r\n" ++ "\r\n" ++ "has header2\r\n" ++ "--12345\r\n" ++ "Content-Type: text/plain\r\n" ++ "Content-ID: \r\n" ++ "Content-ID: \r\n" ++ "Content-ID: \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, "", ++ strlen(""), 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(""), "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, "", ++ strlen(""), 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(""), "has header4"); ++ if (rc) { ++ return (rc - rcbase); ++ } ++ ++ cid_uri = pjsip_uri_get_uri(pjsip_parse_uri(pool, "", ++ strlen(""), 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(""), "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(""), "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); -- cgit From 3181481463fd09ee78a610619d683527bdaad8ae Mon Sep 17 00:00:00 2001 From: Sebastian Kemper Date: Fri, 20 Aug 2021 22:59:49 +0200 Subject: asterisk: bump to version 18.11.2 asterisk: update AST_EXT_TOOL_CHECK for OpenWrt Issue #672 shows that the current macro has some pitfalls, at least when running within OpenWrt's buildroot. The macro is used to detect these tools: 1. xml2-config 2. mysql_config 3. neon-config 4. net-snmp-config 5. sdl-config (we're not using SDL) The macro also adds configure arguments that allow to specify a path like so: --with-mysqlclient=PATH Macro problems: 1. If no PATH is specified, it adds "/bin" to the search path. Obviously this is a bad thing when cross-compiling. 2. If a PATH is specified, it adds it to the start of every include and library path it encounters. These paths are then broken. This commit makes problem 1 go away by making the addition of "${$1_DIR}/bin" to the PATH dependent on there being a PATH handed to the macro. An alternative would be to remove the PATH addition altogether, but then the macro wouldn't behave as expected. It also removes the path filtering of the include and lib dirs to address problem 2. Closes #672 Signed-off-by: Sebastian Kemper (cherry picked from commit 79a0acfe56256748615159f6e08687570ac2cf88) asterisk: bump to 18.7.1 The removed patch has been applied upstream and is part of this release. Signed-off-by: Andre Heider (cherry picked from commit 0399a3dc730ae639636bcd053193b37751f8df4d) asterisk: add missing modules + dependency Signed-off-by: Sebastian Kemper (cherry picked from commit 04b6b267f1c36e228655236ce054b5e0eb15c804) asterisk: fix build on macos This commit adds a patch to fix /sbin/launchd detection on macos Signed-off-by: Sergey V. Lobanov (cherry picked from commit 4209a36afe4c66365bdffc5f62d287e94cfc8edd) asterisk: bump to version 18.11.2 - add two new modules (app_sf and func_json) - update 100-build-reproducibly.patch as upstream refactored some of the code - refresh patches This bump includes fixes for the following security issues: https://downloads.asterisk.org/pub/security/AST-2022-001.html https://downloads.asterisk.org/pub/security/AST-2022-002.html https://downloads.asterisk.org/pub/security/AST-2022-003.html Signed-off-by: Sebastian Kemper (cherry picked from commit 958401fa8f98e50df02917eded1eb4815997985d) asterisk: add --without-libxslt to configure Since upstream commit b40c4d59b1dd803cad79060fb5b5a48d249ba578 "--disable-xmldoc" does no longer prevent the linking to libxslt, if available. If that's the case one is greeted with the following error: Package asterisk is missing dependencies for the following libraries: libxslt.so.1 This commit explicitly disables the use of libxslt, to avoid the dependency. Signed-off-by: Sebastian Kemper (cherry picked from commit 64a1d2faef62352327c4aaeec803ce71ff5d2c40) --- net/asterisk/Makefile | 29 +++- ...able-semaphores-on-uclibc-otherwise-allow.patch | 2 +- ...ix-detection-of-re-entrant-resolver-funct.patch | 2 +- ...anded-A-option-to-add-caller-announcement.patch | 147 --------------------- net/asterisk/patches/100-build-reproducibly.patch | 22 +-- net/asterisk/patches/130-eventfd.patch | 2 +- net/asterisk/patches/140-use-default-lua.patch | 2 +- net/asterisk/patches/160-AST_EXT_TOOL_CHECK.patch | 22 +++ ...ininstall-launchd-issue-on-cross-platfrom.patch | 55 ++++++++ 9 files changed, 117 insertions(+), 166 deletions(-) delete mode 100644 net/asterisk/patches/090-app_dial-expanded-A-option-to-add-caller-announcement.patch create mode 100644 net/asterisk/patches/160-AST_EXT_TOOL_CHECK.patch create mode 100644 net/asterisk/patches/180_build-fix-bininstall-launchd-issue-on-cross-platfrom.patch diff --git a/net/asterisk/Makefile b/net/asterisk/Makefile index 8cc8755..f63789b 100644 --- a/net/asterisk/Makefile +++ b/net/asterisk/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=asterisk -PKG_VERSION:=18.5.1 -PKG_RELEASE:=2 +PKG_VERSION:=18.11.2 +PKG_RELEASE:=1 PKG_SOURCE:=asterisk-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://downloads.asterisk.org/pub/telephony/asterisk/releases -PKG_HASH:=e7d78716a0deeadf24b7d537cd24c11c2d9a096265eefc9470565c4da0fc54c7 +PKG_HASH:=b456d19610e53789446e097bb9773a82a04088922de0cfaff2b818326b67296b PKG_BUILD_DEPENDS:=libxml2/host @@ -58,6 +58,7 @@ MODULES_AVAILABLE:= \ app-directed-pickup \ app-directory \ app-disa \ + app-dtmfstore \ app-dumpchan \ app-exec \ app-externalivr \ @@ -68,6 +69,7 @@ MODULES_AVAILABLE:= \ app-ices \ app-image \ app-ivrdemo \ + app-mf \ app-milliwatt \ app-minivm \ app-mixmonitor \ @@ -81,10 +83,12 @@ MODULES_AVAILABLE:= \ app-read \ app-readexten \ app-record \ + app-reload \ app-saycounted \ app-sayunixtime \ app-senddtmf \ app-sendtext \ + app-sf \ app-skel \ app-sms \ app-softhangup \ @@ -100,6 +104,7 @@ MODULES_AVAILABLE:= \ app-url \ app-userevent \ app-verbose \ + app-waitforcond \ app-voicemail \ app-voicemail-imap \ app-voicemail-odbc \ @@ -180,6 +185,7 @@ MODULES_AVAILABLE:= \ func-enum \ func-env \ func-extstate \ + func-frame-drop \ func-frame-trace \ func-global \ func-groupcount \ @@ -187,6 +193,7 @@ MODULES_AVAILABLE:= \ func-holdintercept \ func-iconv \ func-jitterbuffer \ + func-json \ func-lock \ func-math \ func-md5 \ @@ -196,6 +203,8 @@ MODULES_AVAILABLE:= \ func-presencestate \ func-rand \ func-realtime \ + func-sayfiles \ + func-scramble \ func-sha1 \ func-shell \ func-sorcery \ @@ -304,6 +313,7 @@ MODULES_AVAILABLE:= \ res-stun-monitor \ res-timing-dahdi \ res-timing-pthread \ + res-tonedetect \ res-xmpp UTILS_AVAILABLE:= \ @@ -564,6 +574,7 @@ CONFIGURE_ARGS+= \ --without-pjproject-bundled \ --with-libedit="$(STAGING_DIR)/usr" \ --with-libxml2 \ + --without-libxslt \ $(if $(CONFIG_PACKAGE_$(PKG_NAME)-res-snmp),--with-netsnmp="$(STAGING_DIR)/usr",--without-netsnmp) \ --without-newt \ --without-osptk \ @@ -781,16 +792,18 @@ $(eval $(call BuildAsteriskModule,app-dictate,Virtual dictation machine,Virtual $(eval $(call BuildAsteriskModule,app-directed-pickup,Directed call pickup,Directed call pickup application.,,,app_directed_pickup,,)) $(eval $(call BuildAsteriskModule,app-directory,Extension directory,Extension directory.,,,app_directory,,)) $(eval $(call BuildAsteriskModule,app-disa,Direct Inward System Access,Direct Inward System Access application.,,,app_disa,,)) +$(eval $(call BuildAsteriskModule,app-dtmfstore,DTMF storage,Technology independent async DTMF storage.,,,app_dtmfstore,,)) $(eval $(call BuildAsteriskModule,app-dumpchan,Dump info about channel,Dump info about the calling channel.,,,app_dumpchan,,)) $(eval $(call BuildAsteriskModule,app-exec,Exec application,Executes dialplan applications.,,,app_exec,,)) $(eval $(call BuildAsteriskModule,app-externalivr,External IVR interface,External IVR interface application.,,,app_externalivr,,)) $(eval $(call BuildAsteriskModule,app-festival,Simple festival interface,Simple Festival interface.,,festival.conf,app_festival,,)) $(eval $(call BuildAsteriskModule,app-flash,Flash channel,Flash channel application.,+$(PKG_NAME)-chan-dahdi,,app_flash,,)) $(eval $(call BuildAsteriskModule,app-followme,Find-me/follow-me,Find-Me/Follow-Me application.,,followme.conf,app_followme,,)) -$(eval $(call BuildAsteriskModule,app-getcpeid,Get ADSI CPE ID,Get ADSI CPE ID.,,,app_getcpeid,,)) +$(eval $(call BuildAsteriskModule,app-getcpeid,Get ADSI CPE ID,Get ADSI CPE ID.,+asterisk-res-adsi,,app_getcpeid,,)) $(eval $(call BuildAsteriskModule,app-ices,Encode and stream,Encode and stream via Icecast and IceS.,,,app_ices,,)) $(eval $(call BuildAsteriskModule,app-image,Image transmission,Image transmission application.,,,app_image,,)) $(eval $(call BuildAsteriskModule,app-ivrdemo,IVR demo,IVR demo application.,,,app_ivrdemo,,)) +$(eval $(call BuildAsteriskModule,app-mf,MF digits,Send MF digits Application.,,,app_mf,,)) $(eval $(call BuildAsteriskModule,app-milliwatt,Digital milliwatt [mu-law] test app,Digital milliwatt test application.,,,app_milliwatt,,)) $(eval $(call BuildAsteriskModule,app-minivm,Minimal voicemail system,A minimal voicemail e-mail system.,,extensions_minivm.conf minivm.conf,app_minivm,,)) $(eval $(call BuildAsteriskModule,app-mixmonitor,Record a call and mix the audio,Mixed audio monitoring application.,,,app_mixmonitor,,)) @@ -804,10 +817,12 @@ $(eval $(call BuildAsteriskModule,app-queue,True Call Queueing,True call queuein $(eval $(call BuildAsteriskModule,app-read,Variable read,Read variable application.,,,app_read,,)) $(eval $(call BuildAsteriskModule,app-readexten,Extension to variable,Read and evaluate extension validity.,,,app_readexten,,)) $(eval $(call BuildAsteriskModule,app-record,Record sound file,Trivial record application.,,,app_record,,)) +$(eval $(call BuildAsteriskModule,app-reload,Reload,Reload module[s].,,,app_reload,,)) $(eval $(call BuildAsteriskModule,app-saycounted,Decline words,Decline words according to channel language.,,,app_saycounted,,)) $(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,,)) @@ -823,6 +838,7 @@ $(eval $(call BuildAsteriskModule,app-transfer,Transfers caller to other ext,Tra $(eval $(call BuildAsteriskModule,app-url,Send URL,Send URL applications.,,,app_url,,)) $(eval $(call BuildAsteriskModule,app-userevent,Custom user event,Custom user event application.,,,app_userevent,,)) $(eval $(call BuildAsteriskModule,app-verbose,Verbose logging,Send verbose output.,,,app_verbose,,)) +$(eval $(call BuildAsteriskModule,app-waitforcond,Wait for condition,Wait until condition is true.,,,app_waitforcond,,)) $(eval $(call BuildAsteriskModule,app-voicemail,Voicemail,Voicemail module.,,voicemail.conf,app_voicemail,vm-*,)) $(eval $(call BuildAsteriskModule,app-voicemail-imap,Voicemail IMAP,Voicemail module.,+uw-imap,,app_voicemail_imap,,)) $(eval $(call BuildAsteriskModule,app-voicemail-odbc,Voicemail ODBC,Voicemail module.,+unixodbc,,app_voicemail_odbc,,)) @@ -903,6 +919,7 @@ $(eval $(call BuildAsteriskModule,func-dialplan,Dialplan context/extension/prior $(eval $(call BuildAsteriskModule,func-enum,ENUM,ENUM related dialplan functions.,,enum.conf,func_enum,,)) $(eval $(call BuildAsteriskModule,func-env,Environment functions,Environment/filesystem dialplan functions.,,,func_env,,)) $(eval $(call BuildAsteriskModule,func-extstate,Hinted extension state,Gets the state of an extension in the dialplan.,,,func_extstate,,)) +$(eval $(call BuildAsteriskModule,func-frame-drop,Frame drop,Function to drop frames on a channel.,,,func_frame_drop,,)) $(eval $(call BuildAsteriskModule,func-frame-trace,Frame trace for internal ast_frame debugging,Frame trace for internal ast_frame debugging.,,,func_frame_trace,,)) $(eval $(call BuildAsteriskModule,func-global,Global variable,Variable dialplan functions.,,,func_global,,)) $(eval $(call BuildAsteriskModule,func-groupcount,Group count,Channel group dialplan functions.,,,func_groupcount,,)) @@ -910,6 +927,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,,)) @@ -919,6 +937,8 @@ $(eval $(call BuildAsteriskModule,func-pitchshift,Audio effects dialplan functio $(eval $(call BuildAsteriskModule,func-presencestate,Hinted presence state,Gets or sets a presence state in the dialplan.,,,func_presencestate,,)) $(eval $(call BuildAsteriskModule,func-rand,RAND dialplan function,Random number dialplan function.,,,func_rand,,)) $(eval $(call BuildAsteriskModule,func-realtime,REALTIME dialplan function,Read/write/store/destroy values from a realtime repository.,,,func_realtime,,)) +$(eval $(call BuildAsteriskModule,func-sayfiles,Say files,Say application files.,,,func_sayfiles,,)) +$(eval $(call BuildAsteriskModule,func-scramble,Scramble,Frequency inverting voice scrambler.,,,func_scramble,,)) $(eval $(call BuildAsteriskModule,func-sha1,SHA-1 computation dialplan function,SHA-1 computation dialplan function.,,,func_sha1,,)) $(eval $(call BuildAsteriskModule,func-shell,Shell,Collects the output generated by a command executed by the system shell.,,,func_shell,,)) $(eval $(call BuildAsteriskModule,func-sorcery,Get a field from a sorcery object,Get a field from a sorcery object.,,,func_sorcery,,)) @@ -1027,6 +1047,7 @@ $(eval $(call BuildAsteriskModule,res-stir-shaken,STIR/SHAKEN resource module,ST $(eval $(call BuildAsteriskModule,res-stun-monitor,STUN monitoring,STUN network monitor.,,res_stun_monitor.conf,res_stun_monitor,,)) $(eval $(call BuildAsteriskModule,res-timing-dahdi,DAHDI Timing Interface,DAHDI timing interface.,+$(PKG_NAME)-chan-dahdi,,res_timing_dahdi,,)) $(eval $(call BuildAsteriskModule,res-timing-pthread,pthread Timing Interface,pthread timing interface.,,,res_timing_pthread,,)) +$(eval $(call BuildAsteriskModule,res-tonedetect,Tone detection,Tone detection module.,,,res_tonedetect,,)) $(eval $(call BuildAsteriskModule,res-xmpp,XMPP client and component module,Asterisk XMPP interface.,+libiksemel +libopenssl,xmpp.conf,res_xmpp,,)) ################################ diff --git a/net/asterisk/patches/001-disable-semaphores-on-uclibc-otherwise-allow.patch b/net/asterisk/patches/001-disable-semaphores-on-uclibc-otherwise-allow.patch index b7d3f53..e8917e9 100644 --- a/net/asterisk/patches/001-disable-semaphores-on-uclibc-otherwise-allow.patch +++ b/net/asterisk/patches/001-disable-semaphores-on-uclibc-otherwise-allow.patch @@ -1,6 +1,6 @@ --- a/configure.ac +++ b/configure.ac -@@ -1040,15 +1040,18 @@ AC_LINK_IFELSE( +@@ -1090,15 +1090,18 @@ AC_LINK_IFELSE( # Some platforms define sem_init(), but only support sem_open(). joyous. AC_MSG_CHECKING(for working unnamed semaphores) diff --git a/net/asterisk/patches/002-configure-fix-detection-of-re-entrant-resolver-funct.patch b/net/asterisk/patches/002-configure-fix-detection-of-re-entrant-resolver-funct.patch index 9dad5bb..fad4417 100644 --- a/net/asterisk/patches/002-configure-fix-detection-of-re-entrant-resolver-funct.patch +++ b/net/asterisk/patches/002-configure-fix-detection-of-re-entrant-resolver-funct.patch @@ -18,7 +18,7 @@ Signed-off-by: Bernd Kuhls --- a/configure.ac +++ b/configure.ac -@@ -1434,7 +1434,11 @@ AC_LINK_IFELSE( +@@ -1484,7 +1484,11 @@ AC_LINK_IFELSE( #include #endif #include ], diff --git a/net/asterisk/patches/090-app_dial-expanded-A-option-to-add-caller-announcement.patch b/net/asterisk/patches/090-app_dial-expanded-A-option-to-add-caller-announcement.patch deleted file mode 100644 index bd20730..0000000 --- a/net/asterisk/patches/090-app_dial-expanded-A-option-to-add-caller-announcement.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 1e5a2cfe3037823b17dd4ac47b071f02d6f9825f Mon Sep 17 00:00:00 2001 -From: Naveen Albert -Date: Fri, 21 May 2021 20:08:58 -0400 -Subject: [PATCH] app_dial: Expanded A option to add caller announcement - -Hitherto, the A option has made it possible to play -audio upon answer to the called party only. This option -is expanded to allow for playback of an audio file to -the caller instead of or in addition to the audio -played to the answerer. - -ASTERISK-29442 - -Change-Id: If6eed3ff5c341dc8c588c8210987f2571e891e5e ---- - apps/app_dial.c | 79 +++++++++++++++---- - doc/CHANGES-staging/app_dial_announcement.txt | 6 ++ - 2 files changed, 68 insertions(+), 17 deletions(-) - create mode 100644 doc/CHANGES-staging/app_dial_announcement.txt - ---- a/apps/app_dial.c -+++ b/apps/app_dial.c -@@ -93,11 +93,17 @@ - - - --