--- channels/chan_sip.c.orig 2009-08-06 11:08:33.000000000 +0200 +++ channels/chan_sip.c 2009-08-06 10:24:13.000000000 +0200 @@ -497,8 +497,8 @@ #define DEFAULT_CONTEXT "default" #define DEFAULT_MOHINTERPRET "default" #define DEFAULT_MOHSUGGEST "" -#define DEFAULT_VMEXTEN "asterisk" -#define DEFAULT_CALLERID "asterisk" +#define DEFAULT_VMEXTEN "smartel" +#define DEFAULT_CALLERID "smartel" #define DEFAULT_NOTIFYMIME "application/simple-message-summary" #define DEFAULT_MWITIME 10 #define DEFAULT_ALLOWGUEST TRUE @@ -508,15 +508,16 @@ #define DEFAULT_TOS_AUDIO 0 /*!< Audio packets should be marked as DSCP EF (Expedited Forwarding), but the default is 0 to be compatible with previous versions. */ #define DEFAULT_TOS_VIDEO 0 /*!< Video packets should be marked as DSCP AF41, but the default is 0 to be compatible with previous versions. */ #define DEFAULT_ALLOW_EXT_DOM TRUE -#define DEFAULT_REALM "asterisk" +#define DEFAULT_REALM "smartel" #define DEFAULT_NOTIFYRINGING TRUE +#define DEFAULT_SENDCALLINFO TRUE #define DEFAULT_PEDANTIC FALSE #define DEFAULT_AUTOCREATEPEER FALSE #define DEFAULT_QUALIFY FALSE #define DEFAULT_T1MIN 100 /*!< 100 MS for minimal roundtrip time */ #define DEFAULT_MAX_CALL_BITRATE (384) /*!< Max bitrate for video */ #ifndef DEFAULT_USERAGENT -#define DEFAULT_USERAGENT "Asterisk PBX" /*!< Default Useragent: header unless re-defined in sip.conf */ +#define DEFAULT_USERAGENT "smarTel PBX" /*!< Default Useragent: header unless re-defined in sip.conf */ #endif @@ -541,6 +542,7 @@ static int global_limitonpeers; /*!< Match call limit on peers only */ static int global_rtautoclear; static int global_notifyringing; /*!< Send notifications on ringing */ +static int global_sendcallinfo; /*!< Send info about called and calling party */ static int global_notifyhold; /*!< Send notifications on hold */ static int global_alwaysauthreject; /*!< Send 401 Unauthorized for all failing requests */ static int srvlookup; /*!< SRV Lookup on or off. Default is on */ @@ -805,10 +807,15 @@ #define SIP_PAGE2_UDPTL_DESTINATION (1 << 28) /*!< 28: Use source IP of RTP as destination if NAT is enabled */ #define SIP_PAGE2_DIALOG_ESTABLISHED (1 << 29) /*!< 29: Has a dialog been established? */ #define SIP_PAGE2_RPORT_PRESENT (1 << 30) /*!< 30: Was rport received in the Via header? */ +#define SIP_PAGE2_CID_UPDATE (3 << 31) +#define SIP_PAGE2_CID_UPDATE_NEVER (0 << 31) +#define SIP_PAGE2_CID_UPDATE_INFO (1 << 31) +#define SIP_PAGE2_CID_UPDATE_REINVITE (2 << 31) + #define SIP_PAGE2_FLAGS_TO_COPY \ (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | \ - SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_UDPTL_DESTINATION) + SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_CID_UPDATE) /* SIP packet flags */ #define SIP_PKT_DEBUG (1 << 0) /*!< Debug this packet */ @@ -995,6 +1002,7 @@ int rtptimeout; /*!< RTP timeout time */ struct sockaddr_in recv; /*!< Received as */ struct in_addr ourip; /*!< Our IP */ + struct in_addr rtpip; /*!< Our RTP IP */ struct ast_channel *owner; /*!< Who owns us (if we have an owner) */ struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */ int route_persistant; /*!< Is this the "real" route? */ @@ -1052,6 +1060,7 @@ * * The large-scale changes would be a good idea for implementing during an SDP rewrite. */ + int pickup_cid_update_done; struct offered_media offered_media[3]; } *iflist = NULL; @@ -1154,6 +1163,7 @@ ast_group_t callgroup; /*!< Call group */ ast_group_t pickupgroup; /*!< Pickup group */ struct sockaddr_in addr; /*!< IP address of peer */ + struct in_addr rtpip; /*!< RTP IP address */ int maxcallbitrate; /*!< Maximum Bitrate for a video call */ /* Qualification */ @@ -1593,6 +1603,9 @@ static struct ast_udptl *sip_get_udptl_peer(struct ast_channel *chan); static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl); +/*------ CID Update Support --------- */ +static int transmit_cid_update(struct sip_pvt *p); + /*! \brief Definition of this channel for PBX channel registration */ static const struct ast_channel_tech sip_tech = { .type = "SIP", @@ -7645,8 +7658,29 @@ case DIALOG_INFO_XML: /* SNOM subscribes in this format */ ast_build_string(&t, &maxbytes, "\n"); ast_build_string(&t, &maxbytes, "\n", p->dialogver++, full ? "full":"partial", mto); - if ((state & AST_EXTENSION_RINGING) && global_notifyringing) - ast_build_string(&t, &maxbytes, "\n", p->exten); + if ((state & AST_EXTENSION_RINGING) && global_notifyringing) { + if (global_sendcallinfo && !ast_strlen_zero(hint)) { /* include informations about called and calling party as pickup info */ + struct ast_channel *chan = NULL; + struct sip_pvt *np = NULL; + + while ((chan = ast_walk_channel_by_name_prefix_locked(chan, hint, strlen(hint)))) { + if((chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_DOWN) && chan->tech_pvt) { /* Send call info */ + np = chan->tech_pvt; + ast_build_string(&t, &maxbytes, "\n", p->exten, np->callid); + ast_build_string(&t, &maxbytes, "%s\n", p->exten, p->exten, mfrom); + ast_build_string(&t, &maxbytes, "sip:%s@%s\n", np->fromname, np->fromuser, p->fromdomain, p->exten, p->fromdomain); + + ast_log(LOG_DEBUG, "Sent call-pickup info to peer %s\n", p->peername); + ast_channel_unlock(chan); + break; /* everything done, jump out of channel walk */ + } + ast_channel_unlock(chan); + } + } else { + ast_build_string(&t, &maxbytes, "\n", p->exten); + } + + } else ast_build_string(&t, &maxbytes, "\n", p->exten); ast_build_string(&t, &maxbytes, "%s\n", statestring); @@ -13832,10 +13866,15 @@ static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target) { int res = 0; + struct sip_request req; + struct sip_pvt *p = NULL; struct ast_channel *peera = NULL, *peerb = NULL, *peerc = NULL, *peerd = NULL; + char tmp[500]; + char *t = tmp; + size_t maxbytes = sizeof(tmp); /* We will try to connect the transferee with the target and hangup @@ -13890,6 +13929,21 @@ res = -1; } else ast_log(LOG_DEBUG, "SIP transfer: Succeeded to masquerade channels.\n"); + + if (peerd && !strcasecmp(peerd->tech->type, "SIP")) { + p = peerd->tech_pvt; + if (p && ast_test_flag(&(p->flags[1]), SIP_PAGE2_CID_UPDATE_INFO)) { + ast_log(LOG_DEBUG, "SIP transfer: Sending CID update to %s.\n", peerd->name); + reqprep(&req, p, SIP_INFO, 0, 1); + add_header(&req, "Content-Type", "message/sipfrag"); + ast_build_string(&t, &maxbytes, "From: \"%s\" %s\r\n", peerd->cid.cid_name, peerd->cid.cid_num); + ast_build_string(&t, &maxbytes, "To: \"%s\" %s\r\n", peerc->cid.cid_name, peerc->cid.cid_num); + add_header_contentLength(&req, strlen(tmp)); + add_line(&req, tmp); + send_request(p, &req, 0, p->ocseq); + } + } + return res; } else { ast_log(LOG_NOTICE, "SIP Transfer attempted with no appropriate bridged calls to transfer\n"); @@ -16697,6 +16751,10 @@ if (ast_mutex_trylock(&sip->lock)) continue; + if (sip->owner && (sip->owner->_state == AST_STATE_UP) && !sip->pickup_cid_update_done) { + res = transmit_cid_update(sip); + } + /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */ if (sip->rtp && sip->owner && (sip->owner->_state == AST_STATE_UP) && @@ -17526,6 +17584,14 @@ ast_copy_string(user->md5secret, v->value, sizeof(user->md5secret)); } else if (!strcasecmp(v->name, "callerid")) { ast_callerid_split(v->value, user->cid_name, sizeof(user->cid_name), user->cid_num, sizeof(user->cid_num)); + } else if (!strcasecmp(v->name, "calleridupdate")) { + if (!strcasecmp(v->value, "never")) { + ast_clear_flag((&user->flags[1]), SIP_PAGE2_CID_UPDATE_INFO); + ast_set_flag((&user->flags[1]), SIP_PAGE2_CID_UPDATE_NEVER); + } else if (!strcasecmp(v->value, "info")) { + ast_clear_flag((&user->flags[1]), SIP_PAGE2_CID_UPDATE_NEVER); + ast_set_flag((&user->flags[1]), SIP_PAGE2_CID_UPDATE_INFO); + } } else if (!strcasecmp(v->name, "fullname")) { ast_copy_string(user->cid_name, v->value, sizeof(user->cid_name)); } else if (!strcasecmp(v->name, "cid_number")) { @@ -17661,6 +17727,8 @@ struct ast_flags mask[2] = {{(0)}}; int alt_fullcontact = alt ? 1 : 0; char fullcontact[sizeof(peer->fullcontact)] = ""; + struct ast_hostent ahp; + struct hostent *hp; if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) /* Note we do NOT use find_peer here, to avoid realtime recursion */ @@ -17881,6 +17949,14 @@ ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); peer->rtpkeepalive = global_rtpkeepalive; } + } else if (!strcasecmp(v->name, "calleridupdate")) { + if (!strcasecmp(v->value, "never")) { + ast_clear_flag((&peer->flags[1]), SIP_PAGE2_CID_UPDATE_INFO); + ast_set_flag((&peer->flags[1]), SIP_PAGE2_CID_UPDATE_NEVER); + } else if (!strcasecmp(v->value, "info")) { + ast_clear_flag((&peer->flags[1]), SIP_PAGE2_CID_UPDATE_NEVER); + ast_set_flag((&peer->flags[1]), SIP_PAGE2_CID_UPDATE_INFO); + } } else if (!strcasecmp(v->name, "setvar")) { /* Set peer channel variable */ varname = ast_strdupa(v->value); @@ -17912,6 +17988,12 @@ peer->maxcallbitrate = atoi(v->value); if (peer->maxcallbitrate < 0) peer->maxcallbitrate = default_maxcallbitrate; + } else if (!strcasecmp(v->name, "rtpip")) { + if (!(hp = ast_gethostbyname(v->value, &ahp))) { + ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); + } else { + memcpy(&peer->rtpip, hp->h_addr, sizeof(peer->rtpip)); + } } } if (!ast_strlen_zero(fullcontact)) { @@ -18055,6 +18137,7 @@ global_regcontext[0] = '\0'; expiry = DEFAULT_EXPIRY; global_notifyringing = DEFAULT_NOTIFYRINGING; + global_sendcallinfo = DEFAULT_SENDCALLINFO; global_limitonpeers = FALSE; global_directrtpsetup = FALSE; /* Experimental feature, disabled by default */ global_notifyhold = FALSE; @@ -18161,6 +18244,14 @@ ast_set2_flag(&global_flags[1], i || ast_true(v->value), SIP_PAGE2_RTAUTOCLEAR); } else if (!strcasecmp(v->name, "usereqphone")) { ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE); + } else if (!strcasecmp(v->name, "calleridupdate")) { + if (!strcasecmp(v->value, "never")) { + ast_clear_flag((&global_flags[1]), SIP_PAGE2_CID_UPDATE_INFO); + ast_set_flag((&global_flags[1]), SIP_PAGE2_CID_UPDATE_NEVER); + } else if (!strcasecmp(v->value, "info")) { + ast_clear_flag((&global_flags[1]), SIP_PAGE2_CID_UPDATE_NEVER); + ast_set_flag((&global_flags[1]), SIP_PAGE2_CID_UPDATE_INFO); + } } else if (!strcasecmp(v->name, "relaxdtmf")) { global_relaxdtmf = ast_true(v->value); } else if (!strcasecmp(v->name, "checkmwi")) { @@ -18195,6 +18286,8 @@ global_directrtpsetup = ast_true(v->value); } else if (!strcasecmp(v->name, "notifyringing")) { global_notifyringing = ast_true(v->value); + } else if (!strcasecmp(v->name, "sendcallinfo")) { + global_sendcallinfo = ast_true(v->value); } else if (!strcasecmp(v->name, "notifyhold")) { global_notifyhold = ast_true(v->value); } else if (!strcasecmp(v->name, "alwaysauthreject")) { @@ -19342,6 +19435,38 @@ return 0; } +static int transmit_cid_update(struct sip_pvt *p) +{ + int res = 0; + struct sip_request req; + char tmp[500]; + char *t = tmp; + size_t maxbytes = sizeof(tmp); + struct ast_channel *ast = p->owner; + int channelpickup = pbx_builtin_getvar_helper(ast, "CHANNELPICKUP") ? 1 : 0; + + if (channelpickup) { + struct ast_channel *bc = ast_bridged_channel(ast); + ast_log(LOG_DEBUG, "Sending CID update on channel %s for bridged channel %s\n", ast->name, bc ? bc->name : "None"); + if (p && ast_test_flag(&(p->flags[1]), SIP_PAGE2_CID_UPDATE_INFO)) { + reqprep(&req, p, SIP_INFO, 0, 1); + add_header(&req, "Content-Type", "message/sipfrag"); + ast_build_string(&t, &maxbytes, "From: \r\n"); + ast_build_string(&t, &maxbytes, "To: \"%s\" %s\r\n", bc ? bc->cid.cid_name : ast->cid.cid_name, bc ? bc->cid.cid_num : ast->cid.cid_num); + add_header_contentLength(&req, strlen(tmp)); + add_line(&req, tmp); + send_request(p, &req, 0, p->ocseq); + } + if (bc) + p->pickup_cid_update_done = 1; + } + else { + p->pickup_cid_update_done = 1; + } + + return res; +} + AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Session Initiation Protocol (SIP)", .load = load_module, .unload = unload_module,