--- /usr/src/asterisk_trunk_org/include/asterisk/pbx.h 2011-05-22 12:17:50.000000000 -0400 +++ /usr/src/asterisk_trunk/include/asterisk/pbx.h 2011-06-02 18:54:23.000000000 -0400 @@ -66,6 +66,7 @@ AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */ + AST_EXTENSION_REQLINESEIZE = 1 << 5, /*!< request line seize */ }; --- /usr/src/asterisk_trunk_org/channels/sip/include/sip.h 2011-06-02 18:52:49.000000000 -0400 +++ /usr/src/asterisk_trunk/channels/sip/include/sip.h 2011-06-02 18:54:23.000000000 -0400 @@ -419,6 +419,7 @@ DIALOG_INFO_XML, CPIM_PIDF_XML, PIDF_XML, + CALL_INFO, MWI_NOTIFICATION, CALL_COMPLETION, }; @@ -703,6 +704,7 @@ struct sip_proxy outboundproxy; /*!< Outbound proxy */ char default_context[AST_MAX_CONTEXT]; char default_subscribecontext[AST_MAX_CONTEXT]; + char default_notify_exten[AST_MAX_CONTEXT]; struct ast_ha *contact_ha; /*! \brief Global list of addresses dynamic peers are not allowed to use */ struct ast_format_cap *caps; /*!< Supported codecs */ int tcp_enabled; @@ -940,6 +942,7 @@ AST_STRING_FIELD(exten); /*!< Extension where to start */ AST_STRING_FIELD(context); /*!< Context for this call */ AST_STRING_FIELD(subscribecontext); /*!< Subscribecontext */ + AST_STRING_FIELD(notify_exten); /*!< Notify_Extension for Broadsoft */ AST_STRING_FIELD(subscribeuri); /*!< Subscribecontext */ AST_STRING_FIELD(fromdomain); /*!< Domain to show in the from field */ AST_STRING_FIELD(fromuser); /*!< User to show in the user field */ @@ -1173,6 +1176,7 @@ AST_STRING_FIELD(remotesecret); /*!< Remote secret (trunks, remote devices) */ AST_STRING_FIELD(context); /*!< Default context for incoming calls */ AST_STRING_FIELD(subscribecontext); /*!< Default context for subscriptions */ + AST_STRING_FIELD(notify_exten); /*!< notify_exten for Broadsoft */ AST_STRING_FIELD(username); /*!< Temporary username until registration */ AST_STRING_FIELD(accountcode); /*!< Account code */ AST_STRING_FIELD(tohost); /*!< If not dynamic, IP address */ --- /usr/src/asterisk_trunk_org/channels/chan_sip.c 2011-06-02 18:52:49.000000000 -0400 +++ /usr/src/asterisk_trunk/channels/chan_sip.c 2011-06-02 19:10:04.000000000 -0400 @@ -612,6 +612,7 @@ { 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 */ + { CALL_INFO, "call-info", "call-info", "call-info" }, /* partial added broadsoft implement */ { MWI_NOTIFICATION, "message-summary", "application/simple-message-summary", "mwi" } /* RFC 3842: Mailbox notification */ }; @@ -12430,6 +12431,26 @@ } ast_str_append(tmp, 0, "\n\n"); break; + case CALL_INFO: /* sipura spa-9xx's and Cisco SPA's subscribe in this Broadsoft format for ShareCallAppearance */ + /* will just send state out to appearance state 1 and only use idle and held states */ + if (state != AST_EXTENSION_REQLINESEIZE){ + /* ast_verbose("statestring = %s\n",statestring); */ + ast_str_append(tmp, 0, "domain ); + if ((strcmp(statestring,"idle") == 0) || (strcmp(statestring,"terminated")== 0)) { + statestring = "idle" ; + ast_str_append(tmp, 0, ">;appearance-index=*;appearance-state=" ); + } + if (strcmp(statestring,"early") == 0) { + ast_str_append(tmp, 0, ">;appearance-index=1;appearance-state=" ); + } + if (strcmp(statestring,"confirmed") == 0) { + statestring = "held"; + ast_str_append(tmp, 0, ">;appearance-index=1;appearance-state=" ); + } + ast_str_append(tmp, 0, statestring, "\n" ); + } + break; case NONE: default: break; @@ -12508,6 +12529,10 @@ case AST_EXTENSION_REMOVED: add_header(&req, "Subscription-State", "terminated;reason=noresource"); break; + case AST_EXTENSION_REQLINESEIZE: + add_header(&req, "Event" , "Line-Seize"); + add_header(&req, "Subscription-State", "active, 14"); + break; default: if (p->expiry) add_header(&req, "Subscription-State", "active"); @@ -12535,6 +12560,17 @@ add_header(&req, "Content-Type", subscriptiontype->mediatype); p->dialogver++; break; + case CALL_INFO: /* Sipura and Cisco Spa's subscribe in this format */ + /* will just send state out to appearance state 1 and only use idle and held states */ + if (state != AST_EXTENSION_REQLINESEIZE){ + state_notify_build_xml(state, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto); + add_header(&req, "Event", "call-info"); + add_header(&req, "Call-Info", tmp->str); + } + else { + ast_verbose("CALL_INFO failed in transmit_state_notify\n"); + } + break; case NONE: default: break; @@ -14285,7 +14321,7 @@ struct sip_pvt *p = data; sip_pvt_lock(p); - + switch(state) { case AST_EXTENSION_DEACTIVATED: /* Retry after a while */ case AST_EXTENSION_REMOVED: /* Extension is gone */ @@ -15148,7 +15184,20 @@ return SIP_GET_DEST_EXTEN_FOUND; } } - + if (req->method == SIP_INVITE) { /* remaining check if this is INVITE with Call-Info, ie part of Broadsoft shared call feature */ + ast_copy_string(tmpf, get_header(req, "Call-Info"), sizeof(tmpf)); + if (!ast_strlen_zero(tmpf)) {/* need to get notify_exten from related peer */ + struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FALSE, FALSE, 0); + if (pp) { + ast_string_field_set(p, exten, pp->notify_exten); + ast_string_field_set(p, context, pp->subscribecontext); + } else { + ast_verbose ("problem: cannot find related peer for patching notify_exten into destination\n" ); + } + } + return SIP_GET_DEST_EXTEN_FOUND; + } + /* Return 1 for pickup extension or overlap dialling support (if we support it) */ if((ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP) && ast_canmatch_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from))) || @@ -24300,6 +24349,12 @@ } else event = (char *) eventheader; /* XXX is this legal ? */ + /* if not new subscription, but rather Subscribe line-seize event, just acknowledge it */ + if (!strcmp(event, "line-seize" )) { + transmit_response(p, "200 OK", req); + transmit_state_notify(p, AST_EXTENSION_REQLINESEIZE, 1, 18 ); + return(0); + } /* Handle authentication if we're new and not a retransmission. We can't just * use if !req->ignore, because then we'll end up sending * a 200 OK if someone retransmits without sending auth */ @@ -24362,7 +24417,7 @@ if (ast_strlen_zero(p->tag)) make_our_tag(p->tag, sizeof(p->tag)); - if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */ + if (!strcmp(event, "presence") || !strcmp(event, "dialog") || !strcmp(event, "call-info") ) { /* Presence, RFC 3842 */ unsigned int pidf_xml; const char *accept; int start = 0; @@ -24374,6 +24429,10 @@ /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */ accept = __get_header(req, "Accept", &start); + if (!strcmp(event, "call-info")) { /* Linksys SPA and Cisco SPA uses Broadsoft Call-Info */ + subscribed = CALL_INFO; + start = 1; + } while ((subscribed == NONE) && !ast_strlen_zero(accept)) { pidf_xml = strstr(accept, "application/pidf+xml") ? 1 : 0; @@ -24508,6 +24567,7 @@ /* Add subscription for extension state from the PBX core */ if (p->subscribed != MWI_NOTIFICATION && p->subscribed != CALL_COMPLETION && !resubscribe) { + if (p->stateid > -1) { ast_extension_state_del(p->stateid, cb_extensionstate); /* we need to dec the refcount, now that the extensionstate is removed */ @@ -26659,6 +26719,7 @@ ast_copy_flags(&peer->flags[2], &global_flags[2], SIP_PAGE3_FLAGS_TO_COPY); ast_string_field_set(peer, context, sip_cfg.default_context); ast_string_field_set(peer, subscribecontext, sip_cfg.default_subscribecontext); + ast_string_field_set(peer, notify_exten, sip_cfg.default_notify_exten); ast_string_field_set(peer, language, default_language); ast_string_field_set(peer, mohinterpret, default_mohinterpret); ast_string_field_set(peer, mohsuggest, default_mohsuggest); @@ -26954,6 +27015,8 @@ ast_set_flag(&peer->flags[1], SIP_PAGE2_HAVEPEERCONTEXT); } else if (!strcasecmp(v->name, "subscribecontext")) { ast_string_field_set(peer, subscribecontext, v->value); + } else if (!strcasecmp(v->name, "notify_exten")) { + ast_string_field_set(peer, notify_exten, v->value); } else if (!strcasecmp(v->name, "fromdomain")) { char *fromdomainport; ast_string_field_set(peer, fromdomain, v->value); @@ -27686,6 +27749,7 @@ /* Initialize some reasonable defaults at SIP reload (used both for channel and as default for devices */ ast_copy_string(sip_cfg.default_context, DEFAULT_CONTEXT, sizeof(sip_cfg.default_context)); sip_cfg.default_subscribecontext[0] = '\0'; + sip_cfg.default_notify_exten[0] = '\0'; sip_cfg.default_max_forwards = DEFAULT_MAX_FORWARDS; default_language[0] = '\0'; default_fromdomain[0] = '\0'; @@ -27751,6 +27815,8 @@ ast_copy_string(sip_cfg.default_context, v->value, sizeof(sip_cfg.default_context)); } else if (!strcasecmp(v->name, "subscribecontext")) { ast_copy_string(sip_cfg.default_subscribecontext, v->value, sizeof(sip_cfg.default_subscribecontext)); + } else if (!strcasecmp(v->name, "notify_exten")) { + ast_copy_string(sip_cfg.default_notify_exten, v->value, sizeof(sip_cfg.default_notify_exten)); } else if (!strcasecmp(v->name, "callcounter")) { global_callcounter = ast_true(v->value) ? 1 : 0; } else if (!strcasecmp(v->name, "allowguest")) {