minor cleanup and reorganization (issue #5073)
[asterisk/asterisk.git] / patches / bug_3710_sip_refer.patch
1 Index: channels/chan_sip.c
2 ===================================================================
3 RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
4 retrieving revision 1.711
5 diff -u -u -r1.711 chan_sip.c
6 --- channels/chan_sip.c 29 Apr 2005 20:42:48 -0000      1.711
7 +++ channels/chan_sip.c 1 May 2005 03:27:31 -0000
8 @@ -71,6 +71,7 @@
9  
10  /* #define VOCAL_DATA_HACK */
11  
12 +#define SIP_RETVAL_IGNORE 42 /* shrug */
13  #define SIPDUMPER
14  #define DEFAULT_DEFAULT_EXPIRY  120
15  #define DEFAULT_MAX_EXPIRY      3600
16 @@ -667,6 +668,7 @@
17  static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime);
18  static int sip_do_reload(void);
19  static int expire_register(void *data);
20 +static int sip_addheader(struct ast_channel *chan, void *data);
21  static int callevents = 0;
22  
23  static struct ast_channel *sip_request(const char *type, int format, void *data, int *cause);
24 @@ -1247,7 +1249,7 @@
25         /* Delete it, it needs to disappear */
26         if (peer->call)
27                 sip_destroy(peer->call);
28 -       if(peer->chanvars) {
29 +       if (peer->chanvars) {
30                 ast_variables_destroy(peer->chanvars);
31                 peer->chanvars = NULL;
32         }
33 @@ -1312,7 +1314,7 @@
34                     !strcasecmp(tmp->value, "user")) {
35                         ast_variables_destroy(var);
36                         return NULL;
37 -               } else if(!newpeername && !strcasecmp(tmp->name, "name")) {
38 +               } else if (!newpeername && !strcasecmp(tmp->name, "name")) {
39                         newpeername = tmp->value;
40                 }
41                 tmp = tmp->next;
42 @@ -1322,9 +1324,9 @@
43                 peer = build_peer(newpeername, var, ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS) ? 0 : 1);
44  
45                 if (peer) {
46 -                       if(ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS)) {
47 +                       if (ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS)) {
48                                 ast_copy_flags((&peer->flags_page2),(&global_flags_page2), SIP_PAGE2_RTAUTOCLEAR|SIP_PAGE2_RTCACHEFRIENDS);
49 -                               if(ast_test_flag((&global_flags_page2), SIP_PAGE2_RTAUTOCLEAR)) {
50 +                               if (ast_test_flag((&global_flags_page2), SIP_PAGE2_RTAUTOCLEAR)) {
51                                         if (peer->expire > -1) {
52                                                 ast_sched_del(sched, peer->expire);
53                                         }
54 @@ -1374,7 +1376,7 @@
55  static void sip_destroy_user(struct sip_user *user)
56  {
57         ast_free_ha(user->ha);
58 -       if(user->chanvars) {
59 +       if (user->chanvars) {
60                 ast_variables_destroy(user->chanvars);
61                 user->chanvars = NULL;
62         }
63 @@ -1526,6 +1528,8 @@
64                 }
65         }
66         if (!p && !found) {
67 +               char *ptr, *hostp;
68 +
69                 hostn = peer;
70                 if (port)
71                         portno = atoi(port);
72 @@ -1542,7 +1546,15 @@
73                                 portno = tportno;
74                         }
75                 }
76 -               hp = ast_gethostbyname(hostn, &ahp);
77 +               if ((hostp = ast_strdupa(hostn))) {
78 +                       if ((ptr = strchr(hostp, '?'))) {
79 +                               *ptr = '\0';
80 +                       }
81 +               } else {
82 +                       hostp = peer;
83 +               }
84 +               
85 +               hp = ast_gethostbyname(hostp, &ahp);
86                 if (hp) {
87                         strncpy(r->tohost, peer, sizeof(r->tohost) - 1);
88                         memcpy(&r->sa.sin_addr, hp->h_addr, sizeof(r->sa.sin_addr));
89 @@ -1742,7 +1754,7 @@
90                         free(cp);
91                 }
92                 ast_mutex_destroy(&p->lock);
93 -               if(p->chanvars) {
94 +               if (p->chanvars) {
95                         ast_variables_destroy(p->chanvars);
96                         p->chanvars = NULL;
97                 }
98 @@ -2531,7 +2543,7 @@
99         if (!p->rtp) {
100                 ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
101                  ast_mutex_destroy(&p->lock);
102 -               if(p->chanvars) {
103 +               if (p->chanvars) {
104                         ast_variables_destroy(p->chanvars);
105                         p->chanvars = NULL;
106                 }
107 @@ -3097,7 +3109,7 @@
108                         if (!strcasecmp(aliases[x].fullname, var))
109                                 shortname = aliases[x].shortname;
110         }
111 -       if(!ast_strlen_zero(shortname)) {
112 +       if (!ast_strlen_zero(shortname)) {
113                 snprintf(req->header[req->headers], sizeof(req->data) - req->len - 4, "%s: %s\r\n", shortname, value);
114         } else {
115                 snprintf(req->header[req->headers], sizeof(req->data) - req->len - 4, "%s: %s\r\n", var, value);
116 @@ -3714,7 +3726,7 @@
117         }
118         /* Start by sending our preferred codecs */
119         for (x = 0 ; x < 32 ; x++) {
120 -               if(!(pref_codec = ast_codec_pref_index(&p->prefs,x)))
121 +               if (!(pref_codec = ast_codec_pref_index(&p->prefs,x)))
122                         break; 
123                 if ((capability & pref_codec) && !(alreadysent & pref_codec)) {
124                         if (debug)
125 @@ -3861,7 +3873,7 @@
126         while( *e && ( *e < 33 ) ) {
127                 e++; 
128         }
129 -       if( !*e ) {
130 +       if ( !*e ) {
131                 return -1;
132         }
133      
134 @@ -3869,7 +3881,7 @@
135                 /* We have a response */
136                 req->rlPart2 = e;
137                 len = strlen( req->rlPart2 );
138 -               if( len < 2 ) { 
139 +               if ( len < 2 ) { 
140                         return -1;
141                 }
142                 e+= len - 1;
143 @@ -3879,18 +3891,18 @@
144                 *(++e)= '\0';
145         } else {
146                 /* We have a request */
147 -               if( *e == '<' ) { 
148 +               if ( *e == '<' ) { 
149                         e++;
150 -                       if( !*e ) { 
151 +                       if ( !*e ) { 
152                                 return -1; 
153                         }  
154                 }
155                 req->rlPart2 = e;       /* URI */
156 -               if( ( e= strrchr( req->rlPart2, 'S' ) ) == NULL ) {
157 +               if ( ( e= strrchr( req->rlPart2, 'S' ) ) == NULL ) {
158                         return -1;
159                 }
160                 while( isspace( *(--e) ) ) {}
161 -               if( *e == '>' ) {
162 +               if ( *e == '>' ) {
163                         *e = '\0';
164                 } else {
165                         *(++e)= '\0';
166 @@ -4995,7 +5007,7 @@
167  
168         /* Save User agent */
169         useragent = get_header(req, "User-Agent");
170 -       if(useragent && strcasecmp(useragent, p->useragent)) {
171 +       if (useragent && strcasecmp(useragent, p->useragent)) {
172                 strncpy(p->useragent, useragent, sizeof(p->useragent) - 1);
173                 if (option_verbose > 3) {
174                         ast_verbose(VERBOSE_PREFIX_3 "Saved useragent \"%s\" for peer %s\n",p->useragent,p->name);  
175 @@ -5223,12 +5235,12 @@
176                                 c+= strlen("response=");
177                                 if ((*c == '\"')) {
178                                         response=++c;
179 -                                       if((c = strchr(c,'\"')))
180 +                                       if ((c = strchr(c,'\"')))
181                                                 *c = '\0';
182  
183                                 } else {
184                                         response=c;
185 -                                       if((c = strchr(c,',')))
186 +                                       if ((c = strchr(c,',')))
187                                                 *c = '\0';
188                                 }
189  
190 @@ -5236,11 +5248,11 @@
191                                 c+= strlen("uri=");
192                                 if ((*c == '\"')) {
193                                         resp_uri=++c;
194 -                                       if((c = strchr(c,'\"')))
195 +                                       if ((c = strchr(c,'\"')))
196                                                 *c = '\0';
197                                 } else {
198                                         resp_uri=c;
199 -                                       if((c = strchr(c,',')))
200 +                                       if ((c = strchr(c,',')))
201                                                 *c = '\0';
202                                 }
203  
204 @@ -5250,7 +5262,7 @@
205                                 c++;
206                 }
207                 snprintf(a1, sizeof(a1), "%s:%s:%s", username, global_realm, secret);
208 -               if(!ast_strlen_zero(resp_uri))
209 +               if (!ast_strlen_zero(resp_uri))
210                         snprintf(a2, sizeof(a2), "%s:%s", sip_methods[sipmethod].text, resp_uri);
211                 else
212                         snprintf(a2, sizeof(a2), "%s:%s", sip_methods[sipmethod].text, uri);
213 @@ -5484,8 +5496,23 @@
214         return 0;
215  }
216  
217 +static int sip_extract_tag(char **in) 
218 +{
219 +       char *tag;
220 +
221 +       if ((tag = ast_strcasestr(*in, "tag="))) {
222 +               char *ptr;
223 +               tag += 4;
224 +               if ((ptr = strchr(tag, ';'))) {
225 +                       *ptr = '\0';
226 +               }
227 +               return 0;
228 +       }
229 +       return -1;
230 +}
231 +
232  /*--- get_sip_pvt_byid_locked: Lock interface lock and find matching pvt lock  ---*/
233 -static struct sip_pvt *get_sip_pvt_byid_locked(char *callid) 
234 +static struct sip_pvt *get_sip_pvt_byid_locked(char *callid, struct sip_request *req, char *totag, char *fromtag) 
235  {
236         struct sip_pvt *sip_pvt_ptr = NULL;
237         
238 @@ -5494,8 +5521,38 @@
239         sip_pvt_ptr = iflist;
240         while(sip_pvt_ptr) {
241                 if (!strcmp(sip_pvt_ptr->callid, callid)) {
242 +                       char *real_totag = NULL, *real_fromtag = NULL;
243 +                       int match = 1;
244 +
245                         /* Go ahead and lock it (and its owner) before returning */
246                         ast_mutex_lock(&sip_pvt_ptr->lock);
247 +
248 +                       if (req && pedanticsipchecking) {
249 +                               if (totag) {
250 +                                       real_totag = ast_strdupa(get_header(req, "To"));
251 +                                       if (sip_extract_tag(&real_totag)) {
252 +                                               real_totag = NULL;
253 +                                       }
254 +                                       if (strcmp(real_totag, totag)) {
255 +                                               match = 0;
256 +                                       }
257 +                               }
258 +                               if (match && fromtag) {
259 +                                       real_fromtag = ast_strdupa(get_header(req, "From"));
260 +                                       if (sip_extract_tag(&real_fromtag)) {
261 +                                               real_fromtag = NULL;
262 +                                       }
263 +                                       if (strcmp(real_fromtag, fromtag)) {
264 +                                               match = 0;
265 +                                       }
266 +                               }
267 +                       }
268 +                       
269 +                       if (!match) {
270 +                               ast_mutex_unlock(&sip_pvt_ptr->lock);
271 +                               break;
272 +                       }
273 +                       
274                         if (sip_pvt_ptr->owner) {
275                                 while(ast_mutex_trylock(&sip_pvt_ptr->owner->lock)) {
276                                         ast_mutex_unlock(&sip_pvt_ptr->lock);
277 @@ -5532,14 +5589,12 @@
278         return replaced;
279  }
280  
281 -
282 -
283  /*--- get_refer_info: Call transfer support (new standard) ---*/
284  static int get_refer_info(struct sip_pvt *sip_pvt, struct sip_request *outgoing_req)
285  {
286  
287         char *p_refer_to = NULL, *p_referred_by = NULL, *h_refer_to = NULL, *h_referred_by = NULL, *h_contact = NULL;
288 -       char *replace_callid = "", *refer_to = NULL, *referred_by = NULL, *ptr = NULL;
289 +       char *replace_callid = "", *refer_to = NULL, *referred_by = NULL, *ptr = NULL, *replaces_header=NULL, *refer_uri;
290         struct sip_request *req = NULL;
291         struct sip_pvt *sip_pvt_ptr = NULL;
292         struct ast_channel *chan = NULL, *peer = NULL;
293 @@ -5550,14 +5605,14 @@
294                 req = &sip_pvt->initreq;
295         }
296         
297 -       if(!( (p_refer_to = get_header(req, "Refer-To")) && (h_refer_to = ast_strdupa(p_refer_to)) )) {
298 +       if (!( (p_refer_to = get_header(req, "Refer-To")) && (h_refer_to = ast_strdupa(p_refer_to)) )) {
299                 ast_log(LOG_WARNING, "No Refer-To Header That's illegal\n");
300                 return -1;
301         }
302  
303         refer_to = ditch_braces(h_refer_to);
304  
305 -       if(!( (p_referred_by = get_header(req, "Referred-By")) && (h_referred_by = ast_strdupa(p_referred_by)) )) {
306 +       if (!( (p_referred_by = get_header(req, "Referred-By")) && (h_referred_by = ast_strdupa(p_referred_by)) )) {
307                 ast_log(LOG_WARNING, "No Refer-To Header That's illegal\n");
308                 return -1;
309         }
310 @@ -5570,9 +5625,11 @@
311                 ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", referred_by);
312                 return -1;
313         }
314 +
315 +
316         refer_to += 4;
317         referred_by += 4;
318 -       
319 +       refer_uri = ast_strdupa(refer_to);      
320         
321         if ((ptr = strchr(refer_to, '?'))) {
322                 /* Search for arguemnts */
323 @@ -5580,10 +5637,7 @@
324                 ptr++;
325                 if (!strncasecmp(ptr, "REPLACES=", 9)) {
326                         replace_callid = ast_strdupa(ptr + 9);
327 -                       /* someday soon to support invite/replaces properly!
328 -                          replaces_header = ast_strdupa(replace_callid); 
329 -                          -anthm
330 -                       */
331 +                       replaces_header = ast_strdupa(replace_callid); 
332                         sip_unescape_uri(replace_callid);
333                         if ((ptr = strchr(replace_callid, '%'))) 
334                                 *ptr = '\0';
335 @@ -5617,19 +5671,50 @@
336                 strncpy(sip_pvt->referred_by, "", sizeof(sip_pvt->referred_by) - 1);
337                 strncpy(sip_pvt->refer_contact, "", sizeof(sip_pvt->refer_contact) - 1);
338                 sip_pvt->refer_call = NULL;
339 -               if ((sip_pvt_ptr = get_sip_pvt_byid_locked(replace_callid))) {
340 +               if ((sip_pvt_ptr = get_sip_pvt_byid_locked(replace_callid, req, NULL, NULL))) {
341                         sip_pvt->refer_call = sip_pvt_ptr;
342                         if (sip_pvt->refer_call == sip_pvt) {
343                                 ast_log(LOG_NOTICE, "Supervised transfer attempted to transfer into same call id (%s == %s)!\n", replace_callid, sip_pvt->callid);
344                                 sip_pvt->refer_call = NULL;
345 -                       } else
346 -                               return 0;
347 +                       } 
348 +                       return 0;
349                 } else {
350 -                       ast_log(LOG_NOTICE, "Supervised transfer requested, but unable to find callid '%s'.  Both legs must reside on Asterisk box to transfer at this time.\n", replace_callid);
351 -                       /* XXX The refer_to could contain a call on an entirely different machine, requiring an 
352 -                         INVITE with a replaces header -anthm XXX */
353 +                       /* Don't ask me =0 ?, SIP made do it! */
354 +                       int cause = 0, res = -1;
355 +                       struct ast_channel *ichan = NULL;
356  
357 -                       
358 +                       transmit_notify_with_sipfrag(sip_pvt, sip_pvt->ocseq);
359 +                       if ((ptr = strchr(refer_uri, ';'))) {
360 +                               *ptr = '\0';
361 +                       }
362 +
363 +                       if ((ichan = sip_request("SIP", sip_pvt->owner ? sip_pvt->owner->readformat : AST_FORMAT_ULAW, refer_uri, &cause))) {
364 +                               struct ast_frame *f;
365 +                               char *rbuf;     
366 +                               ast_log(LOG_DEBUG, "Going hunting for a remote INVITE/Replaces at [%s] Wish me luck!\n", refer_uri);
367 +                               if ((rbuf = alloca(strlen(replaces_header) + 10))) {
368 +                                       sprintf(rbuf, "Replaces: %s", replaces_header);
369 +                                       sip_addheader(ichan, rbuf);
370 +                                       sip_call(ichan, refer_uri, 20000);
371 +                                       ast_channel_masquerade(sip_pvt->owner, ichan);
372 +                                       if ((f = ast_read(ichan))) {
373 +                                               ast_log(LOG_DEBUG, "WooHoo! The INVITE/Replaces Worked!\n");
374 +                                               ast_frfree(f);
375 +                                               transmit_response(sip_pvt, "202 Accepted", req);
376 +                                               res = SIP_RETVAL_IGNORE; /* means do nothing more */
377 +                                       } else {
378 +                                               res = -1;
379 +                                       }
380 +                               } else {
381 +                                       ast_log(LOG_ERROR,"Memory Error!\n");
382 +                                       res = -1;
383 +                               }
384 +
385 +                               ast_hangup(ichan);
386 +                       } else {
387 +                               res = -1;
388 +                       }
389 +                       return res;
390                 }
391         } else if (ast_exists_extension(NULL, sip_pvt->context, refer_to, 1, NULL) || !strcmp(refer_to, ast_parking_ext())) {
392                 /* This is an unsupervised transfer */
393 @@ -5643,7 +5728,7 @@
394                         strncpy(sip_pvt->refer_contact, h_contact, sizeof(sip_pvt->refer_contact) - 1);
395                 }
396                 sip_pvt->refer_call = NULL;
397 -               if((chan = sip_pvt->owner) && (peer = ast_bridged_channel(sip_pvt->owner))) {
398 +               if ((chan = sip_pvt->owner) && (peer = ast_bridged_channel(sip_pvt->owner))) {
399                         pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
400                         pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
401                 }
402 @@ -5818,7 +5903,7 @@
403                 *end = '\0';
404         else
405                 output[0] = '\0';
406 -       if(strstr(input,"privacy=full") || strstr(input,"privacy=uri"))
407 +       if (strstr(input,"privacy=full") || strstr(input,"privacy=uri"))
408                 return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
409  
410         return 0;
411 @@ -5851,7 +5936,7 @@
412  
413         rpid = get_header(req, "Remote-Party-ID");
414         memset(rpid_num,0,sizeof(rpid_num));
415 -       if(!ast_strlen_zero(rpid)) 
416 +       if (!ast_strlen_zero(rpid)) 
417                 p->callingpres = get_rpid_num(rpid,rpid_num, sizeof(rpid_num));
418  
419         of = ditch_braces(from);
420 @@ -5887,14 +5972,14 @@
421                 ast_copy_flags(p, user, SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_NAT | SIP_PROG_INBAND | SIP_OSPAUTH);
422                 /* copy channel vars */
423                 for (v = user->chanvars ; v ; v = v->next) {
424 -                       if((tmpvar = ast_variable_new(v->name, v->value))) {
425 +                       if ((tmpvar = ast_variable_new(v->name, v->value))) {
426                                 tmpvar->next = p->chanvars; 
427                                 p->chanvars = tmpvar;
428                         }
429                 }
430                 p->prefs = user->prefs;
431                 /* replace callerid if rpid found, and not restricted */
432 -               if(!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
433 +               if (!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
434                         if (*calleridname)
435                                 strncpy(p->cid_name, calleridname, sizeof(p->cid_name) - 1);
436                         strncpy(p->cid_num, rpid_num, sizeof(p->cid_num) - 1);
437 @@ -5966,7 +6051,7 @@
438                         /* Take the peer */
439                         ast_copy_flags(p, peer, SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_NAT | SIP_PROG_INBAND | SIP_OSPAUTH);
440                         /* replace callerid if rpid found, and not restricted */
441 -                       if(!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
442 +                       if (!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
443                                 if (*calleridname)
444                                         strncpy(p->cid_name, calleridname, sizeof(p->cid_name) - 1);
445                                 strncpy(p->cid_num, rpid_num, sizeof(p->cid_num) - 1);
446 @@ -5999,7 +6084,7 @@
447                                 strncpy(p->authname, peer->name, sizeof(p->authname) - 1);
448                                 /* copy channel vars */
449                                 for (v = peer->chanvars ; v ; v = v->next) {
450 -                                       if((tmpvar = ast_variable_new(v->name, v->value))) {
451 +                                       if ((tmpvar = ast_variable_new(v->name, v->value))) {
452                                                 tmpvar->next = p->chanvars; 
453                                                 p->chanvars = tmpvar;
454                                         }
455 @@ -6737,10 +6822,10 @@
456                 pref = &peer->prefs;
457                 for(x = 0; x < 32 ; x++) {
458                         codec = ast_codec_pref_index(pref,x);
459 -                       if(!codec)
460 +                       if (!codec)
461                                 break;
462                         ast_cli(fd, "%s", ast_getformatname(codec));
463 -                       if(x < 31 && ast_codec_pref_index(pref,x+1))
464 +                       if (x < 31 && ast_codec_pref_index(pref,x+1))
465                                 ast_cli(fd, "|");
466                 }
467  
468 @@ -6820,10 +6905,10 @@
469                 pref = &peer->prefs;
470                 for(x = 0; x < 32 ; x++) {
471                         codec = ast_codec_pref_index(pref,x);
472 -                       if(!codec)
473 +                       if (!codec)
474                                 break;
475                         ast_cli(fd, "%s", ast_getformatname(codec));
476 -                       if(x < 31 && ast_codec_pref_index(pref,x+1))
477 +                       if (x < 31 && ast_codec_pref_index(pref,x+1))
478                                 ast_cli(fd, ",");
479                 }
480  
481 @@ -6896,10 +6981,10 @@
482                 pref = &user->prefs;
483                 for(x = 0; x < 32 ; x++) {
484                         codec = ast_codec_pref_index(pref,x);
485 -                       if(!codec)
486 +                       if (!codec)
487                                 break;
488                         ast_cli(fd, "%s", ast_getformatname(codec));
489 -                       if(x < 31 && ast_codec_pref_index(pref,x+1))
490 +                       if (x < 31 && ast_codec_pref_index(pref,x+1))
491                                 ast_cli(fd, "|");
492                 }
493  
494 @@ -7976,12 +8061,12 @@
495                 }
496                 switch(resp) {
497                 case 100:       /* 100 Trying */
498 -                       if(sipmethod == SIP_INVITE) {
499 +                       if (sipmethod == SIP_INVITE) {
500                                 sip_cancel_destroy(p);
501                         }
502                         break;
503                 case 183:       /* 183 Session Progress */
504 -                       if(sipmethod == SIP_INVITE) {
505 +                       if (sipmethod == SIP_INVITE) {
506                                 sip_cancel_destroy(p);
507                                 if (!ast_strlen_zero(get_header(req, "Content-Type")))
508                                         process_sdp(p, req);
509 @@ -7992,7 +8077,7 @@
510                         }
511                         break;
512                 case 180:       /* 180 Ringing */
513 -                       if(sipmethod == SIP_INVITE) {
514 +                       if (sipmethod == SIP_INVITE) {
515                                 sip_cancel_destroy(p);
516                                 if (p->owner) {
517                                         ast_queue_control(p->owner, AST_CONTROL_RINGING);
518 @@ -8071,8 +8156,8 @@
519                                                 for(;;) {
520                                                         contact = __get_header(req, "Contact", &start);
521                                                         /* this loop ensures we get a contact header about our register request */
522 -                                                       if(!ast_strlen_zero(contact)) {
523 -                                                               if( (tmptmp=strstr(contact, p->our_contact))) {
524 +                                                       if (!ast_strlen_zero(contact)) {
525 +                                                               if ( (tmptmp=strstr(contact, p->our_contact))) {
526                                                                         contact=tmptmp;
527                                                                         break;
528                                                                 }
529 @@ -8146,7 +8231,7 @@
530                                 transmit_request(p, SIP_ACK, seqno, 0, 0);
531                                 /* Then we AUTH */
532                                 /* But only if the packet wasn't marked as ignore in handle_request */
533 -                               if(!ignore){
534 +                               if (!ignore){
535                                         p->theirtag[0]='\0';    /* forget their old tag, so we don't match tags when getting response */
536                                         if ((p->authtries > 1) || do_proxy_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization", SIP_INVITE, 1)) {
537                                                 ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", get_header(&p->initreq, "From"));
538 @@ -8419,18 +8504,19 @@
539  
540                 if (peera->cdr && peerb->cdr) {
541                         peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
542 -               } else if(peera->cdr) {
543 +               } else if (peera->cdr) {
544                         peerb->cdr = peera->cdr;
545                 }
546                 peera->cdr = NULL;
547  
548                 if (peerb->cdr && peerc->cdr) {
549                         peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
550 -               } else if(peerc->cdr) {
551 +               } else if (peerc->cdr) {
552                         peerb->cdr = peerc->cdr;
553                 }
554                 peerc->cdr = NULL;
555                 
556 +               ast_log(LOG_DEBUG, "XXXX Trying to masquerade %s and %s\n", peerb->name, peerc->name);
557                 if (ast_channel_masquerade(peerb, peerc)) {
558                         ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name);
559                         res = -1;
560 @@ -8478,7 +8564,24 @@
561         struct ast_channel *c=NULL;
562         int gotdest;
563         struct ast_frame af = { AST_FRAME_NULL, };
564 +       char *p_replaces, *replace_id = NULL;
565  
566 +       if ((p_replaces = get_header(req, "Replaces"))) {
567 +               if (ast_strlen_zero(p_replaces)) {
568 +                       p_replaces = NULL;
569 +               } else {
570 +                       char *ptr;
571 +                       ast_log(LOG_DEBUG, "I SEE a Replaces [%s]\n", p_replaces);
572 +                       replace_id = ast_strdupa(p_replaces);
573 +                       if (strchr(replace_id, '%')) {
574 +                               sip_unescape_uri(replace_id);
575 +                       }
576 +                       if ((ptr = strchr(replace_id, ';'))) {
577 +                               *ptr = '\0';
578 +                       }
579 +               }
580 +       }
581 +       
582         if (ast_test_flag(p, SIP_OUTGOING) && p->owner && (p->owner->_state != AST_STATE_UP)) {
583                 /* This is a call to ourself.  Send ourselves an error code and stop
584                    processing immediately, as SIP really has no good mechanism for
585 @@ -8487,6 +8590,7 @@
586                 /* We do NOT destroy p here, so that our response will be accepted */
587                 return 0;
588         }
589 +       
590         if (!ignore) {
591                 /* Use this as the basis */
592                 if (debug)
593 @@ -8511,8 +8615,10 @@
594                                 ast_log(LOG_DEBUG, "Hm....  No sdp for the moment\n");
595                         }
596                 }
597 -       } else if (debug)
598 +       } else if (debug) {
599                 ast_verbose("Ignoring this request\n");
600 +       }
601 +       
602         if (!p->lastinvite && !ignore && !p->owner) {
603                 /* Handle authentication if this is our first invite */
604                 res = check_user(p, req, SIP_INVITE, e, 1, sin, ignore);
605 @@ -8563,22 +8669,22 @@
606                 get_rdnis(p, NULL);
607                 extract_uri(p, req);
608                 build_contact(p);
609 -
610 -               if (gotdest) {
611 +               
612 +               if (!replace_id && gotdest) {
613                         if (gotdest < 0) {
614                                 if (ignore)
615                                         transmit_response(p, "404 Not Found", req);
616                                 else
617                                         transmit_response_reliable(p, "404 Not Found", req, 1);
618                                 update_user_counter(p,DEC_IN_USE);
619 -                       } else {
620 -                               if (ignore)
621 -                                       transmit_response(p, "484 Address Incomplete", req);
622 -                               else
623 -                                       transmit_response_reliable(p, "484 Address Incomplete", req, 1);
624 -                               update_user_counter(p,DEC_IN_USE);
625 -                       }
626 -                       ast_set_flag(p, SIP_NEEDDESTROY);               
627 +                               } else {
628 +                                       if (ignore)
629 +                                               transmit_response(p, "484 Address Incomplete", req);
630 +                                       else
631 +                                               transmit_response_reliable(p, "484 Address Incomplete", req, 1);
632 +                                       update_user_counter(p,DEC_IN_USE);
633 +                               }
634 +                               ast_set_flag(p, SIP_NEEDDESTROY);               
635                 } else {
636                         /* If no extension was specified, use the s one */
637                         if (ast_strlen_zero(p->exten))
638 @@ -8591,16 +8697,41 @@
639                         /* Save Record-Route for any later requests we make on this dialogue */
640                         build_route(p, req, 0);
641                         if (c) {
642 +                               if (replace_id) {
643 +                                       struct sip_pvt *refer_pvt;
644 +                                       struct ast_frame *f;
645 +                                       
646 +                                       if ((refer_pvt = get_sip_pvt_byid_locked(replace_id, req, NULL, p->theirtag))) {
647 +                                               ast_log(LOG_DEBUG, "XXXXXXXX I PARSED a Replaces [%s]\n", p_replaces);
648 +                                               transmit_response(p, "100 Trying", req);
649 +                                               ast_mutex_unlock(&refer_pvt->owner->lock);
650 +                                               ast_mutex_unlock(&refer_pvt->lock);
651 +                                               ast_channel_masquerade(refer_pvt->owner, c );
652 +                                               ast_hangup(c);
653 +                                               c = refer_pvt->owner;
654 +                                               if ((f = ast_read(c))) {
655 +                                                       ast_log(LOG_DEBUG, "XXXXXXXX I DID a Replaces [%s]\n", p_replaces);
656 +                                                       ast_frfree(f);
657 +                                                       ast_setstate(c, AST_STATE_UP);
658 +                                               }
659 +                                       } else {
660 +                                               transmit_response_with_allow(p, "481 Call/Transaction Does Not Exist", req, 0);
661 +                                               return 0;
662 +                                       }
663 +                               }
664                                 /* Pre-lock the call */
665                                 ast_mutex_lock(&c->lock);
666                         }
667                 }
668 -               
669 -       } else 
670 +       } else {
671                 c = p->owner;
672 -       if (!ignore && p)
673 +       }
674 +       
675 +       if (!ignore && p) {
676                 p->lastinvite = seqno;
677 +       }
678         if (c) {
679 +
680                 switch(c->_state) {
681                 case AST_STATE_DOWN:
682                         transmit_response(p, "100 Trying", req);
683 @@ -8688,11 +8819,13 @@
684         if (ast_strlen_zero(p->context))
685                 strncpy(p->context, default_context, sizeof(p->context) - 1);
686         res = get_refer_info(p, req);
687 -       if (res < 0)
688 +       if (res == SIP_RETVAL_IGNORE) {
689 +               ignore = 1;
690 +       } else if (res < 0) {
691                 transmit_response_with_allow(p, "404 Not Found", req, 1);
692 -       else if (res > 0)
693 +       } else if (res > 0) {
694                 transmit_response_with_allow(p, "484 Address Incomplete", req, 1);
695 -       else {
696 +       } else {
697                 int nobye = 0;
698                 if (!ignore) {
699                         if (p->refer_call) {
700 @@ -9016,7 +9149,7 @@
701         cseq += len;
702  
703         /* Determine the request URI for sip, sips or tel URIs */
704 -       if( determine_firstline_parts( req ) < 0 ) {
705 +       if ( determine_firstline_parts( req ) < 0 ) {
706                 return -1; 
707         }
708         cmd = req->rlPart1;
709 @@ -9723,7 +9856,7 @@
710                         ast_set_flag(flags, SIP_PROG_INBAND_YES);
711         } else if (!strcasecmp(v->name, "allowguest")) {
712  #ifdef OSP_SUPPORT
713 -               if(!strcasecmp(v->value, "osp"))
714 +               if (!strcasecmp(v->value, "osp"))
715                         global_allowguest = 2;
716                 else 
717  #endif
718 @@ -9893,7 +10026,7 @@
719                                 if (varname && (varval = strchr(varname,'='))) {
720                                         *varval = '\0';
721                                         varval++;
722 -                                       if((tmpvar = ast_variable_new(varname, varval))) {
723 +                                       if ((tmpvar = ast_variable_new(varname, varval))) {
724                                                 tmpvar->next = user->chanvars;
725                                                 user->chanvars = tmpvar;
726                                         }
727 @@ -10037,7 +10170,7 @@
728                         peer->expiry = expiry;
729                 }
730                 /* If we have channel variables, remove them (reload) */
731 -               if(peer->chanvars) {
732 +               if (peer->chanvars) {
733                         ast_variables_destroy(peer->chanvars);
734                         peer->chanvars = NULL;
735                 }
736 @@ -10210,7 +10343,7 @@
737                                 if (varname && (varval = strchr(varname,'='))) {
738                                         *varval = '\0';
739                                         varval++;
740 -                                       if((tmpvar = ast_variable_new(varname, varval))) {
741 +                                       if ((tmpvar = ast_variable_new(varname, varval))) {
742                                                 tmpvar->next = peer->chanvars;
743                                                 peer->chanvars = tmpvar;
744                                         }
745 @@ -10347,7 +10480,7 @@
746                         ast_set2_flag((&global_flags_page2), ast_true(v->value), SIP_PAGE2_RTNOUPDATE); 
747                 } else if (!strcasecmp(v->name, "rtautoclear")) {
748                         int i = atoi(v->value);
749 -                       if(i > 0)
750 +                       if (i > 0)
751                                 global_rtautoclear = i;
752                         else
753                                 i = 0;
754 @@ -11124,7 +11257,7 @@
755                         p = p->next;
756                         /* Free associated memory */
757                         ast_mutex_destroy(&pl->lock);
758 -                       if(pl->chanvars) {
759 +                       if (pl->chanvars) {
760                                 ast_variables_destroy(pl->chanvars);
761                                 pl->chanvars = NULL;
762                         }