diff options
-rw-r--r-- | pjsip/include/pjsip-simple/presence.h | 42 | ||||
-rw-r--r-- | pjsip/src/pjsip-simple/presence.c | 31 | ||||
-rw-r--r-- | pjsip/src/pjsip-simple/presence_body.c | 26 | ||||
-rw-r--r-- | tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.xml | 124 |
4 files changed, 217 insertions, 6 deletions
diff --git a/pjsip/include/pjsip-simple/presence.h b/pjsip/include/pjsip-simple/presence.h index 7c996123..eaf8ba86 100644 --- a/pjsip/include/pjsip-simple/presence.h +++ b/pjsip/include/pjsip-simple/presence.h @@ -328,11 +328,31 @@ PJ_DECL(pj_status_t) pjsip_pres_create_xpidf(pj_pool_t *pool, * @param status The presence status to be initialized. * * @return PJ_SUCCESS on success. + * + * @see pjsip_pres_parse_pidf2() */ PJ_DECL(pj_status_t) pjsip_pres_parse_pidf(pjsip_rx_data *rdata, pj_pool_t *pool, pjsip_pres_status *status); +/** + * This is a utility function to parse PIDF body into PJSIP presence status. + * + * @param body Text body, with one extra space at the end to place + * NULL character temporarily during parsing. + * @param body_len Length of the body, not including the NULL termination + * character. + * @param pool Pool to allocate memory to copy the strings into + * the presence status structure. + * @param status The presence status to be initialized. + * + * @return PJ_SUCCESS on success. + * + * @see pjsip_pres_parse_pidf() + */ +PJ_DECL(pj_status_t) pjsip_pres_parse_pidf2(char *body, unsigned body_len, + pj_pool_t *pool, + pjsip_pres_status *status); /** @@ -344,12 +364,34 @@ PJ_DECL(pj_status_t) pjsip_pres_parse_pidf(pjsip_rx_data *rdata, * @param status The presence status to be initialized. * * @return PJ_SUCCESS on success. + * + * @see pjsip_pres_parse_xpidf2() */ PJ_DECL(pj_status_t) pjsip_pres_parse_xpidf(pjsip_rx_data *rdata, pj_pool_t *pool, pjsip_pres_status *status); +/** + * This is a utility function to parse X-PIDF body into PJSIP presence status. + * + * @param body Text body, with one extra space at the end to place + * NULL character temporarily during parsing. + * @param body_len Length of the body, not including the NULL termination + * character. + * @param pool Pool to allocate memory to copy the strings into + * the presence status structure. + * @param status The presence status to be initialized. + * + * @return PJ_SUCCESS on success. + * + * @see pjsip_pres_parse_xpidf() + */ +PJ_DECL(pj_status_t) pjsip_pres_parse_xpidf2(char *body, unsigned body_len, + pj_pool_t *pool, + pjsip_pres_status *status); + + /** * @} diff --git a/pjsip/src/pjsip-simple/presence.c b/pjsip/src/pjsip-simple/presence.c index 24049359..b2f48262 100644 --- a/pjsip/src/pjsip-simple/presence.c +++ b/pjsip/src/pjsip-simple/presence.c @@ -21,6 +21,7 @@ #include <pjsip-simple/errno.h> #include <pjsip-simple/evsub_msg.h> #include <pjsip/sip_module.h> +#include <pjsip/sip_multipart.h> #include <pjsip/sip_endpoint.h> #include <pjsip/sip_dialog.h> #include <pj/assert.h> @@ -682,6 +683,7 @@ static pj_status_t pres_process_rx_notify( pjsip_pres *pres, pj_str_t **p_st_text, pjsip_hdr *res_hdr) { + const pj_str_t STR_MULTIPART = { "multipart", 9 }; pjsip_ctype_hdr *ctype_hdr; pj_status_t status; @@ -707,7 +709,36 @@ static pj_status_t pres_process_rx_notify( pjsip_pres *pres, } /* Parse content. */ + if (pj_stricmp(&ctype_hdr->media.type, &STR_MULTIPART)==0) { + pjsip_multipart_part *mpart; + pjsip_media_type ctype; + + pjsip_media_type_init(&ctype, (pj_str_t*)&STR_APPLICATION, + (pj_str_t*)&STR_PIDF_XML); + mpart = pjsip_multipart_find_part(rdata->msg_info.msg->body, + &ctype, NULL); + if (mpart) { + status = pjsip_pres_parse_pidf2((char*)mpart->body->data, + mpart->body->len, pres->tmp_pool, + &pres->tmp_status); + } + if (mpart==NULL) { + pjsip_media_type_init(&ctype, (pj_str_t*)&STR_APPLICATION, + (pj_str_t*)&STR_XPIDF_XML); + mpart = pjsip_multipart_find_part(rdata->msg_info.msg->body, + &ctype, NULL); + if (mpart) { + status = pjsip_pres_parse_xpidf2((char*)mpart->body->data, + mpart->body->len, + pres->tmp_pool, + &pres->tmp_status); + } else { + status = PJSIP_SIMPLE_EBADCONTENT; + } + } + } + else if (pj_stricmp(&ctype_hdr->media.type, &STR_APPLICATION)==0 && pj_stricmp(&ctype_hdr->media.subtype, &STR_PIDF_XML)==0) { diff --git a/pjsip/src/pjsip-simple/presence_body.c b/pjsip/src/pjsip-simple/presence_body.c index a57e8df9..70ce0226 100644 --- a/pjsip/src/pjsip-simple/presence_body.c +++ b/pjsip/src/pjsip-simple/presence_body.c @@ -199,12 +199,19 @@ PJ_DEF(pj_status_t) pjsip_pres_parse_pidf( pjsip_rx_data *rdata, pj_pool_t *pool, pjsip_pres_status *pres_status) { + return pjsip_pres_parse_pidf2((char*)rdata->msg_info.msg->body->data, + rdata->msg_info.msg->body->len, + pool, pres_status); +} + +PJ_DEF(pj_status_t) pjsip_pres_parse_pidf2(char *body, unsigned body_len, + pj_pool_t *pool, + pjsip_pres_status *pres_status) +{ pjpidf_pres *pidf; pjpidf_tuple *pidf_tuple; - pidf = pjpidf_parse(rdata->tp_info.pool, - (char*)rdata->msg_info.msg->body->data, - rdata->msg_info.msg->body->len); + pidf = pjpidf_parse(pool, body, body_len); if (pidf == NULL) return PJSIP_SIMPLE_EBADPIDF; @@ -251,11 +258,18 @@ PJ_DEF(pj_status_t) pjsip_pres_parse_xpidf(pjsip_rx_data *rdata, pj_pool_t *pool, pjsip_pres_status *pres_status) { + return pjsip_pres_parse_xpidf2((char*)rdata->msg_info.msg->body->data, + rdata->msg_info.msg->body->len, + pool, pres_status); +} + +PJ_DEF(pj_status_t) pjsip_pres_parse_xpidf2(char *body, unsigned body_len, + pj_pool_t *pool, + pjsip_pres_status *pres_status) +{ pjxpidf_pres *xpidf; - xpidf = pjxpidf_parse(rdata->tp_info.pool, - (char*)rdata->msg_info.msg->body->data, - rdata->msg_info.msg->body->len); + xpidf = pjxpidf_parse(pool, body, body_len); if (xpidf == NULL) return PJSIP_SIMPLE_EBADXPIDF; diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.xml b/tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.xml new file mode 100644 index 00000000..49e42747 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.xml @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE scenario SYSTEM "sipp.dtd"> + +<!-- This program is free software; you can redistribute it and/or --> +<!-- modify it under the terms of the GNU General Public License as --> +<!-- published by the Free Software Foundation; either version 2 of the --> +<!-- License, or (at your option) any later version. --> +<!-- --> +<!-- This program is distributed in the hope that it will be useful, --> +<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of --> +<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --> +<!-- GNU General Public License for more details. --> +<!-- --> +<!-- You should have received a copy of the GNU General Public License --> +<!-- along with this program; if not, write to the --> +<!-- Free Software Foundation, Inc., --> +<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --> +<!-- --> +<!-- Late NOTIFY scenario: --> +<!-- - UAC sends SUBSCRIBE, we reply with 200 --> +<!-- - we send NOTIFY, expect 200 --> +<!-- - UAC sends SUBSCRIBE, we ignore --> +<!-- - we send NOTIFY --> +<!-- See http://trac.pjsip.org/repos/ticket/911 --> +<!-- --> + +<scenario name="SUBSCRIBE tests"> + <!-- Establish subscription --> + <recv request="SUBSCRIBE" crlf="true"> + <action> + <ereg regexp=".*" search_in="hdr" header="From" assign_to="3"/> + <ereg regexp="sip:(.*)>" search_in="hdr" header="Contact" assign_to="4,5"/> + <assign assign_to="4" variable="5" /> + </action> + </recv> + + <send> + <![CDATA[ + + SIP/2.0 200 OK + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:sipp@[local_ip]:[local_port]> + Content-Length: 0 + Expires: 60 + ]]> + </send> + + <send retrans="500"> + <![CDATA[ + NOTIFY sip:[$5] SIP/2.0 + Via: SIP/2.0/[transport] [local_ip]:[local_port];rport;branch=z9hG4bKPj01 + From: sipp <sip:sipp@[local_ip]>;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: presence + Subscription-State: active;expires=50 + Content-Type: multipart/mixed;boundary=abcd + + --abcd + Content-Type: text/plain + + Hi there, please don't read this part. + --abcd + Content-Type: application/pidf+xml + + <?xml version="1.0" encoding="UTF-8"?> + <presence xmlns="urn:ietf:params:xml:ns:pidf" xmlns:op="urn:oma:xml:prs:pidf:oma-pres" entity="sip:test@pjsip.org"> + <tuple id="17415d5738f332a64a2f1d8cfb4ab0a5"> + <status> + <basic>open</basic> + </status> + </tuple> + </presence> + --abcd-- + ]]> + </send> + + <recv response="200"> + </recv> + + <!-- Subscription has been established at this point --> + + + <!-- ******* + + Wait for subscription refresh, reply with 481 + + --> + + <recv request="SUBSCRIBE" crlf="true"> + </recv> + + <send> + <![CDATA[ + + SIP/2.0 481 You should resubscribe mow + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:sipp@[local_ip]:[local_port]> + Content-Length: 0 + ]]> + </send> + + + + + <!-- definition of the response time repartition table (unit is ms) --> + <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> + + <!-- definition of the call length repartition table (unit is ms) --> + <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> + +</scenario> + |