Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 143795) +++ channels/chan_sip.c (working copy) @@ -863,7 +863,7 @@ static int regobjs = 0; /*!< Registry objects */ /* }@ */ -static struct ast_flags global_flags[2] = {{0}}; /*!< global SIP_ flags */ +static struct ast_flags global_flags[3] = {{0}}; /*!< global SIP_ flags */ static char used_context[AST_MAX_CONTEXT]; /*!< name of automatically created context for unloading */ @@ -1117,6 +1117,15 @@ /*@}*/ +/*! \name SIPflags3 + a third page of flags (for flags[2] */ +/*@{*/ +#define SIP_PAGE3_ASSERTED_IDENTITY (1 << 0) /*!< GP: Use P-Asserted-Identity instead of Remote-Party-ID */ + +#define SIP_PAGE3_FLAGS_TO_COPY \ + (SIP_PAGE3_ASSERTED_IDENTITY) +/*@}*/ + /*! \name SIPflagsT38 T.38 set of flags */ @@ -1332,7 +1341,7 @@ ast_group_t pickupgroup; /*!< Pickup group */ int lastinvite; /*!< Last Cseq of invite */ int lastnoninvite; /*!< Last Cseq of non-invite */ - struct ast_flags flags[2]; /*!< SIP_ flags */ + struct ast_flags flags[3]; /*!< SIP_ flags */ /* boolean or small integers that don't belong in flags */ char do_history; /*!< Set if we want to record history */ @@ -1556,7 +1565,7 @@ struct ast_codec_pref prefs; /*!< codec prefs */ int lastmsgssent; unsigned int sipoptions; /*!< Supported SIP options */ - struct ast_flags flags[2]; /*!< SIP_ flags */ + struct ast_flags flags[3]; /*!< SIP_ flags */ /*! Mailboxes that this peer cares about */ AST_LIST_HEAD_NOLOCK(, sip_mailbox) mailboxes; @@ -8116,63 +8125,72 @@ /*! \brief Add Remote-Party-ID header to SIP message */ static int add_rpid(struct sip_request *req, struct sip_pvt *p) { char tmp[256]; - char *lid_num = NULL; - char *lid_name = NULL; - int lid_pres; + char *cid_num = NULL; + char *cid_name = NULL; + int callingpres; const char *fromdomain; const char *privacy = NULL; const char *screen = NULL; if (p->owner && p->owner->connected.id.number) - lid_num = p->owner->connected.id.number; + cid_num = p->owner->connected.id.number; if (p->owner && p->owner->connected.id.name) - lid_name = p->owner->connected.id.name; - lid_pres = (p->owner) ? p->owner->connected.id.number_presentation : AST_PRES_NUMBER_NOT_AVAILABLE; + cid_name = p->owner->connected.id.name; + callingpres = (p->owner) ? p->owner->connected.id.number_presentation : AST_PRES_NUMBER_NOT_AVAILABLE; - if (ast_strlen_zero(lid_num)) + if (ast_strlen_zero(cid_num)) return 0; - if (ast_strlen_zero(lid_name)) - lid_name = lid_num; + if (ast_strlen_zero(cid_name)) + cid_name = cid_num; fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)); - snprintf(tmp, sizeof(tmp), "\"%s\" ;party=%s", lid_name, lid_num, fromdomain, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "calling" : "called"); + if (ast_test_flag(&p->flags[2], SIP_PAGE3_ASSERTED_IDENTITY)) { + snprintf(tmp, sizeof(tmp), "\"%s\" ", cid_name, cid_num, fromdomain); + add_header(req, "P-Asserted-Identity", tmp); - switch (lid_pres) { - case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: - case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: - privacy = "off"; - screen = "no"; - break; - case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: - case AST_PRES_ALLOWED_NETWORK_NUMBER: - privacy = "off"; - screen = "yes"; - break; - case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED: - case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: - privacy = "full"; - screen = "no"; - break; - case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: - case AST_PRES_PROHIB_NETWORK_NUMBER: - privacy = "full"; - screen = "yes"; - break; - case AST_PRES_NUMBER_NOT_AVAILABLE: - break; - default: - if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) + if ((callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) + add_header(req, "Privacy", "id"); + } else { + snprintf(tmp, sizeof(tmp), "\"%s\" ;party=%s", cid_name, cid_num, fromdomain, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "calling" : "called"); + + switch (callingpres) { + case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: + case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: + privacy = "off"; + screen = "no"; + break; + case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: + case AST_PRES_ALLOWED_NETWORK_NUMBER: + privacy = "off"; + screen = "yes"; + break; + case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED: + case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: privacy = "full"; - else - privacy = "off"; - screen = "no"; - break; + screen = "no"; + break; + case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: + case AST_PRES_PROHIB_NETWORK_NUMBER: + privacy = "full"; + screen = "yes"; + break; + case AST_PRES_NUMBER_NOT_AVAILABLE: + break; + default: + if ((callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) + privacy = "full"; + else + privacy = "off"; + screen = "no"; + break; + } + + if (!ast_strlen_zero(privacy) && !ast_strlen_zero(screen)) + snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), ";privacy=%s;screen=%s", privacy, screen); + + add_header(req, "Remote-Party-ID", tmp); } - if (!ast_strlen_zero(privacy) && !ast_strlen_zero(screen)) - snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), ";privacy=%s;screen=%s", privacy, screen); - - add_header(req, "Remote-Party-ID", tmp); return 0; } @@ -11204,7 +11222,10 @@ req = oreq; if (!req) req = &p->initreq; - ast_copy_string(tmp, get_header(req, "Remote-Party-ID"), sizeof(tmp)); + if (ast_test_flag(&p->flags[2], SIP_PAGE3_ASSERTED_IDENTITY)) + ast_copy_string(tmp, get_header(req, "P-Asserted-Identity"), sizeof(tmp)); + else + ast_copy_string(tmp, get_header(req, "Remote-Party-ID"), sizeof(tmp)); if (ast_strlen_zero(tmp)) return 0; @@ -11226,9 +11247,12 @@ if (!end) return 0; *end++ = '\0'; - if (strncasecmp(start, "sip:", 4)) + if (!strncasecmp(start, "sip:", 4)) + cid_num = start + 4; + else if (!strncasecmp(start, "sips:", 5)) + cid_num = start + 5; + else return 0; - cid_num = start + 4; if (ast_is_shrinkable_phonenumber(cid_num)) ast_shrink_phone_number(cid_num); start = end; @@ -11237,32 +11261,38 @@ if (!end) return 0; *end++ = '\0'; - if (*end) { - start = end; - if (*start != ';') - return 0; - *start++ = '\0'; - while (!ast_strlen_zero(start)) { - end = strchr(start, ';'); - if (end) - *end++ = '\0'; - if (!strncasecmp(start, "privacy=", 8)) - privacy = start + 8; - else if (!strncasecmp(start, "screen=", 7)) - screen = start + 7; + + if (ast_test_flag(&p->flags[2], SIP_PAGE3_ASSERTED_IDENTITY)) { + if (!strcasecmp(get_header(req, "Privacy"), "id")) + callingpres = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN; + } else { + if (*end) { start = end; - } + if (*start != ';') + return 0; + *start++ = '\0'; + while (!ast_strlen_zero(start)) { + end = strchr(start, ';'); + if (end) + *end++ = '\0'; + if (!strncasecmp(start, "privacy=", 8)) + privacy = start + 8; + else if (!strncasecmp(start, "screen=", 7)) + screen = start + 7; + start = end; + } - if (!strcasecmp(privacy, "full")) { - if (!strcasecmp(screen, "yes")) - callingpres = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN; - else if (!strcasecmp(screen, "no")) - callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; - } else { - if (!strcasecmp(screen, "yes")) - callingpres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; - else if (!strcasecmp(screen, "no")) - callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; + if (!strcasecmp(privacy, "full")) { + if (!strcasecmp(screen, "yes")) + callingpres = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN; + else if (!strcasecmp(screen, "no")) + callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; + } else { + if (!strcasecmp(screen, "yes")) + callingpres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; + else if (!strcasecmp(screen, "no")) + callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; + } } } @@ -11991,6 +12021,7 @@ /* Take the peer */ ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); + ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); /* Copy SIP extensions profile to peer */ /* XXX is this correct before a successful auth ? */ @@ -12026,6 +12057,8 @@ if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable, req->ignore))) { ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); + ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); + /* If we have a call limit, set flag */ if (peer->call_limit) ast_set_flag(&p->flags[0], SIP_CALL_LIMIT); @@ -20432,6 +20465,7 @@ p->socket = peer->socket; ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); + ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); /* Send OPTIONs to peer's fullcontact */ if (!ast_strlen_zero(peer->fullcontact)) @@ -20891,6 +20925,9 @@ } else if (!strcasecmp(v->name, "t38pt_usertpsource")) { ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION); ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION); + } else if (!strcasecmp(v->name, "assertedidentity")) { + ast_set_flag(&mask[2], SIP_PAGE3_ASSERTED_IDENTITY); + ast_set2_flag(&flags[2], ast_true(v->value), SIP_PAGE3_ASSERTED_IDENTITY); } else res = 0; @@ -21079,6 +21116,7 @@ } ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY); ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY); + ast_copy_flags(&peer->flags[2], &global_flags[2], SIP_PAGE3_FLAGS_TO_COPY); strcpy(peer->context, default_context); strcpy(peer->subscribecontext, default_subscribecontext); strcpy(peer->language, default_language); @@ -21172,8 +21210,8 @@ int firstpass=1; int format=0; /* Ama flags */ time_t regseconds = 0; - struct ast_flags peerflags[2] = {{(0)}}; - struct ast_flags mask[2] = {{(0)}}; + struct ast_flags peerflags[3] = {{(0)}}; + struct ast_flags mask[3] = {{(0)}}; char callback[256] = ""; struct sip_peer tmp_peer; const char *srvlookup = NULL; Index: apps/app_directed_pickup.c =================================================================== --- apps/app_directed_pickup.c (revision 143795) +++ apps/app_directed_pickup.c (working copy) @@ -66,9 +66,18 @@ static int pickup_do(struct ast_channel *chan, struct ast_channel *target) { int res = 0; + struct ast_party_connected_line connected_caller; ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name); + connected_caller = target->connected; + connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; + ast_connected_line_update(chan, &connected_caller); + + ast_party_connected_line_collect_caller(&connected_caller, &chan->cid); + connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; + ast_queue_connected_line_update(chan, &connected_caller); + if ((res = ast_answer(chan))) { ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); return -1;