add sipcc to tree for sdp parser

This commit is contained in:
Michael Jerris committed 2012-12-17 20:15:23 -05:00
1 parent 36f89c8b7c
commit 0f00946782
369 files changed
+183596

No files matched your search

+677
View File
@@ -0,0 +1,677 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <limits.h>
#include <errno.h>
#include "ccsip_callinfo.h"
#include "ccsip_protocol.h"
#include "ccsip_core.h"
#include "cpr_string.h"
#include "cpr_strings.h"
#include "cpr_types.h"
#include "cpr_stdio.h"
#include "cpr_memory.h"
#include "cpr_stdlib.h"
#include "phone_debug.h"
#define FEAT_STRING_SIZE 80
/*
* which_feature
*
* Description:
*
* A quick determination of the feature based on the string.
*/
static cc_call_info_e
which_feature (char *feat_string_p)
{
if (cpr_strcasecmp(feat_string_p, SIP_CI_HOLD_STR) == 0)
return CC_FEAT_HOLD;
if (cpr_strcasecmp(feat_string_p, SIP_CI_RESUME_STR) == 0)
return CC_FEAT_RESUME;
if (cpr_strcasecmp(feat_string_p, SIP_CI_BARGE_STR) == 0)
return CC_FEAT_BARGE;
if (cpr_strcasecmp(feat_string_p, SIP_CI_CBARGE_STR) == 0)
return CC_FEAT_CBARGE;
if (cpr_strcasecmp(feat_string_p, SIP_CI_CALL_INFO_STR) == 0)
return CC_FEAT_CALLINFO;
return CC_FEAT_NONE;
}
/*
* parse_call_info_parm
*
* Description:
*
* Parse potential callinfo feature parms.
*/
static void
parse_call_info_parm (char *parm_p, cc_call_info_data_t * feature_data_p)
{
static const char fname[] = "parse_call_info_parm";
char *temp_p;
uint16_t instance_id;
unsigned long strtoul_result;
char *strtoul_end;
if (!parm_p)
return;
while (parm_p) {
parm_p++;
SKIP_LWS(parm_p);
if (!cpr_strncasecmp(parm_p, SIP_CI_SECURITY,
sizeof(SIP_CI_SECURITY) - 1)) {
parm_p = parm_p + sizeof(SIP_CI_SECURITY) - 1;
SKIP_LWS(parm_p);
if (*parm_p) {
feature_data_p->call_info_feat_data.feature_flag |= CC_SECURITY;
if (!cpr_strncasecmp(parm_p, SIP_CI_SECURITY_UNKNOWN,
sizeof(SIP_CI_SECURITY_UNKNOWN) - 1)) {
feature_data_p->call_info_feat_data.security = CC_SECURITY_UNKNOWN;
} else if (!cpr_strncasecmp(parm_p, SIP_CI_SECURITY_AUTH,
sizeof(SIP_CI_SECURITY_AUTH) - 1)) {
feature_data_p->call_info_feat_data.security = CC_SECURITY_AUTHENTICATED;
} else if (!cpr_strncasecmp(parm_p, SIP_CI_SECURITY_ENCRYPTED,
sizeof(SIP_CI_SECURITY_ENCRYPTED) - 1)) {
feature_data_p->call_info_feat_data.security = CC_SECURITY_ENCRYPTED;
} else if (!cpr_strncasecmp(parm_p, SIP_CI_SECURITY_NOT_AUTH,
sizeof(SIP_CI_SECURITY_NOT_AUTH) - 1)) {
feature_data_p->call_info_feat_data.security = CC_SECURITY_NOT_AUTHENTICATED;
} else {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "Unknown security"
" value %s\n", fname, parm_p);
feature_data_p->call_info_feat_data.security = CC_SECURITY_UNKNOWN;
}
} else {
break;
}
} else if (!cpr_strncasecmp(parm_p, SIP_CI_POLICY,
sizeof(SIP_CI_POLICY) - 1)) {
parm_p = parm_p + sizeof(SIP_CI_POLICY) - 1;
SKIP_LWS(parm_p);
if (*parm_p) {
feature_data_p->call_info_feat_data.feature_flag |= CC_POLICY;
if (!cpr_strncasecmp(parm_p, SIP_CI_POLICY_CHAPERONE ,
sizeof(SIP_CI_POLICY_CHAPERONE) - 1)) {
feature_data_p->call_info_feat_data.policy = CC_POLICY_CHAPERONE;
} else if (!cpr_strncasecmp(parm_p, SIP_CI_POLICY_UNKNOWN,
sizeof(SIP_CI_POLICY_UNKNOWN) - 1)) {
feature_data_p->call_info_feat_data.policy = CC_POLICY_UNKNOWN;
} else {
CCSIP_DEBUG_ERROR("%s ERROR: Unknown policy"
" value %s\n", fname, parm_p) ;
feature_data_p->call_info_feat_data.policy = CC_POLICY_UNKNOWN;
}
} else {
break;
}
} else if (!cpr_strncasecmp(parm_p, SIP_CI_ORIENTATION,
sizeof(SIP_CI_ORIENTATION) - 1)) {
parm_p = parm_p + sizeof(SIP_CI_ORIENTATION) - 1;
SKIP_LWS(parm_p);
if (*parm_p) {
feature_data_p->call_info_feat_data.feature_flag |= CC_ORIENTATION;
if (!cpr_strncasecmp(parm_p, SIP_CI_ORIENTATION_FROM,
sizeof(SIP_CI_ORIENTATION_FROM) - 1)) {
feature_data_p->call_info_feat_data.orientation = CC_ORIENTATION_FROM;
} else if (!cpr_strncasecmp(parm_p, SIP_CI_ORIENTATION_TO,
sizeof(SIP_CI_ORIENTATION_TO) - 1)) {
feature_data_p->call_info_feat_data.orientation = CC_ORIENTATION_TO;
} else {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "Unknown orientation info"
" value %s\n", fname, parm_p);
feature_data_p->call_info_feat_data.orientation = CC_ORIENTATION_NONE;
}
} else {
break;
}
} else if (!cpr_strncasecmp(parm_p, SIP_CI_UI_STATE,
sizeof(SIP_CI_UI_STATE) - 1)) {
parm_p = parm_p + sizeof(SIP_CI_UI_STATE) - 1;
SKIP_LWS(parm_p);
if (*parm_p) {
feature_data_p->call_info_feat_data.feature_flag |= CC_UI_STATE;
if (!cpr_strncasecmp(parm_p, SIP_CI_UI_STATE_RINGOUT,
sizeof(SIP_CI_UI_STATE_RINGOUT) - 1)) {
feature_data_p->call_info_feat_data.ui_state = CC_UI_STATE_RINGOUT;
} else if (!cpr_strncasecmp(parm_p, SIP_CI_UI_STATE_CONNECTED,
sizeof(SIP_CI_UI_STATE_CONNECTED) - 1)) {
feature_data_p->call_info_feat_data.ui_state = CC_UI_STATE_CONNECTED;
} else if (!cpr_strncasecmp(parm_p, SIP_CI_UI_STATE_BUSY,
sizeof(SIP_CI_UI_STATE_BUSY) - 1)) {
feature_data_p->call_info_feat_data.ui_state = CC_UI_STATE_BUSY;
} else {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "Unknown call state"
" value %s\n", fname, parm_p);
/* Unknown value, ignore the call state */
feature_data_p->call_info_feat_data.feature_flag &=
~(CC_UI_STATE);
feature_data_p->call_info_feat_data.ui_state =
CC_UI_STATE_NONE;
}
} else {
break;
}
} else if (!cpr_strncasecmp(parm_p, SIP_CI_CALL_INSTANCE,
sizeof(SIP_CI_CALL_INSTANCE) - 1)) {
parm_p = parm_p + sizeof(SIP_CI_CALL_INSTANCE) - 1;
SKIP_LWS(parm_p);
if (*parm_p) {
int idx=0;
char tempbuf[4];
feature_data_p->call_info_feat_data.feature_flag |= CC_CALL_INSTANCE;
/* Initialized the call instance id, just in case */
feature_data_p->call_info_feat_data.caller_id.call_instance_id
= 0;
/* Parse instance id from line */
temp_p = parm_p;
while (isdigit((int) *parm_p)&&idx<3) {
tempbuf[idx++] = *parm_p++;
}
tempbuf[idx] = 0;
if (idx == 0) {
/* Did not find any digit after "call_instance=" */
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "no digits found for"
" call_instance parameter.\n", fname);
feature_data_p->call_info_feat_data.feature_flag &=
~(CC_CALL_INSTANCE);
break;
} else {
errno = 0;
strtoul_result = strtoul(tempbuf, &strtoul_end, 10);
if (errno || tempbuf == strtoul_end || strtoul_result > USHRT_MAX) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "parse error for call_instance_id: %s",
__FUNCTION__, tempbuf);
strtoul_result = 0;
}
feature_data_p->call_info_feat_data.caller_id.call_instance_id =
(uint16_t) strtoul_result;
}
} else {
break;
}
} else if (!cpr_strncasecmp(parm_p, SIP_CI_PRIORITY,
sizeof(SIP_CI_PRIORITY) - 1)) {
parm_p = parm_p + sizeof(SIP_CI_PRIORITY) - 1;
SKIP_LWS(parm_p);
if (*parm_p) {
temp_p = parm_p;
if ((!cpr_strncasecmp(parm_p, SIP_CI_PRIORITY_URGENT,
sizeof(SIP_CI_PRIORITY_URGENT) - 1)) ||
(!cpr_strncasecmp(parm_p, SIP_CI_PRIORITY_EMERGENCY,
sizeof(SIP_CI_PRIORITY_EMERGENCY) - 1))) {
feature_data_p->call_info_feat_data.priority = CC_CALL_PRIORITY_URGENT;
} // otherwise, it will be defaulted to normal priority
else {
errno = 0;
strtoul_result = strtoul(temp_p, &strtoul_end, 10);
if (errno || temp_p == strtoul_end || strtoul_result > MAX_INSTANCES) {
/*
* Call instance ID should not exceed max instances
* or calls.
*/
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "invalid call_instance"
" value %u\n", fname, (unsigned) strtoul_result);
feature_data_p->call_info_feat_data.feature_flag &=
~(CC_CALL_INSTANCE);
} else {
instance_id = (uint16_t) strtoul_result;
feature_data_p->call_info_feat_data.caller_id.call_instance_id = instance_id;
}
}
}
} else if (!cpr_strncasecmp(parm_p, SIP_CI_GCID,
sizeof(SIP_CI_GCID) - 1)) {
parm_p = parm_p + sizeof(SIP_CI_GCID) - 1;
SKIP_LWS(parm_p);
memset(feature_data_p->call_info_feat_data.global_call_id, 0, CC_GCID_LEN);
if (*parm_p) {
temp_p = strchr(parm_p, SEMI_COLON);
if (temp_p) {
unsigned int length = ((temp_p - parm_p)<CC_GCID_LEN) ?
(temp_p - parm_p):(CC_GCID_LEN);
sstrncpy(feature_data_p->call_info_feat_data.global_call_id, parm_p, length);
} else {
// No Semicolon found this could be the last parameter
sstrncpy(feature_data_p->call_info_feat_data.global_call_id, parm_p, CC_GCID_LEN);
}
feature_data_p->call_info_feat_data.global_call_id[CC_GCID_LEN-1] = 0;
}
} else if (!cpr_strncasecmp(parm_p, SIP_CI_DUSTINGCALL,
sizeof(SIP_CI_DUSTINGCALL) - 1)) {
parm_p = parm_p + sizeof(SIP_CI_DUSTINGCALL) - 1;
SKIP_LWS(parm_p);
feature_data_p->call_info_feat_data.dusting = TRUE;
}
parm_p = strchr(parm_p, SEMI_COLON);
}
}
/*
* parse_gen_parm
*
* Description:
*
* Parse feature parms where the only expected parm is the purpose.
*/
static void
parse_gen_parm (char *parm_p, cc_call_info_data_t * feature_data_p)
{
if (!parm_p)
return;
while (parm_p) {
parm_p++;
SKIP_LWS(parm_p);
if (!cpr_strncasecmp(parm_p, SIP_CI_GENERIC,
sizeof(SIP_CI_GENERIC) - 1)) {
parm_p = parm_p + sizeof(SIP_CI_GENERIC) - 1;
SKIP_LWS(parm_p);
if (*parm_p) {
if (!cpr_strncasecmp(parm_p, SIP_CI_GENERIC_ICON,
sizeof(SIP_CI_GENERIC_ICON) - 1)) {
feature_data_p->purpose = CC_PURPOSE_ICON;
} else {
if (!cpr_strncasecmp(parm_p, SIP_CI_GENERIC_INFO,
sizeof(SIP_CI_GENERIC_INFO) - 1)) {
feature_data_p->purpose = CC_PURPOSE_INFO;
} else {
if (!cpr_strncasecmp(parm_p, SIP_CI_GENERIC_CARD,
sizeof(SIP_CI_GENERIC_CARD) - 1)) {
feature_data_p->purpose = CC_PURPOSE_CARD;
}
}
}
}
} else {
break;
}
parm_p = strchr(parm_p, SEMI_COLON);
}
}
/*
* set_parm_defaults
*
* Description:
*
* A quick determination of the feature based on the string.
*/
static void
set_parm_defaults (cc_call_info_t *call_info_p)
{
switch (call_info_p->type) {
case CC_FEAT_HOLD:
case CC_FEAT_RESUME:
case CC_FEAT_NONE:
call_info_p->data.hold_resume_reason = CC_REASON_NONE;
break;
case CC_FEAT_BARGE:
case CC_FEAT_CBARGE:
call_info_p->data.purpose = CC_PURPOSE_NONE;
break;
case CC_FEAT_CALLINFO:
call_info_p->data.call_info_feat_data.policy = CC_POLICY_NONE;
call_info_p->data.call_info_feat_data.security = CC_SECURITY_NONE;
call_info_p->data.call_info_feat_data.orientation = CC_ORIENTATION_NONE;
call_info_p->data.call_info_feat_data.ui_state = CC_UI_STATE_NONE;
call_info_p->data.call_info_feat_data.priority = CC_CALL_PRIORITY_NORMAL;
call_info_p->data.call_info_feat_data.global_call_id[0] = 0;
call_info_p->data.call_info_feat_data.dusting = FALSE;
break;
default:
break;
}
}
/*
* ccsip_decode_call_info_hdr
*
* Description:
*
* Main method which decodes a single call info header and stores the
* related parms.
*
* Example Input:
* ---------------
* <urn:x-cisco-remotecc:hold>; reason= conference
* <urn:x-cisco-remotecc:callinfo>; seCuRity=unsecure; orienTation= to
*/
static void
ccsip_decode_call_info_hdr (const char *call_info_hdr_p,
cc_call_info_t *call_info_p)
{
char *ptr = NULL;
char *laq_ptr = NULL;
char *raq_ptr = NULL;
boolean ret_val = FALSE;
char feat_string[FEAT_STRING_SIZE];
memset(feat_string, '\0', sizeof(feat_string));
/*
* call_info_hdr_p and call_info_p are verified by caller so they
* are not checked here.
*/
ptr = laq_ptr = strchr(call_info_hdr_p, LAQUOT);
raq_ptr = strchr(call_info_hdr_p, RAQUOT);
// Parse out the remotecc string and the feature string.
if (laq_ptr && raq_ptr) {
ptr++;
// Verify the remotecc string.
if (!cpr_strncasecmp(ptr, URN_REMOTECC, sizeof(URN_REMOTECC) - 1)) {
ptr += sizeof(URN_REMOTECC) - 1;
sstrncpy(feat_string, ptr, raq_ptr - ptr + 1);
// Which feature do we have in this header?
call_info_p->type = which_feature(feat_string);
if (call_info_p->type != CC_FEAT_NONE) {
ret_val = TRUE;
set_parm_defaults(call_info_p);
}
}
}
if (!ret_val) {
return;
}
if (!(ptr = strchr(raq_ptr, SEMI_COLON))) {
return;
}
switch (call_info_p->type) {
case CC_FEAT_CALLINFO:
parse_call_info_parm(ptr, &call_info_p->data);
break;
default:
parse_gen_parm(ptr, &call_info_p->data);
}
}
/*
* ccsip_encode_call_info_hdr
*
* Description:
*
* Encode the call info header using the passed in feature id and
* feature specific data.
*
* The miscParms parameter will usually be null. It exists in case
* you want to toss in an additional string parm without using the
* encoding mechanism. An example would be "extraParm= text".
*
* Remember to delete the store in the return parm. It is the
* caller's responsibility.
*/
char *
ccsip_encode_call_info_hdr (cc_call_info_t *call_info_p,
const char *misc_parms_p)
{
static const char *fname = "ccsip_encode_call_info_hdr";
char *header;
header = (char *) cpr_malloc(MAX_SIP_HEADER_LENGTH);
if (!header) {
return NULL;
}
if (!call_info_p) {
cpr_free(header);
return NULL;
}
snprintf(header, MAX_SIP_HEADER_LENGTH, "<%s", URN_REMOTECC);
switch (call_info_p->type) {
case CC_FEAT_HOLD:
case CC_FEAT_RESUME:
if (call_info_p->type == CC_FEAT_HOLD) {
sstrncat(header, SIP_CI_HOLD_STR,
MAX_SIP_HEADER_LENGTH - strlen(header));
} else {
sstrncat(header, SIP_CI_RESUME_STR,
MAX_SIP_HEADER_LENGTH - strlen(header));
}
sstrncat(header, ">", MAX_SIP_HEADER_LENGTH - strlen(header));
switch (call_info_p->data.hold_resume_reason) {
case CC_REASON_NONE:
case CC_REASON_INTERNAL:
case CC_REASON_SWAP:
break;
case CC_REASON_XFER:
sstrncat(header, "; reason= ",
MAX_SIP_HEADER_LENGTH - strlen(header));
sstrncat(header, SIP_CI_HOLD_REASON_XFER,
MAX_SIP_HEADER_LENGTH - strlen(header));
break;
case CC_REASON_CONF:
sstrncat(header, "; reason= ",
MAX_SIP_HEADER_LENGTH - strlen(header));
sstrncat(header, SIP_CI_HOLD_REASON_CONF,
MAX_SIP_HEADER_LENGTH - strlen(header));
break;
default:
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "unsupported hold_resume_reason\n",
fname);
cpr_free(header);
return NULL;
}
/* Add swap information */
if (call_info_p->data.call_info_feat_data.swap == TRUE) {
sstrncat(header, "; operation= swap",
MAX_SIP_HEADER_LENGTH - strlen(header));
}
if (call_info_p->data.call_info_feat_data.protect == TRUE) {
sstrncat(header, "; protect= true; noholdreversion",
MAX_SIP_HEADER_LENGTH - strlen(header));
}
break;
case CC_FEAT_INIT_CALL:
/* Add global call id here */
if (call_info_p->data.initcall.gcid[0] != '\0') {
sstrncat(header, "callinfo>; gci= ",
MAX_SIP_HEADER_LENGTH - strlen(header));
sstrncat(header, call_info_p->data.initcall.gcid,
MAX_SIP_HEADER_LENGTH - strlen(header));
} else {
cpr_free(header);
return NULL;
}
/* Add the monitor mode here if it exists */
if (call_info_p->data.initcall.monitor_mode != CC_MONITOR_NONE) {
sstrncat(header, "; mode=",
MAX_SIP_HEADER_LENGTH - strlen(header));
switch (call_info_p->data.initcall.monitor_mode) {
case CC_MONITOR_SILENT :
sstrncat(header, SIP_CI_SILENT_STR,
MAX_SIP_HEADER_LENGTH - strlen(header));
break;
case CC_MONITOR_COACHING :
sstrncat(header, SIP_CI_COACHING_STR,
MAX_SIP_HEADER_LENGTH - strlen(header));
break;
default:
break;
}
}
break;
case CC_FEAT_TOGGLE_TO_WHISPER_COACHING:
sstrncat(header, "callinfo>",
MAX_SIP_HEADER_LENGTH - strlen(header));
sstrncat(header, "; mode=",
MAX_SIP_HEADER_LENGTH - strlen(header));
sstrncat(header, SIP_CI_COACHING_STR,
MAX_SIP_HEADER_LENGTH - strlen(header));
break;
case CC_FEAT_TOGGLE_TO_SILENT_MONITORING:
sstrncat(header, "callinfo>",
MAX_SIP_HEADER_LENGTH - strlen(header));
sstrncat(header, "; mode=",
MAX_SIP_HEADER_LENGTH - strlen(header));
sstrncat(header, SIP_CI_SILENT_STR,
MAX_SIP_HEADER_LENGTH - strlen(header));
break;
default:
cpr_free(header);
return NULL;
}
if (misc_parms_p) {
sstrncat(header, misc_parms_p,
MAX_SIP_HEADER_LENGTH - strlen(header));
}
sstrncat(header, "\0", MAX_SIP_HEADER_LENGTH - strlen(header));
return (header);
}
/*
* ccsip_free_call_info_header
*
* Description:
*
* Frees the memory allocated to a call info structure.
*/
void
ccsip_free_call_info_header (cc_call_info_t *call_info_p)
{
if(call_info_p->type == CC_FEAT_CALLINFO) {
}
cpr_free(call_info_p);
}
/*
* ccsip_process_call_info_header
*
* Description:
*
* Checks if there is a call info header in the provided SIP message. If there is,
* the call info in the CCB is cleared and the new call info is parsed into the
* CCB call info structure.
*/
void
ccsip_process_call_info_header (sipMessage_t *request_p, ccsipCCB_t *ccb)
{
char *call_info_hdrs[MAX_CALL_INFO_HEADERS];
uint16_t num_call_info_headers;
int i = 0;
if (!ccb) {
return;
}
if (ccb->in_call_info) {
ccsip_free_call_info_header(ccb->in_call_info);
ccb->in_call_info = NULL;
}
if (!request_p) {
return;
}
memset(call_info_hdrs, 0, MAX_CALL_INFO_HEADERS * sizeof(char *));
num_call_info_headers = sippmh_get_num_particular_headers(request_p,
SIP_HEADER_CALL_INFO,
SIP_HEADER_CALL_INFO,
call_info_hdrs,
MAX_CALL_INFO_HEADERS);
if (num_call_info_headers > 0) {
ccb->in_call_info = (cc_call_info_t *)
cpr_calloc(1, sizeof(cc_call_info_t));
if (ccb->in_call_info) {
ccb->in_call_info->data.call_info_feat_data.feature_flag = 0;
// Parse each Call-Info header
for (i = 0; i < MAX_CALL_INFO_HEADERS; i++) {
if (call_info_hdrs[i]) {
ccsip_decode_call_info_hdr(call_info_hdrs[i], ccb->in_call_info);
}
}
} else {
ccb->in_call_info = NULL;
}
}
}
/*
* ccsip_store_call_info
*
* Description: Used for storing call_info received from GSM
*
* Store specified call info structure in ccb.
*/
void
ccsip_store_call_info (cc_call_info_t *call_info_p, ccsipCCB_t *ccb)
{
if (!ccb) {
return;
}
if (ccb->out_call_info) {
ccsip_free_call_info_header(ccb->out_call_info);
ccb->out_call_info = NULL;
}
if (call_info_p->type != CC_FEAT_NONE) {
ccb->out_call_info = (cc_call_info_t *)
cpr_malloc(sizeof(cc_call_info_t));
if (ccb->out_call_info) {
memcpy(ccb->out_call_info, call_info_p, sizeof(cc_call_info_t));
} else {
ccb->out_call_info = NULL;
}
}
}
+305
View File
@@ -0,0 +1,305 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "ccapi.h"
#include "string_lib.h"
#include "ccsip_pmh.h"
#include "ccsip_messaging.h"
/*
* Function: sip_cc_mv_msg_body_to_cc_msg
*
* Parameters: cc_msg - pointer to cc_msgbody_info structure to
* move the content from the SIP body msg. to.
* sip_msg - pointer to sipMessage_t structure of the source
* body.
*
* Description: This routine moves the body parts from sipMessage_t to
* CCAPI body msg. Once the content is moved,
* the all pointers from the sipMessage_t structure,
* will be NULL so that they are not own by SIP stack.
* The destination of the msg. needs to free the
* memory for of the parts.
*
* Returns: N/A
*
*/
void sip_cc_mv_msg_body_to_cc_msg (cc_msgbody_info_t *cc_msg,
sipMessage_t *sip_msg)
{
int i;
uint32_t num_parts = 0;
cc_msgbody_t *part;
if (cc_msg == NULL) {
/* destination to move msg. to */
return;
}
if (sip_msg == NULL) {
/* No SIP message to move from, set number of part to zero */
cc_msg->num_parts = 0;
return;
}
part = &cc_msg->parts[0];
for (i = 0; (i < sip_msg->num_body_parts) &&
(i < CC_MAX_BODY_PARTS); i++) {
if ((sip_msg->mesg_body[i].msgBody != NULL) &&
(sip_msg->mesg_body[i].msgLength)) {
/* Body */
part->body = sip_msg->mesg_body[i].msgBody;
part->body_length = sip_msg->mesg_body[i].msgLength;
sip_msg->mesg_body[i].msgBody = NULL;
/* Content type */
part->content_type =
sip2cctype(sip_msg->mesg_body[i].msgContentTypeValue);
/* Disposition */
part->content_disposition.disposition =
sip2ccdisp(sip_msg->mesg_body[i].msgContentDisp);
part->content_disposition.required_handling =
sip_msg->mesg_body[i].msgRequiredHandling;
/* Content ID */
part->content_id = sip_msg->mesg_body[i].msgContentId;
sip_msg->mesg_body[i].msgContentId = NULL;
/* Next part */
part++;
num_parts++;
}
}
/* Set the number of parts */
cc_msg->num_parts = num_parts;
}
/*
* Function: sip_cc_create_cc_msg_body_from_sip_msg
*
* Parameters: cc_msg - pointer to cc_msgbody_info structure to
* store the content of the SIP body msg.
* sip_msg - pointer to sipMessage_t structure of the source
* body.
*
* Description: This routine creates the cc_msgbody_info_t content
* from the SIP message. The original msg. body in the
* SIP message remains in the SIP message.
*
* Returns: TRUE - success
* FALSE - fail.
*
*/
boolean sip_cc_create_cc_msg_body_from_sip_msg (cc_msgbody_info_t *cc_msg,
sipMessage_t *sip_msg)
{
int i, len;
uint32_t num_parts = 0;
cc_msgbody_t *part;
boolean status = TRUE;
if (cc_msg == NULL) {
/* destination to move msg. to */
return (FALSE);
}
if (sip_msg == NULL) {
/* No SIP message to move from, set number of part to zero */
cc_msg->num_parts = 0;
return (FALSE);
}
memset(cc_msg, 0, sizeof(cc_msgbody_info_t));
part = &cc_msg->parts[0];
for (i = 0; (i < sip_msg->num_body_parts) &&
(i < CC_MAX_BODY_PARTS) ; i++) {
if ((sip_msg->mesg_body[i].msgBody != NULL) &&
(sip_msg->mesg_body[i].msgLength)) {
/* Body */
part->body = (char *) cpr_malloc(sip_msg->mesg_body[i].msgLength);
if (part->body != NULL) {
part->body_length = sip_msg->mesg_body[i].msgLength;
memcpy(part->body,
sip_msg->mesg_body[i].msgBody,
sip_msg->mesg_body[i].msgLength);
} else {
/* Unable to allocate memory for msg. body */
status = FALSE;
break;
}
/* Content type */
part->content_type =
sip2cctype(sip_msg->mesg_body[i].msgContentTypeValue);
/* Disposition */
part->content_disposition.disposition =
sip2ccdisp(sip_msg->mesg_body[i].msgContentDisp);
part->content_disposition.required_handling =
sip_msg->mesg_body[i].msgRequiredHandling;
/* Content ID */
if (sip_msg->mesg_body[i].msgContentId != NULL) {
/* Get length of the msgContentID with NULL */
len = strlen(sip_msg->mesg_body[i].msgContentId) + 1;
part->content_id = (char *) cpr_malloc(len);
if (part->content_id != NULL) {
memcpy(part->content_id,
sip_msg->mesg_body[i].msgContentId,
len);
} else {
/* Unable to allocate allocate memory for content ID */
status = FALSE;
break;
}
} else {
/* No content ID */
part->content_id = NULL;
}
/* Next part */
part++;
num_parts++;
}
}
/* Set the number of parts */
cc_msg->num_parts = num_parts;
if (!status) {
/*
* Faied for some reason, free the resources that mighe be
* created before failure
*/
cc_free_msg_body_parts(cc_msg);
}
return (status);
}
void sip_cc_setup (callid_t call_id, line_t line,
string_t calling_name, string_t calling_number, string_t alt_calling_number,
boolean display_calling_number,
string_t called_name, string_t called_number,
boolean display_called_number,
string_t orig_called_name, string_t orig_called_number,
string_t last_redirect_name, string_t last_redirect_number,
cc_call_type_e call_type,
cc_alerting_type alert_info,
vcm_ring_mode_t alerting_ring,
vcm_tones_t alerting_tone, cc_call_info_t *call_info_p,
boolean replaces, string_t recv_info_list, sipMessage_t *sip_msg)
{
cc_caller_id_t caller_id;
cc_msgbody_info_t cc_body_info;
caller_id.calling_name = calling_name;
caller_id.calling_number = calling_number;
caller_id.alt_calling_number = alt_calling_number;
caller_id.display_calling_number = display_calling_number;
caller_id.called_name = called_name;
caller_id.called_number = called_number;
caller_id.display_called_number = display_called_number;
caller_id.last_redirect_name = last_redirect_name;
caller_id.last_redirect_number = last_redirect_number;
caller_id.orig_called_name = orig_called_name;
caller_id.orig_called_number = orig_called_number;
caller_id.orig_rpid_number = strlib_empty();
caller_id.call_type = call_type;
/* Move the SIP body parts to the CCAPI msg. body information block */
sip_cc_mv_msg_body_to_cc_msg(&cc_body_info, sip_msg);
// Check with CraigB
cc_setup(CC_SRC_SIP, call_id, line, &caller_id, alert_info,
alerting_ring, alerting_tone, NULL, call_info_p, replaces,
recv_info_list, &cc_body_info);
}
#ifdef REMOVED_UNUSED_FUNCTION
void sip_cc_setup_ack (callid_t call_id, line_t line,
cc_msgbody_info_t *msg_body)
{
cc_setup_ack(CC_SRC_SIP, call_id, line, NULL, msg_body);
}
#endif
void sip_cc_proceeding (callid_t call_id, line_t line)
{
cc_proceeding(CC_SRC_SIP, call_id, line, NULL);
}
void sip_cc_alerting (callid_t call_id, line_t line,
sipMessage_t *sip_msg, int inband)
{
cc_msgbody_info_t cc_body_info;
/* Move the SIP body parts to the CCAPI msg. body information block */
sip_cc_mv_msg_body_to_cc_msg(&cc_body_info, sip_msg);
cc_alerting(CC_SRC_SIP, call_id, line, NULL, &cc_body_info,
(boolean)inband);
}
void sip_cc_connected (callid_t call_id, line_t line, string_t recv_info_list, sipMessage_t *sip_msg)
{
cc_msgbody_info_t cc_body_info;
/* Move the SIP body parts to the CCAPI msg. body information block */
sip_cc_mv_msg_body_to_cc_msg(&cc_body_info, sip_msg);
cc_connected(CC_SRC_SIP, call_id, line, NULL, recv_info_list, &cc_body_info);
}
void sip_cc_connected_ack (callid_t call_id, line_t line,
sipMessage_t *sip_msg)
{
cc_msgbody_info_t cc_body_info;
/* Move the SIP body parts to the CCAPI msg. body information block */
sip_cc_mv_msg_body_to_cc_msg(&cc_body_info, sip_msg);
cc_connected_ack(CC_SRC_SIP, call_id, line, NULL, &cc_body_info);
}
void sip_cc_release (callid_t call_id, line_t line, cc_causes_t cause,
const char *dialstring)
{
cc_release(CC_SRC_SIP, call_id, line, cause, dialstring, NULL);
}
void sip_cc_release_complete (callid_t call_id, line_t line, cc_causes_t cause)
{
cc_release_complete(CC_SRC_SIP, call_id, line, cause, NULL);
}
void sip_cc_feature (callid_t call_id, line_t line, cc_features_t feature, void *data)
{
cc_feature(CC_SRC_SIP, call_id, line, feature, (cc_feature_data_t *)data);
}
void sip_cc_feature_ack (callid_t call_id, line_t line, cc_features_t feature,
void *data, cc_causes_t cause)
{
cc_feature_ack(CC_SRC_SIP, call_id, line, feature, (cc_feature_data_t *)data, cause);
}
void sip_cc_mwi (callid_t call_id, line_t line, boolean on, int type,
int newCount, int oldCount, int hpNewCount, int hpOldCount)
{
cc_mwi(CC_SRC_SIP, call_id, line, on, type, newCount, oldCount, hpNewCount, hpOldCount);
}
void sip_cc_options (callid_t call_id, line_t line, sipMessage_t *pSipMessage)
{
cc_options_sdp_req(CC_SRC_SIP, call_id, line, pSipMessage);
}
void sip_cc_audit (callid_t call_id, line_t line, boolean apply_ringout)
{
cc_audit_sdp_req(CC_SRC_SIP, call_id, line, apply_ringout);
}
@@ -0,0 +1,260 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_in.h"
#include "ccsip_common_cb.h"
#include "sip_common_transport.h"
#include "prot_configmgr.h"
#include "ccsip_register.h"
#include "util_string.h"
/**
* This function will set dest ip and port in common control block of SCB and PCB.
*
* @param[in] cb_p - pointer to the header control block.
*
* @return none
*
* @pre (cb_p != NULL)
*/
void ccsip_common_util_set_dest_ipaddr_port (ccsip_common_cb_t *cb_p)
{
char addr[MAX_IPADDR_STR_LEN];
if (cb_p->dest_sip_addr.type == CPR_IP_ADDR_INVALID) {
sipTransportGetPrimServerAddress(cb_p->dn_line, addr);
dns_error_code = sipTransportGetServerAddrPort(addr,
&cb_p->dest_sip_addr,
(uint16_t *)&cb_p->dest_sip_port,
&cb_p->SRVhandle,
FALSE);
if (dns_error_code == 0) {
util_ntohl(&(cb_p->dest_sip_addr), &(cb_p->dest_sip_addr));
} else {
sipTransportGetServerIPAddr(&(cb_p->dest_sip_addr), cb_p->dn_line);
}
cb_p->dest_sip_port = ((dns_error_code == 0) && (cb_p->dest_sip_port)) ?
ntohs((uint16_t)cb_p->dest_sip_port) :
(sipTransportGetPrimServerPort(cb_p->dn_line));
}
}
/**
* This function will set source ip in common control block of SCB and PCB.
*
* @param[in] cb_p - pointer to the header control block.
*
* @return none
*
* @pre (cb_p != NULL)
*/
void ccsip_common_util_set_src_ipaddr (ccsip_common_cb_t *cb_p)
{
int nat_enable = 0;
config_get_value(CFGID_NAT_ENABLE, &nat_enable, sizeof(nat_enable));
if (nat_enable == 0) {
sip_config_get_net_device_ipaddr(&(cb_p->src_addr));
} else {
sip_config_get_nat_ipaddr(&(cb_p->src_addr));
}
}
/*
* This function will set retry settings in common control block of SCB and PCB.
*
* Description: Based on transport used, determines the value to be
* used to set either TimerE or TimerF
* 1. For reliable tranport: we SHOULD start timer F (= 64*T1),
* no retransmits are required.
* 2. To prevent retransmits for TCP/TLS, we set scbp->retx_counter
* to Max value.
* 3. For unreliable tranport: we SHOULD start timer E (= T1),
* retransmits are required.
* This routine must only be invoked before sending a request for
* the first time with valid args.
*
* @param[in] cb_p - pointer to header control block.
* @param[out] timeout_p - returns the value to be used to set a timer.
*
* @return none
*
* @pre (cb_p != NULL) and (timeout_p != NULL)
*/
void ccsip_common_util_set_retry_settings (ccsip_common_cb_t *cb_p, int *timeout_p)
{
uint32_t max_retx = 0;
const char *transport = NULL;
*timeout_p = 0;
cb_p->retx_flag = TRUE;
config_get_value(CFGID_TIMER_T1, timeout_p, sizeof(*timeout_p));
transport = sipTransportGetTransportType(cb_p->dn_line, TRUE, NULL);
if (transport) {
if (strcmp(transport, "UDP") == 0) {
cb_p->retx_counter = 0;
} else {
config_get_value(CFGID_SIP_RETX, &max_retx, sizeof(max_retx));
if (max_retx > MAX_NON_INVITE_RETRY_ATTEMPTS) {
max_retx = MAX_NON_INVITE_RETRY_ATTEMPTS;
}
cb_p->retx_counter = max_retx;
(*timeout_p) = (64 * (*timeout_p));
}
}
}
/**
* This function will generate authorization header value.
*
* @param[in] pSipMessage - pointer to sipMessage_t
* @param[in] cb_p - pointer to header control block.
* @param[in] rsp_method - response method
* @param[in] response_code - response code
* @param[in] uri - uri
*
* @return TRUE if it is successful.
*
* @pre (cb_p != NULL) and (pSipMessage != NULL) and (rsp_method != NULL) and (uri != NULL)
*/
boolean ccsip_common_util_generate_auth (sipMessage_t *pSipMessage, ccsip_common_cb_t *cb_p,
const char *rsp_method, int response_code, char *uri)
{
static const char fname[] = "ccsip_common_util_generate_auth";
const char *authenticate = NULL;
credentials_t credentials;
sip_authen_t *sip_authen = NULL;
char *author_str = NULL;
if (!(cb_p->authen.cred_type & CRED_LINE)) {
cb_p->authen.cred_type |= CRED_LINE;
} else {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"configured credentials for line %d not accepeted. Verify the config\n",
fname, cb_p->dn_line);
return FALSE;
}
/*
* get authname & password from configuration.
*/
cred_get_line_credentials(cb_p->dn_line, &credentials,
sizeof(credentials.id),
sizeof(credentials.pw));
/*
* Extract Authenticate/Proxy-Authenticate header from the message.
*/
authenticate = sippmh_get_header_val(pSipMessage, AUTH_HDR(response_code), NULL);
if (authenticate == NULL) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"%s header missing in the %d response\n",
fname, AUTH_HDR_STR(response_code), response_code);
return FALSE;
}
CCSIP_DEBUG_TASK(DEB_F_PREFIX"Authenticate header %s = %s\n", DEB_F_PREFIX_ARGS(SIP_AUTH, fname), AUTH_HDR_STR(response_code), authenticate);
/*
* Parse Authenticate header.
*/
sip_authen = sippmh_parse_authenticate(authenticate);
if (sip_authen == NULL) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"%s:%s header formatted incorrectly in the %d response\n",
fname, AUTH_HDR_STR(response_code), authenticate, response_code);
return FALSE;
}
cb_p->authen.new_flag = FALSE;
cb_p->authen.cnonce[0] = '\0';
/*
* Generate Authorization string.
*/
if (sipSPIGenerateAuthorizationResponse(sip_authen,
uri,
rsp_method,
credentials.id,
credentials.pw,
&author_str,
&(cb_p->authen.nc_count),
NULL) == TRUE) {
if (cb_p->authen.authorization != NULL) {
cpr_free(cb_p->authen.authorization);
cb_p->authen.authorization = NULL;
}
if (cb_p->authen.sip_authen != NULL) {
sippmh_free_authen(cb_p->authen.sip_authen);
cb_p->authen.sip_authen = NULL;
}
cb_p->authen.authorization = (char *)
cpr_malloc(strlen(author_str) * sizeof(char) + 1);
/*
* Cache the Authorization header so that it can be
* used for later requests
*/
if (cb_p->authen.authorization != NULL) {
memcpy(cb_p->authen.authorization, author_str,
strlen(author_str) * sizeof(char) + 1);
cb_p->authen.status_code = response_code;
cb_p->authen.sip_authen = sip_authen;
}
cpr_free(author_str);
} else {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Authorization header build unsuccessful\n", fname);
sippmh_free_authen(sip_authen);
return FALSE;
}
return TRUE;
}
/**
* This function will extract user part from sip From header.
*
* @param[in] pSipMessage - pointer to sipMessage_t
* @param[out] entity - pointer to user buffer.
*
* @return void
*
* @pre (pSipMessage != NULL) and (entity != NULL)
*/
void ccsip_util_get_from_entity (sipMessage_t *pSipMessage, char *entity)
{
const char *sip_from = NULL;
sipLocation_t *from_loc = NULL;
sip_from = sippmh_get_cached_header_val(pSipMessage, FROM);
if (sip_from != NULL) {
from_loc = sippmh_parse_from_or_to((char *) sip_from, TRUE);
if ((from_loc) && (from_loc->genUrl->schema == URL_TYPE_SIP) && (from_loc->genUrl->u.sipUrl->user)) {
sstrncpy(entity, from_loc->genUrl->u.sipUrl->user, CC_MAX_DIALSTRING_LEN);
}
}
if (from_loc) {
sippmh_free_location(from_loc);
}
}
/**
* This function will extract user part from sip URL.
*
* @param[in] url - pointer to URL
* @param[out] user - pointer to user buffer.
*
* @return void
*
* @pre (url != NULL) and (user != NULL)
*/
void ccsip_util_extract_user (char *url, char *user)
{
genUrl_t *genUrl = NULL;
genUrl = sippmh_parse_url(url, TRUE);
if (genUrl != NULL) {
sstrncpy(user, genUrl->u.sipUrl->user, CC_MAX_DIALSTRING_LEN);
sippmh_genurl_free(genUrl);
}
}
File diff suppressed because it is too large. Load diff
+392
View File
@@ -0,0 +1,392 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "debug.h"
#include "phone_debug.h"
#include "ccsip_publish.h"
#include "util_string.h"
#include "sip_interface_regmgr.h"
extern boolean dump_reg_msg;
/* SIP flags */
cc_int32_t SipDebugMessage = 1; /* SIP messaging output */
cc_int32_t SipDebugState = 0; /* SIP State Machine output */
cc_int32_t SipDebugTask = 1; /* SIP Task output */
cc_int32_t SipDebugRegState = 0; /* SIP Registration State Mach. output */
/**
* SipRelDevEnabled flag is not a debug print flag. It actually turns
* on and off reliable delivery module in sip layer. We will keep
* this on as retransmissions are enabled on CUCM by default even for TCP transport
*/
int32_t SipRelDevEnabled = 1; /* Is reliable delivery on? */
int32_t SipDebugGenContactHeader = 0; /* Generate Contact header */
cc_int32_t SipDebugTrx = 0; /* SIP Transaction Layer output */
cc_int32_t GSMDebug = 0;
cc_int32_t FIMDebug = 0;
cc_int32_t LSMDebug = 0;
cc_int32_t FSMDebugSM = 0;
int32_t CSMDebugSM = 0;
cc_int32_t CCDebug = 0;
cc_int32_t CCDebugMsg = 0;
cc_int32_t AuthDebug = 0;
cc_int32_t g_DEFDebug = 1;
cc_int32_t TNPDebug = 1;
cc_int32_t VCMDebug = 0;
cc_int32_t CCEVENTDebug = 0;
cc_int32_t PLATDebug = 0;
cc_int32_t TMRDebug = 0;
cc_int32_t g_dcsmDebug = 0;
/**
*
* Dump sip messages
*
* @param msg - message buffer
* pSIPMessage - parsed message structure
* cc_remote_ipaddr - remote ip address
* cc_remote_port - remote port number
*
* @return none
*
* @pre (valid pSIPMessage AND
* valid cc_remote_ipaddr)
*/
void ccsip_dump_send_msg_info (char *msg, sipMessage_t *pSIPMessage,
cpr_ip_addr_t *cc_remote_ipaddr,
uint16_t cc_remote_port)
{
char *disp_buf;
const char *req_uri;
const char *cseq;
const char *callid;
char ipaddr_str[MAX_IPADDR_STR_LEN];
static const char fname[] = "ccsip_dump_send_msg_info";
ipaddr2dotted(ipaddr_str, cc_remote_ipaddr);
req_uri = sippmh_get_header_val(pSIPMessage, SIP_HEADER_TO, NULL);
if (req_uri == NULL) {
/* No REQ URI, fill with blank */
req_uri = "";
}
cseq = sippmh_get_header_val(pSIPMessage, SIP_HEADER_CSEQ, NULL);
if (cseq == NULL) {
/* No REQ CSEQ, fill with blank */
cseq = "";
}
callid = sippmh_get_header_val(pSIPMessage, SIP_HEADER_CALLID, NULL);
if (callid == NULL) {
/* No REQ CSEQ, fill with blank */
callid = "";
}
/* For messages starting with SIP add 8 byte. default
* debugs do not show all the SIP message information
* rather show initial msg.
*/
if (msg != NULL) {
if (msg[0] == 'S' &&
msg[1] == 'I' &&
msg[2] == 'P') {
disp_buf = &msg[8];
} else {
disp_buf = msg;
}
if ((strncmp(disp_buf, SIP_METHOD_REGISTER, sizeof(SIP_METHOD_REGISTER)-1) == 0) &&
(!dump_reg_msg)) {
return;
}
} else {
/* No msg. buffer */
disp_buf = NULL;
}
if (disp_buf != NULL) {
DEF_DEBUG(DEB_F_PREFIX"<%s:%-4d>:%c%c%c%c%c%c%c: %-10s :%-6s::%s\n",
DEB_F_PREFIX_ARGS(SIP_MSG_SEND, fname),
ipaddr_str, cc_remote_port,
disp_buf[0],
disp_buf[1],
disp_buf[2],
disp_buf[3],
disp_buf[4],
disp_buf[5],
disp_buf[6],
req_uri,
cseq, callid);
} else {
/* No msg to send */
DEF_DEBUG(DEB_F_PREFIX"<%s:%-4d>: empty message\n",
DEB_F_PREFIX_ARGS(SIP_MSG_SEND, fname),
ipaddr_str, cc_remote_port);
}
}
/**
*
* Dump sip messages
*
* @param msg - message buffer
* pSIPMessage - parsed message structure
* cc_remote_ipaddr - remote ip address
* cc_remote_port - remote port number
*
* @return none
*
* @pre (valid pSIPMessage AND
* valid cc_remote_ipaddr)
*/
void ccsip_dump_recv_msg_info (sipMessage_t *pSIPMessage,
cpr_ip_addr_t *cc_remote_ipaddr,
uint16_t cc_remote_port)
{
char *disp_buf;
const char *req_uri;
const char *cseq;
const char *callid;
char ipaddr_str[MAX_IPADDR_STR_LEN];
cpr_ip_addr_t cc_ipaddr;
static const char fname[] = "ccsip_dump_recv_msg_info";
util_ntohl(&cc_ipaddr, cc_remote_ipaddr);
ipaddr2dotted(ipaddr_str, &cc_ipaddr);
req_uri = sippmh_get_cached_header_val(pSIPMessage, FROM);
if (req_uri == NULL) {
/* No REQ URI, fill with blank */
req_uri = "";
}
cseq = sippmh_get_cached_header_val(pSIPMessage, CSEQ);
if (cseq == NULL) {
/* No REQ CSEQ, fill with blank */
cseq = "";
}
callid = sippmh_get_cached_header_val(pSIPMessage, CALLID);
if (callid == NULL) {
/* No REQ CSEQ, fill with blank */
callid = "";
}
if (!dump_reg_msg) {
if (strstr(cseq, SIP_METHOD_REGISTER) != NULL) {
return;
}
}
/* For messages starting with SIP add 8 byte. default
* debugs do not show all the SIP message information
* rather show initial msg.
*/
if (pSIPMessage->mesg_line != NULL) {
if (pSIPMessage->mesg_line[0] == 'S' &&
pSIPMessage->mesg_line[1] == 'I' &&
pSIPMessage->mesg_line[2] == 'P') {
disp_buf = &(pSIPMessage->mesg_line[8]);
} else {
disp_buf = pSIPMessage->mesg_line;
}
} else {
/*
* It is possible that this function is called with
* invalid message or partially received.
*/
disp_buf = NULL;
}
if (disp_buf != NULL) {
DEF_DEBUG(DEB_F_PREFIX"<%s:%-4d>:%c%c%c%c%c%c%c: %-10s :%-6s::%s\n",
DEB_F_PREFIX_ARGS(SIP_MSG_RECV, fname),
ipaddr_str, cc_remote_port,
disp_buf[0],
disp_buf[1],
disp_buf[2],
disp_buf[3],
disp_buf[4],
disp_buf[5],
disp_buf[6],
req_uri,
cseq, callid);
} else {
/* No line received */
DEF_DEBUG(DEB_F_PREFIX"<%s:%-4d>: empty message\n",
DEB_F_PREFIX_ARGS(SIP_MSG_RECV, fname),
ipaddr_str, cc_remote_port);
}
}
/**
*
* platform_print_sip_msg
*
* The function perform printing SIP msg.
*
* Parameters: msg - pointer to character strings of the SIP messages.
*
* Return Value: None
*
*/
void
platform_print_sip_msg (const char *msg)
{
char *buf;
int msg_to_crypto_line_len, msg_to_digits_tag_len, buf_len;
const char *c_line_begin, *c_line_end;
static const char crypto_line_tag[] = "a=crypto:";
static const char crypto_mask[] = "...";
static const char digits_tag[] = "digits=";
if (msg == NULL) {
return;
}
buginf_msg("\n");
/* replace digits for security reasons */
if (strstr(msg, "kpml-response")) {
/* This is kpml response. so supress printing digits. */
c_line_begin = strstr(msg, digits_tag);
if (c_line_begin == NULL) {
/* No digits, print everything */
buginf_msg(msg);
return;
}
/*
* Calculate the length of the msg. to print from
* from the beginning to the end of the "digits=" i.e.
*/
msg_to_digits_tag_len = c_line_begin - msg + sizeof(digits_tag);
buf_len = msg_to_digits_tag_len + sizeof(crypto_mask);
buf = (char *) cpr_malloc(buf_len);
if (buf == NULL) {
/* No memory */
return;
}
/* Copy the message upto "digits=" */
memcpy(buf, msg, msg_to_digits_tag_len);
/* Copy mask and the end NULL terminating char to the buffer */
memcpy(&buf[msg_to_digits_tag_len], crypto_mask, sizeof(crypto_mask));
/* Print it out now */
buginf_msg(buf);
cpr_free(buf);
c_line_end = c_line_begin + sizeof(digits_tag) + 3; /* 3 beacuse " + digit + " */
msg = c_line_end;
buginf_msg(msg);
} else if (sip_regmgr_get_sec_level(1) == ENCRYPTED) {
/* The 1st. line is using encrypted signaling */
while (TRUE) {
c_line_begin = strstr(msg, crypto_line_tag);
if (c_line_begin == NULL) {
/* No more crypto line, print whatever left and done */
buginf_msg(msg);
return;
} else {
/*
* Found a crypto line:
*
* Allocate buffer to print the msg. including this
* instance of crypto line but no crypto parameter.
* For example:
*
* v=0
* o=Cisco-SIPUA 3052 7 IN IP4 10.80.35.217
* s=SIP Call
* t=0 0
* m=audio 28926 RTP/SAVP 0 8 18 101
* c=IN IP4 10.80.35.217
* a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:GqT...
* a=rtpmap:0 PCMU/8000
*
*
* The output of printing will be
*
* v=0
* o=Cisco-SIPUA 3052 7 IN IP4 10.80.35.217
* s=SIP Call
* t=0 0
* m=audio 28926 RTP/SAVP 0 8 18 101
* c=IN IP4 10.80.35.217
* a=crypto:1...
* a=rtpmap:0 PCMU/8000
*
*/
/*
* Calculate the length of the msg. to print from
* current position to the end of the "a=crypto:n" i.e.
* from the current of msg passes the ":" by one character
* after of the "a=crypto:". This allows the first character
* of the crypto tag field character to be included in the
* output. Note that there is no explicit adding this
* extra character in the code below because of the
* sizeof(crypto_line_tag) includes extra 1 byte of string
* termination character already. It will be the extra
* character to print after the ":".
*/
msg_to_crypto_line_len = c_line_begin - msg +
sizeof(crypto_line_tag);
/*
* The buffer allocated to print includes the length from
* current msg pointer to this instance of crypto line +
* the mask length plus 1 byte for NULL terminating character.
* The NULL terminating character is included in the
* sizeof(crypto_mask) below.
*/
buf_len = msg_to_crypto_line_len + sizeof(crypto_mask);
buf = (char *) cpr_malloc(buf_len);
if (buf == NULL) {
/* No memory */
return;
}
/* Copy the message including this instance of crypto line */
memcpy(buf, msg, msg_to_crypto_line_len);
/* Copy mask and the end NULL terminating char to the buffer */
memcpy(&buf[msg_to_crypto_line_len], crypto_mask,
sizeof(crypto_mask));
/* Print it out now */
buginf_msg(buf);
cpr_free(buf);
/* Find the end of the crypto line */
c_line_end = strpbrk(c_line_begin, "\n");
if (c_line_end != NULL) {
/* Skip pass the "\n" character of the crypto line */
msg = c_line_end + 1;
} else {
/* Some thing is wrong, no end line character in SDP */
return;
}
}
}
} else {
/* print full content */
buginf_msg(msg);
}
}
/*
* Function: ccsip_debug_init()
*
* Parameters: None
*
* Description: Initialize the Debug keywords used by the SIP protocol stack.
*
* Returns: None
*
*/
void
ccsip_debug_init (void)
{
/* Placeholder for doing any initialization related tasks */
}
+898
View File
@@ -0,0 +1,898 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_stdio.h"
#include "ccsip_core.h"
#include "ccsip_callinfo.h"
#include "ccsip_messaging.h"
#include "uiapi.h"
#include "lsm.h"
#include "fsm.h"
#include "vcm.h"
#include "phone_debug.h"
#include "singly_link_list.h"
#include "ccapi.h"
extern int httpish_strncasecmp(const char *s1, const char *s2, size_t len);
typedef unsigned int info_index_t;
typedef unsigned int type_index_t;
typedef struct {
info_package_handler_t handler;
info_index_t info_index; // the index of the info_package in g_registered_info array
// i.e., the value returned by find_info_index()
type_index_t type_index; // the index of the content_type in g_registered_type array
// i.e., the value returned by find_type_index()
} handler_record_t;
/* Info Package handler registry */
static sll_handle_t s_handler_registry = NULL;
#define INDEX_NOT_FOUND ((unsigned int)-1)
/*
* g_registered_info[] contains the Info Package strings (such as
* "conference") for the registered handlers.
*/
char *g_registered_info[MAX_INFO_HANDLER];
static char *s_registered_type[MAX_INFO_HANDLER];
static sll_match_e is_matching_type(void *find_by_p, void *data_p);
static info_index_t find_info_index(const char *info_package);
static info_index_t find_next_available_info_index(void);
static type_index_t find_type_index(const char *type_package);
static type_index_t find_next_available_type_index(void);
static handler_record_t *find_handler_record(info_index_t info_index,
type_index_t type_index);
static boolean is_info_package_registered(info_index_t info_index);
static boolean is_content_type_registered(type_index_t type_index);
static void update_recv_info_list(const char *header_field_value,
string_t *info_packages);
static void media_control_info_package_handler(line_t line, callid_t call_id,
const char *info_package,
const char *content_type,
const char *message_body);
#ifdef _CONF_ROSTER_
static void conf_info_package_handler(line_t line, callid_t call_id,
const char *info_package,
const char *content_type,
const char *message_body);
#endif
/*
* Function: find_info_index
*
* Parameters:
* info_package - the Info Package to find
*
* Description:
* Finds the Info Package in g_registered_info array.
*
* Return:
* info_index_t - the index of the Info Package in the array
* INDEX_NOT_FOUND - the Info Package was not found in the array
*/
static info_index_t
find_info_index(const char *info_package)
{
info_index_t info_index;
for (info_index = 0; info_index < MAX_INFO_HANDLER; info_index++) {
if (g_registered_info[info_index] &&
httpish_strncasecmp(info_package,
g_registered_info[info_index],
strlen(g_registered_info[info_index])) == 0) {
return info_index;
}
}
return INDEX_NOT_FOUND;
}
/*
* Function: find_next_available_info_index
*
* Parameters:
* None
*
* Description:
* Finds an empty slot in g_registered_info array.
*
* Return:
* info_index_t - the index of the empty slot in the array
* INDEX_NOT_FOUND - the array is full
*/
static info_index_t
find_next_available_info_index(void)
{
info_index_t info_index;
for (info_index = 0; info_index < MAX_INFO_HANDLER; info_index++) {
if (g_registered_info[info_index] == NULL) {
return info_index;
}
}
return INDEX_NOT_FOUND;
}
/*
* Function: find_type_index
*
* Parameters:
* content_type - the Content Type to find
*
* Description:
* Finds the Content Type in s_registered_type array.
*
* Return:
* type_index_t - the index of the Content Type in the array
* INDEX_NOT_FOUND - the Content Type was not found in the array
*/
static type_index_t
find_type_index(const char *content_type)
{
type_index_t type_index;
for (type_index = 0; type_index < MAX_INFO_HANDLER; type_index++) {
if (s_registered_type[type_index] &&
httpish_strncasecmp(content_type,
s_registered_type[type_index],
strlen(s_registered_type[type_index])) == 0) {
return type_index;
}
}
return INDEX_NOT_FOUND;
}
/*
* Function: find_next_available_type_index
*
* Parameters:
* None
*
* Description:
* Finds an empty slot in s_registered_type array.
*
* Return:
* type_index_t - the index of the empty slot in the array
* INDEX_NOT_FOUND - the array is full
*/
static type_index_t
find_next_available_type_index(void)
{
type_index_t type_index;
for (type_index = 0; type_index < MAX_INFO_HANDLER; type_index++) {
if (s_registered_type[type_index] == NULL) {
return type_index;
}
}
return INDEX_NOT_FOUND;
}
/*
* Function: is_matching_type
*
* Parameters:
* find_by_p - searching criteria
* data_p - a node
*
* Description:
* Checks to see if the node matches the searching criteria.
*
* Return:
* SLL_MATCH_FOUND - the node is a match
* SLL_MATCH_NOT_FOUND - the node is not a match
*/
static sll_match_e
is_matching_type(void *find_by_p, void *data_p)
{
handler_record_t *tuple = (handler_record_t *)find_by_p;
handler_record_t *node = (handler_record_t *)data_p;
if ((node->info_index == tuple->info_index) &&
(node->type_index == tuple->type_index)) {
return SLL_MATCH_FOUND;
}
return SLL_MATCH_NOT_FOUND;
}
/*
* Function: find_handler_record
*
* Parameters:
* info_index - the index of the Info Package in g_registered_info array
* type_index - the index of the Content Type in s_registered_type array
*
* Description:
* Finds the Info Package handler registered for the Info Package/Content
* Type pair.
*
* Return:
* handler_record_t * - the registered handler record
* NULL - otherwise
*/
static handler_record_t *
find_handler_record(info_index_t info_index, type_index_t type_index)
{
handler_record_t tuple;
tuple.info_index = info_index;
tuple.type_index = type_index;
return (handler_record_t *)sll_find(s_handler_registry, &tuple);
}
/*
* Function: is_info_package_registered
*
* Parameters:
* info_index - the index of the Info Package in g_registered_info array
*
* Description:
* Checks to see if a handler was registered for the Info Package.
*
* Return:
* TRUE - a handler was registered for the Info Package
* FALSE - otherwise
*/
static boolean
is_info_package_registered(info_index_t info_index)
{
handler_record_t *record;
for (record = (handler_record_t *)sll_next(s_handler_registry, NULL);
record != NULL;
record = (handler_record_t *)sll_next(s_handler_registry, record)) {
if (record->info_index == info_index) {
return TRUE;
}
}
return FALSE;
}
/*
* Function: is_content_type_registered
*
* Parameters:
* type_index - the index of the Content Type in s_registered_type array
*
* Description:
* Checks to see if a handler was registered for the Content Type.
*
* Return:
* TRUE - a handler was registered for the Content Type
* FALSE - otherwise
*/
static boolean
is_content_type_registered(type_index_t type_index)
{
handler_record_t *record;
for (record = (handler_record_t *)sll_next(s_handler_registry, NULL);
record != NULL;
record = (handler_record_t *)sll_next(s_handler_registry, record)) {
if (record->type_index == type_index) {
return TRUE;
}
}
return FALSE;
}
/*
* Function: ccsip_register_info_package_handler
*
* Parameters:
* info_package - the Info Package for the handler
* content_type - the Content Type for the handler
* handler - the handler
*
* Description:
* Registers the handler for the Info Package/Content Type pair.
*
* Return:
* SIP_OK - the handler was registered successfully
* SIP_ERROR - otherwise
*/
int
ccsip_register_info_package_handler(const char *info_package,
const char *content_type,
info_package_handler_t handler)
{
static const char *fname = "ccsip_register_info_package_handler";
info_index_t info_index;
type_index_t type_index;
char *tmp_info = NULL;
char *tmp_type = NULL;
handler_record_t *record;
if (s_handler_registry == NULL) {
CCSIP_DEBUG_TASK("%s: Info Package handler was not initialized\n", fname);
return SIP_ERROR;
}
if ((info_package == NULL) || (content_type == NULL) || (handler == NULL)) {
CCSIP_DEBUG_ERROR("%s: invalid parameter\n", fname);
return SIP_ERROR;
}
/* Find the info_index for the info_package */
info_index = find_info_index(info_package);
if (info_index == INDEX_NOT_FOUND) {
/* Find the first available slot */
info_index = find_next_available_info_index();
if (info_index == INDEX_NOT_FOUND) {
CCSIP_DEBUG_ERROR("%s: maximum reached\n", fname);
return SIP_ERROR;
}
tmp_info = cpr_strdup(info_package);
if (tmp_info == NULL) {
CCSIP_DEBUG_ERROR("%s: failed to duplicate info_package string\n", fname);
return SIP_ERROR;
}
}
/* Find the type_index for the content_type */
type_index = find_type_index(content_type);
if (type_index == INDEX_NOT_FOUND) {
/* Find the first available slot */
type_index = find_next_available_type_index();
if (type_index == INDEX_NOT_FOUND) {
CCSIP_DEBUG_ERROR("%s: maximum reached\n", fname);
if (tmp_info != NULL) {
cpr_free(tmp_info);
}
return SIP_ERROR;
}
tmp_type = cpr_strdup(content_type);
if (tmp_type == NULL) {
CCSIP_DEBUG_ERROR("%s: failed to duplicate info_package string\n", fname);
if (tmp_info != NULL) {
cpr_free(tmp_info);
}
return SIP_ERROR;
}
}
/* Check to see if the info/type tuple has been registered before */
if (find_handler_record(info_index, type_index) != NULL) {
CCSIP_DEBUG_ERROR("%s: Info Package handler already registered\n", fname);
return SIP_ERROR;
}
/*
* At this point, info_index points to the slot in g_registered_info where
* either:
*
* 1) the info_package is residing, or
* 2) the info_package (a copy of which is pointed to by *tmp_info) will be
* copied to before the function returns
*
* type_index is similar.
*/
record = (handler_record_t *)cpr_malloc(sizeof(handler_record_t));
if (record == NULL) {
if (tmp_type != NULL) {
cpr_free(tmp_type);
}
if (tmp_info != NULL) {
cpr_free(tmp_info);
}
CCSIP_DEBUG_ERROR("%s: failed to allocate info handler record\n", fname);
return SIP_ERROR;
}
record->handler = handler;
record->info_index = info_index;
record->type_index = type_index;
if (sll_append(s_handler_registry, record) != SLL_RET_SUCCESS) {
cpr_free(record);
if (tmp_type != NULL) {
cpr_free(tmp_type);
}
if (tmp_info != NULL) {
cpr_free(tmp_info);
}
CCSIP_DEBUG_ERROR("%s: failed to insert to the registry\n", fname);
return SIP_ERROR;
}
if (tmp_info != NULL) {
g_registered_info[info_index] = tmp_info;
}
if (tmp_type != NULL) {
s_registered_type[type_index] = tmp_type;
}
return SIP_OK;
}
/*
* Function: ccsip_deregister_info_package_handler
*
* Parameters:
* info_package - the Info Package for the handler
* content_type - the Content Type for the handler
* handler - the handler
*
* Description:
* Deregisters the handler for the Info Package/Content Type pair.
*
* Return:
* SIP_OK - the handler was registered successfully
* SIP_ERROR - otherwise
*/
int
ccsip_deregister_info_package_handler(const char *info_package,
const char *content_type,
info_package_handler_t handler)
{
static const char *fname = "ccsip_deregister_info_package_handler";
info_index_t info_index;
type_index_t type_index;
handler_record_t *record;
if (s_handler_registry == NULL) {
CCSIP_DEBUG_TASK("%s: Info Package handler was not initialized\n", fname);
return SIP_ERROR;
}
/* Find the info_index for the info_package */
info_index = find_info_index(info_package);
if (info_index == INDEX_NOT_FOUND) {
CCSIP_DEBUG_ERROR("%s: handler was not registered (%s)\n",
fname, info_package);
return SIP_ERROR;
}
/* Find the type_index for the content_type */
type_index = find_type_index(content_type);
if (type_index == INDEX_NOT_FOUND) {
CCSIP_DEBUG_ERROR("%s: handler was not registered (%s)\n",
fname, content_type);
return SIP_ERROR;
}
/* Find the handler record */
record = find_handler_record(info_index, type_index);
if ((record == NULL) || (record->handler != handler)) {
CCSIP_DEBUG_ERROR("%s: handler was not registered (%p)\n",
fname, handler);
return SIP_ERROR;
}
(void)sll_remove(s_handler_registry, record);
cpr_free(record);
if (!is_info_package_registered(info_index)) {
/* The info_package was not found in the registry, meaning we're
* the last one who registered for this particular info_package */
cpr_free(g_registered_info[info_index]);
g_registered_info[info_index] = NULL;
}
if (!is_content_type_registered(type_index)) {
/* The content_type was not found in the registry, meaning we're
* the last one who registered for this particular content_type */
cpr_free(s_registered_type[type_index]);
s_registered_type[type_index] = NULL;
}
return SIP_OK;
}
/*
* Function: update_recv_info_list
*
* Parameters:
* header_field_value - the header field value to match (e.g.,
* "conference")
* info_packages - the Info Packages string to append the header
* field value to
*
* Description:
* Checks to see if a handler is registered for the header field value
* (e.g., "conference"), if so, append the header field value to
* the end of info_packages.
*
* Returns:
* None
*/
static void
update_recv_info_list(const char *header_field_value, string_t *info_packages)
{
static const char *fname = "update_recv_info_list";
info_index_t info_index;
if ((header_field_value == NULL) || (info_packages == NULL) ||
(*info_packages == NULL)) {
CCSIP_DEBUG_ERROR("%s: invalid parameter\n", fname);
return;
}
info_index = find_info_index(header_field_value);
if (info_index != INDEX_NOT_FOUND) {
/* Info-Package is supported */
if (**info_packages == '\0') {
*info_packages = strlib_update(*info_packages,
g_registered_info[info_index]);
} else {
*info_packages = strlib_append(*info_packages, ", ");
*info_packages = strlib_append(*info_packages,
g_registered_info[info_index]);
}
}
}
/*
* Function: ccsip_parse_send_info_header
*
* Parameters:
* ccb - the SIP CCB
* pSipMessage - the SIP message
*
* Description:
* Checks the Send-Info header (if exists) to see if a handler was
* registered for the Info Package. If so, append the Info Package
* to the end of recv_info_list.
*
* Returns:
* None
*/
void
ccsip_parse_send_info_header(sipMessage_t *pSipMessage, string_t *recv_info_list)
{
char *send_info[MAX_INFO_HANDLER];
int count;
int i;
char *header_field_values;
char *header_field_value;
char *separator;
// leading white spaces are trimmed, but not trailing ones
count = sippmh_get_num_particular_headers(pSipMessage,
SIP_HEADER_SEND_INFO,
NULL,
send_info,
MAX_INFO_HANDLER);
if (count == 0) {
return;
}
for (i = 0; (i < count) && (i < MAX_INFO_HANDLER); i++) {
header_field_values = cpr_strdup(send_info[i]);
if (header_field_values == NULL) {
return;
}
header_field_value = header_field_values;
while ((separator = strchr(header_field_value, COMMA)) != NULL) {
*separator++ = '\0';
update_recv_info_list(header_field_value, recv_info_list);
header_field_value = separator;
SKIP_WHITE_SPACE(header_field_value);
}
update_recv_info_list(header_field_value, recv_info_list);
cpr_free(header_field_values);
}
}
/*
* Function: ccsip_handle_info_package
*
* Parameters:
* ccb - the SIP CCB
* pSipMessage - the SIP message
*
* Description:
* Handles an incoming unsolicited Info Package message.
* XXX Currently this function only handles the first part in a
* multi-part Info Package message.
*
* Return:
* SIP_OK - if request processed.
* SIP_ERROR - if there is error
*/
int
ccsip_handle_info_package(ccsipCCB_t *ccb, sipMessage_t *pSipMessage)
{
static const char *fname = "ccsip_handle_info_package";
const char *info_package;
const char *content_type;
info_index_t info_index;
type_index_t type_index;
handler_record_t *record;
uint16_t status_code;
const char *reason_phrase;
int return_code = SIP_ERROR;
/* FIXME Media Control currently does not follow the IETF draft
draft-ietf-sip-info-events-01, so short-circuit here and
bypass all the Info Package related stuff below. */
// leading white spaces are trimmed, but not trailing ones
content_type = sippmh_get_cached_header_val(pSipMessage,
CONTENT_TYPE);
if (content_type &&
httpish_strncasecmp(content_type,
SIP_CONTENT_TYPE_MEDIA_CONTROL,
strlen(SIP_CONTENT_TYPE_MEDIA_CONTROL)) == 0) {
media_control_info_package_handler(ccb->dn_line, ccb->gsm_id,
"", // legacy mode, no Info Package
SIP_CONTENT_TYPE_MEDIA_CONTROL,
pSipMessage->mesg_body[0].msgBody);
if (sipSPISendErrorResponse(pSipMessage, 200, SIP_SUCCESS_SETUP_PHRASE,
0, NULL, NULL) != TRUE) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_SIP_SPI_SEND_ERROR),
fname, SIP_SUCCESS_SETUP_PHRASE);
return SIP_ERROR;
}
return SIP_OK;
}
/*
* Parse the Info-Package header
*/
// leading white spaces are trimmed, but not trailing ones
info_package = sippmh_get_header_val(pSipMessage,
SIP_HEADER_INFO_PACKAGE,
NULL);
if (info_package == NULL) {
/* No Info-Package header */
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Missing Info-Package header\n",
DEB_F_PREFIX_ARGS(SIP_INFO_PACKAGE, fname));
if (pSipMessage->num_body_parts == 0) {
/* No Info-Package header, and no body poarts */
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Missing message body\n",
DEB_F_PREFIX_ARGS(SIP_INFO_PACKAGE, fname));
/* Send 200 OK for legacy UA support */
status_code = 200;
reason_phrase = SIP_SUCCESS_SETUP_PHRASE;
return_code = SIP_OK;
} else {
/* No Info-Package header, but with body part(s) */
if (pSipMessage->num_body_parts > 1) {
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Multipart Info Package"
DEB_F_PREFIX_ARGS(SIP_INFO_PACKAGE, fname));
}
type_index = find_type_index(pSipMessage->mesg_body[0].msgContentType);
if (type_index == INDEX_NOT_FOUND) {
/* No Info-Package header, and Content-Type is not supported */
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Unsupported Content Type\n",
DEB_F_PREFIX_ARGS(SIP_INFO_PACKAGE, fname));
/* Send 415 Unsupported Media Type */
status_code = SIP_CLI_ERR_MEDIA;
reason_phrase = SIP_CLI_ERR_MEDIA_PHRASE;
} else {
/* No Info-Package header, but Conent-Type is supported */
/* Send 200 OK for legacy UA support */
status_code = 200;
reason_phrase = SIP_SUCCESS_SETUP_PHRASE;
return_code = SIP_OK;
}
}
} else {
/* With Info-Package header */
if (pSipMessage->num_body_parts == 0) {
/* With Info-Package header, but no body parts */
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Missing message body\n",
DEB_F_PREFIX_ARGS(SIP_INFO_PACKAGE, fname));
/* ? */
/* Send 489 Bad Event */
status_code = SIP_CLI_ERR_BAD_EVENT;
reason_phrase = SIP_CLI_ERR_BAD_EVENT_PHRASE;
} else {
/* With Info-Package header and body part(s) */
if (pSipMessage->num_body_parts > 1) {
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Multipart Info Package "
"(only the first part is processed)\n",
DEB_F_PREFIX_ARGS(SIP_INFO_PACKAGE, fname));
}
info_index = find_info_index(info_package);
if (info_index == INDEX_NOT_FOUND) {
/* Info-Package is not supported */
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Unsupported Info Package\n",
DEB_F_PREFIX_ARGS(SIP_INFO_PACKAGE, fname));
/* Send 489 Bad Event */
status_code = SIP_CLI_ERR_BAD_EVENT;
reason_phrase = SIP_CLI_ERR_BAD_EVENT_PHRASE;
} else {
/* Info-Package is supported */
type_index = find_type_index(pSipMessage->mesg_body[0].msgContentType);
record = find_handler_record(info_index, type_index);
if (record == NULL) {
/* Info-Package header is supported, but Content-Type is not */
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Unsupported Content Type\n",
DEB_F_PREFIX_ARGS(SIP_INFO_PACKAGE, fname));
/* Send 415 Unsupported Media Type */
status_code = SIP_CLI_ERR_MEDIA;
reason_phrase = SIP_CLI_ERR_MEDIA_PHRASE;
} else {
/* a handler is registered */
(*record->handler)(ccb->dn_line, ccb->gsm_id,
g_registered_info[record->info_index],
s_registered_type[record->type_index],
pSipMessage->mesg_body[0].msgBody);
/* Send 200 OK */
status_code = 200;
reason_phrase = SIP_SUCCESS_SETUP_PHRASE;
return_code = SIP_OK;
}
}
}
}
if (sipSPISendErrorResponse(pSipMessage, status_code, reason_phrase,
0, NULL, NULL) != TRUE) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_SIP_SPI_SEND_ERROR),
fname, reason_phrase);
return SIP_ERROR;
}
return return_code;
}
static void
media_control_info_package_handler(line_t line, callid_t call_id,
const char *info_package,
const char *content_type,
const char *message_body)
{
}
#ifdef _CONF_ROSTER_
static void
conf_info_package_handler(line_t line, callid_t call_id,
const char *info_package,
const char *content_type,
const char *message_body)
{
static const char *fname = "conf_info_package_handler";
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"info_package: %s content_type: %s\n",
DEB_F_PREFIX_ARGS(SIP_INFO_PACKAGE, fname),
info_package, content_type);
ui_info_received(line, lsm_get_ui_id(call_id), info_package, content_type,
message_body);
}
#endif
/*
* Function: ccsip_info_package_handler_init
*
* Parameters:
* None
*
* Description:
* Initializes the Info Package handler framework.
*
* Return:
* SIP_OK - Info Package handler framework initialized successfully
* SIP_ERROR - otherwise
*/
int
ccsip_info_package_handler_init(void)
{
static const char *fname = "ccsip_info_package_handler_init";
info_index_t info_index;
type_index_t type_index;
if (s_handler_registry != NULL) {
// Is this considered an error?
CCSIP_DEBUG_TASK("%s: Info Package handler already initialized\n", fname);
return SIP_OK;
}
/* Create the SLL */
s_handler_registry = sll_create(is_matching_type);
if (s_handler_registry == NULL) {
CCSIP_DEBUG_ERROR("%s: failed to create the registry\n", fname);
return SIP_ERROR;
}
for (info_index = 0; info_index < MAX_INFO_HANDLER; info_index++) {
g_registered_info[info_index] = NULL;
}
for (type_index = 0; type_index < MAX_INFO_HANDLER; type_index++) {
s_registered_type[type_index] = NULL;
}
// XXX Where is the best place to register the application-specific handler?
#ifdef _CONF_ROSTER_
/* Register the handler for conference & x-cisco-conference Info Packages */
ccsip_register_info_package_handler(INFO_PACKAGE_CONFERENCE,
CONTENT_TYPE_CONFERENCE_INFO,
conf_info_package_handler);
ccsip_register_info_package_handler(INFO_PACKAGE_CISCO_CONFERENCE,
CONTENT_TYPE_CONFERENCE_INFO,
conf_info_package_handler);
#endif
return SIP_OK;
}
/*
* Function: ccsip_info_package_handler_shutdown
*
* Parameters:
* None
*
* Description:
* Shuts down the Info Package handler framework.
*
* Return:
* None
*/
void
ccsip_info_package_handler_shutdown(void)
{
static const char *fname = "ccsip_info_package_handler_shutdown";
info_index_t info_index;
type_index_t type_index;
handler_record_t *record;
if (s_handler_registry == NULL) {
// Is this considered an error?
CCSIP_DEBUG_TASK("%s: Info Package handler was not initialized\n", fname);
return;
}
for (type_index = 0; type_index < MAX_INFO_HANDLER; type_index++) {
if (s_registered_type[type_index] != NULL) {
cpr_free(s_registered_type[type_index]);
s_registered_type[type_index] = NULL;
}
}
for (info_index = 0; info_index < MAX_INFO_HANDLER; info_index++) {
if (g_registered_info[info_index] != NULL) {
cpr_free(g_registered_info[info_index]);
g_registered_info[info_index] = NULL;
}
}
/* Deregister each Info Package handler */
for (record = (handler_record_t *)sll_next(s_handler_registry, NULL);
record != NULL;
record = (handler_record_t *)sll_next(s_handler_registry, record)) {
cpr_free(record);
}
/* Destroy the SLL */
sll_destroy(s_handler_registry);
s_handler_registry = NULL;
}
File diff suppressed because it is too large. Load diff
+122
View File
@@ -0,0 +1,122 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_stdio.h"
#include "cpr_string.h"
#include "phone.h"
#include "phone_debug.h"
#include "ccsip_register.h"
#include "ccsip_task.h"
#include "ccsip_pmh.h"
#include "config.h"
#include "sip_common_transport.h"
#include "sip_csps_transport.h"
#include "uiapi.h"
#include "sip_interface_regmgr.h"
#include "platform_api.h"
extern void platform_sync_cfg_vers(char *cfg_ver, char *dp_ver, char *softkey_ver);
extern void platform_reg_failover_ind(void *data);
extern void platform_reg_fallback_ind(void *data);
extern int platGetUnregReason();
extern void ccsip_add_wlan_classifiers();
void ccsip_remove_wlan_classifiers();
/*
* Function: sip_platform_init()
*
* Parameters: None
*
* Description: Performs platform initialization stuff. Should probably be
* renamed or moved to make it more "generic".
*
* Returns: None
*
*/
void
sip_platform_init (void)
{
// Since we have all our configuration information now
// we want to do a final check to see if our network media
// type has changed
/* Unregister the phone */
ccsip_register_cancel(FALSE, TRUE);
ccsip_register_reset_proxy();
/*
* Make sure that the IP stack is up before trying to connect
*/
if (PHNGetState() > STATE_IP_CFG) {
ccsip_add_wlan_classifiers();
/*
* regmgr - The SIPTaskDisconnectFromSipProxies and
* SIPTaskConnectToSipProxies calls will be called
* as part of the transport interface init and regmgr
* inits.
*/
ccsip_register_all_lines();
ui_sip_config_done();
} else {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "IP Stack Not Initialized.\n", "sip_platform_init");
}
}
/*
* Send StationReset message
* Parameters supplied by application:
* none
* Parameters supplied in the message
* - reset type (RESTART)
*/
int
sip_platform_ui_restart (void)
{
phone_reset(DEVICE_RESTART);
return TRUE;
}
void
sip_platform_handle_service_control_notify (sipServiceControl_t *scp)
{
switch (scp->action) {
case SERVICE_CONTROL_ACTION_RESET:
platform_reset_req(DEVICE_RESET);
break;
case SERVICE_CONTROL_ACTION_RESTART:
platform_reset_req(DEVICE_RESTART);
break;
case SERVICE_CONTROL_ACTION_CHECK_VERSION:
platform_sync_cfg_vers(scp->configVersionStamp,
scp->dialplanVersionStamp,
scp->softkeyVersionStamp);
break;
case SERVICE_CONTROL_ACTION_APPLY_CONFIG:
// call the function to process apply config NOTIFY message.
platform_apply_config(scp->configVersionStamp,
scp->dialplanVersionStamp,
scp->fcpVersionStamp,
scp->cucm_result,
scp->firmwareLoadId,
scp->firmwareInactiveLoadId,
scp->loadServer,
scp->logServer,
scp->ppid);
break;
default:
break;
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,989 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_string.h"
#include "cpr_memory.h"
#include "phntask.h"
#include "text_strings.h"
#include "ccsip_platform.h"
#include "phone_debug.h"
#include "ccsip_task.h"
#include "ccsip_pmh.h"
#include "ccsip_register.h"
#include "ccsip_core.h"
#include "ccsip_subsmanager.h"
/*
* Constants
*/
/*
* Globals TODO: hang off of a single SIP global
*/
sipPlatformUITimer_t sipPlatformUISMTimers[MAX_CCBS];
sipPlatformUIExpiresTimer_t sipPlatformUISMExpiresTimers[MAX_CCBS];
sipPlatformUIExpiresTimer_t sipPlatformUISMRegExpiresTimers[MAX_CCBS];
sipPlatformUIExpiresTimer_t sipPlatformUISMLocalExpiresTimers[MAX_CCBS];
// This timer will kick in after 1xx in releasing state so if 2xx gets lost
// we will be able to kill the ccb
sipPlatformSupervisionTimer_t sipPlatformSupervisionTimers[MAX_TEL_LINES];
sipPlatformUITimer_t sipPlatformUISMSubNotTimers[MAX_SCBS];
sipPlatformSupervisionTimer_t sipPlatformSubNotPeriodicTimer;
static cprTimer_t sipPlatformRegAllFailedTimer;
static cprTimer_t sipPlatformNotifyTimer;
static cprTimer_t sipPlatformStandbyKeepaliveTimer;
static cprTimer_t sipPlatformUnRegistrationTimer;
static cprTimer_t sipPassThroughTimer;
int
sip_platform_timers_init (void)
{
static const char fname[] = "sip_platform_timers_init";
static const char sipMsgTimerName[] = "sipMsg";
static const char sipExpireTimerName[] = "sipExp";
static const char sipRegTimeOutTimerName[] = "sipRegTimeout";
static const char sipRegExpireTimerName[] = "sipRegExp";
static const char sipLocalExpireTimerName[] = "sipLocalExp";
static const char sipSupervisionTimerName[] = "sipSupervision";
static const char sipSubNotTimerName[] = "sipSubNot";
static const char sipSubNotPeriodicTimerName[] = "sipSubNotPeriodic";
static const char sipRegAllFailedTimerName[] = "sipRegAllFailed";
static const char sipNotifyTimerName[] = "sipNotify";
static const char sipStandbyKeepaliveTimerName[] = "sipStandbyKeepalive";
static const char sipUnregistrationTimerName[] = "sipUnregistration";
static const char sipPassThroughTimerName[] = "sipPassThrough";
int i;
for (i = 0; i < MAX_CCBS; i++) {
sipPlatformUISMTimers[i].timer =
cprCreateTimer(sipMsgTimerName,
SIP_MSG_TIMER,
TIMER_EXPIRATION,
sip_msgq);
sipPlatformUISMTimers[i].reg_timer =
cprCreateTimer(sipRegTimeOutTimerName,
SIP_REG_TIMEOUT_TIMER,
TIMER_EXPIRATION,
sip_msgq);
sipPlatformUISMExpiresTimers[i].timer =
cprCreateTimer(sipExpireTimerName,
SIP_EXPIRES_TIMER,
TIMER_EXPIRATION,
sip_msgq);
sipPlatformUISMRegExpiresTimers[i].timer =
cprCreateTimer(sipRegExpireTimerName,
SIP_REG_EXPIRES_TIMER,
TIMER_EXPIRATION,
sip_msgq);
sipPlatformUISMLocalExpiresTimers[i].timer =
cprCreateTimer(sipLocalExpireTimerName,
SIP_LOCAL_EXPIRES_TIMER,
TIMER_EXPIRATION,
sip_msgq);
if (!sipPlatformUISMTimers[i].timer ||
!sipPlatformUISMTimers[i].reg_timer ||
!sipPlatformUISMExpiresTimers[i].timer ||
!sipPlatformUISMRegExpiresTimers[i].timer ||
!sipPlatformUISMLocalExpiresTimers[i].timer) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Failed to create one or more"
" UISM timers: %d\n", fname, i);
return SIP_ERROR;
}
}
for (i = 0; i < MAX_TEL_LINES; i++) {
sipPlatformSupervisionTimers[i].timer =
cprCreateTimer(sipSupervisionTimerName,
SIP_SUPERVISION_TIMER,
TIMER_EXPIRATION,
sip_msgq);
}
for (i = 0; i < MAX_SCBS; i++) {
sipPlatformUISMSubNotTimers[i].timer =
cprCreateTimer(sipSubNotTimerName,
SIP_SUBNOT_TIMER,
TIMER_EXPIRATION,
sip_msgq);
if (!sipPlatformUISMSubNotTimers[i].timer) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Failed to create Sub/Not"
" UISM timers: %d\n", fname, i);
return SIP_ERROR;
}
}
sipPlatformSubNotPeriodicTimer.timer =
cprCreateTimer(sipSubNotPeriodicTimerName,
SIP_SUBNOT_PERIODIC_TIMER,
TIMER_EXPIRATION,
sip_msgq);
if (!sipPlatformSubNotPeriodicTimer.timer) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Failed to create supervision timer: %d\n",
fname, i);
return SIP_ERROR;
}
sipPlatformRegAllFailedTimer =
cprCreateTimer(sipRegAllFailedTimerName,
SIP_REGALLFAIL_TIMER,
TIMER_EXPIRATION,
sip_msgq);
if (!sipPlatformRegAllFailedTimer) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Failed to create RegAllFailed timer\n", fname);
return SIP_ERROR;
}
/*
* Create the standby cc keepalive timer used by the
* registration Manager.
*/
sipPlatformStandbyKeepaliveTimer =
cprCreateTimer(sipStandbyKeepaliveTimerName,
SIP_KEEPALIVE_TIMER,
TIMER_EXPIRATION,
sip_msgq);
if (!sipPlatformStandbyKeepaliveTimer) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Failed to create Standby"
" keepalive timer\n", fname);
return SIP_ERROR;
}
sipPlatformUnRegistrationTimer =
cprCreateTimer(sipUnregistrationTimerName,
SIP_UNREGISTRATION_TIMER,
TIMER_EXPIRATION,
sip_msgq);
if (!sipPlatformUnRegistrationTimer) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Failed to create Stanby keepalive timer\n",
fname);
return SIP_ERROR;
}
sipPlatformNotifyTimer =
cprCreateTimer(sipNotifyTimerName,
SIP_NOTIFY_TIMER,
TIMER_EXPIRATION,
sip_msgq);
if (!sipPlatformNotifyTimer) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Failed to create Notify timer\n", fname);
return SIP_ERROR;
}
sipPassThroughTimer =
cprCreateTimer(sipPassThroughTimerName,
SIP_PASSTHROUGH_TIMER,
TIMER_EXPIRATION,
sip_msgq);
if (!sipPassThroughTimer) {
CCSIP_DEBUG_ERROR("%s: failed to create sip PassThrough timer\n", fname);
return SIP_ERROR;
}
return SIP_OK;
}
void
sip_platform_timers_shutdown (void)
{
int i;
for (i = 0; i < MAX_CCBS; i++) {
sip_platform_msg_timer_stop(i);
(void) cprDestroyTimer(sipPlatformUISMTimers[i].timer);
sipPlatformUISMTimers[i].timer = NULL;
(void) cprDestroyTimer(sipPlatformUISMTimers[i].reg_timer);
sipPlatformUISMTimers[i].reg_timer = NULL;
(void) sip_platform_expires_timer_stop(i);
(void) cprDestroyTimer(sipPlatformUISMExpiresTimers[i].timer);
sipPlatformUISMExpiresTimers[i].timer = NULL;
(void) sip_platform_register_expires_timer_stop(i);
(void) cprDestroyTimer(sipPlatformUISMRegExpiresTimers[i].timer);
sipPlatformUISMRegExpiresTimers[i].timer = NULL;
(void) sip_platform_localexpires_timer_stop(i);
(void) cprDestroyTimer(sipPlatformUISMLocalExpiresTimers[i].timer);
sipPlatformUISMLocalExpiresTimers[i].timer = NULL;
}
for (i = 0; i < MAX_TEL_LINES; i++) {
(void) sip_platform_supervision_disconnect_timer_stop(i);
(void) cprDestroyTimer(sipPlatformSupervisionTimers[i].timer);
sipPlatformSupervisionTimers[i].timer = NULL;
}
for (i = 0; i < MAX_SCBS; i++) {
sip_platform_msg_timer_subnot_stop(&sipPlatformUISMSubNotTimers[i]);
(void) cprDestroyTimer(sipPlatformUISMSubNotTimers[i].timer);
sipPlatformUISMSubNotTimers[i].timer = NULL;
}
(void) sip_platform_subnot_periodic_timer_stop();
(void) cprDestroyTimer(sipPlatformSubNotPeriodicTimer.timer);
sipPlatformSubNotPeriodicTimer.timer = NULL;
(void) sip_platform_reg_all_fail_timer_stop();
(void) cprDestroyTimer(sipPlatformRegAllFailedTimer);
sipPlatformRegAllFailedTimer = NULL;
(void) sip_platform_standby_keepalive_timer_stop();
(void) cprDestroyTimer(sipPlatformStandbyKeepaliveTimer);
sipPlatformStandbyKeepaliveTimer = NULL;
(void) sip_platform_unregistration_timer_stop();
(void) cprDestroyTimer(sipPlatformUnRegistrationTimer);
sipPlatformUnRegistrationTimer = NULL;
(void) sip_platform_notify_timer_stop();
(void) cprDestroyTimer(sipPlatformNotifyTimer);
sipPlatformNotifyTimer = NULL;
(void) sip_platform_pass_through_timer_stop();
(void) cprDestroyTimer(sipPassThroughTimer);
sipPassThroughTimer = NULL;
}
/********************************************************
*
* Message timer support functions for SIP SM
*
********************************************************/
void
sip_platform_msg_timers_init (void)
{
static const char fname[] = "sip_platform_msg_timers_init";
static long timer_init_complete = 0;
int i;
cprTimer_t timer, reg_timer;
for (i = 0; i < MAX_CCBS; i++) {
if (timer_init_complete) {
if ((cprCancelTimer(sipPlatformUISMTimers[i].timer)
== CPR_FAILURE) ||
(cprCancelTimer(sipPlatformUISMTimers[i].reg_timer)
== CPR_FAILURE)) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_GENERAL_FUNCTIONCALL_FAILED),
fname, "cprCancelTimer");
}
}
timer = sipPlatformUISMTimers[i].timer;
reg_timer = sipPlatformUISMTimers[i].reg_timer;
if (sipPlatformUISMTimers[i].message_buffer != NULL) {
cpr_free(sipPlatformUISMTimers[i].message_buffer);
sipPlatformUISMTimers[i].message_buffer = NULL;
sipPlatformUISMTimers[i].message_buffer_len = 0;
}
memset(&sipPlatformUISMTimers[i], 0, sizeof(sipPlatformUITimer_t));
sipPlatformUISMTimers[i].timer = timer;
sipPlatformUISMTimers[i].reg_timer = reg_timer;
}
timer_init_complete = 1;
return;
}
int
sip_platform_msg_timer_start (uint32_t msec,
void *data,
int idx,
char *message_buffer,
int message_buffer_len,
int message_type,
cpr_ip_addr_t *ipaddr,
uint16_t port,
boolean isRegister)
{
static const char fname[] = "sip_platform_msg_timer_start";
cprTimer_t timer;
/* validate index */
if ((idx < MIN_TEL_LINES) || (idx >= MAX_CCBS)) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_LINE_NUMBER_INVALID),
fname, idx);
return SIP_ERROR;
}
/* validate length */
if (message_buffer_len >= SIP_UDP_MESSAGE_SIZE) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_MSG_BUFFER_TOO_BIG),
fname, message_buffer_len);
return SIP_ERROR;
}
/* stop the timer if it is running */
if (cprCancelTimer(sipPlatformUISMTimers[idx].timer) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
if (cprCancelTimer(sipPlatformUISMTimers[idx].reg_timer) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
if (sipPlatformUISMTimers[idx].message_buffer == NULL) {
sipPlatformUISMTimers[idx].message_buffer = (char *)cpr_malloc(message_buffer_len+1);
if (sipPlatformUISMTimers[idx].message_buffer == NULL) return SIP_ERROR;
}
else if (message_buffer != sipPlatformUISMTimers[idx].message_buffer) {
cpr_free(sipPlatformUISMTimers[idx].message_buffer);
sipPlatformUISMTimers[idx].message_buffer = (char *)cpr_malloc(message_buffer_len+1);
if (sipPlatformUISMTimers[idx].message_buffer == NULL) return SIP_ERROR;
}
sipPlatformUISMTimers[idx].message_buffer_len = message_buffer_len;
sipPlatformUISMTimers[idx].message_buffer[message_buffer_len] = '\0';
memcpy(sipPlatformUISMTimers[idx].message_buffer, message_buffer,
message_buffer_len);
sipPlatformUISMTimers[idx].message_type = (sipMethod_t) message_type;
sipPlatformUISMTimers[idx].ipaddr = *ipaddr;
sipPlatformUISMTimers[idx].port = port;
/* start the timer */
if (isRegister) {
timer = sipPlatformUISMTimers[idx].reg_timer;
} else {
timer = sipPlatformUISMTimers[idx].timer;
}
if (cprStartTimer(timer, msec, data) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprStartTimer");
cpr_free(sipPlatformUISMTimers[idx].message_buffer);
sipPlatformUISMTimers[idx].message_buffer = NULL;
sipPlatformUISMTimers[idx].message_buffer_len = 0;
return SIP_ERROR;
}
sipPlatformUISMTimers[idx].outstanding = TRUE;
return SIP_OK;
}
void
sip_platform_msg_timer_stop (int idx)
{
static const char fname[] = "sip_platform_msg_timer_stop";
if ((idx < MIN_TEL_LINES) || (idx >= MAX_CCBS)) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_LINE_NUMBER_INVALID),
fname, idx);
return;
}
if ((cprCancelTimer(sipPlatformUISMTimers[idx].timer) == CPR_FAILURE) ||
(cprCancelTimer(sipPlatformUISMTimers[idx].reg_timer) == CPR_FAILURE)) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprCancelTimer");
return;
}
sipPlatformUISMTimers[idx].outstanding = FALSE;
}
boolean
sip_platform_msg_timer_outstanding_get (int idx)
{
return sipPlatformUISMTimers[idx].outstanding;
}
void
sip_platform_msg_timer_outstanding_set (int idx, boolean value)
{
sipPlatformUISMTimers[idx].outstanding = value;
}
int
sip_platform_msg_timer_update_destination (int idx,
cpr_ip_addr_t *ipaddr,
uint16_t port)
{
static const char fname[] = "sip_platform_msg_timer_update_destination";
if ((idx < TEL_CCB_START) || (idx > REG_BACKUP_CCB)) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_LINE_NUMBER_INVALID),
fname, idx);
return SIP_ERROR;
}
if (ipaddr == NULL) {
sipPlatformUISMExpiresTimers[idx].ipaddr = ip_addr_invalid;
} else {
sipPlatformUISMTimers[idx].ipaddr = *ipaddr;
}
sipPlatformUISMTimers[idx].port = port;
return SIP_OK;
}
/********************************************************
*
* Expires timer support functions for SIP SM
*
********************************************************/
int
sip_platform_expires_timer_start (uint32_t msec,
int idx,
cpr_ip_addr_t *ipaddr,
uint16_t port)
{
static const char fname[] = "sip_platform_expires_timer_start";
if (sip_platform_expires_timer_stop(idx) == SIP_ERROR) {
return SIP_ERROR;
}
if (ipaddr == NULL) {
sipPlatformUISMExpiresTimers[idx].ipaddr = ip_addr_invalid;
} else {
sipPlatformUISMExpiresTimers[idx].ipaddr = *ipaddr;
}
sipPlatformUISMExpiresTimers[idx].port = port;
//sip_platform_expires_timer_callback
if (cprStartTimer(sipPlatformUISMExpiresTimers[idx].timer, msec,
(void *) (long)idx) == CPR_FAILURE) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
return SIP_OK;
}
int
sip_platform_expires_timer_stop (int idx)
{
static const char fname[] = "sip_platform_expires_timer_stop";
if ((idx < MIN_TEL_LINES) || (idx >= MAX_CCBS)) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_LINE_NUMBER_INVALID),
fname, idx);
return SIP_ERROR;
}
if (cprCancelTimer(sipPlatformUISMExpiresTimers[idx].timer)
== CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
return SIP_OK;
}
int
sip_platform_register_expires_timer_start (uint32_t msec, int idx)
{
static const char fname[] = "sip_platform_register_expires_timer_start";
if (sip_platform_register_expires_timer_stop(idx) == SIP_ERROR) {
return SIP_ERROR;
}
if (cprStartTimer(sipPlatformUISMRegExpiresTimers[idx].timer, msec,
(void *)(long) idx) == CPR_FAILURE) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
return SIP_OK;
}
int
sip_platform_register_expires_timer_stop (int idx)
{
static const char fname[] = "sip_platform_register_expires_timer_stop";
if ((idx < MIN_TEL_LINES) || (idx >= MAX_CCBS)) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_LINE_NUMBER_INVALID),
fname, idx);
return SIP_ERROR;
}
if (cprCancelTimer(sipPlatformUISMRegExpiresTimers[idx].timer)
== CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
return SIP_OK;
}
/********************************************************
*
* Local Expires timer support functions for SIP SM
*
********************************************************/
int
sip_platform_localexpires_timer_start (uint32_t msec,
int idx,
cpr_ip_addr_t *ipaddr,
uint16_t port)
{
static const char fname[] = "sip_platform_localexpires_timer_start";
if (sip_platform_localexpires_timer_stop(idx) == SIP_ERROR) {
return SIP_ERROR;
}
sipPlatformUISMLocalExpiresTimers[idx].ipaddr = *ipaddr;
sipPlatformUISMLocalExpiresTimers[idx].port = port;
//sip_platform_localexpires_timer_callback
if (cprStartTimer(sipPlatformUISMLocalExpiresTimers[idx].timer, msec,
(void *)(long) idx) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
return SIP_OK;
}
int
sip_platform_localexpires_timer_stop (int idx)
{
static const char fname[] = "sip_platform_localexpires_timer_stop";
if ((idx < MIN_TEL_LINES) || (idx >= MAX_CCBS)) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_LINE_NUMBER_INVALID),
fname, idx);
return SIP_ERROR;
}
if (cprCancelTimer(sipPlatformUISMLocalExpiresTimers[idx].timer)
== CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
return SIP_OK;
}
sipMethod_t
sip_platform_msg_timer_messageType_get (int idx)
{
if ((idx >= TEL_CCB_START) && (idx <= REG_BACKUP_CCB)) {
if (sipPlatformUISMTimers[idx].outstanding) {
return sipPlatformUISMTimers[idx].message_type;
}
}
return sipMethodUnknown;
}
/*
* Call disconnect timer
*/
int
sip_platform_supervision_disconnect_timer_start (uint32_t msec, int idx)
{
static const char fname[] = "sip_platform_supervision_disconnect_timer_start";
if (sip_platform_supervision_disconnect_timer_stop(idx) == SIP_ERROR) {
return SIP_ERROR;
}
if (cprStartTimer(sipPlatformSupervisionTimers[idx].timer, msec,
(void *)(long) idx) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
return SIP_OK;
}
int
sip_platform_supervision_disconnect_timer_stop (int idx)
{
static const char fname[] = "sip_platform_supervision_disconnect_timer_stop";
if ((idx < TEL_CCB_START) || (idx > TEL_CCB_END)) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_LINE_NUMBER_INVALID), fname, idx);
return SIP_ERROR;
}
if (cprCancelTimer(sipPlatformSupervisionTimers[idx].timer)
== CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
idx, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
return SIP_OK;
}
void
sip_platform_post_timer (uint32_t cmd, void *data)
{
static const char fname[] = "sip_platform_post_timer";
uint32_t *timer_msg = NULL;
/* grab msg buffer */
timer_msg = (uint32_t *) SIPTaskGetBuffer(sizeof(uint32_t));
if (!timer_msg) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_SYSBUF_UNAVAILABLE), fname);
return;
}
*timer_msg = (long) data;
/* Put it on the SIP message queue */
if (SIPTaskSendMsg(cmd, (cprBuffer_t) timer_msg, sizeof(uint32_t), NULL)
== CPR_FAILURE) {
cpr_free(timer_msg);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "Send msg failed.\n", fname);
}
return;
}
/****************************************************
* Timer functions for Subscribe / Notify operations
****************************************************/
int
sip_platform_msg_timer_subnot_start (uint32_t msec,
sipPlatformUITimer_t *timer_p,
uint32_t id,
char *message_buffer,
int message_buffer_len,
int message_type,
cpr_ip_addr_t *ipaddr,
uint16_t port)
{
static const char fname[] = "sip_platform_msg_timer_start_subnot";
sip_platform_msg_timer_subnot_stop(timer_p);
if (message_buffer_len > SIP_UDP_MESSAGE_SIZE) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_MSG_BUFFER_TOO_BIG),
fname, message_buffer_len);
return SIP_ERROR;
}
if (timer_p->message_buffer == NULL) {
timer_p->message_buffer = (char *)cpr_malloc(message_buffer_len+1);
if (timer_p->message_buffer == NULL) return SIP_ERROR;
}
else if (timer_p->message_buffer != message_buffer) {
cpr_free(timer_p->message_buffer);
timer_p->message_buffer = (char *)cpr_malloc(message_buffer_len+1);
if (timer_p->message_buffer == NULL) return SIP_ERROR;
}
timer_p->message_buffer_len = message_buffer_len;
timer_p->message_buffer[message_buffer_len] = '\0';
memcpy(timer_p->message_buffer, message_buffer,
message_buffer_len);
timer_p->message_type =
(sipMethod_t) message_type;
timer_p->ipaddr = *ipaddr;
timer_p->port = port;
if (cprStartTimer(timer_p->timer, msec, (void *)(long)id) == CPR_FAILURE) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "%s failed\n",
fname, "cprStartTimer");
cpr_free(timer_p->message_buffer);
timer_p->message_buffer = NULL;
timer_p->message_buffer_len = 0;
return SIP_ERROR;
}
return SIP_OK;
}
void
sip_platform_msg_timer_subnot_stop (sipPlatformUITimer_t *timer_p)
{
static const char fname[] = "sip_platform_msg_timer_stop_subnot";
if (timer_p->message_buffer != NULL) {
cpr_free(timer_p->message_buffer);
timer_p->message_buffer = NULL;
}
if (cprCancelTimer(timer_p->timer) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(DEB_F_PREFIX "%s failed\n",
DEB_F_PREFIX_ARGS(SIP_TIMER, fname), "cprCancelTimer");
return;
}
}
void
sip_platform_subnot_msg_timer_callback (void *data)
{
sip_platform_post_timer(SIP_TMR_MSG_RETRY_SUBNOT, data);
}
int
sip_platform_subnot_periodic_timer_start (uint32_t msec)
{
static const char fname[] = "sip_platform_subnot_periodic_timer_start";
if (sip_platform_subnot_periodic_timer_stop() == SIP_ERROR) {
return SIP_ERROR;
}
if (cprStartTimer(sipPlatformSubNotPeriodicTimer.timer, msec, (void *) 0)
== CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
-1, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
sipPlatformSubNotPeriodicTimer.started = TRUE;
return SIP_OK;
}
int
sip_platform_subnot_periodic_timer_stop (void)
{
static const char fname[] = "sip_platform_subnot_periodic_timer_stop";
if (sipPlatformSubNotPeriodicTimer.started == TRUE) {
if (cprCancelTimer(sipPlatformSubNotPeriodicTimer.timer)
== CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
-1, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
}
sipPlatformSubNotPeriodicTimer.started = FALSE;
return SIP_OK;
}
void
sip_platform_subnot_periodic_timer_callback (void *data)
{
sip_platform_post_timer(SIP_TMR_PERIODIC_SUBNOT, data);
}
/**
** sip_platform_reg_all_fail_timer_start
* Starts a timer when all registrations fail.
*
* @param msec Value of the timer to be started
*
* @return SIP_OK if timer could be started; else SIP_ERROR
*
*/
int
sip_platform_reg_all_fail_timer_start (uint32_t msec)
{
static const char fname[] = "sip_platform_reg_all_fail_timer_start";
if (sip_platform_reg_all_fail_timer_stop() == SIP_ERROR) {
return SIP_ERROR;
}
if (cprStartTimer(sipPlatformRegAllFailedTimer, msec, NULL) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
CCSIP_DEBUG_REG_STATE(DEB_F_PREFIX
"Timer started for %lu msecs\n", DEB_F_PREFIX_ARGS(SIP_TIMER, fname), msec);
return SIP_OK;
}
/**
** sip_platform_reg_all_fail_timer_stop
* Stops the Reg-All Fail timer
*
* @param none
*
* @return SIP_OK if timer could be stopped; else SIP_ERROR
*
*/
int
sip_platform_reg_all_fail_timer_stop (void)
{
static const char fname[] = "sip_platform_reg_all_fail_timer_stop";
if (cprCancelTimer(sipPlatformRegAllFailedTimer) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
return SIP_OK;
}
/****************************************************
* Timer functions for standby cc keepalive operations
****************************************************/
int
sip_platform_standby_keepalive_timer_start (uint32_t msec)
{
static const char fname[] = "sip_platform_standby_keepalive_timer_start";
if (sip_platform_standby_keepalive_timer_stop() == SIP_ERROR) {
return SIP_ERROR;
}
if (cprStartTimer(sipPlatformStandbyKeepaliveTimer, msec, NULL)
== CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
CCSIP_DEBUG_STATE(DEB_F_PREFIX
"Timer started for %lu msecs\n", DEB_F_PREFIX_ARGS(SIP_TIMER, fname), msec);
return SIP_OK;
}
int
sip_platform_standby_keepalive_timer_stop ()
{
static const char fname[] = "sip_platform_standby_keepalive_timer_stop";
if (cprCancelTimer(sipPlatformStandbyKeepaliveTimer) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
return SIP_OK;
}
int
sip_platform_unregistration_timer_start (uint32_t msec, boolean external)
{
static const char fname[] = "sip_platform_unregistration_timer_start";
if (sip_platform_unregistration_timer_stop() == SIP_ERROR) {
return SIP_ERROR;
}
if (cprStartTimer(sipPlatformUnRegistrationTimer, msec, (void *)(long)external)
== CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
CCSIP_DEBUG_STATE(DEB_F_PREFIX
"Timer started for %lu msecs\n", DEB_F_PREFIX_ARGS(SIP_TIMER, fname), msec);
return SIP_OK;
}
int
sip_platform_unregistration_timer_stop ()
{
static const char fname[] = "sip_platform_unregistration_timer_stop";
if (cprCancelTimer(sipPlatformUnRegistrationTimer) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
return SIP_OK;
}
void
sip_platform_unregistration_callback (void *data)
{
sip_platform_post_timer(SIP_TMR_SHUTDOWN_PHASE2, data);
}
int
sip_platform_notify_timer_start (uint32_t msec)
{
static const char fname[] = "sip_platform_notify_timer_start";
if (sip_platform_notify_timer_stop() == SIP_ERROR) {
return SIP_ERROR;
}
if (cprStartTimer(sipPlatformNotifyTimer, msec, NULL) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
CCSIP_DEBUG_STATE(DEB_F_PREFIX
"Timer started for %lu msecs\n", DEB_F_PREFIX_ARGS(SIP_TIMER, fname), msec);
return SIP_OK;
}
int
sip_platform_notify_timer_stop ()
{
static const char fname[] = "sip_platform_notify_timer_stop";
if (cprCancelTimer(sipPlatformNotifyTimer) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
return SIP_OK;
}
/***********************************************
* PassThrough Timer
***********************************************
** sip_platform_pass_through_timer_start
* Starts a timer when all registrations fail.
*
* @param sec Value of the timer to be started
*
* @return SIP_OK if timer could be started; else SIP_ERROR
*
*/
int
sip_platform_pass_through_timer_start (uint32_t sec)
{
static const char fname[] = "sip_platform_pass_through_timer_start";
if (sip_platform_pass_through_timer_stop() == SIP_ERROR) {
return SIP_ERROR;
}
if (cprStartTimer(sipPassThroughTimer, sec*1000, NULL) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprStartTimer");
return SIP_ERROR;
}
CCSIP_DEBUG_REG_STATE("%s: Regmgr Pass Through Timer started for %lu secs\n", fname, sec);
return SIP_OK;
}
/**
** sip_platform_pass_through_timer_stop
* Stops the Pass Through timer
*
* @param none
*
* @return SIP_OK if timer could be stopped; else SIP_ERROR
*
*/
int
sip_platform_pass_through_timer_stop (void)
{
static const char fname[] = "sip_platform_pass_through_timer_stop";
if (cprCancelTimer(sipPassThroughTimer) == CPR_FAILURE) {
CCSIP_DEBUG_STATE(get_debug_string(DEBUG_SIP_FUNCTIONCALL_FAILED),
0, 0, fname, "cprCancelTimer");
return SIP_ERROR;
}
return SIP_OK;
}
@@ -0,0 +1,176 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_ipc.h"
#include "cpr_errno.h"
#include "cpr_socket.h"
#include "cpr_in.h"
#include "ccsip_core.h"
#include "ccsip_task.h"
#include "sip_platform_task.h"
#include "ccsip_platform_udp.h"
#include "sip_common_transport.h"
#include "sip_common_regmgr.h"
#include "phone_debug.h"
#include "util_string.h"
#include "ccsip_platform_tcp.h"
#include "text_strings.h"
#include "ccsip_register.h"
#include "phntask.h"
#include "plat_api.h"
#include "sip_socket_api.h"
#define HOST_SIZE 64
cpr_socket_t sip_tls_create_connection(sipSPIMessage_t *spi_msg,
boolean blocking,
sec_level_t sec);
extern cpr_sockaddr_t *sip_set_sockaddr(cpr_sockaddr_storage *psock_storage, uint16_t family,
cpr_ip_addr_t ip_addr, uint16_t port, uint16_t *addr_len);
/*
* sip_tls_create_connection()
* Description : This routine is called is response to a create connection
* request from SIP_SPI to SIP_TLS.
*
* Input : spi_msg - Pointer to sipSPIMessage_t containing the create conn
* parameters.
* blocking - connection mode; FALSE - nonblock; TRUE - block
*
* Output : Nothing
*/
cpr_socket_t
sip_tls_create_connection (sipSPIMessage_t *spi_msg, boolean blocking,
sec_level_t sec)
{
const char fname[] = "sip_tls_create_connection";
int idx;
sipSPICreateConnection_t *create_msg;
char ipaddr_str[MAX_IPADDR_STR_LEN];
plat_soc_status_e ret;
cpr_socket_t sock = INVALID_SOCKET;
uint16_t sec_port = 0;
plat_soc_connect_status_e conn_status;
int tos_dscp_val = 0; // set to default if there is no config. for dscp
#ifdef IPV6_STACK_ENABLED
int ip_mode = CPR_IP_MODE_IPV4;
#endif
uint16_t af_listen = AF_INET6;
cpr_sockaddr_storage sock_addr;
uint16_t addr_len;
int ip_mode = 0; // currently hardcoded to ipv4
plat_soc_connect_mode_e conn_mode;
#ifdef IPV6_STACK_ENABLED
config_get_value(CFGID_IP_ADDR_MODE, &ip_mode, sizeof(ip_mode));
/*
* Create a socket
*/
if (ip_mode == CPR_IP_MODE_IPV6 ||
ip_mode == CPR_IP_MODE_DUAL) {
af_listen = AF_INET6;
} else {
#endif
af_listen = AF_INET;
#ifdef IPV6_STACK_ENABLED
}
#endif
sip_tcp_init_conn_table();
create_msg = &(spi_msg->createConnMsg);
ipaddr2dotted(ipaddr_str, &create_msg->addr);
ret = platSecIsServerSecure();
if (ret != PLAT_SOCK_SECURE) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Secure connection is not created because"
" there is no secure servers\n", fname);
return INVALID_SOCKET;
}
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX
"Creating secure connection\n", DEB_F_PREFIX_ARGS(SIP_TLS, fname));
/* connect securely via TLS */
config_get_value(CFGID_DSCP_FOR_CALL_CONTROL, (int *)&tos_dscp_val,
sizeof(tos_dscp_val));
if (sec == AUTHENTICATED) {
conn_mode = PLAT_SOCK_AUTHENTICATED;
} else if (sec == ENCRYPTED) {
conn_mode = PLAT_SOCK_ENCRYPTED;
} else {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Secure connection is not created. Security mode was"
" not encrypyted or authenticated.\n", fname);
conn_mode = PLAT_SOCK_NON_SECURE;
}
sock = platSecSocConnect(ipaddr_str, /* host */
create_msg->port, /* port */
ip_mode, /* ip mode, ipv4 = 0, ipv6 = 1, dual = 2 */
blocking, /* 1 - block */
tos_dscp_val, /* TOS value */
conn_mode, /* The mode (Auth/Encry/None) */
&sec_port); /* local port */
if (sock < 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Secure connect failed!!\n",fname);
return INVALID_SOCKET;
}
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX "Secure connect ok\n", DEB_F_PREFIX_ARGS(SIP_TLS, fname));
if (!blocking) {
/* should not call this api in blocking mode */
conn_status = platSecSockIsConnected(sock);
if (conn_status == PLAT_SOCK_CONN_FAILED) {
(void)sipSocketClose(sock, TRUE);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Establish non-blocking mode secure"
" connection failed!!\n", fname);
return INVALID_SOCKET;
}
} else {
conn_status = PLAT_SOCK_CONN_OK;
}
if (sip_tcp_set_sock_options(sock) != TRUE) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX "Socket set option failure\n",
fname);
}
idx = sip_tcp_get_free_conn_entry();
if (idx == -1) {
/* Send create connection failed message to SIP_SPI */
(void)sipSocketClose(sock, TRUE);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Get free TCP connection entry failed\n",
fname);
return INVALID_SOCKET;
}
memset(&sock_addr, 0, sizeof(sock_addr));
(void) sip_set_sockaddr(&sock_addr, af_listen, create_msg->addr,
(uint16_t)(create_msg->port), &addr_len);
sip_tcp_conn_tab[idx].fd = sock;
sip_tcp_conn_tab[idx].ipaddr = create_msg->addr;
sip_tcp_conn_tab[idx].port = create_msg->port;
sip_tcp_conn_tab[idx].context = spi_msg->context;
sip_tcp_conn_tab[idx].dirtyFlag = FALSE;
sip_tcp_conn_tab[idx].addr = sock_addr;
sip_tcp_conn_tab[idx].soc_type = SIP_SOC_TLS;
if (conn_status == PLAT_SOCK_CONN_OK) {
sip_tcp_conn_tab[idx].state = SOCK_CONNECTED;
} else {
sip_tcp_conn_tab[idx].state = SOCK_CONNECT_PENDING;
}
create_msg->local_listener_port = (uint16) sec_port;
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX
"Local listening port=%d\n", DEB_F_PREFIX_ARGS(SIP_TLS, fname),
create_msg->local_listener_port);
(void)sip_tcp_attach_socket(sock);
return (sock);
}
@@ -0,0 +1,455 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_socket.h"
#include "cpr_memory.h"
#include "cpr_ipc.h"
#include "cpr_in.h"
#include "cpr_errno.h"
#include "cpr_string.h"
#include "util_string.h"
#include "text_strings.h"
#include "ccsip_core.h"
#include "ccsip_task.h"
#include "ccsip_platform_udp.h"
#include "phone.h"
#include "phone_debug.h"
#include "sip_common_transport.h"
#include "sip_platform_task.h"
#include "sip_socket_api.h"
// FIXME include does not exist on windows
//#include <net/if.h>
static uint16_t af_family_listen = AF_INET6;
static uint16_t af_family_connect = AF_INET6;
/*
* To set the appropriate socket strcutre based on the family. The called
* of the function is responsible for allocating the memory.
*
* @param psock_storage pointer to cpar_sockaddr_storage
* family network family AF_INET or AF_INET6
* ip_addr ip address
* port
* addr_len legth returned based on family
*
*
* @return pointer to cpr_sockaddr, which is also psock_storage
*
* @pre none
*
*/
cpr_sockaddr_t *sip_set_sockaddr (cpr_sockaddr_storage *psock_storage, uint16_t family,
cpr_ip_addr_t ip_addr, uint16_t port, uint16_t *addr_len)
{
static const char fname[] = "sip_set_sockaddr";
cpr_sockaddr_in6_t *pin6_addr;
cpr_sockaddr_in_t *pin_addr;
cpr_sockaddr_t *psock_addr;
uint32_t tmp_ip;
int i,j;
unsigned char tmp;
switch (family) {
case AF_INET6:
pin6_addr = (cpr_sockaddr_in6_t *)psock_storage;
memset(pin6_addr, 0, sizeof(cpr_sockaddr_in6_t));
pin6_addr->sin6_family = family;
pin6_addr->sin6_port = htons(port);
if (ip_addr.type == CPR_IP_ADDR_IPV4) {
if (ip_addr.u.ip4 != INADDR_ANY) {
pin6_addr->sin6_addr.addr.base16[5] = 0xffff;
}
tmp_ip = ntohl(ip_addr.u.ip4);
memcpy((void *)&(pin6_addr->sin6_addr.addr.base16[6]), (void *)&tmp_ip, 4);
} else {
for (i=0, j=15; i<16; i++, j--) {
tmp = pin6_addr->sin6_addr.addr.base8[j];
pin6_addr->sin6_addr.addr.base8[j] = ip_addr.u.ip6.addr.base8[i];
ip_addr.u.ip6.addr.base8[i] = tmp;
}
}
*addr_len = sizeof(cpr_sockaddr_in6_t);
return(psock_addr=(cpr_sockaddr_t *)pin6_addr);
case AF_INET:
if (ip_addr.type == CPR_IP_ADDR_IPV6) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Setting ipv6 address in AF_INET\n",fname);
break;
}
pin_addr = (cpr_sockaddr_in_t *)psock_storage;
memset(pin_addr, 0, sizeof(cpr_sockaddr_in_t));
pin_addr->sin_family = family;
pin_addr->sin_addr.s_addr = htonl(ip_addr.u.ip4);
pin_addr->sin_port = htons(port);
*addr_len = sizeof(cpr_sockaddr_in_t);
return(psock_addr=(cpr_sockaddr_t *)pin_addr);
default:
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Unable to set sockaddr.\n",fname);
break;
}
return(NULL);
}
int
sip_platform_udp_channel_listen (cpr_ip_mode_e ip_mode, cpr_socket_t *s,
cpr_ip_addr_t *local_ipaddr,
uint16_t local_port)
{
static const char fname[] = "sip_platform_udp_channel_listen";
cpr_sockaddr_storage sock_addr;
uint16_t addr_len;
/*
* If socket passed is is not INVALID_SOCKET close it first
*/
if (*s != INVALID_SOCKET) {
if (sipSocketClose(*s, FALSE) != CPR_SUCCESS) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "sipSocketClose", cpr_errno);
}
sip_platform_task_reset_listen_socket(*s);
}
/*
* Create a socket
*/
if (ip_mode == CPR_IP_MODE_IPV6 ||
ip_mode == CPR_IP_MODE_DUAL) {
af_family_listen = AF_INET6;
} else {
af_family_listen = AF_INET;
}
*s = cprSocket(af_family_listen, SOCK_DGRAM, 0);
if (*s == INVALID_SOCKET) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "cprSocket unable to open socket", cpr_errno);
if (ip_mode == CPR_IP_MODE_DUAL) {
af_family_listen = AF_INET;
CCSIP_DEBUG_TASK(DEB_F_PREFIX"Socket open failed for IPv6 using IPv4 address.",
DEB_F_PREFIX_ARGS(SIP_SDP, fname));
*s = cprSocket(af_family_listen, SOCK_DGRAM, 0);
if (*s == INVALID_SOCKET) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "cprSocket unable to open socket for IPv4",
cpr_errno);
return SIP_ERROR;
}
}
}
(void) sip_set_sockaddr(&sock_addr, af_family_listen, *local_ipaddr,
local_port, &addr_len);
if (cprBind(*s, (cpr_sockaddr_t *)&sock_addr, addr_len) == CPR_FAILURE) {
(void) sipSocketClose(*s, FALSE);
*s = INVALID_SOCKET;
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "cprBind", cpr_errno);
return SIP_ERROR;
}
sip_platform_task_set_listen_socket(*s);
return SIP_OK;
}
int
sip_platform_udp_channel_create (cpr_ip_mode_e ip_mode, cpr_socket_t *s,
cpr_ip_addr_t *remote_ipaddr,
uint16_t remote_port,
uint32_t local_udp_port)
{
static const char *fname = "sip_platform_udp_channel_create";
cpr_sockaddr_storage sock_addr;
uint16_t addr_len;
cpr_sockaddr_storage local_sock_addr;
cpr_ip_addr_t local_signaladdr;
int tos_dscp_val = 0; // set to default if there is no config. for dscp
CPR_IP_ADDR_INIT(local_signaladdr);
if (*s != INVALID_SOCKET) {
(void) sipSocketClose(*s, FALSE);
}
if (ip_mode == CPR_IP_MODE_IPV6 ||
ip_mode == CPR_IP_MODE_DUAL) {
af_family_connect = AF_INET6;
} else {
af_family_connect = AF_INET;
}
/*
* Create socket
*/
*s = cprSocket(af_family_connect, SOCK_DGRAM, 0);
if (*s == INVALID_SOCKET) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "cprSocket unable to open socket",
cpr_errno);
/* Try opening ipv4 socket */
if (ip_mode == CPR_IP_MODE_DUAL) {
CCSIP_DEBUG_TASK("%s: cprSocket Open failed for IPv6 trying IPv4",
fname);
af_family_connect = AF_INET;
*s = cprSocket(af_family_connect, SOCK_DGRAM, 0);
if (*s == INVALID_SOCKET) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "cprSocket unable to open AF_INET socket",
cpr_errno);
return SIP_ERROR;
}
}
}
sip_config_get_net_device_ipaddr(&local_signaladdr);
memset(&local_sock_addr, 0, sizeof(local_sock_addr));
(void) sip_set_sockaddr(&local_sock_addr, af_family_connect, local_signaladdr, 0, &addr_len);
CCSIP_DEBUG_REG_STATE(DEB_F_PREFIX"local_signaladdr.u.ip4=%x\n",
DEB_F_PREFIX_ARGS(SIP_SDP, fname), local_signaladdr.u.ip4);
if(cprBind(*s, (cpr_sockaddr_t *)&local_sock_addr, addr_len)){
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"UDP bind failed with errno %d\n", fname, cpr_errno);
(void) sipSocketClose(*s, FALSE);
*s = INVALID_SOCKET;
return SIP_ERROR;
}
/*
* Connect to remote address
*/
(void) sip_set_sockaddr(&sock_addr, af_family_connect, *remote_ipaddr,
remote_port, &addr_len);
/* if (cprConnect(*s, (cpr_sockaddr_t *)&sock_addr, addr_len) == CPR_FAILURE) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "cprConnect", cpr_errno);
(void) sipSocketClose(*s, FALSE);
*s = INVALID_SOCKET;
return SIP_ERROR;
}
*/
// set IP tos/dscp value for SIP messaging
config_get_value(CFGID_DSCP_FOR_CALL_CONTROL, (int *)&tos_dscp_val,
sizeof(tos_dscp_val));
if (cprSetSockOpt(*s, SOL_IP, IP_TOS, (void *)&tos_dscp_val,
sizeof(tos_dscp_val)) == CPR_FAILURE) {
// do NOT take hard action; just log the error and move on
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Unable to set IP TOS %d on UDP socket. "
"cpr_errno = %d\n", fname, tos_dscp_val, cpr_errno);
}
return SIP_OK;
}
int
sip_platform_udp_channel_destroy (cpr_socket_t s)
{
static const char fname[] = "sip_platform_udp_channel_destroy";
if (s != INVALID_SOCKET) {
if (sipSocketClose(s, FALSE) == CPR_FAILURE) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "sipSocketClose", cpr_errno);
return SIP_ERROR;
}
}
return SIP_OK;
}
int
sip_platform_udp_channel_read (cpr_socket_t s,
cprBuffer_t buf,
uint16_t *len,
cpr_sockaddr_t *soc_addr,
cpr_socklen_t *soc_addr_len)
{
static const char *fname = "sip_platform_udp_channel_read";
int bytes_read;
// NOT USED: cpr_sockaddr_in_t *addr = (cpr_sockaddr_in_t *)soc_addr;
bytes_read = cprRecvFrom(s, buf, CPR_MAX_MSG_SIZE, 0, soc_addr,
soc_addr_len);
switch (bytes_read) {
case SOCKET_ERROR:
/*
* If no data is available to read (CPR_EWOULDBLOCK),
* for non-blocking socket, it is not an error.
*/
cpr_free(buf);
*len = 0;
if (cpr_errno != CPR_EWOULDBLOCK) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"fd[%d]\n", fname, s);
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "cprRecvFrom", cpr_errno);
return SIP_ERROR;
}
/*
* Will continue reading when data arrives at socket
*/
break;
case 0:
/*
* Return value 0 is OK. This does NOT mean the connection
* has closed by the peer, as with TCP sockets. With UDP
* sockets, there is no such thing as closing a connection.
*/
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"No data on fd %d\n", DEB_F_PREFIX_ARGS(SIP_SDP, fname), s);
cpr_free(buf);
*len = 0;
break;
default:
/* PKT has been read */
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Recvd on fd %d\n", DEB_F_PREFIX_ARGS(SIP_SDP, fname), s);
*len = (uint16_t) bytes_read;
break;
}
return SIP_OK;
}
int
sip_platform_udp_channel_send (cpr_socket_t s, char *buf, uint16_t len)
{
static const char *fname = "sip_platform_udp_channel_send";
ssize_t bytesSent;
/*
* Check not exceeding max allowed payload size
*/
if (len >= PKTBUF_SIZ) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_UDP_PAYLOAD_TOO_LARGE),
fname, len, PKTBUF_SIZ);
return SIP_ERROR;
}
while (len > 0) {
bytesSent = sipSocketSend(s, (void *)buf, (size_t)len, 0, FALSE);
if (bytesSent == SOCKET_ERROR) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "cprSend", cpr_errno);
return SIP_ERROR;
}
len -= bytesSent;
buf += bytesSent;
}
return SIP_OK;
}
/**
*
* sip_platform_udp_read_socket
*
* Read from the socket to extract received message
*
* Parameters: s - the socket
*
* Return Value: None
*
*/
void
sip_platform_udp_read_socket (cpr_socket_t s)
{
cprBuffer_t buf;
uint16_t len = 0;
cpr_sockaddr_storage from;
cpr_socklen_t from_len;
const char *fname = "sip_platform_udp_read_socket";
if (af_family_listen == AF_INET6) {
from_len = sizeof(cpr_sockaddr_in6_t);
} else {
from_len = sizeof(cpr_sockaddr_in_t);
}
buf = SIPTaskGetBuffer(CPR_MAX_MSG_SIZE);
if (buf) {
if ((sip_platform_udp_channel_read(s, buf, &len,
(cpr_sockaddr_t *)&from, &from_len) == SIP_OK) &&
(len != 0)) {
(void) SIPTaskProcessUDPMessage(buf, len, from);
}
} else {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"No buffers available to read UDP socket.\n",
fname);
}
}
int
sip_platform_udp_channel_sendto (cpr_socket_t s, char *buf, uint32_t len,
cpr_ip_addr_t *dst_ipaddr, uint16_t dst_port)
{
static const char *fname = "sip_platform_udp_channel_sendto";
ssize_t bytesSent;
cpr_sockaddr_storage sock_addr;
uint16_t addr_len;
cpr_ip_addr_t dest_ip_addr;
/*
* Connect to remote address
*/
dest_ip_addr = *dst_ipaddr;
(void) sip_set_sockaddr(&sock_addr, af_family_connect, dest_ip_addr,
dst_port, &addr_len);
/*
* Check not exceeding max allowed payload size
*/
if (len >= PKTBUF_SIZ) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_UDP_PAYLOAD_TOO_LARGE),
fname, len, PKTBUF_SIZ);
return SIP_ERROR;
}
while (len > 0) {
bytesSent = cprSendTo(s, (void *)buf, (size_t)len, 0,
(cpr_sockaddr_t *)&sock_addr, addr_len);
if ((bytesSent == SOCKET_ERROR) && (cpr_errno == CPR_ECONNREFUSED)) {
/*
* Will get socket error ECONNREFUSED after an ICMP message
* resend the message
*/
CCSIP_DEBUG_TASK(DEB_F_PREFIX"UDP send to error %d\n", DEB_F_PREFIX_ARGS(SIP_SOCK, fname), cpr_errno);
bytesSent = cprSendTo(s, (void *)buf, (size_t)len, 0,
(cpr_sockaddr_t *)&sock_addr, addr_len);
}
if (bytesSent == SOCKET_ERROR) {
CCSIP_DEBUG_ERROR(get_debug_string(DEBUG_GENERAL_SYSTEMCALL_FAILED),
fname, "cprSendTo", cpr_errno);
return SIP_ERROR;
}
len -= bytesSent;
buf += bytesSent;
}
return SIP_OK;
}
File diff suppressed because it is too large. Load diff
+896
View File
@@ -0,0 +1,896 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ccsip_publish.h"
#include "phntask.h"
#include "sip_common_transport.h"
#include "ccsip_task.h"
#include "ccsip_callinfo.h"
#include "ccsip_macros.h"
#include "util_string.h"
#include "cpr_rand.h"
#include "platform_api.h"
#include "ccsip_register.h"
#include "ccsip_reldev.h"
#include "debug.h"
static sll_handle_t s_PCB_list = NULL; // signly linked list handle of PCBs
static int outgoingPublishes;
static boolean sipSPISendPublish(ccsip_publish_cb_t *pcb_p, boolean authen);
static void free_pending_reqs (sll_handle_t list);
/**
* This function will generate a new handle and return it.
*
* @return a non-zero integer value
*/
static pub_handle_t generate_new_pub_handle (void)
{
static pub_handle_t handle = 0;
handle++;
if (handle == NULL_PUBLISH_HANDLE) {
handle++;
}
return handle;
}
/**
* This function will check if it is the PCB we are looking for based on the key.
* This is only invoked by sll_find().
*
* @param[in] key - pointer to the key.
* @param[in] data - pointer to a node data.
*
* @return SLL_MATCH_FOUND if the node matches.
* Otherwise, SLL_MATCH_NOT_FOUND is returned.
*
* @pre (key != NULL) and (data != NULL)
*/
static sll_match_e is_matching_pcb (void *key, void *data)
{
pub_handle_t pub_handle = *((pub_handle_t *)key);
ccsip_publish_cb_t *pcb_p = (ccsip_publish_cb_t *)data;
if (pub_handle == pcb_p->pub_handle) {
return SLL_MATCH_FOUND;
}
return SLL_MATCH_NOT_FOUND;
}
/**
* This function will create a PCB. It will also create the PCB linked list.
*
* @return NULL if there are no resources to create a PCB.
* Otherwise, pointer to a new PCB is returned.
*
* @pre (key != NULL) and (data != NULL)
*/
static ccsip_publish_cb_t *get_new_pcb (void)
{
ccsip_publish_cb_t *pcb_p;
/*
* If PCB list is not created yet, create the list.
*/
if (s_PCB_list == NULL) {
s_PCB_list = sll_create(is_matching_pcb);
if (s_PCB_list == NULL) {
return NULL;
}
}
pcb_p = (ccsip_publish_cb_t *)cpr_malloc(sizeof(ccsip_publish_cb_t));
if (pcb_p == NULL) {
return NULL;
}
memset(pcb_p, 0, sizeof(ccsip_publish_cb_t));
pcb_p->pub_handle = generate_new_pub_handle();
pcb_p->hb.cb_type = PUBLISH_CB;
pcb_p->hb.dn_line = 1; // for now set it to primary line. This will change when we do line based PUBLISH.
/*
* set up dest & src ip addr and port number.
*/
ccsip_common_util_set_dest_ipaddr_port(&pcb_p->hb);
ccsip_common_util_set_src_ipaddr(&pcb_p->hb);
pcb_p->hb.local_port = sipTransportGetListenPort(pcb_p->hb.dn_line, NULL);
pcb_p->retry_timer.timer = cprCreateTimer("PUBLISH retry timer",
SIP_PUBLISH_RETRY_TIMER,
TIMER_EXPIRATION,
sip_msgq);
if (pcb_p->retry_timer.timer == NULL) {
cpr_free(pcb_p);
return NULL;
}
pcb_p->pending_reqs = sll_create(NULL);
if (pcb_p->pending_reqs == NULL) {
(void)cprDestroyTimer(pcb_p->retry_timer.timer);
cpr_free(pcb_p);
return NULL;
}
(void) sll_append(s_PCB_list, pcb_p);
return pcb_p;
}
/**
* This function will find matching PCB by the key in the PCB list.
*
* @param[in] pub_handle - publish handle.
*
* @return NULL if there is no matching PCB
* Otherwise, pointer to the found PCB is returned.
*
* @pre (pub_handle > 0) and (s_PCB_list != NULL)
*/
static ccsip_publish_cb_t *find_pcb (pub_handle_t pub_handle)
{
ccsip_publish_cb_t *pcb_p;
pcb_p = (ccsip_publish_cb_t *)sll_find(s_PCB_list, &pub_handle);
return pcb_p;
}
/**
* This function will find matching PCB by the SIP Call-ID in the PCB list.
*
* @param[in] callID_p - SIP Call-ID
*
* @return NULL if there is no matching PCB
* Otherwise, pointer to the found PCB is returned.
*
* @pre (callID_p != NULL)
*/
static ccsip_publish_cb_t *find_pcb_by_sip_callid (const char *callID_p)
{
ccsip_publish_cb_t *pcb_p;
pcb_p = (ccsip_publish_cb_t *)sll_next(s_PCB_list, NULL);
while (pcb_p != NULL) {
if (strncmp(callID_p, pcb_p->hb.sipCallID, (sizeof(pcb_p->hb.sipCallID) -1)) == 0) {
return pcb_p;
}
pcb_p = (ccsip_publish_cb_t *)sll_next(s_PCB_list, pcb_p);
}
return NULL;
}
/**
* This function will free up the PCB resources and removes it from the PCB list.
*
* @param[in] pcb_p - pointer to a PCB.
*
* @return none
*
* @pre (pcb_p != NULL)
*/
static void free_pcb (ccsip_publish_cb_t *pcb_p)
{
if (pcb_p->hb.authen.authorization != NULL) {
cpr_free(pcb_p->hb.authen.authorization);
}
if (pcb_p->hb.authen.sip_authen != NULL) {
sippmh_free_authen(pcb_p->hb.authen.sip_authen);
}
cpr_free(pcb_p->entity_tag);
free_pending_reqs(pcb_p->pending_reqs);
(void)cprDestroyTimer(pcb_p->retry_timer.timer);
free_event_data(pcb_p->hb.event_data_p);
(void)sll_remove(s_PCB_list, (void *)pcb_p);
cpr_free(pcb_p);
}
/**
* This function will append the application request in a pending list.
*
* @param[in] pcb_p - pointer to a PCB.
* @param[in] msg_p - pointer to an application request.
*
* @return TRUE if it is successful.
* Otherwise, FALSE is returned.
*
* @pre (pcb_p != NULL) and (msg_p != NULL)
* @post ((slink_list_t *)s_pres_req_list->count++)
*/
static boolean append_pending_reqs (ccsip_publish_cb_t *pcb_p, pub_req_t *msg_p)
{
pub_req_t *temp_msg_p;
temp_msg_p = (pub_req_t *)cpr_malloc(sizeof(pub_req_t));
if (temp_msg_p == NULL) {
return FALSE;
}
(*temp_msg_p) = (*msg_p);
(void) sll_append(pcb_p->pending_reqs, temp_msg_p);
return TRUE;
}
/**
* This function will free up entire list of pending requests
*
* @param[in] list - pending requests list handle
*
* @return none
*
*/
static void free_pending_reqs (sll_handle_t list)
{
pub_req_t *msg_p;
if (list == NULL) {
return;
}
msg_p = (pub_req_t *)sll_next(list, NULL);
while (msg_p != NULL) {
free_event_data(msg_p->event_data_p);
(void)sll_remove(list, (void *)msg_p);
cpr_free(msg_p);
msg_p = (pub_req_t *)sll_next(list, NULL);
}
sll_destroy(list);
}
/**
* This function will send the PUBLSIH request response to the application.
*
* @param[in] resp_code - this also includes error responses that start at 1000
* @param[in] pub_handle - handle to a PCB
* @param[in] app_handle - application generated handle to this PUBLISH context.
* @param[in] callback_task - task in which the application resides.
* @param[in] resp_msg_id - messageID posted to the task.
*
* @return none
*/
static void send_resp_to_app (int resp_code, pub_handle_t pub_handle, pub_handle_t app_handle,
cc_srcs_t callback_task, int resp_msg_id)
{
static const char fname[] = "send_resp_to_app";
pub_rsp_t rsp;
rsp.resp_code = resp_code;
rsp.pub_handle = pub_handle;
rsp.app_handle = app_handle;
if (publish_int_response(&rsp, callback_task, resp_msg_id) != CC_RC_SUCCESS) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Failed to post PUBLISH response to the application", fname);
}
}
/**
* This function will process SIPSPI_EV_CC_PUBLISH posted by applications.
* If there is an outstanding transaction, it will hold the request in the pending list.
*
* @param[in] buf - inter-process message buffer.
*
* @return SIP_OK if it successfully processes the request.
* SIP_ERROR if it fails to process the request.
* SIP_DEFER if it defers the processing.
*
* @note This will not free buf.
*
* @pre (buf != NULL)
*/
int publish_handle_ev_app_publish (cprBuffer_t buf)
{
static const char fname[] = "publish_handle_ev_app_publish";
pub_req_t *msg_p = (pub_req_t *)buf;
ccsip_publish_cb_t *pcb_p;
/*
* If this is initial PUBLISH, allocate a PCB.
* Otherwise, look up for PCB based on pub_handle.
*/
if (msg_p->pub_handle != NULL_PUBLISH_HANDLE) {
pcb_p = find_pcb(msg_p->pub_handle);
if (pcb_p == NULL) {
send_resp_to_app(PUBLISH_FAILED_NOCONTEXT, msg_p->pub_handle, msg_p->app_handle,
msg_p->callback_task, msg_p->resp_msg_id);
free_event_data(msg_p->event_data_p);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX
"Modification PUBLISH cannot be sent as the PCB is missing\n",
fname);
return SIP_ERROR;
}
/*
* Check if there is an outstanding transaction.
* if so, put the request in pending request queue.
*/
if (pcb_p->outstanding_trxn == TRUE) {
if (append_pending_reqs(pcb_p, msg_p) == TRUE) {
CCSIP_DEBUG_TASK(DEB_F_PREFIX"deffering as there is an outstanding transaction\n",
DEB_F_PREFIX_ARGS(SIP_PUB, fname));
return SIP_DEFER;
}
/* free up PCB and respond with error */
free_pcb (pcb_p);
send_resp_to_app(PUBLISH_FAILED_NORESOURCE, msg_p->pub_handle, msg_p->app_handle,
msg_p->callback_task, msg_p->resp_msg_id);
free_event_data(msg_p->event_data_p);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Queueing outgoing PUBLISH request failed\n", fname);
return SIP_ERROR;
}
/*
* if event_data_p is NULL, this is terminating PUBLISH.
* otherwise, it is a modifying PUBLISH.
*/
free_event_data(pcb_p->hb.event_data_p);
pcb_p->hb.event_data_p = msg_p->event_data_p;
if ((msg_p->event_data_p == NULL) && (msg_p->expires == 0)) { // removing PUBLISH
pcb_p->hb.orig_expiration = 0;
}
} else {
pcb_p = get_new_pcb();
if (pcb_p == NULL) {
send_resp_to_app(PUBLISH_FAILED_NORESOURCE, msg_p->pub_handle, msg_p->app_handle,
msg_p->callback_task, msg_p->resp_msg_id);
free_event_data(msg_p->event_data_p);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"PCB allocation failed\n", fname);
return SIP_ERROR;
}
pcb_p->app_handle = msg_p->app_handle;
sstrncpy(pcb_p->ruri, msg_p->ruri, MAX_URI_LENGTH);
sstrncpy(pcb_p->esc, msg_p->esc, MAX_URI_LENGTH);
pcb_p->hb.orig_expiration = msg_p->expires;
pcb_p->hb.event_type = msg_p->event_type;
pcb_p->hb.event_data_p = msg_p->event_data_p;
pcb_p->callback_task = msg_p->callback_task;
pcb_p->resp_msg_id = msg_p->resp_msg_id;
}
pcb_p->hb.authen.cred_type = 0;
if (sipSPISendPublish(pcb_p, FALSE) == TRUE) {
pcb_p->outstanding_trxn = TRUE;
outgoingPublishes++;
CCSIP_DEBUG_TASK(DEB_F_PREFIX"PUBLISH request sent successfully\n", DEB_F_PREFIX_ARGS(SIP_PUB, fname));
return SIP_OK;
}
/* free up PCB and respond with error */
free_pcb (pcb_p);
send_resp_to_app(PUBLISH_FAILED_SEND, msg_p->pub_handle, msg_p->app_handle,
msg_p->callback_task, msg_p->resp_msg_id);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Failed to send PUBLISH request\n", fname);
return SIP_ERROR;
}
/**
* 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);
}
/**
* This function will handle retry-timer expiration
*
* @param[in] handle - handle to PCB
*
* @return 0 if it is successful in handling the timer
* Otherwise, -1 is returned
*
* @pre (handle != 0)
*/
int publish_handle_retry_timer_expire (uint32_t handle)
{
static const char fname[] = "publish_handle_retry_timer_expire";
pub_handle_t pub_handle = handle;
ccsip_publish_cb_t *pcb_p;
uint32_t max_retx = 0;
uint32_t time_t1 = 0;
uint32_t time_t2 = 0;
uint32_t timeout = 0;
/*
* find the PCB
*/
pcb_p = find_pcb(pub_handle);
if (pcb_p == NULL) {
/* No PCB. So do nothing. */
return 0;
}
if (pcb_p->hb.retx_flag == FALSE) {
/* probably we got some response. so do nothing */
return 0;
}
config_get_value(CFGID_SIP_RETX, &max_retx, sizeof(max_retx));
if (max_retx > MAX_NON_INVITE_RETRY_ATTEMPTS) {
max_retx = MAX_NON_INVITE_RETRY_ATTEMPTS;
}
if (pcb_p->hb.retx_counter < max_retx) {
pcb_p->hb.retx_counter++;
config_get_value(CFGID_TIMER_T1, &time_t1, sizeof(time_t1));
timeout = time_t1 * (1 << pcb_p->hb.retx_counter);
config_get_value(CFGID_TIMER_T2, &time_t2, sizeof(time_t2));
if (timeout > time_t2) {
timeout = time_t2;
}
CCSIP_DEBUG_TASK(DEB_F_PREFIX"Resending message #%d\n",
DEB_F_PREFIX_ARGS(SIP_PUB, fname), pcb_p->hb.retx_counter);
if (sipTransportSendMessage(NULL,
pcb_p->retry_timer.message_buffer,
pcb_p->retry_timer.message_buffer_len,
pcb_p->retry_timer.message_type,
&(pcb_p->retry_timer.ipaddr),
pcb_p->retry_timer.port,
FALSE, TRUE, timeout, pcb_p) < 0) {
/* free up PCB and respond with error */
send_resp_to_app(PUBLISH_FAILED_SEND, pcb_p->pub_handle, pcb_p->app_handle,
pcb_p->callback_task, pcb_p->resp_msg_id);
free_pcb (pcb_p);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to send message", fname);
return (-1);
}
} else {
/*
* send timeout response and free up PCB
*/
send_resp_to_app(SIP_CLI_ERR_REQ_TIMEOUT, pcb_p->pub_handle, pcb_p->app_handle,
pcb_p->callback_task, pcb_p->resp_msg_id);
free_pcb (pcb_p);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"reached MAX retries", fname);
}
return 0;
}
/**
* This function will check if wee need to send refresh PUBLISH.
* If so, it will send refresh PUBLISH
*
* @param[in] none
*
* @return none
*/
void publish_handle_periodic_timer_expire (void)
{
static const char fname[] = "publish_handle_periodic_timer_expire";
int delta = 0;
ccsip_publish_cb_t *pcb_p;
pub_req_t msg;
config_get_value(CFGID_TIMER_SUBSCRIBE_DELTA, &delta,
sizeof(delta));
pcb_p = (ccsip_publish_cb_t *)sll_next(s_PCB_list, NULL);
while (pcb_p != NULL) {
if (pcb_p->outstanding_trxn == FALSE) {
if (pcb_p->hb.expires >= TMR_PERIODIC_PUBLISH_INTERVAL) {
pcb_p->hb.expires -= TMR_PERIODIC_PUBLISH_INTERVAL;
}
if (pcb_p->hb.expires <= (delta + TMR_PERIODIC_PUBLISH_INTERVAL)) {
CCSIP_DEBUG_TASK(DEB_F_PREFIX"sending REFRESH PUBLISH", DEB_F_PREFIX_ARGS(SIP_PUB, fname));
memset (&msg, 0, sizeof(msg));
/* refresh is triggered by NULL event data and non-zero expires value */
msg.pub_handle = pcb_p->pub_handle;
msg.expires = pcb_p->hb.orig_expiration;
(void)publish_handle_ev_app_publish(&msg);
}
}
pcb_p = (ccsip_publish_cb_t *)sll_next(s_PCB_list, pcb_p);
}
}
/**
* This function will process the response to PUBLISH request sent by us.
*
* @param[in] pSipMessage - pointer to received SIP response msg
*
* @return SIP_OK if it successfully processes the response.
* SIP_ERROR if it fails to process the response.
*
* @pre (pSipMessage != NULL)
*/
int publish_handle_ev_sip_response (sipMessage_t *pSipMessage)
{
static const char fname[] = "publish_handle_ev_sip_response";
const char *callID_p = NULL;
int response_code = 0;
const char *expires = NULL;
const char *sip_etag = NULL;
long expiry_time;
pub_req_t *msg_p;
ccsip_publish_cb_t *pcb_p;
int entity_tag_size;
callID_p = sippmh_get_cached_header_val(pSipMessage, CALLID);
if (!callID_p) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Cannot obtain SIP Call ID.\n", fname);
return SIP_ERROR;
}
/*
* Find PCB by Call-ID. The Call-IDs generated by the phone ae unique.
*/
pcb_p = find_pcb_by_sip_callid(callID_p);
if (pcb_p == NULL) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"No matching PCB found\n", fname);
return SIP_ERROR;
}
/*
* Cancel the retry_timer and set the retx_flag to FALSE.
*/
sip_platform_msg_timer_subnot_stop(&(pcb_p->retry_timer));
pcb_p->hb.retx_flag = FALSE;
// Parse the return code
(void) sipGetResponseCode(pSipMessage, &response_code);
if (response_code >= 200) {
pcb_p->outstanding_trxn = FALSE;
}
if ((response_code == SIP_CLI_ERR_UNAUTH) ||
(response_code == SIP_CLI_ERR_PROXY_REQD)) {
CCSIP_DEBUG_TASK(DEB_F_PREFIX"Authentication Required\n", DEB_F_PREFIX_ARGS(SIP_PUB, fname));
if (ccsip_common_util_generate_auth(pSipMessage, &pcb_p->hb, SIP_METHOD_PUBLISH,
response_code, pcb_p->full_ruri) == TRUE) {
if (sipSPISendPublish(pcb_p, TRUE) == TRUE) {
pcb_p->outstanding_trxn = TRUE;
CCSIP_DEBUG_TASK(DEB_F_PREFIX"sent request with Auth header\n", DEB_F_PREFIX_ARGS(SIP_PUB, fname));
return SIP_OK;
}
}
/*
* Since we failed to resend the PUBLISH request, free up the PCB and let the app know.
*/
send_resp_to_app(PUBLISH_FAILED_SEND, pcb_p->pub_handle, pcb_p->app_handle,
pcb_p->callback_task, pcb_p->resp_msg_id);
free_pcb (pcb_p);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to respond to auth challenge\n", fname);
return SIP_ERROR;
}
/*
* if response code is 423, grab Min-Expires and send new PUBLISH with new expires value
*/
if (response_code == SIP_CLI_ERR_INTERVAL_TOO_SMALL) {
expires = sippmh_get_header_val(pSipMessage,
(const char *)SIP_HEADER_MIN_EXPIRES,
NULL);
if (expires) {
expiry_time = strtoul(expires, NULL, 10);
//ensure new Min-Expires is > what we set before in Expires
if ((long) expiry_time > pcb_p->hb.expires) {
pcb_p->hb.expires = expiry_time;
pcb_p->hb.orig_expiration = expiry_time;
}
if (sipSPISendPublish(pcb_p, FALSE) == TRUE) {
pcb_p->outstanding_trxn = TRUE;
CCSIP_DEBUG_TASK(DEB_F_PREFIX"sent request with increased expires\n", DEB_F_PREFIX_ARGS(SIP_PUB, fname));
return SIP_OK;
}
}
/*
* Since we failed to resend the PUBLISH request, free up the PCB and let the app know.
*/
send_resp_to_app(PUBLISH_FAILED_SEND, pcb_p->pub_handle, pcb_p->app_handle,
pcb_p->callback_task, pcb_p->resp_msg_id);
free_pcb (pcb_p);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to respond to 423\n", fname);
return SIP_ERROR;
}
/*
* if the response_code is > 299, free up the PCB and let the app know.
*/
if (response_code > 299) {
send_resp_to_app(response_code, pcb_p->pub_handle, pcb_p->app_handle,
pcb_p->callback_task, pcb_p->resp_msg_id);
free_pcb (pcb_p);
CCSIP_DEBUG_TASK(DEB_F_PREFIX"received %d response\n", DEB_F_PREFIX_ARGS(SIP_PUB, fname), response_code);
return SIP_OK;
}
/*
* if the response is < 200, do nothing.
*/
if (response_code < 200) {
CCSIP_DEBUG_TASK(DEB_F_PREFIX"received %d response\n", DEB_F_PREFIX_ARGS(SIP_PUB, fname), response_code);
return SIP_OK;
}
/*
* If it is PUBLISH remove operation, free up PCB
*/
if (pcb_p->hb.orig_expiration == 0) {
send_resp_to_app(response_code, pcb_p->pub_handle, pcb_p->app_handle,
pcb_p->callback_task, pcb_p->resp_msg_id);
free_pcb (pcb_p);
CCSIP_DEBUG_TASK(DEB_F_PREFIX"removed PCB as this was a terminating PUBLISH\n", DEB_F_PREFIX_ARGS(SIP_PUB, fname));
return SIP_OK;
}
/*
* extract Expires and SIP-ETag headers and save them.
*/
expires = sippmh_get_header_val(pSipMessage, SIP_HEADER_EXPIRES, NULL);
if (expires) {
expiry_time = strtoul(expires, NULL, 10);
pcb_p->hb.expires = expiry_time;
}
sip_etag = sippmh_get_header_val(pSipMessage, SIP_HEADER_SIPETAG, NULL);
if (sip_etag != NULL) {
cpr_free(pcb_p->entity_tag);
entity_tag_size = strlen(sip_etag) + 1;
pcb_p->entity_tag = cpr_malloc(entity_tag_size);
if (pcb_p->entity_tag != NULL) {
sstrncpy(pcb_p->entity_tag, sip_etag, entity_tag_size);
} else {
free_pcb (pcb_p);
send_resp_to_app(PUBLISH_FAILED_NORESOURCE, pcb_p->pub_handle, pcb_p->app_handle,
pcb_p->callback_task, pcb_p->resp_msg_id);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"memory allocation failed\n", fname);
return SIP_ERROR;
}
}
/*
* If there are no pending requests, provide the response to the application.
*/
msg_p = (pub_req_t *)sll_next(pcb_p->pending_reqs, NULL);
if (msg_p != NULL) {
(void)sll_remove(pcb_p->pending_reqs, msg_p);
(void)publish_handle_ev_app_publish(msg_p);
cpr_free(msg_p);
return SIP_OK;
}
send_resp_to_app(response_code, pcb_p->pub_handle, pcb_p->app_handle,
pcb_p->callback_task, pcb_p->resp_msg_id);
CCSIP_DEBUG_TASK(DEB_F_PREFIX"sent response %d to app\n", DEB_F_PREFIX_ARGS(SIP_PUB, fname), response_code);
return SIP_OK;
}
/**
* This function will inform the application that phone is either
* 1. restarting or
* 2. failing over/ falling back
*
* @note detection of CCM reboot will be handled by PUBLISH ETag mechanism.
*
* @param[in] none
*
* @return none
*/
void publish_reset (void)
{
ccsip_publish_cb_t *pcb_p;
pcb_p = (ccsip_publish_cb_t *)sll_next(s_PCB_list, NULL);
while (pcb_p != NULL) {
send_resp_to_app(PUBLISH_FAILED_RESET, pcb_p->pub_handle, pcb_p->app_handle,
pcb_p->callback_task, pcb_p->resp_msg_id);
free_pcb(pcb_p);
pcb_p = (ccsip_publish_cb_t *)sll_next(s_PCB_list, NULL);
}
}
/**
* This function will print the stats (invoked by show command)
*
* @param[in] none
*
* @return 0 always
*/
cc_int32_t show_publish_stats (cc_int32_t argc, const char *argv[])
{
debugif_printf("------ Current PUBLISH Statistics ------\n");
if (s_PCB_list != NULL) {
debugif_printf("Number of PCBs allocated: %d\n", sll_count(s_PCB_list));
} else {
debugif_printf("Number of PCBs allocated: 0\n");
}
debugif_printf("Total outgoing PUBLISH requests: %d\n", outgoingPublishes);
return 0;
}
File diff suppressed because it is too large. Load diff
+284
View File
@@ -0,0 +1,284 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_string.h"
#include "ccsip_reldev.h"
#include "ccsip_macros.h"
#include "phone_debug.h"
#include "ccsip_pmh.h"
#include "ccsip_messaging.h"
#include "sip_common_transport.h"
#include "util_string.h"
/* Constants */
#define SIP_RRLIST_LENGTH (MAX_TEL_LINES)
/* Global variables */
sipRelDevMessageRecord_t gSIPRRList[SIP_RRLIST_LENGTH];
void
sipRelDevMessageStore (sipRelDevMessageRecord_t * pMessageRecord)
{
static int counter = 0;
/* Loop around */
if (counter > (SIP_RRLIST_LENGTH - 1)) {
counter = 0;
}
gSIPRRList[counter] = *pMessageRecord;
gSIPRRList[counter].valid_coupled_message = FALSE;
counter++;
}
boolean
sipRelDevMessageIsDuplicate (sipRelDevMessageRecord_t *pMessageRecord,
int *idx)
{
int i = 0;
for (i = 0; i < SIP_RRLIST_LENGTH; i++) {
if ((strcmp(pMessageRecord->call_id, gSIPRRList[i].call_id) == 0) &&
(pMessageRecord->cseq_number == gSIPRRList[i].cseq_number) &&
(pMessageRecord->cseq_method == gSIPRRList[i].cseq_method) &&
(strcasecmp_ignorewhitespace(pMessageRecord->tag, gSIPRRList[i].tag) == 0) &&
(strcmp(pMessageRecord->from_user, gSIPRRList[i].from_user) == 0) &&
(strcmp(pMessageRecord->from_host, gSIPRRList[i].from_host) == 0) &&
(strcmp(pMessageRecord->to_user, gSIPRRList[i].to_user) == 0)) {
if (pMessageRecord->is_request) {
*idx = i;
return (TRUE);
} else {
if (pMessageRecord->response_code == gSIPRRList[i].response_code) {
*idx = i;
return (TRUE);
}
}
}
}
*idx = -1;
return (FALSE);
}
/*
* 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.\n", 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.\n",
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);
}
/*
* Function: sipRelDevGetStoredCoupledMessage
*
* Parameters:
* idx - int for the idx to retrieve stored SIP message.
* dest_buffer - pointer to char to retrieve the copy of the
* stored SIP message.
* dest_buf_size - uint32_t for the size of the dest_buffer.
*
* Description:
* The function gets the stored SIP message for the request entry.
*
* Returns:
* The function returns the number of the bytes of the SIP message
* obtained if SIP message is found otherwise it returns zero (
* no SIP message available).
*/
uint32_t
sipRelDevGetStoredCoupledMessage (int idx,
char *dest_buffer,
uint32_t dest_buf_size)
{
sipRelDevMessageRecord_t *record;
if (dest_buffer == NULL) {
/* No destination buffer given, can not provide any result */
return (0);
}
if ((idx < 0) || (idx >= SIP_RRLIST_LENGTH)) {
/* the stored message is out of range */
return (0);
}
record = &gSIPRRList[idx];
if (!record->valid_coupled_message) {
/* No message stored for the given idx */
return (0);
}
if ((record->coupled_message.message_buf_len > dest_buf_size) ||
(record->coupled_message.message_buf_len == 0)) {
/*
* The stored message size is larger than the give buffer or
* stored message length is zero?
*/
return (0);
}
/* Get the stored message to the caller */
memcpy(dest_buffer, &record->coupled_message.message_buf[0],
record->coupled_message.message_buf_len);
return (record->coupled_message.message_buf_len);
}
int
sipRelDevCoupledMessageSend (int idx)
{
static const char *fname = "sipRelDevCoupledMessageSend";
char dest_ipaddr_str[MAX_IPADDR_STR_LEN];
if ((idx < 0) || (idx >= SIP_RRLIST_LENGTH)) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Argument Check: idx (=%d) out of bounds.\n",
fname, idx);
return SIP_ERROR;
}
if (gSIPRRList[idx].valid_coupled_message) {
ipaddr2dotted(dest_ipaddr_str,
&gSIPRRList[idx].coupled_message.dest_ipaddr);
CCSIP_DEBUG_MESSAGE(DEB_F_PREFIX"Sending stored coupled message (idx=%d) to "
"<%s>:<%d>\n", DEB_F_PREFIX_ARGS(SIP_MSG_SEND, fname), idx, dest_ipaddr_str,
gSIPRRList[idx].coupled_message.dest_port);
if (sipTransportChannelSend(NULL,
gSIPRRList[idx].coupled_message.message_buf,
gSIPRRList[idx].coupled_message.message_buf_len,
sipMethodInvalid,
&(gSIPRRList[idx].coupled_message.dest_ipaddr),
gSIPRRList[idx].coupled_message.dest_port,
0) < 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"sipTransportChannelSend() failed."
" Stored message not sent.\n", fname);
return SIP_ERROR;
}
} else {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Duplicate message detected but failed to"
" find valid coupled message. Stored message not sent.\n",
fname);
return SIP_ERROR;
}
return SIP_OK;
}
/*
* Function for clearing all the messages belonging to the
* associated with the specified call_id, from_user, from_host,
* and to_user
*/
void
sipRelDevMessagesClear (const char *call_id,
const char *from_user,
const char *from_host,
const char *to_user)
{
int i = 0;
for (i = 0; i < SIP_RRLIST_LENGTH; i++) {
if ((strcmp(call_id, gSIPRRList[i].call_id) == 0) &&
(strcmp(from_user, gSIPRRList[i].from_user) == 0) &&
(strcmp(from_host, gSIPRRList[i].from_host) == 0) &&
(strcmp(to_user, gSIPRRList[i].to_user) == 0)) {
memset(&gSIPRRList[i], 0, sizeof(sipRelDevMessageRecord_t));
}
}
return;
}
/*
* Function for clearing all the messages
*/
void sipRelDevAllMessagesClear(){
int i = 0;
for (i = 0; i < SIP_RRLIST_LENGTH; i++) {
memset(&gSIPRRList[i], 0, sizeof(sipRelDevMessageRecord_t));
}
return;
}
+354
View File
@@ -0,0 +1,354 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Implements functions to parse and create SDP(Session Description Protocol)
* (RFC 2327) messages. Coded to be sufficient for SIP only.
* Note: The SDP body fields as per the RFC are :
* Optional items are marked with a `*'.
*
* Session description
* v= (protocol version)
* o= (owner/creator and session identifier).
* s= (session name)
* i=* (session information)
* u=* (URI of description)
* e=* (email address)
* p=* (phone number)
* c=* (connection information - not required if included in all media)
* b=* (bandwidth information)
* One or more time descriptions (see below)
* z=* (time zone adjustments)
* k=* (encryption key)
* a=* (zero or more session attribute lines)
* Zero or more media descriptions (see below)
*
*Time description
* t= (time the session is active)
* r=* (zero or more repeat times)
*
*Media description
* m= (media name and transport address)
* i=* (media title)
* c=* (connection information - optional if included at session-level)
* b=* (bandwidth information)
* k=* (encryption key)
* a=* (zero or more media attribute lines)
*
* Note that the mandatory fields are :
* v= , o=, s=, t=, m=
* Email address and phone number (e=, p=) fields would very soon be useful
* to SDP in large scale SIP networks.
*
* t= 0 0
* would indicate an unbound or a permanent session . This would be changed
* to specific (or probably user-configured values) once the time duration
* of SIP call sessions are recorded and are used for scheduling.
*/
#include "cpr_types.h"
#include "cpr_memory.h"
#include "sdp.h"
#include "text_strings.h"
#include "ccsip_sdp.h"
#include "ccsip_core.h"
#include "phone_debug.h"
static void *ccsip_sdp_config = NULL; /* SDP parser/builder configuration */
/*
* sip_sdp_init
*
* This function initializes SDP parser with SIP-specific parameters.
* This includes supported media, network types, address types,
* transports and codecs.
*
* The function must be called once.
*
* Returns TRUE - successful
* FALSE - failed
*/
boolean
sip_sdp_init (void)
{
ccsip_sdp_config = sdp_init_config();
if (!ccsip_sdp_config) {
CCSIP_ERR_MSG("sdp_init_config() failure");
return FALSE;
}
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_AUDIO, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_VIDEO, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_APPLICATION, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_DATA, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_CONTROL, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_NAS_RADIUS, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_NAS_TACACS, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_NAS_DIAMETER, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_NAS_L2TP, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_NAS_LOGIN, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_NAS_NONE, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_IMAGE, TRUE);
sdp_media_supported(ccsip_sdp_config, SDP_MEDIA_TEXT, TRUE);
sdp_nettype_supported(ccsip_sdp_config, SDP_NT_INTERNET, TRUE);
sdp_addrtype_supported(ccsip_sdp_config, SDP_AT_IP4, TRUE);
sdp_addrtype_supported(ccsip_sdp_config, SDP_AT_IP6, TRUE);
sdp_transport_supported(ccsip_sdp_config, SDP_TRANSPORT_RTPAVP, TRUE);
sdp_transport_supported(ccsip_sdp_config, SDP_TRANSPORT_UDPTL, TRUE);
sdp_require_session_name(ccsip_sdp_config, FALSE);
return (TRUE);
}
/*
* sipsdp_create()
*
* Allocate a standard SDP with SIP config and set debug options
* based on ccsip debug settings
*/
sdp_t *
sipsdp_create (const char *peerconnection)
{
sdp_t *sdp;
sdp = sdp_init_description(peerconnection, ccsip_sdp_config);
if (!sdp) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"SDP allocation failure\n", __FUNCTION__);
return (NULL);
}
/*
* Map "ccsip debug events (or info)" to SDP warnings
* "ccsip debug errors to SDP errors
*/
CCSIP_INFO_DEBUG {
sdp_debug(sdp, SDP_DEBUG_WARNINGS, TRUE);
}
CCSIP_ERR_DEBUG {
sdp_debug(sdp, SDP_DEBUG_ERRORS, TRUE);
}
#ifdef DEBUG_SDP_LIB
/*
* Enabling this is redundant to the existing message printing
* available for the entire SIP text messages, so it is not
* enabled here. It is useful for debugging the SDP parser,
* however.
*/
CCSIP_MESSAGES_DEBUG {
sdp_debug(sdp, SDP_DEBUG_TRACE, TRUE);
}
#endif
return (sdp);
}
/*
* sipsdp_free()
*
* Frees the SIP SDP structure, the contained common SDP structure,
* and each stream structure in the linked stream list.
*
* sip_sdp is set to NULL after being freed.
*/
void
sipsdp_free (cc_sdp_t **sip_sdp)
{
const char *fname = "sipsdp_free: ";
sdp_result_e sdp_ret;
if (!*sip_sdp) {
return;
}
if ((*sip_sdp)->src_sdp) {
sdp_ret = sdp_free_description((*sip_sdp)->src_sdp);
if (sdp_ret != SDP_SUCCESS) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"%d while freeing src_sdp\n",
fname, sdp_ret);
}
}
if ((*sip_sdp)->dest_sdp) {
sdp_ret = sdp_free_description((*sip_sdp)->dest_sdp);
if (sdp_ret != SDP_SUCCESS) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"%d while freeing dest_sdp\n",
fname, sdp_ret);
}
}
SDP_FREE(*sip_sdp);
}
/*
* sipsdp_info_create()
*
* Allocates and initializes a SIP SDP structure. This function does
* not create the src_sdp, dest_sdp, or streams list.
*
* Returns: pointer to SIP SDP structure - if successful
* NULL - failure to allocate storage
*/
cc_sdp_t *
sipsdp_info_create (void)
{
cc_sdp_t *sdp_info = (cc_sdp_t *) cpr_malloc(sizeof(cc_sdp_t));
if (sdp_info) {
sdp_info->src_sdp = NULL;
sdp_info->dest_sdp = NULL;
}
return (sdp_info);
}
/*
* sipsdp_src_dest_free()
*
* Frees the SRC and/or DEST SDP. It will also free the sdp_info
* structure if both SRC and DEST SDP are freed.
*
* Input:
* flags - bitmask indicating if src and/or dest sdp should be
* freed
*
* Returns:
* sdp_info is set to NULL if freed.
*/
void
sipsdp_src_dest_free (uint16_t flags, cc_sdp_t **sdp_info)
{
const char *fname = "sipsdp_src_dest_free: ";
sdp_result_e sdp_ret;
if ((sdp_info == NULL) || (*sdp_info == NULL)) {
return;
}
/* Free the SRC and/or DEST SDP */
if (flags & CCSIP_SRC_SDP_BIT) {
if ((*sdp_info)->src_sdp) {
sdp_ret = sdp_free_description((*sdp_info)->src_sdp);
if (sdp_ret != SDP_SUCCESS) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"%d while freeing src_sdp\n",
fname, sdp_ret);
}
(*sdp_info)->src_sdp = NULL;
}
}
if (flags & CCSIP_DEST_SDP_BIT) {
if ((*sdp_info)->dest_sdp) {
sdp_ret = sdp_free_description((*sdp_info)->dest_sdp);
if (sdp_ret != SDP_SUCCESS) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"%d while freeing dest_sdp\n",
fname, sdp_ret);
}
(*sdp_info)->dest_sdp = NULL;
}
}
/*
* If both src and dest sdp are NULL, there is no need to keep the
* sdp_info structure around. Free it.
*/
if (((*sdp_info)->src_sdp == NULL) && ((*sdp_info)->dest_sdp == NULL)) {
sipsdp_free(sdp_info);
*sdp_info = NULL;
}
}
/*
* sipsdp_src_dest_create()
*
* Allocates and initializes a SRC and/or DEST SDP. If the sdp_info
* structure has not yet been allocated, it is allocated here.
*
* Input:
* flags - bitmask indicating if src and/or dest sdp should be
* created
*
* Returns: pointer to SIP SDP structure - if successful
* NULL - failure to allocate storage
*/
void
sipsdp_src_dest_create (const char *peerconnection,
uint16_t flags, cc_sdp_t **sdp_info)
{
if (!(*sdp_info)) {
*sdp_info = sipsdp_info_create();
if (!(*sdp_info)) {
return;
}
}
/* Create the SRC and/or DEST SDP */
if (flags & CCSIP_SRC_SDP_BIT) {
(*sdp_info)->src_sdp = sipsdp_create(peerconnection);
if (!((*sdp_info)->src_sdp)) {
sipsdp_src_dest_free(flags, sdp_info);
return;
}
}
if (flags & CCSIP_DEST_SDP_BIT) {
(*sdp_info)->dest_sdp = sipsdp_create(peerconnection);
if (!((*sdp_info)->dest_sdp)) {
sipsdp_src_dest_free(flags, sdp_info);
return;
}
}
}
/*
* sipsdp_write_to_buf()
*
* This function builds the specified SDP in a text buffer and returns
* a pointer to this buffer.
*
* Returns: pointer to buffer - no errors
* NULL - errors were encountered while building
* the SDP. The details of the build failure
* can be determined by enabling SDP debugs
* and by examining SDP library error counters.
*/
char *
sipsdp_write_to_buf (cc_sdp_t *sdp_info, uint32_t *retbytes)
{
flex_string fs;
uint32_t sdp_len;
sdp_result_e rc;
flex_string_init(&fs);
if (!sdp_info || !sdp_info->src_sdp) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"NULL sdp_info or src_sdp\n", __FUNCTION__);
return (NULL);
}
if ((rc = sdp_build(sdp_info->src_sdp, &fs))
!= SDP_SUCCESS) {
CCSIP_DEBUG_TASK(DEB_F_PREFIX"sdp_build rc=%s\n", DEB_F_PREFIX_ARGS(SIP_SDP, __FUNCTION__),
sdp_get_result_name(rc));
flex_string_free(&fs);
*retbytes = 0;
return (NULL);
}
*retbytes = fs.string_length;
/* We are not calling flex_string_free on this, instead returning the buffer
* caller's responsibility to free
*/
return fs.buffer;
}
+134
View File
@@ -0,0 +1,134 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file implements a bunch of stuff used only by ccsip_spi.c,
* and this is done mostly to reduce the file size and some extra
* modularity. Includes things like tables/trees to hold SIP and
* CCAPI callids, conversion from CCAPI to SIP cause codes and the
* like.
*/
#include "plstr.h"
#include "cpr_types.h"
#include "cpr_stdlib.h"
#include "cpr_string.h"
#include "pmhutils.h"
#include "ccsip_spi_utils.h"
#include "util_string.h"
#include "ccsip_core.h"
extern uint32_t IPNameCk(char *name, char *addr_error);
/*
* Checks a token which forms a part of the
* domain-name and makes sure that it conforms
* to the grammar specified in RFC 1034 (DNS)
*/
int
sipSPICheckDomainToken (char *token)
{
if (token == NULL) {
return FALSE;
}
if (*token) {
if (isalnum((int)token[strlen(token) - 1]) == FALSE) {
return FALSE;
}
}
if (isalnum((int)token[0]) == FALSE) {
return FALSE;
}
while (*token) {
if ((isalnum((int)*token) == FALSE) && (*token != '-')) {
return FALSE;
}
token++;
}
return TRUE;
}
/*
* Checks domain-name is valid syntax-wise
* Returns TRUE, if valid
*/
boolean
sipSPI_validate_hostname (char *str)
{
char *tok;
char ip_addr_out[MAX_IPADDR_STR_LEN];
char *strtok_state;
if (str == NULL) {
return FALSE;
}
/* Check if valid IPv6 address */
if (cpr_inet_pton(AF_INET6, str, ip_addr_out)) {
return TRUE;
}
if (*str) {
if (isalnum((int)str[strlen(str) - 1]) == FALSE) {
return FALSE;
}
}
if (isalnum((int)str[0]) == FALSE) {
return FALSE;
}
tok = PL_strtok_r(str, ".", &strtok_state);
if (tok == NULL) {
return FALSE;
} else {
if (sipSPICheckDomainToken(tok) == FALSE) {
return FALSE;
}
}
while ((tok = PL_strtok_r(NULL, ".", &strtok_state)) != NULL) {
if (sipSPICheckDomainToken(tok) == FALSE) {
return FALSE;
}
}
return TRUE;
}
/*
* Determines if the IP address or domain-name is
* valid (syntax-wise only)
* Returns TRUE, if valid
*/
boolean
sipSPI_validate_ip_addr_name (char *str)
{
uint32_t sip_address;
boolean retval = TRUE;
char *target = NULL;
char addr_error;
if (str == NULL) {
return FALSE;
} else {
target = cpr_strdup(str);
if (!target) {
return FALSE;
}
}
sip_address = IPNameCk(target, &addr_error);
if ((!sip_address) && (addr_error)) {
cpr_free(target);
return retval;
} else {
if (sipSPI_validate_hostname(target) == FALSE) {
retval = FALSE;
}
}
cpr_free(target);
return retval;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,86 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_CALLINFO_H_
#define _CCSIP_CALLINFO_H_
#include "cpr_types.h"
#include "ccapi.h"
#include "ccsip_core.h"
#define MAX_SIP_HEADER_LENGTH 1024
#define MAX_URI_LENGTH 256
#define URN_REMOTECC "urn:x-cisco-remotecc:"
#define LAQUOT '<'
#define RAQUOT '>'
#define SPACE ' '
#define TAB '\t'
#define SEMI_COLON ';'
// Feature string that appear in the feature-urn. For example in
// <urn:x-cisco-remotecc:hold>, "hold" is the feature string.
#define SIP_CI_HOLD_STR "hold"
#define SIP_CI_RESUME_STR "resume"
#define SIP_CI_BARGE_STR "barge"
#define SIP_CI_CBARGE_STR "cbarge"
#define SIP_CI_CALL_INFO_STR "callinfo"
#define SIP_CI_SILENT_STR "silent"
#define SIP_CI_COACHING_STR "coaching"
// Definitions relating to the hold-resume feature urn.
#define SIP_CI_HOLD_REASON "reason="
#define SIP_CI_HOLD_REASON_XFER "transfer"
#define SIP_CI_HOLD_REASON_CONF "conference"
// Definitions relating to the callinfo feature urn.
#define SIP_CI_SECURITY "security="
#define SIP_CI_SECURITY_UNKNOWN "unknown"
#define SIP_CI_SECURITY_NOT_AUTH "NotAuthenticated"
#define SIP_CI_SECURITY_AUTH "Authenticated"
#define SIP_CI_SECURITY_ENCRYPTED "Encrypted"
#define SIP_CI_ORIENTATION "orientation="
#define SIP_CI_ORIENTATION_TO "to"
#define SIP_CI_ORIENTATION_FROM "from"
#define SIP_CI_POLICY "policy="
#define SIP_CI_POLICY_UNKNOWN "unknown"
#define SIP_CI_POLICY_CHAPERONE "chaperone"
#define SIP_CI_CALL_INSTANCE "call-instance="
#define SIP_CI_CTI_CALLID "cti-callid="
#define SIP_CI_UI_STATE "ui-state="
#define SIP_CI_UI_STATE_RINGOUT "ringout"
#define SIP_CI_UI_STATE_CONNECTED "connected"
#define SIP_CI_PRIORITY "priority="
#define SIP_CI_PRIORITY_URGENT "urgent"
#define SIP_CI_PRIORITY_EMERGENCY "emergency"
#define SIP_CI_UI_STATE_BUSY "busy"
#define SIP_CI_GCID "gci="
#define SIP_CI_DUSTINGCALL "isDustingCall"
// Definitions relating to a generic feature parm.
#define SIP_CI_GENERIC "purpose="
#define SIP_CI_GENERIC_ICON "icon"
#define SIP_CI_GENERIC_INFO "info"
#define SIP_CI_GENERIC_CARD "card"
#define SKIP_LWS(p) while (*p == SPACE || *p == TAB) { \
p++; \
}
#define SKIP_WHITE_SPACE(p) while (*p == SPACE || *p == TAB || \
*p == '\n') { \
p++; \
}
/*
* Encoding function
*/
char* ccsip_encode_call_info_hdr(cc_call_info_t *call_info_p,
const char *misc_parms_p);
void ccsip_free_call_info_header(cc_call_info_t *call_info_p);
void ccsip_store_call_info(cc_call_info_t *call_info_p, ccsipCCB_t* ccb);
void ccsip_process_call_info_header(sipMessage_t *request_p, ccsipCCB_t* ccb);
#endif
+41
View File
@@ -0,0 +1,41 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_CC_H_
#define _CCSIP_CC_H_
#include "ccapi.h"
void sip_cc_setup(int gsm_call_id, int line, string_t calling_name,
string_t calling_number, string_t alt_calling_number, boolean display_calling_number,
string_t called_name, string_t called_number,
boolean display_called_number, string_t orig_called_name,
string_t orig_called_number, string_t last_redirect_name,
string_t last_redirect_number, cc_call_type_e call_type,
cc_alerting_type alert_info, vcm_ring_mode_t alerting_ring,
vcm_tones_t alerting_tone, cc_call_info_t *call_info_p,
boolean replaces, string_t recv_info_list, sipMessage_t *sip_msg);
void sip_cc_setup_ack(int call_id, int line, cc_msgbody_info_t *msg_body);
void sip_cc_proceeding(int gsm_call_id, int line);
void sip_cc_alerting(int gsm_call_id, int line, sipMessage_t *sip_msg,
int inband);
void sip_cc_connected(int gsm_call_id, int line, string_t recv_info_list, sipMessage_t *sip_msg);
void sip_cc_connected_ack(int gsm_call_id, int line, sipMessage_t *sip_msg);
void sip_cc_release(int gsm_call_id, int line, cc_causes_t cause,
const char *dialstring);
void sip_cc_release_complete(int gsm_call_id, int line, cc_causes_t cause);
void sip_cc_feature(int call_id, int line, int feature, void *data);
void sip_cc_feature_ack(int call_id, int line, int feature, void *data,
cc_causes_t cause);
void sip_cc_mwi(int call_id, int line, boolean on, int type,
int newCount, int oldCount, int hpNewCount, int hpOldCount);
void sip_cc_mv_msg_body_to_cc_msg(cc_msgbody_info_t *cc_msg,
sipMessage_t *sip_msg);
boolean sip_cc_create_cc_msg_body_from_sip_msg(cc_msgbody_info_t *cc_msg,
sipMessage_t *sip_msg);
void sip_cc_options(callid_t call_id, line_t line, sipMessage_t *pSipMessage);
void sip_cc_audit(callid_t call_id, line_t line, boolean apply_ringout);
#endif
@@ -0,0 +1,56 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_COMMON_CB_H_
#define _CCSIP_COMMON_CB_H_
#include "cpr_types.h"
#include "phone_types.h"
#include "ccapi.h"
#include "dns_utils.h"
#include "ccsip_platform.h"
#include "ccsip_pmh.h"
#include "ccsip_core.h"
#include "xml_parser_defines.h"
#define HOOK_STATUS_STR "hook status"
#define BLF_SPEEDDIAL_STR "blf speed dial"
typedef enum {
SUBNOT_CB,
PUBLISH_CB,
UNSOLICIT_NOTIFY_CB
} ccsip_cb_type_e;
typedef struct {
ccsip_cb_type_e cb_type;
line_t dn_line;
cpr_ip_addr_t dest_sip_addr;
uint32_t dest_sip_port; /* Destination port */
cpr_ip_addr_t src_addr; /* Source address */
uint32_t local_port; /* Source port */
srv_handle_t SRVhandle; /* handle for dns_gethostbysrv() */
unsigned int retx_counter;
boolean retx_flag;
char sipCallID[MAX_SIP_CALL_ID];
sipAuthenticate_t authen;
long orig_expiration; /* Original time to expire */
long expires; /* Running expiry timer */
ccsip_event_data_t *event_data_p;
cc_subscriptions_t event_type; /* event type, such as presence */
cc_subscriptions_t accept_type; /* accept type, such as presence */
} ccsip_common_cb_t;
extern void ccsip_common_util_set_dest_ipaddr_port(ccsip_common_cb_t *cb_p);
extern void ccsip_common_util_set_src_ipaddr(ccsip_common_cb_t *cb_p);
extern void ccsip_common_util_set_retry_settings(ccsip_common_cb_t *cb_p, int *timeout_p);
extern boolean ccsip_common_util_generate_auth(sipMessage_t *pSipMessage, ccsip_common_cb_t *cb_p,
const char *rsp_method, int response_code, char *uri);
extern void ccsip_util_extract_user(char *url, char *user);
extern void ccsip_util_get_from_entity(sipMessage_t *pSipMessage, char *entity);
#endif //_CCSIP_COMMON_CB_H_
+866
View File
@@ -0,0 +1,866 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_CORE_H_
#define _CCSIP_CORE_H_
#include "cpr_types.h"
#include "cpr_memory.h"
#include "task.h"
//#include "network.h"
#include "ccapi.h"
#include "ccsip_sdp.h"
#include "ccsip_pmh.h"
#include "config.h"
#include "dns_utils.h"
#include "ccsip_platform.h"
#include "ccsip_platform_timers.h"
#include "cc_constants.h"
#include "sessionConstants.h"
#define SIP_DEFER (-2)
#define SIP_ERROR (-1)
#define SIP_OK (0)
#define SIP_L_C_F_PREFIX "SIP : %d/%d : %s : " // requires 3 args: line_id, call_id, fname
#define SIP_F_PREFIX "SIP : %s : " // requires 1 arg: fname
#define SUPERVISION_DISCONNECT_TIMEOUT 32000
#define SIP_WARNING_LENGTH 100
#define RPID_DISABLED 0
#define RPID_ENABLED 1
#define MAX_INVITE_RETRY_ATTEMPTS 6
#define MAX_NON_INVITE_RETRY_ATTEMPTS 10
typedef enum {
SIP_STATE_NONE = -1,
SIP_STATE_BASE = 0,
SIP_STATE_IDLE = SIP_STATE_BASE,
SIP_STATE_SENT_INVITE,
SIP_STATE_SENT_INVITE_CONNECTED,
SIP_STATE_RECV_INVITE,
SIP_STATE_RECV_INVITE_PROCEEDING,
SIP_STATE_RECV_INVITE_ALERTING,
SIP_STATE_RECV_INVITE_CONNECTED,
SIP_STATE_ACTIVE,
SIP_STATE_SENT_MIDCALL_INVITE,
SIP_STATE_RECV_MIDCALL_INVITE_CCFEATUREACK_PENDING,
SIP_STATE_RECV_MIDCALL_INVITE_SIPACK_PENDING,
SIP_STATE_RELEASE,
SIP_STATE_BLIND_XFER_PENDING,
SIP_STATE_IDLE_MSG_TIMER_OUTSTANDING,
SIP_STATE_SENT_OOD_REFER,
SIP_STATE_RECV_UPDATEMEDIA_CCFEATUREACK_PENDING,
SIP_STATE_END = SIP_STATE_RECV_UPDATEMEDIA_CCFEATUREACK_PENDING
} sipSMStateType_t;
typedef enum
{
SIP_REG_STATE_INV = -1,
SIP_REG_STATE_NONE = 0,
SIP_REG_STATE_BASE = 1,
SIP_REG_STATE_IDLE = SIP_REG_STATE_BASE,
SIP_REG_STATE_REGISTERING,
SIP_REG_STATE_REGISTERED,
SIP_REG_STATE_UNREGISTERING,
SIP_REG_STATE_IN_FALLBACK,
SIP_REG_STATE_STABILITY_CHECK,
SIP_REG_STATE_TOKEN_WAIT,
SIP_REG_STATE_END = SIP_REG_STATE_TOKEN_WAIT
} sipRegSMStateType_t;
typedef enum {
SIPSPI_EV_INVALID = -1,
SIPSPI_EV_BASE = 0,
E_SIP_INVITE = SIPSPI_EV_BASE,
E_SIP_ACK,
E_SIP_BYE,
E_SIP_CANCEL,
E_SIP_1xx,
E_SIP_2xx,
E_SIP_3xx,
E_SIP_NOTIFY,
E_SIP_FAILURE_RESPONSE,
E_SIP_REFER,
E_SIP_OPTIONS,
E_SIP_SUBSCRIBE,
E_SIP_UPDATE,
E_CC_SETUP,
E_CC_SETUP_ACK,
E_CC_PROCEEDING,
E_CC_ALERTING,
E_CC_CONNECTED,
E_CC_CONNECTED_ACK,
E_CC_RELEASE,
E_CC_RELEASE_COMPLETE,
E_CC_FEATURE,
E_CC_FEATURE_ACK,
E_CC_CAPABILITIES,
E_CC_CAPABILITIES_ACK,
E_CC_SUBSCRIBE,
E_CC_NOTIFY,
E_CC_INFO,
E_SIP_INV_EXPIRES_TIMER,
E_SIP_INV_LOCALEXPIRES_TIMER,
E_SIP_SUPERVISION_DISCONNECT_TIMER,
E_SIP_TIMER,
E_SIP_GLARE_AVOIDANCE_TIMER,
E_SIP_UPDATE_RESPONSE,
E_SIP_ICMP_UNREACHABLE,
SIPSPI_EV_END = E_SIP_ICMP_UNREACHABLE
} sipSMEventType_t;
typedef enum {
H_INVALID_EVENT = -1,
SIPSPI_EV_INDEX_BASE = 0,
/*0*/H_IDLE_EV_SIP_INVITE = SIPSPI_EV_INDEX_BASE, /* ccsip_handle_idle_ev_sip_invite, */
/*1*/H_IDLE_EV_CC_SETUP, /* ccsip_handle_idle_ev_cc_setup, */
/*2*/H_SENTINVITE_EV_SIP_1XX, /* ccsip_handle_sentinvite_ev_sip_1xx, */
/*3*/H_SENTINVITE_EV_SIP_2XX, /* ccsip_handle_sentinvite_ev_sip_2xx, */
/*4*/H_SENTINVITE_EV_SIP_FXX, /* ccsip_handle_sentinvite_ev_sip_fxx, */
/*5*/H_DISCONNECT_LOCAL_EARLY, /* ccsip_handle_disconnect_local_early, */
/*6*/H_DISCONNECT_REMOTE, /* ccsip_handle_disconnect_remote, */
/*7*/H_SENTINVITECONNECTED_EV_CC_CONNECTED_ACK, /* ccsip_handle_sentinviteconnected_ev_cc_connected_ack, */
/*8*/H_DISCONNECT_LOCAL, /* ccsip_handle_disconnect_local, */
/*9*/H_RECVINVITE_EV_CC_SETUP_ACK, /* ccsip_handle_recvinvite_ev_cc_setup_ack, */
/*10*/H_RECVINVITE_EV_CC_PROCEEDING, /* ccsip_handle_recvinvite_ev_cc_proceeding, */
/*11*/H_RECVINVITE_EV_CC_ALERTING, /* ccsip_handle_recvinvite_ev_cc_alerting, */
/*12*/H_RECVINVITE_EV_CC_CONNECTED, /* ccsip_handle_recvinvite_ev_cc_connected, */
/*13*/H_DISCONNECT_LOCAL_UNANSWERED, /* ccsip_handle_disconnect_local_unanswered, */
/*14*/H_RECVINVITE_EV_SIP_ACK, /* ccsip_handle_recvinvite_ev_sip_ack, */
/*15*/H_ACTIVE_EV_SIP_INVITE, /* ccsip_handle_active_ev_sip_invite, */
/*16*/H_ACTIVE_EV_CC_FEATURE, /* ccsip_handle_active_ev_cc_feature, */
/*17*/H_ACCEPT_2XX, /* ccsip_handle_accept_2xx, */
/*18*/H_REFER_SIP_MESSAGE, /* ccsip_handle_refer_sip_message, */
/*19*/H_ACTIVE_EV_CC_FEATURE_ACK, /* ccsip_handle_active_ev_cc_feature_ack, */
/*20*/H_SENTINVITE_MIDCALL_EV_SIP_2XX, /* ccsip_handle_sentinvite_midcall_ev_sip_2xx */
/*21*/H_SENTINVITE_MIDCALL_EV_CC_FEATURE, /* ccsip_handle_sentinvite_midcall_ev_cc_feature */
/*22*/H_RECVMIDCALLINVITE_CCFEATUREACKPENDING_EV_CC_FEATURE_ACK, /* ccsip_handle_recvmidcallinvite_ccfeatureackpending_ev_cc_feature_ack */
/*23*/H_RECVMIDCALLINVITE_SIPACKPENDING_EV_SIP_ACK, /* ccsip_handle_recvmidcallinvite_sipackpending_ev_sip_ack, */
/*24*/H_DEFAULT_SIP_MESSAGE, /* ccsip_handle_default_sip_message, */
/*25*/H_DEFAULT_SIP_RESPONSE, /* ccsip_handle_default_sip_response, */
/*26*/H_DEFAULT, /* ccsip_handle_default, */
/*27*/H_SIP_INV_EXPIRES_TIMER, /* ccsip_handle_disconnect_local_early, */
/*28*/H_SIP_OPTIONS, /* ccsip_handle_answer_options_request, */
/*29*/H_SENTINVITE_EV_SIP_3XX, /* ccsip_handle_sentinvite_ev_sip_3xx, */
/*30*/H_RECV_ERR_EV_SIP_ACK, /* ccsip_handle_recv_error_response_ev_sip_ack,*/
/*31*/H_SENTBYE_EV_SIP_2XX, /* ccsip_handle_sentbye_ev_sip_2xx,*/
/*32*/H_SENTBYE_EV_SIP_1XX, /* ccsip_handle_sentbye_ev_sip_1xx,*/
/*33*/H_SENTBYE_EV_SIP_FXX, /* ccsip_handle_sentbye_ev_sip_fxx,*/
/*34*/H_SENTBYE_EV_SIP_INVITE, /* ccsip_handle_sentbye_recvd_invite,*/
/*35*/H_SENTBYE_SUPERVISION_DISCONNECT_TIMER, /* ccsip_handle_sendbye_ev_supervision_disconnect*/
/*36*/H_RELEASE_COMPLETE, /* ccsip_handle_release_complete, */
/*37*/H_ACTIVE_2xx, /* ccsip_handle_Active_2xx*/
/*38*/H_BLIND_NOTIFY, /* ccsip_handle_send_blind_notify, */
/*39*/H_SENT_BLINDNTFY, /* ccsip_handle_sentblindntfy_ev_sip_2xx, */
/*40*/H_BYE_RELEASE, /* ccsip_handle_release_ev_sip_bye, */
/*41*/H_HANDLE_LOCALEXPIRES_TIMER, /* ccsip_handle_localexpires_timer */
/*42*/H_DEFAULT_SIP_TIMER, /* ccsip_handle_default_sip_timer */
/*43*/H_EARLY_EV_SIP_UPDATE, /* ccsip_handle_early_ev_sip_update */
/*44*/H_EARLY_EV_SIP_UPDATE_RESPONSE, /* ccsip_handle_early_ev_sip_update_response */
/*45*/H_EARLY_EV_CC_FEATURE, /* ccsip_handle_early_ev_cc_feature */
/*46*/H_EARLY_EV_CC_FEATURE_ACK, /* ccsip_handle_early_ev_cc_feature_ack */
/*47*/H_CONFIRM_EV_SIP_UPDATE, /* ccsip_handle_active_ev_sip_update */
/*48*/H_RECVUPDATEMEDIA_CCFEATUREACKPENDING_EV_CC_FEATURE_ACK, /* ccsip_handle_recvupdatemedia_ccfeatureackpending_ev_cc_feature_ack */
/*49*/H_SIP_GLARE_AVOIDANCE_TIMER, /* ccsip_handle_timer_glare_avoidance */
/*50*/H_RECVINVITE_SENTOK_NO_SIP_ACK, /* ccsip_handle_recvinvite_ev_expires_timer */
/*51*/H_EV_SIP_UNSOLICITED_NOTIFY, /* ccsip_handle_unsolicited_notify */
/*52*/H_RECVINVITE_EV_SIP_2XX, /* ccsip_handle_recvinvite_ev_sip_2xx */
/*53*/H_ICMP_UNREACHABLE, /* ccsip_handle_icmp_unreachable */
/*54*/H_DISCONNECT_MEDIA_CHANGE, /* ccsip_handle_disconnect_media_change*/
/*55*/H_DEFAULT_EV_CC_FEATURE, /* ccsip_handle_default_ev_cc_feature */
/*56*/H_DEFAULT_RECVREQ_ACK_PENDING_EV_CC_FEATURE, /* ccsip_handle_default_recvreq_ack_pending_ev_cc_feature */
/*57*/H_OOD_REFER_RESPONSE_EV_SIP_1xx, /* ccsip_handle_sent_ood_refer_ev_sip_1xx */
/*58*/H_OOD_REFER_RESPONSE_EV_SIP_2xx, /* ccsip_handle_sent_ood_refer_ev_sip_2xx */
/*59*/H_OOD_REFER_RESPONSE_EV_SIP_fxx, /* ccsip_handle_sent_ood_refer_ev_sip_fxx */
/*60*/H_RELEASE_EV_CC_FEATURE, /* ccsip_handle_release_ev_cc_feature */
/*61*/H_EV_CC_INFO, /* ccsip_handle_ev_cc_info */
/*62*/H_RELEASE_EV_RELEASE, /* ccsip_handle_release_ev_release */
SIPSPI_EV_INDEX_END = H_RELEASE_EV_RELEASE
} sipSMAction_t;
/*
* This structure defines TCP/UDP Connection
* Parameters.
* This is used during processing Contact
* and Route headers received in the SIP
* messages
*/
typedef enum {
SIP_SM_DIS_METHOD_BYE = 0,
SIP_SM_DIS_METHOD_CANCEL
} sipSMDisMethod_t;
typedef struct {
char last_call_id[MAX_SIP_CALL_ID];
uint32_t last_bye_cseq_number;
cpr_ip_addr_t last_bye_dest_ipaddr;
uint16_t last_bye_dest_port;
cpr_ip_addr_t proxy_dest_ipaddr;
line_t dn_line;
char last_bye_also_string[MAX_SIP_URL_LENGTH];
char last_route[MAX_SIP_URL_LENGTH];
char last_route_request_uri[MAX_SIP_URL_LENGTH];
char via_branch[VIA_BRANCH_LENGTH];
sipStatusCodeClass_t last_rspcode_rcvd;
} sipCallHistory_t;
typedef enum {
SIP_SM_NO_XFR = 0,
SIP_SM_BLND_XFR,
SIP_SM_ATTN_XFR
} sipSMXfrType_t;
typedef struct sipRedirectInfo_ {
sipContact_t *sipContact; /* Contact header received in the 3xx */
uint16_t next_choice; /* Index of next Contact location to use */
} sipRedirectInfo_t;
typedef struct {
int retries_401_407;
int cred_type;
char *authorization;
int status_code;
sip_authen_t *sip_authen;
char cnonce[9];
int nc_count;
boolean new_flag;
} sipAuthenticate_t;
/* SIP REGISTER method info */
typedef struct {
int registered;
int tmr_expire;
int act_time;
char proxy[MAX_IPADDR_STR_LEN];
cpr_ip_addr_t addr;
uint16_t port;
uint8_t rereg_pending;
} sipRegister_t;
/* AVT payload info */
typedef struct {
int payload_type; //TODO BLASBERG: uint8_t or uint16_t should be acceptable
} sipAvtPayloadType_t;
/* Identifies CCB type because registration & call control use the same CCBs */
typedef enum {
SIP_NONE_CCB,
SIP_REG_CCB,
SIP_CALL_CCB
} sipCCBTypes_t;
/*
* Define the types of CC's
*/
typedef enum {
CC_CCM = CC_MODE_CCM,
CC_OTHER = CC_MODE_NONCCM,
MAX_CC_TYPES
} CC_ID;
/*
* Offer/answer state
*/
typedef enum {
OA_IDLE,
OA_OFFER_SENT,
OA_OFFER_RECEIVED,
OA_ANSWER_SENT,
OA_ANSWER_RECEIVED
} sipOfferAnswerState;
/* Indentifies how proxy selection is being done */
typedef enum {
SIP_PROXY_DEFAULT, /* Current selection is configured proxy */
SIP_PROXY_BACKUP, /* Current selection is configured backup proxy */
SIP_PROXY_DO_NOT_CHANGE_MIDCALL /* Do not select a different proxy even on failure*/
} sipCCBProxySelection;
typedef struct
{
union {
string_t sip_via_header; // For received requests
string_t sip_via_branch; // For sent requests
} u;
string_t sip_via_sentby;
sipMethod_t cseq_method;
uint32_t cseq_number;
} sipTransaction_t;
typedef struct
{
char sipCallID[MAX_SIP_CALL_ID];
callid_t gsm_id;
callid_t con_call_id;
callid_t blind_xfer_call_id;
sipSMStateType_t state;
line_t index;
line_t dn_line;
boolean hold_initiated;
uint32_t retx_counter;
sipCCBTypes_t type;
/*
* first_backup indicates whether or not the backup proxy has just been
* activated. After the first message is retransmitted, the flag will be
* reset to FALSE.
*/
boolean first_backup;
sipCCBProxySelection proxySelection; /* Indicates how proxy selection is being done */
cpr_ip_addr_t outBoundProxyAddr; /* IP address of outbound proxy for this call */
// uint16_t outBoundProxyPort; /* Outbound proxy port for this call */
uint32_t outBoundProxyPort; /* Outbound proxy port for this call */
srv_handle_t SRVhandle; /* handle for dns_gethostbysrv() */
srv_handle_t ObpSRVhandle; /* SRVhandle for the outbound proxy */
int routeMode; /* Current routemode set by UIMatchDialTemplate() */
void *udpId; /* handle to UDPApplIcmpHandler */
/*
* An INVITE/ACK/1xx/2xx can be accompanied with a Contact header.
* Future requests should go there. This field is used to store the
* parsed Contact header received with any of these messages.
*/
sipContact_t *contact_info;
/* Refer To and refere by headers Needed for next generated call */
/*
* Any SIP request such as INVITE, BYE, CANCEL etc and INVITE 200 OK,
* 401 & 484 responses can have a Record-Route header. This field is
* used to store the parsed Record-Route header received in any of
* these messages.
*/
sipRecordRoute_t *record_route_info;
string_t calledDisplayedName;
string_t callingNumber;
string_t altCallingNumber;
string_t callingDisplayName;
string_t calledNumber;
boolean displayCalledNumber;
boolean displayCallingNumber;
uint16_t calledNumberLen;
boolean calledNumberFirstDigitDialed;
/*
* The following field encodes boolean bit flags (on or off) for
* loopback, inband_alerting, sip_tcp, incoming, added_to_table,
* do_call_history, rsvp_reserved, msgPassthru, sigoCall,
* sent_bye, sent_cancel, sent_bye_response, sent_3456xx, recd_456xx,
* harikiri, timed_out, sd_in_ack
*/
uint32_t flags;
#define LOOPBACK 1
#define INBAND_ALERTING (1<<1)
#define SIP_TCP (1<<2)
#define INCOMING (1<<3)
#define ADDED_TO_TABLE (1<<4)
#define DO_CALL_HISTORY (1<<5)
#define RSVP_RESERVED (1<<6)
#define SENT_BYE (1<<7)
#define SENT_CANCEL (1<<8)
#define RECD_BYE (1<<9)
#define SENT_3456XX (1<<10)
#define RECD_456XX (1<<11)
#define HARIKIRI (1<<12)
#define TIMED_OUT (1<<13)
#define SD_IN_ACK (1<<14)
#define MSG_PASSTHRU (1<<15)
#define SIGO_CALL (1<<16)
#define RECD_1xx (1<<17)
#define SEND_CANCEL (1<<18)
#define FINAL_NOTIFY (1<<19)
#define SENT_INVITE_REPLACE (1<<20)
/*
* SIP signalling channel info: source and destination
*/
cpr_ip_addr_t src_addr; /* Source address */
cpr_ip_addr_t dest_sip_addr; /* Destination address */
// uint16_t local_port; /* Source port */
// uint16_t dest_sip_port; /* Destination port */
uint32_t local_port; /* Source port */
uint32_t dest_sip_port; /* Destination port */
int16_t sip_socket_handle;
/*
* RTP/SDP
*/
cc_msgbody_info_t local_msg_body; /* store local sent msg bodies */
// sipSdp_t *src_sdp;
// ushort src_port;
// sipSdp_t *dest_sdp;
// uint16_t dest_port;
// uint32_t dest_addr;
char *old_session_id;
char *old_version_id;
// ushort dest_sdp_media;
// boolean rtp_rx_opened;
// boolean rtp_tx_opened;
// cc_sdp_t cc_sdp;
/*
* Headers
*/
char ReqURI[MAX_SIP_URL_LENGTH]; /* "Working" Req-URI */
string_t ReqURIOriginal; /* Original outgoing call Req-URI */
string_t sip_from;
string_t sip_to;
string_t sip_to_tag;
string_t sip_from_tag;
string_t sip_contact;
string_t sip_remote_party_id;
string_t sip_reqby;
string_t sip_require;
string_t sip_unsupported;
char *diversion[MAX_DIVERSION_HEADERS];
#define MAX_REQ_OUTSTANDING 3
sipTransaction_t sent_request[MAX_REQ_OUTSTANDING];
sipTransaction_t recv_request[MAX_REQ_OUTSTANDING];
uint32_t last_recv_request_cseq;
sipMethod_t last_recv_request_cseq_method;
uint32_t last_used_cseq;
uint32_t last_recv_invite_cseq;
string_t sip_referTo;
string_t sip_referredBy;
string_t referto;
string_t sipxfercallid;
boolean wastransferred;
boolean blindtransferred;
unsigned int xfer_status;
/* Store all of the parsed diversion header info */
sipDiversionInfo_t *div_info;
cc_call_type_e call_type;
/* Store all of the parsed Remote-Party-ID headers */
sipRemotePartyIdInfo_t *rpid_info;
/* Shallow pointer to the "best" parsed Remote-Party-ID header */
sipRemotePartyId_t *best_rpid;
/* To save the Via headers on the INVITE */
sipMessage_t *last_request;
/*
* Features
*/
sipSMXfrType_t xfr_inprogress;
cc_features_t featuretype;
sipAvtPayloadType_t avt;
/*
* Registration/Authentication
*/
sipRegister_t reg;
sipAuthenticate_t authen;
/*
* Two fields that can be sent with the Refer-To header
*/
char *refer_proxy_auth;
#ifdef SIP_ACC_CONT
char *refer_acc_cont;
#endif
/*
* This struct would be allocated when the call is actually redirected
* Idea is to save memory in the ccb for non-redirected calls.
*/
sipRedirectInfo_t *redirect_info;
/*
* Enum of what was in the alert-info header.
*/
cc_alerting_type alert_info;
/*
* Contents of incoming and outgoing call-info headers
*/
cc_call_info_t *in_call_info;
cc_call_info_t *out_call_info;
/*
* Ringing/tone pattern to play
*/
vcm_ring_mode_t alerting_ring;
vcm_tones_t alerting_tone;
/*
* Personal Directory
*/
boolean call_entered_into_pd;
boolean wait_for_ack;
boolean send_delayed_bye;
boolean retx_flag;
boolean early_transfer;
boolean first_pass_3xx;
CC_ID cc_type;
void *cc_cfg_table_entry;
/*
* Contents of supported and required headers
*/
#define replaces_tag 1
#define rel_tag (1<<1)
#define early_session_tag (1<<2)
#define join_tag (1<<3)
#define path_tag (1<<4)
#define precondition_tag (1<<5)
#define pref_tag (1<<6)
#define privacy_tag (1<<7)
#define sec_agree_tag (1<<8)
#define timer_tag (1<<9)
#define norefersub_tag (1<<10)
#define cisco_callinfo_tag (1<< 11)
#define cisco_srtp_fallback_tag (1<< 12)
#define extended_refer_tag (1<<16)
#define cisco_serviceuri_tag (1<<18)
#define cisco_escapecodes_tag (1<<19)
#define cisco_service_control_tag (1<<20)
#define sdp_anat_tag (1<< 21)
#define unrecognized_tag (1<<31)
uint32_t supported_tags;
uint32_t required_tags;
#define SUPPORTED_TAGS replaces_tag | join_tag | sdp_anat_tag | norefersub_tag
/*
* Contents of the the allow header accepted by the remote side
*/
#define ALLOW_ACK 1
#define ALLOW_BYE (1<<1)
#define ALLOW_CANCEL (1<<2)
#define ALLOW_INFO (1<<3)
#define ALLOW_INVITE (1<<4)
#define ALLOW_MESSAGE (1<<5)
#define ALLOW_NOTIFY (1<<6)
#define ALLOW_OPTIONS (1<<7)
#define ALLOW_PRACK (1<<8)
#define ALLOW_PUBLISH (1<<9)
#define ALLOW_REFER (1<<10)
#define ALLOW_REGISTER (1<<11)
#define ALLOW_SUBSCRIBE (1<<12)
#define ALLOW_UPDATE (1<<13)
uint16_t allow_methods;
sipOfferAnswerState oa_state;
int last_recvd_response_code;
sipJoinInfo_t *join_info;
cc_feature_data_t *feature_data;
int dup_flags;
void *mother_ccb;
#define DUP_NO_FLAGS 0x00
#define DUP_CCB 0x01
#define DUP_CCB_NEW_CALLID 0x02
#define DUP_CCB_INIT_STATE 0x04
#define DUP_CCB_REINIT_DNS 0x08
#define DUP_CCB_STOLEN_FEAT_DATA 0x10
cc_kfact_t *kfactor_ptr;
boolean send_reason_header;
uint32_t callref;
} ccsipCCB_t;
typedef struct {
ccsipCCB_t ccbs[MAX_CCBS];
int backup_active; /* Currently use reduce invite retry count */
} ccsipGlobInfo_t;
typedef struct {
sipSMEventType_t type;
ccsipCCB_t *ccb;
union {
sipMessage_t *pSipMessage;
cc_msg_t *cc_msg;
cpr_ip_addr_t UsrInfo;
} u;
} sipSMEvent_t;
typedef void (*sipSMEventActionFn_t)(ccsipCCB_t *ccb, sipSMEvent_t *event);
typedef void (*shutdown_callback_fn)(void *data);
typedef struct {
shutdown_callback_fn callback;
void *data;
} shutdown_t;
typedef enum {
SIP_SDP_SUCCESS = 0,
SIP_SDP_SESSION_AUDIT,
SIP_SDP_DNS_FAIL,
SIP_SDP_NO_MEDIA,
SIP_SDP_ERROR,
SIP_SDP_NOT_PRESENT
} sipsdp_status_t;
extern ccsipGlobInfo_t gGlobInfo;
sipSMAction_t get_handler_index(sipSMStateType_t isipsmstate,
sipSMEventType_t isipsmevent);
void ccsip_handle_idle_ev_sip_invite(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_idle_ev_cc_setup(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentinvite_ev_sip_1xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentinvite_ev_sip_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentinvite_ev_sip_3xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentinvite_ev_sip_fxx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentinviteconnected_ev_cc_connected_ack(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_recvinvite_ev_cc_setup_ack(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_recvinvite_ev_cc_proceeding(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_recvinvite_ev_cc_alerting(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_recvinvite_ev_cc_connected(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_recvinvite_ev_sip_ack(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_active_ev_cc_feature(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_active_ev_cc_feature_hold(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_active_ev_cc_feature_resume_or_media(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_active_ev_cc_feature_other(ccsipCCB_t *ccb,
sipSMEvent_t event);
void ccsip_handle_active_ev_sip_invite(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_recvmidcallinvite_ccfeatureackpending_ev_cc_feature_ack(
ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_recvmidcallinvite_sipackpending_ev_sip_ack(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_accept_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_active_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_default(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_default_sip_message(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_default_sip_response(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_default_sip_timer(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_disconnect_local(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_disconnect_local_early(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_disconnect_local_unanswered(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_disconnect_remote(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_refer_sip_message(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_active_ev_cc_feature_ack(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_active_ev_cc_feature_xfer(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_active_ev_cc_feature_indication(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_sentbye_recvd_invite(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentbye_ev_sip_fxx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentbye_ev_sip_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentbye_ev_sip_1xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sendbye_ev_supervision_disconnect(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_recv_error_response_ev_sip_ack(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_release_complete(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_send_blind_notify(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentblindntfy_ev_sip_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_release_ev_sip_bye(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_process_in_call_options_request(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_ev_cc_answer_options_request(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_ev_cc_answer_audit_request(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_localexpires_timer(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_early_ev_sip_update(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_early_ev_sip_update_response(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_early_ev_cc_feature(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_early_ev_cc_feature_ack(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_active_ev_sip_update(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_recvupdatemedia_ccfeatureackpending_ev_cc_feature_ack(
ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_timer_glare_avoidance(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_recvinvite_ev_expires_timer(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_unsolicited_notify(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_recvinvite_ev_sip_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_icmp_unreachable(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_disconnect_media_change(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sent_ood_refer_ev_sip_1xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sent_ood_refer_ev_sip_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sent_ood_refer_ev_sip_fxx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_default_ev_cc_feature(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_default_recvreq_ack_pending_ev_cc_feature(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_sentinvite_midcall_ev_cc_feature(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_sentinvite_midcall_ev_sip_2xx(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void ccsip_handle_release_ev_cc_feature(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_ev_cc_info(ccsipCCB_t *ccb, sipSMEvent_t *event);
void ccsip_handle_release_ev_release(ccsipCCB_t *ccb, sipSMEvent_t *event);
int sip_sm_init(void);
void sip_shutdown(void);
void sip_shutdown_phase1(int, int reason);
void sip_shutdown_phase2(int);
void sip_restart(void);
int sip_sm_ccb_init(ccsipCCB_t *ccb, line_t index, int DN,
sipRegSMStateType_t initial_state);
ccsipCCB_t *sip_sm_get_ccb_by_index(line_t index);
ccsipCCB_t *sip_sm_get_ccb_by_ccm_id_and_index(int ccm_id, line_t idx);
ccsipCCB_t *sip_sm_get_ccb_by_callid(const char *callid);
ccsipCCB_t *sip_sm_get_ccb_next_available(line_t *line_number);
ccsipCCB_t *sip_sm_get_ccb_by_gsm_id(callid_t gsm_id);
ccsipCCB_t *sip_sm_get_ccb_by_target_call_id(callid_t con_id);
ccsipCCB_t *sip_sm_get_target_call_by_gsm_id(callid_t gsm_id);
ccsipCCB_t *sip_sm_get_target_call_by_con_call_id(callid_t con_call_id);
boolean sip_is_releasing(ccsipCCB_t* ccb);
callid_t sip_sm_get_blind_xfereror_ccb_by_gsm_id(callid_t gsm_id);
uint16_t sip_sm_determine_ccb(const char *callid,
sipCseq_t *sipCseq,
sipMessage_t *pSipMessage,
boolean is_request,
ccsipCCB_t **ccb);
void sip_sm_call_cleanup(ccsipCCB_t *ccb);
void free_duped(ccsipCCB_t *dupCCB);
int sip_sm_process_event(sipSMEvent_t *pEvent);
int sip_sm_process_cc_event(cprBuffer_t buf);
void sip_sm_util_normalize_name(ccsipCCB_t *ccb, char *dialString);
const char *sip_util_state2string(sipSMStateType_t state);
const char *sip_util_event2string(sipSMEventType_t event);
const char *sip_util_method2string(sipMethod_t method);
boolean sip_sm_is_bye_or_cancel_response(sipMessage_t *response);
sipSMEventType_t sip_util_ccevent2sipccevent(cc_msgs_t cc_msg_type);
const char *sip_util_feature2string(cc_features_t feature);
void sip_create_new_sip_call_id(char *sipCallID, uint8_t *mac_address,
char *pSrcAddrStr);
void sip_util_get_new_call_id(ccsipCCB_t *ccb);
boolean sip_sm_is_previous_call_id(const char *pCallID,
line_t *pPreviousCallLine);
boolean sip_sm_util_is_timeinterval(const char *pStr);
void sip_decrement_backup_active_count(ccsipCCB_t *ccb);
//int sip_sm_active_calls(void);
#ifdef DEBUG
void print_ccb_memoryusage(ccsipCCB_t *ccb);
#endif
void sip_sm_200and300_update(ccsipCCB_t *ccb, sipMessage_t *response,
int response_code);
char *sip_sm_purify_tag(char *tag);
boolean sip_sm_is_invite_response(sipMessage_t *response);
boolean sip_sm_is_refer_response(sipMessage_t *response);
boolean sip_sm_is_notify_response(sipMessage_t *response);
void sip_sm_dequote_string(char *str, int max_size);
void sip_sm_check_retx_timers(ccsipCCB_t *ccb, sipMessage_t *message);
int strcasecmp_ignorewhitespace(const char *cs, const char *ct);
void sip_util_make_ccmsgsdp(cc_sdp_t *pCcMsgSdp, ccsipCCB_t *ccb);
int sip_dns_gethostbysrv(char *domain,
cpr_ip_addr_t *ipaddr_ptr,
uint16_t *port,
srv_handle_t *srv_order,
boolean retried_addr);
int sip_dns_gethostbysrvorname(char *hname,
cpr_ip_addr_t *ipaddr_ptr,
uint16_t *port);
void sip_util_make_tag(char *tag_str);
void get_sip_error_string(char *errortext, int response);
int ccsip_cc_to_sip_cause(cc_causes_t cause, char **phrase);
void sip_sm_update_to_on_midcall_200(ccsipCCB_t *ccb, sipMessage_t *response);
sipServiceControl_t *ccsip_get_notify_service_control(sipMessage_t *pSipMessage);
boolean ccsip_is_special_name_to_mask_display_number(const char *name);
void sip_sm_change_state(ccsipCCB_t *ccb, sipSMStateType_t new_state);
#define SIP_SM_CALL_SETUP_NOT_COMPLETED(x) \
((x->state == SIP_STATE_RECV_INVITE) || \
(x->state == SIP_STATE_RECV_INVITE_PROCEEDING) || \
(x->state == SIP_STATE_RECV_INVITE_ALERTING) || \
(x->state == SIP_STATE_RECV_INVITE_CONNECTED))
#define SIP_SM_CALL_SETUP_RESPONDING(x) \
((x->state == SIP_STATE_RECV_INVITE_PROCEEDING) || \
(x->state == SIP_STATE_RECV_INVITE_ALERTING))
#define ccsip_is_replace_setup(replace) (replace)
extern char *ccsip_find_preallocated_sip_local_tag(line_t dn_line);
extern void ccsip_free_preallocated_sip_local_tag(line_t dn_line);
extern char *getPreallocatedSipCallID(line_t dn_line);
extern char *getPreallocatedSipLocalTag(line_t dn_line);
extern ccsipCCB_t* create_dupCCB(ccsipCCB_t *origCCB, int dup_flags);
/* Info Package stuff */
#define MAX_INFO_HANDLER 32
/*
* g_registered_info[] contains the Info Package strings (such as
* "conference") for the registered handlers.
*
* The index of g_registered_info[] goes from 0 to MAX_INFO_HANDLER - 1.
*/
extern char *g_registered_info[];
typedef void (*info_package_handler_t)(line_t line, callid_t call_id,
const char *info_package,
const char *content_type,
const char *message_body);
int ccsip_info_package_handler_init(void);
void ccsip_info_package_handler_shutdown(void);
int ccsip_register_info_package_handler(const char *info_package,
const char *content_type,
info_package_handler_t handler);
int ccsip_deregister_info_package_handler(const char *info_package,
const char *content_type,
info_package_handler_t handler);
void ccsip_parse_send_info_header(sipMessage_t *pSipMessage, string_t *recv_info_list);
int ccsip_handle_info_package(ccsipCCB_t *ccb, sipMessage_t *pSipMessage);
#endif
@@ -0,0 +1,23 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_CREDENTIALS_H_
#define _CCSIP_CREDENTIALS_H_
#include "cpr_types.h"
#include "prot_configmgr.h"
#define CRED_MAX_ID_LEN AUTH_NAME_SIZE
#define CRED_MAX_PW_LEN 32
#define CRED_USER 0x00000001
#define CRED_LINE 0x00000002
typedef struct _credentials {
char id[CRED_MAX_ID_LEN];
char pw[CRED_MAX_PW_LEN];
} credentials_t;
#endif
+24
View File
@@ -0,0 +1,24 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_MACROS_H_
#define _CCSIP_MACROS_H_
#define EVENT_ACTION_SM(x) \
(gSIPHandlerTable[x])
#define UPDATE_FLAGS(x, y) \
(x = (x == STATUS_SUCCESS) ? y : x)
#define GET_SIP_MESSAGE() sippmh_message_create()
#define REG_CHECK_EVENT_SANITY(x, y) \
((x - SIP_REG_STATE_BASE >= 0) && (x <= SIP_REG_STATE_END) && \
(y - SIPSPI_REG_EV_BASE >=0) && (y <= SIPSPI_REG_EV_END))
#define REG_EVENT_ACTION(x, y) \
(gSIPRegSMTable[x - SIP_REG_STATE_BASE][y - SIPSPI_REG_EV_BASE])
#endif
@@ -0,0 +1,290 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_MESSAGING_H_
#define _CCSIP_MESSAGING_H_
#include "ccsip_sdp.h"
#include "ccsip_pmh.h"
#include "ccsip_credentials.h"
#include "ccsip_core.h"
#include "ccsip_subsmanager.h"
#include "ccapi.h"
#define SIP_MESSAGING_OK (0)
#define SIP_MESSAGING_ERROR (1)
#define SIP_MESSAGING_DUPLICATE (2)
#define SIP_MESSAGING_NEW_CALLID (3)
#define SIP_MESSAGING_ERROR_STALE_RESP (4)
#define SIP_MESSAGING_ERROR_UNSUPPORTED_MEDIA (5)
#define SIP_MESSAGING_ERROR_NO_TRX (6)
#define SIP_MESSAGING_NOT_ACCEPTABLE (7)
#define SIP_MESSAGING_ENDPOINT_NOT_FOUND (8)
#define NUM_INITIAL_RECORD_ROUTE_BUFS 4
typedef enum {
SIP_INVITE_TYPE_INVALID = 0,
SIP_INVITE_TYPE_NORMAL,
SIP_INVITE_TYPE_MIDCALL,
SIP_INVITE_TYPE_TRANSFER,
SIP_INVITE_TYPE_AUTHORIZATION,
SIP_INVITE_TYPE_REDIRECTED
} sipInviteType_t;
typedef enum {
SIP_RTP_INCLUDE_MEDIA_INVALID = 0,
SIP_RTP_INCLUDE_MEDIA_ALL,
SIP_RTP_INCLUDE_MEDIA_PREFERRED,
SIP_RTP_INCLUDE_MEDIA_MATCHING
} sipRTPIncludeMedia_t;
typedef enum {
SIP_REF_NONE = 0,
SIP_REF_XFER,
SIP_REF_DIR_XFER,
SIP_REF_TOKEN,
SIP_REF_UNKNOWN
} sipRefEnum_e;
typedef struct {
unsigned int flags;
unsigned int extflags;
} sipMessageFlag_t;
#define SIP_HEADER_CONTACT_BIT 1
#define SIP_HEADER_RECORD_ROUTE_BIT (1<<1)
#define SIP_HEADER_ROUTE_BIT (1<<2)
#define SIP_HEADER_SPARE_BIT0 (1<<3)
#define SIP_HEADER_REQUESTED_BY_BIT (1<<4)
#define SIP_HEADER_DIVERSION_BIT (1<<5)
#define SIP_HEADER_AUTHENTICATION_BIT (1<<6)
#define SIP_HEADER_REFER_TO_BIT (1<<7)
#define SIP_HEADER_REFERRED_BY_BIT (1<<8)
#define SIP_HEADER_REPLACES_BIT (1<<9)
#define SIP_HEADER_EVENT_BIT (1<<10)
#define SIP_HEADER_EXPIRES_BIT (1<<11)
#define SIP_HEADER_ACCEPT_BIT (1<<12)
#define SIP_HEADER_ALLOW_BIT (1<<13)
#define SIP_HEADER_CISCO_GUID_BIT (1<<14)
#define SIP_HEADER_SPARE_BIT1 (1<<15)
#define SIP_HEADER_UNSUPPORTED_BIT (1<<16)
#define SIP_HEADER_REMOTE_PARTY_ID_BIT (1<<17)
#define SIP_HEADER_PROXY_AUTH_BIT (1<<18)
#define SIP_HEADER_REQUIRE_BIT (1<<19)
#define SIP_HEADER_CALL_INFO_BIT (1<<20)
#define SIP_HEADER_SUPPORTED_BIT (1<<21)
#define SIP_HEADER_RETRY_AFTER_BIT (1<<22)
#define SIP_HEADER_ALLOW_EVENTS_BIT (1<<23)
#define SIP_HEADER_CONTENT_TYPE_BIT (1<<24)
#define SIP_HEADER_CONTENT_LENGTH_BIT (1<<25)
#define SIP_HEADER_JOIN_INFO_BIT (1<<26)
#define SIP_HEADER_ACCEPT_ENCODING_BIT (1<<27)
#define SIP_HEADER_ACCEPT_LANGUAGE_BIT (1<<28)
#define SIP_HEADER_OPTIONS_CONTENT_TYPE_BIT (1<<29)
#define SIP_HEADER_REASON_BIT (1<<30)
#define SIP_HEADER_RECV_INFO_BIT (1U<<31)
#define SIP_RFC_SUPPORTED_TAGS REQ_SUPP_PARAM_REPLACES "," \
REQ_SUPP_PARAM_JOIN "," \
REQ_SUPP_PARAM_SDP_ANAT "," \
REQ_SUPP_PARAM_NOREFERSUB
/*
* The REQ_SUPP_PARAM_EXTENED_REFER is only used in Cisco CCM environment.
* The tag is no longer in IANA.
*/
#define SIP_CISCO_SUPPORTED_TAGS REQ_SUPP_PARAM_EXTENED_REFER "," \
REQ_SUPP_PARAM_CISCO_CALLINFO "," \
REQ_SUPP_PARAM_CISCO_ESCAPECODES "," \
REQ_SUPP_PARAM_CISCO_MONREC
#define SIP_CISCO_SUPPORTED_REG_TAGS \
SIP_RFC_SUPPORTED_TAGS "," \
SIP_CISCO_SUPPORTED_TAGS
boolean sipSPISendInvite(ccsipCCB_t *ccb,
sipInviteType_t inviteType,
boolean initInvite);
boolean sipSPISendInviteMidCall(ccsipCCB_t *ccb, boolean expires);
void sipSPISendInviteResponse100(ccsipCCB_t *ccb, boolean remove_to_tag);
void sipSPISendInviteResponse180(ccsipCCB_t *ccb);
void sipSPISendInviteResponse200(ccsipCCB_t *ccb);
void sipSPISendInviteResponse302(ccsipCCB_t *ccb);
boolean sipSPISendOptionResponse(ccsipCCB_t *ccb, sipMessage_t *);
boolean sipSPIsendNonActiveOptionResponse(sipMessage_t *msg,
cc_msgbody_info_t *local_msg_body);
void sipSPISendInviteResponse(ccsipCCB_t *ccb,
uint16_t statusCode,
const char *reason_phrase,
uint16_t warnCode,
const char *warn_phrase,
boolean send_sd,
boolean retx);
void sipSPISendBye(ccsipCCB_t *ccb,
char *alsoString,
sipMessage_t *pForked200);
void sipSPISendCancel(ccsipCCB_t *ccb);
boolean sipSPISendByeOrCancelResponse(ccsipCCB_t *ccb,
sipMessage_t *request,
sipMethod_t sipMethodByeorCancel);
boolean sipSPISendAck(ccsipCCB_t *ccb, sipMessage_t *response);
boolean sipSPISendRegister(ccsipCCB_t *ccb,
boolean no_dns_lookup,
const char *user,
int expires_int);
boolean sipSPISendErrorResponse(sipMessage_t *msg, uint16_t status_code,
const char *reason_phrase,
uint16_t status_code_warning,
const char *reason_phrase_warning,
ccsipCCB_t *ccb);
boolean sipSPISendLastMessage(ccsipCCB_t *ccb);
boolean sipSPIGenerateAuthorizationResponse(sip_authen_t * sip_authen,
const char *uri,
const char *method,
const char *user_name,
const char *user_password,
char **author_str,
int *nc_count,
ccsipCCB_t *ccb);
void sipSPIGenerateGenAuthorizationResponse(ccsipCCB_t *ccb,
sipMessage_t *request,
sipRet_t *flag,
char *method);
void sipSPIGenerateTargetUrl(genUrl_t *genUrl, char *sipurlstr);
void sipSPIGenerateSipUrl(sipUrl_t *sipUrl, char *sipurlstr);
boolean sipSPISendRefer(ccsipCCB_t *ccb, char *referto,
sipRefEnum_e referto_type);
boolean sipSPISendReferResponse202(ccsipCCB_t *ccb);
boolean sipSPISendNotify(ccsipCCB_t *ccb, int referto);
boolean sipSPISendInfo(ccsipCCB_t *ccb, const char *info_package,
const char *content_type, const char *message_body);
boolean sipSPISendUpdate(ccsipCCB_t *ccb);
boolean sipSPISendUpdateResponse(ccsipCCB_t *ccb,
boolean send_sdp,
cc_causes_t cause,
boolean retx);
boolean sipSPISendNotifyResponse(ccsipCCB_t *ccb, cc_causes_t cause);
boolean sipSPIAddStdHeaders(sipMessage_t *msg,
ccsipCCB_t *ccb,
boolean isResponse);
sipMessage_t *sipSPIBuildRegisterHeaders(ccsipCCB_t *ccb,
const char *user,
int expires_int);
boolean sipSPIAddLocalVia(sipMessage_t *msg,
ccsipCCB_t *ccb,
sipMethod_t method);
boolean sipSPIAddRequestVia(ccsipCCB_t *ccb,
sipMessage_t *response,
sipMessage_t *request,
sipMethod_t method);
boolean sipSPIAddCiscoGuid(sipMessage_t *msg, ccsipCCB_t *ccb);
boolean sipSPIAddRouteHeaders(sipMessage_t *msg,
ccsipCCB_t *ccb,
char *result_route,
int result_route_length);
sipRet_t sipAddDateHeader(sipMessage_t *sip_message);
const char *sipGetMethodString(sipMethod_t methodname);
void sip_option_response_rtp_media_get_info(cc_sdp_t *src_sdp);
//sipSdp_t* CreateSDPtext();
sipRet_t sipSPIAddContactHeader(ccsipCCB_t *ccb, sipMessage_t *request);
sipRet_t sipSPIAddReasonHeader (ccsipCCB_t *ccb, sipMessage_t *request);
boolean sipSPIGenerateReferredByHeader(ccsipCCB_t *ccb);
boolean sipSPIGenRequestURI(ccsipCCB_t *ccb,
sipMethod_t sipmethod,
boolean initInvite);
// Message Factory
sipRet_t sipSPIAddCommonHeaders(ccsipCCB_t *ccb,
sipMessage_t *request,
boolean isResponse,
sipMethod_t method,
uint32_t response_cseq_number);
boolean CreateRequest(ccsipCCB_t *ccb,
sipMessageFlag_t messageflag,
sipMethod_t sipmethod,
sipMessage_t *request,
boolean initInvite,
uint32_t response_cseq_number);
boolean CreateResponse(ccsipCCB_t *ccb,
sipMessageFlag_t messageflag,
uint16_t status_code,
sipMessage_t *response,
const char *reason_phrase,
uint16_t status_code_warning,
const char *reason_phrase_warning,
sipMethod_t);
boolean SendRequest(ccsipCCB_t *ccb,
sipMessage_t *request,
sipMethod_t method,
boolean midcall,
boolean reTx,
boolean timer);
boolean AddGeneralHeaders(ccsipCCB_t *ccb,
sipMessageFlag_t messageflag,
sipMessage_t *request,
sipMethod_t method);
boolean getCSeqInfo(sipMessage_t *request,
sipCseq_t **request_cseq_structure);
int sipSPICheckRequest(ccsipCCB_t *ccb, sipMessage_t *request);
int sipSPICheckResponse(ccsipCCB_t *ccb, sipMessage_t *response);
int sipSPICheckContact(const char *pContactStr);
void sipGetRequestMethod(sipMessage_t *pRequest, sipMethod_t *pMethod);
int sipGetResponseMethod(sipMessage_t *pResponse, sipMethod_t *pMethod);
int sipGetResponseCode(sipMessage_t *pResponse, int *pResponseCode);
int sipSPIIncomingCallSDP(ccsipCCB_t *ccb,
boolean call_hold,
boolean udpate_ver);
char *sipSPIUrlDestination(sipUrl_t *sipUrl);
int sipGetMessageCSeq(sipMessage_t *pMessage, uint32_t *pResultCSeqNumber,
sipMethod_t * pResultCSeqMethod);
void sipGetMessageToTag(sipMessage_t *pMessage, char *to_tag,
int to_tag_max_length);
boolean sipSPISendByeAuth(sipMessage_t *pResponse,
sipAuthenticate_t authen,
cpr_ip_addr_t *dest_ipaddr,
uint16_t dest_port,
uint32_t cseq_number,
char *alsoString,
char *last_call_route,
char *last_call_route_request_uri,
line_t previous_call_line);
void free_sip_message(sipMessage_t *message);
void sipSPISendFailureResponseAck(ccsipCCB_t *ccb,
sipMessage_t *response,
boolean prevcall,
line_t previous_call_line);
/* ICMP Unreachable handler routine */
void sip_platform_icmp_unreachable_callback(void *ccyb, uint32_t ipaddr);
cc_disposition_type_t sip2ccdisp(uint8_t type);
cc_content_type_t sip2cctype(uint8_t type);
/* Transaction record manipulation methods */
int16_t get_last_request_trx_index(ccsipCCB_t *ccb, boolean sent);
int16_t get_next_request_trx_index(ccsipCCB_t *ccb, boolean sent);
int16_t get_method_request_trx_index(ccsipCCB_t *ccb, sipMethod_t method,
boolean sent);
void clean_method_request_trx(ccsipCCB_t *ccb, sipMethod_t method, boolean sent);
line_t get_dn_line_from_dn(const char *watcher);
boolean sipSPIGenerateRouteHeaderUAC(sipRecordRoute_t *, char *, int,
boolean *loose_routing);
boolean sipSPIGenerateRouteHeaderUAS(sipRecordRoute_t *, char *, int,
boolean *loose_routing);
boolean sipSPIGenerateContactHeader(sipContact_t *, char *, int);
void get_reason_string(int unreg_reason, char *unreg_reason_str, int len);
#endif
@@ -0,0 +1,65 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_PLATFORM_H_
#define _CCSIP_PLATFORM_H_
#include "phone_platform_constants.h"
// SIP standard defines the max to be the path MTU if it is
// known, otherwise it should be 1500
// We are defining the max message size to be 2560, 1500 + 1060 bytes of
// extended buffer space (which is also the same as the PacketBuffer size
// #define PKTBUF_SIZ 3072 defined in phone.h
#define SIP_UDP_MESSAGE_SIZE 3072 /* Max size of a SIP message */
/* Constants */
#define MAX_SIP_URL_LENGTH 512
#define MAX_SIP_TAG_LENGTH 256
#define MAX_SIP_DISPLAYNAME_LENGTH 64
#define VIA_BRANCH_LENGTH 16
/*
* MAX_SIP_DATE_LENGTH is used in ccsip_messaging for
* the SIP Date header routine.
* It has been defined here to be consistent with the rest
* of the defines for the SIP message
*/
#define MAX_SIP_DATE_LENGTH 63 //Extended for foreign language
#define CCSIP_START_CSEQ 100
#define MAX_SIP_CALL_ID 128 /* Max size of a Call ID header string */
#define MAX_DIVERSION_HEADERS 25
/*********************************************************
*
*
* Phone constants
*
*
*********************************************************/
#define MAX_REG_BACKUP 1 // Max number of backup registration CCBs
#define MIN_TEL_LINES 0 // Min number of lines
#define MAX_TEL_LINES MAX_CALLS // Max number of calls
#define MAX_PHYSICAL_DIR_NUM 6 // Max number of physical directory numbers
#define MAX_UI_LINES_PER_DN (MAX_LINES_PER_DN + 1) // Max number of lines per DN
#define MAX_CCBS (MAX_TEL_LINES + MAX_REG_LINES + MAX_REG_BACKUP)
#define TEL_CCB_START (MIN_TEL_LINES)
#define TEL_CCB_END (TEL_CCB_START + MAX_TEL_LINES -1)
#define REG_CCB_START (TEL_CCB_END + 1)
#define REG_CCB_END (REG_CCB_START + MAX_REG_LINES -1)
#define REG_BACKUP_CCB (REG_CCB_END + 1)
#define REG_FALLBACK_CCB_START (REG_BACKUP_CCB + 1)
#define REG_FALLBACK_CCB_END (REG_FALLBACK_CCB_START +4)
#define REG_BACKUP_DN 1
#define REG_BACKUP_LINE 7
#define MAX_LINES_7940 2
#define INVALID_DN_LINE (REG_FALLBACK_CCB_END + 1)
#define INIT_DN_LINE 0
void sip_platform_init(void);
int sip_platform_ui_restart(void);
extern void platform_print_sip_msg(const char *msg);
#endif
@@ -0,0 +1,99 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __CCSIP_PLATFORM_TCP__H__
#define __CCSIP_PLATFORM_TCP__H__
/* The maximum number of connections allowed */
#define MAX_SIP_CONNECTIONS (64 - 2)
#define SIP_TCP_SEND_OK 0
#define SIP_TCP_SIZE_ERROR 1
#define SIP_TCP_SEND_ERROR 2
#define SIP_SOC_TCP 0
#define SIP_SOC_TLS 1
#define SIP_TCP_NOT_CONNECTED 0
#define SIP_TCP_CONNECTED 1
typedef struct _sendData
{
struct _sendData *next;
char *data;
uint16_t bytesLeft;
uint16_t bytesSent;
void *context;
boolean msg_display;
uint8_t ip_sig_tos;
} ccsipTCPSendData_t;
typedef struct
{
uint16 connectionId;
} sipTCPTimerContext_t;
typedef struct
{
cpr_socket_t fd; /* Socket file descriptor */
cpr_sockaddr_storage addr;
cpr_ip_addr_t ipaddr; /* Remote IP address */
uint16_t port; /* Remote port # */
sock_state_t state;
char *prev_msg;
uint32_t prev_bytes;
void *context; /* Connection Manager's context */
/* queue for partial socket writes */
sll_handle_t sendQueue;
boolean dirtyFlag;
boolean pend_closure; /* Indicates to close the connection
* entry on completion of partial
* socket message writes
*/
int error_cause;
int soc_type;
} sip_tcp_conn_t;
typedef struct
{
cpr_socket_t read[MAX_SIP_CONNECTIONS];
cpr_socket_t write[MAX_SIP_CONNECTIONS];
} sip_connection_t;
extern sip_connection_t sip_conn;
extern uint32_t nfds;
extern fd_set read_fds;
extern fd_set write_fds;
extern sip_tcp_conn_t sip_tcp_conn_tab[MAX_CONNECTIONS];
/*
*
* Function declarations
*
*/
int sip_tcp_fd_to_connid(cpr_socket_t fd);
cpr_socket_t sip_tcp_create_connection(sipSPIMessage_t *spi_msg);
void sip_tcp_read_socket(cpr_socket_t this_fd);
int sip_tcp_channel_send(cpr_socket_t s,
char *buf,
uint32_t len);
void sip_tcp_createconnfailed_to_spi(cpr_ip_addr_t *ipaddr,
uint16_t port,
void *context,
ccsipSockErrCodes_e errcode,
int connid);
void sip_tcp_purge_entry(sipSPIConnId_t connid);
void sipTcpFlushRetrySendQueue(sip_tcp_conn_t *entry);
void sip_tcp_resend(int connid);
extern int sip_tcp_get_free_conn_entry(void);
extern int sip_tcp_attach_socket(cpr_socket_t s);
extern void sip_tcp_init_conn_table(void);
extern boolean sip_tcp_set_sock_options(int fd);
void sipTransportClearServerHandle(cpr_ip_addr_t *ipaddr,
uint16_t port,
int connid);
void sipTcpFreeSendQueue(int connid);
extern cpr_socket_t sip_tcp_create_conn_using_blocking_socket (sipSPIMessage_t *spi_msg);
#endif /* __CCSIP_PLATFORM_TCP__H__ */
@@ -0,0 +1,164 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_PLATFORM_TIMERS_H_
#define _CCSIP_PLATFORM_TIMERS_H_
#include "cpr_types.h"
#include "cpr_timers.h"
#include "ccsip_platform.h"
#include "ccsip_pmh.h"
#define LINE_NOT_FOUND -1
/*
* Defintions
*/
typedef void (*sipTimerCallbackFn_t)(cprTimer_t pTmrBlk);
typedef struct
{
cprTimer_t timer;
cprTimer_t reg_timer;
int line;
char* message_buffer;
int message_buffer_len;
sipMethod_t message_type;
cpr_ip_addr_t ipaddr;
uint16_t port;
boolean outstanding;
} sipPlatformUITimer_t;
typedef struct
{
cprTimer_t timer;
int line;
cpr_ip_addr_t ipaddr;
uint16_t port;
} sipPlatformUIExpiresTimer_t;
typedef struct
{
cprTimer_t timer;
int line;
boolean started;
} sipPlatformSupervisionTimer_t;
extern sipPlatformUITimer_t sipPlatformUISMSubNotTimers[]; // Array of timers
/*
* Prototypes
*/
int
sip_platform_timers_init(void);
void
sip_platform_post_timer(uint32_t cmd, void *data);
void
sip_platform_msg_timers_init(void);
int
sip_platform_msg_timer_start(uint32_t msec,
void *data,
int line,
char *message_buffer,
int message_buffer_len,
int message_type,
cpr_ip_addr_t *ipaddr,
uint16_t port,
boolean isRegister);
void
sip_platform_msg_timer_stop(int line);
boolean
sip_platform_msg_timer_outstanding_get(int line);
void
sip_platform_msg_timer_outstanding_set(int line, boolean value);
void
sip_platform_msg_timer_callback(void *data);
int
sip_platform_expires_timer_start(uint32_t msec,
int line,
cpr_ip_addr_t *ipaddr,
uint16_t port);
int
sip_platform_expires_timer_stop(int line);
void
sip_platform_expires_timer_callback(void *data);
int
sip_platform_register_expires_timer_start(uint32_t msec,
int line);
int
sip_platform_register_expires_timer_stop(int line);
int
sip_platform_localexpires_timer_start(uint32_t msec,
int line,
cpr_ip_addr_t *ipaddr,
uint16_t port);
int
sip_platform_localexpires_timer_stop(int line);
void
sip_platform_localexpires_timer_callback(void *data);
int
sip_platform_msg_timer_update_destination(int line,
cpr_ip_addr_t *ipaddr,
uint16_t port);
sipMethod_t
sip_platform_msg_timer_messageType_get(int line);
// Supervision timer
int
sip_platform_supervision_disconnect_timer_start(uint32_t msec,
int line);
int
sip_platform_supervision_disconnect_timer_stop(int line);
void
sip_platform_supervision_disconnect_timer_callback(void *data);
// Sub/Not Timers
int
sip_platform_msg_timer_subnot_start(uint32_t msec,
sipPlatformUITimer_t *,
uint32_t index,
char *message_buffer,
int message_buffer_len,
int message_type,
cpr_ip_addr_t *ipaddr,
uint16_t port);
void
sip_platform_msg_timer_subnot_stop(sipPlatformUITimer_t *);
void
sip_platform_subnot_msg_timer_callback(void *data);
int
sip_platform_subnot_periodic_timer_start(uint32_t msec);
int
sip_platform_subnot_periodic_timer_stop(void);
void
sip_platform_subnot_periodic_timer_callback(void *data);
int
sip_platform_standby_keepalive_timer_start(uint32_t msec);
int
sip_platform_standby_keepalive_timer_stop();
void
sip_platform_standby_keepalive_callback(void *data);
int
sip_platform_unregistration_timer_start(uint32_t msec, boolean external);
int
sip_platform_unregistration_timer_stop();
void
sip_platform_unregistration_callback(void *data);
void
sip_platform_timers_shutdown(void);
int
sip_platform_notify_timer_start(uint32_t msec);
int
sip_platform_notify_timer_stop();
int
sip_platform_reg_all_fail_timer_start(uint32_t msec);
int
sip_platform_reg_all_fail_timer_stop(void);
int
sip_platform_pass_through_timer_start(uint32_t sec);
int
sip_platform_pass_through_timer_stop(void);
#endif
@@ -0,0 +1,12 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __CCSIP_PLATFORM_TLS__H__
#define __CCSIP_PLATFORM_TLS__H__
extern cpr_socket_t sip_tls_create_connection(sipSPIMessage_t *spi_msg,
boolean blocking,
sec_level_t sec);
#endif /* __CCSIP_PLATFORM_TLS__H__ */
@@ -0,0 +1,46 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_PLATFORM_UDP_H_
#define _CCSIP_PLATFORM_UDP_H_
#include "cpr_types.h"
#include "cpr_socket.h"
#include "cpr_memory.h"
int
sip_platform_udp_channel_listen(cpr_ip_mode_e ip_mode, cpr_socket_t *s,
cpr_ip_addr_t *local_ipaddr,
uint16_t local_port);
int
sip_platform_udp_channel_accept(cpr_socket_t listenSoc,
cpr_socket_t *s);
int
sip_platform_udp_channel_create(cpr_ip_mode_e ip_mode, cpr_socket_t *s,
cpr_ip_addr_t *remote_ipaddr,
uint16_t remote_port,
uint32_t local_udp_port);
int
sip_platform_udp_channel_destroy(cpr_socket_t s);
int
sip_platform_udp_channel_send(cpr_socket_t s,
char *buf,
uint16_t buf_len);
void
sip_platform_udp_read_socket(cpr_socket_t s);
int
sip_platform_udp_channel_sendto(cpr_socket_t s,
char *buf,
uint32_t buf_len,
cpr_ip_addr_t *dst_addr,
uint16_t dst_port);
int
sip_platform_udp_channel_read(cpr_socket_t s,
cprBuffer_t buf,
uint16_t *len,
cpr_sockaddr_t *soc_addr,
cpr_socklen_t *soc_addr_len);
#endif
+827
View File
@@ -0,0 +1,827 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_PMH_H_
#define _CCSIP_PMH_H_
#include "cpr_types.h"
#include "pmhdefs.h"
#include "httpish.h"
#include "ccsip_protocol.h"
#include "string_lib.h"
#include "ccsip_platform.h"
#include "ccapi.h"
#define MAX_REFER_TO_HEADER_CONTENTS 6
#define MAX_REMOTE_PARTY_ID_HEADERS 10
#define MAX_REPLACES_HEADERS 1
#define MAX_REFER_TO_HEADERS 2
#define MAX_REFER_BY_HEADERS 1
#define MAX_CALL_INFO_HEADERS 4
#define MAX_SUB_STATE_HEADER_SIZE 96
#define TEMP_PARSE_BUFFER_SIZE 10
/*
* Maximum number of Location/Contact headers we will parse. These
* specify the locations to try to contact the called party, and I figure
* the user is not going to wait for ever, and simplicity helps.
*/
#define SIP_MAX_LOCATIONS 6
/* Used when we create Via headers. Does not apply to incoming messages.*/
#define SIP_MAX_VIA_LENGTH 128
/* Broadsoft: Max length of "other" parameters in 3xx messages. */
#define SIP_MAX_OTHER_PARAM_LENGTH 256
#define TWO_POWER_31 2147483648UL
/*
* Some of this corresponds directly to HTTP/1.1 message structure.
*/
typedef httpish_header sip_header;
typedef httpishMsg_t sipMessage_t;
typedef httpishReqLine_t sipReqLine_t;
typedef httpishRespLine_t sipRespLine_t;
typedef httpishStatusCodeClass_t sipStatusCodeClass_t;
typedef hStatus_t sipRet_t;
typedef enum
{
sipMethodInvalid = 0,
sipMethodRegister = 100,
sipMethodOptions,
sipMethodInvite,
sipMethodBye,
sipMethodCancel,
sipMethodPrack,
sipMethodComet,
sipMethodNotify,
sipMethodRefer,
sipMethodAck,
sipMethodMessage,
sipMethodSubscribe,
sipMethodPublish,
sipMethodUpdate,
sipMethodResponse,
sipMethodInfo,
sipMethodUnknown
} sipMethod_t;
typedef enum
{
SIP_BASIC = 1,
SIP_DIGEST,
SIP_UNKNOWN
} sip_scheme_t;
typedef enum
{
SIP_SUCCESS,
SIP_FAILURE,
SIP_INTERNAL_ERR,
SIP_UNACCEPTABLE_MEDIA_ERR,
SIP_PRE_CONDITION_FAIL_ERR,
SIP_NO_RESOURCE,
SIP_MSG_CREATE_ERR,
SIP_MSG_PARSE_ERR,
SIP_MSG_INCOMPLETE_ERR,
SIP_SUCCESS_DNS_PENDING,
SIP_SUCCESS_QOS_PENDING,
SIP_VIA_DNS_QUERY_REQUIRED,
SIP_SUCCESS_QOS_DNS_PENDING,
SIP_SUCCESS_DELAYED_MEDIA,
SIP_SUCCESS_QOS_DELAYED_MEDIA,
SIP_ADDR_UNAVAILABLE,
SIP_MAX_RC
} ccsipRet_e;
/* This is used to store the parsed attribute/value pair */
typedef struct {
char *attr;
char *value;
} attr_value_pair_t;
typedef struct
{
/*
* Not storing the schema because we don't deal with non-SIP URLs.
* The rest of the fields do not have any meaning if the URL
* in question is non-SIP. Our parse routine itself would return
* failure.
*/
char *user;
char *password;
char *host;
char *maddr;
char *other;
char *method;
uint16_t port;
boolean port_present;
int16_t transport;
uint8_t is_phone;
uint8_t ttl_val;
char num_headers; /* number of headers in the avpair below */
attr_value_pair_t *headerp; /* everything after the '?' */
boolean lr_flag;
boolean is_ipv6;
} sipUrl_t;
typedef struct
{
char *user;
char *isdn_subaddr;
char *post_dial;
char *unparsed_tsp;
char *future_ext;
} telUrl_t;
typedef enum
{
URL_TYPE_SIP = 1,
URL_TYPE_TEL,
URL_TYPE_CID,
URL_TYPE_UNKNOWN
} urlType_t;
typedef struct
{
urlType_t schema;
boolean sips;
char *str_start;
char *phone_context;
char *other_params[SIP_MAX_LOCATIONS];
union {
sipUrl_t *sipUrl;
telUrl_t *telUrl;
} u;
} genUrl_t;
typedef struct
{
char *str_start; /* beginning of duplicated string */
sip_scheme_t scheme;
char *user_pass;
char *realm;
char *d_username;
char *unparsed_uri;
char *response;
char *algorithm;
char *cnonce;
char *opaque;
char *qop;
char *nc_count;
char *auth_param; /* for future extension */
char *nonce;
} sip_author_t;
typedef struct
{
/* Could be Basic or PGP */
char *str_start; /* beginning of duplicated string */
sip_scheme_t scheme;
char *user_pass;
char *realm;
char *version;
char *algorithm;
char *nonce;
char *unparsed_domain;
char *opaque;
char *stale;
char *qop;
} sip_authen_t;
typedef struct _sipLocation_t
{
char *loc_start;
char *name;
genUrl_t *genUrl;
char *tag;
} sipLocation_t;
typedef sipLocation_t sipFrom_t;
typedef sipLocation_t sipTo_t;
/*
* Definition of the flags in the sipContactParams_t.
* The flags in the sipContact_t is used to store boolean
* parameters (not numerical value).
*/
#define SIP_CONTACT_PARM_X_CISCO_NEWREG (1 << 0) /* new reg parameter */
typedef struct
{
int action; /* Proxy or Redirect */
char *qval;
uint32_t expires;
char *expires_gmt;
char *extn_attr;
uint32_t flags;
} sipContactParams_t;
typedef struct
{
sipLocation_t *locations[SIP_MAX_LOCATIONS];
sipContactParams_t params[SIP_MAX_LOCATIONS];
uint16_t num_locations;
boolean new_flag;
} sipContact_t;
typedef struct
{
sipLocation_t *locations[SIP_MAX_LOCATIONS];
uint16_t num_locations;
boolean new_flag;
} sipRecordRoute_t;
typedef enum
{
sipTransportTypeUDP = 2345,
sipTransportTypeTCP
} sipTransportType_t;
/* DIVERSION HEADER STRUCTURE */
typedef struct
{
sipLocation_t *locations;
// char *reason;
uint32_t limit;
uint32_t counter;
char *privacy;
char *screen;
} sipDiversion_t;
typedef struct
{
string_t orig_called_name;
string_t orig_called_number;
string_t last_redirect_name;
string_t last_redirect_number;
} sipDiversionInfo_t;
typedef struct
{
/*
* We are not storing the protocol ( should be SIP always )
*/
char *version;
char *transport;
char *host;
char *ttl;
char *maddr;
char *recd_host;
char *branch_param;
/* Remaining Via header(s) if any in the input string */
char *more_via;
uint16_t remote_port;
uint8_t flags;
boolean is_ipv6;
#define VIA_IS_HIDDEN (0x01)
} sipVia_t;
typedef struct
{
uint32_t number;
sipMethod_t method;
} sipCseq_t;
typedef struct
{
uint32_t response_num;
uint32_t cseq_num;
sipMethod_t method;
} sipRack_t;
typedef enum
{
sipSessionTypeInvalid = 0,
sipSessionTypeMedia,
sipSessionTypeQoS,
sipSessionTypeSecurity
} sipSessionType_t;
/* Data structure for Replaces header */
typedef struct
{
char *str_start;
char *callid;
char *toTag;
char *fromTag;
char *signature_scheme;
} sipReplaces_t;
/* Data structure for Refer-To header */
typedef struct
{
char *ref_to_start;
genUrl_t *targetUrl;
char *sip_replaces_hdr;
char *sip_acc_cont;
char *sip_proxy_auth;
} sipReferTo_t;
/* Data structure for Refer method */
typedef struct
{
sipReferTo_t *refer_to_info; /* Refer-To header */
const char *referred_by_info; /* Referred-by header */
} sipRefer_t;
/* Data structures for Remote-Party-Id */
typedef struct
{
sipLocation_t *loc;
char *screen;
char *party_type;
char *id_type;
char *privacy;
char *np;
} sipRemotePartyId_t;
typedef struct
{
unsigned int num_rpid; /* Number of rpid instantiations present */
sipRemotePartyId_t *rpid[MAX_REMOTE_PARTY_ID_HEADERS];
} sipRemotePartyIdInfo_t;
typedef enum
{
SUBSCRIPTION_STATE_INVALID = 0,
SUBSCRIPTION_STATE_ACTIVE,
SUBSCRIPTION_STATE_PENDING,
SUBSCRIPTION_STATE_TERMINATED
} sip_subs_state_e;
typedef enum
{
SUBSCRIPTION_STATE_REASON_INVALID = 0,
SUBSCRIPTION_STATE_REASON_DEACTIVATED,
SUBSCRIPTION_STATE_REASON_PROBATION,
SUBSCRIPTION_STATE_REASON_REJECTED,
SUBSCRIPTION_STATE_REASON_TIMEOUT,
SUBSCRIPTION_STATE_REASON_GIVEUP,
SUBSCRIPTION_STATE_REASON_NORESOURCE
} sip_subs_state_reason_e;
typedef struct
{
sip_subs_state_e state;
uint32_t expires;
sip_subs_state_reason_e reason;
uint32_t retry_after;
} sipSubscriptionStateInfo_t;
typedef enum {
SERVICE_CONTROL_ACTION_INVALID = 0,
SERVICE_CONTROL_ACTION_RESET,
SERVICE_CONTROL_ACTION_RESTART,
SERVICE_CONTROL_ACTION_CHECK_VERSION,
SERVICE_CONTROL_ACTION_CALL_PRESERVATION,
SERVICE_CONTROL_ACTION_APPLY_CONFIG
} sip_service_control_action_e;
typedef struct
{
sip_service_control_action_e action;
char *registerCallID;
char *configVersionStamp;
char *dialplanVersionStamp;
char *softkeyVersionStamp;
char *fcpVersionStamp;
char *cucm_result;
char *firmwareLoadId;
char *firmwareInactiveLoadId;
char *loadServer;
char *logServer;
boolean ppid;
} sipServiceControl_t;
typedef struct
{
char *call_id;
char *from_tag;
char *to_tag;
} sipJoinInfo_t;
typedef enum {
mwiVoiceType = 1,
mwiFaxType,
mwiTextMessage
} messageCountType_t;
typedef struct {
boolean mesg_waiting_on;
int32_t type;
int32_t newCount;
int32_t oldCount;
int32_t hpNewCount;
int32_t hpOldCount;
} sipMessageSummary_t;
/*
* Returns a sipMethod_t value given a character method name.
* Returns sipMethodUnknown if the method is not on the list of recognized
* methods.
*/
PMH_EXTERN sipMethod_t sippmh_get_method_code(const char *);
PMH_EXTERN genUrl_t *sippmh_parse_url(char *url, boolean dup_flag);
/*
* See comment above.
*/
PMH_EXTERN void sippmh_genurl_free(genUrl_t *);
PMH_EXTERN sipLocation_t *sippmh_parse_from_or_to(char *from, boolean dup_flag);
PMH_EXTERN sipLocation_t *sippmh_parse_nameaddr_or_addrspec(char *input_loc_ptr,
char *start_ptr,
boolean dup_flag,
boolean name_addr_only_flag,
char **more_ptr);
/*
* See comment above.
*/
PMH_EXTERN void sippmh_free_location(sipLocation_t *);
/*
* Same comments as parse_location
*/
PMH_EXTERN sipContact_t *sippmh_parse_contact(const char *contact);
/*
* Same comments as parse_location
*/
PMH_EXTERN sipDiversion_t *sippmh_parse_diversion(const char *diversion,
char *diversionhead);
/*
* Same comments as free_location.
*/
PMH_EXTERN void sippmh_free_diversion(sipDiversion_t *);
PMH_EXTERN void sippmh_free_diversion_info(sipDiversionInfo_t *div_info);
/*
* Same comments as free_location.
*/
PMH_EXTERN void sippmh_free_contact(sipContact_t *);
/*
* Same comments as parse_location
*/
PMH_EXTERN sipVia_t *sippmh_parse_via(const char *via);
/*
* Same comments as free_location.
*/
PMH_EXTERN void sippmh_free_via(sipVia_t *via);
PMH_EXTERN void sippmh_process_via_header(sipMessage_t *sip_message,
cpr_ip_addr_t *source_ip_address);
/*
* Same comments as parse_location
*/
PMH_EXTERN sipCseq_t *sippmh_parse_cseq(const char *cseq);
PMH_EXTERN boolean sippmh_parse_rseq(const char *rseq, uint32_t *rseq_val);
PMH_EXTERN sipRack_t *sippmh_parse_rack(const char *rack);
/*
* Does a proper comparison of From: headers.(kind of like
* a URL comparison.
* TRUE if equal, FALSE if not.
*/
PMH_EXTERN boolean sippmh_are_froms_equal(sipFrom_t *from1, sipFrom_t *from2);
/*
* Does a proper comparison of To: headers.(kind of like
* a URL comparison.
* TRUE if equal, FALSE if not.
* At this time, sipTo is really the sipLocation struct, but
* this is kept different in case things change.
*/
PMH_EXTERN boolean sippmh_are_tos_equal(sipTo_t *to1, sipTo_t *to2);
/*
* Does a comparison of SIP URLs.
* TRUE if equal, FALSE if not.
*/
PMH_EXTERN boolean sippmh_are_urls_equal(sipUrl_t *url1, sipUrl_t *url2);
/*
* Utility to get the callid of a message.
* Returns NULL if the header is not found.
* Returned pointer should not be freed.
*/
//PMH_EXTERN const char *sippmh_get_callid(sipMessage_t *msg);
/*
* Adds a Cseq: header to the message.
* msg = sipMessage_t struct
* method, seq = method, seq in the Cseq eg Cseq: 428 INVITE
* Assumes that the maximum length of the resulting header is
* less than 32 characters.
*/
PMH_EXTERN sipRet_t sippmh_add_cseq(sipMessage_t *msg, const char *method,
uint32_t seq);
PMH_EXTERN sipRet_t sippmh_add_rack(sipMessage_t *msg, uint32_t rseq,
uint32_t cseq, const char *method);
/*
* Utility to check whether the URL is valid.
* TRUE if yes, FALSE if not.
*/
PMH_EXTERN boolean sippmh_valid_url(genUrl_t *genUrl);
PMH_EXTERN boolean sippmh_valid_reqline_url(genUrl_t *genUrl);
PMH_EXTERN sipRecordRoute_t *sippmh_parse_record_route(const char *);
PMH_EXTERN sipRecordRoute_t *sippmh_copy_record_route (sipRecordRoute_t *rr);
PMH_EXTERN void sippmh_free_record_route(sipRecordRoute_t *);
PMH_EXTERN cc_content_disposition_t *sippmh_parse_content_disposition(const char *input_content_disp);
PMH_EXTERN sipReferTo_t *sippmh_parse_refer_to(char *ref_to);
PMH_EXTERN sipReplaces_t *sippmh_parse_replaces(char *replcs, boolean dup_flag);
PMH_EXTERN void sippmh_free_replaces(sipReplaces_t *repl);
PMH_EXTERN void sippmh_free_refer_to(sipReferTo_t *ref);
PMH_EXTERN void sippmh_free_refer(sipRefer_t *ref);
PMH_EXTERN void sippmh_convertEscCharToChar(const char *inputStr,
size_t inputStrLen,
char *outputStr);
PMH_EXTERN int sippmh_cmpURLStrings(const char *s1, const char *s2,
boolean ignore_case);
PMH_EXTERN sip_author_t *sippmh_parse_authorization(const char *);
PMH_EXTERN char *sippmh_generate_authorization(sip_author_t *);
PMH_EXTERN void sippmh_free_author(sip_author_t *);
PMH_EXTERN sip_authen_t *sippmh_parse_authenticate(const char *);
PMH_EXTERN void sippmh_free_authen(sip_authen_t *);
PMH_EXTERN sip_author_t *sippmh_parse_proxy_author(const char *);
PMH_EXTERN sip_authen_t *sippmh_parse_proxy_authen(const char *);
PMH_EXTERN sipRemotePartyId_t *sippmh_parse_remote_party_id(
const char *input_remote_party_id);
PMH_EXTERN boolean sippmh_parse_kpml_event_id_params(char *params,
char **call_id,
char **from_tag,
char **to_tag);
PMH_EXTERN void sippmh_free_remote_party_id_info(sipRemotePartyIdInfo_t *rpid_info);
PMH_EXTERN char *sippmh_parse_user(char *url);
PMH_EXTERN int sippmh_parse_subscription_state(sipSubscriptionStateInfo_t *subsStateInfo,
const char *subs_state);
PMH_EXTERN int sippmh_add_subscription_state(sipMessage_t *msg,
sipSubscriptionStateInfo_t *subsStateInfo);
string_t sippmh_parse_displaystr(string_t displaystr);
#define sippmh_parse_to(x) sippmh_parse_location(x)
#define sippmh_free_to(x) sippmh_free_location(x)
#define sippmh_parse_from(x) sippmh_parse_location(x)
#define sippmh_free_from(x) sippmh_free_location(x)
PMH_EXTERN int sippmh_add_call_info(sipMessage_t *sipMessage,
cc_call_info_t *callInfo);
PMH_EXTERN uint32_t sippmh_parse_supported_require(const char *header,
char **punsupported_options);
PMH_EXTERN uint16_t sippmh_parse_allow_header(const char *header);
PMH_EXTERN uint16_t sippmh_parse_accept_header(const char *header);
PMH_EXTERN sipServiceControl_t
*sippmh_parse_service_control_body(char *msgBody, int msgLength);
PMH_EXTERN void sippmh_free_service_control_info(sipServiceControl_t *scp);
PMH_EXTERN sipJoinInfo_t *sippmh_parse_join_header(const char *header);
PMH_EXTERN void sippmh_free_join_info(sipJoinInfo_t *join);
PMH_EXTERN sipRet_t sippmh_add_join_header(sipMessage_t *message,
sipJoinInfo_t *join);
PMH_EXTERN int32_t sippmh_parse_max_forwards(const char *max_fwd_hdr);
PMH_EXTERN string_t sippmh_get_url_from_hdr(char *string);
PMH_EXTERN int32_t sippmh_parse_message_summary(sipMessage_t *pSipMessage, sipMessageSummary_t *mesgSummary);
/*
* The following SIP parser functions are the same as corresponding
* HTTP/1.1 message parser functions.
*/
#define sippmh_message_create() httpish_msg_create()
#define sippmh_message_free( x ) httpish_msg_free( x )
#define sippmh_is_request( x ) httpish_msg_is_request( x , SIP_SCHEMA, SIP_SCHEMA_LEN)
#define sippmh_is_message_complete( x ) httpish_msg_is_complete( x )
#define sippmh_get_request_line( x ) httpish_msg_get_reqline( x )
#define sippmh_get_response_line( x ) httpish_msg_get_respline( x )
#define sippmh_free_request_line( x ) httpish_msg_free_reqline( x )
#define sippmh_free_response_line( x ) httpish_msg_free_respline( x )
#define sippmh_process_network_message( x, y, z) \
httpish_msg_process_network_msg( x, y, z)
#define sippmh_get_code_class( x ) httpish_msg_get_code_class( x )
#define sippmh_add_request_line( x, y, a, b ) \
httpish_msg_add_reqline( x, y, a, b )
#define sippmh_add_response_line( x, y , a, b) \
httpish_msg_add_respline( x, y , a, b)
#define sippmh_add_text_header( x, y, z ) \
httpish_msg_add_text_header( x, y, z )
#define sippmh_add_int_header( x, y, z ) \
httpish_msg_add_int_header( x, y, z )
#define sippmh_add_message_body( x, y, z, a, b, c, d) \
httpish_msg_add_body(x, y, z, a, b, c, d)
#define sippmh_remove_header( x, y ) \
httpish_msg_remove_header( x, y )
#define sippmh_msg_header_present( x, y ) \
httpish_msg_header_present(x, y)
#define sippmh_get_header_val( x, y, c_y ) \
httpish_msg_get_header_val( x, y, c_y )
#define sippmh_get_cached_header_val(x, y) \
httpish_msg_get_cached_header_val(x, y)
#define sippmh_get_content_length( x ) \
httpish_msg_get_content_length( x )
#define sippmh_get_all_headers( x, y ) \
httpish_msg_get_all_headers( x, y )
#define sippmh_write_to_buf( x, y ) \
httpish_msg_write_to_buf( x, y )
#define sippmh_write( x, y, z ) \
httpish_msg_write( x, y, z )
#define sippmh_write_to_string( x ) \
httpish_msg_write_to_string( x )
#define sippmh_get_num_headers( x ) \
httpish_msg_get_num_headers( x )
#define sippmh_get_num_particular_headers( a, b, c, d, e ) \
httpish_msg_get_num_particular_headers( a, b, c, d, e )
#define sippmh_get_header_vals( a, b, c, d, e) \
httpish_msg_get_header_vals( a, b, c, d, e)
#define SIPPMH_VERSIONS_EQUAL(a, b) \
(cpr_strcasecmp(a, b) == 0)
/*
* Utility to compare From: header values, given the values rather
* than the sipFrom_t struct.
* Returns TRUE if the same, FALSE if not.
* Expects NULL terminated strings.
*/
PMH_EXTERN boolean sippmh_compare_fromto(const char *a1, const char *a2);
/*
* Same as compare_fromto, but for URL strings.
*/
PMH_EXTERN boolean sippmh_compare_urls(const char *u1, const char *u2);
#define PARSE_ERR_NON_SIP_URL 1
#define ERROR_1 SIP_F_PREFIX"Non-SIP URL\n"
#define PARSE_ERR_NO_MEMORY 2
#define ERROR_2 SIP_F_PREFIX"Out of memory\n"
#define PARSE_ERR_SYNTAX 3
#define ERROR_3 SIP_F_PREFIX"Syntax error at %s\n"
#define ERROR_3_1 SIP_F_PREFIX"Unexpected char %c\n"
#define PARSE_ERR_UNEXPECTED_EOS 4
#define ERROR_4 SIP_F_PREFIX"Unexpected end of string\n"
#define PARSE_ERR_UNTERMINATED_STRING 5
#define ERROR_5 SIP_F_PREFIX"Unmatched \"\n"
#define PARSE_ERR_UNMATCHED_BRACKET 6
#define ERROR_6 SIP_F_PREFIX"Unmatched <>\n"
#define PARSE_ERR_INVALID_TTL_VAL 7
#define ERROR_7 SIP_F_PREFIX"%d: Invalid ttl value(range 0-255)\n"
#define PARSE_ERR_NULL_PTR 8
#define ERROR_8 SIP_F_PREFIX"NULL Pointer\n"
#define AT_SIGN '@'
#define SEMI_COLON ';'
#define COLON ':'
#define EQUAL_SIGN '='
#define ESCAPE_CHAR '\\'
#define TILDA '~'
#define PERCENT '%'
#define STAR '*'
#define UNDERSCORE '_'
#define PLUS '+'
#define SINGLE_QUOTE '\''
#define DOUBLE_QUOTE '"'
#define LEFT_ANGULAR_BRACKET '<'
#define RIGHT_ANGULAR_BRACKET '>'
#define LEFT_SQUARE_BRACKET '['
#define RIGHT_SQUARE_BRACKET ']'
#define LEFT_PARENTHESIS '('
#define RIGHT_PARENTHESIS ')'
#define DOLLAR_SIGN '$'
#define FORWARD_SLASH '/'
#define DOT '.'
#define DASH '-'
#define EXCLAMATION '!'
#define AMPERSAND '&'
#define COMMA ','
#define QUESTION_MARK '?'
#define SPACE ' '
#define TAB '\t'
#define NUMBER_SIGN '#'
#define LEFT_CURLY_BRACE '{'
#define RIGHT_CURLY_BRACE '}'
#define OR_SIGN '|'
#define CARET '^'
#define OPENING_SINGLE_QUOTE '`'
#define PROXY 1
#define REDIRECT 2
#define TRANSPORT_UNSPECIFIED 0
#define TRANSPORT_UDP 1
#define TRANSPORT_TCP 2
#define TRANSPORT_TLS 3
#define TRANSPORT_SCTP 4
#define MAX_TTL_VAL 255
#define SIPPMH_FREE_REQUEST_LINE(x) sippmh_free_request_line(x); UTILFREE(x)
#define SIPPMH_FREE_RESPONSE_LINE(x) sippmh_free_response_line(x); UTILFREE(x)
#define SIPPMH_FREE_URL(x) sippmh_genurl_free(x); UTILFREE(x)
#define SIPPMH_FREE_MESSAGE(x) sippmh_free_message(x) ; UTILFREE(x)
size_t sippmh_convertURLCharToEscChar(const char *inputStr, size_t inputStrLen,
char *outputStr, size_t outputStrSize,
boolean null_terminate);
size_t sippmh_converQuotedStrToEscStr(const char *inputStr, size_t inputStrLen,
char *outputStr, size_t outputStrSize,
boolean null_terminate);
ccsipRet_e ccsip_process_network_message(sipMessage_t **sipmsg_p, char **buf,
unsigned long *nbytes_used,
char **display_msg);
#endif /* _CCSIP_PMH_H_ */
+645
View File
@@ -0,0 +1,645 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_PROTOCOL_H_
#define _CCSIP_PROTOCOL_H_
#include "httpish_protocol.h"
typedef struct sip_header_
{
char *hname;
char *c_hname;
} sip_header_t;
#define SIP_VERSION "SIP/2.0"
#define SIP_SCHEMA "SIP/"
#define SIP_SCHEMA_LEN 4 /* length of the SIP_SCHEMA as defined above */
/* Methods */
#define SIP_METHOD_OPTIONS "OPTIONS"
#define SIP_METHOD_INVITE "INVITE"
#define SIP_METHOD_BYE "BYE"
#define SIP_METHOD_CANCEL "CANCEL"
#define SIP_METHOD_REGISTER "REGISTER"
#define SIP_METHOD_ACK "ACK"
#define SIP_METHOD_PRACK "PRACK"
#define SIP_METHOD_COMET "COMET"
#define SIP_METHOD_NOTIFY "NOTIFY"
#define SIP_METHOD_REFER "REFER"
#define SIP_METHOD_UPDATE "UPDATE"
#define SIP_METHOD_INFO "INFO"
#define SIP_METHOD_MESSAGE "MESSAGE"
#define SIP_METHOD_PUBLISH "PUBLISH"
#define SIP_METHOD_SUBSCRIBE "SUBSCRIBE"
/* Headers */
/*
* We maintain a direct pointer to the header value for the following
* headers.
* Cached headers : Begin
*/
#define FROM 0
#define TO 1
#define VIA 2
#define CALLID 3
#define CSEQ 4
#define CONTACT 5
#define CONTENT_LENGTH 6
#define CONTENT_TYPE 7
#define RECORD_ROUTE 8
#define REQUIRE 9
#define ROUTE 10
#define SUPPORTED 11
/* Cached headers : End */
#define SESSION 24
#define EXPIRES 41
#define LOCATION 42
#define TIMESTAMP 43
#define MAX_FORWARDS 44
#define UNSUPPORTED 45
#define ACCEPT 46
#define ACCEPT_ENCODING 47
#define ACCEPT_LANGUAGE 48
#define ALLOW 49
#define USER_AGENT 50
#define SERVER 51
#define DATE 52
#define CISCO_GUID 53
#define DIVERSION 54
#define EVENT 55
#define SESSION 24
#define CALL_INFO 61
#define JOIN 62
/* Session Header Types - indicates the purpose of SDP bodies */
#define SESSION_MEDIA "Media"
#define SESSION_QOS "QoS"
#define SESSION_SECURITY "Security"
/* Content-Disposition Types */
#define SIP_CONTENT_DISPOSITION_UNKNOWN_VALUE 0
#define SIP_CONTENT_DISPOSITION_RENDER_VALUE 1
#define SIP_CONTENT_DISPOSITION_RENDER "render"
#define SIP_CONTENT_DISPOSITION_SESSION_VALUE 2
#define SIP_CONTENT_DISPOSITION_SESSION "session"
#define SIP_CONTENT_DISPOSITION_ICON_VALUE 3
#define SIP_CONTENT_DISPOSITION_ICON "icon"
#define SIP_CONTENT_DISPOSITION_ALERT_VALUE 4
#define SIP_CONTENT_DISPOSITION_ALERT "alert"
#define SIP_CONTENT_DISPOSITION_PRECONDITION_VALUE 5
#define SIP_CONTENT_DISPOSITION_PRECONDITION "precondition"
/* Content-Disposition Handling */
#define DISPOSITION_HANDLING "handling"
#define DISPOSITION_HANDLING_REQUIRED "required"
#define DISPOSITION_HANDLING_OPTIONAL "optional"
/* Some headers common to HTTP .some of the headers can be received
in compact form ( SIP_C_ .. indicates compact header form ) */
#define SIP_HEADER_CONTENT_LENGTH HTTPISH_HEADER_CONTENT_LENGTH
#define SIP_C_HEADER_CONTENT_LENGTH HTTPISH_C_HEADER_CONTENT_LENGTH
#define SIP_HEADER_CONTENT_TYPE HTTPISH_HEADER_CONTENT_TYPE
#define SIP_C_HEADER_CONTENT_TYPE "c"
#define SIP_HEADER_CONTENT_ENCODING HTTPISH_HEADER_CONTENT_ENCODING
#define SIP_C_HEADER_CONTENT_ENCODING "e"
#define SIP_HEADER_CONTENT_ID HTTPISH_HEADER_CONTENT_ID
#define SIP_HEADER_USER_AGENT HTTPISH_HEADER_USER_AGENT
#define SIP_HEADER_SERVER HTTPISH_HEADER_SERVER
#define SIP_HEADER_DATE HTTPISH_HEADER_DATE
#define SIP_HEADER_VIA HTTPISH_HEADER_VIA
#define SIP_C_HEADER_VIA "v"
#define SIP_HEADER_MAX_FORWARDS HTTPISH_HEADER_MAX_FORWARDS
#define SIP_HEADER_EXPIRES HTTPISH_HEADER_EXPIRES
#define SIP_HEADER_LOCATION HTTPISH_HEADER_LOCATION
#define SIP_C_HEADER_LOCATION "m"
/* Headers specific to SIP .Some of the headers can be received in
compact form */
#define SIP_HEADER_FROM "From"
#define SIP_C_HEADER_FROM "f"
#define SIP_HEADER_TO "To"
#define SIP_C_HEADER_TO "t"
#define SIP_HEADER_CSEQ "CSeq"
#define SIP_HEADER_TIMESTAMP "Timestamp"
#define SIP_HEADER_CALLID "Call-ID"
#define SIP_C_HEADER_CALLID "i"
#define SIP_HEADER_REQUIRE "Require"
#define SIP_HEADER_SUPPORTED "Supported"
#define SIP_C_HEADER_SUPPORTED "k"
#define SIP_HEADER_UNSUPPORTED "Unsupported"
#define SIP_HEADER_CONTACT "Contact"
#define SIP_C_HEADER_CONTACT SIP_C_HEADER_LOCATION
#define SIP_HEADER_CISCO_GUID "Cisco-Guid"
#define SIP_HEADER_WARN "Warning"
#define SIP_HEADER_ACCEPT "Accept"
#define SIP_HEADER_ACCEPT_ENCODING "Accept-Encoding"
#define SIP_HEADER_ACCEPT_LANGUAGE "Accept-Language"
#define SIP_HEADER_ALLOW "Allow"
#define SIP_HEADER_RECORD_ROUTE "Record-Route"
#define SIP_HEADER_ROUTE "Route"
#define SIP_HEADER_SESSION "Session"
#define SIP_HEADER_ALSO "Also"
#define SIP_HEADER_REQUESTED_BY "Requested-By"
#define SIP_HEADER_DIVERSION "Diversion"
#define SIP_HEADER_CC_DIVERSION "CC-Diversion"
#define SIP_HEADER_CC_REDIRECT "CC-Redirect"
#define SIP_HEADER_ALERT_INFO "Alert-Info"
#define SIP_HEADER_RSEQ "RSeq"
#define SIP_HEADER_RACK "RAck"
#define SIP_HEADER_CONTENT_DISP "Content-Disposition"
/* call stats */
#define SIP_RX_CALL_STATS "RTP-RxStat"
#define SIP_TX_CALL_STATS "RTP-TxStat"
/* Spam Specific */
#define SIP_HEADER_AUTHORIZATION "Authorization"
#define SIP_HEADER_PROXY_AUTHORIZATION "Proxy-Authorization"
#define SIP_HEADER_PROXY_AUTHENTICATE "Proxy-Authenticate"
#define SIP_HEADER_WWW_AUTHENTICATE "WWW-Authenticate"
/* Refer parameters */
#define SIP_HEADER_REFER_TO "Refer-To"
#define SIP_C_HEADER_REFER_TO "r"
#define SIP_HEADER_REFERRED_BY "Referred-By"
#define SIP_C_HEADER_REFERRED_BY "b"
#define SIP_HEADER_REPLACES "Replaces"
#define SIP_HEADER_PROXY_AUTH "Proxy-Authorization"
#define SIP_HEADER_ACCEPT_CONTACT "Accept-Contact"
#define SIP_C_HEADER_ACCEPT_CONTACT "a"
#define SIP_HEADER_REMOTE_PARTY_ID "Remote-Party-ID"
#define SIP_HEADER_EVENT "Event"
#define SIP_C_HEADER_EVENT "o"
#define SIP_HEADER_SIPIFMATCH "SIP-If-Match"
#define SIP_HEADER_SIPETAG "SIP-ETag"
#define SIP_HEADER_RETRY_AFTER "Retry-After"
#define SIP_HEADER_MIN_EXPIRES "Min-Expires"
#define SIP_HEADER_REASON "Reason"
/* Event values */
#define SIP_EVENT_REFER "refer"
#define SIP_EVENT_DIALOG "dialog"
#define SIP_EVENT_KPML "kpml"
#define SIP_EVENT_PRESENCE "presence"
#define SIP_EVENT_CONFIG "sip-profile"
#define SIP_EVENT_MWI "message-summary"
/* Event param */
#define SIP_EVENT_ID "id"
/* Subscription states */
#define SIP_HEADER_SUBSCRIPTION_STATE "Subscription-State"
#define SIP_SUBSCRIPTION_STATE_ACTIVE "active"
#define SIP_SUBSCRIPTION_STATE_PENDING "pending"
#define SIP_SUBSCRIPTION_STATE_TERMINATED "terminated"
/* Subscription state params */
#define SIP_SUBSCRIPTION_STATE_EXPIRES "expires"
#define SIP_SUBSCRIPTION_STATE_REASON "reason"
#define SIP_SUBSCRIPTION_STATE_RETRY_AFTER "retry-after"
/* Subscription state reason values */
#define SIP_SUBSCRIPTION_STATE_REASON_DEACTIVATED "deactivated"
#define SIP_SUBSCRIPTION_STATE_REASON_PROBATION "probation"
#define SIP_SUBSCRIPTION_STATE_REASON_REJECTED "rejected"
#define SIP_SUBSCRIPTION_STATE_REASON_TIMEOUT "timeout"
#define SIP_SUBSCRIPTION_STATE_REASON_GIVEUP "giveup"
#define SIP_SUBSCRIPTION_STATE_REASON_NORESOURCE "noresource"
/* Content-Type values */
#define SIP_CONTENT_TYPE_UNKNOWN_VALUE 0
#define SIP_CONTENT_TYPE_UNKNOWN "application/unknown"
#define SIP_CONTENT_TYPE_SDP_VALUE 1
#define SIP_CONTENT_TYPE_SDP "application/sdp"
#define SIP_CONTENT_TYPE_SIP_VALUE 2
#define SIP_CONTENT_TYPE_SIP "application/sip"
#define SIP_CONTENT_TYPE_SIPFRAG_VALUE 3
#define SIP_CONTENT_TYPE_SIPFRAG "message/sipfrag"
#define SIP_CONTENT_TYPE_DIALOG_VALUE 4
#define SIP_CONTENT_TYPE_DIALOG "application/dialog-info+xml"
#define SIP_CONTENT_TYPE_MWI_VALUE 5
#define SIP_CONTENT_TYPE_MWI "application/simple-message-summary"
#define SIP_CONTENT_TYPE_KPML_REQUEST_VALUE 6
#define SIP_CONTENT_TYPE_KPML_REQUEST "application/kpml-request+xml"
#define SIP_CONTENT_TYPE_KPML_RESPONSE_VALUE 7
#define SIP_CONTENT_TYPE_KPML_RESPONSE "application/kpml-response+xml"
#define SIP_CONTENT_TYPE_REMOTECC_REQUEST_VALUE 8
#define SIP_CONTENT_TYPE_REMOTECC_REQUEST "application/x-cisco-remotecc-request+xml"
#define SIP_CONTENT_TYPE_REMOTECC_RESPONSE_VALUE 9
#define SIP_CONTENT_TYPE_REMOTECC_RESPONSE "application/x-cisco-remotecc-response+xml"
#define SIP_CONTENT_TYPE_CTI_VALUE 10
#define SIP_CONTENT_TYPE_CTI "application/x-cisco-cti+xml"
#define SIP_CONTENT_TYPE_CMXML_VALUE 11
#define SIP_CONTENT_TYPE_CMXML "application/x-cisco-remotecc-cm+xml"
#define SIP_CONTENT_TYPE_MULTIPART_MIXED_VALUE 12
#define SIP_CONTENT_TYPE_MULTIPART_MIXED "multipart/mixed"
#define SIP_CONTENT_TYPE_MULTIPART_ALTERNATIVE_VALUE 13
#define SIP_CONTENT_TYPE_MULTIPART_ALTERNATIVE "multipart/alternative"
#define SIP_CONTENT_TYPE_TEXT_PLAIN_VALUE 14
#define SIP_CONTENT_TYPE_TEXT_PLAIN "text/plain"
#define SIP_CONTENT_TYPE_PRESENCE_VALUE 15
#define SIP_CONTENT_TYPE_PRESENCE "application/pidf+xml"
#define SIP_CONTENT_TYPE_CONFIGAPP_VALUE 16
#define SIP_CONTENT_TYPE_CONFIGAPP "application/x-cisco-config+xml"
#define SIP_CONTENT_TYPE_MEDIA_CONTROL "application/media_control+xml"
/* Content-Type for multipart-mime */
#define SIP_CONTENT_TYPE_MULTIPART "multipart/mixed"
#define SIP_CONTENT_BOUNDARY "boundary"
#define SIP_CONTENT_BOUNDARY_TEXT "uniqueBoundary"
/* Content-Encoding */
/* At this time identity is the only one recognize */
#define SIP_CONTENT_ENCODING_IDENTITY "identity"
#define SIP_CONTENT_ENCODING_IDENTITY_VALUE 0
#define SIP_CONTENT_ENCODING_UNKNOWN_VALUE 1
/* Call-info header */
#define SIP_HEADER_CALL_INFO "Call-Info"
#define SIP_CALL_INFO_PURPOSE "Purpose"
#define SIP_CALL_INFO_PURPOSE_INFO "info"
#define SIP_CALL_INFO_PURPOSE_ICON "icon"
#define SIP_CALL_INFO_PURPOSE_CARD "card"
#define SIP_CALL_INFO_ORIENTATION "Orientation"
#define SIP_CALL_INFO_ORIENTATION_TO "To"
#define SIP_CALL_INFO_ORIENTATION_FROM "From"
#define SIP_CALL_INFO_SECURITY "Security"
#define SIP_CALL_INFO_SECURITY_UNKNOWN "Unknown"
#define SIP_CALL_INFO_SECURITY_AUTHENTICATED "Authenticated"
#define SIP_CALL_INFO_SECURITY_NOT_AUTHENTICATED "NotAuthenticated"
/* via-params */
#define MAX_TTL_VAL 255
#define SIP_WELL_KNOWN_PORT 5060
#define SIP_WELL_KNOWN_PORT_STR "5060"
#define VIA_HIDDEN "hidden"
#define VIA_TTL "ttl"
#define VIA_MADDR "maddr"
#define VIA_RECEIVED "received"
#define VIA_BRANCH "branch"
#define VIA_BRANCH_START "z9hG4bK"
/* CC-Diversion Parameters */
#define DIVERSION_REASON "reason"
#define DIVERSION_COUNTER "counter"
#define DIVERSION_LIMIT "limit"
#define DIVERSION_PRIVACY "privacy"
#define DIVERSION_SCREEN "screen"
/* CC-Redirect Parameters */
#define CC_REDIRECT_REASON "redir-reason"
#define CC_REDIRECT_COUNTER "redir-counter"
#define CC_REDIRECT_LIMIT "redir-limit"
/* CC-Diversion Reason Parameter values */
// REASON_UNKNOWN conflicts with winreg.h on Windows.
#ifdef REASON_UNKNOWN
#undef REASON_UNKNOWN
#endif
#define REASON_UNKNOWN "unknown"
#define REASON_USER_BUSY "user-busy"
#define REASON_NO_ANSWER "no-answer"
#define REASON_UNCONDITIONAL "unconditional"
#define REASON_DEFLECTION "deflection"
#define REASON_FOLLOW_ME "follow-me"
#define REASON_OUT_OF_SERVICE "out-of-service"
#define REASON_TIME_OF_DAY "time-of-day"
#define REASON_DO_NOT_DISTURB "do-not-disturb"
#define REASON_UNAVAILABLE "unavailable"
#define REASON_AWAY "away"
/* Replaces parameters */
#define SIGNATURE_SCHEME "scheme"
#define TO_TAG "to-tag"
#define FROM_TAG "from-tag"
/* Remote-Party-Id parameters */
#define RPID_SCREEN "screen"
#define RPID_PARTY_TYPE "party"
#define RPID_ID_TYPE "id-type"
#define RPID_PRIVACY "privacy"
#define RPID_NP "np"
#define RPID_CALLBACK "x-cisco-callback-number="
#define RPID_SCREEN_LEN (sizeof(RPID_SCREEN) - 1)
#define RPID_PARTY_TYPE_LEN (sizeof(RPID_PARTY_TYPE) - 1)
#define RPID_ID_TYPE_LEN (sizeof(RPID_ID_TYPE) - 1)
#define RPID_PRIVACY_LEN (sizeof(RPID_PRIVACY) - 1)
#define RPID_NP_LEN (sizeof(RPID_NP) - 1)
#define RPID_CALLBACK_LEN (sizeof(RPID_CALLBACK) - 1)
#define KPML_ID_CALLID "call-id"
#define KPML_ID_FROM_TAG "from-tag"
#define KPML_ID_TO_TAG "to-tag"
#define KPML_ID_CALLID_LEN (sizeof(SIP_HEADER_CALLID)-1)
#define KPML_ID_FROM_TAG_LEN (sizeof(FROM_TAG)-1)
#define KPML_ID_TO_TAG_LEN (sizeof(TO_TAG)-1)
#define PRIVACY_OFF "off"
#define PRIVACY_NAME "name"
#define PRIVACY_URI "uri"
#define PRIVACY_FULL "full"
#define SCREEN_NO "no"
#define SCREEN_YES "yes"
#define PARTY_TYPE_CALLING "calling"
#define PARTY_TYPE_CALLED "called"
#define SIP_HEADER_ALLOW_EVENTS "Allow-Events"
#define SIP_HEADER_MIME_VERSION "MIME-Version"
#define SIP_MIME_VERSION_VALUE "1.0"
/* Require and Supported header params */
#define REQ_SUPP_PARAM_REPLACES "replaces"
#define REQ_SUPP_PARAM_100REL "100rel"
#define REQ_SUPP_PARAM_EARLY_SESSION "early-session"
#define REQ_SUPP_PARAM_JOIN "join"
#define REQ_SUPP_PARAM_PATH "path"
#define REQ_SUPP_PARAM_PRECONDITION "precondition"
#define REQ_SUPP_PARAM_PREF "pref"
#define REQ_SUPP_PARAM_PRIVACY "privacy"
#define REQ_SUPP_PARAM_SEC_AGREE "sec-agree"
#define REQ_SUPP_PARAM_TIMER "timer"
#define REQ_SUPP_PARAM_NOREFERSUB "norefersub"
#define REQ_SUPP_PARAM_EXTENED_REFER "extended-refer"
#define REQ_SUPP_PARAM_CISCO_CALLINFO "X-cisco-callinfo"
#define REQ_SUPP_PARAM_CISCO_SERVICEURI "X-cisco-serviceuri"
#define REQ_SUPP_PARAM_CISCO_ESCAPECODES "X-cisco-escapecodes"
#define REQ_SUPP_PARAM_CISCO_SERVICE_CONTROL "X-cisco-service-control"
#define REQ_SUPP_PARAM_CISCO_SRTP_FALLBACK "X-cisco-srtp-fallback"
#define REQ_SUPP_PARAM_CISCO_CONFIG "X-cisco-config"
#define REQ_SUPP_PARAM_SDP_ANAT "sdp-anat"
/* Add defines for the SIP Interfcae Specification (SIS) protocol version tags*/
#define REQ_SUPP_PARAM_CISCO_SISTAG "X-cisco-sis-"
#define SIS_CURRENT_PROTOCOL_VERSION "5.2.0"
#define SIS_PROTOCOL_MAJOR_VERSION_SEADRAGON 1
#define SIS_PROTOCOL_MAJOR_VERSION_MUSTER 2
#define SIS_PROTOCOL_MAJOR_VERSION_UNISON 3
#define SIS_PROTOCOL_MAJOR_VERSION_GUILD 4
#define SIS_PROTOCOL_MAJOR_VERSION_ANGELFIRE 5
#define SIS_PROTOCOL_MINOR_VERSION_ANGELFIRE 1
#define SIS_PROTOCOL_MINOR_VERSION_MONTBLANC 1
#define REQ_SUPP_PARAM_CISCO_SIPVER REQ_SUPP_PARAM_CISCO_SISTAG SIS_CURRENT_PROTOCOL_VERSION
#define REQ_SUPP_PARAM_CISCO_MONREC "X-cisco-monrec"
/* Add define for CME version negotiation */
#define REQ_SUPP_PARAM_CISCO_CME_SISTAG "X-cisco-cme-sis-"
/* Contact parameters */
#define REQ_CONT_PARAM_CISCO_NEWREG "X-cisco-newreg"
/* Max-forwards header */
#define SIP_MAX_FORWARDS_DEFAULT_STR "70"
#define SIP_MAX_FORWARDS_DEFAULT_VALUE 70
/* Join header */
#define SIP_HEADER_JOIN "Join"
#define SIP_HEADER_JOIN_FROM_TAG "from-tag"
#define SIP_HEADER_JOIN_TO_TAG "to-tag"
/* Info-Package headers */
#define SIP_HEADER_SEND_INFO "Send-Info"
#define SIP_HEADER_RECV_INFO "Recv-Info"
#define SIP_HEADER_INFO_PACKAGE "Info-Package"
/*
* ALERT : If you are defining a compact header more than 2 bytes long, modify
* routine compact_hdr_cmp() in file httpish.c
*/
/*
* Revised SIP drafts say that we use Contact and not Location in the header.
* But we are supporting both currently for MCI
*/
/* S T A T U S C O D E S */
/* Informational Status Codes 1xx */
#define SIP_1XX_TRYING 100 /* "Trying" */
#define SIP_1XX_RINGING 180 /* "Ringing" */
#define SIP_1XX_CALL_FWD 181 /* "Call is being forwaded" */
#define SIP_1XX_QUEUED 182 /* "Queued" */
#define SIP_1XX_SESSION_PROGRESS 183 /* "Session Progress" */
/* Success Status Code 2xx */
#define SIP_SUCCESS_SETUP 200 /* OK/Success */
#define SIP_ACCEPTED 202 /* Accepted */
#define SIP_STATUS_SUCCESS SIP_SUCCESS_SETUP
/* Redirection Status Codes 3xx */
#define SIP_RED_MULT_CHOICES 300 /* Multiple Choices */
#define SIP_RED_MOVED_PERM 301 /* Moved Permanently */
#define SIP_RED_MOVED_TEMP 302 /* Moved Temporarily */
#define SIP_RED_SEE_OTHER 303 /* See Other */
#define SIP_RED_USE_PROXY 305 /* Use Proxy */
#define SIP_RED_ALT_SERVICE 380 /* Alternative Service */
/* Client Error Status Codes 4xx */
#define SIP_CLI_ERR_BAD_REQ 400 /* Bad Request */
#define SIP_CLI_ERR_UNAUTH 401 /* Unauthorized */
#define SIP_CLI_ERR_PAY_REQD 402 /* Payment Required */
#define SIP_CLI_ERR_FORBIDDEN 403 /* Forbidden */
#define SIP_CLI_ERR_NOT_FOUND 404 /* Not Found */
#define SIP_CLI_ERR_NOT_ALLOWED 405 /* Method Not Allowed */
#define SIP_CLI_ERR_NOT_ACCEPT 406 /* Not Acceptable */
#define SIP_CLI_ERR_PROXY_REQD 407 /* Proxy Authentication Required */
#define SIP_CLI_ERR_REQ_TIMEOUT 408 /* Request Timeout */
#define SIP_CLI_ERR_CONFLICT 409 /* Conflict */
#define SIP_CLI_ERR_GONE 410 /* Gone */
#define SIP_CLI_ERR_LEN_REQD 411 /* Length Required */
#define SIP_CLI_ERR_COND_FAIL 412 /* Conditional req failed */
#define SIP_CLI_ERR_LARGE_MSG 413 /* Request Message Body Too Large */
#define SIP_CLI_ERR_LARGE_URI 414 /* Request-URI Too Large */
#define SIP_CLI_ERR_MEDIA 415 /* Unsupported Media Type */
#define SIP_CLI_ERR_EXTENSION 420 /* Bad Extension */
#define SIP_CLI_ERR_INTERVAL_TOO_SMALL 423 /* Duration too small */
#define SIP_CLI_ERR_ANONYMITY_NOT_ALLOWED 433 /* Anonymity Disallowed */
#define SIP_CLI_ERR_NOT_AVAIL 480 /* Temporarily Not Available */
#define SIP_CLI_ERR_CALLEG 481 /* Call Leg/Transaction Does Not Exist */
#define SIP_CLI_ERR_LOOP_DETECT 482 /* Loop Detected */
#define SIP_CLI_ERR_MANY_HOPS 483 /* Too Many Hops */
#define SIP_CLI_ERR_ADDRESS 484 /* Address Incomplete */
#define SIP_CLI_ERR_AMBIGUOUS 485 /* Ambiguous */
#define SIP_CLI_ERR_BUSY_HERE 486 /* Busy here */
#define SIP_CLI_ERR_REQ_CANCEL 487 /* Request Cancelled */
#define SIP_CLI_ERR_NOT_ACCEPT_HERE 488 /* Not Acceptable Here */
#define SIP_CLI_ERR_BAD_EVENT 489 /* Bad Event */
#define SIP_CLI_ERR_REQ_PENDING 491 /* Request Pending */
/* Server Error Status Codes 5xx */
#define SIP_SERV_ERR_INTERNAL 500 /* Internal Server Error */
#define SIP_SERV_ERR_NOT_IMPLEM 501 /* Not Implemented */
#define SIP_SERV_ERR_BAD_GW 502 /* Bad Gateway */
#define SIP_SERV_ERR_UNAVAIL 503 /* Service Unavailable */
#define SIP_SERV_ERR_GW_TIMEOUT 504 /* Gateway Timeout */
#define SIP_SERV_ERR_SIP_VER 505 /* SIP Version not supported */
#define SIP_SERV_ERR_PRECOND_FAILED 580 /* Precondition Failed */
/* Global Failure Status Codes 6xx */
#define SIP_FAIL_BUSY 600 /* Busy */
#define SIP_FAIL_DECLINE 603 /* Decline */
#define SIP_FAIL_NOT_EXIST 604 /* Does not exist anywhere */
#define SIP_FAIL_NOT_ACCEPT 606 /* Not Acceptable */
/* SIP Warning Codes 3xx */
#define SIP_WARN_INCOMPAT_NETWORK_PROT 300 /* Incompatible Network Protocol */
#define SIP_WARN_INCOMPAT_NETWORK_ADDR 301 /* Incompatible Network Address */
#define SIP_WARN_INCOMPAT_TRANS_PROT 302 /* Incompatible Transport Protocol */
#define SIP_WARN_INCOMPAT_BANDW_UNITS 303 /* Incompatible Bandwidth Units */
#define SIP_WARN_MEDIA_TYPE_UNAVAIL 304 /* Media Type(s) Unavailable */
#define SIP_WARN_INCOMPAT_MEDIA_FORMAT 305 /* Incompatible Media Formats */
#define SIP_WARN_UNKNOWN_MEDIA_ATTRIB 306 /* Media Attribute not understood */
#define SIP_WARN_UNKNOWN_SDP_PARAM 307 /* SDP Parameter not understood */
#define SIP_WARN_MISC 399 /* Miscellaneous */
/* Other warnings */
#define SIP_WARN_PROCESSING_PREVIOUS_REQUEST 901
/* R E A S O N P H R A S E S */
/* Informational 1xx */
#define SIP_1XX_TRYING_PHRASE "Trying"
#define SIP_1XX_RINGING_PHRASE "Ringing"
#define SIP_1XX_CALL_FWD_PHRASE "Call is being forwaded"
#define SIP_1XX_QUEUED_PHRASE "Queued"
#define SIP_1XX_SESSION_PROGRESS_PHRASE "Session Progress"
/* Success 2xx */
#define SIP_SUCCESS_SETUP_PHRASE "OK"
#define SIP_ACCEPTED_PHRASE "Accepted"
/* Redirection 3xx */
#define SIP_RED_MULT_CHOICES_PHRASE "Multiple Choices"
#define SIP_RED_MOVED_PERM_PHRASE "Moved Permanently"
#define SIP_RED_MOVED_TEMP_PHRASE "Moved Temporarily"
#define SIP_RED_SEE_OTHER_PHRASE "See Other"
#define SIP_RED_USE_PROXY_PHRASE "Use Proxy"
#define SIP_RED_ALT_SERVICE_PHRASE "Alternative Service"
/* Client Error 4xx */
#define SIP_CLI_ERR_BAD_REQ_PHRASE "Bad Request"
#define SIP_CLI_ERR_UNAUTH_PHRASE "Unauthorized"
#define SIP_CLI_ERR_PAY_REQD_PHRASE "Payment Required"
#define SIP_CLI_ERR_FORBIDDEN_PHRASE "Forbidden"
#define SIP_CLI_ERR_NOT_FOUND_PHRASE "Not Found"
#define SIP_CLI_ERR_NOT_ALLOWED_PHRASE "Method Not Allowed"
#define SIP_CLI_ERR_NOT_ACCEPT_PHRASE "Not Acceptable"
#define SIP_CLI_ERR_PROXY_REQD_PHRASE "Proxy Authentication Required"
#define SIP_CLI_ERR_REQ_TIMEOUT_PHRASE "Request Timeout"
#define SIP_CLI_ERR_CONFLICT_PHRASE "Conflict"
#define SIP_CLI_ERR_GONE_PHRASE "Gone"
#define SIP_CLI_ERR_LEN_REQD_PHRASE "Length Required"
#define SIP_CLI_ERR_LARGE_MSG_PHRASE "Request Message Body Too Large"
#define SIP_CLI_ERR_LARGE_URI_PHRASE "Request-URI Too Large"
#define SIP_CLI_ERR_MEDIA_PHRASE "Unsupported Media Type"
#define SIP_CLI_ERR_EXTENSION_PHRASE "Bad Extension"
#define SIP_CLI_ERR_NOT_AVAIL_PHRASE "Temporarily Not Available"
#define SIP_CLI_ERR_CALLEG_PHRASE "Call Leg/Transaction Does Not Exist"
#define SIP_CLI_ERR_SUBS_DOES_NOT_EXIST_PHRASE "Subscription Does Not Exist"
#define SIP_CLI_ERR_LOOP_DETECT_PHRASE "Loop Detected"
#define SIP_CLI_ERR_MANY_HOPS_PHRASE "Too Many Hops"
#define SIP_CLI_ERR_ADDRESS_PHRASE "Address Incomplete"
#define SIP_CLI_ERR_AMBIGUOUS_PHRASE "Ambiguous"
#define SIP_CLI_ERR_BUSY_HERE_PHRASE "Busy here"
#define SIP_CLI_ERR_REQ_CANCEL_PHRASE "Request Cancelled"
#define SIP_CLI_ERR_NOT_ACCEPT_HERE_PHRASE "Not Acceptable Here"
#define SIP_CLI_ERR_BAD_EVENT_PHRASE "Bad Event"
#define SIP_CLI_ERR_INTERVAL_TOO_SMALL_PHRASE "Interval too small"
#define SIP_CLI_ERR_INTERVAL_TOO_LARGE_PHRASE "Interval too large"
#define SIP_CLI_ERR_ANONYMITY_NOT_ALLOWED_PHRASE "Anonymity Disallowed"
#define SIP_CLI_ERR_REQ_PENDING_PHRASE "Request Pending"
/* Server Error 5xx */
#define SIP_SERV_ERR_INTERNAL_PHRASE "Internal Server Error"
#define SIP_SERV_ERR_NOT_IMPLEM_PHRASE "Not Implemented"
#define SIP_SERV_ERR_BAD_GW_PHRASE "Bad Gateway"
#define SIP_SERV_ERR_UNAVAIL_PHRASE "Service Unavailable"
#define SIP_SERV_ERR_GW_TIMEOUT_PHRASE "Gateway Timeout"
#define SIP_SERV_ERR_SIP_VER_PHRASE "SIP Version not supported"
#define SIP_SERV_ERR_PRECOND_FAILED_PHRASE "Precondition Failed"
/* Global Failure 6xx */
#define SIP_FAIL_BUSY_PHRASE "Busy"
#define SIP_FAIL_DECLINE_PHRASE "Decline"
#define SIP_FAIL_NOT_EXIST_PHRASE "Does not exist anywhere"
#define SIP_FAIL_NOT_ACCEPT_PHRASE "Not Acceptable"
/* SIP Warning Codes 3xx Phrases */
#define SIP_WARN_INCOMPAT_NETWORK_PROT_PHRASE "\"Incompatible Network Protocol\""
#define SIP_WARN_INCOMPAT_NETWORK_ADDR_PHRASE "\"Incompatible Network Address\""
#define SIP_WARN_INCOMPAT_TRANS_PROT_PHRASE "\"Incompatible Transport Protocol\""
#define SIP_WARN_INCOMPAT_BANDW_UNITS_PHRASE "\"Incompatible Bandwidth Units\""
#define SIP_WARN_MEDIA_TYPE_UNAVAIL_PHRASE "\"Media Type(s) Unavailable\""
#define SIP_WARN_INCOMPAT_MEDIA_FORMAT_PHRASE "\"Incompatible Media Formats\""
#define SIP_WARN_UNKNOWN_MEDIA_ATTRIB_PHRASE "\"Media Attribute not understood\""
#define SIP_WARN_UNKNOWN_SDP_PARAM_PHRASE "\"SDP Parameter not understood\""
#define SIP_WARN_REFER_AMBIGUOUS_PHRASE "\"Ambiguous.Multiple Contacts Found.\""
#define SIP_STATUS_PHRASE_NONE "Unknown"
/* Client Error 400 Bad Request detailed explaination */
#define SIP_CLI_ERR_BAD_REQ_MEDIA_COMP_FAILED "Bad Request - 'Media info comparison failed'"
#define SIP_CLI_ERR_BAD_REQ_SDP_ERROR "Bad Request - 'Invalid SDP information'"
#define SIP_CLI_ERR_BAD_REQ_RECORD_ROUTE "Bad Request - 'Malformed/Missing Record Route'"
#define SIP_CLI_ERR_BAD_REQ_CONTACT_FIELD "Bad Request - 'Malformed/Missing Contact field'"
#define SIP_CLI_ERR_BAD_REQ_CALLID_ABSENT "Bad Request - 'Callid absent'"
#define SIP_CLI_ERR_BAD_REQ_CSEQ_FIELD "Bad Request - 'Error in Cseq field'"
#define SIP_CLI_ERR_BAD_REQ_FROM_OR_TO_FIELD "Bad Request - 'Error in From and/or To field'"
#define SIP_CLI_ERR_BAD_REQ_MEDIA_NEGOTIATION "Bad Request - 'Media Negotiation Failed'"
#define SIP_CLI_ERR_BAD_REQ_URL_ERROR "Bad Request - 'Malformed/Missing URL'"
#define SIP_CLI_ERR_BAD_REQ_ToURL_ERROR "Bad Request - 'Malformed/Missing TO: field'"
#define SIP_CLI_ERR_BAD_REQ_FROMURL_ERROR "Bad Request - 'Malformed/Missing FROM: field'"
#define SIP_CLI_ERR_BAD_REQ_CALLID_ERROR "Bad Request - 'Malformed/Missing CALLID field'"
#define SIP_CLI_ERR_BAD_REQ_REQLINE_ERROR "Bad Request - 'Malformed/Missing REQUEST LINE'"
#define SIP_CLI_ERR_BAD_REQ_IPADDRESS_ERROR "Bad Request - 'Invalid IP Address'"
#define SIP_CLI_ERR_BAD_REQ_CONTENT_LENGTH_ERROR "Bad Request - 'Content length Error'"
#define SIP_CLI_ERR_BAD_REQ_CONTENT_TYPE_ERROR "Bad Request - 'Malformed/Missing SIP CONTENT TYPE field'"
#define SIP_CLI_ERR_BAD_REQ_PHRASE_DIVERSION "Bad Request - 'Malformed CC-Diversion Header'"
#define SIP_CLI_ERR_BAD_REQ_VIA_OR_CSEQ "Bad Request - 'Malformed/Missing VIA OR CSEQ'"
#define SIP_CLI_ERR_BAD_REQ_PHRASE_REFER "Bad Request - 'Malformed REFER Request'"
#define SIP_CLI_ERR_BAD_REQ_PHRASE_REFER_TO "Bad Request - 'Malformed Refer-To Header'"
#define SIP_CLI_ERR_BAD_REQ_PHRASE_REFER_BY "Bad Request - 'Missing Refer-By Header'"
#define SIP_CLI_ERR_BAD_REQ_PHRASE_REPLACES "Bad Request - 'Malformed Replaces Header'"
#define SIP_CLI_ERR_BAD_REQ_METHOD_UNKNOWN "Bad Request - 'Unable to obtain SIP method'"
#define SIP_CLI_ERR_BAD_REQ_BAD_BODY_ENCODING "Bad Request - 'Unable to decode body'"
#define SIP_CLI_ERR_BAD_REQ_SUBSCRIPTION_DELETED "Bad Request - 'Subscription Terminated'"
#define SIP_CLI_ERR_BAD_REQ_NO_BODY "Bad Request - 'Body Expected'"
#define SIP_CLI_ERR_BAD_REQ_NO_SUBSCRIPTION_HEADER "Bad Request - 'Malformed/Missing Subscription-State Header'"
#define SIP_CLI_ERR_BAD_REQ_CONTENT_ID_ERROR "Bad Request - 'Invalid Content-Id field'"
#define SIP_CLI_ERR_BAD_REQ_REQUIRE_HDR "Bad Request - 'Malformed/Missing Require header'"
#endif /*_CCSIP_PROTOCOL_H_*/
@@ -0,0 +1,44 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_PUBLISH_H_
#define _CCSIP_PUBLISH_H_
#include "publish_int.h"
#include "ccsip_common_cb.h"
#include "ccsip_subsmanager.h"
/* the following is to take advantage of SUB/NOT periodic timer */
#define TMR_PERIODIC_PUBLISH_INTERVAL TMR_PERIODIC_SUBNOT_INTERVAL
#define PUBLISH_FAILED_START (1000)
#define PUBLISH_FAILED_NOCONTEXT (PUBLISH_FAILED_START + 1)
#define PUBLISH_FAILED_NORESOURCE (PUBLISH_FAILED_START + 2)
#define PUBLISH_FAILED_SEND (PUBLISH_FAILED_START + 3)
#define PUBLISH_FAILED_RESET (PUBLISH_FAILED_START + 4)
typedef struct {
ccsip_common_cb_t hb; /* this MUST be the first member */
cc_srcs_t callback_task; // CallBack Task ID
int resp_msg_id; //Response Msg ID
char *entity_tag;
pub_handle_t pub_handle;
pub_handle_t app_handle;
char ruri[MAX_URI_LENGTH]; // Address of the resource
char full_ruri[MAX_SIP_URL_LENGTH];
char esc[MAX_URI_LENGTH]; // Event State Compositor
boolean outstanding_trxn;
sipPlatformUITimer_t retry_timer;
sll_handle_t pending_reqs; //holds pending requests
} ccsip_publish_cb_t; //PUBLISH Control Block data structure
extern int publish_handle_ev_app_publish(cprBuffer_t buf);
extern int publish_handle_retry_timer_expire(uint32_t handle);
extern void publish_handle_periodic_timer_expire(void);
extern int publish_handle_ev_sip_response(sipMessage_t *pSipMessage);
extern void publish_reset(void);
extern cc_int32_t show_publish_stats(cc_int32_t argc, const char *argv[]);
#endif // _CCSIP_PUBLISH_H_
+157
View File
@@ -0,0 +1,157 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_REGISTER_H_
#define _CCSIP_REGISTER_H_
#include "cpr_types.h"
#include "cpr_timers.h"
#include "phone.h"
#include "ccsip_core.h"
#include "ccsip_credentials.h"
#include "platform_api.h"
#define MAX_REG_EXPIRES 3600
#include "ccsip_subsmanager.h"
#include "platform_api.h"
#define MAX_RETRIES_401 3
#define AUTH_HDR(status_code) \
(((status_code) == SIP_CLI_ERR_UNAUTH) ? \
(SIP_HEADER_WWW_AUTHENTICATE) : (SIP_HEADER_PROXY_AUTHENTICATE))
#define AUTH_HDR_STR(status_code) \
(((status_code) == SIP_CLI_ERR_UNAUTH) ? \
("WWW-Authenticate") : ("Proxy-Authenticate"))
#define AUTH_BUGINF(status_code) \
(((status_code) == SIP_CLI_ERR_UNAUTH) ? \
("SIP 401 Unauthorized") : ("SIP 407 Proxy Authentication required"))
#define AUTH_NOTIFY(status_code) \
(((status_code) == SIP_CLI_ERR_UNAUTH) ? \
(" 401 <---") : (" 407 <---"))
#define AUTHOR_HDR(status_code) \
(((status_code) == SIP_CLI_ERR_UNAUTH) ? \
(SIP_HEADER_AUTHORIZATION) : (SIP_HEADER_PROXY_AUTHORIZATION))
/*
These numbers need to match up
with whats defined on the J-Side
The Master copy should be here because
the reason needs to be sent out in the register
message
*/
#define UNREG_REASON_UNSPECIFIED 0
//Common with what SCCP uses...need to match with J-Side
//Important! should be defined in plat_api.h for thirdparty application to use.
#define UNREG_REASON_TCP_TIMEOUT CC_UNREG_REASON_TCP_TIMEOUT // 10
#define UNREG_REASON_CM_RESET_TCP CC_UNREG_REASON_CM_RESET_TCP //12
#define UNREG_REASON_CM_ABORTED_TCP CC_UNREG_REASON_CM_ABORTED_TCP //13
#define UNREG_REASON_CM_CLOSED_TCP CC_UNREG_REASON_CM_CLOSED_TCP //14
#define UNREG_REASON_REG_TIMEOUT CC_UNREG_REASON_REG_TIMEOUT //17
#define UNREG_REASON_FALLBACK CC_UNREG_REASON_FALLBACK //18
#define UNREG_REASON_PHONE_KEYPAD CC_UNREG_REASON_PHONE_KEYPAD //20
#define UNREG_REASON_RESET_RESET CC_UNREG_REASON_RESET_RESET //22
#define UNREG_REASON_RESET_RESTART CC_UNREG_REASON_RESET_RESTART //23
#define UNREG_REASON_PHONE_REG_REJ CC_UNREG_REASON_PHONE_REG_REJ //24
#define UNREG_REASON_PHONE_INITIALIZED CC_UNREG_REASON_PHONE_INITIALIZED //25
#define UNREG_REASON_VOICE_VLAN_CHANGED CC_UNREG_REASON_VOICE_VLAN_CHANGED //26
//sip specific ones...need to match with J-Side
#define UNREG_REASON_VERSION_STAMP_MISMATCH CC_UNREG_REASON_VERSION_STAMP_MISMATCH //100
#define UNREG_REASON_VERSION_STAMP_MISMATCH_CONFIG CC_UNREG_REASON_VERSION_STAMP_MISMATCH_CONFIG //101
#define UNREG_REASON_VERSION_STAMP_MISMATCH_SOFTKEY CC_UNREG_REASON_VERSION_STAMP_MISMATCH_SOFTKEY //102
#define UNREG_REASON_VERSION_STAMP_MISMATCH_DIALPLAN CC_UNREG_REASON_VERSION_STAMP_MISMATCH_DIALPLAN //103
#define UNREG_REASON_APPLY_CONFIG_RESTART CC_UNREG_REASON_APPLY_CONFIG_RESTART //104
#define UNREG_REASON_CONFIG_RETRY_RESTART CC_UNREG_REASON_CONFIG_RETRY_RESTART //105
#define UNREG_REASON_TLS_ERROR CC_UNREG_REASON_TLS_ERROR //106
#define UNREG_REASON_RESET_TO_INACTIVE_PARTITION CC_UNREG_REASON_RESET_TO_INACTIVE_PARTITION //107
#define UNREG_REASON_VPN_CONNECTIVITY_LOST CC_UNREG_REASON_VPN_CONNECTIVITY_LOST //108
#define PRIMARY_LINE (1)
typedef enum {
SIP_REG_ERROR,
SIP_REG_OK
} sip_reg_return_code;
typedef enum
{
SIP_REG_INVALID=-1,
SIP_REG_IDLE,
SIP_REG_REGISTERING,
SIP_REG_REGISTERED,
SIP_REG_UNREGISTERING,
SIP_REG_PRE_FALLBACK,
SIP_REG_IN_FAILOVER,
SIP_REG_POST_FAILOVER,
SIP_REG_STANDBY_FAILOVER,
SIP_REG_NO_CC,
SIP_REG_NO_STANDBY,
SIP_REG_NO_REGISTER
} ccsip_register_states_t;
typedef enum
{
E_SIP_REG_NONE = 0,
SIPSPI_REG_EV_BASE = 1,
E_SIP_REG_REG_REQ = SIPSPI_REG_EV_BASE,
E_SIP_REG_CANCEL,
E_SIP_REG_1xx,
E_SIP_REG_2xx,
E_SIP_REG_3xx,
E_SIP_REG_4xx,
E_SIP_REG_FAILURE_RESPONSE,
E_SIP_REG_TMR_ACK,
E_SIP_REG_TMR_EXPIRE,
E_SIP_REG_TMR_WAIT,
E_SIP_REG_TMR_RETRY,
E_SIP_REG_CLEANUP,
SIPSPI_REG_EV_END = E_SIP_REG_CLEANUP
} sipRegSMEventType_t;
typedef struct
{
int line;
boolean cancel;
} ccsip_register_msg_t;
int sip_reg_sm_process_event(sipSMEvent_t *pEvent);
sipRegSMEventType_t ccsip_register_sip2sipreg_event(int sip_event);
int ccsip_register_init(void);
void ccsip_register_timeout_retry(void *data);
void ccsip_register_all_lines(void);
void ccsip_register_cancel(boolean cancel_reg, boolean backup_proxy);
void ccsip_ccm_register_cancel(boolean cancel_reg);
void ccsip_register_set_state(ccsip_register_states_t state);
ccsip_register_states_t ccsip_register_get_state(void);
ccsip_register_states_t ccsip_register_get_register_state(void);
void ccsip_register_reset_proxy(void);
void cred_get_line_credentials(line_t line, credentials_t *pcredentials,
int id_len, int pw_len);
boolean cred_get_user_credentials(line_t line, credentials_t *pcredentials);
boolean cred_get_credentials_r(ccsipCCB_t *ccb, credentials_t *pcredentials);
void ccsip_register_commit(void);
void ccsip_backup_register_commit(void);
void ccsip_register_cleanup(ccsipCCB_t *ccb, boolean start);
void ccsip_register_set_register_state(ccsip_register_states_t state);
int ccsip_register_send_msg(uint32_t cmd, line_t line);
void ccsip_handle_ev_default(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_reg_sm_change_state(ccsipCCB_t *ccb, sipRegSMStateType_t new_state);
boolean ccsip_register_all_unregistered();
void sip_stop_ack_timer(ccsipCCB_t *ccb);
void ccsip_register_shutdown(void);
boolean ccsip_get_ccm_date(char *date_value);
boolean ccsip_is_line_registered(line_t line);
boolean process_retry_after(ccsipCCB_t *ccb, sipMessage_t *response);
#endif
+63
View File
@@ -0,0 +1,63 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_RELDEV_H_
#define _CCSIP_RELDEV_H_
#include "cpr_types.h"
#include "ccsip_pmh.h"
#include "ccsip_core.h"
#define RELDEV_MAX_USER_NAME_LEN 64
#define RELDEV_MAX_HOST_NAME_LEN 64
#define RELDEV_NO_STORED_MSG (-1)
typedef struct
{
char message_buf[SIP_UDP_MESSAGE_SIZE];
uint32_t message_buf_len;
cpr_ip_addr_t dest_ipaddr;
uint16_t dest_port;
} sipRelDevCoupledMessage_t;
typedef struct
{
boolean is_request;
char call_id[MAX_SIP_CALL_ID];
uint32_t cseq_number;
sipMethod_t cseq_method;
char tag[MAX_SIP_TAG_LENGTH];
char from_user[RELDEV_MAX_USER_NAME_LEN];
char from_host[RELDEV_MAX_HOST_NAME_LEN];
char to_user[RELDEV_MAX_USER_NAME_LEN];
int response_code;
sipRelDevCoupledMessage_t coupled_message;
boolean valid_coupled_message;
//int line;
} sipRelDevMessageRecord_t;
void sipRelDevMessageStore(sipRelDevMessageRecord_t *pMessageRecord);
boolean sipRelDevMessageIsDuplicate(sipRelDevMessageRecord_t *pMessageRecord,
int *index);
int sipRelDevCoupledMessageStore(sipMessage_t *pCoupledMessage,
const char *call_id,
uint32_t cseq_number,
sipMethod_t cseq_method,
boolean is_request,
int status_code,
cpr_ip_addr_t *dest_ipaddr,
uint16_t dest_port,
boolean ignore_tag);
int sipRelDevCoupledMessageSend(int index);
void sipRelDevMessagesClear(const char *call_id,
const char *from_user,
const char *from_host,
const char *to_user);
void sipRelDevAllMessagesClear();
uint32_t sipRelDevGetStoredCoupledMessage(int index,
char *dest_buffer,
uint32_t max_buff);
#endif
+159
View File
@@ -0,0 +1,159 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_SDP_H_
#define _CCSIP_SDP_H_
#include "cpr_types.h"
#include "pmhutils.h"
#include "sdp.h"
#include "ccapi.h"
/* SDP bitmask values */
#define CCSIP_SRC_SDP_BIT 0x1
#define CCSIP_DEST_SDP_BIT 0x2
/*
* Create a description or a SIP SDP (sip_info) with
* appropriate values initialized
*/
PMH_EXTERN boolean sip_sdp_init(void);
PMH_EXTERN sdp_t *sipsdp_create(const char *peerconnection);
PMH_EXTERN cc_sdp_t *sipsdp_info_create(void);
PMH_EXTERN void sipsdp_src_dest_free(uint16_t flags, cc_sdp_t **sdp_info);
PMH_EXTERN void sipsdp_src_dest_create(const char *peerconnection,
uint16_t flags, cc_sdp_t **sdp_info);
PMH_EXTERN void sipsdp_free(cc_sdp_t **sip_sdp);
/*
* Stream related sdp utility functions
*/
//PMH_EXTERN sip_sdp_stream_t *sipsdp_stream_create(void);
//PMH_EXTERN void sipsdp_add_stream_to_list(sip_sdp_stream_t *stream,
// sip_sdp_t *sip_sdp);
//PMH_EXTERN void sipsdp_remove_stream_from_list(sip_sdp_stream_t **stream);
//PMH_EXTERN void sipsdp_remove_streams_list(sip_sdp_stream_t **stream_list);
#define SIPSDP_MAX_SESSION_VERSION_LENGTH 32
/*
* Standard session-level parameters
*/
#define SIPSDP_VERSION 0
// RAMC_DEBUG #define SIPSDP_ORIGIN_USERNAME "CiscoSystemsSIP-GW-UserAgent"
#define SIPSDP_ORIGIN_USERNAME "Mozilla-SIPUA"
#define SIPSDP_SESSION_NAME "SIP Call"
/* Possible encoding names fo static payload types*/
#define SIPSDP_ATTR_ENCNAME_PCMU "PCMU"
#define SIPSDP_ATTR_ENCNAME_PCMA "PCMA"
#define SIPSDP_ATTR_ENCNAME_G729 "G729"
#define SIPSDP_ATTR_ENCNAME_G723 "G723"
#define SIPSDP_ATTR_ENCNAME_G726 "G726-32"
#define SIPSDP_ATTR_ENCNAME_G728 "G728"
#define SIPSDP_ATTR_ENCNAME_GSM "GSM"
#define SIPSDP_ATTR_ENCNAME_CN "CN"
#define SIPSDP_ATTR_ENCNAME_G722 "G722"
#define SIPSDP_ATTR_ENCNAME_ILBC "iLBC"
#define SIPSDP_ATTR_ENCNAME_H263v2 "H263-1998"
#define SIPSDP_ATTR_ENCNAME_H264 "H264"
#define SIPSDP_ATTR_ENCNAME_VP8 "VP8"
#define SIPSDP_ATTR_ENCNAME_L16_256K "L16"
#define SIPSDP_ATTR_ENCNAME_ISAC "ISAC"
#define SIPSDP_ATTR_ENCNAME_OPUS "opus"
/* Possible encoding names for DTMF tones dynamic payload types */
#define SIPSDP_ATTR_ENCNAME_TEL_EVENT "telephone-event"
#define SIPSDP_ATTR_ENCNAME_FRF_DIGIT "frf-dialed-digit"
/* Possible encoding names for other dynamic payload types */
#define SIPSDP_ATTR_ENCNAME_CLEAR_CH "X-CCD"
#define SIPSDP_ATTR_ENCNAME_G726R16 "G726-16"
#define SIPSDP_ATTR_ENCNAME_G726R24 "G726-24"
#define SIPSDP_ATTR_ENCNAME_GSMEFR "GSM-EFR"
/* RTPMAP encoding names added from MGCP for compatibility with MGCP
* These could be coming in from Cisco MGCP gateway's SDP via a
* softswitch and SIP GW must interoperate.
*/
#define SIPSDP_ATTR_ENCNAME_G729_A_STR_DOTTED "G.729a"
#define SIPSDP_ATTR_ENCNAME_G729_B_STR_DOTTED "G.729b"
#define SIPSDP_ATTR_ENCNAME_G729_B_LOW_COMPLEXITY_STR_DOTTED "G.729b-L"
#define SIPSDP_ATTR_ENCNAME_G729_A_B_STR_DOTTED "G.729ab"
#define SIPSDP_ATTR_ENCNAME_G7231_HIGH_RATE_STR_DOTTED "G.723.1-H"
#define SIPSDP_ATTR_ENCNAME_G7231_A_HIGH_RATE_STR_DOTTED "G.723.1a-H"
#define SIPSDP_ATTR_ENCNAME_G7231_LOW_RATE_STR_DOTTED "G.723.1-L"
#define SIPSDP_ATTR_ENCNAME_G7231_A_LOW_RATE_STR_DOTTED "G.723.1a-L"
/*
* NSE/XNSE encoding names
*/
#define SIPSDP_ATTR_ENCNAME_XNSE "X-NSE"
#define SIPSDP_ATTR_ENCNAME_NSE "NSE"
/* Possible clock rates */
#define RTPMAP_CLOCKRATE 8000
#define RTPMAP_VIDEO_CLOCKRATE 90000
#define RTPMAP_L16_CLOCKRATE 16000
#define RTPMAP_ISAC_CLOCKRATE 16000
#define RTPMAP_OPUS_CLOCKRATE 48000
#define FMTP_MAX_AVERAGE_BIT_RATE 40000
#define ATTR_PTIME 20
#define ATTR_MAXPTIME 120
#define WEBRTC_DATA_CHANNEL_PROT "webrtc-datachannel"
#define SIPSDP_CONTENT_TYPE "application/sdp"
#define MAX_RTP_PAYLOAD_TYPES 7
#define BITRATE_5300_BPS 5300
#define BITRATE_6300_BPS 6300
/*
* T.38 attribute parameters
*/
#define SIPSDP_ATTR_T38_VERSION_DEF 0
#define SIPSDP_ATTR_T38_FILL_BIT_REMOVAL_DEF FALSE
#define SIPSDP_ATTR_T38_TRANSCODING_MMR_DEF FALSE
#define SIPSDP_ATTR_T38_TRANSCODING_JBIG_DEF FALSE
/* the following two definitions are from VSIToH245BuildFastStartT38OLC() */
#define SIPSDP_ATTR_T38_MAX_BUFFER_DEF 200
#define SIPSDP_ATTR_T38_MAX_DATAGRAM_DEF 72
/*
* Supported NTE range. Note that if the supported NTEs ever becomes a
* non-contiguous set of values, then it will have to be stored as an
* sdp. See the definition of negotiated_nte_sdp for an example. Further,
* where Sdp_ne_cmp_range() is invoked, Sdp_ne_cmp_list() will have to be
* used instead.
*/
#define SIPSDP_NTE_SUPPORTED_LOW 0 /* Min value of DTMF event table */
#define SIPSDP_FRF_SUPPORTED_HIGH 15 /* for dtmf-relay cisco-rtp */
#define SIPSDP_NTE_SUPPORTED_HIGH 16 /* for dtmf-relay rtp-nse */
/*
* Create the "on-wire" version, i.e. ready to put into a SIP message.
* Memory is allocated and should be freed by the user when done
* Returns NULL on failure.
*/
PMH_EXTERN char *sipsdp_write_to_buf(cc_sdp_t *, uint32_t *);
#define SIPSDP_FREE(x) \
if (x) \
{ \
sdp_free_description(x); \
}
#define SIPSDP_MAX_PAYLOAD_TYPES 15
#define MAX_RTP_MEDIA_TYPES 6
#define SIPSDP_NTE_DTMF_MIN 0 /* Min value of DTMF event table */
#define SIPSDP_NTE_DTMF_MAX 15 /* Max DTMF event value supported here */
#endif /*_CCSIP_SDP_H_*/
+14
View File
@@ -0,0 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_SIM_H_
#define _CCSIP_SIM_H_
void SIPTaskTestUdpSend(void);
void SIPTaskSimulateInviteRecv(void);
void SIPTaskSimulateOffhook(void);
void SIPTaskSimulateAckRecv(void);
#endif
+22
View File
@@ -0,0 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_UTILS_H_
#define _CCSIP_UTILS_H_
#include "cpr_types.h"
#include "ccsip_pmh.h"
boolean
sipSPI_validate_hostname(char *);
boolean
sipSPI_validate_ip_addr_name(char *);
extern int
sipSPICheckDomainToken(char *token);
boolean
sipSPI_validate_hostname (char *str);
#endif
@@ -0,0 +1,433 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_SUBSMANAGER_H_
#define _CCSIP_SUBSMANAGER_H_
#include "cpr_types.h"
#include "cpr_ipc.h"
#include "cpr_timers.h"
#include "cpr_socket.h"
#include "ccsip_core.h"
#include "phone_platform_constants.h"
#include "singly_link_list.h"
#include "ccsip_common_cb.h"
/*
* States
*/
typedef enum {
SUBS_STATE_IDLE = 0, // Initial state of the SCB
SUBS_STATE_REGISTERED,
/* out going subscribe SCB states */
SUBS_STATE_SENT_SUBSCRIBE, // Sent SUBSCRIBE
SUBS_STATE_RCVD_NOTIFY, // Received NOTIFY
SUBS_STATE_SENT_SUBSCRIBE_RCVD_NOTIFY, // Sent SUBSCRIBE & Received NOTIFY
/* incoming subscribe SCB states */
SUBS_STATE_RCVD_SUBSCRIBE, // Received SUBSCRIBE
SUBS_STATE_SENT_NOTIFY, // Sent NOTIFY
SUBS_STATE_RCVD_SUBSCRIBE_SENT_NOTIFY, // Received SUBSCRIBE & Sent NOTIFY
/*
* No outstanding outgoing/incoming messages to handle.
* This state is after all outstanding SUBSCRIBE/NOTIFY
* transactions are complete.
*/
SUBS_STATE_ACTIVE,
SUBS_STATE_INVALID
} subsStateType_t;
typedef enum {
SUBSCRIPTION_NULL = 0,
SUBSCRIPTION_TERMINATE
} subscriptionState;
/*
* Subscription ID data type
*/
typedef uint32_t sub_id_t;
#define MAX_EVENT_NAME_LEN 32
#define CCSIP_SUBS_START_CSEQ 1000
/* There may be multiple subscription pending on given call
* the subcription for KPML, remote-cc, offhook notification etc.
*/
#define MAX_SCBS ((MAX_TEL_LINES * 2) < 32 ? 32 : (MAX_TEL_LINES * 2))
#define LIMIT_SCBS_USAGE (MAX_SCBS - ((MAX_SCBS * 20) / 100))
#define TMR_PERIODIC_SUBNOT_INTERVAL 5
#define CCSIP_SUBS_INVALID_SUB_ID (sub_id_t)(-1)
#define MAX_SCB_HISTORY 10
typedef enum {
SM_REASON_CODE_NORMAL = 0,
SM_REASON_CODE_ERROR,
SM_REASON_CODE_SHUTDOWN,
SM_REASON_CODE_ROLLOVER,
SM_REASON_CODE_RESET_REG
} ccsip_reason_code_e;
// Application defined callback functions
// Data to app to indicate response to a sent SUBSCRIBE
typedef struct {
int status_code;
long expires;
} ccsip_subs_result_data_t;
// Data to app to indicate a received SUBSCRIBE
typedef struct {
ccsip_event_data_t *eventData;
int expires;
int line;
string_t from;
string_t to;
} ccsip_subs_ind_data_t;
// Data to app to indicate a received NOTIFY
typedef struct {
ccsip_event_data_t *eventData;
sip_subs_state_e subscription_state; // From the subs-state header
sip_subs_state_reason_e subscription_state_reason;
uint32_t expires;
uint32_t retry_after;
uint32_t cseq;
char entity[CC_MAX_DIALSTRING_LEN]; // used to store From user for incoming unsolicited NOTIFY.
} ccsip_notify_ind_data_t;
// Data to app to indicate response to a sent NOTIFY
typedef struct {
int status_code;
} ccsip_notify_result_data_t;
// Data to app to indicate incoming subscription terminated
typedef struct {
int status_code;
} ccsip_subs_terminate_data_t;
// Containing structure for all stack->app messages
typedef struct ccsip_sub_not_data_t {
int msg_id;
sub_id_t sub_id;
int sub_duration;
cc_subscriptions_t event;
line_t line_id;
callid_t gsm_id;
boolean norefersub;
long request_id;
ccsip_reason_code_e reason_code;
union {
ccsip_subs_ind_data_t subs_ind_data;
ccsip_subs_result_data_t subs_result_data;
ccsip_notify_ind_data_t notify_ind_data;
ccsip_notify_result_data_t notify_result_data;
ccsip_subs_terminate_data_t subs_term_data;
} u;
} ccsip_sub_not_data_t;
// Function to pass an incoming subscribe request
typedef void (*ccsipSubsIndCallbackFn_t)(ccsip_sub_not_data_t *msg_data);
// Function to pass response to a subscribe request
typedef void (*ccsipSubsResultCallbackFn_t)(ccsip_sub_not_data_t *msg_data);
// Function to pass an incoming Notify request
typedef void (*ccsipNotifyIndCallbackFn_t)(ccsip_sub_not_data_t *msg_data);
// Function to pass results of notify request
typedef void (*ccsipNotifyResultCallbackFn_t)(ccsip_sub_not_data_t *msg_data);
// Function to pass general errors
typedef void (*ccsipSubsTerminateCallbackFn_t)(ccsip_sub_not_data_t *msg_data);
typedef void (*ccsipGenericCallbackFn_t)(ccsip_sub_not_data_t *msg_data);
// Return status code
#define SUBSCRIPTION_IN_PROGRESS 1010
#define SUBSCRIPTION_SUCCEEDED 1020
#define SUBSCRIPTION_REJECTED 1030
#define SUBSCRIPTION_FAILED 1040
#define NOTIFY_REQUEST_FAILED 1050
#define SUBSCRIBE_REQUEST_FAILED 1060
#define SUBSCRIBE_FAILED_NORESOURCE 1061
#define SUBSCRIBE_FAILED_BADEVENT 1062
#define SUBSCRIBE_FAILED_BADINFO 1062
#define NETWORK_SUBSCRIPTION_EXPIRED 1070
#define APPLICATION_SUBSCRIPTION_EXPIRED 1080
#define REQUEST_TIMEOUT 1090
// Data passed by app to register for incoming SUBSCRIBE
typedef struct sipspi_subscribe_reg_t_ {
cc_subscriptions_t eventPackage; // Registering for which event
ccsipSubsIndCallbackFn_t subsIndCallback; // Callback function
cc_srcs_t subsIndCallbackTask; // Callback task
int subsIndCallbackMsgID; // msg_id to use in callback
ccsipSubsTerminateCallbackFn_t subsTermCallback; // Callback function when remote side terminates subs
int subsTermCallbackMsgID; // Terminate msg-id
long min_duration; // Min duration for which SUB should be accepted
long max_duration; // Max duration for which SUB should be accepted
} sipspi_subscribe_reg_t;
// Data passed by app to initiate a SUBSCRIBE
typedef struct sipspi_subscribe_t_ {
sub_id_t sub_id; // ID for reSubscribe
cc_subscriptions_t eventPackage; // Event package to send subscribe for
cc_subscriptions_t acceptPackage; // Accept header
long duration; // subscription duration (0=unsubscribe)
char subscribe_uri[CC_MAX_DIALSTRING_LEN];
char subscriber_uri[CC_MAX_DIALSTRING_LEN]; // From field
long request_id; // Returned to subscriber in response
ccsipSubsResultCallbackFn_t subsResultCallback;
ccsipNotifyIndCallbackFn_t notifyIndCallback;
ccsipSubsTerminateCallbackFn_t subsTermCallback;
cc_srcs_t subsNotCallbackTask;
int subsResCallbackMsgID;
int subsNotIndCallbackMsgID;
int subsTermCallbackMsgID;
cpr_ip_addr_t dest_sip_addr; // Destination address
uint16_t dest_sip_port; // Destination port
callid_t call_id;
line_t dn_line; // Associated line, if any
boolean auto_resubscribe; // stack reSubscribes at expiry
boolean norefersub;
ccsip_event_data_t *eventData; // Determined by the eventPackage value
} sipspi_subscribe_t;
// Data by app to respond to a received SUBSCRIBE
typedef struct sipspi_subscribe_resp_t_ {
sub_id_t sub_id; // Subscription id
uint16_t response_code; // Response that should be sent
int duration; // Max duration for the subscribe
} sipspi_subscribe_resp_t;
// Data by app to initiate a NOTIFY
typedef struct sipspi_notify_t_ {
sub_id_t sub_id; // Subscription id
// Info for different notify bodies
ccsipNotifyResultCallbackFn_t notifyResultCallback;
int subsNotResCallbackMsgID;
ccsip_event_data_t *eventData; // Determined by the eventPackage value
cc_subscriptions_t eventPackage; // Event package
subscriptionState subState;
cc_srcs_t subsNotCallbackTask; // Opt.: If not already specified
} sipspi_notify_t;
// Data by app to respond to a received NOTIFY
typedef struct sipspi_notify_resp_t_ {
sub_id_t sub_id;
int response_code;
int duration;
uint32_t cseq;
} sipspi_notify_resp_t;
// Data by app to terminate an existing subscription
typedef struct sipspi_subscribe_term_t_ {
sub_id_t sub_id;
long request_id;
cc_subscriptions_t eventPackage; // Event package
boolean immediate;
} sipspi_subscribe_term_t;
/*
typedef struct sipspi_remotecc_reg_t_{
} sipspi_remotecc_reg_t;
typedef struct sipspi_remotecc_refer_t_{
} sipspi_remotecc_refer_t;
typedef struct sipspi_remotecc_refer_resp_t_{
} sipspi_remotecc_refer_resp_t;
typedef struct sipspi_remotecc_notify_t_{
} sipspi_remotecc_notify_t;
typedef struct sipspi_remotecc_notify_resp_t_{
} sipspi_remotecc_notify_resp_t;
typedef struct sipspi_remotecc_term_t_{
} sipspi_remotecc_term_t;
*/
typedef struct sipspi_msg_t_ {
union {
sipspi_subscribe_reg_t subs_reg;
sipspi_subscribe_t subscribe;
sipspi_subscribe_resp_t subscribe_resp;
sipspi_notify_t notify;
sipspi_notify_resp_t notify_resp;
sipspi_subscribe_term_t subs_term;
/*
* sipspi_remotecc_reg_t remotecc_reg;
* sipspi_remotecc_refer_t remotecc_refer;
* sipspi_remotecc_refer_resp_t remotecc_refer_resp;
* sipspi_remotecc_notify_t remotecc_notify;
* sipspi_remotecc_notify_resp_t remotecc_notify_resp;
* sipspi_remotecc_term_t remotecc_term;
*/
} msg;
} sipspi_msg_t;
// List of app->stack messages
typedef struct sipspi_msg_list_t_ {
uint32_t cmd;
sipspi_msg_t *msg;
struct sipspi_msg_list_t_ *next;
} sipspi_msg_list_t;
// Subscription Control Block
typedef struct {
ccsip_common_cb_t hb; /* this MUST be the first memeber in the struct */
line_t line;
// Subscription ID
sub_id_t sub_id;
// SCB State
boolean pendingClean;
unsigned char pendingCount;
// Subscriber details
boolean internal; // Internal or external
// Callback and messaging details
ccsipSubsIndCallbackFn_t subsIndCallback;
cc_srcs_t subsIndCallbackTask;
cc_srcs_t subsNotCallbackTask;
int subsIndCallbackMsgID;
ccsipSubsResultCallbackFn_t subsResultCallback;
int subsResCallbackMsgID;
ccsipNotifyIndCallbackFn_t notifyIndCallback;
int notIndCallbackMsgID;
ccsipSubsTerminateCallbackFn_t subsTermCallback;
int subsTermCallbackMsgID;
ccsipNotifyResultCallbackFn_t notifyResultCallback;
int notResCallbackMsgID;
short sip_socket_handle;
boolean useDeviceAddressing;
callid_t gsm_id;
long request_id;
// Subscription details
subsStateType_t smState;
subsStateType_t outstandingIncomingNotifyTrxns; // only used for incoming NOTIFYs
unsigned long min_expires;
unsigned long max_expires;
ccsipCCB_t *ccbp; /* associated CCB, if any */
char event_name[MAX_EVENT_NAME_LEN];
boolean auto_resubscribe; /* Resubscribe automatically */
boolean norefersub;
// Messaging details
uint32_t last_sent_request_cseq;
sipMethod_t last_sent_request_cseq_method;
uint32_t last_recv_request_cseq;
sipMethod_t last_recv_request_cseq_method;
// Saved headers
char SubURI[MAX_SIP_URL_LENGTH];
char SubURIOriginal[MAX_SIP_URL_LENGTH];
char SubscriberURI[MAX_SIP_URL_LENGTH];
string_t sip_from;
string_t sip_to;
string_t sip_to_tag;
string_t sip_from_tag;
string_t sip_contact;
string_t cached_record_route;
sipContact_t *contact_info;
sipRecordRoute_t *record_route_info;
sll_handle_t incoming_trxns; // to store via (branch attribute) to track transactions.
string_t callingNumber;
// Subscription headers
sip_subs_state_e subscription_state;
sip_subs_state_reason_e subscription_state_reason;
uint32_t retry_after;
// Linked list of pending app messages
sipspi_msg_list_t *pendingRequests;
} sipSCB_t;
// Transaction Control Block
typedef struct {
ccsip_common_cb_t hb; /* this MUST be the first memeber in the struct */
char full_ruri[MAX_SIP_URL_LENGTH];
cprTimer_t timer; /* transaction timer */
uint32_t trxn_id;
} sipTCB_t;
// Structure to keep track of recent subscriptions
typedef struct {
char last_call_id[MAX_SIP_CALL_ID];
char last_from_tag[MAX_SIP_TAG_LENGTH];
cc_subscriptions_t eventPackage;
} sipSubsHistory_t;
#define MAX_SUB_EVENTS 5
#define MAX_SUB_EVENT_NAME_LEN 16
extern const char eventNames[MAX_SUB_EVENTS][MAX_SUB_EVENT_NAME_LEN];
/*
* Externally called function headers
*/
// For initializing and shutting down
int sip_subsManager_init();
int sip_subsManager_shut();
// Function to handle subscription requests from applications
int subsmanager_handle_ev_cc_feature_subscribe(sipSMEvent_t *);
int subsmanager_handle_ev_cc_feature_notify(sipSMEvent_t *);
int subsmanager_handle_ev_app_subscribe_register(cprBuffer_t buf);
int subsmanager_handle_ev_app_subscribe(cprBuffer_t buf);
int subsmanager_handle_ev_app_subscribe_response(cprBuffer_t buf);
int subsmanager_handle_ev_app_notify(cprBuffer_t buf);
void subsmanager_handle_ev_app_unsolicited_notify(cprBuffer_t buf, line_t line);
int subsmanager_handle_ev_app_notify_response(cprBuffer_t buf);
int subsmanager_handle_ev_app_subscription_terminated(cprBuffer_t buf);
int subsmanager_handle_retry_timer_expire(int scb_index);
void subsmanager_handle_periodic_timer_expire(void);
int subsmanager_test_start_routine();
// Functions to handle remotecc requests from applications
// int subsmanager_handle_ev_app_remotecc_register();
// int subsmanager_handle_ev_app_remotecc_refer();
// int subsmanager_handle_ev_app_remotecc_refer_response();
// int subsmanager_handle_ev_app_remotecc_notify();
// int subsmanager_handle_ev_app_remotecc_notify_response();
// int subsmanager_handle_ev_app_remotecc_terminated();
// Functions to handle requests from network
int subsmanager_handle_ev_sip_subscribe(sipMessage_t *pSipMessage,
sipMethod_t sipMethod,
boolean in_dialog);
int subsmanager_handle_ev_sip_subscribe_notify(sipMessage_t *pSipMessage);
// Function to handle response from network
int subsmanager_handle_ev_sip_response(sipMessage_t *pSipMessage);
void free_event_data(ccsip_event_data_t *event_data);
int sip_subsManager_rollover(void);
int sip_subsManager_reset_reg(void);
void submanager_update_ccb_addr(ccsipCCB_t *ccb);
boolean add_content(ccsip_event_data_t *eventData, sipMessage_t *request, const char *fname);
void pres_unsolicited_notify_ind(ccsip_sub_not_data_t * msg_data);
sipTCB_t *find_tcb_by_sip_callid(const char *callID_p);
int subsmanager_handle_ev_sip_unsolicited_notify_response(sipMessage_t *pSipMessage, sipTCB_t *tcbp);
void subsmanager_unsolicited_notify_timeout(void *data);
#endif
+89
View File
@@ -0,0 +1,89 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _CCSIP_TASK_H_
#define _CCSIP_TASK_H_
#include "cpr_types.h"
#include "cpr_ipc.h"
#include "cpr_socket.h"
#include "cpr_memory.h"
/*
* List of timers that the SIP task is responsible for.
* CPR will send a msg to the SIP task when these
* timers expire. CPR expects a timer id when the timer
* is created, this enum serves that purpose.
*/
typedef enum {
SIP_ACK_TIMER,
SIP_WAIT_TIMER,
SIP_RETRY_TIMER,
SIP_MSG_TIMER,
SIP_EXPIRES_TIMER,
SIP_REG_TIMEOUT_TIMER,
SIP_REG_EXPIRES_TIMER,
SIP_LOCAL_EXPIRES_TIMER,
SIP_SUPERVISION_TIMER,
SIP_GLARE_AVOIDANCE_TIMER,
SIP_KEEPALIVE_TIMER,
SIP_SUBNOT_TIMER,
SIP_SUBNOT_PERIODIC_TIMER,
SIP_PUBLISH_RETRY_TIMER,
SIP_UNSOLICITED_TRANSACTION_TIMER,
SIP_DIAL_TIMEOUT_TIMER,
SIP_FAIL_OVER_START_TIMER,
SIP_FAIL_OVER_COMPLETE_TIMER,
SIP_FALL_BACK_START_TIMER,
SIP_FALL_BACK_COMPLETE_TIMER,
SIP_UNREGISTRATION_TIMER,
SIP_REGALLFAIL_TIMER,
SIP_NOTIFY_TIMER,
SIP_PASSTHROUGH_TIMER
} sipTimerList_t;
/* Action Values for SIPTaskPostShutdown function */
#define SIP_INTERNAL 0
#define SIP_EXTERNAL 1
#define SIP_STOP 2
#define MAX_SIP_REASON_LENGTH 64
#define UNREG_NO_REASON 0
#define VERSION_STAMP_MISMATCH 1
/*
* The code creating the SIP timers needs to have
* access to the sip_msgq variable since CPR
* needs to know where to send the timer expiration
* message.
*/
extern cprMsgQueue_t sip_msgq;
typedef struct
{
boolean taskInited; // FALSE
cprMsgQueue_t msgQueue;
} sipGlobal_t;
/*
* External Data
*/
extern sipGlobal_t sip;
extern char sipHeaderServer[];
extern char sipHeaderUserAgent[];
extern char sipUnregisterReason[];
/*
* Prototypes
*/
void SIPTaskInit(void);
void SIPTaskProcessListEvent(uint32_t cmd, void *msg, void *pUsr, uint16_t len);
int SIPTaskProcessUDPMessage(cprBuffer_t msg, uint16_t len, cpr_sockaddr_storage from);
int SIPTaskProcessConfigChangeNotify(int32_t notify_type);
cpr_status_e SIPTaskSendMsg(uint32_t cmd, cprBuffer_t msg, uint16_t len, void *usr);
cprBuffer_t SIPTaskGetBuffer(uint16_t size);
void SIPTaskReinitialize(boolean checkConfig);
void SIPTaskPostShutdown(int, int reason, const char *reasonInfo);
#endif
+302
View File
@@ -0,0 +1,302 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _HTTPISH_H_
#define _HTTPISH_H_
#include "cpr_types.h"
#include "pmhdefs.h"
#include "httpish_protocol.h"
#include "pmhutils.h"
#include "util_ios_queue.h"
#define HTTPISH_MIN_STATUS_CODE 100
#define HTTPISH_HEADER_CACHE_SIZE 12
#define HTTPISH_HEADER_NAME_SIZE 256
typedef struct h_header
{
struct h_header *next;
char *header;
} httpish_header;
typedef struct {
char *hdr_start;
char *val_start;
} httpish_cache_t;
#define HTTPISH_MAX_BODY_PARTS 6
typedef struct {
uint8_t msgContentDisp;
boolean msgRequiredHandling;
uint8_t msgContentTypeValue;
char *msgContentType;
char *msgBody;
uint32_t msgLength;
char *msgContentId;
uint8_t msgContentEnc;
} msgBody_t;
typedef struct _httpMsg
{
struct _httpMsg *next;
boolean retain_flag; /* If TRUE, Do not free the msg */
char *mesg_line;
queuetype *headers;
msgBody_t mesg_body[HTTPISH_MAX_BODY_PARTS];
char *raw_body;
int32_t content_length;
uint8_t num_body_parts;
boolean is_complete;
boolean headers_read;
/* Cache the most commonly used headers */
httpish_cache_t hdr_cache[HTTPISH_HEADER_CACHE_SIZE];
/* this is the complete message received/sent at the socket */
char *complete_message;
} httpishMsg_t;
typedef struct
{
char *method;
char *url;
char *version;
} httpishReqLine_t;
typedef struct
{
char *reason_phrase;
uint16_t status_code;
char *version;
} httpishRespLine_t;
typedef enum
{
STATUS_SUCCESS = 0,
STATUS_FAILURE,
STATUS_UNKNOWN,
HSTATUS_SUCCESS = STATUS_SUCCESS,
HSTATUS_FAILURE = STATUS_FAILURE,
HSTATUS_UNKNOWN = STATUS_UNKNOWN
} hStatus_t;
typedef enum
{
codeClassInvalid = 0,
codeClass1xx = 1,
codeClass2xx = 2,
codeClass3xx = 3,
codeClass4xx = 4,
codeClass5xx = 5,
codeClass6xx = 6
} httpishStatusCodeClass_t;
/* Creates a message and initializes its internal members */
PMH_EXTERN httpishMsg_t *httpish_msg_create(void);
/* Frees internal members of the message, such as headers */
PMH_EXTERN void httpish_msg_free(httpishMsg_t *);
/*
* Returns TRUE if the message is a HTTPish Request, FALSE if not.
* Return value will be wrong if the function is called before the
* message is complete(see message_is_complete)
*/
PMH_EXTERN boolean httpish_msg_is_request(httpishMsg_t *, const char *, int);
/*
* A message may be complete or incomplete at a point in time, since
* one message may be formed of multiple network packets. This function
* returns TRUE if the message is in fact complete, FALSE if not
*/
PMH_EXTERN boolean httpish_msg_is_complete(httpishMsg_t *);
/*
* Gets a request line structure out of the message i.e parses the message
* line. Null on failure, incomplete message etc. User should call
* httpish_msg_free_reqline when done to free the allocated memory
* inside the structure.
*/
PMH_EXTERN httpishReqLine_t *httpish_msg_get_reqline(httpishMsg_t *);
/* Frees internal members of the request line structure */
PMH_EXTERN void httpish_msg_free_reqline(httpishReqLine_t *);
/*
* Gets a response line structure out of the message i.e parses the message
* line. Null on failure, incomplete message etc. User should call
* httpish_msg_free_respline when done to free the allocated memory
* inside the structure.
*/
PMH_EXTERN httpishRespLine_t *httpish_msg_get_respline(httpishMsg_t *);
/* Frees internal members of the response line structure */
PMH_EXTERN void httpish_msg_free_respline(httpishRespLine_t *);
/*
* Adds a message line to the message given a request line elements.
* This makes it a Request message
* This routine allocates memory internally, which is freed on
* calling httpish_msg_free()
*/
PMH_EXTERN hStatus_t httpish_msg_add_reqline(httpishMsg_t *,
const char *method,
const char *url,
const char *version);
/*
* Adds a message line to the message given response line elements.
* This makes it a Response message
* This routine allocates memory internally, which is freed on
* calling httpish_msg_free(). Status codes are assumed to be a
* maximum of 6 characters long ie <= 999999
*/
PMH_EXTERN hStatus_t httpish_msg_add_respline(httpishMsg_t *,
const char *version,
uint16_t status_code,
const char *reason_phrase);
/*
* Adds a header with a text value to message.
* hname = name of the header for eg. "Content-Type"
* hval = value of the header for eg. "application/sdp"
* This routine allocates memory internally, which is freed on
* calling httpish_msg_free()
*/
PMH_EXTERN hStatus_t httpish_msg_add_text_header(httpishMsg_t *msg,
const char *hname,
const char *hval);
/*
* Adds a header with a integer value to message.
* hname = name of the header for eg. "Content-Length"
* hval = value of the header for eg. 234
* This routine allocates memory internally, which is freed on
* calling httpish_msg_free()
*/
/* Assumes the int is less than 10 characters*/
PMH_EXTERN hStatus_t httpish_msg_add_int_header(httpishMsg_t *msg,
const char *hname,
int32_t hvalue);
/*
* Removes a header from the message.
* hname = name of the header. eg. hname = "From"
* Memory for that header string is freed.
*/
PMH_EXTERN hStatus_t httpish_msg_remove_header(httpishMsg_t *msg,
const char *hname);
/*
* Returns the value of the header if found, NULL if not.
* hname = name of the header, eg. "Content-Length"
* The pointer should not be freed by the user. (It will be
* freed on freeing the message)
*/
PMH_EXTERN const char *httpish_msg_get_header_val(httpishMsg_t *,
const char *hname,
const char *c_hname);
PMH_EXTERN hStatus_t httpish_msg_get_header_vals(httpishMsg_t *,
const char *hname,
const char *c_hname,
uint16_t *nheaders,
char **header_vals);
PMH_EXTERN const char *httpish_msg_get_cached_header_val(httpishMsg_t *, int);
/*
* Gets an array of pointers to all the headers. The number of
* headers is returned in num_headers.
* If invoked such :
* all_the_headers = httpish_msg_get_all_headers(...),
* memory is allocated only for "all_the_headers" array, not for
* its individual elements. Hence only the pointer to the all_the_headers
* array should be freed.
*/
PMH_EXTERN char **httpish_msg_get_all_headers(httpishMsg_t *msg, uint32_t *num_headers);
PMH_EXTERN uint32_t httpish_msg_get_num_headers(httpishMsg_t *msg);
PMH_EXTERN uint16_t httpish_msg_get_num_particular_headers(httpishMsg_t *msg,
const char *hname,
const char *c_hname,
char *header_val[],
uint16_t max_headers);
/*
* Utility function to get value of the Content-Length header. Returns -1
* if the header is not present.
*/
PMH_EXTERN int32_t httpish_msg_get_content_length(httpishMsg_t *);
/*
* Adds the content body to the message. Results in the addition of the
* Content-Length header as well.
*/
PMH_EXTERN hStatus_t httpish_msg_add_body(httpishMsg_t *msg,
char *body,
uint32_t nbytes,
const char *content_type,
uint8_t msg_disposition,
boolean required,
char *content_id);
PMH_EXTERN boolean httpish_msg_header_present(httpishMsg_t *,
const char *hname);
/*
* Allocates a buffer and writes the message into it in the network
* format i.e ready to send. On return, nbytes is filled in with
* the number of bytes contained in the message buffer. Returns
* NULL on failure. User needs to free memory when done.
*/
PMH_EXTERN char *httpish_msg_write_to_buf(httpishMsg_t * msg, uint32_t *nbytes);
/* Writes it out as a null terminated string. Expected use is debug */
PMH_EXTERN char *httpish_msg_write_to_string(httpishMsg_t * msg);
/*
* Writes out a message in the network format(ie ready to send),
* in a user provided buffer. nbytes is filled in with the number
* of bytes in buf on entry and filled in with the
* actual number of bytes written if the return value is SUCCESS.
* There is no attempt to grow or realloc the buffer ie FAILURE
* is returned if the buffer is not large enough.
*/
PMH_EXTERN hStatus_t httpish_msg_write(httpishMsg_t *msg,
char *buf,
uint32_t *nbytes);
/*
* This function is used to read bytes from a network packet into the
* message structure.
* msg = previously created httpishMsg using httpish_msg_create()
* nmsg = network message
* bytes_read = Number of bytes read from nmsg is filled in when the
* function returns.
* It is expected that after this returns HSTATUS_SUCCESS,
* httpish_is_message_complete() is called to see whether a complete
* message was received(or a previously started message was completed,
* at which point it can be processed further.
*/
PMH_EXTERN hStatus_t httpish_msg_process_network_msg(httpishMsg_t *msg,
char *nmsg,
uint32_t *bytes_read);
/*
* Utility to get the class of status codes in http like responses.
* For eg., the class for a code 480 is 4, as currently defined.
*/
PMH_EXTERN httpishStatusCodeClass_t httpish_msg_get_code_class(uint16_t statusCode);
#endif /* _HTTPISH_H_ */
@@ -0,0 +1,32 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _HTTPISH_PROTOCOL_H_
#define _HTTPISH_PROTOCOL_H_
/*
* Some common headers only. There does not seem a whole lot of
* sense in defining error codes since they tend to have different
* semantics
*/
#define HTTPISH_HEADER_CONTENT_LENGTH "Content-Length"
#define HTTPISH_C_HEADER_CONTENT_LENGTH "l"
#define HTTPISH_HEADER_CONTENT_TYPE "Content-Type"
#define HTTPISH_HEADER_CONTENT_ENCODING "Content-Encoding"
#define HTTPISH_HEADER_CONTENT_ID "Content-Id"
#define HTTPISH_HEADER_USER_AGENT "User-Agent"
#define HTTPISH_HEADER_SERVER "Server"
#define HTTPISH_HEADER_DATE "Date"
#define HTTPISH_HEADER_VIA "Via"
#define HTTPISH_HEADER_MAX_FORWARDS "Max-Forwards"
#define HTTPISH_HEADER_EXPIRES "Expires"
#define HTTPISH_HEADER_LOCATION "Location"
#define HTTPISH_HEADER_MIME_VERSION "Mime-Version"
#define uniqueBoundary "uniqueBoundary"
#endif /* _HTTPISH_PROTOCOL_H_ */
+12
View File
@@ -0,0 +1,12 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _PMH_DEFS_H_
#define _PMH_DEFS_H_
#define UTILFREE(x) cpr_free(x)
#define PMH_EXTERN extern
#endif /* _PMH_DEFS_H_ */
+163
View File
@@ -0,0 +1,163 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _PMH_UTILS_H_
#define _PMH_UTILS_H_
#include "cpr_types.h"
#include "pmhdefs.h"
/*
* Define a "stream" created from an input packet. We have to do this
* since SIP * messages may come in over TCP or UDP, so we cannot use
* TCP stream semantics. It is expected that a client interfaces to
* these streams via the API functions defined below, rather than
* directly.
*/
typedef struct
{
char *buff;
char *loc; /* This points to the next byte that will be read */
int32_t nbytes;
int32_t bytes_read;
boolean eof;
boolean error;
} pmhRstream_t;
/*
* Defines a write stream to write things to and finally create an
* "output packet". It is expected that a client interfaces to
* these streams via the API functions defined below, rather than
* directly.
*/
typedef struct
{
char *buff;
int32_t nbytes;
int32_t total_bytes;
boolean growable;
} pmhWstream_t;
typedef struct
{
uint16_t num_tokens;
char **tokens;
} pmhTokens_t;
/*
* Buf is the input buffer holding data that you want to use a "stream".
* The stream uses buf as is, so dont free it. Free it only when done
* ie. by calling pmhutils_rstream_delete. Returns NULL on failure.
* buf = Input buffer containing data.
* nbytes = Number of bytes in buf.
*/
PMH_EXTERN pmhRstream_t *pmhutils_rstream_create(char *buf, uint32_t nbytes);
/*
* Frees internal memory. If freebuf is TRUE, it frees the
* buffer it was created with. If not TRUE, the internal buffer
* should be held by the user and freed when appropriate.
*/
PMH_EXTERN void pmhutils_rstream_delete(pmhRstream_t *rs, boolean freebuf);
/*
* Returns a character from the stream, and advances internal pointer.
* If no characters are left, returns '\0' and sets the eof to TRUE.
*/
PMH_EXTERN char pmhutils_rstream_read_byte(pmhRstream_t *);
/*
* Returns a character buffer from the stream,
* and advances internal pointer.
* If no characters are left, returns NULL and sets the eof to TRUE.
* This routine allocates memory which should be freed by the user.
* nbytes = Number of bytes asked for.
*/
PMH_EXTERN char *pmhutils_rstream_read_bytes(pmhRstream_t *rs, int32_t nbytes);
/*
* Returns a string created from a line(as terminated by \r or \n or \r\n)
* in the stream. This will actually allocate memory for the string,
* which should be freed by the user when done. Empty lines are returned
* as empty strings - ie. first char is \0.
* Updates internal pointer in the stream.
* Returns NULL if eof has been reached on the stream
*/
PMH_EXTERN char *pmhutils_rstream_read_line(pmhRstream_t *);
/* Creates a write stream with an internal buffer of default size */
PMH_EXTERN pmhWstream_t *pmhutils_wstream_create(void);
/* Creates a write stream with a user provided buffer */
PMH_EXTERN pmhWstream_t *pmhutils_wstream_create_with_buf(char *buf,
uint32_t nbytes);
/*
* Grows the write streams internal buffer by a default step.
* Mostly used internally by the write functions
*/
PMH_EXTERN boolean pmhutils_wstream_grow(pmhWstream_t *);
/*
* Frees the internal elements of the write stream,
* including its internal buffer if freebuf is TRUE. If freebuf
* is FALSE, the buffer should be held by the user and freed
* when appropriate.
*/
PMH_EXTERN void pmhutils_wstream_delete(pmhWstream_t *ws, boolean freebuf);
/*
* Writes the input string, followed by a SIP New line
* ie. \r\n
* Returns FALSE on failure.
* Expects a NULL terminated string in "line".
* Returns FALSE on failure(ie no memory etc.)
* May result in creation of memory, which will
* be freed when pmhutils_wstream_free_internal is called.
*/
PMH_EXTERN boolean pmhutils_wstream_write_line(pmhWstream_t *ws, char *line);
/*
* Writes a single character to the output stream.
* Returns FALSE on failure, TRUE on success.
*/
PMH_EXTERN boolean pmhutils_wstream_write_byte(pmhWstream_t *, char);
/*
* Writes a buffer(of length len pointed to by buf) to
* the stream. May result in creation of memory, which will
* be freed when pmhutils_wstream_free_internal is called.
* Returns FALSE on failure(ie no memory etc.)
*/
PMH_EXTERN boolean pmhutils_wstream_write_bytes(pmhWstream_t *ws, char *buf,
uint32_t len);
/*
* Returns the internal buffer, and fills in its length in nbytes.
* This would be used just before wstream_delete(.., FALSE) in order
* to hold the buffer.
*/
PMH_EXTERN char *pmhutils_wstream_getbuf(pmhWstream_t *, uint32_t *nbytes);
PMH_EXTERN uint32_t pmhutils_wstream_get_length(pmhWstream_t *ws);
/*
* A tokenizer like strtok, but creates memory for every token.
* Use only when you have to create the memory anyway.
* Returns NULL if no tokens are found or incase memory allocation
* fails.
*/
PMH_EXTERN pmhTokens_t *pmh_tokenize(const char *str, const char *tokens);
/*
* Util to free all the tokens
*/
PMH_EXTERN void pmh_tokens_free(pmhTokens_t *tokens);
#endif /*_PMH_UTILS_H_*/
+17
View File
@@ -0,0 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _REGMGRAPI_H_
#define _REGMGRAPI_H_
#include "sessionConstants.h"
typedef enum reg_mode_t_ {
REG_MODE_CCM = CC_MODE_CCM,
REG_MODE_NON_CCM = CC_MODE_NONCCM,
} reg_mode_t;
reg_mode_t sip_regmgr_get_cc_mode(line_t line);
#endif /* _REGMGRAPI_H_ */
@@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __SIP_CCM_TRANSPORT_H__
#define __SIP_CCM_TRANSPORT_H__
#include "cpr_types.h"
#include "cpr_socket.h"
#include "phone_types.h"
#define CCM_ID_PRINT(arg) \
(arg == PRIMARY_CCM ? "PRIMARY_CCM" : \
arg == SECONDARY_CCM ? "SECONDARY_CCM" : \
arg == TERTIARY_CCM ? "TERTIARY_CCM" : \
arg == MAX_CCM ? "MAX_CCM" : \
arg == UNUSED_PARAM ? "UNUSED_PARAM" : "Unknown")\
#endif /* __SIP_CCM_TRANSPORT_H__ */
@@ -0,0 +1,157 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __SIP_COMMON_REGMGR_H__
#define __SIP_COMMON_REGMGR_H__
#include "cpr_types.h"
#include "cpr_stdio.h"
#include "cpr_stdlib.h"
#include "cpr_timers.h"
#include "cpr_string.h"
#include "cpr_memory.h"
#include "ccsip_core.h"
#include "singly_link_list.h"
#include "ccsip_platform.h"
#include "sip_common_transport.h"
#define LINE1 0
#define LINE2 1
#define LINE3 2
#define LINE4 3
#define LINE5 4
#define LINE6 5
#define LINE7 6
#define LINE8 7
#define LINE9 8
#define LINE10 9
#define LINE11 10
#define LINE12 11
#define LINE13 12
#define LINE14 13
#define LINE15 14
#define LINE16 15
#define LINE17 16
#define LINE18 17
#define LINE19 18
#define LINE20 19
#define RSP_START 1
#define RSP_COMPLETE 2
#define FAILOVER_RSP 0
#define MAX_FALLBACK_MONITOR_PERIOD 300
#define TLS_CONNECT_TIME 8
#define TOKEN_REFER_TO "<urn:X-cisco-remotecc:token-registration>"
typedef enum {
ACTIVE_FD = 0,
STANDBY_FD,
MAX_FALLBACK_FDs
} CC_FDs;
typedef enum {
RET_SUCCESS = 0,
RET_NO_STANDBY,
RET_START_FALLBACK,
RET_INIT_REBOOT
} RET_CODE;
typedef struct fallback_ccb_t_ {
ccsipCCB_t *ccb;
sipPlatformUIExpiresTimer_t WaitTimer;
sipPlatformUIExpiresTimer_t RetryTimer;
uint32_t StabilityMsgCount;
boolean tls_socket_waiting;
} fallback_ccb_t;
typedef struct ccm_fd_table_t_ {
ti_config_table_t *active_ccm_entry;
ti_config_table_t *standby_ccm_entry;
} ccm_act_stdby_table_t;
//ccm_act_stdby_table_t CCM_Active_Standby_Table[MAX_TEL_LINES+1];
typedef struct ccm_failover_table_t_ {
ti_config_table_t *failover_ccm_entry;
ti_config_table_t *fallback_ccm_entry;
boolean prime_registered;
boolean failover_started;
} ccm_failover_table_t;
typedef struct ccm_fallback_table_t_ {
ti_config_table_t *fallback_ccm_entry;
boolean is_idle;
boolean is_resp;
ccsipCCB_t *ccb;
} ccm_fallback_table_t;
typedef struct {
uint32_t ccb_index; /* ccb index for which this msg is intended for */
CCM_ID ccm_id; /* cucm id */
} ccsip_registration_msg_t;
void notify_register_update(int availableLine);
fallback_ccb_t *sip_regmgr_get_fallback_ccb_by_index(line_t index);
int sip_regmgr_destroy_cc_conns(void);
int sip_regmgr_init(void);
void sip_regmgr_register_lines(boolean prime_only, boolean skip_prime);
void sipRegmgrSendRegisterMsg(uint8_t line, ccsipCCB_t *ccb);
void sip_regmgr_ev_cancel(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_in_fallback_any_response(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_failure_response(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_tmr_ack_retry(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_tmr_expire_standby(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_unreg_tmr_ack(ccsipCCB_t *cb);
void sip_regmgr_trigger_fallback_monitor(void);
void sip_regmgr_setup_new_standby_ccb(CCM_ID ccm_id);
void sip_regmgr_free_fallback_ccb(ccsipCCB_t *ccb);
void sip_regmgr_retry_timeout_expire(void *data);
void sip_regmgr_stability_timeout_expire(void *data);
void sip_regmgr_find_fallback_ccb_by_callid(const char *callid,
ccsipCCB_t **ccb_ret);
boolean sip_regmgr_find_fallback_ccb_by_addr_port(cpr_ip_addr_t *ipaddr,
uint16_t port,
ccsipCCB_t **ccb_ret);
sll_match_e sip_regmgr_fallback_ccb_find(void *find_by_p, void *data_p);
void sip_regmgr_retry_timer_start(fallback_ccb_t *fallback_ccb);
ti_config_table_t *sip_regmgr_ccm_get_conn(line_t dn,
ti_config_table_t *ccm_entry);
void sip_regmgr_check_and_transition(ccsipCCB_t *ccb);
void sip_regmgr_ev_default(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_fallback_retry(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_wait_timeout_expire(void *data);
void sip_regmgr_ev_in_fallback_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_stability_check_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_stability_check_tmr_stable(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void sip_regmgr_ev_stability_check_tmr_wait(ccsipCCB_t *ccb,
sipSMEvent_t *event);
void sip_regmgr_ev_token_wait_2xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_cleanup(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_token_wait_4xx_n_5xx(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_ev_token_wait_tmr_wait(ccsipCCB_t *ccb, sipSMEvent_t *event);
void sip_regmgr_shutdown(void);
void sip_regmgr_rsp(int rsp_id, int rsp_type, boolean waited);
boolean sip_regmgr_check_config_change(void);
void sip_regmgr_process_config_change(void);
void sip_regmgr_send_refer(ccsipCCB_t *ccb);
void sip_regmgr_ccm_restarted(ccsipCCB_t *new_reg_ccb);
void sip_regmgr_notify_timer_callback(void *data);
ccsipCCB_t *sip_regmgr_get_fallback_ccb_list(uint32_t *previous_data_p);
void sip_regmgr_replace_standby(ccsipCCB_t *ccb);
void sip_regmgr_regallfail_timer_callback(void *data);
void sip_regmgr_handle_reg_all_fail(void);
void sip_regmgr_get_config_addr(int ccm_id, char *add_str);
extern boolean g_disable_mass_reg_debug_print;
void regmgr_handle_register_update(line_t last_available_line);
#endif /* __SIP_COMMON_REGMGR_H__ */
@@ -0,0 +1,223 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __SIP_COMMON_TRANSPORT_H__
#define __SIP_COMMON_TRANSPORT_H__
#include "cpr_types.h"
#include "cpr_socket.h"
#include "ccsip_pmh.h"
#include "sip_csps_transport.h"
#include "sip_ccm_transport.h"
#include "singly_link_list.h"
#define MAX_CONNECTIONS 5
/* Macro definition for chacking a valid connid (TCP/UDP) */
#define VALID_CONNID(connid) \
(connid >= 0 && connid < MAX_CONNECTIONS)
typedef enum {
NONE_CC = 0,
ACTIVE_CC = 1,
STANDBY_CC
} CC_POSITION;
/*
* Define the types of connections
*/
/*
* NOTE: Need to match the values in the config matrix
*/
typedef enum {
CONN_NONE = 0,
CONN_TCP,
CONN_UDP,
CONN_TLS,
CONN_TCP_TMP,
CONN_MAX_TYPES
} CONN_TYPE;
// Device Security Modes
typedef enum sec_level_t_ {
NON_SECURE = 0, // Normal, no security
AUTHENTICATED, // Use TLS, server will use NULL encryption
ENCRYPTED, // Use TLS, server will use AES encryption
NOT_IN_CTL // Not in CTL should not be seen by SIP.
} sec_level_t;
typedef enum conn_create_status_t_ {
CONN_INVALID = -1,
CONN_SUCCESS,
CONN_FAILURE
} conn_create_status_t;
typedef struct ti_common_t_ {
uint16_t listen_port;
char addr_str[MAX_IPADDR_STR_LEN];
cpr_ip_addr_t addr;
uint16_t port;
uint16_t sec_port;
CONN_TYPE conn_type;
CONN_TYPE configured_conn_type;
cpr_socket_t handle;
} ti_common_t;
typedef struct ti_ccm_t_ {
CCM_ID ccm_id;
int32_t sec_level;
int32_t is_valid;
} ti_ccm_t;
typedef struct ti_csps_t_ {
char bkup_pxy_addr_str[MAX_IPADDR_STR_LEN];
cpr_ip_addr_t bkup_pxy_addr;
uint16_t bkup_pxy_port;
char emer_pxy_addr_str[MAX_IPADDR_STR_LEN];
uint16_t emer_pxy_port;
char outb_pxy_addr_str[MAX_IPADDR_STR_LEN];
uint16_t outb_pxy_port;
} ti_csps_t;
typedef struct ti_config_table_t_ {
CC_ID cc_type;
ti_common_t ti_common;
union {
ti_ccm_t ti_ccm;
ti_csps_t *ti_csps;
} ti_specific;
} ti_config_table_t;
extern ti_config_table_t *CCM_Config_Table[MAX_REG_LINES + 1][MAX_CCM];
extern ti_config_table_t CCM_Dummy_Entry;
extern ti_config_table_t CSPS_Config_Table[MAX_REG_LINES];
typedef struct cc_config_table_t_ {
CC_ID cc_type;
void *cc_table_entry; // Needs to deferenced as
// ti_config_table_t*
} cc_config_table_t;
typedef long sipSPIConnId_t;
typedef enum {
SOCKET_NO_ERROR = -1,
SOCKET_SEND_ERROR,
SOCKET_RECV_ERROR,
SOCKET_OPEN_ERROR,
SOCKET_OPT_ERROR,
SOCKET_CONNECT_ERROR,
SOCKET_CONN_REFUSED_ERROR,
SOCKET_BIND_ERROR,
SOCKET_REMOTE_CLOSURE,
SOCKET_ADMIN_CLOSURE,
SIP_TCP_CONN_TABLE_FULL
} ccsipSockErrCodes_e;
/* All the possible state of the TCP/UDP sockets */
typedef enum {
SOCK_IDLE, /* not inuse */
SOCK_LISTENING, /* fd is listening on the well-known port */
SOCK_ACCEPTED, /* connection accepted */
SOCK_CONNECTED, /* connection made */
SOCK_CONNECT_PENDING, /* connection is pending */
SOCK_FAILED /* failed, will be closed when all calls fail */
} sock_state_t;
typedef struct {
cpr_ip_addr_t addr;
uint16_t port;
CONN_TYPE transport; /* Specifies UDP, Multicast UDP, TCP */
uint8_t ip_sig_tos;
uint16_t local_listener_port;
} sipSPICreateConnection_t;
typedef struct {
void *context;
sipSPICreateConnection_t createConnMsg;
} sipSPIMessage_t;
void sipTransportSetServerHandleAndPort(cpr_socket_t socket_handle,
uint16_t listen_port,
ti_config_table_t *ccm_table_entry);
int sip_dns_gethostbysrv(char *domain,
cpr_ip_addr_t *ipaddr_ptr,
uint16_t *port,
srv_handle_t *srv_order,
boolean retried_addr);
int sip_dns_gethostbysrvorname(char *hname,
cpr_ip_addr_t *ipaddr_ptr,
uint16_t *port);
conn_create_status_t sip_transport_setup_cc_conn(line_t dn, CCM_ID ccm_id);
int sip_transport_destroy_cc_conn(line_t dn, CCM_ID ccm_id);
int16_t SIPTaskGetProxyPortByDN(line_t dn);
uint32_t SIPTaskGetProxyAddressByDN(line_t dn);
cpr_socket_t SIPTaskGetProxyHandleByDN(line_t dn);
int sipTransportCreateSendMessage(ccsipCCB_t *ccb,
sipMessage_t *pSIPMessage,
sipMethod_t message_type,
cpr_ip_addr_t *cc_remote_ipaddr,
uint16_t cc_remote_port,
boolean isRegister,
boolean reTx,
int timeout, void *scbp,
int reldev_stored_msg);
#define sipTransportChannelCreateSend(a, b, m, c, d, e, f) \
sipTransportCreateSendMessage(a, b, m, c, d, FALSE, TRUE, e, NULL, f)
int sipTransportSendMessage(ccsipCCB_t *ccb,
char *pOutMessageBuf,
uint32_t nbytes,
sipMethod_t message_type,
cpr_ip_addr_t *cc_remote_ipaddr,
uint16_t cc_remote_port,
boolean isRegister,
boolean reTx,
int timeout,
void *scbp);
#define sipTransportChannelSend(a, b, c, m, d, e, f) \
sipTransportSendMessage(a, b, c, m, d, e, FALSE, TRUE, f, NULL)
int sipTransportGetServerAddrPort(char *domain,
cpr_ip_addr_t *ipaddr_ptr,
uint16_t *port,
srv_handle_t *psrv_order,
boolean retried_addr);
int sipTransportGetPrimServerPort(line_t line);
int sipTransportGetBkupServerPort(line_t line);
int sipTransportGetEmerServerPort(line_t line);
int sipTransportGetOutbProxyPort(line_t line);
cpr_ip_type sipTransportGetPrimServerAddress(line_t line, char *buffer);
uint16_t sipTransportGetBkupServerAddress(cpr_ip_addr_t *pip_addr,
line_t line, char *buffer);
void sipTransportGetEmerServerAddress(line_t line, char *buffer);
void sipTransportGetOutbProxyAddress(line_t line, char *buffer);
void sipTransportGetServerIPAddr(cpr_ip_addr_t *pip_addr, line_t line);
int sipTransportInit(void);
uint16_t sipTransportGetServerAddress(cpr_ip_addr_t *pip_addr, line_t dn, line_t index);
short sipTransportGetServerPort(line_t dn, line_t index);
int sipTransportGetCCType(int line, void *cc_table_entry);
void sip_regmgr_set_cc_info(line_t line, line_t dn_line,
CC_ID *cc_type, void *cc_table_entry);
uint16_t sipTransportGetListenPort(line_t line, ccsipCCB_t *ccb);
const char *sipTransportGetTransportType(line_t line, boolean upper_case,
ccsipCCB_t *ccb);
void sipTransportShutdown(void);
extern void ccsip_dump_send_msg_info(char *msg, sipMessage_t *pSIPMessage,
cpr_ip_addr_t *cc_remote_ipaddr,
uint16_t cc_remote_port);
void SIPTaskProcessTCPMessage(sipMessage_t *pSipMessage,
cpr_sockaddr_storage from);
void
sipTransportSetSIPServer();
#endif /* __SIP_COMMON_TRANSPORT_H__ */
@@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __SIP_CSPS_TRANSPORT_H__
#define __SIP_CSPS_TRANSPORT_H__
#include "cpr_types.h"
#include "phone_types.h"
#include "phone_debug.h"
#include "cfgfile_utils.h"
#include "configmgr.h"
#include "ccsip_protocol.h"
#include "ccsip_pmh.h"
#include "ccsip_platform_timers.h"
#include "ccsip_platform_udp.h"
#include "ccsip_messaging.h"
/*
* Defines for Primary, Secondary and Tertiary CC
*/
typedef enum {
PRIMARY_CSPS = 0,
MAX_CSPS
} CSPS_ID;
//extern csps_config_info_t CSPS_Config_Table;
cpr_socket_t sipTransportCSPSGetProxyHandleByDN(line_t dn);
short sipTransportCSPSGetProxyPortByDN(line_t dn);
uint16_t sipTransportCSPSGetProxyAddressByDN(cpr_ip_addr_t *pip_addr,
line_t dn);
uint16_t sip_config_get_proxy_port(line_t line);
uint16_t sip_config_get_backup_proxy_port(void);
void sip_config_get_proxy_addr(line_t line, char *buffer, int buffer_len);
uint16_t sip_config_get_backup_proxy_addr(cpr_ip_addr_t *IPAddress,
char *buffer, int buffer_len);
extern sipPlatformUITimer_t sipPlatformUISMTimers[];
extern ccsipGlobInfo_t gGlobInfo;
extern int dns_error_code; // DNS errror code global
void sipTransportCSPSClearProxyHandle(cpr_ip_addr_t *ipaddr, uint16_t port,
cpr_socket_t this_fd);
#endif /* __SIP_CSPS_TRANSPORT_H__ */
@@ -0,0 +1,64 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _SIP_INTERFACE_REGMGR_H_
#define _SIP_INTERFACE_REGMGR_H_
#include "cpr_types.h"
#include "phone_types.h"
#include "sip_common_transport.h"
#include "regmgrapi.h"
typedef enum reg_rcs_t_ {
REG_RC_SUCCESS,
REG_RC_ERROR,
REG_RC_MAX
} reg_rcs_t;
typedef enum reg_srcs_t_ {
REG_SRC_GSM,
REG_SRC_SIP,
REG_SRC_MAX
} reg_srcs_t;
typedef enum reg_status_t_ {
REG_FAIL,
REG_ALL_FAIL
} reg_status_t;
typedef struct reg_status_msg_t_ {
reg_srcs_t src_id;
reg_status_t msg_id;
} reg_status_msg_t;
typedef enum {
CCM_STATUS_NONE = 0,
CCM_STATUS_STANDBY,
CCM_STATUS_ACTIVE
} reg_ccm_status;
void sip_regmgr_send_status(reg_srcs_t src_id, reg_status_t msg_id);
sec_level_t sip_regmgr_get_sec_level(line_t line);
boolean sip_regmgr_srtp_fallback_enabled(line_t line);
void sip_platform_set_ccm_status();
void sip_platform_cc_mode_notify(void);
void sip_platform_failover_ind(CCM_ID ccm_id);
void sip_platform_fallback_ind(CCM_ID ccm_id);
extern CCM_ID sip_regmgr_get_ccm_id(ccsipCCB_t *ccb);
boolean sip_platform_is_phone_idle(void);
extern void platform_reg_failover_ind(void *to_id);
extern void platform_reg_fallback_ind(void *from_id);
extern void sip_regmgr_phone_idle(boolean waited);
extern void sip_regmgr_fallback_rsp();
extern void sip_regmgr_failover_rsp_start();
extern void sip_regmgr_failover_rsp_complete();
extern void ui_set_ccm_conn_status(const char *addr_str, int status);
extern void platform_cc_mode_notify(int mode);
extern void ui_reg_all_failed(void);
extern void platform_reg_fallback_cfm(void);
extern void platform_regallfail_ind(void *);
extern void sip_platform_logout_reset_req(void);
extern void platform_logout_reset_req (void);
#endif /* _SIP_INTERFACE_REGMGR_H_ */
@@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _SIP_PLATFORM_TASK_H_
#define _SIP_PLATFORM_TASK_H_
#include "cpr_socket.h"
/*
* Prototypes
*/
void sip_platform_task_loop(void *arg);
void sip_platform_task_set_listen_socket(cpr_socket_t s);
void sip_platform_task_set_read_socket(cpr_socket_t s);
void sip_platform_task_clr_read_socket(cpr_socket_t s);
void sip_platform_task_reset_listen_socket(cpr_socket_t s);
#endif
File diff suppressed because it is too large. Load diff
+308
View File
@@ -0,0 +1,308 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_stdlib.h"
#include "cpr_string.h"
#include "pmhutils.h"
#include "phone.h"
#define WSTREAM_START_SIZE 1024
pmhRstream_t *
pmhutils_rstream_create (char *buf, uint32_t nbytes)
{
pmhRstream_t *pmhRstream;
if (!buf || (nbytes == 0)) {
return NULL;
}
pmhRstream = (pmhRstream_t *) cpr_malloc(sizeof(pmhRstream_t));
if (!pmhRstream) {
return NULL;
}
pmhRstream->eof = pmhRstream->error = FALSE;
pmhRstream->buff = pmhRstream->loc = buf;
pmhRstream->nbytes = nbytes;
pmhRstream->bytes_read = 0;
return pmhRstream;
}
void
pmhutils_rstream_delete (pmhRstream_t *pmhRstream, boolean freebuf)
{
if (!pmhRstream) {
return;
}
pmhRstream->error = TRUE;
if (freebuf && pmhRstream->buff) {
cpr_free(pmhRstream->buff);
}
}
char *
pmhutils_rstream_read_bytes (pmhRstream_t *pmhRstream, int32_t nbytes)
{
char *ret;
if (!pmhRstream || !pmhRstream->loc || (pmhRstream->eof == TRUE)) {
return NULL;
}
if (pmhRstream->bytes_read >= pmhRstream->nbytes) {
pmhRstream->eof = TRUE;
return NULL;
}
if ((pmhRstream->nbytes - pmhRstream->bytes_read) < (int32_t) nbytes) {
return NULL;
}
ret = (char *) cpr_malloc((nbytes + 1) * sizeof(char));
if (ret == NULL) {
// Addition of 1 byte (NULL) will save us from strlen errr
return NULL;
}
memcpy(ret, pmhRstream->loc, nbytes);
ret[nbytes] = 0; /* ensure null terminating character */
pmhRstream->bytes_read += nbytes;
pmhRstream->loc += nbytes;
return (ret);
}
#define SANITY_LINE_SIZE PKTBUF_SIZ
unsigned short linesize = 80;
unsigned short incr_size = 32;
char *
pmhutils_rstream_read_line (pmhRstream_t *pmhRstream)
{
char *ret_line;
char *new_loc = NULL;
int offset, bytes_allocated;
boolean line_break;
if (!pmhRstream || !pmhRstream->loc || (pmhRstream->eof == TRUE)) {
return NULL;
}
if (pmhRstream->bytes_read >= pmhRstream->nbytes) {
pmhRstream->eof = TRUE;
return NULL;
}
new_loc = pmhRstream->loc;
ret_line = (char *) cpr_malloc(linesize);
if (ret_line == NULL) {
return NULL;
}
offset = 0;
bytes_allocated = linesize;
/* Search for the first occurrence of a line break */
while (1) {
line_break = FALSE;
if (*new_loc == '\r') {
line_break = TRUE;
new_loc++;
}
if (*new_loc == '\n') {
line_break = TRUE;
new_loc++;
}
if (line_break) {
if (*new_loc != ' ' && *new_loc != '\t') {
break;
}
}
if (offset == (bytes_allocated - 1)) {
char *newbuf;
bytes_allocated += incr_size;
newbuf = (char *) cpr_realloc(ret_line, bytes_allocated);
if (newbuf == NULL) {
if (bytes_allocated != 0) {
cpr_free(ret_line);
}
return NULL;
}
ret_line = newbuf;
}
ret_line[offset++] = *new_loc++;
if (*new_loc == '\0') {
/* We hit the end of buffer before hitting a line break */
pmhRstream->eof = TRUE;
pmhRstream->bytes_read += (new_loc - pmhRstream->loc);
pmhRstream->loc = new_loc;
cpr_free(ret_line);
return NULL;
}
}
pmhRstream->bytes_read += (new_loc - pmhRstream->loc);
/* Update the internal location pointer and bytes read */
if (pmhRstream->bytes_read >= pmhRstream->nbytes) {
pmhRstream->loc = pmhRstream->buff + pmhRstream->nbytes;
pmhRstream->eof = TRUE;
} else {
pmhRstream->loc = pmhRstream->buff + pmhRstream->bytes_read;
}
ret_line[offset] = 0;
return ret_line;
}
pmhWstream_t *
pmhutils_wstream_create_with_buf (char *buf, uint32_t nbytes)
{
pmhWstream_t *pmhWstream = NULL;
if (buf && nbytes && (nbytes > 0)) {
pmhWstream = (pmhWstream_t *) cpr_malloc(sizeof(pmhWstream_t));
if (!pmhWstream) {
return (NULL);
}
pmhWstream->buff = buf;
pmhWstream->nbytes = 0;
pmhWstream->total_bytes = nbytes;
pmhWstream->growable = FALSE;
}
return (pmhWstream);
}
uint32_t
pmhutils_wstream_get_length (pmhWstream_t *ws)
{
if (ws) {
return (ws->nbytes);
} else {
return (0);
}
}
void
pmhutils_wstream_delete (pmhWstream_t *pmhWstream, boolean freebuf)
{
if (pmhWstream && freebuf && pmhWstream->buff) {
cpr_free(pmhWstream->buff);
}
}
boolean
pmhutils_wstream_write_line (pmhWstream_t *pmhWstream, char *this_line)
{
/* Sanity check */
if (this_line == NULL || strlen(this_line) > SANITY_LINE_SIZE) {
return FALSE;
}
if (!(pmhWstream && this_line)) {
return FALSE;
}
while ((pmhWstream->nbytes + (int32_t)strlen(this_line)) >
pmhWstream->total_bytes) {
if (!pmhWstream->growable ||
(FALSE == pmhutils_wstream_grow(pmhWstream))) {
return FALSE;
}
}
memcpy(&pmhWstream->buff[pmhWstream->nbytes], this_line,
strlen(this_line));
pmhWstream->nbytes += strlen(this_line);
if (!pmhutils_wstream_write_byte(pmhWstream, '\r')) {
return FALSE;
}
if (!pmhutils_wstream_write_byte(pmhWstream, '\n')) {
return FALSE;
}
return TRUE;
}
boolean
pmhutils_wstream_write_byte (pmhWstream_t *pmhWstream, char c)
{
if (!pmhWstream) {
return FALSE;
}
if ((pmhWstream->nbytes + 1) > pmhWstream->total_bytes) {
if (!pmhWstream->growable ||
(FALSE == pmhutils_wstream_grow(pmhWstream))) {
return FALSE;
}
}
pmhWstream->buff[pmhWstream->nbytes] = c;
pmhWstream->nbytes++;
return TRUE;
}
boolean
pmhutils_wstream_write_bytes (pmhWstream_t *pmhWstream,
char *inbuf, uint32_t nbytes)
{
if (!pmhWstream) {
return FALSE;
}
while ((pmhWstream->nbytes + (int32_t) nbytes) > pmhWstream->total_bytes) {
if (!pmhWstream->growable ||
(FALSE == pmhutils_wstream_grow(pmhWstream))) {
return FALSE;
}
}
memcpy(&pmhWstream->buff[pmhWstream->nbytes], inbuf, nbytes);
pmhWstream->nbytes += nbytes;
return TRUE;
}
boolean
pmhutils_wstream_grow (pmhWstream_t *pmhWstream)
{
char *newbuf;
if (!pmhWstream || !pmhWstream->buff || !pmhWstream->growable) {
return FALSE;
}
newbuf = (char *) cpr_realloc((void *) pmhWstream->buff,
pmhWstream->total_bytes + WSTREAM_START_SIZE);
if (newbuf == NULL) {
if ((pmhWstream->total_bytes + WSTREAM_START_SIZE) != 0) {
cpr_free(pmhWstream->buff);
}
pmhWstream->buff = NULL;
return FALSE;
}
pmhWstream->buff = newbuf;
pmhWstream->total_bytes += WSTREAM_START_SIZE;
return TRUE;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,206 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_in.h"
#include "cpr_types.h"
#include "phone_types.h"
#include "cpr_string.h"
#include "cpr_socket.h"
#include "ccsip_platform.h"
#include "sip_common_transport.h"
#include "sip_csps_transport.h"
#include "util_string.h"
int
sip_dns_gethostbysrv (char *domain,
cpr_ip_addr_t *ipaddr_ptr,
uint16_t *port,
srv_handle_t *psrv_order,
boolean retried_addr)
{
int bLoopDeath = 0;
uint16_t tmp_port = 0;
int rc=DNS_ERR_NOHOST;
while (!bLoopDeath) {
/* Try and fetch a proxy using DNS SRV records */
rc = dnsGetHostBySRV("sip", "udp", (char *) domain, ipaddr_ptr,
&tmp_port, 100, 1, psrv_order);
switch (rc) {
case DNS_ERR_TTL_EXPIRED:
case DNS_ERR_NOHOST:
/* Re-try if all entries for this proxy have expired
* or the end of the call record list was reached.
*/
break;
default:
/* Run don't walk to the nearest exit */
bLoopDeath = 1;
break;
}
}
if (tmp_port) {
*port = tmp_port;
}
return rc;
}
int
sip_dns_gethostbysrvorname (char *hname,
cpr_ip_addr_t *ipaddr_ptr,
uint16_t *port)
{
/*
* OK according to rfc2543bis-03
* 1. If the destination is an IP address it is used. If no port is
* specified then use 5060
* 2. If the destination specifies the default port (5060) or no port
* then try SRV
* 3. If the destination specifies a port number other than 5060 or
* there are no SRV records A record lookup
*/
srv_handle_t srv_order = NULL;
int rc=DNS_ERR_NOHOST;
if ((*port == SIP_WELL_KNOWN_PORT) || (*port == 0)) {
rc = sip_dns_gethostbysrv(hname, ipaddr_ptr, port, &srv_order, FALSE);
}
if (rc != DNS_OK) {
rc = dnsGetHostByName(hname, ipaddr_ptr, 100, 1);
}
if (srv_order) {
dnsFreeSrvHandle(srv_order);
}
return rc;
}
cpr_socket_t
sipTransportCSPSGetProxyHandleByDN (line_t dn)
{
static const char *fname = "sipTransportCSPSGetProxyHandleByDN";
ti_common_t *ti_common;
if ((((int)dn) < 1) || (((int)dn) > MAX_REG_LINES)) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Args check: DN %d out of "
"bounds.\n", fname, dn);
return INVALID_SOCKET;
}
ti_common = &CSPS_Config_Table[dn - 1].ti_common;
return ((cpr_socket_t) ti_common->handle);
}
short
sipTransportCSPSGetProxyPortByDN (line_t dn)
{
static const char *fname = "sipTransportCSPSGetProxyPortByDN";
ti_common_t *ti_common;
if ((((int)dn) < 1) || (((int)dn) > MAX_REG_LINES)) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Args check: DN %d out of "
"bounds.\n", fname, dn);
return (-1);
}
ti_common = &CSPS_Config_Table[dn - 1].ti_common;
return ((short) ti_common->port);
}
// This function is broken
uint16_t
sipTransportCSPSGetProxyAddressByDN(cpr_ip_addr_t *ip_addr, line_t dn)
{
// static const char *fname = "sipTransportCSPSGetProxyAddressByDN";
// ti_common_t *ti_common;
//
// if ((((int)dn) < 1) || (((int)dn) > MAX_REG_LINES)) {
// CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Args check: DN out of "
// "bounds.\n", fname, dn);
// return (0);
// }
//
// ti_common = &CSPS_Config_Table[dn - 1].ti_common;
//
// ip_addr = &(ti_common->addr);
//
return(1);
}
/*
* sip_config_get_proxy_port()
*
* Get table entry from the table string and option number
*/
uint16_t
sip_config_get_proxy_port (line_t line)
{
uint32_t port;
config_get_line_value(CFGID_PROXY_PORT, &port, sizeof(port), line);
if (port == 0) {
config_get_line_value(CFGID_PROXY_PORT, &port, sizeof(port), DEFAULT_LINE);
}
return ((uint16_t) port);
}
/*
* sip_config_get_proxy_addr()
*
* Get table entry from the table string and option number
*/
void
sip_config_get_proxy_addr (line_t line, char *buffer, int buffer_len)
{
config_get_line_string(CFGID_PROXY_ADDRESS, buffer, line, buffer_len);
if ((strcmp(buffer, UNPROVISIONED) == 0) || (buffer[0] == '\0')) {
config_get_line_string(CFGID_PROXY_ADDRESS, buffer, DEFAULT_LINE,
buffer_len);
}
}
/*
* sip_config_get_backup_proxy_addr()
*
* Get table entry from the table string and option number
*/
uint16_t
sip_config_get_backup_proxy_addr (cpr_ip_addr_t *IPAddress, char *buffer, int buffer_len)
{
*IPAddress = ip_addr_invalid;
config_get_string(CFGID_PROXY_BACKUP, buffer, buffer_len);
if ((cpr_strcasecmp(buffer, UNPROVISIONED) == 0) || (buffer[0] == 0)) {
buffer[0] = 0;
} else {
(void) str2ip(buffer, IPAddress);
}
return (1);
}
/*
* sipTransportCSPSClearProxyHandle
*
* Clear Proxy handle from the table
*/
void
sipTransportCSPSClearProxyHandle (cpr_ip_addr_t *ipaddr,
uint16_t port,
cpr_socket_t this_fd)
{
ti_common_t *ti_common;
int i;
for (i = 0; i < MAX_REG_LINES; i++) {
ti_common = &CSPS_Config_Table[i].ti_common;
if ((ti_common->port == port) &&
util_compare_ip(&(ti_common->addr),ipaddr) &&
(ti_common->handle == this_fd)) {
ti_common->handle = INVALID_SOCKET;
return;
}
}
}
@@ -0,0 +1,313 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_stdio.h"
#include "cpr_string.h"
#include "cpr_memory.h"
#include "ccsip_task.h"
#include "debug.h"
#include "phone_debug.h"
#include "phntask.h"
#include "phone.h"
#include "text_strings.h"
#include "string_lib.h"
#include "gsm.h"
#include "sip_common_transport.h"
#include "sip_common_regmgr.h"
#include "sip_interface_regmgr.h"
#include "ccsip_subsmanager.h"
#include "platform_api.h"
extern ccm_act_stdby_table_t CCM_Active_Standby_Table;
extern cc_config_table_t CC_Config_Table[];
/*
** sip_regmgr_send_status
*
* FILENAME: ip_phone\sip\sip_interface_regmgr.c
*
* PARAMETERS: msg id and the src task id.
*
* DESCRIPTION: Posts the message to the destination task as
* requested.
*
* RETURNS:
*
*/
void
sip_regmgr_send_status (reg_srcs_t src_id, reg_status_t msg_id)
{
static const char fname[] = "sip_regmgr_send_status";
CCSIP_DEBUG_STATE(DEB_F_PREFIX"src_id: %d msg_id: %d", DEB_F_PREFIX_ARGS(SIP_REG, fname), src_id, msg_id);
if (msg_id == REG_ALL_FAIL) {
//All failed ind to platform
ui_reg_all_failed();
CCSIP_DEBUG_REG_STATE(DEB_F_PREFIX"REG ALL FAILED \n", DEB_F_PREFIX_ARGS(SIP_REG, fname));
}
return;
}
/*
** sip_regmgr_get_cc_mode
*
* FILENAME: ip_phone\sip\sip_interface_regmgr.c
*
* PARAMETER: line number for which mode is requested. Initially
* for the ccm it will be same for all linesm, but
* will change when mixed mode support is added.
* DESCRIPTION: returns the current mode the phone is in i.e.
* talking to a ccm -or- not talking to a ccm.
*
* RETURNS:
*
*/
reg_mode_t
sip_regmgr_get_cc_mode (line_t line)
{
if (CCM_Active_Standby_Table.active_ccm_entry) {
return (REG_MODE_CCM);
} else {
return (REG_MODE_NON_CCM);
}
}
boolean
sip_platform_is_phone_idle (void)
{
if (gsm_is_idle()) {
return (TRUE);
}
return (FALSE);
}
/*
** sip_platform_fallback_ind
*
* FILENAME: ip_phone\sip\sip_interface_regmgr.c
*
* PARAMETERS:
*
* DESCRIPTION:
*
*
* RETURNS:
*
*/
void
sip_platform_fallback_ind (CCM_ID ccm_id)
{
static const char fname[] = "sip_platform_fallback_ind";
int from_id = CC_TYPE_CCM;
CCSIP_DEBUG_REG_STATE(DEB_F_PREFIX"ccm-id: %d", DEB_F_PREFIX_ARGS(SIP_FALLBACK, fname), ccm_id);
platform_reg_fallback_ind((void *)(long) from_id);
}
/*
** sip_platform_failover_ind
*
* FILENAME: ip_phone\sip\sip_interface_regmgr.c
*
* PARAMETERS:
*
* DESCRIPTION:
*
* RETURNS: none
*
*/
boolean plat_is_network_interface_changed(void );
void
sip_platform_failover_ind (CCM_ID ccm_id)
{
static const char fname[] = "sip_platform_failover_ind";
int to_id = CC_TYPE_CCM;
CCSIP_DEBUG_REG_STATE(DEB_F_PREFIX"ccm-id=%s=%d", DEB_F_PREFIX_ARGS(SIP_FAILOVER, fname),
ccm_id == PRIMARY_CCM ? "PRIMARY_CCM" :
ccm_id == SECONDARY_CCM ? "SECONDARY_CCM" :
ccm_id == TERTIARY_CCM ? "TERTIARY_CCM" : "Unknown",
ccm_id);
if (plat_is_network_interface_changed()) {
CCSIP_DEBUG_REG_STATE(DEB_F_PREFIX"network i/f changed, sending REG_ALL_FAIL instead", DEB_F_PREFIX_ARGS(SIP_FAILOVER, fname));
ui_reg_all_failed();
return;
}
if (ccm_id == UNUSED_PARAM){
to_id = 3;
}
platform_reg_failover_ind((void *)(long) to_id);
}
/*
** sip_platform_logout_reset_req
*
* FILENAME: ip_phone\sip\sip_platform_logout_reset_req
*
* PARAMETERS: void
*
* DESCRIPTION: Trigger vPhone auto logout and re-DHCP
*
* RETURNS: none
*
*/
void
sip_platform_logout_reset_req(void)
{
platform_logout_reset_req();
}
/*
** sip_platform_set_ccm_status
*
* FILENAME: ip_phone\sip\sip_interface_regmgr.c
*
* PARAMETERS:
*
* DESCRIPTION:
*
* RETURNS: none
*
*/
void
sip_platform_set_ccm_status (void)
{
static const char fname[] = "sip_platform_set_ccm_status";
ti_config_table_t *ccm_table_entry;
char dest_addr_str[MAX_IPADDR_STR_LEN];
CCSIP_DEBUG_STATE(DEB_F_PREFIX"\n", DEB_F_PREFIX_ARGS(SIP_REG, fname));
ccm_table_entry = CCM_Active_Standby_Table.active_ccm_entry;
if (ccm_table_entry) {
sstrncpy(dest_addr_str, ccm_table_entry->ti_common.addr_str,
MAX_IPADDR_STR_LEN);
CCSIP_DEBUG_STATE(DEB_F_PREFIX"addr str1 %s\n", DEB_F_PREFIX_ARGS(SIP_REG, fname), dest_addr_str);
ui_set_ccm_conn_status(dest_addr_str, CCM_STATUS_ACTIVE);
}
ccm_table_entry = CCM_Active_Standby_Table.standby_ccm_entry;
if (ccm_table_entry) {
ui_set_ccm_conn_status(ccm_table_entry->ti_common.addr_str,
CCM_STATUS_STANDBY);
}
}
/*
** sip_regmgr_get_ccm_id
*
* FILENAME: ip_phone\sip\sip_interface_regmgr.c
*
* PARAMETERS: ccb
*
* DESCRIPTION: get ccm id from ccb
*
* RETURNS: ccm id
*/
CCM_ID
sip_regmgr_get_ccm_id (ccsipCCB_t *ccb)
{
ti_config_table_t *ccm_table_ptr = NULL;
ccm_table_ptr = (ti_config_table_t *) ccb->cc_cfg_table_entry;
if (ccm_table_ptr) {
return (ccm_table_ptr->ti_specific.ti_ccm.ccm_id);
}
return (UNUSED_PARAM);
}
/*
** sip_platform_cc_mode_notify
*
* FILENAME: ip_phone\sip\sip_interface_regmgr.c
*
* PARAMETERS: mode
*
* DESCRIPTION: notify cc mode
*
* RETURNS: None
*/
void
sip_platform_cc_mode_notify (void)
{
int mode;
if (CC_Config_Table[0].cc_type == CC_CCM) {
mode = REG_MODE_CCM;
} else {
mode = REG_MODE_NON_CCM;
}
platform_cc_mode_notify(mode);
}
/*
** sip_regmgr_get_sec_level
*
* FILENAME: ip_phone\sip\sip_interface_regmgr.c
*
* PARAMETER: line number for which mode is requested. Initially
* for the ccm it will be same for all linesm, but
* will change when mixed mode support is added.
* DESCRIPTION: returns the current sec level for the phone
* values will be NON-SECURE, AUTHENTICATED and
* ENCRYPTED.
*
* RETURNS: sec level
*
*/
sec_level_t
sip_regmgr_get_sec_level (line_t line)
{
ti_config_table_t *ccm_table_entry;
ti_ccm_t *ti_ccm;
if (CCM_Active_Standby_Table.active_ccm_entry) {
ccm_table_entry = CCM_Active_Standby_Table.active_ccm_entry;
ti_ccm = &ccm_table_entry->ti_specific.ti_ccm;
return ((sec_level_t) ti_ccm->sec_level);
} else {
return (NON_SECURE);
}
}
/*
** sip_regmgr_srtp_fallback_enabled
*
* FILENAME: ip_phone\sip\sip_interface_regmgr.c
*
* PARAMETER: line number for which mode is requested. Initially
* for the ccm it will be same for all linesm, but
* will change when mixed mode support is added.
* DESCRIPTION: returns whether the SRTP fallback is enabled or not.
*
* RETURNS: sec level
*/
boolean
sip_regmgr_srtp_fallback_enabled (line_t line)
{
ccsipCCB_t *ccb;
line_t ndx;
if ((line == 0) || (line > MAX_REG_LINES)) {
/* Invalid Line, requested */
return 0;
}
/* Map the (dn)line number to registered CCB */
ndx = line - 1 + REG_CCB_START;
ccb = sip_sm_get_ccb_by_index(ndx);
if (ccb != NULL) {
if (ccb->supported_tags & cisco_srtp_fallback_tag) {
return (TRUE);
}
}
return (FALSE);
}
@@ -0,0 +1,654 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_ipc.h"
#include "cpr_errno.h"
#include "cpr_socket.h"
#include "cpr_in.h"
#include "cpr_rand.h"
#include "cpr_string.h"
#include "cpr_threads.h"
#include "ccsip_core.h"
#include "ccsip_task.h"
#include "sip_platform_task.h"
#include "ccsip_platform_udp.h"
#include "sip_common_transport.h"
#include "phntask.h"
#include "phone_debug.h"
#include "util_string.h"
#include "ccsip_platform_tcp.h"
#include "ccsip_task.h"
#include "sip_socket_api.h"
#include "platform_api.h"
/*---------------------------------------------------------
*
* Definitions
*
*/
/* The maximum number of messages parsed from the message queue at one time */
#define MAX_SIP_MESSAGES 8
/* The maximum number of connections allowed */
#define MAX_SIP_CONNECTIONS (64 - 2)
/* SIP Message queue waiting thread and the main thread IPC names */
#ifdef __ANDROID__
#define SIP_MSG_IPC_PATH "/data/data/com.cisco.telephony.provider/"
#else
#define SIP_MSG_IPC_PATH "/tmp/"
#endif
#define SIP_MSG_SERV_NAME "SIP-Main-%d"
#define SIP_MSG_CLNT_NAME "SIP-MsgQ-%d"
#define SIP_PAUSE_WAIT_IPC_LISTEN_READY_TIME 50 /* 50ms. */
#define SIP_MAX_WAIT_FOR_IPC_LISTEN_READY 1200 /* 50 * 1200 = 1 minutes */
/*---------------------------------------------------------
*
* Local Variables
*
*/
fd_set read_fds;
fd_set write_fds;
static cpr_socket_t listen_socket = INVALID_SOCKET;
static cpr_socket_t sip_ipc_serv_socket = INVALID_SOCKET;
static cpr_socket_t sip_ipc_clnt_socket = INVALID_SOCKET;
static boolean main_thread_ready = FALSE;
uint32_t nfds = 0;
sip_connection_t sip_conn;
/*
* Internal message structure between main thread and
* message queue waiting thread.
*/
typedef struct sip_int_msg_t_ {
void *msg;
phn_syshdr_t *syshdr;
} sip_int_msg_t;
/* Internal message queue (array) */
static sip_int_msg_t sip_int_msgq_buf[MAX_SIP_MESSAGES] = {{0,0},{0,0}};
/* Main thread and message queue waiting thread IPC names */
static const char *sip_IPC_serv_name = SIP_MSG_IPC_PATH SIP_MSG_SERV_NAME;
static const char *sip_IPC_clnt_name = SIP_MSG_IPC_PATH SIP_MSG_CLNT_NAME;
static cpr_sockaddr_un_t sip_serv_sock_addr;
static cpr_sockaddr_un_t sip_clnt_sock_addr;
/*---------------------------------------------------------
*
* Global Variables
*
*/
extern sipGlobal_t sip;
extern boolean sip_reg_all_failed;
/*---------------------------------------------------------
*
* Function declarations
*
*/
//static void write_to_socket(cpr_socket_t s);
//static int read_socket(cpr_socket_t s);
/*---------------------------------------------------------
*
* Functions
*
*/
/**
*
* sip_platform_task_init
*
* Initialize the SIP Task
*
* Parameters: None
*
* Return Value: None
*
*/
static void
sip_platform_task_init (void)
{
uint16_t i;
for (i = 0; i < MAX_SIP_CONNECTIONS; i++) {
sip_conn.read[i] = INVALID_SOCKET;
sip_conn.write[i] = INVALID_SOCKET;
}
/*
* Initialize cprSelect call parameters
*/
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
return;
}
/**
* sip_create_IPC_sock creates and bind the socket for IPC.
*
* @param[in]name - pointer to the const. character for the
* IPC address (name) to be bound when the
* IPC socket is successfully created.
*
* @return cpr_socket_t - Returns a valid CPR's socket if
* the socket is created sucessafully otherwise
* returns INVALID_SOCKET.
* @pre (name != NULL)
*/
static cpr_socket_t sip_create_IPC_sock (const char *name)
{
const char *fname = "sip_create_IPC_sock";
cpr_socket_t sock;
cpr_sockaddr_un_t addr;
/* Create socket */
sock = cprSocket(AF_LOCAL, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"cprSocket() returned error"
" errno=%d\n", fname, cpr_errno);
return (INVALID_SOCKET);
}
/* Bind to the local socket */
cpr_set_sockun_addr(&addr, name, getpid());
/* make sure file doesn't already exist */
unlink( (char *)addr.sun_path);
/* do the bind */
if (cprBind(sock, (cpr_sockaddr_t *)&addr,
cpr_sun_len(addr)) == CPR_FAILURE) {
(void) sipSocketClose(sock, FALSE);
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"cprBind() failed"
" errno=%d\n", fname, cpr_errno);
return (INVALID_SOCKET);
}
return (sock);
}
/**
* The function is a thread loop that waits on SIP message queue
* visible for the external components (sip_msgq). The thread is used
* to avoid having the main task loop from having to set a small time
* waiting on select() to poll inter-thread messages. The small waiting
* time on select() to poll internal messages queue increases the
* unnecessary of waking up when system is idle. On the platform that
* power conservative is critical such as handheld phone, waking up
* periodically is not good for battery life.
*
* This thread splits the message queue waiting function from the
* main thread waiting on select(). This thread simply listens on the
* internal message queue and signal to the main thread via IPC socket
* or local socket trigger. Therefore the main thread can uniformly
* process internal message event and the network event via select().
* The small internal poll time on select() can be
* avoided.
*
* @param[in] arg - pointer to SIP main thread's message queue.
*
* @return None.
*
* @pre (arg != NULL)
*/
void sip_platform_task_msgqwait (void *arg)
{
const char *fname = "sip_platform_task_msgqwait";
cprMsgQueue_t *msgq = (cprMsgQueue_t *)arg;
unsigned int wait_main_thread = 0;
phn_syshdr_t *syshdr;
void *msg;
uint8_t num_messages = 0;
uint8_t response = 0;
boolean quit_thread = FALSE;
if (msgq == NULL) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"task msgq is null, exiting\n", fname);
return;
}
if (platThreadInit("SIP IPCQ task") != 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to attach thread to JVM\n", fname);
return;
}
/*
* Wait for SIP main thread ready for IPC connection.
*/
while (!main_thread_ready) {
/* Pause for other threads to run while waiting */
cprSleep(SIP_PAUSE_WAIT_IPC_LISTEN_READY_TIME);
wait_main_thread++;
if (wait_main_thread > SIP_MAX_WAIT_FOR_IPC_LISTEN_READY) {
/* Exceed the number of wait time */
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"timeout waiting for listening IPC"
" socket ready, exiting\n", fname);
return;
}
}
/*
* Adjust relative priority of SIP thread.
*/
#ifndef WIN32
(void) cprAdjustRelativeThreadPriority(SIP_THREAD_RELATIVE_PRIORITY);
#else
/* Use default priority */
(void) cprAdjustRelativeThreadPriority(0);
#endif
/*
* The main thread is ready. set global client socket address
* so that the server can send back response.
*/
cpr_set_sockun_addr(&sip_clnt_sock_addr, sip_IPC_clnt_name, getpid());
sip_ipc_clnt_socket = sip_create_IPC_sock(sip_IPC_clnt_name);
if (sip_ipc_clnt_socket == INVALID_SOCKET) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"sip_create_IPC_sock() failed,"
" exiting\n", fname);
return;
}
while (quit_thread == FALSE) {
msg = cprGetMessage(msgq, TRUE, (void **) &syshdr);
while (msg != NULL) {
/*
* There is a message to be forwarded to the main SIP
* thread for processing.
*/
sip_int_msgq_buf[num_messages].msg = msg;
sip_int_msgq_buf[num_messages].syshdr = syshdr;
num_messages++;
switch (syshdr->Cmd) {
case THREAD_UNLOAD:
quit_thread = TRUE;
break;
default:
break;
}
if (num_messages == MAX_SIP_MESSAGES) {
/*
* Limit the number of messages passed to the main SIP
* thread to MAX_SIP_MESSAGES since SIP main thread only
* process messages up to MAX_SIP_MESSAGES at a time.
*/
break;
}
/*
* Check to see if there is more message on the queue
* before sending IPC message trigger to the main SIP
* thread. This is to minimize the overhead of the
* the main SIP thread in processing select().
*/
msg = cprGetMessage(msgq, 0, (void **) &syshdr);
}
if (num_messages) {
CCSIP_DEBUG_TASK(DEB_F_PREFIX"%d msg available on msgq\n", DEB_F_PREFIX_ARGS(SIP_MSG_QUE, fname), num_messages);
/*
* There are some number of messages sent to the main thread,
* trigger the main SIP thread via IPC to process the message.
*/
if (cprSendTo(sip_ipc_clnt_socket, (void *)&num_messages,
sizeof(num_messages), 0,
(cpr_sockaddr_t *)&sip_serv_sock_addr,
cpr_sun_len(sip_serv_sock_addr)) < 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"send IPC failed errno=%d\n", fname, cpr_errno);
}
if (FALSE == quit_thread) {
/*
* Wait for main thread to signal us to get more message.
*/
if (cprRecvFrom(sip_ipc_clnt_socket, &response,
sizeof(response), 0, NULL, NULL) < 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"read IPC failed:"
" errno=%d\n", fname, cpr_errno);
}
num_messages = 0;
}
}
}
}
/**
* sip_process_int_msg - process internal IPC message from the
* the message queue waiting thread.
*
* @param - none.
*
* @return none.
*/
static void sip_process_int_msg (void)
{
const char *fname = "sip_process_int_msg";
ssize_t rcv_len;
uint8_t num_messages = 0;
uint8_t response = 0;
sip_int_msg_t *int_msg;
void *msg;
phn_syshdr_t *syshdr;
/* read the msg count from the IPC socket */
rcv_len = cprRecvFrom(sip_ipc_serv_socket, &num_messages,
sizeof(num_messages), 0, NULL, NULL);
if (rcv_len < 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"read IPC failed:"
" errno=%d\n", fname, cpr_errno);
return;
}
if (num_messages == 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"message queue is empty!\n", fname);
return;
}
if (num_messages > MAX_SIP_MESSAGES) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"number of messages on queue exceeds maximum %d\n", fname,
num_messages);
num_messages = MAX_SIP_MESSAGES;
}
/* process messages */
int_msg = &sip_int_msgq_buf[0];
while (num_messages) {
msg = int_msg->msg;
syshdr = int_msg->syshdr;
if (msg != NULL && syshdr != NULL) {
SIPTaskProcessListEvent(syshdr->Cmd, msg, syshdr->Usr.UsrPtr,
syshdr->Len);
cprReleaseSysHeader(syshdr);
int_msg->msg = NULL;
int_msg->syshdr = NULL;
}
num_messages--; /* one less message to work on */
int_msg++; /* advance to the next message */
}
/*
* Signal message queue waiting thread to get more messages.
*/
if (cprSendTo(sip_ipc_serv_socket, (void *)&response,
sizeof(response), 0,
(cpr_sockaddr_t *)&sip_clnt_sock_addr,
cpr_sun_len(sip_clnt_sock_addr)) < 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"%d sending IPC\n", fname);
}
}
/**
*
* sip_platform_task_loop
*
* Run the SIP task
*
* Parameters: arg - SIP message queue
*
* Return Value: None
*
*/
void
sip_platform_task_loop (void *arg)
{
static const char *fname = "sip_platform_task_loop";
int pending_operations;
uint16_t i;
fd_set sip_read_fds;
fd_set sip_write_fds;
sip_tcp_conn_t *entry;
sip_msgq = (cprMsgQueue_t) arg;
if (!sip_msgq) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"sip_msgq is null, exiting\n", fname);
return;
}
sip.msgQueue = sip_msgq;
sip_platform_task_init();
/*
* Initialize the SIP task
*/
SIPTaskInit();
if (platThreadInit("SIPStack Task") != 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to attach thread to JVM\n", fname);
return;
}
/*
* Adjust relative priority of SIP thread.
*/
#ifndef WIN32
(void) cprAdjustRelativeThreadPriority(SIP_THREAD_RELATIVE_PRIORITY);
#else
/* Use default priority */
(void) cprAdjustRelativeThreadPriority(0);
#endif
/*
* Setup IPC socket addresses for main thread (server)
*/
cpr_set_sockun_addr(&sip_serv_sock_addr, sip_IPC_serv_name, getpid());
/*
* Create IPC between the message queue thread and this main
* thread.
*/
sip_ipc_serv_socket = sip_create_IPC_sock(sip_IPC_serv_name);
if (sip_ipc_serv_socket == INVALID_SOCKET) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"sip_create_IPC_sock() failed:"
" errno=%d\n", fname, cpr_errno);
return;
}
/*
* On Win32 platform, the random seed is stored per thread; therefore,
* each thread needs to seed the random number. It is recommended by
* MS to do the following to ensure randomness across application
* restarts.
*/
cpr_srand((unsigned int)time(NULL));
/*
* Set read IPC socket
*/
sip_platform_task_set_read_socket(sip_ipc_serv_socket);
/*
* Let the message queue waiting thread know that the main
* thread is ready.
*/
main_thread_ready = TRUE;
/*
* Main Event Loop
*/
while (TRUE) {
/*
* Wait on events or timeout
*/
sip_read_fds = read_fds;
// start off by init to zero
FD_ZERO(&sip_write_fds);
// now look for sockets where data has been queued up
for (i = 0; i < MAX_CONNECTIONS; i++) {
entry = sip_tcp_conn_tab + i;
if (-1 != entry->fd && entry->sendQueue && sll_count(entry->sendQueue)) {
FD_SET(entry->fd, &sip_write_fds);
}
}
pending_operations = cprSelect((nfds + 1),
&sip_read_fds,
&sip_write_fds,
NULL, NULL);
if (pending_operations == SOCKET_ERROR) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"cprSelect() failed: errno=%d."
" Recover by initiating sip restart\n",
fname, cpr_errno);
/*
* If we have come here, then either read socket related to
* sip_ipc_serv_socket has got corrupted, or one of the write
* socket related to cucm tcp/tls connection.
* We will recover, by first clearing all fds, then re-establishing
* the connection with sip-msgq by listening on
* sip_ipc_serv_socket.
*/
sip_platform_task_init(); /* this clear FDs */
sip_platform_task_set_read_socket(sip_ipc_serv_socket);
/*
* Since all sockets fds have been cleared above, we can not anyway
* send or receive msg from cucm. So, there is no point
* trying to send registration cancel msg to cucm. Also, a
* call may be active, and in that case we do not want to
* un-register. So, by setting sip_reg_all_failed to true, we
* make sure that no registration cancelation attempt is made.
*/
sip_reg_all_failed = TRUE;
platform_reset_req(DEVICE_RESTART);
continue;
} else if (pending_operations) {
/*
* Listen socket is set only if UDP transport has been
* configured. So see if the select return was for read
* on the listen socket.
*/
if ((listen_socket != INVALID_SOCKET) &&
(sip.taskInited == TRUE) &&
FD_ISSET(listen_socket, &sip_read_fds)) {
sip_platform_udp_read_socket(listen_socket);
pending_operations--;
}
/*
* Check IPC for internal message queue
*/
if (FD_ISSET(sip_ipc_serv_socket, &sip_read_fds)) {
/* read the message to flush the buffer */
sip_process_int_msg();
pending_operations--;
}
/*
* Check all sockets for stuff to do
*/
for (i = 0; ((i < MAX_SIP_CONNECTIONS) &&
(pending_operations > 0)); i++) {
if ((sip_conn.read[i] != INVALID_SOCKET) &&
FD_ISSET(sip_conn.read[i], &sip_read_fds)) {
/*
* Assume tcp
*/
sip_tcp_read_socket(sip_conn.read[i]);
pending_operations--;
}
if ((sip_conn.write[i] != INVALID_SOCKET) &&
FD_ISSET(sip_conn.write[i], &sip_write_fds)) {
int connid;
connid = sip_tcp_fd_to_connid(sip_conn.write[i]);
if (connid >= 0) {
sip_tcp_resend(connid);
}
pending_operations--;
}
}
}
}
}
/**
*
* sip_platform_task_set_listen_socket
*
* Mark the socket for cpr_select to be read
*
* Parameters: s - the socket
*
* Return Value: None
*
*/
void
sip_platform_task_set_listen_socket (cpr_socket_t s)
{
listen_socket = s;
sip_platform_task_set_read_socket(s);
}
/**
*
* sip_platform_task_set_read_socket
*
* Mark the socket for cpr_select to be read
*
* Parameters: s - the socket
*
* Return Value: None
*
*/
void
sip_platform_task_set_read_socket (cpr_socket_t s)
{
if (s != INVALID_SOCKET) {
FD_SET(s, &read_fds);
nfds = MAX(nfds, (uint32_t)s);
}
}
/**
*
* sip_platform_task_reset_listen_socket
*
* Mark the socket as INVALID
*
* Parameters: s - the socket
*
* Return Value: None
*
*/
void
sip_platform_task_reset_listen_socket (cpr_socket_t s)
{
sip_platform_task_clr_read_socket(s);
listen_socket = INVALID_SOCKET;
}
/**
*
* sip_platform_task_clr_read_socket
*
* Mark the socket for cpr_select to be read
*
* Parameters: s - the socket
*
* Return Value: None
*
*/
void
sip_platform_task_clr_read_socket (cpr_socket_t s)
{
if (s != INVALID_SOCKET) {
FD_CLR(s, &read_fds);
}
}
+340
View File
@@ -0,0 +1,340 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cpr_types.h"
#include "cpr_ipc.h"
#include "cpr_errno.h"
#include "cpr_socket.h"
#include "cpr_in.h"
#include "cpr_rand.h"
#include "cpr_string.h"
#include "cpr_threads.h"
#include "ccsip_core.h"
#include "ccsip_task.h"
#include "sip_platform_task.h"
#include "ccsip_platform_udp.h"
#include "sip_common_transport.h"
#include "sip_interface_regmgr.h"
#include "phntask.h"
#include "phone_debug.h"
#include "util_string.h"
#include "ccsip_platform_tcp.h"
#include "ccsip_task.h"
/*---------------------------------------------------------
*
* Definitions
*
*/
/* The maximum number of messages parsed from the message queue at one time */
#define MAX_SIP_MESSAGES 8
/* The maximum number of connections allowed */
#define MAX_SIP_CONNECTIONS (64 - 2)
/* The socket select waiting time out values */
#define SIP_SELECT_NORMAL_TIMEOUT 25000 /* normal select timeout in usec*/
#define SIP_SELECT_QUICK_TIMEOUT 0 /* quick select timeout in usec */
/*---------------------------------------------------------
*
* Local Variables
*
*/
fd_set read_fds;
fd_set write_fds;
static cpr_socket_t listen_socket = INVALID_SOCKET;
uint32_t nfds = 0;
sip_connection_t sip_conn;
/*---------------------------------------------------------
*
* Global Variables
*
*/
extern sipGlobal_t sip;
/*---------------------------------------------------------
*
* Function declarations
*
*/
//static void write_to_socket(cpr_socket_t s);
//static int read_socket(cpr_socket_t s);
/*---------------------------------------------------------
*
* Functions
*
*/
/**
*
* sip_platform_task_init
*
* Initialize the SIP Task
*
* Parameters: None
*
* Return Value: None
*
*/
static void
sip_platform_task_init (void)
{
uint16_t i;
for (i = 0; i < MAX_SIP_CONNECTIONS; i++) {
sip_conn.read[i] = INVALID_SOCKET;
sip_conn.write[i] = INVALID_SOCKET;
}
/*
* Initialize cprSelect call parameters
*/
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
return;
}
/**
*
* sip_platform_task_loop
*
* Run the SIP task
*
* Parameters: arg - SIP message queue
*
* Return Value: None
*
*/
void
sip_platform_task_loop (void *arg)
{
static const char *fname = "sip_platform_task_loop";
int pending_operations;
struct cpr_timeval timeout;
void *msg;
uint32_t cmd;
uint16_t len;
void *usr;
phn_syshdr_t *syshdr;
uint16_t i;
fd_set sip_read_fds;
// fd_set sip_write_fds;
sip_msgq = (cprMsgQueue_t) arg;
if (!sip_msgq) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"sip_msgq is null, exiting\n", fname);
return;
}
sip.msgQueue = sip_msgq;
sip_platform_task_init();
/*
* Initialize the SIP task
*/
SIPTaskInit();
if (platThreadInit("sip_platform_task_loop") != 0) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to attach thread to JVM\n", fname);
return;
}
/*
* Adjust relative priority of SIP thread.
*/
(void) cprAdjustRelativeThreadPriority(SIP_THREAD_RELATIVE_PRIORITY);
/*
* Set the SIP task timeout at 25 milliseconds
*/
timeout.tv_sec = 0;
timeout.tv_usec = SIP_SELECT_NORMAL_TIMEOUT;
/*
* On Win32 platform, the random seed is stored per thread; therefore,
* each thread needs to seed the random number. It is recommended by
* MS to do the following to ensure randomness across application
* restarts.
*/
cpr_srand((unsigned int)time(NULL));
/*
* Main Event Loop
*/
while (TRUE) {
/*
* Wait on events or timeout
*/
sip_read_fds = read_fds;
// sip_write_fds = write_fds;
pending_operations = cprSelect((nfds + 1),
&sip_read_fds,
NULL,
NULL, &timeout);
if (pending_operations == SOCKET_ERROR) {
CCSIP_DEBUG_ERROR(SIP_F_PREFIX"cprSelect() failed: errno=%d\n",
fname, cpr_errno);
} else if (pending_operations) {
/*
* Listen socket is set only if UDP transport has been
* configured. So see if the select return was for read
* on the listen socket.
*/
if ((listen_socket != INVALID_SOCKET) &&
(sip.taskInited == TRUE) &&
FD_ISSET(listen_socket, &sip_read_fds)) {
sip_platform_udp_read_socket(listen_socket);
pending_operations--;
}
/*
* Check all sockets for stuff to do
*/
for (i = 0; ((i < MAX_SIP_CONNECTIONS) &&
(pending_operations != 0)); i++) {
if ((sip_conn.read[i] != INVALID_SOCKET) &&
FD_ISSET(sip_conn.read[i], &sip_read_fds)) {
/*
* Assume tcp
*/
sip_tcp_read_socket(sip_conn.read[i]);
pending_operations--;
}
/*
if ((sip_conn.write[i] != INVALID_SOCKET) &&
FD_ISSET(sip_conn.write[i], &sip_write_fds)) {
int connid;
connid = sip_tcp_fd_to_connid(sip_conn.write[i]);
if (connid >= 0) {
sip_tcp_resend(connid);
}
pending_operations--;
}
*/
}
}
/*
* Process all messages on the message queue
* (e.g. timer callbacks)
*/
i = 0;
while (i++ < MAX_SIP_MESSAGES) {
msg = cprGetMessage(sip_msgq, FALSE, (void **) &syshdr);
if (msg != NULL) {
cmd = syshdr->Cmd;
len = syshdr->Len;
usr = syshdr->Usr.UsrPtr;
SIPTaskProcessListEvent(cmd, msg, usr, len);
cprReleaseSysHeader(syshdr);
syshdr = NULL;
} else {
/* Stop checking for msgs if the queue is empty */
if (syshdr != NULL) {
cprReleaseSysHeader(syshdr);
syshdr = NULL;
}
break;
}
}
/*
* If message servicing loop reaches the maximum loop limit
* it is possible that there are more messages left on the message
* queue. Shorten the socket select time out to come back and
* check the message queue for the message that might be left on
* the queue.
*/
if (i >= MAX_SIP_MESSAGES) {
timeout.tv_usec = SIP_SELECT_QUICK_TIMEOUT;
} else {
/* set normal time out value to poll msg. queue */
timeout.tv_usec = SIP_SELECT_NORMAL_TIMEOUT;
}
}
}
/**
*
* sip_platform_task_set_listen_socket
*
* Mark the socket for cpr_select to be read
*
* Parameters: s - the socket
*
* Return Value: None
*
*/
void
sip_platform_task_set_listen_socket (cpr_socket_t s)
{
listen_socket = s;
sip_platform_task_set_read_socket(s);
}
/**
*
* sip_platform_task_set_read_socket
*
* Mark the socket for cpr_select to be read
*
* Parameters: s - the socket
*
* Return Value: None
*
*/
void
sip_platform_task_set_read_socket (cpr_socket_t s)
{
if (s != INVALID_SOCKET) {
FD_SET(s, &read_fds);
nfds = MAX(nfds, (uint32_t)s);
}
}
/**
*
* sip_platform_task_reset_listen_socket
*
* Mark the socket as INVALID
*
* Parameters: s - the socket
*
* Return Value: None
*
*/
void
sip_platform_task_reset_listen_socket (cpr_socket_t s)
{
sip_platform_task_clr_read_socket(s);
listen_socket = INVALID_SOCKET;
}
/**
*
* sip_platform_task_clr_read_socket
*
* Mark the socket for cpr_select to be read
*
* Parameters: s - the socket
*
* Return Value: None
*
*/
void
sip_platform_task_clr_read_socket (cpr_socket_t s)
{
if (s != INVALID_SOCKET) {
FD_CLR(s, &read_fds);
}
}