#include <daemon.h>
#include <utils/hashtable.h>
+#include <utils/linked_list.h>
#include <threading/rwlock.h>
typedef struct private_lookip_listener_t private_lookip_listener_t;
* Hashtable with entries: host_t => entry_t
*/
hashtable_t *entries;
+
+ /**
+ * List of registered listeners
+ */
+ linked_list_t *listeners;
};
+/**
+ * Listener entry
+ */
+typedef struct {
+ /** callback function */
+ lookip_callback_t cb;
+ /** user data for callback */
+ void *user;
+} listener_entry_t;
+
/**
* Hashtable entry
*/
return a->ip_equals(a, b);
}
+/**
+ * Compare callback that invokes up callback of all registered listeners
+ */
+static bool notify_up(listener_entry_t *listener, entry_t *entry)
+{
+ if (!listener->cb(listener->user, TRUE, entry->vip, entry->other,
+ entry->id, entry->name))
+ {
+ free(listener);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Compare callback that invokes down callback of all registered listeners
+ */
+static bool notify_down(listener_entry_t *listener, entry_t *entry)
+{
+ if (!listener->cb(listener->user, FALSE, entry->vip, entry->other,
+ entry->id, entry->name))
+ {
+ free(listener);
+ return TRUE;
+ }
+ return FALSE;
+}
+
/**
* Add a new entry to the hashtable
*/
.name = strdup(ike_sa->get_name(ike_sa)),
);
+ this->lock->read_lock(this->lock);
+ this->listeners->remove(this->listeners, entry, (void*)notify_up);
+ this->lock->unlock(this->lock);
+
this->lock->write_lock(this->lock);
entry = this->entries->put(this->entries, entry->vip, entry);
this->lock->unlock(this->lock);
this->lock->unlock(this->lock);
if (entry)
{
+ this->lock->read_lock(this->lock);
+ this->listeners->remove(this->listeners, entry, (void*)notify_down);
+ this->lock->unlock(this->lock);
+
entry_destroy(entry);
}
}
entry = this->entries->get(this->entries, vip);
if (entry)
{
- cb(user, entry->vip, entry->other, entry->id, entry->name);
+ cb(user, TRUE, entry->vip, entry->other, entry->id, entry->name);
}
}
else
enumerator = this->entries->create_enumerator(this->entries);
while (enumerator->enumerate(enumerator, &vip, &entry))
{
- cb(user, entry->vip, entry->other, entry->id, entry->name);
+ cb(user, TRUE, entry->vip, entry->other, entry->id, entry->name);
}
enumerator->destroy(enumerator);
}
this->lock->unlock(this->lock);
}
+METHOD(lookip_listener_t, add_listener, void,
+ private_lookip_listener_t *this, lookip_callback_t cb, void *user)
+{
+ listener_entry_t *listener;
+
+ INIT(listener,
+ .cb = cb,
+ .user = user,
+ );
+
+ this->lock->write_lock(this->lock);
+ this->listeners->insert_last(this->listeners, listener);
+ this->lock->unlock(this->lock);
+}
+
METHOD(lookip_listener_t, destroy, void,
private_lookip_listener_t *this)
{
+ this->listeners->destroy_function(this->listeners, free);
this->entries->destroy(this->entries);
this->lock->destroy(this->lock);
free(this);
.ike_updown = _ike_updown,
},
.lookup = _lookup,
+ .add_listener = _add_listener,
.destroy = _destroy,
},
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.entries = hashtable_create((hashtable_hash_t)hash,
(hashtable_equals_t)equals, 32),
+ .listeners = linked_list_create(),
);
return &this->public;
* Callback function to query virtual IP entries
*
* @param user user supplied pointer
+ * @param up TRUE if tunnels established, FALSE if closed
* @param vip virtual IP of remote peer
* @param other peer external IP
* @param id peer identity
* @param name associated connection name
* @return TRUE to receive more results, FALSE to cancel
*/
-typedef bool (*lookip_callback_t)(void *user, host_t *vip, host_t *other,
- identification_t *id, char *name);
+typedef bool (*lookip_callback_t)(void *user, bool up, host_t *vip,
+ host_t *other, identification_t *id, char *name);
/**
* Listener collecting virtual IPs.
/**
* Perform a lookup for a given virtual IP, invoke callback for matches.
*
+ * The "up" parameter is always TRUE when the callback is invoked using
+ * lookup().
+ *
* @param vip virtual IP to look up, NULL to get all entries
* @param cb callback function to invoke
* @param user user data to pass to callback function
void (*lookup)(lookip_listener_t *this, host_t *vip,
lookip_callback_t cb, void *user);
+ /**
+ * Register a listener function that gets notified about virtual IP changes.
+ *
+ * @param cb callback function to invoke
+ * @param user user data to pass to callback function
+ */
+ void (*add_listener)(lookip_listener_t *this,
+ lookip_callback_t cb, void *user);
+
/**
* Destroy a lookip_listener_t.
*/