mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-15 13:58:32 +00:00
add sipcc to tree for sdp parser
This commit is contained in:
1 parent
36f89c8b7c
commit
0f00946782
369 files changed
+183596
No files matched your search
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+305
@@ -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
@@ -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 */
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Executable
+134
@@ -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
|
||||
Executable
+41
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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_ */
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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_*/
|
||||
@@ -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
|
||||
Executable
+22
@@ -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
|
||||
@@ -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
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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_*/
|
||||
Executable
+17
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user