memset(peer, 0, sizeof(*peer));
fosa_cond_init(&peer->cond);
forb_ref_init(&peer->ref);
+ fosa_mutex_init(&peer->send_lock, 0);
}
return peer;
}
forb_peer_release(forb_ref_t *ref)
{
forb_peer_t *peer = container_of(ref, forb_peer_t, ref);
- if (peer->port->proto->peer_destroy) {
- peer->port->proto->peer_destroy(peer);
+ if (peer->port &&
+ peer->port->desc.proto->peer_destroy) {
+ peer->port->desc.proto->peer_destroy(peer);
}
+ if (peer->addr)
+ forb_free(peer->addr);
+
forb_free(peer);
}
fosa_abs_time_t *timeout)
{
forb_peer_t *peer;
+ bool peer_allocated = false;
fosa_mutex_lock(&forb->peer_mutex);
peer = forb_peer_nolock_find(forb, server_id);
if (!peer && !timeout) goto unlock;
if (peer) {
forb_peer_get(peer);
- }
- if (!peer) {
+ } else {
/* We are the first who want to contact this peer */
peer = forb_peer_new();
if (!peer) goto unlock;
peer->server_id = *server_id;
peer->state = FORB_PEER_WANTED;
- forb_peer_get(peer);
- forb_peer_nolock_insert(forb, peer);
+ forb_peer_nolock_insert(forb, forb_peer_get(peer));
+ peer_allocated = true;
}
while (peer->state == FORB_PEER_WANTED) {
int ret;
&forb->peer_mutex,
timeout);
if (ret == FOSA_ETIMEDOUT) {
+ /* No peer discovered within timeout */
+ if (peer_allocated) {
+ forb_peer_nolock_delete(forb, peer);
+ forb_peer_put(peer);
+ }
forb_peer_put(peer);
peer = NULL;
- /* TODO: How to remove the peer from the tree?
- * We should check refcnt and if equal to 1,
- * we should remove it. */
break;
}
}