1 /*
2 * Copyright (C) 2008 iptelorg GmbH
3 *
4 * This file is part of Kamailio, a free SIP server.
5 *
6 * Kamailio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version
10 *
11 * Kamailio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #include "../../core/action.h"
23 #include "../../core/script_cb.h"
24 #include "../../core/dset.h"
25 #include "../../core/cfg/cfg_struct.h"
26 #include "../../core/kemi.h"
27
28 #include "config.h"
29 #include "sip_msg.h"
30 #include "t_reply.h"
31 #include "h_table.h"
32 #include "t_lookup.h"
33 #include "t_fwd.h"
34 #include "t_funcs.h"
35 #include "timer.h"
36 #include "t_cancel.h"
37
38 #include "t_suspend.h"
39
40 #include "../../core/data_lump.h"
41 #include "../../core/data_lump_rpl.h"
42
43
44 #define LOCK_ASYNC_CONTINUE(_t) LOCK_REPLIES(_t)
45 #define UNLOCK_ASYNC_CONTINUE(_t) UNLOCK_REPLIES(_t)
46
47 /* Suspends the transaction for later use.
48 * Save the returned hash_index and label to get
49 * back to the SIP request processing, see the readme.
50 *
51 * Return value:
52 * 0 - success
53 * <0 - failure
54 */
t_suspend(struct sip_msg * msg,unsigned int * hash_index,unsigned int * label)55 int t_suspend(struct sip_msg *msg,
56 unsigned int *hash_index, unsigned int *label)
57 {
58 struct cell *t;
59 int branch;
60 int sip_msg_len;
61
62 t = get_t();
63 if (!t || t == T_UNDEFINED) {
64 LM_ERR("transaction has not been created yet\n");
65 return -1;
66 }
67
68 if (t->flags & T_CANCELED) {
69 /* The transaction has already been canceled */
70 LM_DBG("trying to suspend an already canceled transaction\n");
71 ser_error = E_CANCELED;
72 return 1;
73 }
74 if (t->uas.status >= 200) {
75 LM_DBG("trasaction sent out a final response already - %d\n",
76 t->uas.status);
77 return -3;
78 }
79
80 if (msg->first_line.type != SIP_REPLY) {
81 /* send a 100 Trying reply, because the INVITE processing
82 will probably take a long time */
83 if (msg->REQ_METHOD==METHOD_INVITE && (t->flags&T_AUTO_INV_100)
84 && (t->uas.status < 100)
85 ) {
86 if (!t_reply( t, msg , 100 ,
87 cfg_get(tm, tm_cfg, tm_auto_inv_100_r)))
88 LM_DBG("suspending request processing - sending 100 reply\n");
89 }
90
91 if ((t->nr_of_outgoings==0) && /* if there had already been
92 an UAC created, then the lumps were
93 saved as well */
94 save_msg_lumps(t->uas.request, msg)
95 ) {
96 LM_ERR("failed to save the message lumps\n");
97 return -1;
98 }
99 /* save the message flags */
100 t->uas.request->flags = msg->flags;
101
102 /* add a blind UAC to let the fr timer running */
103 if (add_blind_uac() < 0) {
104 LM_ERR("failed to add the blind UAC\n");
105 return -1;
106 }
107 /* propagate failure route to new branch
108 * - failure route to be executed if the branch is not continued
109 * before timeout */
110 t->uac[t->async_backup.blind_uac].on_failure = t->on_failure;
111 t->flags |= T_ASYNC_SUSPENDED;
112 } else {
113 LM_DBG("this is a suspend on reply - setting msg flag to SUSPEND\n");
114 msg->msg_flags |= FL_RPL_SUSPENDED;
115 /* this is a reply suspend find which branch */
116
117 if (t_check( msg , &branch )==-1){
118 LM_ERR("failed find UAC branch\n");
119 return -1;
120 }
121 LM_DBG("found a a match with branch id [%d] - "
122 "cloning reply message to t->uac[branch].reply\n", branch);
123
124 sip_msg_len = 0;
125 t->uac[branch].reply = sip_msg_cloner( msg, &sip_msg_len );
126
127 if (! t->uac[branch].reply ) {
128 LM_ERR("can't alloc' clone memory\n");
129 return -1;
130 }
131 t->uac[branch].end_reply = ((char*)t->uac[branch].reply) + sip_msg_len;
132
133 LM_DBG("saving transaction data\n");
134 t->uac[branch].reply->flags = msg->flags;
135 t->flags |= T_ASYNC_SUSPENDED;
136 }
137
138 *hash_index = t->hash_index;
139 *label = t->label;
140
141 /* reset the continue flag to be able to suspend in a failure route */
142 t->flags &= ~T_ASYNC_CONTINUE;
143
144 /* backup some extra info that can be used in continuation logic */
145 t->async_backup.backup_route = get_route_type();
146 t->async_backup.backup_branch = get_t_branch();
147 t->async_backup.ruri_new = ruri_get_forking_state();
148
149
150 return 0;
151 }
152
153 /* Continues the SIP request processing previously saved by
154 * t_suspend(). The script does not continue from the same
155 * point, but a separate route block is executed instead.
156 *
157 * Return value:
158 * 0 - success
159 * <0 - failure
160 */
t_continue_helper(unsigned int hash_index,unsigned int label,struct action * rtact,str * cbname,str * cbparam)161 int t_continue_helper(unsigned int hash_index, unsigned int label,
162 struct action *rtact, str *cbname, str *cbparam)
163 {
164 tm_cell_t *t;
165 tm_cell_t *backup_T = T_UNDEFINED;
166 int backup_T_branch = T_BR_UNDEFINED;
167 sip_msg_t *faked_req;
168 sip_msg_t *brpl = NULL;
169 void *erpl = NULL;
170 int faked_req_len = 0;
171 struct cancel_info cancel_data;
172 int branch;
173 struct ua_client *uac =NULL;
174 int ret;
175 int cb_type;
176 int msg_status;
177 int last_uac_status;
178 int reply_status;
179 int do_put_on_wait;
180 struct hdr_field *hdr, *prev = 0, *tmp = 0;
181 int route_type_bk;
182 sr_kemi_eng_t *keng = NULL;
183 str evname = str_init("tm:continue");
184
185 cfg_update();
186
187 backup_T = get_t();
188 backup_T_branch = get_t_branch();
189
190 if (t_lookup_ident_filter(&t, hash_index, label, 1) < 0) {
191 set_t(backup_T, backup_T_branch);
192 LM_WARN("active transaction not found\n");
193 return -1;
194 }
195
196 if (!(t->flags & T_ASYNC_SUSPENDED)) {
197 LM_WARN("transaction is not suspended [%u:%u]\n", hash_index, label);
198 set_t(backup_T, backup_T_branch);
199 return -2;
200 }
201
202 if (t->flags & T_CANCELED) {
203 t->flags &= ~T_ASYNC_SUSPENDED;
204 /* The transaction has already been canceled,
205 * needless to continue */
206 UNREF(t); /* t_unref would kill the transaction */
207 /* reset T as we have no working T anymore */
208 set_t(backup_T, backup_T_branch);
209 return 1;
210 }
211
212 /* The transaction has to be locked to protect it
213 * form calling t_continue() multiple times simultaneously */
214 LOCK_ASYNC_CONTINUE(t);
215
216 t->flags |= T_ASYNC_CONTINUE; /* we can now know anywhere in kamailio
217 * that we are executing post a suspend */
218
219 /* transaction is no longer suspended, resetting the SUSPEND flag */
220 t->flags &= ~T_ASYNC_SUSPENDED;
221
222 /* which route block type were we in when we were suspended */
223 cb_type = FAILURE_CB_TYPE;
224 switch (t->async_backup.backup_route) {
225 case REQUEST_ROUTE:
226 cb_type = FAILURE_CB_TYPE;
227 break;
228 case FAILURE_ROUTE:
229 cb_type = FAILURE_CB_TYPE;
230 break;
231 case TM_ONREPLY_ROUTE:
232 cb_type = ONREPLY_CB_TYPE;
233 break;
234 case BRANCH_ROUTE:
235 cb_type = FAILURE_CB_TYPE;
236 break;
237 }
238
239 if(t->async_backup.backup_route != TM_ONREPLY_ROUTE) {
240 /* resume processing of a sip request */
241 /* get the branch of the blind UAC setup during suspend */
242 branch = t->async_backup.blind_uac;
243 if (branch >= 0) {
244 stop_rb_timers(&t->uac[branch].request);
245
246 if (t->uac[branch].last_received != 0) {
247 /* Either t_continue() has already been
248 * called or the branch has already timed out.
249 * Needless to continue. */
250 t->flags &= ~T_ASYNC_CONTINUE;
251 UNLOCK_ASYNC_CONTINUE(t);
252 UNREF(t); /* t_unref would kill the transaction */
253 set_t(backup_T, backup_T_branch);
254 return 1;
255 }
256
257 /* Set last_received to something >= 200,
258 * the actual value does not matter, the branch
259 * will never be picked up for response forwarding.
260 * If last_received is lower than 200,
261 * then the branch may tried to be cancelled later,
262 * for example when t_reply() is called from
263 * a failure route => deadlock, because both
264 * of them need the reply lock to be held. */
265 t->uac[branch].last_received=500;
266 if(t->uac[branch].reply!=NULL) {
267 LM_WARN("reply (%p) already set for suspended transaction"
268 " (branch: %d)\n",
269 t->uac[branch].reply, branch);
270 } else {
271 /* set it as a faked reply */
272 t->uac[branch].reply=FAKED_REPLY;
273 }
274 uac = &t->uac[branch];
275 }
276 /* else
277 Not a huge problem, fr timer will fire, but CANCEL
278 will not be sent. last_received will be set to 408. */
279
280 /* We should not reset kr here to 0 as it's quite possible before continuing the dev. has correctly set the
281 * kr by, for example, sending a transactional reply in code - resetting here will cause a dirty log message
282 * "WARNING: script writer didn't release transaction" to appear in log files. TODO: maybe we need to add
283 * a special kr for async?
284 * reset_kr();
285 */
286
287 /* fake the request and the environment, like in failure_route */
288 faked_req = fake_req(t->uas.request, 0 /* extra flags */, uac,
289 &faked_req_len);
290 if (faked_req==NULL) {
291 LM_ERR("building fake_req failed\n");
292 ret = -1;
293 goto kill_trans;
294 }
295 faked_env( t, faked_req, 1);
296
297 route_type_bk = get_route_type();
298 set_route_type(FAILURE_ROUTE);
299 /* execute the pre/post -script callbacks based on original route block */
300 if (exec_pre_script_cb(faked_req, cb_type)>0) {
301 if(rtact!=NULL) {
302 if (run_top_route(rtact, faked_req, 0)<0) {
303 LM_ERR("failure inside run_top_route\n");
304 }
305 } else {
306 if(cbname!=NULL && cbname->s!=NULL) {
307 keng = sr_kemi_eng_get();
308 if(keng!=NULL) {
309 if(cbparam && cbparam->s) {
310 evname = *cbparam;
311 }
312 if(sr_kemi_route(keng, faked_req, FAILURE_ROUTE, cbname,
313 &evname)<0) {
314 LM_ERR("error running event route kemi callback\n");
315 }
316 } else {
317 LM_DBG("event callback (%.*s) set, but no cfg engine\n",
318 cbname->len, cbname->s);
319 }
320 } else {
321 LM_WARN("no continue callback\n");
322 }
323 }
324 exec_post_script_cb(faked_req, cb_type);
325 }
326 set_route_type(route_type_bk);
327
328 /* TODO: save_msg_lumps should clone the lumps to shm mem */
329
330 /* restore original environment */
331 faked_env( t, 0, 1);
332 /* update the flags */
333 t->uas.request->flags = faked_req->flags;
334 /* free the fake msg */
335 free_faked_req(faked_req, faked_req_len);
336
337
338 if (t->uas.status < 200) {
339 /* No final reply has been sent yet.
340 * Check whether or not there is any pending branch.
341 */
342 for ( branch = 0;
343 branch < t->nr_of_outgoings;
344 branch++
345 ) {
346 if (t->uac[branch].last_received < 200)
347 break;
348 }
349
350 if (branch == t->nr_of_outgoings) {
351 /* There is not any open branch so there is
352 * no chance that a final response will be received. */
353 ret = 0;
354 goto kill_trans;
355 }
356 }
357
358 } else {
359 /* resume processing of a sip response */
360 branch = t->async_backup.backup_branch;
361
362 init_cancel_info(&cancel_data);
363
364 LM_DBG("continuing from a suspended reply"
365 " - resetting the suspend branch flag\n");
366
367 if (t->uac[branch].reply) {
368 t->uac[branch].reply->msg_flags &= ~FL_RPL_SUSPENDED;
369 } else {
370 LM_WARN("no reply in t_continue for branch. not much we can do\n");
371 return 0;
372 }
373 if (t->uas.request) t->uas.request->msg_flags&= ~FL_RPL_SUSPENDED;
374
375 faked_env( t, t->uac[branch].reply, 1);
376
377 if (exec_pre_script_cb(t->uac[branch].reply, cb_type)>0) {
378 if(rtact!=NULL) {
379 if (run_top_route(rtact, t->uac[branch].reply, 0)<0){
380 LM_ERR("Error in run_top_route\n");
381 }
382 } else {
383 if(cbname!=NULL && cbname->s!=NULL) {
384 keng = sr_kemi_eng_get();
385 if(keng!=NULL) {
386 if(cbparam && cbparam->s) {
387 evname = *cbparam;
388 }
389 if(sr_kemi_route(keng, t->uac[branch].reply,
390 TM_ONREPLY_ROUTE, cbname, &evname)<0) {
391 LM_ERR("error running event route kemi callback\n");
392 }
393 } else {
394 LM_DBG("event callback (%.*s) set, but no cfg engine\n",
395 cbname->len, cbname->s);
396 }
397 } else {
398 LM_WARN("no continue callback\n");
399 }
400 }
401 exec_post_script_cb(t->uac[branch].reply, cb_type);
402 }
403
404 LM_DBG("restoring previous environment\n");
405 faked_env( t, 0, 1);
406
407 /*lock transaction replies - will be unlocked when reply is relayed*/
408 LOCK_REPLIES( t );
409 if ( is_local(t) ) {
410 LM_DBG("t is local - sending reply with status code: [%d]\n",
411 t->uac[branch].reply->first_line.u.reply.statuscode);
412 reply_status = local_reply( t, t->uac[branch].reply, branch,
413 t->uac[branch].reply->first_line.u.reply.statuscode,
414 &cancel_data );
415 if (reply_status == RPS_COMPLETED) {
416 /* no more UAC FR/RETR (if I received a 2xx, there may
417 * be still pending branches ...
418 */
419 cleanup_uac_timers( t );
420 if (is_invite(t)) cancel_uacs(t, &cancel_data, F_CANCEL_B_KILL);
421 /* There is no need to call set_final_timer because we know
422 * that the transaction is local */
423 put_on_wait(t);
424 }else if (unlikely(cancel_data.cancel_bitmap)){
425 /* cancel everything, even non-INVITEs (e.g in case of 6xx), use
426 * cancel_b_method for canceling unreplied branches */
427 cancel_uacs(t, &cancel_data, cfg_get(tm,tm_cfg, cancel_b_flags));
428 }
429
430 } else {
431 LM_DBG("t is not local - relaying reply with status code: [%d]\n",
432 t->uac[branch].reply->first_line.u.reply.statuscode);
433 do_put_on_wait = 0;
434 if(t->uac[branch].reply->first_line.u.reply.statuscode>=200){
435 do_put_on_wait = 1;
436 }
437 reply_status=relay_reply( t, t->uac[branch].reply, branch,
438 t->uac[branch].reply->first_line.u.reply.statuscode,
439 &cancel_data, do_put_on_wait );
440 if (reply_status == RPS_COMPLETED) {
441 /* no more UAC FR/RETR (if I received a 2xx, there may
442 be still pending branches ...
443 */
444 cleanup_uac_timers( t );
445 /* 2xx is a special case: we can have a COMPLETED request
446 * with branches still open => we have to cancel them */
447 if (is_invite(t) && cancel_data.cancel_bitmap)
448 cancel_uacs( t, &cancel_data, F_CANCEL_B_KILL);
449 /* FR for negative INVITES, WAIT anything else */
450 /* Call to set_final_timer is embedded in relay_reply to avoid
451 * race conditions when reply is sent out and an ACK to stop
452 * retransmissions comes before retransmission timer is set.*/
453 }else if (unlikely(cancel_data.cancel_bitmap)){
454 /* cancel everything, even non-INVITEs (e.g in case of 6xx), use
455 * cancel_b_method for canceling unreplied branches */
456 cancel_uacs(t, &cancel_data, cfg_get(tm,tm_cfg, cancel_b_flags));
457 }
458
459 }
460 t->uac[branch].request.flags|=F_RB_REPLIED;
461
462 if (reply_status==RPS_ERROR){
463 goto done;
464 }
465
466 /* update FR/RETR timers on provisional replies */
467
468 msg_status=t->uac[branch].reply->REPLY_STATUS;
469 last_uac_status=t->uac[branch].last_received;
470
471 if (is_invite(t) && msg_status<200 &&
472 ( cfg_get(tm, tm_cfg, restart_fr_on_each_reply) ||
473 ( (last_uac_status<msg_status) &&
474 ((msg_status>=180) || (last_uac_status==0)) )
475 ) ) { /* provisional now */
476 restart_rb_fr(& t->uac[branch].request, t->fr_inv_timeout);
477 t->uac[branch].request.flags|=F_RB_FR_INV; /* mark fr_inv */
478 }
479
480 }
481
482 done:
483 t->flags &= ~T_ASYNC_CONTINUE;
484 if(t->async_backup.backup_route == TM_ONREPLY_ROUTE) {
485 /* response handling */
486 /* backup branch reply to free it later and reset it here under lock */
487 brpl = t->uac[branch].reply;
488 erpl = (void*)t->uac[branch].end_reply;
489 t->uac[branch].reply = 0;
490 t->uac[branch].end_reply = 0;
491 }
492 UNLOCK_ASYNC_CONTINUE(t);
493
494 if(t->async_backup.backup_route != TM_ONREPLY_ROUTE){
495 /* request handling */
496 /* unref the transaction */
497 t_unref(t->uas.request);
498 } else {
499 /* response handling */
500 tm_ctx_set_branch_index(T_BR_UNDEFINED);
501 if(brpl) {
502 /* unref the transaction */
503 t_unref(brpl);
504 LM_DBG("Freeing earlier cloned reply\n");
505
506 /* free lumps that were added during reply processing */
507 del_nonshm_lump( &(brpl->add_rm) );
508 del_nonshm_lump( &(brpl->body_lumps) );
509 del_nonshm_lump_rpl( &(brpl->reply_lump) );
510
511 /* free header's parsed structures that were added */
512 for( hdr=brpl->headers ; hdr ; hdr=hdr->next ) {
513 if (hdr->parsed && hdr_allocs_parse(hdr) &&
514 (hdr->parsed<(void*)brpl ||
515 (erpl && hdr->parsed>=(void*)erpl))) {
516 clean_hdr_field(hdr);
517 hdr->parsed = 0;
518 }
519 }
520
521 /* now go through hdr fields themselves
522 * and remove the pkg allocated space */
523 hdr = brpl->headers;
524 while (hdr) {
525 if ( hdr && ((void*)hdr<(void*)brpl ||
526 (void*)hdr>=(void*)erpl)) {
527 /* this header needs to be freed and removed form the list */
528 if (!prev) {
529 brpl->headers = hdr->next;
530 } else {
531 prev->next = hdr->next;
532 }
533 tmp = hdr;
534 hdr = hdr->next;
535 pkg_free(tmp);
536 } else {
537 prev = hdr;
538 hdr = hdr->next;
539 }
540 }
541 sip_msg_free(brpl);
542 }
543 }
544
545 set_t(backup_T, backup_T_branch);
546 return 0;
547
548 kill_trans:
549 /* The script has hopefully set the error code. If not,
550 * let us reply with a default error. */
551 if ((kill_transaction_unsafe(t,
552 tm_error ? tm_error : E_UNSPEC)) <=0) {
553 LM_ERR("reply generation failed\n");
554 /* The transaction must be explicitely released,
555 * no more timer is running */
556 t->flags &= ~T_ASYNC_CONTINUE;
557 UNLOCK_ASYNC_CONTINUE(t);
558 t_release_transaction(t);
559 } else {
560 t->flags &= ~T_ASYNC_CONTINUE;
561 UNLOCK_ASYNC_CONTINUE(t);
562 }
563
564 /* unref the transaction */
565 if(t->async_backup.backup_route != TM_ONREPLY_ROUTE){
566 /* request handling */
567 t_unref(t->uas.request);
568 } else {
569 /* response handling */
570 t_unref(t->uac[branch].reply);
571 }
572 set_t(backup_T, backup_T_branch);
573 return ret;
574 }
575
t_continue(unsigned int hash_index,unsigned int label,struct action * route)576 int t_continue(unsigned int hash_index, unsigned int label,
577 struct action *route)
578 {
579 return t_continue_helper(hash_index, label, route, NULL, NULL);
580 }
581
t_continue_cb(unsigned int hash_index,unsigned int label,str * cbname,str * cbparam)582 int t_continue_cb(unsigned int hash_index, unsigned int label,
583 str *cbname, str *cbparam)
584 {
585 return t_continue_helper(hash_index, label, NULL, cbname, cbparam);
586 }
587
588 /* Revoke the suspension of the SIP request, i.e.
589 * cancel the fr timer of the blind uac.
590 * This function can be called when something fails
591 * after t_suspend() has already been executed in the same
592 * process, and it turns out that the transaction should
593 * not have been suspended.
594 *
595 * Return value:
596 * 0 - success
597 * <0 - failure
598 */
t_cancel_suspend(unsigned int hash_index,unsigned int label)599 int t_cancel_suspend(unsigned int hash_index, unsigned int label)
600 {
601 struct cell *t;
602 int branch;
603
604 t = get_t();
605 if (!t || t == T_UNDEFINED) {
606 LM_ERR("no active transaction\n");
607 return -1;
608 }
609 /* Only to double-check the IDs */
610 if ((t->hash_index != hash_index)
611 || (t->label != label)
612 ) {
613 LM_ERR("transaction id mismatch\n");
614 return -1;
615 }
616
617 if(t->async_backup.backup_route != TM_ONREPLY_ROUTE){
618 /* The transaction does not need to be locked because this
619 * function is either executed from the original route block
620 * or from failure route which already locks */
621
622 reset_kr(); /* the blind UAC of t_suspend has set kr */
623
624 /* Try to find the blind UAC, and cancel its fr timer.
625 * We assume that the last blind uac called this function. */
626 for ( branch = t->nr_of_outgoings-1;
627 branch >= 0 && t->uac[branch].request.buffer;
628 branch--);
629
630 if (branch >= 0) {
631 stop_rb_timers(&t->uac[branch].request);
632 /* Set last_received to something >= 200,
633 * the actual value does not matter, the branch
634 * will never be picked up for response forwarding.
635 * If last_received is lower than 200,
636 * then the branch may tried to be cancelled later,
637 * for example when t_reply() is called from
638 * a failure rute => deadlock, because both
639 * of them need the reply lock to be held. */
640 t->uac[branch].last_received=500;
641 } else {
642 /* Not a huge problem, fr timer will fire, but CANCEL
643 will not be sent. last_received will be set to 408. */
644 return -1;
645 }
646 }else{
647 branch = t->async_backup.backup_branch;
648
649 LM_DBG("This is a cancel suspend for a response\n");
650
651 t->uac[branch].reply->msg_flags &= ~FL_RPL_SUSPENDED;
652 if (t->uas.request) t->uas.request->msg_flags&= ~FL_RPL_SUSPENDED;
653 }
654
655 return 0;
656 }
657
658