aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-03-04 21:09:13 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-03-04 21:09:13 +0000
commit2df256fdf597a0d1fdffac76183f2162af671dc7 (patch)
treeb100dc519f5d699f54b463a827975f7642db17bc
parent423f68b74fd77762355910d99a99d2c1e6ceb1ce (diff)
Merged revisions 180261 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r180261 | russell | 2009-03-04 15:01:05 -0600 (Wed, 04 Mar 2009) | 54 lines Resolve object matching issues related to the removal of the sip_user object. Previously, chan_sip had both sip_peer and sip_user objects in memory. A patch went in to remove sip_user to simplify the code, since everything could be done with just sip_peer. This patch resolves some regressions found that were introduced by those changes. This code comes from svn/asterisk/team/group/sip-object-matching/. Here is a list of the changes that have been made: 1) When doing a match by name with the find_peer() function, make it much easier to specify which objects should be matched by having a parameter that specifies exactly which object types should be considered. Also, update find_by_name() to handle this parameter. Finally, update all code to use the new option values. 2) When looking up an object for an outbound request by name, consider peers only. (create_addr()) 3) Only match peers on an incoming registration request. 4) When doing authentication (except for SUBSCRIBE), look up users by name, instead of all objects by name. 5) When doing authentication (except for SUBSCRIBE), after looking for a user by name, look for a peer by IP address, instead of all objects by IP address. 6) When handling the SIP qualify CLI command or manager action, look for a peer by name, instead of any object by name. 7) When handling the SIP unregister CLI command, look for a peer by name, instead of any object by name. 9) In sip_do_debug_peer(), search for a peer by name, instead of any object by name. 9) When handling the SIPPEER() dialplan function, search for a peer by name, instead of any object by name. 10) In the following session timer related functions, st_get_se(), st_get_refresher(), and st_get_mode(), when looking for an object for a given sip_pvt using pvt->peername, look for a peer by name, instead of any object by name. 11) Fix build_peer() to properly handle the case where separate type=peer and type=user entries were specified in sip.conf. (closes issue #14505) Reported by: lmadsen Review: http://reviewboard.digium.com/r/172/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.1@180263 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/chan_sip.c135
1 files changed, 73 insertions, 62 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index f4ec29c2c..ab1967177 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -210,8 +210,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define SIPBUFSIZE 512
/* Arguments for find_peer */
-#define FINDALLDEVICES FALSE
-#define FINDONLYUSERS TRUE
+#define FINDUSERS (1 << 0)
+#define FINDPEERS (1 << 1)
+#define FINDALLDEVICES (FINDUSERS | FINDPEERS)
#define XMIT_ERROR -2
@@ -1548,7 +1549,6 @@ struct sip_peer {
char rt_fromcontact; /*!< P: copy fromcontact from realtime */
char host_dynamic; /*!< P: Dynamic Peers register with Asterisk */
char selfdestruct; /*!< P: Automatic peers need to destruct themselves */
- char onlymatchonip; /*!< P: Only match on IP for incoming calls (old type=peer) */
char the_mark; /*!< moved out of ASTOBJ into struct proper; That which bears the_mark should be deleted! */
int expire; /*!< When to expire this peer registration */
@@ -2096,14 +2096,14 @@ static void sip_dump_history(struct sip_pvt *dialog);
/*--- Device object handling */
static struct sip_peer *temp_peer(const char *name);
-static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int ispeer);
+static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime);
static int update_call_counter(struct sip_pvt *fup, int event);
static void sip_destroy_peer(struct sip_peer *peer);
static void sip_destroy_peer_fn(void *peer);
static void set_peer_defaults(struct sip_peer *peer);
static struct sip_peer *temp_peer(const char *name);
static void register_peer_exten(struct sip_peer *peer, int onoff);
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int forcenamematch, int devstate_only);
+static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only);
static int sip_poke_peer_s(const void *data);
static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req);
static void reg_source_db(struct sip_peer *peer);
@@ -4080,7 +4080,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
/* Peer found in realtime, now build it in memory */
- peer = build_peer(newpeername, var, varregs, TRUE, FALSE);
+ peer = build_peer(newpeername, var, varregs, TRUE);
if (!peer) {
if(peerlist)
ast_config_destroy(peerlist);
@@ -4125,7 +4125,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
*/
struct peer_finding_info {
struct sip_peer tmp_peer;
- int forcenamematch;
+ int which_objects;
};
/* Function to assist finding peers by name only */
@@ -4139,28 +4139,45 @@ static int find_by_name(void *obj, void *arg, int flags)
return 0;
}
- /* If we're only looking for name matches, we should avoid type=peer devices,
- since these should not match on any name-based search */
- if (pfi->forcenamematch && search->onlymatchonip) {
- return 0;
+ switch (pfi->which_objects) {
+ case FINDUSERS:
+ if (!(search->type & SIP_TYPE_USER)) {
+ return 0;
+ }
+ break;
+ case FINDPEERS:
+ if (!(search->type & SIP_TYPE_PEER)) {
+ return 0;
+ }
+ break;
+ case FINDALLDEVICES:
+ break;
}
return CMP_MATCH | CMP_STOP;
}
-/*! \brief Locate device by name or ip address
+/*!
+ * \brief Locate device by name or ip address
+ *
+ * \param which_objects Define which objects should be matched when doing a lookup
+ * by name. Valid options are FINDUSERS, FINDPEERS, or FINDALLDEVICES.
+ * Note that this option is not used at all when doing a lookup by IP.
+ *
* This is used on find matching device on name or ip/port.
- If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
-
- \note Avoid using this function in new functions if there is a way to avoid it, i
- since it might cause a database lookup.
-*/
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int forcenamematch, int devstate_only)
+ * If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
+ *
+ * \note Avoid using this function in new functions if there is a way to avoid it,
+ * since it might cause a database lookup.
+ */
+static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only)
{
struct sip_peer *p = NULL;
if (peer) {
- struct peer_finding_info pfi = { .forcenamematch = forcenamematch, };
+ struct peer_finding_info pfi = {
+ .which_objects = which_objects,
+ };
ast_copy_string(pfi.tmp_peer.name, peer, sizeof(pfi.tmp_peer.name));
p = ao2_t_callback(peers, OBJ_POINTER, find_by_name, &pfi, "ao2_callback in peers table");
} else if (sin) { /* search by addr? */
@@ -4432,7 +4449,7 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockadd
dialog->sa.sin_family = AF_INET;
dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */
dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */
- peer = find_peer(peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE);
if (peer) {
int res;
@@ -11200,7 +11217,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
ast_string_field_set(p, exten, name);
build_contact(p);
- peer = find_peer(name, NULL, TRUE, FINDALLDEVICES, FALSE);
+ peer = find_peer(name, NULL, TRUE, FINDPEERS, FALSE);
if (!(peer && ast_apply_ha(peer->ha, sin))) {
/* Peer fails ACL check */
if (peer) {
@@ -12086,11 +12103,11 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
peer = find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE);
} else {
/* First find devices based on username (avoid all type=peer's) */
- peer = find_peer(of, NULL, TRUE, FINDONLYUSERS, FALSE);
+ peer = find_peer(of, NULL, TRUE, FINDUSERS, FALSE);
/* Then find devices based on IP */
if (!peer) {
- peer = find_peer(NULL, &p->recv, TRUE, FINDALLDEVICES, FALSE);
+ peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE);
}
}
@@ -13420,7 +13437,7 @@ static char *_sip_qualify_peer(int type, int fd, struct mansession *s, const str
return CLI_SHOWUSAGE;
load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
- if ((peer = find_peer(argv[3], NULL, load_realtime, FINDALLDEVICES, FALSE))) {
+ if ((peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE))) {
sip_poke_peer(peer, 1);
unref_peer(peer, "qualify: done with peer");
} else if (type == 0) {
@@ -13502,7 +13519,8 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
return CLI_SHOWUSAGE;
load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
- peer = find_peer(argv[3], NULL, load_realtime, FINDALLDEVICES, FALSE);
+ peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE);
+
if (s) { /* Manager */
if (peer) {
const char *id = astman_get_header(m, "ActionID");
@@ -13780,7 +13798,7 @@ static char *sip_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args
/* Load from realtime storage? */
load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? TRUE : FALSE;
- if ((user = find_peer(a->argv[3], NULL, load_realtime, TRUE, FALSE))) {
+ if ((user = find_peer(a->argv[3], NULL, load_realtime, FINDUSERS, FALSE))) {
ao2_lock(user);
ast_cli(a->fd, "\n\n");
ast_cli(a->fd, " * Name : %s\n", user->name);
@@ -13938,7 +13956,7 @@ static char *sip_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
if (a->argc != 3)
return CLI_SHOWUSAGE;
- if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDALLDEVICES, TRUE))) {
+ if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDPEERS, TRUE))) {
if (peer->expire > 0) {
expire_register(ref_peer(peer, "ref for expire_register"));
ast_cli(a->fd, "Unregistered peer \'%s\'\n\n", a->argv[2]);
@@ -14910,7 +14928,7 @@ static char *sip_do_debug_ip(int fd, char *arg)
/*! \brief Turn on SIP debugging for a given peer */
static char *sip_do_debug_peer(int fd, char *arg)
{
- struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE);
if (!peer)
ast_cli(fd, "No such peer '%s'\n", arg);
else if (peer->addr.sin_addr.s_addr == 0)
@@ -15406,7 +15424,7 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
else
colname = "ip";
- if (!(peer = find_peer(data, NULL, TRUE, FINDALLDEVICES, FALSE)))
+ if (!(peer = find_peer(data, NULL, TRUE, FINDPEERS, FALSE)))
return -1;
if (!strcasecmp(colname, "ip")) {
@@ -20617,7 +20635,7 @@ int st_get_se(struct sip_pvt *p, int max)
if (p->stimer->st_cached_max_se) {
return p->stimer->st_cached_max_se;
} else if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
if (pp) {
p->stimer->st_cached_max_se = pp->stimer.st_max_se;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_se");
@@ -20630,7 +20648,7 @@ int st_get_se(struct sip_pvt *p, int max)
if (p->stimer->st_cached_min_se) {
return p->stimer->st_cached_min_se;
} else if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
if (pp) {
p->stimer->st_cached_min_se = pp->stimer.st_min_se;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_se (2)");
@@ -20652,7 +20670,7 @@ enum st_refresher st_get_refresher(struct sip_pvt *p)
return p->stimer->st_cached_ref;
if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
if (pp) {
p->stimer->st_cached_ref = pp->stimer.st_ref;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_refresher");
@@ -20677,7 +20695,7 @@ enum st_mode st_get_mode(struct sip_pvt *p)
return p->stimer->st_cached_mode;
if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
if (pp) {
p->stimer->st_cached_mode = pp->stimer.st_mode_oper;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_mode");
@@ -21507,7 +21525,7 @@ static void add_peer_mailboxes(struct sip_peer *peer, const char *value)
}
/*! \brief Build peer from configuration (file or realtime static/dynamic) */
-static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int ispeer)
+static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
{
struct sip_peer *peer = NULL;
struct ast_ha *oldha = NULL;
@@ -21522,7 +21540,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
const char *srvlookup = NULL;
static int deprecation_warning = 1;
struct ast_str *fullcontact = ast_str_alloca(512);
-
+
if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
/* Note we do NOT use find_peer here, to avoid realtime recursion */
/* We also use a case-sensitive comparison (unlike find_peer) so
@@ -21532,13 +21550,13 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_copy_string(tmp_peer.name, name, sizeof(tmp_peer.name));
peer = ao2_t_find(peers, &tmp_peer, OBJ_POINTER | OBJ_UNLINK, "find and unlink peer from peers table");
}
-
+
if (peer) {
/* Already in the list, remove it and it will be added back (or FREE'd) */
found++;
if (!(peer->the_mark))
firstpass = 0;
- } else {
+ } else {
if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct")))
return NULL;
@@ -21549,17 +21567,16 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_atomic_fetchadd_int(&speerobjs, 1);
}
- peer->onlymatchonip = ispeer; /* If type=peer, don't match on caller ID for incoming calls */
-
/* Note that our peer HAS had its reference count increased */
if (firstpass) {
peer->lastmsgssent = -1;
oldha = peer->ha;
peer->ha = NULL;
set_peer_defaults(peer); /* Set peer defaults */
+ peer->type = 0;
}
if (!found && name)
- ast_copy_string(peer->name, name, sizeof(peer->name));
+ ast_copy_string(peer->name, name, sizeof(peer->name));
/* If we have channel variables, remove them (reload) */
if (peer->chanvars) {
@@ -21613,13 +21630,10 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
}
} else if (!strcasecmp(v->name, "type")) {
if (!strcasecmp(v->value, "peer")) {
- peer->onlymatchonip = TRUE; /* For realtime support, add type=peer in the table */
- peer->type = SIP_TYPE_PEER;
+ peer->type |= SIP_TYPE_PEER;
} else if (!strcasecmp(v->value, "user")) {
- peer->onlymatchonip = FALSE;
- peer->type = SIP_TYPE_USER;
+ peer->type |= SIP_TYPE_USER;
} else if (!strcasecmp(v->value, "friend")) {
- peer->onlymatchonip = FALSE;
peer->type = SIP_TYPE_USER | SIP_TYPE_PEER;
}
} else if (!strcasecmp(v->name, "secret"))
@@ -22618,10 +22632,10 @@ static int reload_config(enum channelreloadreason reason)
hassip = ast_variable_retrieve(ucfg, cat, "hassip");
registersip = ast_variable_retrieve(ucfg, cat, "registersip");
if (ast_true(hassip) || (!hassip && genhassip)) {
- peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0, FALSE);
+ peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
if (peer) {
ao2_t_link(peers, peer, "link peer into peer table");
- if (peer->addr.sin_addr.s_addr) {
+ if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
}
@@ -22670,27 +22684,24 @@ static int reload_config(enum channelreloadreason reason)
ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
continue;
} else {
- int is_peer = 0;
if (!strcasecmp(utype, "user")) {
- is_peer = 1;
+ ;
} else if (!strcasecmp(utype, "friend")) {
- is_peer = 1;
- } else if (!strcasecmp(utype, "peer"))
- is_peer = 2;
- else {
+ ;
+ } else if (!strcasecmp(utype, "peer")) {
+ ;
+ } else {
ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf");
continue;
}
- if (is_peer) {
- peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0, is_peer == 2);
- if (peer) {
- ao2_t_link(peers, peer, "link peer into peers table");
- if (peer->addr.sin_addr.s_addr) {
- ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
- }
- unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left.");
- peer_count++;
+ peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
+ if (peer) {
+ ao2_t_link(peers, peer, "link peer into peers table");
+ if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
+ ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
}
+ unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left.");
+ peer_count++;
}
}
}