mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
5.8 KiB
150 lines
5.8 KiB
/*
|
|
* $Id$
|
|
*
|
|
*
|
|
* Copyright (C) 2001-2003 FhG Fokus
|
|
*
|
|
* This file is part of ser, a free SIP server.
|
|
*
|
|
* ser is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version
|
|
*
|
|
* For a license to use the ser software under conditions
|
|
* other than those described here, or to purchase support for this
|
|
* software, please contact iptel.org by e-mail at the following addresses:
|
|
* info@iptel.org
|
|
*
|
|
* ser is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* History:
|
|
* ---------
|
|
* 2004-02-11 FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
|
|
* 2006-10-10 should_cancel_branch() returns true even for branches with
|
|
* no response or with response <100 (andrei)
|
|
* 2007-06-04 should_cancel_branch() takes another parameter and it is safe
|
|
* to be called w/o REPLY_LOCK held (andrei)
|
|
* 2009-07-14 should_cancel_branch() renamed to prepare_cancel_branch() to
|
|
* better reflect its purpose
|
|
* which_cancel() renamed to prepare_to_cancel() (andrei)
|
|
* 2010-02-26 cancel reason (rfc3326) basic support (andrei)
|
|
*/
|
|
|
|
|
|
#ifndef _CANCEL_H
|
|
#define _CANCEL_H
|
|
|
|
#include <stdio.h> /* just for FILE* for fifo_uac_cancel */
|
|
#include "../../rpc.h"
|
|
#include "../../atomic_ops.h"
|
|
#include "defs.h"
|
|
#include "h_table.h"
|
|
#include "t_reply.h"
|
|
|
|
|
|
/* a buffer is empty but cannot be used by anyone else;
|
|
particularly, we use this value in the buffer pointer
|
|
in local_buffer to tell "a process is already scheduled
|
|
to generate a CANCEL, other processes are not supposed to"
|
|
(which might happen if for example in a three-branch forking,
|
|
two 200 would enter separate processes and compete for
|
|
canceling the third branch); note that to really avoid
|
|
race conditions, the value must be set in REPLY_LOCK
|
|
*/
|
|
|
|
#define BUSY_BUFFER ((char *)-1)
|
|
|
|
/* flags for cancel_uacs(), cancel_branch() */
|
|
#define F_CANCEL_B_KILL 1 /* will completely stop the branch (stops the
|
|
timers), use only before a put_on_wait()
|
|
or set_final_timer()*/
|
|
#define F_CANCEL_B_FAKE_REPLY 2 /* will send a fake 487 to all branches that
|
|
haven't received any response (>=100). It
|
|
assumes the REPLY_LOCK is not held (if it is
|
|
=> deadlock) */
|
|
#define F_CANCEL_B_FORCE_C 4 /* will send a cancel even if no reply was
|
|
received; F_CANCEL_B_FAKE_REPLY will be
|
|
ignored */
|
|
#define F_CANCEL_B_FORCE_RETR 8 /* will not stop request retr. on a branch
|
|
if no provisional response was received;
|
|
F_CANCEL_B_FORCE_C, F_CANCEL_B_FAKE_REPLY
|
|
and F_CANCE_B_KILL take precedence */
|
|
#define F_CANCEL_UNREF 16 /* unref the trans after canceling */
|
|
|
|
|
|
void prepare_to_cancel(struct cell *t, branch_bm_t *cancel_bm, branch_bm_t s);
|
|
int cancel_uacs( struct cell *t, struct cancel_info* cancel_data, int flags );
|
|
int cancel_all_uacs(struct cell *trans, int how);
|
|
int cancel_branch( struct cell *t, int branch,
|
|
#ifdef CANCEL_REASON_SUPPORT
|
|
struct cancel_reason* reason,
|
|
#endif /* CANCEL_REASON_SUPPORT */
|
|
int flags );
|
|
|
|
typedef int(*cancel_uacs_f)(struct cell *t, struct cancel_info* cancel_data,
|
|
int flags);
|
|
typedef int (*cancel_all_uacs_f)(struct cell *trans, int how);
|
|
|
|
typedef void (*prepare_to_cancel_f)(struct cell *t, branch_bm_t *cancel_bm,
|
|
branch_bm_t skip_branches);
|
|
|
|
|
|
/** Check if one branch needs CANCEL-ing and prepare it if it does.
|
|
* Can be called w/o REPLY_LOCK held
|
|
* between this call and the call to cancel_uacs()/cancel_branch()
|
|
* if noreply is set to 1 it will return true even if no reply was received
|
|
* (it will return false only if a final response or a cancel have already
|
|
* been sent on the current branch).
|
|
* if noreply is set to 0 it will return true only if no cancel has already
|
|
* been sent and a provisional (<200) reply >=100 was received.
|
|
* WARNING: has side effects: marks branches that should be canceled
|
|
* and a second call won't return them again.
|
|
* @param t - transaction
|
|
* @param b - branch number
|
|
* @param noreply - 0 or 1. If 1 it will consider a branch with no replies
|
|
* received so far as cancel-able. If 0 only branches that have received
|
|
* a provisional reply (>=100 <200) will be considered.
|
|
*
|
|
* @return 1 if the branch must be canceled (it will be internally marked as
|
|
* cancel-in-progress) and 0 if it doesn't (either a CANCEL is not needed or a
|
|
* CANCEL is in progress: somebody else is trying to CANCEL in the same time).
|
|
*/
|
|
inline short static prepare_cancel_branch( struct cell *t, int b, int noreply )
|
|
{
|
|
int last_received;
|
|
unsigned long old;
|
|
|
|
last_received=t->uac[b].last_received;
|
|
/* if noreply=1 cancel even if no reply received (in this case
|
|
* cancel_branch() won't actually send the cancel but it will do the
|
|
* cleanup) */
|
|
if (last_received<200 && (noreply || last_received>=100)){
|
|
old=atomic_cmpxchg_long((void*)&t->uac[b].local_cancel.buffer, 0,
|
|
(long)(BUSY_BUFFER));
|
|
return old==0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void rpc_cancel(rpc_t* rpc, void* c);
|
|
int cancel_b_flags_fixup(void* handle, str* gname, str* name, void** val);
|
|
int cancel_b_flags_get(unsigned int* f, int m);
|
|
|
|
typedef unsigned int (*tuaccancel_f)( str *headers,str *body,
|
|
unsigned int cancelledIdx,unsigned int cancelledLabel,
|
|
transaction_cb cb, void* cbp);
|
|
|
|
unsigned int t_uac_cancel(str *headers,str *body,
|
|
unsigned int cancelledIdx,unsigned int cancelledLabel,
|
|
transaction_cb cb, void* cbp);
|
|
|
|
#endif
|