So our 1st step is we need to modify our asterisk install to recognize and respond back correctly to phone so it enables its advanced features.
-
Edit ./usr/src/asterisk-13.7.2/channels/sip/include/sip.h
a. Find this section of code
/*! \brief Type of subscription, based on the packages we do support, see \ref subscription_types /
enum subscriptiontype {
NONE = 0,
XPIDF_XML,
DIALOG_INFO_XML,
CPIM_PIDF_XML,
PIDF_XML,
MWI_NOTIFICATION,
CALL_COMPLETION,
};
b. And replace it with
/! \brief Type of subscription, based on the packages we do support, see \ref subscription_types */
enum subscriptiontype {
NONE = 0,
XPIDF_XML,
DIALOG_INFO_XML,
CPIM_PIDF_XML,
PIDF_XML,
MWI_NOTIFICATION,
CALL_COMPLETION,
AVAYA_PPM,
};
-
Edit ./usr/src/asterisk-13.7.2/channels/chan_sip.c
a. Find this section of code
/* RFC 4235: SIP Dialog event package /
{ DIALOG_INFO_XML, “dialog”, “application/dialog-info+xml”, “dialog-info+xml” },
{ CPIM_PIDF_XML, “presence”, “application/cpim-pidf+xml”, “cpim-pidf+xml” }, / RFC 3863 /
{ PIDF_XML, “presence”, “application/pidf+xml”, “pidf+xml” }, / RFC 3863 /
{ XPIDF_XML, “presence”, “application/xpidf+xml”, “xpidf+xml” }, / Pre-RFC 3863 with MS additions /
{ MWI_NOTIFICATION, “message-summary”, “application/simple-message-summary”, “mwi” }, / RFC 3842: Mailbox notification */
b. Add to the following line under the MWI_NOTIFICATION, line
{ AVAYA_PPM ,“avaya-cm-feature-status”, “application/avaya-cm-feature-status+xml”, “multipart/mixed” } /* RFC 3842: Mailbox notification *
c. Add the following function header
static int respprep401(struct sip_request *resp, struct sip_pvt *p, const char *msg, const struct sip_request *req);
d. Add the following function
[details=Summary]static int respprep401(struct sip_request *resp, struct sip_pvt *p, const char *msg, const struct sip_request *req)
{
char newto[256];
const char *ot;
init_resp(resp, msg);
copy_via_headers(p, resp, req, “Via”);
if (msg[0] == ‘1’ || msg[0] == ‘2’)
copy_all_header(resp, req, “Record-Route”);
copy_header(resp, req, “From”);
ot = sip_get_header(req, “To”);
if (!strcasestr(ot, “tag=”) && strncmp(msg, “100”, 3)) {
/* Add the proper tag if we don’t have it already. If they have specified
their tag, use it. Otherwise, use our own tag */
ast_log(LOG_WARNING, “tag401 Check point 1 \n”);
if (!ast_strlen_zero(p->theirtag) && ast_test_flag(&p->flags[0], SIP_OUTGOING)){
ast_log(LOG_WARNING, “tag401 Check point 2 \n”);
snprintf(newto, sizeof(newto), “%s;tag=%s”, ot, p->theirtag);}
else if (p->tag && !ast_test_flag(&p->flags[0], SIP_OUTGOING)){
ast_log(LOG_WARNING, “tag401 Check point 3 \n”);
ast_log(LOG_WARNING, “\n \n”);
ast_log(LOG_WARNING,(strstr(sip_get_header(req, “Contact”), “+avaya-cm-line=1”)));
ast_log(LOG_WARNING, “\n \n”);
if (strstr(sip_get_header(req, “Contact”), “+avaya-cm-line=1”) != NULL) {
ast_log(LOG_WARNING,"\n ****************avaya featute\n ");
snprintf(newto, sizeof(newto), “%s”, ot);
//snprintf(newto, sizeof(newto), “%s;tag=%s”, ot, p->theirtag);
ast_log(LOG_WARNING, “tag401 Check point 3.1 \n”);
}
else {
snprintf(newto, sizeof(newto), “%s;tag=%s”, ot, p->tag);
ast_log(LOG_WARNING, “tag Check401 point 3.2 \n”);
}
}
else{
ast_log(LOG_WARNING, “tag401 Check point 4 \n”);
ast_copy_string(newto, ot, sizeof(newto));}
ot = newto;
}
ast_log(LOG_WARNING, “tag401 Check point 5 \n”);
add_header(resp, “To”, ot);
copy_header(resp, req, “Call-ID”);
copy_header(resp, req, “CSeq”);
if (!ast_strlen_zero(global_useragent))
add_header(resp, “Server”, global_useragent);
add_header(resp, “Allow”, ALLOWED_METHODS);
add_supported(p, resp);
/* If this is an invite, add Session-Timers related headers if the feature is active for this session /
if (p->method == SIP_INVITE && p->stimer && p->stimer->st_active == TRUE) {
char se_hdr[256];
snprintf(se_hdr, sizeof(se_hdr), “%d;refresher=%s”, p->stimer->st_interval,
p->stimer->st_ref == SESSION_TIMER_REFRESHER_US ? “uas” : “uac”);
add_header(resp, “Session-Expires”, se_hdr);
/ RFC 2048, Section 9
- If the refresher parameter in the Session-Expires header field in the
- 2xx response has a value of ‘uac’, the UAS MUST place a Require
- header field into the response with the value ‘timer’.
- …
- If the refresher parameter in
- the 2xx response has a value of ‘uas’ and the Supported header field
- in the request contained the value ‘timer’, the UAS SHOULD place a
- Require header field into the response with the value ‘timer’
*/
if (p->stimer->st_ref == SESSION_TIMER_REFRESHER_THEM ||
(p->stimer->st_ref == SESSION_TIMER_REFRESHER_US &&
p->stimer->st_active_peer_ua == TRUE)) {
resp->reqsipoptions |= SIP_OPT_TIMER;
}
}
if (msg[0] == ‘2’ && (p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER || p->method == SIP_PUBLISH)) {
/* For registration responses, we also need expiry and
contact info /
add_expires(resp, p->expiry);
if (p->expiry) { / Only add contact if we have an expiry time */
char contact[SIPBUFSIZE];
const char *contact_uri = p->method == SIP_SUBSCRIBE ? p->our_contact : p->fullcontact;
char brackets = strchr(contact_uri, ‘<’);
snprintf(contact, sizeof(contact), “%s%s%s;expires=%d”, brackets ? “” : “<”, contact_uri, brackets ? “” : “>”, p->expiry);
add_header(resp, “Contact”, contact); / Not when we unregister */
}
if (p->method == SIP_REGISTER && ast_test_flag(&p->flags[0], SIP_USEPATH)) {
copy_header(resp, req, “Path”);
}
} else if (!ast_strlen_zero(p->our_contact) && resp_needs_contact(msg, p->method)) {
add_header(resp, “Contact”, p->our_contact);
}
if (!ast_strlen_zero(p->url)) {
add_header(resp, “Access-URL”, p->url);
ast_string_field_set(p, url, NULL);
}
/* default to routing the response to the address where the request
- came from. Since we don’t have a transport layer, we do this here.
- The process_via() function will update the port to either the port
- specified in the via header or the default port later on (per RFC
- 3261 section 18.2.2).
*/
p->sa = p->recv;
if (process_via(p, req)) {
ast_log(LOG_WARNING, “error processing via header, will send response to originating address\n”);
}
return 0;
}
[/details]
e. In the function in transmit_response_with_auth find respprep(&resp, p, msg, req); and replace it with respprep401(&resp, p, msg, req);
f. in the function static void state_notify_build_xml switch (subscribed) find the case statement switch (subscribed) and add the following code right above the Case none:
[details=Summary] case AVAYA_PPM: /* SNOM subscribes in this format /
ast_str_append(tmp, 0, “<?xml version=\"1.0\"?>\n”);
ast_str_append(tmp, 0, “<dialog-info xmlns=“urn:ietf:params:xml:ns:dialog-info” version=”%u" state="%s" entity="%s">\n", p->dialogver, full ? “full” : “partial”, mto);
if (data->state > 0 && (data->state & AST_EXTENSION_RINGING) && sip_cfg.notifyringing) {
/ Twice the extension length should be enough for XML encoding */
char local_display[AST_MAX_EXTENSION * 2];
char remote_display[AST_MAX_EXTENSION * 2];
char local_target = ast_strdupa(mto);
/ It may seem odd to base the remote_target on the To header here,
- but testing by reporters on issue ASTERISK-16735 found that basing
- on the From header would cause ringing state hints to not work
- properly on certain SNOM devices. If you are using notifycid properly
- (i.e. in the same extension and context as the dialed call) then this
- should not be an issue since the data will be overwritten shortly
- with channel caller ID
*/
char *remote_target = ast_strdupa(mto);
ast_xml_escape(exten, local_display, sizeof(local_display));
ast_xml_escape(exten, remote_display, sizeof(remote_display));
/* There are some limitations to how this works. The primary one is that the
callee must be dialing the same extension that is being monitored. Simply dialing
the hint’d device is not sufficient. */
if (sip_cfg.notifycid) {
struct ast_channel *callee;
callee = find_ringing_channel(data->device_state_info, p);
if (callee) {
static char *anonymous = "anonymous";
static char *invalid = "anonymous.invalid";
char *cid_num;
char *connected_num;
int need;
int cid_num_restricted, connected_num_restricted;
ast_channel_lock(callee);
cid_num_restricted = (ast_channel_caller(callee)->id.number.presentation &
AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED;
cid_num = S_COR(ast_channel_caller(callee)->id.number.valid,
S_COR(cid_num_restricted, anonymous,
ast_channel_caller(callee)->id.number.str), “”);
need = strlen(cid_num) + (cid_num_restricted ? strlen(invalid) :
strlen(p->fromdomain)) + sizeof("sip:@");
local_target = ast_alloca(need);
snprintf(local_target, need, "sip:%s@%s", cid_num,
cid_num_restricted ? invalid : p->fromdomain);
ast_xml_escape(S_COR(ast_channel_caller(callee)->id.name.valid,
S_COR((ast_channel_caller(callee)->id.name.presentation &
AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED, anonymous,
ast_channel_caller(callee)->id.name.str), ""),
local_display, sizeof(local_display));
connected_num_restricted = (ast_channel_connected(callee)->id.number.presentation &
AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED;
connected_num = S_COR(ast_channel_connected(callee)->id.number.valid,
S_COR(connected_num_restricted, anonymous,
ast_channel_connected(callee)->id.number.str), "");
need = strlen(connected_num) + (connected_num_restricted ? strlen(invalid) :
strlen(p->fromdomain)) + sizeof("sip:@");
remote_target = ast_alloca(need);
snprintf(remote_target, need, "sip:%s@%s", connected_num,
connected_num_restricted ? invalid : p->fromdomain);
ast_xml_escape(S_COR(ast_channel_connected(callee)->id.name.valid,
S_COR((ast_channel_connected(callee)->id.name.presentation &
AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED, anonymous,
ast_channel_connected(callee)->id.name.str), ""),
remote_display, sizeof(remote_display));
ast_channel_unlock(callee);
callee = ast_channel_unref(callee);
}
/* We create a fake call-id which the phone will send back in an INVITE
Replaces header which we can grab and do some magic with. */
if (sip_cfg.pedanticsipchecking) {
ast_str_append(tmp, 0, "<dialog id=\"%s\" call-id=\"pickup-%s\" local-tag=\"%s\" remote-tag=\"%s\" direction=\"recipient\">\n",
exten, p->callid, p->theirtag, p->tag);
} else {
ast_str_append(tmp, 0, “<dialog id=”%s" call-id=“pickup-%s” direction=“recipient”>\n",
exten, p->callid);
}
ast_str_append(tmp, 0,
"\n"
/* See the limitations of this above. Luckily the phone seems to still be
happy when these values are not correct. */
"<identity display="%s">%s\n"
"<target uri="%s"/>\n"
"\n"
"\n"
"<identity display="%s">%s\n"
"<target uri="%s"/>\n"
"\n",
remote_display, remote_target, remote_target, local_display, local_target, local_target);
} else {
ast_str_append(tmp, 0, “<dialog id=”%s" direction=“recipient”>\n", exten);
}
} else {
ast_str_append(tmp, 0, “<dialog id=”%s">\n", exten);
}
ast_str_append(tmp, 0, “%s\n”, statestring);
if (data->state == AST_EXTENSION_ONHOLD) {
ast_str_append(tmp, 0, “\n<target uri=”%s">\n"
"<param pname="+sip.rendering" pvalue=“no”/>\n"
"\n\n", mto);
}
ast_str_append(tmp, 0, “\n\n”);
break;
[/details]
g. in the function sip_get_dest_result get_destination add the following code under If (!oreq)
[details=Summary] if(strstr(sip_get_header(req, “To”), “avaya-cm-fnu=off-hook”) != NULL) {
ast_log(LOG_WARNING, “get_destination Check point 33.1 \n”);
if ((strstr(sip_get_header(req, “Contact”), “uri-user=”) != NULL)) {
const char *contact = sip_get_header(req, “Contact”);
char *URIUSER = strstr(contact, “uri-user=”);
char *URIdomian = strstr(contact, “uri-domain=”);
URIUSER+= 9;
URIUSER[strlen(URIUSER) - strlen(URIdomian)-1] = 0;
uri=URIUSER;
ast_log(LOG_WARNING, " ‘%s’\n", URIUSER);
ast_log(LOG_WARNING, “get_destination Check point 33.2 \n”);
}
}
[/details]
h. add to the following handle_request_invite before if (p->relatedpeer) {
[details=Summary] if(strstr(sip_get_header(req, “To”), “avaya-cm-fnu=off-hook”) != NULL) {
ast_log(LOG_WARNING,"\n ****************avaya featute\n ");
ast_log(LOG_WARNING, “handle_request_invite Check point 2.1 \n”);
check_via(p, req);
copy_request(&p->initreq, req);
pvt_set_needdestroy(p, “forcing expiration”);
transmit_response(p, “183 Session Progress”, req);
goto request_invite_cleanup;
}
[/details]
i. in handle_request_subscribe replace this line
if (!strcmp(event, “presence”) || !strcmp(event, “dialog”)) { /* Presence, RFC 3842 /
with
if (!strcmp(event, “presence”) || !strcmp(event, “dialog”)|| !strcmp(event, “avaya-cm-feature-status”)) { / Presence, RFC 3842 */
j. in handle_request_subscribe under
} else if (strstr(accept, “application/xpidf+xml”)) { subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */
add
} else if (strstr(accept, “application/avaya-cm-feature-status+xml”)) {
_ subscribed = AVAYA_PPM;_
- Recompile Asterisk
a. cd /usr/src
b. cd asterisk-*
c. make
d. make install
e. make config