peer-cfg: Add method to atomically replace child configs

This commit is contained in:
Tobias Brunner 2015-10-16 12:31:38 +02:00
parent 8db4f19ad9
commit 622c2b2c33
2 changed files with 128 additions and 2 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2008 Tobias Brunner
* Copyright (C) 2007-2015 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@ -200,6 +200,117 @@ METHOD(peer_cfg_t, add_child_cfg, void,
this->mutex->unlock(this->mutex);
}
typedef struct {
enumerator_t public;
linked_list_t *removed;
linked_list_t *added;
enumerator_t *wrapped;
bool add;
} child_cfgs_replace_enumerator_t;
METHOD(enumerator_t, child_cfgs_replace_enumerate, bool,
child_cfgs_replace_enumerator_t *this, child_cfg_t **chd, bool *added)
{
child_cfg_t *child_cfg;
if (!this->wrapped)
{
this->wrapped = this->removed->create_enumerator(this->removed);
}
while (TRUE)
{
if (this->wrapped->enumerate(this->wrapped, &child_cfg))
{
if (chd)
{
*chd = child_cfg;
}
if (added)
{
*added = this->add;
}
return TRUE;
}
if (this->add)
{
break;
}
this->wrapped = this->added->create_enumerator(this->added);
this->add = TRUE;
}
return FALSE;
}
METHOD(enumerator_t, child_cfgs_replace_enumerator_destroy, void,
child_cfgs_replace_enumerator_t *this)
{
DESTROY_IF(this->wrapped);
this->removed->destroy_offset(this->removed, offsetof(child_cfg_t, destroy));
this->added->destroy_offset(this->added, offsetof(child_cfg_t, destroy));
free(this);
}
METHOD(peer_cfg_t, replace_child_cfgs, enumerator_t*,
private_peer_cfg_t *this, peer_cfg_t *other_pub)
{
private_peer_cfg_t *other = (private_peer_cfg_t*)other_pub;
linked_list_t *removed, *added;
enumerator_t *mine, *others;
child_cfg_t *my_cfg, *other_cfg;
child_cfgs_replace_enumerator_t *enumerator;
bool found;
removed = linked_list_create();
other->mutex->lock(other->mutex);
added = linked_list_create_from_enumerator(
other->child_cfgs->create_enumerator(other->child_cfgs));
added->invoke_offset(added, offsetof(child_cfg_t, get_ref));
other->mutex->unlock(other->mutex);
this->mutex->lock(this->mutex);
others = added->create_enumerator(added);
mine = this->child_cfgs->create_enumerator(this->child_cfgs);
while (mine->enumerate(mine, &my_cfg))
{
found = FALSE;
while (others->enumerate(others, &other_cfg))
{
if (my_cfg->equals(my_cfg, other_cfg))
{
added->remove_at(added, others);
other_cfg->destroy(other_cfg);
found = TRUE;
break;
}
}
added->reset_enumerator(added, others);
if (!found)
{
this->child_cfgs->remove_at(this->child_cfgs, mine);
removed->insert_last(removed, my_cfg);
}
}
while (others->enumerate(others, &other_cfg))
{
this->child_cfgs->insert_last(this->child_cfgs,
other_cfg->get_ref(other_cfg));
}
others->destroy(others);
mine->destroy(mine);
this->mutex->unlock(this->mutex);
INIT(enumerator,
.public = {
.enumerate = (void*)_child_cfgs_replace_enumerate,
.destroy = (void*)_child_cfgs_replace_enumerator_destroy,
},
.removed = removed,
.added = added,
);
return &enumerator->public;
}
/**
* child_cfg enumerator
*/
@ -645,6 +756,7 @@ peer_cfg_t *peer_cfg_create(char *name,
.get_ike_cfg = _get_ike_cfg,
.add_child_cfg = _add_child_cfg,
.remove_child_cfg = (void*)_remove_child_cfg,
.replace_child_cfgs = _replace_child_cfgs,
.create_child_cfg_enumerator = _create_child_cfg_enumerator,
.select_child_cfg = _select_child_cfg,
.get_cert_policy = _get_cert_policy,

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2008 Tobias Brunner
* Copyright (C) 2007-2015 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@ -153,6 +153,20 @@ struct peer_cfg_t {
*/
void (*remove_child_cfg)(peer_cfg_t *this, enumerator_t *enumerator);
/**
* Replace the CHILD configs with those in the given PEER config.
*
* Configs that are equal are not replaced.
*
* The enumerator enumerates the removed and added CHILD configs
* (child_cfg_t*, bool), where the flag is FALSE for removed configs and
* TRUE for added configs.
*
* @param other other config to get CHILD configs from
* @return an enumerator over removed/added CHILD configs
*/
enumerator_t* (*replace_child_cfgs)(peer_cfg_t *this, peer_cfg_t *other);
/**
* Create an enumerator for all attached CHILD configs.
*