/* * Create an empty multipart body. */ PJ_DEF(pjsip_msg_body*) pjsip_multipart_create( pj_pool_t *pool, const pjsip_media_type *ctype, const pj_str_t *boundary) { pjsip_msg_body *body; pjsip_param *ctype_param; struct multipart_data *mp_data; pj_str_t STR_BOUNDARY = { "boundary", 8 }; PJ_ASSERT_RETURN(pool, NULL); body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body); /* content-type */ if (ctype && ctype->type.slen) { pjsip_media_type_cp(pool, &body->content_type, ctype); } else { pj_str_t STR_MULTIPART = {"multipart", 9}; pj_str_t STR_MIXED = { "mixed", 5 }; pjsip_media_type_init(&body->content_type, &STR_MULTIPART, &STR_MIXED); } /* multipart data */ mp_data = PJ_POOL_ZALLOC_T(pool, struct multipart_data); pj_list_init(&mp_data->part_head); if (boundary) { pj_strdup(pool, &mp_data->boundary, boundary); } else { pj_create_unique_string(pool, &mp_data->boundary); } body->data = mp_data; /* Add ";boundary" parameter to content_type parameter. */ ctype_param = pjsip_param_find(&body->content_type.param, &STR_BOUNDARY); if (!ctype_param) { ctype_param = PJ_POOL_ALLOC_T(pool, pjsip_param); ctype_param->name = STR_BOUNDARY; pj_list_push_back(&body->content_type.param, ctype_param); } ctype_param->value = mp_data->boundary; /* function pointers */ body->print_body = &multipart_print_body; body->clone_data = &multipart_clone_data; return body; }
/* * Create NOTIFY */ PJ_DEF(pj_status_t) pjsip_mwi_notify( pjsip_evsub *sub, pjsip_evsub_state state, const pj_str_t *state_str, const pj_str_t *reason, const pjsip_media_type *mime_type, const pj_str_t *body, pjsip_tx_data **p_tdata) { pjsip_mwi *mwi; pjsip_tx_data *tdata; pj_status_t status; /* Check arguments. */ PJ_ASSERT_RETURN(sub && mime_type && body && p_tdata, PJ_EINVAL); /* Get the mwi object. */ mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id); PJ_ASSERT_RETURN(mwi != NULL, PJ_EINVALIDOP); /* Lock object. */ pjsip_dlg_inc_lock(mwi->dlg); /* Create the NOTIFY request. */ status = pjsip_evsub_notify( sub, state, state_str, reason, &tdata); if (status != PJ_SUCCESS) goto on_return; /* Update the cached message body */ if (mime_type || body) pj_pool_reset(mwi->body_pool); if (mime_type) pjsip_media_type_cp(mwi->body_pool, &mwi->mime_type, mime_type); if (body) pj_strdup(mwi->body_pool, &mwi->body, body); /* Create message body */ status = mwi_create_msg_body( mwi, tdata ); if (status != PJ_SUCCESS) goto on_return; /* Done. */ *p_tdata = tdata; on_return: pjsip_dlg_dec_lock(mwi->dlg); return status; }
/* * Create message body and attach it to the (NOTIFY) request. */ static pj_status_t mwi_create_msg_body( pjsip_mwi *mwi, pjsip_tx_data *tdata) { pjsip_msg_body *body; pj_str_t dup_text; PJ_ASSERT_RETURN(mwi->mime_type.type.slen && mwi->body.slen, PJ_EINVALIDOP); /* Clone the message body and mime type */ pj_strdup(tdata->pool, &dup_text, &mwi->body); /* Create the message body */ body = PJ_POOL_ZALLOC_T(tdata->pool, pjsip_msg_body); pjsip_media_type_cp(tdata->pool, &body->content_type, &mwi->mime_type); body->data = dup_text.ptr; body->len = (unsigned)dup_text.slen; body->print_body = &pjsip_print_text_body; body->clone_data = &pjsip_clone_text_data; /* Attach to tdata */ tdata->msg->body = body; return PJ_SUCCESS; }
/* Parse a multipart part. "pct" is parent content-type */ static pjsip_multipart_part *parse_multipart_part(pj_pool_t *pool, char *start, pj_size_t len, const pjsip_media_type *pct) { pjsip_multipart_part *part = pjsip_multipart_create_part(pool); char *p = start, *end = start+len, *end_hdr = NULL, *start_body = NULL; pjsip_ctype_hdr *ctype_hdr = NULL; TRACE_((THIS_FILE, "Parsing part: begin--\n%.*s\n--end", (int)len, start)); /* Find the end of header area, by looking at an empty line */ for (;;) { while (p!=end && *p!='\n') ++p; if (p==end) { start_body = end; break; } if ((p==start) || (p==start+1 && *(p-1)=='\r')) { /* Empty header section */ end_hdr = start; start_body = ++p; break; } else if (p==end-1) { /* Empty body section */ end_hdr = end; start_body = ++p; } else if ((p>=start+1 && *(p-1)=='\n') || (p>=start+2 && *(p-1)=='\r' && *(p-2)=='\n')) { /* Found it */ end_hdr = (*(p-1)=='\r') ? (p-1) : p; start_body = ++p; break; } else { ++p; } } /* Parse the headers */ if (end_hdr-start > 0) { pjsip_hdr *hdr; pj_status_t status; status = pjsip_parse_headers(pool, start, end_hdr-start, &part->hdr, 0); if (status != PJ_SUCCESS) { PJ_PERROR(2,(THIS_FILE, status, "Warning: error parsing multipart" " header")); } /* Find Content-Type header */ hdr = part->hdr.next; while (hdr != &part->hdr) { TRACE_((THIS_FILE, "Header parsed: %.*s", (int)hdr->name.slen, hdr->name.ptr)); if (hdr->type == PJSIP_H_CONTENT_TYPE) { ctype_hdr = (pjsip_ctype_hdr*)hdr; } hdr = hdr->next; } } /* Assign the body */ part->body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body); if (ctype_hdr) { pjsip_media_type_cp(pool, &part->body->content_type, &ctype_hdr->media); } else if (pct && pj_stricmp2(&pct->subtype, "digest")==0) { part->body->content_type.type = pj_str("message"); part->body->content_type.subtype = pj_str("rfc822"); } else { part->body->content_type.type = pj_str("text"); part->body->content_type.subtype = pj_str("plain"); } if (start_body < end) { part->body->data = start_body; part->body->len = (unsigned)(end - start_body); } else { part->body->data = (void*)""; part->body->len = 0; } TRACE_((THIS_FILE, "Body parsed: \"%.*s\"", (int)part->body->len, part->body->data)); part->body->print_body = &pjsip_print_text_body; part->body->clone_data = &pjsip_clone_text_data; return part; }