void SIPCall::sendSIPInfo(const char *const body, const char *const subtype) { if (not inv or not inv->dlg) throw VoipLinkException("Couldn't get invite dialog"); pj_str_t methodName = CONST_PJ_STR("INFO"); pjsip_method method; pjsip_method_init_np(&method, &methodName); /* Create request message. */ pjsip_tx_data *tdata; if (pjsip_dlg_create_request(inv->dlg, &method, -1, &tdata) != PJ_SUCCESS) { RING_ERR("[call:%s] Could not create dialog", getCallId().c_str()); return; } /* Create "application/<subtype>" message body. */ pj_str_t content; pj_cstr(&content, body); const pj_str_t type = CONST_PJ_STR("application"); pj_str_t pj_subtype; pj_cstr(&pj_subtype, subtype); tdata->msg->body = pjsip_msg_body_create(tdata->pool, &type, &pj_subtype, &content); if (tdata->msg->body == NULL) pjsip_tx_data_dec_ref(tdata); else pjsip_dlg_send_request(inv->dlg, tdata, getSIPVoIPLink()->getModId(), NULL); }
void SIPPresence::fillDoc(pjsip_tx_data *tdata, const pres_msg_data *msg_data) { if (tdata->msg->type == PJSIP_REQUEST_MSG) { const pj_str_t STR_USER_AGENT = CONST_PJ_STR("User-Agent"); std::string useragent(acc_->getUserAgentName()); pj_str_t pJuseragent = pj_str((char*) useragent.c_str()); pjsip_hdr *h = (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool, &STR_USER_AGENT, &pJuseragent); pjsip_msg_add_hdr(tdata->msg, h); } if (msg_data == NULL) return; const pjsip_hdr *hdr; hdr = msg_data->hdr_list.next; while (hdr && hdr != &msg_data->hdr_list) { pjsip_hdr *new_hdr; new_hdr = (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, hdr); DEBUG("adding header", new_hdr->name.ptr); pjsip_msg_add_hdr(tdata->msg, new_hdr); hdr = hdr->next; } if (msg_data->content_type.slen && msg_data->msg_body.slen) { pjsip_msg_body *body; const pj_str_t type = CONST_PJ_STR("application"); const pj_str_t subtype = CONST_PJ_STR("pidf+xml"); body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &msg_data->msg_body); tdata->msg->body = body; } }
pj_status_t InstantMessaging::sip_send (pjsip_inv_session *session, std::string& id, const std::string& text) { pjsip_method msg_method; const pj_str_t type = STR_TEXT; const pj_str_t subtype = STR_PLAIN; pjsip_tx_data *tdata; pj_status_t status; pjsip_dialog* dialog; pj_str_t message; msg_method.id = PJSIP_OTHER_METHOD; msg_method.name = METHOD_NAME; // Get the dialog associated to the call dialog = session->dlg; // Convert the text into a format readable by pjsip message = pj_str ( (char*) text.c_str ()); // Must lock dialog pjsip_dlg_inc_lock (dialog); // Create the message request status = pjsip_dlg_create_request (dialog, &msg_method, -1, &tdata); PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1); // Attach "text/plain" body tdata->msg->body = pjsip_msg_body_create (tdata->pool, &type, &subtype, &message); // Create the Require header to handle recipient-list Content-Disposition type // pjsip_generic_string_hdr reqhdr; // pj_str_t reqhname = pj_str ("Require"); // pj_str_t reqhvalue = pj_str ("recipient-list"); // Create the Content-Type header to handle multipart/mixed and boundary MIME types // pj_str_t ctype = pj_str ("Content-Type"); // pj_str_t sctype = pj_str ("ctype"); // small version of the header name // ctypehdr = pjsip_msg_find_hdr_by_names (tdata->msg, &ctype, &sctype, NULL); // pjsip_generic_string_hdr ctypehdr; // pj_str_t ctypehname = pj_str ("Content-Type"); // pj_str_t ctypehvalue = pj_str ("multipart/mixed;boundary=\"boundary\""); // Add headers to the message // pjsip_generic_string_hdr_init2 (&reqhdr, &reqhname, &reqhvalue); // pj_list_push_back (& (tdata->msg->hdr), (pjsip_hdr*) (&reqhdr)); // pj_list_push_back (& (tdata->msg->hdr), (pjsip_hdr*) (&ctypehdr)); // Send the request status = pjsip_dlg_send_request (dialog, tdata, -1, NULL); // PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1); // Done pjsip_dlg_dec_lock (dialog); // Archive the message this->saveMessage (text, "Me", id); return PJ_SUCCESS; }
/* Send request */ static void send_request(const pjsip_method *method, int cseq, const pj_str_t *branch, pj_bool_t with_offer) { pjsip_tx_data *tdata; pj_str_t dummy_sdp_str = { "v=0\r\n" "o=- 3360842071 3360842071 IN IP4 192.168.0.68\r\n" "s=pjmedia\r\n" "c=IN IP4 192.168.0.68\r\n" "t=0 0\r\n" "m=audio 4000 RTP/AVP 0 101\r\n" "a=rtcp:4001 IN IP4 192.168.0.68\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=sendrecv\r\n" "a=rtpmap:101 telephone-event/8000\r\n" "a=fmtp:101 0-15\r\n", 0 }; pj_status_t status; status = pjsip_dlg_create_request(dlg, method, cseq, &tdata); pj_assert(status == PJ_SUCCESS); if (branch) { pjsip_via_hdr *via; via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); pj_strdup(tdata->pool, &via->branch_param, branch); } if (with_offer) { pjsip_msg_body *body; pj_str_t mime_application = { "application", 11}; pj_str_t mime_sdp = {"sdp", 3}; dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr); body = pjsip_msg_body_create(tdata->pool, &mime_application, &mime_sdp, &dummy_sdp_str); tdata->msg->body = body; } status = pjsip_dlg_send_request(dlg, tdata, -1, NULL); pj_assert(status == PJ_SUCCESS); }
static pj_bool_t mod_stateful_on_rx_request(pjsip_rx_data *rdata) { const pj_str_t stateful_user = { "1", 1 }; pjsip_uri *uri; pjsip_sip_uri *sip_uri; uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri); /* Only want to receive SIP/SIPS scheme */ if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) return PJ_FALSE; sip_uri = (pjsip_sip_uri*) uri; /* Check for matching user part */ if (pj_strcmp(&sip_uri->user, &stateful_user)!=0) return PJ_FALSE; /* * Yes, this is for us. * Respond statefully with 200/OK. */ switch (rdata->msg_info.msg->line.req.method.id) { case PJSIP_INVITE_METHOD: { pjsip_msg_body *body; if (dummy_sdp_str.slen == 0) dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr); body = pjsip_msg_body_create(rdata->tp_info.pool, &mime_application, &mime_sdp, &dummy_sdp_str); pjsip_endpt_respond(app.sip_endpt, &mod_stateful_server, rdata, 200, NULL, NULL, body, NULL); } break; case PJSIP_ACK_METHOD: return PJ_TRUE; default: pjsip_endpt_respond(app.sip_endpt, &mod_stateful_server, rdata, 200, NULL, NULL, NULL, NULL); break; } app.server.cur_state.stateful_cnt++; return PJ_TRUE; }
/* * Enable multipart in msg_data and add a dummy body into the * multipart bodies. */ void add_multipart(pjsua_msg_data *msg_data) { static pjsip_multipart_part *alt_part; if (!alt_part) { pj_str_t type, subtype, content; alt_part = pjsip_multipart_create_part(app_config.pool); type = pj_str("text"); subtype = pj_str("plain"); content = pj_str("Sample text body of a multipart bodies"); alt_part->body = pjsip_msg_body_create(app_config.pool, &type, &subtype, &content); } msg_data->multipart_ctype.type = pj_str("multipart"); msg_data->multipart_ctype.subtype = pj_str("mixed"); pj_list_push_back(&msg_data->multipart_parts, alt_part); }
void send_register_to_as(pjsip_rx_data *received_register, pjsip_tx_data *ok_response, AsInvocation& as, int expires, const std::string& served_user, SAS::TrailId trail) { pj_status_t status; pjsip_tx_data *tdata; pjsip_method method; pjsip_method_set(&method, PJSIP_REGISTER_METHOD); pj_str_t user_uri; pj_cstr(&user_uri, served_user.c_str()); pj_str_t as_uri; pj_cstr(&as_uri, as.server_name.c_str()); status = pjsip_endpt_create_request(stack_data.endpt, &method, // Method &as_uri, // Target &stack_data.scscf_uri, // From &user_uri, // To &stack_data.scscf_uri, // Contact NULL, // Auto-generate Call-ID 1, // CSeq NULL, // No body &tdata); // OUT if (status != PJ_SUCCESS) { //LCOV_EXCL_START LOG_ERROR("Failed to build third-party REGISTER request for server %s", as.server_name.c_str()); return; //LCOV_EXCL_STOP } // Expires header based on 200 OK response pjsip_expires_hdr_create(tdata->pool, expires); pjsip_expires_hdr* expires_hdr = pjsip_expires_hdr_create(tdata->pool, expires); pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)expires_hdr); // TODO: modify orig-ioi of P-Charging-Vector and remove term-ioi if (received_register && ok_response) { // Copy P-Access-Network-Info, P-Visited-Network-Id and P-Charging-Vector // from original message PJUtils::clone_header(&STR_P_A_N_I, received_register->msg_info.msg, tdata->msg, tdata->pool); PJUtils::clone_header(&STR_P_V_N_I, received_register->msg_info.msg, tdata->msg, tdata->pool); PJUtils::clone_header(&STR_P_C_V, received_register->msg_info.msg, tdata->msg, tdata->pool); // Copy P-Charging-Function-Addresses from the OK response. PJUtils::clone_header(&STR_P_C_F_A, ok_response->msg, tdata->msg, tdata->pool); // Generate a message body based on Filter Criteria values char buf[MAX_SIP_MSG_SIZE]; pj_str_t sip_type = pj_str("message"); pj_str_t sip_subtype = pj_str("sip"); pj_str_t xml_type = pj_str("application"); pj_str_t xml_subtype = pj_str("3gpp-ims+xml"); // Build up this multipart body incrementally, based on the ServiceInfo, IncludeRegisterRequest and IncludeRegisterResponse fields pjsip_msg_body *final_body = pjsip_multipart_create(tdata->pool, NULL, NULL); // If we only have one part, we don't want a multipart MIME body - store the reference to each one here to use instead pjsip_msg_body *possible_final_body = NULL; int multipart_parts = 0; if (!as.service_info.empty()) { pjsip_multipart_part *xml_part = pjsip_multipart_create_part(tdata->pool); std::string xml_str = "<ims-3gpp><service-info>"+as.service_info+"</service-info></ims-3gpp>"; pj_str_t xml_pj_str; pj_cstr(&xml_pj_str, xml_str.c_str()); xml_part->body = pjsip_msg_body_create(tdata->pool, &xml_type, &xml_subtype, &xml_pj_str), possible_final_body = xml_part->body; multipart_parts++; pjsip_multipart_add_part(tdata->pool, final_body, xml_part); } if (as.include_register_request) { pjsip_multipart_part *request_part = pjsip_multipart_create_part(tdata->pool); pjsip_msg_print(received_register->msg_info.msg, buf, sizeof(buf)); pj_str_t request_str = pj_str(buf); request_part->body = pjsip_msg_body_create(tdata->pool, &sip_type, &sip_subtype, &request_str), possible_final_body = request_part->body; multipart_parts++; pjsip_multipart_add_part(tdata->pool, final_body, request_part); } if (as.include_register_response) { pjsip_multipart_part *response_part = pjsip_multipart_create_part(tdata->pool); pjsip_msg_print(ok_response->msg, buf, sizeof(buf)); pj_str_t response_str = pj_str(buf); response_part->body = pjsip_msg_body_create(tdata->pool, &sip_type, &sip_subtype, &response_str), possible_final_body = response_part->body; multipart_parts++; pjsip_multipart_add_part(tdata->pool, final_body, response_part); } if (multipart_parts == 0) { final_body = NULL; } else if (multipart_parts == 1) { final_body = possible_final_body; } else { // Just use the multipart MIME body you've built up } tdata->msg->body = final_body; } // Set the SAS trail on the request. set_trail(tdata, trail); // Allocate a temporary structure to record the default handling for this // REGISTER, and send it statefully. ThirdPartyRegData* tsxdata = new ThirdPartyRegData; tsxdata->default_handling = as.default_handling; tsxdata->trail = trail; tsxdata->public_id = served_user; pj_status_t resolv_status = PJUtils::send_request(tdata, 0, tsxdata, &send_register_cb); if (resolv_status != PJ_SUCCESS) { delete tsxdata; // LCOV_EXCL_LINE } }
/* * Send instant messaging outside dialog, using the specified account for * route set and authentication. */ PJ_DEF(pj_status_t) pjsua_im_send( pjsua_acc_id acc_id, const pj_str_t *to, const pj_str_t *mime_type, const pj_str_t *content, const pjsua_msg_data *msg_data, void *user_data) { pjsip_tx_data *tdata; const pj_str_t mime_text_plain = pj_str("text/plain"); pjsip_media_type media_type; pjsua_im_data *im_data; pjsua_acc *acc; pj_status_t status; /* To and message body must be specified. */ PJ_ASSERT_RETURN(to && content, PJ_EINVAL); acc = &pjsua_var.acc[acc_id]; /* Create request. */ status = pjsip_endpt_create_request(pjsua_var.endpt, &pjsip_message_method, (msg_data && msg_data->target_uri.slen? &msg_data->target_uri: to), &acc->cfg.id, to, NULL, NULL, -1, NULL, &tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create request", status); return status; } /* If account is locked to specific transport, then set transport to * the request. */ if (acc->cfg.transport_id != PJSUA_INVALID_ID) { pjsip_tpselector tp_sel; pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel); pjsip_tx_data_set_transport(tdata, &tp_sel); } /* Add accept header. */ pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)pjsua_im_create_accept(tdata->pool)); /* Create suitable Contact header unless a Contact header has been * set in the account. */ /* Ticket #1632: According to RFC 3428: * MESSAGE requests do not initiate dialogs. * User Agents MUST NOT insert Contact header fields into MESSAGE requests */ /* if (acc->contact.slen) { contact = acc->contact; } else { status = pjsua_acc_create_uac_contact(tdata->pool, &contact, acc_id, to); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to generate Contact header", status); pjsip_tx_data_dec_ref(tdata); return status; } } pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool, &STR_CONTACT, &contact)); */ /* Create IM data to keep message details and give it back to * application on the callback */ im_data = PJ_POOL_ZALLOC_T(tdata->pool, pjsua_im_data); im_data->acc_id = acc_id; im_data->call_id = PJSUA_INVALID_ID; pj_strdup_with_null(tdata->pool, &im_data->to, to); pj_strdup_with_null(tdata->pool, &im_data->body, content); im_data->user_data = user_data; /* Set default media type if none is specified */ if (mime_type == NULL) { mime_type = &mime_text_plain; } /* Parse MIME type */ pjsua_parse_media_type(tdata->pool, mime_type, &media_type); /* Add message body */ tdata->msg->body = pjsip_msg_body_create( tdata->pool, &media_type.type, &media_type.subtype, &im_data->body); if (tdata->msg->body == NULL) { pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM); pjsip_tx_data_dec_ref(tdata); return PJ_ENOMEM; } /* Add additional headers etc. */ pjsua_process_msg_data(tdata, msg_data); /* Add route set */ pjsua_set_msg_route_set(tdata, &acc->route_set); /* If via_addr is set, use this address for the Via header. */ if (acc->cfg.allow_via_rewrite && acc->via_addr.host.slen > 0) { tdata->via_addr = acc->via_addr; tdata->via_tp = acc->via_tp; } /* Send request (statefully) */ status = pjsip_endpt_send_request( pjsua_var.endpt, tdata, -1, im_data, &im_callback); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to send request", status); return status; } return PJ_SUCCESS; }
/* * Send instant messaging outside dialog, using the specified account for * route set and authentication. */ PJ_DEF(pj_status_t) pjsua_im_send( pjsua_acc_id acc_id, const pj_str_t *to, const pj_str_t *mime_type, const pj_str_t *content, const pjsua_msg_data *msg_data, void *user_data) { pjsip_tx_data *tdata; const pj_str_t mime_text_plain = pj_str("text/plain"); const pj_str_t STR_CONTACT = { "Contact", 7 }; pjsip_media_type media_type; pjsua_im_data *im_data; pj_str_t contact; pj_status_t status; /* To and message body must be specified. */ PJ_ASSERT_RETURN(to && content, PJ_EINVAL); /* Create request. */ status = pjsip_endpt_create_request(pjsua_var.endpt, &pjsip_message_method, to, &pjsua_var.acc[acc_id].cfg.id, to, NULL, NULL, -1, NULL, &tdata); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create request", status); return status; } /* If account is locked to specific transport, then set transport to * the request. */ if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) { pjsip_tpselector tp_sel; pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel); pjsip_tx_data_set_transport(tdata, &tp_sel); } /* Add accept header. */ pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)pjsua_im_create_accept(tdata->pool)); /* Add contact. */ status = pjsua_acc_create_uac_contact(tdata->pool, &contact, acc_id, to); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to generate Contact header", status); pjsip_tx_data_dec_ref(tdata); return status; } pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool, &STR_CONTACT, &contact)); /* Create IM data to keep message details and give it back to * application on the callback */ im_data = PJ_POOL_ZALLOC_T(tdata->pool, pjsua_im_data); im_data->acc_id = acc_id; im_data->call_id = PJSUA_INVALID_ID; pj_strdup_with_null(tdata->pool, &im_data->to, to); pj_strdup_with_null(tdata->pool, &im_data->body, content); im_data->user_data = user_data; /* Set default media type if none is specified */ if (mime_type == NULL) { mime_type = &mime_text_plain; } /* Parse MIME type */ pjsua_parse_media_type(tdata->pool, mime_type, &media_type); /* Add message body */ tdata->msg->body = pjsip_msg_body_create( tdata->pool, &media_type.type, &media_type.subtype, &im_data->body); if (tdata->msg->body == NULL) { pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM); pjsip_tx_data_dec_ref(tdata); return PJ_ENOMEM; } /* Add additional headers etc. */ pjsua_process_msg_data(tdata, msg_data); /* Add route set */ pjsua_set_msg_route_set(tdata, &pjsua_var.acc[acc_id].route_set); /* Send request (statefully) */ status = pjsip_endpt_send_request( pjsua_var.endpt, tdata, -1, im_data, &im_callback); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to send request", status); return status; } return PJ_SUCCESS; }