Merge kpflemings ASTOBJ improvements (bug #3167)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4578 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2004-12-28 23:27:44 +00:00
parent 526fc0afe9
commit 59e86b63b0
2 changed files with 243 additions and 260 deletions

View File

@@ -1158,8 +1158,7 @@ static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *
ast_destroy_realtime(var); ast_destroy_realtime(var);
} }
if (peer) { if (peer) {
/* Reference and destroy, so when our caller unrefs, we disappear */ /* Destroy, so when our caller unrefs, it will disappear */
ASTOBJ_REF(peer);
ASTOBJ_DESTROY(peer, sip_destroy_peer); ASTOBJ_DESTROY(peer, sip_destroy_peer);
} }
return peer; return peer;
@@ -1180,9 +1179,9 @@ static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin)
struct sip_peer *p = NULL; struct sip_peer *p = NULL;
if (peer) if (peer)
ASTOBJ_CONTAINER_FIND(&peerl,p,peer); p = ASTOBJ_CONTAINER_FIND(&peerl,peer);
else else
ASTOBJ_CONTAINER_FIND_FULL(&peerl,p,sin,name,sip_addr_hashfunc,1,sip_addrcmp); p = ASTOBJ_CONTAINER_FIND_FULL(&peerl,sin,name,sip_addr_hashfunc,1,sip_addrcmp);
if (!p) { if (!p) {
p = realtime_peer(peer, sin); p = realtime_peer(peer, sin);
@@ -1249,7 +1248,7 @@ static struct sip_user *realtime_user(const char *username)
static struct sip_user *find_user(const char *name) static struct sip_user *find_user(const char *name)
{ {
struct sip_user *u = NULL; struct sip_user *u = NULL;
ASTOBJ_CONTAINER_FIND(&userl,u,name); u = ASTOBJ_CONTAINER_FIND(&userl,name);
if (!u) { if (!u) {
u = realtime_user(name); u = realtime_user(name);
} }
@@ -1340,7 +1339,6 @@ static int create_addr(struct sip_pvt *r, char *opeer)
memcpy(&r->recv, &r->sa, sizeof(r->recv)); memcpy(&r->recv, &r->sa, sizeof(r->recv));
} else { } else {
ASTOBJ_UNREF(p,sip_destroy_peer); ASTOBJ_UNREF(p,sip_destroy_peer);
p = NULL;
} }
} }
if (!p && !found) { if (!p && !found) {
@@ -4091,14 +4089,17 @@ static int transmit_register(struct sip_registry *r, char *cmd, char *auth, char
static int sip_reregister(void *data) static int sip_reregister(void *data)
{ {
/* if we are here, we know that we need to reregister. */ /* if we are here, we know that we need to reregister. */
struct sip_registry *r=(struct sip_registry *)data; struct sip_registry *r= ASTOBJ_REF((struct sip_registry *) data);
/* if we couldn't get a reference to the registry object, punt */
if (!r)
return 0;
/* Since registry's are only added/removed by the the monitor thread, this /* Since registry's are only added/removed by the the monitor thread, this
may be overkill to reference/dereference at all here */ may be overkill to reference/dereference at all here */
if (sipdebug) if (sipdebug)
ast_log(LOG_NOTICE, " -- Re-registration for %s@%s\n", r->username, r->hostname); ast_log(LOG_NOTICE, " -- Re-registration for %s@%s\n", r->username, r->hostname);
ASTOBJ_REF(r);
r->expire = -1; r->expire = -1;
__sip_do_register(r); __sip_do_register(r);
ASTOBJ_UNREF(r,sip_registry_destroy); ASTOBJ_UNREF(r,sip_registry_destroy);
@@ -4118,11 +4119,14 @@ static int sip_reg_timeout(void *data)
{ {
/* if we are here, our registration timed out, so we'll just do it over */ /* if we are here, our registration timed out, so we'll just do it over */
struct sip_registry *r=data; struct sip_registry *r = ASTOBJ_REF((struct sip_registry *) data);
struct sip_pvt *p; struct sip_pvt *p;
int res; int res;
ASTOBJ_REF(r); /* if we couldn't get a reference to the registry object, punt */
if (!r)
return 0;
ast_log(LOG_NOTICE, " -- Registration for '%s@%s' timed out, trying again\n", r->username, r->hostname); ast_log(LOG_NOTICE, " -- Registration for '%s@%s' timed out, trying again\n", r->username, r->hostname);
if (r->call) { if (r->call) {
/* Unlink us, destroy old call. Locking is not relevent here because all this happens /* Unlink us, destroy old call. Locking is not relevent here because all this happens
@@ -4130,7 +4134,6 @@ static int sip_reg_timeout(void *data)
p = r->call; p = r->call;
if (p->registry) if (p->registry)
ASTOBJ_UNREF(p->registry, sip_registry_destroy); ASTOBJ_UNREF(p->registry, sip_registry_destroy);
p->registry = NULL;
r->call = NULL; r->call = NULL;
ast_set_flag(p, SIP_NEEDDESTROY); ast_set_flag(p, SIP_NEEDDESTROY);
/* Pretend to ACK anything just in case */ /* Pretend to ACK anything just in case */
@@ -4195,8 +4198,7 @@ static int transmit_register(struct sip_registry *r, char *cmd, char *auth, char
p->sa.sin_port = htons(r->portno); p->sa.sin_port = htons(r->portno);
ast_set_flag(p, SIP_OUTGOING); /* Registration is outgoing call */ ast_set_flag(p, SIP_OUTGOING); /* Registration is outgoing call */
r->call=p; /* Save pointer to SIP packet */ r->call=p; /* Save pointer to SIP packet */
p->registry=r; /* Add pointer to registry in packet */ p->registry=ASTOBJ_REF(r); /* Add pointer to registry in packet */
ASTOBJ_REF(p->registry); /* Reference registry to prevent it from disappearing */
if (!ast_strlen_zero(r->secret)) /* Secret (password) */ if (!ast_strlen_zero(r->secret)) /* Secret (password) */
strncpy(p->peersecret, r->secret, sizeof(p->peersecret)-1); strncpy(p->peersecret, r->secret, sizeof(p->peersecret)-1);
if (!ast_strlen_zero(r->md5secret)) if (!ast_strlen_zero(r->md5secret))
@@ -5028,7 +5030,6 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
peer = find_peer(name, NULL); peer = find_peer(name, NULL);
if (!(peer && ast_apply_ha(peer->ha, sin))) { if (!(peer && ast_apply_ha(peer->ha, sin))) {
ASTOBJ_UNREF(peer,sip_destroy_peer); ASTOBJ_UNREF(peer,sip_destroy_peer);
peer = NULL;
} }
if (peer) { if (peer) {
if (!ast_test_flag(peer, SIP_DYNAMIC)) { if (!ast_test_flag(peer, SIP_DYNAMIC)) {
@@ -5759,7 +5760,6 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req)
static int sip_show_inuse(int fd, int argc, char *argv[]) { static int sip_show_inuse(int fd, int argc, char *argv[]) {
#define FORMAT "%-15.15s %-15.15s %-15.15s %-15.15s %-15.15s\n" #define FORMAT "%-15.15s %-15.15s %-15.15s %-15.15s %-15.15s\n"
#define FORMAT2 "%-15.15s %-15.15s %-15.15s %-15.15s %-15.15s\n" #define FORMAT2 "%-15.15s %-15.15s %-15.15s %-15.15s %-15.15s\n"
struct sip_user *user;
char ilimits[40] = ""; char ilimits[40] = "";
char olimits[40] = ""; char olimits[40] = "";
char iused[40]; char iused[40];
@@ -5768,18 +5768,20 @@ static int sip_show_inuse(int fd, int argc, char *argv[]) {
if (argc != 3) if (argc != 3)
return RESULT_SHOWUSAGE; return RESULT_SHOWUSAGE;
ast_cli(fd, FORMAT, "Username", "incoming", "Limit","outgoing","Limit"); ast_cli(fd, FORMAT, "Username", "incoming", "Limit","outgoing","Limit");
ASTOBJ_CONTAINER_TRAVERSE(&userl,user, do { ASTOBJ_CONTAINER_TRAVERSE(&userl, do {
if (user->incominglimit) ASTOBJ_RDLOCK(iterator);
snprintf(ilimits, sizeof(ilimits), "%d", user->incominglimit); if (iterator->incominglimit)
snprintf(ilimits, sizeof(ilimits), "%d", iterator->incominglimit);
else else
strncpy(ilimits, "N/A", sizeof(ilimits) - 1); strncpy(ilimits, "N/A", sizeof(ilimits) - 1);
if (user->outgoinglimit) if (iterator->outgoinglimit)
snprintf(olimits, sizeof(olimits), "%d", user->outgoinglimit); snprintf(olimits, sizeof(olimits), "%d", iterator->outgoinglimit);
else else
strncpy(olimits, "N/A", sizeof(olimits) - 1); strncpy(olimits, "N/A", sizeof(olimits) - 1);
snprintf(iused, sizeof(iused), "%d", user->inUse); snprintf(iused, sizeof(iused), "%d", iterator->inUse);
snprintf(oused, sizeof(oused), "%d", user->outUse); snprintf(oused, sizeof(oused), "%d", iterator->outUse);
ast_cli(fd, FORMAT2, user->name, iused, ilimits,oused,olimits); ast_cli(fd, FORMAT2, iterator->name, iused, ilimits,oused,olimits);
ASTOBJ_UNLOCK(iterator);
} while (0) ); } while (0) );
return RESULT_SUCCESS; return RESULT_SUCCESS;
#undef FORMAT #undef FORMAT
@@ -5806,17 +5808,19 @@ static char *nat2str(int nat)
static int sip_show_users(int fd, int argc, char *argv[]) static int sip_show_users(int fd, int argc, char *argv[])
{ {
#define FORMAT "%-15.15s %-15.15s %-15.15s %-15.15s %-5.5s%-5.5s\n" #define FORMAT "%-15.15s %-15.15s %-15.15s %-15.15s %-5.5s%-5.5s\n"
struct sip_user *user;
if (argc != 3) if (argc != 3)
return RESULT_SHOWUSAGE; return RESULT_SHOWUSAGE;
ast_cli(fd, FORMAT, "Username", "Secret", "Accountcode", "Def.Context", "ACL", "NAT"); ast_cli(fd, FORMAT, "Username", "Secret", "Accountcode", "Def.Context", "ACL", "NAT");
ASTOBJ_CONTAINER_TRAVERSE(&userl,user, ASTOBJ_CONTAINER_TRAVERSE(&userl, do {
ast_cli(fd, FORMAT, user->name, ASTOBJ_RDLOCK(iterator);
user->secret, ast_cli(fd, FORMAT, iterator->name,
user->accountcode, iterator->secret,
user->context, iterator->accountcode,
user->ha ? "Yes" : "No", iterator->context,
nat2str(user->nat)) iterator->ha ? "Yes" : "No",
nat2str(iterator->nat));
ASTOBJ_UNLOCK(iterator);
} while (0)
); );
return RESULT_SUCCESS; return RESULT_SUCCESS;
#undef FORMAT #undef FORMAT
@@ -5827,7 +5831,6 @@ static int sip_show_peers(int fd, int argc, char *argv[])
{ {
#define FORMAT2 "%-15.15s %-15.15s %s %s %s %-15.15s %-8s %-10s\n" #define FORMAT2 "%-15.15s %-15.15s %s %s %s %-15.15s %-8s %-10s\n"
#define FORMAT "%-15.15s %-15.15s %s %s %s %-15.15s %-8d %-10s\n" #define FORMAT "%-15.15s %-15.15s %s %s %s %-15.15s %-8d %-10s\n"
struct sip_peer *peer;
char name[256] = ""; char name[256] = "";
char iabuf[INET_ADDRSTRLEN]; char iabuf[INET_ADDRSTRLEN];
int total_peers = 0; int total_peers = 0;
@@ -5839,30 +5842,32 @@ static int sip_show_peers(int fd, int argc, char *argv[])
return RESULT_SHOWUSAGE; return RESULT_SHOWUSAGE;
ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Nat", "ACL", "Mask", "Port", "Status"); ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Nat", "ACL", "Mask", "Port", "Status");
ASTOBJ_CONTAINER_TRAVERSE(&peerl,peer, do { ASTOBJ_CONTAINER_TRAVERSE(&peerl, do {
char nm[20] = ""; char nm[20] = "";
char status[20] = ""; char status[20] = "";
int print_line = -1; int print_line = -1;
char srch[2000]; char srch[2000];
ast_inet_ntoa(nm, sizeof(nm), peer->mask); ASTOBJ_RDLOCK(iterator);
if (!ast_strlen_zero(peer->username))
snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); ast_inet_ntoa(nm, sizeof(nm), iterator->mask);
if (!ast_strlen_zero(iterator->username))
snprintf(name, sizeof(name), "%s/%s", iterator->name, iterator->username);
else else
strncpy(name, peer->name, sizeof(name) - 1); strncpy(name, iterator->name, sizeof(name) - 1);
if (peer->maxms) { if (iterator->maxms) {
if (peer->lastms < 0) { if (iterator->lastms < 0) {
strncpy(status, "UNREACHABLE", sizeof(status) - 1); strncpy(status, "UNREACHABLE", sizeof(status) - 1);
peers_offline++; peers_offline++;
} else if (peer->lastms > peer->maxms) { } else if (iterator->lastms > iterator->maxms) {
snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms); snprintf(status, sizeof(status), "LAGGED (%d ms)", iterator->lastms);
peers_online++; peers_online++;
} else if (peer->lastms) { } else if (iterator->lastms) {
snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms); snprintf(status, sizeof(status), "OK (%d ms)", iterator->lastms);
peers_online++; peers_online++;
} else { } else {
/* Checking if port is 0 */ /* Checking if port is 0 */
if ( ntohs(peer->addr.sin_port) == 0 ) { if ( ntohs(iterator->addr.sin_port) == 0 ) {
peers_offline++; peers_offline++;
} else { } else {
peers_online++; peers_online++;
@@ -5872,7 +5877,7 @@ static int sip_show_peers(int fd, int argc, char *argv[])
} else { } else {
strncpy(status, "Unmonitored", sizeof(status) - 1); strncpy(status, "Unmonitored", sizeof(status) - 1);
/* Checking if port is 0 */ /* Checking if port is 0 */
if ( ntohs(peer->addr.sin_port) == 0 ) { if ( ntohs(iterator->addr.sin_port) == 0 ) {
peers_offline++; peers_offline++;
} else { } else {
peers_online++; peers_online++;
@@ -5880,11 +5885,11 @@ static int sip_show_peers(int fd, int argc, char *argv[])
} }
snprintf(srch, sizeof(srch), FORMAT, name, snprintf(srch, sizeof(srch), FORMAT, name,
peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)", iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
ast_test_flag(peer, SIP_DYNAMIC) ? " D " : " ", /* Dynamic or not? */ ast_test_flag(iterator, SIP_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
(peer->nat & SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */ (iterator->nat & SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */
peer->ha ? " A " : " ", /* permit/deny */ iterator->ha ? " A " : " ", /* permit/deny */
nm, ntohs(peer->addr.sin_port), status); nm, ntohs(iterator->addr.sin_port), status);
if (argc == 5) { if (argc == 5) {
if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) { if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) {
@@ -5900,13 +5905,16 @@ static int sip_show_peers(int fd, int argc, char *argv[])
if (print_line) { if (print_line) {
ast_cli(fd, FORMAT, name, ast_cli(fd, FORMAT, name,
peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)", iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
ast_test_flag(peer, SIP_DYNAMIC) ? " D " : " ", /* Dynamic or not? */ ast_test_flag(iterator, SIP_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
(peer->nat & SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */ (iterator->nat & SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */
peer->ha ? " A " : " ", /* permit/deny */ iterator->ha ? " A " : " ", /* permit/deny */
nm, nm,
ntohs(peer->addr.sin_port), status); ntohs(iterator->addr.sin_port), status);
} }
ASTOBJ_UNLOCK(iterator);
total_peers++; total_peers++;
} while(0) ); } while(0) );
ast_cli(fd,"%d sip peers loaded [%d online , %d offline]\n",total_peers,peers_online,peers_offline); ast_cli(fd,"%d sip peers loaded [%d online , %d offline]\n",total_peers,peers_online,peers_offline);
@@ -5917,18 +5925,15 @@ static int sip_show_peers(int fd, int argc, char *argv[])
static int sip_show_objects(int fd, int argc, char *argv[]) static int sip_show_objects(int fd, int argc, char *argv[])
{ {
struct sip_user *user;
struct sip_peer *peer;
struct sip_registry *reg;
char tmp[256]; char tmp[256];
if (argc != 3) if (argc != 3)
return RESULT_SHOWUSAGE; return RESULT_SHOWUSAGE;
ast_cli(fd, "-= User objects: %d static, %d realtime =-\n\n", suserobjs, ruserobjs); ast_cli(fd, "-= User objects: %d static, %d realtime =-\n\n", suserobjs, ruserobjs);
ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &userl, user); ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &userl);
ast_cli(fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs); ast_cli(fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs);
ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &peerl, peer); ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &peerl);
ast_cli(fd, "-= Registry objects: %d =-\n\n", regobjs); ast_cli(fd, "-= Registry objects: %d =-\n\n", regobjs);
ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &regl, reg); ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &regl);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
/*--- print_group: Print call group and pickup group ---*/ /*--- print_group: Print call group and pickup group ---*/
@@ -6049,16 +6054,16 @@ static int sip_show_registry(int fd, int argc, char *argv[])
{ {
#define FORMAT2 "%-30.30s %-12.12s %8.8s %-20.20s\n" #define FORMAT2 "%-30.30s %-12.12s %8.8s %-20.20s\n"
#define FORMAT "%-30.30s %-12.12s %8d %-20.20s\n" #define FORMAT "%-30.30s %-12.12s %8d %-20.20s\n"
struct sip_registry *reg;
char host[80]; char host[80];
if (argc != 3) if (argc != 3)
return RESULT_SHOWUSAGE; return RESULT_SHOWUSAGE;
ast_cli(fd, FORMAT2, "Host", "Username", "Refresh", "State"); ast_cli(fd, FORMAT2, "Host", "Username", "Refresh", "State");
ASTOBJ_CONTAINER_TRAVERSE(&regl,reg, do { ASTOBJ_CONTAINER_TRAVERSE(&regl, do {
snprintf(host, sizeof(host), "%s:%d", reg->hostname, reg->portno ? reg->portno : DEFAULT_SIP_PORT); ASTOBJ_RDLOCK(iterator);
ast_cli(fd, FORMAT, host, snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : DEFAULT_SIP_PORT);
reg->username, reg->refresh, regstate2str(reg->regstate)); ast_cli(fd, FORMAT, host, iterator->username, iterator->refresh, regstate2str(iterator->regstate));
ASTOBJ_UNLOCK(iterator);
} while(0)); } while(0));
return RESULT_SUCCESS; return RESULT_SUCCESS;
#undef FORMAT #undef FORMAT
@@ -8015,7 +8020,7 @@ static void *do_monitor(void *data)
{ {
int res; int res;
struct sip_pvt *sip; struct sip_pvt *sip;
struct sip_peer *peer; struct sip_peer *peer = NULL;
time_t t; time_t t;
int fastrestart =0; int fastrestart =0;
int lastpeernum = -1; int lastpeernum = -1;
@@ -8107,18 +8112,20 @@ restartsearch:
time(&t); time(&t);
fastrestart = 0; fastrestart = 0;
curpeernum = 0; curpeernum = 0;
ASTOBJ_CONTAINER_TRAVERSE(&peerl,peer, ASTOBJ_CONTAINER_TRAVERSE(&peerl, do {
if ((curpeernum > lastpeernum) && !ast_strlen_zero(peer->mailbox) && ((t - peer->lastmsgcheck) > global_mwitime)) { if ((curpeernum > lastpeernum) && !ast_strlen_zero(iterator->mailbox) && ((t - iterator->lastmsgcheck) > global_mwitime)) {
fastrestart = 1; fastrestart = 1;
lastpeernum = curpeernum; lastpeernum = curpeernum;
ASTOBJ_REF(peer); peer = ASTOBJ_REF(iterator);
ast_mutex_unlock(&peer->lock);
break; break;
} };
curpeernum++ curpeernum++;
} while (0)
); );
if (peer) { if (peer) {
ASTOBJ_WRLOCK(peer);
sip_send_mwi_to_peer(peer); sip_send_mwi_to_peer(peer);
ASTOBJ_UNLOCK(peer);
ASTOBJ_UNREF(peer,sip_destroy_peer); ASTOBJ_UNREF(peer,sip_destroy_peer);
} else { } else {
/* Reset where we come from */ /* Reset where we come from */
@@ -8570,20 +8577,16 @@ static struct sip_peer *temp_peer(char *name)
/*--- build_peer: Build peer from config file ---*/ /*--- build_peer: Build peer from config file ---*/
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int temponly) static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int temponly)
{ {
struct sip_peer *peer; struct sip_peer *peer = NULL;
struct sip_peer *prev;
struct ast_ha *oldha = NULL; struct ast_ha *oldha = NULL;
int maskfound=0; int maskfound=0;
int obproxyfound=0; int obproxyfound=0;
int found=0; int found=0;
prev = NULL; if (!temponly)
if (temponly) {
peer = NULL;
} else {
/* Note we do NOT use find_peer here, to avoid realtime recursion */ /* Note we do NOT use find_peer here, to avoid realtime recursion */
ASTOBJ_CONTAINER_FIND_UNLINK(&peerl,peer,prev,name); peer = ASTOBJ_CONTAINER_FIND_UNLINK(&peerl, name);
}
if (peer) { if (peer) {
/* Already in the list, remove it and it will be added back (or FREE'd) */ /* Already in the list, remove it and it will be added back (or FREE'd) */
found++; found++;
@@ -8600,7 +8603,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
peer->pokeexpire = -1; peer->pokeexpire = -1;
} }
} }
/* Note that our peer has NOT had its reference count incrased */ /* Note that our peer HAS had its reference count incrased */
if (peer) { if (peer) {
peer->lastmsgssent = -1; peer->lastmsgssent = -1;
if (!found) { if (!found) {
@@ -9391,35 +9394,49 @@ static struct ast_rtp_protocol sip_rtp = {
/* Also, check registations with other SIP proxies */ /* Also, check registations with other SIP proxies */
static void delete_users(void) static void delete_users(void)
{ {
struct sip_user *user;
struct sip_peer *peer;
struct sip_registry *reg;
/* Delete all users */ /* Delete all users */
ASTOBJ_CONTAINER_DESTROYALL(&userl,user,sip_destroy_user); ASTOBJ_CONTAINER_DESTROYALL(&userl,sip_destroy_user);
ASTOBJ_CONTAINER_DESTROYALL(&regl,reg,sip_registry_destroy); ASTOBJ_CONTAINER_DESTROYALL(&regl,sip_registry_destroy);
ASTOBJ_CONTAINER_MARKALL(&peerl,peer); ASTOBJ_CONTAINER_MARKALL(&peerl);
} }
/*--- prune_peers: Delete all peers marked for deletion ---*/ /*--- prune_peers: Delete all peers marked for deletion ---*/
static void prune_peers(void) static void prune_peers(void)
{ {
/* Prune peers who still are supposed to be deleted */ /* Prune peers who still are supposed to be deleted */
struct sip_peer *peer, *peerlast, *peernext; ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl,sip_destroy_peer);
ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl,peerlast,peernext,peer,sip_destroy_peer); }
/*--- sip_poke_all_peers: Send a poke to all known peers */
static void sip_poke_all_peers(void)
{
ASTOBJ_CONTAINER_TRAVERSE(&peerl, do {
ASTOBJ_WRLOCK(iterator);
sip_poke_peer(iterator);
ASTOBJ_UNLOCK(iterator);
} while (0)
);
}
/*--- sip_send_all_registers: Send all known registrations */
static void sip_send_all_registers(void)
{
ASTOBJ_CONTAINER_TRAVERSE(&regl, do {
ASTOBJ_WRLOCK(iterator);
__sip_do_register(iterator);
ASTOBJ_UNLOCK(iterator);
} while (0)
);
} }
/*--- sip_do_reload: Reload module */ /*--- sip_do_reload: Reload module */
static int sip_do_reload(void) static int sip_do_reload(void)
{ {
struct sip_registry *reg;
struct sip_peer *peer;
delete_users(); delete_users();
reload_config(); reload_config();
prune_peers(); prune_peers();
/* And start the monitor for the first time */ sip_poke_all_peers();
ASTOBJ_CONTAINER_TRAVERSE(&regl,reg,__sip_do_register(reg)); sip_send_all_registers();
ASTOBJ_CONTAINER_TRAVERSE(&peerl,peer,sip_poke_peer(peer));
return 0; return 0;
} }
@@ -9450,8 +9467,6 @@ static struct ast_cli_entry cli_sip_reload =
int load_module() int load_module()
{ {
int res; int res;
struct sip_peer *peer;
struct sip_registry *reg;
ASTOBJ_CONTAINER_INIT(&userl); ASTOBJ_CONTAINER_INIT(&userl);
ASTOBJ_CONTAINER_INIT(&peerl); ASTOBJ_CONTAINER_INIT(&peerl);
@@ -9498,8 +9513,8 @@ int load_module()
ast_register_application(app_dtmfmode, sip_dtmfmode, synopsis_dtmfmode, descrip_dtmfmode); ast_register_application(app_dtmfmode, sip_dtmfmode, synopsis_dtmfmode, descrip_dtmfmode);
ast_register_application(app_sipaddheader, sip_addheader, synopsis_sipaddheader, descrip_sipaddheader); ast_register_application(app_sipaddheader, sip_addheader, synopsis_sipaddheader, descrip_sipaddheader);
ast_register_application(app_sipgetheader, sip_getheader, synopsis_sipgetheader, descrip_sipgetheader); ast_register_application(app_sipgetheader, sip_getheader, synopsis_sipgetheader, descrip_sipgetheader);
ASTOBJ_CONTAINER_TRAVERSE(&peerl,peer,sip_poke_peer(peer)); sip_poke_all_peers();
ASTOBJ_CONTAINER_TRAVERSE(&regl,reg,__sip_do_register(reg)); sip_send_all_registers();
/* And start the monitor for the first time */ /* And start the monitor for the first time */
restart_monitor(); restart_monitor();
@@ -9586,9 +9601,9 @@ int unload_module()
} }
/* Free memory for local network address mask */ /* Free memory for local network address mask */
ast_free_ha(localaddr); ast_free_ha(localaddr);
ASTOBJ_CONTAINER_RELEASE(&userl); ASTOBJ_CONTAINER_DESTROY(&userl);
ASTOBJ_CONTAINER_RELEASE(&peerl); ASTOBJ_CONTAINER_DESTROY(&peerl);
ASTOBJ_CONTAINER_RELEASE(&regl); ASTOBJ_CONTAINER_DESTROY(&regl);
return 0; return 0;
} }

View File

@@ -22,7 +22,6 @@
are used for maximum performance, to support multiple inheritance, and are used for maximum performance, to support multiple inheritance, and
to be easily integrated into existing structures without additional to be easily integrated into existing structures without additional
malloc calls, etc. malloc calls, etc.
*/ */
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)
@@ -39,6 +38,10 @@ extern "C" {
/* C++ is simply a syntactic crutch for those who cannot think for themselves /* C++ is simply a syntactic crutch for those who cannot think for themselves
in an object oriented way. */ in an object oriented way. */
#define ASTOBJ_RDLOCK(object) ast_mutex_lock(&(object)->_lock)
#define ASTOBJ_WRLOCK(object) ast_mutex_lock(&(object)->_lock)
#define ASTOBJ_UNLOCK(object) ast_mutex_unlock(&(object)->_lock)
#ifdef ASTOBJ_CONTAINER_HASHMODEL #ifdef ASTOBJ_CONTAINER_HASHMODEL
#define __ASTOBJ_HASH(type,hashes) \ #define __ASTOBJ_HASH(type,hashes) \
type *next[hashes] type *next[hashes]
@@ -57,60 +60,73 @@ extern "C" {
ASTOBJ_COMPONENTS_NOLOCK_FULL(type,ASTOBJ_DEFAULT_NAMELEN,1) ASTOBJ_COMPONENTS_NOLOCK_FULL(type,ASTOBJ_DEFAULT_NAMELEN,1)
#define ASTOBJ_COMPONENTS(type) \ #define ASTOBJ_COMPONENTS(type) \
ast_mutex_t lock; \ ast_mutex_t _lock; \
ASTOBJ_COMPONENTS_NOLOCK(type) ASTOBJ_COMPONENTS_NOLOCK(type)
#define ASTOBJ_COMPONENTS_FULL(type,namelen,hashes) \ #define ASTOBJ_COMPONENTS_FULL(type,namelen,hashes) \
ast_mutex_t lock; \ ast_mutex_t _lock; \
ASTOBJ_COMPONENTS_NOLOCK_FULL(type,namelen,hashes) ASTOBJ_COMPONENTS_NOLOCK_FULL(type,namelen,hashes)
#define ASTOBJ_REF(object) \ #define ASTOBJ_REF(object) \
do { \ ({ \
ast_mutex_lock(&(object)->lock); \ ASTOBJ_WRLOCK(object); \
(object)->refcount++; \ (object)->refcount++; \
ast_mutex_unlock(&(object)->lock); \ ASTOBJ_UNLOCK(object); \
} while(0) (object); \
})
#define ASTOBJ_UNREF(object,destructor) \ #define ASTOBJ_UNREF(object,destructor) \
do { \ do { \
int destroyme; \ ASTOBJ_WRLOCK(object); \
ast_mutex_lock(&(object)->lock); \ if (__builtin_expect((object)->refcount, 1)) \
if ((object)->refcount > 0) \
(object)->refcount--; \ (object)->refcount--; \
else \ else \
ast_log(LOG_WARNING, "Unreferencing unreferenced (object)!\n"); \ ast_log(LOG_WARNING, "Unreferencing unreferenced (object)!\n"); \
destroyme = (!(object)->refcount) && ((object)->objflags & ASTOBJ_FLAG_DELME); \ ASTOBJ_UNLOCK(object); \
ast_mutex_unlock(&(object)->lock); \ ASTOBJ_DESTROY(object,destructor); \
if (destroyme) \ (object) = NULL; \
destructor((object)); \
} while(0) } while(0)
#define ASTOBJ_MARK(object) \ #define ASTOBJ_MARK(object) \
(object)->objflags |= ASTOBJ_FLAG_MARKED; do { \
ASTOBJ_WRLOCK(object); \
(object)->objflags |= ASTOBJ_FLAG_MARKED; \
ASTOBJ_UNLOCK(object); \
} while(0)
#define ASTOBJ_UNMARK(object) \ #define ASTOBJ_UNMARK(object) \
(object)->objflags &= ~ASTOBJ_FLAG_MARKED; do { \
ASTOBJ_WRLOCK(object); \
(object)->objflags &= ~ASTOBJ_FLAG_MARKED; \
ASTOBJ_UNLOCK(object); \
} while(0)
#define ASTOBJ_DESTROY(object,destructor) \ #define ASTOBJ_DESTROY(object,destructor) \
do { \ do { \
int destroyme; \ if (__builtin_expect((object)->refcount, 1)) { \
ast_mutex_lock(&(object)->lock); \ ASTOBJ_WRLOCK(object); \
destroyme = (!(object)->refcount); \
(object)->objflags |= ASTOBJ_FLAG_DELME; \ (object)->objflags |= ASTOBJ_FLAG_DELME; \
ast_mutex_unlock(&(object)->lock); \ ASTOBJ_UNLOCK(object); \
if (destroyme) \ } else { \
ast_mutex_destroy(&(object)->_lock); \
destructor((object)); \ destructor((object)); \
} \
} while(0) } while(0)
#define ASTOBJ_INIT(object) \ #define ASTOBJ_INIT(object) \
do { \ do { \
ast_mutex_init(&(object)->lock); \ ast_mutex_init(&(object)->_lock); \
object->name[0] = '\0'; \ object->name[0] = '\0'; \
object->refcount = 1; \
} while(0) } while(0)
/* Containers for objects -- current implementation is linked lists, but /* Containers for objects -- current implementation is linked lists, but
should be able to be converted to hashes relatively easily */ should be able to be converted to hashes relatively easily */
#define ASTOBJ_CONTAINER_RDLOCK(container) ast_mutex_lock(&(container)->_lock)
#define ASTOBJ_CONTAINER_WRLOCK(container) ast_mutex_lock(&(container)->_lock)
#define ASTOBJ_CONTAINER_UNLOCK(container) ast_mutex_unlock(&(container)->_lock)
#ifdef ASTOBJ_CONTAINER_HASHMODEL #ifdef ASTOBJ_CONTAINER_HASHMODEL
#error "Hash model for object containers not yet implemented!" #error "Hash model for object containers not yet implemented!"
#else #else
@@ -120,193 +136,145 @@ extern "C" {
#define ASTOBJ_CONTAINER_INIT_FULL(container,hashes,buckets) \ #define ASTOBJ_CONTAINER_INIT_FULL(container,hashes,buckets) \
do { \ do { \
ast_mutex_init(&(container)->lock); \ ast_mutex_init(&(container)->_lock); \
} while(0) } while(0)
#define ASTOBJ_CONTAINER_RELEASE_FULL(container,hashes,buckets) \ #define ASTOBJ_CONTAINER_DESTROY_FULL(container,hashes,buckets) \
do { \ do { \
ast_mutex_destroy(&(container)->lock); \ ast_mutex_destroy(&(container)->_lock); \
} while(0) } while(0)
#define ASTOBJ_CONTAINER_TRAVERSE(container,iterator,eval) \ #define ASTOBJ_CONTAINER_TRAVERSE(container,eval) \
do { \ do { \
ast_mutex_lock(&((container)->lock)); \ typeof((container)->head) iterator; \
(iterator) = (container)->head; \ typeof((container)->head) next; \
while((iterator)) { \ ASTOBJ_CONTAINER_RDLOCK(container); \
ast_mutex_lock(&(iterator)->lock); \ next = (container)->head; \
while((iterator = next)) { \
next = iterator->next[0]; \
eval; \ eval; \
ast_mutex_unlock(&(iterator)->lock); \
(iterator) = (iterator)->next[0]; \
} \ } \
ast_mutex_unlock(&(container)->lock); \ ASTOBJ_CONTAINER_UNLOCK(container); \
} while(0) } while(0)
#define ASTOBJ_CONTAINER_FIND_FULL(container,iterator,data,field,hashfunc,hashoffset,comparefunc) \ #define ASTOBJ_CONTAINER_FIND_FULL(container,data,field,hashfunc,hashoffset,comparefunc) \
do { \ ({ \
int res; \ typeof((container)->head) found = NULL; \
ast_mutex_lock(&((container)->lock)); \ ASTOBJ_CONTAINER_TRAVERSE(container, do { \
(iterator) = (container)->head; \ ASTOBJ_RDLOCK(iterator); \
while((iterator)) { \ if (!(comparefunc(iterator->field, (data)))) { \
ast_mutex_lock(&(iterator)->lock); \ found = ASTOBJ_REF(iterator); \
res = (comparefunc((iterator)->field,(data))); \ } \
if (!res) \ ASTOBJ_UNLOCK(iterator); \
ASTOBJ_REF((iterator)); \ if (found) \
ast_mutex_unlock(&(iterator)->lock); \
if (!res) \
break; \ break; \
(iterator) = (iterator)->next[0]; \ } while (0)); \
} \ found; \
ast_mutex_unlock(&(container)->lock); \ })
} while(0)
#define ASTOBJ_CONTAINER_DESTROYALL(container,iterator,destructor) \ #define ASTOBJ_CONTAINER_DESTROYALL(container,destructor) \
do { \ do { \
ast_mutex_lock(&((container)->lock)); \ typeof((container)->head) iterator; \
(iterator) = (container)->head; \ ASTOBJ_CONTAINER_WRLOCK(container); \
while((iterator)) { \ while((iterator = (container)->head)) { \
(container)->head = (iterator)->next[0]; \ (container)->head = (iterator)->next[0]; \
ASTOBJ_DESTROY(iterator,destructor); \ ASTOBJ_DESTROY(iterator,destructor); \
(iterator) = (container)->head; \
} \ } \
ast_mutex_unlock(&(container)->lock); \ ASTOBJ_CONTAINER_UNLOCK(container); \
} while(0) } while(0)
#define ASTOBJ_CONTAINER_UNLINK_FULL(container,iterator,data,field,hashfunc,hashoffset,comparefunc) \ #define ASTOBJ_CONTAINER_FIND_UNLINK_FULL(container,data,field,hashfunc,hashoffset,comparefunc) \
do { \ ({ \
int res=-1; \ typeof((container)->head) found = NULL; \
ast_mutex_lock(&((container)->lock)); \ typeof((container)->head) prev = NULL; \
(iterator) = (container)->head; \ ASTOBJ_CONTAINER_TRAVERSE(container, do { \
if ((iterator)) { \ ASTOBJ_RDLOCK(iterator); \
ast_mutex_lock(&(iterator)->lock); \ if (!(comparefunc(iterator->field, (data)))) { \
res = (comparefunc((iterator)->field,(data))); \ found = ASTOBJ_REF(iterator); \
if (!res && ((iterator)->refcount < 1)) \ ASTOBJ_CONTAINER_WRLOCK(container); \
ast_log(LOG_WARNING, "Unlink called with refcount < 1!\n"); \ if (prev) \
ast_mutex_unlock(&(iterator)->lock); \ prev->next[0] = next; \
if (!res) \
(container)->head = (iterator)->next[0]; \
else while((iterator)->next[0]) { \
ast_mutex_lock(&(iterator)->next[0]->lock); \
res = (comparefunc((iterator)->next[0]->field,(data))); \
if (!res && ((iterator)->next[0]->refcount < 1)) \
ast_log(LOG_WARNING, "Unlink called with refcount < 1!\n"); \
ast_mutex_unlock(&(iterator)->next[0]->lock); \
if (!res) { \
(iterator)->next[0] = (iterator)->next[0]->next[0]; \
break; \
} \
(iterator) = (iterator)->next[0]; \
} \
} \
ast_mutex_unlock(&(container)->lock); \
} while(0)
#define ASTOBJ_CONTAINER_FIND_UNLINK_FULL(container,reiterator,iterator,data,field,hashfunc,hashoffset,comparefunc) \
do { \
int res=-1; \
(reiterator) = NULL; \
ast_mutex_lock(&((container)->lock)); \
(iterator) = (container)->head; \
if ((iterator)) { \
ast_mutex_lock(&(iterator)->lock); \
res = (comparefunc((iterator)->field,(data))); \
if (!res && ((iterator)->refcount < 1)) \
ast_log(LOG_WARNING, "Unlink called with refcount < 1!\n"); \
ast_mutex_unlock(&(iterator)->lock); \
if (!res) {\
(reiterator) = (container)->head; \
(container)->head = (iterator)->next[0]; \
} else while((iterator)->next[0]) { \
ast_mutex_lock(&(iterator)->next[0]->lock); \
res = (comparefunc((iterator)->next[0]->field,(data))); \
ast_mutex_unlock(&(iterator)->next[0]->lock); \
if (!res) { \
(reiterator) = (iterator)->next[0]; \
(iterator)->next[0] = (iterator)->next[0]->next[0]; \
break; \
} \
(iterator) = (iterator)->next[0]; \
} \
} \
ast_mutex_unlock(&(container)->lock); \
} while(0)
#define ASTOBJ_CONTAINER_PRUNE_MARKED(container,previ,nexti,iterator,destructor) \
do { \
(previ) = NULL; \
ast_mutex_lock(&((container)->lock)); \
(iterator) = (container)->head; \
while((iterator)) { \
ast_mutex_lock(&(iterator)->lock); \
(nexti) = (iterator)->next[0]; \
if ((iterator)->objflags & ASTOBJ_FLAG_MARKED) { \
if ((previ)) \
(previ)->next[0] = (nexti); \
else \ else \
(container)->head = (nexti); \ (container)->head = next; \
ast_mutex_unlock(&(iterator)->lock); \ ASTOBJ_CONTAINER_UNLOCK(container); \
break; \
} \
ASTOBJ_UNLOCK(iterator); \
if (found) \
break; \
prev = iterator; \
} while (0)); \
found; \
})
#define ASTOBJ_CONTAINER_PRUNE_MARKED(container,destructor) \
do { \
typeof((container)->head) prev = NULL; \
ASTOBJ_CONTAINER_TRAVERSE(container, do { \
ASTOBJ_RDLOCK(iterator); \
if (iterator->objflags & ASTOBJ_FLAG_MARKED) { \
ASTOBJ_CONTAINER_WRLOCK(container); \
if (prev) \
prev->next[0] = next; \
else \
(container)->head = next; \
ASTOBJ_CONTAINER_UNLOCK(container); \
ASTOBJ_UNLOCK(iterator); \
ASTOBJ_DESTROY(iterator,destructor); \ ASTOBJ_DESTROY(iterator,destructor); \
} else { \ continue; \
(previ) = (iterator); \
ast_mutex_unlock(&(iterator)->lock); \
} \ } \
(iterator) = (nexti); \ ASTOBJ_UNLOCK(iterator); \
} \ prev = iterator; \
ast_mutex_unlock(&(container)->lock); \ } while (0)); \
} while(0) } while(0)
#define ASTOBJ_CONTAINER_LINK_FULL(container,newobj,data,field,hashfunc,hashoffset,comparefunc) \ #define ASTOBJ_CONTAINER_LINK_FULL(container,newobj,data,field,hashfunc,hashoffset,comparefunc) \
do { \ do { \
ASTOBJ_REF(newobj); \ ASTOBJ_CONTAINER_WRLOCK(container); \
ast_mutex_lock(&(container)->lock); \
(newobj)->next[0] = (container)->head; \ (newobj)->next[0] = (container)->head; \
(container)->head = (newobj); \ (container)->head = (newobj); \
ast_mutex_unlock(&(container)->lock); \ ASTOBJ_CONTAINER_UNLOCK(container); \
} while(0) } while(0)
#endif /* Hash model */ #endif /* List model */
/* Common to hash and linked list models */ /* Common to hash and linked list models */
#define ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type) \ #define ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type) \
ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(type,1,ASTOBJ_DEFAULT_BUCKETS) ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(type,1,ASTOBJ_DEFAULT_BUCKETS)
#define ASTOBJ_CONTAINER_COMPONENTS(type) \ #define ASTOBJ_CONTAINER_COMPONENTS(type) \
ast_mutex_t lock; \ ast_mutex_t _lock; \
ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type) ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type)
#define ASTOBJ_CONTAINER_INIT(container) \ #define ASTOBJ_CONTAINER_INIT(container) \
ASTOBJ_CONTAINER_INIT_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS) ASTOBJ_CONTAINER_INIT_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS)
#define ASTOBJ_CONTAINER_RELEASE(container) \ #define ASTOBJ_CONTAINER_DESTROY(container) \
ASTOBJ_CONTAINER_RELEASE_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS) ASTOBJ_CONTAINER_DESTROY_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS)
#define ASTOBJ_CONTAINER_FIND(container,iterator,namestr) \ #define ASTOBJ_CONTAINER_FIND(container,namestr) \
ASTOBJ_CONTAINER_FIND_FULL(container,iterator,namestr,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp) ASTOBJ_CONTAINER_FIND_FULL(container,namestr,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp)
#define ASTOBJ_CONTAINER_FIND_UNLINK(container,reiterator,iterator,namestr) \ #define ASTOBJ_CONTAINER_FIND_UNLINK(container,namestr) \
ASTOBJ_CONTAINER_FIND_UNLINK_FULL(container,reiterator,iterator,namestr,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp) ASTOBJ_CONTAINER_FIND_UNLINK_FULL(container,namestr,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp)
#define ASTOBJ_CONTAINER_UNLINK(container,iterator,namestr) \
ASTOBJ_CONTAINER_UNLINK_FULL(container,iterator,namestr,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp)
#define ASTOBJ_CONTAINER_LINK(container,newobj) \ #define ASTOBJ_CONTAINER_LINK(container,newobj) \
ASTOBJ_CONTAINER_LINK_FULL(container,newobj,(newobj)->name,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp) ASTOBJ_CONTAINER_LINK_FULL(container,newobj,(newobj)->name,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp)
#define ASTOBJ_CONTAINER_MARKALL(container,iterator) \ #define ASTOBJ_CONTAINER_MARKALL(container) \
ASTOBJ_CONTAINER_TRAVERSE(container,iterator,(iterator)->objflags |= ASTOBJ_FLAG_MARKED) ASTOBJ_CONTAINER_TRAVERSE(container,ASTOBJ_MARK(iterator))
#define ASTOBJ_CONTAINER_UNMARKALL(container,iterator) \ #define ASTOBJ_CONTAINER_UNMARKALL(container) \
ASTOBJ_CONTAINER_TRAVERSE(container,iterator,(iterator)->objflags &= ~ASTOBJ_FLAG_MARKED) ASTOBJ_CONTAINER_TRAVERSE(container,ASTOBJ_UNMARK(iterator))
#define ASTOBJ_DUMP(s,slen,obj) \ #define ASTOBJ_DUMP(s,slen,obj) \
snprintf((s),(slen),"name: %s\nobjflags: %d\nrefcount: %d\n\n", (obj)->name, (obj)->objflags, (obj)->refcount); snprintf((s),(slen),"name: %s\nobjflags: %d\nrefcount: %d\n\n", (obj)->name, (obj)->objflags, (obj)->refcount);
#define ASTOBJ_CONTAINER_DUMP(fd,s,slen,container,iterator) \ #define ASTOBJ_CONTAINER_DUMP(fd,s,slen,container) \
ASTOBJ_CONTAINER_TRAVERSE(container,iterator,do { ASTOBJ_DUMP(s,slen,iterator); ast_cli(fd, s); } while(0)) ASTOBJ_CONTAINER_TRAVERSE(container,do { ASTOBJ_DUMP(s,slen,iterator); ast_cli(fd, s); } while(0))
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)
} }
#endif #endif
#endif #endif