summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2010-10-12 11:35:55 +0000
committerBenny Prijono <bennylp@teluu.com>2010-10-12 11:35:55 +0000
commit457b0d6cc6ade0a1c40b8712b30bd4abe2cd42ee (patch)
treeb551d72a66a2a9932260826ef376cb7f07935ccb
parent9cca1e24c9d348050b07a7ea5706dbad869022f3 (diff)
Closed #1146: support for multipart message bodies in incoming NOTIFY requests
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3337 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/include/pjsip-simple/presence.h42
-rw-r--r--pjsip/src/pjsip-simple/presence.c31
-rw-r--r--pjsip/src/pjsip-simple/presence_body.c26
-rw-r--r--tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.xml124
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>
+