peer->chanvars = NULL;
}
- /* If the schedule delete fails, that means the schedule is currently
- * running, which means we should wait for that thread to complete.
- * Otherwise, there's a crashable race condition.
- *
- * NOTE: once peer is refcounted, this probably is no longer necessary.
- */
- AST_SCHED_DEL(sched, peer->expire);
- AST_SCHED_DEL(sched, peer->pokeexpire);
-
register_peer_exten(peer, FALSE);
ast_free_ha(peer->ha);
if (ast_test_flag(&peer->flags[1], SIP_PAGE2_SELFDESTRUCT))
/* Cache peer */
ast_copy_flags(&peer->flags[1],&global_flags[1], SIP_PAGE2_RTAUTOCLEAR|SIP_PAGE2_RTCACHEFRIENDS);
if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
- AST_SCHED_DEL(sched, peer->expire);
- peer->expire = ast_sched_add(sched, (global_rtautoclear) * 1000, expire_register, (void *)peer);
+ if (!AST_SCHED_DEL(sched, peer->expire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
+ peer->expire = ast_sched_add(sched, (global_rtautoclear) * 1000, expire_register, ASTOBJ_REF(peer));
+ if (peer->expire == -1) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
}
ASTOBJ_CONTAINER_LINK(&peerl,peer);
} else {
*/
if (ast_test_flag(&peer->flags[1], SIP_PAGE2_SELFDESTRUCT) ||
ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
- peer = ASTOBJ_CONTAINER_UNLINK(&peerl, peer); /* Remove from peer list */
- ASTOBJ_UNREF(peer, sip_destroy_peer); /* Remove from memory */
+ peer = ASTOBJ_CONTAINER_UNLINK(&peerl, peer);
+ ASTOBJ_UNREF(peer, sip_destroy_peer);
}
+ ASTOBJ_UNREF(peer, sip_destroy_peer);
+
return 0;
}
/*! \brief Poke peer (send qualify to check if peer is alive and well) */
static int sip_poke_peer_s(const void *data)
{
- struct sip_peer *peer = (struct sip_peer *)data;
+ struct sip_peer *peer = (struct sip_peer *) data;
peer->pokeexpire = -1;
+
sip_poke_peer(peer);
+
+ ASTOBJ_UNREF(peer, sip_destroy_peer);
+
return 0;
}
peer->addr.sin_port = htons(port);
if (sipsock < 0) {
/* SIP isn't up yet, so schedule a poke only, pretty soon */
- AST_SCHED_DEL(sched, peer->pokeexpire);
- peer->pokeexpire = ast_sched_add(sched, ast_random() % 5000 + 1, sip_poke_peer_s, peer);
+ if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
+ peer->pokeexpire = ast_sched_add(sched, ast_random() % 5000 + 1, sip_poke_peer_s, ASTOBJ_REF(peer));
+ if (peer->pokeexpire == -1) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
} else
sip_poke_peer(peer);
- AST_SCHED_DEL(sched, peer->expire);
- peer->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, peer);
+ if (!AST_SCHED_DEL(sched, peer->expire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
+ peer->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, ASTOBJ_REF(peer));
+ if (peer->expire == -1) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
register_peer_exten(peer, TRUE);
}
} else if (!strcasecmp(curi, "*") || !expiry) { /* Unregister this peer */
/* This means remove all registrations and return OK */
memset(&peer->addr, 0, sizeof(peer->addr));
- AST_SCHED_DEL(sched, peer->expire);
+ if (!AST_SCHED_DEL(sched, peer->expire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
destroy_association(peer);
if (curi && ast_strlen_zero(peer->username))
ast_copy_string(peer->username, curi, sizeof(peer->username));
- AST_SCHED_DEL(sched, peer->expire);
+ if (!AST_SCHED_DEL(sched, peer->expire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
if (expiry > max_expiry)
expiry = max_expiry;
if (expiry < min_expiry)
expiry = min_expiry;
- peer->expire = ast_test_flag(&peer->flags[0], SIP_REALTIME) ? -1 :
- ast_sched_add(sched, (expiry + 10) * 1000, expire_register, peer);
+ if (ast_test_flag(&peer->flags[0], SIP_REALTIME)) {
+ peer->expire = -1;
+ } else {
+ peer->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, ASTOBJ_REF(peer));
+ if (peer->expire == -1) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
+ }
pvt->expiry = expiry;
snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port), expiry, peer->username, peer->fullcontact);
if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_RT_FROMCONTACT))
peer->name, s, pingtime);
}
- AST_SCHED_DEL(sched, peer->pokeexpire);
+ if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
+
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
/* Try again eventually */
peer->pokeexpire = ast_sched_add(sched,
is_reachable ? DEFAULT_FREQ_OK : DEFAULT_FREQ_NOTOK,
- sip_poke_peer_s, peer);
+ sip_poke_peer_s, ASTOBJ_REF(peer));
+ if (peer->pokeexpire == -1) {
+ ASTOBJ_UNREF(peer, sip_destroy_peer);
+ }
}
/*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */
peer->call = NULL;
peer->lastms = -1;
ast_device_state_changed("SIP/%s", peer->name);
- /* Try again quickly */
- AST_SCHED_DEL(sched, peer->pokeexpire);
+
+ /* This function gets called one place outside of the scheduler ... */
+ if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
+
+ /* There is no need to ASTOBJ_REF() here. Just let the scheduled callback
+ * inherit the reference that the current callback already has. */
peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer);
+ if (peer->pokeexpire == -1) {
+ ASTOBJ_UNREF(peer, sip_destroy_peer);
+ }
+
return 0;
}
if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
/* IF we have no IP, or this isn't to be monitored, return
imeediately after clearing things out */
- AST_SCHED_DEL(sched, peer->pokeexpire);
+ if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
peer->lastms = 0;
peer->call = NULL;
return 0;
build_via(p);
build_callid_pvt(p);
- AST_SCHED_DEL(sched, peer->pokeexpire);
+ if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
+
p->relatedpeer = peer;
ast_set_flag(&p->flags[0], SIP_OUTGOING);
#ifdef VOCAL_DATA_HACK
xmitres = transmit_invite(p, SIP_OPTIONS, 0, 2);
#endif
gettimeofday(&peer->ps, NULL);
- if (xmitres == XMIT_ERROR)
- sip_poke_noanswer(peer); /* Immediately unreachable, network problems */
- else {
- AST_SCHED_DEL(sched, peer->pokeexpire);
- peer->pokeexpire = ast_sched_add(sched, peer->maxms * 2, sip_poke_noanswer, peer);
+ if (xmitres == XMIT_ERROR) {
+ sip_poke_noanswer(ASTOBJ_REF(peer)); /* Immediately unreachable, network problems */
+ } else {
+ if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
+ peer->pokeexpire = ast_sched_add(sched, peer->maxms * 2, sip_poke_noanswer, ASTOBJ_REF(peer));
+ if (peer->pokeexpire == -1) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
}
return 0;
}
} else {
/* Non-dynamic. Make sure we become that way if we're not */
- AST_SCHED_DEL(sched, peer->expire);
+ if (!AST_SCHED_DEL(sched, peer->expire)) {
+ struct sip_peer *peer_ptr = peer;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
ast_clear_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC);
if (!obproxyfound || !strcasecmp(v->name, "outboundproxy")) {
if (ast_get_ip_or_srv(&peer->addr, v->value, srvlookup ? "_sip._udp" : NULL)) {
ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
ASTOBJ_WRLOCK(iterator);
- AST_SCHED_DEL(sched, iterator->pokeexpire);
+ if (!AST_SCHED_DEL(sched, iterator->pokeexpire)) {
+ struct sip_peer *peer_ptr = iterator;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
ms += 100;
- iterator->pokeexpire = ast_sched_add(sched, ms, sip_poke_peer_s, iterator);
+ iterator->pokeexpire = ast_sched_add(sched, ms, sip_poke_peer_s, ASTOBJ_REF(iterator));
+ if (iterator->pokeexpire == -1) {
+ struct sip_peer *peer_ptr = iterator;
+ ASTOBJ_UNREF(peer_ptr, sip_destroy_peer);
+ }
ASTOBJ_UNLOCK(iterator);
} while (0)
);