mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-30 10:33:13 +00:00
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:
@@ -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), ®l, reg);
|
ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), ®l);
|
||||||
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(®l,reg, do {
|
ASTOBJ_CONTAINER_TRAVERSE(®l, 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(®l,reg,sip_registry_destroy);
|
ASTOBJ_CONTAINER_DESTROYALL(®l,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(®l, 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(®l,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(®l,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(®l);
|
ASTOBJ_CONTAINER_DESTROY(®l);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user