[asterisk-commits] russell: branch russell/iax2_find_callno r114836 - /team/russell/iax2_find_ca...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Apr 29 13:18:19 CDT 2008
Author: russell
Date: Tue Apr 29 13:18:18 2008
New Revision: 114836
URL: http://svn.digium.com/view/asterisk?view=rev&rev=114836
Log:
Rework what I did yesterday to use astobj2, instead, which has properties that
make this safe from deadlocks. Also, go ahead and finish the mods to find_callno()
as well. (all completely untested)
Modified:
team/russell/iax2_find_callno/channels/chan_iax2.c
Modified: team/russell/iax2_find_callno/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_find_callno/channels/chan_iax2.c?view=diff&rev=114836&r1=114835&r2=114836
==============================================================================
--- team/russell/iax2_find_callno/channels/chan_iax2.c (original)
+++ team/russell/iax2_find_callno/channels/chan_iax2.c Tue Apr 29 13:18:18 2008
@@ -854,12 +854,8 @@
* for this is that incoming media frames do not contain our call number. So,
* instead of having to iterate the entire iaxs array, we use this container to
* look up calls where the remote side is using a given call number.
- *
- * This container is an array of lists. The index into the array is the remote
- * call number. The list contains all calls where the remote side is using the
- * index as its call number.
*/
-static AST_DLLIST_HEAD(, chan_iax2_pvt) iax_peercallno_pvts[IAX_MAX_CALLS];
+static struct ao2_container *iax_peercallno_pvts;
/*!
* \brief chan_iax2_pvt structure locks
@@ -1346,13 +1342,86 @@
return res;
}
+static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
+{
+ /* Decrement AUTHREQ count if needed */
+ if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
+ struct iax2_user *user;
+ struct iax2_user tmp_user = {
+ .name = pvt->username,
+ };
+
+ user = ao2_find(users, &tmp_user, OBJ_POINTER);
+ if (user) {
+ ast_atomic_fetchadd_int(&user->curauthreq, -1);
+ user_unref(user);
+ }
+
+ ast_clear_flag(pvt, IAX_MAXAUTHREQ);
+ }
+ /* No more pings or lagrq's */
+ AST_SCHED_DEL(sched, pvt->pingid);
+ AST_SCHED_DEL(sched, pvt->lagid);
+ AST_SCHED_DEL(sched, pvt->autoid);
+ AST_SCHED_DEL(sched, pvt->authid);
+ AST_SCHED_DEL(sched, pvt->initid);
+ AST_SCHED_DEL(sched, pvt->jbid);
+}
+
+static void iax2_frame_free(struct iax_frame *fr)
+{
+ AST_SCHED_DEL(sched, fr->retrans);
+ iax_frame_free(fr);
+}
+
+static void pvt_destructor(void *obj)
+{
+ struct chan_iax2_pvt *pvt = obj;
+ struct iax_frame *cur = NULL;
+
+ iax2_destroy_helper(pvt);
+
+ /* Already gone */
+ ast_set_flag(pvt, IAX_ALREADYGONE);
+
+ AST_LIST_LOCK(&frame_queue);
+ AST_LIST_TRAVERSE(&frame_queue, cur, list) {
+ /* Cancel any pending transmissions */
+ if (cur->callno == pvt->callno) {
+ cur->retries = -1;
+ }
+ }
+ AST_LIST_UNLOCK(&frame_queue);
+
+ if (pvt->reg) {
+ pvt->reg->callno = 0;
+ }
+
+ if (!pvt->owner) {
+ jb_frame frame;
+ if (pvt->vars) {
+ ast_variables_destroy(pvt->vars);
+ pvt->vars = NULL;
+ }
+
+ while (jb_getall(pvt->jb, &frame) == JB_OK) {
+ iax2_frame_free(frame.data);
+ }
+
+ jb_destroy(pvt->jb);
+ ast_string_field_free_memory(pvt);
+ ast_free(pvt);
+ }
+}
+
static struct chan_iax2_pvt *new_iax(struct sockaddr_in *sin, const char *host)
{
struct chan_iax2_pvt *tmp;
jb_conf jbconf;
- if (!(tmp = ast_calloc(1, sizeof(*tmp))))
+ if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) {
return NULL;
+ }
if (ast_string_field_init(tmp, 32)) {
ast_free(tmp);
@@ -1497,20 +1566,22 @@
static void store_by_peercallno(struct chan_iax2_pvt *pvt)
{
- AST_DLLIST_LOCK(&iax_peercallno_pvts[pvt->peercallno]);
- AST_DLLIST_INSERT_HEAD(&iax_peercallno_pvts[pvt->peercallno], pvt, entry);
- AST_DLLIST_UNLOCK(&iax_peercallno_pvts[pvt->peercallno]);
+ if (!pvt->peercallno) {
+ ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
+ return;
+ }
+
+ ao2_link(iax_peercallno_pvts, pvt);
}
static void remove_by_peercallno(struct chan_iax2_pvt *pvt)
{
if (!pvt->peercallno) {
+ ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
return;
}
- AST_DLLIST_LOCK(&iax_peercallno_pvts[pvt->peercallno]);
- AST_DLLIST_REMOVE(&iax_peercallno_pvts[pvt->peercallno], pvt, entry);
- AST_DLLIST_UNLOCK(&iax_peercallno_pvts[pvt->peercallno]);
+ ao2_unlink(iax_peercallno_pvts, pvt);
}
/*!
@@ -1538,7 +1609,24 @@
if (new <= NEW_ALLOW) {
if (callno) {
- /* XXX Look for pvt by peer callno here ... */
+ struct chan_iax2_pvt *pvt;
+ struct chan_iax2_pvt tmp_pvt = {
+ .callno = callno,
+ .peercallno = dcallno,
+ /* hack!! */
+ .frames_received = full_frame,
+ };
+
+ memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr));
+
+ if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
+ if (return_locked) {
+ ast_mutex_lock(&iaxsl[callno]);
+ }
+ ao2_ref(pvt, -1);
+ pvt = NULL;
+ return callno;
+ }
}
for (x = 1; !res && x < maxnontrunkcall; x++) {
@@ -1645,12 +1733,6 @@
static int find_callno_locked(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame) {
return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame);
-}
-
-static void iax2_frame_free(struct iax_frame *fr)
-{
- AST_SCHED_DEL(sched, fr->retrans);
- iax_frame_free(fr);
}
/*!
@@ -2102,32 +2184,6 @@
return res;
}
-static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
-{
- /* Decrement AUTHREQ count if needed */
- if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
- struct iax2_user *user;
- struct iax2_user tmp_user = {
- .name = pvt->username,
- };
-
- user = ao2_find(users, &tmp_user, OBJ_POINTER);
- if (user) {
- ast_atomic_fetchadd_int(&user->curauthreq, -1);
- user_unref(user);
- }
-
- ast_clear_flag(pvt, IAX_MAXAUTHREQ);
- }
- /* No more pings or lagrq's */
- AST_SCHED_DEL(sched, pvt->pingid);
- AST_SCHED_DEL(sched, pvt->lagid);
- AST_SCHED_DEL(sched, pvt->autoid);
- AST_SCHED_DEL(sched, pvt->authid);
- AST_SCHED_DEL(sched, pvt->initid);
- AST_SCHED_DEL(sched, pvt->jbid);
-}
-
/*!
* \note Since this function calls iax2_queue_hangup(), the pvt struct
* for the given call number may disappear during its execution.
@@ -2158,7 +2214,6 @@
static void iax2_destroy(int callno)
{
struct chan_iax2_pvt *pvt = NULL;
- struct iax_frame *cur = NULL;
struct ast_channel *owner = NULL;
retry:
@@ -2176,55 +2231,34 @@
goto retry;
}
}
- if (!owner)
+
+ if (!owner) {
iaxs[callno] = NULL;
+ }
+
if (pvt) {
- if (!owner)
+ if (!owner) {
pvt->owner = NULL;
- iax2_destroy_helper(pvt);
-
- /* Already gone */
- ast_set_flag(pvt, IAX_ALREADYGONE);
-
- if (owner) {
+ } else {
/* If there's an owner, prod it to give up */
/* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup()
* because we already hold the owner channel lock. */
ast_queue_hangup(owner, -1);
}
- AST_LIST_LOCK(&frame_queue);
- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
- /* Cancel any pending transmissions */
- if (cur->callno == pvt->callno)
- cur->retries = -1;
- }
- AST_LIST_UNLOCK(&frame_queue);
-
- if (pvt->reg)
- pvt->reg->callno = 0;
- if (!owner) {
- jb_frame frame;
- if (pvt->vars) {
- ast_variables_destroy(pvt->vars);
- pvt->vars = NULL;
- }
-
- while (jb_getall(pvt->jb, &frame) == JB_OK)
- iax2_frame_free(frame.data);
- jb_destroy(pvt->jb);
- /* gotta free up the stringfields */
- ast_string_field_free_memory(pvt);
- ast_free(pvt);
- }
-
remove_by_peercallno(pvt);
- }
+
+ ao2_ref(pvt, -1);
+ pvt = NULL;
+ }
+
if (owner) {
ast_channel_unlock(owner);
}
- if (callno & 0x4000)
+
+ if (callno & 0x4000) {
update_max_trunk();
+ }
}
static int update_packet(struct iax_frame *f)
@@ -11826,6 +11860,7 @@
ao2_ref(peers, -1);
ao2_ref(users, -1);
+ ao2_ref(iax_peercallno_pvts, -1);
con = ast_context_find(regcontext);
if (con)
@@ -11851,6 +11886,24 @@
return 0;
}
+static int pvt_hash_cb(const void *obj, const int flags)
+{
+ const struct chan_iax2_pvt *pvt = obj;
+
+ return pvt->peercallno;
+}
+
+static int pvt_cmp_cb(void *obj, void *arg, int flags)
+{
+ struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
+
+ /* The frames_received field is used to hold whether we're matching
+ * against a full frame or not ... */
+
+ return match(&pvt2->addr, pvt2->callno, pvt2->peercallno, pvt,
+ pvt2->frames_received) ? CMP_MATCH : 0;
+}
+
/*! \brief Load IAX2 module, load configuraiton ---*/
static int load_module(void)
{
@@ -11864,6 +11917,12 @@
users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
if (!users) {
ao2_ref(peers, -1);
+ return AST_MODULE_LOAD_FAILURE;
+ }
+ iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
+ if (!iax_peercallno_pvts) {
+ ao2_ref(peers, -1);
+ ao2_ref(users, -1);
return AST_MODULE_LOAD_FAILURE;
}
More information about the asterisk-commits
mailing list