/* * Function: sipRelDevCoupledMessageStore * * Parameters: * pCoupledMessage - pointer to sipMessage_t for the message that * needed reliable delivery store. * call_id - pointer to const. char for the SIP call ID. * cseq_number - the uint32_t for CSeq of the message. * sipMethod_t - sipMethod_t the SIP method of the message. * dest_ipaddr - uint32_t IP address of the destination address. * dest_port - uint16_t destination port * ignore_tag - boolean to ignore tag. * * Description: * The function finds the corresponding entry in the gSIPRRList * array that matches call_id, cseq number, method and possibly tag. * If a match entry is found, the SIP message is composed and stored * in the corresponding entry. * * Returns: * idx - When the entry is found and successfully stored the * SIP message. * RELDEV_NO_STORED_MSG - encounter errors or no message is * stored. */ int sipRelDevCoupledMessageStore (sipMessage_t *pCoupledMessage, const char *call_id, uint32_t cseq_number, sipMethod_t cseq_method, boolean is_request, int response_code, cpr_ip_addr_t *dest_ipaddr, uint16_t dest_port, boolean ignore_tag) { static const char *fname = "sipRelDevCoupledMessageStore"; int i = 0; char to_tag[MAX_SIP_TAG_LENGTH]; sipGetMessageToTag(pCoupledMessage, to_tag, MAX_SIP_TAG_LENGTH); CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Storing for reTx (cseq=%d, method=%s, " "to_tag=<%s>)\n", DEB_F_PREFIX_ARGS(SIP_STORE, fname), cseq_number, sipGetMethodString(cseq_method), to_tag); for (i = 0; i < SIP_RRLIST_LENGTH; i++) { if ((strcmp(call_id, gSIPRRList[i].call_id) == 0) && (cseq_number == gSIPRRList[i].cseq_number) && (cseq_method == gSIPRRList[i].cseq_method) && ((ignore_tag) ? TRUE : (strcasecmp_ignorewhitespace(to_tag, gSIPRRList[i].tag) == 0))) { hStatus_t sippmh_write_status = STATUS_FAILURE; uint32_t nbytes = SIP_UDP_MESSAGE_SIZE; /* When storing the ACK message check that you are storing it coupled with the correct response code and not transitional responses */ if (is_request == FALSE || (is_request == TRUE && gSIPRRList[i].response_code == response_code)) { gSIPRRList[i].coupled_message.message_buf[0] = '\0'; sippmh_write_status = sippmh_write(pCoupledMessage, gSIPRRList[i].coupled_message.message_buf, &nbytes); if (sippmh_write_status == STATUS_FAILURE) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"sippmh_write() failed.", fname); return (RELDEV_NO_STORED_MSG); } if ((gSIPRRList[i].coupled_message.message_buf[0] == '\0') || (nbytes == 0)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"sippmh_write() returned empty buffer string.", fname); return (RELDEV_NO_STORED_MSG); } gSIPRRList[i].coupled_message.message_buf_len = nbytes; gSIPRRList[i].coupled_message.dest_ipaddr = *dest_ipaddr; gSIPRRList[i].coupled_message.dest_port = dest_port; gSIPRRList[i].valid_coupled_message = TRUE; /* Return the stored idx to the caller */ return (i); } } } return (RELDEV_NO_STORED_MSG); }
/** * This function will create the PUBLISH message and send it. it also starts the retry timer. * * @param[in] pcb_p - pointer to PCB * @param[in] authen - boolean that indicates whether to add authorization header. * * @return TRUE if it successfully sent PUBLISH * Otherwise, FALSE is returned * * @pre (pcb_p != NULL) */ static boolean sipSPISendPublish (ccsip_publish_cb_t *pcb_p, boolean authen) { static const char fname[] = "sipSPISendPublish"; static uint32_t cseq = 0; char dest_sip_addr_str[MAX_IPADDR_STR_LEN]; char *domainloc; char src_addr_str[MAX_IPADDR_STR_LEN]; char sip_temp_str[MAX_SIP_URL_LENGTH]; char sip_temp_tag[MAX_SIP_URL_LENGTH]; uint8_t mac_address[MAC_ADDRESS_LENGTH]; char via[SIP_MAX_VIA_LENGTH]; int max_forwards_value = 70; static uint16_t count = 1; sipMessage_t *request = NULL; int timeout = 0; request = GET_SIP_MESSAGE(); if (!request) { return FALSE; } /* * Populate full RURI if it is not yet. Sometimes, applications may only provide user part. */ if (pcb_p->full_ruri[0] == 0) { sstrncpy(pcb_p->full_ruri, "sip:", MAX_SIP_URL_LENGTH); sstrncat(pcb_p->full_ruri, pcb_p->ruri, MAX_SIP_URL_LENGTH - sizeof("sip:")); /* check if it has host part */ domainloc = strchr(pcb_p->full_ruri, '@'); if (domainloc == NULL) { domainloc = pcb_p->full_ruri + strlen(pcb_p->full_ruri); if ((domainloc - pcb_p->full_ruri) < (MAX_SIP_URL_LENGTH - 1)) { /* Do not include @ when there is no user part */ if (pcb_p->ruri[0] != '\0') { *domainloc++ = '@'; } ipaddr2dotted(dest_sip_addr_str, &pcb_p->hb.dest_sip_addr); sstrncpy(domainloc, dest_sip_addr_str, MAX_SIP_URL_LENGTH - (domainloc - (pcb_p->full_ruri))); } } } ipaddr2dotted(src_addr_str, &pcb_p->hb.src_addr); // Add request line if (HSTATUS_SUCCESS != sippmh_add_request_line(request, sipGetMethodString(sipMethodPublish), pcb_p->full_ruri, SIP_VERSION)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Request line\n", fname); free_sip_message(request); return (FALSE); } // Add local Via snprintf(via, sizeof(via), "SIP/2.0/%s %s:%d;%s=%s%.8x", sipTransportGetTransportType(1, TRUE, NULL), src_addr_str, pcb_p->hb.local_port, VIA_BRANCH, VIA_BRANCH_START, (unsigned int) cpr_rand()); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_VIA, via)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding VIA header\n", fname); free_sip_message(request); return (FALSE); } // Add To Header snprintf(sip_temp_str, MAX_SIP_URL_LENGTH, "<%s>", pcb_p->full_ruri); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_TO, sip_temp_str)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding TO header\n", fname); free_sip_message(request); return (FALSE); } // Add From Header. sstrncat(sip_temp_str, ";tag=", MAX_SIP_URL_LENGTH - strlen(sip_temp_str)); sip_util_make_tag(sip_temp_tag); sstrncat(sip_temp_str, sip_temp_tag, MAX_SIP_URL_LENGTH - strlen(sip_temp_str)); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_FROM, sip_temp_str)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding FROM header\n", fname); free_sip_message(request); return (FALSE); } // Add Call-ID Header. platform_get_wired_mac_address(mac_address); count++; snprintf(pcb_p->hb.sipCallID, MAX_SIP_CALL_ID, "%.4x%.4x-%.4x%.4x-%.8x-%.8x@%s", // was MAX_SIP_URL_LENGTH mac_address[0] * 256 + mac_address[1], mac_address[2] * 256 + mac_address[3], mac_address[4] * 256 + mac_address[5], count, (unsigned int) cpr_rand(), (unsigned int) cpr_rand(), src_addr_str); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_CALLID, pcb_p->hb.sipCallID)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding CALLID header\n", fname); free_sip_message(request); return (FALSE); } // Add Contact header. Contact header is not needed as per RFC. BUT CCM needs it. snprintf(sip_temp_str, MAX_SIP_URL_LENGTH, "<sip:%.4x%.4x%.4x@%s:%d>", mac_address[0] * 256 + mac_address[1], mac_address[2] * 256 + mac_address[3], mac_address[4] * 256 + mac_address[5], src_addr_str, pcb_p->hb.local_port); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_CONTACT, sip_temp_str)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Contact header\n", fname); free_sip_message(request); return (FALSE); } // Add Cseq. cseq++; if (cseq == 0) { cseq = 1; } if (HSTATUS_SUCCESS != sippmh_add_cseq(request, sipGetMethodString(sipMethodPublish), cseq)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding CSEQ header\n", fname); free_sip_message(request); return (FALSE); } // Add UserAgent header (void) sippmh_add_text_header(request, SIP_HEADER_USER_AGENT, sipHeaderUserAgent); // Add SIP-If-Match header. if (pcb_p->entity_tag != NULL) { if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_SIPIFMATCH, pcb_p->entity_tag)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Event header\n", fname); free_sip_message(request); return (FALSE); } } // Add Expires Header if (HSTATUS_SUCCESS != sippmh_add_int_header(request, SIP_HEADER_EXPIRES, pcb_p->hb.orig_expiration)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Expires header\n", fname); free_sip_message(request); return (FALSE); } // Add max-forwards header config_get_value(CFGID_SIP_MAX_FORWARDS, &max_forwards_value, sizeof(max_forwards_value)); if (HSTATUS_SUCCESS != sippmh_add_int_header(request, SIP_HEADER_MAX_FORWARDS, max_forwards_value)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Max-Forwards header\n", fname); free_sip_message(request); return (FALSE); } // add Authorization header if (authen) { if (HSTATUS_SUCCESS != sippmh_add_text_header(request, AUTHOR_HDR(pcb_p->hb.authen.status_code), pcb_p->hb.authen.authorization)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Authorization header\n", fname); free_sip_message(request); return (FALSE); } } // Add content, if any if (pcb_p->hb.event_data_p) { if (add_content(pcb_p->hb.event_data_p, request, fname) == FALSE) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Content\n", fname); free_sip_message(request); return (FALSE); } } else { if (HSTATUS_SUCCESS != sippmh_add_int_header(request, SIP_HEADER_CONTENT_LENGTH, 0)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Content-Len\n", fname); free_sip_message(request); return (FALSE); } } ccsip_common_util_set_retry_settings(&pcb_p->hb, &timeout); if (sipTransportCreateSendMessage(NULL, request, sipMethodPublish, &(pcb_p->hb.dest_sip_addr), (int16_t) pcb_p->hb.dest_sip_port, FALSE, TRUE, timeout, pcb_p, RELDEV_NO_STORED_MSG) < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to send PUBLISH message\n", fname); return (FALSE); } return (TRUE); }