Index: channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.284 diff -u -r1.284 chan_sip.c --- channels/chan_sip.c 26 Jan 2004 19:12:23 -0000 1.284 +++ channels/chan_sip.c 28 Jan 2004 13:56:29 -0000 @@ -211,6 +211,7 @@ int expiry; /* How long we take to expire */ int branch; /* One random number */ int canreinvite; /* Do we support reinvite */ + int cansipforward; /* will we forward this to any sip-url */ int ringing; /* Have sent 180 ringing */ int progress; /* Have sent 183 message progress */ int tag; /* Another random number */ @@ -336,6 +337,7 @@ int insecure; int nat; int canreinvite; + int cansipforward; unsigned int callgroup; unsigned int pickupgroup; int dtmfmode; @@ -409,6 +411,7 @@ static int sipsock = -1; static int globalnat = 0; static int globalcanreinvite = REINVITE_INVITE; +static int globalcansipforward = 0; static struct sockaddr_in bindaddr; @@ -823,6 +826,7 @@ strncpy(r->fromuser, p->fromuser, sizeof(r->fromuser)-1); r->insecure = p->insecure; r->canreinvite = p->canreinvite; + r->cansipforward = p->cansipforward; r->maxtime = p->maxms; r->callgroup = p->callgroup; r->pickupgroup = p->pickupgroup; @@ -1725,6 +1729,7 @@ strncpy(p->callid, callid, sizeof(p->callid) - 1); /* Assume reinvite OK and via INVITE */ p->canreinvite = globalcanreinvite; + p->cansipforward = globalcansipforward; p->dtmfmode = globaldtmfmode; p->capability = capability; if (p->dtmfmode & SIP_DTMF_RFC2833) @@ -4249,6 +4254,7 @@ ast_rtp_setnat(p->vrtp, p->nat); } p->canreinvite = peer->canreinvite; + p->cansipforward = peer->cansipforward; if (strlen(peer->username)) strncpy(p->username, peer->username, sizeof(p->username) - 1); strncpy(p->peername, peer->name, sizeof(p->peername) - 1); @@ -4792,18 +4798,26 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req) { - char tmp[256] = ""; - char *s, *e; - strncpy(tmp, get_header(req, "Contact"), sizeof(tmp) - 1); - s = ditch_braces(tmp); - e = strchr(tmp, '@'); - if (e) - *e = '\0'; - if (!strncasecmp(s, "sip:", 4)) - s += 4; - ast_log(LOG_DEBUG, "Found 302 Redirect to extension '%s'\n", s); - if (p->owner) - strncpy(p->owner->call_forward, s, sizeof(p->owner->call_forward) - 1); + char tmp[256] = ""; + char *s; + strncpy(tmp, get_header(req, "Contact"), sizeof(tmp) - 1); + s = ditch_braces(tmp); + if (p->cansipforward) { + if (strstr(s,";")) { + *strstr(s,";") = '\0'; + } + ast_verbose(VERBOSE_PREFIX_3 "Found Redirect to SIP URL '%s'\n", s); + } else { + char *e; + e = strchr(tmp, '@'); + if (e) + *e = '\0'; + if (!strncasecmp(s, "sip:", 4)) + s += 4; + ast_verbose(VERBOSE_PREFIX_3 "Found Redirect to extension '%s'\n", s); + } + if (p->owner) + strncpy(p->owner->call_forward, s, sizeof(p->owner->call_forward) - 1); } static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore) @@ -5032,6 +5046,7 @@ } /* XXX Locking issues?? XXX */ switch(resp) { + case 301: /* Forward */ case 302: /* Moved temporarily */ parse_moved_contact(p, req); if (p->owner) @@ -6094,6 +6109,7 @@ peer->capability = capability; /* Assume can reinvite */ peer->canreinvite = globalcanreinvite; + peer->cansipforward = globalcansipforward; peer->dtmfmode = globaldtmfmode; peer->nat = globalnat; peer->selfdestruct = 1; @@ -6163,6 +6179,8 @@ peer->canreinvite = REINVITE_UPDATE; else peer->canreinvite = ast_true(v->value); + } else if (!strcasecmp(v->name, "cansipforward")) { + peer->cansipforward = ast_true(v->value); } else if (!strcasecmp(v->name, "nat")) peer->nat = ast_true(v->value); else if (!strcasecmp(v->name, "context")) @@ -6353,6 +6371,8 @@ globalcanreinvite = REINVITE_UPDATE; else globalcanreinvite = ast_true(v->value); + } else if (!strcasecmp(v->name, "cansipforward")) { + globalcansipforward = ast_true(v->value); } else if (!strcasecmp(v->name, "maxexpirey") || !strcasecmp(v->name, "maxexpiry")) { max_expiry = atoi(v->value); if (max_expiry < 1) Index: apps/app_dial.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_dial.c,v retrieving revision 1.53 diff -u -r1.53 app_dial.c --- apps/app_dial.c 15 Jan 2004 23:38:23 -0000 1.53 +++ apps/app_dial.c 28 Jan 2004 13:56:30 -0000 @@ -105,6 +105,67 @@ #define MAX 256 +/* + * @param call The ast_channel containing the call_forward + * @return A pointer to a newly allocated string looking like "call->forward@call->context" \ + * if the call_forward of the call doesnt include a ":" \ + * else a pointer to a newly allocated string including everything after the ":" + */ +static char *getForwardChan(struct ast_channel *call) { + if (strstr(call->call_forward, ":")) { + return strdup(strstr(call->call_forward, ":") + 1); + } else { + char *returnValue; + // we want "[call->call_forward]@[call->context]\n" + returnValue = malloc(sizeof(returnValue) * (strlen(call->call_forward) + + 1 + + strlen(call->context) + + 1)); + sprintf(returnValue, "%s@%s", call->call_forward, call->context); + return returnValue; + } +} + +/* + * @param call The ast_channel containing the call_forward + * @return A pointer to a newly allocated string containing "Local" if the call_forward \ + * of the call doesnt include a ":" \ + * else a pointer to a newly allocated string containing everything before the ":" + */ +static char *getForwardType(struct ast_channel *call) { + if (strstr(call->call_forward, ":")) { + return strndup(call->call_forward, strstr(call->call_forward, ":") - call->call_forward); + } else { + return strdup("Local"); + } +} + +/* + * @param call The ast_channel containing the callerid + * @return A pointer to a newly allocated string containing the callerid of the call or NULL if it \ + * doesnt exist + */ +static char *getCallerid(struct ast_channel *call) { + if (call->callerid) { + return strdup(call->callerid); + } else { + return NULL; + } +} + +/* + * @param call The ast_channel containing the ani + * @return A pointer to a newly allocated string containing the ani of the call or NULL if it \ + * doesnt exist + */ +static char *getAni(struct ast_channel *call) { + if (call->ani) { + return strdup(call->ani); + } else { + return NULL; + } +} + static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect) { struct localuser *o; @@ -190,14 +251,23 @@ } } else if (o->chan && (o->chan == winner)) { if (strlen(o->chan->call_forward)) { - char tmpchan[256]; /* Before processing channel, go ahead and check for forwarding */ - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s@%s' (thanks to %s)\n", in->name, o->chan->call_forward, o->chan->context, o->chan->name); + char *tmpchan = getForwardChan(o->chan); + char *tmptype = getForwardType(o->chan); + char *tmpcallerid = getCallerid(o->chan); + char *tmpani = getAni(o->chan); /* Setup parameters */ - snprintf(tmpchan, sizeof(tmpchan),"%s@%s", o->chan->call_forward, o->chan->context); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s' (thanks to %s)\n", in->name, o->chan->call_forward, o->chan->name); ast_hangup(o->chan); - o->chan = ast_request("Local", in->nativeformats, tmpchan); + o->chan = ast_request(tmptype, in->nativeformats, tmpchan); + if (tmpcallerid) { + ast_set_callerid(o->chan, tmpcallerid, tmpani ? 1 : 0); + } + free(tmpchan); + free(tmptype); + free(tmpcallerid); + free(tmpani); if (!o->chan) { ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan); o->stillgoing = 0; @@ -532,12 +602,22 @@ continue; } if (strlen(tmp->chan->call_forward)) { - char tmpchan[256]; + char *tmpchan = getForwardChan(tmp->chan); + char *tmptype = getForwardType(tmp->chan); + char *tmpcallerid = getCallerid(tmp->chan); + char *tmpani = getAni(tmp->chan); + /* Setup parameters */ if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context); - snprintf(tmpchan, sizeof(tmpchan),"%s@%s", tmp->chan->call_forward, tmp->chan->context); + ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s'\n", tmp->chan->call_forward); ast_hangup(tmp->chan); - tmp->chan = ast_request("Local", chan->nativeformats, tmpchan); + tmp->chan = ast_request(tmptype, chan->nativeformats, tmpchan); + if (tmpcallerid) { + ast_set_callerid(tmp->chan, tmpcallerid, tmpani ? 1 : 0); + } + free(tmpchan); + free(tmptype); + free(tmpcallerid); + free(tmpani); if (!tmp->chan) { ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan); free(tmp);