Changeset 3243
- Timestamp:
- Aug 1, 2010 9:48:51 AM (14 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 6 added
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/build.symbian/pjsip.mmp
r3046 r3243 44 44 SOURCE sip_errno.c 45 45 SOURCE sip_msg.c 46 SOURCE sip_multipart.c 46 47 SOURCE sip_parser_wrap.cpp 47 48 SOURCE sip_resolve.c -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r3216 r3243 27 27 //#define STEREO_DEMO 28 28 //#define TRANSPORT_ADAPTER_SAMPLE 29 //#define HAVE_MULTIPART_TEST 29 30 30 31 /* Ringtones US UK */ … … 2219 2220 } 2220 2221 2222 #ifdef HAVE_MULTIPART_TEST 2223 /* 2224 * Enable multipart in msg_data and add a dummy body into the 2225 * multipart bodies. 2226 */ 2227 static void add_multipart(pjsua_msg_data *msg_data) 2228 { 2229 static pjsip_multipart_part *alt_part; 2230 2231 if (!alt_part) { 2232 pj_str_t type, subtype, content; 2233 2234 alt_part = pjsip_multipart_create_part(app_config.pool); 2235 2236 type = pj_str("text"); 2237 subtype = pj_str("plain"); 2238 content = pj_str("Sample text body of a multipart bodies"); 2239 alt_part->body = pjsip_msg_body_create(app_config.pool, &type, 2240 &subtype, &content); 2241 } 2242 2243 msg_data->multipart_ctype.type = pj_str("multipart"); 2244 msg_data->multipart_ctype.subtype = pj_str("mixed"); 2245 pj_list_push_back(&msg_data->multipart_parts, alt_part); 2246 } 2247 # define TEST_MULTIPART(msg_data) add_multipart(msg_data) 2248 #else 2249 # define TEST_MULTIPART(msg_data) 2250 #endif 2251 2221 2252 /* 2222 2253 * Find next call when current call is disconnected or when user … … 3433 3464 pj_str_t tmp; 3434 3465 struct input_result result; 3466 pjsua_msg_data msg_data; 3435 3467 pjsua_call_info call_info; 3436 3468 pjsua_acc_info acc_info; … … 3501 3533 } 3502 3534 3503 pjsua_call_make_call( current_acc, &tmp, 0, NULL, NULL, NULL); 3535 pjsua_msg_data_init(&msg_data); 3536 TEST_MULTIPART(&msg_data); 3537 pjsua_call_make_call( current_acc, &tmp, 0, NULL, &msg_data, NULL); 3504 3538 break; 3505 3539 … … 3639 3673 pj_str_t hvalue; 3640 3674 pjsip_generic_string_hdr hcontact; 3641 pjsua_msg_data msg_data;3642 3675 3643 3676 if (!simple_input("Answer with code (100-699)", buf, sizeof(buf))) … … 3887 3920 } else { 3888 3921 int call = current_call; 3889 pjsua_msg_data msg_data;3890 3922 pjsip_generic_string_hdr refer_sub; 3891 3923 pj_str_t STR_REFER_SUB = { "Refer-Sub", 9 }; … … 3942 3974 int call = current_call; 3943 3975 int dst_call; 3944 pjsua_msg_data msg_data;3945 3976 pjsip_generic_string_hdr refer_sub; 3946 3977 pj_str_t STR_REFER_SUB = { "Refer-Sub", 9 }; … … 4084 4115 digits = pj_str(buf); 4085 4116 for (i=0; i<digits.slen; ++i) { 4086 pjsua_msg_data msg_data;4087 4117 char body[80]; 4088 4118 -
pjproject/trunk/pjsip/build/Makefile
r2970 r3243 37 37 export PJSIP_SRCDIR = ../src/pjsip 38 38 export PJSIP_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \ 39 sip_config.o \39 sip_config.o sip_multipart.o \ 40 40 sip_errno.o sip_msg.o sip_parser.o sip_tel_uri.o sip_uri.o \ 41 41 sip_endpoint.o sip_util.o sip_util_proxy.o \ … … 87 87 export TEST_SRCDIR = ../src/test 88 88 export TEST_OBJS += dlg_core_test.o dns_test.o msg_err_test.o \ 89 msg_logger.o msg_test.o regc_test.o \89 msg_logger.o msg_test.o multipart_test.o regc_test.o \ 90 90 test.o transport_loop_test.o transport_tcp_test.o \ 91 91 transport_test.o transport_udp_test.o \ -
pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h
r3222 r3243 383 383 384 384 /** 385 * This structure represents SDP information in a pjsip_rx_data. Application 386 * retrieve this information by calling #pjsip_rdata_get_sdp_info(). This 387 * mechanism supports multipart message body. 388 */ 389 typedef struct pjsip_rdata_sdp_info 390 { 391 /** 392 * Pointer and length of the text body in the incoming message. If 393 * the pointer is NULL, it means the message does not contain SDP 394 * body. 395 */ 396 pj_str_t body; 397 398 /** 399 * This will contain non-zero if an invalid SDP body is found in the 400 * message. 401 */ 402 pj_status_t sdp_err; 403 404 /** 405 * A parsed and validated SDP body. 406 */ 407 pjmedia_sdp_session *sdp; 408 409 } pjsip_rdata_sdp_info; 410 411 412 /** 385 413 * Initialize the invite usage module and register it to the endpoint. 386 414 * The callback argument contains pointer to functions to be called on … … 875 903 pjsip_msg_body **p_body); 876 904 905 /** 906 * Retrieve SDP information from an incoming message. Application should 907 * prefer to use this function rather than parsing the SDP manually since 908 * this function supports multipart message body. 909 * 910 * This function will only parse the SDP once, the first time it is called 911 * on the same message. Subsequent call on the same message will just pick 912 * up the already parsed SDP from the message. 913 * 914 * @param rdata The incoming message. 915 * 916 * @return The SDP info. 917 */ 918 PJ_DECL(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata); 919 877 920 878 921 PJ_END_DECL -
pjproject/trunk/pjsip/include/pjsip.h
r2394 r3243 29 29 #include <pjsip/sip_tel_uri.h> 30 30 #include <pjsip/sip_msg.h> 31 #include <pjsip/sip_multipart.h> 31 32 #include <pjsip/sip_parser.h> 32 33 -
pjproject/trunk/pjsip/include/pjsip/sip_parser.h
r2660 r3243 277 277 * pinpoint the location of the error in the buffer. 278 278 * 279 * @return The instance of the header if parsing was successful l,279 * @return The instance of the header if parsing was successful, 280 280 * or otherwise a NULL pointer will be returned. 281 281 */ … … 288 288 * When there are multiple headers, the headers MUST be separated by either 289 289 * a newline (as in SIP message) or ampersand mark (as in URI). This separator 290 * howeveris optional for the last header.291 * 292 * @param pool the pool.293 * @param input the input text to parse, which must be NULL terminated.294 * @param size the text length.295 * @param hlist the header list to store the parsed headers.290 * is optional for the last header. 291 * 292 * @param pool The pool. 293 * @param input The input text to parse, which must be NULL terminated. 294 * @param size The text length. 295 * @param hlist The header list to store the parsed headers. 296 296 * This list must have been initialized before calling 297 297 * this function. 298 * @param options Specify 1 here to make parsing stop when error is 299 * encountered when parsing the header. Otherwise the 300 * error is silently ignored and parsing resumes to the 301 * next line. 298 302 * @return zero if successfull, or -1 if error is encountered. 299 303 * Upon error, the \a hlist argument MAY contain 300 304 * successfully parsed headers. 301 305 */ 302 PJ_DECL(pj_status_t) pjsip_parse_headers( pj_pool_t *pool, 303 char *input, pj_size_t size,304 pj_list *hlist);306 PJ_DECL(pj_status_t) pjsip_parse_headers( pj_pool_t *pool, char *input, 307 pj_size_t size, pjsip_hdr *hlist, 308 unsigned options); 305 309 306 310 -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r3222 r3243 1187 1187 1188 1188 /** 1189 * Optional message body. 1189 * Optional message body to be added to the message, only when the 1190 * message doesn't have a body. 1190 1191 */ 1191 1192 pj_str_t msg_body; 1192 1193 1194 /** 1195 * Content type of the multipart body. If application wants to send 1196 * multipart message bodies, it puts the parts in \a parts and set 1197 * the content type in \a multipart_ctype. If the message already 1198 * contains a body, the body will be added to the multipart bodies. 1199 */ 1200 pjsip_media_type multipart_ctype; 1201 1202 /** 1203 * List of multipart parts. If application wants to send multipart 1204 * message bodies, it puts the parts in \a parts and set the content 1205 * type in \a multipart_ctype. If the message already contains a body, 1206 * the body will be added to the multipart bodies. 1207 */ 1208 pjsip_multipart_part multipart_parts; 1193 1209 }; 1194 1210 -
pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
r3222 r3243 24 24 #include <pjsip/sip_endpoint.h> 25 25 #include <pjsip/sip_event.h> 26 #include <pjsip/sip_multipart.h> 26 27 #include <pjsip/sip_transaction.h> 27 28 #include <pjmedia/sdp.h> … … 746 747 } 747 748 749 PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata) 750 { 751 pjsip_rdata_sdp_info *sdp_info; 752 pjsip_msg_body *body = rdata->msg_info.msg->body; 753 pjsip_ctype_hdr *ctype_hdr = rdata->msg_info.ctype; 754 pjsip_media_type app_sdp; 755 756 sdp_info = (pjsip_rdata_sdp_info*) 757 rdata->endpt_info.mod_data[mod_inv.mod.id]; 758 if (sdp_info) 759 return sdp_info; 760 761 sdp_info = PJ_POOL_ZALLOC_T(rdata->tp_info.pool, 762 pjsip_rdata_sdp_info); 763 PJ_ASSERT_RETURN(mod_inv.mod.id >= 0, sdp_info); 764 rdata->endpt_info.mod_data[mod_inv.mod.id] = sdp_info; 765 766 pjsip_media_type_init2(&app_sdp, "application", "sdp"); 767 768 if (body && ctype_hdr && 769 pj_stricmp(&ctype_hdr->media.type, &app_sdp.type)==0 && 770 pj_stricmp(&ctype_hdr->media.subtype, &app_sdp.subtype)==0) 771 { 772 sdp_info->body.ptr = (char*)body->data; 773 sdp_info->body.slen = body->len; 774 } else if (body && ctype_hdr && 775 pj_stricmp2(&ctype_hdr->media.type, "multipart")==0 && 776 (pj_stricmp2(&ctype_hdr->media.subtype, "mixed")==0 || 777 pj_stricmp2(&ctype_hdr->media.subtype, "alternative")==0)) 778 { 779 pjsip_multipart_part *part; 780 781 part = pjsip_multipart_find_part(body, &app_sdp, NULL); 782 if (part) { 783 sdp_info->body.ptr = (char*)part->body->data; 784 sdp_info->body.slen = part->body->len; 785 } 786 } 787 788 if (sdp_info->body.ptr) { 789 pj_status_t status; 790 status = pjmedia_sdp_parse(rdata->tp_info.pool, 791 sdp_info->body.ptr, 792 sdp_info->body.slen, 793 &sdp_info->sdp); 794 if (status == PJ_SUCCESS) 795 status = pjmedia_sdp_validate(sdp_info->sdp); 796 797 if (status != PJ_SUCCESS) { 798 sdp_info->sdp = NULL; 799 PJ_PERROR(1,(THIS_FILE, status, 800 "Error parsing/validating SDP body")); 801 } 802 803 sdp_info->sdp_err = status; 804 } 805 806 return sdp_info; 807 } 808 809 748 810 /* 749 811 * Verify incoming INVITE request. … … 766 828 pj_status_t status = PJ_SUCCESS; 767 829 pjsip_hdr res_hdr_list; 830 pjsip_rdata_sdp_info *sdp_info; 768 831 769 832 /* Init return arguments. */ … … 822 885 * only when the body hasn't been parsed before. 823 886 */ 887 if (r_sdp == NULL) { 888 sdp_info = pjsip_rdata_get_sdp_info(rdata); 889 } else { 890 sdp_info = NULL; 891 } 892 824 893 if (r_sdp==NULL && msg->body) { 825 pjsip_msg_body *body = msg->body; 826 pj_str_t str_application = {"application", 11}; 827 pj_str_t str_sdp = { "sdp", 3 }; 828 pjmedia_sdp_session *sdp; 829 830 /* Check content type. */ 831 if (pj_stricmp(&body->content_type.type, &str_application) != 0 || 832 pj_stricmp(&body->content_type.subtype, &str_sdp) != 0) 833 { 834 /* Not "application/sdp" */ 894 895 /* Check if body really contains SDP. */ 896 if (sdp_info->body.ptr == NULL) { 897 /* Couldn't find "application/sdp" */ 835 898 code = PJSIP_SC_UNSUPPORTED_MEDIA_TYPE; 836 899 status = PJSIP_ERRNO_FROM_SIP_STATUS(code); … … 849 912 } 850 913 851 /* Parse and validate SDP */ 852 status = pjmedia_sdp_parse(rdata->tp_info.pool, 853 (char*)body->data, body->len, &sdp); 854 if (status == PJ_SUCCESS) 855 status = pjmedia_sdp_validate(sdp); 856 857 if (status != PJ_SUCCESS) { 914 if (sdp_info->sdp_err != PJ_SUCCESS) { 858 915 /* Unparseable or invalid SDP */ 859 916 code = PJSIP_SC_BAD_REQUEST; … … 865 922 w = pjsip_warning_hdr_create_from_status(rdata->tp_info.pool, 866 923 pjsip_endpt_name(endpt), 867 s tatus);924 sdp_info->sdp_err); 868 925 PJ_ASSERT_RETURN(w, PJ_ENOMEM); 869 926 … … 874 931 } 875 932 876 r_sdp = sdp ;933 r_sdp = sdp_info->sdp; 877 934 } 878 935 … … 1164 1221 struct tsx_inv_data *tsx_inv_data; 1165 1222 pjsip_msg *msg; 1166 pj media_sdp_session *rem_sdp = NULL;1223 pjsip_rdata_sdp_info *sdp_info; 1167 1224 pj_status_t status; 1168 1225 … … 1212 1269 pj_ansi_snprintf(inv->obj_name, PJ_MAX_OBJ_NAME, "inv%p", dlg); 1213 1270 1214 /* Parse SDP in message body, if present. */ 1215 if (msg->body) { 1216 pjsip_msg_body *body = msg->body; 1217 1218 /* Parse and validate SDP */ 1219 status = pjmedia_sdp_parse(inv->pool, (char*)body->data, body->len, 1220 &rem_sdp); 1221 if (status == PJ_SUCCESS) 1222 status = pjmedia_sdp_validate(rem_sdp); 1223 1224 if (status != PJ_SUCCESS) { 1225 pjsip_dlg_dec_lock(dlg); 1226 return status; 1227 } 1271 /* Process SDP in message body, if present. */ 1272 sdp_info = pjsip_rdata_get_sdp_info(rdata); 1273 if (sdp_info->sdp_err) { 1274 pjsip_dlg_dec_lock(dlg); 1275 return sdp_info->sdp_err; 1228 1276 } 1229 1277 1230 1278 /* Create negotiator. */ 1231 if ( rem_sdp) {1232 status = pjmedia_sdp_neg_create_w_remote_offer(inv->pool, 1233 local_sdp, rem_sdp,1279 if (sdp_info->sdp) { 1280 status = pjmedia_sdp_neg_create_w_remote_offer(inv->pool, local_sdp, 1281 sdp_info->sdp, 1234 1282 &inv->neg); 1235 1283 … … 1375 1423 PJ_ASSERT_RETURN(body != NULL, PJ_ENOMEM); 1376 1424 1377 body->content_type.type = STR_APPLICATION;1378 body->content_type.subtype = STR_SDP;1425 pjsip_media_type_init(&body->content_type, (pj_str_t*)&STR_APPLICATION, 1426 (pj_str_t*)&STR_SDP); 1379 1427 body->data = sdp; 1380 1428 body->len = 0; … … 1528 1576 } 1529 1577 1578 1530 1579 /* 1531 1580 * Initiate SDP negotiation in the SDP negotiator. … … 1576 1625 { 1577 1626 struct tsx_inv_data *tsx_inv_data; 1578 static const pj_str_t str_application = { "application", 11 };1579 static const pj_str_t str_sdp = { "sdp", 3 };1580 1627 pj_status_t status; 1581 1628 pjsip_msg *msg; 1582 pj media_sdp_session *rem_sdp;1629 pjsip_rdata_sdp_info *sdp_info; 1583 1630 1584 1631 /* Check if SDP is present in the message. */ … … 1590 1637 } 1591 1638 1592 if (pj_stricmp(&msg->body->content_type.type, &str_application) || 1593 pj_stricmp(&msg->body->content_type.subtype, &str_sdp)) 1594 { 1639 sdp_info = pjsip_rdata_get_sdp_info(rdata); 1640 if (sdp_info->body.ptr == NULL) { 1595 1641 /* Message body is not "application/sdp" */ 1596 1642 return PJMEDIA_SDP_EINSDP; … … 1661 1707 } 1662 1708 1663 /* Parse the SDP body. */ 1664 1665 status = pjmedia_sdp_parse(rdata->tp_info.pool, 1666 (char*)msg->body->data, 1667 msg->body->len, &rem_sdp); 1668 if (status == PJ_SUCCESS) 1669 status = pjmedia_sdp_validate(rem_sdp); 1670 1671 if (status != PJ_SUCCESS) { 1672 char errmsg[PJ_ERR_MSG_SIZE]; 1673 pj_strerror(status, errmsg, sizeof(errmsg)); 1674 PJ_LOG(4,(THIS_FILE, "Error parsing SDP in %s: %s", 1675 pjsip_rx_data_get_info(rdata), errmsg)); 1709 /* Process the SDP body. */ 1710 if (sdp_info->sdp_err) { 1711 PJ_PERROR(4,(THIS_FILE, sdp_info->sdp_err, 1712 "Error parsing SDP in %s", 1713 pjsip_rx_data_get_info(rdata))); 1676 1714 return PJMEDIA_SDP_EINSDP; 1677 1715 } 1716 1717 pj_assert(sdp_info->sdp != NULL); 1678 1718 1679 1719 /* The SDP can be an offer or answer, depending on negotiator's state */ … … 1690 1730 if (inv->neg == NULL) { 1691 1731 status=pjmedia_sdp_neg_create_w_remote_offer(inv->pool, NULL, 1692 rem_sdp, &inv->neg); 1732 sdp_info->sdp, 1733 &inv->neg); 1693 1734 } else { 1694 1735 status=pjmedia_sdp_neg_set_remote_offer(inv->pool_prov, inv->neg, 1695 rem_sdp);1736 sdp_info->sdp); 1696 1737 } 1697 1738 1698 1739 if (status != PJ_SUCCESS) { 1699 char errmsg[PJ_ERR_MSG_SIZE]; 1700 pj_strerror(status, errmsg, sizeof(errmsg)); 1701 PJ_LOG(4,(THIS_FILE, "Error processing SDP offer in %s: %s", 1702 pjsip_rx_data_get_info(rdata), errmsg)); 1740 PJ_PERROR(4,(THIS_FILE, status, "Error processing SDP offer in %", 1741 pjsip_rx_data_get_info(rdata))); 1703 1742 return PJMEDIA_SDP_EINSDP; 1704 1743 } … … 1708 1747 if (mod_inv.cb.on_rx_offer && inv->notify) { 1709 1748 1710 (*mod_inv.cb.on_rx_offer)(inv, rem_sdp);1749 (*mod_inv.cb.on_rx_offer)(inv, sdp_info->sdp); 1711 1750 1712 1751 } … … 1725 1764 1726 1765 status = pjmedia_sdp_neg_set_remote_answer(inv->pool_prov, inv->neg, 1727 rem_sdp);1766 sdp_info->sdp); 1728 1767 1729 1768 if (status != PJ_SUCCESS) { 1730 char errmsg[PJ_ERR_MSG_SIZE]; 1731 pj_strerror(status, errmsg, sizeof(errmsg)); 1732 PJ_LOG(4,(THIS_FILE, "Error processing SDP answer in %s: %s", 1733 pjsip_rx_data_get_info(rdata), errmsg)); 1769 PJ_PERROR(4,(THIS_FILE, status, "Error processing SDP answer in %s", 1770 pjsip_rx_data_get_info(rdata))); 1734 1771 return PJMEDIA_SDP_EINSDP; 1735 1772 } … … 3856 3893 pjsip_tx_data *tdata; 3857 3894 pj_status_t status; 3895 pjsip_rdata_sdp_info *sdp_info; 3858 3896 pjsip_status_code st_code; 3859 3897 … … 3926 3964 * Otherwise generate offer from local active SDP. 3927 3965 */ 3928 if (rdata->msg_info.msg->body != NULL) { 3966 sdp_info = pjsip_rdata_get_sdp_info(rdata); 3967 if (sdp_info->sdp != NULL) { 3929 3968 status = process_answer(inv, 200, tdata, NULL); 3930 3969 } else { -
pjproject/trunk/pjsip/src/pjsip/sip_parser.c
r3003 r3243 21 21 #include <pjsip/sip_uri.h> 22 22 #include <pjsip/sip_msg.h> 23 #include <pjsip/sip_multipart.h> 23 24 #include <pjsip/sip_auth_parser.h> 24 25 #include <pjsip/sip_errno.h> … … 34 35 #include <pj/ctype.h> 35 36 #include <pj/assert.h> 37 38 #define THIS_FILE "sip_parser.c" 36 39 37 40 #define ALNUM … … 269 272 } 270 273 271 /* Concatenate unrecognized params into single string. */272 static void concat_param( pj_str_t *param, pj_pool_t *pool,273 const pj_str_t *pname, const pj_str_t *pvalue )274 {275 pjsip_concat_param_imp(param, pool, pname, pvalue, ';');276 }277 278 274 /* Initialize static properties of the parser. */ 279 275 static pj_status_t init_parser() … … 1053 1049 */ 1054 1050 if (ctype_hdr && scanner->curptr!=scanner->end) { 1055 pjsip_msg_body *body = PJ_POOL_ALLOC_T(pool, pjsip_msg_body); 1056 body->content_type.type = ctype_hdr->media.type; 1057 body->content_type.subtype = ctype_hdr->media.subtype; 1058 body->content_type.param = ctype_hdr->media.param; 1059 1060 body->data = scanner->curptr; 1061 body->len = scanner->end - scanner->curptr; 1062 body->print_body = &pjsip_print_text_body; 1063 body->clone_data = &pjsip_clone_text_data; 1051 /* New: if Content-Type indicates that this is a multipart 1052 * message body, parse it. 1053 */ 1054 const pj_str_t STR_MULTIPART = { "multipart", 9 }; 1055 pjsip_msg_body *body; 1056 1057 if (pj_stricmp(&ctype_hdr->media.type, &STR_MULTIPART)==0) { 1058 body = pjsip_multipart_parse(pool, scanner->curptr, 1059 scanner->end - scanner->curptr, 1060 &ctype_hdr->media, 0); 1061 } else { 1062 body = PJ_POOL_ALLOC_T(pool, pjsip_msg_body); 1063 body->content_type.type = ctype_hdr->media.type; 1064 body->content_type.subtype = ctype_hdr->media.subtype; 1065 body->content_type.param = ctype_hdr->media.param; 1066 1067 body->data = scanner->curptr; 1068 body->len = scanner->end - scanner->curptr; 1069 body->print_body = &pjsip_print_text_body; 1070 body->clone_data = &pjsip_clone_text_data; 1071 } 1064 1072 1065 1073 msg->body = body; … … 1848 1856 /* Parse media parameters */ 1849 1857 while (*scanner->curptr == ';') { 1850 pj _str_t pname, pvalue;1851 int_parse_param(scanner, ctx->pool, &p name, &pvalue, 0);1852 concat_param(&hdr->media.param, ctx->pool, &pname, &pvalue);1858 pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param); 1859 int_parse_param(scanner, ctx->pool, ¶m->name, ¶m->value, 0); 1860 pj_list_push_back(&hdr->media.param, param); 1853 1861 } 1854 1862 … … 2265 2273 } 2266 2274 2275 /* Parse multiple header lines */ 2276 PJ_DEF(pj_status_t) pjsip_parse_headers( pj_pool_t *pool, char *input, 2277 pj_size_t size, pjsip_hdr *hlist, 2278 unsigned options) 2279 { 2280 enum { STOP_ON_ERROR = 1 }; 2281 pj_scanner scanner; 2282 pjsip_parse_ctx ctx; 2283 pj_str_t hname; 2284 PJ_USE_EXCEPTION; 2285 2286 pj_scan_init(&scanner, input, size, PJ_SCAN_AUTOSKIP_WS_HEADER, 2287 &on_syntax_error); 2288 2289 pj_bzero(&ctx, sizeof(ctx)); 2290 ctx.scanner = &scanner; 2291 ctx.pool = pool; 2292 2293 retry_parse: 2294 PJ_TRY 2295 { 2296 /* Parse headers. */ 2297 do { 2298 pjsip_parse_hdr_func * handler; 2299 pjsip_hdr *hdr = NULL; 2300 2301 /* Init hname just in case parsing fails. 2302 * Ref: PROTOS #2412 2303 */ 2304 hname.slen = 0; 2305 2306 /* Get hname. */ 2307 pj_scan_get( &scanner, &pconst.pjsip_TOKEN_SPEC, &hname); 2308 if (pj_scan_get_char( &scanner ) != ':') { 2309 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); 2310 } 2311 2312 /* Find handler. */ 2313 handler = find_handler(&hname); 2314 2315 /* Call the handler if found. 2316 * If no handler is found, then treat the header as generic 2317 * hname/hvalue pair. 2318 */ 2319 if (handler) { 2320 hdr = (*handler)(&ctx); 2321 } else { 2322 hdr = parse_hdr_generic_string(&ctx); 2323 hdr->name = hdr->sname = hname; 2324 } 2325 2326 /* Single parse of header line can produce multiple headers. 2327 * For example, if one Contact: header contains Contact list 2328 * separated by comma, then these Contacts will be split into 2329 * different Contact headers. 2330 * So here we must insert list instead of just insert one header. 2331 */ 2332 if (hdr) 2333 pj_list_insert_nodes_before(hlist, hdr); 2334 2335 /* Parse until EOF or an empty line is found. */ 2336 } while (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr)); 2337 2338 /* If empty line is found, eat it. */ 2339 if (!pj_scan_is_eof(&scanner)) { 2340 if (IS_NEWLINE(*scanner.curptr)) { 2341 pj_scan_get_newline(&scanner); 2342 } 2343 } 2344 } 2345 PJ_CATCH_ANY 2346 { 2347 PJ_LOG(4,(THIS_FILE, "Error parsing header: '%.*s' line %d col %d", 2348 (int)hname.slen, hname.ptr, scanner.line, 2349 pj_scan_get_col(&scanner))); 2350 2351 /* Exception was thrown during parsing. */ 2352 if ((options & STOP_ON_ERROR) == STOP_ON_ERROR) { 2353 pj_scan_fini(&scanner); 2354 return PJSIP_EINVALIDHDR; 2355 } 2356 2357 /* Skip until newline, and parse next header. */ 2358 if (!pj_scan_is_eof(&scanner)) { 2359 /* Skip until next line. 2360 * Watch for header continuation. 2361 */ 2362 do { 2363 pj_scan_skip_line(&scanner); 2364 } while (IS_SPACE(*scanner.curptr)); 2365 } 2366 2367 /* Restore flag. Flag may be set in int_parse_sip_url() */ 2368 scanner.skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER; 2369 2370 /* Continue parse next header, if any. */ 2371 if (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr)) { 2372 goto retry_parse; 2373 } 2374 2375 } 2376 PJ_END; 2377 2378 return PJ_SUCCESS; 2379 } 2380 -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r3239 r3243 646 646 int call_id = -1; 647 647 int sip_err_code; 648 pjmedia_sdp_session *offer , *answer;648 pjmedia_sdp_session *offer=NULL, *answer; 649 649 pj_status_t status; 650 650 … … 766 766 /* Parse SDP from incoming request */ 767 767 if (rdata->msg_info.msg->body) { 768 status = pjmedia_sdp_parse(rdata->tp_info.pool, 769 (char*)rdata->msg_info.msg->body->data, 770 rdata->msg_info.msg->body->len, &offer); 771 if (status == PJ_SUCCESS) { 772 /* Validate */ 773 status = pjmedia_sdp_validate(offer); 774 } 768 pjsip_rdata_sdp_info *sdp_info; 769 770 sdp_info = pjsip_rdata_get_sdp_info(rdata); 771 offer = sdp_info->sdp; 772 773 status = sdp_info->sdp_err; 774 if (status==PJ_SUCCESS && sdp_info->sdp==NULL) 775 status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE); 775 776 776 777 if (status != PJ_SUCCESS) { -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r3216 r3243 143 143 pj_bzero(msg_data, sizeof(*msg_data)); 144 144 pj_list_init(&msg_data->hdr_list); 145 pjsip_media_type_init(&msg_data->multipart_ctype, NULL, NULL); 146 pj_list_init(&msg_data->multipart_parts); 145 147 } 146 148 … … 2226 2228 tdata->msg->body = body; 2227 2229 } 2230 2231 /* Multipart */ 2232 if (!pj_list_empty(&msg_data->multipart_parts) && 2233 msg_data->multipart_ctype.type.slen) 2234 { 2235 pjsip_msg_body *bodies; 2236 pjsip_multipart_part *part; 2237 pj_str_t *boundary = NULL; 2238 2239 bodies = pjsip_multipart_create(tdata->pool, 2240 &msg_data->multipart_ctype, 2241 boundary); 2242 part = msg_data->multipart_parts.next; 2243 while (part != &msg_data->multipart_parts) { 2244 pjsip_multipart_part *part_copy; 2245 2246 part_copy = pjsip_multipart_clone_part(tdata->pool, part); 2247 pjsip_multipart_add_part(tdata->pool, bodies, part_copy); 2248 part = part->next; 2249 } 2250 2251 if (tdata->msg->body) { 2252 part = pjsip_multipart_create_part(tdata->pool); 2253 part->body = tdata->msg->body; 2254 pjsip_multipart_add_part(tdata->pool, bodies, part); 2255 2256 tdata->msg->body = NULL; 2257 } 2258 2259 tdata->msg->body = bodies; 2260 } 2228 2261 } 2229 2262 -
pjproject/trunk/pjsip/src/test/test.c
r2660 r3243 302 302 #endif 303 303 304 #if INCLUDE_MULTIPART_TEST 305 DO_TEST(multipart_test()); 306 #endif 307 304 308 #if INCLUDE_TXDATA_TEST 305 309 DO_TEST(txdata_test()); -
pjproject/trunk/pjsip/src/test/test.h
r2638 r3243 57 57 #define INCLUDE_URI_TEST INCLUDE_MESSAGING_GROUP 58 58 #define INCLUDE_MSG_TEST INCLUDE_MESSAGING_GROUP 59 #define INCLUDE_MULTIPART_TEST INCLUDE_MESSAGING_GROUP 59 60 #define INCLUDE_TXDATA_TEST INCLUDE_MESSAGING_GROUP 60 61 #define INCLUDE_TSX_BENCH INCLUDE_MESSAGING_GROUP … … 72 73 int msg_test(void); 73 74 int msg_err_test(void); 75 int multipart_test(void); 74 76 int txdata_test(void); 75 77 int tsx_bench(void); -
pjproject/trunk/tests/pjsua/inc_sip.py
r3194 r3243 108 108 return msg 109 109 110 def create_req(self, method, sdp, branch="", extra_headers="" ):110 def create_req(self, method, sdp, branch="", extra_headers="", body=""): 111 111 if branch=="": 112 112 self.cseq = self.cseq + 1 … … 120 120 msg = msg.replace("$CONTENT_LENGTH", str(len(sdp))) 121 121 msg = msg + "Content-Type: application/sdp\r\n" 122 msg = msg + "\r\n" 123 msg = msg + sdp 124 elif body!="": 125 msg = msg.replace("$CONTENT_LENGTH", str(len(body))) 126 msg = msg + "\r\n" 127 msg = msg + body 122 128 else: 123 129 msg = msg.replace("$CONTENT_LENGTH", "0") 124 msg = msg + "\r\n"125 msg = msg + sdp126 130 return self.update_fields(msg) 127 131 … … 139 143 return response 140 144 141 def create_invite(self, sdp, extra_headers="" ):145 def create_invite(self, sdp, extra_headers="", body=""): 142 146 self.inv_branch = str(random.random()) 143 return self.create_req("INVITE", sdp, branch=self.inv_branch, extra_headers=extra_headers )147 return self.create_req("INVITE", sdp, branch=self.inv_branch, extra_headers=extra_headers, body=body) 144 148 145 149 def create_ack(self, sdp="", extra_headers=""): … … 253 257 # List of RE patterns that must NOT exist in response 254 258 resp_exclude = [] 259 # Full (non-SDP) body 260 body = "" 255 261 # Constructor 256 262 def __init__(self, name, pjsua_args, sdp, resp_code, 257 263 resp_inc=[], resp_exc=[], use_tcp=False, 258 extra_headers="", complete_msg="",264 extra_headers="", body="", complete_msg="", 259 265 enable_buffer = False): 260 266 self.complete_msg = complete_msg … … 265 271 self.use_tcp = use_tcp 266 272 self.extra_headers = extra_headers 273 self.body = body 267 274 self.inst_param = cfg.InstanceParam("pjsua", pjsua_args) 268 275 self.inst_param.enable_buffer = enable_buffer -
pjproject/trunk/tests/pjsua/mod_sendto.py
r2440 r3243 22 22 req = dlg.update_fields(cfg.complete_msg) 23 23 else: 24 req = dlg.create_invite(cfg.sdp, cfg.extra_headers )24 req = dlg.create_invite(cfg.sdp, cfg.extra_headers, cfg.body) 25 25 resp = dlg.send_request_wait(req, 10) 26 26 if resp=="":
Note: See TracChangeset
for help on using the changeset viewer.